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"
15 #include <type_traits>
21 template <typename IntTypeT
>
22 class IntegerIterator
{
24 template <typename IntType
>
25 explicit IntegerIterator(IntType aCurrent
) : mCurrent(aCurrent
) {}
27 template <typename IntType
>
28 explicit IntegerIterator(const IntegerIterator
<IntType
>& aOther
)
29 : mCurrent(aOther
.mCurrent
) {}
31 IntTypeT
operator*() const { return mCurrent
; }
33 /* Increment and decrement operators */
35 IntegerIterator
& operator++() {
39 IntegerIterator
& operator--() {
43 IntegerIterator
operator++(int) {
48 IntegerIterator
operator--(int) {
54 /* Comparison operators */
56 template <typename IntType1
, typename IntType2
>
57 friend bool operator==(const IntegerIterator
<IntType1
>& aIter1
,
58 const IntegerIterator
<IntType2
>& aIter2
);
59 template <typename IntType1
, typename IntType2
>
60 friend bool operator!=(const IntegerIterator
<IntType1
>& aIter1
,
61 const IntegerIterator
<IntType2
>& aIter2
);
62 template <typename IntType1
, typename IntType2
>
63 friend bool operator<(const IntegerIterator
<IntType1
>& aIter1
,
64 const IntegerIterator
<IntType2
>& aIter2
);
65 template <typename IntType1
, typename IntType2
>
66 friend bool operator<=(const IntegerIterator
<IntType1
>& aIter1
,
67 const IntegerIterator
<IntType2
>& aIter2
);
68 template <typename IntType1
, typename IntType2
>
69 friend bool operator>(const IntegerIterator
<IntType1
>& aIter1
,
70 const IntegerIterator
<IntType2
>& aIter2
);
71 template <typename IntType1
, typename IntType2
>
72 friend bool operator>=(const IntegerIterator
<IntType1
>& aIter1
,
73 const IntegerIterator
<IntType2
>& aIter2
);
79 template <typename IntType1
, typename IntType2
>
80 bool operator==(const IntegerIterator
<IntType1
>& aIter1
,
81 const IntegerIterator
<IntType2
>& aIter2
) {
82 return aIter1
.mCurrent
== aIter2
.mCurrent
;
85 template <typename IntType1
, typename IntType2
>
86 bool operator!=(const IntegerIterator
<IntType1
>& aIter1
,
87 const IntegerIterator
<IntType2
>& aIter2
) {
88 return aIter1
.mCurrent
!= aIter2
.mCurrent
;
91 template <typename IntType1
, typename IntType2
>
92 bool operator<(const IntegerIterator
<IntType1
>& aIter1
,
93 const IntegerIterator
<IntType2
>& aIter2
) {
94 return aIter1
.mCurrent
< aIter2
.mCurrent
;
97 template <typename IntType1
, typename IntType2
>
98 bool operator<=(const IntegerIterator
<IntType1
>& aIter1
,
99 const IntegerIterator
<IntType2
>& aIter2
) {
100 return aIter1
.mCurrent
<= aIter2
.mCurrent
;
103 template <typename IntType1
, typename IntType2
>
104 bool operator>(const IntegerIterator
<IntType1
>& aIter1
,
105 const IntegerIterator
<IntType2
>& aIter2
) {
106 return aIter1
.mCurrent
> aIter2
.mCurrent
;
109 template <typename IntType1
, typename IntType2
>
110 bool operator>=(const IntegerIterator
<IntType1
>& aIter1
,
111 const IntegerIterator
<IntType2
>& aIter2
) {
112 return aIter1
.mCurrent
>= aIter2
.mCurrent
;
115 template <typename IntTypeT
>
118 typedef IntegerIterator
<IntTypeT
> iterator
;
119 typedef IntegerIterator
<IntTypeT
> const_iterator
;
120 typedef ReverseIterator
<IntegerIterator
<IntTypeT
>> reverse_iterator
;
121 typedef ReverseIterator
<IntegerIterator
<IntTypeT
>> const_reverse_iterator
;
123 template <typename IntType
>
124 explicit IntegerRange(IntType aEnd
) : mBegin(0), mEnd(aEnd
) {}
126 template <typename IntType1
, typename IntType2
>
127 IntegerRange(IntType1 aBegin
, IntType2 aEnd
) : mBegin(aBegin
), mEnd(aEnd
) {}
129 iterator
begin() const { return iterator(mBegin
); }
130 const_iterator
cbegin() const { return begin(); }
131 iterator
end() const { return iterator(mEnd
); }
132 const_iterator
cend() const { return end(); }
133 reverse_iterator
rbegin() const { return reverse_iterator(mEnd
); }
134 const_reverse_iterator
crbegin() const { return rbegin(); }
135 reverse_iterator
rend() const { return reverse_iterator(mBegin
); }
136 const_reverse_iterator
crend() const { return rend(); }
143 template <typename T
, bool = std::is_unsigned_v
<T
>>
145 static bool isNonNegative(T t
) { return t
>= 0; }
148 template <typename T
>
149 struct GeqZero
<T
, true> {
150 static bool isNonNegative(T t
) { return true; }
153 } // namespace detail
155 template <typename IntType
>
156 detail::IntegerRange
<IntType
> IntegerRange(IntType aEnd
) {
157 static_assert(std::is_integral_v
<IntType
>, "value must be integral");
158 MOZ_ASSERT(detail::GeqZero
<IntType
>::isNonNegative(aEnd
),
159 "Should never have negative value here");
160 return detail::IntegerRange
<IntType
>(aEnd
);
163 template <typename IntType1
, typename IntType2
>
164 detail::IntegerRange
<IntType2
> IntegerRange(IntType1 aBegin
, IntType2 aEnd
) {
165 static_assert(std::is_integral_v
<IntType1
> && std::is_integral_v
<IntType2
>,
166 "values must both be integral");
167 static_assert(std::is_signed_v
<IntType1
> == std::is_signed_v
<IntType2
>,
168 "signed/unsigned mismatch");
169 MOZ_ASSERT(aEnd
>= aBegin
, "End value should be larger than begin value");
170 return detail::IntegerRange
<IntType2
>(aBegin
, aEnd
);
173 } // namespace mozilla
175 #endif // mozilla_IntegerRange_h