/* * Copyright (c) 2017 Jaroslav Jindrak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBCPP_ITERATOR #define LIBCPP_ITERATOR #include #include #include #include #include #include namespace std { /** * 24.4.3, standard iterator tags: */ struct input_iterator_tag { /* DUMMY BODY */ }; struct output_iterator_tag { /* DUMMY BODY */ }; struct forward_iterator_tag: input_iterator_tag { /* DUMMY BODY */ }; struct bidirectional_iterator_tag: forward_iterator_tag { /* DUMMY BODY */ }; struct random_access_iterator_tag: bidirectional_iterator_tag { /* DUMMY BODY */ }; /** * 24.4.1, iterator traits: */ template struct iterator_traits { using difference_type = typename Iterator::difference_type; using value_type = typename Iterator::value_type; using iterator_category = typename Iterator::iterator_category; using reference = typename Iterator::reference; using pointer = typename Iterator::pointer; }; template struct iterator_traits { using difference_type = ptrdiff_t; using value_type = T; using iterator_category = random_access_iterator_tag; using reference = T&; using pointer = T*; }; template struct iterator_traits { using difference_type = ptrdiff_t; using value_type = T; using iterator_category = random_access_iterator_tag; using reference = const T&; using pointer = const T*; }; /** * 24.4.2, basic iterator: */ template< class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T& > struct iterator { using difference_type = Distance; using value_type = T; using iterator_category = Category; using reference = Reference; using pointer = Pointer; }; /** * 24.4.4, iterator operations */ template void advance(InputIterator& it, Distance n) { for (Distance i = Distance{}; i < n; ++i) ++it; } template typename iterator_traits::difference_type distance(InputIterator first, InputIterator last) { using cat_t = typename iterator_traits::iterator_category; using diff_t = typename iterator_traits::difference_type; if constexpr (is_same_v) return last - first; else { diff_t diff{}; while (first != last) { ++diff; ++first; } return diff; } } template ForwardIterator next(ForwardIterator it, typename iterator_traits::difference_type n = 1) { advance(it, n); return it; } template BidirectionalIterator prev(BidirectionalIterator it, typename iterator_traits::difference_type n = 1) { advance(it, -n); return it; } /** * 24.5.1, reverse iterator: */ template class reverse_iterator : public iterator< typename iterator_traits::iterator_category, typename iterator_traits::value_type, typename iterator_traits::difference_type, typename iterator_traits::pointer, typename iterator_traits::reference > { public: using iterator_type = Iterator; using difference_type = typename iterator_traits::difference_type; using reference = typename iterator_traits::reference; using pointer = typename iterator_traits::pointer; reverse_iterator() : current_{} { /* DUMMY BODY */ } explicit reverse_iterator(Iterator it) : current_{it} { /* DUMMY BODY */ } template reverse_iterator(const reverse_iterator& other) : current_{other.current_} { /* DUMMY BODY */ } template reverse_iterator& operator=(const reverse_iterator& other) { current_ = other.base(); return *this; } Iterator base() const { return current_; } reference operator*() const { auto tmp = current_; return *(--tmp); } pointer operator->() const { return addressof(operator*()); } reverse_iterator& operator++() { --current_; return *this; } reverse_iterator operator++(int) { auto tmp = *this; --current_; return tmp; } reverse_iterator& operator--() { ++current_; return *this; } reverse_iterator operator--(int) { auto tmp = *this; ++current_; return tmp; } reverse_iterator operator+(difference_type n) const { return reverse_iterator{current_ - n}; } reverse_iterator& operator+=(difference_type n) { current_ -= n; return *this; } reverse_iterator operator-(difference_type n) const { return reverse_iterator{current_ + n}; } reverse_iterator& operator-=(difference_type n) { current_ += n; return *this; } auto operator[](difference_type n) const { return current_[-n - 1]; } protected: Iterator current_; }; template bool operator==(const reverse_iterator& lhs, const reverse_iterator& rhs) { return lhs.base() == rhs.base(); } template bool operator<(const reverse_iterator& lhs, const reverse_iterator& rhs) { // Remember: they are reversed! return lhs.base() > rhs.base(); } template bool operator!=(const reverse_iterator& lhs, const reverse_iterator& rhs) { return lhs.base() != rhs.base(); } template bool operator>(const reverse_iterator& lhs, const reverse_iterator& rhs) { return lhs.base() < rhs.base(); } template bool operator>=(const reverse_iterator& lhs, const reverse_iterator& rhs) { return lhs.base() <= rhs.base(); } template bool operator<=(const reverse_iterator& lhs, const reverse_iterator& rhs) { return lhs.base() >= rhs.base(); } template auto operator-(const reverse_iterator& lhs, const reverse_iterator& rhs) -> decltype(rhs.base() - lhs.base()) { return rhs.base() - lhs.base(); } template reverse_iterator operator+( typename reverse_iterator::difference_type n, const reverse_iterator& it ) { return reverse_iterator{it.base() - n}; } template reverse_iterator make_reverse_iterator(Iterator it) { return reverse_iterator(it); } /** * 24.5.2, insert iterators: */ /** * 24.5.2.1, back insert iterator: */ template class back_insert_iterator : public iterator { public: using container_type = Container; explicit back_insert_iterator(Container& cont) : container{std::addressof(cont)} { /* DUMMY BODY */ } back_insert_iterator& operator=(const typename container_type::value_type& value) { container->push_back(value); return *this; } back_insert_iterator& operator=(typename container_type::value_type&& value) { container->push_back(move(value)); return *this; } back_insert_iterator& operator*() { return *this; } back_insert_iterator& operator++() { return *this; } back_insert_iterator operator++(int) { return *this; } protected: Container* container; }; template back_insert_iterator back_inserter(Container& cont) { return back_insert_iterator(cont); } /** * 24.5.2.3, front insert iterator: */ template class front_insert_iterator : public iterator { public: using container_type = Container; explicit front_insert_iterator(Container& cont) : container{std::addressof(cont)} { /* DUMMY BODY */ } front_insert_iterator& operator=(const typename container_type::value_type& value) { container->push_front(value); return *this; } front_insert_iterator& operator=(typename container_type::value_type&& value) { container->push_front(move(value)); return *this; } front_insert_iterator& operator*() { return *this; } front_insert_iterator& operator++() { return *this; } front_insert_iterator operator++(int) { return *this; } protected: Container* container; }; template front_insert_iterator front_inserter(Container& cont) { return front_insert_iterator(cont); } /** * 24.5.2.5, front insert iterator: */ template class insert_iterator : public iterator { public: using container_type = Container; explicit insert_iterator(Container& cont, typename Container::iterator i) : container{std::addressof(cont)}, iter{i} { /* DUMMY BODY */ } insert_iterator& operator=(const typename container_type::value_type& value) { iter = container.insert(iter, value); ++iter; return *this; } insert_iterator& operator=(typename container_type::value_type&& value) { iter = container.insert(iter, move(value)); ++iter; return *this; } insert_iterator& operator*() { return *this; } insert_iterator& operator++() { return *this; } insert_iterator operator++(int) { return *this; } protected: Container* container; typename Container::iterator iter; }; template insert_iterator inserter(Container& cont, typename Container::iterator i) { return insert_iterator(cont, i); } /** * 24.5.3.1, move iterator: */ namespace aux { template struct move_it_get_reference { using type = typename iterator_traits::reference; }; template struct move_it_get_reference< Iterator, enable_if_t< is_reference::reference>::value, void > > { using type = remove_reference_t::reference>&&; }; } template class move_iterator { public: using iterator_type = Iterator; using pointer = iterator_type; using difference_type = typename iterator_traits::difference_type; using value_type = typename iterator_traits::value_type; using iterator_category = typename iterator_traits::iterator_category; using reference = typename aux::move_it_get_reference::type; move_iterator() : current_{} { /* DUMMY BODY */ } explicit move_iterator(iterator_type i) : current_{i} { /* DUMMY BODY */ } // TODO: both require is_convertible template move_iterator(const move_iterator& other) : current_{other.current_} { /* DUMMY BODY */ } template move_iterator& operator=(const move_iterator& other) { current_ = other.current_; return *this; } iterator_type base() const { return current_; } reference operator*() const { return static_cast(*current_); } pointer operator->() const { return current_; } move_iterator& operator++() { ++current_; return *this; } move_iterator operator++(int) { auto tmp = *this; ++current_; return tmp; } move_iterator& operator--() { --current_; return *this; } move_iterator operator--(int) { auto tmp = *this; --current_; return tmp; } move_iterator operator+(difference_type n) const { return move_iterator(current_ + n); } move_iterator& operator+=(difference_type n) { current_ += n; return *this; } move_iterator operator-(difference_type n) const { return move_iterator(current_ - n); } move_iterator& operator-=(difference_type n) { current_ -= n; return *this; } auto operator[](difference_type idx) const { return move(current_[idx]); } private: iterator_type current_; }; template bool operator==(const move_iterator& lhs, const move_iterator& rhs) { return lhs.base() == rhs.base(); } template bool operator!=(const move_iterator& lhs, const move_iterator& rhs) { return lhs.base() != rhs.base(); } template bool operator<(const move_iterator& lhs, const move_iterator& rhs) { return lhs.base() < rhs.base(); } template bool operator<=(const move_iterator& lhs, const move_iterator& rhs) { return !(rhs < lhs); } template bool operator>(const move_iterator& lhs, const move_iterator& rhs) { return rhs < lhs; } template bool operator>=(const move_iterator& lhs, const move_iterator& rhs) { return !(lhs < rhs); } template auto operator-(const move_iterator& lhs, const move_iterator& rhs) -> decltype(rhs.base() - lhs.base()) { return lhs.base() - rhs.base(); } template move_iterator operator+( typename move_iterator::difference_type n, const move_iterator& it ) { return it + n; } template move_iterator make_move_iterator(Iterator it) { return move_iterator(it); } /** * 24.6, stream iterators: */ /** * 24.6.1, class template istream_iterator: */ template, class Distance = ptrdiff_t> class istream_iterator : public iterator { public: using char_type = Char; using traits_type = Traits; using istream_type = basic_istream; // TODO: if T is literal, this should be constexpr istream_iterator() : is_{nullptr}, value_{} { /* DUMMY BODY */ } istream_iterator(istream_type& is) : is_{&is}, value_{} { /* DUMMY BODY */ } istream_iterator(const istream_iterator&) = default; ~istream_iterator() = default; const T& operator*() const { return value_; } const T* operator->() const { return &(operator*()); } istream_iterator& operator++() { if (is_) (*is_) >> value_; return *this; } istream_iterator operator++(int) { auto tmp{*this}; if (is_) (*is_) >> value_; return tmp; } private: basic_istream* is_; T value_; friend bool operator==<>(const istream_iterator&, const istream_iterator&); friend bool operator!=<>(const istream_iterator&, const istream_iterator&); }; template bool operator==(const istream_iterator& lhs, const istream_iterator& rhs) { return lhs.is_ == rhs.is_; } template bool operator!=(const istream_iterator& lhs, const istream_iterator& rhs) { return !(lhs == rhs); } /** * 24.6.2, class template ostream_iterator: */ template> class ostream_iterator : public iterator { public: using char_type = Char; using traits_type = Traits; using ostream_type = basic_ostream; ostream_iterator(ostream_type& os) : os_{&os}, delim_{nullptr} { /* DUMMY BODY */ } ostream_iterator(ostream_type& os, const char_type* delim) : os_{&os}, delim_{delim} { /* DUMMY BODY */ } ostream_iterator(const ostream_iterator&) = default; ~ostream_iterator() = default; ostream_iterator& operator=(const T& value) { os_ << value; if (delim_) os_ << delim_; return *this; } ostream_iterator& operator*() const { return *this; } ostream_iterator& operator++() { return *this; } ostream_iterator& operator++(int) { return *this; } private: basic_ostream* os_; const char_type* delim_; }; /** * 24.6.3, class template istreambuf_iterator: */ template class istreambuf_iterator : public iterator { public: using char_type = Char; using traits_type = Traits; using int_type = typename traits_type::int_type; using streambuf_type = basic_streambuf; using istream_type = basic_istream; class proxy_type { public: proxy_type(int_type c, streambuf_type* sbuf) : char_{c}, sbuf_{sbuf} { /* DUMMY BODY */ } char_type operator*() { return traits_type::to_char_type(char_); } private: int_type char_; streambuf_type* sbuf_; }; constexpr istreambuf_iterator() noexcept : sbuf_{nullptr} { /* DUMMY BODY */ } istreambuf_iterator(const istreambuf_iterator&) noexcept = default; ~istreambuf_iterator() = default; istreambuf_iterator(istream_type& is) noexcept : sbuf_{is.rdbuf()} { /* DUMMY BODY */ } istreambuf_iterator(streambuf_type* sbuf) noexcept : sbuf_{sbuf} { /* DUMMY BODY */ } istreambuf_iterator(const proxy_type& proxy) noexcept : sbuf_{proxy.sbuf_} { /* DUMMY BODY */ } char_type operator*() /* const */ // TODO: Should be const :/ { if (sbuf_) { auto res = sbuf_->sgetc(); if (res == traits_type::eof()) sbuf_ = nullptr; return res; } else return traits_type::eof(); } istreambuf_iterator& operator++() { if (sbuf_) sbuf_->sbumpc(); return *this; } proxy_type operator++(int) { if (sbuf_) return proxy_type{sbuf_->sbumpc(), sbuf_}; else return proxy_type{traits_type::eof(), nullptr}; } bool equal(const istreambuf_iterator& rhs) const { if ((sbuf_ == nullptr && rhs.sbuf_ == nullptr) || (sbuf_ != nullptr && rhs.sbuf_ != nullptr)) return true; else return false; } private: streambuf_type* sbuf_; }; template bool operator==(const istreambuf_iterator& lhs, const istreambuf_iterator& rhs) { return lhs.equal(rhs); } template bool operator!=(const istreambuf_iterator& lhs, const istreambuf_iterator& rhs) { return !lhs.equal(rhs); } /** * 24.6.4, class template ostreambuf_iterator: */ template class ostreambuf_iterator : public iterator { public: using char_type = Char; using traits_type = Traits; using streambuf_type = basic_streambuf; using ostream_type = basic_ostream; ostreambuf_iterator(ostream_type& os) noexcept : sbuf_{os.rdbuf()} { /* DUMMY BODY */ } ostreambuf_iterator(streambuf_type* sbuf) noexcept : sbuf_{sbuf} { /* DUMMY BODY */ } ostreambuf_iterator& operator=(char_type c) { if (!failed() && sbuf_->sputc(c) == traits_type::eof()) failed_ = true; return *this; } ostreambuf_iterator& operator*() { return *this; } ostreambuf_iterator& operator++() { return *this; } ostreambuf_iterator& operator++(int) { return *this; } bool failed() const noexcept { return failed_; } private: streambuf_type* sbuf_; bool failed_{false}; }; /** * 24.7, range access: */ template auto begin(Container& c) -> decltype(c.begin()) { return c.begin(); } template auto begin(const Container& c) -> decltype(c.begin()) { return c.begin(); } template auto end(Container& c) -> decltype(c.end()) { return c.end(); } template auto end(const Container& c) -> decltype(c.end()) { return c.end(); } template constexpr T* begin(T (&array)[N]) noexcept { return array; } template constexpr T* end(T (&array)[N]) noexcept { return array + N; } template constexpr auto cbegin(const Container& c) noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c)) { return std::begin(c); } template constexpr auto cend(const Container& c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c)) { return std::end(c); } template auto rbegin(Container& c) -> decltype(c.rbegin()) { return c.rbegin(); } template auto rbegin(const Container& c) -> decltype(c.rbegin()) { return c.rbegin(); } template auto rend(Container& c) -> decltype(c.rend()) { return c.rend(); } template auto rend(const Container& c) -> decltype(c.rend()) { return c.rend(); } template reverse_iterator rbegin(T (&array)[N]) { return reverse_iterator{array + N}; } template reverse_iterator rend(T (&array)[N]) { return reverse_iterator{array}; } template reverse_iterator rbegin(initializer_list init) { return reverse_iterator{init.end()}; } template reverse_iterator rend(initializer_list init) { return reverse_iterator{init.begin()}; } template auto crbegin(const Container& c) -> decltype(std::rbegin(c)) { return std::rbegin(c); } template auto crend(const Container& c) -> decltype(std::rend(c)) { return std::rend(c); } /** * 24.8, container access: */ template constexpr auto size(const Container& c) -> decltype(c.size()) { return c.size(); } template constexpr size_t size(T (&array)[N]) noexcept { return N; } template constexpr auto empty(const Container& c) -> decltype(c.empty()) { return c.empty(); } template constexpr bool empty(T (&array)[N]) noexcept { return false; } template constexpr bool empty(initializer_list init) noexcept { return init.size() == 0; } template constexpr auto data(Container& c) -> decltype(c.data()) { return c.data(); } template constexpr auto data(const Container& c) -> decltype(c.data()) { return c.data(); } template constexpr T* data(T (&array)[N]) noexcept { return array; } template constexpr const T* data(initializer_list init) noexcept { return init.begin(); } } #endif