]>
Commit | Line | Data |
---|---|---|
2fefc43c | 1 | /* |
bf95c10a | 2 | * Copyright (C) 1996-2022 The Squid Software Foundation and contributors |
2fefc43c FC |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | #ifndef SQUID_BASE_ENUMITERATOR_H | |
10 | #define SQUID_BASE_ENUMITERATOR_H | |
11 | ||
12 | #include <iterator> | |
13 | #include <type_traits> | |
14 | ||
15 | /** Shared functionality between forward and reverse enum iterators | |
16 | * | |
17 | * This class is not very useful by itself, it contains code shared by | |
18 | * EnumIterator and ReverseEnumIterator. | |
19 | * | |
20 | * \see EnumIterator, ReverseEnumIterator | |
21 | */ | |
22 | template <typename EnumType> | |
c3f0885d | 23 | class EnumIteratorBase |
2fefc43c FC |
24 | { |
25 | protected: | |
26 | #if HAVE_STD_UNDERLYING_TYPE | |
27 | typedef typename std::underlying_type<EnumType>::type iterator_type; | |
28 | #else | |
29 | typedef int iterator_type; | |
30 | #endif | |
31 | ||
32 | public: | |
c3f0885d FC |
33 | using iterator_category = std::bidirectional_iterator_tag; |
34 | using value_type = EnumType; | |
35 | using difference_type = std::ptrdiff_t; | |
36 | using pointer = EnumType *; | |
37 | using reference = EnumType &; | |
38 | ||
2fefc43c FC |
39 | explicit EnumIteratorBase(EnumType e) : current(static_cast<iterator_type>(e)) {} |
40 | ||
41 | bool operator==(const EnumIteratorBase &i) const { | |
42 | return current == i.current; | |
43 | } | |
44 | ||
45 | bool operator!=(const EnumIteratorBase &i) const { | |
46 | return current != i.current; | |
47 | } | |
48 | ||
49 | EnumType operator*() const { | |
50 | return static_cast<EnumType>(current); | |
51 | } | |
52 | protected: | |
53 | iterator_type current; | |
54 | }; | |
55 | ||
56 | /** bidirectional iterator over an enum type | |
57 | * | |
58 | * It can be instantiated using any enum (or C++11 strongly-typed enum) | |
59 | * value; the most common expected use scenario has iterators emitted by | |
60 | * EnumRange and WholeEnum via standard begin() and end() calls. | |
61 | * | |
62 | * In order for the iterator to work, it is mandatory that the underlying | |
63 | * enum type's representation values be sequential. | |
64 | * | |
65 | * The iterator does not check for bounds when incrementing or decrementing, | |
66 | * that responsibility is left to the caller. | |
67 | * | |
68 | * \see EnumRange, WholeEnum, ReverseEnumIterator | |
69 | */ | |
70 | template <typename EnumType> | |
71 | class EnumIterator : public EnumIteratorBase<EnumType> | |
72 | { | |
73 | public: | |
74 | explicit EnumIterator(EnumType e) : EnumIteratorBase<EnumType>(e) {} | |
75 | ||
76 | EnumIterator& operator++() { | |
77 | ++ EnumIteratorBase<EnumType>::current; | |
78 | return *this; | |
79 | } | |
80 | ||
81 | EnumIterator& operator++(int) { | |
82 | EnumIterator rv(*this); | |
83 | ++ EnumIteratorBase<EnumType>::current; | |
84 | return rv; | |
85 | } | |
86 | ||
87 | EnumIterator& operator--() { | |
88 | -- EnumIteratorBase<EnumType>::current; | |
89 | return *this; | |
90 | } | |
91 | ||
92 | EnumIterator& operator--(int) { | |
93 | EnumIterator rv(*this); | |
94 | -- EnumIteratorBase<EnumType>::current; | |
95 | return rv; | |
96 | } | |
97 | }; | |
98 | ||
99 | /** bidirectional reverse iterator over an enum type | |
100 | * | |
101 | * It can be instantiated using any enum (or C++11 strongly-typed enum) | |
102 | * value; the most common expected use scenario has iterators emitted by | |
103 | * EnumRange and WholeEnum via standard rbegin() and rend() calls. | |
104 | * | |
105 | * In order for the iterator to work, it is mandatory that the underlying | |
106 | * enum type's representation values be sequential. | |
107 | * | |
108 | * The iterator does not check for bounds; behavior is undefined if the iterator | |
109 | * is incremented (or decremented) outside the range representing valid | |
110 | * enum symbols (remember: an enum is not a data structure). | |
111 | * | |
112 | * \see EnumRange, WholeEnum, EnumIterator | |
113 | */ | |
114 | template <typename EnumType> | |
115 | class ReverseEnumIterator : public EnumIteratorBase<EnumType> | |
116 | { | |
117 | public: | |
118 | explicit ReverseEnumIterator(EnumType e) : EnumIteratorBase<EnumType>(e) {} | |
119 | ||
120 | // prefix increment | |
121 | ReverseEnumIterator& operator++() { | |
122 | -- EnumIteratorBase<EnumType>::current; | |
123 | return *this; | |
124 | } | |
125 | ||
126 | // postfix increment | |
127 | ReverseEnumIterator& operator++(int) { | |
128 | ReverseEnumIterator rv(*this); | |
129 | -- EnumIteratorBase<EnumType>::current; | |
130 | return rv; | |
131 | } | |
132 | ||
133 | // prefix decrement | |
134 | ReverseEnumIterator& operator--() { | |
135 | ++ EnumIteratorBase<EnumType>::current; | |
136 | return *this; | |
137 | } | |
138 | ||
139 | // postfix decrement | |
140 | ReverseEnumIterator& operator--(int) { | |
141 | ReverseEnumIterator rv(*this); | |
142 | ++ EnumIteratorBase<EnumType>::current; | |
143 | return rv; | |
144 | } | |
145 | }; | |
146 | ||
147 | /** Class expressing a continuous range of an enum for range-for expressions | |
148 | * | |
149 | * This class requires that the underlying enum values be represented by | |
150 | * continuous values of an integral type. | |
151 | * Users will usually not rely on this class directly but on the more convenient | |
152 | * EnumRange function | |
153 | * | |
154 | * \note EnumIterator<enum>(EnumType::firstmember,EnumType::lastmember) | |
155 | * will miss EnumType::lastmember while iterating. If you need to iterate | |
156 | * over all of EnumType, use class WholeEnum. | |
157 | * | |
158 | * \see EnumRange, WholeEnum | |
159 | */ | |
160 | template <typename EnumType> | |
161 | class EnumRangeT | |
162 | { | |
163 | public: | |
164 | typedef EnumIterator<EnumType> iterator; | |
165 | typedef ReverseEnumIterator<EnumType> reverse_iterator; | |
166 | EnumRangeT(EnumType first, EnumType one_past_last) : begin_(first), end_(one_past_last) { } | |
167 | iterator begin() const { return iterator(begin_);} | |
168 | iterator end() const { return iterator(end_);} | |
169 | reverse_iterator rbegin() const { return ++reverse_iterator(end_); } | |
170 | reverse_iterator rend() const { return ++reverse_iterator(begin_); } | |
171 | private: | |
172 | EnumType begin_; | |
173 | EnumType end_; | |
174 | }; | |
175 | ||
176 | /** Generate a continuous range of an enum for range-for expressions | |
177 | * | |
178 | * convenience function to deduce the right type for instantiating EnumRangeT. | |
179 | * See EnumRangeT for more detailed documentation and caveats. | |
180 | * | |
181 | * Typical use: | |
182 | * \code | |
183 | * enum class EnumType { | |
184 | * blue, red, yellow, green, pink | |
185 | * }; | |
186 | * for (auto enumvalue : EnumRange(EnumType::red,EnumType::green)) { | |
187 | * do_stuff(enumvalue); // will be called twice, with arguments red and yellow | |
188 | * } | |
189 | * \endcode | |
190 | */ | |
191 | template <typename EnumType> | |
192 | EnumRangeT<EnumType> EnumRange(EnumType begin, EnumType one_past_end) | |
193 | { | |
194 | return EnumRangeT<EnumType>(begin,one_past_end); | |
195 | } | |
196 | ||
197 | /** Class expressing a continuous range of a whole enum for range-for expressions | |
198 | * | |
199 | * Class for iterating all enum values, from EnumType::enumBegin_ up to, but | |
200 | * not including, EnumType::enumEnd_. | |
201 | * | |
202 | * This class requires that: | |
203 | * - the underlying enum values be represented by continuous values of | |
204 | * an integral type. | |
205 | * - both enumBegin_ and enumEnd_ markers must be present as EnumType values; | |
206 | * - enumBegin_ must have the same representation as the first element of the | |
207 | * enum | |
208 | * - enumEnd_ must have a representation that is one past the last | |
209 | * user-accessible value of the enum. | |
210 | * | |
211 | * Typical use: | |
212 | * \code | |
213 | * enum class EnumType { | |
214 | * enumBegin_ = 0, | |
215 | * first_value = enumBegin_, | |
216 | * second_value, | |
217 | * enumEnd_ | |
218 | * }; | |
219 | * for(auto enumvalue : WholeEnum<EnumType>()) { | |
220 | * do_stuff(); | |
221 | * } | |
222 | * \endcode | |
223 | */ | |
224 | template <typename EnumType> | |
225 | class WholeEnum : public EnumRangeT<EnumType> | |
226 | { | |
227 | public: | |
228 | WholeEnum() : EnumRangeT<EnumType>(EnumType::enumBegin_, EnumType::enumEnd_) {} | |
229 | }; | |
230 | ||
231 | #endif /* SQUID_BASE_ENUMITERATOR_H */ | |
232 |