ReverseIterator.h (6033B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* An iterator that acts like another iterator, but iterating in 8 * the negative direction. (Note that not all iterators can iterate 9 * in the negative direction.) */ 10 11 #ifndef mozilla_ReverseIterator_h 12 #define mozilla_ReverseIterator_h 13 14 #include <utility> 15 16 namespace mozilla { 17 18 // This should only be used in cases where std::reverse_iterator cannot be used, 19 // because the underlying iterator is not a proper bidirectional iterator, but 20 // rather, e.g., a stashing iterator such as IntegerIterator. It is less 21 // efficient than std::reverse_iterator for proper bidirectional iterators. 22 template <typename IteratorT> 23 class ReverseIterator { 24 public: 25 using value_type = typename IteratorT::value_type; 26 using pointer = typename IteratorT::pointer; 27 using reference = typename IteratorT::reference; 28 using difference_type = typename IteratorT::difference_type; 29 using iterator_category = typename IteratorT::iterator_category; 30 31 explicit ReverseIterator(IteratorT aIter) : mCurrent(std::move(aIter)) {} 32 33 // The return type is not reference, but rather the return type of 34 // Iterator::operator*(), which might be value_type, to allow this to work 35 // with stashing iterators such as IntegerIterator, see also Bug 1175485. 36 decltype(*std::declval<IteratorT>()) operator*() const { 37 IteratorT tmp = mCurrent; 38 return *--tmp; 39 } 40 41 /* Difference operator */ 42 difference_type operator-(const ReverseIterator& aOther) const { 43 return aOther.mCurrent - mCurrent; 44 } 45 46 /* Increments and decrements operators */ 47 48 ReverseIterator& operator++() { 49 --mCurrent; 50 return *this; 51 } 52 ReverseIterator& operator--() { 53 ++mCurrent; 54 return *this; 55 } 56 ReverseIterator operator++(int) { 57 auto ret = *this; 58 mCurrent--; 59 return ret; 60 } 61 ReverseIterator operator--(int) { 62 auto ret = *this; 63 mCurrent++; 64 return ret; 65 } 66 67 /* Comparison operators */ 68 69 template <typename Iterator1, typename Iterator2> 70 friend bool operator==(const ReverseIterator<Iterator1>& aIter1, 71 const ReverseIterator<Iterator2>& aIter2); 72 template <typename Iterator1, typename Iterator2> 73 friend bool operator!=(const ReverseIterator<Iterator1>& aIter1, 74 const ReverseIterator<Iterator2>& aIter2); 75 template <typename Iterator1, typename Iterator2> 76 friend bool operator<(const ReverseIterator<Iterator1>& aIter1, 77 const ReverseIterator<Iterator2>& aIter2); 78 template <typename Iterator1, typename Iterator2> 79 friend bool operator<=(const ReverseIterator<Iterator1>& aIter1, 80 const ReverseIterator<Iterator2>& aIter2); 81 template <typename Iterator1, typename Iterator2> 82 friend bool operator>(const ReverseIterator<Iterator1>& aIter1, 83 const ReverseIterator<Iterator2>& aIter2); 84 template <typename Iterator1, typename Iterator2> 85 friend bool operator>=(const ReverseIterator<Iterator1>& aIter1, 86 const ReverseIterator<Iterator2>& aIter2); 87 88 private: 89 IteratorT mCurrent; 90 }; 91 92 template <typename Iterator1, typename Iterator2> 93 bool operator==(const ReverseIterator<Iterator1>& aIter1, 94 const ReverseIterator<Iterator2>& aIter2) { 95 return aIter1.mCurrent == aIter2.mCurrent; 96 } 97 98 template <typename Iterator1, typename Iterator2> 99 bool operator!=(const ReverseIterator<Iterator1>& aIter1, 100 const ReverseIterator<Iterator2>& aIter2) { 101 return aIter1.mCurrent != aIter2.mCurrent; 102 } 103 104 template <typename Iterator1, typename Iterator2> 105 bool operator<(const ReverseIterator<Iterator1>& aIter1, 106 const ReverseIterator<Iterator2>& aIter2) { 107 return aIter1.mCurrent > aIter2.mCurrent; 108 } 109 110 template <typename Iterator1, typename Iterator2> 111 bool operator<=(const ReverseIterator<Iterator1>& aIter1, 112 const ReverseIterator<Iterator2>& aIter2) { 113 return aIter1.mCurrent >= aIter2.mCurrent; 114 } 115 116 template <typename Iterator1, typename Iterator2> 117 bool operator>(const ReverseIterator<Iterator1>& aIter1, 118 const ReverseIterator<Iterator2>& aIter2) { 119 return aIter1.mCurrent < aIter2.mCurrent; 120 } 121 122 template <typename Iterator1, typename Iterator2> 123 bool operator>=(const ReverseIterator<Iterator1>& aIter1, 124 const ReverseIterator<Iterator2>& aIter2) { 125 return aIter1.mCurrent <= aIter2.mCurrent; 126 } 127 128 namespace detail { 129 130 template <typename IteratorT, 131 typename ReverseIteratorT = ReverseIterator<IteratorT>> 132 class IteratorRange { 133 public: 134 typedef IteratorT iterator; 135 typedef IteratorT const_iterator; 136 typedef ReverseIteratorT reverse_iterator; 137 typedef ReverseIteratorT const_reverse_iterator; 138 139 IteratorRange(IteratorT aIterBegin, IteratorT aIterEnd) 140 : mIterBegin(std::move(aIterBegin)), mIterEnd(std::move(aIterEnd)) {} 141 142 iterator begin() const { return mIterBegin; } 143 const_iterator cbegin() const { return begin(); } 144 iterator end() const { return mIterEnd; } 145 const_iterator cend() const { return end(); } 146 reverse_iterator rbegin() const { return reverse_iterator(mIterEnd); } 147 const_reverse_iterator crbegin() const { return rbegin(); } 148 reverse_iterator rend() const { return reverse_iterator(mIterBegin); } 149 const_reverse_iterator crend() const { return rend(); } 150 151 IteratorT mIterBegin; 152 IteratorT mIterEnd; 153 }; 154 155 } // namespace detail 156 157 template <typename Range> 158 detail::IteratorRange<typename Range::reverse_iterator> Reversed( 159 Range& aRange) { 160 return {aRange.rbegin(), aRange.rend()}; 161 } 162 163 template <typename Range> 164 detail::IteratorRange<typename Range::const_reverse_iterator> Reversed( 165 const Range& aRange) { 166 return {aRange.rbegin(), aRange.rend()}; 167 } 168 169 } // namespace mozilla 170 171 #endif // mozilla_ReverseIterator_h