/* -*- 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 #include "mozilla/Attributes.h" namespace mozilla { template class ReverseIterator { public: template explicit ReverseIterator(Iterator aIter) : mCurrent(aIter) {} template MOZ_IMPLICIT ReverseIterator(const ReverseIterator& aOther) : mCurrent(aOther.mCurrent) {} decltype(*std::declval()) 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 friend bool operator==(const ReverseIterator& aIter1, const ReverseIterator& aIter2); template friend bool operator!=(const ReverseIterator& aIter1, const ReverseIterator& aIter2); template friend bool operator<(const ReverseIterator& aIter1, const ReverseIterator& aIter2); template friend bool operator<=(const ReverseIterator& aIter1, const ReverseIterator& aIter2); template friend bool operator>(const ReverseIterator& aIter1, const ReverseIterator& aIter2); template friend bool operator>=(const ReverseIterator& aIter1, const ReverseIterator& aIter2); private: IteratorT mCurrent; }; template bool operator==(const ReverseIterator& aIter1, const ReverseIterator& aIter2) { return aIter1.mCurrent == aIter2.mCurrent; } template bool operator!=(const ReverseIterator& aIter1, const ReverseIterator& aIter2) { return aIter1.mCurrent != aIter2.mCurrent; } template bool operator<(const ReverseIterator& aIter1, const ReverseIterator& aIter2) { return aIter1.mCurrent > aIter2.mCurrent; } template bool operator<=(const ReverseIterator& aIter1, const ReverseIterator& aIter2) { return aIter1.mCurrent >= aIter2.mCurrent; } template bool operator>(const ReverseIterator& aIter1, const ReverseIterator& aIter2) { return aIter1.mCurrent < aIter2.mCurrent; } template bool operator>=(const ReverseIterator& aIter1, const ReverseIterator& aIter2) { return aIter1.mCurrent <= aIter2.mCurrent; } namespace detail { template class IteratorRange { public: typedef IteratorT iterator; typedef IteratorT const_iterator; typedef ReverseIterator reverse_iterator; typedef ReverseIterator const_reverse_iterator; template MOZ_IMPLICIT IteratorRange(Iterator1 aIterBegin, Iterator2 aIterEnd) : mIterBegin(aIterBegin), mIterEnd(aIterEnd) {} template MOZ_IMPLICIT IteratorRange(const IteratorRange& 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 detail::IteratorRange Reversed( Range& aRange) { return {aRange.rbegin(), aRange.rend()}; } template detail::IteratorRange Reversed( const Range& aRange) { return {aRange.rbegin(), aRange.rend()}; } } // namespace mozilla #endif // mozilla_ReverseIterator_h