| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| /* An iterator that acts like another iterator, but iterating in |
| * the negative direction. (Note that not all iterators can iterate |
| * in the negative direction.) */ |
| |
| #ifndef mozilla_ReverseIterator_h |
| #define mozilla_ReverseIterator_h |
| |
| #include "mozilla/Attributes.h" |
| #include "mozilla/TypeTraits.h" |
| |
| namespace mozilla { |
| |
| template<typename IteratorT> |
| class ReverseIterator |
| { |
| public: |
| template<typename Iterator> |
| explicit ReverseIterator(Iterator aIter) |
| : mCurrent(aIter) { } |
| |
| template<typename Iterator> |
| MOZ_IMPLICIT ReverseIterator(const ReverseIterator<Iterator>& aOther) |
| : mCurrent(aOther.mCurrent) { } |
| |
| decltype(*DeclVal<IteratorT>()) operator*() const |
| { |
| IteratorT tmp = mCurrent; |
| return *--tmp; |
| } |
| |
| /* Increments and decrements operators */ |
| |
| ReverseIterator& operator++() { --mCurrent; return *this; } |
| ReverseIterator& operator--() { ++mCurrent; return *this; } |
| ReverseIterator operator++(int) { auto ret = *this; mCurrent--; return ret; } |
| ReverseIterator operator--(int) { auto ret = *this; mCurrent++; return ret; } |
| |
| /* Comparison operators */ |
| |
| template<typename Iterator1, typename Iterator2> |
| friend bool operator==(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2); |
| template<typename Iterator1, typename Iterator2> |
| friend bool operator!=(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2); |
| template<typename Iterator1, typename Iterator2> |
| friend bool operator<(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2); |
| template<typename Iterator1, typename Iterator2> |
| friend bool operator<=(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2); |
| template<typename Iterator1, typename Iterator2> |
| friend bool operator>(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2); |
| template<typename Iterator1, typename Iterator2> |
| friend bool operator>=(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2); |
| |
| private: |
| IteratorT mCurrent; |
| }; |
| |
| template<typename Iterator1, typename Iterator2> |
| bool |
| operator==(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2) |
| { |
| return aIter1.mCurrent == aIter2.mCurrent; |
| } |
| |
| template<typename Iterator1, typename Iterator2> |
| bool |
| operator!=(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2) |
| { |
| return aIter1.mCurrent != aIter2.mCurrent; |
| } |
| |
| template<typename Iterator1, typename Iterator2> |
| bool |
| operator<(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2) |
| { |
| return aIter1.mCurrent > aIter2.mCurrent; |
| } |
| |
| template<typename Iterator1, typename Iterator2> |
| bool |
| operator<=(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2) |
| { |
| return aIter1.mCurrent >= aIter2.mCurrent; |
| } |
| |
| template<typename Iterator1, typename Iterator2> |
| bool |
| operator>(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2) |
| { |
| return aIter1.mCurrent < aIter2.mCurrent; |
| } |
| |
| template<typename Iterator1, typename Iterator2> |
| bool |
| operator>=(const ReverseIterator<Iterator1>& aIter1, |
| const ReverseIterator<Iterator2>& aIter2) |
| { |
| return aIter1.mCurrent <= aIter2.mCurrent; |
| } |
| |
| namespace detail { |
| |
| template<typename IteratorT> |
| class IteratorRange |
| { |
| public: |
| typedef IteratorT iterator; |
| typedef IteratorT const_iterator; |
| typedef ReverseIterator<IteratorT> reverse_iterator; |
| typedef ReverseIterator<IteratorT> const_reverse_iterator; |
| |
| template<typename Iterator1, typename Iterator2> |
| MOZ_IMPLICIT IteratorRange(Iterator1 aIterBegin, Iterator2 aIterEnd) |
| : mIterBegin(aIterBegin), mIterEnd(aIterEnd) { } |
| |
| template<typename Iterator> |
| MOZ_IMPLICIT IteratorRange(const IteratorRange<Iterator>& aOther) |
| : mIterBegin(aOther.mIterBegin), mIterEnd(aOther.mIterEnd) { } |
| |
| iterator begin() const { return mIterBegin; } |
| const_iterator cbegin() const { return begin(); } |
| iterator end() const { return mIterEnd; } |
| const_iterator cend() const { return end(); } |
| reverse_iterator rbegin() const { return reverse_iterator(mIterEnd); } |
| const_reverse_iterator crbegin() const { return rbegin(); } |
| reverse_iterator rend() const { return reverse_iterator(mIterBegin); } |
| const_reverse_iterator crend() const { return rend(); } |
| |
| private: |
| IteratorT mIterBegin; |
| IteratorT mIterEnd; |
| }; |
| |
| } // namespace detail |
| |
| template<typename Range> |
| detail::IteratorRange<typename Range::reverse_iterator> |
| Reversed(Range& aRange) |
| { |
| return {aRange.rbegin(), aRange.rend()}; |
| } |
| |
| template<typename Range> |
| detail::IteratorRange<typename Range::const_reverse_iterator> |
| Reversed(const Range& aRange) |
| { |
| return {aRange.rbegin(), aRange.rend()}; |
| } |
| |
| } // namespace mozilla |
| |
| #endif // mozilla_ReverseIterator_h |