Gamedev Framework (gf)  0.3.0
A C++11 framework for 2D games
Flags.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016 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  constexpr Flags(NoneType)
76  : m_data(0)
77  {
78 
79  }
80 
81  constexpr Flags(AllType)
82  : m_data(~0)
83  {
84 
85  }
86 
87  /**
88  * @brief Constructor with an enum value
89  *
90  * @param e An enum value
91  */
92  constexpr Flags(E e)
93  : m_data(static_cast<Type>(e))
94  {
95 
96  }
97 
98  /**
99  * @brief Binary NOT operator
100  *
101  * @returns A bitfield where all flags have been inverted
102  */
103  constexpr Flags<E> operator~() const {
104  return Flags(~m_data);
105  }
106 
107  /**
108  * @brief Binary OR and assignment
109  *
110  * @param flags Another bitfield
111  * @return The bitfield with a binary OR of the flags and the other's flags
112  */
113  Flags<E>& operator|=(Flags<E> flags) {
114  m_data |= flags.m_data;
115  return *this;
116  }
117 
118  /**
119  * @brief Binary AND and assignment
120  *
121  * @param flags Another bitfield
122  * @return The bitfield with a binary AND of the flags and the other's flags
123  */
124  Flags<E>& operator&=(Flags<E> flags) {
125  m_data &= flags.m_data;
126  return *this;
127  }
128 
129  /**
130  * @brief Test if any flag is set
131  *
132  * @returns True if any flag is set
133  */
134  operator bool() const {
135  return m_data != 0;
136  }
137 
138  /**
139  * @brief Test if a specified flag is set
140  *
141  * @param flag The flag to test
142  * @return True if the flag is set
143  */
144  bool test(E flag) const {
145  return (m_data & static_cast<Type>(flag)) != 0;
146  }
147 
148  /**
149  * @brief Set a flag
150  *
151  * @param flag The flag to set
152  */
153  void set(E flag) {
154  m_data |= static_cast<Type>(flag);
155  }
156 
157  /**
158  * @brief Reset a flag
159  *
160  * @param flag The flag to reset
161  */
162  void reset(E flag) {
163  m_data &= ~static_cast<Type>(flag);
164  }
165 
166  using Type = typename std::underlying_type<E>::type;
167 
168  /**
169  * @brief Get the underlying value of the flags
170  *
171  * This function should not be used in normal cases.
172  *
173  * @return The value of the flags
174  */
175  Type getValue() const {
176  return m_data;
177  }
178 
179  private:
180  Flags(Type data)
181  : m_data(data)
182  {
183 
184  }
185 
186  Type m_data;
187  };
188 
189  /**
190  * @relates Flags
191  * @brief Binary OR between two bitfields
192  *
193  * @param lhs The first bitfield
194  * @param rhs The second bitfield
195  * @return The bitfield with a binary OR of the two bitfields
196  */
197  template<typename E>
198  inline
199  Flags<E> operator|(Flags<E> lhs, Flags<E> rhs) {
200  Flags<E> flags(lhs);
201  flags |= rhs;
202  return flags;
203  }
204 
205  /**
206  * @relates Flags
207  * @brief Binary OR between a bitfield and a flag
208  *
209  * @param lhs The bitfield
210  * @param rhs The flag
211  * @return The bitfield with a binary OR of the bitfield and the flag
212  */
213  template<typename E>
214  inline
215  Flags<E> operator|(Flags<E> lhs, E rhs) {
216  Flags<E> flags(lhs);
217  flags |= rhs;
218  return flags;
219  }
220 
221  /**
222  * @relates Flags
223  * @brief Binary OR between a flag and a bitfield
224  *
225  * @param lhs The flag
226  * @param rhs The bitfield
227  * @return The bitfield with a binary OR of the flag and the bitfield
228  */
229  template<typename E>
230  inline
231  Flags<E> operator|(E lhs, Flags<E> rhs) {
232  Flags<E> flags(lhs);
233  flags |= rhs;
234  return flags;
235  }
236 
237  /**
238  * @relates Flags
239  * @brief Binary AND between two bitfields
240  *
241  * @param lhs The first bitfield
242  * @param rhs The second bitfield
243  * @return The bitfield with a binary AND of the two bitfields
244  */
245  template<typename E>
246  inline
247  Flags<E> operator&(Flags<E> lhs, Flags<E> rhs) {
248  Flags<E> flags(lhs);
249  flags &= rhs;
250  return flags;
251  }
252 
253  /**
254  * @relates Flags
255  * @brief Binary AND between a bitfield and a flag
256  *
257  * @param lhs The bitfield
258  * @param rhs The flag
259  * @return The bitfield with a binary AND of the bitfield and the flag
260  */
261  template<typename E>
262  inline
263  Flags<E> operator&(Flags<E> lhs, E rhs) {
264  Flags<E> flags(lhs);
265  flags &= rhs;
266  return flags;
267  }
268 
269  /**
270  * @relates Flags
271  * @brief Binary AND between a flag and a bitfield
272  *
273  * @param lhs The flag
274  * @param rhs The bitfield
275  * @return The bitfield with a binary AND of the flag and the bitfield
276  */
277  template<typename E>
278  inline
279  Flags<E> operator&(E lhs, Flags<E> rhs) {
280  Flags<E> flags(lhs);
281  flags &= rhs;
282  return flags;
283  }
284 
285 #ifndef DOXYGEN_SHOULD_SKIP_THIS
286 }
287 #endif
288 
289 #ifndef DOXYGEN_SHOULD_SKIP_THIS
290 // this traits is not versioned to ease external usage
291 template<typename E>
292 struct EnableBitmaskOperators {
293  static constexpr bool value = false;
294 };
295 #endif
296 
297 }
298 
299 
300 #ifndef DOXYGEN_SHOULD_SKIP_THIS
301 template<typename E>
302 typename std::enable_if<gf::EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
303 operator|(E lhs, E rhs) {
304  gf::Flags<E> flags(lhs);
305  flags |= rhs;
306  return flags;
307 }
308 
309 template<typename E>
310 typename std::enable_if<gf::EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
311 operator&(E lhs, E rhs) {
312  gf::Flags<E> flags(lhs);
313  flags &= rhs;
314  return flags;
315 }
316 
317 template<typename E>
318 typename std::enable_if<gf::EnableBitmaskOperators<E>::value, gf::Flags<E>>::type
319 operator~(E val) {
320  gf::Flags<E> flags(val);
321  return ~flags;
322 }
323 #endif
324 
325 #endif // GF_FLAGS_H
Flags< E > operator|(E lhs, Flags< E > rhs)
Binary OR between a flag and a bitfield.
Definition: Flags.h:231
operator bool() const
Test if any flag is set.
Definition: Flags.h:134
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:175
void reset(E flag)
Reset a flag.
Definition: Flags.h:162
constexpr Flags(NoneType)
Definition: Flags.h:75
Flags< E > operator&(Flags< E > lhs, Flags< E > rhs)
Binary AND between two bitfields.
Definition: Flags.h:247
Semantic type to represent "all".
Definition: Types.h:53
constexpr Flags(AllType)
Definition: Flags.h:81
void set(E flag)
Set a flag.
Definition: Flags.h:153
constexpr Flags(E e)
Constructor with an enum value.
Definition: Flags.h:92
Flags()=default
Default constructor.
Definition: Action.h:34
Flags< E > & operator|=(Flags< E > flags)
Binary OR and assignment.
Definition: Flags.h:113
Flags< E > operator|(Flags< E > lhs, Flags< E > rhs)
Binary OR between two bitfields.
Definition: Flags.h:199
bool test(E flag) const
Test if a specified flag is set.
Definition: Flags.h:144
Flags< E > operator|(Flags< E > lhs, E rhs)
Binary OR between a bitfield and a flag.
Definition: Flags.h:215
constexpr Flags< E > operator~() const
Binary NOT operator.
Definition: Flags.h:103
Flags< E > & operator&=(Flags< E > flags)
Binary AND and assignment.
Definition: Flags.h:124
Flags< E > operator&(E lhs, Flags< E > rhs)
Binary AND between a flag and a bitfield.
Definition: Flags.h:279
Flags< E > operator&(Flags< E > lhs, E rhs)
Binary AND between a bitfield and a flag.
Definition: Flags.h:263