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/. */
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.) */
11 #ifndef mozilla_ReverseIterator_h
12 #define mozilla_ReverseIterator_h
16 #include "mozilla/Attributes.h"
20 // This should only be used in cases where std::reverse_iterator cannot be used,
21 // because the underlying iterator is not a proper bidirectional iterator, but
22 // rather, e.g., a stashing iterator such as IntegerIterator. It is less
23 // efficient than std::reverse_iterator for proper bidirectional iterators.
24 template <typename IteratorT
>
25 class ReverseIterator
{
27 using value_type
= typename
IteratorT::value_type
;
28 using pointer
= typename
IteratorT::pointer
;
29 using reference
= typename
IteratorT::reference
;
30 using difference_type
= typename
IteratorT::difference_type
;
31 using iterator_category
= typename
IteratorT::iterator_category
;
33 explicit ReverseIterator(IteratorT aIter
) : mCurrent(std::move(aIter
)) {}
35 // The return type is not reference, but rather the return type of
36 // Iterator::operator*(), which might be value_type, to allow this to work
37 // with stashing iterators such as IntegerIterator, see also Bug 1175485.
38 decltype(*std::declval
<IteratorT
>()) operator*() const {
39 IteratorT tmp
= mCurrent
;
43 /* Difference operator */
44 difference_type
operator-(const ReverseIterator
& aOther
) const {
45 return aOther
.mCurrent
- mCurrent
;
48 /* Increments and decrements operators */
50 ReverseIterator
& operator++() {
54 ReverseIterator
& operator--() {
58 ReverseIterator
operator++(int) {
63 ReverseIterator
operator--(int) {
69 /* Comparison operators */
71 template <typename Iterator1
, typename Iterator2
>
72 friend bool operator==(const ReverseIterator
<Iterator1
>& aIter1
,
73 const ReverseIterator
<Iterator2
>& aIter2
);
74 template <typename Iterator1
, typename Iterator2
>
75 friend bool operator!=(const ReverseIterator
<Iterator1
>& aIter1
,
76 const ReverseIterator
<Iterator2
>& aIter2
);
77 template <typename Iterator1
, typename Iterator2
>
78 friend bool operator<(const ReverseIterator
<Iterator1
>& aIter1
,
79 const ReverseIterator
<Iterator2
>& aIter2
);
80 template <typename Iterator1
, typename Iterator2
>
81 friend bool operator<=(const ReverseIterator
<Iterator1
>& aIter1
,
82 const ReverseIterator
<Iterator2
>& aIter2
);
83 template <typename Iterator1
, typename Iterator2
>
84 friend bool operator>(const ReverseIterator
<Iterator1
>& aIter1
,
85 const ReverseIterator
<Iterator2
>& aIter2
);
86 template <typename Iterator1
, typename Iterator2
>
87 friend bool operator>=(const ReverseIterator
<Iterator1
>& aIter1
,
88 const ReverseIterator
<Iterator2
>& aIter2
);
94 template <typename Iterator1
, typename Iterator2
>
95 bool operator==(const ReverseIterator
<Iterator1
>& aIter1
,
96 const ReverseIterator
<Iterator2
>& aIter2
) {
97 return aIter1
.mCurrent
== aIter2
.mCurrent
;
100 template <typename Iterator1
, typename Iterator2
>
101 bool operator!=(const ReverseIterator
<Iterator1
>& aIter1
,
102 const ReverseIterator
<Iterator2
>& aIter2
) {
103 return aIter1
.mCurrent
!= aIter2
.mCurrent
;
106 template <typename Iterator1
, typename Iterator2
>
107 bool operator<(const ReverseIterator
<Iterator1
>& aIter1
,
108 const ReverseIterator
<Iterator2
>& aIter2
) {
109 return aIter1
.mCurrent
> aIter2
.mCurrent
;
112 template <typename Iterator1
, typename Iterator2
>
113 bool operator<=(const ReverseIterator
<Iterator1
>& aIter1
,
114 const ReverseIterator
<Iterator2
>& aIter2
) {
115 return aIter1
.mCurrent
>= aIter2
.mCurrent
;
118 template <typename Iterator1
, typename Iterator2
>
119 bool operator>(const ReverseIterator
<Iterator1
>& aIter1
,
120 const ReverseIterator
<Iterator2
>& aIter2
) {
121 return aIter1
.mCurrent
< aIter2
.mCurrent
;
124 template <typename Iterator1
, typename Iterator2
>
125 bool operator>=(const ReverseIterator
<Iterator1
>& aIter1
,
126 const ReverseIterator
<Iterator2
>& aIter2
) {
127 return aIter1
.mCurrent
<= aIter2
.mCurrent
;
132 template <typename IteratorT
,
133 typename ReverseIteratorT
= ReverseIterator
<IteratorT
>>
134 class IteratorRange
{
136 typedef IteratorT iterator
;
137 typedef IteratorT const_iterator
;
138 typedef ReverseIteratorT reverse_iterator
;
139 typedef ReverseIteratorT const_reverse_iterator
;
141 IteratorRange(IteratorT aIterBegin
, IteratorT aIterEnd
)
142 : mIterBegin(std::move(aIterBegin
)), mIterEnd(std::move(aIterEnd
)) {}
144 iterator
begin() const { return mIterBegin
; }
145 const_iterator
cbegin() const { return begin(); }
146 iterator
end() const { return mIterEnd
; }
147 const_iterator
cend() const { return end(); }
148 reverse_iterator
rbegin() const { return reverse_iterator(mIterEnd
); }
149 const_reverse_iterator
crbegin() const { return rbegin(); }
150 reverse_iterator
rend() const { return reverse_iterator(mIterBegin
); }
151 const_reverse_iterator
crend() const { return rend(); }
153 IteratorT mIterBegin
;
157 } // namespace detail
159 template <typename Range
>
160 detail::IteratorRange
<typename
Range::reverse_iterator
> Reversed(
162 return {aRange
.rbegin(), aRange
.rend()};
165 template <typename Range
>
166 detail::IteratorRange
<typename
Range::const_reverse_iterator
> Reversed(
167 const Range
& aRange
) {
168 return {aRange
.rbegin(), aRange
.rend()};
171 } // namespace mozilla
173 #endif // mozilla_ReverseIterator_h