2 // Iterator Wrappers for the C++ library testsuite.
4 // Copyright (C) 2004-2019 Free Software Foundation, Inc.
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)
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.
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/>.
22 // This file provides the following:
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.
30 #include <testsuite_hooks.h>
31 #include <bits/stl_iterator_base_types.h>
33 #if __cplusplus >= 201103L
34 #include <bits/move.h>
37 #ifndef _TESTSUITE_ITERATORS
38 #define _TESTSUITE_ITERATORS
40 #ifdef DISABLE_ITERATOR_DEBUG
41 #define ITERATOR_VERIFY(x)
43 #define ITERATOR_VERIFY(x) VERIFY(x)
49 * @brief Simple container for holding two pointers.
51 * Note that input_iterator_wrapper changes first to denote
52 * how the valid range of == , ++, etc. change as the iterators are used.
55 struct BoundsContainer
59 BoundsContainer(T
* _first
, T
* _last
) : first(_first
), last(_last
)
63 // Simple container for holding state of a set of output iterators.
65 struct OutputContainer
: public BoundsContainer
<T
>
69 OutputContainer(T
* _first
, T
* _last
)
70 : BoundsContainer
<T
>(_first
, _last
), incrementedto(_first
)
72 writtento
= new bool[this->last
- this->first
];
73 for(int i
= 0; i
< this->last
- this->first
; i
++)
78 { delete[] writtento
; }
81 // Produced by output_iterator to allow limited writing to pointer
88 OutputContainer
<T
>* SharedInfo
;
89 WritableObject(T
* ptr_in
,OutputContainer
<T
>* SharedInfo_in
):
90 ptr(ptr_in
), SharedInfo(SharedInfo_in
)
93 #if __cplusplus >= 201103L
96 operator=(U
&& new_val
)
98 ITERATOR_VERIFY(SharedInfo
->writtento
[ptr
- SharedInfo
->first
] == 0);
99 SharedInfo
->writtento
[ptr
- SharedInfo
->first
] = 1;
100 *ptr
= std::forward
<U
>(new_val
);
105 operator=(const U
& new_val
)
107 ITERATOR_VERIFY(SharedInfo
->writtento
[ptr
- SharedInfo
->first
] == 0);
108 SharedInfo
->writtento
[ptr
- SharedInfo
->first
] = 1;
115 * @brief output_iterator wrapper for pointer
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
122 struct output_iterator_wrapper
123 : public std::iterator
<std::output_iterator_tag
, T
, std::ptrdiff_t, T
*, T
&>
125 typedef OutputContainer
<T
> ContainerType
;
127 ContainerType
* SharedInfo
;
129 output_iterator_wrapper(T
* _ptr
, ContainerType
* SharedInfo_in
)
130 : ptr(_ptr
), SharedInfo(SharedInfo_in
)
132 ITERATOR_VERIFY(ptr
>= SharedInfo
->first
&& ptr
<= SharedInfo
->last
);
135 output_iterator_wrapper(const output_iterator_wrapper
& in
)
136 : ptr(in
.ptr
), SharedInfo(in
.SharedInfo
)
142 ITERATOR_VERIFY(ptr
< SharedInfo
->last
);
143 ITERATOR_VERIFY(SharedInfo
->writtento
[ptr
- SharedInfo
->first
] == false);
144 return WritableObject
<T
>(ptr
, SharedInfo
);
147 output_iterator_wrapper
&
148 operator=(const output_iterator_wrapper
& in
)
151 SharedInfo
= in
.SharedInfo
;
155 output_iterator_wrapper
&
158 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
159 ITERATOR_VERIFY(ptr
>=SharedInfo
->incrementedto
);
161 SharedInfo
->incrementedto
=ptr
;
165 output_iterator_wrapper
168 output_iterator_wrapper
<T
> tmp
= *this;
173 #if __cplusplus >= 201103L
175 void operator,(const U
&) const = delete;
179 void operator,(const U
&) const;
183 #if __cplusplus >= 201103L
184 template<typename T
, typename U
>
185 void operator,(const T
&, const output_iterator_wrapper
<U
>&) = delete;
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
; };
194 * @brief input_iterator wrapper for pointer
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
201 class input_iterator_wrapper
202 : public std::iterator
<std::input_iterator_tag
, typename remove_cv
<T
>::type
,
203 std::ptrdiff_t, T
*, T
&>
206 input_iterator_wrapper()
210 typedef BoundsContainer
<T
> ContainerType
;
212 ContainerType
* SharedInfo
;
214 input_iterator_wrapper(T
* _ptr
, ContainerType
* SharedInfo_in
)
215 : ptr(_ptr
), SharedInfo(SharedInfo_in
)
216 { ITERATOR_VERIFY(ptr
>= SharedInfo
->first
&& ptr
<= SharedInfo
->last
); }
218 input_iterator_wrapper(const input_iterator_wrapper
& in
)
219 : ptr(in
.ptr
), SharedInfo(in
.SharedInfo
)
223 operator==(const input_iterator_wrapper
& in
) const
225 ITERATOR_VERIFY(SharedInfo
&& SharedInfo
== in
.SharedInfo
);
226 ITERATOR_VERIFY(ptr
>=SharedInfo
->first
&& in
.ptr
>=SharedInfo
->first
);
227 return ptr
== in
.ptr
;
231 operator!=(const input_iterator_wrapper
& in
) const
233 return !(*this == in
);
239 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
240 ITERATOR_VERIFY(ptr
>= SharedInfo
->first
);
250 input_iterator_wrapper
&
251 operator=(const input_iterator_wrapper
& in
)
254 SharedInfo
= in
.SharedInfo
;
258 input_iterator_wrapper
&
261 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
262 ITERATOR_VERIFY(ptr
>=SharedInfo
->first
);
264 SharedInfo
->first
=ptr
;
274 #if __cplusplus >= 201103L
276 void operator,(const U
&) const = delete;
280 void operator,(const U
&) const;
284 #if __cplusplus >= 201103L
285 template<typename T
, typename U
>
286 void operator,(const T
&, const input_iterator_wrapper
<U
>&) = delete;
290 * @brief forward_iterator wrapper for pointer
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
297 struct forward_iterator_wrapper
: public input_iterator_wrapper
<T
>
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
)
305 forward_iterator_wrapper(const forward_iterator_wrapper
& in
)
306 : input_iterator_wrapper
<T
>(in
)
309 forward_iterator_wrapper()
312 this->SharedInfo
= 0;
318 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
326 forward_iterator_wrapper
&
329 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
334 forward_iterator_wrapper
337 forward_iterator_wrapper
<T
> tmp
= *this;
344 * @brief bidirectional_iterator wrapper for pointer
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
351 struct bidirectional_iterator_wrapper
: public forward_iterator_wrapper
<T
>
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
)
359 bidirectional_iterator_wrapper(const bidirectional_iterator_wrapper
& in
)
360 : forward_iterator_wrapper
<T
>(in
)
363 bidirectional_iterator_wrapper(): forward_iterator_wrapper
<T
>()
366 bidirectional_iterator_wrapper
&
367 operator=(const bidirectional_iterator_wrapper
& in
)
370 this->SharedInfo
= in
.SharedInfo
;
374 bidirectional_iterator_wrapper
&
377 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
382 bidirectional_iterator_wrapper
385 bidirectional_iterator_wrapper
<T
> tmp
= *this;
390 bidirectional_iterator_wrapper
&
393 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
> this->SharedInfo
->first
);
398 bidirectional_iterator_wrapper
401 bidirectional_iterator_wrapper
<T
> tmp
= *this;
408 * @brief random_access_iterator wrapper for pointer
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
415 struct random_access_iterator_wrapper
416 : public bidirectional_iterator_wrapper
<T
>
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
)
424 random_access_iterator_wrapper(const random_access_iterator_wrapper
<T
>& in
)
425 : bidirectional_iterator_wrapper
<T
>(in
)
428 random_access_iterator_wrapper():bidirectional_iterator_wrapper
<T
>()
431 random_access_iterator_wrapper
&
432 operator=(const random_access_iterator_wrapper
& in
)
435 this->SharedInfo
= in
.SharedInfo
;
439 random_access_iterator_wrapper
&
442 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
447 random_access_iterator_wrapper
450 random_access_iterator_wrapper
<T
> tmp
= *this;
455 random_access_iterator_wrapper
&
458 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
> this->SharedInfo
->first
);
463 random_access_iterator_wrapper
466 random_access_iterator_wrapper
<T
> tmp
= *this;
471 random_access_iterator_wrapper
&
472 operator+=(std::ptrdiff_t n
)
476 ITERATOR_VERIFY(n
<= this->SharedInfo
->last
- this->ptr
);
481 ITERATOR_VERIFY(n
<= this->ptr
- this->SharedInfo
->first
);
487 random_access_iterator_wrapper
&
488 operator-=(std::ptrdiff_t n
)
489 { return *this += -n
; }
491 random_access_iterator_wrapper
492 operator-(std::ptrdiff_t n
) const
494 random_access_iterator_wrapper
<T
> tmp
= *this;
499 operator-(const random_access_iterator_wrapper
<T
>& in
) const
501 ITERATOR_VERIFY(this->SharedInfo
== in
.SharedInfo
);
502 return this->ptr
- in
.ptr
;
506 operator[](std::ptrdiff_t n
) const
507 { return *(*this + n
); }
510 operator<(const random_access_iterator_wrapper
<T
>& in
) const
512 ITERATOR_VERIFY(this->SharedInfo
== in
.SharedInfo
);
513 return this->ptr
< in
.ptr
;
517 operator>(const random_access_iterator_wrapper
<T
>& in
) const
523 operator>=(const random_access_iterator_wrapper
<T
>& in
) const
525 return !(*this < in
);
529 operator<=(const random_access_iterator_wrapper
<T
>& in
) const
531 return !(*this > in
);
536 random_access_iterator_wrapper
<T
>
537 operator+(random_access_iterator_wrapper
<T
> it
, std::ptrdiff_t n
)
541 random_access_iterator_wrapper
<T
>
542 operator+(std::ptrdiff_t n
, random_access_iterator_wrapper
<T
> it
)
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.
553 template <class T
, template<class TT
> class ItType
>
554 struct test_container
556 typename ItType
<T
>::ContainerType bounds
;
557 test_container(T
* _first
, T
* _last
) : bounds(_first
, _last
)
560 #if __cplusplus >= 201103L
561 template<std::size_t N
>
563 test_container(T (&arr
)[N
]) : test_container(arr
, arr
+N
)
570 ITERATOR_VERIFY(pos
>= 0 && pos
<= (bounds
.last
- bounds
.first
));
571 return ItType
<T
>(bounds
.first
+ pos
, &bounds
);
577 ITERATOR_VERIFY(pos
>= bounds
.first
&& pos
<= bounds
.last
);
578 return ItType
<T
>(pos
, &bounds
);
583 { return (bounds
.first
)[pos
]; }
587 { return it(bounds
.first
); }
591 { return it(bounds
.last
); }
595 { return bounds
.last
- bounds
.first
; }