Plasma Engine  2.0
Loading...
Searching...
No Matches
Bitfield.h
1#pragma once
2
3#include <Foundation/Containers/DynamicArray.h>
4#include <Foundation/Containers/HybridArray.h>
5#include <Foundation/Containers/Implementation/BitIterator.h>
6#include <Foundation/IO/Stream.h>
7#include <Foundation/Math/Constants.h>
8
15template <class Container>
17{
18public:
19 plBitfield() = default;
20
22 plUInt32 GetCount() const; // [tested]
23
25 template <typename = void> // Template is used to only conditionally compile this function in when it is actually used.
26 void SetCountUninitialized(plUInt32 uiBitCount); // [tested]
27
29 void SetCount(plUInt32 uiBitCount, bool bSetNew = false); // [tested]
30
32 bool IsEmpty() const; // [tested]
33
35 bool IsAnyBitSet(plUInt32 uiFirstBit = 0, plUInt32 uiNumBits = 0xFFFFFFFF) const; // [tested]
36
38 bool IsNoBitSet(plUInt32 uiFirstBit = 0, plUInt32 uiNumBits = 0xFFFFFFFF) const; // [tested]
39
41 bool AreAllBitsSet(plUInt32 uiFirstBit = 0, plUInt32 uiNumBits = 0xFFFFFFFF) const; // [tested]
42
44 void Clear(); // [tested]
45
47 void SetBit(plUInt32 uiBit); // [tested]
48
50 void ClearBit(plUInt32 uiBit); // [tested]
51
53 void SetBitValue(plUInt32 uiBit, bool bValue); // [tested]
54
56 bool IsBitSet(plUInt32 uiBit) const; // [tested]
57
59 void ClearAllBits(); // [tested]
60
62 void SetAllBits(); // [tested]
63
65 void SetBitRange(plUInt32 uiFirstBit, plUInt32 uiNumBits); // [tested]
66
68 void ClearBitRange(plUInt32 uiFirstBit, plUInt32 uiNumBits); // [tested]
69
71 void Swap(plBitfield<Container>& other); // [tested]
73 {
74 using iterator_category = std::forward_iterator_tag;
75 using value_type = plUInt32;
77
78 // Invalid iterator (end)
79 PL_FORCE_INLINE ConstIterator() = default; // [tested]
80
81 // Start iterator.
82 explicit ConstIterator(const plBitfield<Container>& bitfield); // [tested]
83
85 bool IsValid() const; // [tested]
86
88 plUInt32 Value() const; // [tested]
89
91 void Next(); // [tested]
92
93 bool operator==(const ConstIterator& other) const; // [tested]
94 bool operator!=(const ConstIterator& other) const; // [tested]
95
97 plUInt32 operator*() const; // [tested]
98
100 void operator++(); // [tested]
101
102 private:
103 void FindNextChunk(plUInt32 uiStartChunk);
104
105 private:
106 plUInt32 m_uiChunk = 0;
107 sub_iterator m_Iterator;
108 const plBitfield<Container>* m_pBitfield = nullptr;
109 };
110
113 ConstIterator GetIterator() const; // [tested]
114
116 ConstIterator GetEndIterator() const; // [tested]
117
118private:
119 friend struct ConstIterator;
120
121 plUInt32 GetBitInt(plUInt32 uiBitIndex) const;
122 plUInt32 GetBitMask(plUInt32 uiBitIndex) const;
123
124 plUInt32 m_uiCount = 0;
125 Container m_Container;
126};
127
130
132template <plUInt32 BITS>
133using plHybridBitfield = plBitfield<plHybridArray<plUInt32, (BITS + 31) / 32>>;
134
136// begin() /end() for range-based for-loop support
137template <typename Container>
138typename plBitfield<Container>::ConstIterator begin(const plBitfield<Container>& container)
139{
140 return container.GetIterator();
141}
142
143template <typename Container>
144typename plBitfield<Container>::ConstIterator cbegin(const plBitfield<Container>& container)
145{
146 return container.GetIterator();
147}
148
149template <typename Container>
151{
152 return container.GetEndIterator();
153}
154
155template <typename Container>
157{
158 return container.GetEndIterator();
159}
160
164
165template <typename T>
167{
168public:
169 using StorageType = T;
171
172 static constexpr plUInt32 GetStorageTypeBitCount() { return plMath::NumBits<T>(); }
173
176
177 static plStaticBitfield<T> MakeFromMask(StorageType bits);
178
180 bool IsAnyBitSet() const; // [tested]
181
183 bool IsNoBitSet() const; // [tested]
184
186 bool AreAllBitsSet() const; // [tested]
187
189 void SetBit(plUInt32 uiBit); // [tested]
190
192 void ClearBit(plUInt32 uiBit); // [tested]
193
195 void SetBitValue(plUInt32 uiBit, bool bValue); // [tested]
196
198 bool IsBitSet(plUInt32 uiBit) const; // [tested]
199
201 void ClearAllBits(); // [tested]
202
204 void SetAllBits(); // [tested]
205
207 void SetBitRange(plUInt32 uiFirstBit, plUInt32 uiNumBits); // [tested]
208
210 void ClearBitRange(plUInt32 uiFirstBit, plUInt32 uiNumBits); // [tested]
211
213 plUInt32 GetLowestBitSet() const; // [tested]
214
216 plUInt32 GetHighestBitSet() const; // [tested]
217
219 plUInt32 GetNumBitsSet() const; // [tested]
220
222 T GetValue() const; // [tested]
223
225 void SetValue(T value); // [tested]
226
228 void Swap(plStaticBitfield<T>& other); // [tested]
229
231 PL_ALWAYS_INLINE void operator|=(const plStaticBitfield<T>& rhs) { m_Storage |= rhs.m_Storage; }
232
234 PL_ALWAYS_INLINE void operator&=(const plStaticBitfield<T>& rhs) { m_Storage &= rhs.m_Storage; }
235
236 plResult Serialize(plStreamWriter& inout_writer) const
237 {
238 inout_writer.WriteVersion(s_Version);
239 inout_writer << m_Storage;
240 return PL_SUCCESS;
241 }
242
243 plResult Deserialize(plStreamReader& inout_reader)
244 {
245 /*auto version =*/inout_reader.ReadVersion(s_Version);
246 inout_reader >> m_Storage;
247 return PL_SUCCESS;
248 }
249
252 ConstIterator GetIterator() const // [tested]
253 {
254 return ConstIterator(m_Storage);
255 };
256
258 ConstIterator GetEndIterator() const // [tested]
259 {
260 return ConstIterator();
261 };
262
263private:
264 static constexpr plTypeVersion s_Version = 1;
265
266 plStaticBitfield(StorageType initValue)
267 : m_Storage(initValue)
268 {
269 }
270
271 template <typename U>
273
274 template <typename U>
276
277 template <typename U>
279
280 template <typename U>
281 friend bool operator==(plStaticBitfield<U> lhs, plStaticBitfield<U> rhs);
282
283 template <typename U>
284 friend bool operator!=(plStaticBitfield<U> lhs, plStaticBitfield<U> rhs);
285
286 StorageType m_Storage = 0;
287};
288
289template <typename T>
291{
292 return plStaticBitfield<T>(lhs.m_Storage | rhs.m_Storage);
293}
294
295template <typename T>
297{
298 return plStaticBitfield<T>(lhs.m_Storage & rhs.m_Storage);
299}
300
301template <typename T>
303{
304 return plStaticBitfield<T>(lhs.m_Storage ^ rhs.m_Storage);
305}
306
307template <typename T>
308inline bool operator==(plStaticBitfield<T> lhs, plStaticBitfield<T> rhs)
309{
310 return lhs.m_Storage == rhs.m_Storage;
311}
312
313template <typename T>
314inline bool operator!=(plStaticBitfield<T> lhs, plStaticBitfield<T> rhs)
315{
316 return lhs.m_Storage != rhs.m_Storage;
317}
318
320// begin() /end() for range-based for-loop support
321template <typename Container>
323{
324 return container.GetIterator();
325}
326
327template <typename Container>
329{
330 return container.GetIterator();
331}
332
333template <typename Container>
335{
336 return container.GetEndIterator();
337}
338
339template <typename Container>
341{
342 return container.GetEndIterator();
343}
344
349
350#include <Foundation/Containers/Implementation/Bitfield_inl.h>
A template interface, that turns any array class into a bitfield.
Definition Bitfield.h:17
bool IsEmpty() const
Returns true, if the bitfield does not store any bits.
Definition Bitfield_inl.h:52
void SetBitValue(plUInt32 uiBit, bool bValue)
Sets the given bit to 1 or 0 depending on the given value.
Definition Bitfield_inl.h:191
void SetCount(plUInt32 uiBitCount, bool bSetNew=false)
Resizes the Bitfield to hold the given number of bits. If bSetNew is true, new bits are set to 1,...
Definition Bitfield_inl.h:32
bool IsNoBitSet(plUInt32 uiFirstBit=0, plUInt32 uiNumBits=0xFFFFFFFF) const
Returns true, if the bitfield is empty or all bits are set to zero.
Definition Bitfield_inl.h:110
void ClearBit(plUInt32 uiBit)
Clears the given bit to 0.
Definition Bitfield_inl.h:183
ConstIterator GetIterator() const
Returns a constant iterator to the very first set bit. Note that due to the way iterating through bit...
Definition Bitfield_inl.h:309
bool IsBitSet(plUInt32 uiBit) const
Returns true, if the given bit is set to 1.
Definition Bitfield_inl.h:204
plUInt32 GetCount() const
Returns the number of bits that this bitfield stores.
Definition Bitfield_inl.h:16
void SetCountUninitialized(plUInt32 uiBitCount)
Resizes the Bitfield to hold the given number of bits. This version does NOT initialize new bits!
Definition Bitfield_inl.h:23
bool AreAllBitsSet(plUInt32 uiFirstBit=0, plUInt32 uiNumBits=0xFFFFFFFF) const
Returns true, if the bitfield is not empty and all bits are set to one.
Definition Bitfield_inl.h:116
void ClearBitRange(plUInt32 uiFirstBit, plUInt32 uiNumBits)
Clears the range starting at uiFirstBit up to (and including) uiLastBit to 0.
Definition Bitfield_inl.h:264
void SetBit(plUInt32 uiBit)
Sets the given bit to 1.
Definition Bitfield_inl.h:175
void SetBitRange(plUInt32 uiFirstBit, plUInt32 uiNumBits)
Sets the range starting at uiFirstBit up to (and including) uiLastBit to 1.
Definition Bitfield_inl.h:226
void Clear()
Discards all bits and sets count to zero.
Definition Bitfield_inl.h:168
void SetAllBits()
Sets all bits to 1.
Definition Bitfield_inl.h:219
ConstIterator GetEndIterator() const
Returns an invalid iterator. Needed to support range based for loops.
Definition Bitfield_inl.h:315
void Swap(plBitfield< Container > &other)
Swaps two bitfields.
Definition Bitfield_inl.h:302
void ClearAllBits()
Clears all bits to 0.
Definition Bitfield_inl.h:212
bool IsAnyBitSet(plUInt32 uiFirstBit=0, plUInt32 uiNumBits=0xFFFFFFFF) const
Returns true, if the bitfield is not empty and any bit is 1.
Definition Bitfield_inl.h:58
A hybrid array uses in-place storage to handle the first few elements without any allocation....
Definition HybridArray.h:12
Definition Bitfield.h:167
void Swap(plStaticBitfield< T > &other)
Swaps two bitfields.
Definition Bitfield_inl.h:543
plUInt32 GetLowestBitSet() const
Returns the index of the lowest bit that is set. Returns the max index+1 in case no bit is set,...
Definition Bitfield_inl.h:476
bool IsBitSet(plUInt32 uiBit) const
Returns true, if the given bit is set to 1.
Definition Bitfield_inl.h:494
void ClearBit(plUInt32 uiBit)
Clears the given bit to 0.
Definition Bitfield_inl.h:502
bool IsAnyBitSet() const
Returns true, if the bitfield is not zero.
Definition Bitfield_inl.h:424
void ClearBitRange(plUInt32 uiFirstBit, plUInt32 uiNumBits)
Clears the range starting at uiFirstBit up to (and including) uiLastBit to 0.
Definition Bitfield_inl.h:443
bool AreAllBitsSet() const
Returns true, if the bitfield is not empty and all bits are set to one.
Definition Bitfield_inl.h:436
void SetAllBits()
Sets all bits to 1.
Definition Bitfield_inl.h:482
ConstIterator GetIterator() const
Returns a constant iterator to the very first set bit. Note that due to the way iterating through bit...
Definition Bitfield.h:252
PL_ALWAYS_INLINE void operator|=(const plStaticBitfield< T > &rhs)
Modifies this to also contain the bits from rhs.
Definition Bitfield.h:231
void SetValue(T value)
Sets the raw uint that stores all bits.
Definition Bitfield_inl.h:531
plStaticBitfield()
Initializes the bitfield to all zero.
Definition Bitfield_inl.h:412
bool IsNoBitSet() const
Returns true, if the bitfield is all zero.
Definition Bitfield_inl.h:430
plUInt32 GetNumBitsSet() const
Returns the count of how many bits are set in total.
Definition Bitfield_inl.h:464
void ClearAllBits()
Clears all bits to 0. Same as Clear().
Definition Bitfield_inl.h:488
PL_ALWAYS_INLINE void operator&=(const plStaticBitfield< T > &rhs)
Modifies this to only contain the bits that were set in this and rhs.
Definition Bitfield.h:234
T GetValue() const
Returns the raw uint that stores all bits.
Definition Bitfield_inl.h:537
void SetBitValue(plUInt32 uiBit, bool bValue)
Sets the given bit to 1 or 0 depending on the given value.
Definition Bitfield_inl.h:510
void SetBitRange(plUInt32 uiFirstBit, plUInt32 uiNumBits)
Sets the range starting at uiFirstBit up to (and including) uiLastBit to 1.
Definition Bitfield_inl.h:454
void SetBit(plUInt32 uiBit)
Sets the given bit to 1.
Definition Bitfield_inl.h:523
ConstIterator GetEndIterator() const
Returns an invalid iterator. Needed to support range based for loops.
Definition Bitfield.h:258
plUInt32 GetHighestBitSet() const
Returns the index of the highest bit that is set. Returns the max index+1 in case no bit is set,...
Definition Bitfield_inl.h:470
Interface for binary in (read) streams.
Definition Stream.h:22
Interface for binary out (write) streams.
Definition Stream.h:107
PL_ALWAYS_INLINE void WriteVersion(plTypeVersion version)
Writes a type version to the stream.
Definition Stream_inl.h:154
constexpr plUInt32 NumBits()
Returns the number of bits in the given type. Mostly useful for unsigned integer types.
Definition Bitfield.h:73
void operator++()
Shorthand for 'Next'.
Definition Bitfield_inl.h:371
plUInt32 Value() const
Returns the 'value' of the element that this iterator points to.
Definition Bitfield_inl.h:337
bool IsValid() const
Checks whether this iterator points to a valid element.
Definition Bitfield_inl.h:331
plUInt32 operator*() const
Returns 'Value()' to enable foreach.
Definition Bitfield_inl.h:365
void Next()
Advances the iterator to the next element in the map. The iterator will not be valid anymore,...
Definition Bitfield_inl.h:343
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54