Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
MemoryImage.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
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"
11#include "CoreTypes.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"
20#include "Misc/Crc.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"
31
32template <typename T> struct TIsContiguousContainer;
33
34#if defined(WITH_RTTI) || defined(_CPPRTTI) || defined(__GXX_RTTI) || WITH_EDITOR
35#include <typeinfo>
36#endif
37
38class FMemoryImage;
40
41// Store type dependencies for loaded frozen memory images
42// This uses a bit of memory and adds small CPU cost to loading, but is required to support unfreezing memory images that target platforms other than the current
43// This is also required for creating frozen memory images
44#define UE_MEMORYIMAGE_TRACK_TYPE_DEPENDENCIES (WITH_EDITORONLY_DATA)
45
47{
48public:
49 virtual ~FPointerTableBase() {}
50 virtual int32 AddIndexedPointer(const FTypeLayoutDesc& TypeDesc, void* Ptr) = 0;
51 virtual void* GetIndexedPointer(const FTypeLayoutDesc& TypeDesc, uint32 i) const = 0;
52
53 virtual void SaveToArchive(FArchive& Ar, const FPlatformTypeLayoutParameters& LayoutParams, const void* FrozenObject) const;
54 virtual bool LoadFromArchive(FArchive& Ar, const FPlatformTypeLayoutParameters& LayoutParams, void* FrozenObject);
55
57 int32 AddTypeDependency(const FTypeLayoutDesc& TypeDesc);
58 inline const FTypeLayoutDesc* GetTypeDependency(int32 Index) const { return TypeDependencies[Index]; }
59private:
60 TArray<const FTypeLayoutDesc*> TypeDependencies;
61#else
63 inline const FTypeLayoutDesc* GetTypeDependency(int32 Index) const { return nullptr; }
64#endif
65};
66
67template<typename T>
69{
70 TMemoryImageObject() : TypeDesc(nullptr), Object(nullptr), FrozenSize(0u) {}
71
72 TMemoryImageObject(const FTypeLayoutDesc& InTypeDesc, T* InObject, uint32 InFrozenSize)
76 {}
77
78 template<typename TOther>
79 TMemoryImageObject(TOther* InObject)
80 : TypeDesc(InObject ? &GetTypeLayoutDesc(nullptr, *InObject) : nullptr)
82 , FrozenSize(0u)
83 {}
84
85 template<typename TOther>
86 explicit TMemoryImageObject(const TMemoryImageObject<TOther>& Rhs)
88 , Object(static_cast<T*>(Rhs.Object))
90 {}
91
92 void Destroy(const FPointerTableBase* PointerTable);
93
94 // Returns true if the frozen/unfrozen state of the object was changed
95 bool Freeze(FPointerTableBase* PointerTable);
96 bool Unfreeze(const FPointerTableBase* PointerTable);
97
101};
102using FMemoryImageObject = TMemoryImageObject<void>;
103
104FMemoryImageObject FreezeMemoryImageObject(const void* Object, const FTypeLayoutDesc& TypeDesc, FPointerTableBase* PointerTable);
105void* UnfreezeMemoryImageObject(const void* FrozenObject, const FTypeLayoutDesc& TypeDesc, const FPointerTableBase* PointerTable);
106
107template<typename T>
108inline void TMemoryImageObject<T>::Destroy(const FPointerTableBase* PointerTable)
109{
110 if (Object)
111 {
112 InternalDeleteObjectFromLayout(Object, *TypeDesc, PointerTable, FrozenSize > 0u);
113 if (FrozenSize > 0u)
114 {
115 // InternalDeleteObjectFromLayout will delete unfrozen objects,
116 // but won't free frozen objects, since that's not safe for internal object pointers
117 // Here we are working with a root-level object, so it's safe to free it
118 FMemory::Free(Object);
119 }
120 Object = nullptr;
121 FrozenSize = 0u;
122 }
123}
124
125
126template<typename T>
127inline bool TMemoryImageObject<T>::Freeze(FPointerTableBase* PointerTable)
128{
129 if (FrozenSize == 0u && Object)
130 {
131 const FMemoryImageObject FrozenContent = FreezeMemoryImageObject(Object, *TypeDesc, PointerTable);
132 Destroy(nullptr);
133 Object = static_cast<T*>(FrozenContent.Object);
134 FrozenSize = FrozenContent.FrozenSize;
135 return true;
136 }
137 return false;
138}
139
140template<typename T>
141inline bool TMemoryImageObject<T>::Unfreeze(const FPointerTableBase* PointerTable)
142{
143 if (FrozenSize > 0u)
144 {
145 void* UnfrozenObject = UnfreezeMemoryImageObject(Object, *TypeDesc, PointerTable);
146 Destroy(PointerTable);
147 Object = static_cast<T*>(UnfrozenObject);
148 FrozenSize = 0u;
149 return true;
150 }
151 return false;
152}
153
155{
158 uint32 Offset;
159
160 inline bool operator==(const FMemoryImageVTablePointer& Rhs) const
161 {
162 return TypeNameHash == Rhs.TypeNameHash && VTableOffset == Rhs.VTableOffset && Offset == Rhs.Offset;
163 }
164 inline bool operator!=(const FMemoryImageVTablePointer& Rhs) const
165 {
166 return !(*this == Rhs);
167 }
168 inline bool operator<(const FMemoryImageVTablePointer& Rhs) const
169 {
172 return Offset < Rhs.Offset;
173 }
174};
175
177{
179 uint32 Offset;
180
181 inline bool operator==(const FMemoryImageNamePointer& Rhs) const
182 {
183 return Offset == Rhs.Offset && Name.Compare(Rhs.Name) == 0;
184 }
185 inline bool operator!=(const FMemoryImageNamePointer& Rhs) const
186 {
187 return !(*this == Rhs);
188 }
189 inline bool operator<(const FMemoryImageNamePointer& Rhs) const
190 {
191 if (Name != Rhs.Name)
192 {
193 return Name.LexicalLess(Rhs.Name);
194 }
195 return Offset < Rhs.Offset;
196 }
197};
198
200{
207
208 void SaveToArchive(FArchive& Ar) const;
209 void ApplyPatches(void* FrozenObject) const;
210 static FMemoryImageObject LoadFromArchive(FArchive& Ar, const FTypeLayoutDesc& TypeDesc, FPointerTableBase* PointerTable, FPlatformTypeLayoutParameters& OutLayoutParameters);
211};
212
214{
215public:
217 {
220 uint32 Offset;
221 };
222
224 : ParentImage(InImage)
225 , MaxAlignment(1u)
226 {}
227
228 uint32 GetOffset() const { return Bytes.Num(); }
229
230 uint32 WriteAlignment(uint32 Alignment)
231 {
232 const uint32 PrevSize = Bytes.Num();
233 const uint32 Offset = Align(PrevSize, Alignment);
234 Bytes.SetNumZeroed(Offset);
235 MaxAlignment = FMath::Max(MaxAlignment, Alignment);
236 return Offset;
237 }
238
239 void WritePaddingToSize(uint32 Offset)
240 {
241 check(Offset >= (uint32)Bytes.Num());
242 Bytes.SetNumZeroed(Offset);
243 }
244
245 uint32 WriteBytes(const void* Data, uint32 Size)
246 {
247 const uint32 Offset = GetOffset();
248 Bytes.SetNumUninitialized(Offset + Size);
249 FMemory::Memcpy(Bytes.GetData() + Offset, Data, Size);
250 return Offset;
251 }
252
253 uint32 WriteZeroBytes(int32 Num)
254 {
255 const uint32 Offset = GetOffset();
256 Bytes.SetNumZeroed(Offset + Num);
257 return Offset;
258 }
259
260 template<typename T>
261 uint32 WriteBytes(const T& Data) { return WriteBytes(&Data, sizeof(T)); }
262
263 FMemoryImageSection* WritePointer(const FTypeLayoutDesc& StaticTypeDesc, const FTypeLayoutDesc& DerivedTypeDesc, uint32* OutOffsetToBase = nullptr);
264 uint32 WriteRawPointerSizedBytes(uint64 PointerValue);
265 uint32 WriteVTable(const FTypeLayoutDesc& TypeDesc, const FTypeLayoutDesc& DerivedTypeDesc);
266 uint32 WriteFMemoryImageName(int32 NumBytes, const FName& Name);
267 uint32 WriteFScriptName(const FScriptName& Name);
268 uint32 Flatten(FMemoryImageResult& OutResult) const;
269
271
280};
281
283{
284public:
286 : PointerTable(nullptr)
287 , PrevPointerTable(nullptr)
288 , CurrentStruct(nullptr)
289 {
291 }
292
293 FPointerTableBase& GetPointerTable() const { check(PointerTable); return *PointerTable; }
294 const FPointerTableBase& GetPrevPointerTable() const { check(PrevPointerTable); return *PrevPointerTable; }
295
297 {
299 // reserving memory here could reduce the reallocations, but leads to huge spikes for images with many sections. TODO: try chunked array or a better heuristic value for reservation
300 Sections.Add(Section);
301 return Section;
302 }
303
304 /** Merging duplicate sections will make the resulting memory image smaller.
305 * This will only work for data that is expected to be read-only after freezing. Merging sections will break any manual fix-ups applied to the frozen data
306 */
307 void Flatten(FMemoryImageResult& OutResult, bool bMergeDuplicateSections = false);
308
314 const struct UStruct* CurrentStruct;
315};
316
317/**
318 * Value of this struct should never be a valid unfrozen pointer (i.e. a memory address). We rely on real pointers to have lowest bit(s) 0 this days for the alignment, this is checked later.
319 * Unfortunately, we cannot use bitfields as their layout might be compiler-specific, and the data for the target platform is being prepared with a different compiler during the cook.
320 */
322{
323 static constexpr uint64 bIsFrozenBits = 1;
324 static constexpr uint64 OffsetBits = 40;
325 static constexpr uint64 TypeIndexBits = 64 - OffsetBits - bIsFrozenBits;
326
327 static constexpr uint64 bIsFrozenShift = 0;
328 static constexpr uint64 TypeIndexShift = bIsFrozenBits;
329 static constexpr uint64 OffsetShift = bIsFrozenBits + TypeIndexBits;
330
331 static constexpr uint64 bIsFrozenMask = (1ULL << bIsFrozenShift);
332 static constexpr uint64 TypeIndexMask = (((1ULL << TypeIndexBits) - 1ULL) << TypeIndexShift);
333 static constexpr uint64 OffsetMask = (((1ULL << OffsetBits) - 1ULL) << OffsetShift);
334
335 uint64 Packed;
336
337 /** Whether the value is indeed a frozen pointer, must come first to avoid being set in regular pointers - which are expected to point at padded things so are never even. */
338 bool IsFrozen() const
339 {
340 return (Packed & bIsFrozenMask) != 0;
341 }
342
343 void SetIsFrozen(bool bTrue)
344 {
345 Packed = (Packed & ~bIsFrozenMask) | (bTrue ? 1 : 0);
346 }
347
348 /** Signed offset from the current position in the memory image. */
349 int64 GetOffsetFromThis() const
350 {
351 // Since the offset occupies the highest part of the int64, its sign is preserved.
352 // Not masking as there's nothing to the left of the Offset
353 static_assert(OffsetShift + OffsetBits == 64);
354 return static_cast<int64>(Packed/* & OffsetMask*/) >> OffsetShift;
355 }
356
357 void SetOffsetFromThis(int64 Offset)
358 {
359 Packed = (Packed & ~OffsetMask) | (static_cast<uint64>(Offset << OffsetShift) & OffsetMask);
360 }
361
362 /** The pointer type index in the pointer table. Does not store other negative values except for INDEX_NONE */
363 int32 GetTypeIndex() const
364 {
365 return static_cast<int32>((Packed & TypeIndexMask) >> TypeIndexShift) - 1;
366 }
367
368 void SetTypeIndex(int32 TypeIndex)
369 {
370 static_assert(INDEX_NONE == -1, "TypeIndex cannot store INDEX_NONE when it's not -1");
371 // PVS warns about a possible overflow in TypeIndex + 1. We don't care as we don't expect 2^31 type indices anyway
372 Packed = (Packed & ~TypeIndexMask) | ((static_cast<uint64>(TypeIndex + 1) << TypeIndexShift) & TypeIndexMask); //-V1028
373 }
374};
375
376static_assert(sizeof(FFrozenMemoryImagePtr) == sizeof(uint64), "FFrozenMemoryImagePtr is larger than a native pointer would be");
377
378template<typename T>
380{
381public:
382 inline bool IsFrozen() const { return Frozen.IsFrozen(); }
383 inline bool IsValid() const { return UnfrozenPtr != nullptr; }
384 inline bool IsNull() const { return UnfrozenPtr == nullptr; }
385
386 inline TMemoryImagePtr(T* InPtr = nullptr) : UnfrozenPtr(InPtr) { check(!Frozen.IsFrozen()); }
388 inline TMemoryImagePtr& operator=(T* InPtr) { UnfrozenPtr = InPtr; check(!Frozen.IsFrozen()); return *this; }
389 inline TMemoryImagePtr& operator=(const TMemoryImagePtr<T>& InPtr) { UnfrozenPtr = InPtr.Get(); check(!Frozen.IsFrozen()); return *this; }
390
392 {
393
394 }
395
396 inline int64 GetFrozenOffsetFromThis() const { check(IsFrozen()); return Frozen.GetOffsetFromThis(); }
397 inline int32 GetFrozenTypeIndex() const { check(IsFrozen()); return Frozen.GetTypeIndex(); }
398
399 inline T* Get() const
400 {
402 }
403
404 inline T* GetChecked() const { T* Value = Get(); check(Value); return Value; }
405 inline T* operator->() const { return GetChecked(); }
406 inline T& operator*() const { return *GetChecked(); }
407 inline operator T*() const { return Get(); }
408
409 void SafeDelete(const FPointerTableBase* PtrTable = nullptr)
410 {
411 T* RawPtr = Get();
412 if (RawPtr)
413 {
415 UnfrozenPtr = nullptr;
416 }
417 }
418
419 void WriteMemoryImageWithDerivedType(FMemoryImageWriter& Writer, const FTypeLayoutDesc* DerivedTypeDesc) const
420 {
421 const T* RawPtr = Get();
422 if (RawPtr)
423 {
425 uint32 OffsetToBase = 0u;
428 }
429 else
430 {
432 }
433 }
434
435private:
436 inline T* GetFrozenPtrInternal() const
437 {
438 return (T*)((char*)this + Frozen.GetOffsetFromThis());
439 }
440
441protected:
442 union
443 {
444 uint64 Packed;
447 };
448};
449
450namespace Freeze
451{
452 template<typename T>
454 {
455 T* RawPtr = Object.Get();
456 if (RawPtr)
457 {
459
460 uint32 OffsetToBase = 0u;
463 }
464 else
465 {
467 }
468 }
469
470 template<typename T>
471 uint32 IntrinsicUnfrozenCopy(const FMemoryUnfreezeContent& Context, const TMemoryImagePtr<T>& Object, void* OutDst)
472 {
473 const T* RawPtr = Object.Get();
474 if (RawPtr)
475 {
476 // Compile-time type of the thing we're pointing to
478
479 // Actual run-time type of the thing we're pointing to
482 {
483 // It's possible we won't be able to get derived type desc from the context, if we're not storing type dependencies
484 // In this case, if we're unfreezing data for the current platform, we can just grab the derived type directly from the frozen object
485 // If we're NOT unfreezing data for current platform, we can't access the frozen object, so we'll fail in that case
487 }
488 if (DerivedTypeDesc)
489 {
490 // 'this' offset to adjust from the compile-time type to the run-time type
492
497 }
498 else
499 {
500 new(OutDst) TMemoryImagePtr<T>(nullptr);
501 }
502 }
503 else
504 {
505 new(OutDst) TMemoryImagePtr<T>(nullptr);
506 }
507 return sizeof(Object);
508 }
509
510 template<typename T>
511 uint32 IntrinsicAppendHash(const TMemoryImagePtr<T>* DummyObject, const FTypeLayoutDesc& TypeDesc, const FPlatformTypeLayoutParameters& LayoutParams, FSHA1& Hasher)
512 {
514 }
515
516 template<typename T>
517 inline uint32 IntrinsicGetTargetAlignment(const TMemoryImagePtr<T>* DummyObject, const FTypeLayoutDesc& TypeDesc, const FPlatformTypeLayoutParameters& LayoutParams)
518 {
520 }
521
522 template<typename T>
523 void IntrinsicToString(const TMemoryImagePtr<T>& Object, const FTypeLayoutDesc& TypeDesc, const FPlatformTypeLayoutParameters& LayoutParams, FMemoryToStringContext& OutContext)
524 {
525 T* RawPtr = Object.Get();
526 if (RawPtr)
527 {
528 // Compile-time type of the thing we're pointing to
530 // Actual run-time type of the thing we're pointing to
532 // 'this' offset to adjust from the compile-time type to the run-time type
534
535 if (Object.IsFrozen())
536 {
538 }
539 else
540 {
542 }
544 }
545 else
546 {
548 }
549 }
550}
551
553
554template<typename T>
556{
557public:
559 : TMemoryImagePtr<T>(nullptr)
560 {}
561 explicit inline TUniqueMemoryImagePtr(T* InPtr)
563 { }
564
566 {
567 this->SafeDelete();
568 this->Ptr = Other.Ptr;
569 Other.Ptr = nullptr;
570 }
572 {
573 this->SafeDelete();
574 }
576 {
577 this->SafeDelete();
578 this->Ptr = InPtr;
579 }
581 {
582 if (this != &Other)
583 {
584 // We _should_ delete last like TUniquePtr, but we have issues with SafeDelete, and being Frozen or not
585 this->SafeDelete();
586 this->Ptr = Other.Ptr;
587 Other.Ptr = nullptr;
588 }
589
590 return *this;
591 }
592
593};
594
596{
598public:
600
601 /**
602 * Moves the state of another allocator into this one.
603 * Assumes that the allocator is currently empty, i.e. memory may be allocated but any existing elements have already been destructed (if necessary).
604 * @param Other - The allocator to move the state from. This allocator should be left in a valid empty state.
605 */
607
608 /** Destructor. */
610
611 // FContainerAllocatorInterface
613 {
614 return Data.Get();
615 }
616
617 FORCEINLINE SIZE_T GetAllocatedSize(int32 NumAllocatedElements, SIZE_T NumBytesPerElement) const
618 {
619 return NumAllocatedElements * NumBytesPerElement;
620 }
622 {
623 return Data.IsValid();
624 }
625 FORCEINLINE int64 GetFrozenOffsetFromThis() const { return Data.GetFrozenOffsetFromThis(); }
626
627 void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement, uint32 Alignment);
628 void WriteMemoryImage(FMemoryImageWriter& Writer, const FTypeLayoutDesc& TypeDesc, int32 NumAllocatedElements, uint32 Alignment) const;
629 void ToString(const FTypeLayoutDesc& TypeDesc, int32 NumAllocatedElements, int32 MaxAllocatedElements, const FPlatformTypeLayoutParameters& LayoutParams, FMemoryToStringContext& OutContext) const;
630 void CopyUnfrozen(const FMemoryUnfreezeContent& Context, const FTypeLayoutDesc& TypeDesc, int32 NumAllocatedElements, void* Dst) const;
631
632private:
634};
635
636template<uint32 Alignment = DEFAULT_ALIGNMENT>
638{
639public:
640 using SizeType = int32;
641
642 enum { NeedsElementType = false };
643 enum { RequireRangeCheck = true };
645
647 {
648 public:
649 /** Default constructor. */
650 ForAnyElementType() = default;
651
653 {
654 return 0;
655 }
656 FORCEINLINE int32 CalculateSlackReserve(int32 NumElements, int32 NumBytesPerElement) const
657 {
659 }
660 FORCEINLINE int32 CalculateSlackReserve(int32 NumElements, int32 NumBytesPerElement, uint32 AlignmentOfElement) const
661 {
663 }
664 FORCEINLINE int32 CalculateSlackShrink(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement) const
665 {
667 }
668 FORCEINLINE int32 CalculateSlackShrink(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement, uint32 AlignmentOfElement) const
669 {
671 }
672 FORCEINLINE int32 CalculateSlackGrow(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement) const
673 {
675 }
676 FORCEINLINE int32 CalculateSlackGrow(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement, uint32 AlignmentOfElement) const
677 {
679 }
680 FORCEINLINE void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement)
681 {
683 }
684 FORCEINLINE void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement, uint32 AlignmentOfElement)
685 {
687 }
688
689 FORCEINLINE void WriteMemoryImage(FMemoryImageWriter& Writer, const FTypeLayoutDesc& TypeDesc, int32 NumAllocatedElements) const
690 {
692 }
693 };
694
695 template<typename ElementType>
697 {
698 public:
701 };
702};
703
704//@todo stever
705/*static_assert(
706 sizeof(TMemoryImageAllocator<>::ForAnyElementType) == sizeof(FDefaultAllocator::ForAnyElementType) && alignof(TMemoryImageAllocator<>::ForAnyElementType) == alignof(FDefaultAllocator::ForAnyElementType),
707 "TMemoryImageAllocator must be the same layout as FDefaultAllocator for our FScriptArray hacks to work"
708);*/
709
710template <uint32 Alignment>
712{
713 enum { IsZeroConstruct = true };
716};
717
718using FMemoryImageAllocator = TMemoryImageAllocator<>;
719
720using FMemoryImageSparseArrayAllocator = TSparseArrayAllocator<FMemoryImageAllocator, FMemoryImageAllocator>;
721using FMemoryImageSetAllocator = TSetAllocator<FMemoryImageSparseArrayAllocator, FMemoryImageAllocator>;
722
723template<typename T>
724using TMemoryImageArray = TArray<T, FMemoryImageAllocator>;
725
726template<typename ElementType, typename KeyFuncs = DefaultKeyFuncs<ElementType>>
727using TMemoryImageSet = TSet<ElementType, KeyFuncs, FMemoryImageSetAllocator>;
728
729template <typename KeyType, typename ValueType, typename KeyFuncs = TDefaultMapHashableKeyFuncs<KeyType, ValueType, false>>
730using TMemoryImageMap = TMap<KeyType, ValueType, FMemoryImageSetAllocator, KeyFuncs>;
731
732template <>
734{
735 static constexpr bool Value = true;
736};
737
739{
741private:
742 /** Array holding the character data */
744 LAYOUT_FIELD(DataType, Data);
745
746 void ToString(FMemoryToStringContext& OutContext) const;
748public:
749 using ElementType = TCHAR;
750
756
758
759 template <
760 typename CharType,
761 typename = typename TEnableIf<TIsCharType<CharType>::Value>::Type // This TEnableIf is to ensure we don't instantiate this constructor for non-char types, like id* in Obj-C
762 >
763 FORCEINLINE FMemoryImageString(const CharType* Src)
764 {
765 if (Src && *Src)
766 {
771 }
772 }
773
774 FORCEINLINE operator FString() const { return FString(Len(), Data.GetData()); }
775
776 FORCEINLINE const TCHAR* operator*() const
777 {
778 return Data.Num() ? Data.GetData() : TEXT("");
779 }
780
781 FORCEINLINE bool IsEmpty() const { return Data.Num() <= 1; }
782 FORCEINLINE SIZE_T GetAllocatedSize() const { return Data.GetAllocatedSize(); }
783
784 FORCEINLINE int32 Len() const
785 {
786 return Data.Num() ? Data.Num() - 1 : 0;
787 }
788
789 friend inline const TCHAR* GetData(const FMemoryImageString& String)
790 {
791 return *String;
792 }
793
794 friend inline int32 GetNum(const FMemoryImageString& String)
795 {
796 return String.Len();
797 }
798
799 friend inline FArchive& operator<<(FArchive& Ar, FMemoryImageString& Ref)
800 {
801 Ar << Ref.Data;
802 return Ar;
803 }
804
805 inline bool operator==(const FMemoryImageString& Rhs) const
806 {
807 return FCString::Stricmp(**this, *Rhs) == 0;
808 }
809
810 inline bool operator!=(const FMemoryImageString& Rhs) const
811 {
812 return FCString::Stricmp(**this, *Rhs) != 0;
813 }
814
815 inline bool operator==(const FString& Rhs) const
816 {
817 return FCString::Stricmp(**this, *Rhs) == 0;
818 }
819
820 inline bool operator!=(const FString& Rhs) const
821 {
822 return FCString::Stricmp(**this, *Rhs) != 0;
823 }
824
825 inline DataType::ElementAllocatorType& GetAllocatorInstance() { return Data.GetAllocatorInstance(); }
826
827 /** Case insensitive string hash function. */
829 {
830 return FCrc::Strihash_DEPRECATED(*S);
831 }
832};
833
835struct FHashedNameDebugString
836{
837 TMemoryImagePtr<const char> String;
838};
839
840namespace Freeze
841{
842 void IntrinsicWriteMemoryImage(FMemoryImageWriter& Writer, const FHashedNameDebugString& Object, const FTypeLayoutDesc&);
843 uint32 IntrinsicUnfrozenCopy(const FMemoryUnfreezeContent& Context, const FHashedNameDebugString& Object, void* OutDst);
844}
845
846DECLARE_INTRINSIC_TYPE_LAYOUT(FHashedNameDebugString);
847
848#endif // WITH_EDITORONLY_DATA
849
851{
853public:
854 inline FHashedName() : Hash(0u) {}
855 explicit FHashedName(uint64 InHash);
856 FHashedName(const FHashedName& InName);
857 FHashedName(const TCHAR* InString);
858 FHashedName(const FString& InString);
859 FHashedName(const FName& InName);
860
861 inline uint64 GetHash() const { return Hash; }
862 inline bool IsNone() const { return Hash == 0u; }
863
865 const FHashedNameDebugString& GetDebugString() const { return DebugString; }
866#endif
867
868 inline bool operator==(const FHashedName& Rhs) const { return Hash == Rhs.Hash; }
869 inline bool operator!=(const FHashedName& Rhs) const { return Hash != Rhs.Hash; }
870
871 /** For sorting by name */
872 inline bool operator<(const FHashedName& Rhs) const { return Hash < Rhs.Hash; }
873
874 friend inline FArchive& operator<<(FArchive& Ar, FHashedName& String)
875 {
876 Ar << String.Hash;
877 return Ar;
878 }
879
880 friend inline uint32 GetTypeHash(const FHashedName& Name)
881 {
882 return GetTypeHash(Name.Hash);
883 }
884
885 /*inline FString ToString() const
886 {
887 return FString::Printf(TEXT("0x%016X"), Hash);
888 }*/
889
890private:
891 LAYOUT_FIELD(uint64, Hash);
892 LAYOUT_FIELD_EDITORONLY(FHashedNameDebugString, DebugString);
893};
894
895namespace Freeze
896{
897 void IntrinsicToString(const FHashedName& Object, const FTypeLayoutDesc& TypeDesc, const FPlatformTypeLayoutParameters& LayoutParams, FMemoryToStringContext& OutContext);
898}
899
900
902{
903public:
904 template<typename PtrType>
905 static void LoadAndApplyPatchesFromArchive(FArchive& Ar, void* FrozenBase, const PtrType& Ptr)
906 {
907 int32 NumOffsets = 0;
908 Ar << NumOffsets;
910 {
911 uint32 Offset = 0u;
912 Ar << Offset;
913 new((char*)FrozenBase + Offset) PtrType(Ptr);
914 }
915 }
916
917 void SavePatchesToArchive(FArchive& Ar, uint32 PtrIndex) const;
918
919protected:
921 {
922 uint32 Offset;
923 uint32 NextIndex;
924 };
925
927 {
931 };
932
933 void AddPatchedPointerBase(uint32 PtrIndex, uint64 Offset);
934
937};
938
939template<typename T, typename PtrType>
941{
942public:
944
945 void Empty(int32 NewSize = 0)
946 {
948 }
949
950 uint32 Num() const { return Pointers.Num(); }
951 uint32 AddIndexedPointer(T* Ptr) { check(Ptr); return Pointers.AddUnique(Ptr); }
952
953 bool TryAddIndexedPtr(const FTypeLayoutDesc& TypeDesc, void* Ptr, int32& OutIndex)
954 {
956 {
957 OutIndex = AddIndexedPointer(static_cast<T*>(Ptr));
958 return true;
959 }
960 return false;
961 }
962
964 {
965 if (Ptr)
966 {
969 }
970 else
971 {
972 // allow duplicate nullptrs
973 // pointers that were valid when saving may not be found when loading, need to preserve indices
974 Pointers.Add(nullptr);
975 }
976 }
977
978 void AddPatchedPointer(T* Ptr, uint64 Offset)
979 {
982 }
983
984 T* GetIndexedPointer(uint32 i) const { return Pointers[i]; }
985
986 bool TryGetIndexedPtr(const FTypeLayoutDesc& TypeDesc, uint32 i, void*& OutPtr) const
987 {
989 {
991 return true;
992 }
993 return false;
994 }
995
996 void ApplyPointerPatches(void* FrozenBase) const
997 {
998 for (int32 PtrIndex = 0; PtrIndex < PatchLists.Num(); ++PtrIndex)
999 {
1001 while (PatchIndex != ~0u)
1002 {
1006 }
1007 }
1008 }
1009
1010 inline typename TArray<PtrType>::RangedForIteratorType begin() { return Pointers.begin(); }
1011 inline typename TArray<PtrType>::RangedForIteratorType end() { return Pointers.end(); }
1012 inline typename TArray<PtrType>::RangedForConstIteratorType begin() const { return Pointers.begin(); }
1013 inline typename TArray<PtrType>::RangedForConstIteratorType end() const { return Pointers.end(); }
1014private:
1016};
1017
1018template<typename T>
1019class TPtrTable : public TPtrTableBase<T, T*> {};
1020
1021template<typename T>
1023{
1024 using Super = TPtrTableBase<T, TRefCountPtr<T>>;
1025};
1026
1027class FVoidPtrTable : public TPtrTableBase<void, void*> {};
1028
1029#ifdef _MSC_VER
1030#pragma warning(push)
1031#pragma warning(disable : 4583) // destructor is not implicitly called
1032#endif
1033
1034/**
1035 * Note that IndexedPtr types don't declare a default intrinsic type layout.
1036 * Instead any required pointer types need to be declared/implemented using DECLARE_EXPORTED_TEMPLATE_INTRINSIC_TYPE_LAYOUT/IMPLEMENT_TEMPLATE_INTRINSIC_TYPE_LAYOUT.
1037 * The TypeDesc of indexed pointers are compared for equality when adding to pointer tables,
1038 * and it's possible for inline type layouts to generate multiple copies when referenced from multiple modules
1039 */
1040template<typename T, typename PtrType>
1042{
1043public:
1044 using FPtrTable = TPtrTableBase<T, PtrType>;
1045
1046 inline TIndexedPtrBase(T* InPtr = nullptr) : Ptr(InPtr) {}
1047 inline ~TIndexedPtrBase() { if(!IsFrozen()) Ptr.~PtrType(); }
1048
1049 // Copy constructor requires an unfrozen source
1050 inline TIndexedPtrBase(const TIndexedPtrBase<T, PtrType>& Rhs) : Ptr(Rhs.GetUnfrozen()) {}
1051
1052 inline TIndexedPtrBase(const TIndexedPtrBase<T, PtrType>& Rhs, const FPtrTable& InTable) : Ptr(Rhs.Get(InTable)) {}
1053
1054 inline TIndexedPtrBase& operator=(T* Rhs)
1055 {
1056 // If not currently frozen, invoke the standard assignment operator for the underlying pointer type
1057 // If frozen, construct a new (non-frozen) pointer over the existing frozen offset
1058 if (!IsFrozen()) Ptr = Rhs;
1059 else new(&Ptr) PtrType(Rhs);
1060 check(!IsFrozen());
1061 return *this;
1062 }
1063
1064 inline TIndexedPtrBase& operator=(const PtrType& Rhs)
1065 {
1066 if (!IsFrozen()) Ptr = Rhs;
1067 else new(&Ptr) PtrType(Rhs);
1068 check(!IsFrozen());
1069 return *this;
1070 }
1071
1072 inline TIndexedPtrBase& operator=(PtrType&& Rhs)
1073 {
1074 if (!IsFrozen()) Ptr = Rhs;
1075 else new(&Ptr) PtrType(Rhs);
1076 check(!IsFrozen());
1077 return *this;
1078 }
1079
1080 inline bool IsFrozen() const { return PackedIndex & IsFrozenMask; }
1081 inline bool IsValid() const { return PackedIndex != 0u; } // works for both frozen/unfrozen cases
1082 inline bool IsNull() const { return PackedIndex == 0u; }
1083
1084 inline void SafeRelease()
1085 {
1086 if (!IsFrozen())
1087 {
1089 }
1090 }
1091
1092 inline T* Get(const FPtrTable& PtrTable) const
1093 {
1094 if (IsFrozen())
1095 {
1097 }
1098 return Ptr;
1099 }
1100
1101 inline T* Get(const FPointerTableBase* PtrTable) const
1102 {
1103 if (IsFrozen())
1104 {
1105 check(PtrTable);
1107 return static_cast<T*>(PtrTable->GetIndexedPointer(TypeDesc, (uint32)(PackedIndex >> IndexShift)));
1108 }
1109 return Ptr;
1110 }
1111
1112 inline T* GetUnfrozen() const { check(!IsFrozen()); return Ptr; }
1113
1114private:
1115 enum
1116 {
1117 IsFrozenMask = (1 << 0),
1119 };
1120
1121 static void SafeReleaseImpl(T*& InPtr)
1122 {
1123 if (InPtr)
1124 {
1125 delete InPtr;
1126 InPtr = nullptr;
1127 }
1128 }
1129
1130 static void SafeReleaseImpl(TRefCountPtr<T>& InPtr)
1131 {
1133 }
1134
1135 static_assert(sizeof(PtrType) <= sizeof(uint64), "PtrType must fit within a standard pointer");
1136 union
1137 {
1138 PtrType Ptr;
1140 };
1141};
1142
1143#ifdef _MSC_VER
1144#pragma warning(pop)
1145#endif
1146
1147template<typename T, typename PtrType>
1149{
1150 return StaticGetTypeLayoutDesc<TIndexedPtrBase<T, PtrType>>();
1151}
1152
1153namespace Freeze
1154{
1155 template<typename T, typename PtrType>
1156 void IntrinsicWriteMemoryImage(FMemoryImageWriter& Writer, const TIndexedPtrBase<T, PtrType>& Object, const FTypeLayoutDesc& TypeDesc)
1157 {
1159 if (RawPtr)
1160 {
1163 const uint64 FrozenPackedIndex = ((uint64)Index << 1u) | 1u;
1165 }
1166 else
1167 {
1169 }
1170 }
1171
1172 template<typename T, typename PtrType>
1173 uint32 IntrinsicUnfrozenCopy(const FMemoryUnfreezeContent& Context, const TIndexedPtrBase<T, PtrType>& Object, void* OutDst)
1174 {
1176 return sizeof(Object);
1177 }
1178
1179 template<typename T, typename PtrType>
1180 uint32 IntrinsicAppendHash(const TIndexedPtrBase<T, PtrType>* DummyObject, const FTypeLayoutDesc& TypeDesc, const FPlatformTypeLayoutParameters& LayoutParams, FSHA1& Hasher)
1181 {
1183 }
1184
1185 template<typename T, typename PtrType>
1186 inline uint32 IntrinsicGetTargetAlignment(const TIndexedPtrBase<T, PtrType>* DummyObject, const FTypeLayoutDesc& TypeDesc, const FPlatformTypeLayoutParameters& LayoutParams)
1187 {
1189 }
1190}
1191
1192template<typename T>
1193using TIndexedPtr = TIndexedPtrBase<T, T*>;
1194
1195template<typename T>
1196using TIndexedRefCountPtr = TIndexedPtrBase<T, TRefCountPtr<T>>;
1197
1198template<typename T, typename PtrType>
1200{
1201public:
1202 using FPtrTable = TPtrTableBase<T, PtrType>;
1203
1204 inline TPatchedPtrBase(T* InPtr = nullptr) : Ptr(InPtr) {}
1205
1206 inline T* Get() const
1207 {
1208 return Ptr;
1209 }
1210
1211 inline T* GetChecked() const { T* Value = Get(); check(Value); return Value; }
1212 inline T* operator->() const { return GetChecked(); }
1213 inline T& operator*() const { return *GetChecked(); }
1214 inline operator T*() const { return Get(); }
1215
1216private:
1217 static_assert(sizeof(PtrType) == sizeof(void*), "PtrType must be a standard pointer");
1218 PtrType Ptr;
1219};
1220
1221template<typename T>
1222using TPatchedPtr = TPatchedPtrBase<T, T*>;
1223
1224template<typename T>
1225using TPatchedRefCountPtr = TPatchedPtrBase<T, TRefCountPtr<T>>;
#define checkSlow(expr)
#define check(expr)
#define WITH_EDITOR
Definition Build.h:7
@ INDEX_NONE
#define UE_NONCOPYABLE(TypeName)
#define WITH_EDITORONLY_DATA
@ DEFAULT_ALIGNMENT
Definition MemoryBase.h:24
#define UE_MEMORYIMAGE_TRACK_TYPE_DEPENDENCIES
Definition MemoryImage.h:44
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)
#define TEXT(x)
Definition Platform.h:1108
#define FORCEINLINE
Definition Platform.h:644
FHashedName(const TCHAR *InString)
bool IsNone() const
FHashedName(const FName &InName)
bool operator==(const FHashedName &Rhs) const
bool operator!=(const FHashedName &Rhs) const
uint64 GetHash() 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
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)
TArray< uint8 > Bytes
uint32 Flatten(FMemoryImageResult &OutResult) const
TArray< FMemoryImageNamePointer > ScriptNames
uint32 WriteFMemoryImageName(int32 NumBytes, const FName &Name)
uint32 GetOffset() const
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
Definition NameTypes.h:750
FORCEINLINE bool LexicalLess(const FName &Other) const
Definition NameTypes.h:779
virtual void SaveToArchive(FArchive &Ar, const FPlatformTypeLayoutParameters &LayoutParams, const void *FrozenObject) const
virtual int32 AddIndexedPointer(const FTypeLayoutDesc &TypeDesc, void *Ptr)=0
virtual ~FPointerTableBase()
Definition MemoryImage.h:49
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
bool IsValid() const
TIndexedPtrBase(const TIndexedPtrBase< T, PtrType > &Rhs, const FPtrTable &InTable)
T * GetUnfrozen() const
TIndexedPtrBase & operator=(T *Rhs)
T * Get(const FPtrTable &PtrTable) const
bool IsFrozen() const
T * Get(const FPointerTableBase *PtrTable) const
TIndexedPtrBase & operator=(PtrType &&Rhs)
TIndexedPtrBase & operator=(const PtrType &Rhs)
bool IsNull() const
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
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
bool IsValid() const
T * operator->() const
void SafeDelete(const FPointerTableBase *PtrTable=nullptr)
TMemoryImagePtr & operator=(const TMemoryImagePtr< T > &InPtr)
int64 GetFrozenOffsetFromThis() const
TMemoryImagePtr & operator=(T *InPtr)
FFrozenMemoryImagePtr Frozen
T * GetFrozenPtrInternal() const
T * Get() const
T * GetChecked() const
operator T*() const
bool IsFrozen() const
TMemoryImagePtr(T *InPtr=nullptr)
TMemoryImagePtr(const TMemoryImagePtr< T > &InPtr)
bool IsNull() const
int32 GetFrozenTypeIndex() const
void WriteMemoryImageWithDerivedType(FMemoryImageWriter &Writer, const FTypeLayoutDesc *DerivedTypeDesc) const
T & operator*() const
T & operator*() const
TPatchedPtrBase(T *InPtr=nullptr)
T * operator->() const
T * GetChecked() const
T * Get() const
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)
uint32 Num() const
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
bool IsFrozen() const
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< uint8 > Bytes
TArray< FMemoryImageNamePointer > ScriptNames
bool operator==(const FMemoryImageVTablePointer &Rhs) const
bool operator!=(const FMemoryImageVTablePointer &Rhs) const
bool operator<(const FMemoryImageVTablePointer &Rhs) const
TMemoryImageObject(const FTypeLayoutDesc &InTypeDesc, T *InObject, uint32 InFrozenSize)
Definition MemoryImage.h:72
const FTypeLayoutDesc * TypeDesc
Definition MemoryImage.h:98
void Destroy(const FPointerTableBase *PointerTable)
TMemoryImageObject(const TMemoryImageObject< TOther > &Rhs)
Definition MemoryImage.h:86
bool Unfreeze(const FPointerTableBase *PointerTable)
TMemoryImageObject(TOther *InObject)
Definition MemoryImage.h:79
bool Freeze(FPointerTableBase *PointerTable)
Definition UE.h:525