2#define PL_CHECK_CLASS(T) \
3 static_assert(!std::is_trivial<T>::value, \
4 "Trivial POD type is treated as class. Use PL_DECLARE_POD_TYPE(YourClass) or PL_DEFINE_AS_POD_TYPE(ExternalClass) to mark it as POD.")
6template <plConstructionMode mode,
typename T>
9 if constexpr (mode == SkipTrivialTypes && std::is_trivial<T>::value)
15 for (
size_t i = 0; i < uiCount; i++)
17 ::new (pDestination + i) T();
22template <plConstructionMode mode,
typename T>
25 if constexpr (mode == SkipTrivialTypes && std::is_trivial<T>::value)
36 return &Helper::Construct;
40template <
typename Destination,
typename Source>
45 static_assert(std::is_same<Destination, Source>::value ||
46 (std::is_base_of<Destination, Source>::value ==
false && std::is_base_of<Source, Destination>::value ==
false),
47 "Can't copy POD types that are derived from each other. Are you certain any of these types should be POD?");
49 const Destination& copyConverted = copy;
50 for (
size_t i = 0; i < uiCount; i++)
52 memcpy(pDestination + i, ©Converted,
sizeof(Destination));
57 PL_CHECK_CLASS(Destination);
59 for (
size_t i = 0; i < uiCount; i++)
61 ::new (pDestination + i) Destination(copy);
70 PL_ASSERT_DEV(pDestination + uiCount <= pSource || pSource + uiCount <= pDestination,
"Memory regions must not overlap when using CopyConstruct.");
74 memcpy(pDestination, pSource, uiCount *
sizeof(T));
80 for (
size_t i = 0; i < uiCount; i++)
82 ::new (pDestination + i) T(pSource[i]);
92 static void CopyConstruct(
void* pDestination,
const void* pSource)
98 return &Helper::CopyConstruct;
105 static_assert(std::is_rvalue_reference<
decltype(source)>::value,
"'source' parameter is not an rvalue reference.");
106 ::new (pDestination) T(std::forward<T>(source));
112 PL_ASSERT_DEV(pDestination + uiCount <= pSource || pSource + uiCount <= pDestination,
"Memory regions must not overlap when using MoveConstruct.");
115 static_assert(std::is_move_constructible<T>::value,
"Type is not move constructible!");
117 for (
size_t i = 0; i < uiCount; ++i)
119 ::new (pDestination + i) T(std::move(pSource[i]));
123template <
typename Destination,
typename Source>
126 if constexpr (std::is_rvalue_reference<
decltype(source)>::value)
128 static_assert(std::is_rvalue_reference<
decltype(source)>::value,
"This version of CopyOrMoveConstruct should only be called with a rvalue reference!");
130 ::new (pDestination) Destination(std::move(source));
141 PL_ASSERT_DEV(pDestination + uiCount <= pSource || pSource + uiCount <= pDestination,
"Memory regions must not overlap when using RelocateConstruct.");
145 memcpy(pDestination, pSource, uiCount *
sizeof(T));
151 for (
size_t i = 0; i < uiCount; i++)
154 ::new (pDestination + i) T(std::move(pSource[i]));
166 static_assert(std::is_trivially_destructible<T>::value != 0,
"Class is declared as POD but has a non-trivial destructor. Remove the destructor or don't declare it as POD.");
168 else if constexpr (std::is_trivially_destructible<T>::value == 0)
170 for (
size_t i = 0; i < uiCount; ++i)
172 pDestination[i].~T();
193 return &Helper::Destruct;
199 memcpy(pDestination, pSource, uiNumBytesToCopy);
203PL_ALWAYS_INLINE
void plMemoryUtils::Copy(T* pDestination,
const T* pSource,
size_t uiCount)
205 PL_ASSERT_DEV(pDestination < pSource || pSource + uiCount <= pDestination,
"Memory regions must not overlap when using Copy. Use CopyOverlapped instead.");
209 memcpy(pDestination, pSource, uiCount *
sizeof(T));
215 for (
size_t i = 0; i < uiCount; i++)
217 pDestination[i] = pSource[i];
227 memmove(pDestination, pSource, uiCount *
sizeof(T));
233 if (pDestination == pSource)
236 if (pDestination < pSource)
238 for (
size_t i = 0; i < uiCount; i++)
240 pDestination[i] = pSource[i];
245 for (
size_t i = uiCount; i > 0; --i)
247 pDestination[i - 1] = pSource[i - 1];
256 PL_ASSERT_DEV(pDestination + uiCount <= pSource || pSource + uiCount <= pDestination,
"Memory regions must not overlap when using Relocate.");
260 memcpy(pDestination, pSource, uiCount *
sizeof(T));
266 for (
size_t i = 0; i < uiCount; i++)
269 pDestination[i] = std::move(pSource[i]);
281 if (pDestination < pSource)
283 size_t uiDestructCount = pSource - pDestination;
284 Destruct(pDestination, uiDestructCount);
288 size_t uiDestructCount = pDestination - pSource;
289 Destruct(pSource + uiCount, uiDestructCount);
291 memmove(pDestination, pSource, uiCount *
sizeof(T));
295 memmove(pDestination, pSource, uiCount *
sizeof(T));
301 if (pDestination == pSource)
304 if (pDestination < pSource)
306 for (
size_t i = 0; i < uiCount; i++)
308 pDestination[i] = std::move(pSource[i]);
311 size_t uiDestructCount = pSource - pDestination;
312 Destruct(pSource + uiCount - uiDestructCount, uiDestructCount);
316 for (
size_t i = uiCount; i > 0; --i)
318 pDestination[i - 1] = std::move(pSource[i - 1]);
321 size_t uiDestructCount = pDestination - pSource;
332 memmove(pDestination + 1, pDestination, uiCount *
sizeof(T));
341 MoveConstruct(pDestination + uiCount, std::move(pDestination[uiCount - 1]));
343 for (
size_t i = uiCount - 1; i > 0; --i)
345 pDestination[i] = std::move(pDestination[i - 1]);
348 *pDestination = source;
362 memmove(pDestination + 1, pDestination, uiCount *
sizeof(T));
371 MoveConstruct(pDestination + uiCount, std::move(pDestination[uiCount - 1]));
373 for (
size_t i = uiCount - 1; i > 0; --i)
375 pDestination[i] = std::move(pDestination[i - 1]);
378 *pDestination = std::move(source);
388PL_ALWAYS_INLINE
void plMemoryUtils::Prepend(T* pDestination,
const T* pSource,
size_t uiSourceCount,
size_t uiCount)
392 memmove(pDestination + uiSourceCount, pDestination, uiCount *
sizeof(T));
401 MoveConstruct(pDestination + uiSourceCount, pDestination, uiCount);
416 return memcmp(a, b, uiCount *
sizeof(T)) == 0;
422 for (
size_t i = 0; i < uiCount; i++)
434 memset(pDestination, 0, uiCount *
sizeof(T));
437template <
typename T,
size_t N>
446 memset(pDestination, uiBytePattern, uiCount *
sizeof(T));
449template <
typename T,
size_t N>
458 return memcmp(a, b, uiCount *
sizeof(T));
463 return memcmp(a, b, uiNumBytesToCompare);
469 return reinterpret_cast<T*
>(
reinterpret_cast<uintptr_t
>(pPtr) + offset);
475 return reinterpret_cast<T*
>(
reinterpret_cast<size_t>(pPtr) & ~(uiAlignment - 1));
481 return reinterpret_cast<T*
>((
reinterpret_cast<size_t>(pPtr) + uiAlignment - 1) & ~(uiAlignment - 1));
487 return ((uiSize + (uiAlignment - 1)) & ~(uiAlignment - 1));
493 return (
reinterpret_cast<size_t>(pPtr) & (uiAlignment - 1)) == 0;
499 return (uiSize & (uiAlignment - 1)) == 0;
static T * AlignForwards(T *pPtr, size_t uiAlignment)
Aligns the pointer ptr by moving its address forwards to the next multiple of uiAlignment.
static void CopyConstruct(Destination *pDestination, const Source ©, size_t uiCount=1)
Constructs uiCount objects of type T in a raw buffer at pDestination, by creating uiCount copies of c...
static T * AddByteOffset(T *pPtr, std::ptrdiff_t offset)
Returns the address stored in ptr plus the given byte offset iOffset, cast to type T.
static void CopyConstructArray(T *pDestination, const T *pSource, size_t uiCount)
Constructs uiCount objects of type T in a raw buffer at pDestination from an existing array of object...
static T * AlignBackwards(T *pPtr, size_t uiAlignment)
Aligns the pointer ptr by moving its address backwards to the previous multiple of uiAlignment.
static ConstructorFunction MakeConstructorFunction()
Returns a function pointer to construct an instance of T. Returns nullptr for trivial types.
static void CopyOrMoveConstruct(Destination *pDestination, Source &&source)
This function will either move call MoveConstruct or CopyConstruct for a single element source,...
static bool IsEqual(const T *a, const T *b, size_t uiCount=1)
Tests if objects of type T from pSource and pDestination are equal.
static CopyConstructorFunction MakeCopyConstructorFunction()
Returns a function pointer to copy construct an instance of T.
static void ZeroFillArray(T(&destination)[N])
Zeros every byte in the provided memory buffer.
static void RelocateConstruct(T *pDestination, T *pSource, size_t uiCount=1)
Constructs uiCount objects of type T in a raw buffer at pDestination from an existing array of object...
static void Construct(T *pDestination, size_t uiCount=1)
Constructs uiCount objects of type T in a raw buffer at pDestination.
static DestructorFunction MakeDestructorFunction()
Returns a function pointer to destruct an instance of T. Returns nullptr for POD-types.
static bool IsSizeAligned(T uiSize, T uiAlignment)
Checks whether the given size is aligned.
static void RawByteCopy(void *pDestination, const void *pSource, size_t uiNumBytesToCopy)
Copies exactly uiNumBytesToCopy from pSource to pDestination, independent of the involved types and t...
Definition MemoryUtils_inl.h:197
static void PatternFill(T *pDestination, plUInt8 uiBytePattern, size_t uiCount=1)
Fills every byte of the provided buffer with the given value.
static void Prepend(T *pDestination, const T &source, size_t uiCount)
Moves uiCount objects in pDestination by one object and copies source to the free space.
static plInt32 RawByteCompare(const void *a, const void *b, size_t uiNumBytesToCompare)
Compares exactly uiNumBytesToCompare from a and b, independent of the involved types and their sizes.
Definition MemoryUtils_inl.h:461
static void Copy(T *pDestination, const T *pSource, size_t uiCount=1)
Copies objects of type T from pSource to pDestination.
static void PatternFillArray(T(&destination)[N], plUInt8 uiBytePattern)
Fills every byte of the provided buffer with the given value.
static void MoveConstruct(T *pDestination, T &&source)
Constructs an object of type T in a raw buffer at pDestination, by using move construction from sourc...
static plInt32 Compare(const T *a, const T *b, size_t uiCount=1)
Compares two buffers of raw memory byte wise.
static bool IsAligned(const T *pPtr, size_t uiAlignment)
Checks whether ptr is aligned to a memory address that is a multiple of uiAlignment.
static void RelocateOverlapped(T *pDestination, T *pSource, size_t uiCount=1)
Moves objects of type T from pSource to pDestination.
static void CopyOverlapped(T *pDestination, const T *pSource, size_t uiCount=1)
Copies objects of type T from pSource to pDestination.
static void ZeroFill(T *pDestination, size_t uiCount=1)
Zeros every byte in the provided memory buffer.
static T AlignSize(T uiSize, T uiAlignment)
Aligns the given size uiSize by rounding up to the next multiple of the size.
static void Relocate(T *pDestination, T *pSource, size_t uiCount=1)
Moves objects of type T from pSource to pDestination.
static void Destruct(T *pDestination, size_t uiCount=1)
Destructs uiCount objects of type T at pDestination.
If there is an % operator which takes a plTypeIsMemRelocatable and returns a CompileTimeTrueType T is...
Definition TypeTraits.h:67
If there is an % operator which takes a TypeIsPod and returns a CompileTimeTrueType T is Pod....
Definition TypeTraits.h:43