|  | /* -*- 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 |