OSDN Git Service

2004-11-29 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 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 = 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       void
100       operator=(T& new_val)
101       {
102         ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
103         SharedInfo->writtento[ptr - SharedInfo->first] = 1;
104         ptr = new_val;
105       }
106     };
107
108   /**
109    * @brief output_iterator wrapper for pointer
110    * 
111    * This class takes a pointer and wraps it to provide exactly
112    * the requirements of a output_iterator. It should not be
113    * instansiated directly, but generated from a test_container
114    */
115   template<class T>
116   struct output_iterator_wrapper: public std::iterator
117   <std::output_iterator_tag, T, ptrdiff_t, T*, T&>
118   {
119     typedef OutputContainer<T> ContainerType;
120     T* ptr;
121     ContainerType* SharedInfo;
122
123     output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
124       :ptr(_ptr), SharedInfo(SharedInfo_in)
125     {
126       ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last);
127     }
128     
129     output_iterator_wrapper(const output_iterator_wrapper& in)
130       :ptr(in.ptr), SharedInfo(in.SharedInfo)
131     { }
132
133     WritableObject<T>
134     operator*() const
135     {
136       ITERATOR_VERIFY(ptr < SharedInfo->last);
137       ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == false);
138       return WritableObject<T>(ptr, SharedInfo);
139     }
140     
141     output_iterator_wrapper&
142     operator=(const output_iterator_wrapper& in) 
143     {
144       ptr = in.ptr;
145       SharedInfo = in.SharedInfo;
146     }
147
148     output_iterator_wrapper&
149     operator++()
150     {
151       ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
152       ITERATOR_VERIFY(ptr>=SharedInfo->first);
153       ptr++;
154       SharedInfo->first=ptr;
155       return *this;
156     }
157
158     output_iterator_wrapper
159     operator++(int)
160     {
161       output_iterator_wrapper<T> tmp = *this;
162       ++*this;
163       return tmp;
164     }
165
166   };
167
168   /**
169    * @brief input_iterator wrapper for pointer
170    * 
171    * This class takes a pointer and wraps it to provide exactly
172    * the requirements of a input_iterator. It should not be
173    * instansiated directly, but generated from a test_container
174    */
175   template<class T>
176   class input_iterator_wrapper:public std::iterator
177   <std::input_iterator_tag, T, ptrdiff_t, T*, T&>
178   {
179   protected:
180     input_iterator_wrapper()
181     { }
182
183   public:
184     typedef BoundsContainer<T> ContainerType;
185     T* ptr;
186     ContainerType* SharedInfo;
187
188     input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
189       : ptr(_ptr), SharedInfo(SharedInfo_in)
190     { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); }
191     
192     input_iterator_wrapper(const input_iterator_wrapper& in)
193       : ptr(in.ptr), SharedInfo(in.SharedInfo)
194     { }
195
196     bool
197     operator==(const input_iterator_wrapper& in) const
198     {
199       ITERATOR_VERIFY(SharedInfo != NULL && SharedInfo == in.SharedInfo);
200       ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first);
201       return ptr == in.ptr;
202     }
203
204     bool
205     operator!=(const input_iterator_wrapper& in) const
206     {
207       return !(*this == in);
208     }
209
210     T&
211     operator*() const
212     {
213       ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
214       ITERATOR_VERIFY(ptr >= SharedInfo->first);
215       return *ptr;
216     }
217
218     T*
219     operator->() const
220     {
221       return &**this;
222     }
223
224     input_iterator_wrapper&
225     operator=(const input_iterator_wrapper& in)
226     {
227       ptr = in.ptr;
228       SharedInfo = in.SharedInfo;
229       return *this;
230     }
231
232     input_iterator_wrapper&
233     operator++()
234     {
235       ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
236       ITERATOR_VERIFY(ptr>=SharedInfo->first);
237       ptr++;
238       SharedInfo->first=ptr;
239       return *this;
240     }
241
242     void
243     operator++(int)
244     {
245       ++*this;
246     }
247   };
248
249
250   /**
251    * @brief forward_iterator wrapper for pointer
252    * 
253    * This class takes a pointer and wraps it to provide exactly
254    * the requirements of a forward_iterator. It should not be
255    * instansiated directly, but generated from a test_container
256    */
257   template<class T>
258   struct forward_iterator_wrapper:public input_iterator_wrapper<T>
259   {
260     typedef BoundsContainer<T> ContainerType;
261     typedef std::forward_iterator_tag iterator_category;
262     forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
263       :input_iterator_wrapper<T>(_ptr, SharedInfo_in)
264     { }
265     
266     forward_iterator_wrapper(const forward_iterator_wrapper& in)
267       :input_iterator_wrapper<T>(in)
268     { }
269
270     forward_iterator_wrapper()
271     {
272       this->ptr = NULL;
273       this->SharedInfo = NULL;
274     }
275
276     T&
277     operator*() const
278     {
279       ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
280       return *(this->ptr);
281     }
282
283     T*
284     operator->() const
285     { return &**this; }
286
287     forward_iterator_wrapper&
288     operator++()
289     {
290       ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
291       this->ptr++;
292       return *this;
293     }
294
295     forward_iterator_wrapper
296     operator++(int)
297     {
298       forward_iterator_wrapper<T> tmp = *this;
299       ++*this;
300       return tmp;
301     }
302    };
303
304   /**
305    * @brief bidirectional_iterator wrapper for pointer
306    * 
307    * This class takes a pointer and wraps it to provide exactly
308    * the requirements of a forward_iterator. It should not be
309    * instansiated directly, but generated from a test_container
310    */
311   template<class T>
312   struct bidirectional_iterator_wrapper:public forward_iterator_wrapper<T>
313   {
314     typedef BoundsContainer<T> ContainerType;
315     typedef std::bidirectional_iterator_tag iterator_category;
316     bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
317       :forward_iterator_wrapper<T>(_ptr, SharedInfo_in)
318     { }
319
320     bidirectional_iterator_wrapper(const bidirectional_iterator_wrapper& in)
321       :forward_iterator_wrapper<T>(in)
322     { }
323
324     bidirectional_iterator_wrapper(): forward_iterator_wrapper<T>()
325     { }
326
327     bidirectional_iterator_wrapper&
328     operator=(const bidirectional_iterator_wrapper& in)
329     {
330       this->ptr = in.ptr;
331       this->SharedInfo = in.SharedInfo;
332       return *this;
333     }
334    
335     bidirectional_iterator_wrapper&
336     operator++()
337     {
338       ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
339       this->ptr++;
340       return *this;
341     }
342
343     bidirectional_iterator_wrapper
344     operator++(int)
345     {
346       bidirectional_iterator_wrapper<T> tmp = *this;
347       ++*this;
348       return tmp;
349     }
350
351     bidirectional_iterator_wrapper& 
352     operator--()
353     {
354       ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
355       this->ptr--;
356       return *this;
357     }
358
359     bidirectional_iterator_wrapper
360     operator--(int)
361     { 
362       bidirectional_iterator_wrapper<T> tmp = *this;
363       --*this;
364       return tmp;
365     }
366    };
367
368   /**
369    * @brief random_access_iterator wrapper for pointer
370    * 
371    * This class takes a pointer and wraps it to provide exactly
372    * the requirements of a forward_iterator. It should not be
373    * instansiated directly, but generated from a test_container
374    */
375   template<class T>
376   struct random_access_iterator_wrapper:public bidirectional_iterator_wrapper<T>
377   {
378     typedef BoundsContainer<T> ContainerType;
379     typedef std::random_access_iterator_tag iterator_category;
380     random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
381       : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in)
382     { }
383
384     random_access_iterator_wrapper(const random_access_iterator_wrapper<T>& in)
385       : bidirectional_iterator_wrapper<T>(in)
386     { }
387
388     random_access_iterator_wrapper():bidirectional_iterator_wrapper<T>()
389     { }
390
391     random_access_iterator_wrapper&
392     operator=(const random_access_iterator_wrapper& in)
393     {
394       this->ptr = in.ptr;
395       this->SharedInfo = in.SharedInfo;
396     }
397
398     random_access_iterator_wrapper&
399     operator++()
400     {
401       ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
402       this->ptr++;
403       return *this;
404     }
405
406     random_access_iterator_wrapper
407     operator++(int)
408     {
409       random_access_iterator_wrapper<T> tmp = *this;
410       ++*this;
411       return tmp;
412     }
413
414     random_access_iterator_wrapper&
415     operator--()
416     {
417       ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
418       this->ptr--;
419       return *this;
420     }
421
422     random_access_iterator_wrapper
423     operator--(int)
424     {
425       random_access_iterator_wrapper<T> tmp = *this;
426       ++*this;
427       return tmp;
428     }
429
430     random_access_iterator_wrapper&
431     operator+=(ptrdiff_t n)
432     {
433       if(n > 0)
434         {
435           ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr);
436           this->ptr += n;
437         }
438       else
439         {
440           ITERATOR_VERIFY(n <= this->ptr - this->SharedInfo->first);
441           this->ptr += n;
442         }
443       return *this;
444     }
445
446     random_access_iterator_wrapper
447     operator+(ptrdiff_t n)
448     {
449       random_access_iterator_wrapper<T> tmp = *this;
450       return tmp += n;
451     }
452
453     random_access_iterator_wrapper&
454     operator-=(ptrdiff_t n)
455     { return *this += -n; }
456
457     random_access_iterator_wrapper
458     operator-(ptrdiff_t n)
459     {
460       random_access_iterator_wrapper<T> tmp = *this;
461       return tmp -= n;
462     }
463
464     ptrdiff_t
465     operator-(const random_access_iterator_wrapper<T>& in)
466     {
467       ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
468       return this->ptr - in.ptr;
469     }
470
471     T&
472     operator[](ptrdiff_t n)
473     { return *(this + n); }
474
475     bool
476     operator<(const random_access_iterator_wrapper<T>& in) const
477     {
478       ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
479       return this->ptr < in.ptr;
480     }
481
482     bool
483     operator>(const random_access_iterator_wrapper<T>& in) const
484     {
485       return in < *this;
486     }
487
488     bool
489     operator>=(const random_access_iterator_wrapper<T>& in) const
490     {
491       return !(*this < in);
492     }
493
494     bool 
495     operator<=(const random_access_iterator_wrapper<T>& in) const
496     {
497       return !(*this > in);
498     }
499    };
500
501
502   /** 
503    * @brief A container-type class for holding iterator wrappers
504    * test_container takes two parameters, a class T and an iterator
505    * wrapper templated by T (for example forward_iterator_wrapper<T>.
506    * It takes two pointers representing a range and presents them as 
507    * a container of iterators.
508    */
509   template <class T, template<class T> class ItType>
510   struct test_container
511   {
512     typename ItType<T>::ContainerType bounds;
513     test_container(T* _first, T* _last):bounds(_first, _last)
514     { }
515
516     ItType<T>
517     it(int pos)
518     {
519       ITERATOR_VERIFY(pos >= 0 && pos <= (bounds.last - bounds.first));
520       return ItType<T>(bounds.first + pos, &bounds);
521     }
522
523     ItType<T>
524     it(T* pos)
525     {
526       ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last);
527       return ItType<T>(pos, &bounds);
528     }
529
530     ItType<T>
531     begin()
532     { return it(bounds.first); }
533
534     ItType<T>
535     end()
536     { return it(bounds.last); }
537    };
538 }
539 #endif