UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
SparseArray.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7#include "HAL/UnrealMemory.h"
11#include "Templates/Less.h"
12#include "Containers/Array.h"
15#include "Containers/BitArray.h"
21#include <initializer_list>
22
23#if UE_BUILD_SHIPPING || UE_BUILD_TEST
24 #define TSPARSEARRAY_RANGED_FOR_CHECKS 0
25#else
26 #define TSPARSEARRAY_RANGED_FOR_CHECKS 1
27#endif
28
35
36// Forward declarations.
37template<typename ElementType,typename Allocator = FDefaultSparseArrayAllocator >
38class TSparseArray;
39
40template <typename T, typename Allocator> void* operator new(size_t Size, TSparseArray<T, Allocator>& Array);
41template <typename T, typename Allocator> void* operator new(size_t Size, TSparseArray<T, Allocator>& Array, int32 Index);
42inline void* operator new(size_t Size, const FSparseArrayAllocationInfo& Allocation);
43
45template<typename ElementType>
47{
49 ElementType ElementData;
50
51 struct
52 {
55
58 };
59};
60
62
63template<size_t SizeOfElementType, size_t AlignOfElementType, typename Allocator>
65{
66protected:
71
74 : FirstFreeIndex(-1)
76 {
77 }
78
80 [[nodiscard]] explicit consteval TSparseArrayBase(EConstEval)
83 , FirstFreeIndex(-1)
85 {
86 }
87
94
97 {
98 check(Index >= 0);
101
102 // Flag the element as allocated.
103 AllocationFlags[Index] = true;
104
105 // Set the allocation info.
107 Result.Index = Index;
108 Result.Pointer = &((FElementOrFreeListLink*)Data.GetData())[Result.Index].ElementData;
109
110 return Result;
111 }
112
118 {
119 int32 Index;
121 {
123
124 // Remove and use the first index from the list of free elements.
129 {
130 DataPtr[FirstFreeIndex].PrevFreeIndex = -1;
131 }
132 }
133 else
134 {
135 // Add a new element.
137 AllocationFlags.Add(false);
138 }
139
140 return AllocateIndex(Index);
141 }
142
144 {
145 FElementOrFreeListLink* DataPtr;
146
147 int32 Index;
149 {
150 Index = AllocationFlags.FindAndSetFirstZeroBit(LowestFreeIndexSearchStart);
151 LowestFreeIndexSearchStart = Index + 1;
152
153 DataPtr = (FElementOrFreeListLink*)Data.GetData();
154
155 // Update FirstFreeIndex
156 if (FirstFreeIndex == Index)
157 {
159 }
160
161 // Link our next and prev free nodes together
162 if (DataPtr[Index].NextFreeIndex >= 0)
163 {
164 DataPtr[DataPtr[Index].NextFreeIndex].PrevFreeIndex = DataPtr[Index].PrevFreeIndex;
165 }
166
167 if (DataPtr[Index].PrevFreeIndex >= 0)
168 {
169 DataPtr[DataPtr[Index].PrevFreeIndex].NextFreeIndex = DataPtr[Index].NextFreeIndex;
170 }
171
173 }
174 else
175 {
176 // Add a new element.
178 AllocationFlags.Add(true);
179
180 // Defer getting the data pointer until after a possible reallocation
181 DataPtr = (FElementOrFreeListLink*)Data.GetData();
182 }
183
185 Result.Index = Index;
186 Result.Pointer = &DataPtr[Result.Index].ElementData;
187 return Result;
188 }
189
192 {
194
195 for (; Count; --Count)
196 {
198
199 // Mark the element as free and add it to the free element list.
201 {
203 }
204 DataPtr[Index].PrevFreeIndex = -1;
208 AllocationFlags[Index] = false;
209
210 ++Index;
211 }
212 }
213
220 {
222 {
224
225 // allocate memory in the array itself - reserve first to ensure that resizing-for-growth doesn't occur
228
230
231 // now mark the new elements as free
232 for (int32 FreeIndex = ExpectedNumElements - 1; FreeIndex >= ElementIndex; --FreeIndex)
233 {
234 if (NumFreeIndices)
235 {
237 }
238 DataPtr[FreeIndex].PrevFreeIndex = -1;
242 }
243
245 {
247 }
248 else
249 {
251 }
252 }
253 }
254
256 void Shrink()
257 {
258 // Determine the highest allocated index in the data array.
260
263 {
264 if (NumFreeIndices > 0)
265 {
267
268 // Look for elements in the free list that are in the memory to be freed.
270 while (FreeIndex != INDEX_NONE)
271 {
273 {
274 const int32 PrevFreeIndex = DataPtr[FreeIndex].PrevFreeIndex;
275 const int32 NextFreeIndex = DataPtr[FreeIndex].NextFreeIndex;
276 if (NextFreeIndex != -1)
277 {
278 DataPtr[NextFreeIndex].PrevFreeIndex = PrevFreeIndex;
279 }
280 if (PrevFreeIndex != -1)
281 {
282 DataPtr[PrevFreeIndex].NextFreeIndex = NextFreeIndex;
283 }
284 else
285 {
286 FirstFreeIndex = NextFreeIndex;
287 }
289
290 FreeIndex = NextFreeIndex;
291 }
292 else
293 {
295 }
296 }
297 }
298
299 // Truncate unallocated elements at the end of the data array.
302 }
303
304 // Shrink the data array.
305 Data.Shrink();
306 }
307
323 {
327
328 // Reverse iteration to build the list from low to high indices
330 {
331 // If we have an unused element, add it to the free list
332 if (!IsValidIndex(Index))
333 {
334 DataPtr[Index].PrevFreeIndex = INDEX_NONE;
335 DataPtr[Index].NextFreeIndex = INDEX_NONE;
336
338 {
341 }
342
345 }
346 }
347
348 // Set up the new head
350 }
351
357 {
358 FElementOrFreeListLink* DataPtr;
359
360 // Enlarge the array to include the given index.
361 if (Index >= Data.Num())
362 {
364
365 // Defer getting the data pointer until after a possible reallocation
366 DataPtr = (FElementOrFreeListLink*)Data.GetData();
367
368 while (AllocationFlags.Num() < Data.Num())
369 {
371 DataPtr[FreeIndex].PrevFreeIndex = -1;
373 if (NumFreeIndices)
374 {
376 }
380 };
381 }
382 else
383 {
384 DataPtr = (FElementOrFreeListLink*)Data.GetData();
385 }
386
387 // Verify that the specified index is free.
389
390 // Remove the index from the list of free elements.
392 const int32 PrevFreeIndex = DataPtr[Index].PrevFreeIndex;
393 const int32 NextFreeIndex = DataPtr[Index].NextFreeIndex;
394 if (PrevFreeIndex != -1)
395 {
396 DataPtr[PrevFreeIndex].NextFreeIndex = NextFreeIndex;
397 }
398 else
399 {
400 FirstFreeIndex = NextFreeIndex;
401 }
402 if (NextFreeIndex != -1)
403 {
404 DataPtr[NextFreeIndex].PrevFreeIndex = PrevFreeIndex;
405 }
406
407 return AllocateIndex(Index);
408 }
409
412 bool Compact()
413 {
414 int32 NumFree = NumFreeIndices;
415 if (NumFree == 0)
416 {
417 return false;
418 }
419
420 bool bResult = false;
421
423
424 int32 EndIndex = Data.Num();
425 int32 TargetIndex = EndIndex - NumFree;
427 while (FreeIndex != -1)
428 {
429 int32 NextFreeIndex = DataPtr[FreeIndex].NextFreeIndex;
430 if (FreeIndex < TargetIndex)
431 {
432 // We need an element here
433 do
434 {
435 --EndIndex;
436 }
437 while (!AllocationFlags[EndIndex]);
438
439 RelocateConstructItems<FElementOrFreeListLink>(DataPtr + FreeIndex, DataPtr + EndIndex, 1);
441
442 bResult = true;
443 }
444
445 FreeIndex = NextFreeIndex;
446 }
447
448 Data.RemoveAt(TargetIndex, NumFree, EAllowShrinking::No);
449 AllocationFlags.RemoveAt(TargetIndex, NumFree);
450
451 NumFreeIndices = 0;
452 FirstFreeIndex = -1;
453
454 // Shrink the data array.
455 Data.Shrink();
456
457 return bResult;
458 }
459
461 {
462 return Data.Num();
463 }
464
465 [[nodiscard]] bool IsEmpty() const
466 {
467 return Data.Num() == NumFreeIndices;
468 }
469
470 [[nodiscard]] int32 Num() const
471 {
472 return Data.Num() - NumFreeIndices;
473 }
474
476 [[nodiscard]] int32 Max() const
477 {
478 return Data.Max();
479 }
480
485
487 {
488 return AllocationFlags[Index];
489 }
490
498
501
504
507
510};
511
512template <typename AllocatorType, typename InDerivedType = void>
514
522template<typename InElementType, typename Allocator /*= FDefaultSparseArrayAllocator */>
523class TSparseArray : public TSparseArrayBase<sizeof(InElementType), alignof(InElementType), Allocator>
524{
526 using ElementType = InElementType;
527
528 template <typename, typename>
529 friend class TScriptSparseArray;
530
531public:
534 {
535 UE_STATIC_ASSERT_WARN(TIsTriviallyRelocatable_V<InElementType>, "TArray can only be used with trivially relocatable types");
536
537 // Destruct the elements in the array.
538 Empty();
539 }
540
542 // Start - intrusive TOptional<TSparseArray> state //
544 constexpr static bool bHasIntrusiveUnsetOptionalState = true;
546
551
553 {
554 return Data == Tag;
555 }
557 // End - intrusive TOptional<TSparseArray> state //
559
562
564 int32 Add(const ElementType& Element)
565 {
567 new(Allocation) ElementType(Element);
568 return Allocation.Index;
569 }
570
572 int32 Add(ElementType&& Element)
573 {
575 new(Allocation) ElementType(MoveTemp(Element));
576 return Allocation.Index;
577 }
578
580
587 template <typename... ArgsType>
588 inline int32 Emplace(ArgsType&&... Args)
589 {
591 new(Allocation) ElementType(Forward<ArgsType>(Args)...);
592 return Allocation.Index;
593 }
594
603 template <typename... ArgsType>
604 inline int32 EmplaceAtLowestFreeIndex(int32& LowestFreeIndexSearchStart, ArgsType&&... Args)
605 {
606 FSparseArrayAllocationInfo Allocation = AddUninitializedAtLowestFreeIndex(LowestFreeIndexSearchStart);
607 new(Allocation) ElementType(Forward<ArgsType>(Args)...);
608 return Allocation.Index;
609 }
610
618 template <typename... ArgsType>
619 inline int32 EmplaceAt(int32 Index, ArgsType&&... Args)
620 {
623 {
624 Allocation = InsertUninitialized(Index);
625 }
626 else
627 {
628 FElementOrFreeListLink* Elem = (FElementOrFreeListLink*)Data.GetData() + Index;
629 ((ElementType&)Elem->ElementData).~ElementType();
630
631 Allocation.Index = Index;
632 Allocation.Pointer = &Elem->ElementData;
633 }
634
635 new(Allocation) ElementType(Forward<ArgsType>(Args)...);
636 return Allocation.Index;
637 }
638
640
645 {
646 new(InsertUninitialized(Index)) ElementType(Element);
647 }
648
651 {
652 if constexpr (!std::is_trivially_destructible_v<ElementType>)
653 {
654 DestroyElements(Index, Count);
655 }
656
658 }
659
661
667 {
668 // Destruct the allocated elements.
669 if constexpr (!std::is_trivially_destructible_v<ElementType>)
670 {
671 DestroyElements();
672 }
673
674 // Free the allocated elements.
676 FirstFreeIndex = -1;
677 NumFreeIndices = 0;
679 }
680
682 void Reset()
683 {
684 // Destruct the allocated elements.
685 if constexpr (!std::is_trivially_destructible_v<ElementType>)
686 {
687 DestroyElements();
688 }
689
690 // Free the allocated elements.
691 Data.Reset();
692 FirstFreeIndex = -1;
693 NumFreeIndices = 0;
695 }
696
697 using SuperType::Reserve;
698 using SuperType::Shrink;
699 using SuperType::Compact;
700
704 {
705 if (NumFreeIndices == 0)
706 {
707 return false;
708 }
709
710 // Copy the existing elements to a new array.
713 for(TIterator It(*this);It;++It)
714 {
715 new(CompactedArray.AddUninitialized()) ElementType(MoveTempIfPossible(*It));
716 }
717
718 // Replace this array with the compacted array.
720
721 return true;
722 }
723
725 template<typename PREDICATE_CLASS>
726 void Sort( const PREDICATE_CLASS& Predicate )
727 {
728 if(Num() > 0)
729 {
730 // Compact the elements array so all the elements are contiguous.
731 Compact();
732
733 // Sort the elements according to the provided comparison class.
735 }
736 }
737
739 void Sort()
740 {
742 }
743
745 template<typename PREDICATE_CLASS>
746 void StableSort(const PREDICATE_CLASS& Predicate)
747 {
748 if (Num() > 0)
749 {
750 // Compact the elements array so all the elements are contiguous.
752
753 // Sort the elements according to the provided comparison class.
755 }
756 }
757
760 {
762 }
763
765
772 template <typename Predicate>
774 {
775 for (TConstIterator It = CreateConstIterator(); It; ++It)
776 {
777 if (::Invoke(Pred, *It))
778 {
779 return It.GetIndex();
780 }
781 }
782
783 return INDEX_NONE;
784 }
785
792 {
793 // The goal of this function is to be fast, and so the implementation may be improved at any time even if it gives different results.
794
795 if (NumFreeIndices == 0)
796 {
797 return Data.Num() - 1; // this will return INDEX_NONE if Data is empty.
798 }
799
800 return AllocationFlags.Find(true);
801 }
802
812
814 void CountBytes(FArchive& Ar) const
815 {
816 Data.CountBytes(Ar);
818 }
819
820 [[nodiscard]] bool IsCompact() const
821 {
822 return NumFreeIndices == 0;
823 }
824
829 [[nodiscard]] bool operator==(const TSparseArray& B) const
830 {
831 if (GetMaxIndex() != B.GetMaxIndex())
832 {
833 return false;
834 }
835
836 for (int32 ElementIndex = 0; ElementIndex < GetMaxIndex(); ElementIndex++)
837 {
838 const bool bIsAllocatedA = IsAllocated(ElementIndex);
839 const bool bIsAllocatedB = B.IsAllocated(ElementIndex);
841 {
842 return false;
843 }
844 else if (bIsAllocatedA)
845 {
846 if ((*this)[ElementIndex] != B[ElementIndex])
847 {
848 return false;
849 }
850 }
851 }
852
853 return true;
854 }
855
860 [[nodiscard]] bool operator!=(const TSparseArray& B) const
861 {
862 return !(*this == B);
863 }
864
866 [[nodiscard]] constexpr TSparseArray() = default;
867
868 [[nodiscard]] explicit consteval TSparseArray(EConstEval)
870 {
871 }
872
875 {
876 this->Move(*this, InCopy);
877 }
878
882 {
883 *this = InCopy;
884 }
885
887 [[nodiscard]] TSparseArray(std::initializer_list<ElementType> InList)
888 : SuperType()
889 {
890 *this = InList;
891 }
892
895 {
896 if(this != &InCopy)
897 {
898 this->Move(*this, InCopy);
899 }
900 return *this;
901 }
902
905 {
906 if (this != &InCopy)
907 {
909
910 // Reallocate the array.
911 Empty(SrcMax);
913
914 // Copy the other array's element allocation state.
915 FirstFreeIndex = InCopy.FirstFreeIndex;
916 NumFreeIndices = InCopy.NumFreeIndices;
917 AllocationFlags = InCopy.AllocationFlags;
918
919 FElementOrFreeListLink* DestData = ( FElementOrFreeListLink*)Data.GetData();
920 const FElementOrFreeListLink* SrcData = (const FElementOrFreeListLink*)InCopy.Data.GetData();
921
922 // Determine whether we need per element construction or bulk copy is fine
923 if constexpr (!std::is_trivially_copy_constructible_v<ElementType>)
924 {
925 // Use the inplace new to copy the element to an array element
926 for (int32 Index = 0; Index < SrcMax; ++Index)
927 {
928 FElementOrFreeListLink& DestElement = DestData[Index];
929 const FElementOrFreeListLink& SrcElement = SrcData [Index];
930 if (InCopy.IsAllocated(Index))
931 {
932 ::new((uint8*)&DestElement.ElementData) ElementType(*(const ElementType*)&SrcElement.ElementData);
933 }
934 else
935 {
936 DestElement.PrevFreeIndex = SrcElement.PrevFreeIndex;
937 DestElement.NextFreeIndex = SrcElement.NextFreeIndex;
938 }
939 }
940 }
941 else
942 {
943 if (SrcMax)
944 {
945 // Use the much faster path for types that allow it
946 FMemory::Memcpy(DestData, SrcData, sizeof(FElementOrFreeListLink) * SrcMax);
947 }
948 }
949 }
950 return *this;
951 }
952
954 TSparseArray& operator=(std::initializer_list<ElementType> InList)
955 {
956 this->Reset();
957 this->Reserve((uint32)InList.size());
958 for (const ElementType& Element : InList)
959 {
960 Add(Element);
961 }
962 return *this;
963 }
964
965private:
966 template <typename SparseArrayType>
967 inline static void Move(SparseArrayType& ToArray, SparseArrayType& FromArray)
968 {
969 // Destruct the allocated elements.
970 if constexpr (!std::is_trivially_destructible_v<ElementType>)
971 {
972 ToArray.DestroyElements();
973 }
974
975 ToArray.Data = (DataType&&)FromArray.Data;
976 ToArray.AllocationFlags = (AllocationBitArrayType&&)FromArray.AllocationFlags;
977
978 ToArray.FirstFreeIndex = FromArray.FirstFreeIndex;
979 ToArray.NumFreeIndices = FromArray.NumFreeIndices;
980 FromArray.FirstFreeIndex = -1;
981 FromArray.NumFreeIndices = 0;
982 }
983
984 FORCEINLINE void DestroyElements()
985 {
986 DestroyElements(0, Data.Num());
987 }
988
989 FORCENOINLINE void DestroyElements(int32 Index, int32 Count)
990 {
991 const int32 EndIndex = Index + Count;
992 FElementOrFreeListLink* DataPtr = (FElementOrFreeListLink*)Data.GetData();
993 for (int32 i = Index; i < EndIndex; ++i)
994 {
995 if (IsValidIndex(i))
996 {
997 ((ElementType&)DataPtr[i].ElementData).~ElementType();
998 }
999 }
1000 }
1001
1002public:
1003 // Accessors.
1005 {
1006 checkSlow(Index >= 0 && Index < Data.Num() && Index < AllocationFlags.Num());
1007 //checkSlow(AllocationFlags[Index]); // Disabled to improve loading times -BZ
1008 return *(ElementType*)&((FElementOrFreeListLink*)Data.GetData())[Index].ElementData;
1009 }
1010 [[nodiscard]] const ElementType& operator[](int32 Index) const
1011 {
1012 checkSlow(Index >= 0 && Index < Data.Num() && Index < AllocationFlags.Num());
1013 //checkSlow(AllocationFlags[Index]); // Disabled to improve loading times -BZ
1014 return *(ElementType*)&((FElementOrFreeListLink*)Data.GetData())[Index].ElementData;
1015 }
1016 [[nodiscard]] int32 PointerToIndex(const ElementType* Ptr) const
1017 {
1018 checkSlow(Data.Num());
1019 int32 Index = (int32)((FElementOrFreeListLink*)Ptr - (FElementOrFreeListLink*)Data.GetData());
1021 return Index;
1022 }
1026 using SuperType::IsEmpty;
1027 using SuperType::Num;
1028 using SuperType::Max;
1029
1036 UE_FORCEINLINE_HINT void CheckAddress(const ElementType* Addr) const
1037 {
1038 Data.CheckAddress(Addr);
1039 }
1040
1041private:
1042
1044 template<bool bConst>
1045 class TBaseIterator
1046 {
1047 public:
1049
1050 private:
1051 typedef std::conditional_t<bConst,const TSparseArray,TSparseArray> ArrayType;
1052 typedef std::conditional_t<bConst,const ElementType,ElementType> ItElementType;
1053
1054 public:
1055 [[nodiscard]] explicit TBaseIterator(ArrayType& InArray, const BitArrayItType& InBitArrayIt)
1056 : Array (InArray)
1057 , BitArrayIt(InBitArrayIt)
1058 {
1059 }
1060
1061 inline TBaseIterator& operator++()
1062 {
1063 // Iterate to the next set allocation flag.
1064 ++BitArrayIt;
1065 return *this;
1066 }
1067
1068 [[nodiscard]] UE_FORCEINLINE_HINT int32 GetIndex() const
1069 {
1070 return BitArrayIt.GetIndex();
1071 }
1072
1073 [[nodiscard]] UE_FORCEINLINE_HINT bool operator==(const TBaseIterator& Rhs) const
1074 {
1075 return BitArrayIt == Rhs.BitArrayIt && &Array == &Rhs.Array;
1076 }
1077 [[nodiscard]] UE_FORCEINLINE_HINT bool operator!=(const TBaseIterator& Rhs) const
1078 {
1079 return BitArrayIt != Rhs.BitArrayIt || &Array != &Rhs.Array;
1080 }
1081
1083 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
1084 {
1085 return !!BitArrayIt;
1086 }
1087
1089 [[nodiscard]] UE_FORCEINLINE_HINT bool operator !() const
1090 {
1091 return !(bool)*this;
1092 }
1093
1094 [[nodiscard]] UE_FORCEINLINE_HINT ItElementType& operator*() const
1095 {
1096 return Array[GetIndex()];
1097 }
1098 [[nodiscard]] UE_FORCEINLINE_HINT ItElementType* operator->() const
1099 {
1100 return &Array[GetIndex()];
1101 }
1102 [[nodiscard]] UE_FORCEINLINE_HINT const FRelativeBitReference& GetRelativeBitReference() const
1103 {
1104 return BitArrayIt;
1105 }
1106
1107 protected:
1108 ArrayType& Array;
1109 BitArrayItType BitArrayIt;
1110 };
1111
1112public:
1113
1115 class TIterator : public TBaseIterator<false>
1116 {
1117 public:
1119 : TBaseIterator<false>(InArray, TConstSetBitIterator<typename Allocator::BitArrayAllocator>(InArray.AllocationFlags))
1120 {
1121 }
1122
1127
1130 {
1131 this->Array.RemoveAt(this->GetIndex());
1132 }
1133 };
1134
1136 class TConstIterator : public TBaseIterator<true>
1137 {
1138 public:
1140 : TBaseIterator<true>(InArray, TConstSetBitIterator<typename Allocator::BitArrayAllocator>(InArray.AllocationFlags))
1141 {
1142 }
1143
1148 };
1149
1150 #if TSPARSEARRAY_RANGED_FOR_CHECKS
1152 {
1153 public:
1159
1160 [[nodiscard]] inline bool operator!=(const TRangedForIterator& Rhs) const
1161 {
1162 // We only need to do the check in this operator, because no other operator will be
1163 // called until after this one returns.
1164 //
1165 // Also, we should only need to check one side of this comparison - if the other iterator isn't
1166 // even from the same array then the compiler has generated bad code.
1167 ensureMsgf(this->Array.Num() == InitialNum, TEXT("Container has changed during ranged-for iteration!"));
1168 return *(TIterator*)this != *(TIterator*)&Rhs;
1169 }
1170 private:
1171 int32 InitialNum;
1172 };
1173
1175 {
1176 public:
1182
1183 [[nodiscard]] inline bool operator!=(const TRangedForConstIterator& Rhs) const
1184 {
1185 // We only need to do the check in this operator, because no other operator will be
1186 // called until after this one returns.
1187 //
1188 // Also, we should only need to check one side of this comparison - if the other iterator isn't
1189 // even from the same array then the compiler has generated bad code.
1190 ensureMsgf(this->Array.Num() == InitialNum, TEXT("Container has changed during ranged-for iteration!"));
1191 return *(TIterator*)this != *(TIterator*)&Rhs;
1192 }
1193 private:
1194 int32 InitialNum;
1195 };
1196 #else
1197 using TRangedForIterator = TIterator;
1198 using TRangedForConstIterator = TConstIterator;
1199 #endif
1200
1203 {
1204 return TIterator(*this);
1205 }
1206
1209 {
1210 return TConstIterator(*this);
1211 }
1212
1213public:
1222
1223public:
1225 template<typename SubsetAllocator = FDefaultBitArrayAllocator>
1227 {
1228 public:
1235 {
1236 // Iterate to the next element which is both allocated and has its bit set in the other bit array.
1237 ++BitArrayIt;
1238 return *this;
1239 }
1241 {
1242 return BitArrayIt.GetIndex();
1243 }
1244
1246 [[nodiscard]] UE_FORCEINLINE_HINT explicit operator bool() const
1247 {
1248 return !!BitArrayIt;
1249 }
1252 {
1253 return !(bool)*this;
1254 }
1255
1256 [[nodiscard]] UE_FORCEINLINE_HINT const ElementType& operator*() const
1257 {
1258 return Array[GetIndex()];
1259 }
1260 [[nodiscard]] UE_FORCEINLINE_HINT const ElementType* operator->() const
1261 {
1262 return &Array[GetIndex()];
1263 }
1265 {
1266 return BitArrayIt;
1267 }
1268 private:
1269 const TSparseArray& Array;
1271 };
1272
1275 {
1276 this->Reserve(this->Num() + OtherArray.Num());
1277 for ( typename TSparseArray::TConstIterator It(OtherArray); It; ++It )
1278 {
1279 this->Add(*It);
1280 }
1281 return *this;
1282 }
1284 {
1285 this->Reserve(this->Num() + OtherArray.Num());
1286 for ( int32 Idx = 0; Idx < OtherArray.Num(); Idx++ )
1287 {
1288 this->Add(OtherArray[Idx]);
1289 }
1290 return *this;
1291 }
1292
1293private:
1294
1295 using FElementOrFreeListLink = typename SuperType::FElementOrFreeListLink;
1296
1298 template <typename PREDICATE_CLASS>
1299 class FElementCompareClass
1300 {
1301 const PREDICATE_CLASS& Predicate;
1302
1303 public:
1304 [[nodiscard]] FElementCompareClass( const PREDICATE_CLASS& InPredicate )
1305 : Predicate( InPredicate )
1306 {
1307 }
1308
1309 [[nodiscard]] bool operator()( const FElementOrFreeListLink& A,const FElementOrFreeListLink& B ) const
1310 {
1311 return Predicate(*(ElementType*)&A.ElementData,*(ElementType*)&B.ElementData);
1312 }
1313 };
1314
1317
1318 using SuperType::Data;
1322
1323public:
1325 {
1326 checkf(!Writer.Is32BitTarget(), TEXT("TSparseArray does not currently support freezing for 32bits"));
1328 {
1329 // Write Data
1330 const int32 NumElements = this->Data.Num();
1331 if (NumElements > 0)
1332 {
1335 for (int32 i = 0; i < NumElements; ++i)
1336 {
1337 const FElementOrFreeListLink& Elem = ((const FElementOrFreeListLink*)this->Data.GetData())[i];
1338 const uint32 StartOffset = ArrayWriter.WriteAlignment<FElementOrFreeListLink>();
1339 if (this->AllocationFlags[i])
1340 {
1341 ArrayWriter.WriteObject(&Elem.ElementData, ElementTypeDesc);
1342 }
1343 else
1344 {
1345 ArrayWriter.WriteBytes(Elem.PrevFreeIndex);
1346 ArrayWriter.WriteBytes(Elem.NextFreeIndex);
1347 }
1348 ArrayWriter.WritePaddingToSize(StartOffset + sizeof(FElementOrFreeListLink));
1349 }
1350 }
1351 else
1352 {
1353 Writer.WriteNullPointer();
1354 }
1355 Writer.WriteBytes(NumElements);
1356 Writer.WriteBytes(NumElements);
1357
1358 //
1359 this->AllocationFlags.WriteMemoryImage(Writer);
1360 Writer.WriteBytes(this->FirstFreeIndex);
1361 Writer.WriteBytes(this->NumFreeIndices);
1362 }
1363 else
1364 {
1365 Writer.WriteBytes(TSparseArray());
1366 }
1367 }
1368
1369 void CopyUnfrozen(const FMemoryUnfreezeContent& Context, void* Dst) const
1370 {
1372 {
1375 {
1376 ::new((void*)&DstObject->Data) DataType();
1377 DstObject->Data.SetNumUninitialized(this->Data.Num());
1378 for (int32 i = 0; i < this->Data.Num(); ++i)
1379 {
1380 const FElementOrFreeListLink& Elem = ((const FElementOrFreeListLink*)this ->Data.GetData())[i];
1381 FElementOrFreeListLink& DstElem = (( FElementOrFreeListLink*)DstObject->Data.GetData())[i];
1382 if (this->AllocationFlags[i])
1383 {
1384 Context.UnfreezeObject(&Elem.ElementData, ElementTypeDesc, &DstElem.ElementData);
1385 }
1386 else
1387 {
1388 DstElem.PrevFreeIndex = Elem.PrevFreeIndex;
1389 DstElem.NextFreeIndex = Elem.NextFreeIndex;
1390 }
1391 }
1392 }
1393
1394 ::new((void*)&DstObject->AllocationFlags) AllocationBitArrayType(this->AllocationFlags);
1395 DstObject->FirstFreeIndex = this->FirstFreeIndex;
1396 DstObject->NumFreeIndices = this->NumFreeIndices;
1397 }
1398 else
1399 {
1400 ::new((void*)Dst) TSparseArray();
1401 }
1402 }
1403
1404 static void AppendHash(const FPlatformTypeLayoutParameters& LayoutParams, FSHA1& Hasher)
1405 {
1407 {
1409 }
1410 }
1411};
1412
1413namespace Freeze
1414{
1415 template<typename ElementType, typename Allocator>
1417 {
1418 Object.WriteMemoryImage(Writer);
1419 }
1420
1421 template<typename ElementType, typename Allocator>
1423 {
1424 Object.CopyUnfrozen(Context, OutDst);
1425 return sizeof(Object);
1426 }
1427
1428 template<typename ElementType, typename Allocator>
1430 {
1432 return DefaultAppendHash(TypeDesc, LayoutParams, Hasher);
1433 }
1434}
1435
1437
1438//
1439// TSparseArray operator news.
1440//
1441template <typename T, typename Allocator> void* operator new( size_t Size, TSparseArray<T, Allocator>& Array )
1442{
1443 check( Size == sizeof( T ) );
1444 const int32 Index = Array.AddUninitialized().Index;
1445 return &Array[ Index ];
1446}
1447template <typename T, typename Allocator> void* operator new( size_t Size, TSparseArray<T, Allocator>& Array, int32 Index )
1448{
1449 check( Size == sizeof( T ) );
1450 Array.InsertUninitialized( Index );
1451 return &Array[ Index ];
1452}
1453
1455{
1456 // ElementOffset is at zero offset from the TSparseArrayElementOrFreeListLink - not stored here
1459};
1460
1461// Untyped sparse array type for accessing TSparseArray data, like FScriptArray for TArray.
1462// Must have the same memory representation as a TSet.
1463template <typename AllocatorType, typename InDerivedType>
1465{
1466 using DerivedType = std::conditional_t<std::is_void_v<InDerivedType>, TScriptSparseArray, InDerivedType>;
1467
1468public:
1469 [[nodiscard]] static constexpr FScriptSparseArrayLayout GetScriptLayout(int32 ElementSize, int32 ElementAlignment)
1470 {
1472 Result.Alignment = FMath::Max(ElementAlignment, (int32)alignof(FFreeListLink));
1473 Result.Size = FMath::Max(ElementSize, (int32)sizeof (FFreeListLink));
1474
1475 return Result;
1476 }
1477
1479 : FirstFreeIndex(-1)
1480 , NumFreeIndices(0)
1481 {
1482 }
1483
1485 // Start - intrusive TOptional<TSparseArray> state //
1487 constexpr static bool bHasIntrusiveUnsetOptionalState = true;
1489
1491 : Data(Tag)
1492 {
1493 }
1495 {
1496 return Data == Tag;
1497 }
1499 // End - intrusive TOptional<TSparseArray> state //
1501
1503 {
1504 return AllocationFlags.IsValidIndex(Index) && AllocationFlags[Index];
1505 }
1506
1508 {
1509 return AllocationFlags[Index];
1510 }
1511
1512 [[nodiscard]] bool IsEmpty() const
1513 {
1514 return Data.Num() == NumFreeIndices;
1515 }
1516
1517 [[nodiscard]] int32 Num() const
1518 {
1519 return Data.Num() - NumFreeIndices;
1520 }
1521
1523 [[nodiscard]] int32 Max() const
1524 {
1525 return Data.Max();
1526 }
1527
1529 {
1530 return Data.NumUnchecked() - NumFreeIndices;
1531 }
1532
1535 {
1536 return Data.Num();
1537 }
1538
1539 [[nodiscard]] bool IsCompact() const
1540 {
1541 return NumFreeIndices == 0;
1542 }
1543
1545 {
1546 return (uint8*)Data.GetData() + Layout.Size * Index;
1547 }
1548
1550 {
1551 return (const uint8*)Data.GetData() + Layout.Size * Index;
1552 }
1553
1555 {
1556 checkSlow(this != &Other);
1557 Empty(0, Layout);
1558 Data.MoveAssign(Other.Data, Layout.Size, Layout.Alignment);
1559 AllocationFlags.MoveAssign(Other.AllocationFlags);
1560 FirstFreeIndex = Other.FirstFreeIndex; Other.FirstFreeIndex = 0;
1561 NumFreeIndices = Other.NumFreeIndices; Other.NumFreeIndices = 0;
1562 }
1563
1565 {
1566 // Free the allocated elements.
1567 Data.Empty(Slack, Layout.Size, Layout.Alignment);
1568 FirstFreeIndex = -1;
1569 NumFreeIndices = 0;
1570 AllocationFlags.Empty(Slack);
1571 }
1572
1579 {
1580 int32 Index;
1581 if (NumFreeIndices)
1582 {
1583 // Remove and use the first index from the list of free elements.
1584 Index = FirstFreeIndex;
1585 FirstFreeIndex = GetFreeListLink(FirstFreeIndex, Layout)->NextFreeIndex;
1586 --NumFreeIndices;
1587 if(NumFreeIndices)
1588 {
1589 GetFreeListLink(FirstFreeIndex, Layout)->PrevFreeIndex = -1;
1590 }
1591 }
1592 else
1593 {
1594 // Add a new element.
1595 Index = Data.Add(1, Layout.Size, Layout.Alignment);
1596 AllocationFlags.Add(false);
1597 }
1598
1599 AllocationFlags[Index] = true;
1600
1601 return Index;
1602 }
1603
1606 {
1607 for (; Count; --Count)
1608 {
1609 check(AllocationFlags[Index]);
1610
1611 // Mark the element as free and add it to the free element list.
1612 if(NumFreeIndices)
1613 {
1614 GetFreeListLink(FirstFreeIndex, Layout)->PrevFreeIndex = Index;
1615 }
1616
1617 auto* IndexData = GetFreeListLink(Index, Layout);
1618 IndexData->PrevFreeIndex = -1;
1619 IndexData->NextFreeIndex = NumFreeIndices > 0 ? FirstFreeIndex : INDEX_NONE;
1620 FirstFreeIndex = Index;
1621 ++NumFreeIndices;
1622 AllocationFlags[Index] = false;
1623
1624 ++Index;
1625 }
1626 }
1627
1628private:
1629 TScriptArray <typename AllocatorType::ElementAllocator> Data;
1631 int32 FirstFreeIndex = -1;
1632 int32 NumFreeIndices = 0;
1633
1634 // This function isn't intended to be called, just to be compiled to validate the correctness of the type.
1635 static void CheckConstraints()
1636 {
1638 typedef TSparseArray<int32> RealType;
1639
1640 // Check that the class footprint is the same
1641 static_assert(sizeof (ScriptType) == sizeof (RealType), "TScriptSparseArray's size doesn't match TSparseArray");
1642 static_assert(alignof(ScriptType) == alignof(RealType), "TScriptSparseArray's alignment doesn't match TSparseArray");
1643
1644 // Check member sizes
1645 static_assert(sizeof(DeclVal<ScriptType>().Data) == sizeof(DeclVal<RealType>().Data), "TScriptSparseArray's Data member size does not match TSparseArray's");
1646 static_assert(sizeof(DeclVal<ScriptType>().AllocationFlags) == sizeof(DeclVal<RealType>().AllocationFlags), "TScriptSparseArray's AllocationFlags member size does not match TSparseArray's");
1647 static_assert(sizeof(DeclVal<ScriptType>().FirstFreeIndex) == sizeof(DeclVal<RealType>().FirstFreeIndex), "TScriptSparseArray's FirstFreeIndex member size does not match TSparseArray's");
1648 static_assert(sizeof(DeclVal<ScriptType>().NumFreeIndices) == sizeof(DeclVal<RealType>().NumFreeIndices), "TScriptSparseArray's NumFreeIndices member size does not match TSparseArray's");
1649
1650 // Check member offsets
1651 static_assert(STRUCT_OFFSET(ScriptType, Data) == STRUCT_OFFSET(RealType, Data), "TScriptSparseArray's Data member offset does not match TSparseArray's");
1652 static_assert(STRUCT_OFFSET(ScriptType, AllocationFlags) == STRUCT_OFFSET(RealType, AllocationFlags), "TScriptSparseArray's AllocationFlags member offset does not match TSparseArray's");
1653 static_assert(STRUCT_OFFSET(ScriptType, FirstFreeIndex) == STRUCT_OFFSET(RealType, FirstFreeIndex), "TScriptSparseArray's FirstFreeIndex member offset does not match TSparseArray's");
1654 static_assert(STRUCT_OFFSET(ScriptType, NumFreeIndices) == STRUCT_OFFSET(RealType, NumFreeIndices), "TScriptSparseArray's NumFreeIndices member offset does not match TSparseArray's");
1655
1656 // Check free index offsets
1657 static_assert(STRUCT_OFFSET(ScriptType::FFreeListLink, PrevFreeIndex) == STRUCT_OFFSET(RealType::FElementOrFreeListLink, PrevFreeIndex), "TScriptSparseArray's FFreeListLink's PrevFreeIndex member offset does not match TSparseArray's");
1658 static_assert(STRUCT_OFFSET(ScriptType::FFreeListLink, NextFreeIndex) == STRUCT_OFFSET(RealType::FElementOrFreeListLink, NextFreeIndex), "TScriptSparseArray's FFreeListLink's NextFreeIndex member offset does not match TSparseArray's");
1659 }
1660
1661 struct FFreeListLink
1662 {
1664 int32 PrevFreeIndex;
1665
1667 int32 NextFreeIndex;
1668 };
1669
1671 UE_FORCEINLINE_HINT FFreeListLink* GetFreeListLink(int32 Index, const FScriptSparseArrayLayout& Layout)
1672 {
1673 return (FFreeListLink*)GetData(Index, Layout);
1674 }
1675
1676public:
1677 // These should really be private, because they shouldn't be called, but there's a bunch of code
1678 // that needs to be fixed first.
1680 void operator=(const TScriptSparseArray&) { check(false); }
1681};
1682
1683template <typename AllocatorType, typename InDerivedType>
1685{
1686 enum { Value = true };
1687};
1688
1689class FScriptSparseArray : public TScriptSparseArray<FDefaultSparseArrayAllocator, FScriptSparseArray>
1690{
1692
1693public:
1694 using Super::Super;
1695
1697 // Start - intrusive TOptional<FSparseArray> state //
1701 // End - intrusive TOptional<FSparseArray> state //
1703};
1704
1708inline void* operator new(size_t Size,const FSparseArrayAllocationInfo& Allocation)
1709{
1710 UE_ASSUME(Allocation.Pointer);
1711 return Allocation.Pointer;
1712}
1713inline void operator delete(void* ,const FSparseArrayAllocationInfo& Allocation)
1714{
1715}
1716
1718template<typename ElementType,typename Allocator>
1720{
1721 Array.CountBytes(Ar);
1722 if( Ar.IsLoading() )
1723 {
1724 // Load array.
1726 Ar << NewNumElements;
1727 Array.Empty( NewNumElements );
1728 for(int32 ElementIndex = 0;ElementIndex < NewNumElements;ElementIndex++)
1729 {
1730 Ar << *::new(Array.AddUninitialized())ElementType;
1731 }
1732 }
1733 else
1734 {
1735 // Save array.
1736 int32 NewNumElements = Array.Num();
1737 Ar << NewNumElements;
1739 {
1740 Ar << *It;
1741 }
1742 }
1743 return Ar;
1744}
1745
1747template<typename ElementType,typename Allocator>
1749{
1750 int32 NumElements = InArray.Num();
1751 FStructuredArchive::FArray Array = Slot.EnterArray(NumElements);
1752 if (Slot.GetUnderlyingArchive().IsLoading())
1753 {
1754 InArray.Empty(NumElements);
1755
1756 for (int32 Index = 0; Index < NumElements; ++Index)
1757 {
1759 {
1760 return;
1761 }
1762
1764 ElementSlot << *::new(InArray.AddUninitialized())ElementType;
1765 }
1766 }
1767 else
1768 {
1769 for (typename TSparseArray<ElementType, Allocator>::TIterator It(InArray); It; ++It)
1770 {
1772 ElementSlot << *It;
1773 }
1774 }
1775}
1776
1777#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_4
1780#endif
#define FORCENOINLINE
Definition AndroidPlatform.h:142
#define FORCEINLINE
Definition AndroidPlatform.h:140
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#define verify(expr)
Definition AssertionMacros.h:319
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define UE_STATIC_ASSERT_WARN(bExpression, Message)
Definition CoreMiscDefines.h:431
EConstEval
Definition CoreMiscDefines.h:161
@ ConstEval
Definition CoreMiscDefines.h:161
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
#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
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
return true
Definition ExternalRpcRegistry.cpp:601
#define DECLARE_TEMPLATE_INTRINSIC_TYPE_LAYOUT(TemplatePrefix, T)
Definition MemoryLayout.h:661
const bool
Definition NetworkReplayStreaming.h:178
FArchive & operator<<(FArchive &Ar, TSparseArray< ElementType, Allocator > &Array)
Definition SparseArray.h:1719
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTempIfPossible(T &&Obj) noexcept
Definition UnrealTemplate.h:538
void Move(T &A, typename TMoveSupportTraits< T >::Copy B)
Definition UnrealTemplate.h:24
UE_REWRITE constexpr void Exchange(T &A, T &B)
Definition UnrealTemplate.h:627
#define STRUCT_OFFSET(struc, member)
Definition UnrealTemplate.h:218
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32 Size
Definition VulkanMemory.cpp:4034
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
UE_FORCEINLINE_HINT bool IsCriticalError() const
Definition Archive.h:373
virtual void CountBytes(SIZE_T InNum, SIZE_T InMax)
Definition Archive.h:125
Definition MemoryImageWriter.h:14
CORE_API uint32 WriteBytes(const void *Data, uint32 Size)
Definition MemoryImage.cpp:2143
CORE_API uint32 WriteNullPointer()
Definition MemoryImage.cpp:2148
CORE_API uint32 WriteAlignment(uint32 Alignment)
Definition MemoryImage.cpp:2133
bool Is32BitTarget() const
Definition MemoryImageWriter.h:26
CORE_API FMemoryImageWriter WritePointer(const FTypeLayoutDesc &StaticTypeDesc, const FTypeLayoutDesc &DerivedTypeDesc, uint32 *OutOffsetToBase=nullptr)
Definition MemoryImage.cpp:2153
Definition MemoryImageWriter.h:78
Definition BitArray.h:281
Definition SecureHash.h:314
Definition SparseArray.h:1690
Definition StructuredArchiveSlots.h:172
Definition StructuredArchiveSlots.h:52
UE_API FStructuredArchiveArray EnterArray(int32 &Num)
Definition StructuredArchiveSlots.h:257
Definition ArrayView.h:139
Definition Array.h:670
UE_FORCEINLINE_HINT SizeType AddUninitialized()
Definition Array.h:1664
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void RemoveAt(SizeType Index, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2083
UE_FORCEINLINE_HINT void CheckAddress(const ElementType *Addr) const
Definition Array.h:1955
void Reset(SizeType NewSize=0)
Definition Array.h:2246
UE_NODEBUG UE_FORCEINLINE_HINT ElementType * GetData() UE_LIFETIMEBOUND
Definition Array.h:1027
UE_REWRITE SizeType Max() const
Definition Array.h:1161
UE_NODEBUG void CountBytes(FArchive &Ar) const
Definition Array.h:1649
UE_NODEBUG UE_FORCEINLINE_HINT SIZE_T GetAllocatedSize(void) const
Definition Array.h:1059
UE_FORCEINLINE_HINT void Shrink()
Definition Array.h:1278
void Empty(SizeType Slack=0)
Definition Array.h:2273
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
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
int32 Add(const bool Value)
Definition BitArray.h:615
void Empty(int32 ExpectedNumBits=0)
Definition BitArray.h:779
int32 Find(bool bValue) const
Definition BitArray.h:1084
int32 FindAndSetFirstZeroBit(int32 StartIndex=0)
Definition BitArray.h:1258
int32 FindLast(bool bValue) const
Definition BitArray.h:1213
uint32 GetAllocatedSize(void) const
Definition BitArray.h:1062
void Reset()
Definition BitArray.h:817
void WriteMemoryImage(FMemoryImageWriter &Writer) const
Definition BitArray.h:1908
UE_FORCEINLINE_HINT void Init(bool bValue, int32 InNumBits)
Definition BitArray.h:828
void CountBytes(FArchive &Ar) const
Definition BitArray.h:1068
void RemoveAt(int32 BaseIndex, int32 NumBitsToRemove=1)
Definition BitArray.h:1004
Definition BitArray.h:2072
Definition BitArray.h:1944
Definition Array.h:64
void Empty(int32 Slack, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:142
int32 Add(int32 Count, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:82
void MoveAssign(TScriptArray &Other, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:131
FORCEINLINE int32 Num() const
Definition ScriptArray.h:40
FORCEINLINE int32 Max() const
Definition ScriptArray.h:51
FORCEINLINE int32 NumUnchecked() const
Definition ScriptArray.h:46
FORCEINLINE void * GetData()
Definition ScriptArray.h:24
Definition BitArray.h:2216
void MoveAssign(DerivedType &Other)
Definition BitArray.h:2248
int32 Add(const bool Value)
Definition BitArray.h:2270
void Empty(int32 Slack=0)
Definition BitArray.h:2257
bool IsValidIndex(int32 Index) const
Definition BitArray.h:2231
Definition SparseArray.h:1465
void operator=(const TScriptSparseArray &)
Definition SparseArray.h:1680
static constexpr FScriptSparseArrayLayout GetScriptLayout(int32 ElementSize, int32 ElementAlignment)
Definition SparseArray.h:1469
int32 Num() const
Definition SparseArray.h:1517
int32 AddUninitialized(const FScriptSparseArrayLayout &Layout)
Definition SparseArray.h:1578
void * GetData(int32 Index, const FScriptSparseArrayLayout &Layout)
Definition SparseArray.h:1544
int32 NumUnchecked() const
Definition SparseArray.h:1528
const void * GetData(int32 Index, const FScriptSparseArrayLayout &Layout) const
Definition SparseArray.h:1549
bool IsCompact() const
Definition SparseArray.h:1539
int32 GetMaxIndex() const
Definition SparseArray.h:1534
TScriptSparseArray(FIntrusiveUnsetOptionalState Tag)
Definition SparseArray.h:1490
static constexpr bool bHasIntrusiveUnsetOptionalState
Definition SparseArray.h:1487
TScriptSparseArray(const TScriptSparseArray &)
Definition SparseArray.h:1679
void RemoveAtUninitialized(const FScriptSparseArrayLayout &Layout, int32 Index, int32 Count=1)
Definition SparseArray.h:1605
void MoveAssign(DerivedType &Other, const FScriptSparseArrayLayout &Layout)
Definition SparseArray.h:1554
bool IsValidIndex(int32 Index) const
Definition SparseArray.h:1502
bool operator==(FIntrusiveUnsetOptionalState Tag) const
Definition SparseArray.h:1494
bool IsEmpty() const
Definition SparseArray.h:1512
bool IsAllocated(int32 Index) const
Definition SparseArray.h:1507
int32 Max() const
Definition SparseArray.h:1523
void Empty(int32 Slack, const FScriptSparseArrayLayout &Layout)
Definition SparseArray.h:1564
TScriptSparseArray()
Definition SparseArray.h:1478
Definition SparseArray.h:65
constexpr TSparseArrayBase()
Definition SparseArray.h:73
int32 FirstFreeIndex
Definition SparseArray.h:506
void SortFreeList()
Definition SparseArray.h:322
FSparseArrayAllocationInfo AllocateIndex(int32 Index)
Definition SparseArray.h:96
int32 Num() const
Definition SparseArray.h:470
AllocationBitArrayType AllocationFlags
Definition SparseArray.h:503
TSparseArrayBase(const TSparseArrayBase &InCopy)
Definition SparseArray.h:89
bool Compact()
Definition SparseArray.h:412
int32 NumFreeIndices
Definition SparseArray.h:509
int32 Max() const
Definition SparseArray.h:476
consteval TSparseArrayBase(EConstEval)
Definition SparseArray.h:80
FSparseArrayAllocationInfo AddUninitializedAtLowestFreeIndex(int32 &LowestFreeIndexSearchStart)
Definition SparseArray.h:143
void RemoveAtUninitialized(int32 Index, int32 Count=1)
Definition SparseArray.h:191
FSparseArrayAllocationInfo AddUninitialized()
Definition SparseArray.h:117
TArray< FElementOrFreeListLink, typename Allocator::ElementAllocator > DataType
Definition SparseArray.h:499
DataType Data
Definition SparseArray.h:500
bool IsValidIndex(int32 Index) const
Definition SparseArray.h:481
TSparseArrayBase(FIntrusiveUnsetOptionalState Tag)
Definition SparseArray.h:67
FSparseArrayAllocationInfo InsertUninitialized(int32 Index)
Definition SparseArray.h:356
bool IsAllocated(int32 Index) const
Definition SparseArray.h:486
TSparseArrayElementOrFreeListLink< TAlignedBytes< SizeOfElementType, AlignOfElementType > > FElementOrFreeListLink
Definition SparseArray.h:497
TBitArray< typename Allocator::BitArrayAllocator > AllocationBitArrayType
Definition SparseArray.h:502
void Shrink()
Definition SparseArray.h:256
void Reserve(int32 ExpectedNumElements)
Definition SparseArray.h:219
int32 GetMaxIndex() const
Definition SparseArray.h:460
bool IsEmpty() const
Definition SparseArray.h:465
Definition SparseArray.h:1137
TConstIterator(const TSparseArray &InArray, const typename TBaseIterator< true >::BitArrayItType &InBitArrayIt)
Definition SparseArray.h:1144
TConstIterator(const TSparseArray &InArray)
Definition SparseArray.h:1139
Definition SparseArray.h:1227
TConstSubsetIterator(const TSparseArray &InArray, const TBitArray< SubsetAllocator > &InBitArray)
Definition SparseArray.h:1229
UE_FORCEINLINE_HINT const FRelativeBitReference & GetRelativeBitReference() const
Definition SparseArray.h:1264
UE_FORCEINLINE_HINT bool operator!() const
Definition SparseArray.h:1251
TConstSubsetIterator & operator++()
Definition SparseArray.h:1234
UE_FORCEINLINE_HINT const ElementType & operator*() const
Definition SparseArray.h:1256
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition SparseArray.h:1240
UE_FORCEINLINE_HINT const ElementType * operator->() const
Definition SparseArray.h:1260
Definition SparseArray.h:1116
void RemoveCurrent()
Definition SparseArray.h:1129
TIterator(TSparseArray &InArray, const typename TBaseIterator< false >::BitArrayItType &InBitArrayIt)
Definition SparseArray.h:1123
TIterator(TSparseArray &InArray)
Definition SparseArray.h:1118
Definition SparseArray.h:1175
TRangedForConstIterator(const TSparseArray &InArray, const typename TBaseIterator< true >::BitArrayItType &InBitArrayIt)
Definition SparseArray.h:1177
bool operator!=(const TRangedForConstIterator &Rhs) const
Definition SparseArray.h:1183
Definition SparseArray.h:1152
TRangedForIterator(TSparseArray &InArray, const typename TBaseIterator< false >::BitArrayItType &InBitArrayIt)
Definition SparseArray.h:1154
bool operator!=(const TRangedForIterator &Rhs) const
Definition SparseArray.h:1160
Definition SparseArray.h:524
constexpr TSparseArray()=default
static constexpr bool bHasIntrusiveUnsetOptionalState
Definition SparseArray.h:544
void RemoveAt(int32 Index, int32 Count=1)
Definition SparseArray.h:650
SIZE_T GetAllocatedSize(void) const
Definition SparseArray.h:808
UE_FORCEINLINE_HINT TRangedForConstIterator end() const
Definition SparseArray.h:1221
void StableSort()
Definition SparseArray.h:759
void StableSort(const PREDICATE_CLASS &Predicate)
Definition SparseArray.h:746
int32 Add(const ElementType &Element)
Definition SparseArray.h:564
TSparseArray & operator=(std::initializer_list< ElementType > InList)
Definition SparseArray.h:954
int32 EmplaceAt(int32 Index, ArgsType &&... Args)
Definition SparseArray.h:619
TSparseArray(const TSparseArray &InCopy)
Definition SparseArray.h:880
UE_FORCEINLINE_HINT TRangedForIterator begin()
Definition SparseArray.h:1218
bool operator==(const TSparseArray &B) const
Definition SparseArray.h:829
void CountBytes(FArchive &Ar) const
Definition SparseArray.h:814
TIterator CreateIterator()
Definition SparseArray.h:1202
TSparseArray(FIntrusiveUnsetOptionalState Tag)
Definition SparseArray.h:547
bool IsCompact() const
Definition SparseArray.h:820
int32 PointerToIndex(const ElementType *Ptr) const
Definition SparseArray.h:1016
static void AppendHash(const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
Definition SparseArray.h:1404
TSparseArray & operator+=(const TArray< ElementType > &OtherArray)
Definition SparseArray.h:1283
ElementType & operator[](int32 Index)
Definition SparseArray.h:1004
TSparseArray & operator=(const TSparseArray &InCopy)
Definition SparseArray.h:904
void WriteMemoryImage(FMemoryImageWriter &Writer) const
Definition SparseArray.h:1324
TSparseArray(TSparseArray &&InCopy)
Definition SparseArray.h:874
void Reset()
Definition SparseArray.h:682
TSparseArray(std::initializer_list< ElementType > InList)
Definition SparseArray.h:887
UE_FORCEINLINE_HINT void CheckAddress(const ElementType *Addr) const
Definition SparseArray.h:1036
int32 Emplace(ArgsType &&... Args)
Definition SparseArray.h:588
const ElementType & operator[](int32 Index) const
Definition SparseArray.h:1010
~TSparseArray()
Definition SparseArray.h:533
void Sort()
Definition SparseArray.h:739
consteval TSparseArray(EConstEval)
Definition SparseArray.h:868
int32 Add(ElementType &&Element)
Definition SparseArray.h:572
int32 EmplaceAtLowestFreeIndex(int32 &LowestFreeIndexSearchStart, ArgsType &&... Args)
Definition SparseArray.h:604
TSparseArray & operator+=(const TSparseArray &OtherArray)
Definition SparseArray.h:1274
UE_FORCEINLINE_HINT TRangedForConstIterator begin() const
Definition SparseArray.h:1219
bool operator==(FIntrusiveUnsetOptionalState Tag) const
Definition SparseArray.h:552
TConstIterator CreateConstIterator() const
Definition SparseArray.h:1208
TSparseArray & operator=(TSparseArray &&InCopy)
Definition SparseArray.h:894
int32 IndexOfByPredicate(Predicate Pred) const
Definition SparseArray.h:773
bool operator!=(const TSparseArray &B) const
Definition SparseArray.h:860
void CopyUnfrozen(const FMemoryUnfreezeContent &Context, void *Dst) const
Definition SparseArray.h:1369
void Sort(const PREDICATE_CLASS &Predicate)
Definition SparseArray.h:726
bool CompactStable()
Definition SparseArray.h:703
void Empty(int32 ExpectedNumElements=0)
Definition SparseArray.h:666
void Insert(int32 Index, typename TTypeTraits< ElementType >::ConstInitType Element)
Definition SparseArray.h:644
UE_FORCEINLINE_HINT TRangedForIterator end()
Definition SparseArray.h:1220
int32 FindArbitraryElementIndex() const
Definition SparseArray.h:791
CORE_API FArchive & GetUnderlyingArchive() const
Definition StructuredArchiveSlots.cpp:7
UE_REWRITE void Sort(RangeType &&Range)
Definition Sort.h:16
UE_REWRITE void StableSort(RangeType &&Range)
Definition StableSort.h:125
Definition Array.h:3955
UE_NODEBUG void IntrinsicWriteMemoryImage(FMemoryImageWriter &Writer, const TArray< T, AllocatorType > &Object, const FTypeLayoutDesc &)
Definition Array.h:3957
CORE_API uint32 DefaultAppendHash(const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
Definition MemoryImage.cpp:575
CORE_API uint32 AppendHash(const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
Definition MemoryImage.cpp:864
UE_NODEBUG uint32 IntrinsicUnfrozenCopy(const FMemoryUnfreezeContent &Context, const TArray< T, AllocatorType > &Object, void *OutDst)
Definition Array.h:3963
UE_NODEBUG uint32 IntrinsicAppendHash(const TArray< T, AllocatorType > *DummyObject, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
Definition Array.h:3970
FVector operator*(const FSquareMatrix3 &InMatrix, const FVector &InVector)
Definition ARBlueprintLibrary.cpp:650
bool operator!=(const FCachedAssetKey &A, const FCachedAssetKey &B)
Definition AssetDataMap.h:506
bool operator==(const FCachedAssetKey &A, const FCachedAssetKey &B)
Definition AssetDataMap.h:501
FORCEINLINE UE_STRING_CLASS RhsType && Rhs
Definition String.cpp.inl:718
@ false
Definition radaudio_common.h:23
U16 Index
Definition radfft.cpp:71
Definition IntrusiveUnsetOptionalState.h:71
static UE_FORCEINLINE_HINT void * Memcpy(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:160
Definition MemoryLayout.h:799
Definition SparseArray.h:1455
int32 Size
Definition SparseArray.h:1458
int32 Alignment
Definition SparseArray.h:1457
Definition SparseArray.h:31
int32 Index
Definition SparseArray.h:32
void * Pointer
Definition SparseArray.h:33
Definition MemoryLayout.h:108
Definition TypeCompatibleBytes.h:17
Definition ContainerAllocationPolicies.h:256
Definition MemoryLayout.h:626
Definition UnrealTypeTraits.h:172
Definition Less.h:19
TCallTraits< T >::ParamType ConstInitType
Definition UnrealTypeTraits.h:336