| // -*- C++ -*- |
| // Iterator Wrappers for the C++ library testsuite. |
| // |
| // Copyright (C) 2004, 2005 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 2, or (at your option) |
| // any later version. |
| // |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| // |
| // You should have received a copy of the GNU General Public License along |
| // with this library; see the file COPYING. If not, write to the Free |
| // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
| // USA. |
| // |
| // As a special exception, you may use this file as part of a free software |
| // library without restriction. Specifically, if other files instantiate |
| // templates or use macros or inline functions from this file, or you compile |
| // this file and link it with other files to produce an executable, this |
| // file does not by itself cause the resulting executable to be covered by |
| // the GNU General Public License. This exception does not however |
| // invalidate any other reasons why the executable file might be covered by |
| // the GNU General Public License. |
| |
| // This file provides the following: |
| // |
| // input_iterator_wrapper, output_iterator_wrapper |
| // forward_iterator_wrapper, bidirectional_iterator_wrapper and |
| // random_access_wrapper, which attempt to exactly perform the requirements |
| // of these types of iterators. These are constructed from the class |
| // test_container, which is given two pointers to T and an iterator type. |
| |
| #include <testsuite_hooks.h> |
| #include <iterator> |
| |
| #ifndef _TESTSUITE_ITERATORS |
| #define _TESTSUITE_ITERATORS |
| |
| #ifdef DISABLE_ITERATOR_DEBUG |
| #define ITERATOR_VERIFY(x) |
| #else |
| #define ITERATOR_VERIFY(x) VERIFY(x) |
| #endif |
| |
| namespace __gnu_test |
| { |
| /** |
| * @brief Simple container for holding two pointers. |
| * |
| * Note that input_iterator_wrapper changes first to denote |
| * how the valid range of == , ++, etc. change as the iterators are used. |
| */ |
| template<typename T> |
| struct BoundsContainer |
| { |
| T* first; |
| T* last; |
| BoundsContainer(T* _first, T* _last) |
| : first(_first), last(_last) |
| { } |
| }; |
| |
| // Simple container for holding state of a set of output iterators. |
| template<typename T> |
| struct OutputContainer : public BoundsContainer<T> |
| { |
| T* incrementedto; |
| bool* writtento; |
| OutputContainer(T* _first, T* _last) |
| : BoundsContainer<T>(_first, _last), incrementedto(_first) |
| { |
| writtento = new bool[this->last - this->first]; |
| for(int i = 0; i < this->last - this->first; i++) |
| writtento[i] = false; |
| } |
| |
| ~OutputContainer() |
| { delete[] writtento; } |
| }; |
| |
| // Produced by output_iterator to allow limited writing to pointer |
| template<class T> |
| class WritableObject |
| { |
| T* ptr; |
| |
| public: |
| OutputContainer<T>* SharedInfo; |
| WritableObject(T* ptr_in,OutputContainer<T>* SharedInfo_in): |
| ptr(ptr_in), SharedInfo(SharedInfo_in) |
| { } |
| |
| template<class U> |
| void |
| operator=(const U& new_val) |
| { |
| ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0); |
| SharedInfo->writtento[ptr - SharedInfo->first] = 1; |
| *ptr = new_val; |
| } |
| }; |
| |
| /** |
| * @brief output_iterator wrapper for pointer |
| * |
| * This class takes a pointer and wraps it to provide exactly |
| * the requirements of a output_iterator. It should not be |
| * instansiated directly, but generated from a test_container |
| */ |
| template<class T> |
| struct output_iterator_wrapper: public std::iterator |
| <std::output_iterator_tag, T, ptrdiff_t, T*, T&> |
| { |
| typedef OutputContainer<T> ContainerType; |
| T* ptr; |
| ContainerType* SharedInfo; |
| |
| output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
| :ptr(_ptr), SharedInfo(SharedInfo_in) |
| { |
| ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); |
| } |
| |
| output_iterator_wrapper(const output_iterator_wrapper& in) |
| :ptr(in.ptr), SharedInfo(in.SharedInfo) |
| { } |
| |
| WritableObject<T> |
| operator*() const |
| { |
| ITERATOR_VERIFY(ptr < SharedInfo->last); |
| ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == false); |
| return WritableObject<T>(ptr, SharedInfo); |
| } |
| |
| output_iterator_wrapper& |
| operator=(const output_iterator_wrapper& in) |
| { |
| ptr = in.ptr; |
| SharedInfo = in.SharedInfo; |
| return *this; |
| } |
| |
| output_iterator_wrapper& |
| operator++() |
| { |
| ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); |
| ITERATOR_VERIFY(ptr>=SharedInfo->incrementedto); |
| ptr++; |
| SharedInfo->incrementedto=ptr; |
| return *this; |
| } |
| |
| output_iterator_wrapper |
| operator++(int) |
| { |
| output_iterator_wrapper<T> tmp = *this; |
| ++*this; |
| return tmp; |
| } |
| |
| }; |
| |
| /** |
| * @brief input_iterator wrapper for pointer |
| * |
| * This class takes a pointer and wraps it to provide exactly |
| * the requirements of a input_iterator. It should not be |
| * instansiated directly, but generated from a test_container |
| */ |
| template<class T> |
| class input_iterator_wrapper:public std::iterator |
| <std::input_iterator_tag, T, ptrdiff_t, T*, T&> |
| { |
| protected: |
| input_iterator_wrapper() |
| { } |
| |
| public: |
| typedef BoundsContainer<T> ContainerType; |
| T* ptr; |
| ContainerType* SharedInfo; |
| |
| input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
| : ptr(_ptr), SharedInfo(SharedInfo_in) |
| { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); } |
| |
| input_iterator_wrapper(const input_iterator_wrapper& in) |
| : ptr(in.ptr), SharedInfo(in.SharedInfo) |
| { } |
| |
| bool |
| operator==(const input_iterator_wrapper& in) const |
| { |
| ITERATOR_VERIFY(SharedInfo != NULL && SharedInfo == in.SharedInfo); |
| ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first); |
| return ptr == in.ptr; |
| } |
| |
| bool |
| operator!=(const input_iterator_wrapper& in) const |
| { |
| return !(*this == in); |
| } |
| |
| T& |
| operator*() const |
| { |
| ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); |
| ITERATOR_VERIFY(ptr >= SharedInfo->first); |
| return *ptr; |
| } |
| |
| T* |
| operator->() const |
| { |
| return &**this; |
| } |
| |
| input_iterator_wrapper& |
| operator=(const input_iterator_wrapper& in) |
| { |
| ptr = in.ptr; |
| SharedInfo = in.SharedInfo; |
| return *this; |
| } |
| |
| input_iterator_wrapper& |
| operator++() |
| { |
| ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last); |
| ITERATOR_VERIFY(ptr>=SharedInfo->first); |
| ptr++; |
| SharedInfo->first=ptr; |
| return *this; |
| } |
| |
| void |
| operator++(int) |
| { |
| ++*this; |
| } |
| }; |
| |
| |
| /** |
| * @brief forward_iterator wrapper for pointer |
| * |
| * This class takes a pointer and wraps it to provide exactly |
| * the requirements of a forward_iterator. It should not be |
| * instansiated directly, but generated from a test_container |
| */ |
| template<class T> |
| struct forward_iterator_wrapper:public input_iterator_wrapper<T> |
| { |
| typedef BoundsContainer<T> ContainerType; |
| typedef std::forward_iterator_tag iterator_category; |
| forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
| :input_iterator_wrapper<T>(_ptr, SharedInfo_in) |
| { } |
| |
| forward_iterator_wrapper(const forward_iterator_wrapper& in) |
| :input_iterator_wrapper<T>(in) |
| { } |
| |
| forward_iterator_wrapper() |
| { |
| this->ptr = NULL; |
| this->SharedInfo = NULL; |
| } |
| |
| T& |
| operator*() const |
| { |
| ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); |
| return *(this->ptr); |
| } |
| |
| T* |
| operator->() const |
| { return &**this; } |
| |
| forward_iterator_wrapper& |
| operator++() |
| { |
| ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); |
| this->ptr++; |
| return *this; |
| } |
| |
| forward_iterator_wrapper |
| operator++(int) |
| { |
| forward_iterator_wrapper<T> tmp = *this; |
| ++*this; |
| return tmp; |
| } |
| }; |
| |
| /** |
| * @brief bidirectional_iterator wrapper for pointer |
| * |
| * This class takes a pointer and wraps it to provide exactly |
| * the requirements of a forward_iterator. It should not be |
| * instansiated directly, but generated from a test_container |
| */ |
| template<class T> |
| struct bidirectional_iterator_wrapper:public forward_iterator_wrapper<T> |
| { |
| typedef BoundsContainer<T> ContainerType; |
| typedef std::bidirectional_iterator_tag iterator_category; |
| bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
| :forward_iterator_wrapper<T>(_ptr, SharedInfo_in) |
| { } |
| |
| bidirectional_iterator_wrapper(const bidirectional_iterator_wrapper& in) |
| :forward_iterator_wrapper<T>(in) |
| { } |
| |
| bidirectional_iterator_wrapper(): forward_iterator_wrapper<T>() |
| { } |
| |
| bidirectional_iterator_wrapper& |
| operator=(const bidirectional_iterator_wrapper& in) |
| { |
| this->ptr = in.ptr; |
| this->SharedInfo = in.SharedInfo; |
| return *this; |
| } |
| |
| bidirectional_iterator_wrapper& |
| operator++() |
| { |
| ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); |
| this->ptr++; |
| return *this; |
| } |
| |
| bidirectional_iterator_wrapper |
| operator++(int) |
| { |
| bidirectional_iterator_wrapper<T> tmp = *this; |
| ++*this; |
| return tmp; |
| } |
| |
| bidirectional_iterator_wrapper& |
| operator--() |
| { |
| ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first); |
| this->ptr--; |
| return *this; |
| } |
| |
| bidirectional_iterator_wrapper |
| operator--(int) |
| { |
| bidirectional_iterator_wrapper<T> tmp = *this; |
| --*this; |
| return tmp; |
| } |
| }; |
| |
| /** |
| * @brief random_access_iterator wrapper for pointer |
| * |
| * This class takes a pointer and wraps it to provide exactly |
| * the requirements of a forward_iterator. It should not be |
| * instansiated directly, but generated from a test_container |
| */ |
| template<class T> |
| struct random_access_iterator_wrapper:public bidirectional_iterator_wrapper<T> |
| { |
| typedef BoundsContainer<T> ContainerType; |
| typedef std::random_access_iterator_tag iterator_category; |
| random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in) |
| : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in) |
| { } |
| |
| random_access_iterator_wrapper(const random_access_iterator_wrapper<T>& in) |
| : bidirectional_iterator_wrapper<T>(in) |
| { } |
| |
| random_access_iterator_wrapper():bidirectional_iterator_wrapper<T>() |
| { } |
| |
| random_access_iterator_wrapper& |
| operator=(const random_access_iterator_wrapper& in) |
| { |
| this->ptr = in.ptr; |
| this->SharedInfo = in.SharedInfo; |
| return *this; |
| } |
| |
| random_access_iterator_wrapper& |
| operator++() |
| { |
| ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last); |
| this->ptr++; |
| return *this; |
| } |
| |
| random_access_iterator_wrapper |
| operator++(int) |
| { |
| random_access_iterator_wrapper<T> tmp = *this; |
| ++*this; |
| return tmp; |
| } |
| |
| random_access_iterator_wrapper& |
| operator--() |
| { |
| ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first); |
| this->ptr--; |
| return *this; |
| } |
| |
| random_access_iterator_wrapper |
| operator--(int) |
| { |
| random_access_iterator_wrapper<T> tmp = *this; |
| --*this; |
| return tmp; |
| } |
| |
| random_access_iterator_wrapper& |
| operator+=(ptrdiff_t n) |
| { |
| if(n > 0) |
| { |
| ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr); |
| this->ptr += n; |
| } |
| else |
| { |
| ITERATOR_VERIFY(n <= this->ptr - this->SharedInfo->first); |
| this->ptr += n; |
| } |
| return *this; |
| } |
| |
| random_access_iterator_wrapper& |
| operator-=(ptrdiff_t n) |
| { return *this += -n; } |
| |
| random_access_iterator_wrapper |
| operator-(ptrdiff_t n) const |
| { |
| random_access_iterator_wrapper<T> tmp = *this; |
| return tmp -= n; |
| } |
| |
| ptrdiff_t |
| operator-(const random_access_iterator_wrapper<T>& in) const |
| { |
| ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); |
| return this->ptr - in.ptr; |
| } |
| |
| T& |
| operator[](ptrdiff_t n) const |
| { return *(*this + n); } |
| |
| bool |
| operator<(const random_access_iterator_wrapper<T>& in) const |
| { |
| ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo); |
| return this->ptr < in.ptr; |
| } |
| |
| bool |
| operator>(const random_access_iterator_wrapper<T>& in) const |
| { |
| return in < *this; |
| } |
| |
| bool |
| operator>=(const random_access_iterator_wrapper<T>& in) const |
| { |
| return !(*this < in); |
| } |
| |
| bool |
| operator<=(const random_access_iterator_wrapper<T>& in) const |
| { |
| return !(*this > in); |
| } |
| }; |
| |
| template<typename T> |
| random_access_iterator_wrapper<T> |
| operator+(random_access_iterator_wrapper<T> it, ptrdiff_t n) |
| { return it += n; } |
| |
| template<typename T> |
| random_access_iterator_wrapper<T> |
| operator+(ptrdiff_t n, random_access_iterator_wrapper<T> it) |
| { return it += n; } |
| |
| |
| /** |
| * @brief A container-type class for holding iterator wrappers |
| * test_container takes two parameters, a class T and an iterator |
| * wrapper templated by T (for example forward_iterator_wrapper<T>. |
| * It takes two pointers representing a range and presents them as |
| * a container of iterators. |
| */ |
| template <class T, template<class T> class ItType> |
| struct test_container |
| { |
| typename ItType<T>::ContainerType bounds; |
| test_container(T* _first, T* _last):bounds(_first, _last) |
| { } |
| |
| ItType<T> |
| it(int pos) |
| { |
| ITERATOR_VERIFY(pos >= 0 && pos <= (bounds.last - bounds.first)); |
| return ItType<T>(bounds.first + pos, &bounds); |
| } |
| |
| ItType<T> |
| it(T* pos) |
| { |
| ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last); |
| return ItType<T>(pos, &bounds); |
| } |
| |
| ItType<T> |
| begin() |
| { return it(bounds.first); } |
| |
| ItType<T> |
| end() |
| { return it(bounds.last); } |
| }; |
| } |
| #endif |