]> git.ipfire.org Git - thirdparty/squid.git/blob - src/base/EnumIterator.h
c3673595f6952643c239de07aac2a5bd932828da
[thirdparty/squid.git] / src / base / EnumIterator.h
1 /*
2 * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
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