OSDN Git Service

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