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