diff --git a/Code/Dqn.h b/Code/Dqn.h index 6bd136e..49e4351 100644 --- a/Code/Dqn.h +++ b/Code/Dqn.h @@ -1,23 +1,30 @@ -// #define DQN_ENABLE_ASSERTS -// To enable DQN_ASSERT, otherwise compile out and use non aborting asserts where appropriate - -// #define DQN_IMPLEMENTATION -// In one and only one C++ file to enable the header file - +// ------------------------------------------------------------------------------------------------- +// +// Preprocessor Config +// +// ------------------------------------------------------------------------------------------------- +// #define DQN_IMPLEMENTATION In one and only one C++ file to enable the header file +// #define DQN_NO_ASSERT Disable assertions +// #define DQN_STATIC_API Apply static to all function definitions and disable external linkage to other TU's. +// // #define DQN_ALLOCATOR_DEFAULT_TO_NULL +// // If defined, 0 initialising an allocator uses the null allocator (i.e. crashes // when allocating). It forces the user to specify explicitly which allocator // to use, for example. -/* - Dqn_Allocator allocator = {}; - allocator.type = Dqn_AllocatorType::Heap; - - or - - Dqn_Allocator allocator = Dqn_AllocatorHeap() -*/ - +// +// Dqn_Allocator allocator = {}; +// allocator.type = Dqn_AllocatorType::Heap; +// +// or +// +// Dqn_Allocator allocator = Dqn_AllocatorHeap() +// // Otherwise if not defined, Dqn_Allocator allocator = {}; will by default use malloc, realloc, free +// + +#if !defined(DQN_H) +#define DQN_H #if defined(_MSC_VER) #if defined(_CRT_SECURE_NO_WARNINGS) @@ -27,9 +34,246 @@ #endif #endif +#include // FLT_MAX +#include // uint/int typedefs +#include // va_list +#include // INT_MIN/MAX etc +#include // ptrdiff_t + // ------------------------------------------------------------------------------------------------- // -// NOTE: stb_sprintf +// NOTE: Overridable Macros +// +// ------------------------------------------------------------------------------------------------- +#if !defined(DQN_CALLOC) + #include + #define DQN_CALLOC(count, size) calloc(count, size) +#endif + +#if !defined(DQN_MALLOC) + #include + #define DQN_MALLOC(size) malloc(size) +#endif + +#if !defined(DQN_FREE) + #include + #define DQN_FREE(ptr) free(ptr) +#endif + +#if !defined(DQN_MEMCOPY) + #include + #define DQN_MEMCOPY(dest, src, count) memcpy(dest, src, count) +#endif + +#if !defined(DQN_MEMSET) + #include + #define DQN_MEMSET(dest, value, count) memset(dest, value, count) +#endif + +#if !defined(DQN_MEMCMP) + #include + #define DQN_MEMCMP(ptr1, ptr2, num) memcmp(ptr1, ptr2, num) +#endif + +#if !defined(DQN_SQRTF) + #include + #define DQN_SQRTF(val) sqrtf(val) +#endif + + +// ------------------------------------------------------------------------------------------------- +// +// Compiler +// +// ------------------------------------------------------------------------------------------------- +#if defined(_MSC_VER) + #define DQN_COMPILER_MSVC +#elif defined(__clang__) + #define DQN_COMPILER_CLANG +#elif defined(__GNUC__) + #define DQN_COMPILER_GCC +#endif + +// ------------------------------------------------------------------------------------------------- +// +// Utility Macros +// +// ------------------------------------------------------------------------------------------------- +#define DQN_CAST(val) (val) +#define DQN_ABS(val) (((val) < 0) ? (-(val)) : (val)) +#define DQN_SQUARED(val) ((val) * (val)) +#define DQN_MIN(a, b) ((a < b) ? (a) : (b)) +#define DQN_MAX(a, b) ((a > b) ? (a) : (b)) +#define DQN_SWAP(a, b) \ + do \ + { \ + auto tmp = a; \ + a = b; \ + b = tmp; \ + } while (0) + +#define DQN_LEN_AND_STR(string) Dqn_CharCount(str), string +#define DQN_STR_AND_LEN(string) string, Dqn_CharCount(string) +#define DQN_STR_AND_LEN_I(string) string, (int)Dqn_CharCount(string) +#define DQN_FOR_EACH(i, limit) for (Dqn_isize i = 0; i < (Dqn_isize)(limit); ++i) +#define DQN_FOR_EACH_REVERSE(i, limit) for (Dqn_isize i = (Dqn_isize)(limit-1); i >= 0; --i) +#define DQN_FOR_EACH_ITERATOR(it_name, array, num) for (auto it_name = array; it_name != (array + num); it_name++) + +#define DQN_BYTES(val) (val) +#define DQN_KILOBYTES(val) (1024ULL * DQN_BYTES(val)) +#define DQN_MEGABYTES(val) (1024ULL * DQN_KILOBYTES(val)) +#define DQN_GIGABYTES(val) (1024ULL * DQN_MEGABYTES(val)) + +#define DQN_MINS_TO_S(val) ((val) * 60ULL) +#define DQN_HOURS_TO_S(val) (DQN_MINS_TO_S(val) * 60ULL) +#define DQN_DAYS_TO_S(val) (DQN_HOURS_TO_S(val) * 24ULL) +#define DQN_YEARS_TO_S(val) (DQN_DAYS_TO_S(val) * 365ULL) +#define DQN_ISIZEOF(val) DQN_CAST(ptrdiff_t)sizeof(val) + +#ifdef DQN_COMPILER_MSVC + #define DQN_DEBUG_BREAK __debugbreak() +#elif defined(DQN_COMPILER_CLANG) || defined(DQN_COMPILER_GCC) + #include + #define DQN_DEBUG_BREAK raise(SIGTRAP) +#endif + +#define DQN_INVALID_CODE_PATH 0 +#define DQN_SECONDS_TO_MS(val) ((val) * 1000.0f) +#define DQN_MATH_PI 3.14159265359f +#define DQN_DEGREE_TO_RADIAN(val) (val) * (DQN_MATH_PI / 180.0f) + +#if defined(DQN_STATIC_API) + #define DQN_API static +#else + #define DQN_API +#endif +#define DQN_LOCAL_PERSIST static + +// ------------------------------------------------------------------------------------------------- +// +// Assert Macro +// +// ------------------------------------------------------------------------------------------------ +#if defined(DQN_NO_ASSERT) + #define DQN_ASSERT(expr) + #define DQN_ASSERT_MSG(expr, fmt, ...) + #define DQN_ASSERT_IF(expr) if ((expr)) + #define DQN_ASSERT_MSG_IF(expr, fmt, ...) if ((expr)) +#else + #define DQN_ASSERT(expr) DQN_ASSERT_MSG(expr, "") + #define DQN_ASSERT_MSG(expr, fmt, ...) \ + if (!(expr)) \ + { \ + DQN_LOG_E("Assert: [" #expr "] " fmt, ##__VA_ARGS__); \ + DQN_DEBUG_BREAK; \ + } + + #define DQN_ASSERT_IF(expr) DQN_ASSERT_MSG_IF(expr, "") + #define DQN_ASSERT_MSG_IF(expr, fmt, ...) \ + DQN_ASSERT_MSG(!(expr), fmt, ## __VA_ARGS__) \ + if (0) +#endif + +// ------------------------------------------------------------------------------------------------ +// +// Typedefs +// +// ------------------------------------------------------------------------------------------------ +using Dqn_uintptr = uintptr_t; +using Dqn_usize = size_t; +using Dqn_isize = ptrdiff_t; +using Dqn_f64 = double; +using Dqn_f32 = float; +using Dqn_i64 = int64_t; +using Dqn_i32 = int32_t; +using Dqn_i16 = int16_t; +using Dqn_i8 = int8_t; +using Dqn_uchar = unsigned char; +using Dqn_uint = unsigned int; +using Dqn_u64 = uint64_t; +using Dqn_u32 = uint32_t; +using Dqn_u16 = uint16_t; +using Dqn_u8 = uint8_t; +using Dqn_b32 = int32_t; + +// ------------------------------------------------------------------------------------------------ +// +// Constants +// +// ------------------------------------------------------------------------------------------------ +const Dqn_i32 DQN_I32_MAX = INT32_MAX; +const Dqn_u32 DQN_U32_MAX = UINT32_MAX; +const Dqn_f32 DQN_F32_MAX = FLT_MAX; +const Dqn_isize DQN_ISIZE_MAX = PTRDIFF_MAX; +const Dqn_usize DQN_USIZE_MAX = SIZE_MAX; + +// ------------------------------------------------------------------------------------------------ +// +// Compile Time Utilities +// +// ------------------------------------------------------------------------------------------------ +template +constexpr Dqn_usize Dqn_ArrayCount(T const (&)[N]) +{ + return N; +} + +template +constexpr Dqn_isize Dqn_ArrayCountI(T const (&)[N]) +{ + return N; +} + +template +constexpr Dqn_usize Dqn_CharCount(char const (&)[N]) +{ + return N - 1; +} + +template +constexpr Dqn_isize Dqn_CharCountI(char const (&)[N]) +{ + return N - 1; +} + +// ------------------------------------------------------------------------------------------------ +// +// Defer Macro +// +// ------------------------------------------------------------------------------------------------ +template +struct DqnDefer +{ + Procedure proc; + DqnDefer(Procedure p) : proc(p) {} + ~DqnDefer() { proc(); } +}; + +struct DqnDeferHelper +{ + template + DqnDefer operator+(Lambda lambda) { return DqnDefer(lambda); }; +}; + +#define DQN_TOKEN_COMBINE2(x, y) x ## y +#define DQN_TOKEN_COMBINE(x, y) DQN_TOKEN_COMBINE2(x, y) +#define DQN_UNIQUE_NAME(prefix) DQN_TOKEN_COMBINE(prefix, __LINE__) +#define DQN_DEFER const auto DQN_UNIQUE_NAME(defer_lambda_) = DqnDeferHelper() + [&]() + +// ------------------------------------------------------------------------------------------------ +// +// Utility Enums +// +// ------------------------------------------------------------------------------------------------ +enum struct Dqn_ZeroMem +{ + No, + Yes +}; + +// ------------------------------------------------------------------------------------------------- +// +// stb_sprintf // // ------------------------------------------------------------------------------------------------- // stb_sprintf - v1.05 - public domain snprintf() implementation @@ -210,234 +454,85 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char c STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); - #endif // STB_SPRINTF_H_INCLUDE // ------------------------------------------------------------------------------------------------- // -// DQN +// NOTE: Logging // // ------------------------------------------------------------------------------------------------- -#ifndef DQN_H -#define DQN_H +#define X_MACRO \ + X_ENTRY(Debug, "DBG") \ + X_ENTRY(Error, "ERR") \ + X_ENTRY(Warning, "WRN") \ + X_ENTRY(Info, "INF") \ + X_ENTRY(Memory, "MEM") -#include // FLT_MAX -#include // uint/int typedefs -#include // memset, memcmp, strlen, strcmp -#include // va_list -#include // INT_MIN/MAX etc -#include // ptrdiff_t +#define X_ENTRY(enum_val, string) enum_val, +enum struct Dqn_LogType { X_MACRO }; +#undef X_ENTRY -#undef DQN_HEADER_IMPLEMENTATION -#include "DqnHeader.h" +#define X_ENTRY(enum_val, string) string, +char const *Dqn_LogTypeString[] = { X_MACRO }; +#undef X_MACRO -#ifndef DQN_CALLOC - #include - #define DQN_CALLOC(count, size) calloc(count, size) -#endif +#define DQN_LOG_E(fmt, ...) dqn_core.Log(Dqn_LogType::Error, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) +#define DQN_LOG_D(fmt, ...) dqn_core.Log(Dqn_LogType::Debug, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) +#define DQN_LOG_W(fmt, ...) dqn_core.Log(Dqn_LogType::Warning, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) +#define DQN_LOG_I(fmt, ...) dqn_core.Log(Dqn_LogType::Info, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) +#define DQN_LOG_M(fmt, ...) dqn_core.Log(Dqn_LogType::Memory, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) +#define DQN_LOG(log_type, fmt, ...) dqn_core.Log(log_type, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#ifndef DQN_MALLOC - #include - #define DQN_MALLOC(size) malloc(size) -#endif +#define DQN_LOG_PROC(name) void name(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, ...) +typedef DQN_LOG_PROC(Dqn_LogProc); -#ifndef DQN_FREE - #include - #define DQN_FREE(ptr) free(ptr) -#endif +DQN_API void Dqn_LogV(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, va_list va); +DQN_API DQN_LOG_PROC(Dqn_Log); -#ifndef DQN_SQRTF - #include - #define DQN_SQRTF(val) sqrtf(val) -#endif - -#ifndef DQN_MEMCOPY - #include - #define DQN_MEMCOPY(dest, src, count) memcpy(dest, src, count) -#endif - -#ifndef DQN_MEMSET - #include - #define DQN_MEMSET(dest, value, count) memset(dest, value, count) -#endif - -#ifndef DQN_MEMCMP - #include - #define DQN_MEMCMP(ptr1, ptr2, num) memcmp(ptr1, ptr2, num) -#endif - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Typedefs, Macros, Utils -// @ -// @ ------------------------------------------------------------------------------------------------- -#define DQN_CAST(val) (val) -#define DQN_ABS(val) (((val) < 0) ? (-(val)) : (val)) -#define DQN_SQUARED(val) ((val) * (val)) -#define DQN_MIN(a, b) ((a < b) ? (a) : (b)) -#define DQN_MAX(a, b) ((a > b) ? (a) : (b)) -#define DQN_SWAP(a, b) \ - do \ - { \ - auto tmp = a; \ - a = b; \ - b = tmp; \ - } while (0) - -#define DQN_LEN_AND_STR(string) Dqn_CharCount(str), string -#define DQN_STR_AND_LEN(string) string, Dqn_CharCount(string) -#define DQN_STR_AND_LEN_I(string) string, (int)Dqn_CharCount(string) -#define DQN_FOR_EACH(i, limit) for (Dqn_isize i = 0; i < (Dqn_isize)(limit); ++i) -#define DQN_FOR_EACH_REVERSE(i, limit) for (Dqn_isize i = (Dqn_isize)(limit-1); i >= 0; --i) -#define DQN_FOR_EACH_ITERATOR(it_name, array, num) for (auto it_name = array; it_name != (array + num); it_name++) - -#define DQN_BYTES(val) (val) -#define DQN_KILOBYTES(val) (1024ULL * DQN_BYTES(val)) -#define DQN_MEGABYTES(val) (1024ULL * DQN_KILOBYTES(val)) -#define DQN_GIGABYTES(val) (1024ULL * DQN_MEGABYTES(val)) - -#define DQN_MINS_TO_S(val) ((val) * 60ULL) -#define DQN_HOURS_TO_S(val) (DQN_MINS_TO_S(val) * 60ULL) -#define DQN_DAYS_TO_S(val) (DQN_HOURS_TO_S(val) * 24ULL) -#define DQN_YEARS_TO_S(val) (DQN_DAYS_TO_S(val) * 365ULL) - -#define DQN_ARRAY_COUNT(array) (sizeof(array)/sizeof(array[0])) -#define DQN_ISIZEOF(val) DQN_CAST(ptrdiff_t)sizeof(val) - -#ifdef _MSC_VER - #define DQN_DEBUG_BREAK __debugbreak() -#else - #include - #define DQN_DEBUG_BREAK raise(SIGTRAP) -#endif - -#ifndef DQN_ASSERT_MSG - #define DQN_ASSERT_MSG(expr, fmt, ...) \ - if (!(expr)) \ - { \ - DQN_LOG_E("Assert: [" #expr "] " fmt, ##__VA_ARGS__); \ - DQN_DEBUG_BREAK; \ - } -#endif - -#define DQN_ASSERT(expr) DQN_ASSERT_MSG(expr, "") -#define DQN_ASSERT_IF(expr) DQN_ASSERT_MSG_IF(expr, "") -#define DQN_ASSERT_MSG_IF(expr, fmt, ...) \ - DQN_ASSERT_MSG(!(expr), fmt, ## __VA_ARGS__); \ - if (0) - -#define DQN_INVALID_CODE_PATH 0 -#define DQN_SECONDS_TO_MS(val) ((val) * 1000.0f) -#define DQN_MATH_PI 3.14159265359f -#define DQN_DEGREE_TO_RADIAN(val) (val) * (DQN_MATH_PI / 180.0f) - -#define DQN_FILE_SCOPE static -#define DQN_LOCAL_PERSIST static - -using Dqn_uintptr = uintptr_t; -using Dqn_usize = size_t; -using Dqn_isize = ptrdiff_t; - -using Dqn_f64 = double; -using Dqn_f32 = float; - -using Dqn_i64 = int64_t; -using Dqn_i32 = int32_t; -using Dqn_i16 = int16_t; -using Dqn_i8 = int8_t; - -using Dqn_uchar = unsigned char; -using Dqn_uint = unsigned int; -using Dqn_u64 = uint64_t; -using Dqn_u32 = uint32_t; -using Dqn_u16 = uint16_t; -using Dqn_u8 = uint8_t; - -using Dqn_b32 = int32_t; - -const Dqn_i32 DQN_I32_MAX = INT32_MAX; -const Dqn_u32 DQN_U32_MAX = UINT32_MAX; -const Dqn_f32 DQN_F32_MAX = FLT_MAX; -const Dqn_isize DQN_ISIZE_MAX = PTRDIFF_MAX; -const Dqn_usize DQN_USIZE_MAX = SIZE_MAX; - - -template -DQN_HEADER_COPY_PROTOTYPE(constexpr Dqn_usize, Dqn_ArrayCount(T const (&)[N])) { return N; } - -template -DQN_HEADER_COPY_PROTOTYPE(constexpr Dqn_isize, Dqn_ArrayCountI(T const (&)[N])) { return N; } - -template -DQN_HEADER_COPY_PROTOTYPE(constexpr Dqn_usize, Dqn_CharCount(char const (&)[N])) { return N - 1; } - -template -DQN_HEADER_COPY_PROTOTYPE(constexpr Dqn_isize, Dqn_CharCountI(char const (&)[N])) { return N - 1; } - -template -struct DqnDefer +// ------------------------------------------------------------------------------------------------- +// +// Core Config +// +// ------------------------------------------------------------------------------------------------- +struct Dqn_Core { - Procedure proc; - DqnDefer(Procedure p) : proc(p) {} - ~DqnDefer() { proc(); } + Dqn_LogProc *Log; +}; +extern Dqn_Core dqn_core; + +// ------------------------------------------------------------------------------------------------- +// +// Dqn_Align +// +// ------------------------------------------------------------------------------------------------- +// NOTE: Even if pointer is aligned, align it again, ensuring there's at minimum +// 1 byte and at most alignment bytes of space between the aligned pointer and +// raw pointer. We do this to keep metadata exactly 1 byte behind the aligned +// pointer. +DQN_API Dqn_uintptr Dqn_AlignAddressEnsuringSpace(Dqn_uintptr address, Dqn_u8 alignment); +DQN_API Dqn_uintptr Dqn_AlignAddress (Dqn_uintptr address, Dqn_u8 alignment); + +// ------------------------------------------------------------------------------------------------- +// +// Dqn_PointerMetadata +// +// ------------------------------------------------------------------------------------------------- +struct Dqn_PointerMetadata +{ + Dqn_u8 alignment; + Dqn_u8 offset; // Subtract offset from aligned ptr to return to the allocation ptr }; -struct DqnDeferHelper -{ - template - DqnDefer operator+(Lambda lambda) { return DqnDefer(lambda); }; -}; +DQN_API Dqn_isize Dqn_PointerMetadata_SizeRequired(Dqn_isize size, Dqn_u8 alignment); +DQN_API char *Dqn_PointerMetadata_Init(void *ptr, Dqn_u8 alignment); +DQN_API Dqn_PointerMetadata Dqn_PointerMetadata_Get(void *ptr); +DQN_API char *Dqn_PointerMetadata_GetRawPointer(void *ptr); -#define DQN_TOKEN_COMBINE2(x, y) x ## y -#define DQN_TOKEN_COMBINE(x, y) DQN_TOKEN_COMBINE2(x, y) -#define DQN_UNIQUE_NAME(prefix) DQN_TOKEN_COMBINE(prefix, __LINE__) -#define DQN_DEFER const auto DQN_UNIQUE_NAME(defer_lambda_) = DqnDeferHelper() + [&]() - -enum struct Dqn_ZeroMem { No, Yes }; - -enum struct Dqn_LogType -{ - Debug, - Error, - Warning, - Info, - Memory, -}; - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Logging -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(constexpr inline char const *, Dqn_LogTypeTag(Dqn_LogType type)) -{ - if (type == Dqn_LogType::Debug) return " DBG"; - else if (type == Dqn_LogType::Error) return " ERR"; - else if (type == Dqn_LogType::Warning) return "WARN"; - else if (type == Dqn_LogType::Info) return "INFO"; - else if (type == Dqn_LogType::Memory) return " MEM"; - return " XXX"; -} - -DQN_HEADER_COPY_BEGIN -// NOTE: Set the callback to get called whenever a log message has been printed -#define DQN_LOG_CALLBACK(name) void name(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *log_str) -typedef DQN_LOG_CALLBACK(Dqn_LogCallback); -Dqn_LogCallback *Dqn_log_callback; - -#define DQN_LOG_E(fmt, ...) Dqn_Log(Dqn_LogType::Error, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG_D(fmt, ...) Dqn_Log(Dqn_LogType::Debug, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG_W(fmt, ...) Dqn_Log(Dqn_LogType::Warning, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG_I(fmt, ...) Dqn_Log(Dqn_LogType::Info, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG_M(fmt, ...) Dqn_Log(Dqn_LogType::Memory, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG(log_type, fmt, ...) Dqn_Log(log_type, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -DQN_HEADER_COPY_END -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Math -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_BEGIN +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Math +// +// ------------------------------------------------------------------------------------------------- union Dqn_V2I { struct { Dqn_i32 x, y; }; @@ -509,6 +604,15 @@ union Dqn_V2 constexpr Dqn_V2 &operator+=(Dqn_V2 other) { *this = *this + other; return *this; } }; +DQN_API Dqn_V2I Dqn_V2_ToV2I (Dqn_V2 a); +DQN_API Dqn_V2 Dqn_V2_Min (Dqn_V2 a, Dqn_V2 b); +DQN_API Dqn_V2 Dqn_V2_Max (Dqn_V2 a, Dqn_V2 b); +DQN_API Dqn_V2 Dqn_V2_Abs (Dqn_V2 a); +DQN_API Dqn_f32 Dqn_V2_Dot (Dqn_V2 a, Dqn_V2 b); +DQN_API Dqn_f32 Dqn_V2_LengthSq (Dqn_V2 a, Dqn_V2 b); +DQN_API Dqn_V2 Dqn_V2_Normalise (Dqn_V2 a); +DQN_API Dqn_V2 Dqn_V2_Perpendicular(Dqn_V2 a); + union Dqn_V3 { struct { Dqn_f32 x, y, z; }; @@ -579,6 +683,8 @@ union Dqn_V4 constexpr Dqn_V4 &operator+=(Dqn_V4 other) { *this = *this + other; return *this; } }; +DQN_API Dqn_f32 Dqn_V4_Dot(Dqn_V4 const *a, Dqn_V4 const *b); + struct Dqn_Rect { Dqn_V2 min, max; @@ -596,6 +702,18 @@ struct Dqn_RectI32 Dqn_RectI32(Dqn_V2I min, Dqn_V2I max) : min(min), max(max) {} }; +DQN_API Dqn_Rect Dqn_Rect_InitFromPosAndSize(Dqn_V2 pos, Dqn_V2 size); +DQN_API Dqn_V2 Dqn_Rect_Center (Dqn_Rect rect); +DQN_API Dqn_b32 Dqn_Rect_ContainsPoint (Dqn_Rect rect, Dqn_V2 p); +DQN_API Dqn_b32 Dqn_Rect_ContainsRect (Dqn_Rect a, Dqn_Rect b); +DQN_API Dqn_V2 Dqn_Rect_Size (Dqn_Rect rect); +DQN_API Dqn_Rect Dqn_Rect_Move (Dqn_Rect src, Dqn_V2 move_amount); +DQN_API Dqn_b32 Dqn_Rect_Intersects (Dqn_Rect a, Dqn_Rect b); +DQN_API Dqn_Rect Dqn_Rect_Intersection (Dqn_Rect a, Dqn_Rect b); +DQN_API Dqn_Rect Dqn_Rect_Union (Dqn_Rect a, Dqn_Rect b); +DQN_API Dqn_Rect Dqn_Rect_FromRectI32 (Dqn_RectI32 a); +DQN_API Dqn_V2I Dqn_RectI32_Size (Dqn_RectI32 rect); + union Dqn_Mat4 { Dqn_f32 e[16]; @@ -603,38 +721,28 @@ union Dqn_Mat4 Dqn_f32 row_major[4][4]; Dqn_f32 operator[](Dqn_usize i) const { return e[i]; } }; -DQN_HEADER_COPY_END -DQN_HEADER_COPY_PROTOTYPE(template int, Dqn_MemCmpType(T const *ptr1, T const *ptr2)) -{ - int result = DQN_MEMCMP(ptr1, ptr2, sizeof(T)); - return result; -} +DQN_API Dqn_Mat4 Dqn_Mat4_Identity (); +DQN_API Dqn_Mat4 Dqn_Mat4_Scale3f (Dqn_f32 x, Dqn_f32 y, Dqn_f32 z); +DQN_API Dqn_Mat4 Dqn_Mat4_ScaleV3 (Dqn_V3 vec); +DQN_API Dqn_Mat4 Dqn_Mat4_Translate3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z); +DQN_API Dqn_Mat4 Dqn_Mat4_TranslateV3(Dqn_V3 vec); +DQN_API Dqn_Mat4 operator* (Dqn_Mat4 const &a, Dqn_Mat4 const &b); +DQN_API Dqn_V4 operator* (Dqn_Mat4 const &mat, Dqn_V4 const &vec); -DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_MemZero(T *src)) -{ - T *result = DQN_CAST(T *)DQN_MEMSET(src, 0, sizeof(T)); - return result; -} +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Math Utils +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_V2 Dqn_LerpV2 (Dqn_V2 a, Dqn_f32 t, Dqn_V2 b); +DQN_API Dqn_f32 Dqn_LerpF32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b); -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_AllocatorAlignMetadata -// @ -// @ ------------------------------------------------------------------------------------------------- -// @ For embedding alignment metadata into pointers, useful for custom allocators -struct Dqn_AllocatorAlignMetadata -{ - Dqn_u8 alignment; - Dqn_u8 offset; // Subtract offset from aligned ptr to return to the allocation ptr -}; - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_Allocator -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_BEGIN +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Allocator +// +// ------------------------------------------------------------------------------------------------- enum struct Dqn_Allocator_Type { #if defined(DQN_ALLOCATOR_DEFAULT_TO_NULL) @@ -673,50 +781,27 @@ struct Dqn_Allocator Dqn_Allocator_AllocateProc *allocate; Dqn_Allocator_FreeProc *free; }; -DQN_HEADER_COPY_END -DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_InitWithNull()) -{ - Dqn_Allocator result = {}; - result.type = Dqn_Allocator_Type::Null; - return result; -} +DQN_API Dqn_Allocator Dqn_Allocator_InitWithNull (); +DQN_API Dqn_Allocator Dqn_Allocator_InitWithHeap (); +DQN_API Dqn_Allocator Dqn_Allocator_InitWithXHeap(); +DQN_API Dqn_Allocator Dqn_Allocator_InitWithArena(Dqn_ArenaAllocator *arena); +DQN_API void *Dqn_Allocator_Allocate (Dqn_Allocator *allocator, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes); +DQN_API void Dqn_Allocator_Free (Dqn_Allocator *allocator, void *ptr); -DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_InitWithHeap()) -{ - Dqn_Allocator result = {}; - result.type = Dqn_Allocator_Type::Heap; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_InitWithXHeap()) -{ - Dqn_Allocator result = {}; - result.type = Dqn_Allocator_Type::XHeap; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_InitWithArena(Dqn_ArenaAllocator *arena)) -{ - Dqn_Allocator result = {}; - result.type = Dqn_Allocator_Type::Arena; - result.context.arena = arena; - return result; -} - -void *Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem); -DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_Allocator_AllocateType(Dqn_Allocator *allocator, Dqn_isize num, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)) +template +DQN_API T * +Dqn_Allocator_AllocateType(Dqn_Allocator *allocator, Dqn_isize num, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes) { auto *result = DQN_CAST(T *)Dqn_Allocator_Allocate(allocator, sizeof(T) * num, alignof(T), zero_mem); return result; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_ArenaAllocator -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_BEGIN +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_ArenaAllocator +// +// ------------------------------------------------------------------------------------------------- struct Dqn_ArenaAllocatorBlock { void *memory; @@ -757,21 +842,68 @@ struct Dqn_ArenaAllocatorScopedRegion Dqn_ArenaAllocatorRegion region; }; -void * Dqn_ArenaAllocator_Allocate(Dqn_ArenaAllocator *arena, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem); -Dqn_b32 Dqn_ArenaAllocator_Reserve(Dqn_ArenaAllocator *arena, Dqn_isize size); -DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_ArenaAllocator_AllocateType(Dqn_ArenaAllocator *arena, Dqn_isize num = 1, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)) +DQN_API Dqn_ArenaAllocator Dqn_ArenaAllocator_InitWithAllocator(Dqn_Allocator allocator, Dqn_isize size = 0); +DQN_API Dqn_ArenaAllocator Dqn_ArenaAllocator_InitWithMemory (void *memory, Dqn_isize size); +DQN_API void *Dqn_ArenaAllocator_Allocate (Dqn_ArenaAllocator *arena, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes); +DQN_API void Dqn_ArenaAllocator_Free (Dqn_ArenaAllocator *arena); +DQN_API Dqn_b32 Dqn_ArenaAllocator_Reserve (Dqn_ArenaAllocator *arena, Dqn_isize size); +DQN_API void Dqn_ArenaAllocator_ResetUsage (Dqn_ArenaAllocator *arena, Dqn_ZeroMem zero_mem); +DQN_API Dqn_ArenaAllocatorRegion Dqn_ArenaAllocator_BeginRegion (Dqn_ArenaAllocator *arena); +DQN_API void Dqn_ArenaAllocator_EndRegion (Dqn_ArenaAllocatorRegion region); +DQN_API Dqn_ArenaAllocatorScopedRegion Dqn_ArenaAllocator_MakeScopedRegion (Dqn_ArenaAllocator *arena); + +template +T *Dqn_ArenaAllocator_AllocateType(Dqn_ArenaAllocator *arena, Dqn_isize num = 1, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes) { auto *result = DQN_CAST(T *)Dqn_ArenaAllocator_Allocate(arena, sizeof(T) * num, alignof(T), zero_mem); return result; } -DQN_HEADER_COPY_END -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: String -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_BEGIN +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Bit +// +// ------------------------------------------------------------------------------------------------- +DQN_API void Dqn_Bit_UnsetInplace(Dqn_u32 *flags, Dqn_u32 bitfield); +DQN_API void Dqn_Bit_SetInplace(Dqn_u32 *flags, Dqn_u32 bitfield); +DQN_API Dqn_b32 Dqn_Bit_IsSet(Dqn_u32 bits, Dqn_u32 bits_to_set); +DQN_API Dqn_b32 Dqn_Bit_IsNotSet(Dqn_u32 bits, Dqn_u32 bits_to_check); + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Safe Arithmetic +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_i64 Dqn_Safe_AddI64 (Dqn_i64 a, Dqn_i64 b); +DQN_API Dqn_i64 Dqn_Safe_MulI64 (Dqn_i64 a, Dqn_i64 b); +DQN_API Dqn_u64 Dqn_Safe_AddU64 (Dqn_u64 a, Dqn_u64 b); +DQN_API Dqn_u64 Dqn_Safe_SubU64 (Dqn_u64 a, Dqn_u64 b); +DQN_API Dqn_u32 Dqn_Safe_SubU32 (Dqn_u32 a, Dqn_u32 b); +DQN_API Dqn_u64 Dqn_Safe_MulU64 (Dqn_u64 a, Dqn_u64 b); +DQN_API int Dqn_Safe_TruncateISizeToInt (Dqn_isize val); +DQN_API Dqn_i32 Dqn_Safe_TruncateISizeToI32 (Dqn_isize val); +DQN_API Dqn_i8 Dqn_Safe_TruncateISizeToI8 (Dqn_isize val); +DQN_API Dqn_u32 Dqn_Safe_TruncateUSizeToU32 (Dqn_u64 val); +DQN_API int Dqn_Safe_TruncateUSizeToI32 (Dqn_usize val); +DQN_API int Dqn_Safe_TruncateUSizeToInt (Dqn_usize val); +DQN_API Dqn_isize Dqn_Safe_TruncateUSizeToISize(Dqn_usize val); + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Char +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_b32 Dqn_Char_IsAlpha (char ch); +DQN_API Dqn_b32 Dqn_Char_IsDigit (char ch); +DQN_API Dqn_b32 Dqn_Char_IsAlphaNum (char ch); +DQN_API Dqn_b32 Dqn_Char_IsWhitespace(char ch); +DQN_API char Dqn_Char_ToLower (char ch); + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: String +// +// ------------------------------------------------------------------------------------------------- struct Dqn_String { union { @@ -788,21 +920,76 @@ struct Dqn_String char *end () { return str + len; } }; -inline Dqn_b32 operator==(Dqn_String const &lhs, Dqn_String const &rhs) -{ - Dqn_b32 result = lhs.len == rhs.len && (DQN_MEMCMP(lhs.str, rhs.str, lhs.len) == 0); - return result; -} - +DQN_API Dqn_b32 Dqn_String_Compare (Dqn_String const lhs, Dqn_String const rhs); +DQN_API Dqn_b32 Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs); +DQN_API Dqn_String Dqn_String_Copy (Dqn_Allocator *allocator, Dqn_String const src); +DQN_API Dqn_String Dqn_String_TrimWhitespaceAround (Dqn_String src); +DQN_API Dqn_b32 operator== (Dqn_String const &lhs, Dqn_String const &rhs); #define DQN_STRING_LITERAL(string) {string, Dqn_CharCountI(string)} -DQN_HEADER_COPY_END -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: String Builder -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_BEGIN +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Asprintf (Allocate Sprintf) +// +// ------------------------------------------------------------------------------------------------- +// return: The allocated string. If allocation fails, the str returned is nullptr and length is set o the size required, NOT INCLUDING the null terminator. +DQN_API Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va); +DQN_API Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...); + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Str +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_b32 Dqn_Str_Equals (char const *a, char const *b, Dqn_isize a_len = -1, Dqn_isize b_len = -1); +DQN_API char const *Dqn_Str_FindMulti (char const *buf, char const *find_list[], Dqn_isize const *find_string_lens, Dqn_isize find_len, Dqn_isize *match_index, Dqn_isize buf_len = -1); +DQN_API char const *Dqn_Str_Find (char const *buf, char const *find, Dqn_isize buf_len = -1, Dqn_isize find_len = -1); +DQN_API Dqn_b32 Dqn_Str_Match (char const *src, char const *find, int find_len); +DQN_API char const *Dqn_Str_SkipToChar (char const *src, char ch); +DQN_API char const *Dqn_Str_SkipToNextAlphaNum (char const *src); +DQN_API char const *Dqn_Str_SkipToNextDigit (char const *src); +DQN_API char const *Dqn_Str_SkipToNextChar (char const *src); +DQN_API char const *Dqn_Str_SkipToNextWord (char const *src); +DQN_API char const *Dqn_Str_SkipToNextWhitespace (char const *src); +DQN_API char const *Dqn_Str_SkipWhitespace (char const *src); +DQN_API char const *Dqn_Str_SkipToCharInPlace (char const **src, char ch); +DQN_API char const *Dqn_Str_SkipToNextAlphaNumInPlace (char const **src); +DQN_API char const *Dqn_Str_SkipToNextCharInPlace (char const **src); +DQN_API char const *Dqn_Str_SkipToNextWhitespaceInPlace(char const **src); +DQN_API char const *Dqn_Str_SkipToNextWordInPlace (char const **src); +DQN_API char const *Dqn_Str_SkipWhitespaceInPlace (char const **src); +DQN_API Dqn_u64 Dqn_Str_ToU64 (char const *buf, int len = -1); +DQN_API Dqn_i64 Dqn_Str_ToI64 (char const *buf, int len = -1); + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_File +// +// ------------------------------------------------------------------------------------------------- +DQN_API char *Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_isize *file_size); + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Utiltiies +// +// ------------------------------------------------------------------------------------------------- +struct Dqn_U64Str +{ + // Points to the start of the str in the buffer, not necessarily buf since + // we write into the buffer in reverse + char *str; + char buf[27]; // NOTE(doyle): 27 is the maximum size of Dqn_u64 including commas + int len; +}; + +DQN_API char *Dqn_EpochTimeToDate(Dqn_i64 timestamp, char *buf, Dqn_isize buf_len); +DQN_API char *Dqn_U64ToStr (Dqn_u64 val, Dqn_U64Str *result, Dqn_b32 comma_sep); + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: String Builder +// +// ------------------------------------------------------------------------------------------------- struct Dqn_StringBuilderBlock { char *mem; @@ -820,7 +1007,6 @@ struct Dqn_StringBuilder Dqn_StringBuilderBlock fixed_mem_block; Dqn_StringBuilderBlock *last_mem_block; }; -DQN_HEADER_COPY_END template void Dqn_StringBuilder__LazyInitialise(Dqn_StringBuilder *builder) @@ -832,8 +1018,9 @@ void Dqn_StringBuilder__LazyInitialise(Dqn_StringBuilder *builder) builder->last_mem_block = &builder->fixed_mem_block; } -// @ size_required: The length of the string not including the null terminator. -template DQN_FILE_SCOPE char *Dqn_StringBuilder_AllocateWriteBuffer(Dqn_StringBuilder *builder, Dqn_isize size_required) +// size_required: The length of the string not including the null terminator. +template +DQN_API char *Dqn_StringBuilder_AllocateWriteBuffer(Dqn_StringBuilder *builder, Dqn_isize size_required) { if (!builder->fixed_mem_block.mem) { @@ -861,8 +1048,8 @@ template DQN_FILE_SCOPE char *Dqn_StringBuilder_AllocateWriteBuffe return result; } -// @ The necessary length to build the string, it returns the length not including the null-terminator -DQN_HEADER_COPY_PROTOTYPE(template Dqn_isize, Dqn_StringBuilder_BuildLength(Dqn_StringBuilder const *builder)) +// The necessary length to build the string, it returns the length not including the null-terminator +template Dqn_isize Dqn_StringBuilder_BuildLength(Dqn_StringBuilder const *builder) { Dqn_isize result = 0; for (Dqn_StringBuilderBlock const *block = &builder->fixed_mem_block; @@ -875,7 +1062,8 @@ DQN_HEADER_COPY_PROTOTYPE(template Dqn_isize, Dqn_StringBuilder_Bu return result; } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_BuildToDest(Dqn_StringBuilder const *builder, char *dest, Dqn_usize dest_size)) +template +void Dqn_StringBuilder_BuildToDest(Dqn_StringBuilder const *builder, char *dest, Dqn_usize dest_size) { if (!dest) return; if (dest_size == 1) { dest[0] = 0; return; } @@ -897,7 +1085,8 @@ DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_BuildTo else ptr[-1] = 0; // Oops ran out of space. Terminate the output prematurely. } -DQN_HEADER_COPY_PROTOTYPE(template char *, Dqn_StringBuilder_Build(Dqn_StringBuilder *builder, Dqn_Allocator *allocator, Dqn_isize *len = nullptr)) +template +char *Dqn_StringBuilder_Build(Dqn_StringBuilder *builder, Dqn_Allocator *allocator, Dqn_isize *len = nullptr) { Dqn_isize len_ = 0; if (!len) len = &len_; @@ -907,14 +1096,16 @@ DQN_HEADER_COPY_PROTOTYPE(template char *, Dqn_StringBuilder_Build return result; } -DQN_HEADER_COPY_PROTOTYPE(template Dqn_String, Dqn_StringBuilder_BuildString(Dqn_StringBuilder *builder, Dqn_Allocator *allocator)) +template +Dqn_String Dqn_StringBuilder_BuildString(Dqn_StringBuilder *builder, Dqn_Allocator *allocator) { Dqn_String result = {}; result.str = Dqn_StringBuilder_Build(builder, allocator, &result.len); return result; } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_VFmtAppend(Dqn_StringBuilder *builder, char const *fmt, va_list va)) +template +void Dqn_StringBuilder_VFmtAppend(Dqn_StringBuilder *builder, char const *fmt, va_list va) { if (!fmt) return; va_list va2; @@ -928,7 +1119,8 @@ DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_VFmtApp builder->last_mem_block->used--; // stbsp_vsnprintf null terminates, back out the null-terminator from the mem block } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_FmtAppend(Dqn_StringBuilder *builder, char const *fmt, ...)) +template +void Dqn_StringBuilder_FmtAppend(Dqn_StringBuilder *builder, char const *fmt, ...) { va_list va; va_start(va, fmt); @@ -936,7 +1128,8 @@ DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_FmtAppe va_end(va); } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_Append(Dqn_StringBuilder *builder, char const *str, Dqn_isize len = -1)) +template +void Dqn_StringBuilder_Append(Dqn_StringBuilder *builder, char const *str, Dqn_isize len = -1) { if (!str) return; if (len == -1) len = DQN_CAST(Dqn_isize)strlen(str); @@ -945,20 +1138,23 @@ DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_Append( DQN_MEMCOPY(buf, str, len); } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_AppendString(Dqn_StringBuilder *builder, Dqn_String const string)) +template +void Dqn_StringBuilder_AppendString(Dqn_StringBuilder *builder, Dqn_String const string) { if (!string.str || string.len == 0) return; char *buf = Dqn_StringBuilder_AllocateWriteBuffer(builder, string.len); DQN_MEMCOPY(buf, string.str, string.len); } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_AppendChar(Dqn_StringBuilder *builder, char ch)) +template +void Dqn_StringBuilder_AppendChar(Dqn_StringBuilder *builder, char ch) { char *buf = Dqn_StringBuilder_AllocateWriteBuffer(builder, 1); *buf++ = ch; } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_Free(Dqn_StringBuilder *builder)) +template +void Dqn_StringBuilder_Free(Dqn_StringBuilder *builder) { for (Dqn_StringBuilderBlock *block = builder->fixed_mem_block.next; block; @@ -971,11 +1167,11 @@ DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_StringBuilder_Free(Dq Dqn_StringBuilder__LazyInitialise(builder); } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_Slices -// @ -// @ ------------------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Slices +// +// ------------------------------------------------------------------------------------------------- template struct Dqn_Slice { @@ -1000,7 +1196,7 @@ Dqn_b32 operator==(Dqn_Slice const &lhs, Dqn_Slice const &rhs) } template -DQN_HEADER_COPY_PROTOTYPE(inline Dqn_Slice, Dqn_Slice_InitWithArray(T (&array)[N])) +inline Dqn_Slice Dqn_Slice_InitWithArray(T (&array)[N]) { Dqn_Slice result = {}; result.len = N; @@ -1009,7 +1205,7 @@ DQN_HEADER_COPY_PROTOTYPE(inline Dqn_Slice, Dqn_Slice_InitWithArray(T (&array } -DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_Allocate(Dqn_Allocator *allocator, Dqn_isize len, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)) +template inline Dqn_Slice Dqn_Slice_Allocate(Dqn_Allocator *allocator, Dqn_isize len, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes) { Dqn_Slice result = {}; result.len = len; @@ -1017,7 +1213,7 @@ DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_A return result; } -DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, T const *src, Dqn_isize len)) +template inline Dqn_Slice Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, T const *src, Dqn_isize len) { Dqn_Slice result = {}; result.len = len; @@ -1027,13 +1223,13 @@ DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_C return result; } -DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, Dqn_Slice const src)) +template inline Dqn_Slice Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, Dqn_Slice const src) { Dqn_Slice result = Dqn_Slice_CopyNullTerminated(allocator, src.data, src.len); return result; } -DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_Copy(Dqn_Allocator *allocator, T const *src, Dqn_isize len)) +template inline Dqn_Slice Dqn_Slice_Copy(Dqn_Allocator *allocator, T const *src, Dqn_isize len) { Dqn_Slice result = {}; result.len = len; @@ -1042,13 +1238,13 @@ DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_C return result; } -DQN_HEADER_COPY_PROTOTYPE(template inline Dqn_Slice, Dqn_Slice_Copy(Dqn_Allocator *allocator, Dqn_Slice const src)) +template inline Dqn_Slice Dqn_Slice_Copy(Dqn_Allocator *allocator, Dqn_Slice const src) { Dqn_Slice result = Dqn_Slice_Copy(allocator, src.data, src.len); return result; } -DQN_HEADER_COPY_PROTOTYPE(template inline bool, Dqn_Slice_Equals(Dqn_Slice const a, Dqn_Slice const b)) +template inline bool Dqn_Slice_Equals(Dqn_Slice const a, Dqn_Slice const b) { bool result = false; if (a.len != b.len) return result; @@ -1056,11 +1252,11 @@ DQN_HEADER_COPY_PROTOTYPE(template inline bool, Dqn_Slice_Equals(Dq return result; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_FixedArray -// @ -// @ ------------------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_FixedArray +// +// ------------------------------------------------------------------------------------------------- template void Dqn__EraseStableFromCArray(T *array, Dqn_isize len, Dqn_isize max, Dqn_isize index) { @@ -1071,7 +1267,7 @@ template void Dqn__EraseStableFromCArray(T *array, Dqn_isize len, D memmove(array + index, array + next_index, bytes_to_copy); } -DQN_HEADER_COPY_BEGIN + #define DQN_FIXED_ARRAY_TEMPLATE template #define DQN_FIXED_ARRAY_TEMPLATE_DECL Dqn_FixedArray DQN_FIXED_ARRAY_TEMPLATE struct Dqn_FixedArray @@ -1089,17 +1285,16 @@ DQN_FIXED_ARRAY_TEMPLATE struct Dqn_FixedArray T const *end () const { return data + len; } T const *operator+ (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, len); return data + i; } }; -DQN_HEADER_COPY_END DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(Dqn_isize, Dqn_FixedArray_Max(DQN_FIXED_ARRAY_TEMPLATE_DECL const *)) +Dqn_isize Dqn_FixedArray_Max(DQN_FIXED_ARRAY_TEMPLATE_DECL const *) { Dqn_isize result = MAX_; return result; } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(DQN_FIXED_ARRAY_TEMPLATE_DECL, Dqn_FixedArray_Init(T const *item, int num)) +DQN_FIXED_ARRAY_TEMPLATE_DECL Dqn_FixedArray_Init(T const *item, int num) { DQN_FIXED_ARRAY_TEMPLATE_DECL result = {}; Dqn_FixedArray_Add(&result, item, num); @@ -1107,7 +1302,7 @@ DQN_HEADER_COPY_PROTOTYPE(DQN_FIXED_ARRAY_TEMPLATE_DECL, Dqn_FixedArray_Init(T c } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *items, Dqn_isize num)) +T * Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *items, Dqn_isize num) { DQN_ASSERT(a->len + num <= MAX_); T *result = static_cast(DQN_MEMCOPY(a->data + a->len, items, sizeof(T) * num)); @@ -1116,7 +1311,7 @@ DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const item)) +T * Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const item) { DQN_ASSERT(a->len < MAX_); a->data[a->len++] = item; @@ -1124,7 +1319,7 @@ DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Make(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num)) +T * Dqn_FixedArray_Make(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num) { DQN_ASSERT(a->len + num <= MAX_); T *result = a->data + a->len; @@ -1133,19 +1328,19 @@ DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Make(DQN_FIXED_ARRAY_TEMPLATE_DECL } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_FixedArray_Clear(DQN_FIXED_ARRAY_TEMPLATE_DECL *a)) +void Dqn_FixedArray_Clear(DQN_FIXED_ARRAY_TEMPLATE_DECL *a) { a->len = 0; } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_FixedArray_EraseStable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index)) +void Dqn_FixedArray_EraseStable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index) { Dqn__EraseStableFromCArray(a->data, a->len--, MAX_, index); } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_FixedArray_EraseUnstable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index)) +void Dqn_FixedArray_EraseUnstable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index) { DQN_ASSERT(index >= 0 && index < a->len); if (--a->len == 0) return; @@ -1154,21 +1349,21 @@ DQN_HEADER_COPY_PROTOTYPE(void, Dqn_FixedArray_EraseUnstable(DQN_FIXED_ARRAY_TEM DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_FixedArray_Pop(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num = 1)) +void Dqn_FixedArray_Pop(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num = 1) { DQN_ASSERT(a->len - num >= 0); a->len -= num; } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Peek(DQN_FIXED_ARRAY_TEMPLATE_DECL *a)) +T * Dqn_FixedArray_Peek(DQN_FIXED_ARRAY_TEMPLATE_DECL *a) { T *result = (a->len == 0) ? nullptr : a->data + (a->len - 1); return result; } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(T , Dqn_FixedArray_PeekCopy(DQN_FIXED_ARRAY_TEMPLATE_DECL const *a)) +T Dqn_FixedArray_PeekCopy(DQN_FIXED_ARRAY_TEMPLATE_DECL const *a) { DQN_ASSERT(a->len > 0); T const *result = a->data + (a->len - 1); @@ -1176,14 +1371,14 @@ DQN_HEADER_COPY_PROTOTYPE(T , Dqn_FixedArray_PeekCopy(DQN_FIXED_ARRAY_TEMPLATE_D } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(Dqn_isize, Dqn_FixedArray_GetIndex(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *entry)) +Dqn_isize Dqn_FixedArray_GetIndex(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *entry) { Dqn_isize result = a->end() - entry; return result; } template -DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, EqualityProc IsEqual)) +T * Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, EqualityProc IsEqual) { for (T &entry : (*a)) { @@ -1193,9 +1388,9 @@ DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL return nullptr; } -// @ return: True if the entry was found, false if not- the entry is made using Dqn_FixedArray_Make() in this case +// return: True if the entry was found, false if not- the entry is made using Dqn_FixedArray_Make() in this case template -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_FixedArray_FindElseMake(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T **entry, EqualityProc IsEqual)) +Dqn_b32 Dqn_FixedArray_FindElseMake(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T **entry, EqualityProc IsEqual) { Dqn_b32 result = true; T *search = Dqn_FixedArray_Find(a, IsEqual); @@ -1210,7 +1405,7 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_FixedArray_FindElseMake(DQN_FIXED_ARRAY_T } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T *find)) +T *Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T *find) { for (T &entry : (*a)) { @@ -1221,18 +1416,17 @@ DQN_HEADER_COPY_PROTOTYPE(T *, Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL } DQN_FIXED_ARRAY_TEMPLATE -DQN_HEADER_COPY_PROTOTYPE(Dqn_Slice, Dqn_FixedArray_Slice(DQN_FIXED_ARRAY_TEMPLATE_DECL *a)) +Dqn_Slice Dqn_FixedArray_Slice(DQN_FIXED_ARRAY_TEMPLATE_DECL *a) { Dqn_Slice result = {a->data, a->len}; return result; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_Array -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_BEGIN +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Array +// +// ------------------------------------------------------------------------------------------------- template struct Dqn_Array { Dqn_Allocator allocator; @@ -1249,9 +1443,8 @@ template struct Dqn_Array T const *operator+(Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; } T *operator+(Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; } }; -DQN_HEADER_COPY_END -DQN_HEADER_COPY_PROTOTYPE(template Dqn_Array, Dqn_Array_InitWithMemory(T *memory, Dqn_isize max, Dqn_isize len = 0)) +template Dqn_Array Dqn_Array_InitWithMemory(T *memory, Dqn_isize max, Dqn_isize len = 0) { Dqn_Array result = {}; result.allocator = Dqn_Allocator_InitWithNull(); @@ -1261,7 +1454,7 @@ DQN_HEADER_COPY_PROTOTYPE(template Dqn_Array, Dqn_Array_InitWith return result; } -DQN_HEADER_COPY_PROTOTYPE(template Dqn_Array, Dqn_Array_InitWithAllocatorNoGrow(Dqn_Allocator *allocator, Dqn_isize max, Dqn_isize len = 0, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)) +template Dqn_Array Dqn_Array_InitWithAllocatorNoGrow(Dqn_Allocator *allocator, Dqn_isize max, Dqn_isize len = 0, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes) { T *memory = DQN_CAST(T *)Dqn_Allocator_Allocate(allocator, sizeof(T) * max, alignof(T), zero_mem); Dqn_Array result = Dqn_Array_InitWithMemory(memory, max, len); @@ -1269,7 +1462,7 @@ DQN_HEADER_COPY_PROTOTYPE(template Dqn_Array, Dqn_Array_InitWith } -DQN_HEADER_COPY_PROTOTYPE(template bool, Dqn_Array_Reserve(Dqn_Array *a, Dqn_isize size)) +template bool Dqn_Array_Reserve(Dqn_Array *a, Dqn_isize size) { if (size <= a->len) return true; T *new_ptr = DQN_CAST(T *)Dqn_Allocator_Allocate(&a->allocator, sizeof(T) * size, alignof(T)); @@ -1287,7 +1480,7 @@ DQN_HEADER_COPY_PROTOTYPE(template bool, Dqn_Array_Reserve(Dqn_Arra return true; } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_Array_Free(Dqn_Array *a)) +template void Dqn_Array_Free(Dqn_Array *a) { Dqn_Allocator_Free(&a->allocator, a->data); } @@ -1305,7 +1498,7 @@ template bool Dqn_Array__GrowIfNeeded(Dqn_Array *a, Dqn_isize nu return result; } -DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_Array_Add(Dqn_Array *a, T const *items, Dqn_isize num)) +template T * Dqn_Array_Add(Dqn_Array *a, T const *items, Dqn_isize num) { if (!Dqn_Array__GrowIfNeeded(a, num)) return nullptr; @@ -1314,14 +1507,14 @@ DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_Array_Add(Dqn_Array return result; } -DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_Array_Add(Dqn_Array *a, T const item)) +template T * Dqn_Array_Add(Dqn_Array *a, T const item) { if (!Dqn_Array__GrowIfNeeded(a, 1)) return nullptr; a->data[a->len++] = item; return &a->data[a->len - 1]; } -DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_Array_Make(Dqn_Array *a, Dqn_isize num)) +template T * Dqn_Array_Make(Dqn_Array *a, Dqn_isize num) { if (!Dqn_Array__GrowIfNeeded(a, num)) return nullptr; @@ -1330,42 +1523,41 @@ DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_Array_Make(Dqn_Array return result; } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_Array_Clear(Dqn_Array *a, bool zero_mem = false)) +template void Dqn_Array_Clear(Dqn_Array *a, bool zero_mem = false) { a->len = 0; if (zero_mem) DQN_MEMSET(a->data, 0, sizeof(T) * a->max); } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_Array_EraseStable(Dqn_Array *a, Dqn_isize index)) +template void Dqn_Array_EraseStable(Dqn_Array *a, Dqn_isize index) { Dqn__EraseStableFromCArray(a->data, a->len--, a->max, index); } -DQN_HEADER_COPY_PROTOTYPE(template void, - Dqn_Array_EraseUnstable(Dqn_Array *a, Dqn_isize index)) + +template void Dqn_Array_EraseUnstable(Dqn_Array *a, Dqn_isize index) { DQN_ASSERT(index >= 0 && index < a->len); if (--a->len == 0) return; a->data[index] = a->data[a->len]; } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_Array_Pop(Dqn_Array *a, Dqn_isize num)) +template void Dqn_Array_Pop(Dqn_Array *a, Dqn_isize num) { DQN_ASSERT(a->len - num >= 0); a->len -= num; } -DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_Array_Peek(Dqn_Array *a)) +template T * Dqn_Array_Peek(Dqn_Array *a) { T *result = (a->len == 0) ? nullptr : a->data + (a->len - 1); return result; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_FixedString -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_BEGIN +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_FixedString +// +// ------------------------------------------------------------------------------------------------- template struct Dqn_FixedString { @@ -1399,16 +1591,15 @@ struct Dqn_FixedString char *begin () { return data; } char *end () { return data + len; } }; -DQN_HEADER_COPY_END -DQN_HEADER_COPY_PROTOTYPE(template int, Dqn_FixedString_Capacity(Dqn_FixedString *)) +template int Dqn_FixedString_Capacity(Dqn_FixedString *) { int result = MAX_; return result; } -DQN_HEADER_COPY_PROTOTYPE(template void, Dqn_FixedString_Clear(Dqn_FixedString *str)) { *str = {}; } -DQN_HEADER_COPY_PROTOTYPE(template Dqn_b32, Dqn_FixedString_AppendVFmt(Dqn_FixedString *str, char const *fmt, va_list va)) +template void Dqn_FixedString_Clear(Dqn_FixedString *str) { *str = {}; } +template Dqn_b32 Dqn_FixedString_AppendVFmt(Dqn_FixedString *str, char const *fmt, va_list va) { va_list va2; va_copy(va2, va); @@ -1421,7 +1612,7 @@ DQN_HEADER_COPY_PROTOTYPE(template Dqn_b32, Dqn_FixedString_App return result; } -DQN_HEADER_COPY_PROTOTYPE(template Dqn_b32, Dqn_FixedString_AppendFmt(Dqn_FixedString *str, char const *fmt, ...)) +template Dqn_b32 Dqn_FixedString_AppendFmt(Dqn_FixedString *str, char const *fmt, ...) { va_list va; va_start(va, fmt); @@ -1430,17 +1621,14 @@ DQN_HEADER_COPY_PROTOTYPE(template Dqn_b32, Dqn_FixedString_App return result; } -DQN_HEADER_COPY_PROTOTYPE(template Dqn_b32, Dqn_FixedString_Append(Dqn_FixedString *str, char const *src, Dqn_isize len = -1)) +template Dqn_b32 Dqn_FixedString_Append(Dqn_FixedString *str, char const *src, Dqn_isize len = -1) { if (len == -1) len = DQN_CAST(Dqn_isize)strlen(src); Dqn_isize space = MAX_ - str->len; Dqn_b32 result = true; DQN_ASSERT_MSG_IF(len >= space, "len: %jd, space: %jd", len, space) - { - len = space; - result = false; - } + return false; DQN_MEMCOPY(str->data + str->len, src, len); str->len += len; @@ -1448,70 +1636,29 @@ DQN_HEADER_COPY_PROTOTYPE(template Dqn_b32, Dqn_FixedString_App return result; } -DQN_HEADER_COPY_PROTOTYPE(template Dqn_String, Dqn_FixedString_ToString(Dqn_FixedString const *str)) +template Dqn_String Dqn_FixedString_ToString(Dqn_FixedString const *str) { Dqn_String result = { str->str, str->len }; return result; } - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_U64Str -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_BEGIN -struct Dqn_U64Str -{ - // Points to the start of the str in the buffer, not necessarily buf since - // we write into the buffer in reverse - char *str; - char buf[27]; // NOTE(doyle): 27 is the maximum size of Dqn_u64 including commas - int len; -}; -DQN_HEADER_COPY_END #endif // DQN_H -#ifdef DQN_IMPLEMENTATION +// ------------------------------------------------------------------------------------------------- +// +// Implementation +// +// ------------------------------------------------------------------------------------------------- +#if defined(DQN_IMPLEMENTATION) #define STB_SPRINTF_IMPLEMENTATION #include // fprintf, FILE, stdout, stderr +#include // Dqn_EpochTimeToDate -DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_U64Str_ToStr(Dqn_u64 val, Dqn_U64Str *result, Dqn_b32 comma_sep)) -{ - int buf_index = (int)(Dqn_ArrayCount(result->buf) - 1); - result->buf[buf_index--] = 0; - - if (val == 0) - { - result->buf[buf_index--] = '0'; - result->len = 1; - } - else - { - for (int digit_count = 0; val > 0; result->len++, digit_count++) - { - if (comma_sep && (digit_count != 0) && (digit_count % 3 == 0)) - { - result->buf[buf_index--] = ','; - result->len++; - } - - auto digit = DQN_CAST(char)(val % 10); - result->buf[buf_index--] = '0' + digit; - val /= 10; - } - } - - result->str = result->buf + (buf_index + 1); - return result->str; -} - - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Logging -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_LogV(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, va_list va)) +// ------------------------------------------------------------------------------------------------- +// +// Logging +// +// ------------------------------------------------------------------------------------------------- +DQN_API void Dqn_LogV(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, va_list va) { char const *file_ptr = file; auto file_ptr_len = DQN_CAST(Dqn_isize)file_len; @@ -1534,28 +1681,50 @@ DQN_HEADER_COPY_PROTOTYPE(void, Dqn_LogV(Dqn_LogType type, char const *file, Dqn line, (int)func_len, func, - Dqn_LogTypeTag(type)); + Dqn_LogTypeString[DQN_CAST(int)type]); vfprintf(handle, fmt, va); - fprintf(handle, "\n"); + fputc('\n', handle); } -// @ return: This returns a boolean as a hack so you can combine it in if expressions. I use it for my DQN_ASSERT_IF macro -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Log(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, ...)) +DQN_API void Dqn_Log(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, ...) { va_list va; va_start(va, fmt); Dqn_LogV(type, file, file_len, func, func_len, line, fmt, va); va_end(va); - return true; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_Align* -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_uintptr, Dqn_AlignAddress(Dqn_uintptr address, Dqn_u8 alignment)) +// ------------------------------------------------------------------------------------------------- +// +// Core Config +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_Core Dqn__CoreDefault() +{ + Dqn_Core result = {}; + result.Log = Dqn_Log; + return result; +} +Dqn_Core dqn_core = Dqn__CoreDefault(); + +// ------------------------------------------------------------------------------------------------- +// +// Dqn_Align* +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_uintptr Dqn_AlignAddressEnsuringSpace(Dqn_uintptr address, Dqn_u8 alignment) +{ + Dqn_uintptr remainder = address % alignment; + Dqn_uintptr offset_to_align = alignment - remainder; + Dqn_uintptr result = address + offset_to_align; + DQN_ASSERT(result % alignment == 0); + DQN_ASSERT(result >= address); + DQN_ASSERT(offset_to_align >= 1 && offset_to_align <= alignment); + return result; +} + +DQN_API Dqn_uintptr Dqn_AlignAddress(Dqn_uintptr address, Dqn_u8 alignment) { Dqn_uintptr result = address; if (alignment > 0) @@ -1570,24 +1739,22 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_uintptr, Dqn_AlignAddress(Dqn_uintptr address, Dqn return result; } -// @ NOTE: Even if pointer is aligned, align it again, ensuring there's at minimum -// @ 1 byte and at most alignment bytes of space between the aligned pointer and -// @ raw pointer. We do this to keep metadata exactly 1 byte behind the aligned -// @ pointer. -DQN_HEADER_COPY_PROTOTYPE(Dqn_uintptr, Dqn_AlignAddressEnsuringSpace(Dqn_uintptr address, Dqn_u8 alignment)) +// ------------------------------------------------------------------------------------------------- +// +// Dqn_PointerMetadata +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_isize Dqn_PointerMetadata_SizeRequired(Dqn_isize size, Dqn_u8 alignment) { - Dqn_uintptr remainder = address % alignment; - Dqn_uintptr offset_to_align = alignment - remainder; - Dqn_uintptr result = address + offset_to_align; - DQN_ASSERT(result % alignment == 0); - DQN_ASSERT(result >= address); - DQN_ASSERT(offset_to_align >= 1 && offset_to_align <= alignment); + DQN_ASSERT(alignment > 0); + if (alignment <= 0) alignment = 1; + Dqn_isize result = size + DQN_CAST(Dqn_i8)(alignment - 1) + DQN_CAST(Dqn_isize)sizeof(Dqn_PointerMetadata); return result; } -DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_AllocatorAlignMetadata_Init(void *ptr, Dqn_u8 alignment)) +DQN_API char *Dqn_PointerMetadata_Init(void *ptr, Dqn_u8 alignment) { - DQN_ASSERT_MSG((alignment & 1) == 0, "Alignment must be a power of 2, %u", alignment); + DQN_ASSERT_MSG(alignment == 1 || (alignment & 1) == 0, "Alignment must be a power of 2, %u", alignment); // NOTE: Given a pointer, it can misaligned by up to (Alignment - 1) bytes. // After calculating the offset to apply on the aligned ptr, we store the @@ -1607,7 +1774,7 @@ DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_AllocatorAlignMetadata_Init(void *ptr, Dqn // Offset is [0->Alignment-1] bytes from the Unaligned ptr. auto raw_ptr = DQN_CAST(uintptr_t) ptr; - auto unaligned_ptr = raw_ptr + sizeof(Dqn_AllocatorAlignMetadata); + auto unaligned_ptr = raw_ptr + sizeof(Dqn_PointerMetadata); auto result = DQN_CAST(uintptr_t) unaligned_ptr; if ((unaligned_ptr % alignment) > 0) @@ -1620,55 +1787,350 @@ DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_AllocatorAlignMetadata_Init(void *ptr, Dqn ptrdiff_t difference = DQN_CAST(ptrdiff_t)result - DQN_CAST(ptrdiff_t)raw_ptr; DQN_ASSERT(difference <= DQN_CAST(Dqn_u8)-1); - auto *metadata_ptr = DQN_CAST(Dqn_AllocatorAlignMetadata *)(result - sizeof(Dqn_AllocatorAlignMetadata)); + auto *metadata_ptr = DQN_CAST(Dqn_PointerMetadata *)(result - sizeof(Dqn_PointerMetadata)); metadata_ptr->alignment = alignment; metadata_ptr->offset = DQN_CAST(Dqn_u8)difference; return DQN_CAST(char *)result; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_AllocatorAlignMetadata, Dqn_AllocatorAlignMetadata_Get(void *ptr)) +DQN_API Dqn_PointerMetadata Dqn_PointerMetadata_Get(void *ptr) { auto *aligned_ptr = DQN_CAST(char *) ptr; - auto result = *DQN_CAST(Dqn_AllocatorAlignMetadata *)(aligned_ptr - sizeof(Dqn_AllocatorAlignMetadata)); + auto result = *DQN_CAST(Dqn_PointerMetadata *)(aligned_ptr - sizeof(Dqn_PointerMetadata)); return result; } -DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_AllocatorAlignMetadata_GetRawPointer(void *ptr)) +DQN_API char *Dqn_PointerMetadata_GetRawPointer(void *ptr) { - Dqn_AllocatorAlignMetadata metadata = Dqn_AllocatorAlignMetadata_Get(ptr); + Dqn_PointerMetadata metadata = Dqn_PointerMetadata_Get(ptr); char *result = DQN_CAST(char *) ptr - metadata.offset; return result; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_isize, Dqn_AllocatorAlignMetadata_SizeRequired(Dqn_isize size, Dqn_u8 alignment)) +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_V2 +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_V2I Dqn_V2_ToV2I(Dqn_V2 a) { - DQN_ASSERT(alignment > 0); - if (alignment <= 0) alignment = 1; - Dqn_isize result = size + DQN_CAST(Dqn_i8)(alignment - 1) + DQN_CAST(Dqn_isize)sizeof(Dqn_AllocatorAlignMetadata); + Dqn_V2I result(static_cast(a.x), static_cast(a.y)); return result; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_Allocator -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)) +DQN_API Dqn_V2 Dqn_V2_Min(Dqn_V2 a, Dqn_V2 b) { - char *result = nullptr; + Dqn_V2 result = Dqn_V2(DQN_MIN(a.x, b.x), DQN_MIN(a.y, b.y)); + return result; +} + +DQN_API Dqn_V2 Dqn_V2_Max(Dqn_V2 a, Dqn_V2 b) +{ + Dqn_V2 result = Dqn_V2(DQN_MAX(a.x, b.x), DQN_MAX(a.y, b.y)); + return result; +} + +DQN_API Dqn_V2 Dqn_V2_Abs(Dqn_V2 a) +{ + Dqn_V2 result = Dqn_V2(DQN_ABS(a.x), DQN_ABS(a.y)); + return result; +} + +DQN_API Dqn_f32 Dqn_V2_Dot(Dqn_V2 a, Dqn_V2 b) +{ + Dqn_f32 result = (a.x * b.x) + (a.y * b.y); + return result; +} + +DQN_API Dqn_f32 Dqn_V2_LengthSq(Dqn_V2 a, Dqn_V2 b) +{ + Dqn_f32 x_side = b.x - a.x; + Dqn_f32 y_side = b.y - a.y; + Dqn_f32 result = DQN_SQUARED(x_side) + DQN_SQUARED(y_side); + return result; +} + +DQN_API Dqn_V2 Dqn_V2_Normalise(Dqn_V2 a) +{ + Dqn_f32 length_sq = DQN_SQUARED(a.x) + DQN_SQUARED(a.y); + Dqn_f32 length = DQN_SQRTF(length_sq); + Dqn_V2 result = a / length; + return result; +} + +DQN_API Dqn_V2 Dqn_V2_Perpendicular(Dqn_V2 a) +{ + Dqn_V2 result = Dqn_V2(-a.y, a.x); + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_V4 +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_f32 Dqn_V4_Dot(Dqn_V4 const *a, Dqn_V4 const *b) +{ + Dqn_f32 result = (a->x * b->x) + (a->y * b->y) + (a->z * b->z) + (a->w * b->w); + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Rect +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_Rect Dqn_Rect_InitFromPosAndSize(Dqn_V2 pos, Dqn_V2 size) +{ + Dqn_Rect result = {}; + result.min = pos; + if (size.w < 0) result.min.x -= size.w; + if (size.h < 0) result.min.y -= size.h; + result.max = result.min + Dqn_V2_Abs(size); + return result; +} + +DQN_API Dqn_V2 Dqn_Rect_Center(Dqn_Rect rect) +{ + Dqn_V2 size = rect.max - rect.min; + Dqn_V2 result = rect.min + (size * 0.5f); + return result; +} + +DQN_API Dqn_b32 Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p) +{ + Dqn_b32 result = (p.x >= rect.min.x && p.x <= rect.max.x && p.y >= rect.min.y && p.y <= rect.max.y); + return result; +} + + +DQN_API Dqn_b32 Dqn_Rect_ContainsRect(Dqn_Rect a, Dqn_Rect b) +{ + Dqn_b32 result = (b.min >= a.min && b.max <= a.max); + return result; +} + + +DQN_API Dqn_V2 Dqn_Rect_Size(Dqn_Rect rect) +{ + Dqn_V2 result = rect.max - rect.min; + return result; +} + +DQN_API Dqn_Rect Dqn_Rect_Move(Dqn_Rect src, Dqn_V2 move_amount) +{ + Dqn_Rect result = src; + result.min += move_amount; + result.max += move_amount; + return result; +} + +DQN_API Dqn_b32 Dqn_Rect_Intersects(Dqn_Rect a, Dqn_Rect b) +{ + Dqn_b32 result = (a.min.x <= b.max.x && a.max.x >= b.min.x) && + (a.min.y <= b.max.y && a.max.y >= b.min.y); + return result; +} + +DQN_API Dqn_Rect Dqn_Rect_Intersection(Dqn_Rect a, Dqn_Rect b) +{ + Dqn_Rect result = {}; + if (Dqn_Rect_Intersects(a, b)) + { + result.min.x = DQN_MAX(a.min.x, b.min.x); + result.min.y = DQN_MAX(a.min.y, b.min.y); + result.max.x = DQN_MIN(a.max.x, b.max.x); + result.max.y = DQN_MIN(a.max.y, b.max.y); + } + + return result; +} + +DQN_API Dqn_Rect Dqn_Rect_Union(Dqn_Rect a, Dqn_Rect b) +{ + Dqn_Rect result = {}; + result.min.x = DQN_MIN(a.min.x, b.min.x); + result.min.y = DQN_MIN(a.min.y, b.min.y); + result.max.x = DQN_MAX(a.max.x, b.max.x); + result.max.y = DQN_MAX(a.max.y, b.max.y); + return result; +} + +DQN_API Dqn_Rect Dqn_Rect_FromRectI32(Dqn_RectI32 a) +{ + Dqn_Rect result = Dqn_Rect(a.min, a.max); + return result; +} + +DQN_API Dqn_V2I Dqn_RectI32_Size(Dqn_RectI32 rect) +{ + Dqn_V2I result = rect.max - rect.min; + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Mat4 +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_Mat4 Dqn_Mat4_Identity() +{ + Dqn_Mat4 result = + { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }; + return result; +} + +DQN_API Dqn_Mat4 Dqn_Mat4_Scale3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z) +{ + Dqn_Mat4 result = + { + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1, + }; + return result; +} + +DQN_API Dqn_Mat4 Dqn_Mat4_ScaleV3(Dqn_V3 vec) +{ + Dqn_Mat4 result = Dqn_Mat4_Scale3f(vec.x, vec.y, vec.z); + return result; +} + +DQN_API Dqn_Mat4 Dqn_Mat4_Translate3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z) +{ + Dqn_Mat4 result = + { + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1, + }; + return result; +} + +DQN_API Dqn_Mat4 Dqn_Mat4_TranslateV3(Dqn_V3 vec) +{ + Dqn_Mat4 result = Dqn_Mat4_Translate3f(vec.x, vec.y, vec.z); + return result; +} + +DQN_API Dqn_Mat4 operator*(Dqn_Mat4 const &a, Dqn_Mat4 const &b) +{ + Dqn_V4 const *row1 = a.row + 0; + Dqn_V4 const *row2 = a.row + 1; + Dqn_V4 const *row3 = a.row + 2; + Dqn_V4 const *row4 = a.row + 3; + Dqn_V4 const col1 = Dqn_V4(b.row_major[0][0], b.row_major[1][0], b.row_major[2][0], b.row_major[3][0]); + Dqn_V4 const col2 = Dqn_V4(b.row_major[0][1], b.row_major[1][1], b.row_major[2][1], b.row_major[3][1]); + Dqn_V4 const col3 = Dqn_V4(b.row_major[0][2], b.row_major[1][2], b.row_major[2][2], b.row_major[3][3]); + Dqn_V4 const col4 = Dqn_V4(b.row_major[0][3], b.row_major[1][3], b.row_major[2][3], b.row_major[3][3]); + + Dqn_Mat4 result = + { + Dqn_V4_Dot(row1, &col1), Dqn_V4_Dot(row1, &col2), Dqn_V4_Dot(row1, &col3), Dqn_V4_Dot(row1, &col4), + Dqn_V4_Dot(row2, &col1), Dqn_V4_Dot(row2, &col2), Dqn_V4_Dot(row2, &col3), Dqn_V4_Dot(row2, &col4), + Dqn_V4_Dot(row3, &col1), Dqn_V4_Dot(row3, &col2), Dqn_V4_Dot(row3, &col3), Dqn_V4_Dot(row3, &col4), + Dqn_V4_Dot(row4, &col1), Dqn_V4_Dot(row4, &col2), Dqn_V4_Dot(row4, &col3), Dqn_V4_Dot(row4, &col4), + }; + return result; +} + +DQN_API Dqn_V4 operator*(Dqn_Mat4 const &mat, Dqn_V4 const &vec) +{ + Dqn_f32 x = vec.x, y = vec.y, z = vec.z, w = vec.w; + Dqn_V4 result = + { + (mat[0] * x) + (mat[1] * y) + (mat[2] * z) + (mat[3] * w), + (mat[4] * x) + (mat[5] * y) + (mat[6] * z) + (mat[7] * w), + (mat[8] * x) + (mat[9] * y) + (mat[10] * z) + (mat[11] * w), + (mat[12] * x) + (mat[13] * y) + (mat[14] * z) + (mat[15] * w), + }; + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Math Utils +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_V2 Dqn_LerpV2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b) +{ + Dqn_V2 result = {}; + result.x = a.x + ((b.x - a.x) * t); + result.y = a.y + ((b.y - a.y) * t); + return result; +} + +DQN_API Dqn_f32 Dqn_LerpF32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b) +{ + Dqn_f32 result = a + ((b - a) * t); + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// Dqn_Allocator +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_Allocator Dqn_Allocator_InitWithNull() +{ + Dqn_Allocator result = {}; + result.type = Dqn_Allocator_Type::Null; + return result; +} + +DQN_API Dqn_Allocator Dqn_Allocator_InitWithHeap() +{ + Dqn_Allocator result = {}; + result.type = Dqn_Allocator_Type::Heap; + return result; +} + +DQN_API Dqn_Allocator Dqn_Allocator_InitWithXHeap() +{ + Dqn_Allocator result = {}; + result.type = Dqn_Allocator_Type::XHeap; + return result; +} + +DQN_API Dqn_Allocator Dqn_Allocator_InitWithArena(Dqn_ArenaAllocator *arena) +{ + Dqn_Allocator result = {}; + result.type = Dqn_Allocator_Type::Arena; + result.context.arena = arena; + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Allocator +// +// ------------------------------------------------------------------------------------------------- +DQN_API void *Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem) +{ + char *result = nullptr; switch (allocator->type) { - case Dqn_Allocator_Type::Null: + case Dqn_Allocator_Type::Null: return result; default: break; case Dqn_Allocator_Type::Heap: case Dqn_Allocator_Type::XHeap: { - size = Dqn_AllocatorAlignMetadata_SizeRequired(size, alignment); + size = Dqn_PointerMetadata_SizeRequired(size, alignment); void *ptr = zero_mem == Dqn_ZeroMem::Yes ? DQN_CALLOC(1, DQN_CAST(size_t)size) : DQN_MALLOC(size); - result = Dqn_AllocatorAlignMetadata_Init(ptr, alignment); + result = Dqn_PointerMetadata_Init(ptr, alignment); if (!result && allocator->type == Dqn_Allocator_Type::XHeap) + { DQN_ASSERT(result); + } } break; @@ -1694,17 +2156,17 @@ DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Allocate(Dqn_Allocator *allocato return result; } -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_Allocator_Free(Dqn_Allocator *allocator, void *ptr)) +void Dqn_Allocator_Free(Dqn_Allocator *allocator, void *ptr) { switch (allocator->type) { - case Dqn_Allocator_Type::Null: + case Dqn_Allocator_Type::Null: return; default: break; case Dqn_Allocator_Type::Heap: case Dqn_Allocator_Type::XHeap: { - char *raw_ptr = Dqn_AllocatorAlignMetadata_GetRawPointer(ptr); + char *raw_ptr = Dqn_PointerMetadata_GetRawPointer(ptr); DQN_FREE(raw_ptr); } break; @@ -1727,12 +2189,12 @@ DQN_HEADER_COPY_PROTOTYPE(void, Dqn_Allocator_Free(Dqn_Allocator *allocator, voi } } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_ArenaAllocator -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_FILE_SCOPE Dqn_ArenaAllocatorBlock *Dqn_ArenaAllocator__AllocateBlock(Dqn_ArenaAllocator *arena, Dqn_isize requested_size) +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_ArenaAllocator +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_ArenaAllocatorBlock *Dqn_ArenaAllocator__AllocateBlock(Dqn_ArenaAllocator *arena, Dqn_isize requested_size) { Dqn_isize min_block_size = arena->min_block_size; if (min_block_size == 0) min_block_size = DQN_MEM_ARENA_DEFAULT_MIN_BLOCK_SIZE; @@ -1749,7 +2211,7 @@ DQN_FILE_SCOPE Dqn_ArenaAllocatorBlock *Dqn_ArenaAllocator__AllocateBlock(Dqn_Ar return result; } -DQN_FILE_SCOPE void Dqn_ArenaAllocator__FreeBlock(Dqn_ArenaAllocator *arena, Dqn_ArenaAllocatorBlock *block) +DQN_API void Dqn_ArenaAllocator__FreeBlock(Dqn_ArenaAllocator *arena, Dqn_ArenaAllocatorBlock *block) { if (!block) return; @@ -1763,7 +2225,7 @@ DQN_FILE_SCOPE void Dqn_ArenaAllocator__FreeBlock(Dqn_ArenaAllocator *arena, Dqn Dqn_Allocator_Free(&arena->allocator, block); } -DQN_FILE_SCOPE void Dqn_ArenaAllocator__AttachBlock(Dqn_ArenaAllocator *arena, Dqn_ArenaAllocatorBlock *new_block) +DQN_API void Dqn_ArenaAllocator__AttachBlock(Dqn_ArenaAllocator *arena, Dqn_ArenaAllocatorBlock *new_block) { if (arena->top_mem_block) { @@ -1779,7 +2241,33 @@ DQN_FILE_SCOPE void Dqn_ArenaAllocator__AttachBlock(Dqn_ArenaAllocator *arena, D } } -DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_ArenaAllocator_Allocate(Dqn_ArenaAllocator *arena, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)) +DQN_API Dqn_ArenaAllocator Dqn_ArenaAllocator_InitWithAllocator(Dqn_Allocator allocator, Dqn_isize size) +{ + Dqn_ArenaAllocator result = {}; + result.allocator = allocator; + if (size > 0) + { + DQN_ASSERT_MSG(size >= DQN_ISIZEOF(*result.curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_ArenaAllocatorBlock struct into the memory buffer", size, sizeof(*result.curr_mem_block)); + Dqn_ArenaAllocatorBlock *mem_block = Dqn_ArenaAllocator__AllocateBlock(&result, size); + Dqn_ArenaAllocator__AttachBlock(&result, mem_block); + } + return result; +} + +DQN_API Dqn_ArenaAllocator Dqn_ArenaAllocator_InitWithMemory(void *memory, Dqn_isize size) +{ + Dqn_ArenaAllocator result = {}; + DQN_ASSERT_MSG(size >= DQN_ISIZEOF(*result.curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_ArenaAllocatorBlock struct into the memory buffer", size, sizeof(*result.curr_mem_block)); + result.allocator = Dqn_Allocator_InitWithNull(); + auto *mem_block = DQN_CAST(Dqn_ArenaAllocatorBlock *) memory; + *mem_block = {}; + mem_block->memory = DQN_CAST(Dqn_u8 *) memory + sizeof(*mem_block); + mem_block->size = size - DQN_CAST(Dqn_isize)sizeof(*mem_block); + Dqn_ArenaAllocator__AttachBlock(&result, mem_block); + return result; +} + +DQN_API void *Dqn_ArenaAllocator_Allocate(Dqn_ArenaAllocator *arena, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem) { Dqn_isize allocation_size = size + (alignment - 1); Dqn_b32 need_new_mem_block = true; @@ -1811,7 +2299,7 @@ DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_ArenaAllocator_Allocate(Dqn_ArenaAllocator return result; } -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_ArenaAllocator_Free(Dqn_ArenaAllocator *arena)) +DQN_API void Dqn_ArenaAllocator_Free(Dqn_ArenaAllocator *arena) { for (Dqn_ArenaAllocatorBlock *mem_block = arena->top_mem_block; mem_block;) { @@ -1827,7 +2315,7 @@ DQN_HEADER_COPY_PROTOTYPE(void, Dqn_ArenaAllocator_Free(Dqn_ArenaAllocator *aren arena->allocator = allocator; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_ArenaAllocator_Reserve(Dqn_ArenaAllocator *arena, Dqn_isize size)) +DQN_API Dqn_b32 Dqn_ArenaAllocator_Reserve(Dqn_ArenaAllocator *arena, Dqn_isize size) { if (arena->top_mem_block) { @@ -1841,33 +2329,7 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_ArenaAllocator_Reserve(Dqn_ArenaAllocator return true; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_ArenaAllocator, Dqn_ArenaAllocator_InitWithAllocator(Dqn_Allocator allocator, Dqn_isize size = 0)) -{ - Dqn_ArenaAllocator result = {}; - result.allocator = allocator; - if (size > 0) - { - DQN_ASSERT_MSG(size >= DQN_ISIZEOF(*result.curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_ArenaAllocatorBlock struct into the memory buffer", size, sizeof(*result.curr_mem_block)); - Dqn_ArenaAllocatorBlock *mem_block = Dqn_ArenaAllocator__AllocateBlock(&result, size); - Dqn_ArenaAllocator__AttachBlock(&result, mem_block); - } - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_ArenaAllocator, Dqn_ArenaAllocator_InitWithMemory(void *memory, Dqn_isize size)) -{ - Dqn_ArenaAllocator result = {}; - DQN_ASSERT_MSG(size >= DQN_ISIZEOF(*result.curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_ArenaAllocatorBlock struct into the memory buffer", size, sizeof(*result.curr_mem_block)); - result.allocator = Dqn_Allocator_InitWithNull(); - auto *mem_block = DQN_CAST(Dqn_ArenaAllocatorBlock *) memory; - *mem_block = {}; - mem_block->memory = DQN_CAST(Dqn_u8 *) memory + sizeof(*mem_block); - mem_block->size = size - DQN_CAST(Dqn_isize)sizeof(*mem_block); - Dqn_ArenaAllocator__AttachBlock(&result, mem_block); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_ArenaAllocator_ResetUsage(Dqn_ArenaAllocator *arena, Dqn_ZeroMem zero_mem)) +DQN_API void Dqn_ArenaAllocator_ResetUsage(Dqn_ArenaAllocator *arena, Dqn_ZeroMem zero_mem) { arena->usage_before_last_reset = 0; arena->wastage_before_last_reset = 0; @@ -1885,7 +2347,7 @@ DQN_HEADER_COPY_PROTOTYPE(void, Dqn_ArenaAllocator_ResetUsage(Dqn_ArenaAllocator } } -Dqn_ArenaAllocatorRegion Dqn_ArenaAllocator_BeginRegion(Dqn_ArenaAllocator *arena) +DQN_API Dqn_ArenaAllocatorRegion Dqn_ArenaAllocator_BeginRegion(Dqn_ArenaAllocator *arena) { Dqn_ArenaAllocatorRegion result = {}; result.arena = arena; @@ -1895,7 +2357,7 @@ Dqn_ArenaAllocatorRegion Dqn_ArenaAllocator_BeginRegion(Dqn_ArenaAllocator *aren return result; } -void Dqn_ArenaAllocator_EndRegion(Dqn_ArenaAllocatorRegion region) +DQN_API void Dqn_ArenaAllocator_EndRegion(Dqn_ArenaAllocatorRegion region) { while (region.top_mem_block != region.arena->top_mem_block) { @@ -1914,6 +2376,11 @@ void Dqn_ArenaAllocator_EndRegion(Dqn_ArenaAllocatorRegion region) region = {}; } +Dqn_ArenaAllocatorScopedRegion Dqn_ArenaAllocator_MakeScopedRegion(Dqn_ArenaAllocator *arena) +{ + return Dqn_ArenaAllocatorScopedRegion(arena); +} + Dqn_ArenaAllocatorScopedRegion::Dqn_ArenaAllocatorScopedRegion(Dqn_ArenaAllocator *arena) { this->region = Dqn_ArenaAllocator_BeginRegion(arena); @@ -1924,19 +2391,229 @@ Dqn_ArenaAllocatorScopedRegion::~Dqn_ArenaAllocatorScopedRegion() Dqn_ArenaAllocator_EndRegion(this->region); } -Dqn_ArenaAllocatorScopedRegion Dqn_ArenaAllocator_MakeScopedRegion(Dqn_ArenaAllocator *arena) +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Bit +// +// ------------------------------------------------------------------------------------------------- +DQN_API void Dqn_Bit_UnsetInplace(Dqn_u32 *flags, Dqn_u32 bitfield) { - return Dqn_ArenaAllocatorScopedRegion(arena); + *flags = (*flags & ~bitfield); } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_Asprintf (Allocate Sprintf) -// @ -// @ ------------------------------------------------------------------------------------------------- -// @ return: The allocated string. If allocation fails, the str ptr returned is nullptr and length is set o the size required, NOT INCLUDING the null terminator. -int Dqn_Safe_TruncateISizeToInt(Dqn_isize val); -DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va)) +DQN_API void Dqn_Bit_SetInplace(Dqn_u32 *flags, Dqn_u32 bitfield) +{ + *flags = (*flags | bitfield); +} + +DQN_API Dqn_b32 Dqn_Bit_IsSet(Dqn_u32 bits, Dqn_u32 bits_to_set) +{ + auto result = DQN_CAST(Dqn_b32)((bits & bits_to_set) == bits_to_set); + return result; +} + +DQN_API Dqn_b32 Dqn_Bit_IsNotSet(Dqn_u32 bits, Dqn_u32 bits_to_check) +{ + auto result = !Dqn_Bit_IsSet(bits, bits_to_check); + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Safe Arithmetic +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_i64 Dqn_Safe_AddI64(Dqn_i64 a, Dqn_i64 b) +{ + DQN_ASSERT_MSG(a <= INT64_MAX - b, "%zu <= %zu", a, INT64_MAX - b); + Dqn_i64 result = a + b; + return result; +} + +DQN_API Dqn_i64 Dqn_Safe_MulI64(Dqn_i64 a, Dqn_i64 b) +{ + DQN_ASSERT_MSG(a <= INT64_MAX / b , "%zu <= %zu", a, INT64_MAX / b); + Dqn_i64 result = a * b; + return result; +} + +DQN_API Dqn_u64 Dqn_Safe_AddU64(Dqn_u64 a, Dqn_u64 b) +{ + DQN_ASSERT_MSG(a <= UINT64_MAX - b, "%zu <= %zu", a, UINT64_MAX - b); + Dqn_u64 result = a + b; + return result; +} + +DQN_API Dqn_u64 Dqn_Safe_SubU64(Dqn_u64 a, Dqn_u64 b) +{ + DQN_ASSERT_MSG(a >= b, "%zu >= %zu", a, b); + Dqn_u64 result = a - b; + return result; +} + +DQN_API Dqn_u32 Dqn_Safe_SubU32(Dqn_u32 a, Dqn_u32 b) +{ + DQN_ASSERT_MSG(a >= b, "%zu >= %zu", a, b); + Dqn_u32 result = a - b; + return result; +} + +DQN_API Dqn_u64 Dqn_Safe_MulU64(Dqn_u64 a, Dqn_u64 b) +{ + DQN_ASSERT_MSG(a <= UINT64_MAX / b , "%zu <= %zu", a, UINT64_MAX / b); + Dqn_u64 result = a * b; + return result; +} + +DQN_API int Dqn_Safe_TruncateISizeToInt(Dqn_isize val) +{ + DQN_ASSERT_MSG(val >= INT_MIN && val <= INT_MAX, "%zd >= %zd && %zd <= %zd", val, INT_MIN, val, INT_MAX); + auto result = (int)val; + return result; +} + +DQN_API Dqn_i32 Dqn_Safe_TruncateISizeToI32(Dqn_isize val) +{ + DQN_ASSERT_MSG(val >= INT32_MIN && val <= INT32_MAX, "%zd >= %zd && %zd <= %zd", val, INT32_MIN, val, INT32_MAX); + auto result = DQN_CAST(Dqn_i32)val; + return result; +} + + +DQN_API Dqn_i8 Dqn_Safe_TruncateISizeToI8(Dqn_isize val) +{ + DQN_ASSERT_MSG(val >= INT8_MIN && val <= INT8_MAX, "%zd >= %zd && %zd <= %zd", val, INT8_MIN, val, INT8_MAX); + auto result = DQN_CAST(Dqn_i8)val; + return result; +} + + +DQN_API Dqn_u32 Dqn_Safe_TruncateUSizeToU32(Dqn_u64 val) +{ + DQN_ASSERT_MSG(val <= UINT32_MAX, "%zu <= %zu", val, UINT32_MAX); + auto result = DQN_CAST(Dqn_u32)val; + return result; +} + + +DQN_API int Dqn_Safe_TruncateUSizeToI32(Dqn_usize val) +{ + DQN_ASSERT_MSG(val <= INT32_MAX, "%zu <= %zd", val, INT32_MAX); + auto result = DQN_CAST(int)val; + return result; +} + + +DQN_API int Dqn_Safe_TruncateUSizeToInt(Dqn_usize val) +{ + DQN_ASSERT_MSG(val <= INT_MAX, "%zu <= %zd", val, INT_MAX); + auto result = DQN_CAST(int)val; + return result; +} + +DQN_API Dqn_isize Dqn_Safe_TruncateUSizeToISize(Dqn_usize val) +{ + DQN_ASSERT_MSG(val <= DQN_CAST(Dqn_usize)DQN_ISIZE_MAX, "%zu <= %zu", val, DQN_CAST(Dqn_usize)DQN_ISIZE_MAX); + auto result = DQN_CAST(Dqn_isize)val; + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Char +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_b32 Dqn_Char_IsAlpha(char ch) +{ + Dqn_b32 result = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); + return result; +} + +DQN_API Dqn_b32 Dqn_Char_IsDigit(char ch) +{ + Dqn_b32 result = (ch >= '0' && ch <= '9'); + return result; +} + +DQN_API Dqn_b32 Dqn_Char_IsAlphaNum(char ch) +{ + Dqn_b32 result = Dqn_Char_IsAlpha(ch) || Dqn_Char_IsDigit(ch); + return result; +} + +DQN_API Dqn_b32 Dqn_Char_IsWhitespace(char ch) +{ + Dqn_b32 result = (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); + return result; +} + +DQN_API char Dqn_Char_ToLower(char ch) +{ + char result = ch; + if (result >= 'A' && result <= 'Z') + result = 'a' - 'A'; + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_String +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_b32 Dqn_String_Compare(Dqn_String const lhs, Dqn_String const rhs) +{ + Dqn_b32 result = false; + if (lhs.len == rhs.len) + result = (memcmp(lhs.str, rhs.str, DQN_CAST(size_t)lhs.len) == 0); + return result; +} + +DQN_API Dqn_b32 Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs) +{ + Dqn_b32 result = (lhs.len == rhs.len); + if (result) + { + for (Dqn_isize index = 0; index < lhs.len && result; index++) + result = (Dqn_Char_ToLower(lhs.str[index]) == Dqn_Char_ToLower(rhs.str[index])); + } + return result; +} + +DQN_API Dqn_String Dqn_String_Copy(Dqn_Allocator *allocator, Dqn_String const src) +{ + Dqn_String result = src; + result.str = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, result.len, alignof(char)); + DQN_MEMCOPY(result.str, src.str, DQN_CAST(size_t)result.len); + return result; +} + +DQN_API Dqn_String Dqn_String_TrimWhitespaceAround(Dqn_String src) +{ + Dqn_String result = src; + if (src.len <= 0) return result; + + char *start = src.str; + char *end = start + (src.len - 1); + while (Dqn_Char_IsWhitespace(start[0])) start++; + while (end != start && Dqn_Char_IsWhitespace(end[0])) end--; + + result.str = start; + result.len = (end - start) + 1; + return result; +} + +DQN_API Dqn_b32 operator==(Dqn_String const &lhs, Dqn_String const &rhs) +{ + Dqn_b32 result = lhs.len == rhs.len && (DQN_MEMCMP(lhs.str, rhs.str, lhs.len) == 0); + return result; +} + +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Asprintf (Allocate Sprintf) +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va) { Dqn_String result = {}; va_list va2; @@ -1952,7 +2629,7 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_Asprintf(Dqn_Allocator *allocator, cha return result; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...)) +DQN_API Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...) { va_list va; va_start(va, fmt); @@ -1961,453 +2638,12 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_Asprintf(Dqn_Allocator *allocator, cha return result; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Vectors -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2I, Dqn_V2_ToV2I(Dqn_V2 a)) -{ - Dqn_V2I result(static_cast(a.x), static_cast(a.y)); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2, Dqn_V2_Min(Dqn_V2 a, Dqn_V2 b)) -{ - Dqn_V2 result = Dqn_V2(DQN_MIN(a.x, b.x), DQN_MIN(a.y, b.y)); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2, Dqn_V2_Max(Dqn_V2 a, Dqn_V2 b)) -{ - Dqn_V2 result = Dqn_V2(DQN_MAX(a.x, b.x), DQN_MAX(a.y, b.y)); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2, Dqn_V2_Abs(Dqn_V2 a)) -{ - Dqn_V2 result = Dqn_V2(DQN_ABS(a.x), DQN_ABS(a.y)); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_f32, Dqn_V2_Dot(Dqn_V2 a, Dqn_V2 b)) -{ - Dqn_f32 result = (a.x * b.x) + (a.y * b.y); - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_f32, Dqn_V2_LengthSq(Dqn_V2 a, Dqn_V2 b)) -{ - Dqn_f32 x_side = b.x - a.x; - Dqn_f32 y_side = b.y - a.y; - Dqn_f32 result = DQN_SQUARED(x_side) + DQN_SQUARED(y_side); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2, Dqn_V2_Normalise(Dqn_V2 a)) -{ - Dqn_f32 length_sq = DQN_SQUARED(a.x) + DQN_SQUARED(a.y); - Dqn_f32 length = sqrtf(length_sq); - Dqn_V2 result = a / length; - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2, Dqn_V2_Perpendicular(Dqn_V2 a)) -{ - Dqn_V2 result = Dqn_V2(-a.y, a.x); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_f32, Dqn_V4_Dot(Dqn_V4 const *a, Dqn_V4 const *b)) -{ - Dqn_f32 result = (a->x * b->x) + (a->y * b->y) + (a->z * b->z) + (a->w * b->w); - return result; -} - - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Rect -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_Rect, Dqn_Rect_InitFromPosAndSize(Dqn_V2 pos, Dqn_V2 size)) -{ - Dqn_Rect result = {}; - result.min = pos; - if (size.w < 0) result.min.x -= size.w; - if (size.h < 0) result.min.y -= size.h; - result.max = result.min + Dqn_V2_Abs(size); - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2, Dqn_Rect_Center(Dqn_Rect rect)) -{ - Dqn_V2 size = rect.max - rect.min; - Dqn_V2 result = rect.min + (size * 0.5f); - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p)) -{ - Dqn_b32 result = (p.x >= rect.min.x && p.x <= rect.max.x && p.y >= rect.min.y && p.y <= rect.max.y); - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Rect_ContainsRect(Dqn_Rect a, Dqn_Rect b)) -{ - Dqn_b32 result = (b.min >= a.min && b.max <= a.max); - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2, Dqn_Rect_Size(Dqn_Rect rect)) -{ - Dqn_V2 result = rect.max - rect.min; - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Rect, Dqn_Rect_Move(Dqn_Rect src, Dqn_V2 move_amount)) -{ - Dqn_Rect result = src; - result.min += move_amount; - result.max += move_amount; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Rect_Intersects(Dqn_Rect a, Dqn_Rect b)) -{ - Dqn_b32 result = (a.min.x <= b.max.x && a.max.x >= b.min.x) && - (a.min.y <= b.max.y && a.max.y >= b.min.y); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Rect, Dqn_Rect_Intersection(Dqn_Rect a, Dqn_Rect b)) -{ - Dqn_Rect result = {}; - if (Dqn_Rect_Intersects(a, b)) - { - result.min.x = DQN_MAX(a.min.x, b.min.x); - result.min.y = DQN_MAX(a.min.y, b.min.y); - result.max.x = DQN_MIN(a.max.x, b.max.x); - result.max.y = DQN_MIN(a.max.y, b.max.y); - } - - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Rect, Dqn_Rect_Union(Dqn_Rect a, Dqn_Rect b)) -{ - Dqn_Rect result = {}; - result.min.x = DQN_MIN(a.min.x, b.min.x); - result.min.y = DQN_MIN(a.min.y, b.min.y); - result.max.x = DQN_MAX(a.max.x, b.max.x); - result.max.y = DQN_MAX(a.max.y, b.max.y); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Rect, Dqn_Rect_FromRectI32(Dqn_RectI32 a)) -{ - Dqn_Rect result = Dqn_Rect(a.min, a.max); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2I, Dqn_RectI32_Size(Dqn_RectI32 rect)) -{ - Dqn_V2I result = rect.max - rect.min; - return result; -} - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Math Utils -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_V2, Dqn_LerpV2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b)) -{ - Dqn_V2 result = {}; - result.x = a.x + ((b.x - a.x) * t); - result.y = a.y + ((b.y - a.y) * t); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_f32, Dqn_LerpF32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b)) -{ - Dqn_f32 result = a + ((b - a) * t); - return result; -} - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_Mat4 -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_Mat4, Dqn_Mat4_Identity()) -{ - Dqn_Mat4 result = - { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - }; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Mat4, Dqn_Mat4_Scale3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z)) -{ - Dqn_Mat4 result = - { - x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1, - }; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Mat4, Dqn_Mat4_ScaleV3(Dqn_V3 vec)) -{ - Dqn_Mat4 result = Dqn_Mat4_Scale3f(vec.x, vec.y, vec.z); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Mat4, Dqn_Mat4_Translate3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z)) -{ - Dqn_Mat4 result = - { - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1, - }; - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Mat4, Dqn_Mat4_TranslateV3(Dqn_V3 vec)) -{ - Dqn_Mat4 result = Dqn_Mat4_Translate3f(vec.x, vec.y, vec.z); - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_Mat4, operator*(Dqn_Mat4 const &a, Dqn_Mat4 const &b)) -{ - Dqn_V4 const *row1 = a.row + 0; - Dqn_V4 const *row2 = a.row + 1; - Dqn_V4 const *row3 = a.row + 2; - Dqn_V4 const *row4 = a.row + 3; - Dqn_V4 const col1 = Dqn_V4(b.row_major[0][0], b.row_major[1][0], b.row_major[2][0], b.row_major[3][0]); - Dqn_V4 const col2 = Dqn_V4(b.row_major[0][1], b.row_major[1][1], b.row_major[2][1], b.row_major[3][1]); - Dqn_V4 const col3 = Dqn_V4(b.row_major[0][2], b.row_major[1][2], b.row_major[2][2], b.row_major[3][3]); - Dqn_V4 const col4 = Dqn_V4(b.row_major[0][3], b.row_major[1][3], b.row_major[2][3], b.row_major[3][3]); - - Dqn_Mat4 result = - { - Dqn_V4_Dot(row1, &col1), Dqn_V4_Dot(row1, &col2), Dqn_V4_Dot(row1, &col3), Dqn_V4_Dot(row1, &col4), - Dqn_V4_Dot(row2, &col1), Dqn_V4_Dot(row2, &col2), Dqn_V4_Dot(row2, &col3), Dqn_V4_Dot(row2, &col4), - Dqn_V4_Dot(row3, &col1), Dqn_V4_Dot(row3, &col2), Dqn_V4_Dot(row3, &col3), Dqn_V4_Dot(row3, &col4), - Dqn_V4_Dot(row4, &col1), Dqn_V4_Dot(row4, &col2), Dqn_V4_Dot(row4, &col3), Dqn_V4_Dot(row4, &col4), - }; - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_V4, operator*(Dqn_Mat4 const &mat, Dqn_V4 const &vec)) -{ - Dqn_f32 x = vec.x, y = vec.y, z = vec.z, w = vec.w; - Dqn_V4 result = - { - (mat[0] * x) + (mat[1] * y) + (mat[2] * z) + (mat[3] * w), - (mat[4] * x) + (mat[5] * y) + (mat[6] * z) + (mat[7] * w), - (mat[8] * x) + (mat[9] * y) + (mat[10] * z) + (mat[11] * w), - (mat[12] * x) + (mat[13] * y) + (mat[14] * z) + (mat[15] * w), - }; - return result; -} - - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Helper Functions -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_Bit_UnsetInplace(Dqn_u32 *flags, Dqn_u32 bitfield)) -{ - *flags = (*flags & ~bitfield); -} - - -DQN_HEADER_COPY_PROTOTYPE(void, Dqn_Bit_SetInplace(Dqn_u32 *flags, Dqn_u32 bitfield)) -{ - *flags = (*flags | bitfield); -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Bit_IsSet(Dqn_u32 bits, Dqn_u32 bits_to_set)) -{ - auto result = DQN_CAST(Dqn_b32)((bits & bits_to_set) == bits_to_set); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Bit_IsNotSet(Dqn_u32 bits, Dqn_u32 bits_to_check)) -{ - auto result = !Dqn_Bit_IsSet(bits, bits_to_check); - return result; -} - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Safe Arithmetic -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_i64, Dqn_Safe_AddI64(Dqn_i64 a, Dqn_i64 b)) -{ - DQN_ASSERT_MSG(a <= INT64_MAX - b, "%zu <= %zu", a, INT64_MAX - b); - Dqn_i64 result = a + b; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_i64, Dqn_Safe_MulI64(Dqn_i64 a, Dqn_i64 b)) -{ - DQN_ASSERT_MSG(a <= INT64_MAX / b , "%zu <= %zu", a, INT64_MAX / b); - Dqn_i64 result = a * b; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_u64, Dqn_Safe_AddU64(Dqn_u64 a, Dqn_u64 b)) -{ - DQN_ASSERT_MSG(a <= UINT64_MAX - b, "%zu <= %zu", a, UINT64_MAX - b); - Dqn_u64 result = a + b; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_u64, Dqn_Safe_SubU64(Dqn_u64 a, Dqn_u64 b)) -{ - DQN_ASSERT_MSG(a >= b, "%zu >= %zu", a, b); - Dqn_u64 result = a - b; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_u32, Dqn_Safe_SubU32(Dqn_u32 a, Dqn_u32 b)) -{ - DQN_ASSERT_MSG(a >= b, "%zu >= %zu", a, b); - Dqn_u32 result = a - b; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_u64, Dqn_Safe_MulU64(Dqn_u64 a, Dqn_u64 b)) -{ - DQN_ASSERT_MSG(a <= UINT64_MAX / b , "%zu <= %zu", a, UINT64_MAX / b); - Dqn_u64 result = a * b; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(int, Dqn_Safe_TruncateISizeToInt(Dqn_isize val)) -{ - DQN_ASSERT_MSG(val >= INT_MIN && val <= INT_MAX, "%zd >= %zd && %zd <= %zd", val, INT_MIN, val, INT_MAX); - auto result = (int)val; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_i32, Dqn_Safe_TruncateISizeToI32(Dqn_isize val)) -{ - DQN_ASSERT_MSG(val >= INT32_MIN && val <= INT32_MAX, "%zd >= %zd && %zd <= %zd", val, INT32_MIN, val, INT32_MAX); - auto result = DQN_CAST(Dqn_i32)val; - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_i8, Dqn_Safe_TruncateISizeToI8(Dqn_isize val)) -{ - DQN_ASSERT_MSG(val >= INT8_MIN && val <= INT8_MAX, "%zd >= %zd && %zd <= %zd", val, INT8_MIN, val, INT8_MAX); - auto result = DQN_CAST(Dqn_i8)val; - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_u32, Dqn_Safe_TruncateUSizeToU32(Dqn_u64 val)) -{ - DQN_ASSERT_MSG(val <= UINT32_MAX, "%zu <= %zu", val, UINT32_MAX); - auto result = DQN_CAST(Dqn_u32)val; - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(int, Dqn_Safe_TruncateUSizeToI32(Dqn_usize val)) -{ - DQN_ASSERT_MSG(val <= INT32_MAX, "%zu <= %zd", val, INT32_MAX); - auto result = DQN_CAST(int)val; - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(int, Dqn_Safe_TruncateUSizeToInt(Dqn_usize val)) -{ - DQN_ASSERT_MSG(val <= INT_MAX, "%zu <= %zd", val, INT_MAX); - auto result = DQN_CAST(int)val; - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_isize, Dqn_Safe_TruncateUSizeToISize(Dqn_usize val)) -{ - DQN_ASSERT_MSG(val <= DQN_CAST(Dqn_usize)DQN_ISIZE_MAX, "%zu <= %zu", val, DQN_CAST(Dqn_usize)DQN_ISIZE_MAX); - auto result = DQN_CAST(Dqn_isize)val; - return result; -} - - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Char Helpers -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsAlpha(char ch)) -{ - Dqn_b32 result = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsDigit(char ch)) -{ - Dqn_b32 result = (ch >= '0' && ch <= '9'); - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsAlphaNum(char ch)) -{ - Dqn_b32 result = Dqn_Char_IsAlpha(ch) || Dqn_Char_IsDigit(ch); - return result; -} - - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsWhitespace(char ch)) -{ - Dqn_b32 result = (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(char, Dqn_Char_ToLower(char ch)) -{ - char result = ch; - if (result >= 'A' && result <= 'Z') - result = 'a' - 'A'; - return result; -} - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: String Helpers -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Str_Equals(char const *a, char const *b, Dqn_isize a_len = -1, Dqn_isize b_len = -1)) +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_Str +// +// ------------------------------------------------------------------------------------------------- +DQN_API Dqn_b32 Dqn_Str_Equals(char const *a, char const *b, Dqn_isize a_len, Dqn_isize b_len) { if (a_len == -1) a_len = DQN_CAST(Dqn_isize)strlen(a); if (b_len == -1) b_len = DQN_CAST(Dqn_isize)strlen(b); @@ -2415,7 +2651,7 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Str_Equals(char const *a, char const *b, return (strncmp(a, b, DQN_CAST(size_t)a_len) == 0); } -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_FindMulti(char const *buf, char const *find_list[], Dqn_isize const *find_string_lens, Dqn_isize find_len, Dqn_isize *match_index, Dqn_isize buf_len = -1)) +DQN_API char const *Dqn_Str_FindMulti(char const *buf, char const *find_list[], Dqn_isize const *find_string_lens, Dqn_isize find_len, Dqn_isize *match_index, Dqn_isize buf_len) { char const *result = nullptr; if (find_len == 0) return result; @@ -2443,7 +2679,7 @@ DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_FindMulti(char const *buf, char return result; } -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_Find(char const *buf, char const *find, Dqn_isize buf_len = -1, Dqn_isize find_len = -1)) +DQN_API char const *Dqn_Str_Find(char const *buf, char const *find, Dqn_isize buf_len, Dqn_isize find_len) { if (find_len == 0) return nullptr; if (buf_len < 0) buf_len = DQN_CAST(Dqn_isize)strlen(buf); @@ -2465,107 +2701,100 @@ DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_Find(char const *buf, char const return result; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Str_Match(char const *src, char const *find, int find_len)) +DQN_API Dqn_b32 Dqn_Str_Match(char const *src, char const *find, int find_len) { - if (find_len == -1) find_len = Dqn_Safe_TruncateUSizeToInt(strlen(find)); - auto result = DQN_CAST(Dqn_b32)(strncmp(src, find, DQN_CAST(size_t)find_len) == 0); - return result; + if (find_len == -1) find_len = Dqn_Safe_TruncateUSizeToInt(strlen(find)); + auto result = DQN_CAST(Dqn_b32)(strncmp(src, find, DQN_CAST(size_t)find_len) == 0); + return result; } -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToChar(char const *src, char ch)) +DQN_API char const *Dqn_Str_SkipToChar(char const *src, char ch) { - char const *result = src; - while (result && result[0] && result[0] != ch) ++result; - return result; + char const *result = src; + while (result && result[0] && result[0] != ch) ++result; + return result; } - -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextAlphaNum(char const *src)) +DQN_API char const *Dqn_Str_SkipToNextAlphaNum(char const *src) { - char const *result = src; - while (result && result[0] && !Dqn_Char_IsAlphaNum(result[0])) ++result; - return result; + char const *result = src; + while (result && result[0] && !Dqn_Char_IsAlphaNum(result[0])) ++result; + return result; } - -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextDigit(char const *src)) +DQN_API char const *Dqn_Str_SkipToNextDigit(char const *src) { - char const *result = src; - while (result && result[0] && !Dqn_Char_IsDigit(result[0])) ++result; - return result; + char const *result = src; + while (result && result[0] && !Dqn_Char_IsDigit(result[0])) ++result; + return result; } - -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextChar(char const *src)) +DQN_API char const *Dqn_Str_SkipToNextChar(char const *src) { - char const *result = src; - while (result && result[0] && !Dqn_Char_IsAlpha(result[0])) ++result; - return result; + char const *result = src; + while (result && result[0] && !Dqn_Char_IsAlpha(result[0])) ++result; + return result; } - -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextWord(char const *src)) +DQN_API char const *Dqn_Str_SkipToNextWord(char const *src) { - char const *result = src; - while (result && result[0] && !Dqn_Char_IsWhitespace(result[0])) ++result; - while (result && result[0] && Dqn_Char_IsWhitespace(result[0])) ++result; - return result; + char const *result = src; + while (result && result[0] && !Dqn_Char_IsWhitespace(result[0])) ++result; + while (result && result[0] && Dqn_Char_IsWhitespace(result[0])) ++result; + return result; } - -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextWhitespace(char const *src)) +DQN_API char const *Dqn_Str_SkipToNextWhitespace(char const *src) { - char const *result = src; - while (result && result[0] && !Dqn_Char_IsWhitespace(result[0])) ++result; - return result; + char const *result = src; + while (result && result[0] && !Dqn_Char_IsWhitespace(result[0])) ++result; + return result; } - -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipWhitespace(char const *src)) +DQN_API char const *Dqn_Str_SkipWhitespace(char const *src) { - char const *result = src; - while (result && result[0] && Dqn_Char_IsWhitespace(result[0])) ++result; - return result; + char const *result = src; + while (result && result[0] && Dqn_Char_IsWhitespace(result[0])) ++result; + return result; } - -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToCharInPlace(char const **src, char ch)) +DQN_API char const *Dqn_Str_SkipToCharInPlace(char const **src, char ch) { *src = Dqn_Str_SkipToChar(*src, ch); return *src; } -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextAlphaNumInPlace(char const **src)) +DQN_API char const *Dqn_Str_SkipToNextAlphaNumInPlace(char const **src) { *src = Dqn_Str_SkipToNextAlphaNum(*src); return *src; } -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextCharInPlace(char const **src)) +DQN_API char const *Dqn_Str_SkipToNextCharInPlace(char const **src) { *src = Dqn_Str_SkipToNextChar(*src); return *src; } -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextWhitespaceInPlace(char const **src)) +DQN_API char const *Dqn_Str_SkipToNextWhitespaceInPlace(char const **src) { *src = Dqn_Str_SkipToNextWhitespace(*src); return *src; } -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipToNextWordInPlace(char const **src)) +DQN_API char const *Dqn_Str_SkipToNextWordInPlace(char const **src) { *src = Dqn_Str_SkipToNextWord(*src); return *src; } -DQN_HEADER_COPY_PROTOTYPE(char const *, Dqn_Str_SkipWhitespaceInPlace(char const **src)) +DQN_API char const *Dqn_Str_SkipWhitespaceInPlace(char const **src) { *src = Dqn_Str_SkipWhitespace(*src); return *src; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_u64, Dqn_Str_ToU64(char const *buf, int len = -1)) +DQN_API Dqn_u64 Dqn_Str_ToU64(char const *buf, int len) { Dqn_u64 result = 0; if (!buf) return result; @@ -2589,7 +2818,7 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_u64, Dqn_Str_ToU64(char const *buf, int len = -1)) return result; } -DQN_HEADER_COPY_PROTOTYPE(Dqn_i64, Dqn_Str_ToI64(char const *buf, int len = -1)) +DQN_API Dqn_i64 Dqn_Str_ToI64(char const *buf, int len) { Dqn_i64 result = 0; if (!buf) return result; @@ -2622,59 +2851,12 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_i64, Dqn_Str_ToI64(char const *buf, int len = -1)) return result; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Dqn_String -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_String_Compare(Dqn_String const lhs, Dqn_String const rhs)) -{ - Dqn_b32 result = false; - if (lhs.len == rhs.len) - result = (memcmp(lhs.str, rhs.str, DQN_CAST(size_t)lhs.len) == 0); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs)) -{ - Dqn_b32 result = (lhs.len == rhs.len); - if (result) - { - for (Dqn_isize index = 0; index < lhs.len && result; index++) - result = (Dqn_Char_ToLower(lhs.str[index]) == Dqn_Char_ToLower(rhs.str[index])); - } - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_String_Copy(Dqn_Allocator *allocator, Dqn_String const src)) -{ - Dqn_String result = src; - result.str = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, result.len, alignof(char)); - DQN_MEMCOPY(result.str, src.str, DQN_CAST(size_t)result.len); - return result; -} - -DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_String_TrimWhitespaceAround(Dqn_String src)) -{ - Dqn_String result = src; - if (src.len <= 0) return result; - - char *start = src.str; - char *end = start + (src.len - 1); - while (Dqn_Char_IsWhitespace(start[0])) start++; - while (end != start && Dqn_Char_IsWhitespace(end[0])) end--; - - result.str = start; - result.len = (end - start) + 1; - return result; -} - -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: File -// @ -// @ ------------------------------------------------------------------------------------------------- -DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_isize *file_size)) +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Dqn_File +// +// ------------------------------------------------------------------------------------------------- +DQN_API char *Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_isize *file_size) { Dqn_isize file_size_ = 0; if (!file_size) file_size = &file_size_; @@ -2687,31 +2869,34 @@ DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_File_ReadAll(Dqn_Allocator *allocator, cha *file_size = ftell(file_handle); if (DQN_CAST(long)(*file_size) == -1L) { - DQN_ASSERT(*file_size != -1L); - *file_size = 0; + DQN_LOG_E("Failed to determine '%s' file size using ftell\n", file); + return nullptr; } rewind(file_handle); auto *result = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, *file_size + 1, alignof(char)); - DQN_ASSERT(result); - result[*file_size] = 0; + if (!result) + { + DQN_LOG_M("Failed to allocate %td bytes to read file '%s'\n", file_size + 1, file); + return nullptr; + } + result[*file_size] = 0; if (fread(result, DQN_CAST(size_t)(*file_size), 1, file_handle) != 1) { - fprintf(stderr, "Failed to fread: %td bytes into buffer from file: %s\n", *file_size, file); + DQN_LOG_E("Failed to read %td bytes into buffer from '%s'\n", *file_size, file); return nullptr; } return result; } -// @ ------------------------------------------------------------------------------------------------- -// @ -// @ NOTE: Utils -// @ -// @ ------------------------------------------------------------------------------------------------- -#include -DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_EpochTimeToDate(Dqn_i64 timestamp, char *buf, Dqn_isize buf_len)) +// ------------------------------------------------------------------------------------------------- +// +// NOTE: Utilities +// +// ------------------------------------------------------------------------------------------------- +DQN_API char *Dqn_EpochTimeToDate(Dqn_i64 timestamp, char *buf, Dqn_isize buf_len) { DQN_ASSERT(buf_len >= 0); time_t time = DQN_CAST(time_t)timestamp; @@ -2719,6 +2904,36 @@ DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_EpochTimeToDate(Dqn_i64 timestamp, char *b strftime(buf, DQN_CAST(Dqn_usize)buf_len, "%c", date_time); return buf; } + +DQN_API char *Dqn_U64ToStr(Dqn_u64 val, Dqn_U64Str *result, Dqn_b32 comma_sep) +{ + int buf_index = (int)(Dqn_ArrayCount(result->buf) - 1); + result->buf[buf_index--] = 0; + + if (val == 0) + { + result->buf[buf_index--] = '0'; + result->len = 1; + } + else + { + for (int digit_count = 0; val > 0; result->len++, digit_count++) + { + if (comma_sep && (digit_count != 0) && (digit_count % 3 == 0)) + { + result->buf[buf_index--] = ','; + result->len++; + } + + auto digit = DQN_CAST(char)(val % 10); + result->buf[buf_index--] = '0' + digit; + val /= 10; + } + } + + result->str = result->buf + (buf_index + 1); + return result->str; +} #endif // DQN_IMPLEMENTATION #ifdef STB_SPRINTF_IMPLEMENTATION diff --git a/Code/DqnHeader.h b/Code/DqnHeader.h deleted file mode 100644 index 3a86f3a..0000000 --- a/Code/DqnHeader.h +++ /dev/null @@ -1,321 +0,0 @@ -#ifndef DQN_HEADER_H -#define DQN_HEADER_H - -// Compile & Run -/* - MSVC - cl /O2 /MT /W4 /EHsc /FC /wd4201 /D DQN_HEADER_IMPLEMENTATION /Tp DqnHeader.h /link /nologo - DqnHeader.exe Dqn.h > Dqn_Generated.h -*/ - -// NOTE: Copy the function prototype, all functions will be whitespaced aligned to the longest return type of the file -// NOTE: If you function contains a comma NOT in the argument list (i.e. multiple template parameters), this macro does NOT work. -// Please use the DQN_HEADER_COPY_BEGIN and DQN_HEADER_COPY_END unfortunately. -#define DQN_HEADER_COPY_PROTOTYPE(func_return, func_name_and_types) func_return func_name_and_types - -// NOTE: Copy all contents from the file between the begin and end macro -#define DQN_HEADER_COPY_BEGIN -#define DQN_HEADER_COPY_END - -// NOTE: Copy comments by writing comments with the prefix, "// @" -// @ Hello this comment will be copied to the output - -// NOTE: Example Input -#if 0 - #include "DqnHeader.h" - - // @ ptr1: Pointer to the first block of memory - // @ ptr2: Pointer to the second block of memory - // @ num_bytes: The number of bytes to compare in both blocks of memory - DQN_HEADER_COPY_PROTOTYPE(int, Dqn_MemCmp(void const *ptr1, void const *ptr2, size_t num_bytes)) - { - int result = memcmp(ptr1, ptr2, num_bytes); - return result; - } - - DQN_HEADER_COPY_BEGIN - struct HelloWorld - { - int foo, bar; - }; - DQN_HEADER_COPY_END -#endif - -// NOTE: Example Output -#if 0 - // @ ptr1: Pointer to the first block of memory - // @ ptr2: Pointer to the second block of memory - // @ num_bytes: The number of bytes to compare in both blocks of memory - int Dqn_MemCmp(void const *ptr1, void const *ptr2, size_t num_bytes); - struct HelloWorld - { - int foo, bar; - }; -#endif - -#endif /* DQN_HEADER_H */ - -#ifdef DQN_HEADER_IMPLEMENTATION - -#define _CRT_SECURE_NO_WARNINGS // NOTE: Undefined at end of file -#include - -#define DQN_USE_PRIMITIVE_TYPEDEFS -#define DQN_IMPLEMENTATION -#include "Dqn.h" - -char const *ParseFunctionReturnType(char const *ptr, Dqn_isize *len) -{ - char const *result = Dqn_Str_SkipWhitespace(ptr); - Dqn_isize result_len = 0; - for (int scope = 0; ptr; ptr++) // NOTE: Parse the function return type - { - if (ptr[0] == '<' || ptr[0] == '>') - { - if (ptr[0] == '<') scope++; - else scope--; - continue; - } - else if (ptr[0] == ',') - { - if (scope != 0) continue; - result_len = static_cast(ptr - result); - break; - } - } - - if (len) *len = result_len; - return result; -} - -char const *ParseFunctionNameAndParameters(char const *ptr, Dqn_isize *len) -{ - char const *result = ptr; - int result_len = 0; - for (int scope = 0; ptr; ptr++) // NOTE: Parse the function name and parameters - { - if (ptr[0] == '(') scope++; - else if (ptr[0] == ')') - { - if (scope-- != 0) continue; - result_len = static_cast(ptr - result); - break; - } - } - - *len = result_len; - return result; -} - -char const *ParseFunctionComment(char const *ptr, Dqn_isize *len) -{ - while (ptr[0] != '"') ptr++; - ptr++; - - char const *result = ptr; - Dqn_isize result_len = 0; - for (;;) - { - while (ptr[0] != '"') - ptr++; - - if (ptr[-1] != '\\') - { - result_len = ptr - result; - break; - } - } - - *len = result_len; - return result; - -} - -enum struct HeaderEntryType -{ - Prototype, - Comment, - CopyBegin, - Count -}; - -struct HeaderEntry -{ - HeaderEntryType type; - union - { - struct - { - Dqn_String return_val; - Dqn_String name_and_args; - } function_decl; - - Dqn_String comment; - Dqn_String copy_range; - }; -}; - -int main(int argc, char *argv[]) -{ - if (argc < 1) - { - fprintf(stdout, "Header Usage: %s [, ...]\n", argv[0]); - return 0; - } - - Dqn_ArenaAllocator arena = {}; - arena.allocator = Dqn_Allocator_InitWithXHeap(); - Dqn_Allocator allocator = Dqn_Allocator_InitWithArena(&arena); - Dqn_ArenaAllocator_Reserve(&arena, DQN_MEGABYTES(16)); - for (Dqn_isize arg_index = 1; arg_index < argc; ++arg_index) - { - char const *file = argv[arg_index]; - Dqn_isize buf_size = 0; - char *buf = Dqn_File_ReadAll(&allocator, file, &buf_size); - if (!buf) - { - fprintf(stderr, "Failed to read file: %s\n", file); - continue; - } - - char constexpr HEADER_COPY_PROTOTYPE[] = "DQN_HEADER_COPY_PROTOTYPE"; - char constexpr HEADER_COMMENT[] = "// @"; - char constexpr HEADER_COPY_BEGIN[] = "DQN_HEADER_COPY_BEGIN"; - char constexpr HEADER_COPY_END[] = "DQN_HEADER_COPY_END"; - - char const *find_list[] = {HEADER_COPY_PROTOTYPE, HEADER_COMMENT, HEADER_COPY_BEGIN}; - Dqn_isize constexpr find_string_lens[] = { - Dqn_CharCountI(HEADER_COPY_PROTOTYPE), - Dqn_CharCountI(HEADER_COMMENT), - Dqn_CharCountI(HEADER_COPY_BEGIN), - }; - - Dqn_isize num_header_entries = 0; - { - char const *ptr = buf; - char const *ptr_end = buf + buf_size; - Dqn_isize ptr_len = buf_size; - Dqn_isize matched_find_index = -1; - for (char const *token = Dqn_Str_FindMulti(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len); - token; - token = Dqn_Str_FindMulti(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len)) - { - ptr = token + find_string_lens[matched_find_index]; - num_header_entries++; - ptr_len = ptr_end - ptr; - } - } - - auto *header_entries = Dqn_ArenaAllocator_AllocateType(&arena, num_header_entries); - Dqn_isize header_entries_index = 0; - Dqn_isize max_prototype_return_val = 0; - - char const *ptr = buf; - char const *ptr_end = buf + buf_size; - Dqn_isize ptr_len = buf_size; - Dqn_isize matched_find_index = -1; - for (char const *token = Dqn_Str_FindMulti(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len); - token; - token = Dqn_Str_FindMulti(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len)) - { - HeaderEntry *entry = header_entries + header_entries_index++; - entry->type = static_cast(matched_find_index); - if (matched_find_index == (Dqn_isize)HeaderEntryType::Prototype) - { - ptr = token + find_string_lens[matched_find_index] + 1 /*macro start parenthesis*/; - Dqn_isize func_type_len = 0; - char const *func_type = ParseFunctionReturnType(ptr, &func_type_len); - - ptr = func_type + func_type_len + 1; // Ptr is at macro comma, skip the comma - ptr = Dqn_Str_SkipWhitespace(ptr); - Dqn_isize func_name_len = 0; - char const *func_name = ParseFunctionNameAndParameters(ptr, &func_name_len); - - entry->function_decl.return_val = Dqn_Asprintf(&allocator, "%.*s", func_type_len, func_type); - entry->function_decl.name_and_args = Dqn_Asprintf(&allocator, "%.*s", func_name_len, func_name); - ptr = func_name + func_name_len + 1; // Ptr is at macro closing paren, skip the paren - - max_prototype_return_val = DQN_MAX(max_prototype_return_val, func_type_len); - } - else if (matched_find_index == (Dqn_isize)HeaderEntryType::Comment) - { - char const *comment_start = token; - ptr = token; - while (ptr[0] != '\n' && ptr[0] != '\r') - ptr++; - Dqn_isize comment_len = ptr - comment_start; - - entry->comment.str = Dqn_ArenaAllocator_AllocateType(&arena, comment_len); - DQN_FOR_EACH(comment_index, comment_len) - { - // NOTE: We capture "// @", and we want to skip the @ symbol, its ugly which is at the index 3 - // Also if a space is given after the '@' symbol then skip that too. - char ch = comment_start[comment_index]; - if (comment_index == 3 && ch == '@') continue; - if (comment_index == 4 && ch == ' ') continue; - entry->comment.str[entry->comment.len++] = ch; - } - - while (entry->comment.len > 0 && Dqn_Char_IsWhitespace(entry->comment.str[entry->comment.len - 1])) - entry->comment.len--; - ptr = comment_start + comment_len; - } - else if (matched_find_index == (Dqn_isize)HeaderEntryType::CopyBegin) - { - ptr = token + find_string_lens[matched_find_index]; - ptr = Dqn_Str_SkipWhitespace(ptr); - char const *copy_start = ptr; - char const *copy_end = Dqn_Str_Find(ptr, HEADER_COPY_END, ptr_len, Dqn_CharCountI(HEADER_COPY_END)); - if (!copy_end) - { - fprintf(stderr, "Header copy begin macro: %s not matched with a copy end macro: %s", HEADER_COPY_BEGIN, HEADER_COPY_END); - return -1; - } - - Dqn_isize copy_len = copy_end - copy_start; - entry->copy_range.str = Dqn_ArenaAllocator_AllocateType(&arena, copy_len); - DQN_FOR_EACH(copy_index, copy_len) - { - char ch = copy_start[copy_index]; - if (ch == '\r') continue; - entry->copy_range.str[entry->copy_range.len++] = ch; - } - ptr = copy_end; - } - - ptr_len = ptr_end - ptr; - } - DQN_ASSERT(header_entries_index == num_header_entries); - - DQN_FOR_EACH(entry_index, header_entries_index) - { - HeaderEntry const *entry = header_entries + entry_index; - switch(entry->type) - { - case HeaderEntryType::Prototype: - { - Dqn_isize remaining_space = max_prototype_return_val - entry->function_decl.return_val.len + 1; - fprintf(stdout, "%.*s", (int)entry->function_decl.return_val.len, entry->function_decl.return_val.str); - DQN_FOR_EACH(space, remaining_space) fputs(" ", stdout); - fprintf(stdout, " %.*s;\n", (int)entry->function_decl.name_and_args.len, entry->function_decl.name_and_args.str); - } - break; - - case HeaderEntryType::Comment: - { - fprintf(stdout, "%.*s\n", (int)entry->comment.len, entry->comment.str); - } - break; - - case HeaderEntryType::CopyBegin: - { - fprintf(stdout, "%.*s\n", (int)entry->copy_range.len, entry->copy_range.str); - } - break; - } - } - } -} - -#undef _CRT_SECURE_NO_WARNINGS -#endif /* DQN_HEADER_IMPLEMENTATION */ diff --git a/Code/DqnHeader_Generated.h b/Code/DqnHeader_Generated.h deleted file mode 100644 index f99719a..0000000 --- a/Code/DqnHeader_Generated.h +++ /dev/null @@ -1,690 +0,0 @@ -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Typedefs, Macros, Utils -// -// ------------------------------------------------------------------------------------------------- -constexpr Dqn_usize Dqn_ArrayCount(T const (&)[N]); -constexpr Dqn_isize Dqn_ArrayCountI(T const (&)[N]); -constexpr Dqn_usize Dqn_CharCount(char const (&)[N]); -constexpr Dqn_isize Dqn_CharCountI(char const (&)[N]); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Logging -// -// ------------------------------------------------------------------------------------------------- -constexpr inline char const * Dqn_LogTypeTag(Dqn_LogType type); -// NOTE: Set the callback to get called whenever a log message has been printed -#define DQN_LOG_CALLBACK(name) void name(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *log_str) -typedef DQN_LOG_CALLBACK(Dqn_LogCallback); -Dqn_LogCallback *Dqn_log_callback; - -#define DQN_LOG_E(fmt, ...) Dqn_Log(Dqn_LogType::Error, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG_D(fmt, ...) Dqn_Log(Dqn_LogType::Debug, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG_W(fmt, ...) Dqn_Log(Dqn_LogType::Warning, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG_I(fmt, ...) Dqn_Log(Dqn_LogType::Info, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG_M(fmt, ...) Dqn_Log(Dqn_LogType::Memory, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) -#define DQN_LOG(log_type, fmt, ...) Dqn_Log(log_type, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__) - -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Math -// -// ------------------------------------------------------------------------------------------------- -union Dqn_V2I -{ - struct { Dqn_i32 x, y; }; - struct { Dqn_i32 w, h; }; - struct { Dqn_i32 min, max; }; - Dqn_i32 e[2]; - - Dqn_V2I() = default; - constexpr Dqn_V2I(Dqn_f32 x_, Dqn_f32 y_): x((Dqn_i32)x_), y((Dqn_i32)y_) {} - constexpr Dqn_V2I(Dqn_i32 x_, Dqn_i32 y_): x(x_), y(y_) {} - constexpr Dqn_V2I(Dqn_i32 xy): x(xy), y(xy) {} - - constexpr bool operator!=(Dqn_V2I other) const { return !(*this == other); } - constexpr bool operator==(Dqn_V2I other) const { return (x == other.x) && (y == other.y); } - constexpr bool operator>=(Dqn_V2I other) const { return (x >= other.x) && (y >= other.y); } - constexpr bool operator<=(Dqn_V2I other) const { return (x <= other.x) && (y <= other.y); } - constexpr bool operator< (Dqn_V2I other) const { return (x < other.x) && (y < other.y); } - constexpr bool operator> (Dqn_V2I other) const { return (x > other.x) && (y > other.y); } - constexpr Dqn_V2I operator- (Dqn_V2I other) const { Dqn_V2I result(x - other.x, y - other.y); return result; } - constexpr Dqn_V2I operator+ (Dqn_V2I other) const { Dqn_V2I result(x + other.x, y + other.y); return result; } - constexpr Dqn_V2I operator* (Dqn_V2I other) const { Dqn_V2I result(x * other.x, y * other.y); return result; } - constexpr Dqn_V2I operator* (Dqn_f32 other) const { Dqn_V2I result(x * other, y * other); return result; } - constexpr Dqn_V2I operator* (Dqn_i32 other) const { Dqn_V2I result(x * other, y * other); return result; } - constexpr Dqn_V2I operator/ (Dqn_V2I other) const { Dqn_V2I result(x / other.x, y / other.y); return result; } - constexpr Dqn_V2I operator/ (Dqn_f32 other) const { Dqn_V2I result(x / other, y / other); return result; } - constexpr Dqn_V2I operator/ (Dqn_i32 other) const { Dqn_V2I result(x / other, y / other); return result; } - constexpr Dqn_V2I &operator*=(Dqn_V2I other) { *this = *this * other; return *this; } - constexpr Dqn_V2I &operator*=(Dqn_f32 other) { *this = *this * other; return *this; } - constexpr Dqn_V2I &operator*=(Dqn_i32 other) { *this = *this * other; return *this; } - constexpr Dqn_V2I &operator-=(Dqn_V2I other) { *this = *this - other; return *this; } - constexpr Dqn_V2I &operator+=(Dqn_V2I other) { *this = *this + other; return *this; } -}; - -union Dqn_V2 -{ - struct { Dqn_f32 x, y; }; - struct { Dqn_f32 w, h; }; - struct { Dqn_f32 min, max; }; - Dqn_f32 e[2]; - - Dqn_V2() = default; - constexpr Dqn_V2(Dqn_f32 a) : x(a), y(a) {} - constexpr Dqn_V2(Dqn_i32 a) : x((Dqn_f32)a), y((Dqn_f32)a) {} - constexpr Dqn_V2(Dqn_f32 x_, Dqn_f32 y_): x(x_), y(y_) {} - constexpr Dqn_V2(Dqn_i32 x_, Dqn_i32 y_): x((Dqn_f32)x_), y((Dqn_f32)y_) {} - constexpr Dqn_V2(Dqn_V2I a) : x((Dqn_f32)a.x), y((Dqn_f32)a.y) {} - - constexpr bool operator!=(Dqn_V2 other) const { return !(*this == other); } - constexpr bool operator==(Dqn_V2 other) const { return (x == other.x) && (y == other.y); } - constexpr bool operator>=(Dqn_V2 other) const { return (x >= other.x) && (y >= other.y); } - constexpr bool operator<=(Dqn_V2 other) const { return (x <= other.x) && (y <= other.y); } - constexpr bool operator< (Dqn_V2 other) const { return (x < other.x) && (y < other.y); } - constexpr bool operator> (Dqn_V2 other) const { return (x > other.x) && (y > other.y); } - constexpr Dqn_V2 operator- (Dqn_V2 other) const { Dqn_V2 result(x - other.x, y - other.y); return result; } - constexpr Dqn_V2 operator+ (Dqn_V2 other) const { Dqn_V2 result(x + other.x, y + other.y); return result; } - constexpr Dqn_V2 operator* (Dqn_V2 other) const { Dqn_V2 result(x * other.x, y * other.y); return result; } - constexpr Dqn_V2 operator* (Dqn_f32 other) const { Dqn_V2 result(x * other, y * other); return result; } - constexpr Dqn_V2 operator* (Dqn_i32 other) const { Dqn_V2 result(x * other, y * other); return result; } - constexpr Dqn_V2 operator/ (Dqn_V2 other) const { Dqn_V2 result(x / other.x, y / other.y); return result; } - constexpr Dqn_V2 operator/ (Dqn_f32 other) const { Dqn_V2 result(x / other, y / other); return result; } - constexpr Dqn_V2 operator/ (Dqn_i32 other) const { Dqn_V2 result(x / other, y / other); return result; } - constexpr Dqn_V2 &operator*=(Dqn_V2 other) { *this = *this * other; return *this; } - constexpr Dqn_V2 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; } - constexpr Dqn_V2 &operator*=(Dqn_i32 other) { *this = *this * other; return *this; } - constexpr Dqn_V2 &operator/=(Dqn_V2 other) { *this = *this / other; return *this; } - constexpr Dqn_V2 &operator/=(Dqn_f32 other) { *this = *this / other; return *this; } - constexpr Dqn_V2 &operator/=(Dqn_i32 other) { *this = *this / other; return *this; } - constexpr Dqn_V2 &operator-=(Dqn_V2 other) { *this = *this - other; return *this; } - constexpr Dqn_V2 &operator+=(Dqn_V2 other) { *this = *this + other; return *this; } -}; - -union Dqn_V3 -{ - struct { Dqn_f32 x, y, z; }; - struct { Dqn_f32 r, g, b; }; - Dqn_V2 xy; - Dqn_f32 e[3]; - - Dqn_V3() = default; - constexpr Dqn_V3(Dqn_f32 a) : x(a), y(a), z(a) {} - constexpr Dqn_V3(Dqn_i32 a) : x((Dqn_f32)a), y((Dqn_f32)a), z((Dqn_f32)a) {} - constexpr Dqn_V3(Dqn_f32 x_, Dqn_f32 y_, Dqn_f32 z_): x(x_), y(y_), z(z_) {} - constexpr Dqn_V3(Dqn_i32 x_, Dqn_i32 y_, Dqn_f32 z_): x((Dqn_f32)x_), y((Dqn_f32)y_), z((Dqn_f32)z_) {} - constexpr Dqn_V3(Dqn_V2 xy, Dqn_f32 z_) : x(xy.x), y(xy.y), z(z_) {} - - constexpr bool operator!= (Dqn_V3 other) const { return !(*this == other); } - constexpr bool operator== (Dqn_V3 other) const { return (x == other.x) && (y == other.y) && (z == other.z); } - constexpr bool operator>= (Dqn_V3 other) const { return (x >= other.x) && (y >= other.y) && (z >= other.z); } - constexpr bool operator<= (Dqn_V3 other) const { return (x <= other.x) && (y <= other.y) && (z <= other.z); } - constexpr bool operator< (Dqn_V3 other) const { return (x < other.x) && (y < other.y) && (z < other.z); } - constexpr bool operator> (Dqn_V3 other) const { return (x > other.x) && (y > other.y) && (z > other.z); } - constexpr Dqn_V3 operator- (Dqn_V3 other) const { Dqn_V3 result(x - other.x, y - other.y, z - other.z); return result; } - constexpr Dqn_V3 operator+ (Dqn_V3 other) const { Dqn_V3 result(x + other.x, y + other.y, z + other.z); return result; } - constexpr Dqn_V3 operator* (Dqn_V3 other) const { Dqn_V3 result(x * other.x, y * other.y, z * other.z); return result; } - constexpr Dqn_V3 operator* (Dqn_f32 other) const { Dqn_V3 result(x * other, y * other, z * other); return result; } - constexpr Dqn_V3 operator* (Dqn_i32 other) const { Dqn_V3 result(x * other, y * other, z * other); return result; } - constexpr Dqn_V3 operator/ (Dqn_V3 other) const { Dqn_V3 result(x / other.x, y / other.y, z / other.z); return result; } - constexpr Dqn_V3 operator/ (Dqn_f32 other) const { Dqn_V3 result(x / other, y / other, z / other); return result; } - constexpr Dqn_V3 operator/ (Dqn_i32 other) const { Dqn_V3 result(x / other, y / other, z / other); return result; } - constexpr Dqn_V3 &operator*=(Dqn_V3 other) { *this = *this * other; return *this; } - constexpr Dqn_V3 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; } - constexpr Dqn_V3 &operator*=(Dqn_i32 other) { *this = *this * other; return *this; } - constexpr Dqn_V3 &operator/=(Dqn_V3 other) { *this = *this / other; return *this; } - constexpr Dqn_V3 &operator/=(Dqn_f32 other) { *this = *this / other; return *this; } - constexpr Dqn_V3 &operator/=(Dqn_i32 other) { *this = *this / other; return *this; } - constexpr Dqn_V3 &operator-=(Dqn_V3 other) { *this = *this - other; return *this; } - constexpr Dqn_V3 &operator+=(Dqn_V3 other) { *this = *this + other; return *this; } -}; - -union Dqn_V4 -{ - struct { Dqn_f32 x, y, z, w; }; - struct { Dqn_f32 r, g, b, a; }; - Dqn_V3 rgb; - Dqn_f32 e[4]; - - Dqn_V4() = default; - constexpr Dqn_V4(Dqn_f32 xyzw) : x(xyzw), y(xyzw), z(xyzw), w(xyzw) {} - constexpr Dqn_V4(Dqn_f32 x_, Dqn_f32 y_, Dqn_f32 z_, Dqn_f32 w_): x(x_), y(y_), z(z_), w(w_) {} - constexpr Dqn_V4(Dqn_i32 x_, Dqn_i32 y_, Dqn_i32 z_, Dqn_i32 w_): x((Dqn_f32)x_), y((Dqn_f32)y_), z((Dqn_f32)z_), w((Dqn_f32)w_) {} - constexpr Dqn_V4(Dqn_V3 xyz, Dqn_f32 w_) : x(xyz.x), y(xyz.y), z(xyz.z), w(w_) {} - - constexpr bool operator!=(Dqn_V4 other) const { return !(*this == other); } - constexpr bool operator==(Dqn_V4 other) const { return (x == other.x) && (y == other.y) && (z == other.z) && (w == other.w); } - constexpr bool operator>=(Dqn_V4 other) const { return (x >= other.x) && (y >= other.y) && (z >= other.z) && (w >= other.w); } - constexpr bool operator<=(Dqn_V4 other) const { return (x <= other.x) && (y <= other.y) && (z <= other.z) && (w <= other.w); } - constexpr bool operator< (Dqn_V4 other) const { return (x < other.x) && (y < other.y) && (z < other.z) && (w < other.w); } - constexpr bool operator> (Dqn_V4 other) const { return (x > other.x) && (y > other.y) && (z > other.z) && (w > other.w); } - constexpr Dqn_V4 operator- (Dqn_V4 other) const { Dqn_V4 result(x - other.x, y - other.y, z - other.z, w - other.w); return result; } - constexpr Dqn_V4 operator+ (Dqn_V4 other) const { Dqn_V4 result(x + other.x, y + other.y, z + other.z, w + other.w); return result; } - constexpr Dqn_V4 operator* (Dqn_V4 other) const { Dqn_V4 result(x * other.x, y * other.y, z * other.z, w * other.w); return result; } - constexpr Dqn_V4 operator* (Dqn_f32 other) const { Dqn_V4 result(x * other, y * other, z * other, w * other); return result; } - constexpr Dqn_V4 operator* (Dqn_i32 other) const { Dqn_V4 result(x * other, y * other, z * other, w * other); return result; } - constexpr Dqn_V4 operator/ (Dqn_f32 other) const { Dqn_V4 result(x / other, y / other, z / other, w / other); return result; } - constexpr Dqn_V4 &operator*=(Dqn_V4 other) { *this = *this * other; return *this; } - constexpr Dqn_V4 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; } - constexpr Dqn_V4 &operator*=(Dqn_i32 other) { *this = *this * other; return *this; } - constexpr Dqn_V4 &operator-=(Dqn_V4 other) { *this = *this - other; return *this; } - constexpr Dqn_V4 &operator+=(Dqn_V4 other) { *this = *this + other; return *this; } -}; - -struct Dqn_Rect -{ - Dqn_V2 min, max; - Dqn_Rect() = default; - Dqn_Rect(Dqn_V2 min, Dqn_V2 max) : min(min), max(max) {} - Dqn_Rect(Dqn_V2I min, Dqn_V2I max) : min(min), max(max) {} -}; - -struct Dqn_RectI32 -{ - Dqn_V2I min, max; - Dqn_RectI32() = default; - Dqn_RectI32(Dqn_V2I min, Dqn_V2I max) : min(min), max(max) {} -}; - -union Dqn_Mat4 -{ - Dqn_f32 e[16]; - Dqn_V4 row[4]; - Dqn_f32 row_major[4][4]; - Dqn_f32 operator[](Dqn_usize i) const { return e[i]; } -}; - -template int Dqn_MemCmpType(T const *ptr1, T const *ptr2); -template T * Dqn_MemZero(T *src); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_Allocator -// -// ------------------------------------------------------------------------------------------------- -// Custom allocations must include Dqn_AllocateMetadata before the aligned_ptr, see Dqn_AllocateMetadata for more information -enum struct Dqn_Allocator_Type -{ -#if defined(DQN_ALLOCATOR_DEFAULT_TO_NULL) - Null, - Heap, // Malloc, realloc, free -#else - Heap, // Malloc, realloc, free - Null, -#endif - - XHeap, // Malloc realloc, free, crash on failure - Arena, - Custom, -}; - -#define DQN_ALLOCATOR_ALLOCATE_PROC(name) void *name(Dqn_isize size, Dqn_u8 alignment, void *user_context) -#define DQN_ALLOCATOR_REALLOC_PROC(name) void *name(void *old_ptr, Dqn_isize old_size, Dqn_isize new_size, void *user_context) -#define DQN_ALLOCATOR_FREE_PROC(name) void name(void *ptr, void *user_context) -typedef DQN_ALLOCATOR_ALLOCATE_PROC(Dqn_Allocator_AllocateProc); -typedef DQN_ALLOCATOR_REALLOC_PROC(Dqn_Allocator_ReallocProc); -typedef DQN_ALLOCATOR_FREE_PROC(Dqn_Allocator_FreeProc); -struct Dqn_Allocator -{ - Dqn_Allocator_Type type; - union - { - void *user; - struct Dqn_ArenaAllocator *arena; - } context; - - Dqn_isize bytes_allocated; - Dqn_isize total_bytes_allocated; - - Dqn_isize allocations; - Dqn_isize total_allocations; - - // NOTE: Only required if type == Dqn_Allocator_Type::Custom - Dqn_Allocator_AllocateProc *allocate; - Dqn_Allocator_ReallocProc *realloc; - Dqn_Allocator_FreeProc *free; -}; - -Dqn_Allocator inline Dqn_Allocator_InitWithNull(); -Dqn_Allocator inline Dqn_Allocator_InitWithHeap(); -Dqn_Allocator inline Dqn_Allocator_InitWithXHeap(); -Dqn_Allocator inline Dqn_Allocator_InitWithArena(Dqn_ArenaAllocator *arena); -template T * Dqn_Allocator_AllocateType(Dqn_Allocator *allocator, Dqn_isize num); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_AllocatorMetadata -// -// ------------------------------------------------------------------------------------------------- -// Custom Dqn_Allocator implementations must include allocation metadata exactly (aligned_ptr - sizeof(Dqn_AllocatorMetadata)) bytes from the aligned ptr. -struct Dqn_AllocateMetadata -{ - Dqn_u8 alignment; - Dqn_u8 offset; // Subtract offset from aligned ptr to return to the allocation ptr -}; - -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_ArenaAllocator -// -// ------------------------------------------------------------------------------------------------- -struct Dqn_ArenaAllocatorBlock -{ - void *memory; - Dqn_isize size; - Dqn_isize used; - Dqn_ArenaAllocatorBlock *prev; - Dqn_ArenaAllocatorBlock *next; -}; - -Dqn_usize const DQN_MEM_ARENA_DEFAULT_MIN_BLOCK_SIZE = DQN_KILOBYTES(4); -struct Dqn_ArenaAllocator -{ - // NOTE: Configuration (fill once after "Zero Initialisation {}") - Dqn_isize min_block_size; - Dqn_Allocator allocator; - - // NOTE: Read Only - Dqn_ArenaAllocatorBlock *curr_mem_block; - Dqn_ArenaAllocatorBlock *top_mem_block; - Dqn_isize highest_used_mark; - int total_allocated_mem_blocks; -}; - -struct Dqn_ArenaAllocatorRegion -{ - Dqn_ArenaAllocator *arena; - Dqn_ArenaAllocatorBlock *curr_mem_block; - Dqn_isize curr_mem_block_used; - Dqn_ArenaAllocatorBlock *top_mem_block; -}; - -struct Dqn_ArenaAllocatorScopedRegion -{ - Dqn_ArenaAllocatorScopedRegion(Dqn_ArenaAllocator *arena); - ~Dqn_ArenaAllocatorScopedRegion(); - Dqn_ArenaAllocatorRegion region; -}; - -void * Dqn_ArenaAllocator_Allocate(Dqn_ArenaAllocator *arena, Dqn_isize size, Dqn_u8 alignment); -Dqn_b32 Dqn_ArenaAllocator_Reserve(Dqn_ArenaAllocator *arena, Dqn_isize size); -DQN_HEADER_COPY_PROTOTYPE(template T *, Dqn_ArenaAllocator_AllocateType(Dqn_ArenaAllocator *arena, Dqn_isize num)) -{ - auto *result = DQN_CAST(T *)Dqn_ArenaAllocator_Allocate(arena, sizeof(T) * num, alignof(T)); - return result; -} - - -// ------------------------------------------------------------------------------------------------- -// -// NOTE: String -// -// ------------------------------------------------------------------------------------------------- -struct Dqn_String -{ - union { - // NOTE: To appease GCC, Clang can't assign C string literal to char * - // Only UB if you try modify a string originally declared const - char const *str_; - char *str; - }; - - Dqn_isize len; - char const *begin() const { return str; } - char const *end () const { return str + len; } - char *begin() { return str; } - char *end () { return str + len; } -}; -#define DQN_STRING_LITERAL(string) {string, Dqn_CharCountI(string)} - -// ------------------------------------------------------------------------------------------------- -// -// NOTE: String Builder -// -// ------------------------------------------------------------------------------------------------- -struct Dqn_StringBuilderBlock -{ - char *mem; - Dqn_isize size; - Dqn_isize used; - Dqn_StringBuilderBlock *next; -}; - -Dqn_isize constexpr DQN_STRING_BUILDER_MIN_BLOCK_SIZE = DQN_KILOBYTES(4); -template -struct Dqn_StringBuilder -{ - Dqn_Allocator allocator; - char fixed_mem[N]; - Dqn_StringBuilderBlock fixed_mem_block; - Dqn_StringBuilderBlock *last_mem_block; -}; - -// size_required: The length of the string not including the null terminator. -// The necessary length to build the string, it returns the length not including the null-terminator -template Dqn_isize Dqn_StringBuilder_BuildLength(Dqn_StringBuilder const *builder); -template void Dqn_StringBuilder_BuildToDest(Dqn_StringBuilder const *builder, char *dest, Dqn_usize dest_size); -template char * Dqn_StringBuilder_Build(Dqn_StringBuilder *builder, Dqn_Allocator *allocator, Dqn_isize *len = nullptr); -template Dqn_String Dqn_StringBuilder_BuildString(Dqn_StringBuilder *builder, Dqn_Allocator *allocator); -template void Dqn_StringBuilder_VFmtAppend(Dqn_StringBuilder *builder, char const *fmt, va_list va); -template void Dqn_StringBuilder_FmtAppend(Dqn_StringBuilder *builder, char const *fmt, ...); -template void Dqn_StringBuilder_Append(Dqn_StringBuilder *builder, char const *str, Dqn_isize len = -1); -template void Dqn_StringBuilder_AppendString(Dqn_StringBuilder *builder, Dqn_String const string); -template void Dqn_StringBuilder_AppendChar(Dqn_StringBuilder *builder, char ch); -template void Dqn_StringBuilder_Free(Dqn_StringBuilder *builder); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_Slices -// -// ------------------------------------------------------------------------------------------------- -inline Dqn_Slice Dqn_Slice_InitWithArray(T (&array)[N]); -template inline Dqn_Slice Dqn_Slice_Allocate(Dqn_Allocator *allocator, Dqn_isize len); -template inline Dqn_Slice Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, T const *src, Dqn_isize len); -template inline Dqn_Slice Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, Dqn_Slice const src); -template inline Dqn_Slice Dqn_Slice_Copy(Dqn_Allocator *allocator, T const *src, Dqn_isize len); -template inline Dqn_Slice Dqn_Slice_Copy(Dqn_Allocator *allocator, Dqn_Slice const src); -template inline bool Dqn_Slice_Equals(Dqn_Slice const a, Dqn_Slice const b); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_FixedArray -// -// ------------------------------------------------------------------------------------------------- -#define DQN_FIXED_ARRAY_TEMPLATE template -#define DQN_FIXED_ARRAY_TEMPLATE_DECL Dqn_FixedArray -DQN_FIXED_ARRAY_TEMPLATE struct Dqn_FixedArray -{ - T data[MAX_]; - Dqn_isize max = MAX_; - Dqn_isize len; - - T &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, len); return data[i]; } - T *begin () { return data; } - T *end () { return data + len; } - T *operator+ (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, len); return data + i; } - - T const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, i, len); return data[i]; } - T const *begin () const { return data; } - T const *end () const { return data + len; } - T const *operator+ (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, len); return data + i; } -}; - -int Dqn_FixedArray_Capacity(DQN_FIXED_ARRAY_TEMPLATE_DECL *); -DQN_FIXED_ARRAY_TEMPLATE_DECL Dqn_FixedArray_Init(T const *item, int num); -T * Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *items, Dqn_isize num); -T * Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const item); -T * Dqn_FixedArray_Make(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num); -void Dqn_FixedArray_Clear(DQN_FIXED_ARRAY_TEMPLATE_DECL *a); -void Dqn_FixedArray_EraseStable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index); -void Dqn_FixedArray_EraseUnstable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index); -void Dqn_FixedArray_Pop(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num = 1); -T * Dqn_FixedArray_Peek(DQN_FIXED_ARRAY_TEMPLATE_DECL *a); -Dqn_isize Dqn_FixedArray_GetIndex(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *entry); -T * Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, EqualityProc IsEqual); -T * Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T *find); -Dqn_Slice Dqn_FixedArray_Slice(DQN_FIXED_ARRAY_TEMPLATE_DECL *a); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_Array -// -// ------------------------------------------------------------------------------------------------- -template struct Dqn_Array -{ - Dqn_Allocator allocator; - T *data; - Dqn_isize len; - Dqn_isize max; - - T const operator[](Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; } - T operator[](Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; } - T const *begin () const { return data; } - T const *end () const { return data + len; } - T *begin () { return data; } - T *end () { return data + len; } - T const *operator+(Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; } - T *operator+(Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; } -}; - -template Dqn_Array Dqn_Array_InitWithMemory(T *memory, Dqn_isize max, Dqn_isize len = 0); -template Dqn_Array Dqn_Array_InitWithAllocatorNoGrow(Dqn_Allocator *allocator, Dqn_isize max, Dqn_isize len = 0); -template bool Dqn_Array_Reserve(Dqn_Array *a, Dqn_isize size); -template void Dqn_Array_Free(Dqn_Array *a); -template T * Dqn_Array_Add(Dqn_Array *a, T const *items, Dqn_isize num); -template T * Dqn_Array_Add(Dqn_Array *a, T const item); -template T * Dqn_Array_Make(Dqn_Array *a, Dqn_isize num); -template void Dqn_Array_Clear(Dqn_Array *a, bool zero_mem = false); -template void Dqn_Array_EraseStable(Dqn_Array *a, Dqn_isize index); -template void Dqn_Array_EraseUnstable(Dqn_Array *a, Dqn_isize index); -template void Dqn_Array_Pop(Dqn_Array *a, Dqn_isize num); -template T * Dqn_Array_Peek(Dqn_Array *a); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_FixedString -// -// ------------------------------------------------------------------------------------------------- -template -struct Dqn_FixedString -{ - union { char data[MAX_]; char str[MAX_]; char buf[MAX_]; }; - Dqn_isize len; - Dqn_isize max = MAX_; - - Dqn_FixedString() { data[0] = 0; len = 0; } - Dqn_FixedString(char const *fmt, ...) - { - *this = {}; - va_list va; - va_start(va, fmt); - Dqn_FixedString_AppendVFmt(this, fmt, va); - va_end(va); - } - - Dqn_b32 operator==(Dqn_FixedString const &other) const - { - if (len != other.len) return false; - bool result = memcmp(data, other.data, len); - return result; - } - - Dqn_b32 operator!=(Dqn_FixedString const &other) const { return !(*this == other); } - - char const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; } - char &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; } - char const *begin () const { return data; } - char const *end () const { return data + len; } - char *begin () { return data; } - char *end () { return data + len; } -}; - -template int Dqn_FixedString_Capacity(Dqn_FixedString *); -template void Dqn_FixedString_Clear(Dqn_FixedString *str); -template Dqn_b32 Dqn_FixedString_AppendVFmt(Dqn_FixedString *str, char const *fmt, va_list va); -template Dqn_b32 Dqn_FixedString_AppendFmt(Dqn_FixedString *str, char const *fmt, ...); -template Dqn_b32 Dqn_FixedString_Append(Dqn_FixedString *str, char const *src, Dqn_isize len = -1); -template Dqn_String Dqn_FixedString_ToString(Dqn_FixedString const *str); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_U64Str -// -// ------------------------------------------------------------------------------------------------- -struct Dqn_U64Str -{ - // Points to the start of the str in the buffer, not necessarily buf since - // we write into the buffer in reverse - char *str; - char buf[27]; // NOTE(doyle): 27 is the maximum size of Dqn_u64 including commas - int len; -}; - -char * Dqn_U64Str_ToStr(Dqn_u64 val, Dqn_U64Str *result, Dqn_b32 comma_sep); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Logging -// -// ------------------------------------------------------------------------------------------------- -void Dqn_LogV(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, va_list va); -// return: This returns a boolean as a hack so you can combine it in if expressions. I use it for my IF_ASSERT macro -Dqn_b32 Dqn_Log(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, ...); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_AllocateMetadata -// -// ------------------------------------------------------------------------------------------------- -char * Dqn_AllocateMetadata_Init(void *ptr, Dqn_u8 alignment); -// TODO(doyle): Use bit masks and only support POT. That approach reflects how computers work better. -Dqn_AllocateMetadata Dqn_AllocateMetadata_Get(void *ptr); -char * Dqn_AllocateMetadata_GetRawPointer(void *ptr); -Dqn_isize Dqn_AllocateMetadata_SizeRequired(Dqn_isize size, Dqn_u8 alignment); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_Allocator -// -// ------------------------------------------------------------------------------------------------- -void * Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_isize size, Dqn_u8 alignment); -void * Dqn_Allocator_Realloc(Dqn_Allocator *allocator, void *old_ptr, Dqn_isize old_size, Dqn_isize new_size); -void Dqn_Allocator_Free(Dqn_Allocator *allocator, void *ptr); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_ArenaAllocator -// -// ------------------------------------------------------------------------------------------------- -void * Dqn_ArenaAllocator_Allocate(Dqn_ArenaAllocator *arena, Dqn_isize size, Dqn_u8 alignment); -void Dqn_ArenaAllocator_Free(Dqn_ArenaAllocator *arena); -Dqn_b32 Dqn_ArenaAllocator_Reserve(Dqn_ArenaAllocator *arena, Dqn_isize size); -Dqn_ArenaAllocator Dqn_ArenaAllocator_InitWithAllocator(Dqn_Allocator allocator, Dqn_isize size); -Dqn_ArenaAllocator Dqn_ArenaAllocator_InitWithMemory(void *memory, Dqn_isize size); -void Dqn_ArenaAllocator_ResetUsage(Dqn_ArenaAllocator *arena, Dqn_ZeroMem zero_mem); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_Asprintf (Allocate Sprintf) -// -// ------------------------------------------------------------------------------------------------- -// return: The allocated string. If allocation fails, the str ptr returned is nullptr and length is set o the size required, NOT INCLUDING the null terminator. -Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va); -Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Vectors -// -// ------------------------------------------------------------------------------------------------- -Dqn_V2I Dqn_V2_ToV2I(Dqn_V2 a); -Dqn_V2 Dqn_V2_Max(Dqn_V2 a, Dqn_V2 b); -Dqn_V2 Dqn_V2_Abs(Dqn_V2 a); -Dqn_f32 Dqn_V2_Dot(Dqn_V2 a, Dqn_V2 b); -Dqn_f32 Dqn_V2_LengthSq(Dqn_V2 a, Dqn_V2 b); -Dqn_V2 Dqn_V2_Normalise(Dqn_V2 a); -Dqn_V2 Dqn_V2_Perpendicular(Dqn_V2 a); -Dqn_f32 Dqn_V4_Dot(Dqn_V4 const *a, Dqn_V4 const *b); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Rect -// -// ------------------------------------------------------------------------------------------------- -Dqn_Rect Dqn_Rect_InitFromPosAndSize(Dqn_V2 pos, Dqn_V2 size); -Dqn_V2 Dqn_Rect_Center(Dqn_Rect rect); -Dqn_b32 Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p); -Dqn_b32 Dqn_Rect_ContainsRect(Dqn_Rect a, Dqn_Rect b); -Dqn_V2 Dqn_Rect_Size(Dqn_Rect rect); -Dqn_Rect Dqn_Rect_Move(Dqn_Rect src, Dqn_V2 move_amount); -Dqn_Rect Dqn_Rect_Intersection(Dqn_Rect a, Dqn_Rect b); -Dqn_Rect Dqn_Rect_Union(Dqn_Rect a, Dqn_Rect b); -Dqn_Rect Dqn_Rect_FromRectI32(Dqn_RectI32 a); -Dqn_V2I Dqn_RectI32_Size(Dqn_RectI32 rect); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Math Utils -// -// ------------------------------------------------------------------------------------------------- -Dqn_V2 Dqn_LerpV2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b); -Dqn_f32 Dqn_LerpF32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_Mat4 -// -// ------------------------------------------------------------------------------------------------- -Dqn_Mat4 Dqn_Mat4_Identity(); -Dqn_Mat4 Dqn_Mat4_Scale3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z); -Dqn_Mat4 Dqn_Mat4_ScaleV3(Dqn_V3 vec); -Dqn_Mat4 Dqn_Mat4_Translate3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z); -Dqn_Mat4 Dqn_Mat4_TranslateV3(Dqn_V3 vec); -Dqn_Mat4 operator*(Dqn_Mat4 const &a, Dqn_Mat4 const &b); -Dqn_V4 operator*(Dqn_Mat4 const &mat, Dqn_V4 const &vec); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Helper Functions -// -// ------------------------------------------------------------------------------------------------- -void Dqn_Bit_UnsetInplace(Dqn_u32 *flags, Dqn_u32 bitfield); -void Dqn_Bit_SetInplace(Dqn_u32 *flags, Dqn_u32 bitfield); -Dqn_b32 Dqn_Bit_IsSet(Dqn_u32 bits, Dqn_u32 bits_to_set); -Dqn_b32 Dqn_Bit_IsNotSet(Dqn_u32 bits, Dqn_u32 bits_to_check); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Safe Arithmetic -// -// ------------------------------------------------------------------------------------------------- -Dqn_i64 Dqn_Safe_AddI64(Dqn_i64 a, Dqn_i64 b); -Dqn_i64 Dqn_Safe_MulI64(Dqn_i64 a, Dqn_i64 b); -Dqn_u64 Dqn_Safe_AddU64(Dqn_u64 a, Dqn_u64 b); -Dqn_u64 Dqn_Safe_SubU64(Dqn_u64 a, Dqn_u64 b); -Dqn_u32 Dqn_Safe_SubU32(Dqn_u32 a, Dqn_u32 b); -Dqn_u64 Dqn_Safe_MulU64(Dqn_u64 a, Dqn_u64 b); -int Dqn_Safe_TruncateISizeToInt(Dqn_isize val); -Dqn_i32 Dqn_Safe_TruncateISizeToI32(Dqn_isize val); -Dqn_i8 Dqn_Safe_TruncateISizeToI8(Dqn_isize val); -Dqn_u32 Dqn_Safe_TruncateUSizeToU32(Dqn_u64 val); -int Dqn_Safe_TruncateUSizeToI32(Dqn_usize val); -int Dqn_Safe_TruncateUSizeToInt(Dqn_usize val); -Dqn_isize Dqn_Safe_TruncateUSizeToISize(Dqn_usize val); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Char Helpers -// -// ------------------------------------------------------------------------------------------------- -Dqn_b32 Dqn_Char_IsAlpha(char ch); -Dqn_b32 Dqn_Char_IsDigit(char ch); -Dqn_b32 Dqn_Char_IsAlphaNum(char ch); -Dqn_b32 Dqn_Char_IsWhitespace(char ch); -char Dqn_Char_ToLower(char ch); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: String Helpers -// -// ------------------------------------------------------------------------------------------------- -Dqn_b32 Dqn_Str_Equals(char const *a, char const *b, Dqn_isize a_len = -1, Dqn_isize b_len = -1); -char const * Dqn_Str_FindMulti(char const *buf, char const *find_list[], Dqn_isize const *find_string_lens, Dqn_isize find_len, Dqn_isize *match_index, Dqn_isize buf_len = -1); -char const * Dqn_Str_Find(char const *buf, char const *find, Dqn_isize buf_len = -1, Dqn_isize find_len = -1); -Dqn_b32 Dqn_Str_Match(char const *src, char const *find, int find_len); -char const * Dqn_Str_SkipToChar(char const *src, char ch); -char const * Dqn_Str_SkipToNextAlphaNum(char const *src); -char const * Dqn_Str_SkipToNextDigit(char const *src); -char const * Dqn_Str_SkipToNextChar(char const *src); -char const * Dqn_Str_SkipToNextWord(char const *src); -char const * Dqn_Str_SkipToNextWhitespace(char const *src); -char const * Dqn_Str_SkipWhitespace(char const *src); -char const * Dqn_Str_SkipToCharInPlace(char const **src, char ch); -char const * Dqn_Str_SkipToNextAlphaNumInPlace(char const **src); -char const * Dqn_Str_SkipToNextCharInPlace(char const **src); -char const * Dqn_Str_SkipToNextWhitespaceInPlace(char const **src); -char const * Dqn_Str_SkipToNextWordInPlace(char const **src); -char const * Dqn_Str_SkipWhitespaceInPlace(char const **src); -Dqn_u64 Dqn_Str_ToU64(char const *buf, int len = -1); -Dqn_i64 Dqn_Str_ToI64(char const *buf, int len = -1); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Dqn_String -// -// ------------------------------------------------------------------------------------------------- -Dqn_b32 Dqn_String_Compare(Dqn_String const lhs, Dqn_String const rhs); -Dqn_b32 Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs); -Dqn_String Dqn_String_Copy(Dqn_Allocator *allocator, Dqn_String const src); -Dqn_String Dqn_String_TrimWhitespaceAround(Dqn_String src); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: File -// -// ------------------------------------------------------------------------------------------------- -char * Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_isize *file_size); -// ------------------------------------------------------------------------------------------------- -// -// NOTE: Utils -// -// ------------------------------------------------------------------------------------------------- -char * Dqn_EpochTimeToDate(Dqn_i64 timestamp, char *buf, Dqn_isize buf_len); diff --git a/Code/Dqn_UnitTests.cpp b/Code/Dqn_UnitTests.cpp index 235d0c0..1c714fa 100644 --- a/Code/Dqn_UnitTests.cpp +++ b/Code/Dqn_UnitTests.cpp @@ -1,4 +1,5 @@ #define DQN_USE_PRIMITIVE_TYPEDEFS +#define DQN_NO_ASSERT #define DQN_IMPLEMENTATION #include "Dqn.h" @@ -13,11 +14,11 @@ struct TestState struct TestingState { - int num_tests_in_group; - int num_tests_ok_in_group; - TestState test; - Dqn_ArenaAllocator arena_; - Dqn_Allocator allocator; + int num_tests_in_group; + int num_tests_ok_in_group; + TestState test; + Dqn_ArenaAllocator arena_; + Dqn_Allocator allocator; }; #define ANSI_COLOR_RED "\x1b[31m" @@ -106,7 +107,7 @@ void TestState_PrintResult(TestState const *result) } } -DQN_FILE_SCOPE void UnitTests() +static void UnitTests() { TestingState testing_state = {}; // --------------------------------------------------------------------------------------------- @@ -141,7 +142,7 @@ DQN_FILE_SCOPE void UnitTests() { TEST_START_SCOPE(testing_state, "ArenaAllocator - Allocate Small"); - Dqn_ArenaAllocator arena = {}; + Dqn_ArenaAllocator arena = {}; arena.allocator = Dqn_Allocator_InitWithHeap(); Dqn_Allocator allocator = Dqn_Allocator_InitWithArena(&arena); char constexpr EXPECT[] = "hello_world"; @@ -154,10 +155,10 @@ DQN_FILE_SCOPE void UnitTests() // NOTE: Alignment Test { - Dqn_u8 const ALIGNMENT3 = 3; + Dqn_u8 const ALIGNMENT3 = 4; Dqn_u8 const NUM_BYTES = sizeof(Dqn_u32); { - TEST_START_SCOPE(testing_state, "HeapAllocator - Align to 3 bytes"); + TEST_START_SCOPE(testing_state, "HeapAllocator - Align to 32 bytes"); Dqn_Allocator allocator = Dqn_Allocator_InitWithHeap(); auto *buf = DQN_CAST(Dqn_u32 *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3); DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); }; @@ -166,7 +167,7 @@ DQN_FILE_SCOPE void UnitTests() } { - TEST_START_SCOPE(testing_state, "XHeapAllocator - Align to 3 bytes"); + TEST_START_SCOPE(testing_state, "XHeapAllocator - Align to 32 bytes"); Dqn_Allocator allocator = Dqn_Allocator_InitWithXHeap(); auto *buf = DQN_CAST(Dqn_u32 *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3); DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); }; @@ -175,7 +176,7 @@ DQN_FILE_SCOPE void UnitTests() } { - TEST_START_SCOPE(testing_state, "ArenaAllocator - Align to 3 bytes"); + TEST_START_SCOPE(testing_state, "ArenaAllocator - Align to 32 bytes"); Dqn_ArenaAllocator arena = {}; Dqn_Allocator allocator = Dqn_Allocator_InitWithArena(&arena); auto *buf = DQN_CAST(Dqn_u32 *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3); @@ -184,17 +185,17 @@ DQN_FILE_SCOPE void UnitTests() } } - // NOTE: Dqn_AllocateMetadata tests + // NOTE: Dqn_PointerMetadata tests { - Dqn_u8 const ALIGNMENT3 = 3; + Dqn_u8 const ALIGNMENT3 = 4; Dqn_u8 const NUM_BYTES = 4; - Dqn_u8 const MAX_OFFSET = (ALIGNMENT3 - 1) + sizeof(Dqn_AllocateMetadata); + Dqn_u8 const MAX_OFFSET = (ALIGNMENT3 - 1) + sizeof(Dqn_PointerMetadata); { TEST_START_SCOPE(testing_state, "HeapAllocator - Allocation metadata initialised"); Dqn_Allocator allocator = Dqn_Allocator_InitWithHeap(); char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3); DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); }; - Dqn_AllocateMetadata metadata = Dqn_AllocateMetadata_Get(buf); + Dqn_PointerMetadata metadata = Dqn_PointerMetadata_Get(buf); TEST_EXPECT_MSG(testing_state, metadata.alignment == ALIGNMENT3, "metadata.alignment: %u, ALIGNMENT3: %u", metadata.alignment, ALIGNMENT3); TEST_EXPECT_MSG(testing_state, metadata.offset <= MAX_OFFSET, "metadata.offset: %u, MAX_OFFSET: %u", metadata.offset, MAX_OFFSET); } @@ -204,18 +205,7 @@ DQN_FILE_SCOPE void UnitTests() Dqn_Allocator allocator = Dqn_Allocator_InitWithXHeap(); char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3); DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); }; - Dqn_AllocateMetadata metadata = Dqn_AllocateMetadata_Get(buf); - TEST_EXPECT_MSG(testing_state, metadata.alignment == ALIGNMENT3, "metadata.alignment: %u, ALIGNMENT3: %u", metadata.alignment, ALIGNMENT3); - TEST_EXPECT_MSG(testing_state, metadata.offset <= MAX_OFFSET, "metadata.offset: %u, MAX_OFFSET: %u", metadata.offset, MAX_OFFSET); - } - - { - TEST_START_SCOPE(testing_state, "ArenaAllocator - Allocation metadata initialised"); - Dqn_ArenaAllocator arena = {}; - Dqn_Allocator allocator = Dqn_Allocator_InitWithArena(&arena); - char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3); - DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); }; - Dqn_AllocateMetadata metadata = Dqn_AllocateMetadata_Get(buf); + Dqn_PointerMetadata metadata = Dqn_PointerMetadata_Get(buf); TEST_EXPECT_MSG(testing_state, metadata.alignment == ALIGNMENT3, "metadata.alignment: %u, ALIGNMENT3: %u", metadata.alignment, ALIGNMENT3); TEST_EXPECT_MSG(testing_state, metadata.offset <= MAX_OFFSET, "metadata.offset: %u, MAX_OFFSET: %u", metadata.offset, MAX_OFFSET); } diff --git a/readme.md b/readme.md index 5e118c2..bfd4bfc 100644 --- a/readme.md +++ b/readme.md @@ -1,53 +1,2 @@ # Dqn -Personal utility library. - -## DqnHeader -A simple C++ introspection metaprogram designed as a prebuild step and generates a summary of function prototypes and comments in a header file based on annotations. It is not designed to be used as a header file for compilation and will most likely fail syntax rules if tried. - -The generated file is written to stdout. - -### Build -Build DqnHeader by defining `DQN_HEADER_IMPLEMENTATION` before compiling and execute it as follows - -`DqnHeader.exe SourceCode.h > GeneratedFile.h` - -### Usage -Include `DqnHeader.h` in a file and use the macros, annotations as described. - * Extract function prototypes using the `DQN_HEADER_COPY_PROTOTYPE` macro - * Copy comments by writing comments with `// @` as the prefix - * Copy many lines of code by enclosing it in `DQN_HEADER_COPY_BEGIN` and `DQN_HEADER_COPY_END` macros - -``` -#include "DqnHeader.h" - -// @ ptr1: Pointer to the first block of memory -// @ ptr2: Pointer to the second block of memory -// @ num_bytes: The number of bytes to compare in both blocks of memory -DQN_HEADER_COPY_PROTOTYPE(int, Dqn_MemCmp(void const *ptr1, void const *ptr2, size_t num_bytes)) -{ - int result = memcmp(ptr1, ptr2, num_bytes); - return result; -} - -DQN_HEADER_COPY_BEGIN -struct HelloWorld -{ - int foo, bar; -}; -DQN_HEADER_COPY_END - -``` - -Which generates the following output - -``` -// ptr1: Pointer to the first block of memory -// ptr2: Pointer to the second block of memory -// num_bytes: The number of bytes to compare in both blocks of memory -int Dqn_MemCmp(void const *ptr1, void const *ptr2, size_t num_bytes); -struct HelloWorld -{ - int foo, bar; -}; -``` - +Personal utility library that provides allocator aware data structures, custom memory allocators and various miscellaneous helpers.