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
60 BoundsContainer(T
* _first
, T
* _last
) : first(_first
), last(_last
)
63 std::size_t size() const { return last
- first
; }
66 // Simple container for holding state of a set of output iterators.
68 struct OutputContainer
: public BoundsContainer
<T
>
73 OutputContainer(T
* _first
, T
* _last
)
74 : BoundsContainer
<T
>(_first
, _last
), incrementedto(_first
),
75 writtento(new bool[this->size()]())
79 { delete[] writtento
; }
82 // Produced by output_iterator to allow limited writing to pointer
89 OutputContainer
<T
>* SharedInfo
;
91 WritableObject(T
* ptr_in
, OutputContainer
<T
>* SharedInfo_in
):
92 ptr(ptr_in
), SharedInfo(SharedInfo_in
)
95 #if __cplusplus >= 201103L
97 typename
std::enable_if
<std::is_assignable
<T
&, U
>::value
>::type
98 operator=(U
&& new_val
)
100 ITERATOR_VERIFY(SharedInfo
->writtento
[ptr
- SharedInfo
->first
] == 0);
101 SharedInfo
->writtento
[ptr
- SharedInfo
->first
] = 1;
102 *ptr
= std::forward
<U
>(new_val
);
107 operator=(const U
& new_val
)
109 ITERATOR_VERIFY(SharedInfo
->writtento
[ptr
- SharedInfo
->first
] == 0);
110 SharedInfo
->writtento
[ptr
- SharedInfo
->first
] = 1;
117 * @brief output_iterator wrapper for pointer
119 * This class takes a pointer and wraps it to provide exactly
120 * the requirements of a output_iterator. It should not be
121 * instantiated directly, but generated from a test_container
124 struct output_iterator_wrapper
125 : public std::iterator
<std::output_iterator_tag
, T
, std::ptrdiff_t, T
*, T
&>
127 typedef OutputContainer
<T
> ContainerType
;
129 ContainerType
* SharedInfo
;
131 output_iterator_wrapper(T
* _ptr
, ContainerType
* SharedInfo_in
)
132 : ptr(_ptr
), SharedInfo(SharedInfo_in
)
134 ITERATOR_VERIFY(ptr
>= SharedInfo
->first
&& ptr
<= SharedInfo
->last
);
137 #if __cplusplus >= 201103L
138 output_iterator_wrapper() = delete;
140 output_iterator_wrapper(const output_iterator_wrapper
&) = default;
142 output_iterator_wrapper
&
143 operator=(const output_iterator_wrapper
&) = default;
149 ITERATOR_VERIFY(ptr
< SharedInfo
->last
);
150 ITERATOR_VERIFY(SharedInfo
->writtento
[ptr
- SharedInfo
->first
] == false);
151 return WritableObject
<T
>(ptr
, SharedInfo
);
154 output_iterator_wrapper
&
157 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
158 ITERATOR_VERIFY(ptr
>=SharedInfo
->incrementedto
);
160 SharedInfo
->incrementedto
=ptr
;
164 output_iterator_wrapper
167 output_iterator_wrapper
<T
> tmp
= *this;
172 #if __cplusplus >= 201103L
174 void operator,(const U
&) const = delete;
178 void operator,(const U
&) const;
182 #if __cplusplus >= 201103L
183 template<typename T
, typename U
>
184 void operator,(const T
&, const output_iterator_wrapper
<U
>&) = delete;
187 #if __cplusplus >= 2011L
188 using std::remove_cv
;
190 template<typename T
> struct remove_cv
{ typedef T type
; };
191 template<typename T
> struct remove_cv
<const T
> { typedef T type
; };
192 template<typename T
> struct remove_cv
<volatile T
> { typedef T type
; };
193 template<typename T
> struct remove_cv
<const volatile T
> { typedef T type
; };
197 * @brief input_iterator wrapper for pointer
199 * This class takes a pointer and wraps it to provide exactly
200 * the requirements of a input_iterator. It should not be
201 * instantiated directly, but generated from a test_container
204 class input_iterator_wrapper
205 : public std::iterator
<std::input_iterator_tag
, typename remove_cv
<T
>::type
,
206 std::ptrdiff_t, T
*, T
&>
209 input_iterator_wrapper() : ptr(0), SharedInfo(0)
213 typedef BoundsContainer
<T
> ContainerType
;
215 ContainerType
* SharedInfo
;
217 input_iterator_wrapper(T
* _ptr
, ContainerType
* SharedInfo_in
)
218 : ptr(_ptr
), SharedInfo(SharedInfo_in
)
219 { ITERATOR_VERIFY(ptr
>= SharedInfo
->first
&& ptr
<= SharedInfo
->last
); }
221 #if __cplusplus >= 201103L
222 input_iterator_wrapper(const input_iterator_wrapper
&) = default;
224 input_iterator_wrapper
&
225 operator=(const input_iterator_wrapper
&) = default;
229 operator==(const input_iterator_wrapper
& in
) const
231 ITERATOR_VERIFY(SharedInfo
&& SharedInfo
== in
.SharedInfo
);
232 ITERATOR_VERIFY(ptr
>=SharedInfo
->first
&& in
.ptr
>=SharedInfo
->first
);
233 return ptr
== in
.ptr
;
237 operator!=(const input_iterator_wrapper
& in
) const
239 return !(*this == in
);
245 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
246 ITERATOR_VERIFY(ptr
>= SharedInfo
->first
);
256 input_iterator_wrapper
&
259 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
260 ITERATOR_VERIFY(ptr
>=SharedInfo
->first
);
262 SharedInfo
->first
=ptr
;
272 #if __cplusplus >= 201103L
274 void operator,(const U
&) const = delete;
278 void operator,(const U
&) const;
282 #if __cplusplus >= 201103L
283 template<typename T
, typename U
>
284 void operator,(const T
&, const input_iterator_wrapper
<U
>&) = delete;
288 * @brief forward_iterator wrapper for pointer
290 * This class takes a pointer and wraps it to provide exactly
291 * the requirements of a forward_iterator. It should not be
292 * instantiated directly, but generated from a test_container
295 struct forward_iterator_wrapper
: public input_iterator_wrapper
<T
>
297 typedef BoundsContainer
<T
> ContainerType
;
298 typedef std::forward_iterator_tag iterator_category
;
300 forward_iterator_wrapper(T
* _ptr
, ContainerType
* SharedInfo_in
)
301 : input_iterator_wrapper
<T
>(_ptr
, SharedInfo_in
)
304 forward_iterator_wrapper()
307 #if __cplusplus >= 201103L
308 forward_iterator_wrapper(const forward_iterator_wrapper
&) = default;
310 forward_iterator_wrapper
&
311 operator=(const forward_iterator_wrapper
&) = default;
317 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
325 forward_iterator_wrapper
&
328 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
333 forward_iterator_wrapper
336 forward_iterator_wrapper
<T
> tmp
= *this;
343 * @brief bidirectional_iterator wrapper for pointer
345 * This class takes a pointer and wraps it to provide exactly
346 * the requirements of a bidirectional_iterator. It should not be
347 * instantiated directly, but generated from a test_container
350 struct bidirectional_iterator_wrapper
: public forward_iterator_wrapper
<T
>
352 typedef BoundsContainer
<T
> ContainerType
;
353 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()
360 : forward_iterator_wrapper
<T
>()
363 #if __cplusplus >= 201103L
364 bidirectional_iterator_wrapper(
365 const bidirectional_iterator_wrapper
&) = default;
367 bidirectional_iterator_wrapper
&
368 operator=(const bidirectional_iterator_wrapper
&) = default;
371 bidirectional_iterator_wrapper
&
374 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
379 bidirectional_iterator_wrapper
382 bidirectional_iterator_wrapper
<T
> tmp
= *this;
387 bidirectional_iterator_wrapper
&
390 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
> this->SharedInfo
->first
);
395 bidirectional_iterator_wrapper
398 bidirectional_iterator_wrapper
<T
> tmp
= *this;
405 * @brief random_access_iterator wrapper for pointer
407 * This class takes a pointer and wraps it to provide exactly
408 * the requirements of a random_access_iterator. It should not be
409 * instantiated directly, but generated from a test_container
412 struct random_access_iterator_wrapper
413 : public bidirectional_iterator_wrapper
<T
>
415 typedef BoundsContainer
<T
> ContainerType
;
416 typedef std::random_access_iterator_tag iterator_category
;
418 random_access_iterator_wrapper(T
* _ptr
, ContainerType
* SharedInfo_in
)
419 : bidirectional_iterator_wrapper
<T
>(_ptr
, SharedInfo_in
)
422 random_access_iterator_wrapper()
423 : bidirectional_iterator_wrapper
<T
>()
426 #if __cplusplus >= 201103L
427 random_access_iterator_wrapper(
428 const random_access_iterator_wrapper
&) = default;
430 random_access_iterator_wrapper
&
431 operator=(const random_access_iterator_wrapper
&) = default;
434 random_access_iterator_wrapper
&
437 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
442 random_access_iterator_wrapper
445 random_access_iterator_wrapper
<T
> tmp
= *this;
450 random_access_iterator_wrapper
&
453 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
> this->SharedInfo
->first
);
458 random_access_iterator_wrapper
461 random_access_iterator_wrapper
<T
> tmp
= *this;
466 random_access_iterator_wrapper
&
467 operator+=(std::ptrdiff_t n
)
471 ITERATOR_VERIFY(n
<= this->SharedInfo
->last
- this->ptr
);
476 ITERATOR_VERIFY(n
<= this->ptr
- this->SharedInfo
->first
);
482 random_access_iterator_wrapper
&
483 operator-=(std::ptrdiff_t n
)
484 { return *this += -n
; }
486 random_access_iterator_wrapper
487 operator-(std::ptrdiff_t n
) const
489 random_access_iterator_wrapper
<T
> tmp
= *this;
494 operator-(const random_access_iterator_wrapper
<T
>& in
) const
496 ITERATOR_VERIFY(this->SharedInfo
== in
.SharedInfo
);
497 return this->ptr
- in
.ptr
;
501 operator[](std::ptrdiff_t n
) const
502 { return *(*this + n
); }
505 operator<(const random_access_iterator_wrapper
<T
>& in
) const
507 ITERATOR_VERIFY(this->SharedInfo
== in
.SharedInfo
);
508 return this->ptr
< in
.ptr
;
512 operator>(const random_access_iterator_wrapper
<T
>& in
) const
518 operator>=(const random_access_iterator_wrapper
<T
>& in
) const
520 return !(*this < in
);
524 operator<=(const random_access_iterator_wrapper
<T
>& in
) const
526 return !(*this > in
);
531 random_access_iterator_wrapper
<T
>
532 operator+(random_access_iterator_wrapper
<T
> it
, std::ptrdiff_t n
)
536 random_access_iterator_wrapper
<T
>
537 operator+(std::ptrdiff_t n
, random_access_iterator_wrapper
<T
> it
)
542 * @brief A container-type class for holding iterator wrappers
543 * test_container takes two parameters, a class T and an iterator
544 * wrapper templated by T (for example forward_iterator_wrapper<T>.
545 * It takes two pointers representing a range and presents them as
546 * a container of iterators.
548 template <class T
, template<class TT
> class ItType
>
549 struct test_container
551 typename ItType
<T
>::ContainerType bounds
;
553 test_container(T
* _first
, T
* _last
) : bounds(_first
, _last
)
556 #if __cplusplus >= 201103L
557 template<std::size_t N
>
559 test_container(T (&arr
)[N
]) : test_container(arr
, arr
+N
)
566 ITERATOR_VERIFY(pos
>= 0 && pos
<= size());
567 return ItType
<T
>(bounds
.first
+ pos
, &bounds
);
573 ITERATOR_VERIFY(pos
>= bounds
.first
&& pos
<= bounds
.last
);
574 return ItType
<T
>(pos
, &bounds
);
579 { return (bounds
.first
)[pos
]; }
583 { return it(bounds
.first
); }
587 { return it(bounds
.last
); }
591 { return bounds
.size(); }
594 #if __cplusplus > 201703L
596 struct contiguous_iterator_wrapper
597 : random_access_iterator_wrapper
<T
>
599 using random_access_iterator_wrapper
<T
>::random_access_iterator_wrapper
;
601 using iterator_concept
= std::contiguous_iterator_tag
;
603 contiguous_iterator_wrapper
&
606 random_access_iterator_wrapper
<T
>::operator++();
610 contiguous_iterator_wrapper
&
613 random_access_iterator_wrapper
<T
>::operator--();
617 contiguous_iterator_wrapper
625 contiguous_iterator_wrapper
633 contiguous_iterator_wrapper
&
634 operator+=(std::ptrdiff_t n
)
636 random_access_iterator_wrapper
<T
>::operator+=(n
);
640 friend contiguous_iterator_wrapper
641 operator+(contiguous_iterator_wrapper iter
, std::ptrdiff_t n
)
642 { return iter
+= n
; }
644 friend contiguous_iterator_wrapper
645 operator+(std::ptrdiff_t n
, contiguous_iterator_wrapper iter
)
646 { return iter
+= n
; }
648 contiguous_iterator_wrapper
&
649 operator-=(std::ptrdiff_t n
)
650 { return *this += -n
; }
652 friend contiguous_iterator_wrapper
653 operator-(contiguous_iterator_wrapper iter
, std::ptrdiff_t n
)
654 { return iter
-= n
; }
657 // A type meeting the minimum std::range requirements
658 template<typename T
, template<typename
> class Iter
>
661 // Adds default constructor to Iter<T> if needed
662 struct iterator
: Iter
<T
>
666 iterator() : Iter
<T
>(nullptr, nullptr) { }
668 using Iter
<T
>::operator++;
670 iterator
& operator++() { Iter
<T
>::operator++(); return *this; }
678 friend bool operator==(const sentinel
& s
, const I
& i
)
679 { return s
.end
== i
.ptr
; }
681 friend bool operator!=(const sentinel
& s
, const I
& i
)
682 { return !(s
== i
); }
684 friend bool operator==(const I
& i
, const sentinel
& s
)
687 friend bool operator!=(const I
& i
, const sentinel
& s
)
688 { return !(s
== i
); }
694 if constexpr (std::default_constructible
<Iter
<T
>>)
695 return Iter
<T
>(p
, &bounds
);
697 return iterator(p
, &bounds
);
701 test_range(T
* first
, T
* last
) : bounds(first
, last
)
704 template<std::size_t N
>
706 test_range(T (&arr
)[N
]) : test_range(arr
, arr
+N
)
709 auto begin() & { return get_iterator(bounds
.first
); }
713 using I
= decltype(get_iterator(bounds
.last
));
714 if constexpr (std::sentinel_for
<I
, I
>)
715 return get_iterator(bounds
.last
);
717 return sentinel
<I
>{bounds
.last
};
720 typename Iter
<T
>::ContainerType bounds
;
723 // A type meeting the minimum std::sized_range requirements
724 template<typename T
, template<typename
> class Iter
>
725 struct test_sized_range
: test_range
<T
, Iter
>
727 using test_range
<T
, Iter
>::test_range
;
729 std::size_t size() const noexcept
730 { return this->bounds
.size(); }
733 } // namespace __gnu_test
734 #endif // _TESTSUITE_ITERATORS