#ifndef SPROUT_ITERATOR_BYTES_ITERATOR_HPP #define SPROUT_ITERATOR_BYTES_ITERATOR_HPP #include #include #include #include #include #include namespace sprout { // // bytes_iterator // template< typename Iterator, typename Traits = sprout::big_endian_traits::value_type> > class bytes_iterator : public std::iterator< typename std::iterator_traits::iterator_category, unsigned char, std::ptrdiff_t, void, unsigned char > { public: typedef Iterator base_type; typedef Traits traits_type; private: typedef std::iterator< typename std::iterator_traits::iterator_category, unsigned char, std::ptrdiff_t, void, unsigned char > iterator_type; public: typedef typename iterator_type::iterator_category iterator_category; typedef typename iterator_type::value_type value_type; typedef typename iterator_type::difference_type difference_type; typedef typename iterator_type::pointer pointer; typedef typename iterator_type::reference reference; private: struct next_tag {}; struct prev_tag {}; struct ra_tag {}; private: base_type it_; difference_type i_; private: SPROUT_CONSTEXPR bytes_iterator(base_type it, difference_type i) : it_(it) , i_(i) {} SPROUT_CONSTEXPR bytes_iterator(base_type it, difference_type i, next_tag) : it_(i / traits_type::size() == 0 ? it : sprout::next(it)) , i_(i % traits_type::size()) {} SPROUT_CONSTEXPR bytes_iterator(base_type it, difference_type i, prev_tag) : it_((i + 1 - traits_type::size()) / traits_type::size() == 0 ? it : sprout::prev(it)) , i_(i % traits_type::size() + traits_type::size()) {} SPROUT_CONSTEXPR bytes_iterator(base_type it, difference_type i, ra_tag) : it_(i >= 0 ? sprout::next(it, i / traits_type::size()) : sprout::next(it, (i + 1 - traits_type::size()) / traits_type::size()) ) , i_(i >= 0 ? i % traits_type::size() : i % traits_type::size() + traits_type::size() ) {} public: SPROUT_CONSTEXPR bytes_iterator() : it_() , i_() {} bytes_iterator(bytes_iterator const&) = default; explicit SPROUT_CONSTEXPR bytes_iterator(base_type it) : it_(it) , i_() {} SPROUT_CONSTEXPR bytes_iterator next() const { return bytes_iterator(it_, i_ + 1, next_tag()); } SPROUT_CONSTEXPR bytes_iterator prev() const { return bytes_iterator(it_, i_ - 1, prev_tag()); } void swap(bytes_iterator& other) { using std::swap; swap(it_, other.it_); swap(i_, other.i_); } friend SPROUT_CONSTEXPR bool operator==(bytes_iterator const& lhs, bytes_iterator const& rhs) { return lhs.it_ == rhs.it_ && lhs.i_ == rhs.i_; } friend SPROUT_CONSTEXPR bool operator!=(bytes_iterator const& lhs, bytes_iterator const& rhs) { return !(lhs == rhs); } friend SPROUT_CONSTEXPR bool operator<(bytes_iterator const& lhs, bytes_iterator const& rhs) { return lhs.it_ < rhs.it_ || lhs.it_ == rhs.it_ && lhs.i_ < rhs.i_; } friend SPROUT_CONSTEXPR bool operator>(bytes_iterator const& lhs, bytes_iterator const& rhs) { return rhs < lhs; } friend SPROUT_CONSTEXPR bool operator<=(bytes_iterator const& lhs, bytes_iterator const& rhs) { return !(rhs < lhs); } friend SPROUT_CONSTEXPR bool operator>=(bytes_iterator const& lhs, bytes_iterator const& rhs) { return !(lhs < rhs); } SPROUT_CONSTEXPR reference operator*() const { return traits_type::get_byte(*it_, i_); } bytes_iterator& operator++() { bytes_iterator temp(next()); temp.swap(*this); return *this; } bytes_iterator operator++(int) { bytes_iterator result(*this); ++*this; return result; } bytes_iterator& operator--() { bytes_iterator temp(prev()); temp.swap(*this); return *this; } bytes_iterator operator--(int) { bytes_iterator result(*this); --*this; return result; } SPROUT_CONSTEXPR bytes_iterator operator+(difference_type n) const { return bytes_iterator(it_, i_ + n, ra_tag()); } SPROUT_CONSTEXPR bytes_iterator operator-(difference_type n) const { return bytes_iterator(it_, i_ - n, ra_tag()); } bytes_iterator& operator+=(difference_type n) { bytes_iterator temp(it_, i_ + n, ra_tag()); temp.swap(this); return this; } bytes_iterator& operator-=(difference_type n) { bytes_iterator temp(it_, i_ - n, ra_tag()); temp.swap(this); return this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { return *(*this + n); } friend SPROUT_CONSTEXPR difference_type operator-(bytes_iterator const& lhs, bytes_iterator const& rhs) { return (lhs.it_ - rhs.it_) * traits_type::size() + (lhs.i_ - rhs.i_); } friend SPROUT_CONSTEXPR bytes_iterator operator+(difference_type n, bytes_iterator const& it) { return it + n; } }; // // swap // template inline void swap(sprout::bytes_iterator& lhs, sprout::bytes_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } // // next // template inline SPROUT_CONSTEXPR sprout::bytes_iterator next( sprout::bytes_iterator const& it ) { return it.next(); } template inline SPROUT_CONSTEXPR sprout::bytes_iterator next( sprout::bytes_iterator const& it, typename sprout::bytes_iterator::difference_type n ) { return it + n; } // // prev // template inline SPROUT_CONSTEXPR sprout::bytes_iterator prev( sprout::bytes_iterator const& it ) { return it.prev(); } template inline SPROUT_CONSTEXPR sprout::bytes_iterator prev( sprout::bytes_iterator const& it, typename sprout::bytes_iterator::difference_type n ) { return it - n; } // // make_bytes_iterator // template inline SPROUT_CONSTEXPR sprout::bytes_iterator make_bytes_iterator(Iterator it) { return sprout::bytes_iterator(it); } template inline SPROUT_CONSTEXPR sprout::bytes_iterator make_bytes_iterator(Iterator it, Traits) { return sprout::bytes_iterator(it); } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_BYTES_ITERATOR_HPP