Bug 1637291 [wpt PR 23538] - Update some scriptlevel tests to match the new syntax...
[gecko.git] / mfbt / IntegerRange.h
blob9d6720192d27cb33d69c1f66c77673602bf669cf
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>
17 namespace mozilla {
19 namespace detail {
21 template <typename IntTypeT>
22 class IntegerIterator {
23 public:
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++() {
36 ++mCurrent;
37 return *this;
39 IntegerIterator& operator--() {
40 --mCurrent;
41 return *this;
43 IntegerIterator operator++(int) {
44 auto ret = *this;
45 ++mCurrent;
46 return ret;
48 IntegerIterator operator--(int) {
49 auto ret = *this;
50 --mCurrent;
51 return ret;
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);
75 private:
76 IntTypeT mCurrent;
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>
116 class IntegerRange {
117 public:
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(); }
138 private:
139 IntTypeT mBegin;
140 IntTypeT mEnd;
143 template <typename T, bool = std::is_unsigned_v<T>>
144 struct GeqZero {
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