diff --git a/mfbt/ReverseIterator.h b/mfbt/ReverseIterator.h new file mode 100644 index 00000000000..e9b2d9b8a04 --- /dev/null +++ b/mfbt/ReverseIterator.h @@ -0,0 +1,190 @@ +/* -*- 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/IteratorTraits.h" + +namespace mozilla { + +template +class ReverseIterator +{ +public: + typedef typename IteratorTraits::ValueType ValueType; + typedef typename IteratorTraits::DifferenceType DifferenceType; + + template + explicit ReverseIterator(Iterator aIter) + : mCurrent(aIter) { } + + template + MOZ_IMPLICIT ReverseIterator(const ReverseIterator& aOther) + : mCurrent(aOther.mCurrent) { } + + ValueType& 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; } + + ReverseIterator operator+(DifferenceType aN) const + { + return ReverseIterator(mCurrent - aN); + } + ReverseIterator operator-(DifferenceType aN) const + { + return ReverseIterator(mCurrent + aN); + } + ReverseIterator& operator+=(DifferenceType aN) + { + mCurrent -= aN; + return *this; + } + ReverseIterator& operator-=(DifferenceType aN) + { + mCurrent += aN; + return *this; + } + + /* 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 + IteratorRange(Iterator1 aIterBegin, Iterator2 aIterEnd) + : mIterBegin(aIterBegin), mIterEnd(aIterEnd) { } + + template + 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 diff --git a/mfbt/moz.build b/mfbt/moz.build index b1bf1e73e4b..921bc8d0c1d 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -60,6 +60,7 @@ EXPORTS.mozilla = [ 'RefCountType.h', 'ReentrancyGuard.h', 'RefPtr.h', + 'ReverseIterator.h', 'RollingMean.h', 'Scoped.h', 'SegmentedVector.h',