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