OSDN Git Service

2006-01-15 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / testsuite / testsuite_iterators.h
1 // -*- C++ -*-
2 // Iterator Wrappers for the C++ library testsuite. 
3 //
4 // Copyright (C) 2004, 2005 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING.  If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 // USA.
21 //
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 // This file provides the following:
32 //
33 // input_iterator_wrapper, output_iterator_wrapper
34 // forward_iterator_wrapper, bidirectional_iterator_wrapper and
35 // random_access_wrapper, which attempt to exactly perform the requirements
36 // of these types of iterators. These are constructed from the class
37 // test_container, which is given two pointers to T and an iterator type.
38
39 #include <testsuite_hooks.h>
40 #include <iterator>
41
42 #ifndef _TESTSUITE_ITERATORS
43 #define _TESTSUITE_ITERATORS
44
45 #ifdef DISABLE_ITERATOR_DEBUG
46 #define ITERATOR_VERIFY(x)
47 #else
48 #define ITERATOR_VERIFY(x) VERIFY(x)
49 #endif
50
51 namespace __gnu_test
52 {
53   /**
54    * @brief Simple container for holding two pointers.
55    *
56    * Note that input_iterator_wrapper changes first to denote
57    * how the valid range of == , ++, etc. change as the iterators are used.
58    */
59   template<typename T>
60     struct BoundsContainer
61     {
62       T* first;
63       T* last;
64       BoundsContainer(T* _first, T* _last)
65         : first(_first), last(_last)
66       { }
67     };
68
69   // Simple container for holding state of a set of output iterators.
70   template<typename T>
71     struct OutputContainer : public BoundsContainer<T>
72     {
73       T* incrementedto;
74       bool* writtento;
75       OutputContainer(T* _first, T* _last)
76         : BoundsContainer<T>(_first, _last), incrementedto(_first)
77       {
78         writtento = new bool[this->last - this->first];
79         for(int i = 0; i < this->last - this->first; i++)
80           writtento[i] = false;
81       }
82
83       ~OutputContainer()
84       { delete[] writtento; }
85     };
86
87   // Produced by output_iterator to allow limited writing to pointer
88   template<class T>
89     class WritableObject
90     {
91       T* ptr;
92
93     public:
94       OutputContainer<T>* SharedInfo;
95       WritableObject(T* ptr_in,OutputContainer<T>* SharedInfo_in):
96         ptr(ptr_in), SharedInfo(SharedInfo_in)
97       { }
98
99       template<class U>
100       void
101       operator=(const U& new_val)
102       {
103         ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
104         SharedInfo->writtento[ptr - SharedInfo->first] = 1;
105         *ptr = new_val;
106       }
107     };
108
109   /**
110    * @brief output_iterator wrapper for pointer
111    * 
112    * This class takes a pointer and wraps it to provide exactly
113    * the requirements of a output_iterator. It should not be
114    * instansiated directly, but generated from a test_container
115    */
116   template<class T>
117   struct output_iterator_wrapper: public std::iterator
118   <std::output_iterator_tag, T, ptrdiff_t, T*, T&>
119   {
120     typedef OutputContainer<T> ContainerType;
121     T* ptr;
122     ContainerType* SharedInfo;
123
124     output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
125       :ptr(_ptr), SharedInfo(SharedInfo_in)
126     {
127       ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last);
128     }
129     
130     output_iterator_wrapper(const output_iterator_wrapper& in)
131       :ptr(in.ptr), SharedInfo(in.SharedInfo)
132     { }
133
134     WritableObject<T>
135     operator*() const
136     {
137       ITERATOR_VERIFY(ptr < SharedInfo->last);
138       ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == false);
139       return WritableObject<T>(ptr, SharedInfo);
140     }
141     
142     output_iterator_wrapper&
143     operator=(const output_iterator_wrapper& in) 
144     {
145       ptr = in.ptr;
146       SharedInfo = in.SharedInfo;
147       return *this;
148     }
149
150     output_iterator_wrapper&
151     operator++()
152     {
153       ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
154       ITERATOR_VERIFY(ptr>=SharedInfo->incrementedto);
155       ptr++;
156       SharedInfo->incrementedto=ptr;
157       return *this;
158     }
159
160     output_iterator_wrapper
161     operator++(int)
162     {
163       output_iterator_wrapper<T> tmp = *this;
164       ++*this;
165       return tmp;
166     }
167
168   };
169
170   /**
171    * @brief input_iterator wrapper for pointer
172    * 
173    * This class takes a pointer and wraps it to provide exactly
174    * the requirements of a input_iterator. It should not be
175    * instansiated directly, but generated from a test_container
176    */
177   template<class T>
178   class input_iterator_wrapper:public std::iterator
179   <std::input_iterator_tag, T, ptrdiff_t, T*, T&>
180   {
181   protected:
182     input_iterator_wrapper()
183     { }
184
185   public:
186     typedef BoundsContainer<T> ContainerType;
187     T* ptr;
188     ContainerType* SharedInfo;
189
190     input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
191       : ptr(_ptr), SharedInfo(SharedInfo_in)
192     { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); }
193     
194     input_iterator_wrapper(const input_iterator_wrapper& in)
195       : ptr(in.ptr), SharedInfo(in.SharedInfo)
196     { }
197
198     bool
199     operator==(const input_iterator_wrapper& in) const
200     {
201       ITERATOR_VERIFY(SharedInfo != NULL && SharedInfo == in.SharedInfo);
202       ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first);
203       return ptr == in.ptr;
204     }
205
206     bool
207     operator!=(const input_iterator_wrapper& in) const
208     {
209       return !(*this == in);
210     }
211
212     T&
213     operator*() const
214     {
215       ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
216       ITERATOR_VERIFY(ptr >= SharedInfo->first);
217       return *ptr;
218     }
219
220     T*
221     operator->() const
222     {
223       return &**this;
224     }
225
226     input_iterator_wrapper&
227     operator=(const input_iterator_wrapper& in)
228     {
229       ptr = in.ptr;
230       SharedInfo = in.SharedInfo;
231       return *this;
232     }
233
234     input_iterator_wrapper&
235     operator++()
236     {
237       ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
238       ITERATOR_VERIFY(ptr>=SharedInfo->first);
239       ptr++;
240       SharedInfo->first=ptr;
241       return *this;
242     }
243
244     void
245     operator++(int)
246     {
247       ++*this;
248     }
249   };
250
251
252   /**
253    * @brief forward_iterator wrapper for pointer
254    * 
255    * This class takes a pointer and wraps it to provide exactly
256    * the requirements of a forward_iterator. It should not be
257    * instansiated directly, but generated from a test_container
258    */
259   template<class T>
260   struct forward_iterator_wrapper:public input_iterator_wrapper<T>
261   {
262     typedef BoundsContainer<T> ContainerType;
263     typedef std::forward_iterator_tag iterator_category;
264     forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
265       :input_iterator_wrapper<T>(_ptr, SharedInfo_in)
266     { }
267     
268     forward_iterator_wrapper(const forward_iterator_wrapper& in)
269       :input_iterator_wrapper<T>(in)
270     { }
271
272     forward_iterator_wrapper()
273     {
274       this->ptr = NULL;
275       this->SharedInfo = NULL;
276     }
277
278     T&
279     operator*() const
280     {
281       ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
282       return *(this->ptr);
283     }
284
285     T*
286     operator->() const
287     { return &**this; }
288
289     forward_iterator_wrapper&
290     operator++()
291     {
292       ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
293       this->ptr++;
294       return *this;
295     }
296
297     forward_iterator_wrapper
298     operator++(int)
299     {
300       forward_iterator_wrapper<T> tmp = *this;
301       ++*this;
302       return tmp;
303     }
304    };
305
306   /**
307    * @brief bidirectional_iterator wrapper for pointer
308    * 
309    * This class takes a pointer and wraps it to provide exactly
310    * the requirements of a forward_iterator. It should not be
311    * instansiated directly, but generated from a test_container
312    */
313   template<class T>
314   struct bidirectional_iterator_wrapper:public forward_iterator_wrapper<T>
315   {
316     typedef BoundsContainer<T> ContainerType;
317     typedef std::bidirectional_iterator_tag iterator_category;
318     bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
319       :forward_iterator_wrapper<T>(_ptr, SharedInfo_in)
320     { }
321
322     bidirectional_iterator_wrapper(const bidirectional_iterator_wrapper& in)
323       :forward_iterator_wrapper<T>(in)
324     { }
325
326     bidirectional_iterator_wrapper(): forward_iterator_wrapper<T>()
327     { }
328
329     bidirectional_iterator_wrapper&
330     operator=(const bidirectional_iterator_wrapper& in)
331     {
332       this->ptr = in.ptr;
333       this->SharedInfo = in.SharedInfo;
334       return *this;
335     }
336    
337     bidirectional_iterator_wrapper&
338     operator++()
339     {
340       ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
341       this->ptr++;
342       return *this;
343     }
344
345     bidirectional_iterator_wrapper
346     operator++(int)
347     {
348       bidirectional_iterator_wrapper<T> tmp = *this;
349       ++*this;
350       return tmp;
351     }
352
353     bidirectional_iterator_wrapper& 
354     operator--()
355     {
356       ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
357       this->ptr--;
358       return *this;
359     }
360
361     bidirectional_iterator_wrapper
362     operator--(int)
363     { 
364       bidirectional_iterator_wrapper<T> tmp = *this;
365       --*this;
366       return tmp;
367     }
368    };
369
370   /**
371    * @brief random_access_iterator wrapper for pointer
372    * 
373    * This class takes a pointer and wraps it to provide exactly
374    * the requirements of a forward_iterator. It should not be
375    * instansiated directly, but generated from a test_container
376    */
377   template<class T>
378   struct random_access_iterator_wrapper:public bidirectional_iterator_wrapper<T>
379   {
380     typedef BoundsContainer<T> ContainerType;
381     typedef std::random_access_iterator_tag iterator_category;
382     random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
383       : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in)
384     { }
385
386     random_access_iterator_wrapper(const random_access_iterator_wrapper<T>& in)
387       : bidirectional_iterator_wrapper<T>(in)
388     { }
389
390     random_access_iterator_wrapper():bidirectional_iterator_wrapper<T>()
391     { }
392
393     random_access_iterator_wrapper&
394     operator=(const random_access_iterator_wrapper& in)
395     {
396       this->ptr = in.ptr;
397       this->SharedInfo = in.SharedInfo;
398       return *this;
399     }
400
401     random_access_iterator_wrapper&
402     operator++()
403     {
404       ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
405       this->ptr++;
406       return *this;
407     }
408
409     random_access_iterator_wrapper
410     operator++(int)
411     {
412       random_access_iterator_wrapper<T> tmp = *this;
413       ++*this;
414       return tmp;
415     }
416
417     random_access_iterator_wrapper&
418     operator--()
419     {
420       ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
421       this->ptr--;
422       return *this;
423     }
424
425     random_access_iterator_wrapper
426     operator--(int)
427     {
428       random_access_iterator_wrapper<T> tmp = *this;
429       --*this;
430       return tmp;
431     }
432
433     random_access_iterator_wrapper&
434     operator+=(ptrdiff_t n)
435     {
436       if(n > 0)
437         {
438           ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr);
439           this->ptr += n;
440         }
441       else
442         {
443           ITERATOR_VERIFY(n <= this->ptr - this->SharedInfo->first);
444           this->ptr += n;
445         }
446       return *this;
447     }
448
449     random_access_iterator_wrapper&
450     operator-=(ptrdiff_t n)
451     { return *this += -n; }
452
453     random_access_iterator_wrapper
454     operator-(ptrdiff_t n) const
455     {
456       random_access_iterator_wrapper<T> tmp = *this;
457       return tmp -= n;
458     }
459
460     ptrdiff_t
461     operator-(const random_access_iterator_wrapper<T>& in) const
462     {
463       ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
464       return this->ptr - in.ptr;
465     }
466
467     T&
468     operator[](ptrdiff_t n) const
469     { return *(*this + n); }
470
471     bool
472     operator<(const random_access_iterator_wrapper<T>& in) const
473     {
474       ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
475       return this->ptr < in.ptr;
476     }
477
478     bool
479     operator>(const random_access_iterator_wrapper<T>& in) const
480     {
481       return in < *this;
482     }
483
484     bool
485     operator>=(const random_access_iterator_wrapper<T>& in) const
486     {
487       return !(*this < in);
488     }
489
490     bool 
491     operator<=(const random_access_iterator_wrapper<T>& in) const
492     {
493       return !(*this > in);
494     }
495    };
496
497   template<typename T>
498     random_access_iterator_wrapper<T>
499     operator+(random_access_iterator_wrapper<T> it, ptrdiff_t n)
500     { return it += n; }
501
502   template<typename T>
503     random_access_iterator_wrapper<T>
504     operator+(ptrdiff_t n, random_access_iterator_wrapper<T> it) 
505     { return it += n; }
506
507
508   /** 
509    * @brief A container-type class for holding iterator wrappers
510    * test_container takes two parameters, a class T and an iterator
511    * wrapper templated by T (for example forward_iterator_wrapper<T>.
512    * It takes two pointers representing a range and presents them as 
513    * a container of iterators.
514    */
515   template <class T, template<class T> class ItType>
516   struct test_container
517   {
518     typename ItType<T>::ContainerType bounds;
519     test_container(T* _first, T* _last):bounds(_first, _last)
520     { }
521
522     ItType<T>
523     it(int pos)
524     {
525       ITERATOR_VERIFY(pos >= 0 && pos <= (bounds.last - bounds.first));
526       return ItType<T>(bounds.first + pos, &bounds);
527     }
528
529     ItType<T>
530     it(T* pos)
531     {
532       ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last);
533       return ItType<T>(pos, &bounds);
534     }
535
536     ItType<T>
537     begin()
538     { return it(bounds.first); }
539
540     ItType<T>
541     end()
542     { return it(bounds.last); }
543    };
544 }
545 #endif