Gamedev Framework (gf)  0.4.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 #ifndef DOXYGEN_SHOULD_SKIP_THIS
272 }
273 #endif
274 
275 #ifndef DOXYGEN_SHOULD_SKIP_THIS
276 // this traits is not versioned to ease external usage
277 template<typename E>
278 struct EnableBitmaskOperators {
279  static constexpr bool value = false;
280 };
281 #endif
282 
283 }
284 
285 #ifndef DOXYGEN_SHOULD_SKIP_THIS
286 template<typename E>
287 constexpr
288 typename std::enable_if<gf::EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
289 operator|(E lhs, E rhs) {
290  return gf::Flags<E>(lhs) | gf::Flags<E>(rhs);
291 }
292 
293 template<typename E>
294 constexpr
295 typename std::enable_if<gf::EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
296 operator&(E lhs, E rhs) {
297  return gf::Flags<E>(lhs) & gf::Flags<E>(rhs);
298 }
299 
300 template<typename E>
301 constexpr
302 typename std::enable_if<gf::EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
303 operator~(E val) {
304  return ~gf::Flags<E>(val);
305 }
306 #endif
307 
308 #endif // GF_FLAGS_H
constexpr bool test(E flag) const
Test if a specified flag is set.
Definition: Flags.h:170
Semantic type to represent "none".
Definition: Types.h:37
Bitfield relying on an enumeration.
Definition: Flags.h:68
Type getValue() const
Get the underlying value of the flags.
Definition: Flags.h:201
constexpr Flags operator|(Flags flags) const
Binary OR between two bitfields.
Definition: Flags.h:119
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(AllType)
Constructor with all flags set.
Definition: Flags.h:87
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 Flags< E > operator&(Flags< E > lhs, E rhs)
Binary AND between a bitfield and a flag.
Definition: Flags.h:253
Flags()=default
Default constructor.
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 AND between two bitfields.
Definition: Flags.h:140
constexpr Flags< E > operator~() const
Binary NOT operator.
Definition: Flags.h:109
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
Flags< E > & operator&=(Flags< E > flags)
Binary AND and assignment.
Definition: Flags.h:150
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