198 lines
7.6 KiB
C++
198 lines
7.6 KiB
C++
#pragma once
|
|
|
|
#include <Core/Common/CoreTypes.h>
|
|
#include <Juliet.h>
|
|
|
|
#include <algorithm>
|
|
#include <bit>
|
|
#include <cassert>
|
|
#include <concepts>
|
|
#include <source_location>
|
|
|
|
namespace Juliet
|
|
{
|
|
|
|
#define global static
|
|
|
|
// 1. Stringify helpers
|
|
#define JULIET_STR(x) #x
|
|
#define JULIET_TOSTRING(x) JULIET_STR(x)
|
|
|
|
// 2. Define the pragma operator based on compiler
|
|
#if defined(__clang__) || defined(__GNUC__)
|
|
#define JULIET_PRAGMA(x) _Pragma(#x)
|
|
#define JULIET_SUPPRESS_MSVC(id)
|
|
#define JULIET_SUPPRESS_CLANG(str) JULIET_PRAGMA(clang diagnostic ignored str)
|
|
#elif defined(_MSC_VER)
|
|
#define JULIET_PRAGMA(x) __pragma(x)
|
|
#define JULIET_SUPPRESS_MSVC(id) JULIET_PRAGMA(warning(disable : id))
|
|
#define JULIET_SUPPRESS_CLANG(str)
|
|
#else
|
|
#define JULIET_PRAGMA(x)
|
|
#define JULIET_SUPPRESS_MSVC(id)
|
|
#define JULIET_SUPPRESS_CLANG(str)
|
|
#endif
|
|
|
|
// 3. The Agnostic "Push/Pop"
|
|
#if defined(__clang__)
|
|
#define JULIET_WARNING_PUSH JULIET_PRAGMA(clang diagnostic push)
|
|
#define JULIET_WARNING_POP JULIET_PRAGMA(clang diagnostic pop)
|
|
#elif defined(_MSC_VER)
|
|
#define JULIET_WARNING_PUSH JULIET_PRAGMA(warning(push))
|
|
#define JULIET_WARNING_POP JULIET_PRAGMA(warning(pop))
|
|
#else
|
|
#define JULIET_WARNING_PUSH
|
|
#define JULIET_WARNING_POP
|
|
#endif
|
|
|
|
#if defined(_MSC_VER)
|
|
// MSVC specific intrinsic
|
|
#define JULIET_PLATFORM_BREAK() (__nop(), __debugbreak())
|
|
#elif defined(__clang__) || defined(__GNUC__)
|
|
// Clang/GCC specific intrinsic
|
|
#define JULIET_PLATFORM_BREAK() __builtin_trap()
|
|
#else
|
|
#include <signal.h>
|
|
#define JULIET_PLATFORM_BREAK() raise(SIGTRAP)
|
|
#endif
|
|
|
|
#if JULIET_DEBUG
|
|
#define JULIET_ASSERT_INTERNAL(expression, message) \
|
|
JULIET_WARNING_PUSH \
|
|
JULIET_SUPPRESS_CLANG("-Wextra-semi-stmt") \
|
|
JULIET_SUPPRESS_MSVC(4127) \
|
|
JULIET_SUPPRESS_MSVC(4548) \
|
|
{ \
|
|
if (!(expression)) [[unlikely]] \
|
|
{ \
|
|
Juliet::JulietAssert(#expression, message); \
|
|
} \
|
|
} \
|
|
JULIET_WARNING_POP \
|
|
static_assert(true, "")
|
|
|
|
#define AssertHR(hr_expression, message) \
|
|
do \
|
|
{ \
|
|
long hr_val = (hr_expression); \
|
|
if (hr_val < 0) \
|
|
{ \
|
|
Juliet::JulietAssert(#hr_expression, message, std::source_location::current(), hr_val); \
|
|
} \
|
|
} \
|
|
while (0)
|
|
|
|
#define GET_ASSERT_MACRO(_1, _2, NAME, ...) NAME
|
|
#define Assert(...) GET_ASSERT_MACRO(__VA_ARGS__, JULIET_ASSERT_INTERNAL, JULIET_ASSERT_NO_MSG)(__VA_ARGS__)
|
|
#define JULIET_ASSERT_NO_MSG(expression) JULIET_ASSERT_INTERNAL(expression, "No additional information provided.")
|
|
|
|
#define Unimplemented() \
|
|
do \
|
|
{ \
|
|
Juliet::JulietAssert("UNIMPLEMENTED", "This code path is not yet functional."); \
|
|
} \
|
|
while (0)
|
|
|
|
#else
|
|
#define Assert(...) ((void)0)
|
|
#define AssertHR(hr_expression, message) ((void)(hr_expression))
|
|
#define Unimplemented() ((void)0)
|
|
#endif
|
|
|
|
JULIET_API extern void JulietAssert(const char* expression, const char* message,
|
|
std::source_location location = std::source_location::current(), long handleResult = 0);
|
|
|
|
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
|
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
|
|
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
|
|
inline void ZeroSize(size_t size, void* ptr)
|
|
{
|
|
auto Byte = (uint8*)ptr;
|
|
while (size--)
|
|
{
|
|
*Byte++ = 0;
|
|
}
|
|
}
|
|
|
|
#define Restrict __restrict
|
|
|
|
template <class Function>
|
|
class DeferredFunction
|
|
{
|
|
public:
|
|
explicit DeferredFunction(const Function& otherFct) noexcept
|
|
: Callback(otherFct)
|
|
{
|
|
}
|
|
explicit DeferredFunction(Function&& otherFct) noexcept
|
|
: Callback(std::move(otherFct))
|
|
{
|
|
}
|
|
|
|
~DeferredFunction() noexcept { Callback(); }
|
|
|
|
DeferredFunction(const DeferredFunction&) = delete;
|
|
DeferredFunction(const DeferredFunction&&) = delete;
|
|
void operator=(const DeferredFunction&) = delete;
|
|
void operator=(DeferredFunction&&) = delete;
|
|
|
|
private:
|
|
Function Callback;
|
|
};
|
|
|
|
template <class Function>
|
|
auto Defer(Function&& fct) noexcept
|
|
{
|
|
return DeferredFunction<std::decay_t<Function>>{ std::forward<Function>(fct) };
|
|
}
|
|
|
|
inline bool IsValid(ByteBuffer buffer)
|
|
{
|
|
return buffer.Size > 0 && buffer.Data;
|
|
}
|
|
|
|
extern JULIET_API void Free(ByteBuffer& buffer);
|
|
|
|
template <std::integral T>
|
|
[[nodiscard]] constexpr T AlignPow2(T x, T alignment)
|
|
{
|
|
// Safety Check:
|
|
Assert(std::has_single_bit(static_cast<size_t>(alignment)));
|
|
|
|
return (x + alignment - 1) & ~(alignment - 1);
|
|
}
|
|
|
|
template <typename T>
|
|
inline void Swap(T* Restrict a, T* Restrict b)
|
|
{
|
|
T temp = std::move(*a);
|
|
*a = std::move(*b);
|
|
*b = std::move(temp);
|
|
}
|
|
|
|
// Move to another file dedicated to those
|
|
#if defined(__clang__)
|
|
#define COMPILER_CLANG 1
|
|
#elif defined(_MSC_VER)
|
|
#define COMPILER_MSVC 1
|
|
#endif
|
|
|
|
// Undef anything not defined
|
|
#if !defined(COMPILER_CLANG)
|
|
#define COMPILER_CLANG 0
|
|
#endif
|
|
#if !defined(COMPILER_MSVC)
|
|
#define COMPILER_MSVC 0
|
|
#endif
|
|
|
|
#if COMPILER_MSVC
|
|
#define AlignOf(T) __alignof(T)
|
|
#elif COMPILER_CLANG
|
|
#define AlignOf(T) __alignof(T)
|
|
#elif COMPILER_GCC
|
|
#define AlignOf(T) __alignof__(T)
|
|
#else
|
|
#error AlignOf not defined for this compiler.
|
|
#endif
|
|
} // namespace Juliet
|