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