UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
BitArray.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
6#include "CoreTypes.h"
8#include "HAL/UnrealMemory.h"
11#include "Misc/EnumClassFlags.h"
15#include "Templates/EnableIf.h"
16#include "Templates/Invoke.h"
19
21class FSHA1;
22template<typename Allocator > class TBitArray;
23
24// Functions for manipulating bit sets.
25struct FBitSet
26{
29 {
30 const uint32 LowestBitMask = (Mask) & (-(int32)Mask);
31 const uint32 BitIndex = FMath::FloorLog2(LowestBitMask);
33 return BitIndex;
34 }
35
36 // Clang generates 7 instructions for int32 DivideAndRoundUp but only 2 for uint32
38
44};
45
46// Forward declaration.
47template<typename Allocator = FDefaultBitArrayAllocator,typename OtherAllocator = FDefaultBitArrayAllocator, bool Both=true>
49template<typename Allocator = FDefaultBitArrayAllocator>
50class TBitArray;
51template<typename Allocator = FDefaultBitArrayAllocator>
53template <typename AllocatorType, typename InDerivedType = void>
54class TScriptBitArray;
55
58{
60 MaxSize = 1 << 0,
62 MinSize = 1 << 1,
64 MaintainSize = 1 << 2,
65
67 OneFillMissingBits = 1 << 4,
68};
70
71namespace UE::Core::Private
72{
73 template <typename AllocatorA, typename AllocatorB, typename OutAllocator, typename ProjectionType>
75 {
76 check((const void*)&InA != (const void*)&InB && (const void*)&InA != (const void*)&OutResult && (const void*)&InB != (const void*)&OutResult);
77
79 {
80
81 const int32 MinNumBits = FMath::Min(InA.Num(), InB.Num());
82 if (MinNumBits > 0)
83 {
84 OutResult.Reserve(MinNumBits);
85 OutResult.NumBits = MinNumBits;
86
89
91
93 {
94 const uint32 NewValue = Invoke(InProjection, IteratorA.GetWord(), IteratorB.GetWord());
95 IteratorResult.SetWord(NewValue);
96 }
97 }
98
99 }
101 {
102
103 const int32 MaxNumBits = FMath::Max(InA.Num(), InB.Num());
105
106 if (MaxNumBits)
107 {
108 OutResult.Reserve(MaxNumBits);
109 OutResult.NumBits = MaxNumBits;
110
113
114 IteratorA.FillMissingBits(MissingBitsFill);
115 IteratorB.FillMissingBits(MissingBitsFill);
116
118
120 {
121 uint32 A = IteratorA ? IteratorA.GetWord() : MissingBitsFill;
122 uint32 B = IteratorB ? IteratorB.GetWord() : MissingBitsFill;
123
125 }
126 }
127
128 }
129 else
130 {
131 checkf(false, TEXT("Invalid size flag specified for binary bitwise AND"));
132 }
133
134 OutResult.CheckInvariants();
135 }
136
137
138 template<typename OtherAllocator, typename OutAllocator, typename ProjectionType>
140 {
141 if constexpr (std::is_same_v<OtherAllocator, OutAllocator>)
142 {
143 check(&InOther != &OutResult);
144 }
145
146 int32 NewNumBits = OutResult.NumBits;
148 {
149 NewNumBits = FMath::Min(InOther.Num(), OutResult.Num());
150 }
152 {
153 NewNumBits = FMath::Max(InOther.Num(), OutResult.Num());
154 }
155
156 const int32 SizeDifference = NewNumBits - OutResult.NumBits;
157 if (SizeDifference < 0)
158 {
159 OutResult.NumBits = NewNumBits;
160 OutResult.ClearPartialSlackBits();
161 }
162 else if (SizeDifference > 0)
163 {
166 }
167
169 if (OutResult.NumBits != 0)
170 {
172 IteratorOther.FillMissingBits(MissingBitsFill);
173
175
177 {
178 const uint32 OtherValue = IteratorOther ? IteratorOther.GetWord() : MissingBitsFill;
180 }
181 }
182
183 OutResult.CheckInvariants();
184 }
185}
186
189{
190public:
191
196
197 [[nodiscard]] UE_FORCEINLINE_HINT operator bool() const
198 {
199 return (Data & Mask) != 0;
200 }
201 UE_FORCEINLINE_HINT void operator=(const bool NewValue)
202 {
203 if(NewValue)
204 {
205 Data |= Mask;
206 }
207 else
208 {
209 Data &= ~Mask;
210 }
211 }
212 UE_FORCEINLINE_HINT void operator|=(const bool NewValue)
213 {
214 if (NewValue)
215 {
216 Data |= Mask;
217 }
218 }
219 UE_FORCEINLINE_HINT void operator&=(const bool NewValue)
220 {
221 if (!NewValue)
222 {
223 Data &= ~Mask;
224 }
225 }
226 UE_FORCEINLINE_HINT void AtomicSet(const bool NewValue)
227 {
228 uint32 Current = static_cast<uint32>(FPlatformAtomics::AtomicRead_Relaxed((const volatile int32*)&Data));
229 if(NewValue)
230 {
231 if (!(Current & Mask))
232 {
233 FPlatformAtomics::InterlockedOr((volatile int32*)&Data, (int32)Mask);
234 }
235 }
236 else
237 {
238 if (Current & Mask)
239 {
240 FPlatformAtomics::InterlockedAnd((volatile int32*)&Data, (int32)~Mask);
241 }
242 }
243 }
245 {
246 // As this is emulating a reference, assignment should not rebind,
247 // it should write to the referenced bit.
248 *this = (bool)Copy;
249 return *this;
250 }
251
252private:
253 uint32& Data;
254 uint32 Mask;
255};
256
257
260{
261public:
262
267
268 [[nodiscard]] UE_FORCEINLINE_HINT operator bool() const
269 {
270 return (Data & Mask) != 0;
271 }
272
273private:
274 const uint32& Data;
275 uint32 Mask;
276};
277
278
281{
282public:
284 : WordIndex(BitIndex >> NumBitsPerDWORDLogTwo)
285 , Mask(1 << (BitIndex & (NumBitsPerDWORD - 1)))
286 {
287 }
288
291
293 {
294 return (WordIndex == Other.WordIndex) & (Mask == Other.Mask);
295 }
296
298 {
299 return !(Other == *this);
300 }
301};
302
304{
305public:
318 static CORE_API void MemmoveBitsWordOrder(uint32* DestBits, int32 DestOffset, const uint32* SourceBits, int32 SourceOffset, uint32 NumBits);
319 static inline void MemmoveBitsWordOrder(int32* DestBits, int32 DestOffset, const int32* SourceBits, int32 SourceOffset, uint32 NumBits)
320 {
321 MemmoveBitsWordOrder(reinterpret_cast<uint32*>(DestBits), DestOffset, reinterpret_cast<const uint32*>(SourceBits), SourceOffset, NumBits);
322 }
323
325 inline static void ModularizeWordOffset(uint32*& Data, int32& Offset)
326 {
327 ModularizeWordOffset(const_cast<uint32 const*&>(Data), Offset);
328 }
329
331 static void ModularizeWordOffset(uint32 const*& Data, int32& Offset);
332
333private:
334
339 static void MemmoveBitsWordOrderAlignedInternal(uint32*const StartDest, const uint32*const StartSource, int32 StartOffset, uint32 NumBits);
340
342};
343
348template<typename Allocator /*= FDefaultBitArrayAllocator*/>
350{
351 template <typename, typename>
352 friend class TScriptBitArray;
353
354 template <typename AllocatorA, typename AllocatorB, typename OutAllocator, typename ProjectionType>
356
357 template<typename OtherAllocator, typename OutAllocator, typename ProjectionType>
359
360 typedef uint32 WordType;
361 static constexpr WordType FullWordMask = (WordType)-1;
362
363public:
364
365 typedef typename Allocator::template ForElementType<uint32> AllocatorType;
366
367 template<typename>
369
370 template<typename,typename,bool>
372
373 [[nodiscard]] constexpr TBitArray()
374 : NumBits(0)
375 , MaxBits(AllocatorInstance.GetInitialCapacity() * NumBitsPerDWORD)
376 {
377 // ClearPartialSlackBits is already satisfied since final word does not exist when NumBits == 0
378 }
379
380 [[nodiscard]] explicit consteval TBitArray(EConstEval)
381 : AllocatorInstance(ConstEval)
382 , NumBits(0)
383 , MaxBits(AllocatorInstance.GetInitialCapacity() * NumBitsPerDWORD)
384 {
385 }
386
393 : MaxBits(AllocatorInstance.GetInitialCapacity() * NumBitsPerDWORD)
394 {
395 Init(bValue, InNumBits);
396 }
397
402 {
403 this->Move(*this, Other);
404 }
405
410 : NumBits(0)
411 , MaxBits(0)
412 {
414 }
415
416 template<typename OtherAllocator>
418 : NumBits(0)
419 , MaxBits(0)
420 {
422 }
423
428 {
429 if (this != &Other)
430 {
431 this->Move(*this, Other);
432 }
433
434 return *this;
435 }
436
441 {
442 // check for self assignment since we don't use swap() mechanic
443 if (this != &Copy)
444 {
446 }
447 return *this;
448 }
449
450
451 template<typename OtherAllocator>
453 {
454 // No need for a self-assignment check. If we were the same, we'd be using
455 // the default assignment operator.
457 return *this;
458 }
459
461 {
462 if (Num() != Other.Num())
463 {
464 return false;
465 }
466
467 return FMemory::Memcmp(GetData(), Other.GetData(), GetNumWords() * sizeof(uint32)) == 0;
468 }
469
471 {
472 //sort by length
473 if (Num() != Other.Num())
474 {
475 return Num() < Other.Num();
476 }
477
478 uint32 NumWords = GetNumWords();
479 const uint32* Data0 = GetData();
480 const uint32* Data1 = Other.GetData();
481
482 //lexicographically compare
483 for (uint32 i = 0; i < NumWords; i++)
484 {
485 if (Data0[i] != Data1[i])
486 {
487 return Data0[i] < Data1[i];
488 }
489 }
490 return false;
491 }
492
493#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
495 {
496 return !(*this == Other);
497 }
498#endif
499
500private:
502 {
504 }
505
506 [[nodiscard]] UE_FORCEINLINE_HINT uint32 GetMaxWords() const
507 {
508 return FBitSet::CalculateNumWords(MaxBits);
509 }
510
512 {
514 return ~0u >> UnusedBits;
515 }
516
517 UE_FORCEINLINE_HINT static void SetWords(uint32* Words, int32 NumWords, bool bValue)
518 {
519 if (NumWords > 8)
520 {
521 FMemory::Memset(Words, bValue ? 0xff : 0, NumWords * sizeof(uint32));
522 }
523 else
524 {
525 uint32 Word = bValue ? ~0u : 0u;
526 for (int32 Idx = 0; Idx < NumWords; ++Idx)
527 {
528 Words[Idx] = Word;
529 }
530 }
531 }
532
533 template <typename BitArrayType>
535 {
536 ToArray.AllocatorInstance.MoveToEmpty(FromArray.AllocatorInstance);
537
538 ToArray .NumBits = FromArray.NumBits;
539 ToArray .MaxBits = FromArray.MaxBits;
540 FromArray.NumBits = 0;
541 FromArray.MaxBits = 0;
542 // No need to call this.ClearPartialSlackBits, because the words we're copying or moving from satisfy the invariant
543 // No need to call FromArray.ClearPartialSlackBits because NumBits == 0 automatically satisfies the invariant
544 }
545
546 template<typename OtherAllocator>
547 void Assign(const TBitArray<OtherAllocator>& Other)
548 {
549 Empty(Other.Num());
550 NumBits = Other.Num();
551 if (NumBits)
552 {
553 FMemory::Memcpy(GetData(), Other.GetData(), GetNumWords() * sizeof(uint32));
554 // No need to call ClearPartialSlackBits, because the bits we're copying from satisfy the invariant
555 // If NumBits == 0, the invariant is automatically satisfied so we also don't need ClearPartialSlackBits in that case.
556 }
557 }
558
559
560public:
561
565 void CheckInvariants() const
566 {
567#if DO_CHECK
568 checkf(NumBits <= MaxBits, TEXT("TBitArray::NumBits (%d) should never be greater than MaxBits (%d)"), NumBits, MaxBits);
569 checkf(NumBits >= 0 && MaxBits >= 0, TEXT("NumBits (%d) and MaxBits (%d) should always be >= 0"), NumBits, MaxBits);
570
571 // Verify the ClearPartialSlackBits invariant
573 if (UsedBits != 0)
574 {
576 const uint32 SlackMask = FullWordMask << UsedBits;
577
578 const uint32 LastWord = *(GetData() + LastWordIndex);
579 checkf((LastWord & SlackMask) == 0, TEXT("TBitArray slack bits are non-zero, this will result in undefined behavior."));
580 }
581#endif
582 }
583
588 {
589 // serialize number of bits
590 Ar << NumBits;
591
592 if (Ar.IsLoading())
593 {
594 // no need for slop when reading; set MaxBits to the smallest legal value that is >= NumBits
595 MaxBits = NumBitsPerDWORD * FMath::Max(FBitSet::CalculateNumWords(NumBits), (uint32)AllocatorInstance.GetInitialCapacity());
596
597 // allocate room for new bits
598 Realloc(0);
599 }
600
601 // serialize the data as one big chunk
602 Ar.Serialize(GetData(), GetNumWords() * sizeof(uint32));
603
604 if (Ar.IsLoading() && !Ar.IsObjectReferenceCollector() && !Ar.IsCountingMemory())
605 {
606 // Clear slack bits incase they were serialized non-null
607 ClearPartialSlackBits();
608 }
609 }
610
615 int32 Add(const bool Value)
616 {
617 const int32 Index = AddUninitialized(1);
618 SetBitNoCheck(Index, Value);
619 return Index;
620 }
621
627 {
628 // Support for legacy behavior requires us to silently ignore NumBitsToAdd < 0
629 if (NumBitsToAdd < 0)
630 {
631 return NumBits;
632 }
635 return Index;
636 }
637
646 template <typename InWordType>
653
661 template <typename OtherAllocator>
669
676 {
677 check(NumBitsToAdd >= 0);
679 if (NumBitsToAdd > 0)
680 {
684 {
685 // We're not extending into a new word, so we don't need to reserve more memory and we don't need to clear the unused bits on the final word
687 }
688 else
689 {
692 ClearPartialSlackBits();
693 }
694 }
695 return AddedIndex;
696 }
697
704 {
706 SetBitNoCheck(Index, Value);
707 }
708
720
729 template <typename InWordType>
735
743 template <typename OtherAllocator>
750
758 {
759 check(0 <= Index && Index <= NumBits);
760 check(NumBitsToAdd >= 0);
761
762 if (NumBitsToAdd > 0)
763 {
767 if (NumToShift > 0)
768 {
769 // MemmoveBitsWordOrder handles overlapping source and dest
771 }
772 }
773 }
774
780 {
782 const int32 InitialMaxBits = AllocatorInstance.GetInitialCapacity() * NumBitsPerDWORD;
783
784 NumBits = 0;
785
786 // If we need more bits or can shrink our allocation, do so
787 // Otherwise, reuse current initial allocation
788 if (ExpectedNumBits > MaxBits || MaxBits > InitialMaxBits)
789 {
790 MaxBits = FMath::Max(ExpectedNumBits, InitialMaxBits);
791 Realloc(0);
792 }
793 }
794
801 {
802 if (Number > MaxBits)
803 {
804 const uint32 MaxWords = AllocatorInstance.CalculateSlackGrow(
806 GetMaxWords(),
807 sizeof(uint32)
808 );
809 MaxBits = MaxWords * NumBitsPerDWORD;
810 Realloc(NumBits);
811 }
812 }
813
817 void Reset()
818 {
819 NumBits = 0;
820 }
821
829 {
831
832 const uint32 NumWords = GetNumWords();
833 const uint32 MaxWords = GetMaxWords();
834
835 if (NumWords > 0)
836 {
837 if (NumWords > MaxWords)
838 {
839 AllocatorInstance.ResizeAllocation(0, NumWords, sizeof(uint32));
840 MaxBits = NumWords * NumBitsPerDWORD;
841 }
842
843 SetWords(GetData(), NumWords, bValue);
844 ClearPartialSlackBits();
845 }
846 }
847
850 {
853
854 if (InNumBits > MaxBits)
855 {
857 const uint32 MaxWords = AllocatorInstance.CalculateSlackReserve(
859
860 AllocatorInstance.ResizeAllocation(PreviousNumWords, MaxWords, sizeof(uint32));
861
862 MaxBits = MaxWords * NumBitsPerDWORD;
863 }
864
865 ClearPartialSlackBits();
866 }
867
869 template <typename ValueType>
870 FORCENOINLINE void SetNum(int32 InNumBits, ValueType bValue)
871 {
872 static_assert(std::is_same_v<ValueType, bool>, "TBitArray::SetNum: unexpected type passed as the bValue argument (expected bool)");
876 {
878 }
879 }
880
888 {
889 check(Index >= 0 && NumBitsToSet >= 0 && Index + NumBitsToSet <= NumBits);
890
891 if (NumBitsToSet == 0)
892 {
893 return;
894 }
895
896 // Work out which uint32 index to set from, and how many
897 uint32 StartIndex = Index / NumBitsPerDWORD;
898 uint32 Count = (Index + NumBitsToSet + (NumBitsPerDWORD - 1)) / NumBitsPerDWORD - StartIndex;
899
900 // Work out masks for the start/end of the sequence
901 uint32 StartMask = FullWordMask << (Index % NumBitsPerDWORD);
903
904 uint32* Data = GetData() + StartIndex;
905 if (Value)
906 {
907 if (Count == 1)
908 {
909 *Data |= StartMask & EndMask;
910 }
911 else
912 {
913 *Data++ |= StartMask;
914 Count -= 2;
915 while (Count != 0)
916 {
917 *Data++ = ~0u;
918 --Count;
919 }
920 *Data |= EndMask;
921 }
922 }
923 else
924 {
925 if (Count == 1)
926 {
927 *Data &= ~(StartMask & EndMask);
928 }
929 else
930 {
931 *Data++ &= ~StartMask;
932 Count -= 2;
933 while (Count != 0)
934 {
935 *Data++ = 0;
936 --Count;
937 }
938 *Data &= ~EndMask;
939 }
940 }
941
943 }
944
953 template <typename InWordType>
955 {
956 check(Index >= 0 && NumBitsToSet >= 0 && Index + NumBitsToSet <= NumBits);
957 check(NumBitsToSet == 0 || ReadBits != nullptr);
958
959 // The planned implementation for big endian:
960 // iterate over each InWordType in ReadBits, and upcast it to the TBitArray's WordType. Call MemmoveBitsWordOrder(GetData(), Index + n, &UpcastedWord, ReadOffsetBits, Min(NumBitsToSet, BitsPerWord-ReadOffsetBits) for each word
961 static_assert(PLATFORM_LITTLE_ENDIAN, "SetRangeFromRange does not yet support big endian platforms");
963 }
964
972 template <typename OtherAllocator>
979
988 template <typename InWordType>
990 {
991 check(Index >= 0 && NumBitsToGet >= 0 && Index + NumBitsToGet <= NumBits);
992 check(NumBitsToGet == 0 || WriteBits != nullptr);
993
994 // See SetRangeFromRange for notes on the planned big endian implementation
995 static_assert(PLATFORM_LITTLE_ENDIAN, "SetRangeFromRange does not yet support big endian platforms");
997 }
998
1005 {
1006 check(BaseIndex >= 0 && NumBitsToRemove >= 0 && BaseIndex + NumBitsToRemove <= NumBits);
1007
1008 if (BaseIndex + NumBitsToRemove != NumBits)
1009 {
1010 // MemmoveBitsWordOrder handles overlapping source and dest
1011 uint32 NumToShift = NumBits - (BaseIndex + NumBitsToRemove);
1013 }
1014
1016
1017 ClearPartialSlackBits();
1019 }
1020
1021 /* Removes bits from the array by swapping them with bits at the end of the array.
1022 * This is mainly implemented so that other code using TArray::RemoveSwap will have
1023 * matching indices.
1024 * @param BaseIndex - The index of the first bit to remove.
1025 * @param NumBitsToRemove - The number of consecutive bits to remove.
1026 */
1028 {
1029 check(BaseIndex >= 0 && NumBitsToRemove >= 0 && BaseIndex + NumBitsToRemove <= NumBits);
1030 if( BaseIndex < NumBits - NumBitsToRemove )
1031 {
1032 // Copy bits from the end to the region we are removing
1034 {
1035#if PLATFORM_MAC || PLATFORM_LINUX
1036 // Clang compiler doesn't understand the short syntax, so let's be explicit
1037 int32 FromIndex = NumBits - NumBitsToRemove + Index;
1038 FConstBitReference From(GetData()[FromIndex / NumBitsPerDWORD],1 << (FromIndex & (NumBitsPerDWORD - 1)));
1039
1040 int32 ToIndex = BaseIndex + Index;
1042
1043 To = (bool)From;
1044#else
1045 (*this)[BaseIndex + Index] = (bool)(*this)[NumBits - NumBitsToRemove + Index];
1046#endif
1047 }
1048 }
1049
1050 // Remove the bits from the end of the array.
1052
1053 ClearPartialSlackBits();
1055 }
1056
1057
1063 {
1064 return FBitSet::CalculateNumWords(MaxBits) * sizeof(uint32);
1065 }
1066
1068 void CountBytes(FArchive& Ar) const
1069 {
1070 Ar.CountBytes(
1071 GetNumWords() * sizeof(uint32),
1072 GetMaxWords() * sizeof(uint32)
1073 );
1074 }
1075
1084 [[nodiscard]] int32 Find(bool bValue) const
1085 {
1086 return FindFromImpl(bValue, 0, NumBits);
1087 }
1088
1089private:
1090
1091 int32 FindFromImpl(bool bValue, int32 StartIndex, int32 EndIndexExclusive) const
1092 {
1093 // Produce a mask for the first iteration
1094 uint32 Mask = ~0u << (StartIndex % FBitSet::BitsPerWord);
1095
1096 // Iterate over the array until we see a word with a matching bit
1097 const uint32 Test = bValue ? 0u : ~0u;
1098
1099 const uint32* RESTRICT DwordArray = GetData();
1102 while (DwordIndex < DwordCount && (DwordArray[DwordIndex] & Mask) == (Test & Mask))
1103 {
1104 ++DwordIndex;
1105 Mask = ~0u;
1106 }
1107
1108 if (DwordIndex < DwordCount)
1109 {
1110 // If we're looking for a false, then we flip the bits - then we only need to find the first one bit
1111 const uint32 Bits = (bValue ? DwordArray[DwordIndex] : ~DwordArray[DwordIndex]) & Mask;
1112 UE_ASSUME(Bits != 0);
1113 const int32 LowestBitIndex = FMath::CountTrailingZeros(Bits) + (DwordIndex << NumBitsPerDWORDLogTwo);
1115 {
1116 return LowestBitIndex;
1117 }
1118 }
1119
1120 return INDEX_NONE;
1121 }
1122
1123 int32 FindLastFromImpl(bool bValue, int32 EndIndexExclusive) const
1124 {
1125 // We need to early out on empty bit arrays in order to avoid iterating on the first (inexistent) DWord :
1126 if (NumBits == 0)
1127 {
1128 return INDEX_NONE;
1129 }
1130
1131 // Produce a mask for the first iteration
1132 uint32 Mask = GetLastWordMask(EndIndexExclusive);
1133
1134 // Iterate over the array until we see a word with a matching bit
1135 const uint32* RESTRICT DwordArray = GetData();
1137 const uint32 Test = bValue ? 0u : ~0u;
1138 for (;;)
1139 {
1140 if (DwordIndex == 0)
1141 {
1142 return INDEX_NONE;
1143 }
1144 --DwordIndex;
1145 if ((DwordArray[DwordIndex] & Mask) != (Test & Mask))
1146 {
1147 break;
1148 }
1149 Mask = ~0u;
1150 }
1151
1152 // If we're looking for a false, then we flip the bits - then we only need to find the last one bit
1153 const uint32 Bits = (bValue ? DwordArray[DwordIndex] : ~DwordArray[DwordIndex]) & Mask;
1154 UE_ASSUME(Bits != 0);
1155
1156 uint32 BitIndex = (NumBitsPerDWORD - 1) - FMath::CountLeadingZeros(Bits);
1157
1158 int32 Result = BitIndex + (DwordIndex << NumBitsPerDWORDLogTwo);
1159 return Result;
1160 }
1161
1162public:
1163
1175 template <typename IndexType>
1176 [[nodiscard]] UE_FORCEINLINE_HINT int32 FindFrom(bool bValue, IndexType StartIndex) const
1177 {
1178 static_assert(!std::is_same_v<IndexType, bool>, "TBitArray::FindFrom: unexpected bool passed as the StartIndex argument");
1179 checkSlow((StartIndex >= 0) && (StartIndex <= NumBits));
1180 return FindFromImpl(bValue, StartIndex, NumBits);
1181 }
1182
1196 template <typename IndexType>
1197 [[nodiscard]] UE_FORCEINLINE_HINT int32 FindFrom(bool bValue, IndexType StartIndex, IndexType EndIndexExclusive) const
1198 {
1199 static_assert(!std::is_same_v<IndexType, bool>, "TBitArray::FindFrom: unexpected bool passed as the StartIndex argument");
1200 checkSlow((StartIndex >= 0) && (StartIndex <= NumBits));
1202 return FindFromImpl(bValue, StartIndex, EndIndexExclusive);
1203 }
1204
1213 [[nodiscard]] int32 FindLast(bool bValue) const
1214 {
1215 return FindLastFromImpl(bValue, /*EndIndexExclusive = */NumBits);
1216 }
1217
1227 template <typename IndexType>
1228 [[nodiscard]] int32 FindLastFrom(bool bValue, IndexType EndIndexInclusive) const
1229 {
1230 static_assert(!std::is_same_v<IndexType, bool>, "TBitArray::FindLastFrom: unexpected bool passed as the EndIndexInclusive argument");
1231 // This range check here ([-1, NumBits)) is because the end index is inclusive and because this is the reverse logic of the FindFrom range ([0, NumBits])
1232 // It doesn't make much sense to allow EndIndexInclusive to be -1 in FindLastFrom (since that will always fail), much like it doesn't make sense to allow
1233 // StartIndex to be NumBits in FindFrom (for the same reason) but this keeps the implementations consistent
1235 return FindLastFromImpl(bValue, /*EndIndexExclusive = */EndIndexInclusive + 1);
1236 }
1237
1245 [[nodiscard]] UE_FORCEINLINE_HINT bool Contains(bool bValue) const
1246 {
1247 return Find(bValue) != INDEX_NONE;
1248 }
1249
1259 {
1260 const int32 FirstZeroBitIndex = FindFromImpl(false, StartIndex, NumBits);
1262 {
1263 (*this)[FirstZeroBitIndex] = true;
1265 }
1266 return FirstZeroBitIndex;
1267 }
1268
1276 {
1277 const int32 LastZeroBitIndex = FindLast(false);
1279 {
1280 (*this)[LastZeroBitIndex] = true;
1282 }
1283 return LastZeroBitIndex;
1284 }
1285
1289 template <typename AllocatorA, typename AllocatorB>
1291 {
1292 TBitArray Result;
1294 return Result;
1295 }
1296
1300 template <typename OtherAllocator, typename BinaryOpType>
1306
1310 template <typename OtherAllocator>
1316
1320 template <typename AllocatorA, typename AllocatorB>
1322 {
1323 if constexpr (std::is_same_v<AllocatorA, AllocatorB>)
1324 {
1325 check(&A != &B);
1326 }
1327
1328 TBitArray Result;
1330 return Result;
1331 }
1332
1336 template <typename OtherAllocator>
1342
1346 template <typename AllocatorA, typename AllocatorB>
1348 {
1349 TBitArray Result;
1351 return Result;
1352 }
1353
1357 template <typename OtherAllocator>
1363
1368 {
1369 for (FWordIterator It(*this); It; ++It)
1370 {
1371 It.SetWord(~It.GetWord());
1372 }
1373 }
1374
1379 {
1380 if (ToIndex == INDEX_NONE)
1381 {
1382 ToIndex = NumBits;
1383 }
1384
1385 checkSlow(FromIndex >= 0);
1386 checkSlow(ToIndex >= FromIndex && ToIndex <= NumBits);
1387
1388 int32 NumSetBits = 0;
1389 for (FConstWordIterator It(*this, FromIndex, ToIndex); It; ++It)
1390 {
1391 NumSetBits += FMath::CountBits(It.GetWord());
1392 }
1393 return NumSetBits;
1394 }
1395
1404 template <typename OtherAllocator>
1406 {
1407 const uint32 MissingBitsFill = bMissingBitValue ? ~0u : 0;
1408
1411
1412 ThisIterator.FillMissingBits(MissingBitsFill);
1413 OtherIterator.FillMissingBits(MissingBitsFill);
1414
1415 while (ThisIterator || OtherIterator)
1416 {
1417 const uint32 A = ThisIterator ? ThisIterator.GetWord() : MissingBitsFill;
1418 const uint32 B = OtherIterator ? OtherIterator.GetWord() : MissingBitsFill;
1419 if (A != B)
1420 {
1421 return false;
1422 }
1423
1424 ++ThisIterator;
1425 ++OtherIterator;
1426 }
1427
1428 return true;
1429 }
1430
1439 {
1440 const int32 NumToAdd = DesiredNum - Num();
1441 if (NumToAdd > 0)
1442 {
1444 return NumToAdd;
1445 }
1446 return 0;
1447 }
1448
1449 // Accessors.
1451 {
1452 return InIndex >= 0 && InIndex < NumBits;
1453 }
1454
1461 [[nodiscard]] bool IsEmpty() const
1462 {
1463 return NumBits == 0;
1464 }
1465
1467 [[nodiscard]] UE_FORCEINLINE_HINT int32 Max() const { return MaxBits; }
1469 {
1470 check(Index>=0 && Index<NumBits);
1471 return FBitReference(
1473 1 << (Index & (NumBitsPerDWORD - 1))
1474 );
1475 }
1477 {
1478 check(Index>=0 && Index<NumBits);
1479 return FConstBitReference(
1481 1 << (Index & (NumBitsPerDWORD - 1))
1482 );
1483 }
1485 {
1487 checkSlow(RelativeReference.WordIndex >= 0);
1488 checkSlow(((uint32)RelativeReference.WordIndex + 1) * NumBitsPerDWORD - 1 - FMath::CountLeadingZeros(RelativeReference.Mask) < (uint32)NumBits);
1489 return FBitReference(
1490 GetData()[RelativeReference.WordIndex],
1492 );
1493 }
1495 {
1497 checkSlow(RelativeReference.WordIndex >= 0);
1498 checkSlow(((uint32)RelativeReference.WordIndex + 1) * NumBitsPerDWORD - 1 - FMath::CountLeadingZeros(RelativeReference.Mask) < (uint32)NumBits);
1499 return FConstBitReference(
1500 GetData()[RelativeReference.WordIndex],
1502 );
1503 }
1504
1507 {
1508 public:
1510 : FRelativeBitReference(StartIndex)
1511 , Array(InArray)
1512 , Index(StartIndex)
1513 {
1514 }
1516 {
1517 ++Index;
1518 this->Mask <<= 1;
1519 if(!this->Mask)
1520 {
1521 // Advance to the next uint32.
1522 this->Mask = 1;
1523 ++this->WordIndex;
1524 }
1525 return *this;
1526 }
1527
1529 {
1530 return GetValue();
1531 }
1532
1534 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
1535 {
1536 return Index < Array.Num();
1537 }
1538
1541 {
1542 return !(bool)*this;
1543 }
1544
1545 [[nodiscard]] UE_FORCEINLINE_HINT FBitReference GetValue() const { return FBitReference(Array.GetData()[this->WordIndex],this->Mask); }
1547 private:
1548 TBitArray<Allocator>& Array;
1549 int32 Index;
1550 };
1551
1554 {
1555 public:
1562
1565 , Array(InArray)
1566 , Index(-1)
1567 {
1568 }
1569
1571 {
1572 --Index;
1573 this->Mask >>= 1;
1574 if (!this->Mask)
1575 {
1576 // Advance to the next uint32.
1577 this->Mask = (1u << (NumBitsPerDWORD - 1u));
1578 --this->WordIndex;
1579 }
1580 return *this;
1581 }
1582
1584 {
1585 return GetValue();
1586 }
1587
1589 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
1590 {
1591 return Index >= 0;
1592 }
1593
1596 {
1597 return !(bool)*this;
1598 }
1599
1600 [[nodiscard]] UE_FORCEINLINE_HINT FBitReference GetValue() const { return FBitReference(Array.GetData()[this->WordIndex], this->Mask); }
1602 private:
1603 TBitArray<Allocator>& Array;
1604 int32 Index;
1605 };
1606
1609 {
1610 public:
1612 : FRelativeBitReference(StartIndex)
1613 , Array(InArray)
1614 , Index(StartIndex)
1615 {
1616 }
1618 {
1619 ++Index;
1620 this->Mask <<= 1;
1621 if(!this->Mask)
1622 {
1623 // Advance to the next uint32.
1624 this->Mask = 1;
1625 ++this->WordIndex;
1626 }
1627 return *this;
1628 }
1629
1631 {
1632 return GetValue();
1633 }
1634
1636 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
1637 {
1638 return Index < Array.Num();
1639 }
1642 {
1643 return !(bool)*this;
1644 }
1645
1646 [[nodiscard]] UE_FORCEINLINE_HINT FConstBitReference GetValue() const { return FConstBitReference(Array.GetData()[this->WordIndex],this->Mask); }
1648 private:
1649 const TBitArray<Allocator>& Array;
1650 int32 Index;
1651 };
1652
1655 {
1656 public:
1665 , Array(InArray)
1666 , Index(-1)
1667 {
1668 }
1670 {
1671 --Index;
1672 this->Mask >>= 1u;
1673 if(!this->Mask)
1674 {
1675 // Advance to the next uint32.
1676 this->Mask = (1u << (NumBitsPerDWORD-1u));
1677 --this->WordIndex;
1678 }
1679 return *this;
1680 }
1681
1683 {
1684 return GetValue();
1685 }
1686
1688 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
1689 {
1690 return Index >= 0;
1691 }
1694 {
1695 return !(bool)*this;
1696 }
1697
1698 [[nodiscard]] UE_FORCEINLINE_HINT FConstBitReference GetValue() const { return FConstBitReference(Array.GetData()[this->WordIndex],this->Mask); }
1700 private:
1701 const TBitArray<Allocator>& Array;
1702 int32 Index;
1703 };
1704
1706 {
1707 return (uint32*)AllocatorInstance.GetAllocation();
1708 }
1709
1711 {
1712 return (uint32*)AllocatorInstance.GetAllocation();
1713 }
1714
1715private:
1716 template<typename WordType>
1717 struct TWordIteratorBase
1718 {
1719 [[nodiscard]] explicit operator bool() const
1720 {
1721 return CurrentIndex < NumWords;
1722 }
1723
1724 [[nodiscard]] int32 GetIndex() const
1725 {
1726 return CurrentIndex;
1727 }
1728
1729 [[nodiscard]] uint32 GetWord() const
1730 {
1731 checkSlow(CurrentIndex < NumWords);
1732
1733 if (CurrentMask == ~0u)
1734 {
1735 return Data[CurrentIndex];
1736 }
1737 else if (MissingBitsFill == 0)
1738 {
1739 return Data[CurrentIndex] & CurrentMask;
1740 }
1741 else
1742 {
1743 return (Data[CurrentIndex] & CurrentMask) | (MissingBitsFill & ~CurrentMask);
1744 }
1745 }
1746
1747 void operator++()
1748 {
1749 ++this->CurrentIndex;
1750 if (this->CurrentIndex == NumWords-1)
1751 {
1752 CurrentMask = FinalMask;
1753 }
1754 else
1755 {
1756 CurrentMask = ~0u;
1757 }
1758 }
1759
1760 void FillMissingBits(uint32 InMissingBitsFill)
1761 {
1762 MissingBitsFill = InMissingBitsFill;
1763 }
1764
1765 protected:
1766
1767 [[nodiscard]] explicit TWordIteratorBase(WordType* InData, int32 InStartBitIndex, int32 InEndBitIndex)
1768 : Data(InData)
1769 , CurrentIndex(InStartBitIndex / NumBitsPerDWORD)
1770 , NumWords(FMath::DivideAndRoundUp(InEndBitIndex, NumBitsPerDWORD))
1771 , CurrentMask(~0u << (InStartBitIndex % NumBitsPerDWORD))
1772 , FinalMask(~0u)
1773 , MissingBitsFill(0)
1774 {
1776 if (Shift < NumBitsPerDWORD)
1777 {
1778 FinalMask = ~0u >> Shift;
1779 }
1780
1781 if (CurrentIndex == NumWords - 1)
1782 {
1783 CurrentMask &= FinalMask;
1784 FinalMask = CurrentMask;
1785 }
1786 }
1787
1788 WordType* RESTRICT Data;
1789
1790 int32 CurrentIndex;
1791 int32 NumWords;
1792
1793 uint32 CurrentMask;
1794 uint32 FinalMask;
1795 uint32 MissingBitsFill;
1796 };
1797
1798public:
1799 struct FConstWordIterator : TWordIteratorBase<const uint32>
1800 {
1802 : TWordIteratorBase<const uint32>(InArray.GetData(), 0, InArray.Num())
1803 {
1804 }
1805
1812 };
1813
1814
1815 struct FWordIterator : TWordIteratorBase<uint32>
1816 {
1818 : TWordIteratorBase<uint32>(InArray.GetData(), 0, InArray.Num())
1819 {
1820 }
1821
1823 {
1824 checkSlow(this->CurrentIndex < this->NumWords);
1825
1826 if (this->CurrentIndex == this->NumWords-1)
1827 {
1828 this->Data[this->CurrentIndex] = InWord & this->FinalMask;
1829 }
1830 else
1831 {
1832 this->Data[this->CurrentIndex] = InWord;
1833 }
1834 }
1835 };
1836
1841 [[nodiscard]] UE_FORCEINLINE_HINT FIterator end() { return FIterator(*this, NumBits); }
1842 [[nodiscard]] UE_FORCEINLINE_HINT FConstIterator end() const { return FConstIterator(*this, NumBits); }
1843
1848
1849private:
1850 AllocatorType AllocatorInstance;
1851 int32 NumBits;
1852 int32 MaxBits;
1853
1854 FORCENOINLINE void Realloc(int32 PreviousNumBits)
1855 {
1858
1859 AllocatorInstance.ResizeAllocation(PreviousNumWords,MaxWords,sizeof(uint32));
1860 ClearPartialSlackBits(); // Implement class invariant
1861 }
1862
1863 void SetBitNoCheck(int32 Index, bool Value)
1864 {
1866 uint32 BitOffset = (Index % NumBitsPerDWORD);
1867 Word = (Word & ~(1 << BitOffset)) | (((uint32)Value) << BitOffset);
1868 }
1869
1873 void ClearPartialSlackBits()
1874 {
1875 // TBitArray has a contract about bits outside of the active range - the bits in the final word past NumBits are guaranteed to be 0
1876 // This prevents easy-to-make determinism errors from users of TBitArray that do not carefully mask the final word.
1877 // It also allows us optimize some operations which would otherwise require us to mask the last word.
1879 if (UsedBits != 0)
1880 {
1882 const uint32 SlackMask = FullWordMask >> (NumBitsPerDWORD - UsedBits);
1883
1886 }
1887 }
1888
1889 template<bool bFreezeMemoryImage, typename Dummy=void>
1890 struct TSupportsFreezeMemoryImageHelper
1891 {
1892 static void WriteMemoryImage(FMemoryImageWriter& Writer, const TBitArray&) { Writer.WriteBytes(TBitArray()); }
1893 };
1894
1895 template<typename Dummy>
1896 struct TSupportsFreezeMemoryImageHelper<true, Dummy>
1897 {
1898 static void WriteMemoryImage(FMemoryImageWriter& Writer, const TBitArray& Object)
1899 {
1900 const int32 NumWords = FMath::DivideAndRoundUp(Object.NumBits, NumBitsPerDWORD);
1901 Object.AllocatorInstance.WriteMemoryImage(Writer, StaticGetTypeLayoutDesc<uint32>(), NumWords);
1902 Writer.WriteBytes(Object.NumBits);
1903 Writer.WriteBytes(Object.NumBits);
1904 }
1905 };
1906
1907public:
1909 {
1911 checkf(!Writer.Is32BitTarget(), TEXT("TBitArray does not currently support freezing for 32bits"));
1912 TSupportsFreezeMemoryImageHelper<bSupportsFreezeMemoryImage>::WriteMemoryImage(Writer, *this);
1913 }
1914};
1915
1916namespace Freeze
1917{
1918 template<typename Allocator>
1920 {
1921 Object.WriteMemoryImage(Writer);
1922 }
1923}
1924
1926
1927template<typename Allocator>
1929{
1930 uint32 NumWords = FBitSet::CalculateNumWords(BitArray.Num());
1931 uint32 Hash = NumWords;
1932 const uint32* Data = BitArray.GetData();
1933 for (uint32 i = 0; i < NumWords; i++)
1934 {
1935 Hash ^= Data[i];
1936 }
1937 return Hash;
1938}
1939
1940
1942template<typename Allocator>
1944{
1945public:
1946
1949 , Array (InArray)
1950 , UnvisitedBitMask (~0U)
1951 , CurrentBitIndex (0)
1952 , BaseBitIndex (0)
1953 {
1954 if (Array.Num())
1955 {
1956 FindFirstSetBit();
1957 }
1958 }
1959
1961 : FRelativeBitReference(StartIndex)
1962 , Array (InArray)
1963 , UnvisitedBitMask ((~0U) << (StartIndex & (NumBitsPerDWORD - 1)))
1964 , CurrentBitIndex (StartIndex)
1965 , BaseBitIndex (StartIndex & ~(NumBitsPerDWORD - 1))
1966 {
1967 check(StartIndex >= 0 && StartIndex <= Array.Num());
1968 if (StartIndex != Array.Num())
1969 {
1970 FindFirstSetBit();
1971 }
1972 }
1973
1976 {
1977 // Mark the current bit as visited.
1978 UnvisitedBitMask &= ~this->Mask;
1979
1980 // Find the first set bit that hasn't been visited yet.
1981 FindFirstSetBit();
1982
1983 return *this;
1984 }
1985
1987 {
1988 // We only need to compare the bit index and the array... all the rest of the state is unobservable.
1989 return CurrentBitIndex == Rhs.CurrentBitIndex && &Array == &Rhs.Array;
1990 }
1991
1992#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
1994 {
1995 return !(*this == Rhs);
1996 }
1997#endif
1998
2000 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
2001 {
2002 return CurrentBitIndex < Array.Num();
2003 }
2006 {
2007 return !(bool)*this;
2008 }
2009
2012 {
2013 return CurrentBitIndex;
2014 }
2015
2016private:
2017
2018 const TBitArray<Allocator>& Array;
2019
2020 uint32 UnvisitedBitMask;
2021 int32 CurrentBitIndex;
2022 int32 BaseBitIndex;
2023
2025 void FindFirstSetBit()
2026 {
2027 const uint32* ArrayData = Array.GetData();
2028 const int32 ArrayNum = Array.Num();
2029 const int32 LastWordIndex = (ArrayNum - 1) / NumBitsPerDWORD;
2030
2031 // Advance to the next non-zero uint32.
2032 uint32 RemainingBitMask = ArrayData[this->WordIndex] & UnvisitedBitMask;
2033 while (!RemainingBitMask)
2034 {
2035 ++this->WordIndex;
2036 BaseBitIndex += NumBitsPerDWORD;
2037 if (this->WordIndex > LastWordIndex)
2038 {
2039 // We've advanced past the end of the array.
2040 CurrentBitIndex = ArrayNum;
2041 return;
2042 }
2043
2045 UnvisitedBitMask = ~0u;
2046 }
2047
2048 // This operation has the effect of unsetting the lowest set bit of BitMask
2050
2051 // This operation XORs the above mask with the original mask, which has the effect
2052 // of returning only the bits which differ; specifically, the lowest bit
2054
2055 // If the Nth bit was the lowest set bit of BitMask, then this gives us N
2056 CurrentBitIndex = BaseBitIndex + NumBitsPerDWORD - 1 - FMath::CountLeadingZeros(this->Mask);
2057
2058 // If we've accidentally iterated off the end of an array but still within the same Word
2059 // then set the index to the last index of the array
2060 if (CurrentBitIndex > ArrayNum)
2061 {
2062 CurrentBitIndex = ArrayNum;
2063 }
2064 }
2065};
2066
2067
2070template<typename Allocator,typename OtherAllocator, bool Both>
2072{
2073public:
2074
2079 int32 StartIndex = 0
2080 )
2081 : FRelativeBitReference(StartIndex)
2082 , ArrayA(InArrayA)
2083 , ArrayB(InArrayB)
2084 , UnvisitedBitMask((~0U) << (StartIndex & (NumBitsPerDWORD - 1)))
2085 , CurrentBitIndex(StartIndex)
2086 , BaseBitIndex(StartIndex & ~(NumBitsPerDWORD - 1))
2087 {
2088 check(ArrayA.Num() == ArrayB.Num());
2089
2090 FindFirstSetBit();
2091 }
2092
2095 {
2096 checkSlow(ArrayA.Num() == ArrayB.Num());
2097
2098 // Mark the current bit as visited.
2099 UnvisitedBitMask &= ~this->Mask;
2100
2101 // Find the first set bit that hasn't been visited yet.
2102 FindFirstSetBit();
2103
2104 return *this;
2105
2106 }
2107
2109 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
2110 {
2111 return CurrentBitIndex < ArrayA.Num();
2112 }
2115 {
2116 return !(bool)*this;
2117 }
2118
2121 {
2122 return CurrentBitIndex;
2123 }
2124
2125private:
2126
2127 const TBitArray<Allocator>& ArrayA;
2128 const TBitArray<OtherAllocator>& ArrayB;
2129
2130 uint32 UnvisitedBitMask;
2131 int32 CurrentBitIndex;
2132 int32 BaseBitIndex;
2133
2135 void FindFirstSetBit()
2136 {
2137 const uint32 EmptyArrayData = 0;
2138 const uint32* ArrayDataA = ArrayA.GetData();
2139 if (!ArrayDataA)
2140 {
2142 }
2143 const uint32* ArrayDataB = ArrayB.GetData();
2144 if (!ArrayDataB)
2145 {
2147 }
2148
2149 // Advance to the next non-zero uint32.
2151
2152 if (Both)
2153 {
2154 RemainingBitMask = ArrayDataA[this->WordIndex] & ArrayDataB[this->WordIndex] & UnvisitedBitMask;
2155 }
2156 else
2157 {
2158 RemainingBitMask = (ArrayDataA[this->WordIndex] | ArrayDataB[this->WordIndex]) & UnvisitedBitMask;
2159 }
2160
2161 while(!RemainingBitMask)
2162 {
2163 this->WordIndex++;
2164 BaseBitIndex += NumBitsPerDWORD;
2165 const int32 LastWordIndex = (ArrayA.Num() - 1) / NumBitsPerDWORD;
2166 if (this->WordIndex <= LastWordIndex)
2167 {
2168 if (Both)
2169 {
2170 RemainingBitMask = ArrayDataA[this->WordIndex] & ArrayDataB[this->WordIndex];
2171 }
2172 else
2173 {
2174 RemainingBitMask = ArrayDataA[this->WordIndex] | ArrayDataB[this->WordIndex];
2175 }
2176
2177 UnvisitedBitMask = ~0;
2178 }
2179 else
2180 {
2181 // We've advanced past the end of the array.
2182 CurrentBitIndex = ArrayA.Num();
2183 return;
2184 }
2185 };
2186
2187 // We can assume that RemainingBitMask!=0 here.
2189
2190 // This operation has the effect of unsetting the lowest set bit of BitMask
2192
2193 // This operation XORs the above mask with the original mask, which has the effect
2194 // of returning only the bits which differ; specifically, the lowest bit
2196
2197 // If the Nth bit was the lowest set bit of BitMask, then this gives us N
2198 CurrentBitIndex = BaseBitIndex + NumBitsPerDWORD - 1 - FMath::CountLeadingZeros(this->Mask);
2199 }
2200};
2201
2202// A specialization of TConstDualSetBitIterator for iterating over two TBitArray containers and
2203// stop only when bits in the same location in each are both set.
2204template<typename Allocator, typename OtherAllocator>
2206
2207// A specialization of TConstDualSetBitIterator for iterating over two TBitArray containers and
2208// stop only when either, or both, of the bits in the same location in each are set.
2209template<typename Allocator, typename OtherAllocator>
2211
2212// Untyped bit array type for accessing TBitArray data, like FScriptArray for TArray.
2213// Must have the same memory representation as a TBitArray.
2214template <typename Allocator, typename InDerivedType>
2216{
2217 using DerivedType = std::conditional_t<std::is_void_v<InDerivedType>, TScriptBitArray, InDerivedType>;
2218
2219public:
2226 : NumBits(0)
2227 , MaxBits(0)
2228 {
2229 }
2230
2232 {
2233 return Index >= 0 && Index < NumBits;
2234 }
2235
2237 {
2239 return FBitReference(GetData()[Index / NumBitsPerDWORD], 1 << (Index & (NumBitsPerDWORD - 1)));
2240 }
2241
2243 {
2245 return FConstBitReference(GetData()[Index / NumBitsPerDWORD], 1 << (Index & (NumBitsPerDWORD - 1)));
2246 }
2247
2248 void MoveAssign(DerivedType& Other)
2249 {
2250 checkSlow(this != &Other);
2251 Empty(0);
2252 AllocatorInstance.MoveToEmpty(Other.AllocatorInstance);
2253 NumBits = Other.NumBits; Other.NumBits = 0;
2254 MaxBits = Other.MaxBits; Other.MaxBits = 0;
2255 }
2256
2257 void Empty(int32 Slack = 0)
2258 {
2259 NumBits = 0;
2260
2262 // If the expected number of bits doesn't match the allocated number of bits, reallocate.
2263 if (MaxBits != Slack)
2264 {
2265 MaxBits = Slack;
2266 Realloc(0);
2267 }
2268 }
2269
2270 int32 Add(const bool Value)
2271 {
2272 const int32 Index = NumBits;
2273 NumBits++;
2274 if (NumBits > MaxBits)
2275 {
2276 ReallocGrow(NumBits - 1);
2277 }
2278 else if ((Index % NumBitsPerDWORD) == 0)
2279 {
2280 // Clear the new word to maintain the ClearPartialSlackBits invariant.
2281 GetData()[Index / NumBitsPerDWORD] = 0;
2282 }
2283 (*this)[Index] = Value;
2284 return Index;
2285 }
2286
2287private:
2288 typedef typename Allocator::template ForElementType<uint32> AllocatorType;
2289
2290 AllocatorType AllocatorInstance;
2291 int32 NumBits;
2292 int32 MaxBits;
2293
2294 // This function isn't intended to be called, just to be compiled to validate the correctness of the type.
2295 static void CheckConstraints()
2296 {
2298 typedef TBitArray<> RealType;
2299
2300 // Check that the class footprint is the same
2301 static_assert(sizeof (ScriptType) == sizeof (RealType), "TScriptBitArray's size doesn't match TBitArray");
2302 static_assert(alignof(ScriptType) == alignof(RealType), "TScriptBitArray's alignment doesn't match TBitArray");
2303
2304 // Check member sizes
2305 static_assert(sizeof(DeclVal<ScriptType>().AllocatorInstance) == sizeof(DeclVal<RealType>().AllocatorInstance), "TScriptBitArray's AllocatorInstance member size does not match TBitArray's");
2306 static_assert(sizeof(DeclVal<ScriptType>().NumBits) == sizeof(DeclVal<RealType>().NumBits), "TScriptBitArray's NumBits member size does not match TBitArray's");
2307 static_assert(sizeof(DeclVal<ScriptType>().MaxBits) == sizeof(DeclVal<RealType>().MaxBits), "TScriptBitArray's MaxBits member size does not match TBitArray's");
2308
2309 // Check member offsets
2310 static_assert(STRUCT_OFFSET(ScriptType, AllocatorInstance) == STRUCT_OFFSET(RealType, AllocatorInstance), "TScriptBitArray's AllocatorInstance member offset does not match TBitArray's");
2311 static_assert(STRUCT_OFFSET(ScriptType, NumBits) == STRUCT_OFFSET(RealType, NumBits), "TScriptBitArray's NumBits member offset does not match TBitArray's");
2312 static_assert(STRUCT_OFFSET(ScriptType, MaxBits) == STRUCT_OFFSET(RealType, MaxBits), "TScriptBitArray's MaxBits member offset does not match TBitArray's");
2313 }
2314
2315 [[nodiscard]] UE_FORCEINLINE_HINT uint32* GetData()
2316 {
2317 return (uint32*)AllocatorInstance.GetAllocation();
2318 }
2319
2320 [[nodiscard]] UE_FORCEINLINE_HINT const uint32* GetData() const
2321 {
2322 return (const uint32*)AllocatorInstance.GetAllocation();
2323 }
2324
2325 FORCENOINLINE void Realloc(int32 PreviousNumBits)
2326 {
2327 const uint32 MaxWords = AllocatorInstance.CalculateSlackReserve(
2329 sizeof(uint32)
2330 );
2331 MaxBits = MaxWords * NumBitsPerDWORD;
2333
2334 AllocatorInstance.ResizeAllocation(PreviousNumWords, MaxWords, sizeof(uint32));
2335
2337 {
2338 // Reset the newly allocated slack Words.
2339 FMemory::Memzero((uint32*)AllocatorInstance.GetAllocation() + PreviousNumWords, (MaxWords - PreviousNumWords) * sizeof(uint32));
2340 }
2341 }
2342 FORCENOINLINE void ReallocGrow(int32 PreviousNumBits)
2343 {
2344 // Allocate memory for the new bits.
2345 const uint32 MaxWords = AllocatorInstance.CalculateSlackGrow(
2348 sizeof(uint32)
2349 );
2350 MaxBits = MaxWords * NumBitsPerDWORD;
2352 AllocatorInstance.ResizeAllocation(PreviousNumWords, MaxWords, sizeof(uint32));
2354 {
2355 // Reset the newly allocated slack Words.
2356 FMemory::Memzero((uint32*)AllocatorInstance.GetAllocation() + PreviousNumWords, (MaxWords - PreviousNumWords) * sizeof(uint32));
2357 }
2358 }
2359
2360public:
2361 // These should really be private, because they shouldn't be called, but there's a bunch of code
2362 // that needs to be fixed first.
2364 void operator=(const TScriptBitArray&) { check(false); }
2365};
2366
2367template <typename AllocatorType, typename InDerivedType>
2369{
2370 enum { Value = true };
2371};
2372
2373class FScriptBitArray : public TScriptBitArray<FDefaultBitArrayAllocator, FScriptBitArray>
2374{
2376
2377public:
2378 using Super::Super;
2379};
2380
2381template<typename Allocator>
2383{
2384 BitArray.Serialize(Ar);
2385 return Ar;
2386}
#define PLATFORM_LITTLE_ENDIAN
Definition AndroidPlatform.h:38
#define FORCENOINLINE
Definition AndroidPlatform.h:142
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
EBitwiseOperatorFlags
Definition BitArray.h:58
FArchive & operator<<(FArchive &Ar, TBitArray< Allocator > &BitArray)
Definition BitArray.h:2382
UE_FORCEINLINE_HINT uint32 GetTypeHash(const TBitArray< Allocator > &BitArray)
Definition BitArray.h:1928
#define NumBitsPerDWORD
Definition ContainerAllocationPolicies.h:1371
#define NumBitsPerDWORDLogTwo
Definition ContainerAllocationPolicies.h:1372
@ INDEX_NONE
Definition CoreMiscDefines.h:150
EConstEval
Definition CoreMiscDefines.h:161
@ ConstEval
Definition CoreMiscDefines.h:161
#define UE_LIFETIMEBOUND
Definition Platform.h:812
#define TEXT(x)
Definition Platform.h:1272
#define UE_ASSUME(x)
Definition Platform.h:833
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
#define RESTRICT
Definition Platform.h:706
AUTORTFM_INFER UE_FORCEINLINE_HINT constexpr auto Invoke(FuncType &&Func, ArgTypes &&... Args) -> decltype(((FuncType &&) Func)((ArgTypes &&) Args...))
Definition Invoke.h:44
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
constexpr bool EnumHasAnyFlags(Enum Flags, Enum Contains)
Definition EnumClassFlags.h:35
#define ENUM_CLASS_FLAGS(Enum)
Definition EnumClassFlags.h:6
return true
Definition ExternalRpcRegistry.cpp:601
constexpr uint32 GetNumWords(uint32 Num)
Definition FilePackageStore.cpp:474
FORCEINLINE uint32 ToIndex(FHairStrandsTiles::ETileType Type)
Definition HairStrandsData.h:93
void Init()
Definition LockFreeList.h:4
#define DECLARE_TEMPLATE_INTRINSIC_TYPE_LAYOUT(TemplatePrefix, T)
Definition MemoryLayout.h:661
const bool
Definition NetworkReplayStreaming.h:178
void Move(T &A, typename TMoveSupportTraits< T >::Copy B)
Definition UnrealTemplate.h:24
#define STRUCT_OFFSET(struc, member)
Definition UnrealTemplate.h:218
uint32 Offset
Definition VulkanMemory.cpp:4033
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
virtual void Serialize(void *V, int64 Length)
Definition Archive.h:1689
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
UE_FORCEINLINE_HINT bool IsObjectReferenceCollector() const
Definition Archive.h:456
virtual void CountBytes(SIZE_T InNum, SIZE_T InMax)
Definition Archive.h:125
UE_FORCEINLINE_HINT bool IsCountingMemory() const
Definition Archive.h:468
Definition BitArray.h:304
friend class FBitArrayMemoryTest
Definition BitArray.h:341
static CORE_API void MemmoveBitsWordOrder(uint32 *DestBits, int32 DestOffset, const uint32 *SourceBits, int32 SourceOffset, uint32 NumBits)
Definition BitArray.cpp:7
static void MemmoveBitsWordOrder(int32 *DestBits, int32 DestOffset, const int32 *SourceBits, int32 SourceOffset, uint32 NumBits)
Definition BitArray.h:319
static void ModularizeWordOffset(uint32 *&Data, int32 &Offset)
Definition BitArray.h:325
Definition BitArray.h:189
UE_FORCEINLINE_HINT FBitReference & operator=(const FBitReference &Copy)
Definition BitArray.h:244
UE_FORCEINLINE_HINT void operator&=(const bool NewValue)
Definition BitArray.h:219
UE_FORCEINLINE_HINT void AtomicSet(const bool NewValue)
Definition BitArray.h:226
UE_FORCEINLINE_HINT FBitReference(uint32 &InData UE_LIFETIMEBOUND, uint32 InMask)
Definition BitArray.h:192
UE_FORCEINLINE_HINT void operator|=(const bool NewValue)
Definition BitArray.h:212
UE_FORCEINLINE_HINT void operator=(const bool NewValue)
Definition BitArray.h:201
Definition BitArray.h:260
UE_FORCEINLINE_HINT FConstBitReference(const uint32 &InData UE_LIFETIMEBOUND, uint32 InMask)
Definition BitArray.h:263
Definition MemoryImageWriter.h:14
CORE_API uint32 WriteBytes(const void *Data, uint32 Size)
Definition MemoryImage.cpp:2143
bool Is32BitTarget() const
Definition MemoryImageWriter.h:26
Definition MemoryImage.h:49
Definition BitArray.h:281
UE_FORCEINLINE_HINT bool operator!=(FRelativeBitReference Other) const
Definition BitArray.h:297
int32 WordIndex
Definition BitArray.h:289
UE_FORCEINLINE_HINT FRelativeBitReference(int32 BitIndex)
Definition BitArray.h:283
UE_FORCEINLINE_HINT bool operator==(FRelativeBitReference Other) const
Definition BitArray.h:292
uint32 Mask
Definition BitArray.h:290
Definition SecureHash.h:314
Definition BitArray.h:2374
Definition BitArray.h:1609
UE_FORCEINLINE_HINT bool operator!() const
Definition BitArray.h:1641
UE_FORCEINLINE_HINT FConstIterator & operator++()
Definition BitArray.h:1617
UE_FORCEINLINE_HINT FConstBitReference GetValue() const
Definition BitArray.h:1646
UE_FORCEINLINE_HINT FConstIterator(const TBitArray< Allocator > &InArray UE_LIFETIMEBOUND, int32 StartIndex=0)
Definition BitArray.h:1611
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition BitArray.h:1647
UE_FORCEINLINE_HINT FConstBitReference operator*() const
Definition BitArray.h:1630
Definition BitArray.h:1655
UE_FORCEINLINE_HINT FConstBitReference GetValue() const
Definition BitArray.h:1698
UE_FORCEINLINE_HINT FConstReverseIterator(const TBitArray< Allocator > &InArray UE_LIFETIMEBOUND, int32 StartIndex)
Definition BitArray.h:1663
UE_FORCEINLINE_HINT FConstBitReference operator*() const
Definition BitArray.h:1682
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition BitArray.h:1699
UE_FORCEINLINE_HINT bool operator!() const
Definition BitArray.h:1693
UE_FORCEINLINE_HINT FConstReverseIterator(const TBitArray< Allocator > &InArray UE_LIFETIMEBOUND)
Definition BitArray.h:1657
UE_FORCEINLINE_HINT FConstReverseIterator & operator++()
Definition BitArray.h:1669
Definition BitArray.h:1507
UE_FORCEINLINE_HINT FBitReference operator*() const
Definition BitArray.h:1528
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition BitArray.h:1546
UE_FORCEINLINE_HINT FIterator(TBitArray< Allocator > &InArray UE_LIFETIMEBOUND, int32 StartIndex=0)
Definition BitArray.h:1509
UE_FORCEINLINE_HINT FIterator & operator++()
Definition BitArray.h:1515
UE_FORCEINLINE_HINT FBitReference GetValue() const
Definition BitArray.h:1545
UE_FORCEINLINE_HINT bool operator!() const
Definition BitArray.h:1540
Definition BitArray.h:1554
UE_FORCEINLINE_HINT FBitReference GetValue() const
Definition BitArray.h:1600
UE_FORCEINLINE_HINT FReverseIterator & operator++()
Definition BitArray.h:1570
UE_FORCEINLINE_HINT FBitReference operator*() const
Definition BitArray.h:1583
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition BitArray.h:1601
UE_FORCEINLINE_HINT FReverseIterator(TBitArray< Allocator > &InArray UE_LIFETIMEBOUND)
Definition BitArray.h:1556
UE_FORCEINLINE_HINT FReverseIterator(TBitArray< Allocator > &InArray UE_LIFETIMEBOUND, int32 StartIndex)
Definition BitArray.h:1563
UE_FORCEINLINE_HINT bool operator!() const
Definition BitArray.h:1595
Definition BitArray.h:350
UE_FORCEINLINE_HINT int32 Num() const
Definition BitArray.h:1466
UE_FORCEINLINE_HINT bool IsValidIndex(int32 InIndex) const
Definition BitArray.h:1450
static TBitArray BitwiseOR(const TBitArray< AllocatorA > &A, const TBitArray< AllocatorB > &B, EBitwiseOperatorFlags InFlags)
Definition BitArray.h:1321
int32 Add(const bool Value)
Definition BitArray.h:615
UE_FORCEINLINE_HINT const FConstBitReference AccessCorrespondingBit(const FRelativeBitReference &RelativeReference) const
Definition BitArray.h:1494
void CheckInvariants() const
Definition BitArray.h:565
static TBitArray BitwiseXOR(const TBitArray< AllocatorA > &A, const TBitArray< AllocatorB > &B, EBitwiseOperatorFlags InFlags)
Definition BitArray.h:1347
void SetRangeFromRange(int32 Index, int32 NumBitsToSet, const InWordType *ReadBits, int32 ReadOffsetBits=0)
Definition BitArray.h:954
UE_FORCEINLINE_HINT bool operator==(const TBitArray< Allocator > &Other) const
Definition BitArray.h:460
UE_FORCEINLINE_HINT int32 FindFrom(bool bValue, IndexType StartIndex) const
Definition BitArray.h:1176
UE_FORCEINLINE_HINT int32 FindFrom(bool bValue, IndexType StartIndex, IndexType EndIndexExclusive) const
Definition BitArray.h:1197
UE_FORCEINLINE_HINT FConstReverseIterator rend() const
Definition BitArray.h:1847
UE_FORCEINLINE_HINT TBitArray(TBitArray &&Other)
Definition BitArray.h:401
void Empty(int32 ExpectedNumBits=0)
Definition BitArray.h:779
UE_FORCEINLINE_HINT bool operator<(const TBitArray< Allocator > &Other) const
Definition BitArray.h:470
int32 AddRange(const InWordType *ReadBits, int32 NumBitsToAdd, int32 ReadOffsetBits=0)
Definition BitArray.h:647
TBitArray & CombineWithBitwiseAND(const TBitArray< OtherAllocator > &InOther, EBitwiseOperatorFlags InFlags)
Definition BitArray.h:1311
UE_FORCEINLINE_HINT FBitReference AccessCorrespondingBit(const FRelativeBitReference &RelativeReference)
Definition BitArray.h:1484
void BitwiseNOT()
Definition BitArray.h:1367
int32 Find(bool bValue) const
Definition BitArray.h:1084
UE_FORCEINLINE_HINT int32 Max() const
Definition BitArray.h:1467
int32 FindAndSetFirstZeroBit(int32 StartIndex=0)
Definition BitArray.h:1258
int32 FindAndSetLastZeroBit()
Definition BitArray.h:1275
void Serialize(FArchive &Ar)
Definition BitArray.h:587
int32 FindLast(bool bValue) const
Definition BitArray.h:1213
UE_FORCEINLINE_HINT FReverseIterator rbegin()
Definition BitArray.h:1844
UE_FORCEINLINE_HINT TBitArray & operator=(const TBitArray &Copy)
Definition BitArray.h:440
uint32 GetAllocatedSize(void) const
Definition BitArray.h:1062
void SetNumUninitialized(int32 InNumBits)
Definition BitArray.h:849
void InsertRange(const TBitArray< OtherAllocator > &ReadBits, int32 Index, int32 NumBitsToAdd, int32 ReadOffsetBits=0)
Definition BitArray.h:744
int32 AddRange(const TBitArray< OtherAllocator > &ReadBits, int32 NumBitsToAdd, int32 ReadOffsetBits=0)
Definition BitArray.h:662
UE_FORCEINLINE_HINT FReverseIterator rend()
Definition BitArray.h:1846
TBitArray & CombineWithBinaryOp(const TBitArray< OtherAllocator > &InOther, EBitwiseOperatorFlags InFlags, BinaryOpType &&InBinaryOp)
Definition BitArray.h:1301
void Reset()
Definition BitArray.h:817
int32 AddUninitialized(int32 NumBitsToAdd)
Definition BitArray.h:675
FORCENOINLINE void SetNum(int32 InNumBits, ValueType bValue)
Definition BitArray.h:870
UE_FORCEINLINE_HINT TBitArray(const TBitArray< OtherAllocator > &Copy)
Definition BitArray.h:417
int32 CountSetBits(int32 FromIndex=0, int32 ToIndex=INDEX_NONE) const
Definition BitArray.h:1378
UE_FORCEINLINE_HINT TBitArray(bool bValue, int32 InNumBits)
Definition BitArray.h:392
consteval TBitArray(EConstEval)
Definition BitArray.h:380
FORCENOINLINE void SetRange(int32 Index, int32 NumBitsToSet, bool Value)
Definition BitArray.h:887
int32 PadToNum(int32 DesiredNum, bool bPadValue)
Definition BitArray.h:1438
bool IsEmpty() const
Definition BitArray.h:1461
UE_FORCEINLINE_HINT TBitArray(const TBitArray &Copy)
Definition BitArray.h:409
Allocator::template ForElementType< uint32 > AllocatorType
Definition BitArray.h:365
UE_FORCEINLINE_HINT bool operator!=(const TBitArray< Allocator > &Other) const
Definition BitArray.h:494
UE_FORCEINLINE_HINT FConstReverseIterator rbegin() const
Definition BitArray.h:1845
void InsertUninitialized(int32 Index, int32 NumBitsToAdd)
Definition BitArray.h:757
UE_FORCEINLINE_HINT TBitArray & operator=(const TBitArray< OtherAllocator > &Copy)
Definition BitArray.h:452
TBitArray & CombineWithBitwiseOR(const TBitArray< OtherAllocator > &InOther, EBitwiseOperatorFlags InFlags)
Definition BitArray.h:1337
void Insert(bool Value, int32 Index)
Definition BitArray.h:703
void Insert(bool Value, int32 Index, int32 NumBitsToAdd)
Definition BitArray.h:715
void WriteMemoryImage(FMemoryImageWriter &Writer) const
Definition BitArray.h:1908
void RemoveAtSwap(int32 BaseIndex, int32 NumBitsToRemove=1)
Definition BitArray.h:1027
UE_FORCEINLINE_HINT FIterator end()
Definition BitArray.h:1841
UE_FORCEINLINE_HINT FConstIterator end() const
Definition BitArray.h:1842
constexpr TBitArray()
Definition BitArray.h:373
UE_FORCEINLINE_HINT const uint32 * GetData() const
Definition BitArray.h:1705
int32 Add(const bool Value, int32 NumBitsToAdd)
Definition BitArray.h:626
UE_FORCEINLINE_HINT void SetRangeFromRange(int32 Index, int32 NumBitsToSet, const TBitArray< OtherAllocator > &ReadBits, int32 ReadOffsetBits=0)
Definition BitArray.h:973
UE_FORCEINLINE_HINT bool Contains(bool bValue) const
Definition BitArray.h:1245
int32 FindLastFrom(bool bValue, IndexType EndIndexInclusive) const
Definition BitArray.h:1228
UE_FORCEINLINE_HINT void GetRange(int32 Index, int32 NumBitsToGet, InWordType *WriteBits, int32 WriteOffsetBits=0) const
Definition BitArray.h:989
UE_FORCEINLINE_HINT void Init(bool bValue, int32 InNumBits)
Definition BitArray.h:828
UE_FORCEINLINE_HINT TBitArray & operator=(TBitArray &&Other)
Definition BitArray.h:427
UE_FORCEINLINE_HINT FConstIterator begin() const
Definition BitArray.h:1840
UE_FORCEINLINE_HINT FIterator begin()
Definition BitArray.h:1839
UE_FORCEINLINE_HINT FBitReference operator[](int32 Index)
Definition BitArray.h:1468
void Reserve(int32 Number)
Definition BitArray.h:800
void InsertRange(const InWordType *ReadBits, int32 Index, int32 NumBitsToAdd, int32 ReadOffsetBits=0)
Definition BitArray.h:730
static TBitArray BitwiseAND(const TBitArray< AllocatorA > &A, const TBitArray< AllocatorB > &B, EBitwiseOperatorFlags InFlags)
Definition BitArray.h:1290
void CountBytes(FArchive &Ar) const
Definition BitArray.h:1068
UE_FORCEINLINE_HINT const FConstBitReference operator[](int32 Index) const
Definition BitArray.h:1476
bool CompareSetBits(const TBitArray< OtherAllocator > &Other, const bool bMissingBitValue) const
Definition BitArray.h:1405
void RemoveAt(int32 BaseIndex, int32 NumBitsToRemove=1)
Definition BitArray.h:1004
UE_FORCEINLINE_HINT uint32 * GetData()
Definition BitArray.h:1710
TBitArray & CombineWithBitwiseXOR(const TBitArray< OtherAllocator > &InOther, EBitwiseOperatorFlags InFlags)
Definition BitArray.h:1358
Definition BitArray.h:2072
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition BitArray.h:2120
UE_FORCEINLINE_HINT bool operator!() const
Definition BitArray.h:2114
UE_FORCEINLINE_HINT TConstDualSetBitIterator & operator++()
Definition BitArray.h:2094
UE_FORCEINLINE_HINT TConstDualSetBitIterator(const TBitArray< Allocator > &InArrayA, const TBitArray< OtherAllocator > &InArrayB, int32 StartIndex=0)
Definition BitArray.h:2076
Definition BitArray.h:1944
UE_FORCEINLINE_HINT bool operator==(const TConstSetBitIterator &Rhs) const
Definition BitArray.h:1986
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition BitArray.h:2011
TConstSetBitIterator(const TBitArray< Allocator > &InArray UE_LIFETIMEBOUND, int32 StartIndex)
Definition BitArray.h:1960
TConstSetBitIterator(const TBitArray< Allocator > &InArray UE_LIFETIMEBOUND)
Definition BitArray.h:1947
UE_FORCEINLINE_HINT TConstSetBitIterator & operator++()
Definition BitArray.h:1975
UE_FORCEINLINE_HINT bool operator!() const
Definition BitArray.h:2005
UE_FORCEINLINE_HINT bool operator!=(const TConstSetBitIterator &Rhs) const
Definition BitArray.h:1993
Definition BitArray.h:2216
FBitReference operator[](int32 Index)
Definition BitArray.h:2236
void MoveAssign(DerivedType &Other)
Definition BitArray.h:2248
TScriptBitArray()
Definition BitArray.h:2225
int32 Add(const bool Value)
Definition BitArray.h:2270
void Empty(int32 Slack=0)
Definition BitArray.h:2257
FConstBitReference operator[](int32 Index) const
Definition BitArray.h:2242
void operator=(const TScriptBitArray &)
Definition BitArray.h:2364
bool IsValidIndex(int32 Index) const
Definition BitArray.h:2231
TScriptBitArray(const TScriptBitArray &)
Definition BitArray.h:2363
GeometryCollection::Facades::FMuscleActivationData Data
Definition MuscleActivationConstraints.h:15
@ Bits
Definition PacketView.h:34
@ NumBits
Definition MeshPassProcessor.h:87
const Type Shift
Definition GenericApplication.h:43
Definition Array.h:3955
UE_NODEBUG void IntrinsicWriteMemoryImage(FMemoryImageWriter &Writer, const TArray< T, AllocatorType > &Object, const FTypeLayoutDesc &)
Definition Array.h:3957
Definition TestUtils.cpp:8
implementation
Definition PlayInEditorLoadingScope.h:8
void BitwiseOperatorImpl(const TBitArray< OtherAllocator > &InOther, TBitArray< OutAllocator > &OutResult, EBitwiseOperatorFlags InFlags, ProjectionType &&InProjection)
Definition BitArray.h:139
void BitwiseBinaryOperatorImpl(const TBitArray< AllocatorA > &InA, const TBitArray< AllocatorB > &InB, TBitArray< OutAllocator > &OutResult, EBitwiseOperatorFlags InFlags, ProjectionType &&InProjection)
Definition BitArray.h:74
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732
U16 Index
Definition radfft.cpp:71
Definition BitArray.h:26
static constexpr uint32 BitsPerWord
Definition BitArray.h:37
static UE_FORCEINLINE_HINT uint32 CalculateNumWords(int32 NumBits)
Definition BitArray.h:39
static UE_FORCEINLINE_HINT uint32 GetAndClearNextBit(uint32 &Mask)
Definition BitArray.h:28
Definition UnrealMathUtility.h:270
static constexpr UE_FORCEINLINE_HINT T DivideAndRoundUp(T Dividend, T Divisor)
Definition UnrealMathUtility.h:694
static constexpr UE_FORCEINLINE_HINT T DivideAndRoundDown(T Dividend, T Divisor)
Definition UnrealMathUtility.h:701
static UE_FORCEINLINE_HINT void * Memzero(void *Dest, SIZE_T Count)
Definition UnrealMemory.h:131
static UE_FORCEINLINE_HINT int32 Memcmp(const void *Buf1, const void *Buf2, SIZE_T Count)
Definition UnrealMemory.h:114
static UE_FORCEINLINE_HINT void * Memcpy(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:160
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition UnrealMemory.h:119
Definition MemoryLayout.h:108
Definition ContainerAllocationPolicies.h:256
Definition BitArray.h:1800
FConstWordIterator(const TBitArray< Allocator > &InArray UE_LIFETIMEBOUND, int32 InStartBitIndex, int32 InEndBitIndex)
Definition BitArray.h:1806
FConstWordIterator(const TBitArray< Allocator > &InArray UE_LIFETIMEBOUND)
Definition BitArray.h:1801
Definition BitArray.h:1816
FWordIterator(TBitArray< Allocator > &InArray UE_LIFETIMEBOUND)
Definition BitArray.h:1817
void SetWord(uint32 InWord)
Definition BitArray.h:1822
Definition UnrealTypeTraits.h:172