Skip to content

Commit

Permalink
Minor improvements; Moved CopyMemory/MoveMemory/ZeroMemory to RTTI
Browse files Browse the repository at this point in the history
  • Loading branch information
Epixu committed Sep 25, 2023
1 parent c043ddb commit e9a4faf
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 222 deletions.
14 changes: 14 additions & 0 deletions source/Core/Common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@
/// Exploits [[deprecated("warning")]] to log template instantiations
#define LANGULUS_TEMPLATE() [[deprecated("template intantiation")]]

/// Checks if code is executed at compile-time
/// @attention must be followed by {...}
/// TODO when we transition to C++23, we should replace
/// if (std::is_constant_evaluated()) statements with if consteval ones
#define IF_CONSTEXPR() if (std::is_constant_evaluated())

#if LANGULUS_COMPILER(MSVC)
/// Force no inlining
#define LANGULUS_NOINLINE() __declspec(noinline)
Expand Down Expand Up @@ -432,6 +438,9 @@ namespace Langulus
or requires (FROM& from) { static_cast<TO>(from); }
or ::std::convertible_to<FROM, TO>;

template<class T>
concept Enum = ::std::is_enum_v<T>;

template<class T>
concept Fundamental = ::std::is_fundamental_v<T>;

Expand Down Expand Up @@ -505,6 +514,11 @@ namespace Langulus
and Complete<Decay<TO>...>
and (Inner::Convertible<Decay<FROM>, Decay<TO>> and ...);

/// Check if the origin T is an enum type
template<class... T>
concept Enum = Complete<Decay<T>...>
and (Inner::Enum<Decay<T>> and ...);

/// Check if the origin T is a fundamental type
template<class... T>
concept Fundamental = Complete<Decay<T>...>
Expand Down
222 changes: 0 additions & 222 deletions source/Core/Utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,226 +291,4 @@ namespace Langulus
return r > 0 ? v + (alignment - r) : v;
}

/// Wrapper for memcpy
/// @tparam TO - destination memory type (deducible)
/// @tparam FROM - source memory type (deducible)
/// @param to - [out] destination memory
/// @param from - source of data to copy
template<class TO, class FROM>
LANGULUS(INLINED)
void CopyMemory(TO* to, const FROM* from) noexcept {
static_assert(CT::Void<TO>
or CT::Sparse<TO>
or CT::POD<TO>
or ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(you can suppress this error by casting pointer to void*)");

static_assert(CT::Void<TO>
or(CT::Same<TO, FROM> and CT::Sparse<TO> == CT::Sparse<FROM>),
"TO and FROM must be the exact same types"
"(you can suppress this error by casting pointer to void*)");

if constexpr (CT::Void<TO>)
LANGULUS_ERROR("Bytecount not specified when copying void pointers");

::std::memcpy(
static_cast<void*>(to),
static_cast<const void*>(from),
sizeof(TO)
);
}

/// Wrapper for memcpy
/// @tparam TO - destination memory type (deducible)
/// @tparam FROM - source memory type (deducible)
/// @param to - [out] destination memory
/// @param from - source of data to copy
/// @param count - number of elements to copy
/// @attention count becomes bytecount, when TO is void
template<class TO, class FROM>
LANGULUS(INLINED)
void CopyMemory(TO* to, const FROM* from, const Count& count) noexcept {
static_assert(CT::Void<TO>
or CT::Sparse<TO>
or CT::POD<TO>
or ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(you can suppress this error by casting pointer to void*)");

static_assert(CT::Void<TO>
or(CT::Same<TO, FROM> and CT::Sparse<TO> == CT::Sparse<FROM>),
"TO and FROM must be the exact same types"
"(you can suppress this error by casting pointer to void*)");

if constexpr (CT::Void<TO>) {
::std::memcpy(
static_cast<void*>(to),
static_cast<const void*>(from),
count
);
}
else {
::std::memcpy(
static_cast<void*>(to),
static_cast<const void*>(from),
sizeof(TO) * count
);
}
}

/// Wrapper for memset
/// @tparam TO - destination memory type (deducible)
/// @tparam FILLER - value to fill in with
/// @param to - [out] destination memory
template<int FILLER, class TO>
LANGULUS(INLINED)
void FillMemory(TO* to) noexcept {
static_assert(CT::Void<TO>
or CT::Sparse<TO>
or CT::POD<TO>
or ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(you can suppress this error by casting to void*)");

static_assert(FILLER
or CT::Nullifiable<TO>
or CT::Void<TO>
or CT::Sparse<TO>
or CT::Fundamental<TO>,
"Filling with zeroes requires the type to be reflected as nullifiable, "
"or be a pointer/fundamental (you can suppress this error by casting to void*)");

if constexpr (CT::Void<TO>)
LANGULUS_ERROR("Bytecount not specified when filling void pointer");

::std::memset(static_cast<void*>(to), FILLER, sizeof(TO));
}

/// Wrapper for memset
/// @tparam TO - destination memory type (deducible)
/// @tparam FILLER - value to fill in with
/// @param to - [out] destination memory
/// @param count - number of elements to fill
/// @attention count becomes bytecount, when TO is void
template<int FILLER, class TO>
LANGULUS(INLINED)
void FillMemory(TO* to, const Count& count) noexcept {
static_assert(CT::Void<TO>
or CT::Sparse<TO>
or CT::POD<TO>
or ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(you can suppress this error by casting to void*)");

static_assert(FILLER
or CT::Nullifiable<TO>
or CT::Void<TO>
or CT::Sparse<TO>
or CT::Fundamental<TO>,
"Filling with zeroes requires the type to be reflected as nullifiable, "
"or be a pointer/fundamental (you can suppress this error by casting to void*)");

if constexpr (CT::Void<TO>)
::std::memset(static_cast<void*>(to), FILLER, count);
else
::std::memset(static_cast<void*>(to), FILLER, sizeof(TO) * count);
}

/// Wrapper for memset 0
/// @tparam TO - destination memory type (deducible)
/// @param to - [out] destination memory
template<class TO>
LANGULUS(INLINED)
void ZeroMemory(TO* to) noexcept {
return FillMemory<0>(to);
}

/// Wrapper for memset 0
/// @tparam TO - destination memory type (deducible)
/// @param to - [out] destination memory
/// @param count - number of elements to fill
/// @attention count becomes bytecount, when TO is void
template<class TO>
LANGULUS(INLINED)
void ZeroMemory(TO* to, const Count& count) noexcept {
return FillMemory<0>(to, count);
}

/// Wrapper for memmove
/// @tparam TO - destination memory type (deducible)
/// @tparam FROM - source memory type (deducible)
/// @param to - [out] destination memory
/// @param from - source of data to move
template<class TO, class FROM>
LANGULUS(INLINED)
void MoveMemory(TO* to, const FROM* from) noexcept {
static_assert(CT::Void<TO>
or CT::Sparse<TO>
or CT::POD<TO>
or ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(You can suppress this error by casting pointer to void*)");

static_assert(CT::Void<TO>
or(CT::Same<TO, FROM> and CT::Sparse<TO> == CT::Sparse<FROM>),
"TO and FROM must be the exact same types"
"(you can suppress this error by casting pointer to void*)");

if constexpr (CT::Void<TO>)
LANGULUS_ERROR("Bytecount not specified when filling void pointer");

::std::memmove(
static_cast<void*>(to),
static_cast<const void*>(from),
sizeof(TO)
);

#if LANGULUS(PARANOID)
TODO() // zero old memory, but beware - `from` and `to` might overlap
#endif
}

/// Wrapper for memmove
/// @tparam TO - destination memory type (deducible)
/// @tparam FROM - source memory type (deducible)
/// @param to - [out] destination memory
/// @param from - source of data to move
/// @param count - number of elements to move
/// @attention count becomes bytecount, when TO is void
template<class TO, class FROM>
LANGULUS(INLINED)
void MoveMemory(TO* to, const FROM* from, const Count& count) noexcept {
static_assert(CT::Void<TO>
or CT::Sparse<TO>
or CT::POD<TO>
or ::std::is_trivial_v<TO>,
"TO must be either pointer, reflected as POD, or trivial. "
"(You can suppress this error by casting pointer to void*)");

static_assert(CT::Void<TO>
or(CT::Same<TO, FROM> and CT::Sparse<TO> == CT::Sparse<FROM>),
"TO and FROM must be the exact same types"
"(you can suppress this error by casting pointer to void*)");

if constexpr (CT::Void<TO>) {
::std::memmove(
static_cast<void*>(to),
static_cast<const void*>(from),
count
);
}
else {
::std::memmove(
static_cast<void*>(to),
static_cast<const void*>(from),
sizeof(TO) * count
);
}

#if LANGULUS(PARANOID)
TODO() // zero old memory, but beware - `from` and `to` might overlap
#endif
}

} // namespace Langulus

0 comments on commit e9a4faf

Please sign in to comment.