5#include "Containers/Array.h"
6#include "Containers/ContainerAllocationPolicies.h"
7#include "Containers/HashTable.h"
8#include "Containers/Map.h"
9#include "Containers/Set.h"
10#include "Containers/UnrealString.h"
12#include "HAL/MemoryBase.h"
13#include "HAL/PlatformCrt.h"
14#include "HAL/PlatformString.h"
15#include "HAL/PreprocessorHelpers.h"
16#include "HAL/UnrealMemory.h"
17#include "Math/UnrealMathUtility.h"
18#include "Misc/AssertionMacros.h"
19#include "Misc/CString.h"
21#include "Misc/SecureHash.h"
22#include "Serialization/Archive.h"
23#include "Serialization/MemoryImageWriter.h"
24#include "Serialization/MemoryLayout.h"
25#include "Templates/AlignmentTemplates.h"
26#include "Templates/EnableIf.h"
27#include "Templates/RefCounting.h"
28#include "Templates/TypeHash.h"
29#include "Traits/IsCharType.h"
30#include "UObject/NameTypes.h"
34#if defined(WITH_RTTI) || defined(_CPPRTTI
) || defined(__GXX_RTTI) || WITH_EDITOR
58 inline const FTypeLayoutDesc* GetTypeDependency(int32 Index)
const {
return TypeDependencies[Index]; }
60 TArray<
const FTypeLayoutDesc*> TypeDependencies;
78 template<
typename TOther>
85 template<
typename TOther>
112 InternalDeleteObjectFromLayout(Object, *TypeDesc, PointerTable, FrozenSize > 0u);
118 FMemory::Free(Object);
129 if (FrozenSize == 0u && Object)
131 const FMemoryImageObject FrozenContent = FreezeMemoryImageObject(Object, *TypeDesc, PointerTable);
133 Object =
static_cast<T*>(FrozenContent.Object);
134 FrozenSize = FrozenContent.FrozenSize;
145 void* UnfrozenObject = UnfreezeMemoryImageObject(Object, *TypeDesc, PointerTable);
146 Destroy(PointerTable);
147 Object =
static_cast<T*>(UnfrozenObject);
166 return !(*
this == Rhs);
187 return !(*
this == Rhs);
232 const uint32 PrevSize = Bytes.Num();
233 const uint32 Offset = Align(PrevSize, Alignment);
234 Bytes.SetNumZeroed(Offset);
235 MaxAlignment = FMath::Max(MaxAlignment, Alignment);
241 check(Offset >= (uint32)Bytes.Num());
242 Bytes.SetNumZeroed(Offset);
248 Bytes.SetNumUninitialized(Offset + Size);
249 FMemory::Memcpy(Bytes.GetData() + Offset, Data, Size);
256 Bytes.SetNumZeroed(Offset + Num);
300 Sections.Add(Section);
305
306
318
319
320
370 static_assert(
INDEX_NONE == -1,
"TypeIndex cannot store INDEX_NONE when it's not -1");
376static_assert(
sizeof(
FFrozenMemoryImagePtr) ==
sizeof(uint64),
"FFrozenMemoryImagePtr is larger than a native pointer would be");
602
603
604
605
619 return NumAllocatedElements * NumBytesPerElement;
623 return Data.IsValid();
627 void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement, uint32 Alignment);
640 using SizeType = int32;
695 template<
typename ElementType>
706
707
708
710template <uint32 Alignment>
718using FMemoryImageAllocator = TMemoryImageAllocator<>;
720using FMemoryImageSparseArrayAllocator = TSparseArrayAllocator<FMemoryImageAllocator, FMemoryImageAllocator>;
721using FMemoryImageSetAllocator = TSetAllocator<FMemoryImageSparseArrayAllocator, FMemoryImageAllocator>;
724using TMemoryImageArray = TArray<T, FMemoryImageAllocator>;
726template<
typename ElementType,
typename KeyFuncs = DefaultKeyFuncs<ElementType>>
727using TMemoryImageSet = TSet<ElementType, KeyFuncs, FMemoryImageSetAllocator>;
729template <
typename KeyType,
typename ValueType,
typename KeyFuncs = TDefaultMapHashableKeyFuncs<KeyType, ValueType,
false>>
730using TMemoryImageMap = TMap<KeyType, ValueType, FMemoryImageSetAllocator, KeyFuncs>;
749 using ElementType = TCHAR;
778 return Data.Num() ? Data.GetData() :
TEXT(
"");
786 return Data.Num() ? Data.Num() - 1 : 0;
807 return FCString::Stricmp(**
this, *Rhs) == 0;
812 return FCString::Stricmp(**
this, *Rhs) != 0;
817 return FCString::Stricmp(**
this, *Rhs) == 0;
822 return FCString::Stricmp(**
this, *Rhs) != 0;
830 return FCrc::Strihash_DEPRECATED(*S);
835struct FHashedNameDebugString
843 uint32 IntrinsicUnfrozenCopy(
const FMemoryUnfreezeContent& Context,
const FHashedNameDebugString& Object,
void* OutDst);
861 inline uint64
GetHash()
const {
return Hash; }
862 inline bool IsNone()
const {
return Hash == 0u; }
865 const FHashedNameDebugString& GetDebugString()
const {
return DebugString; }
882 return GetTypeHash(Name.Hash);
886
887
888
904 template<
typename PtrType>
939template<
typename T,
typename PtrType>
1030#pragma warning(push)
1031#pragma warning(disable : 4583
)
1035
1036
1037
1038
1039
1040template<
typename T,
typename PtrType>
1092 inline T*
Get(
const FPtrTable& PtrTable)
const
1135 static_assert(
sizeof(PtrType) <=
sizeof(uint64),
"PtrType must fit within a standard pointer");
1147template<
typename T,
typename PtrType>
1150 return StaticGetTypeLayoutDesc<TIndexedPtrBase<T, PtrType>>();
1155 template<
typename T,
typename PtrType>
1172 template<
typename T,
typename PtrType>
1179 template<
typename T,
typename PtrType>
1185 template<
typename T,
typename PtrType>
1198template<
typename T,
typename PtrType>
1217 static_assert(
sizeof(PtrType) ==
sizeof(
void*),
"PtrType must be a standard pointer");
#define UE_NONCOPYABLE(TypeName)
#define WITH_EDITORONLY_DATA
#define UE_MEMORYIMAGE_TRACK_TYPE_DEPENDENCIES
FMemoryImageObject FreezeMemoryImageObject(const void *Object, const FTypeLayoutDesc &TypeDesc, FPointerTableBase *PointerTable)
void * UnfreezeMemoryImageObject(const void *FrozenObject, const FTypeLayoutDesc &TypeDesc, const FPointerTableBase *PointerTable)
#define DECLARE_TEMPLATE_INTRINSIC_TYPE_LAYOUT(TemplatePrefix, T)
#define LAYOUT_FIELD(T, Name,...)
#define LAYOUT_TOSTRING(Func)
#define DECLARE_EXPORTED_TYPE_LAYOUT(T, RequiredAPI, Interface)
#define LAYOUT_FIELD_EDITORONLY(T, Name,...)
#define DECLARE_INTRINSIC_TYPE_LAYOUT(T)
FHashedName(const TCHAR *InString)
FHashedName(const FName &InName)
bool operator==(const FHashedName &Rhs) const
bool operator!=(const FHashedName &Rhs) const
friend uint32 GetTypeHash(const FHashedName &Name)
FHashedName(const FString &InString)
FHashedName(const FHashedName &InName)
bool operator<(const FHashedName &Rhs) const
FHashedName(uint64 InHash)
FORCEINLINE FScriptContainerElement * GetAllocation() const
void ToString(const FTypeLayoutDesc &TypeDesc, int32 NumAllocatedElements, int32 MaxAllocatedElements, const FPlatformTypeLayoutParameters &LayoutParams, FMemoryToStringContext &OutContext) const
void CopyUnfrozen(const FMemoryUnfreezeContent &Context, const FTypeLayoutDesc &TypeDesc, int32 NumAllocatedElements, void *Dst) const
FMemoryImageAllocatorBase()=default
~FMemoryImageAllocatorBase()
FORCEINLINE int64 GetFrozenOffsetFromThis() const
FORCEINLINE SIZE_T GetAllocatedSize(int32 NumAllocatedElements, SIZE_T NumBytesPerElement) const
TMemoryImagePtr< FScriptContainerElement > Data
FORCEINLINE bool HasAllocation()
void MoveToEmpty(FMemoryImageAllocatorBase &Other)
void WriteMemoryImage(FMemoryImageWriter &Writer, const FTypeLayoutDesc &TypeDesc, int32 NumAllocatedElements, uint32 Alignment) const
void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement, uint32 Alignment)
TArray< TRefCountPtr< FMemoryImageSection > > Sections
const FPointerTableBase * PrevPointerTable
void Flatten(FMemoryImageResult &OutResult, bool bMergeDuplicateSections=false)
const FPointerTableBase & GetPrevPointerTable() const
FPointerTableBase & GetPointerTable() const
FMemoryImageSection * AllocateSection()
FPlatformTypeLayoutParameters HostLayoutParameters
FPointerTableBase * PointerTable
const struct UStruct * CurrentStruct
FPlatformTypeLayoutParameters TargetLayoutParameters
TArray< FSectionPointer > Pointers
TArray< FMemoryImageVTablePointer > VTables
uint32 WriteBytes(const T &Data)
uint32 WriteFScriptName(const FScriptName &Name)
uint32 WriteVTable(const FTypeLayoutDesc &TypeDesc, const FTypeLayoutDesc &DerivedTypeDesc)
FMemoryImageSection(FMemoryImage *InImage)
uint32 WriteZeroBytes(int32 Num)
FMemoryImageSection * WritePointer(const FTypeLayoutDesc &StaticTypeDesc, const FTypeLayoutDesc &DerivedTypeDesc, uint32 *OutOffsetToBase=nullptr)
FMemoryImage * ParentImage
void WritePaddingToSize(uint32 Offset)
uint32 WriteBytes(const void *Data, uint32 Size)
TArray< FMemoryImageNamePointer > MemoryImageNames
uint32 WriteRawPointerSizedBytes(uint64 PointerValue)
uint32 Flatten(FMemoryImageResult &OutResult) const
TArray< FMemoryImageNamePointer > ScriptNames
uint32 WriteFMemoryImageName(int32 NumBytes, const FName &Name)
uint32 WriteAlignment(uint32 Alignment)
FMemoryImageString & operator=(FMemoryImageString &&)=default
FORCEINLINE FMemoryImageString(const FString &Other)
friend FORCEINLINE uint32 GetTypeHash(const FMemoryImageString &S)
FORCEINLINE SIZE_T GetAllocatedSize() const
bool operator==(const FString &Rhs) const
FORCEINLINE FMemoryImageString(const CharType *Src)
FORCEINLINE const TCHAR * operator*() const
FMemoryImageString & operator=(const FMemoryImageString &)=default
friend int32 GetNum(const FMemoryImageString &String)
FORCEINLINE operator FString() const
friend const TCHAR * GetData(const FMemoryImageString &String)
FMemoryImageString()=default
FORCEINLINE bool IsEmpty() const
FORCEINLINE int32 Len() const
bool operator==(const FMemoryImageString &Rhs) const
FMemoryImageString(const FMemoryImageString &)=default
DataType::ElementAllocatorType & GetAllocatorInstance()
bool operator!=(const FMemoryImageString &Rhs) const
FMemoryImageString(FMemoryImageString &&)=default
void ToString(FMemoryToStringContext &OutContext) const
bool operator!=(const FString &Rhs) const
int32 Compare(const FName &Other) const
FORCEINLINE bool operator!=(FName Other) const
FORCEINLINE bool LexicalLess(const FName &Other) const
virtual void SaveToArchive(FArchive &Ar, const FPlatformTypeLayoutParameters &LayoutParams, const void *FrozenObject) const
virtual int32 AddIndexedPointer(const FTypeLayoutDesc &TypeDesc, void *Ptr)=0
virtual ~FPointerTableBase()
virtual void * GetIndexedPointer(const FTypeLayoutDesc &TypeDesc, uint32 i) const =0
virtual bool LoadFromArchive(FArchive &Ar, const FPlatformTypeLayoutParameters &LayoutParams, void *FrozenObject)
static void LoadAndApplyPatchesFromArchive(FArchive &Ar, void *FrozenBase, const PtrType &Ptr)
TArray< FPatchOffset > PatchOffsets
void AddPatchedPointerBase(uint32 PtrIndex, uint64 Offset)
void SavePatchesToArchive(FArchive &Ar, uint32 PtrIndex) const
TArray< FPatchOffsetList > PatchLists
TIndexedPtrBase(const TIndexedPtrBase< T, PtrType > &Rhs, const FPtrTable &InTable)
TIndexedPtrBase & operator=(T *Rhs)
T * Get(const FPtrTable &PtrTable) const
T * Get(const FPointerTableBase *PtrTable) const
TIndexedPtrBase & operator=(PtrType &&Rhs)
TIndexedPtrBase & operator=(const PtrType &Rhs)
TIndexedPtrBase(T *InPtr=nullptr)
TIndexedPtrBase(const TIndexedPtrBase< T, PtrType > &Rhs)
static void SafeReleaseImpl(TRefCountPtr< T > &InPtr)
static void SafeReleaseImpl(T *&InPtr)
FORCEINLINE int32 CalculateSlackReserve(int32 NumElements, int32 NumBytesPerElement, uint32 AlignmentOfElement) const
ForAnyElementType()=default
FORCEINLINE int32 CalculateSlackShrink(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement) const
FORCEINLINE int32 CalculateSlackReserve(int32 NumElements, int32 NumBytesPerElement) const
FORCEINLINE int32 CalculateSlackGrow(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement) const
FORCEINLINE SizeType GetInitialCapacity() const
FORCEINLINE void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement, uint32 AlignmentOfElement)
FORCEINLINE int32 CalculateSlackShrink(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement, uint32 AlignmentOfElement) const
FORCEINLINE int32 CalculateSlackGrow(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement, uint32 AlignmentOfElement) const
FORCEINLINE void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement)
FORCEINLINE void WriteMemoryImage(FMemoryImageWriter &Writer, const FTypeLayoutDesc &TypeDesc, int32 NumAllocatedElements) const
FORCEINLINE ElementType * GetAllocation() const
@ SupportsFreezeMemoryImage
void SafeDelete(const FPointerTableBase *PtrTable=nullptr)
TMemoryImagePtr & operator=(const TMemoryImagePtr< T > &InPtr)
int64 GetFrozenOffsetFromThis() const
TMemoryImagePtr & operator=(T *InPtr)
FFrozenMemoryImagePtr Frozen
T * GetFrozenPtrInternal() const
TMemoryImagePtr(T *InPtr=nullptr)
TMemoryImagePtr(const TMemoryImagePtr< T > &InPtr)
int32 GetFrozenTypeIndex() const
void WriteMemoryImageWithDerivedType(FMemoryImageWriter &Writer, const FTypeLayoutDesc *DerivedTypeDesc) const
TPatchedPtrBase(T *InPtr=nullptr)
TArray< PtrType >::RangedForConstIteratorType end() const
bool TryAddIndexedPtr(const FTypeLayoutDesc &TypeDesc, void *Ptr, int32 &OutIndex)
void Empty(int32 NewSize=0)
TArray< PtrType >::RangedForIteratorType end()
void AddPatchedPointer(T *Ptr, uint64 Offset)
TArray< PtrType > Pointers
void LoadIndexedPointer(T *Ptr)
TArray< PtrType >::RangedForIteratorType begin()
bool TryGetIndexedPtr(const FTypeLayoutDesc &TypeDesc, uint32 i, void *&OutPtr) const
static const FTypeLayoutDesc & StaticGetPtrTypeLayoutDesc()
void ApplyPointerPatches(void *FrozenBase) const
TArray< PtrType >::RangedForConstIteratorType begin() const
T * GetIndexedPointer(uint32 i) const
uint32 AddIndexedPointer(T *Ptr)
TUniqueMemoryImagePtr & operator=(T *InPtr)
TUniqueMemoryImagePtr & operator=(TUniqueMemoryImagePtr &&Other)
TUniqueMemoryImagePtr(T *InPtr)
TUniqueMemoryImagePtr(TUniqueMemoryImagePtr &&Other)
uint32 IntrinsicAppendHash(const TMemoryImagePtr< T > *DummyObject, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
uint32 IntrinsicAppendHash(const TIndexedPtrBase< T, PtrType > *DummyObject, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
uint32 IntrinsicGetTargetAlignment(const TMemoryImagePtr< T > *DummyObject, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams)
void IntrinsicToString(const FHashedName &Object, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FMemoryToStringContext &OutContext)
uint32 IntrinsicUnfrozenCopy(const FMemoryUnfreezeContent &Context, const TIndexedPtrBase< T, PtrType > &Object, void *OutDst)
void IntrinsicWriteMemoryImage(FMemoryImageWriter &Writer, const TIndexedPtrBase< T, PtrType > &Object, const FTypeLayoutDesc &TypeDesc)
uint32 IntrinsicGetTargetAlignment(const TIndexedPtrBase< T, PtrType > *DummyObject, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams)
uint32 IntrinsicUnfrozenCopy(const FMemoryUnfreezeContent &Context, const TMemoryImagePtr< T > &Object, void *OutDst)
void IntrinsicToString(const TMemoryImagePtr< T > &Object, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FMemoryToStringContext &OutContext)
void IntrinsicWriteMemoryImage(FMemoryImageWriter &Writer, const TMemoryImagePtr< T > &Object, const FTypeLayoutDesc &)
static constexpr uint64 bIsFrozenMask
void SetOffsetFromThis(int64 Offset)
int64 GetOffsetFromThis() const
static constexpr uint64 TypeIndexMask
static constexpr uint64 bIsFrozenShift
static constexpr uint64 OffsetShift
void SetIsFrozen(bool bTrue)
static constexpr uint64 TypeIndexBits
static constexpr uint64 TypeIndexShift
static constexpr uint64 OffsetMask
static constexpr uint64 bIsFrozenBits
static constexpr uint64 OffsetBits
int32 GetTypeIndex() const
void SetTypeIndex(int32 TypeIndex)
bool operator==(const FMemoryImageNamePointer &Rhs) const
bool operator<(const FMemoryImageNamePointer &Rhs) const
bool operator!=(const FMemoryImageNamePointer &Rhs) const
FPointerTableBase * PointerTable
void ApplyPatches(void *FrozenObject) const
static FMemoryImageObject LoadFromArchive(FArchive &Ar, const FTypeLayoutDesc &TypeDesc, FPointerTableBase *PointerTable, FPlatformTypeLayoutParameters &OutLayoutParameters)
FPlatformTypeLayoutParameters TargetLayoutParameters
TArray< FMemoryImageVTablePointer > VTables
TArray< FMemoryImageNamePointer > MemoryImageNames
void SaveToArchive(FArchive &Ar) const
TArray< FMemoryImageNamePointer > ScriptNames
bool operator==(const FMemoryImageVTablePointer &Rhs) const
bool operator!=(const FMemoryImageVTablePointer &Rhs) const
bool operator<(const FMemoryImageVTablePointer &Rhs) const
@ SupportsFreezeMemoryImage
@ SupportsElementAlignment
static constexpr bool Value
TMemoryImageObject(const FTypeLayoutDesc &InTypeDesc, T *InObject, uint32 InFrozenSize)
const FTypeLayoutDesc * TypeDesc
void Destroy(const FPointerTableBase *PointerTable)
TMemoryImageObject(const TMemoryImageObject< TOther > &Rhs)
bool Unfreeze(const FPointerTableBase *PointerTable)
TMemoryImageObject(TOther *InObject)
bool Freeze(FPointerTableBase *PointerTable)