Gamedev Framework (gf)  0.6.0
A C++11 framework for 2D games
Flags.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2017 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef GF_FLAGS_H
22 #define GF_FLAGS_H
23 
24 #include <type_traits>
25 
26 #include "Types.h"
27 
28 namespace gf {
29 #ifndef DOXYGEN_SHOULD_SKIP_THIS
30 inline namespace v1 {
31 #endif
32 
33  /**
34  * @ingroup core
35  * @brief Bitfield relying on an enumeration
36  *
37  * ~~~
38  * enum class AnimalProperties {
39  * HasClaws = 0x01,
40  * CanFly = 0x02,
41  * EatsFish = 0x04,
42  * IsEndangered = 0x08,
43  * };
44  *
45  * namespace gf {
46  * template<>
47  * struct EnableBitmaskOperators<AnimalProperties> {
48  * static constexpr bool value = true;
49  * };
50  * }
51  *
52  * gf::Flags<AnimalProperties> seahawk = AnimalProperties::CanFly | AnimalProperties::EatsFish;
53  * seahawk |= AnimalProperties::IsEndangered;
54  *
55  * bool b = seahawk.test(AnimalProperties::HasClaws); // false
56  * ~~~
57  *
58  * If you do not initialize flags, then the state is undefined. You can use
59  * semantic constants gf::All and gf::None to set all the flags or none.
60  *
61  * ~~~{.cc}
62  * gf::Flags<AnimalProperties> unicorn(gf::All);
63  *
64  * gf::Flags<AnimalProperties> rat(gf::None);
65  * ~~~
66  */
67  template<typename E>
68  class Flags {
69  public:
70  /**
71  * @brief Default constructor
72  */
73  Flags() = default;
74 
75  /**
76  * @brief Constructor with no flag set
77  */
78  constexpr Flags(NoneType)
79  : m_data(0)
80  {
81 
82  }
83 
84  /**
85  * @brief Constructor with all flags set
86  */
87  constexpr Flags(AllType)
88  : m_data(~0)
89  {
90 
91  }
92 
93  /**
94  * @brief Constructor with an enum value
95  *
96  * @param e An enum value
97  */
98  constexpr Flags(E e)
99  : m_data(static_cast<Type>(e))
100  {
101 
102  }
103 
104  /**
105  * @brief Binary NOT operator
106  *
107  * @returns A bitfield where all flags have been inverted
108  */
109  constexpr Flags<E> operator~() const {
110  return Flags(~m_data);
111  }
112 
113  /**
114  * @brief Binary OR between two bitfields
115  *
116  * @param flags Another bitfield
117  * @return The bitfield with a binary OR of the two bitfields
118  */
119  constexpr Flags operator|(Flags flags) const {
120  return Flags(m_data | flags.m_data);
121  }
122 
123  /**
124  * @brief Binary OR and assignment
125  *
126  * @param flags Another bitfield
127  * @return The bitfield with a binary OR of the flags and the other's flags
128  */
129  Flags<E>& operator|=(Flags<E> flags) {
130  m_data |= flags.m_data;
131  return *this;
132  }
133 
134  /**
135  * @brief Binary AND between two bitfields
136  *
137  * @param flags Another bitfield
138  * @return The bitfield with a binary AND of the two bitfields
139  */
140  constexpr Flags operator&(Flags flags) const {
141  return Flags(m_data & flags.m_data);
142  }
143 
144  /**
145  * @brief Binary AND and assignment
146  *
147  * @param flags Another bitfield
148  * @return The bitfield with a binary AND of the flags and the other's flags
149  */
150  Flags<E>& operator&=(Flags<E> flags) {
151  m_data &= flags.m_data;
152  return *this;
153  }
154 
155  /**
156  * @brief Test if any flag is set
157  *
158  * @returns True if any flag is set
159  */
160  constexpr operator bool() const {
161  return m_data != 0;
162  }
163 
164  /**
165  * @brief Test if a specified flag is set
166  *
167  * @param flag The flag to test
168  * @return True if the flag is set
169  */
170  constexpr bool test(E flag) const {
171  return (m_data & static_cast<Type>(flag)) != 0;
172  }
173 
174  /**
175  * @brief Set a flag
176  *
177  * @param flag The flag to set
178  */
179  void set(E flag) {
180  m_data |= static_cast<Type>(flag);
181  }
182 
183  /**
184  * @brief Reset a flag
185  *
186  * @param flag The flag to reset
187  */
188  void reset(E flag) {
189  m_data &= ~static_cast<Type>(flag);
190  }
191 
192  using Type = typename std::underlying_type<E>::type;
193 
194  /**
195  * @brief Get the underlying value of the flags
196  *
197  * This function should not be used in normal cases.
198  *
199  * @return The value of the flags
200  */
201  Type getValue() const {
202  return m_data;
203  }
204 
205  private:
206  constexpr Flags(Type data)
207  : m_data(data)
208  {
209 
210  }
211 
212  Type m_data;
213  };
214 
215  /**
216  * @relates Flags
217  * @brief Binary OR between a bitfield and a flag
218  *
219  * @param lhs The bitfield
220  * @param rhs The flag
221  * @return The bitfield with a binary OR of the bitfield and the flag
222  */
223  template<typename E>
224  constexpr
225  Flags<E> operator|(Flags<E> lhs, E rhs) {
226  return lhs | Flags<E>(rhs);
227  }
228 
229  /**
230  * @relates Flags
231  * @brief Binary OR between a flag and a bitfield
232  *
233  * @param lhs The flag
234  * @param rhs The bitfield
235  * @return The bitfield with a binary OR of the flag and the bitfield
236  */
237  template<typename E>
238  constexpr
239  Flags<E> operator|(E lhs, Flags<E> rhs) {
240  return Flags<E>(lhs) | rhs;
241  }
242 
243  /**
244  * @relates Flags
245  * @brief Binary AND between a bitfield and a flag
246  *
247  * @param lhs The bitfield
248  * @param rhs The flag
249  * @return The bitfield with a binary AND of the bitfield and the flag
250  */
251  template<typename E>
252  constexpr
253  Flags<E> operator&(Flags<E> lhs, E rhs) {
254  return lhs & Flags<E>(rhs);
255  }
256 
257  /**
258  * @relates Flags
259  * @brief Binary AND between a flag and a bitfield
260  *
261  * @param lhs The flag
262  * @param rhs The bitfield
263  * @return The bitfield with a binary AND of the flag and the bitfield
264  */
265  template<typename E>
266  constexpr
267  Flags<E> operator&(E lhs, Flags<E> rhs) {
268  return Flags<E>(lhs) & rhs;
269  }
270 
271 
272  /**
273  * @relates Flags
274  * @brief Combine a single enum value into a flag value
275  *
276  * @param flag An enum value
277  * @returns The enum value turned into a flag value
278  */
279  template<typename E>
280  constexpr Flags<E> combineFlags(E flag) {
281  return Flags<E>(flag);
282  }
283 
284  /**
285  * @relates Flags
286  * @brief Combine several enum values into a flag value
287  *
288  * @param flag An enum value
289  * @param others The other enum values
290  * @returns The enum values turned into a flag value
291  */
292  template<typename E, typename ... F>
293  constexpr Flags<E> combineFlags(E flag, F ... others) {
294  return Flags<E>(flag) | combineFlags(others ...);
295  }
296 
297 #ifndef DOXYGEN_SHOULD_SKIP_THIS
298 }
299 
300 
301 // this traits is not versioned
302 
303 template<typename E>
304 struct EnableBitmaskOperators {
305  static constexpr bool value = false;
306 };
307 
308 // these overloads are only available to gf enum types and gf flags
309 // unless you add: "using gf::operator|;"
310 
311 template<typename E>
312 constexpr
313 typename std::enable_if<EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
314 operator|(E lhs, E rhs) {
315  return gf::Flags<E>(lhs) | gf::Flags<E>(rhs);
316 }
317 
318 template<typename E>
319 constexpr
320 typename std::enable_if<EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
321 operator&(E lhs, E rhs) {
322  return gf::Flags<E>(lhs) & gf::Flags<E>(rhs);
323 }
324 
325 template<typename E>
326 constexpr
327 typename std::enable_if<EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
328 operator~(E val) {
329  return ~gf::Flags<E>(val);
330 }
331 
332 #endif
333 }
334 
335 #endif // GF_FLAGS_H
Semantic type to represent "none".
Definition: Types.h:37
Bitfield relying on an enumeration.
Definition: Flags.h:68
Flags< E > & operator &=(Flags< E > flags)
Binary AND and assignment.
Definition: Flags.h:150
constexpr Flags< E > combineFlags(E flag, F ... others)
Combine several enum values into a flag value.
Definition: Flags.h:293
void reset(E flag)
Reset a flag.
Definition: Flags.h:188
constexpr Flags(NoneType)
Constructor with no flag set.
Definition: Flags.h:78
Semantic type to represent "all".
Definition: Types.h:53
constexpr Flags operator &(Flags flags) const
Binary AND between two bitfields.
Definition: Flags.h:140
constexpr Flags(AllType)
Constructor with all flags set.
Definition: Flags.h:87
constexpr Flags< E > operator~() const
Binary NOT operator.
Definition: Flags.h:109
void set(E flag)
Set a flag.
Definition: Flags.h:179
constexpr Flags(E e)
Constructor with an enum value.
Definition: Flags.h:98
constexpr bool test(E flag) const
Test if a specified flag is set.
Definition: Flags.h:170
Flags()=default
Default constructor.
Type getValue() const
Get the underlying value of the flags.
Definition: Flags.h:201
The namespace for gf classes.
Definition: Action.h:34
Flags< E > & operator|=(Flags< E > flags)
Binary OR and assignment.
Definition: Flags.h:129
constexpr Flags operator|(Flags flags) const
Binary OR between two bitfields.
Definition: Flags.h:119
constexpr Flags< E > operator&(Flags< E > lhs, E rhs)
Binary AND between a bitfield and a flag.
Definition: Flags.h:253
constexpr Flags< E > operator|(Flags< E > lhs, E rhs)
Binary OR between a bitfield and a flag.
Definition: Flags.h:225
constexpr Flags< E > operator&(E lhs, Flags< E > rhs)
Binary AND between a flag and a bitfield.
Definition: Flags.h:267
constexpr Flags< E > operator|(E lhs, Flags< E > rhs)
Binary OR between a flag and a bitfield.
Definition: Flags.h:239
constexpr operator bool() const
Test if any flag is set.
Definition: Flags.h:160
constexpr Flags< E > combineFlags(E flag)
Combine a single enum value into a flag value.
Definition: Flags.h:280