UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ScriptArray.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"
10#include "Containers/Array.h"
11#include <initializer_list>
12
13
18template <typename AllocatorType>
20 : protected AllocatorType::ForAnyElementType
21{
22public:
23
25 {
26 return this->GetAllocation();
27 }
28 [[nodiscard]] FORCEINLINE const void* GetData() const
29 {
30 return this->GetAllocation();
31 }
33 {
34 return i>=0 && i<ArrayNum;
35 }
36 [[nodiscard]] bool IsEmpty() const
37 {
38 return ArrayNum == 0;
39 }
41 {
44 return ArrayNum;
45 }
47 {
48 return ArrayNum;
49 }
52 {
53 return ArrayMax;
54 }
56 {
57 Insert( Index, Count, NumBytesPerElement, AlignmentOfElement );
58 FMemory::Memzero( (uint8*)this->GetAllocation()+(SIZE_T)Index*NumBytesPerElement, (SIZE_T)Count*NumBytesPerElement );
59 }
61 {
62 check(Count>=0);
63 check(ArrayNum>=0);
65 check(Index>=0);
67
68 const int32 OldNum = ArrayNum;
69 if( (ArrayNum+=Count)>ArrayMax )
70 {
71 ResizeGrow(OldNum, NumBytesPerElement, AlignmentOfElement);
72 }
74 (
75 (uint8*)this->GetAllocation() + ((SIZE_T)Index+Count )*NumBytesPerElement,
76 (uint8*)this->GetAllocation() + ((SIZE_T)Index )*NumBytesPerElement,
77 ((SIZE_T)OldNum-Index)*NumBytesPerElement
78 );
79
80 SlackTrackerNumChanged();
81 }
83 {
84 check(Count>=0);
87
88 const int32 OldNum = ArrayNum;
89 if( (ArrayNum+=Count)>ArrayMax )
90 {
91 ResizeGrow(OldNum, NumBytesPerElement, AlignmentOfElement);
92 }
93
94 SlackTrackerNumChanged();
95
96 return OldNum;
97 }
99 {
100 const int32 Index = Add( Count, NumBytesPerElement, AlignmentOfElement );
101 FMemory::Memzero( (uint8*)this->GetAllocation()+ (SIZE_T)Index*NumBytesPerElement, (SIZE_T)Count*NumBytesPerElement );
102 return Index;
103 }
104 void Shrink( int32 NumBytesPerElement, uint32 AlignmentOfElement )
105 {
108 if (ArrayNum != ArrayMax)
109 {
110 ResizeTo(ArrayNum, NumBytesPerElement, AlignmentOfElement);
111 }
112 }
113 void SetNumUninitialized(int32 NewNum, int32 NumBytesPerElement, uint32 AlignmentOfElement, EAllowShrinking AllowShrinking = UE::Core::Private::AllowShrinkingByDefault<AllocatorType>())
114 {
115 checkSlow(NewNum >= 0);
116 int32 OldNum = Num();
117 if (NewNum > OldNum)
118 {
119 Add(NewNum - OldNum, NumBytesPerElement, AlignmentOfElement);
120 }
121 else if (NewNum < OldNum)
122 {
124 }
125 }
126 UE_ALLOWSHRINKING_BOOL_DEPRECATED("SetNumUninitialized")
127 FORCEINLINE void SetNumUninitialized(int32 NewNum, int32 NumBytesPerElement, uint32 AlignmentOfElement, bool bAllowShrinking)
128 {
130 }
132 {
133 checkSlow(this != &Other);
134 Empty(0, NumBytesPerElement, AlignmentOfElement);
135 this->MoveToEmpty(Other);
136 ArrayNum = Other.ArrayNum; Other.ArrayNum = 0;
137 ArrayMax = Other.ArrayMax; Other.ArrayMax = 0;
138
139 this->SlackTrackerNumChanged();
140 Other.SlackTrackerNumChanged();
141 }
142 void Empty( int32 Slack, int32 NumBytesPerElement, uint32 AlignmentOfElement )
143 {
144 checkSlow(Slack>=0);
145 ArrayNum = 0;
146
147 SlackTrackerNumChanged();
148
149 if (Slack != ArrayMax)
150 {
151 ResizeTo(Slack, NumBytesPerElement, AlignmentOfElement);
152 }
153 }
154 void Reset(int32 NewSize, int32 NumBytesPerElement, uint32 AlignmentOfElement)
155 {
156 if (NewSize <= ArrayMax)
157 {
158 ArrayNum = 0;
159
160 SlackTrackerNumChanged();
161 }
162 else
163 {
164 Empty(NewSize, NumBytesPerElement, AlignmentOfElement);
165 }
166 }
167 void SwapMemory(int32 A, int32 B, int32 NumBytesPerElement )
168 {
170 (uint8*)this->GetAllocation()+((SIZE_T)NumBytesPerElement*A),
171 (uint8*)this->GetAllocation()+((SIZE_T)NumBytesPerElement*B),
172 NumBytesPerElement
173 );
174 }
176 : ArrayNum( 0 )
177 , ArrayMax( 0 )
178 {
179 }
180 void CountBytes( FArchive& Ar, int32 NumBytesPerElement ) const
181 {
182 Ar.CountBytes( (SIZE_T)ArrayNum*NumBytesPerElement, (SIZE_T)ArrayMax*NumBytesPerElement );
183 }
184 FORCEINLINE void CheckAddress(const void* Addr, int32 NumBytesPerElement) const
185 {
186 checkf((const char*)Addr < (const char*)GetData() || (const char*)Addr >= ((const char*)GetData() + (SIZE_T)ArrayMax * NumBytesPerElement), TEXT("Attempting to use a container element (%p) which already comes from the container being modified (%p, ArrayMax: %lld, ArrayNum: %lld, SizeofElement: %d)!"), Addr, GetData(), (long long)ArrayMax, (long long)ArrayNum, NumBytesPerElement);
187 }
192 {
193 return ArrayMax - ArrayNum;
194 }
195
196 void Remove(int32 Index, int32 Count, int32 NumBytesPerElement, uint32 AlignmentOfElement, EAllowShrinking AllowShrinking = UE::Core::Private::AllowShrinkingByDefault<AllocatorType>())
197 {
198 if (Count)
199 {
200 checkSlow(Count >= 0);
201 checkSlow(Index >= 0);
204
205 // Skip memmove in the common case that there is nothing to move.
207 if (NumToMove)
208 {
210 (
211 (uint8*)this->GetAllocation() + ((SIZE_T)Index)* NumBytesPerElement,
212 (uint8*)this->GetAllocation() + ((SIZE_T)Index + Count) * NumBytesPerElement,
213 (SIZE_T)NumToMove * NumBytesPerElement
214 );
215 }
216 ArrayNum -= Count;
217
218 SlackTrackerNumChanged();
219
221 {
222 ResizeShrink(NumBytesPerElement, AlignmentOfElement);
223 }
224 checkSlow(ArrayNum >= 0);
226 }
227 }
229 FORCEINLINE void Remove(int32 Index, int32 Count, int32 NumBytesPerElement, uint32 AlignmentOfElement, bool bAllowShrinking)
230 {
231 Remove(Index, Count, NumBytesPerElement, AlignmentOfElement, bAllowShrinking ? EAllowShrinking::Yes : EAllowShrinking::No);
232 }
233 [[nodiscard]] SIZE_T GetAllocatedSize(int32 NumBytesPerElement) const
234 {
235 return ((const typename AllocatorType::ForAnyElementType*)this)->GetAllocatedSize(ArrayMax, NumBytesPerElement);
236 }
237
238protected:
239
241 : ArrayNum( 0 )
242 , ArrayMax( InNum )
243 {
244 if (ArrayMax)
245 {
246 ResizeInit(NumBytesPerElement, AlignmentOfElement);
247 }
248 ArrayNum = InNum;
249
250 SlackTrackerNumChanged();
251 }
254
256 {
257 ArrayMax = this->CalculateSlackReserve(ArrayMax, NumBytesPerElement, AlignmentOfElement);
258 this->ResizeAllocation(ArrayNum, ArrayMax, NumBytesPerElement, AlignmentOfElement);
259 }
261 {
262 ArrayMax = this->CalculateSlackGrow(ArrayNum, ArrayMax, NumBytesPerElement, AlignmentOfElement);
263 this->ResizeAllocation(OldNum, ArrayMax, NumBytesPerElement, AlignmentOfElement);
264 }
266 {
267 const int32 NewArrayMax = this->CalculateSlackShrink(ArrayNum, ArrayMax, NumBytesPerElement, AlignmentOfElement);
268 if (NewArrayMax != ArrayMax)
269 {
271 this->ResizeAllocation(ArrayNum, ArrayMax, NumBytesPerElement, AlignmentOfElement);
272 }
273 }
275 {
276 if (NewMax)
277 {
278 NewMax = this->CalculateSlackReserve(NewMax, NumBytesPerElement);
279 }
280 if (NewMax != ArrayMax)
281 {
283 this->ResizeAllocation(ArrayNum, ArrayMax, NumBytesPerElement, AlignmentOfElement);
284 }
285 }
286
287private:
288 FORCEINLINE void SlackTrackerNumChanged()
289 {
290#if UE_ENABLE_ARRAY_SLACK_TRACKING
292 {
293 ((typename AllocatorType::ForAnyElementType*)this)->SlackTrackerLogNum(ArrayNum);
294 }
295#endif
296 }
297
298public:
300 // Start - intrusive TOptional<TScriptArray> state //
302 constexpr static bool bHasIntrusiveUnsetOptionalState = true;
304
306 : ArrayNum(0)
307 , ArrayMax(-1)
308 {
309 // Use ArrayMax == -1 as our intrusive state so that the destructor still works without change, as it doesn't use ArrayMax.
310 }
312 {
313 return ArrayMax == -1;
314 }
316 // End - intrusive TOptional<TScriptArray> state //
318
319 // These should really be private, because they shouldn't be called, but there's a bunch of code
320 // that needs to be fixed first.
321 TScriptArray(const TScriptArray&) { check(false); }
322 void operator=(const TScriptArray&) { check(false); }
323};
324
325template<typename AllocatorType> struct TIsZeroConstructType<TScriptArray<AllocatorType>> { enum { Value = true }; };
326
327class FScriptArray : public TScriptArray<FHeapAllocator>
328{
330
331public:
332 [[nodiscard]] FScriptArray() = default;
333
335 {
336 Super::MoveAssign(Other, NumBytesPerElement, AlignmentOfElement);
337 }
338
339protected:
341 : TScriptArray<FHeapAllocator>(InNum, NumBytesPerElement, AlignmentOfElement)
342 {
343 }
344
345public:
347 // Start - intrusive TOptional<FScriptArray> state //
355 // End - intrusive TOptional<FScriptArray> state //
357
358 // These should really be private, because they shouldn't be called, but there's a bunch of code
359 // that needs to be fixed first.
360 [[nodiscard]] FScriptArray(const FScriptArray&) { check(false); }
361 void operator=(const FScriptArray&) { check(false); }
362};
363
364template<> struct TIsZeroConstructType<FScriptArray> { enum { Value = true }; };
EAllowShrinking
Definition AllowShrinking.h:10
#define UE_ALLOWSHRINKING_BOOL_DEPRECATED(FunctionName)
Definition AllowShrinking.h:31
#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 checkf(expr, format,...)
Definition AssertionMacros.h:315
#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
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
void * GetAllocation(void *Target, uint32 Size, uint32 Offset, uint32 Alignment=16)
Definition OpenGLBuffer.cpp:57
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
virtual void CountBytes(SIZE_T InNum, SIZE_T InMax)
Definition Archive.h:125
Definition ScriptArray.h:328
void operator=(const FScriptArray &)
Definition ScriptArray.h:361
FScriptArray(int32 InNum, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:340
FScriptArray(FIntrusiveUnsetOptionalState Tag)
Definition ScriptArray.h:350
FScriptArray()=default
FScriptArray(const FScriptArray &)
Definition ScriptArray.h:360
void MoveAssign(FScriptArray &Other, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:334
Definition ScriptArray.h:21
int32 AddZeroed(int32 Count, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:98
FORCEINLINE bool IsValidIndex(int32 i) const
Definition ScriptArray.h:32
void Empty(int32 Slack, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:142
void Reset(int32 NewSize, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:154
int32 ArrayMax
Definition ScriptArray.h:253
TScriptArray()
Definition ScriptArray.h:175
FORCEINLINE void CheckAddress(const void *Addr, int32 NumBytesPerElement) const
Definition ScriptArray.h:184
void Remove(int32 Index, int32 Count, int32 NumBytesPerElement, uint32 AlignmentOfElement, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition ScriptArray.h:196
void CountBytes(FArchive &Ar, int32 NumBytesPerElement) const
Definition ScriptArray.h:180
FORCEINLINE const void * GetData() const
Definition ScriptArray.h:28
int32 Add(int32 Count, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:82
FORCENOINLINE void ResizeShrink(int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:265
void Shrink(int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:104
void operator=(const TScriptArray &)
Definition ScriptArray.h:322
bool IsEmpty() const
Definition ScriptArray.h:36
FORCENOINLINE void ResizeGrow(int32 OldNum, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:260
TScriptArray(FIntrusiveUnsetOptionalState Tag)
Definition ScriptArray.h:305
FORCENOINLINE void ResizeTo(int32 NewMax, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:274
FORCENOINLINE void ResizeInit(int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:255
bool operator==(FIntrusiveUnsetOptionalState Tag) const
Definition ScriptArray.h:311
FORCEINLINE int32 GetSlack() const
Definition ScriptArray.h:191
void MoveAssign(TScriptArray &Other, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:131
TScriptArray(int32 InNum, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:240
void SwapMemory(int32 A, int32 B, int32 NumBytesPerElement)
Definition ScriptArray.h:167
void Insert(int32 Index, int32 Count, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:60
static constexpr bool bHasIntrusiveUnsetOptionalState
Definition ScriptArray.h:302
FORCEINLINE int32 Num() const
Definition ScriptArray.h:40
int32 ArrayNum
Definition ScriptArray.h:252
void SetNumUninitialized(int32 NewNum, int32 NumBytesPerElement, uint32 AlignmentOfElement, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition ScriptArray.h:113
void InsertZeroed(int32 Index, int32 Count, int32 NumBytesPerElement, uint32 AlignmentOfElement)
Definition ScriptArray.h:55
SIZE_T GetAllocatedSize(int32 NumBytesPerElement) const
Definition ScriptArray.h:233
FORCEINLINE int32 Max() const
Definition ScriptArray.h:51
TScriptArray(const TScriptArray &)
Definition ScriptArray.h:321
FORCEINLINE int32 NumUnchecked() const
Definition ScriptArray.h:46
FORCEINLINE void * GetData()
Definition ScriptArray.h:24
Definition ContainerAllocationPolicies.h:618
U16 Index
Definition radfft.cpp:71
Definition IntrusiveUnsetOptionalState.h:71
static UE_FORCEINLINE_HINT void * Memmove(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:109
static UE_FORCEINLINE_HINT void * Memzero(void *Dest, SIZE_T Count)
Definition UnrealMemory.h:131
static UE_FORCEINLINE_HINT void Memswap(void *Ptr1, void *Ptr2, SIZE_T Size)
Definition UnrealMemory.h:187
Definition ContainerAllocationPolicies.h:256
Definition UnrealTypeTraits.h:172