1 // This may look like C code, but it's really -*- C++ -*-
2 /*
3 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
4 *
5 * See the LICENSE file for terms of use.
6 */
7 #ifndef WFLAGS_H_
8 #define WFLAGS_H_
9
10 #include <Wt/WDllDefs.h>
11 #include <cassert>
12
13 namespace Wt {
14
15 /*! \class WFlags Wt/WFlags.h Wt/WFlags.h
16 * \brief Utility class for type-safe combinations of enumeration flags.
17 *
18 * This type is used in %Wt API whenever one or more flag options are
19 * expected, instead of an <tt>int</tt>. The class provides type
20 * safety, in the sense that it checks that the correct combination of
21 * enum values is bound to the argument, and does not cost any
22 * run-time overhead (internally it uses only an <tt>int</tt> to
23 * represent the combination of flags.
24 */
25
26 struct NoFlagsType { };
27 const NoFlagsType None = NoFlagsType();
28
29 template<typename EnumType>
30 class WFlags
31 {
32 typedef const WFlags<EnumType>& MaskType;
33 public:
34 typedef EnumType enum_type;
35
36 /*! \brief Default constructor.
37 */
38 inline WFlags(NoFlagsType none = None);
39
40 /*! \brief Construct from a single enum value.
41 */
42 inline WFlags(EnumType flag);
43
44 /*! \brief Copy constructor.
45 */
46 inline WFlags(const WFlags<EnumType>& other);
47
48 /*! \brief Assignment operator.
49 */
50 inline WFlags<EnumType>& operator=(const WFlags<EnumType>& other);
51
52 /*! \brief Assignment operator.
53 */
54 inline WFlags<EnumType>& operator=(const EnumType other);
55
56 /*! \brief Returns whether a flag is set.
57 */
58 inline bool test(EnumType flag) const;
59
60 /*! \brief Returns true if this WFlags contains no flags.
61 */
62 inline bool empty() const;
63
64 /*! \brief Clears a flag.
65 */
66 inline WFlags<EnumType>& clear(EnumType value);
67
68 /*! \brief Cast to the enum type.
69 *
70 * The internal <tt>int</tt> representation is simply cast to the
71 * enum type, without any additional checks.
72 */
73 inline operator EnumType() const;
74
75 inline int bitCount() const;
76
77 /*! \brief Negation operator.
78 *
79 * Returns whether different from 0.
80 */
81 inline bool operator!() const;
82
83 /*! \brief Bitwise AND operator.
84 *
85 * Returns flags that are the bitwise AND of this and \p mask.
86 */
87 inline WFlags<EnumType> operator&(EnumType mask) const;
88
89 /*! \brief Bitwise AND operator.
90 *
91 * Returns flags that are the bitwise AND of this and \p mask.
92 */
93 inline WFlags<EnumType> operator&(MaskType mask) const;
94
95 /*! \brief Modifying bitwise AND operator.
96 *
97 * Sets as value the bitwise AND of this and \p mask.
98 */
99 inline WFlags<EnumType>& operator&=(EnumType mask);
100
101 /*! \brief Modifying bitwise AND operator.
102 *
103 * Sets as value the bitwise AND of this and \p mask.
104 */
105 inline WFlags<EnumType>& operator&=(MaskType mask);
106
107 /*! \brief Bitwise XOR operator.
108 *
109 * Returns flags that are the bitwise XOR of this and \p other.
110 */
111 inline WFlags<EnumType> operator^(WFlags<EnumType> other) const;
112
113 /*! \brief Bitwise XOR operator.
114 *
115 * Returns flags that are the bitwise XOR of this and \p other.
116 */
117 inline WFlags<EnumType> operator^(EnumType other) const;
118
119 /*! \brief Modifying bitwise XOR operator.
120 *
121 * Sets as value the bitwise XOR of this and \p other.
122 */
123 inline WFlags<EnumType>& operator^=(WFlags<EnumType> other);
124
125 /*! \brief Modifying bitwise XOR operator.
126 *
127 * Sets as value the bitwise XOR of this and \p other.
128 */
129 inline WFlags<EnumType>& operator^=(EnumType other);
130
131 /*! \brief Bitwise OR operator.
132 *
133 * Returns flags that are the bitwise OR of this and \p other.
134 */
135 inline WFlags<EnumType> operator|(WFlags<EnumType> other) const;
136
137 /*! \brief Bitwise OR operator.
138 *
139 * Returns flags that are the bitwise OR of this and \p other.
140 */
141 inline WFlags<EnumType> operator|(EnumType other) const;
142
143 /*! \brief Modifying bitwise OR operator.
144 *
145 * Sets as value the bitwise OR of this and \p other.
146 */
147 inline WFlags<EnumType>& operator|=(WFlags<EnumType> other);
148
149 /*! \brief Modifying bitwise OR operator.
150 *
151 * Sets as value the bitwise OR of this and \p other.
152 */
153 inline WFlags<EnumType>& operator|=(EnumType other);
154
155 /*! \brief Inversion operator.
156 *
157 * Returns flags that are the inverted of this.
158 */
159 inline WFlags<EnumType> operator~() const;
160
161 inline bool operator==(WFlags<EnumType> other) const;
162 inline bool operator==(EnumType other) const;
163 inline bool operator!=(WFlags<EnumType> other) const;
164 inline bool operator!=(EnumType other) const;
165 inline bool operator<(WFlags<EnumType> other) const;
166
value()167 inline int value() const { return flags_; }
168
169 private:
170 unsigned int flags_;
171
WFlags(int flags,bool)172 WFlags(int flags, bool): flags_(flags) {}
createFromInt(int flags)173 inline static WFlags<EnumType> createFromInt(int flags) {
174 return WFlags(flags, false);
175 }
176
177 };
178
179 template<typename EnumType>
WFlags(const WFlags<EnumType> & other)180 WFlags<EnumType>::WFlags(const WFlags<EnumType>& other):
181 flags_(other.flags_)
182 {
183 }
184
185 template<typename EnumType>
WFlags(enum_type flag)186 WFlags<EnumType>::WFlags(enum_type flag):
187 flags_(static_cast<unsigned int>(flag))
188 {
189 }
190
191 template<typename EnumType>
WFlags(NoFlagsType)192 WFlags<EnumType>::WFlags(NoFlagsType /* noFlags */)
193 : flags_(0)
194 { }
195
196 template<typename EnumType>
test(enum_type flag)197 bool WFlags<EnumType>::test(enum_type flag) const
198 {
199 return flags_ & static_cast<unsigned int>(flag);
200 }
201
202 template<typename EnumType>
empty()203 bool WFlags<EnumType>::empty() const
204 {
205 return flags_ == 0;
206 }
207
208 template<typename EnumType>
clear(enum_type flag)209 WFlags<EnumType>& WFlags<EnumType>::clear(enum_type flag)
210 {
211 flags_ &= ~static_cast<unsigned int>(flag);
212 return *this;
213 }
214
215 template<typename EnumType>
EnumType()216 WFlags<EnumType>::operator EnumType() const
217 {
218 return static_cast<EnumType>(flags_);
219 }
220
221 template<typename EnumType>
bitCount()222 int WFlags<EnumType>::bitCount() const
223 {
224 unsigned n = flags_;
225 int retval = 0;
226 while (n) {
227 retval ++;
228 n &= n - 1;
229 }
230 return retval;
231 }
232
233 template<typename EnumType>
234 bool WFlags<EnumType>::operator!() const
235 {
236 return !flags_;
237 }
238
239 template<typename EnumType>
240 WFlags<EnumType> WFlags<EnumType>::operator&(EnumType mask) const
241 {
242 return WFlags<EnumType>::createFromInt(flags_ & (unsigned)mask);
243 }
244
245 template<typename EnumType>
246 WFlags<EnumType> WFlags<EnumType>::operator&(MaskType mask) const
247 {
248 return WFlags<EnumType>::createFromInt(flags_ & mask.value());
249 }
250
251 template<typename EnumType>
252 WFlags<EnumType> &WFlags<EnumType>::operator&=(MaskType mask)
253 {
254 flags_ &= mask.value();
255 return *this;
256 }
257
258 template<typename EnumType>
259 WFlags<EnumType> &WFlags<EnumType>::operator&=(EnumType mask)
260 {
261 flags_ &= (unsigned)mask;
262 return *this;
263 }
264
265 template<typename EnumType>
266 WFlags<EnumType>& WFlags<EnumType>::operator=(const WFlags<EnumType>& other)
267 {
268 flags_ = other.flags_;
269 return *this;
270 }
271
272 template<typename EnumType>
273 WFlags<EnumType>& WFlags<EnumType>::operator=(const EnumType other)
274 {
275 flags_ = static_cast<unsigned int>(other);
276 return *this;
277 }
278
279 template<typename EnumType>
280 WFlags<EnumType> WFlags<EnumType>::operator^(WFlags<EnumType> other) const
281 {
282 return WFlags<EnumType>::createFromInt(flags_ ^ other.flags_);
283 }
284
285 template<typename EnumType>
286 WFlags<EnumType> WFlags<EnumType>::operator^(EnumType other) const
287 {
288 return WFlags<EnumType>::createFromInt(flags_ ^ other);
289 }
290
291 template<typename EnumType>
292 WFlags<EnumType>& WFlags<EnumType>::operator^=(WFlags<EnumType> other)
293 {
294 flags_ ^= other.flags_;
295 return *this;
296 }
297
298 template<typename EnumType>
299 WFlags<EnumType>& WFlags<EnumType>::operator^=(EnumType other)
300 {
301 flags_ ^= other;
302 return *this;
303 }
304
305 template<typename EnumType>
306 WFlags<EnumType> WFlags<EnumType>::operator|(WFlags<EnumType> other) const
307 {
308 return WFlags<EnumType>::createFromInt(flags_ | other.flags_);
309 }
310
311 template<typename EnumType>
312 WFlags<EnumType> WFlags<EnumType>::operator|(EnumType other) const
313 {
314 return WFlags<EnumType>::createFromInt
315 (flags_ | static_cast<unsigned int>(other));
316 }
317
318 template<typename EnumType>
319 WFlags<EnumType>& WFlags<EnumType>::operator|=(WFlags<EnumType> other)
320 {
321 flags_ |= other.flags_;
322 return *this;
323 }
324
325 template<typename EnumType>
326 WFlags<EnumType>& WFlags<EnumType>::operator|=(EnumType other)
327 {
328 flags_ |= static_cast<unsigned int>(other);
329 return *this;
330 }
331
332 template<typename EnumType>
333 WFlags<EnumType> WFlags<EnumType>::operator~() const
334 {
335 return WFlags<EnumType>::createFromInt(~flags_);
336 }
337
338 template<typename EnumType>
339 bool WFlags<EnumType>::operator==(WFlags<EnumType> other) const
340 {
341 return flags_ == other.flags_;
342 }
343
344 template<typename EnumType>
345 bool WFlags<EnumType>::operator==(EnumType other) const
346 {
347 return flags_ == static_cast<unsigned int>(other);
348 }
349
350 template<typename EnumType>
351 bool WFlags<EnumType>::operator!=(WFlags<EnumType> other) const
352 {
353 return flags_ != other.flags_;
354 }
355
356 template<typename EnumType>
357 bool WFlags<EnumType>::operator!=(EnumType other) const
358 {
359 return flags_ != static_cast<unsigned int>(other);
360 }
361
362 template<typename EnumType>
363 bool WFlags<EnumType>::operator<(WFlags<EnumType> other) const
364 {
365 return flags_ < other.flags_;
366 }
367
368 #ifndef WT_TARGET_JAVA
369 #define W_DECLARE_OPERATORS_FOR_FLAGS(EnumType) \
370 inline Wt::WFlags<EnumType> operator|(EnumType l, EnumType r) { \
371 Wt::WFlags<EnumType> retval(l); \
372 retval |= r; \
373 return retval; \
374 } \
375 inline Wt::WFlags<EnumType> operator|(EnumType l, \
376 Wt::WFlags<EnumType> r) { \
377 return r | l; \
378 }
379 #else
380 #define W_DECLARE_OPERATORS_FOR_FLAGS(EnumType) \
381 Wt::WFlags<EnumType> operator|(EnumType l, EnumType r); \
382 Wt::WFlags<EnumType> operator|(EnumType l, Wt::WFlags<EnumType> r); \
383 bool operator==(EnumType l, Wt::WFlags<EnumType> r); \
384 bool operator==(EnumType l, int zero);
385 #endif
386 }
387
388 #endif // WFLAGS_H_
389
390