A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
BitFlag.hh
1#pragma once
2
3#include <Logger.hh>
4
5#include <array>
6#include <cstddef>
7#include <cstdint>
8#include <limits>
9#include <type_traits>
10
11// We can't include Common.hh, because we have a cyclic dependency
12typedef uint32_t u32;
13
14namespace EGG {
15
19template <typename T, typename E>
20 requires(std::is_enum_v<E> && std::is_integral_v<T>)
21struct TBitFlag {
24 constexpr TBitFlag() {
25 makeAllZero();
26 }
27
31 constexpr TBitFlag(T mask) {
32 setDirect(mask);
33 }
34
38 constexpr TBitFlag(E e) : TBitFlag() {
39 setBit(e);
40 }
41
43 [[nodiscard]] constexpr operator T() const {
44 return getDirect();
45 }
46
50 constexpr TBitFlag<T, E> &operator=(const TBitFlag<T, E> &rhs) {
51 bits = rhs.bits;
52 return *this;
53 }
54
60 template <typename... Es>
61 requires(std::is_same_v<Es, E> && ...)
62 constexpr TBitFlag<T, E> &setBit(Es... es) {
63 (setBit_(es), ...);
64 return *this;
65 }
66
71 template <typename... Es>
72 requires(std::is_same_v<Es, E> && ...)
73 constexpr TBitFlag<T, E> &resetBit(Es... es) {
74 (resetBit_(es), ...);
75 return *this;
76 }
77
83 template <typename... Es>
84 requires(std::is_same_v<Es, E> && ...)
85 constexpr TBitFlag<T, E> &changeBit(bool on, Es... es) {
86 (changeBit_(on, es), ...);
87 return *this;
88 }
89
94 template <typename... Es>
95 requires(std::is_same_v<Es, E> && ...)
96 constexpr TBitFlag<T, E> &toggleBit(Es... es) {
97 (toggleBit_(es), ...);
98 return *this;
99 }
100
106 template <typename... Es>
107 requires(std::is_same_v<Es, E> && ...)
108 [[nodiscard]] constexpr bool onBit(Es... es) const {
109 return (onAnyBit(es...));
110 }
111
117 template <typename... Es>
118 requires(std::is_same_v<Es, E> && ...)
119 [[nodiscard]] constexpr bool onAnyBit(Es... es) const {
120 return (onBit_(es) || ...);
121 }
122
128 template <typename... Es>
129 requires(std::is_same_v<Es, E> && ...)
130 [[nodiscard]] constexpr bool onAllBit(Es... es) const {
131 return (onBit_(es) && ...);
132 }
133
139 template <typename... Es>
140 requires(std::is_same_v<Es, E> && ...)
141 [[nodiscard]] constexpr bool offBit(Es... es) const {
142 return offAllBit(es...);
143 }
144
150 template <typename... Es>
151 requires(std::is_same_v<Es, E> && ...)
152 [[nodiscard]] constexpr bool offAllBit(Es... es) const {
153 return (offBit_(es) && ...);
154 }
155
161 template <typename... Es>
162 requires(std::is_same_v<Es, E> && ...)
163 [[nodiscard]] constexpr bool offAnyBit(Es... es) const {
164 return (offBit_(es) || ...);
165 }
166
172 template <typename... Es>
173 requires(std::is_same_v<Es, E> && ...)
174 [[nodiscard]] constexpr T maskBit(Es... es) const {
175 return bits & makeMask(es...);
176 }
177
182 template <typename... Es>
183 requires(std::is_same_v<Es, E> && ...)
184 [[nodiscard]] constexpr T makeMask(Es... es) const {
185 return (makeMask_(es) | ...);
186 }
187
191 constexpr TBitFlag<T, E> &set(T mask) {
192 bits |= mask;
193 return *this;
194 }
195
199 constexpr TBitFlag<T, E> &reset(T mask) {
200 bits &= ~mask;
201 return *this;
202 }
203
208 constexpr TBitFlag<T, E> &change(bool on, T mask) {
209 return on ? set(mask) : reset(mask);
210 }
211
215 [[nodiscard]] constexpr bool on(T mask) const {
216 return (bits & mask) != 0;
217 }
218
222 [[nodiscard]] constexpr bool onAll(T mask) const {
223 return (bits | mask) == bits;
224 }
225
229 [[nodiscard]] constexpr bool off(T mask) const {
230 return (bits & mask) == 0;
231 }
232
234 constexpr void makeAllZero() {
235 bits = 0;
236 }
237
240 [[nodiscard]] constexpr T getDirect() const {
241 return bits;
242 }
243
246 constexpr void setDirect(T mask) {
247 bits = mask;
248 }
249
250private:
251 typedef std::underlying_type_t<E> EI;
252 static constexpr size_t MAX_CAPACITY = std::numeric_limits<T>::digits;
253
257 constexpr void setBit_(E e) {
258 ASSERT(static_cast<EI>(e) < MAX_CAPACITY);
259 set(makeMask_(e));
260 }
261
265 constexpr void resetBit_(E e) {
266 ASSERT(static_cast<EI>(e) < MAX_CAPACITY);
267 reset(makeMask_(e));
268 }
269
274 constexpr void changeBit_(bool on, E e) {
275 ASSERT(static_cast<EI>(e) < MAX_CAPACITY);
276 change(on, makeMask_(e));
277 }
278
282 constexpr void toggleBit_(E e) {
283 ASSERT(static_cast<EI>(e) < MAX_CAPACITY);
284 changeBit_(offBit_(e), e);
285 }
286
291 [[nodiscard]] constexpr bool onBit_(E e) const {
292 ASSERT(static_cast<EI>(e) < MAX_CAPACITY);
293 return on(makeMask_(e));
294 }
295
300 [[nodiscard]] constexpr bool offBit_(E e) const {
301 ASSERT(static_cast<EI>(e) < MAX_CAPACITY);
302 return off(makeMask_(e));
303 }
304
309 [[nodiscard]] constexpr T makeMask_(E e) const {
310 ASSERT(static_cast<EI>(e) < MAX_CAPACITY);
311 return static_cast<T>(1) << static_cast<T>(e);
312 }
313
315};
316
320template <size_t N, typename E>
321 requires(std::is_enum_v<E> && N > 64)
323public:
326 constexpr TBitFlagExt() {
327 makeAllZero();
328 }
329
333 std::fill(bits.begin(), bits.end(), 0);
334 return *this;
335 }
336
342 template <typename... Es>
343 requires(std::is_same_v<Es, E> && ...)
344 constexpr TBitFlagExt<N, E> &setBit(Es... es) {
345 (setBit_(es), ...);
346 return *this;
347 }
348
353 template <typename... Es>
354 requires(std::is_same_v<Es, E> && ...)
355 constexpr TBitFlagExt<N, E> &resetBit(Es... es) {
356 (resetBit_(es), ...);
357 return *this;
358 }
359
365 template <typename... Es>
366 requires(std::is_same_v<Es, E> && ...)
367 constexpr TBitFlagExt<N, E> &changeBit(bool on, Es... es) {
368 (changeBit_(on, es), ...);
369 return *this;
370 }
371
377 template <typename... Es>
378 requires(std::is_same_v<Es, E> && ...)
379 [[nodiscard]] constexpr bool onBit(Es... es) const {
380 return onAnyBit(es...);
381 }
382
388 template <typename... Es>
389 requires(std::is_same_v<Es, E> && ...)
390 [[nodiscard]] constexpr bool onAnyBit(Es... es) const {
391 return (onBit_(es) || ...);
392 }
393
399 template <typename... Es>
400 requires(std::is_same_v<Es, E> && ...)
401 [[nodiscard]] constexpr bool onAllBit(Es... es) const {
402 return (onBit_(es) && ...);
403 }
404
410 template <typename... Es>
411 requires(std::is_same_v<Es, E> && ...)
412 [[nodiscard]] constexpr bool offBit(Es... es) const {
413 return offAllBit(es...);
414 }
415
421 template <typename... Es>
422 requires(std::is_same_v<Es, E> && ...)
423 [[nodiscard]] constexpr bool offAllBit(Es... es) const {
424 return (offBit_(es) && ...);
425 }
426
432 template <typename... Es>
433 requires(std::is_same_v<Es, E> && ...)
434 [[nodiscard]] constexpr bool offAnyBit(Es... es) const {
435 return (offBit_(es) || ...);
436 }
437
438private:
439 typedef std::underlying_type_t<E> EI;
440
444 constexpr void setBit_(E e) {
445 auto [field, mask] = makeMask_(e);
446 field |= mask;
447 }
448
452 constexpr void resetBit_(E e) {
453 auto [field, mask] = makeMask_(e);
454 field &= ~mask;
455 }
456
461 [[nodiscard]] constexpr void changeBit_(bool on, E e) {
462 on ? setBit_(e) : resetBit_(e);
463 }
464
469 [[nodiscard]] constexpr bool onBit_(E e) const {
470 auto [field, mask] = makeMask_(e);
471 return (field & mask) != 0;
472 }
473
478 [[nodiscard]] constexpr bool offBit_(E e) const {
479 auto [field, mask] = makeMask_(e);
480 return (field & mask) == 0;
481 }
482
483 typedef u32 T;
484
489 [[nodiscard]] constexpr std::pair<T, T> makeMask_(E e) const {
490 EI ei = static_cast<EI>(e);
491 ASSERT(ei < N);
492 return std::pair<T, T>(bits[ei / C], static_cast<T>(1) << (ei % C));
493 }
494
499 [[nodiscard]] constexpr std::pair<T &, T> makeMask_(E e) {
500 EI ei = static_cast<EI>(e);
501 ASSERT(ei < N);
502 return std::pair<T &, T>(bits[ei / C], static_cast<T>(1) << (ei % C));
503 }
504
505 static constexpr size_t C = 8 * sizeof(T);
506 std::array<T, (N + C - 1) / C> bits;
507};
508
509} // namespace EGG
Wrapper around a variable length bitfield with an enum corresponding to its bits.
Definition BitFlag.hh:322
constexpr void changeBit_(bool on, E e)
Internal. Changes a specific bit.
Definition BitFlag.hh:461
constexpr bool offBit(Es... es) const
Checks if all of the corresponding bits for the provided enum values are off.
Definition BitFlag.hh:412
constexpr TBitFlagExt< N, E > & makeAllZero()
Resets all the bits to zero across the entire bitfield array.
Definition BitFlag.hh:332
constexpr bool offAllBit(Es... es) const
Checks if all of the corresponding bits for the provided enum values are off.
Definition BitFlag.hh:423
constexpr TBitFlagExt()
Default constructor, initializes all flags to off.
Definition BitFlag.hh:326
constexpr std::pair< T, T > makeMask_(E e) const
Gets bit index and mask for a specific bit.
Definition BitFlag.hh:489
constexpr bool onBit(Es... es) const
Checks if any of the corresponding bits for the provided enum values are on.
Definition BitFlag.hh:379
constexpr void setBit_(E e)
Internal. Sets a specific bit.
Definition BitFlag.hh:444
constexpr TBitFlagExt< N, E > & resetBit(Es... es)
Resets the corresponding bits for the provided enum values.
Definition BitFlag.hh:355
constexpr bool offBit_(E e) const
Checks if a specific bit is off.
Definition BitFlag.hh:478
constexpr void resetBit_(E e)
Internal. Resets a specific bit.
Definition BitFlag.hh:452
constexpr std::pair< T &, T > makeMask_(E e)
Gets bit index and mask for a specific bit.
Definition BitFlag.hh:499
constexpr bool onAllBit(Es... es) const
Checks if all of the corresponding bits for the provided enum values are on.
Definition BitFlag.hh:401
constexpr bool offAnyBit(Es... es) const
Checks if any of the corresponding bits for the provided enum values are off.
Definition BitFlag.hh:434
constexpr bool onBit_(E e) const
Checks if a specific bit is on.
Definition BitFlag.hh:469
constexpr bool onAnyBit(Es... es) const
Checks if any of the corresponding bits for the provided enum values are on.
Definition BitFlag.hh:390
EGG core library.
Definition Archive.cc:6
Wrapper around an integral type with an enum corresponding to its bits.
Definition BitFlag.hh:21
constexpr bool offBit_(E e) const
Checks if a specific bit is off.
Definition BitFlag.hh:300
constexpr bool on(T mask) const
Checks if any bits are on in the specified mask.
Definition BitFlag.hh:215
constexpr TBitFlag< T, E > & resetBit(Es... es)
Resets the corresponding bits for the provided enum values.
Definition BitFlag.hh:73
constexpr TBitFlag(T mask)
Constructor that initializes the bit flags with a given mask.
Definition BitFlag.hh:31
constexpr bool onBit(Es... es) const
Checks if any of the corresponding bits for the provided enum values are on.
Definition BitFlag.hh:108
constexpr T maskBit(Es... es) const
Creates an applied mask of the corresponding bits for the provided enum values.
Definition BitFlag.hh:174
constexpr bool onAllBit(Es... es) const
Checks if all of the corresponding bits for the provided enum values are on.
Definition BitFlag.hh:130
constexpr T makeMask(Es... es) const
Creates a mask of the corresponding bits for the provided enum values.
Definition BitFlag.hh:184
constexpr bool onAnyBit(Es... es) const
Checks if any of the corresponding bits for the provided enum values are on.
Definition BitFlag.hh:119
constexpr void resetBit_(E e)
Internal. Resets a specific bit.
Definition BitFlag.hh:265
constexpr T getDirect() const
Gets the current bit mask.
Definition BitFlag.hh:240
T bits
The bit mask representing the flags.
Definition BitFlag.hh:314
constexpr void toggleBit_(E e)
Internal. Toggles a specific bit.
Definition BitFlag.hh:282
constexpr void setBit_(E e)
Internal. Sets a specific bit.
Definition BitFlag.hh:257
constexpr bool offBit(Es... es) const
Checks if all of the corresponding bits for the provided enum values are off.
Definition BitFlag.hh:141
constexpr void setDirect(T mask)
Sets the bits using a direct mask.
Definition BitFlag.hh:246
constexpr void makeAllZero()
Resets all the bits to zero.
Definition BitFlag.hh:234
constexpr TBitFlag< T, E > & set(T mask)
Sets the bits using a direct mask.
Definition BitFlag.hh:191
constexpr bool offAllBit(Es... es) const
Checks if all of the corresponding bits for the provided enum values are off.
Definition BitFlag.hh:152
constexpr bool offAnyBit(Es... es) const
Checks if any of the corresponding bits for the provided enum values are off.
Definition BitFlag.hh:163
constexpr TBitFlag< T, E > & reset(T mask)
Resets the bits using a direct mask.
Definition BitFlag.hh:199
constexpr bool onAll(T mask) const
Checks if all bits are on in the specified mask.
Definition BitFlag.hh:222
constexpr TBitFlag(E e)
Constructor that initializes the bit flags with a given enum.
Definition BitFlag.hh:38
constexpr void changeBit_(bool on, E e)
Internal. Changes a specific bit.
Definition BitFlag.hh:274
constexpr TBitFlag< T, E > & operator=(const TBitFlag< T, E > &rhs)
Assignment operator.
Definition BitFlag.hh:50
constexpr bool onBit_(E e) const
Checks if a specific bit is on.
Definition BitFlag.hh:291
constexpr TBitFlag< T, E > & change(bool on, T mask)
Changes the bits using a direct mask.
Definition BitFlag.hh:208
constexpr bool off(T mask) const
Checks if all bits are off in the specified mask.
Definition BitFlag.hh:229
constexpr TBitFlag()
Default constructor, initializes all flags to off.
Definition BitFlag.hh:24
constexpr T makeMask_(E e) const
Creates a mask for a specific bit.
Definition BitFlag.hh:309
constexpr TBitFlag< T, E > & toggleBit(Es... es)
Toggles the corresponding bits for the provided enum values.
Definition BitFlag.hh:96