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 /* Iterator over ranges of integers */
9 #ifndef mozilla_IntegerRange_h
10 #define mozilla_IntegerRange_h
12 #include "mozilla/Assertions.h"
13 #include "mozilla/ReverseIterator.h"
14 #include "mozilla/TypeTraits.h"
20 template <typename IntTypeT
>
21 class IntegerIterator
{
23 template <typename IntType
>
24 explicit IntegerIterator(IntType aCurrent
) : mCurrent(aCurrent
) {}
26 template <typename IntType
>
27 explicit IntegerIterator(const IntegerIterator
<IntType
>& aOther
)
28 : mCurrent(aOther
.mCurrent
) {}
30 IntTypeT
operator*() const { return mCurrent
; }
32 /* Increment and decrement operators */
34 IntegerIterator
& operator++() {
38 IntegerIterator
& operator--() {
42 IntegerIterator
operator++(int) {
47 IntegerIterator
operator--(int) {
53 /* Comparison operators */
55 template <typename IntType1
, typename IntType2
>
56 friend bool operator==(const IntegerIterator
<IntType1
>& aIter1
,
57 const IntegerIterator
<IntType2
>& aIter2
);
58 template <typename IntType1
, typename IntType2
>
59 friend bool operator!=(const IntegerIterator
<IntType1
>& aIter1
,
60 const IntegerIterator
<IntType2
>& aIter2
);
61 template <typename IntType1
, typename IntType2
>
62 friend bool operator<(const IntegerIterator
<IntType1
>& aIter1
,
63 const IntegerIterator
<IntType2
>& aIter2
);
64 template <typename IntType1
, typename IntType2
>
65 friend bool operator<=(const IntegerIterator
<IntType1
>& aIter1
,
66 const IntegerIterator
<IntType2
>& aIter2
);
67 template <typename IntType1
, typename IntType2
>
68 friend bool operator>(const IntegerIterator
<IntType1
>& aIter1
,
69 const IntegerIterator
<IntType2
>& aIter2
);
70 template <typename IntType1
, typename IntType2
>
71 friend bool operator>=(const IntegerIterator
<IntType1
>& aIter1
,
72 const IntegerIterator
<IntType2
>& aIter2
);
78 template <typename IntType1
, typename IntType2
>
79 bool operator==(const IntegerIterator
<IntType1
>& aIter1
,
80 const IntegerIterator
<IntType2
>& aIter2
) {
81 return aIter1
.mCurrent
== aIter2
.mCurrent
;
84 template <typename IntType1
, typename IntType2
>
85 bool operator!=(const IntegerIterator
<IntType1
>& aIter1
,
86 const IntegerIterator
<IntType2
>& aIter2
) {
87 return aIter1
.mCurrent
!= aIter2
.mCurrent
;
90 template <typename IntType1
, typename IntType2
>
91 bool operator<(const IntegerIterator
<IntType1
>& aIter1
,
92 const IntegerIterator
<IntType2
>& aIter2
) {
93 return aIter1
.mCurrent
< aIter2
.mCurrent
;
96 template <typename IntType1
, typename IntType2
>
97 bool operator<=(const IntegerIterator
<IntType1
>& aIter1
,
98 const IntegerIterator
<IntType2
>& aIter2
) {
99 return aIter1
.mCurrent
<= aIter2
.mCurrent
;
102 template <typename IntType1
, typename IntType2
>
103 bool operator>(const IntegerIterator
<IntType1
>& aIter1
,
104 const IntegerIterator
<IntType2
>& aIter2
) {
105 return aIter1
.mCurrent
> aIter2
.mCurrent
;
108 template <typename IntType1
, typename IntType2
>
109 bool operator>=(const IntegerIterator
<IntType1
>& aIter1
,
110 const IntegerIterator
<IntType2
>& aIter2
) {
111 return aIter1
.mCurrent
>= aIter2
.mCurrent
;
114 template <typename IntTypeT
>
117 typedef IntegerIterator
<IntTypeT
> iterator
;
118 typedef IntegerIterator
<IntTypeT
> const_iterator
;
119 typedef ReverseIterator
<IntegerIterator
<IntTypeT
>> reverse_iterator
;
120 typedef ReverseIterator
<IntegerIterator
<IntTypeT
>> const_reverse_iterator
;
122 template <typename IntType
>
123 explicit IntegerRange(IntType aEnd
) : mBegin(0), mEnd(aEnd
) {}
125 template <typename IntType1
, typename IntType2
>
126 IntegerRange(IntType1 aBegin
, IntType2 aEnd
) : mBegin(aBegin
), mEnd(aEnd
) {}
128 iterator
begin() const { return iterator(mBegin
); }
129 const_iterator
cbegin() const { return begin(); }
130 iterator
end() const { return iterator(mEnd
); }
131 const_iterator
cend() const { return end(); }
132 reverse_iterator
rbegin() const { return reverse_iterator(mEnd
); }
133 const_reverse_iterator
crbegin() const { return rbegin(); }
134 reverse_iterator
rend() const { return reverse_iterator(mBegin
); }
135 const_reverse_iterator
crend() const { return rend(); }
142 template <typename T
, bool = IsUnsigned
<T
>::value
>
144 static bool isNonNegative(T t
) { return t
>= 0; }
147 template <typename T
>
148 struct GeqZero
<T
, true> {
149 static bool isNonNegative(T t
) { return true; }
152 } // namespace detail
154 template <typename IntType
>
155 detail::IntegerRange
<IntType
> IntegerRange(IntType aEnd
) {
156 static_assert(IsIntegral
<IntType
>::value
, "value must be integral");
157 MOZ_ASSERT(detail::GeqZero
<IntType
>::isNonNegative(aEnd
),
158 "Should never have negative value here");
159 return detail::IntegerRange
<IntType
>(aEnd
);
162 template <typename IntType1
, typename IntType2
>
163 detail::IntegerRange
<IntType2
> IntegerRange(IntType1 aBegin
, IntType2 aEnd
) {
164 static_assert(IsIntegral
<IntType1
>::value
&& IsIntegral
<IntType2
>::value
,
165 "values must both be integral");
166 static_assert(IsSigned
<IntType1
>::value
== IsSigned
<IntType2
>::value
,
167 "signed/unsigned mismatch");
168 MOZ_ASSERT(aEnd
>= aBegin
, "End value should be larger than begin value");
169 return detail::IntegerRange
<IntType2
>(aBegin
, aEnd
);
172 } // namespace mozilla
174 #endif // mozilla_IntegerRange_h