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 contiguous enum values */
8 :
9 : /*
10 : * Implements generator functions that create a range to iterate over the values
11 : * of a scoped or unscoped enum. Unlike IntegerRange, which can only function on
12 : * the underlying integral type, the elements of the generated sequence will
13 : * have the type of the enum in question.
14 : *
15 : * Note that the enum values should be contiguous in the iterated range;
16 : * unfortunately there exists no way for EnumeratedRange to enforce this
17 : * either dynamically or at compile time.
18 : */
19 :
20 : #ifndef mozilla_EnumeratedRange_h
21 : #define mozilla_EnumeratedRange_h
22 :
23 : #include <type_traits>
24 :
25 : #include "mozilla/ReverseIterator.h"
26 :
27 : namespace mozilla {
28 :
29 : namespace detail {
30 :
31 : template<typename EnumTypeT>
32 : class EnumeratedIterator
33 : {
34 : public:
35 : typedef typename std::underlying_type<EnumTypeT>::type IntTypeT;
36 :
37 : template<typename EnumType>
38 1874 : explicit EnumeratedIterator(EnumType aCurrent)
39 1874 : : mCurrent(aCurrent) { }
40 :
41 : template<typename EnumType>
42 : explicit EnumeratedIterator(const EnumeratedIterator<EnumType>& aOther)
43 : : mCurrent(aOther.mCurrent) { }
44 :
45 33941 : EnumTypeT operator*() const { return mCurrent; }
46 :
47 : /* Increment and decrement operators */
48 :
49 33941 : EnumeratedIterator& operator++()
50 : {
51 33941 : mCurrent = EnumTypeT(IntTypeT(mCurrent) + IntTypeT(1));
52 33941 : return *this;
53 : }
54 : EnumeratedIterator& operator--()
55 : {
56 : mCurrent = EnumTypeT(IntTypeT(mCurrent) - IntTypeT(1));
57 : return *this;
58 : }
59 : EnumeratedIterator operator++(int)
60 : {
61 : auto ret = *this;
62 : mCurrent = EnumTypeT(IntTypeT(mCurrent) + IntTypeT(1));
63 : return ret;
64 : }
65 : EnumeratedIterator operator--(int)
66 : {
67 : auto ret = *this;
68 : mCurrent = EnumTypeT(IntTypeT(mCurrent) - IntTypeT(1));
69 : return ret;
70 : }
71 :
72 : /* Comparison operators */
73 :
74 : template<typename EnumType>
75 : friend bool operator==(const EnumeratedIterator<EnumType>& aIter1,
76 : const EnumeratedIterator<EnumType>& aIter2);
77 : template<typename EnumType>
78 : friend bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
79 : const EnumeratedIterator<EnumType>& aIter2);
80 : template<typename EnumType>
81 : friend bool operator<(const EnumeratedIterator<EnumType>& aIter1,
82 : const EnumeratedIterator<EnumType>& aIter2);
83 : template<typename EnumType>
84 : friend bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
85 : const EnumeratedIterator<EnumType>& aIter2);
86 : template<typename EnumType>
87 : friend bool operator>(const EnumeratedIterator<EnumType>& aIter1,
88 : const EnumeratedIterator<EnumType>& aIter2);
89 : template<typename EnumType>
90 : friend bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
91 : const EnumeratedIterator<EnumType>& aIter2);
92 :
93 : private:
94 : EnumTypeT mCurrent;
95 : };
96 :
97 : template<typename EnumType>
98 : bool operator==(const EnumeratedIterator<EnumType>& aIter1,
99 : const EnumeratedIterator<EnumType>& aIter2)
100 : {
101 : return aIter1.mCurrent == aIter2.mCurrent;
102 : }
103 :
104 : template<typename EnumType>
105 34878 : bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
106 : const EnumeratedIterator<EnumType>& aIter2)
107 : {
108 34878 : return aIter1.mCurrent != aIter2.mCurrent;
109 : }
110 :
111 : template<typename EnumType>
112 : bool operator<(const EnumeratedIterator<EnumType>& aIter1,
113 : const EnumeratedIterator<EnumType>& aIter2)
114 : {
115 : return aIter1.mCurrent < aIter2.mCurrent;
116 : }
117 :
118 : template<typename EnumType>
119 : bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
120 : const EnumeratedIterator<EnumType>& aIter2)
121 : {
122 : return aIter1.mCurrent <= aIter2.mCurrent;
123 : }
124 :
125 : template<typename EnumType>
126 : bool operator>(const EnumeratedIterator<EnumType>& aIter1,
127 : const EnumeratedIterator<EnumType>& aIter2)
128 : {
129 : return aIter1.mCurrent > aIter2.mCurrent;
130 : }
131 :
132 : template<typename EnumType>
133 : bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
134 : const EnumeratedIterator<EnumType>& aIter2)
135 : {
136 : return aIter1.mCurrent >= aIter2.mCurrent;
137 : }
138 :
139 : template<typename EnumTypeT>
140 : class EnumeratedRange
141 : {
142 : public:
143 : typedef EnumeratedIterator<EnumTypeT> iterator;
144 : typedef EnumeratedIterator<EnumTypeT> const_iterator;
145 : typedef ReverseIterator<iterator> reverse_iterator;
146 : typedef ReverseIterator<const_iterator> const_reverse_iterator;
147 :
148 : template<typename EnumType>
149 937 : EnumeratedRange(EnumType aBegin, EnumType aEnd)
150 937 : : mBegin(aBegin), mEnd(aEnd) { }
151 :
152 937 : iterator begin() const { return iterator(mBegin); }
153 : const_iterator cbegin() const { return begin(); }
154 937 : iterator end() const { return iterator(mEnd); }
155 : const_iterator cend() const { return end(); }
156 : reverse_iterator rbegin() const { return reverse_iterator(mEnd); }
157 : const_reverse_iterator crbegin() const { return rbegin(); }
158 : reverse_iterator rend() const { return reverse_iterator(mBegin); }
159 : const_reverse_iterator crend() const { return rend(); }
160 :
161 : private:
162 : EnumTypeT mBegin;
163 : EnumTypeT mEnd;
164 : };
165 :
166 : } // namespace detail
167 :
168 : #ifdef __GNUC__
169 : // Enums can have an unsigned underlying type, which makes some of the
170 : // comparisons below always true or always false. Temporarily disable
171 : // -Wtype-limits to avoid breaking -Werror builds.
172 : # pragma GCC diagnostic push
173 : # pragma GCC diagnostic ignored "-Wtype-limits"
174 : #endif
175 :
176 : // Create a range to iterate from aBegin to aEnd, exclusive.
177 : template<typename EnumType>
178 : inline detail::EnumeratedRange<EnumType>
179 937 : MakeEnumeratedRange(EnumType aBegin, EnumType aEnd)
180 : {
181 937 : MOZ_ASSERT(aBegin <= aEnd, "Cannot generate invalid, unbounded range!");
182 937 : return detail::EnumeratedRange<EnumType>(aBegin, aEnd);
183 : }
184 :
185 : // Create a range to iterate from EnumType(0) to aEnd, exclusive. EnumType(0)
186 : // should exist, but note that there is no way for us to ensure that it does!
187 : template<typename EnumType>
188 : inline detail::EnumeratedRange<EnumType>
189 99 : MakeEnumeratedRange(EnumType aEnd)
190 : {
191 99 : return MakeEnumeratedRange(EnumType(0), aEnd);
192 : }
193 :
194 : #ifdef __GNUC__
195 : # pragma GCC diagnostic pop
196 : #endif
197 :
198 : } // namespace mozilla
199 :
200 : #endif // mozilla_EnumeratedRange_h
201 :
|