]> git.ipfire.org Git - thirdparty/squid.git/blame - src/base/EnumIterator.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / base / EnumIterator.h
CommitLineData
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 */
22template <typename EnumType>
23class EnumIteratorBase : public std::iterator<std::bidirectional_iterator_tag, EnumType>
24{
25protected:
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
32public:
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 }
46protected:
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 */
64template <typename EnumType>
65class EnumIterator : public EnumIteratorBase<EnumType>
66{
67public:
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 */
108template <typename EnumType>
109class ReverseEnumIterator : public EnumIteratorBase<EnumType>
110{
111public:
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 */
154template <typename EnumType>
155class EnumRangeT
156{
157public:
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_); }
165private:
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 */
185template <typename EnumType>
186EnumRangeT<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 */
218template <typename EnumType>
219class WholeEnum : public EnumRangeT<EnumType>
220{
221public:
222 WholeEnum() : EnumRangeT<EnumType>(EnumType::enumBegin_, EnumType::enumEnd_) {}
223};
224
225#endif /* SQUID_BASE_ENUMITERATOR_H */
226