Plasma Engine  2.0
Loading...
Searching...
No Matches
Bitflags.h
1#pragma once
2
4
5#include <Foundation/Basics.h>
6#include <Foundation/Containers/Implementation/BitIterator.h>
7#include <Foundation/Types/Enum.h>
8
80template <typename T>
82{
83private:
84 using Enum = typename T::Enum;
85 using Bits = typename T::Bits;
86 using StorageType = typename T::StorageType;
87
88public:
90
92 PL_ALWAYS_INLINE plBitflags()
93 : m_Value(T::Default) // [tested]
94 {
95 }
96
98 PL_ALWAYS_INLINE plBitflags(Enum flag1) // [tested]
99 {
100 m_Value = (StorageType)flag1;
101 }
102
103 PL_ALWAYS_INLINE void operator=(Enum flag1) { m_Value = (StorageType)flag1; }
104
106 PL_ALWAYS_INLINE bool operator==(const StorageType rhs) const // [tested]
107 {
108 return m_Value == rhs;
109 }
110
112 PL_ALWAYS_INLINE bool operator!=(const StorageType rhs) const { return m_Value != rhs; }
113
115 PL_ALWAYS_INLINE bool operator==(const plBitflags<T>& rhs) const { return m_Value == rhs.m_Value; }
116
118 PL_ALWAYS_INLINE bool operator!=(const plBitflags<T>& rhs) const { return m_Value != rhs.m_Value; }
119
121 PL_ALWAYS_INLINE void Clear() // [tested]
122 {
123 m_Value = 0;
124 }
125
127 PL_ALWAYS_INLINE bool IsSet(Enum flag) const // [tested]
128 {
129 return (m_Value & flag) != 0;
130 }
131
133 PL_ALWAYS_INLINE bool AreAllSet(const plBitflags<T>& rhs) const // [tested]
134 {
135 return (m_Value & rhs.m_Value) == rhs.m_Value;
136 }
137
139 PL_ALWAYS_INLINE bool AreNoneSet(const plBitflags<T>& rhs) const // [tested]
140 {
141 return (m_Value & rhs.m_Value) == 0;
142 }
143
145 PL_ALWAYS_INLINE bool IsAnySet(const plBitflags<T>& rhs) const // [tested]
146 {
147 return (m_Value & rhs.m_Value) != 0;
148 }
149
151 PL_ALWAYS_INLINE void Add(const plBitflags<T>& rhs) // [tested]
152 {
153 m_Value |= rhs.m_Value;
154 }
155
157 PL_ALWAYS_INLINE void Remove(const plBitflags<T>& rhs) // [tested]
158 {
159 m_Value &= (~rhs.m_Value);
160 }
161
163 PL_ALWAYS_INLINE void Toggle(const plBitflags<T>& rhs) // [tested]
164 {
165 m_Value ^= rhs.m_Value;
166 }
167
169 PL_ALWAYS_INLINE void AddOrRemove(const plBitflags<T>& rhs, bool bState) // [tested]
170 {
171 m_Value = (bState) ? m_Value | rhs.m_Value : m_Value & (~rhs.m_Value);
172 }
173
175 PL_ALWAYS_INLINE plBitflags<T> operator|(const plBitflags<T>& rhs) const // [tested]
176 {
177 return plBitflags<T>(m_Value | rhs.m_Value);
178 }
179
181 PL_ALWAYS_INLINE plBitflags<T> operator&(const plBitflags<T>& rhs) const // [tested]
182 {
183 return plBitflags<T>(m_Value & rhs.m_Value);
184 }
185
187 PL_ALWAYS_INLINE void operator|=(const plBitflags<T>& rhs) // [tested]
188 {
189 m_Value |= rhs.m_Value;
190 }
191
193 PL_ALWAYS_INLINE void operator&=(const plBitflags<T>& rhs) // [tested]
194 {
195 m_Value &= rhs.m_Value;
196 }
197
199 PL_ALWAYS_INLINE StorageType GetValue() const // [tested]
200 {
201 return m_Value;
202 }
203
205 PL_ALWAYS_INLINE void SetValue(StorageType value) // [tested]
206 {
207 m_Value = value;
208 }
209
211 PL_ALWAYS_INLINE bool IsNoFlagSet() const // [tested]
212 {
213 return m_Value == 0;
214 }
215
217 PL_ALWAYS_INLINE bool IsAnyFlagSet() const // [tested]
218 {
219 return m_Value != 0;
220 }
221
224 PL_ALWAYS_INLINE ConstIterator GetIterator() const // [tested]
225 {
226 return ConstIterator((Enum)m_Value);
227 }
228
230 PL_ALWAYS_INLINE ConstIterator GetEndIterator() const // [tested]
231 {
232 return ConstIterator();
233 }
234
235private:
236 PL_ALWAYS_INLINE explicit plBitflags(StorageType flags)
237 : m_Value(flags)
238 {
239 }
240
241 union
242 {
243 StorageType m_Value;
244 Bits m_bits;
245 };
246};
247
249// begin() /end() for range-based for-loop support
250template <typename T>
251typename plBitflags<T>::ConstIterator begin(const plBitflags<T>& container)
252{
253 return container.GetIterator();
254}
255
256template <typename T>
257typename plBitflags<T>::ConstIterator cbegin(const plBitflags<T>& container)
258{
259 return container.GetIterator();
260}
261
262template <typename T>
263typename plBitflags<T>::ConstIterator end(const plBitflags<T>& container)
264{
265 return container.GetEndIterator();
266}
267
268template <typename T>
269typename plBitflags<T>::ConstIterator cend(const plBitflags<T>& container)
270{
271 return container.GetEndIterator();
272}
273
276#define PL_DECLARE_FLAGS_OPERATORS(FlagsType) \
277 inline plBitflags<FlagsType> operator|(FlagsType::Enum lhs, FlagsType::Enum rhs) \
278 { \
279 return (plBitflags<FlagsType>(lhs) | plBitflags<FlagsType>(rhs)); \
280 } \
281 \
282 inline plBitflags<FlagsType> operator&(FlagsType::Enum lhs, FlagsType::Enum rhs) \
283 { \
284 return (plBitflags<FlagsType>(lhs) & plBitflags<FlagsType>(rhs)); \
285 }
286
287
288
305#define PL_DECLARE_FLAGS_WITH_DEFAULT(InternalStorageType, BitflagsTypeName, DefaultValue, ...) \
306 struct BitflagsTypeName \
307 { \
308 static constexpr plUInt32 Count = PL_VA_NUM_ARGS(__VA_ARGS__); \
309 using StorageType = InternalStorageType; \
310 enum Enum \
311 { \
312 PL_EXPAND_ARGS_WITH_INDEX(PL_DECLARE_FLAGS_ENUM, ##__VA_ARGS__) Default = DefaultValue \
313 }; \
314 struct Bits \
315 { \
316 PL_EXPAND_ARGS(PL_DECLARE_FLAGS_BITS, ##__VA_ARGS__) \
317 }; \
318 PL_ENUM_TO_STRING(__VA_ARGS__) \
319 }; \
320 PL_DECLARE_FLAGS_OPERATORS(BitflagsTypeName)
321
322#define PL_DECLARE_FLAGS(InternalStorageType, BitflagsTypeName, ...) \
323 PL_DECLARE_FLAGS_WITH_DEFAULT(InternalStorageType, BitflagsTypeName, 0, ##__VA_ARGS__)
325
327#define PL_DECLARE_FLAGS_ENUM(name, n) name = PL_BIT(n),
328
330#define PL_DECLARE_FLAGS_BITS(name) StorageType name : 1;
331
Definition BitIterator.h:27
The plBitflags class allows you to work with type-safe bitflags.
Definition Bitflags.h:82
PL_ALWAYS_INLINE bool operator!=(const StorageType rhs) const
Comparison operator.
Definition Bitflags.h:112
PL_ALWAYS_INLINE void Clear()
Clears all flags.
Definition Bitflags.h:121
PL_ALWAYS_INLINE void Toggle(const plBitflags< T > &rhs)
Toggles the state of the given flag.
Definition Bitflags.h:163
PL_ALWAYS_INLINE plBitflags< T > operator|(const plBitflags< T > &rhs) const
Returns an object that has the flags of this and rhs combined.
Definition Bitflags.h:175
PL_ALWAYS_INLINE bool AreAllSet(const plBitflags< T > &rhs) const
Returns whether all the given flags are set.
Definition Bitflags.h:133
PL_ALWAYS_INLINE bool operator==(const StorageType rhs) const
Comparison operator.
Definition Bitflags.h:106
PL_ALWAYS_INLINE bool operator==(const plBitflags< T > &rhs) const
Comparison operator.
Definition Bitflags.h:115
PL_ALWAYS_INLINE bool IsNoFlagSet() const
Returns true if not a single bit is set.
Definition Bitflags.h:211
PL_ALWAYS_INLINE void SetValue(StorageType value)
Overwrites the flags with a new value.
Definition Bitflags.h:205
PL_ALWAYS_INLINE void Remove(const plBitflags< T > &rhs)
Removes the given flag.
Definition Bitflags.h:157
PL_ALWAYS_INLINE void operator|=(const plBitflags< T > &rhs)
Modifies this to also contain the bits from rhs.
Definition Bitflags.h:187
PL_ALWAYS_INLINE StorageType GetValue() const
Returns the stored value as the underlying integer type.
Definition Bitflags.h:199
PL_ALWAYS_INLINE plBitflags()
Constructor. Initializes the flags to the default value.
Definition Bitflags.h:92
PL_ALWAYS_INLINE bool operator!=(const plBitflags< T > &rhs) const
Comparison operator.
Definition Bitflags.h:118
PL_ALWAYS_INLINE void operator&=(const plBitflags< T > &rhs)
Modifies this to only contain the bits that were set in this and rhs.
Definition Bitflags.h:193
PL_ALWAYS_INLINE ConstIterator GetIterator() const
Returns a constant iterator to the very first set bit. Note that due to the way iterating through bit...
Definition Bitflags.h:224
PL_ALWAYS_INLINE void AddOrRemove(const plBitflags< T > &rhs, bool bState)
Sets or clears the given flag.
Definition Bitflags.h:169
PL_ALWAYS_INLINE bool IsAnyFlagSet() const
Returns true if any bitflag is set.
Definition Bitflags.h:217
PL_ALWAYS_INLINE plBitflags< T > operator&(const plBitflags< T > &rhs) const
Returns an object that has the flags that were set both in this and rhs.
Definition Bitflags.h:181
PL_ALWAYS_INLINE bool IsAnySet(const plBitflags< T > &rhs) const
Returns whether any of the given flags is set.
Definition Bitflags.h:145
PL_ALWAYS_INLINE bool IsSet(Enum flag) const
Checks if certain flags are set within the bitfield.
Definition Bitflags.h:127
PL_ALWAYS_INLINE bool AreNoneSet(const plBitflags< T > &rhs) const
Returns whether none of the given flags is set.
Definition Bitflags.h:139
PL_ALWAYS_INLINE plBitflags(Enum flag1)
Converts the incoming type to plBitflags<T>
Definition Bitflags.h:98
PL_ALWAYS_INLINE ConstIterator GetEndIterator() const
Returns an invalid iterator. Needed to support range based for loops.
Definition Bitflags.h:230
PL_ALWAYS_INLINE void Add(const plBitflags< T > &rhs)
Sets the given flag.
Definition Bitflags.h:151