diff --git a/Redcraft.Utility/Source/Private/Testing/MemoryTesting.cpp b/Redcraft.Utility/Source/Private/Testing/MemoryTesting.cpp index 09d95a0..39f2ef3 100644 --- a/Redcraft.Utility/Source/Private/Testing/MemoryTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/MemoryTesting.cpp @@ -2,6 +2,7 @@ #include "Memory/Memory.h" #include "Memory/Alignment.h" +#include "Memory/MemoryOperator.h" #include "Miscellaneous/AssertionMacros.h" NAMESPACE_REDCRAFT_BEGIN @@ -15,6 +16,7 @@ void TestMemory() TestAlignment(); TestMemoryBuffer(); TestMemoryMalloc(); + TestMemoryOperator(); } void TestAlignment() @@ -139,6 +141,67 @@ void TestMemoryMalloc() } +NAMESPACE_UNNAMED_BEGIN + +struct FTracker +{ + static int32 Status; + FTracker() { always_check(Status == 0); Status = -1; } + FTracker(const FTracker&) { always_check(Status == 1); Status = -1; } + FTracker(FTracker&&) { always_check(Status == 2); Status = -1; } + ~FTracker() { always_check(Status == 3); Status = -1; } + FTracker& operator=(const FTracker&) { always_check(Status == 4); Status = -1; return *this; } + FTracker& operator=(FTracker&&) { always_check(Status == 5); Status = -1; return *this; } + friend bool operator==(const FTracker&, const FTracker&) { always_check(Status == 6); Status = -1; return true; } +}; + +int32 FTracker::Status = -1; + +NAMESPACE_UNNAMED_END + +void TestMemoryOperator() +{ + + FTracker* PtrA = reinterpret_cast(Memory::Malloc(sizeof(FTracker))); + FTracker* PtrB = reinterpret_cast(Memory::Malloc(sizeof(FTracker))); + + FTracker::Status = 0; + Memory::DefaultConstruct(PtrA); + always_check(FTracker::Status == -1); + + FTracker::Status = 1; + Memory::Construct(PtrA, PtrB); + always_check(FTracker::Status == -1); + + FTracker::Status = 2; + Memory::MoveConstruct(PtrA, PtrB); + always_check(FTracker::Status == -1); + + FTracker::Status = -1; + Memory::RelocateConstruct(PtrA, PtrB); + always_check(FTracker::Status == -1); + + FTracker::Status = 3; + Memory::Destruct(PtrA); + always_check(FTracker::Status == -1); + + FTracker::Status = 4; + Memory::CopyAssign(PtrA, PtrB); + always_check(FTracker::Status == -1); + + FTracker::Status = 5; + Memory::MoveAssign(PtrA, PtrB); + always_check(FTracker::Status == -1); + + FTracker::Status = 6; + const bool bResult = Memory::Compare(PtrA, PtrB); + always_check(bResult); + always_check(FTracker::Status == -1); + + Memory::Free(PtrA); + Memory::Free(PtrB); +} + NAMESPACE_END(Testing) NAMESPACE_MODULE_END(Utility) diff --git a/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp b/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp index f4bae8f..f72faa4 100644 --- a/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp @@ -17,7 +17,7 @@ void TestMiscellaneous() TestTypeInfo(); } -NAMESPACE_PRIVATE_BEGIN +NAMESPACE_UNNAMED_BEGIN void TestNoEntry() { @@ -47,7 +47,7 @@ void TestUnimplemented() always_unimplemented(); } -NAMESPACE_PRIVATE_END +NAMESPACE_UNNAMED_END void TestAssertionMacros() { @@ -61,16 +61,16 @@ void TestAssertionMacros() always_checkf(true, "True!"); //always_checkf(false, "False!"); - //NAMESPACE_PRIVATE::TestNoEntry(); + //TestNoEntry(); - NAMESPACE_PRIVATE::TestNoReentry(); - //NAMESPACE_PRIVATE::TestNoReentry(); + TestNoReentry(); + //TestNoReentry(); - NAMESPACE_PRIVATE::TestNoRecursion(0); - NAMESPACE_PRIVATE::TestNoRecursion(0); - //NAMESPACE_PRIVATE::TestNoRecursion(1); + TestNoRecursion(0); + TestNoRecursion(0); + //TestNoRecursion(1); - //NAMESPACE_PRIVATE::TestUnimplemented(); + //TestUnimplemented(); verify(true); //verify(false); @@ -209,12 +209,12 @@ void TestCompare() } -NAMESPACE_PRIVATE_BEGIN +NAMESPACE_UNNAMED_BEGIN template struct TTestTemplateType { }; -NAMESPACE_PRIVATE_END +NAMESPACE_UNNAMED_END void TestTypeInfo() { @@ -224,8 +224,8 @@ void TestTypeInfo() always_check(TempA == TempB); always_check(TempA == Typeid(void)); - FTypeInfo TempC(Typeid(NAMESPACE_PRIVATE::TTestTemplateType)); - FTypeInfo TempD = Typeid(NAMESPACE_PRIVATE::TTestTemplateType); + FTypeInfo TempC(Typeid(TTestTemplateType)); + FTypeInfo TempD = Typeid(TTestTemplateType); FTypeInfo TempE, TempF; TempE = TempC; diff --git a/Redcraft.Utility/Source/Public/Memory/MemoryOperator.h b/Redcraft.Utility/Source/Public/Memory/MemoryOperator.h new file mode 100644 index 0000000..4093999 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Memory/MemoryOperator.h @@ -0,0 +1,183 @@ +#pragma once + +#include "CoreTypes.h" +#include "Templates/Utility.h" +#include "Concepts/Comparable.h" +#include "TypeTraits/TypeTraits.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +NAMESPACE_BEGIN(Memory) + +template + requires (TIsDefaultConstructible::Value || TIsZeroConstructible::Value) +FORCEINLINE void DefaultConstruct(ElementType* Address, SizeType Count = 1) +{ + if constexpr (TIsZeroConstructible::Value) + { + Memory::Memset(Address, 0, sizeof(ElementType) * Count); + } + else + { + ElementType* Element = (ElementType*)Address; + while (Count) + { + new (Element) ElementType; + ++Element; + --Count; + } + } +} + +template + requires (TIsConstructible::Value || TIsBitwiseConstructible::Value) +FORCEINLINE void Construct(DestinationElementType* Destination, const SourceElementType* Source, SizeType Count = 1) +{ + if constexpr (TIsBitwiseConstructible::Value) + { + Memory::Memcpy(Destination, Source, sizeof(SourceElementType) * Count); + } + else + { + while (Count) + { + new (Destination) DestinationElementType(*Source); + ++(DestinationElementType*&)Destination; + ++Source; + --Count; + } + } +} + +template + requires (TIsMoveConstructible::Value) +FORCEINLINE void MoveConstruct(ElementType* Destination, ElementType* Source, SizeType Count = 1) +{ + if constexpr (TIsTriviallyMoveConstructible::Value) + { + Memory::Memmove(Destination, Source, sizeof(ElementType) * Count); + } + else + { + while (Count) + { + new (Destination) ElementType(MoveTemp(*Source)); + ++(ElementType*&)Destination; + ++Source; + --Count; + } + } +} + +template + requires ((TIsConstructible::Value && TIsDestructible::Value) || TIsBitwiseRelocatable::Value) +FORCEINLINE void RelocateConstruct(DestinationElementType* Destination, SourceElementType* Source, SizeType Count = 1) +{ + if constexpr (TIsBitwiseRelocatable::Value) + { + Memory::Memmove(Destination, Source, sizeof(SourceElementType) * Count); + } + else + { + while (Count) + { + typedef SourceElementType RelocateConstructItemsElementTypeTypedef; + + new (Destination) DestinationElementType(MoveTemp(*Source)); + ++(DestinationElementType*&)Destination; + (Source++)->RelocateConstructItemsElementTypeTypedef::~RelocateConstructItemsElementTypeTypedef(); + --Count; + } + } +} + +template + requires (TIsDestructible::Value) +FORCEINLINE void Destruct(ElementType* Element, SizeType Count = 1) +{ + if constexpr (!TIsTriviallyDestructible::Value) + { + while (Count) + { + typedef ElementType DestructItemsElementTypeTypedef; + + Element->DestructItemsElementTypeTypedef::~DestructItemsElementTypeTypedef(); + ++Element; + --Count; + } + } +} + +template + requires (TIsCopyAssignable::Value) +FORCEINLINE void CopyAssign(ElementType* Destination, const ElementType* Source, SizeType Count = 1) +{ + if constexpr (TIsTriviallyCopyAssignable::Value) + { + Memory::Memcpy(Destination, Source, sizeof(ElementType) * Count); + } + else + { + while (Count) + { + *Destination = *Source; + ++Destination; + ++Source; + --Count; + } + } +} + +template + requires (TIsMoveAssignable::Value) +FORCEINLINE void MoveAssign(ElementType* Destination, ElementType* Source, SizeType Count = 1) +{ + if constexpr (TIsTriviallyCopyConstructible::Value) + { + Memory::Memmove(Destination, Source, sizeof(ElementType) * Count); + } + else + { + while (Count) + { + *Destination = MoveTemp(*Source); + ++(ElementType*&)Destination; + ++Source; + --Count; + } + } +} + +template + requires (CEqualityComparable || TIsBitwiseComparable::Value) +FORCEINLINE bool Compare(const ElementType* LHS, const ElementType* RHS, SizeType Count = 1) +{ + if constexpr (TIsBitwiseComparable::Value) + { + return !Memory::Memcmp(LHS, RHS, sizeof(ElementType) * Count); + } + else + { + while (Count) + { + if (!(*LHS == *RHS)) + { + return false; + } + + ++LHS; + ++RHS; + --Count; + } + + return true; + } +} + +NAMESPACE_END(Memory) + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Testing/MemoryTesting.h b/Redcraft.Utility/Source/Public/Testing/MemoryTesting.h index ba103db..4491fca 100644 --- a/Redcraft.Utility/Source/Public/Testing/MemoryTesting.h +++ b/Redcraft.Utility/Source/Public/Testing/MemoryTesting.h @@ -12,6 +12,7 @@ REDCRAFTUTILITY_API void TestMemory(); REDCRAFTUTILITY_API void TestAlignment(); REDCRAFTUTILITY_API void TestMemoryBuffer(); REDCRAFTUTILITY_API void TestMemoryMalloc(); +REDCRAFTUTILITY_API void TestMemoryOperator(); NAMESPACE_END(Testing)