33#ifndef DVD_PLATFORM_DEFINES_H_
34#define DVD_PLATFORM_DEFINES_H_
43#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3
44#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
45#define GET_5TH_ARG(arg1, arg2, arg3, arg4, arg5, ...) arg5
46#define GET_6TH_ARG(arg1, arg2, arg3, arg4, arg5, arg6, ...) arg6
51 static bool seen_this = false; \
54 Console::errorfn("[ STUBBED ] {} ({} : {})\n",\
55 x, __FILE__, __LINE__); \
60#define STUBBED(x) static_assert(true, "")
64#define TO_STRING_NAME(X) #X
65#define TO_STRING(X) TO_STRING_NAME(X)
73#define TYPEDEF_SMART_POINTERS_FOR_TYPE(T) \
74 using T ## _wptr = std::weak_ptr<T>; \
75 using T ## _ptr = std::shared_ptr<T>; \
76 using T ## _cwptr = std::weak_ptr<const T>; \
77 using T ## _cptr = std::shared_ptr<const T>;\
78 using T ## _uptr = std::unique_ptr<T>;
81#define FWD_DECLARE_MANAGED_CLASS(T) \
83 TYPEDEF_SMART_POINTERS_FOR_TYPE(T)
85#define FWD_DECLARE_MANAGED_STRUCT(T) \
87 TYPEDEF_SMART_POINTERS_FOR_TYPE(T)
90#define CONCATENATE_IMPL(s1, s2) s1##s2
91#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
93#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__)
95#define ANONYMOUSE_VARIABLE(str) CONCATENATE(str, __LINE__)
100#define _FUNCTION_NAME_AND_SIG_ __FUNCSIG__
101#elif defined(__GNUC__)
102#define _FUNCTION_NAME_AND_SIG_ __PRETTY_FUNCTION__
104#define _FUNCTION_NAME_AND_SIG_ __FUNCTION__
108#if defined(USING_CLANG)
109#define NO_DESTROY [[clang::no_destroy]]
115#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \
116template<typename... Args> \
117constexpr auto highLevelF(Args&&... args) -> decltype(lowLevelF(FWD(args)...)) \
119 return lowLevelF(FWD(args)...); \
125template <
typename TSignature>
128template <
typename TReturn,
typename... TArgs>
134 TReturn(*_erased_fn)(
void*, TArgs...);
137 template <
typename T>
requires std::is_invocable_v<T&(TArgs...)> && (!std::is_same_v<std::decay_t<T>,
function_view>)
139 _erased_fn = [](
void* ptr, TArgs... xs) -> TReturn {
140 return (*
reinterpret_cast<std::add_pointer_t<T>
>(ptr))(
145 decltype(
auto)
operator()(TArgs... xs)
const
146 noexcept(
noexcept(_erased_fn(_ptr,
FWD(xs)...))) {
147 return _erased_fn(_ptr,
FWD(xs)...);
178 return _ID_VIEW(str.data(), str.size(), value);
181[[nodiscard]]
constexpr U64 operator ""_id(
const char* str,
const size_t len)
214extern void SetThreadName(std::string_view threadName)
noexcept;
216extern bool CallSystemCmd(std::string_view cmd, std::string_view args);
218bool DebugBreak(
bool condition =
true) noexcept;
237[[nodiscard]] constexpr T
toBit(const T
X) {
266 while (width > 1u || height > 1u)
276template<
typename T>
requires std::is_unsigned_v<T>
278 return !(x == 0) && !(x & (x - 1));
281[[nodiscard]]
constexpr size_t realign_offset(
const size_t offset,
const size_t align)
noexcept {
282 return (offset + align - 1) & ~(align - 1);
286template<
typename Iterator,
typename Pred>
287void for_each_interval(Iterator from, Iterator to, std::ptrdiff_t partition_size, Pred&& operation)
289 if (partition_size > 0) {
290 Iterator partition_end = from;
291 while (partition_end != to)
293 while (partition_end != to && std::distance(from, partition_end) < partition_size)
297 operation(from, partition_end);
298 from = partition_end;
306 c.reserve( std::declval<typename C::size_type>() );
311 c.emplace_back( std::declval<typename C::value_type>() );
317 c.assign( std::declval<
decltype(std::declval<C>().begin())>(),
318 std::declval<decltype(std::declval<C>().end())>());
324template<
typename C >
requires has_reserve<C>
326 c.reserve(c.size() + n);
330using std::make_index_sequence;
331using std::index_sequence;
335 template <
typename T, std::size_t ... Is>
336 constexpr std::array<T,
sizeof...(Is)>
340 return { {(
static_cast<void>(Is), value)...} };
343 template <
typename T, std::size_t ... Is>
344 constexpr eastl::array<T,
sizeof...(Is)>
347 return { {(
static_cast<void>(Is), value)...} };
352template <std::
size_t N,
typename T>
358template <std::
size_t N,
typename T>
371 [[nodiscard]]
bool Negative() const noexcept {
return (
i >> 31) != 0; }
383 [[nodiscard]]
bool Negative() const noexcept {
return (
i >> 63) != 0; }
394 const F32 absDiff = std::abs(A - B);
395 if (absDiff <= maxDiff) {
408 return std::abs(uA.
i - uB.
i) <= maxUlpsDiff;
414 const D64 absDiff = std::abs(A - B);
415 if (absDiff <= maxDiff) {
428 return std::abs(uA.
i - uB.
i) <= maxUlpsDiff;
434 const F32 diff = std::abs(A - B);
435 if (diff <= maxDiff) {
439 const F32 largest = std::max(std::abs(A), std::abs(B));
440 return diff <= largest * maxRelDiff;
446 const D64 diff = std::abs(A - B);
447 if (diff <= maxDiff) {
453 const D64 largest = B > A ? B : A;
455 return diff <= largest * maxRelDiff;
458#define NOP() static_assert(true, "")
467 template <
typename Fun>
485 template <
typename FunctionType,
bool executeOnException>
500 template <
typename Fun>
505 template <
typename Fun>
510 template <
typename Fun>
541#define SCOPE_FAIL auto ANONYMOUS_VARIABLE(SCOPE_FAIL_STATE) = detail::ScopeGuardOnFail() + [&]() noexcept
542#define SCOPE_SUCCESS auto ANONYMOUS_VARIABLE(SCOPE_FAIL_STATE) = detail::ScopeGuardOnSuccess() + [&]()
543#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) = detail::ScopeGuardOnExit() + [&]() noexcept
548template <
typename T,
typename U = T>
550 return x >= min && x <= max;
552template <
typename T,
typename U = T>
554 return x > min && x < max;
573 return abs(
X) <= TOLERANCE;
576template<
typename T,
typename U = T>
578 return abs(
X -
static_cast<T
>(Y)) <= TOLERANCE;
581template<
typename T,
typename U = T>
596template<
typename T,
typename U = T>
598 return X ==
static_cast<T
>(Y);
623template <
bool IsFromSigned,
bool IsToSigned>
630 template <
typename TO,
typename FROM>
634 ?
static_cast<U32>(to_underlying_type(from))
636 std::numeric_limits<TO>::lowest(),
637 std::numeric_limits<TO>::max()) &&
638 "Number to cast exceeds numeric limits.");
640 return static_cast<TO
>(from);
648 template <
typename TO,
typename FROM>
652 std::numeric_limits<TO>::lowest(),
653 std::numeric_limits<TO>::max()) &&
654 "Number to cast exceeds numeric limits.");
656 return static_cast<TO
>(from);
664 template <
typename TO,
typename FROM>
668 assert(from >= 0 &&
"Number to cast exceeds numeric limits.");
671 using UnsignedFrom =
typename std::make_unsigned<FROM>::type;
673 std::numeric_limits<TO>::lowest(),
674 std::numeric_limits<TO>::max()) &&
675 "Number to cast exceeds numeric limits.");
676 return static_cast<TO
>(from);
684 template <
typename TO,
typename FROM>
688 std::numeric_limits<TO>::lowest(),
689 std::numeric_limits<TO>::max()) &&
690 "Number to cast exceeds numeric limits.");
692 return static_cast<TO
>(from);
697template <
typename TO,
typename FROM>
703 std::numeric_limits<TO>::is_signed>
704 ::template cast<TO>(from);
706 return static_cast<TO
>(from);
710template <
typename TO>
713 return static_cast<TO
>(from);
716template <
typename TO>
719 return static_cast<TO
>(from);
727 bool DIVIDE_ASSERT_FUNC(
bool expression,
const char* expressionStr,
const char* file,
int line,
const char* failMessage)
noexcept;
730#define DIVIDE_ASSERT_2_ARGS(expression, msg) Assert::DIVIDE_ASSERT_FUNC(expression, #expression, __FILE__, __LINE__, msg)
731#define DIVIDE_ASSERT_1_ARGS(expression) DIVIDE_ASSERT_2_ARGS(expression, "UNEXPECTED CALL")
733#define ___DETAIL_DIVIDE_ASSERT(...) EXP(GET_3RD_ARG(__VA_ARGS__, DIVIDE_ASSERT_2_ARGS, DIVIDE_ASSERT_1_ARGS, ))
734#define DIVIDE_ASSERT(...) EXP(___DETAIL_DIVIDE_ASSERT(__VA_ARGS__)(__VA_ARGS__))
736#define DIVIDE_UNEXPECTED_CALL_MSG(X) DIVIDE_ASSERT(false, X)
737#define DIVIDE_UNEXPECTED_CALL() DIVIDE_UNEXPECTED_CALL_MSG("UNEXPECTED CALL")
739template <
typename Ret,
typename... Args >
742template <
typename Ret,
typename... Args >
745template <
typename Ret,
typename... Args >
ScopeGuardForNewException(FunctionType &&fn)
UncaughtExceptionCounter ec_
ScopeGuardForNewException(const FunctionType &fn)
~ScopeGuardForNewException() noexcept(executeOnException)
ScopeGuard(Fun &&fn) noexcept
UncaughtExceptionCounter() noexcept
bool newUncaughtException() noexcept
function_view(T &&x) noexcept
TReturn signature_type(void *, TArgs...)
bool DIVIDE_ASSERT_FUNC(const bool expression, const char *expressionStr, const char *file, int line, const char *failMessage) noexcept
It is safe to call evaluate expressions and call functions inside the assert check as it will compile...
constexpr eastl::array< T, sizeof...(Is)> create_eastl_array(T value, index_sequence< Is... >)
auto operator+(ScopeGuardOnExit, Fun &&fn) noexcept
constexpr std::array< T, sizeof...(Is)> create_array(T value, index_sequence< Is... >)
Handle console commands that start with a forward slash.
void GetWindowHandle(void *window, WindowHandle &handleOut) noexcept
void SetClipboardText(const char *text) noexcept
DELEGATE_STD< Ret, Args... > DELEGATE
F32 PlatformDefaultDPI() noexcept
bool COMPARE_TOLERANCE_ACCURATE(const T X, const T Y, const T TOLERANCE) noexcept
void for_each_interval(Iterator from, Iterator to, std::ptrdiff_t partition_size, Pred &&operation)
bool IS_ZERO(const T X) noexcept
bool IS_IN_RANGE_EXCLUSIVE(const T x, const U min, const U max) noexcept
bool CursorState() noexcept
void SetThreadName(std::string_view threadName) noexcept
std::function< Ret(Args...) > DELEGATE_STD
constexpr eastl::array< T, N > create_eastl_array(const T &value)
constexpr U32 val_32_const
constexpr D64 EPSILON_D64
constexpr U64 to_U64(const T value)
SysInfo & sysInfo() noexcept
bool IS_IN_RANGE_INCLUSIVE(const T x, const U min, const U max) noexcept
bool IS_LEQUAL(T X, T Y) noexcept
TO safe_static_cast(FROM from)
bool CallSystemCmd(std::string_view cmd, std::string_view args)
bool DebugBreak(const bool condition) noexcept
std::string CurrentDateTimeString()
void DIVIDE_ASSERT_MSG_BOX(const char *failMessage) noexcept
const char * GetClipboardText() noexcept
constexpr U64 val_64_const
void SetThreadPriority(ThreadPriority priority)
void EnforceDPIScaling() noexcept
constexpr U64 _ID_VIEW(const char *const str, const size_t len, const U64 value=val_64_const) noexcept
bool IS_TOLERANCE(const T X, const T TOLERANCE) noexcept
constexpr F32 EPSILON_F32
ErrorCode PlatformInit(int argc, char **argv)
bool AlmostEqualRelativeAndAbs(const F32 A, const F32 B, const F32 maxDiff, const F32 maxRelDiff) noexcept
constexpr U32 powerOfTwo(U32 X) noexcept
const SysInfo & const_sysInfo() noexcept
constexpr U32 prime_32_const
constexpr size_t realign_offset(const size_t offset, const size_t align) noexcept
constexpr U64 _ID(const char *const str, const U64 value=val_64_const) noexcept
constexpr bool isPowerOfTwo(const T x) noexcept
bool COMPARE_TOLERANCE(const T X, const U Y, const T TOLERANCE) noexcept
constexpr U64 prime_64_const
constexpr U32 mipLevels(U32 width, U32 height) noexcept
constexpr U32 previousPowerOfTwo(const U32 X) noexcept
constexpr Handle< T > INVALID_HANDLE
void optional_reserve(C &, std::size_t)
constexpr std::array< T, N > create_array(const T &value)
bool GetAvailableMemory(SysInfo &info)
bool AlmostEqualUlpsAndAbs(const F32 A, const F32 B, const F32 maxDiff, const I32 maxUlpsDiff) noexcept
bool COMPARE(T X, U Y) noexcept
void ToggleCursor(bool state) noexcept
eastl::function< Ret(Args...) > DELEGATE_EASTL
bool IS_GEQUAL(T X, T Y) noexcept
should be fast enough as the first condition is almost always true
constexpr T toBit(const T X)
Converts an arbitrary positive integer value to a bitwise value used for masks.
void InitSysInfo(SysInfo &info, I32 argc, char **argv)
FORCE_INLINE bool operator==(const Handle &rhs) const
ResourcePath _workingDirectory
size_t _availableRamInBytes
static TO cast(FROM from)
static TO cast(FROM from)
static TO cast(FROM from)
static TO cast(FROM from)
ref: http://blog.molecular-matters.com/2011/08/12/a-safer-static_cast/#more-120
I64 RawExponent() const noexcept
I64 RawMantissa() const noexcept
bool Negative() const noexcept
Double_t(const D64 num=0.0) noexcept
bool Negative() const noexcept
I32 RawMantissa() const noexcept
Float_t(const F32 num=0.0f) noexcept
I32 RawExponent() const noexcept