Line data Source code
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 "mozilla/Attributes.h"
15 : #include "mozilla/TypeTraits.h"
16 :
17 : namespace mozilla {
18 :
19 : template<typename IteratorT>
20 10764 : class ReverseIterator
21 : {
22 : public:
23 : template<typename Iterator>
24 5390 : explicit ReverseIterator(Iterator aIter)
25 5390 : : mCurrent(aIter) { }
26 :
27 : template<typename Iterator>
28 : MOZ_IMPLICIT ReverseIterator(const ReverseIterator<Iterator>& aOther)
29 : : mCurrent(aOther.mCurrent) { }
30 :
31 2459 : decltype(*DeclVal<IteratorT>()) operator*() const
32 : {
33 2459 : IteratorT tmp = mCurrent;
34 2459 : return *--tmp;
35 : }
36 :
37 : /* Increments and decrements operators */
38 :
39 999 : ReverseIterator& operator++() { --mCurrent; return *this; }
40 : ReverseIterator& operator--() { ++mCurrent; return *this; }
41 0 : ReverseIterator operator++(int) { auto ret = *this; mCurrent--; return ret; }
42 : ReverseIterator operator--(int) { auto ret = *this; mCurrent++; return ret; }
43 :
44 : /* Comparison operators */
45 :
46 : template<typename Iterator1, typename Iterator2>
47 : friend bool operator==(const ReverseIterator<Iterator1>& aIter1,
48 : const ReverseIterator<Iterator2>& aIter2);
49 : template<typename Iterator1, typename Iterator2>
50 : friend bool operator!=(const ReverseIterator<Iterator1>& aIter1,
51 : const ReverseIterator<Iterator2>& aIter2);
52 : template<typename Iterator1, typename Iterator2>
53 : friend bool operator<(const ReverseIterator<Iterator1>& aIter1,
54 : const ReverseIterator<Iterator2>& aIter2);
55 : template<typename Iterator1, typename Iterator2>
56 : friend bool operator<=(const ReverseIterator<Iterator1>& aIter1,
57 : const ReverseIterator<Iterator2>& aIter2);
58 : template<typename Iterator1, typename Iterator2>
59 : friend bool operator>(const ReverseIterator<Iterator1>& aIter1,
60 : const ReverseIterator<Iterator2>& aIter2);
61 : template<typename Iterator1, typename Iterator2>
62 : friend bool operator>=(const ReverseIterator<Iterator1>& aIter1,
63 : const ReverseIterator<Iterator2>& aIter2);
64 :
65 : private:
66 : IteratorT mCurrent;
67 : };
68 :
69 : template<typename Iterator1, typename Iterator2>
70 : bool
71 0 : operator==(const ReverseIterator<Iterator1>& aIter1,
72 : const ReverseIterator<Iterator2>& aIter2)
73 : {
74 0 : return aIter1.mCurrent == aIter2.mCurrent;
75 : }
76 :
77 : template<typename Iterator1, typename Iterator2>
78 : bool
79 3694 : operator!=(const ReverseIterator<Iterator1>& aIter1,
80 : const ReverseIterator<Iterator2>& aIter2)
81 : {
82 3694 : return aIter1.mCurrent != aIter2.mCurrent;
83 : }
84 :
85 : template<typename Iterator1, typename Iterator2>
86 : bool
87 : operator<(const ReverseIterator<Iterator1>& aIter1,
88 : const ReverseIterator<Iterator2>& aIter2)
89 : {
90 : return aIter1.mCurrent > aIter2.mCurrent;
91 : }
92 :
93 : template<typename Iterator1, typename Iterator2>
94 : bool
95 : operator<=(const ReverseIterator<Iterator1>& aIter1,
96 : const ReverseIterator<Iterator2>& aIter2)
97 : {
98 : return aIter1.mCurrent >= aIter2.mCurrent;
99 : }
100 :
101 : template<typename Iterator1, typename Iterator2>
102 : bool
103 : operator>(const ReverseIterator<Iterator1>& aIter1,
104 : const ReverseIterator<Iterator2>& aIter2)
105 : {
106 : return aIter1.mCurrent < aIter2.mCurrent;
107 : }
108 :
109 : template<typename Iterator1, typename Iterator2>
110 : bool
111 : operator>=(const ReverseIterator<Iterator1>& aIter1,
112 : const ReverseIterator<Iterator2>& aIter2)
113 : {
114 : return aIter1.mCurrent <= aIter2.mCurrent;
115 : }
116 :
117 : namespace detail {
118 :
119 : template<typename IteratorT>
120 : class IteratorRange
121 : {
122 : public:
123 : typedef IteratorT iterator;
124 : typedef IteratorT const_iterator;
125 : typedef ReverseIterator<IteratorT> reverse_iterator;
126 : typedef ReverseIterator<IteratorT> const_reverse_iterator;
127 :
128 : template<typename Iterator1, typename Iterator2>
129 2695 : MOZ_IMPLICIT IteratorRange(Iterator1 aIterBegin, Iterator2 aIterEnd)
130 2695 : : mIterBegin(aIterBegin), mIterEnd(aIterEnd) { }
131 :
132 : template<typename Iterator>
133 : MOZ_IMPLICIT IteratorRange(const IteratorRange<Iterator>& aOther)
134 : : mIterBegin(aOther.mIterBegin), mIterEnd(aOther.mIterEnd) { }
135 :
136 2695 : iterator begin() const { return mIterBegin; }
137 : const_iterator cbegin() const { return begin(); }
138 2695 : iterator end() const { return mIterEnd; }
139 : const_iterator cend() const { return end(); }
140 : reverse_iterator rbegin() const { return reverse_iterator(mIterEnd); }
141 : const_reverse_iterator crbegin() const { return rbegin(); }
142 : reverse_iterator rend() const { return reverse_iterator(mIterBegin); }
143 : const_reverse_iterator crend() const { return rend(); }
144 :
145 : private:
146 : IteratorT mIterBegin;
147 : IteratorT mIterEnd;
148 : };
149 :
150 : } // namespace detail
151 :
152 : template<typename Range>
153 : detail::IteratorRange<typename Range::reverse_iterator>
154 2564 : Reversed(Range& aRange)
155 : {
156 2564 : return {aRange.rbegin(), aRange.rend()};
157 : }
158 :
159 : template<typename Range>
160 : detail::IteratorRange<typename Range::const_reverse_iterator>
161 131 : Reversed(const Range& aRange)
162 : {
163 131 : return {aRange.rbegin(), aRange.rend()};
164 : }
165 :
166 : } // namespace mozilla
167 :
168 : #endif // mozilla_ReverseIterator_h
|