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 : /* Iterator over ranges of integers */
8 :
9 : #ifndef mozilla_IntegerRange_h
10 : #define mozilla_IntegerRange_h
11 :
12 : #include "mozilla/Assertions.h"
13 : #include "mozilla/ReverseIterator.h"
14 : #include "mozilla/TypeTraits.h"
15 :
16 : namespace mozilla {
17 :
18 : namespace detail {
19 :
20 : template<typename IntTypeT>
21 : class IntegerIterator
22 : {
23 : public:
24 : template<typename IntType>
25 15472 : explicit IntegerIterator(IntType aCurrent)
26 15472 : : mCurrent(aCurrent) { }
27 :
28 : template<typename IntType>
29 : explicit IntegerIterator(const IntegerIterator<IntType>& aOther)
30 : : mCurrent(aOther.mCurrent) { }
31 :
32 15601 : IntTypeT operator*() const { return mCurrent; }
33 :
34 : /* Increment and decrement operators */
35 :
36 15601 : IntegerIterator& operator++() { ++mCurrent; return *this; }
37 0 : IntegerIterator& operator--() { --mCurrent; return *this; }
38 : IntegerIterator operator++(int) { auto ret = *this; ++mCurrent; return ret; }
39 : IntegerIterator operator--(int) { auto ret = *this; --mCurrent; return ret; }
40 :
41 : /* Comparison operators */
42 :
43 : template<typename IntType1, typename IntType2>
44 : friend bool operator==(const IntegerIterator<IntType1>& aIter1,
45 : const IntegerIterator<IntType2>& aIter2);
46 : template<typename IntType1, typename IntType2>
47 : friend bool operator!=(const IntegerIterator<IntType1>& aIter1,
48 : const IntegerIterator<IntType2>& aIter2);
49 : template<typename IntType1, typename IntType2>
50 : friend bool operator<(const IntegerIterator<IntType1>& aIter1,
51 : const IntegerIterator<IntType2>& aIter2);
52 : template<typename IntType1, typename IntType2>
53 : friend bool operator<=(const IntegerIterator<IntType1>& aIter1,
54 : const IntegerIterator<IntType2>& aIter2);
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 :
62 : private:
63 : IntTypeT mCurrent;
64 : };
65 :
66 : template<typename IntType1, typename IntType2>
67 : bool operator==(const IntegerIterator<IntType1>& aIter1,
68 : const IntegerIterator<IntType2>& aIter2)
69 : {
70 : return aIter1.mCurrent == aIter2.mCurrent;
71 : }
72 :
73 : template<typename IntType1, typename IntType2>
74 23337 : bool operator!=(const IntegerIterator<IntType1>& aIter1,
75 : const IntegerIterator<IntType2>& aIter2)
76 : {
77 23337 : return aIter1.mCurrent != aIter2.mCurrent;
78 : }
79 :
80 : template<typename IntType1, typename IntType2>
81 : bool operator<(const IntegerIterator<IntType1>& aIter1,
82 : const IntegerIterator<IntType2>& aIter2)
83 : {
84 : return aIter1.mCurrent < aIter2.mCurrent;
85 : }
86 :
87 : template<typename IntType1, typename IntType2>
88 : bool operator<=(const IntegerIterator<IntType1>& aIter1,
89 : const IntegerIterator<IntType2>& aIter2)
90 : {
91 : return aIter1.mCurrent <= aIter2.mCurrent;
92 : }
93 :
94 : template<typename IntType1, typename IntType2>
95 : bool operator>(const IntegerIterator<IntType1>& aIter1,
96 : const IntegerIterator<IntType2>& aIter2)
97 : {
98 : return aIter1.mCurrent > aIter2.mCurrent;
99 : }
100 :
101 : template<typename IntType1, typename IntType2>
102 : bool operator>=(const IntegerIterator<IntType1>& aIter1,
103 : const IntegerIterator<IntType2>& aIter2)
104 : {
105 : return aIter1.mCurrent >= aIter2.mCurrent;
106 : }
107 :
108 : template<typename IntTypeT>
109 : class IntegerRange
110 : {
111 : public:
112 : typedef IntegerIterator<IntTypeT> iterator;
113 : typedef IntegerIterator<IntTypeT> const_iterator;
114 : typedef ReverseIterator<IntegerIterator<IntTypeT>> reverse_iterator;
115 : typedef ReverseIterator<IntegerIterator<IntTypeT>> const_reverse_iterator;
116 :
117 : template<typename IntType>
118 7736 : explicit IntegerRange(IntType aEnd)
119 7736 : : mBegin(0), mEnd(aEnd) { }
120 :
121 : template<typename IntType1, typename IntType2>
122 : IntegerRange(IntType1 aBegin, IntType2 aEnd)
123 : : mBegin(aBegin), mEnd(aEnd) { }
124 :
125 7732 : iterator begin() const { return iterator(mBegin); }
126 : const_iterator cbegin() const { return begin(); }
127 7732 : iterator end() const { return iterator(mEnd); }
128 : const_iterator cend() const { return end(); }
129 4 : reverse_iterator rbegin() const { return reverse_iterator(mEnd); }
130 : const_reverse_iterator crbegin() const { return rbegin(); }
131 4 : reverse_iterator rend() const { return reverse_iterator(mBegin); }
132 : const_reverse_iterator crend() const { return rend(); }
133 :
134 : private:
135 : IntTypeT mBegin;
136 : IntTypeT mEnd;
137 : };
138 :
139 : template<typename T, bool = IsUnsigned<T>::value>
140 : struct GeqZero
141 : {
142 0 : static bool check(T t) {
143 0 : return t >= 0;
144 : }
145 : };
146 :
147 : template<typename T>
148 : struct GeqZero<T, true>
149 : {
150 7736 : static bool check(T t) {
151 7736 : return true;
152 : }
153 : };
154 :
155 : } // namespace detail
156 :
157 : template<typename IntType>
158 : detail::IntegerRange<IntType>
159 7736 : IntegerRange(IntType aEnd)
160 : {
161 : static_assert(IsIntegral<IntType>::value, "value must be integral");
162 7736 : MOZ_ASSERT(detail::GeqZero<IntType>::check(aEnd),
163 : "Should never have negative value here");
164 7736 : return detail::IntegerRange<IntType>(aEnd);
165 : }
166 :
167 : template<typename IntType1, typename IntType2>
168 : detail::IntegerRange<IntType2>
169 : IntegerRange(IntType1 aBegin, IntType2 aEnd)
170 : {
171 : static_assert(IsIntegral<IntType1>::value && IsIntegral<IntType2>::value,
172 : "values must both be integral");
173 : static_assert(IsSigned<IntType1>::value == IsSigned<IntType2>::value,
174 : "signed/unsigned mismatch");
175 : MOZ_ASSERT(aEnd >= aBegin, "End value should be larger than begin value");
176 : return detail::IntegerRange<IntType2>(aBegin, aEnd);
177 : }
178 :
179 : } // namespace mozilla
180 :
181 : #endif // mozilla_IntegerRange_h
|