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