Do massive overhaul and simplification of DN

This commit is contained in:
doylet 2026-03-07 20:40:16 +11:00
parent ad019541a4
commit 19df3b75ce
53 changed files with 3880 additions and 5101 deletions

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,174 @@
#include "../dn.h" #include "../dn.h"
#endif #endif
// NOTE: Compiler identification
// Warning! Order is important here, clang-cl on Windows defines _MSC_VER
#if defined(_MSC_VER)
#if defined(__clang__)
#define DN_COMPILER_CLANG_CL
#define DN_COMPILER_CLANG
#else
#define DN_COMPILER_MSVC
#endif
#elif defined(__clang__)
#define DN_COMPILER_CLANG
#elif defined(__GNUC__)
#define DN_COMPILER_GCC
#endif
// NOTE: __has_feature
// MSVC for example does not support the feature detection macro for instance so we compile it out
#if defined(__has_feature)
#define DN_HAS_FEATURE(expr) __has_feature(expr)
#else
#define DN_HAS_FEATURE(expr) 0
#endif
// NOTE: __has_builtin
// MSVC for example does not support the feature detection macro for instance so we compile it out
#if defined(__has_builtin)
#define DN_HAS_BUILTIN(expr) __has_builtin(expr)
#else
#define DN_HAS_BUILTIN(expr) 0
#endif
// NOTE: Warning suppression macros
#if defined(DN_COMPILER_MSVC)
#define DN_MSVC_WARNING_PUSH __pragma(warning(push))
#define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__))
#define DN_MSVC_WARNING_POP __pragma(warning(pop))
#else
#define DN_MSVC_WARNING_PUSH
#define DN_MSVC_WARNING_DISABLE(...)
#define DN_MSVC_WARNING_POP
#endif
#if defined(DN_COMPILER_CLANG) || defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG_CL)
#define DN_GCC_WARNING_PUSH _Pragma("GCC diagnostic push")
#define DN_GCC_WARNING_DISABLE_HELPER_0(x) #x
#define DN_GCC_WARNING_DISABLE_HELPER_1(y) DN_GCC_WARNING_DISABLE_HELPER_0(GCC diagnostic ignored #y)
#define DN_GCC_WARNING_DISABLE(warning) _Pragma(DN_GCC_WARNING_DISABLE_HELPER_1(warning))
#define DN_GCC_WARNING_POP _Pragma("GCC diagnostic pop")
#else
#define DN_GCC_WARNING_PUSH
#define DN_GCC_WARNING_DISABLE(...)
#define DN_GCC_WARNING_POP
#endif
// NOTE: Host OS identification
#if defined(_WIN32)
#define DN_OS_WIN32
#elif defined(__gnu_linux__) || defined(__linux__)
#define DN_OS_UNIX
#endif
// NOTE: Platform identification
#if !defined(DN_PLATFORM_EMSCRIPTEN) && \
!defined(DN_PLATFORM_POSIX) && \
!defined(DN_PLATFORM_WIN32)
#if defined(__aarch64__) || defined(_M_ARM64)
#define DN_PLATFORM_ARM64
#elif defined(__EMSCRIPTEN__)
#define DN_PLATFORM_EMSCRIPTEN
#elif defined(DN_OS_WIN32)
#define DN_PLATFORM_WIN32
#else
#define DN_PLATFORM_POSIX
#endif
#endif
// NOTE: Windows crap
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#if defined(_CRT_SECURE_NO_WARNINGS)
#define DN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED
#else
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
// NOTE: Force Inline
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#define DN_FORCE_INLINE __forceinline
#else
#define DN_FORCE_INLINE inline __attribute__((always_inline))
#endif
// NOTE: Function/Variable Annotations
#if defined(DN_STATIC_API)
#define DN_API static
#else
#define DN_API
#endif
// NOTE: C/CPP Literals
// Declare struct literals that work in both C and C++ because the syntax is different between
// languages.
#if 0
struct Foo { int a; }
struct Foo foo = DN_LITERAL(Foo){32}; // Works on both C and C++
#endif
#if defined(__cplusplus)
#define DN_Literal(T) T
#else
#define DN_Literal(T) (T)
#endif
// NOTE: Thread Locals
#if defined(__cplusplus)
#define DN_THREAD_LOCAL thread_local
#else
#define DN_THREAD_LOCAL _Thread_local
#endif
// NOTE: C variadic argument annotations
// TODO: Other compilers
#if defined(DN_COMPILER_MSVC)
#define DN_FMT_ATTRIB _Printf_format_string_
#else
#define DN_FMT_ATTRIB
#endif
// NOTE: Type Cast
#define DN_Cast(val) (val)
// NOTE: Zero initialisation macro
#if defined(__cplusplus)
#define DN_ZeroInit {}
#else
#define DN_ZeroInit {0}
#endif
// NOTE: Address sanitizer
#if !defined(DN_ASAN_POISON)
#define DN_ASAN_POISON 0
#endif
#if !defined(DN_ASAN_VET_POISON)
#define DN_ASAN_VET_POISON 0
#endif
#define DN_ASAN_POISON_ALIGNMENT 8
#if !defined(DN_ASAN_POISON_GUARD_SIZE)
#define DN_ASAN_POISON_GUARD_SIZE 128
#endif
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#include <sanitizer/asan_interface.h>
#endif
// NOTE: Macros // NOTE: Macros
#define DN_Stringify(x) #x #define DN_Stringify(x) #x
#define DN_TokenCombine2(x, y) x ## y #define DN_TokenCombine2(x, y) x ## y
#define DN_TokenCombine(x, y) DN_TokenCombine2(x, y) #define DN_TokenCombine(x, y) DN_TokenCombine2(x, y)
#if defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64)
#define DN_64_BIT
#else
#define DN_32_BIT
#endif
#include <stdarg.h> // va_list #include <stdarg.h> // va_list
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@ -70,8 +233,8 @@
// NOTE: Math // NOTE: Math
#define DN_PiF32 3.14159265359f #define DN_PiF32 3.14159265359f
#define DN_DegreesToRadians(degrees) ((degrees) * (DN_PI / 180.0f)) #define DN_DegreesToRadsF32(degrees) ((degrees) * (DN_PiF32 / 180.0f))
#define DN_RadiansToDegrees(radians) ((radians) * (180.f * DN_PI)) #define DN_RadsToDegreesF32(radians) ((radians) * (180.f * DN_PiF32))
#define DN_Abs(val) (((val) < 0) ? (-(val)) : (val)) #define DN_Abs(val) (((val) < 0) ? (-(val)) : (val))
#define DN_Max(a, b) (((a) > (b)) ? (a) : (b)) #define DN_Max(a, b) (((a) > (b)) ? (a) : (b))
@ -138,6 +301,23 @@
((((u64) >> 8) & 0xFF) << 48) | \ ((((u64) >> 8) & 0xFF) << 48) | \
((((u64) >> 0) & 0xFF) << 56)) ((((u64) >> 0) & 0xFF) << 56))
// NOTE: Helper macros to declare an array data structure for a given `Type`
#define DN_DArrayStructDecl(Type) \
struct Type##Array \
{ \
Type* data; \
DN_USize count; \
DN_USize max; \
}
#define DN_FixedArrayStructDecl(Type, capacity) \
struct Type##x##capacity##Array \
{ \
Type data[capacity]; \
DN_USize count; \
DN_USize max; \
}
// NOTE: Types // NOTE: Types
typedef intptr_t DN_ISize; typedef intptr_t DN_ISize;
typedef uintptr_t DN_USize; typedef uintptr_t DN_USize;
@ -178,6 +358,12 @@ struct DN_Str8
DN_USize size; // The number of bytes in the string DN_USize size; // The number of bytes in the string
}; };
struct DN_Str8Slice
{
DN_Str8 *data;
DN_USize count;
};
struct DN_Str8x16 { char data[16]; DN_USize size; }; struct DN_Str8x16 { char data[16]; DN_USize size; };
struct DN_Str8x32 { char data[32]; DN_USize size; }; struct DN_Str8x32 { char data[32]; DN_USize size; };
struct DN_Str8x64 { char data[64]; DN_USize size; }; struct DN_Str8x64 { char data[64]; DN_USize size; };
@ -314,7 +500,7 @@ struct DN_DeferHelper
#error "Compiler not supported" #error "Compiler not supported"
#endif #endif
#if defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) #if defined(DN_64_BIT)
#define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU64(value) #define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU64(value)
#else #else
#define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU32(value) #define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU32(value)
@ -516,6 +702,7 @@ enum DN_ArenaFlags_
DN_ArenaFlags_NoPoison = 1 << 1, DN_ArenaFlags_NoPoison = 1 << 1,
DN_ArenaFlags_NoAllocTrack = 1 << 2, DN_ArenaFlags_NoAllocTrack = 1 << 2,
DN_ArenaFlags_AllocCanLeak = 1 << 3, DN_ArenaFlags_AllocCanLeak = 1 << 3,
DN_ArenaFlags_SimAlloc = 1 << 4,
// NOTE: Internal flags. Do not use // NOTE: Internal flags. Do not use
DN_ArenaFlags_UserBuffer = 1 << 4, DN_ArenaFlags_UserBuffer = 1 << 4,
@ -823,6 +1010,172 @@ struct DN_Profiler
DN_F64 frame_avg_tsc; DN_F64 frame_avg_tsc;
}; };
enum DN_ErrSinkMode
{
DN_ErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
DN_ErrSinkMode_DebugBreakOnErrorLog, // Debug break (int3) when error is encountered and the sink is ended by the 'end and log' functions.
DN_ErrSinkMode_ExitOnError, // When an error is encountered, exit the program with the error code of the error that was caught.
};
struct DN_ErrSinkMsg
{
DN_I32 error_code;
DN_Str8 msg;
DN_CallSite call_site;
DN_ErrSinkMsg *next;
DN_ErrSinkMsg *prev;
};
struct DN_ErrSinkNode
{
DN_CallSite call_site; // Call site that the node was created
DN_ErrSinkMode mode; // Controls how the sink behaves when an error is registered onto the sink.
DN_ErrSinkMsg *msg_sentinel; // List of error messages accumulated for the current scope
DN_U64 arena_pos; // Position to reset the arena when the scope is ended
};
struct DN_ErrSink
{
DN_Arena* arena; // Dedicated allocator from the thread's local storage
DN_ErrSinkNode stack[128]; // Each entry contains errors accumulated between a [begin, end] region of the active sink.
DN_USize stack_size;
};
struct DN_TCScratch
{
DN_Arena* arena;
DN_ArenaTempMem temp_mem;
DN_B32 destructed;
};
#if defined(__cplusplus)
struct DN_TCScratchCpp
{
DN_TCScratchCpp(DN_Arena **conflicts, DN_USize count);
~DN_TCScratchCpp();
DN_TCScratch data;
};
#endif
struct DN_TCInitArgs
{
DN_U64 main_reserve;
DN_U64 main_commit;
DN_U64 temp_reserve;
DN_U64 temp_commit;
DN_U64 err_sink_reserve;
DN_U64 err_sink_commit;
};
struct DN_TCCore // (T)hread (C)ontext sitting in thread-local storage
{
DN_Str8x64 name;
DN_U64 thread_id;
DN_CallSite call_site;
DN_Arena main_arena_;
DN_Arena temp_a_arena_;
DN_Arena temp_b_arena_;
DN_Arena err_sink_arena_;
DN_Arena* main_arena;
DN_Arena* temp_a_arena;
DN_Arena* temp_b_arena;
DN_ErrSink err_sink;
DN_Arena* frame_arena;
};
struct DN_PCG32 { DN_U64 state; };
struct DN_MurmurHash3 { DN_U64 e[2]; };
enum DN_LogType
{
DN_LogType_Debug,
DN_LogType_Info,
DN_LogType_Warning,
DN_LogType_Error,
DN_LogType_Count,
};
enum DN_LogBold
{
DN_LogBold_No,
DN_LogBold_Yes,
};
struct DN_LogStyle
{
DN_LogBold bold;
bool colour;
DN_U8 r, g, b;
};
struct DN_LogTypeParam
{
bool is_u32_enum;
DN_U32 u32;
DN_Str8 str8;
};
enum DN_LogColourType
{
DN_LogColourType_Fg,
DN_LogColourType_Bg,
};
struct DN_LogDate
{
DN_U16 year;
DN_U8 month;
DN_U8 day;
DN_U8 hour;
DN_U8 minute;
DN_U8 second;
};
struct DN_LogPrefixSize
{
DN_USize size;
DN_USize padding;
};
struct DN_StackTraceFrame
{
DN_U64 address;
DN_U64 line_number;
DN_Str8 file_name;
DN_Str8 function_name;
};
struct DN_StackTraceFrameSlice
{
DN_StackTraceFrame *data;
DN_USize count;
};
struct DN_StackTraceRawFrame
{
void *process;
DN_U64 base_addr;
};
struct DN_StackTraceWalkResult
{
void *process; // [Internal] Windows handle to the process
DN_U64 *base_addr; // The addresses of the functions in the stack trace
DN_U16 size; // The number of `base_addr`'s stored from the walk
};
struct DN_StackTraceWalkResultIterator
{
DN_StackTraceRawFrame raw_frame;
DN_U16 index;
};
typedef void DN_LogEmitFromTypeFVFunc(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
#if !defined(DN_STB_SPRINTF_HEADER_ONLY) #if !defined(DN_STB_SPRINTF_HEADER_ONLY)
#define STB_SPRINTF_IMPLEMENTATION #define STB_SPRINTF_IMPLEMENTATION
#define STB_SPRINTF_STATIC #define STB_SPRINTF_STATIC
@ -847,6 +1200,9 @@ DN_API bool DN_MemEq (void const *lhs, DN
DN_API DN_U64 DN_AtomicSetValue64 (DN_U64 volatile *target, DN_U64 value); DN_API DN_U64 DN_AtomicSetValue64 (DN_U64 volatile *target, DN_U64 value);
DN_API DN_U32 DN_AtomicSetValue32 (DN_U32 volatile *target, DN_U32 value); DN_API DN_U32 DN_AtomicSetValue32 (DN_U32 volatile *target, DN_U32 value);
DN_API DN_USize DN_AlignUpPowerOfTwoUSize (DN_USize val);
DN_API DN_U64 DN_AlignUpPowerOfTwoU64 (DN_U64 val);
DN_API DN_U32 DN_AlignUpPowerOfTwoU32 (DN_U32 val);
DN_API DN_CPUIDResult DN_CPUID (DN_CPUIDArgs args); DN_API DN_CPUIDResult DN_CPUID (DN_CPUIDArgs args);
DN_API DN_USize DN_CPUHasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size); DN_API DN_USize DN_CPUHasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size);
@ -950,7 +1306,7 @@ DN_API bool DN_ArenaOwnsPtr (DN_Arena const *are
DN_API DN_Str8x64 DN_ArenaInfoStr8x64 (DN_ArenaInfo info); DN_API DN_Str8x64 DN_ArenaInfoStr8x64 (DN_ArenaInfo info);
DN_API DN_ArenaStats DN_ArenaSumStatsArray (DN_ArenaStats const *array, DN_USize size); DN_API DN_ArenaStats DN_ArenaSumStatsArray (DN_ArenaStats const *array, DN_USize size);
DN_API DN_ArenaStats DN_ArenaSumStats (DN_ArenaStats lhs, DN_ArenaStats rhs); DN_API DN_ArenaStats DN_ArenaSumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
DN_API DN_ArenaStats DN_ArenaSumArenaArrayToStats(DN_Arena const *array, DN_USize size); DN_API DN_ArenaStats DN_ArenaSumArenaArrayToStats (DN_Arena const *array, DN_USize size);
DN_API DN_ArenaTempMem DN_ArenaTempMemBegin (DN_Arena *arena); DN_API DN_ArenaTempMem DN_ArenaTempMemBegin (DN_Arena *arena);
DN_API void DN_ArenaTempMemEnd (DN_ArenaTempMem mem); DN_API void DN_ArenaTempMemEnd (DN_ArenaTempMem mem);
#define DN_ArenaNew(arena, T, zmem) (T *)DN_ArenaAlloc(arena, sizeof(T), alignof(T), zmem) #define DN_ArenaNew(arena, T, zmem) (T *)DN_ArenaAlloc(arena, sizeof(T), alignof(T), zmem)
@ -975,6 +1331,43 @@ DN_API void * DN_PoolCopy (DN_Pool *pool, void
#define DN_PoolNewCopy(pool, T, src) (T *)DN_PoolCopy (pool, (src), sizeof(T), alignof(T)) #define DN_PoolNewCopy(pool, T, src) (T *)DN_PoolCopy (pool, (src), sizeof(T), alignof(T))
#define DN_PoolNewArrayCopy(pool, T, src, count) (T *)DN_PoolCopy (pool, (src), sizeof(T) * (count), alignof(T)) #define DN_PoolNewArrayCopy(pool, T, src, count) (T *)DN_PoolCopy (pool, (src), sizeof(T) * (count), alignof(T))
DN_API DN_ErrSink* DN_ErrSinkBegin_ (DN_ErrSink *err, DN_ErrSinkMode mode, DN_CallSite call_site);
#define DN_ErrSinkBegin(err, mode) DN_ErrSinkBegin_(err, mode, DN_CALL_SITE)
#define DN_ErrSinkBeginDefault(err) DN_ErrSinkBegin(err, DN_ErrSinkMode_Nil)
DN_API bool DN_ErrSinkHasError (DN_ErrSink *err);
DN_API DN_ErrSinkMsg* DN_ErrSinkEnd (DN_Arena *arena, DN_ErrSink *err);
DN_API DN_Str8 DN_ErrSinkEndStr8 (DN_Arena *arena, DN_ErrSink *err);
DN_API void DN_ErrSinkEndIgnore (DN_ErrSink *err);
DN_API bool DN_ErrSinkEndLogError_ (DN_ErrSink *err, DN_CallSite call_site, DN_Str8 msg);
#define DN_ErrSinkEndLogError(err, err_msg) DN_ErrSinkEndLogError_(err, DN_CALL_SITE, err_msg)
DN_API bool DN_ErrSinkEndLogErrorFV_ (DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
#define DN_ErrSinkEndLogErrorFV(err, fmt, args) DN_ErrSinkEndLogErrorFV_(err, DN_CALL_SITE, fmt, args)
DN_API bool DN_ErrSinkEndLogErrorF_ (DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_ErrSinkEndLogErrorF(err, fmt, ...) DN_ErrSinkEndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__)
DN_API void DN_ErrSinkEndExitIfErrorF_ (DN_ErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_ErrSinkEndExitIfErrorF(err, exit_val, fmt, ...) DN_ErrSinkEndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__)
DN_API void DN_ErrSinkEndExitIfErrorFV_ (DN_ErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args);
#define DN_ErrSinkEndExitIfErrorFV(err, exit_val, fmt, args) DN_ErrSinkEndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args)
DN_API void DN_ErrSinkAppendFV_ (DN_ErrSink *err, DN_U32 error_code, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
#define DN_ErrSinkAppendFV(error, error_code, fmt, args) DN_ErrSinkAppendFV_(error, error_code, DN_CALL_SITE, fmt, args)
DN_API void DN_ErrSinkAppendF_ (DN_ErrSink *err, DN_U32 error_code, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_ErrSinkAppendF(error, error_code, fmt, ...) DN_ErrSinkAppendF_(error, error_code, DN_CALL_SITE, fmt, ##__VA_ARGS__)
DN_API void DN_TCInit (DN_TCCore *tc, DN_U64 thread_id, DN_Arena *main_arena, DN_Arena *temp_a_arena, DN_Arena *temp_b_arena, DN_Arena *err_sink_arena);
DN_API void DN_TCInitFromMemFuncs (DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_ArenaMemFuncs mem_funcs);
DN_API void DN_TCDeinit (DN_TCCore *tc);
DN_API void DN_TCEquip (DN_TCCore *tc);
DN_API DN_TCCore* DN_TCGet ();
DN_API DN_Arena* DN_TCMainArena ();
DN_API DN_Arena* DN_TCTempArena (DN_Arena **conflicts, DN_USize count);
DN_API DN_TCScratch DN_TCScratchBegin (DN_Arena **conflicts, DN_USize count);
DN_API void DN_TCScratchEnd (DN_TCScratch *scratch);
DN_API void DN_TCSetFrameArena (DN_Arena *arena);
DN_API DN_Arena* DN_TCFrameArena ();
DN_API DN_ErrSink* DN_TCErrSink ();
#define DN_TCErrSinkBegin(mode) DN_ErrSinkBegin(DN_TCErrSink(), mode)
#define DN_TCErrSinkBeginDefault() DN_ErrSinkBeginDefault(DN_TCErrSink())
DN_API bool DN_CharIsAlphabet (char ch); DN_API bool DN_CharIsAlphabet (char ch);
DN_API bool DN_CharIsDigit (char ch); DN_API bool DN_CharIsDigit (char ch);
DN_API bool DN_CharIsAlphaNum (char ch); DN_API bool DN_CharIsAlphaNum (char ch);
@ -1003,6 +1396,8 @@ DN_API DN_USize DN_CStr8Size (char const *src);
DN_API DN_USize DN_CStr16Size (wchar_t const *src); DN_API DN_USize DN_CStr16Size (wchar_t const *src);
#define DN_Str16Lit(string) DN_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1} #define DN_Str16Lit(string) DN_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1}
#define DN_Str16FromPtr(data, size) DN_Literal(DN_Str16){(wchar_t *)(data), (DN_USize)(size)}
#define DN_Str8Lit(c_str) DN_Literal(DN_Str8){(char *)(c_str), sizeof(c_str) - 1} #define DN_Str8Lit(c_str) DN_Literal(DN_Str8){(char *)(c_str), sizeof(c_str) - 1}
#define DN_Str8PrintFmt(string) (int)((string).size), (string).data #define DN_Str8PrintFmt(string) (int)((string).size), (string).data
#define DN_Str8FromPtr(data, size) DN_Literal(DN_Str8){(char *)(data), (DN_USize)(size)} #define DN_Str8FromPtr(data, size) DN_Literal(DN_Str8){(char *)(data), (DN_USize)(size)}
@ -1028,10 +1423,20 @@ DN_API DN_Str8x128 DN_Str8x128FromFmt (DN_FMT_ATTRIB char
DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_Str8x256 DN_Str8x256FromFmt (DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8x256 DN_Str8x256FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_Str8x16AppendFmt (DN_Str8x16 *str, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_Str8x16AppendFmtV (DN_Str8x16 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_Str8x32AppendFmt (DN_Str8x32 *str, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_Str8x32AppendFmtV (DN_Str8x32 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_Str8x64AppendFmt (DN_Str8x64 *str, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_Str8x64AppendFmtV (DN_Str8x64 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_Str8x128AppendFmt (DN_Str8x128 *str, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_Str8x128AppendFmtV (DN_Str8x128 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_Str8x256AppendFmt (DN_Str8x256 *str, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_Str8x256AppendFmtV (DN_Str8x256 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_Str8x32 DN_Str8x32FromU64 (DN_U64 val, char separator); DN_API DN_Str8x32 DN_Str8x32FromU64 (DN_U64 val, char separator);
DN_API bool DN_Str8IsAll (DN_Str8 string, DN_Str8IsAllType is_all); DN_API bool DN_Str8IsAll (DN_Str8 string, DN_Str8IsAllType is_all);
DN_API char * DN_Str8End (DN_Str8 string); DN_API char * DN_Str8End (DN_Str8 string);
DN_API DN_Str8 DN_Str8Slice (DN_Str8 string, DN_USize offset, DN_USize size); DN_API DN_Str8 DN_Str8Subset (DN_Str8 string, DN_USize offset, DN_USize size);
DN_API DN_Str8 DN_Str8Advance (DN_Str8 string, DN_USize amount); DN_API DN_Str8 DN_Str8Advance (DN_Str8 string, DN_USize amount);
DN_API DN_Str8 DN_Str8NextLine (DN_Str8 string); DN_API DN_Str8 DN_Str8NextLine (DN_Str8 string);
DN_API DN_Str8BSplitResult DN_Str8BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); DN_API DN_Str8BSplitResult DN_Str8BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size);
@ -1048,7 +1453,7 @@ DN_API DN_Str8 DN_Str8ReverseSegment (DN_Arena *arena, DN
DN_API bool DN_Str8Eq (DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); DN_API bool DN_Str8Eq (DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DN_API bool DN_Str8EqInsensitive (DN_Str8 lhs, DN_Str8 rhs); DN_API bool DN_Str8EqInsensitive (DN_Str8 lhs, DN_Str8 rhs);
DN_API bool DN_Str8StartsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); DN_API bool DN_Str8StartsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DN_API bool DN_Str8StartsWithInsensitive(DN_Str8 string, DN_Str8 prefix); DN_API bool DN_Str8StartsWithInsensitive (DN_Str8 string, DN_Str8 prefix);
DN_API bool DN_Str8EndsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); DN_API bool DN_Str8EndsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DN_API bool DN_Str8EndsWithInsensitive (DN_Str8 string, DN_Str8 prefix); DN_API bool DN_Str8EndsWithInsensitive (DN_Str8 string, DN_Str8 prefix);
DN_API bool DN_Str8HasChar (DN_Str8 string, char ch); DN_API bool DN_Str8HasChar (DN_Str8 string, char ch);
@ -1064,7 +1469,7 @@ DN_API DN_Str8 DN_Str8FileNameFromPath (DN_Str8 path);
DN_API DN_Str8 DN_Str8FileNameNoExtension (DN_Str8 path); DN_API DN_Str8 DN_Str8FileNameNoExtension (DN_Str8 path);
DN_API DN_Str8 DN_Str8FilePathNoExtension (DN_Str8 path); DN_API DN_Str8 DN_Str8FilePathNoExtension (DN_Str8 path);
DN_API DN_Str8 DN_Str8FileExtension (DN_Str8 path); DN_API DN_Str8 DN_Str8FileExtension (DN_Str8 path);
DN_API DN_Str8 DN_Str8FileDirectoryFromPath(DN_Str8 path); DN_API DN_Str8 DN_Str8FileDirectoryFromPath (DN_Str8 path);
DN_API DN_Str8 DN_Str8AppendF (DN_Arena *arena, DN_Str8 string, char const *fmt, ...); DN_API DN_Str8 DN_Str8AppendF (DN_Arena *arena, DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8 DN_Str8AppendFV (DN_Arena *arena, DN_Str8 string, char const *fmt, va_list args); DN_API DN_Str8 DN_Str8AppendFV (DN_Arena *arena, DN_Str8 string, char const *fmt, va_list args);
DN_API DN_Str8 DN_Str8FillF (DN_Arena *arena, DN_USize count, char const *fmt, ...); DN_API DN_Str8 DN_Str8FillF (DN_Arena *arena, DN_USize count, char const *fmt, ...);
@ -1073,6 +1478,10 @@ DN_API void DN_Str8Remove (DN_Str8 *string, DN
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddle (DN_Arena *arena, DN_Str8 str8, DN_U32 side_size, DN_Str8 truncator); DN_API DN_Str8TruncateResult DN_Str8TruncateMiddle (DN_Arena *arena, DN_Str8 str8, DN_U32 side_size, DN_Str8 truncator);
DN_API DN_Str8 DN_Str8Lower (DN_Arena *arena, DN_Str8 string); DN_API DN_Str8 DN_Str8Lower (DN_Arena *arena, DN_Str8 string);
DN_API DN_Str8 DN_Str8Upper (DN_Arena *arena, DN_Str8 string); DN_API DN_Str8 DN_Str8Upper (DN_Arena *arena, DN_Str8 string);
DN_API DN_Str8 DN_Str8PadNewLines (DN_Arena *arena, DN_Str8 src, DN_Str8 pad);
DN_API DN_Str8 DN_Str8Replace (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena, DN_Str8EqCase eq_case);
DN_API DN_Str8 DN_Str8ReplaceSensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
DN_API DN_Str8 DN_Str8ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
DN_API DN_Str8Builder DN_Str8BuilderFromArena (DN_Arena *arena); DN_API DN_Str8Builder DN_Str8BuilderFromArena (DN_Arena *arena);
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRef (DN_Arena *arena, DN_Str8 const *strings, DN_USize size); DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRef (DN_Arena *arena, DN_Str8 const *strings, DN_USize size);
@ -1104,7 +1513,7 @@ DN_API bool DN_Str8BuilderPrependF (DN_Str8Bu
DN_API bool DN_Str8BuilderErase (DN_Str8Builder *builder, DN_Str8 string); DN_API bool DN_Str8BuilderErase (DN_Str8Builder *builder, DN_Str8 string);
DN_API DN_Str8 DN_Str8BuilderBuild (DN_Str8Builder const *builder, DN_Arena *arena); DN_API DN_Str8 DN_Str8BuilderBuild (DN_Str8Builder const *builder, DN_Arena *arena);
DN_API DN_Str8 DN_Str8BuilderBuildDelimited (DN_Str8Builder const *builder, DN_Str8 delimiter, DN_Arena *arena); DN_API DN_Str8 DN_Str8BuilderBuildDelimited (DN_Str8Builder const *builder, DN_Str8 delimiter, DN_Arena *arena);
DN_API DN_Slice<DN_Str8> DN_Str8BuilderBuildSlice (DN_Str8Builder const *builder, DN_Arena *arena); DN_API DN_Str8Slice DN_Str8BuilderBuildSlice (DN_Str8Builder const *builder, DN_Arena *arena);
DN_API int DN_EncodeUTF8Codepoint (uint8_t utf8[4], uint32_t codepoint); DN_API int DN_EncodeUTF8Codepoint (uint8_t utf8[4], uint32_t codepoint);
DN_API int DN_EncodeUTF16Codepoint (uint16_t utf16[2], uint32_t codepoint); DN_API int DN_EncodeUTF16Codepoint (uint16_t utf16[2], uint32_t codepoint);
@ -1158,4 +1567,70 @@ DN_API void DN_ProfilerDump (DN_Profiler
DN_API DN_F64 DN_ProfilerSecFromTSC (DN_Profiler *profiler, DN_U64 duration_tsc); DN_API DN_F64 DN_ProfilerSecFromTSC (DN_Profiler *profiler, DN_U64 duration_tsc);
DN_API DN_F64 DN_ProfilerMsFromTSC (DN_Profiler *profiler, DN_U64 duration_tsc); DN_API DN_F64 DN_ProfilerMsFromTSC (DN_Profiler *profiler, DN_U64 duration_tsc);
DN_API DN_PCG32 DN_PCG32Init (DN_U64 seed);
DN_API DN_U32 DN_PCG32Next (DN_PCG32 *rng);
DN_API DN_U64 DN_PCG32Next64 (DN_PCG32 *rng);
DN_API DN_U32 DN_PCG32Range (DN_PCG32 *rng, DN_U32 low, DN_U32 high);
DN_API DN_F32 DN_PCG32NextF32 (DN_PCG32 *rng);
DN_API DN_F64 DN_PCG32NextF64 (DN_PCG32 *rng);
DN_API void DN_PCG32Advance (DN_PCG32 *rng, DN_U64 delta);
#if !defined(DN_FNV1A32_SEED)
#define DN_FNV1A32_SEED 2166136261U
#endif
#if !defined(DN_FNV1A64_SEED)
#define DN_FNV1A64_SEED 14695981039346656037ULL
#endif
DN_API DN_U32 DN_FNV1AHashU32FromBytes (void const *bytes, DN_USize size, DN_U32 seed);
DN_API DN_U64 DN_FNV1AHashU64FromBytes (void const *bytes, DN_USize size, DN_U64 seed);
DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX86 (void const *bytes, int len, DN_U32 seed);
DN_API DN_MurmurHash3 DN_MurmurHash3HashU128FromBytesX64 (void const *bytes, int len, DN_U32 seed);
DN_API DN_U64 DN_MurmurHash3HashU64FromBytesX64 (void const *bytes, int len, DN_U32 seed);
DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX64 (void const *bytes, int len, DN_U32 seed);
#if defined(DN_64_BIT)
#define DN_MurmurHash3HashU32FromBytes(bytes, len, seed) DN_MurmurHash3HashU32FromBytesX64(bytes, len, seed)
#else
#define DN_MurmurHash3HashU32FromBytes(bytes, len, seed) DN_MurmurHash3HashU32FromBytesX86(bytes, len, seed)
#endif
#define DN_LogResetEscapeCode "\x1b[0m"
#define DN_LogBoldEscapeCode "\x1b[1m"
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB (DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b);
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromU32 (DN_LogColourType colour, DN_U32 value);
DN_API DN_LogPrefixSize DN_LogMakePrefix (DN_LogStyle style, DN_LogTypeParam type, DN_CallSite call_site, DN_LogDate date, char *dest, DN_USize dest_size);
DN_API void DN_LogSetEmitFromTypeFVFunc (DN_LogEmitFromTypeFVFunc *print_func, void *user_data);
DN_API void DN_LogEmitFromType (DN_LogTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_LogTypeParam DN_LogMakeU32LogTypeParam (DN_LogType type);
#define DN_LogDebugF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Debug), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LogInfoF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LogWarningF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LogErrorF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__)
// NOTE: OS primitives that the OS layer can provide for the base layer but is optional.
#if defined(DN_FREESTANDING)
#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalk(...)
#define DN_StackTraceWalkResultIterate(...)
#define DN_StackTraceWalkResultToStr8(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalkStr8(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A")
#define DN_StackTraceGetFrames(...)
#define DN_StackTraceRawFrameToFrame(...)
#define DN_StackTracePrint(...)
#define DN_StackTraceReloadSymbols(...)
#else
DN_API DN_StackTraceWalkResult DN_StackTraceWalk (DN_Arena *arena, DN_U16 limit);
DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk);
DN_API DN_Str8 DN_StackTraceWalkResultToStr8 (DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip);
DN_API DN_Str8 DN_StackTraceWalkStr8 (DN_Arena *arena, DN_U16 limit, DN_U16 skip);
DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap (DN_U16 limit, DN_U16 skip);
DN_API DN_StackTraceFrameSlice DN_StackTraceGetFrames (DN_Arena *arena, DN_U16 limit);
DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame (DN_Arena *arena, DN_StackTraceRawFrame raw_frame);
DN_API void DN_StackTracePrint (DN_U16 limit);
DN_API void DN_StackTraceReloadSymbols ();
#endif
#endif // !defined(DN_BASE_H) #endif // !defined(DN_BASE_H)

View File

@ -5,7 +5,7 @@
do { \ do { \
if (!(expr)) { \ if (!(expr)) { \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LOG_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ DN_LogErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \ DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \ ##__VA_ARGS__); \
DN_DebugBreak; \ DN_DebugBreak; \
@ -33,7 +33,7 @@
do { \ do { \
if (!(expr)) { \ if (!(expr)) { \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \ DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \ ##__VA_ARGS__); \
DN_DebugBreak; \ DN_DebugBreak; \
@ -46,7 +46,7 @@
if (!(expr) && once) { \ if (!(expr) && once) { \
once = false; \ once = false; \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \ DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \ ##__VA_ARGS__); \
DN_DebugBreak; \ DN_DebugBreak; \
@ -68,10 +68,10 @@
#define DN_Check(expr) DN_CheckF(expr, "") #define DN_Check(expr) DN_CheckF(expr, "")
#if defined(DN_NO_CHECK_BREAK) #if defined(DN_NO_CHECK_BREAK)
#define DN_CheckF(expr, fmt, ...) \ #define DN_CheckF(expr, fmt, ...) \
((expr) ? true : (DN_LOG_WarningF(fmt, ##__VA_ARGS__), false)) ((expr) ? true : (DN_LogWarningF(fmt, ##__VA_ARGS__), false))
#else #else
#define DN_CheckF(expr, fmt, ...) \ #define DN_CheckF(expr, fmt, ...) \
((expr) ? true : (DN_LOG_ErrorF(fmt, ##__VA_ARGS__), DN_StackTracePrint(128 /*limit*/), DN_DebugBreak, false)) ((expr) ? true : (DN_LogErrorF(fmt, ##__VA_ARGS__), DN_StackTracePrint(128 /*limit*/), DN_DebugBreak, false))
#endif #endif
#endif #endif

View File

@ -1,160 +0,0 @@
#if !defined(DN_BASE_COMPILER_H)
#define DN_BASE_COMPILER_H
// NOTE: Compiler identification
// Warning! Order is important here, clang-cl on Windows defines _MSC_VER
#if defined(_MSC_VER)
#if defined(__clang__)
#define DN_COMPILER_CLANG_CL
#define DN_COMPILER_CLANG
#else
#define DN_COMPILER_MSVC
#endif
#elif defined(__clang__)
#define DN_COMPILER_CLANG
#elif defined(__GNUC__)
#define DN_COMPILER_GCC
#endif
// NOTE: __has_feature
// MSVC for example does not support the feature detection macro for instance so we compile it out
#if defined(__has_feature)
#define DN_HAS_FEATURE(expr) __has_feature(expr)
#else
#define DN_HAS_FEATURE(expr) 0
#endif
// NOTE: __has_builtin
// MSVC for example does not support the feature detection macro for instance so we compile it out
#if defined(__has_builtin)
#define DN_HAS_BUILTIN(expr) __has_builtin(expr)
#else
#define DN_HAS_BUILTIN(expr) 0
#endif
// NOTE: Warning suppression macros
#if defined(DN_COMPILER_MSVC)
#define DN_MSVC_WARNING_PUSH __pragma(warning(push))
#define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__))
#define DN_MSVC_WARNING_POP __pragma(warning(pop))
#else
#define DN_MSVC_WARNING_PUSH
#define DN_MSVC_WARNING_DISABLE(...)
#define DN_MSVC_WARNING_POP
#endif
#if defined(DN_COMPILER_CLANG) || defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG_CL)
#define DN_GCC_WARNING_PUSH _Pragma("GCC diagnostic push")
#define DN_GCC_WARNING_DISABLE_HELPER_0(x) #x
#define DN_GCC_WARNING_DISABLE_HELPER_1(y) DN_GCC_WARNING_DISABLE_HELPER_0(GCC diagnostic ignored #y)
#define DN_GCC_WARNING_DISABLE(warning) _Pragma(DN_GCC_WARNING_DISABLE_HELPER_1(warning))
#define DN_GCC_WARNING_POP _Pragma("GCC diagnostic pop")
#else
#define DN_GCC_WARNING_PUSH
#define DN_GCC_WARNING_DISABLE(...)
#define DN_GCC_WARNING_POP
#endif
// NOTE: Host OS identification
#if defined(_WIN32)
#define DN_OS_WIN32
#elif defined(__gnu_linux__) || defined(__linux__)
#define DN_OS_UNIX
#endif
// NOTE: Platform identification
#if !defined(DN_PLATFORM_EMSCRIPTEN) && \
!defined(DN_PLATFORM_POSIX) && \
!defined(DN_PLATFORM_WIN32)
#if defined(__aarch64__) || defined(_M_ARM64)
#define DN_PLATFORM_ARM64
#elif defined(__EMSCRIPTEN__)
#define DN_PLATFORM_EMSCRIPTEN
#elif defined(DN_OS_WIN32)
#define DN_PLATFORM_WIN32
#else
#define DN_PLATFORM_POSIX
#endif
#endif
// NOTE: Windows crap
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#if defined(_CRT_SECURE_NO_WARNINGS)
#define DN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED
#else
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
// NOTE: Force Inline
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#define DN_FORCE_INLINE __forceinline
#else
#define DN_FORCE_INLINE inline __attribute__((always_inline))
#endif
// NOTE: Function/Variable Annotations
#if defined(DN_STATIC_API)
#define DN_API static
#else
#define DN_API
#endif
// NOTE: C/CPP Literals
// Declare struct literals that work in both C and C++ because the syntax is different between
// languages.
#if 0
struct Foo { int a; }
struct Foo foo = DN_LITERAL(Foo){32}; // Works on both C and C++
#endif
#if defined(__cplusplus)
#define DN_Literal(T) T
#else
#define DN_Literal(T) (T)
#endif
// NOTE: Thread Locals
#if defined(__cplusplus)
#define DN_THREAD_LOCAL thread_local
#else
#define DN_THREAD_LOCAL _Thread_local
#endif
// NOTE: C variadic argument annotations
// TODO: Other compilers
#if defined(DN_COMPILER_MSVC)
#define DN_FMT_ATTRIB _Printf_format_string_
#else
#define DN_FMT_ATTRIB
#endif
// NOTE: Type Cast
#define DN_Cast(val) (val)
// NOTE: Zero initialisation macro
#if defined(__cplusplus)
#define DN_ZeroInit {}
#else
#define DN_ZeroInit {0}
#endif
// NOTE: Address sanitizer
#if !defined(DN_ASAN_POISON)
#define DN_ASAN_POISON 0
#endif
#if !defined(DN_ASAN_VET_POISON)
#define DN_ASAN_VET_POISON 0
#endif
#define DN_ASAN_POISON_ALIGNMENT 8
#if !defined(DN_ASAN_POISON_GUARD_SIZE)
#define DN_ASAN_POISON_GUARD_SIZE 128
#endif
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#include <sanitizer/asan_interface.h>
#endif
#endif // !defined(DN_BASE_COMPILER_H)

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,70 @@
#if !defined(DN_CONTAINERS_H) #if !defined(DN_CONTAINERS_H)
#define DN_CONTAINERS_H #define DN_CONTAINERS_H
// Containers that are imlpemented using primarily macros for operating on data structures that are
// embedded into a C style struct or from a set of defined variables from the available scope. Keep
// it stupid simple, structs and functions. Minimal amount of container types with flexible
// construction leads to less duplicated container code and less template meta-programming.
//
// PArray => Pointer (to) Array
// LArray => Literal Array
// Define a C array and size. (P) array macros take a pointer to the aray, its size and its max
// capacity. The (L) array macros take the literal array and derives the max capacity
// automatically using DN_ArrayCountU(l_array).
//
// MyStruct buffer[TB_ASType_Count] = {};
// DN_USize size = 0;
// MyStruct *item_0 = DN_PArrayMake(buffer, &size, DN_ArrayCountU(buffer), DN_ZMem_No);
// MyStruct *item_1 = DN_LArrayMake(buffer, &size, DN_ZMem_No);
//
// IArray => Intrusive Array
// Define a struct with the members `data`, `size` and `max`:
//
// struct MyArray {
// MyStruct *data;
// DN_USize size;
// DN_USize max;
// } my_array = {};
// MyStruct *item = DN_IArrayMake(&my_array, DN_ZMem_No);
//
// ISinglyLL => Intrusive Singly Linked List
// Define a struct with the members `next`:
//
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// } my_link = {};
//
// MyLinkItem *first_item = DN_ISinglyLLDetach(&my_link, MyLinkItem);
//
// DoublyLL => Doubly Linked List
// Define a struct with the members `next` and `prev`. This list has null pointers for head->prev
// and tail->next.
//
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// MyLinkItem *prev;
// } my_link = {};
//
// MyLinkItem first_item = {}, second_item = {};
// DN_DoublyLLAppend(&first_item, &second_item); // first_item -> second_item
//
// SentinelDoublyLL => Sentinel Doubly Linked List
// Uses a sentinel/dummy node as the list head. The sentinel points to itself when empty.
// Define a struct with the members `next` and `prev`:
//
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// MyLinkItem *prev;
// } my_list = {};
//
// DN_SentinelDoublyLLInit(&my_list);
// DN_SentinelDoublyLLAppend(&my_list, &new_item);
// DN_SentinelDoublyLLForEach(it, &my_list) { /* ... */ }
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn.h" #include "../dn.h"
#endif #endif
struct DN_Ring struct DN_Ring
@ -13,7 +75,6 @@ struct DN_Ring
DN_U64 read_pos; DN_U64 read_pos;
}; };
// NOTE: DN_CArray /////////////////////////////////////////////////////////////////////////////////
enum DN_ArrayErase enum DN_ArrayErase
{ {
DN_ArrayErase_Unstable, DN_ArrayErase_Unstable,
@ -45,42 +106,6 @@ template <typename T> struct DN_ArrayFindResult
DN_USize index; // Index to the value if a match is found, 0 otherwise DN_USize index; // Index to the value if a match is found, 0 otherwise
}; };
#if !defined(DN_NO_SARRAY)
// NOTE: DN_SArray /////////////////////////////////////////////////////////////////////////////////
template <typename T> struct DN_SArray
{
T *data; // Pointer to the start of the array items in the block of memory
DN_USize size; // Number of items currently in the array
DN_USize max; // Maximum number of items this array can store
T *begin() { return data; }
T *end () { return data + size; }
T const *begin() const { return data; }
T const *end () const { return data + size; }
};
#endif // !defined(DN_NO_SARRAY)
#if !defined(DN_NO_FARRAY)
// NOTE: DN_FArray /////////////////////////////////////////////////////////////////////////////////
template <typename T, DN_USize N> struct DN_FArray
{
T data[N]; // Pointer to the start of the array items in the block of memory
DN_USize size; // Number of items currently in the array
T *begin() { return data; }
T *end () { return data + size; }
T const *begin() const { return data; }
T const *end () const { return data + size; }
};
template <typename T> using DN_FArray8 = DN_FArray<T, 8>;
template <typename T> using DN_FArray16 = DN_FArray<T, 16>;
template <typename T> using DN_FArray32 = DN_FArray<T, 32>;
template <typename T> using DN_FArray64 = DN_FArray<T, 64>;
#endif // !defined(DN_NO_FARRAY)
#if !defined(DN_NO_DSMAP)
// NOTE: DN_DSMap //////////////////////////////////////////////////////////////////////////////////
enum DN_DSMapKeyType enum DN_DSMapKeyType
{ {
// Key | Key Hash | Map Index // Key | Key Hash | Map Index
@ -136,93 +161,29 @@ template <typename T> struct DN_DSMapResult
DN_DSMapSlot<T> *slot; DN_DSMapSlot<T> *slot;
T *value; T *value;
}; };
#endif // !defined(DN_NO_DSMAP)
#if !defined(DN_NO_LIST) #define DN_ISinglyLLDetach(list) (decltype(list))DN_SinglyLLDetach((void **)&(list), (void **)&(list)->next)
// NOTE: DN_List ///////////////////////////////////////////////////////////////////////////////////
template <typename T> struct DN_ListChunk
{
T *data;
DN_USize size;
DN_USize count;
DN_ListChunk<T> *next;
DN_ListChunk<T> *prev;
};
template <typename T> struct DN_ListIterator #define DN_SentinelDoublyLLInit(list) (list)->next = (list)->prev = (list)
{ #define DN_SentinelDoublyLLIsSentinel(list, item) ((list) == (item))
DN_B32 init; // True if DN_List_Iterate has been called at-least once on this iterator #define DN_SentinelDoublyLLIsEmpty(list) (!(list) || ((list) == (list)->next))
DN_ListChunk<T> *chunk; // The chunk that the iterator is reading from #define DN_SentinelDoublyLLIsInit(list) ((list)->next && (list)->prev)
DN_USize chunk_data_index; // The index in the chunk the iterator is referencing #define DN_SentinelDoublyLLHasItems(list) ((list) && ((list) != (list)->next))
DN_USize index; // The index of the item in the list as if it was flat array #define DN_SentinelDoublyLLForEach(it, list) auto *it = (list)->next; (it) != (list); (it) = (it)->next
T *data; // Pointer to the data the iterator is referencing. Nullptr if invalid.
};
template <typename T> struct DN_List #define DN_SentinelDoublyLLInitArena(list, T, arena) \
{
DN_USize count; // Cumulative count of all items made across all list chunks
DN_USize chunk_size; // When new ListChunk's are required, the minimum 'data' entries to allocate for that node.
DN_ListChunk<T> *head;
DN_ListChunk<T> *tail;
};
#endif // !defined(DN_NO_LIST)
// NOTE: Macros for operating on data structures that are embedded into a C style struct or from a
// set of defined variables from the available scope. Keep it stupid simple, structs and functions.
// Minimal amount of container types with flexible construction leads to less duplicated container
// code and less template meta-programming.
//
// LArray => Literal Array
// Define a C array and size:
//
// ```
// MyStruct buffer[TB_ASType_Count] = {};
// DN_USize size = 0;
// MyStruct *item = DN_LArray_Make(buffer, size, DN_ArrayCountU(buffer), DN_ZMem_No);
// ```
//
// IArray => Intrusive Array
// Define a struct with the members 'data', 'size' and 'max':
//
// ```
// struct MyArray {
// MyStruct *data;
// DN_USize size;
// DN_USize max;
// } my_array = {};
//
// MyStruct *item = DN_IArray_Make(&my_array, MyArray, DN_ZMem_No);
// ```
// ISLList => Intrusive Singly Linked List
// Define a struct with the members 'next':
//
// ```
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// } my_link = {};
//
// MyLinkItem *first_item = DN_ISLList_Detach(&my_link, MyLinkItem);
// ```
#define DN_DLList_Init(list) \
(list)->next = (list)->prev = (list)
#define DN_DLList_IsSentinel(list, item) ((list) == (item))
#define DN_DLList_InitArena(list, T, arena) \
do { \ do { \
(list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \ (list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \
DN_DLList_Init(list); \ DN_SentinelDoublyLLInit(list); \
} while (0) } while (0)
#define DN_DLList_InitPool(list, T, pool) \ #define DN_SentinelDoublyLLInitPool(list, T, pool) \
do { \ do { \
(list) = DN_PoolNew(pool, T); \ (list) = DN_PoolNew(pool, T); \
DN_DLList_Init(list); \ DN_SentinelDoublyLLInit(list); \
} while (0) } while (0)
#define DN_DLList_Detach(item) \ #define DN_SentinelDoublyLLDetach(item) \
do { \ do { \
if (item) { \ if (item) { \
(item)->prev->next = (item)->next; \ (item)->prev->next = (item)->next; \
@ -232,17 +193,17 @@ template <typename T> struct DN_List
} \ } \
} while (0) } while (0)
#define DN_DLList_Dequeue(list, dest_ptr) \ #define DN_SentinelDoublyLLDequeue(list, dest_ptr) \
if (DN_DLList_HasItems(list)) { \ if (DN_SentinelDoublyLLHasItems(list)) { \
dest_ptr = (list)->next; \ dest_ptr = (list)->next; \
DN_DLList_Detach(dest_ptr); \ DN_SentinelDoublyLLDetach(dest_ptr); \
} }
#define DN_DLList_Append(list, item) \ #define DN_SentinelDoublyLLAppend(list, item) \
do { \ do { \
if (item) { \ if (item) { \
if ((item)->next) \ if ((item)->next) \
DN_DLList_Detach(item); \ DN_SentinelDoublyLLDetach(item); \
(item)->next = (list)->next; \ (item)->next = (list)->next; \
(item)->prev = (list); \ (item)->prev = (list); \
(item)->next->prev = (item); \ (item)->next->prev = (item); \
@ -250,11 +211,11 @@ template <typename T> struct DN_List
} \ } \
} while (0) } while (0)
#define DN_DLList_Prepend(list, item) \ #define DN_SentinelDoublyLLPrepend(list, item) \
do { \ do { \
if (item) { \ if (item) { \
if ((item)->next) \ if ((item)->next) \
DN_DLList_Detach(item); \ DN_SentinelDoublyLLDetach(item); \
(item)->next = (list); \ (item)->next = (list); \
(item)->prev = (list)->prev; \ (item)->prev = (list)->prev; \
(item)->next->prev = (item); \ (item)->next->prev = (item); \
@ -262,17 +223,17 @@ template <typename T> struct DN_List
} \ } \
} while (0) } while (0)
#define DN_DLList_IsEmpty(list) \ // DoublyLL => Non-intrusive Doubly Linked List
(!(list) || ((list) == (list)->next)) // A simple doubly linked list where each node has `next` and `prev` pointers.
// The head is passed as a pointer-to-pointer to allow head updates.
#define DN_DLList_IsInit(list) \ //
((list)->next && (list)->prev) // struct MyLinkItem {
// int data;
#define DN_DLList_HasItems(list) \ // MyLinkItem *next;
((list) && ((list) != (list)->next)) // MyLinkItem *prev;
// } *head = nullptr;
#define DN_DLList_ForEach(it, list) \ // DN_DoublyLLAppend(&head, new_item);
auto *it = (list)->next; (it) != (list); (it) = (it)->next // for (MyLinkItem *it = head; it; it = it->next) { /* ... */ }
#define DN_DoublyLLDetach(head, ptr) \ #define DN_DoublyLLDetach(head, ptr) \
do { \ do { \
@ -317,182 +278,121 @@ template <typename T> struct DN_List
} \ } \
} while (0) } while (0)
#define DN_ISLList_Detach(list) (decltype(list))DN_CSLList_Detach((void **)&(list), (void **)&(list)->next) // NOTE: For C++ we need to cast the void* returned in these functions to the concrete type. In C,
// no cast is needed.
#if defined(__cplusplus)
#define DN_CppDeclType(x) decltype(x)
#else
#define DN_CppDeclType
#endif
#define DN_LArray_ResizeFromPool(c_array, size, max, pool, new_max) DN_CArray2_ResizeFromPool((void **)&(c_array), size, max, sizeof((c_array)[0]), pool, new_max) #define DN_PArrayResizeFromPool(ptr, size, max, pool, new_max) DN_CArrayResizeFromPool((void **)&(ptr), size, max, sizeof((ptr)[0]), pool, new_max)
#define DN_LArray_GrowFromPool(c_array, size, max, pool, new_max) DN_CArray2_GrowFromPool((void **)&(c_array), size, max, sizeof((c_array)[0]), pool, new_max) #define DN_PArrayGrowFromPool(ptr, size, max, pool, new_max) DN_CArrayGrowFromPool((void **)&(ptr), size, max, sizeof((ptr)[0]), pool, new_max)
#define DN_LArray_GrowIfNeededFromPool(c_array, size, max, pool, add_count) DN_CArray2_GrowIfNeededFromPool((void **)(c_array), size, max, sizeof((c_array)[0]), pool, add_count) #define DN_PArrayGrowIfNeededFromPool(ptr, size, max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, max, sizeof((ptr)[0]), pool, add_count)
#define DN_LArray_MakeArray(c_array, size, max, count, z_mem) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), count, z_mem) #define DN_PArrayMakeArray(ptr, size, max, count, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), count, z_mem)
#define DN_LArray_MakeArrayZ(c_array, size, max, count) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), count, DN_ZMem_Yes) #define DN_PArrayMakeArrayZ(ptr, size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), count, DN_ZMem_Yes)
#define DN_LArray_Make(c_array, size, max, z_mem) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), 1, z_mem) #define DN_PArrayMake(ptr, size, max, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), 1, z_mem)
#define DN_LArray_MakeZ(c_array, size, max) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), 1, DN_ZMem_Yes) #define DN_PArrayMakeZ(ptr, size, max) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), 1, DN_ZMem_Yes)
#define DN_LArray_AddArray(c_array, size, max, items, count, add) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, add) #define DN_PArrayAddArray(ptr, size, max, items, count, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), items, count, add)
#define DN_LArray_Add(c_array, size, max, item, add) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, add) #define DN_PArrayAdd(ptr, size, max, item, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), &item, 1, add)
#define DN_LArray_AppendArray(c_array, size, max, items, count) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, DN_ArrayAdd_Append) #define DN_PArrayAppendArray(ptr, size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), items, count, DN_ArrayAdd_Append)
#define DN_LArray_Append(c_array, size, max, item) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, DN_ArrayAdd_Append) #define DN_PArrayAppend(ptr, size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Append)
#define DN_LArray_PrependArray(c_array, size, max, items, count) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, DN_ArrayAdd_Prepend) #define DN_PArrayPrependArray(ptr, size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), items, count, DN_ArrayAdd_Prepend)
#define DN_LArray_Prepend(c_array, size, max, item) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, DN_ArrayAdd_Prepend) #define DN_PArrayPrepend(ptr, size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Prepend)
#define DN_LArray_EraseRange(c_array, size, begin_index, count, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), begin_index, count, erase) #define DN_PArrayEraseRange(ptr, size, begin_index, count, erase) DN_CArrayEraseRange(ptr, size, sizeof((ptr)[0]), begin_index, count, erase)
#define DN_LArray_Erase(c_array, size, index, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), index, 1, erase) #define DN_PArrayErase(ptr, size, index, erase) DN_CArrayEraseRange(ptr, size, sizeof((ptr)[0]), index, 1, erase)
#define DN_LArray_InsertArray(c_array, size, max, index, items, count) (decltype(&(c_array)[0]))DN_CArray2_InsertArray(c_array, size, max, sizeof((c_array)[0]), index, items, count) #define DN_PArrayInsertArray(ptr, size, max, index, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, size, max, sizeof((ptr)[0]), index, items, count)
#define DN_LArray_Insert(c_array, size, max, index, item) (decltype(&(c_array)[0]))DN_CArray2_InsertArray(c_array, size, max, sizeof((c_array)[0]), index, &item, 1) #define DN_PArrayInsert(ptr, size, max, index, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, size, max, sizeof((ptr)[0]), index, &item, 1)
#define DN_PArrayPopFront(ptr, size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopFront(ptr, size, sizeof((ptr)[0]), count)
#define DN_PArrayPopBack(ptr, size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopBack(ptr, size, sizeof((ptr)[0]), count)
#define DN_IArray_ResizeFromPool(array, pool, new_max) DN_CArray2_ResizeFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max) #define DN_LArrayResizeFromPool(c_array, size, pool, new_max) DN_PArrayResizeFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max)
#define DN_IArray_GrowFromPool(array, pool, new_max) DN_CArray2_GrowFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max) #define DN_LArrayGrowFromPool(c_array, size, pool, new_max) DN_PArrayGrowFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max)
#define DN_IArray_GrowIfNeededFromPool(array, pool, add_count) DN_CArray2_GrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, add_count) #define DN_LArrayGrowIfNeededFromPool(c_array, size, pool, add_count) DN_PArrayGrowIfNeededFromPool(c_array, size, DN_ArrayCountU(c_array), pool, add_count)
#define DN_IArray_MakeArray(array, count, z_mem) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, z_mem) #define DN_LArrayMakeArray(c_array, size, count, z_mem) DN_PArrayMakeArray(c_array, size, DN_ArrayCountU(c_array), count, z_mem)
#define DN_IArray_MakeArrayZ(array, count) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, DN_ZMem_Yes) #define DN_LArrayMakeArrayZ(c_array, size, count) DN_PArrayMakeArrayZ(c_array, size, DN_ArrayCountU(c_array), count)
#define DN_IArray_Make(array, z_mem) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, z_mem) #define DN_LArrayMake(c_array, size, z_mem) DN_PArrayMake(c_array, size, DN_ArrayCountU(c_array), z_mem)
#define DN_IArray_MakeZ(array) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, DN_ZMem_Yes) #define DN_LArrayMakeZ(c_array, size, max) DN_PArrayMakeZ(c_array, size, DN_ArrayCountU(c_array), max)
#define DN_IArray_AddArray(array, items, count, add) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, add) #define DN_LArrayAddArray(c_array, size, items, count, add) DN_PArrayAddArray(c_array, size, DN_ArrayCountU(c_array), items, count, add)
#define DN_IArray_Add(array, item, add) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, add) #define DN_LArrayAdd(c_array, size, item, add) DN_PArrayAdd(c_array, size, DN_ArrayCountU(c_array), item, add)
#define DN_IArray_AppendArray(array, items, count) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Append) #define DN_LArrayAppendArray(c_array, size, items, count) DN_PArrayAppendArray(c_array, size, DN_ArrayCountU(c_array), items, count)
#define DN_IArray_Append(array, item) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Append) #define DN_LArrayAppend(c_array, size, item) DN_PArrayAppend(c_array, size, DN_ArrayCountU(c_array), item)
#define DN_IArray_PrependArray(array, items, count) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Prepend) #define DN_LArrayPrependArray(c_array, size, items, count) DN_PArrayPrependArray(c_array, size, DN_ArrayCountU(c_array), items, count)
#define DN_IArray_Prepend(array, item) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend) #define DN_LArrayPrepend(c_array, size, item) DN_PArrayPrepend(c_array, size, DN_ArrayCountU(c_array), item)
#define DN_IArray_EraseRange(array, begin_index, count, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), begin_index, count, erase) #define DN_LArrayEraseRange(c_array, size, begin_index, count, erase) DN_PArrayEraseRange(c_array, size, DN_ArrayCountU(c_array), begin_index, count, erase)
#define DN_IArray_Erase(array, index, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), index, 1, erase) #define DN_LArrayErase(c_array, size, index, erase) DN_PArrayErase(c_array, size, DN_ArrayCountU(c_array), index, erase)
#define DN_IArray_InsertArray(array, index, items, count) (decltype(&((array)->data)[0]))DN_CArray2_InsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, items, count) #define DN_LArrayInsertArray(c_array, size, index, items, count) DN_PArrayInsertArray(c_array, size, DN_ArrayCountU(c_array), index, items, count)
#define DN_IArray_Insert(array, index, item, count) (decltype(&((array)->data)[0]))DN_CArray2_InsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, &item, 1) #define DN_LArrayInsert(c_array, size, index, item) DN_PArrayInsert(c_array, size, DN_ArrayCountU(c_array), index, item)
#define DN_LArrayPopFront(c_array, size, count) DN_PArrayPopFront(c_array, size, DN_ArrayCountU(c_array), count)
#define DN_LArrayPopBack(c_array, size, count) DN_PArrayPopBack(c_array, size, DN_ArrayCountU(c_array), count)
DN_API DN_ArrayEraseResult DN_CArray2_EraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); #define DN_IArrayResizeFromPool(array, pool, new_max) DN_CArrayResizeFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max)
DN_API void *DN_CArray2_MakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem); #define DN_IArrayGrowFromPool(array, pool, new_max) DN_CArrayGrowFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max)
DN_API void *DN_CArray2_AddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add); #define DN_IArrayGrowIfNeededFromPool(array, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, add_count)
DN_API bool DN_CArray2_Resize (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max); #define DN_IArrayMakeArray(array, count, z_mem) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, z_mem)
DN_API bool DN_CArray2_Grow (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max); #define DN_IArrayMakeArrayZ(array, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, DN_ZMem_Yes)
DN_API bool DN_CArray2_GrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool); #define DN_IArrayMake(array, z_mem) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, z_mem)
DN_API void *DN_CSLList_Detach (void **link, void **next); #define DN_IArrayMakeZ(array) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, DN_ZMem_Yes)
#define DN_IArrayAddArray(array, items, count, add) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, add)
#define DN_IArrayAdd(array, item, add) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, add)
#define DN_IArrayAppendArray(array, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Append)
#define DN_IArrayAppend(array, item) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Append)
#define DN_IArrayPrependArray(array, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Prepend)
#define DN_IArrayPrepend(array, item) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend)
#define DN_IArrayEraseRange(array, begin_index, count, erase) DN_CArrayEraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), begin_index, count, erase)
#define DN_IArrayErase(array, index, erase) DN_CArrayEraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), index, 1, erase)
#define DN_IArrayInsertArray(array, index, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayInsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, items, count)
#define DN_IArrayInsert(array, index, item, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayInsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, &item, 1)
#define DN_IArrayPopFront(array, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayPopFront((array)->data, &(array)->size, sizeof(((array)->data)[0]), count)
#define DN_IArrayPopBack(array, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayPopBack((array)->data, &(array)->size, sizeof(((array)->data)[0]), count)
DN_API bool DN_Ring_HasSpace (DN_Ring const *ring, DN_U64 size); #define DN_ISliceAllocArena(T, slice_ptr, count_, zmem, arena) (T *)DN_SliceAllocArena((void **)&((slice_ptr)->data), &((slice_ptr)->count), count_, sizeof(T), alignof(T), zmem, arena)
DN_API bool DN_Ring_HasData (DN_Ring const *ring, DN_U64 size);
DN_API void DN_Ring_Write (DN_Ring *ring, void const *src, DN_U64 src_size);
#define DN_Ring_WriteStruct(ring, item) DN_Ring_Write((ring), (item), sizeof(*(item)))
DN_API void DN_Ring_Read (DN_Ring *ring, void *dest, DN_U64 dest_size);
#define DN_Ring_ReadStruct(ring, dest) DN_Ring_Read((ring), (dest), sizeof(*(dest)))
template <typename T> DN_ArrayEraseResult DN_CArray_EraseRange (T *data, DN_USize *size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); DN_API void* DN_SliceAllocArena (void **data, DN_USize *slice_size_field, DN_USize size, DN_USize elem_size, DN_U8 align, DN_ZMem zmem, DN_Arena *arena);
template <typename T> T * DN_CArray_MakeArray (T *data, DN_USize *size, DN_USize max, DN_USize count, DN_ZMem z_mem);
template <typename T> T * DN_CArray_InsertArray (T *data, DN_USize *size, DN_USize max, DN_USize index, T const *items, DN_USize count);
template <typename T> T DN_CArray_PopFront (T *data, DN_USize *size, DN_USize count);
template <typename T> T DN_CArray_PopBack (T *data, DN_USize *size, DN_USize count);
template <typename T> DN_ArrayFindResult<T> DN_CArray_Find (T *data, DN_USize size, T const &value);
// NOTE: DN_SArray ///////////////////////////////////////////////////////////////////////////////// DN_API void* DN_CArrayInsertArray (void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count);
#if !defined(DN_NO_SARRAY) DN_API void* DN_CArrayPopFront (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
template <typename T> DN_SArray<T> DN_SArray_Init (DN_Arena *arena, DN_USize size, DN_ZMem z_mem); DN_API void* DN_CArrayPopBack (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
template <typename T> DN_SArray<T> DN_SArray_InitSlice (DN_Arena *arena, DN_Slice<T> slice, DN_USize size, DN_ZMem z_mem); DN_API DN_ArrayEraseResult DN_CArrayEraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T, size_t N> DN_SArray<T> DN_SArray_InitCArray (DN_Arena *arena, T const (&array)[N], DN_USize size, DN_ZMem); DN_API void* DN_CArrayMakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem);
template <typename T> DN_SArray<T> DN_SArray_InitBuffer (T* buffer, DN_USize size); DN_API void* DN_CArrayAddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add);
template <typename T> bool DN_SArray_IsValid (DN_SArray<T> const *array); DN_API bool DN_CArrayResizeFromPool (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
template <typename T> DN_Slice<T> DN_SArray_Slice (DN_SArray<T> const *array); DN_API bool DN_CArrayGrowFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
template <typename T> T * DN_SArray_AddArray (DN_SArray<T> *array, T const *items, DN_USize count); DN_API bool DN_CArrayGrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool);
template <typename T, DN_USize N> T * DN_SArray_AddCArray (DN_SArray<T> *array, T const (&items)[N]);
template <typename T> T * DN_SArray_Add (DN_SArray<T> *array, T const &item);
#define DN_SArray_AddArrayAssert(...) DN_HardAssert(DN_SArray_AddArray(__VA_ARGS__))
#define DN_SArray_AddCArrayAssert(...) DN_HardAssert(DN_SArray_AddCArray(__VA_ARGS__))
#define DN_SArray_AddAssert(...) DN_HardAssert(DN_SArray_Add(__VA_ARGS__))
template <typename T> T * DN_SArray_MakeArray (DN_SArray<T> *array, DN_USize count, DN_ZMem z_mem);
template <typename T> T * DN_SArray_Make (DN_SArray<T> *array, DN_ZMem z_mem);
#define DN_SArray_MakeArrayAssert(...) DN_HardAssert(DN_SArray_MakeArray(__VA_ARGS__))
#define DN_SArray_MakeAssert(...) DN_HardAssert(DN_SArray_Make(__VA_ARGS__))
template <typename T> T * DN_SArray_InsertArray (DN_SArray<T> *array, DN_USize index, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_SArray_InsertCArray (DN_SArray<T> *array, DN_USize index, T const (&items)[N]);
template <typename T> T * DN_SArray_Insert (DN_SArray<T> *array, DN_USize index, T const &item);
#define DN_SArray_InsertArrayAssert(...) DN_HardAssert(DN_SArray_InsertArray(__VA_ARGS__))
#define DN_SArray_InsertCArrayAssert(...) DN_HardAssert(DN_SArray_InsertCArray(__VA_ARGS__))
#define DN_SArray_InsertAssert(...) DN_HardAssert(DN_SArray_Insert(__VA_ARGS__))
template <typename T> T DN_SArray_PopFront (DN_SArray<T> *array, DN_USize count);
template <typename T> T DN_SArray_PopBack (DN_SArray<T> *array, DN_USize count);
template <typename T> DN_ArrayEraseResult DN_SArray_EraseRange (DN_SArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T> void DN_SArray_Clear (DN_SArray<T> *array);
#endif // !defined(DN_NO_SARRAY)
#if !defined(DN_NO_FARRAY) DN_API void* DN_SinglyLLDetach (void **link, void **next);
#define DN_FArray_ToSArray(array) DN_SArray_InitBuffer((array)->data, DN_ArrayCountU((array)->data))
template <typename T, DN_USize N> DN_FArray<T, N> DN_FArray_Init (T const *array, DN_USize count);
#define DN_FArray_HasData(array) ((array).data && (array).size)
template <typename T, DN_USize N> DN_FArray<T, N> DN_FArray_InitSlice (DN_Slice<T> slice);
template <typename T, DN_USize N, DN_USize K> DN_FArray<T, N> DN_FArray_InitCArray (T const (&items)[K]);
template <typename T, DN_USize N> bool DN_FArray_IsValid (DN_FArray<T, N> const *array);
template <typename T, DN_USize N> DN_USize DN_FArray_Max (DN_FArray<T, N> const *) { return N; }
template <typename T, DN_USize N> DN_Slice<T> DN_FArray_Slice (DN_FArray<T, N> const *array);
template <typename T, DN_USize N> T * DN_FArray_AddArray (DN_FArray<T, N> *array, T const *items, DN_USize count);
template <typename T, DN_USize N, DN_USize K> T * DN_FArray_AddCArray (DN_FArray<T, N> *array, T const (&items)[K]);
template <typename T, DN_USize N> T * DN_FArray_Add (DN_FArray<T, N> *array, T const &item);
#define DN_FArray_AddArrayAssert(...) DN_HardAssert(DN_FArray_AddArray(__VA_ARGS__))
#define DN_FArray_AddCArrayAssert(...) DN_HardAssert(DN_FArray_AddCArray(__VA_ARGS__))
#define DN_FArray_AddAssert(...) DN_HardAssert(DN_FArray_Add(__VA_ARGS__))
template <typename T, DN_USize N> T * DN_FArray_MakeArray (DN_FArray<T, N> *array, DN_USize count, DN_ZMem z_mem);
template <typename T, DN_USize N> T * DN_FArray_Make (DN_FArray<T, N> *array, DN_ZMem z_mem);
#define DN_FArray_MakeArrayAssert(...) DN_HardAssert(DN_FArray_MakeArray(__VA_ARGS__))
#define DN_FArray_MakeAssert(...) DN_HardAssert(DN_FArray_Make(__VA_ARGS__))
template <typename T, DN_USize N> T * DN_FArray_InsertArray (DN_FArray<T, N> *array, T const &item, DN_USize index);
template <typename T, DN_USize N, DN_USize K> T * DN_FArray_InsertCArray (DN_FArray<T, N> *array, DN_USize index, T const (&items)[K]);
template <typename T, DN_USize N> T * DN_FArray_Insert (DN_FArray<T, N> *array, DN_USize index, T const &item);
#define DN_FArray_InsertArrayAssert(...) DN_HardAssert(DN_FArray_InsertArray(__VA_ARGS__))
#define DN_FArray_InsertAssert(...) DN_HardAssert(DN_FArray_Insert(__VA_ARGS__))
template <typename T, DN_USize N> T DN_FArray_PopFront (DN_FArray<T, N> *array, DN_USize count);
template <typename T, DN_USize N> T DN_FArray_PopBack (DN_FArray<T, N> *array, DN_USize count);
template <typename T, DN_USize N> DN_ArrayFindResult<T> DN_FArray_Find (DN_FArray<T, N> *array, T const &find);
template <typename T, DN_USize N> DN_ArrayEraseResult DN_FArray_EraseRange (DN_FArray<T, N> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T, DN_USize N> void DN_FArray_Clear (DN_FArray<T, N> *array);
#endif // !defined(DN_NO_FARRAY)
#if !defined(DN_NO_SLICE) DN_API bool DN_RingHasSpace (DN_Ring const *ring, DN_U64 size);
#define DN_TO_SLICE(val) DN_Slice_Init((val)->data, (val)->size) DN_API bool DN_RingHasData (DN_Ring const *ring, DN_U64 size);
#define DN_Slice_InitCArray(array) DN_Slice_Init(array, DN_ArrayCountU(array)) DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size);
template <typename T> DN_Slice<T> DN_Slice_Init (T* const data, DN_USize size); #define DN_RingWriteStruct(ring, item) DN_RingWrite((ring), (item), sizeof(*(item)))
template <typename T, DN_USize N> DN_Slice<T> DN_Slice_InitCArrayCopy (DN_Arena *arena, T const (&array)[N]); DN_API void DN_RingRead (DN_Ring *ring, void *dest, DN_U64 dest_size);
template <typename T> DN_Slice<T> DN_Slice_Copy (DN_Arena *arena, DN_Slice<T> slice); #define DN_RingReadStruct(ring, dest) DN_RingRead((ring), (dest), sizeof(*(dest)))
template <typename T> DN_Slice<T> DN_Slice_CopyPtr (DN_Arena *arena, T* const data, DN_USize size);
template <typename T> DN_Slice<T> DN_Slice_Alloc (DN_Arena *arena, DN_USize size, DN_ZMem z_mem);
DN_Str8 DN_Slice_Str8Render (DN_Arena *arena, DN_Slice<DN_Str8> array, DN_Str8 separator);
DN_Str8 DN_Slice_Str8RenderSpaceSeparated (DN_Arena *arena, DN_Slice<DN_Str8> array);
DN_Str16 DN_Slice_Str16Render (DN_Arena *arena, DN_Slice<DN_Str16> array, DN_Str16 separator);
DN_Str16 DN_Slice_Str16RenderSpaceSeparated(DN_Arena *arena, DN_Slice<DN_Str16> array);
#endif // !defined(DN_NO_SLICE)
#if !defined(DN_NO_DSMAP) template <typename T> DN_DSMap<T> DN_DSMapInit (DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags);
template <typename T> DN_DSMap<T> DN_DSMap_Init (DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags); template <typename T> void DN_DSMapDeinit (DN_DSMap<T> *map, DN_ZMem z_mem);
template <typename T> void DN_DSMap_Deinit (DN_DSMap<T> *map, DN_ZMem z_mem); template <typename T> bool DN_DSMapIsValid (DN_DSMap<T> const *map);
template <typename T> bool DN_DSMap_IsValid (DN_DSMap<T> const *map); template <typename T> DN_U32 DN_DSMapHash (DN_DSMap<T> const *map, DN_DSMapKey key);
template <typename T> DN_U32 DN_DSMap_Hash (DN_DSMap<T> const *map, DN_DSMapKey key); template <typename T> DN_U32 DN_DSMapHashToSlotIndex (DN_DSMap<T> const *map, DN_DSMapKey key);
template <typename T> DN_U32 DN_DSMap_HashToSlotIndex (DN_DSMap<T> const *map, DN_DSMapKey key); template <typename T> DN_DSMapResult<T> DN_DSMapFind (DN_DSMap<T> const *map, DN_DSMapKey key);
template <typename T> DN_DSMapResult<T> DN_DSMap_Find (DN_DSMap<T> const *map, DN_DSMapKey key); template <typename T> DN_DSMapResult<T> DN_DSMapMake (DN_DSMap<T> *map, DN_DSMapKey key);
template <typename T> DN_DSMapResult<T> DN_DSMap_Make (DN_DSMap<T> *map, DN_DSMapKey key); template <typename T> DN_DSMapResult<T> DN_DSMapSet (DN_DSMap<T> *map, DN_DSMapKey key, T const &value);
template <typename T> DN_DSMapResult<T> DN_DSMap_Set (DN_DSMap<T> *map, DN_DSMapKey key, T const &value); template <typename T> DN_DSMapResult<T> DN_DSMapFindKeyU64 (DN_DSMap<T> const *map, DN_U64 key);
template <typename T> DN_DSMapResult<T> DN_DSMap_FindKeyU64 (DN_DSMap<T> const *map, DN_U64 key); template <typename T> DN_DSMapResult<T> DN_DSMapMakeKeyU64 (DN_DSMap<T> *map, DN_U64 key);
template <typename T> DN_DSMapResult<T> DN_DSMap_MakeKeyU64 (DN_DSMap<T> *map, DN_U64 key); template <typename T> DN_DSMapResult<T> DN_DSMapSetKeyU64 (DN_DSMap<T> *map, DN_U64 key, T const &value);
template <typename T> DN_DSMapResult<T> DN_DSMap_SetKeyU64 (DN_DSMap<T> *map, DN_U64 key, T const &value); template <typename T> DN_DSMapResult<T> DN_DSMapFindKeyStr8 (DN_DSMap<T> const *map, DN_Str8 key);
template <typename T> DN_DSMapResult<T> DN_DSMap_FindKeyStr8 (DN_DSMap<T> const *map, DN_Str8 key); template <typename T> DN_DSMapResult<T> DN_DSMapMakeKeyStr8 (DN_DSMap<T> *map, DN_Str8 key);
template <typename T> DN_DSMapResult<T> DN_DSMap_MakeKeyStr8 (DN_DSMap<T> *map, DN_Str8 key); template <typename T> DN_DSMapResult<T> DN_DSMapSetKeyStr8 (DN_DSMap<T> *map, DN_Str8 key, T const &value);
template <typename T> DN_DSMapResult<T> DN_DSMap_SetKeyStr8 (DN_DSMap<T> *map, DN_Str8 key, T const &value); template <typename T> bool DN_DSMapResize (DN_DSMap<T> *map, DN_U32 size);
template <typename T> bool DN_DSMap_Resize (DN_DSMap<T> *map, DN_U32 size); template <typename T> bool DN_DSMapErase (DN_DSMap<T> *map, DN_DSMapKey key);
template <typename T> bool DN_DSMap_Erase (DN_DSMap<T> *map, DN_DSMapKey key); template <typename T> bool DN_DSMapEraseKeyU64 (DN_DSMap<T> *map, DN_U64 key);
template <typename T> bool DN_DSMap_EraseKeyU64 (DN_DSMap<T> *map, DN_U64 key); template <typename T> bool DN_DSMapEraseKeyStr8 (DN_DSMap<T> *map, DN_Str8 key);
template <typename T> bool DN_DSMap_EraseKeyStr8 (DN_DSMap<T> *map, DN_Str8 key); template <typename T> DN_DSMapKey DN_DSMapKeyBuffer (DN_DSMap<T> const *map, void const *data, DN_U32 size);
template <typename T> DN_DSMapKey DN_DSMap_KeyBuffer (DN_DSMap<T> const *map, void const *data, DN_U32 size); template <typename T> DN_DSMapKey DN_DSMapKeyBufferAsU64NoHash (DN_DSMap<T> const *map, void const *data, DN_U32 size);
template <typename T> DN_DSMapKey DN_DSMap_KeyBufferAsU64NoHash (DN_DSMap<T> const *map, void const *data, DN_U32 size); template <typename T> DN_DSMapKey DN_DSMapKeyU64 (DN_DSMap<T> const *map, DN_U64 u64);
template <typename T> DN_DSMapKey DN_DSMap_KeyU64 (DN_DSMap<T> const *map, DN_U64 u64); template <typename T> DN_DSMapKey DN_DSMapKeyStr8 (DN_DSMap<T> const *map, DN_Str8 string);
template <typename T> DN_DSMapKey DN_DSMap_KeyStr8 (DN_DSMap<T> const *map, DN_Str8 string); #define DN_DSMapKeyCStr8(map, string) DN_DSMapKeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1)
#define DN_DSMap_KeyCStr8(map, string) DN_DSMap_KeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1) DN_API DN_DSMapKey DN_DSMapKeyU64NoHash (DN_U64 u64);
DN_API DN_DSMapKey DN_DSMap_KeyU64NoHash (DN_U64 u64); DN_API bool DN_DSMapKeyEquals (DN_DSMapKey lhs, DN_DSMapKey rhs);
DN_API bool DN_DSMap_KeyEquals (DN_DSMapKey lhs, DN_DSMapKey rhs);
DN_API bool operator== (DN_DSMapKey lhs, DN_DSMapKey rhs); DN_API bool operator== (DN_DSMapKey lhs, DN_DSMapKey rhs);
#endif // !defined(DN_NO_DSMAP)
#if !defined(DN_NO_LIST)
template <typename T> DN_List<T> DN_List_Init (DN_USize chunk_size);
template <typename T, size_t N> DN_List<T> DN_List_InitCArray (DN_Arena *arena, DN_USize chunk_size, T const (&array)[N]);
template <typename T> T * DN_List_At (DN_List<T> *list, DN_USize index, DN_ListChunk<T> **at_chunk);
template <typename T> void DN_List_Clear (DN_List<T> *list);
template <typename T> bool DN_List_Iterate (DN_List<T> *list, DN_ListIterator<T> *it, DN_USize start_index);
template <typename T> T * DN_List_MakeArena (DN_List<T> *list, DN_Arena *arena, DN_USize count);
template <typename T> T * DN_List_MakePool (DN_List<T> *list, DN_Pool *pool, DN_USize count);
template <typename T> T * DN_List_AddArena (DN_List<T> *list, DN_Arena *arena, T const &value);
template <typename T> T * DN_List_AddPool (DN_List<T> *list, DN_Pool *pool, T const &value);
template <typename T> void DN_List_AddListArena (DN_List<T> *list, DN_Arena *arena, DN_List<T> other);
template <typename T> void DN_List_AddListArena (DN_List<T> *list, DN_Pool *pool, DN_List<T> other);
template <typename T> DN_Slice<T> DN_List_ToSliceCopy (DN_List<T> const *list, DN_Arena* arena);
#endif // !defined(DN_NO_LIST)
#endif // !defined(DN_CONTAINER_H) #endif // !defined(DN_CONTAINER_H)

View File

@ -15,12 +15,9 @@ DN_API void DN_LeakTrackAlloc_(DN_LeakTracker *leak, void *ptr, DN_USize size, b
DN_TicketMutex_End(&leak->alloc_table_mutex); DN_TicketMutex_End(&leak->alloc_table_mutex);
}; };
// NOTE: If the entry was not added, we are reusing a pointer that has been freed.
// TODO: Add API for always making the item but exposing a var to indicate if the item was newly created or it
// already existed.
DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/); DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/);
DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table; DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table;
DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMap_MakeKeyU64(alloc_table, DN_Cast(DN_U64) ptr); DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMapMakeKeyU64(alloc_table, DN_Cast(DN_U64) ptr);
DN_LeakAlloc *alloc = alloc_entry.value; DN_LeakAlloc *alloc = alloc_entry.value;
if (alloc_entry.found) { if (alloc_entry.found) {
if ((alloc->flags & DN_LeakAllocFlag_Freed) == 0) { if ((alloc->flags & DN_LeakAllocFlag_Freed) == 0) {
@ -76,7 +73,7 @@ DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr)
DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/); DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/);
DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table; DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table;
DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMap_FindKeyU64(alloc_table, DN_Cast(uintptr_t) ptr); DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMapFindKeyU64(alloc_table, DN_Cast(uintptr_t) ptr);
DN_HardAssertF(alloc_entry.found, DN_HardAssertF(alloc_entry.found,
"Allocated pointer can not be removed as it does not exist in the " "Allocated pointer can not be removed as it does not exist in the "
"allocation table. When this memory was allocated, the pointer was " "allocation table. When this memory was allocated, the pointer was "
@ -128,7 +125,7 @@ DN_API void DN_LeakDump_(DN_LeakTracker *leak)
leaked_bytes += alloc->size; leaked_bytes += alloc->size;
leak_count++; leak_count++;
DN_Str8x32 alloc_size = DN_ByteCountStr8x32(alloc->size); DN_Str8x32 alloc_size = DN_ByteCountStr8x32(alloc->size);
DN_LOG_WarningF( DN_LogWarningF(
"Pointer (0x%p) leaked %.*s at:\n" "Pointer (0x%p) leaked %.*s at:\n"
"%.*s", "%.*s",
alloc->ptr, alloc->ptr,
@ -139,6 +136,6 @@ DN_API void DN_LeakDump_(DN_LeakTracker *leak)
if (leak_count) { if (leak_count) {
DN_Str8x32 leak_size = DN_ByteCountStr8x32(leaked_bytes); DN_Str8x32 leak_size = DN_ByteCountStr8x32(leaked_bytes);
DN_LOG_WarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_Str8PrintFmt(leak_size)); DN_LogWarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_Str8PrintFmt(leak_size));
} }
} }

View File

@ -2,7 +2,7 @@
#define DN_BASE_LEAK_H #define DN_BASE_LEAK_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
enum DN_LeakAllocFlag enum DN_LeakAllocFlag

View File

@ -1,130 +0,0 @@
#define DN_BASE_LOG_CPP
#if defined(_CLANDG)
#include "../dn.h"
#endif
static DN_LOGEmitFromTypeFVFunc *g_dn_base_log_emit_from_type_fv_func_;
static void *g_dn_base_log_emit_from_type_fv_user_context_;
DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType colour, DN_U8 r, DN_U8 g, DN_U8 b)
{
DN_THREAD_LOCAL char buffer[32];
buffer[0] = 0;
DN_Str8 result = {};
result.size = DN_SNPrintF(buffer,
DN_ArrayCountU(buffer),
"\x1b[%d;2;%u;%u;%um",
colour == DN_LOGColourType_Fg ? 38 : 48,
r,
g,
b);
result.data = buffer;
return result;
}
DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromU32(DN_LOGColourType colour, DN_U32 value)
{
DN_U8 r = DN_Cast(DN_U8)(value >> 24);
DN_U8 g = DN_Cast(DN_U8)(value >> 16);
DN_U8 b = DN_Cast(DN_U8)(value >> 8);
DN_Str8 result = DN_LOG_ColourEscapeCodeStr8FromRGB(colour, r, g, b);
return result;
}
DN_API DN_LOGPrefixSize DN_LOG_MakePrefix(DN_LOGStyle style, DN_LOGTypeParam type, DN_CallSite call_site, DN_LOGDate date, char *dest, DN_USize dest_size)
{
DN_Str8 type_str8 = type.str8;
if (type.is_u32_enum) {
switch (type.u32) {
case DN_LOGType_Debug: type_str8 = DN_Str8Lit("DEBUG"); break;
case DN_LOGType_Info: type_str8 = DN_Str8Lit("INFO "); break;
case DN_LOGType_Warning: type_str8 = DN_Str8Lit("WARN"); break;
case DN_LOGType_Error: type_str8 = DN_Str8Lit("ERROR"); break;
case DN_LOGType_Count: type_str8 = DN_Str8Lit("BADXX"); break;
}
}
static DN_USize max_type_length = 0;
max_type_length = DN_Max(max_type_length, type_str8.size);
int type_padding = DN_Cast(int)(max_type_length - type_str8.size);
DN_Str8 colour_esc = {};
DN_Str8 bold_esc = {};
DN_Str8 reset_esc = {};
if (style.colour) {
bold_esc = DN_Str8Lit(DN_LOG_BoldEscapeCode);
reset_esc = DN_Str8Lit(DN_LOG_ResetEscapeCode);
colour_esc = DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b);
}
DN_Str8 file_name = DN_Str8FileNameFromPath(call_site.file);
DN_GCC_WARNING_PUSH
DN_GCC_WARNING_DISABLE(-Wformat)
DN_GCC_WARNING_DISABLE(-Wformat-extra-args)
DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(4477)
int size = DN_SNPrintF(dest,
DN_Cast(int)dest_size,
"%04u-%02u-%02uT%02u:%02u:%02u" // date
"%S" // colour
"%S" // bold
" %S" // type
"%.*s" // type padding
"%S" // reset
" %S" // file name
":%05I32u " // line number
,
date.year,
date.month,
date.day,
date.hour,
date.minute,
date.second,
colour_esc, // colour
bold_esc, // bold
type_str8, // type
DN_Cast(int) type_padding,
"", // type padding
reset_esc, // reset
file_name, // file name
call_site.line); // line number
DN_MSVC_WARNING_POP // '%S' requires an argument of type 'wchar_t *', but variadic argument 7 has type 'DN_Str8'
DN_GCC_WARNING_POP
static DN_USize max_header_length = 0;
DN_USize size_no_ansi_codes = size - colour_esc.size - reset_esc.size - bold_esc.size;
max_header_length = DN_Max(max_header_length, size_no_ansi_codes);
DN_USize header_padding = max_header_length - size_no_ansi_codes;
DN_LOGPrefixSize result = {};
result.size = size;
result.padding = header_padding;
return result;
}
DN_API void DN_LOG_SetEmitFromTypeFVFunc(DN_LOGEmitFromTypeFVFunc *print_func, void *user_data)
{
g_dn_base_log_emit_from_type_fv_func_ = print_func;
g_dn_base_log_emit_from_type_fv_user_context_ = user_data;
}
DN_API void DN_LOG_EmitFromType(DN_LOGTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...)
{
DN_LOGEmitFromTypeFVFunc *func = g_dn_base_log_emit_from_type_fv_func_;
void *user_context = g_dn_base_log_emit_from_type_fv_user_context_;
if (func) {
va_list args;
va_start(args, fmt);
func(type, user_context, call_site, fmt, args);
va_end(args);
}
}
DN_API DN_LOGTypeParam DN_LOG_MakeU32LogTypeParam(DN_LOGType type)
{
DN_LOGTypeParam result = {};
result.is_u32_enum = true;
result.u32 = type;
return result;
}

View File

@ -1,74 +0,0 @@
#if !defined(DN_BASE_LOG_H)
#define DN_BASE_LOG_H
#if defined(_CLANGD)
#include "../dn.h"
#endif
enum DN_LOGType
{
DN_LOGType_Debug,
DN_LOGType_Info,
DN_LOGType_Warning,
DN_LOGType_Error,
DN_LOGType_Count,
};
enum DN_LOGBold
{
DN_LOGBold_No,
DN_LOGBold_Yes,
};
struct DN_LOGStyle
{
DN_LOGBold bold;
bool colour;
DN_U8 r, g, b;
};
struct DN_LOGTypeParam
{
bool is_u32_enum;
DN_U32 u32;
DN_Str8 str8;
};
enum DN_LOGColourType
{
DN_LOGColourType_Fg,
DN_LOGColourType_Bg,
};
struct DN_LOGDate
{
DN_U16 year;
DN_U8 month;
DN_U8 day;
DN_U8 hour;
DN_U8 minute;
DN_U8 second;
};
struct DN_LOGPrefixSize
{
DN_USize size;
DN_USize padding;
};
typedef void DN_LOGEmitFromTypeFVFunc(DN_LOGTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
#define DN_LOG_ResetEscapeCode "\x1b[0m"
#define DN_LOG_BoldEscapeCode "\x1b[1m"
DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType colour, DN_U8 r, DN_U8 g, DN_U8 b);
DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromU32(DN_LOGColourType colour, DN_U32 value);
DN_API DN_LOGPrefixSize DN_LOG_MakePrefix (DN_LOGStyle style, DN_LOGTypeParam type, DN_CallSite call_site, DN_LOGDate date, char *dest, DN_USize dest_size);
DN_API void DN_LOG_SetEmitFromTypeFVFunc (DN_LOGEmitFromTypeFVFunc *print_func, void *user_data);
DN_API void DN_LOG_EmitFromType (DN_LOGTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_LOGTypeParam DN_LOG_MakeU32LogTypeParam (DN_LOGType type);
#define DN_LOG_DebugF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Debug), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LOG_InfoF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LOG_WarningF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LOG_ErrorF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#endif // !defined(DN_BASE_LOG_H)

View File

@ -1,60 +0,0 @@
#if !defined(DN_BASE_OS_H)
#define DN_BASE_OS_H
#if defined(_CLANGD)
#include "../dn.h"
#endif
// NOTE: OS primitives that the OS layer can provide for the base layer but is optional.
struct DN_StackTraceFrame
{
DN_U64 address;
DN_U64 line_number;
DN_Str8 file_name;
DN_Str8 function_name;
};
struct DN_StackTraceRawFrame
{
void *process;
DN_U64 base_addr;
};
struct DN_StackTraceWalkResult
{
void *process; // [Internal] Windows handle to the process
DN_U64 *base_addr; // The addresses of the functions in the stack trace
DN_U16 size; // The number of `base_addr`'s stored from the walk
};
struct DN_StackTraceWalkResultIterator
{
DN_StackTraceRawFrame raw_frame;
DN_U16 index;
};
#if defined(DN_FREESTANDING)
#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalk(...)
#define DN_StackTraceWalkResultIterate(...)
#define DN_StackTraceWalkResultToStr8(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalkStr8(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A")
#define DN_StackTraceGetFrames(...)
#define DN_StackTraceRawFrameToFrame(...)
#define DN_StackTracePrint(...)
#define DN_StackTraceReloadSymbols(...)
#else
DN_API DN_StackTraceWalkResult DN_StackTraceWalk (struct DN_Arena *arena, DN_U16 limit);
DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk);
DN_API DN_Str8 DN_StackTraceWalkResultToStr8 (struct DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip);
DN_API DN_Str8 DN_StackTraceWalkStr8 (struct DN_Arena *arena, DN_U16 limit, DN_U16 skip);
DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap (DN_U16 limit, DN_U16 skip);
DN_API DN_Slice<DN_StackTraceFrame> DN_StackTraceGetFrames (struct DN_Arena *arena, DN_U16 limit);
DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame (struct DN_Arena *arena, DN_StackTraceRawFrame raw_frame);
DN_API void DN_StackTracePrint (DN_U16 limit);
DN_API void DN_StackTraceReloadSymbols ();
#endif
#endif // !defined(DN_BASE_OS_H)

View File

@ -1,8 +1,8 @@
#define DN_ASYNC_CPP #define DN_ASYNC_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#include "dn_async.h" #include "dn_async.h"
#endif #endif
@ -18,8 +18,8 @@ static DN_I32 DN_ASYNC_ThreadEntryPoint_(DN_OSThread *thread)
DN_ASYNCTask task = {}; DN_ASYNCTask task = {};
for (DN_OS_MutexScope(&async->ring_mutex)) { for (DN_OS_MutexScope(&async->ring_mutex)) {
if (DN_Ring_HasData(ring, sizeof(task))) if (DN_RingHasData(ring, sizeof(task)))
DN_Ring_Read(ring, &task, sizeof(task)); DN_RingRead(ring, &task, sizeof(task));
} }
if (task.work.func) { if (task.work.func) {
@ -72,8 +72,8 @@ static bool DN_ASYNC_QueueTask_(DN_ASYNCCore *async, DN_ASYNCTask const *task, D
bool result = false; bool result = false;
for (DN_OS_MutexScope(&async->ring_mutex)) { for (DN_OS_MutexScope(&async->ring_mutex)) {
for (;;) { for (;;) {
if (DN_Ring_HasSpace(&async->ring, sizeof(*task))) { if (DN_RingHasSpace(&async->ring, sizeof(*task))) {
DN_Ring_WriteStruct(&async->ring, task); DN_RingWriteStruct(&async->ring, task);
result = true; result = true;
break; break;
} }

View File

@ -2,8 +2,8 @@
#define DN_ASYNC_H #define DN_ASYNC_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#endif #endif
enum DN_ASYNCPriority enum DN_ASYNCPriority

View File

@ -2,11 +2,7 @@
#define DN_BIN_PACK_H #define DN_BIN_PACK_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif
#if !defined(DN_BASE_INC_H)
#error dn_base_inc.h must be included before this
#endif #endif
enum DN_BinPackMode enum DN_BinPackMode

View File

@ -63,7 +63,7 @@ DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST[]
DN_CGenTableHeaderType_Name, DN_CGenTableHeaderType_Name,
}; };
static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_OSErrSink *err) static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_ErrSink *err)
{ {
bool result = false; bool result = false;
if (!cgen || !cgen->file_list || !cgen->arena) if (!cgen || !cgen->file_list || !cgen->arena)
@ -283,7 +283,7 @@ static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_OSErrSink *err)
return result; return result;
} }
DN_API DN_CGen DN_CGen_FromFilesArgV(int argc, char const **argv, DN_OSErrSink *err) DN_API DN_CGen DN_CGen_FromFilesArgV(int argc, char const **argv, DN_ErrSink *err)
{ {
DN_CGen result = {}; DN_CGen result = {};
result.arena = MD_ArenaAlloc(); result.arena = MD_ArenaAlloc();
@ -341,7 +341,7 @@ DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_
if (result.enum_val == 0) { if (result.enum_val == 0) {
MD_CodeLoc loc = MD_CodeLocFromNode(DN_Cast(MD_Node *) node); MD_CodeLoc loc = MD_CodeLocFromNode(DN_Cast(MD_Node *) node);
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
DN_Str8 user_msg = DN_Str8FromFmtVArena(tmem.arena, fmt, args); DN_Str8 user_msg = DN_Str8FromFmtVArena(tmem.arena, fmt, args);
@ -357,6 +357,7 @@ DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_
} }
DN_Str8 error_msg = DN_Str8BuilderBuild(&builder, tmem.arena); DN_Str8 error_msg = DN_Str8BuilderBuild(&builder, tmem.arena);
DN_TCScratchEnd(&tmem);
MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Error, DN_Cast(char *) "%.*s", DN_Str8PrintFmt(error_msg)); MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Error, DN_Cast(char *) "%.*s", DN_Str8PrintFmt(error_msg));
DN_OS_Exit(DN_Cast(uint32_t) - 1); DN_OS_Exit(DN_Cast(uint32_t) - 1);
} }
@ -371,13 +372,14 @@ DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node)
return result; return result;
} }
DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err, char const *fmt, ...) DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_ErrSink *err, char const *fmt, ...)
{ {
if (!err) if (!err)
return; return;
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8Builder builder = DN_Str8BuilderFromTLS(); DN_Str8Builder builder = {};
builder.arena = tmem.arena;
MD_String8 kind_string = MD_StringFromMessageKind(kind); MD_String8 kind_string = MD_StringFromMessageKind(kind);
MD_CodeLoc loc = MD_CodeLocFromNode(node); MD_CodeLoc loc = MD_CodeLocFromNode(node);
@ -388,14 +390,15 @@ DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err,
DN_Str8BuilderAppendFV(&builder, fmt, args); DN_Str8BuilderAppendFV(&builder, fmt, args);
va_end(args); va_end(args);
DN_Str8 msg = DN_Str8BuilderBuild(&builder, tmem.arena); DN_Str8 msg = DN_Str8BuilderBuild(&builder, err->arena);
DN_TCScratchEnd(&tmem);
DN_OS_ErrSinkAppendF(err, DN_Cast(uint32_t) - 1, "%.*s", DN_Str8PrintFmt(msg)); DN_OS_ErrSinkAppendF(err, DN_Cast(uint32_t) - 1, "%.*s", DN_Str8PrintFmt(msg));
} }
DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_OSErrSink *err) DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_ErrSink *err)
{ {
bool result = true; bool result = true;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8Builder builder = {}; DN_Str8Builder builder = {};
builder.arena = tmem.arena; builder.arena = tmem.arena;
@ -419,6 +422,7 @@ DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *he
DN_Str8PrintFmt(missing_headers)); DN_Str8PrintFmt(missing_headers));
} }
DN_TCScratchEnd(&tmem);
return result; return result;
} }
@ -515,13 +519,14 @@ static void DN_CGen_EmitRowWhitespace_(DN_CGenTableRow const *row, DN_CppFile *c
if (tag->comment.size <= 0) if (tag->comment.size <= 0)
break; break;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 prefix = DN_Str8FromFmtArena(tmem.arena, "// NOTE: %.*s ", MD_S8VArg(tag->comment)); DN_Str8 prefix = DN_Str8FromFmtArena(tmem.arena, "// NOTE: %.*s ", MD_S8VArg(tag->comment));
int line_padding = DN_Max(100 - (DN_Cast(int) prefix.size + (DN_CppSpacePerIndent(cpp) * cpp->indent)), 0); int line_padding = DN_Max(100 - (DN_Cast(int) prefix.size + (DN_CppSpacePerIndent(cpp) * cpp->indent)), 0);
DN_CppPrint(cpp, "%.*s", DN_Str8PrintFmt(prefix)); DN_CppPrint(cpp, "%.*s", DN_Str8PrintFmt(prefix));
for (int index = 0; index < line_padding; index++) for (int index = 0; index < line_padding; index++)
DN_CppAppend(cpp, "/"); DN_CppAppend(cpp, "/");
DN_CppAppend(cpp, "\n"); DN_CppAppend(cpp, "\n");
DN_TCScratchEnd(&tmem);
} break; } break;
case DN_CGenTableRowTagType_EmptyLine: { case DN_CGenTableRowTagType_EmptyLine: {
@ -533,17 +538,18 @@ static void DN_CGen_EmitRowWhitespace_(DN_CGenTableRow const *row, DN_CppFile *c
DN_Str8 DN_CGen_ConvertTemplatesToEmittableLiterals_(DN_Arena *arena, DN_Str8 type) DN_Str8 DN_CGen_ConvertTemplatesToEmittableLiterals_(DN_Arena *arena, DN_Str8 type)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); DN_TCScratch tmem = DN_TCScratchBegin(&arena, 1);
DN_Str8 result = DN_Str8TrimWhitespaceAround(type); DN_Str8 result = DN_Str8TrimWhitespaceAround(type);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("<"), /*replace*/ DN_Str8Lit("_"), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("<"), /*replace*/ DN_Str8Lit("_"), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(">"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(">"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive);
result = DN_Str8TrimWhitespaceAround(result); result = DN_Str8TrimWhitespaceAround(result);
DN_TCScratchEnd(&tmem);
return result; return result;
} }
DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type) DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); DN_TCScratch tmem = DN_TCScratchBegin(&arena, 1);
DN_Str8 result = DN_Str8TrimWhitespaceAround(type); DN_Str8 result = DN_Str8TrimWhitespaceAround(type);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("*"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("*"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("constexpr"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("constexpr"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive);
@ -551,6 +557,7 @@ DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type)
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("static"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("static"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(" "), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(" "), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive);
result = DN_Str8TrimWhitespaceAround(result); result = DN_Str8TrimWhitespaceAround(result);
DN_TCScratchEnd(&tmem);
return result; return result;
} }
@ -563,9 +570,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_CppLine(cpp, "%.*sType_Nil,", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "%.*sType_Nil,", DN_Str8PrintFmt(emit_prefix));
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next)
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string); DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string);
DN_CppLine(cpp, "%.*sType_%.*s,", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(enum_name)); DN_CppLine(cpp, "%.*sType_%.*s,", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(enum_name));
DN_TCScratchEnd(&tmem);
} }
DN_CppLine(cpp, "%.*sType_Count,", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "%.*sType_Count,", DN_Str8PrintFmt(emit_prefix));
} }
@ -584,7 +592,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
// TODO(doyle): Verify the codegen table has the headers from the table it references // TODO(doyle): Verify the codegen table has the headers from the table it references
int longest_type_name = 0; int longest_type_name = 0;
for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_CGenTableRow const *row = it.table->rows + row_index; DN_CGenTableRow const *row = it.table->rows + row_index;
DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppType].string, row); DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppType].string, row);
@ -594,6 +602,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
length += emit_prefix.size; length += emit_prefix.size;
longest_type_name = DN_Max(longest_type_name, DN_Cast(int) length); longest_type_name = DN_Max(longest_type_name, DN_Cast(int) length);
DN_TCScratchEnd(&tmem);
} }
DN_CppStructBlock(cpp, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(it.cgen_table_column[DN_CGenTableHeaderType_Name].string)) DN_CppStructBlock(cpp, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(it.cgen_table_column[DN_CGenTableHeaderType_Name].string))
@ -606,8 +615,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
if (cpp_name.column.string.size <= 0 || cpp_type.column.string.size <= 0) if (cpp_name.column.string.size <= 0 || cpp_type.column.string.size <= 0)
continue; continue;
// NOTE: Generate cpp array size /////////////////////////////////// // NOTE: Generate cpp array size
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 array_size = {}; DN_Str8 array_size = {};
if (cpp_array_size.column.string.size) if (cpp_array_size.column.string.size)
array_size = DN_Str8FromFmtArena(tmem.arena, "[%.*s]", DN_Str8PrintFmt(cpp_array_size.column.string)); array_size = DN_Str8FromFmtArena(tmem.arena, "[%.*s]", DN_Str8PrintFmt(cpp_array_size.column.string));
@ -620,6 +629,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
if (DN_CGen_WillCodeGenTypeName(cgen, find_name)) if (DN_CGen_WillCodeGenTypeName(cgen, find_name))
emit_cpp_type = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type.column.string)); emit_cpp_type = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type.column.string));
} }
DN_TCScratchEnd(&tmem);
int name_to_type_padding = 1 + longest_type_name - DN_Cast(int) emit_cpp_type.size; int name_to_type_padding = 1 + longest_type_name - DN_Cast(int) emit_cpp_type.size;
@ -803,7 +813,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
// for types that are declared in the same mdesk file. We will also // for types that are declared in the same mdesk file. We will also
// calculate the longest type name that we will generate for whitespace // calculate the longest type name that we will generate for whitespace
// padding purposes. // padding purposes.
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_USize longest_cpp_type_name = 0; DN_USize longest_cpp_type_name = 0;
auto cpp_type_list = DN_SArray_Init<DN_Str8>(tmem.arena, it.table->row_count, DN_ZMem_Yes); auto cpp_type_list = DN_SArray_Init<DN_Str8>(tmem.arena, it.table->row_count, DN_ZMem_Yes);
@ -814,7 +824,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
// NOTE: CHeck the length of the string after turning it into emittable code // NOTE: CHeck the length of the string after turning it into emittable code
DN_Str8 cpp_type_name = DN_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string); DN_Str8 cpp_type_name = DN_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string);
if (DN_CGen_WillCodeGenTypeName(cgen, cpp_type_name)) if (DN_CGen_WillCodeGenTypeName(cgen, cpp_type_name))
cpp_type_name = DN_Str8FromTLSF("%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type_name)); cpp_type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type_name));
DN_Str8 cpp_type_name_no_templates = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, cpp_type_name); DN_Str8 cpp_type_name_no_templates = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, cpp_type_name);
longest_cpp_type_name = DN_Max(longest_cpp_type_name, cpp_type_name_no_templates.size); longest_cpp_type_name = DN_Max(longest_cpp_type_name, cpp_type_name_no_templates.size);
@ -849,7 +859,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
index_the_field_references = sub_row_index; index_the_field_references = sub_row_index;
} }
cpp_array_size_field_str8 = cpp_array_size_field_str8 =
DN_Str8FromTLSF("&g_%.*s%.*s_type_fields[%zu]", DN_Str8FromFmtArena(tmem.arena, "&g_%.*s%.*s_type_fields[%zu]",
DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(emit_prefix),
DN_Str8PrintFmt(struct_name.string), DN_Str8PrintFmt(struct_name.string),
index_the_field_references); index_the_field_references);
@ -862,7 +872,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size;
DN_USize cpp_type_padding = 1 + longest_cpp_type_name - cpp_type_name.size; DN_USize cpp_type_padding = 1 + longest_cpp_type_name - cpp_type_name.size;
DN_Str8 cpp_type_enum = DN_Str8FromTLSF("%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(orig_cpp_type_no_templates)); DN_Str8 cpp_type_enum = DN_Str8FromFmtArena(tmem.arena, "%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(orig_cpp_type_no_templates));
DN_USize cpp_type_enum_padding = cpp_type_padding + (orig_cpp_type.size - cpp_type_name.size); DN_USize cpp_type_enum_padding = cpp_type_padding + (orig_cpp_type.size - cpp_type_name.size);
DN_Str8 cpp_label_str8 = cpp_name.column.string; DN_Str8 cpp_label_str8 = cpp_name.column.string;
@ -960,10 +970,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
if (cpp_name.column.string.size <= 0) if (cpp_name.column.string.size <= 0)
continue; continue;
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size;
DN_Str8 cpp_value_str8 = cpp_value.column.string.size ? cpp_value.column.string : DN_Str8FromTLSF("%zu", row_index); DN_Str8 cpp_value_str8 = cpp_value.column.string.size ? cpp_value.column.string : DN_Str8FromFmtArena(tmem.arena, "%zu", row_index);
DN_Str8 cpp_type_enum = DN_Str8FromTLSF("%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(struct_or_enum_name)); DN_Str8 cpp_type_enum = DN_Str8FromFmtArena(tmem.arena, "%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(struct_or_enum_name));
DN_Str8 cpp_label_str8 = cpp_name.column.string; DN_Str8 cpp_label_str8 = cpp_name.column.string;
DN_USize cpp_label_str8_padding = cpp_name_padding; DN_USize cpp_label_str8_padding = cpp_name_padding;
@ -972,7 +982,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
cpp_label_str8_padding = 1 + it.table->headers[cpp_label.index].longest_string - cpp_label.column.string.size; cpp_label_str8_padding = 1 + it.table->headers[cpp_label.index].longest_string - cpp_label.column.string.size;
} }
DN_Str8Builder builder = DN_Str8BuilderFromTLS(); DN_Str8Builder builder = {};
builder.arena = tmem.arena;
// NOTE: row // NOTE: row
DN_Str8BuilderAppendF(&builder, "{%2d, ", row_index); DN_Str8BuilderAppendF(&builder, "{%2d, ", row_index);
@ -1015,10 +1026,12 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_Str8BuilderAppendF(&builder, "/*array_size*/ 0, "); DN_Str8BuilderAppendF(&builder, "/*array_size*/ 0, ");
DN_Str8BuilderAppendF(&builder, "/*array_size_field*/ NULL},"); DN_Str8BuilderAppendF(&builder, "/*array_size_field*/ NULL},");
DN_Str8 line = DN_Str8BuilderBuildFromTLS(&builder); DN_Str8 line = DN_Str8BuilderBuild(&builder, tmem.arena);
DN_TCScratchEnd(&tmem);
DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line)); DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line));
} }
} }
DN_TCScratchEnd(&tmem);
} }
} }
} }
@ -1026,12 +1039,13 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
int longest_name_across_all_tables = 0; int longest_name_across_all_tables = 0;
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string;
if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) if (DN_CGen_WillCodeGenTypeName(cgen, type_name))
type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name));
longest_name_across_all_tables = DN_Max(longest_name_across_all_tables, DN_Cast(int) type_name.size); longest_name_across_all_tables = DN_Max(longest_name_across_all_tables, DN_Cast(int) type_name.size);
DN_TCScratchEnd(&tmem);
} }
} }
@ -1042,20 +1056,21 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_USize longest_type_name = 0; DN_USize longest_type_name = 0;
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string;
if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) if (DN_CGen_WillCodeGenTypeName(cgen, type_name))
type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name));
longest_type_name = DN_Max(longest_type_name, type_name.size); longest_type_name = DN_Max(longest_type_name, type_name.size);
DN_TCScratchEnd(&tmem);
} }
} }
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string;
if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) if (DN_CGen_WillCodeGenTypeName(cgen, type_name))
type_name = DN_Str8FromTLSF("%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name));
int name_padding = 1 + longest_name_across_all_tables - DN_Cast(int) type_name.size; int name_padding = 1 + longest_name_across_all_tables - DN_Cast(int) type_name.size;
DN_Str8 type_info_kind = {}; DN_Str8 type_info_kind = {};
@ -1080,9 +1095,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_Str8 fields_count = DN_Str8Lit("0"); DN_Str8 fields_count = DN_Str8Lit("0");
if (!DN_Str8Eq(fields, DN_Str8Lit("NULL"))) if (!DN_Str8Eq(fields, DN_Str8Lit("NULL")))
fields_count = DN_Str8FromTLSF("sizeof(%.*s)/sizeof(%.*s[0])", DN_Str8PrintFmt(fields), DN_Str8PrintFmt(fields)); fields_count = DN_Str8FromFmtArena(tmem.arena, "sizeof(%.*s)/sizeof(%.*s[0])", DN_Str8PrintFmt(fields), DN_Str8PrintFmt(fields));
DN_Str8Builder builder = DN_Str8BuilderFromTLS(); DN_Str8Builder builder = {};
builder.arena = tmem.arena;
// NOTE: name // NOTE: name
DN_Str8BuilderAppendF(&builder, "{DN_Str8Lit(\"%.*s\"),%*s", DN_Str8PrintFmt(type_name), name_padding, ""); DN_Str8BuilderAppendF(&builder, "{DN_Str8Lit(\"%.*s\"),%*s", DN_Str8PrintFmt(type_name), name_padding, "");
@ -1101,7 +1117,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
// NOTE: DN_TypeField length // NOTE: DN_TypeField length
DN_Str8BuilderAppendF(&builder, "/*count*/ %.*s},", DN_Str8PrintFmt(fields_count)); DN_Str8BuilderAppendF(&builder, "/*count*/ %.*s},", DN_Str8PrintFmt(fields_count));
DN_Str8 line = DN_Str8BuilderBuildFromTLS(&builder); DN_Str8 line = DN_Str8BuilderBuild(&builder, tmem.arena);
DN_TCScratchEnd(&tmem);
DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line)); DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line));
} }
} }
@ -1115,7 +1132,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
{ {
DN_CppLine(cpp, "case %.*sType_Nil: break;", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "case %.*sType_Nil: break;", DN_Str8PrintFmt(emit_prefix));
DN_CppLine(cpp, "case %.*sType_Count: break;", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "case %.*sType_Count: break;", DN_Str8PrintFmt(emit_prefix));
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string); DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string);
@ -1129,6 +1146,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_CppLine(cpp, "case %.*s: result = g_%.*stypes + %.*s; break;", DN_Str8PrintFmt(full_enum_name), DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(full_enum_name)); DN_CppLine(cpp, "case %.*s: result = g_%.*stypes + %.*s; break;", DN_Str8PrintFmt(full_enum_name), DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(full_enum_name));
} }
} }
DN_TCScratchEnd(&tmem);
} }
DN_CppLine(cpp, "return result;"); DN_CppLine(cpp, "return result;");
} }

View File

@ -2,8 +2,8 @@
#define DN_CGEN_H #define DN_CGEN_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#include "../Standalone/dn_cpp_file.h" #include "../Standalone/dn_cpp_file.h"
#endif #endif
@ -38,27 +38,6 @@
#error Metadesk 'md.h' must be included before 'dn_cgen.h' #error Metadesk 'md.h' must be included before 'dn_cgen.h'
#endif #endif
#if !defined(DN_BASE_INC_H)
#error dn_base_inc.h must be included before this
#endif
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$\ $$$$$$$$\ $$\ $$\
// $$ __$$\ $$ __$$\ $$ _____|$$$\ $$ |
// $$ / \__|$$ / \__|$$ | $$$$\ $$ |
// $$ | $$ |$$$$\ $$$$$\ $$ $$\$$ |
// $$ | $$ |\_$$ |$$ __| $$ \$$$$ |
// $$ | $$\ $$ | $$ |$$ | $$ |\$$$ |
// \$$$$$$ |\$$$$$$ |$$$$$$$$\ $$ | \$$ |
// \______/ \______/ \________|\__| \__|
//
// dn_cgen.h -- C/C++ code generation from table data in Metadesk files
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
enum DN_CGenTableKeyType enum DN_CGenTableKeyType
{ {
DN_CGenTableKeyType_Nil, DN_CGenTableKeyType_Nil,
@ -194,12 +173,12 @@ enum DN_CGenEmit
(str8).size \ (str8).size \
} }
DN_API DN_CGen DN_CGen_InitFilesArgV(int argc, char const **argv, DN_OSErrSink *err); DN_API DN_CGen DN_CGen_InitFilesArgV(int argc, char const **argv, DN_ErrSink *err);
DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8(DN_CGenTableHeaderType type); DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8(DN_CGenTableHeaderType type);
DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_CGenMapNodeToEnum const *valid_keys, DN_USize valid_keys_size, char const *fmt, ...); DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_CGenMapNodeToEnum const *valid_keys, DN_USize valid_keys_size, char const *fmt, ...);
DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node); DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node);
DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err, char const *fmt, ...); DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_ErrSink *err, char const *fmt, ...);
DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_OSErrSink *err); DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_ErrSink *err);
DN_API DN_CGenLookupColumnAtHeader DN_CGen_LookupColumnAtHeader(DN_CGenTable *table, DN_Str8 header, DN_CGenTableRow const *row); DN_API DN_CGenLookupColumnAtHeader DN_CGen_LookupColumnAtHeader(DN_CGenTable *table, DN_Str8 header, DN_CGenTableRow const *row);
DN_API bool DN_CGen_LookupNextTableInCodeGenTable(DN_CGen *cgen, DN_CGenTable *cgen_table, DN_CGenLookupTableIterator *it); DN_API bool DN_CGen_LookupNextTableInCodeGenTable(DN_CGen *cgen, DN_CGenTable *cgen_table, DN_CGenLookupTableIterator *it);
DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFile *cpp, DN_Str8 emit_prefix); DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFile *cpp, DN_Str8 emit_prefix);

View File

@ -2,7 +2,7 @@
#define DN_CSV_H #define DN_CSV_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
enum DN_CSVSerialise enum DN_CSVSerialise

View File

@ -1,6 +1,5 @@
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#include "../dn_os_inc.h"
#endif #endif
DN_MSVC_WARNING_PUSH DN_MSVC_WARNING_PUSH
@ -31,10 +30,11 @@ void DN_Demo()
// NOTE: DN_HexFromBytes // NOTE: DN_HexFromBytes
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
unsigned char bytes[2] = {0xFA, 0xCE}; unsigned char bytes[2] = {0xFA, 0xCE};
DN_Str8 hex = DN_HexFromBytesPtrArena(bytes, sizeof(bytes), tmem.arena); DN_Str8 hex = DN_HexFromBytesPtrArena(bytes, sizeof(bytes), scratch.arena);
DN_Assert(DN_Str8Eq(hex, DN_Str8Lit("face"))); // NOTE: Guaranteed to be null-terminated DN_Assert(DN_Str8Eq(hex, DN_Str8Lit("face"))); // NOTE: Guaranteed to be null-terminated
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_BytesFromHex // NOTE: DN_BytesFromHex
@ -119,8 +119,8 @@ void DN_Demo()
// buffer, this buffer must be valid throughout the lifetime of the hash // buffer, this buffer must be valid throughout the lifetime of the hash
// table! // table!
{ {
// NOTE: DN_DSMap_Init // NOTE: DN_DSMapInit
// NOTE: DN_DSMap_Deinit // NOTE: DN_DSMapDeinit
// //
// Initialise a hash table where the table size *must* be a // Initialise a hash table where the table size *must* be a
// power-of-two, otherwise an assert will be triggered. If // power-of-two, otherwise an assert will be triggered. If
@ -139,15 +139,15 @@ void DN_Demo()
// A 'Deinit' of the map will similarly deallocate the passed in arena (as // A 'Deinit' of the map will similarly deallocate the passed in arena (as
// the map takes ownership of the arena). // the map takes ownership of the arena).
DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil);
DN_DSMap<int> map = DN_DSMap_Init<int>(&arena, /*size*/ 1024, DN_DSMapFlags_Nil); // Size must be PoT! DN_DSMap<int> map = DN_DSMapInit<int>(&arena, /*size*/ 1024, DN_DSMapFlags_Nil); // Size must be PoT!
DN_Assert(DN_DSMap_IsValid(&map)); // Valid if no initialisation failure (e.g. mem alloc failure) DN_Assert(DN_DSMapIsValid(&map)); // Valid if no initialisation failure (e.g. mem alloc failure)
// NOTE: DN_DSMap_KeyCStringLit // NOTE: DN_DSMapKeyCStringLit
// NOTE: DN_DSMap_KeyU64 // NOTE: DN_DSMapKeyU64
// NOTE: DN_DSMap_KeyU64NoHash // NOTE: DN_DSMapKeyU64NoHash
// NOTE: DN_DSMap_KeyBuffer // NOTE: DN_DSMapKeyBuffer
// NOTE: DN_DSMap_KeyStr8 // NOTE: DN_DSMapKeyStr8
// NOTE: DN_DSMap_KeyStr8Copy // NOTE: DN_DSMapKeyStr8Copy
// Create a hash-table key where: // Create a hash-table key where:
// //
// KeyCStringLit: Uses a Hash(cstring literal) // KeyCStringLit: Uses a Hash(cstring literal)
@ -168,11 +168,11 @@ void DN_Demo()
// already sufficiently uniformly distributed already (e.g. using 8 // already sufficiently uniformly distributed already (e.g. using 8
// bytes taken from a SHA256 hash as the key) and the first 4 bytes // bytes taken from a SHA256 hash as the key) and the first 4 bytes
// will be used verbatim. // will be used verbatim.
DN_DSMapKey key = DN_DSMap_KeyStr8(&map, DN_Str8Lit("Sample Key")); DN_DSMapKey key = DN_DSMapKeyStr8(&map, DN_Str8Lit("Sample Key"));
// NOTE: DN_DSMap_Find // NOTE: DN_DSMapFind
// NOTE: DN_DSMap_Make // NOTE: DN_DSMapMake
// NOTE: DN_DSMap_Set // NOTE: DN_DSMapSet
// //
// Query or commit key-value pair to the table, where: // Query or commit key-value pair to the table, where:
// //
@ -190,7 +190,7 @@ void DN_Demo()
// the table will be grown to 2x the current the size before insertion // the table will be grown to 2x the current the size before insertion
// completes. // completes.
{ {
DN_DSMapResult<int> set_result = DN_DSMap_Set(&map, key, 0xCAFE); DN_DSMapResult<int> set_result = DN_DSMapSet(&map, key, 0xCAFE);
DN_Assert(!set_result.found); // First time we are setting the key-value pair, it wasn't previously in the table DN_Assert(!set_result.found); // First time we are setting the key-value pair, it wasn't previously in the table
DN_Assert(map.occupied == 2); // Sentinel + new element == 2 DN_Assert(map.occupied == 2); // Sentinel + new element == 2
} }
@ -206,38 +206,38 @@ void DN_Demo()
DN_Assert(DN_Str8Eq(DN_Str8FromPtr(it_key.buffer_data, it_key.buffer_size), DN_Str8Lit("Sample Key"))); DN_Assert(DN_Str8Eq(DN_Str8FromPtr(it_key.buffer_data, it_key.buffer_size), DN_Str8Lit("Sample Key")));
} }
// NOTE: DN_DSMap_Erase // NOTE: DN_DSMapErase
// //
// Remove the key-value pair from the table. If by erasing the key-value // Remove the key-value pair from the table. If by erasing the key-value
// pair from the table puts the table under 25% load, the table will be // pair from the table puts the table under 25% load, the table will be
// shrunk by 1/2 the current size after erasing. The table will not shrink // shrunk by 1/2 the current size after erasing. The table will not shrink
// below the initial size that the table was initialised as. // below the initial size that the table was initialised as.
{ {
bool erased = DN_DSMap_Erase(&map, key); bool erased = DN_DSMapErase(&map, key);
DN_Assert(erased); DN_Assert(erased);
DN_Assert(map.occupied == 1); // Sentinel element DN_Assert(map.occupied == 1); // Sentinel element
} }
DN_DSMap_Deinit(&map, DN_ZMem_Yes); // Deallocates the 'arena' for us! DN_DSMapDeinit(&map, DN_ZMem_Yes); // Deallocates the 'arena' for us!
} }
// NOTE: DN_DSMap_Hash // NOTE: DN_DSMapHash
// //
// Hash the input key using the custom hash function if it's set on the map, // Hash the input key using the custom hash function if it's set on the map,
// otherwise uses the default hashing function (32bit Murmur3). // otherwise uses the default hashing function (32bit Murmur3).
// NOTE: DN_DSMap_HashToSlotIndex // NOTE: DN_DSMapHashToSlotIndex
// //
// Calculate the index into the map's 'slots' array from the given hash. // Calculate the index into the map's 'slots' array from the given hash.
// NOTE: DN_DSMap_Resize // NOTE: DN_DSMapResize
// //
// Resize the table and move all elements to the new map, note that the new // Resize the table and move all elements to the new map, note that the new
// size must be a power of two. This function wil fail on memory allocation // size must be a power of two. This function wil fail on memory allocation
// failure, or the requested size is smaller than the current number of // failure, or the requested size is smaller than the current number of
// elements in the map to resize. // elements in the map to resize.
// NOTE: DN_OSErrSink // NOTE: DN_ErrSink
// //
// Error sinks are a way of accumulating errors from API calls related or // Error sinks are a way of accumulating errors from API calls related or
// unrelated into 1 unified error handling pattern. The implemenation of a // unrelated into 1 unified error handling pattern. The implemenation of a
@ -273,11 +273,11 @@ void DN_Demo()
// (B) Error handling using pipelining and and error proof APIs. APIs that // (B) Error handling using pipelining and and error proof APIs. APIs that
// produce errors take in the error sink as a parameter. // produce errors take in the error sink as a parameter.
if (0) { if (0) {
DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil);
DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error); DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error);
DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error); DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error);
DN_OS_FileClose(&file); DN_OS_FileClose(&file);
if (DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to file")) { if (DN_ErrSinkEndLogErrorF(error, "Failed to write to file")) {
// Do error handling! // Do error handling!
} }
} }
@ -297,7 +297,7 @@ void DN_Demo()
// be populated by the first error encountered in that scope. // be populated by the first error encountered in that scope.
if (0) { if (0) {
DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil);
DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error); DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error);
DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error); DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error);
DN_OS_FileClose(&file); DN_OS_FileClose(&file);
@ -305,12 +305,12 @@ void DN_Demo()
{ {
// NOTE: My error sinks are thread-local, so the returned 'error' is // NOTE: My error sinks are thread-local, so the returned 'error' is
// the same as the 'error' value above. // the same as the 'error' value above.
DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); DN_TCErrSinkBegin(DN_ErrSinkMode_Nil);
DN_OS_FileWriteAll(DN_Str8Lit("/path/to/another/file"), DN_Str8Lit("123"), error); DN_OS_FileWriteAll(DN_Str8Lit("/path/to/another/file"), DN_Str8Lit("123"), error);
DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to another file"); DN_ErrSinkEndLogErrorF(error, "Failed to write to another file");
} }
if (DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to file")) { if (DN_ErrSinkEndLogErrorF(error, "Failed to write to file")) {
// Do error handling! // Do error handling!
} }
} }
@ -357,16 +357,6 @@ void DN_Demo()
// //
// And the non-named version emit just the 'value' portion // And the non-named version emit just the 'value' portion
// NOTE: DN_List_Iterate
{
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
DN_List<int> list = DN_List_Init<int>(/*chunk_size*/ 128);
for (DN_ListIterator<int> it = {}; DN_List_Iterate(&list, &it, 0);) {
int *item = it.data;
(void)item;
}
}
// NOTE: DN_LOGProc // NOTE: DN_LOGProc
// //
// Function prototype of the logging interface exposed by this library. Logs // Function prototype of the logging interface exposed by this library. Logs
@ -438,10 +428,11 @@ void DN_Demo()
// If 'tmp_path' is written to successfuly, the file will be copied over into // If 'tmp_path' is written to successfuly, the file will be copied over into
// 'path'. // 'path'.
if (0) { if (0) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil);
DN_OS_FileWriteAllSafe(/*path*/ DN_Str8Lit("C:/Home/my.txt"), /*buffer*/ DN_Str8Lit("Hello world"), error); DN_OS_FileWriteAllSafe(/*path*/ DN_Str8Lit("C:/Home/my.txt"), /*buffer*/ DN_Str8Lit("Hello world"), error);
DN_OS_ErrSinkEndAndLogErrorF(error, ""); DN_ErrSinkEndLogErrorF(error, "");
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_OS_EstimateTSCPerSecond // NOTE: DN_OS_EstimateTSCPerSecond
@ -630,7 +621,7 @@ void DN_Demo()
// Int -> U32: 0 or UINT32_MAX // Int -> U32: 0 or UINT32_MAX
// Int -> U64: 0 or UINT64_MAX // Int -> U64: 0 or UINT64_MAX
// NOTE: DN_StackTrace // NOTE: DN_OS_StackTrace
// Emit stack traces at the calling site that these functions are invoked // Emit stack traces at the calling site that these functions are invoked
// from. // from.
// //
@ -647,15 +638,15 @@ void DN_Demo()
// the debug APIs are aware of how to resolve the new addresses imported // the debug APIs are aware of how to resolve the new addresses imported
// into the address space. // into the address space.
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
// NOTE: DN_StackTraceWalk // NOTE: DN_OS_StackTraceWalk
// //
// Generate a stack trace as a series of addresses to the base of the // Generate a stack trace as a series of addresses to the base of the
// functions on the call-stack at the current instruction pointer. The // functions on the call-stack at the current instruction pointer. The
// addresses are stored in order from the current executing function // addresses are stored in order from the current executing function
// first to the most ancestor function last in the walk. // first to the most ancestor function last in the walk.
DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, /*depth limit*/ 128); DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, /*depth limit*/ 128);
// Loop over the addresses produced in the stack trace // Loop over the addresses produced in the stack trace
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);) { for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);) {
@ -663,7 +654,7 @@ void DN_Demo()
// //
// Converts the base address into a human readable stack trace // Converts the base address into a human readable stack trace
// entry (e.g. address, line number, file and function name). // entry (e.g. address, line number, file and function name).
DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(tmem.arena, it.raw_frame); DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(scratch.arena, it.raw_frame);
// You may then print out the frame like so // You may then print out the frame like so
if (0) if (0)
@ -675,13 +666,15 @@ void DN_Demo()
// to resolve the new addresses. // to resolve the new addresses.
DN_StackTraceReloadSymbols(); DN_StackTraceReloadSymbols();
// NOTE: DN_StackTraceGetFrames // NOTE: DN_OS_StackTraceGetFrames
// //
// Helper function to create a stack trace and automatically convert the // Helper function to create a stack trace and automatically convert the
// raw frames into human readable frames. This function effectively // raw frames into human readable frames. This function effectively
// calls 'Walk' followed by 'RawFrameToFrame'. // calls 'Walk' followed by 'RawFrameToFrame'.
DN_Slice<DN_StackTraceFrame> frames = DN_StackTraceGetFrames(tmem.arena, /*depth limit*/ 128); DN_StackTraceFrameSlice frames = DN_StackTraceGetFrames(scratch.arena, /*depth limit*/ 128);
(void)frames; (void)frames;
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_Str8FromArena // NOTE: DN_Str8FromArena
@ -693,10 +686,11 @@ void DN_Demo()
// The returned string's 'size' member variable does *not* include this // The returned string's 'size' member variable does *not* include this
// additional null-terminating byte. // additional null-terminating byte.
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8FromArena(tmem.arena, /*size*/ 1, DN_ZMem_Yes); DN_Str8 string = DN_Str8FromArena(scratch.arena, /*size*/ 1, DN_ZMem_Yes);
DN_Assert(string.size == 1); DN_Assert(string.size == 1);
DN_Assert(string.data[string.size] == 0); // It is null-terminated! DN_Assert(string.data[string.size] == 0); // It is null-terminated!
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_Str8BSplit // NOTE: DN_Str8BSplit
@ -773,14 +767,15 @@ void DN_Demo()
// always be a newly allocated copy, irrespective of if any replacements // always be a newly allocated copy, irrespective of if any replacements
// were done or not. // were done or not.
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8Replace(/*string*/ DN_Str8Lit("Foo Foo Bar"), DN_Str8 string = DN_Str8Replace(/*string*/ DN_Str8Lit("Foo Foo Bar"),
/*find*/ DN_Str8Lit("Foo"), /*find*/ DN_Str8Lit("Foo"),
/*replace*/ DN_Str8Lit("Moo"), /*replace*/ DN_Str8Lit("Moo"),
/*start_index*/ 1, /*start_index*/ 1,
/*arena*/ tmem.arena, /*arena*/ scratch.arena,
/*eq_case*/ DN_Str8EqCase_Sensitive); /*eq_case*/ DN_Str8EqCase_Sensitive);
DN_Assert(DN_Str8Eq(string, DN_Str8Lit("Foo Moo Bar"))); DN_Assert(DN_Str8Eq(string, DN_Str8Lit("Foo Moo Bar")));
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_Str8Segment // NOTE: DN_Str8Segment
@ -791,18 +786,19 @@ void DN_Demo()
// Reverse segment delimits the string counting 'segment_size' from the back // Reverse segment delimits the string counting 'segment_size' from the back
// of the string. // of the string.
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8Segment(tmem.arena, /*string*/ DN_Str8Lit("123456789"), /*segment_size*/ 3, /*segment_char*/ ','); DN_Str8 string = DN_Str8Segment(scratch.arena, /*string*/ DN_Str8Lit("123456789"), /*segment_size*/ 3, /*segment_char*/ ',');
DN_Assert(DN_Str8Eq(string, DN_Str8Lit("123,456,789"))); DN_Assert(DN_Str8Eq(string, DN_Str8Lit("123,456,789")));
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_Str8Split // NOTE: DN_Str8Split
{ {
// Splits the string at each delimiter into substrings occuring prior and // Splits the string at each delimiter into substrings occuring prior and
// after until the next delimiter. // after until the next delimiter.
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
{ {
DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ tmem.arena, DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ scratch.arena,
/*string*/ DN_Str8Lit("192.168.8.1"), /*string*/ DN_Str8Lit("192.168.8.1"),
/*delimiter*/ DN_Str8Lit("."), /*delimiter*/ DN_Str8Lit("."),
/*mode*/ DN_Str8SplitIncludeEmptyStrings_No); /*mode*/ DN_Str8SplitIncludeEmptyStrings_No);
@ -816,7 +812,7 @@ void DN_Demo()
// You can include empty strings that occur when splitting by setting // You can include empty strings that occur when splitting by setting
// the split mode to include empty strings. // the split mode to include empty strings.
{ {
DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ tmem.arena, DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ scratch.arena,
/*string*/ DN_Str8Lit("a--b"), /*string*/ DN_Str8Lit("a--b"),
/*delimiter*/ DN_Str8Lit("-"), /*delimiter*/ DN_Str8Lit("-"),
/*mode*/ DN_Str8SplitIncludeEmptyStrings_Yes); /*mode*/ DN_Str8SplitIncludeEmptyStrings_Yes);
@ -825,6 +821,8 @@ void DN_Demo()
DN_Str8Eq(splits.data[1], DN_Str8Lit("")) && DN_Str8Eq(splits.data[1], DN_Str8Lit("")) &&
DN_Str8Eq(splits.data[2], DN_Str8Lit("b"))); DN_Str8Eq(splits.data[2], DN_Str8Lit("b")));
} }
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_I64FromStr8, DN_U64FromStr8 // NOTE: DN_I64FromStr8, DN_U64FromStr8
@ -931,7 +929,7 @@ void DN_Demo()
// NOTE: DN_ThreadContext // NOTE: DN_ThreadContext
// //
// Each thread is assigned in their thread-local storage (TLS) tmem and // Each thread is assigned in their thread-local storage (TLS) scratch and
// permanent arena allocators. These can be used for allocations with a // permanent arena allocators. These can be used for allocations with a
// lifetime scoped to the lexical scope or for storing data permanently // lifetime scoped to the lexical scope or for storing data permanently
// using the arena paradigm. // using the arena paradigm.
@ -939,40 +937,43 @@ void DN_Demo()
// TLS in this implementation is implemented using the `thread_local` C/C++ // TLS in this implementation is implemented using the `thread_local` C/C++
// keyword. // keyword.
// //
// 99% of the time you will want DN_OS_TLSTMem(...) which returns you a // 99% of the time you will want DN_OS_TLSTMem...) which returns you a
// temporary arena for function lifetime allocations. On scope exit, the // temporary arena for function lifetime allocations. On scope exit, the
// arena is cleared out. // arena is cleared out.
// //
// This library's paradigm revolves heavily around arenas including tmem // This library's paradigm revolves heavily around arenas including scratch
// arenas into child functions for temporary calculations. If an arena is // arenas into child functions for temporary calculations. If an arena is
// passed into a function, this poses a problem sometimes known as // passed into a function, this poses a problem sometimes known as
// 'arena aliasing'. // 'arena aliasing'.
// //
// If an arena aliases another arena (e.g. the arena passed in) is the same // If an arena aliases another arena (e.g. the arena passed in) is the same
// as the tmem arena requested in the function, we risk the tmem arena // as the scratch arena requested in the function, we risk the scratch arena
// on scope exit deallocating memory belonging to the caller. // on scope exit deallocating memory belonging to the caller.
// //
// To avoid this we the 'DN_OS_TLSTMem(...)' API takes in a list of arenas // To avoid this we the 'DN_OS_TLSTMem...)' API takes in a list of arenas
// to ensure that we provide a tmem arena that *won't* alias with the // to ensure that we provide a scratch arena that *won't* alias with the
// caller's arena. If arena aliasing occurs, with ASAN on, generally // caller's arena. If arena aliasing occurs, with ASAN on, generally
// the library will trap and report use-after-poison once violated. // the library will trap and report use-after-poison once violated.
{ {
DN_OSTLSTMem tmem_a = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch_a = DN_TCScratchBegin(nullptr, 0);
// Now imagine we call a function where we pass tmem_a.arena down // Now imagine we call a function where we pass scratch_a.arena down
// into it .. If we call tmem again, we need to pass in the arena // into it .. If we call scratch again, we need to pass in the arena
// to prevent aliasing. // to prevent aliasing.
DN_OSTLSTMem tmem_b = DN_OS_TLSTMem(tmem_a.arena); DN_TCScratch scratch_b = DN_TCScratchBegin(&scratch_a.arena, 1);
DN_Assert(tmem_a.arena != tmem_b.arena); DN_Assert(scratch_a.arena != scratch_b.arena);
DN_TCScratchEnd(&scratch_b);
DN_TCScratchEnd(&scratch_a);
} }
// @proc DN_Thread_GetTMem // @proc DN_Thread_Getscratch
// @desc Retrieve the per-thread temporary arena allocator that is reset on scope // @desc Retrieve the per-thread temporary arena allocator that is reset on scope
// exit. // exit.
// The tmem arena must be deconflicted with any existing arenas in the // The scratch arena must be deconflicted with any existing arenas in the
// function to avoid trampling over each other's memory. Consider the situation // function to avoid trampling over each other's memory. Consider the situation
// where the tmem arena is passed into the function. Inside the function, if // where the scratch arena is passed into the function. Inside the function, if
// the same arena is reused then, if both arenas allocate, when the inner arena // the same arena is reused then, if both arenas allocate, when the inner arena
// is reset, this will undo the passed in arena's allocations in the function. // is reset, this will undo the passed in arena's allocations in the function.
@ -988,9 +989,10 @@ void DN_Demo()
// NOTE: DN_CVT_AgeFromU64 // NOTE: DN_CVT_AgeFromU64
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8x128 string = DN_AgeStr8FromSecF64(DN_SecFromHours(2) + DN_SecFromMins(30), DN_AgeUnit_All); DN_Str8x128 string = DN_AgeStr8FromSecF64(DN_SecFromHours(2) + DN_SecFromMins(30), DN_AgeUnit_All);
DN_Assert(DN_Str8Eq(DN_Str8FromStruct(&string), DN_Str8Lit("2h 30m"))); DN_Assert(DN_Str8Eq(DN_Str8FromStruct(&string), DN_Str8Lit("2h 30m")));
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_VArray // NOTE: DN_VArray
@ -1017,21 +1019,21 @@ void DN_Demo()
// In addition to no realloc on expansion or shrinking. // In addition to no realloc on expansion or shrinking.
// //
{ {
// NOTE: DN_VArray_Init // NOTE: DN_OS_VArrayInit
// NOTE: DN_VArray_InitByteSize // NOTE: DN_OS_VArrayInitByteSize
// //
// Initialise an array with the requested byte size or item capacity // Initialise an array with the requested byte size or item capacity
// respectively. The returned array may have a higher capacity than the // respectively. The returned array may have a higher capacity than the
// requested amount since requested memory from the OS may have a certain // requested amount since requested memory from the OS may have a certain
// alignment requirement (e.g. on Windows reserve/commit are 64k/4k // alignment requirement (e.g. on Windows reserve/commit are 64k/4k
// aligned). // aligned).
DN_VArray<int> array = DN_VArray_Init<int>(1024); DN_VArray<int> array = DN_OS_VArrayInit<int>(1024);
DN_Assert(array.size == 0 && array.max >= 1024); DN_Assert(array.size == 0 && array.max >= 1024);
// NOTE: DN_VArray_Make // NOTE: DN_OS_VArrayMake
// NOTE: DN_VArray_Add // NOTE: DN_OS_VArrayAdd
// NOTE: DN_VArray_MakeArray // NOTE: DN_OS_VArrayMakeArray
// NOTE: DN_VArray_AddArray // NOTE: DN_OS_VArrayAddArray
// //
// Allocate items from the array where: // Allocate items from the array where:
// //
@ -1040,11 +1042,11 @@ void DN_Demo()
// //
// If the array has run out of capacity or was never initialised, a null // If the array has run out of capacity or was never initialised, a null
// pointer is returned. // pointer is returned.
int *item = DN_VArray_Add(&array, 0xCAFE); int *item = DN_OS_VArrayAdd(&array, 0xCAFE);
DN_Assert(*item == 0xCAFE && array.size == 1); DN_Assert(*item == 0xCAFE && array.size == 1);
// NOTE: DN_VArray_AddCArray // NOTE: DN_OS_VArrayAddCArray
DN_VArray_AddCArray(&array, {1, 2, 3}); DN_OS_VArrayAddCArray(&array, {1, 2, 3});
DN_Assert(array.size == 4); DN_Assert(array.size == 4);
// TODO(doyle): There's a bug here with the negative erase! // TODO(doyle): There's a bug here with the negative erase!
@ -1054,7 +1056,7 @@ void DN_Demo()
if (index != 1) if (index != 1)
continue; continue;
// NOTE: DN_VArray_EraseRange // NOTE: DN_OS_VArrayEraseRange
// //
// Erase the next 'count' items at 'begin_index' in the array. // Erase the next 'count' items at 'begin_index' in the array.
// 'count' can be positive or negative which dictates the if we // 'count' can be positive or negative which dictates the if we
@ -1072,7 +1074,7 @@ void DN_Demo()
// TODO(doyle): There's a bug here! This doesn't work. // TODO(doyle): There's a bug here! This doesn't work.
// Erase index 0 with the negative count! // Erase index 0 with the negative count!
DN_ArrayEraseResult erase_result = DN_VArray_EraseRange(&array, DN_ArrayEraseResult erase_result = DN_OS_VArrayEraseRange(&array,
/*begin_index*/ index, /*begin_index*/ index,
/*count*/ -1, /*count*/ -1,
/*erase*/ DN_ArrayErase_Stable); /*erase*/ DN_ArrayErase_Stable);
@ -1089,7 +1091,7 @@ void DN_Demo()
array.data[2] == 3); array.data[2] == 3);
#endif #endif
// NOTE: DN_VArray_Reserve // NOTE: DN_OS_VArrayReserve
// //
// Ensure that the requested number of items are backed by physical pages // Ensure that the requested number of items are backed by physical pages
// from the OS. Calling this pre-emptively will minimise syscalls into the // from the OS. Calling this pre-emptively will minimise syscalls into the
@ -1097,9 +1099,9 @@ void DN_Demo()
// in bytes to the allocation granularity of OS allocation APIs hence the // in bytes to the allocation granularity of OS allocation APIs hence the
// reserved space may be greater than the requested amount (e.g. this is 4k // reserved space may be greater than the requested amount (e.g. this is 4k
// on Windows). // on Windows).
DN_VArray_Reserve(&array, /*count*/ 8); DN_OS_VArrayReserve(&array, /*count*/ 8);
DN_VArray_Deinit(&array); DN_OS_VArrayDeinit(&array);
} }
// NOTE: DN_W32_LastError // NOTE: DN_W32_LastError
@ -1108,13 +1110,14 @@ void DN_Demo()
if (0) { if (0) {
// Generate the error string for the last Win32 API called that return // Generate the error string for the last Win32 API called that return
// an error value. // an error value.
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_W32Error get_last_error = DN_W32_LastError(tmem.arena); DN_OSW32Error get_last_error = DN_OS_W32LastError(scratch.arena);
printf("Error (%lu): %.*s", get_last_error.code, DN_Str8PrintFmt(get_last_error.msg)); printf("Error (%lu): %.*s", get_last_error.code, DN_Str8PrintFmt(get_last_error.msg));
// Alternatively, pass in the error code directly // Alternatively, pass in the error code directly
DN_W32Error error_msg_for_code = DN_W32_ErrorCodeToMsg(tmem.arena, /*error_code*/ 0); DN_OSW32Error error_msg_for_code = DN_OS_W32ErrorCodeToMsg(scratch.arena, /*error_code*/ 0);
printf("Error (%lu): %.*s", error_msg_for_code.code, DN_Str8PrintFmt(error_msg_for_code.msg)); printf("Error (%lu): %.*s", error_msg_for_code.code, DN_Str8PrintFmt(error_msg_for_code.msg));
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_W32_MakeProcessDPIAware // NOTE: DN_W32_MakeProcessDPIAware

View File

@ -1,269 +0,0 @@
#define DN_HASH_CPP
#if defined(_CLANGD)
#include "dn_hash.h"
#endif
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$\ $$\ $$$$$$\ $$$$$$\ $$\ $$\
// $$ | $$ |$$ __$$\ $$ __$$\ $$ | $$ |
// $$ | $$ |$$ / $$ |$$ / \__|$$ | $$ |
// $$$$$$$$ |$$$$$$$$ |\$$$$$$\ $$$$$$$$ |
// $$ __$$ |$$ __$$ | \____$$\ $$ __$$ |
// $$ | $$ |$$ | $$ |$$\ $$ |$$ | $$ |
// $$ | $$ |$$ | $$ |\$$$$$$ |$$ | $$ |
// \__| \__|\__| \__| \______/ \__| \__|
//
// dn_hash.cpp
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
// NOTE: DN_FNV1A
// Default values recommended by: http://isthe.com/chongo/tech/comp/fnv/
DN_API DN_U32 DN_FNV1A32_Iterate(void const *bytes, DN_USize size, DN_U32 hash)
{
auto buffer = DN_Cast(DN_U8 const *)bytes;
for (DN_USize i = 0; i < size; i++)
hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/;
return hash;
}
DN_API DN_U32 DN_FNV1A32_Hash(void const *bytes, DN_USize size)
{
DN_U32 result = DN_FNV1A32_Iterate(bytes, size, DN_FNV1A32_SEED);
return result;
}
DN_API DN_U64 DN_FNV1A64_Iterate(void const *bytes, DN_USize size, DN_U64 hash)
{
auto buffer = DN_Cast(DN_U8 const *)bytes;
for (DN_USize i = 0; i < size; i++)
hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/;
return hash;
}
DN_API DN_U64 DN_FNV1A64_Hash(void const *bytes, DN_USize size)
{
DN_U64 result = DN_FNV1A64_Iterate(bytes, size, DN_FNV1A64_SEED);
return result;
}
// NOTE: DN_MurmurHash3 ////////////////////////////////////////////////////////////////////////////
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#define DN_MMH3_ROTL32(x, y) _rotl(x, y)
#define DN_MMH3_ROTL64(x, y) _rotl64(x, y)
#else
#define DN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y)))
#define DN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y)))
#endif
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
DN_FORCE_INLINE DN_U32 DN_MurmurHash3_GetBlock32(DN_U32 const *p, int i)
{
return p[i];
}
DN_FORCE_INLINE DN_U64 DN_MurmurHash3_GetBlock64(DN_U64 const *p, int i)
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
DN_FORCE_INLINE DN_U32 DN_MurmurHash3_FMix32(DN_U32 h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
DN_FORCE_INLINE DN_U64 DN_MurmurHash3_FMix64(DN_U64 k)
{
k ^= k >> 33;
k *= 0xff51afd7ed558ccd;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53;
k ^= k >> 33;
return k;
}
DN_API DN_U32 DN_MurmurHash3_x86U32(void const *key, int len, DN_U32 seed)
{
const DN_U8 *data = (const DN_U8 *)key;
const int nblocks = len / 4;
DN_U32 h1 = seed;
const DN_U32 c1 = 0xcc9e2d51;
const DN_U32 c2 = 0x1b873593;
//----------
// body
const DN_U32 *blocks = (const DN_U32 *)(data + nblocks * 4);
for (int i = -nblocks; i; i++)
{
DN_U32 k1 = DN_MurmurHash3_GetBlock32(blocks, i);
k1 *= c1;
k1 = DN_MMH3_ROTL32(k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = DN_MMH3_ROTL32(h1, 13);
h1 = h1 * 5 + 0xe6546b64;
}
//----------
// tail
const DN_U8 *tail = (const DN_U8 *)(data + nblocks * 4);
DN_U32 k1 = 0;
switch (len & 3)
{
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = DN_MMH3_ROTL32(k1, 15);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h1 = DN_MurmurHash3_FMix32(h1);
return h1;
}
DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128(void const *key, int len, DN_U32 seed)
{
const DN_U8 *data = (const DN_U8 *)key;
const int nblocks = len / 16;
DN_U64 h1 = seed;
DN_U64 h2 = seed;
const DN_U64 c1 = 0x87c37b91114253d5;
const DN_U64 c2 = 0x4cf5ad432745937f;
//----------
// body
const DN_U64 *blocks = (const DN_U64 *)(data);
for (int i = 0; i < nblocks; i++)
{
DN_U64 k1 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 0);
DN_U64 k2 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 1);
k1 *= c1;
k1 = DN_MMH3_ROTL64(k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = DN_MMH3_ROTL64(h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
k2 *= c2;
k2 = DN_MMH3_ROTL64(k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = DN_MMH3_ROTL64(h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
//----------
// tail
const DN_U8 *tail = (const DN_U8 *)(data + nblocks * 16);
DN_U64 k1 = 0;
DN_U64 k2 = 0;
switch (len & 15)
{
case 15:
k2 ^= ((DN_U64)tail[14]) << 48;
case 14:
k2 ^= ((DN_U64)tail[13]) << 40;
case 13:
k2 ^= ((DN_U64)tail[12]) << 32;
case 12:
k2 ^= ((DN_U64)tail[11]) << 24;
case 11:
k2 ^= ((DN_U64)tail[10]) << 16;
case 10:
k2 ^= ((DN_U64)tail[9]) << 8;
case 9:
k2 ^= ((DN_U64)tail[8]) << 0;
k2 *= c2;
k2 = DN_MMH3_ROTL64(k2, 33);
k2 *= c1;
h2 ^= k2;
case 8:
k1 ^= ((DN_U64)tail[7]) << 56;
case 7:
k1 ^= ((DN_U64)tail[6]) << 48;
case 6:
k1 ^= ((DN_U64)tail[5]) << 40;
case 5:
k1 ^= ((DN_U64)tail[4]) << 32;
case 4:
k1 ^= ((DN_U64)tail[3]) << 24;
case 3:
k1 ^= ((DN_U64)tail[2]) << 16;
case 2:
k1 ^= ((DN_U64)tail[1]) << 8;
case 1:
k1 ^= ((DN_U64)tail[0]) << 0;
k1 *= c1;
k1 = DN_MMH3_ROTL64(k1, 31);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 = DN_MurmurHash3_FMix64(h1);
h2 = DN_MurmurHash3_FMix64(h2);
h1 += h2;
h2 += h1;
DN_MurmurHash3 result = {};
result.e[0] = h1;
result.e[1] = h2;
return result;
}

View File

@ -1,49 +0,0 @@
#if !defined(DN_HASH_H)
#define DN_HASH_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#endif
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$\ $$\ $$$$$$\ $$$$$$\ $$\ $$\
// $$ | $$ |$$ __$$\ $$ __$$\ $$ | $$ |
// $$ | $$ |$$ / $$ |$$ / \__|$$ | $$ |
// $$$$$$$$ |$$$$$$$$ |\$$$$$$\ $$$$$$$$ |
// $$ __$$ |$$ __$$ | \____$$\ $$ __$$ |
// $$ | $$ |$$ | $$ |$$\ $$ |$$ | $$ |
// $$ | $$ |$$ | $$ |\$$$$$$ |$$ | $$ |
// \__| \__|\__| \__| \______/ \__| \__|
//
// dn_hash.h -- Hashing functions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
// NOTE: DN_FNV1A //////////////////////////////////////////////////////////////////////////////////
#if !defined(DN_FNV1A32_SEED)
#define DN_FNV1A32_SEED 2166136261U
#endif
#if !defined(DN_FNV1A64_SEED)
#define DN_FNV1A64_SEED 14695981039346656037ULL
#endif
// NOTE: DN_MurmurHash3 ////////////////////////////////////////////////////////////////////////////
struct DN_MurmurHash3 { uint64_t e[2]; };
// NOTE: DN_FNV1A //////////////////////////////////////////////////////////////////////////////////
DN_API uint32_t DN_FNV1A32_Hash (void const *bytes, DN_USize size);
DN_API uint64_t DN_FNV1A64_Hash (void const *bytes, DN_USize size);
DN_API uint32_t DN_FNV1A32_Iterate (void const *bytes, DN_USize size, uint32_t hash);
DN_API uint64_t DN_FNV1A64_Iterate (void const *bytes, DN_USize size, uint64_t hash);
// NOTE: DN_MurmurHash3 ////////////////////////////////////////////////////////////////////////////
DN_API uint32_t DN_MurmurHash3_x86U32 (void const *key, int len, uint32_t seed);
DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128 (void const *key, int len, uint32_t seed);
#define DN_MurmurHash3_x64U128AsU64(key, len, seed) (DN_MurmurHash3_x64U128(key, len, seed).e[0])
#define DN_MurmurHash3_x64U128AsU32(key, len, seed) (DN_Cast(uint32_t)DN_MurmurHash3_x64U128(key, len, seed).e[0])
#endif // !defined(DN_HASH_H)

View File

@ -4,102 +4,6 @@
#include "dn_helpers.h" #include "dn_helpers.h"
#endif #endif
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$\ $$\ $$$$$$$$\ $$\ $$$$$$$\ $$$$$$$$\ $$$$$$$\ $$$$$$\
// $$ | $$ |$$ _____|$$ | $$ __$$\ $$ _____|$$ __$$\ $$ __$$\
// $$ | $$ |$$ | $$ | $$ | $$ |$$ | $$ | $$ |$$ / \__|
// $$$$$$$$ |$$$$$\ $$ | $$$$$$$ |$$$$$\ $$$$$$$ |\$$$$$$\
// $$ __$$ |$$ __| $$ | $$ ____/ $$ __| $$ __$$< \____$$\
// $$ | $$ |$$ | $$ | $$ | $$ | $$ | $$ |$$\ $$ |
// $$ | $$ |$$$$$$$$\ $$$$$$$$\ $$ | $$$$$$$$\ $$ | $$ |\$$$$$$ |
// \__| \__|\________|\________|\__| \________|\__| \__| \______/
//
// dn_helpers.cpp
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
// NOTE: DN_PCG32 //////////////////////////////////////////////////////////////////////////////////
#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL
#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL
DN_API DN_PCG32 DN_PCG32_Init(uint64_t seed)
{
DN_PCG32 result = {};
DN_PCG32_Next(&result);
result.state += seed;
DN_PCG32_Next(&result);
return result;
}
DN_API uint32_t DN_PCG32_Next(DN_PCG32 *rng)
{
uint64_t state = rng->state;
rng->state = state * DN_PCG_DEFAULT_MULTIPLIER_64 + DN_PCG_DEFAULT_INCREMENT_64;
// XSH-RR
uint32_t value = (uint32_t)((state ^ (state >> 18)) >> 27);
int rot = state >> 59;
return rot ? (value >> rot) | (value << (32 - rot)) : value;
}
DN_API uint64_t DN_PCG32_Next64(DN_PCG32 *rng)
{
uint64_t value = DN_PCG32_Next(rng);
value <<= 32;
value |= DN_PCG32_Next(rng);
return value;
}
DN_API uint32_t DN_PCG32_Range(DN_PCG32 *rng, uint32_t low, uint32_t high)
{
uint32_t bound = high - low;
uint32_t threshold = -(int32_t)bound % bound;
for (;;) {
uint32_t r = DN_PCG32_Next(rng);
if (r >= threshold)
return low + (r % bound);
}
}
DN_API float DN_PCG32_NextF32(DN_PCG32 *rng)
{
uint32_t x = DN_PCG32_Next(rng);
return (float)(int32_t)(x >> 8) * 0x1.0p-24f;
}
DN_API double DN_PCG32_NextF64(DN_PCG32 *rng)
{
uint64_t x = DN_PCG32_Next64(rng);
return (double)(int64_t)(x >> 11) * 0x1.0p-53;
}
DN_API void DN_PCG32_Advance(DN_PCG32 *rng, uint64_t delta)
{
uint64_t cur_mult = DN_PCG_DEFAULT_MULTIPLIER_64;
uint64_t cur_plus = DN_PCG_DEFAULT_INCREMENT_64;
uint64_t acc_mult = 1;
uint64_t acc_plus = 0;
while (delta != 0) {
if (delta & 1) {
acc_mult *= cur_mult;
acc_plus = acc_plus * cur_mult + cur_plus;
}
cur_plus = (cur_mult + 1) * cur_plus;
cur_mult *= cur_mult;
delta >>= 1;
}
rng->state = acc_mult * rng->state + acc_plus;
}
#if !defined(DN_NO_JSON_BUILDER)
// NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
DN_API DN_JSONBuilder DN_JSONBuilder_Init(DN_Arena *arena, int spaces_per_indent) DN_API DN_JSONBuilder DN_JSONBuilder_Init(DN_Arena *arena, int spaces_per_indent)
{ {
DN_JSONBuilder result = {}; DN_JSONBuilder result = {};
@ -167,9 +71,10 @@ DN_API void DN_JSONBuilder_KeyValue(DN_JSONBuilder *builder, DN_Str8 key, DN_Str
DN_API void DN_JSONBuilder_KeyValueFV(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, va_list args) DN_API void DN_JSONBuilder_KeyValueFV(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, va_list args)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(builder->string_builder.arena); DN_TCScratch scratch = DN_TCScratchBegin(&builder->string_builder.arena, 1);
DN_Str8 value = DN_Str8FromFmtVArena(tmem.arena, value_fmt, args); DN_Str8 value = DN_Str8FromFmtVArena(scratch.arena, value_fmt, args);
DN_JSONBuilder_KeyValue(builder, key, value); DN_JSONBuilder_KeyValue(builder, key, value);
DN_TCScratchEnd(&scratch);
} }
DN_API void DN_JSONBuilder_KeyValueF(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...) DN_API void DN_JSONBuilder_KeyValueF(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...)
@ -246,4 +151,3 @@ DN_API void DN_JSONBuilder_BoolNamed(DN_JSONBuilder *builder, DN_Str8 key, bool
DN_Str8 value_string = value ? DN_Str8Lit("true") : DN_Str8Lit("false"); DN_Str8 value_string = value ? DN_Str8Lit("true") : DN_Str8Lit("false");
DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data); DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data);
} }
#endif // !defined(DN_NO_JSON_BUILDER)

View File

@ -2,16 +2,7 @@
#define DN_HELPERS_H #define DN_HELPERS_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#include "dn_math.h"
#endif
#if !defined(DN_BASE_H)
#error dn_base_inc.h must be included before this
#endif
#if !defined(DN_MATH_H)
#error dn_math.h must be included before this
#endif #endif
/* /*
@ -31,11 +22,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: DN_PCG32 //////////////////////////////////////////////////////////////////////////////////
struct DN_PCG32 { uint64_t state; };
#if !defined(DN_NO_JSON_BUILDER) #if !defined(DN_NO_JSON_BUILDER)
// NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
enum DN_JSONBuilderItem enum DN_JSONBuilderItem
{ {
DN_JSONBuilderItem_Empty, DN_JSONBuilderItem_Empty,
@ -100,15 +87,6 @@ struct DN_BinarySearchResult
template <typename T> template <typename T>
using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context); using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context);
// NOTE: DN_PCG32 //////////////////////////////////////////////////////////////////////////////////
DN_API DN_PCG32 DN_PCG32_Init (uint64_t seed);
DN_API uint32_t DN_PCG32_Next (DN_PCG32 *rng);
DN_API uint64_t DN_PCG32_Next64 (DN_PCG32 *rng);
DN_API uint32_t DN_PCG32_Range (DN_PCG32 *rng, uint32_t low, uint32_t high);
DN_API DN_F32 DN_PCG32_NextF32 (DN_PCG32 *rng);
DN_API DN_F64 DN_PCG32_NextF64 (DN_PCG32 *rng);
DN_API void DN_PCG32_Advance (DN_PCG32 *rng, uint64_t delta);
#if !defined(DN_NO_JSON_BUILDER) #if !defined(DN_NO_JSON_BUILDER)
// NOTE: DN_JSONBuilder //////////////////////////////////////////////////////////////////////////// // NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
#define DN_JSONBuilder_Object(builder) \ #define DN_JSONBuilder_Object(builder) \

View File

@ -407,7 +407,7 @@ void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site)
json_string_s const *key = curr->name; json_string_s const *key = curr->name;
if (it->flags & json_parse_flags_allow_location_information) { if (it->flags & json_parse_flags_allow_location_information) {
json_string_ex_s const *info = DN_Cast(json_string_ex_s const *)key; json_string_ex_s const *info = DN_Cast(json_string_ex_s const *)key;
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning),
call_site, call_site,
"Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]", "Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]",
info->line_no, info->line_no,
@ -417,7 +417,7 @@ void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site)
DN_Cast(int) value_type_size, DN_Cast(int) value_type_size,
value_type); value_type);
} else { } else {
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning),
call_site, call_site,
"Unknown key-value pair in object [key=%.*s, value=%.*s]", "Unknown key-value pair in object [key=%.*s, value=%.*s]",
DN_Cast(int) key->string_size, DN_Cast(int) key->string_size,

View File

@ -2,7 +2,7 @@
#define DN_JSON_H #define DN_JSON_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#include "../External/json.h" #include "../External/json.h"
#endif #endif
@ -10,13 +10,13 @@
#error Sheredom json.h (github.com/sheredom/json.h) must be included before this file #error Sheredom json.h (github.com/sheredom/json.h) must be included before this file
#endif #endif
// NOTE: DN_JSON ////////////////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON
void *DN_JSON_ArenaAllocFunc (void *user_data, size_t count); void *DN_JSON_ArenaAllocFunc (void *user_data, size_t count);
char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size); char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size);
bool DN_JSON_String8Cmp (json_string_s const *lhs, DN_Str8 rhs); bool DN_JSON_String8Cmp (json_string_s const *lhs, DN_Str8 rhs);
// NOTE: DN_JSON_It ///////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_It
enum DN_JSONItEntryType enum DN_JSONItEntryType
{ {
DN_JSON_ItEntryTypeObjElement, DN_JSON_ItEntryTypeObjElement,
@ -42,7 +42,7 @@ struct DN_JSONIt
DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json); DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json);
// NOTE: DN_JSON_ItPush/Pop ///////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItPush/Pop
bool DN_JSON_ItPushObjElement (DN_JSONIt *it, json_object_element_s *element); bool DN_JSON_ItPushObjElement (DN_JSONIt *it, json_object_element_s *element);
bool DN_JSON_ItPushObj (DN_JSONIt *it, json_object_s *obj); bool DN_JSON_ItPushObj (DN_JSONIt *it, json_object_s *obj);
bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element); bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element);
@ -50,7 +50,7 @@ bool DN_JSON_ItPushArray (DN_JSONIt *it, json_value_s *value);
bool DN_JSON_ItPushValue (DN_JSONIt *it, json_value_s *value); bool DN_JSON_ItPushValue (DN_JSONIt *it, json_value_s *value);
void DN_JSON_ItPop (DN_JSONIt *it); void DN_JSON_ItPop (DN_JSONIt *it);
// NOTE: DN_JSON_It tree navigation ///////////////////////////////////////////////////////// // NOTE: DN_JSON_It tree navigation
json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it); json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it);
bool DN_JSON_ItNext(DN_JSONIt *it); bool DN_JSON_ItNext(DN_JSONIt *it);
@ -58,12 +58,12 @@ bool DN_JSON_ItNext(DN_JSONIt *it);
for(void *DN_UniqueName(ptr) = DN_JSON_ItPushCurrValue(it); DN_UniqueName(ptr); DN_JSON_ItPop(it), DN_UniqueName(ptr) = nullptr) \ for(void *DN_UniqueName(ptr) = DN_JSON_ItPushCurrValue(it); DN_UniqueName(ptr); DN_JSON_ItPop(it), DN_UniqueName(ptr) = nullptr) \
while (DN_JSON_ItNext(it)) while (DN_JSON_ItNext(it))
// NOTE: DN_JSON_ItCurr ///////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItCurr
DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it); DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it);
json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it); json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it);
json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it); json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it);
// NOTE: DN_JSON_ItValueIs ////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItValueIs
json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type); json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type);
json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it); json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it);
json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it); json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it);
@ -74,7 +74,7 @@ json_value_s *DN_JSON_ItValueIsNull(DN_JSONIt *it);
size_t DN_JSON_ItValueArraySize(DN_JSONIt *it); size_t DN_JSON_ItValueArraySize(DN_JSONIt *it);
// NOTE: DN_JSON_ItKeyValueIs /////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItKeyValueIs
DN_Str8 DN_JSON_ItKey(DN_JSONIt *it); DN_Str8 DN_JSON_ItKey(DN_JSONIt *it);
bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key); bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key);
json_object_s *DN_JSON_ItKeyValueIsObj(DN_JSONIt *it, DN_Str8 key); json_object_s *DN_JSON_ItKeyValueIsObj(DN_JSONIt *it, DN_Str8 key);
@ -84,7 +84,7 @@ json_number_s *DN_JSON_ItKeyValueIsNumber(DN_JSONIt *it, DN_Str8 key);
json_value_s *DN_JSON_ItKeyValueIsBool(DN_JSONIt *it, DN_Str8 key); json_value_s *DN_JSON_ItKeyValueIsBool(DN_JSONIt *it, DN_Str8 key);
json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key); json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key);
// NOTE: DN_JSON_ItValueTo ////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItValueTo
DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it); DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it);
int64_t DN_JSON_ItValueToI64(DN_JSONIt *it); int64_t DN_JSON_ItValueToI64(DN_JSONIt *it);
uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it); uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it);

View File

@ -1255,18 +1255,18 @@ DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset)
return result; return result;
} }
DN_API DN_V2F32 DN_M2x3_ScaleGet(DN_M2x3 m2x3)
{
DN_V2F32 result = DN_V2F32_From2N(m2x3.row[0][0], m2x3.row[1][1]);
return result;
}
DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale)
{ {
DN_M2x3 result = { DN_M2x3 result = {{
{ scale.x, 0, 0,
scale.x, 0, scale.y, 0,
0, }};
0,
0,
scale.y,
0,
}
};
return result; return result;
} }

View File

@ -2,7 +2,7 @@
#define DN_MATH_H #define DN_MATH_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
DN_MSVC_WARNING_PUSH DN_MSVC_WARNING_PUSH
@ -34,25 +34,25 @@ union DN_V2F32
struct { DN_F32 w, h; }; struct { DN_F32 w, h; };
DN_F32 data[2]; DN_F32 data[2];
}; };
DN_DArrayStructDecl(DN_V2F32);
union DN_V3F32 union DN_V3F32
{ {
struct { DN_F32 x, y, z; }; struct { DN_F32 x, y, z; };
struct { DN_F32 r, g, b; }; struct { DN_F32 r, g, b; };
DN_V2F32 xy;
DN_F32 data[3]; DN_F32 data[3];
}; };
union DN_V4F32 union DN_V4F32
{ {
struct { DN_F32 x, y, z, w; }; struct { DN_F32 x, y, z, w; };
struct { DN_F32 r, g, b, a; }; struct { DN_F32 r, g, b, a; };
#if !defined(DN_NO_V3)
DN_V3F32 rgb; DN_V3F32 rgb;
DN_V3F32 xyz; DN_V3F32 xyz;
#endif
DN_F32 data[4]; DN_F32 data[4];
}; };
DN_DArrayStructDecl(DN_V4F32);
DN_MSVC_WARNING_POP DN_MSVC_WARNING_POP
struct DN_M4 struct DN_M4
@ -137,10 +137,10 @@ DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN
DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b);
DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a);
#define DN_V2U16_Zero DN_Literal(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} #define DN_V2U16_Zero DN_Literal(DN_V2U16){{(DN_U16)(0), (DN_U16)(0)}}
#define DN_V2U16_One DN_Literal(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} #define DN_V2U16_One DN_Literal(DN_V2U16){{(DN_U16)(1), (DN_U16)(1)}}
#define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} #define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(DN_U16)(x), (DN_U16)(x)}}
#define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} #define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(DN_U16)(x), (DN_U16)(y)}}
DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs);
DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs);
@ -165,6 +165,11 @@ DN_API DN_V2U16 & operator/= (DN_V2U16& lhs,
DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs);
DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs);
#define DN_V2U32_Zero DN_Literal(DN_V2U32){{(DN_U32)(0), (DN_U32)(0)}}
#define DN_V2U32_One DN_Literal(DN_V2U32){{(DN_U32)(1), (DN_U32)(1)}}
#define DN_V2U32_From1N(x) DN_Literal(DN_V2U32){{(DN_U32)(x), (DN_U32)(x)}}
#define DN_V2U32_From2N(x, y) DN_Literal(DN_V2U32){{(DN_U32)(x), (DN_U32)(y)}}
#define DN_V2F32_Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} #define DN_V2F32_Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}}
#define DN_V2F32_One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} #define DN_V2F32_One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}}
#define DN_V2F32_From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} #define DN_V2F32_From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}}
@ -315,6 +320,7 @@ DN_API bool operator== (DN_M2x3 const
DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs);
DN_API DN_M2x3 DN_M2x3_Identity (); DN_API DN_M2x3 DN_M2x3_Identity ();
DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset);
DN_API DN_V2F32 DN_M2x3_ScaleGet (DN_M2x3 m2x3);
DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale);
DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians);
DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2);
@ -323,6 +329,7 @@ DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN
#define DN_Rect_From2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)} #define DN_Rect_From2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)}
#define DN_Rect_From4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}} #define DN_Rect_From4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}}
#define DN_Rect_Zero DN_Rect_From4N(0, 0, 0, 0)
DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs);
DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect);

View File

@ -91,14 +91,14 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_OS_ThreadSetName(DN_Str8FromPtr(curl->thread.name.data, curl->thread.name.size)); DN_OS_ThreadSetName(DN_Str8FromPtr(curl->thread.name.data, curl->thread.name.size));
while (!curl->kill_thread) { while (!curl->kill_thread) {
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
// NOTE: Handle events sitting in the ring queue // NOTE: Handle events sitting in the ring queue
for (bool dequeue_ring = true; dequeue_ring;) { for (bool dequeue_ring = true; dequeue_ring;) {
DN_NETCurlRingEvent event = {}; DN_NETCurlRingEvent event = {};
for (DN_OS_MutexScope(&curl->ring_mutex)) { for (DN_OS_MutexScope(&curl->ring_mutex)) {
if (DN_Ring_HasData(&curl->ring, sizeof(event))) if (DN_RingHasData(&curl->ring, sizeof(event)))
DN_Ring_Read(&curl->ring, &event, sizeof(event)); DN_RingRead(&curl->ring, &event, sizeof(event));
} }
DN_NETRequest *req = DN_NET_RequestFromHandle(event.request); DN_NETRequest *req = DN_NET_RequestFromHandle(event.request);
@ -126,9 +126,9 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
case DN_NETCurlRingEventType_SendWS: { case DN_NETCurlRingEventType_SendWS: {
DN_Str8 payload = {}; DN_Str8 payload = {};
for (DN_OS_MutexScope(&curl->ring_mutex)) { for (DN_OS_MutexScope(&curl->ring_mutex)) {
DN_Assert(DN_Ring_HasData(&curl->ring, event.ws_send_size)); DN_Assert(DN_RingHasData(&curl->ring, event.ws_send_size));
payload = DN_Str8FromArena(tmem.arena, event.ws_send_size, DN_ZMem_No); payload = DN_Str8FromArena(tmem.arena, event.ws_send_size, DN_ZMem_No);
DN_Ring_Read(&curl->ring, payload.data, payload.size); DN_RingRead(&curl->ring, payload.data, payload.size);
} }
DN_U32 curlws_flag = 0; DN_U32 curlws_flag = 0;
@ -370,6 +370,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_I32 sleep_time_ms = ws_count > 0 ? 16 : INT32_MAX; DN_I32 sleep_time_ms = ws_count > 0 ? 16 : INT32_MAX;
curl_multi_poll(curl->thread_curlm, nullptr, 0, sleep_time_ms, nullptr); curl_multi_poll(curl->thread_curlm, nullptr, 0, sleep_time_ms, nullptr);
DN_TCScratchEnd(&tmem);
} }
return 0; return 0;
@ -526,7 +527,7 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D
event.type = DN_NETCurlRingEventType_DoRequest; event.type = DN_NETCurlRingEventType_DoRequest;
event.request = result; event.request = result;
for (DN_OS_MutexScope(&curl_core->ring_mutex)) for (DN_OS_MutexScope(&curl_core->ring_mutex))
DN_Ring_WriteStruct(&curl_core->ring, &event); DN_RingWriteStruct(&curl_core->ring, &event);
curl_multi_wakeup(curl_core->thread_curlm); curl_multi_wakeup(curl_core->thread_curlm);
} }
@ -569,9 +570,9 @@ void DN_NET_CurlDoWSSend(DN_NETRequestHandle handle, DN_Str8 payload, DN_NETWSSe
event.ws_send = send; event.ws_send = send;
for (DN_OS_MutexScope(&curl->ring_mutex)) { for (DN_OS_MutexScope(&curl->ring_mutex)) {
DN_Assert(DN_Ring_HasSpace(&curl->ring, payload.size)); DN_Assert(DN_RingHasSpace(&curl->ring, payload.size));
DN_Ring_WriteStruct(&curl->ring, &event); DN_RingWriteStruct(&curl->ring, &event);
DN_Ring_Write(&curl->ring, payload.data, payload.size); DN_RingWrite(&curl->ring, payload.data, payload.size);
} }
curl_multi_wakeup(curl->thread_curlm); curl_multi_wakeup(curl->thread_curlm);
} }
@ -627,7 +628,7 @@ static DN_NETResponse DN_NET_CurlHandleFinishedRequest_(DN_NETCurlCore *curl, DN
} }
for (DN_OS_MutexScope(&curl->ring_mutex)) for (DN_OS_MutexScope(&curl->ring_mutex))
DN_Ring_WriteStruct(&curl->ring, &event); DN_RingWriteStruct(&curl->ring, &event);
curl_multi_wakeup(curl->thread_curlm); curl_multi_wakeup(curl->thread_curlm);
return result; return result;

View File

@ -1,6 +1,6 @@
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#endif #endif
#if !defined(DN_UT_H) #if !defined(DN_UT_H)
@ -440,7 +440,7 @@ static DN_UTCore DN_Tests_Arena()
static DN_UTCore DN_Tests_Bin() static DN_UTCore DN_Tests_Bin()
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_UTCore test = DN_UT_Init(); DN_UTCore test = DN_UT_Init();
DN_UT_LogF(&test, "DN_Bin\n"); DN_UT_LogF(&test, "DN_Bin\n");
{ {
@ -502,25 +502,26 @@ static DN_UTCore DN_Tests_Bin()
uint32_t number = 0xd095f6; uint32_t number = 0xd095f6;
for (DN_UT_Test(&test, "Convert %x to string", number)) { for (DN_UT_Test(&test, "Convert %x to string", number)) {
DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), tmem.arena); DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), scratch.arena);
DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("f695d000")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex)); DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("f695d000")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
} }
number = 0xf6ed00; number = 0xf6ed00;
for (DN_UT_Test(&test, "Convert %x to string", number)) { for (DN_UT_Test(&test, "Convert %x to string", number)) {
DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), tmem.arena); DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), scratch.arena);
DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("00edf600")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex)); DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("00edf600")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
} }
DN_Str8 hex = DN_Str8Lit("0xf6ed00"); DN_Str8 hex = DN_Str8Lit("0xf6ed00");
for (DN_UT_Test(&test, "Convert %.*s to bytes", DN_Str8PrintFmt(hex))) { for (DN_UT_Test(&test, "Convert %.*s to bytes", DN_Str8PrintFmt(hex))) {
DN_Str8 bytes = DN_BytesFromHexStr8Arena(hex, tmem.arena); DN_Str8 bytes = DN_BytesFromHexStr8Arena(hex, scratch.arena);
DN_UT_AssertF(&test, DN_UT_AssertF(&test,
DN_Str8Eq(bytes, DN_Str8Lit("\xf6\xed\x00")), DN_Str8Eq(bytes, DN_Str8Lit("\xf6\xed\x00")),
"number_hex=%.*s", "number_hex=%.*s",
DN_Str8PrintFmt(DN_HexFromBytesPtrArena(bytes.data, bytes.size, tmem.arena))); DN_Str8PrintFmt(DN_HexFromBytesPtrArena(bytes.data, bytes.size, scratch.arena)));
} }
} }
DN_TCScratchEnd(&scratch);
return test; return test;
} }
@ -838,40 +839,40 @@ static DN_UTCore DN_Tests_BaseContainers()
DN_UT_LogF(&result, "DN_DSMap\n"); DN_UT_LogF(&result, "DN_DSMap\n");
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
{ {
DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil);
uint32_t const MAP_SIZE = 64; uint32_t const MAP_SIZE = 64;
DN_DSMap<uint64_t> map = DN_DSMap_Init<uint64_t>(&arena, MAP_SIZE, DN_DSMapFlags_Nil); DN_DSMap<uint64_t> map = DN_DSMapInit<uint64_t>(&arena, MAP_SIZE, DN_DSMapFlags_Nil);
DN_DEFER DN_DEFER
{ {
DN_DSMap_Deinit(&map, DN_ZMem_Yes); DN_DSMapDeinit(&map, DN_ZMem_Yes);
}; };
for (DN_UT_Test(&result, "Find non-existent value")) { for (DN_UT_Test(&result, "Find non-existent value")) {
DN_DSMapResult<uint64_t> find = DN_DSMap_FindKeyStr8(&map, DN_Str8Lit("Foo")); DN_DSMapResult<uint64_t> find = DN_DSMapFindKeyStr8(&map, DN_Str8Lit("Foo"));
DN_UT_Assert(&result, !find.found); DN_UT_Assert(&result, !find.found);
DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.size == MAP_SIZE);
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/);
} }
DN_DSMapKey key = DN_DSMap_KeyCStr8(&map, "Bar"); DN_DSMapKey key = DN_DSMapKeyCStr8(&map, "Bar");
for (DN_UT_Test(&result, "Insert value and lookup")) { for (DN_UT_Test(&result, "Insert value and lookup")) {
uint64_t desired_value = 0xF00BAA; uint64_t desired_value = 0xF00BAA;
uint64_t *slot_value = DN_DSMap_Set(&map, key, desired_value).value; uint64_t *slot_value = DN_DSMapSet(&map, key, desired_value).value;
DN_UT_Assert(&result, slot_value); DN_UT_Assert(&result, slot_value);
DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.size == MAP_SIZE);
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.occupied == 2); DN_UT_Assert(&result, map.occupied == 2);
uint64_t *value = DN_DSMap_Find(&map, key).value; uint64_t *value = DN_DSMapFind(&map, key).value;
DN_UT_Assert(&result, value); DN_UT_Assert(&result, value);
DN_UT_Assert(&result, *value == desired_value); DN_UT_Assert(&result, *value == desired_value);
} }
for (DN_UT_Test(&result, "Remove key")) { for (DN_UT_Test(&result, "Remove key")) {
DN_DSMap_Erase(&map, key); DN_DSMapErase(&map, key);
DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.size == MAP_SIZE);
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/);
@ -892,13 +893,13 @@ static DN_UTCore DN_Tests_BaseContainers()
case DSMapTestType_MakeSlot: prefix = DN_Str8Lit("Make slot"); break; case DSMapTestType_MakeSlot: prefix = DN_Str8Lit("Make slot"); break;
} }
DN_ArenaTempMemScope temp_mem_scope = DN_ArenaTempMemScope(tmem.arena); DN_ArenaTempMemScope temp_mem_scope = DN_ArenaTempMemScope(scratch.arena);
DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil);
uint32_t const MAP_SIZE = 64; uint32_t const MAP_SIZE = 64;
DN_DSMap<uint64_t> map = DN_DSMap_Init<uint64_t>(&arena, MAP_SIZE, DN_DSMapFlags_Nil); DN_DSMap<uint64_t> map = DN_DSMapInit<uint64_t>(&arena, MAP_SIZE, DN_DSMapFlags_Nil);
DN_DEFER DN_DEFER
{ {
DN_DSMap_Deinit(&map, DN_ZMem_Yes); DN_DSMapDeinit(&map, DN_ZMem_Yes);
}; };
for (DN_UT_Test(&result, "%.*s: Test growing", DN_Str8PrintFmt(prefix))) { for (DN_UT_Test(&result, "%.*s: Test growing", DN_Str8PrintFmt(prefix))) {
@ -906,27 +907,27 @@ static DN_UTCore DN_Tests_BaseContainers()
uint64_t value = 0; uint64_t value = 0;
uint64_t grow_threshold = map_start_size * 3 / 4; uint64_t grow_threshold = map_start_size * 3 / 4;
for (; map.occupied != grow_threshold; value++) { for (; map.occupied != grow_threshold; value++) {
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_UT_Assert(&result, !DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, !DN_DSMapFind<uint64_t>(&map, key).found);
DN_DSMapResult<uint64_t> make_result = {}; DN_DSMapResult<uint64_t> make_result = {};
if (result_type == DSMapTestType_Set) if (result_type == DSMapTestType_Set)
make_result = DN_DSMap_Set(&map, key, value); make_result = DN_DSMapSet(&map, key, value);
else else
make_result = DN_DSMap_Make(&map, key); make_result = DN_DSMapMake(&map, key);
DN_UT_Assert(&result, !make_result.found); DN_UT_Assert(&result, !make_result.found);
DN_UT_Assert(&result, DN_DSMap_Find<uint64_t>(&map, key).value); DN_UT_Assert(&result, DN_DSMapFind<uint64_t>(&map, key).value);
} }
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.size == map_start_size); DN_UT_Assert(&result, map.size == map_start_size);
DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/ + value); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/ + value);
{ // NOTE: One more item should cause the table to grow by 2x { // NOTE: One more item should cause the table to grow by 2x
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_DSMapResult<uint64_t> make_result = {}; DN_DSMapResult<uint64_t> make_result = {};
if (result_type == DSMapTestType_Set) if (result_type == DSMapTestType_Set)
make_result = DN_DSMap_Set(&map, key, value); make_result = DN_DSMapSet(&map, key, value);
else else
make_result = DN_DSMap_Make(&map, key); make_result = DN_DSMapMake(&map, key);
value++; value++;
DN_UT_Assert(&result, !make_result.found); DN_UT_Assert(&result, !make_result.found);
@ -948,16 +949,16 @@ static DN_UTCore DN_Tests_BaseContainers()
// NOTE: Validate each slot value // NOTE: Validate each slot value
uint64_t value_result = index - 1; uint64_t value_result = index - 1;
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value_result); DN_DSMapKey key = DN_DSMapKeyU64(&map, value_result);
DN_UT_Assert(&result, DN_DSMap_KeyEquals(slot->key, key)); DN_UT_Assert(&result, DN_DSMapKeyEquals(slot->key, key));
if (result_type == DSMapTestType_Set) if (result_type == DSMapTestType_Set)
DN_UT_Assert(&result, slot->value == value_result); DN_UT_Assert(&result, slot->value == value_result);
else else
DN_UT_Assert(&result, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 DN_UT_Assert(&result, slot->value == 0); // NOTE: Make slot does not set the key so should be 0
DN_UT_Assert(&result, slot->key.hash == DN_DSMap_Hash(&map, slot->key)); DN_UT_Assert(&result, slot->key.hash == DN_DSMapHash(&map, slot->key));
// NOTE: Check the reverse lookup is correct // NOTE: Check the reverse lookup is correct
DN_DSMapResult<uint64_t> check = DN_DSMap_Find(&map, slot->key); DN_DSMapResult<uint64_t> check = DN_DSMapFind(&map, slot->key);
DN_UT_Assert(&result, slot->value == *check.value); DN_UT_Assert(&result, slot->value == *check.value);
} }
} }
@ -968,17 +969,17 @@ static DN_UTCore DN_Tests_BaseContainers()
uint64_t value = 0; uint64_t value = 0;
uint64_t shrink_threshold = map.size * 1 / 4; uint64_t shrink_threshold = map.size * 1 / 4;
for (; map.occupied != shrink_threshold; value++) { for (; map.occupied != shrink_threshold; value++) {
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_UT_Assert(&result, DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, DN_DSMapFind<uint64_t>(&map, key).found);
DN_DSMap_Erase(&map, key); DN_DSMapErase(&map, key);
DN_UT_Assert(&result, !DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, !DN_DSMapFind<uint64_t>(&map, key).found);
} }
DN_UT_Assert(&result, map.size == start_map_size); DN_UT_Assert(&result, map.size == start_map_size);
DN_UT_Assert(&result, map.occupied == start_map_occupied - value); DN_UT_Assert(&result, map.occupied == start_map_occupied - value);
{ // NOTE: One more item should cause the table to shrink by 2x { // NOTE: One more item should cause the table to shrink by 2x
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_DSMap_Erase(&map, key); DN_DSMapErase(&map, key);
value++; value++;
DN_UT_Assert(&result, map.size == start_map_size / 2); DN_UT_Assert(&result, map.size == start_map_size / 2);
@ -995,34 +996,35 @@ static DN_UTCore DN_Tests_BaseContainers()
for (uint64_t index = 1 /*Sentinel*/; index < map.occupied; index++) { for (uint64_t index = 1 /*Sentinel*/; index < map.occupied; index++) {
// NOTE: Generate the key // NOTE: Generate the key
uint64_t value_result = value + (index - 1); uint64_t value_result = value + (index - 1);
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value_result); DN_DSMapKey key = DN_DSMapKeyU64(&map, value_result);
// NOTE: Validate each slot value // NOTE: Validate each slot value
DN_DSMapResult<uint64_t> find_result = DN_DSMap_Find(&map, key); DN_DSMapResult<uint64_t> find_result = DN_DSMapFind(&map, key);
DN_UT_Assert(&result, find_result.value); DN_UT_Assert(&result, find_result.value);
DN_UT_Assert(&result, find_result.slot->key == key); DN_UT_Assert(&result, find_result.slot->key == key);
if (result_type == DSMapTestType_Set) if (result_type == DSMapTestType_Set)
DN_UT_Assert(&result, *find_result.value == value_result); DN_UT_Assert(&result, *find_result.value == value_result);
else else
DN_UT_Assert(&result, *find_result.value == 0); // NOTE: Make slot does not set the key so should be 0 DN_UT_Assert(&result, *find_result.value == 0); // NOTE: Make slot does not set the key so should be 0
DN_UT_Assert(&result, find_result.slot->key.hash == DN_DSMap_Hash(&map, find_result.slot->key)); DN_UT_Assert(&result, find_result.slot->key.hash == DN_DSMapHash(&map, find_result.slot->key));
// NOTE: Check the reverse lookup is correct // NOTE: Check the reverse lookup is correct
DN_DSMapResult<uint64_t> check = DN_DSMap_Find(&map, find_result.slot->key); DN_DSMapResult<uint64_t> check = DN_DSMapFind(&map, find_result.slot->key);
DN_UT_Assert(&result, *find_result.value == *check.value); DN_UT_Assert(&result, *find_result.value == *check.value);
} }
for (; map.occupied != 1; value++) { // NOTE: Remove all items from the table for (; map.occupied != 1; value++) { // NOTE: Remove all items from the table
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_UT_Assert(&result, DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, DN_DSMapFind<uint64_t>(&map, key).found);
DN_DSMap_Erase(&map, key); DN_DSMapErase(&map, key);
DN_UT_Assert(&result, !DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, !DN_DSMapFind<uint64_t>(&map, key).found);
} }
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.size == map.initial_size); DN_UT_Assert(&result, map.size == map.initial_size);
DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/);
} }
} }
DN_TCScratchEnd(&scratch);
} }
DN_UT_LogF(&result, "DN_IArray\n"); DN_UT_LogF(&result, "DN_IArray\n");
@ -1040,7 +1042,7 @@ static DN_UTCore DN_Tests_BaseContainers()
array.max = DN_ArrayCountU(array_buffer); array.max = DN_ArrayCountU(array_buffer);
for (DN_UT_Test(&result, "Make item")) { for (DN_UT_Test(&result, "Make item")) {
int *item = DN_IArray_Make(&array, DN_ZMem_Yes); int *item = DN_IArrayMake(&array, DN_ZMem_Yes);
DN_UT_Assert(&result, item && array.size == 1); DN_UT_Assert(&result, item && array.size == 1);
} }
} }
@ -1050,7 +1052,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Positive count, middle of array, stable erase")) { for (DN_UT_Test(&result, "Positive count, middle of array, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 5, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 2); DN_UT_Assert(&result, erase.items_erased == 2);
DN_UT_Assert(&result, erase.it_index == 3); DN_UT_Assert(&result, erase.it_index == 3);
@ -1061,7 +1063,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Negative count, middle of array, stable erase")) { for (DN_UT_Test(&result, "Negative count, middle of array, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 3); DN_UT_Assert(&result, erase.items_erased == 3);
DN_UT_Assert(&result, erase.it_index == 3); DN_UT_Assert(&result, erase.it_index == 3);
@ -1072,7 +1074,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "count = -1, stable erase")) { for (DN_UT_Test(&result, "count = -1, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -1, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -1, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 3, 4, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 1); DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 5); DN_UT_Assert(&result, erase.it_index == 5);
@ -1083,7 +1085,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Positive count, unstable erase")) { for (DN_UT_Test(&result, "Positive count, unstable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Unstable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Unstable);
int expected[] = {0, 1, 2, 8, 9, 5, 6, 7}; int expected[] = {0, 1, 2, 8, 9, 5, 6, 7};
DN_UT_Assert(&result, erase.items_erased == 2); DN_UT_Assert(&result, erase.items_erased == 2);
DN_UT_Assert(&result, erase.it_index == 3); DN_UT_Assert(&result, erase.it_index == 3);
@ -1094,7 +1096,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Negative count, unstable erase")) { for (DN_UT_Test(&result, "Negative count, unstable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Unstable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Unstable);
int expected[] = {0, 1, 2, 7, 8, 9, 6}; int expected[] = {0, 1, 2, 7, 8, 9, 6};
DN_UT_Assert(&result, erase.items_erased == 3); DN_UT_Assert(&result, erase.items_erased == 3);
DN_UT_Assert(&result, erase.it_index == 3); DN_UT_Assert(&result, erase.it_index == 3);
@ -1105,18 +1107,18 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Edge case - begin_index at start, negative count")) { for (DN_UT_Test(&result, "Edge case - begin_index at start, negative count")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 0, -2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 0, -2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
DN_UT_Assert(&result, size == 10); DN_UT_Assert(&result, size == 9);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
} }
for (DN_UT_Test(&result, "Edge case - begin_index at end, positive count")) { for (DN_UT_Test(&result, "Edge case - begin_index at end, positive count")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 9, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 9, 2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
DN_UT_Assert(&result, erase.items_erased == 1); DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 9); DN_UT_Assert(&result, erase.it_index == 9);
@ -1127,7 +1129,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Invalid input - count = 0")) { for (DN_UT_Test(&result, "Invalid input - count = 0")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, 0, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 0, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
@ -1137,7 +1139,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Invalid input - null data")) { for (DN_UT_Test(&result, "Invalid input - null data")) {
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(nullptr, &size, sizeof(int), 5, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(nullptr, &size, sizeof(int), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
DN_UT_Assert(&result, size == 10); DN_UT_Assert(&result, size == 10);
@ -1145,7 +1147,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Invalid input - null size")) { for (DN_UT_Test(&result, "Invalid input - null size")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, NULL, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, NULL, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
} }
@ -1153,7 +1155,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Invalid input - empty array")) { for (DN_UT_Test(&result, "Invalid input - empty array")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 0; DN_USize size = 0;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
DN_UT_Assert(&result, size == 0); DN_UT_Assert(&result, size == 0);
@ -1162,7 +1164,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Out-of-bounds begin_index")) { for (DN_UT_Test(&result, "Out-of-bounds begin_index")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 15, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 15, 2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 10); DN_UT_Assert(&result, erase.it_index == 10);
@ -1171,77 +1173,31 @@ static DN_UTCore DN_Tests_BaseContainers()
} }
} }
DN_UT_LogF(&result, "DN_FArray\n");
{
for (DN_UT_Test(&result, "Initialise from raw array")) {
int raw_array[] = {1, 2};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_UT_Assert(&result, array.size == 2);
DN_UT_Assert(&result, array.data[0] == 1);
DN_UT_Assert(&result, array.data[1] == 2);
}
for (DN_UT_Test(&result, "Erase stable 1 element from array")) {
int raw_array[] = {1, 2, 3};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_FArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable);
DN_UT_Assert(&result, array.size == 2);
DN_UT_Assert(&result, array.data[0] == 1);
DN_UT_Assert(&result, array.data[1] == 3);
}
for (DN_UT_Test(&result, "Erase unstable 1 element from array")) {
int raw_array[] = {1, 2, 3};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_FArray_EraseRange(&array, 0 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable);
DN_UT_Assert(&result, array.size == 2);
DN_UT_Assert(&result, array.data[0] == 3);
DN_UT_Assert(&result, array.data[1] == 2);
}
for (DN_UT_Test(&result, "Add 1 element to array")) {
int const ITEM = 2;
int raw_array[] = {1};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_FArray_Add(&array, ITEM);
DN_UT_Assert(&result, array.size == 2);
DN_UT_Assert(&result, array.data[0] == 1);
DN_UT_Assert(&result, array.data[1] == ITEM);
}
for (DN_UT_Test(&result, "Clear array")) {
int raw_array[] = {1};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_FArray_Clear(&array);
DN_UT_Assert(&result, array.size == 0);
}
}
DN_UT_LogF(&result, "DN_VArray\n"); DN_UT_LogF(&result, "DN_VArray\n");
{ {
{ {
DN_VArray<uint32_t> array = DN_VArray_InitByteSize<uint32_t>(DN_Kilobytes(64)); DN_VArray<uint32_t> array = DN_OS_VArrayInitByteSize<uint32_t>(DN_Kilobytes(64));
DN_DEFER DN_DEFER
{ {
DN_VArray_Deinit(&array); DN_OS_VArrayDeinit(&array);
}; };
for (DN_UT_Test(&result, "Test adding an array of items to the array")) { for (DN_UT_Test(&result, "Test adding an array of items to the array")) {
uint32_t array_literal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; uint32_t array_literal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
DN_VArray_AddArray<uint32_t>(&array, array_literal, DN_ArrayCountU(array_literal)); DN_OS_VArrayAddArray<uint32_t>(&array, array_literal, DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test stable erase, 1 item, the '2' value from the array")) { for (DN_UT_Test(&result, "Test stable erase, 1 item, the '2' value from the array")) {
DN_VArray_EraseRange(&array, 2 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable); DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable);
uint32_t array_literal[] = {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; uint32_t array_literal[] = {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test unstable erase, 1 item, the '1' value from the array")) { for (DN_UT_Test(&result, "Test unstable erase, 1 item, the '1' value from the array")) {
DN_VArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable); DN_OS_VArrayEraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable);
uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
@ -1251,49 +1207,49 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Test un/stable erase, OOB")) { for (DN_UT_Test(&result, "Test un/stable erase, OOB")) {
for (DN_ArrayErase erase : erase_enums) { for (DN_ArrayErase erase : erase_enums) {
uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
DN_VArray_EraseRange(&array, DN_ArrayCountU(array_literal) /*begin_index*/, DN_ArrayCountU(array_literal) + 100 /*count*/, erase); DN_OS_VArrayEraseRange(&array, DN_ArrayCountU(array_literal) /*begin_index*/, DN_ArrayCountU(array_literal) + 100 /*count*/, erase);
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
} }
for (DN_UT_Test(&result, "Test flipped begin/end index stable erase, 2 items, the '15, 3' value from the array")) { for (DN_UT_Test(&result, "Test flipped begin/end index stable erase, 2 items, the '15, 3' value from the array")) {
DN_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Stable); DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Stable);
uint32_t array_literal[] = {0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; uint32_t array_literal[] = {0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test flipped begin/end index unstable erase, 2 items, the '4, 5' value from the array")) { for (DN_UT_Test(&result, "Test flipped begin/end index unstable erase, 2 items, the '4, 5' value from the array")) {
DN_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Unstable); DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Unstable);
uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10, 11, 12}; uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10, 11, 12};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test stable erase range, 2+1 (oob) item, the '13, 14, +1 OOB' value from the array")) { for (DN_UT_Test(&result, "Test stable erase range, 2+1 (oob) item, the '13, 14, +1 OOB' value from the array")) {
DN_VArray_EraseRange(&array, 8 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Stable); DN_OS_VArrayEraseRange(&array, 8 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Stable);
uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10}; uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test unstable erase range, 3+1 (oob) item, the '11, 12, +1 OOB' value from the array")) { for (DN_UT_Test(&result, "Test unstable erase range, 3+1 (oob) item, the '11, 12, +1 OOB' value from the array")) {
DN_VArray_EraseRange(&array, 6 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Unstable); DN_OS_VArrayEraseRange(&array, 6 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Unstable);
uint32_t array_literal[] = {0, 13, 14, 6, 7, 8}; uint32_t array_literal[] = {0, 13, 14, 6, 7, 8};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test stable erase -overflow OOB, erasing the '0, 13' value from the array")) { for (DN_UT_Test(&result, "Test stable erase -overflow OOB, erasing the '0, 13' value from the array")) {
DN_VArray_EraseRange(&array, 1 /*begin_index*/, -DN_ISIZE_MAX /*count*/, DN_ArrayErase_Stable); DN_OS_VArrayEraseRange(&array, 1 /*begin_index*/, -DN_ISIZE_MAX /*count*/, DN_ArrayErase_Stable);
uint32_t array_literal[] = {14, 6, 7, 8}; uint32_t array_literal[] = {14, 6, 7, 8};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test unstable erase +overflow OOB, erasing the '7, 8' value from the array")) { for (DN_UT_Test(&result, "Test unstable erase +overflow OOB, erasing the '7, 8' value from the array")) {
DN_VArray_EraseRange(&array, 2 /*begin_index*/, DN_ISIZE_MAX /*count*/, DN_ArrayErase_Unstable); DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, DN_ISIZE_MAX /*count*/, DN_ArrayErase_Unstable);
uint32_t array_literal[] = {14, 6}; uint32_t array_literal[] = {14, 6};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
@ -1301,7 +1257,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Test adding an array of items after erase")) { for (DN_UT_Test(&result, "Test adding an array of items after erase")) {
uint32_t array_literal[] = {0, 1, 2, 3}; uint32_t array_literal[] = {0, 1, 2, 3};
DN_VArray_AddArray<uint32_t>(&array, array_literal, DN_ArrayCountU(array_literal)); DN_OS_VArrayAddArray<uint32_t>(&array, array_literal, DN_ArrayCountU(array_literal));
uint32_t expected_literal[] = {14, 6, 0, 1, 2, 3}; uint32_t expected_literal[] = {14, 6, 0, 1, 2, 3};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(expected_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(expected_literal));
@ -1331,16 +1287,16 @@ static DN_UTCore DN_Tests_BaseContainers()
DN_MSVC_WARNING_POP DN_MSVC_WARNING_POP
DN_VArray<UnalignedObject> array = DN_VArray_InitByteSize<UnalignedObject>(DN_Kilobytes(64)); DN_VArray<UnalignedObject> array = DN_OS_VArrayInitByteSize<UnalignedObject>(DN_Kilobytes(64));
DN_DEFER DN_DEFER
{ {
DN_VArray_Deinit(&array); DN_OS_VArrayDeinit(&array);
}; };
// NOTE: Verify that the items returned from the data array are // NOTE: Verify that the items returned from the data array are
// contiguous in memory. // contiguous in memory.
UnalignedObject *make_item_a = DN_VArray_MakeArray(&array, 1, DN_ZMem_Yes); UnalignedObject *make_item_a = DN_OS_VArrayMakeArray(&array, 1, DN_ZMem_Yes);
UnalignedObject *make_item_b = DN_VArray_MakeArray(&array, 1, DN_ZMem_Yes); UnalignedObject *make_item_b = DN_OS_VArrayMakeArray(&array, 1, DN_ZMem_Yes);
DN_Memset(make_item_a->data, 'a', sizeof(make_item_a->data)); DN_Memset(make_item_a->data, 'a', sizeof(make_item_a->data));
DN_Memset(make_item_b->data, 'b', sizeof(make_item_b->data)); DN_Memset(make_item_b->data, 'b', sizeof(make_item_b->data));
DN_UT_Assert(&result, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1)); DN_UT_Assert(&result, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1));
@ -1642,8 +1598,8 @@ DN_Str8 const DN_UT_HASH_STRING_[] =
void DN_Tests_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input) void DN_Tests_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 input_hex = DN_HexFromBytesPtrArena(input.data, input.size, tmem.arena); DN_Str8 input_hex = DN_HexFromBytesPtrArena(input.data, input.size, scratch.arena);
switch (hash_type) { switch (hash_type) {
case Hash_SHA3_224: { case Hash_SHA3_224: {
@ -1758,6 +1714,7 @@ void DN_Tests_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input)
DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&expect).data)); DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&expect).data));
} break; } break;
} }
DN_TCScratchEnd(&scratch);
} }
#endif // defined(DN_UNIT_TESTS_WITH_KECCAK) #endif // defined(DN_UNIT_TESTS_WITH_KECCAK)
@ -1845,10 +1802,11 @@ static DN_UTCore DN_Tests_OS()
} }
for (DN_UT_Test(&result, "Query executable directory")) { for (DN_UT_Test(&result, "Query executable directory")) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 os_result = DN_OS_EXEDir(tmem.arena); DN_Str8 os_result = DN_OS_EXEDir(scratch.arena);
DN_UT_Assert(&result, os_result.size); DN_UT_Assert(&result, os_result.size);
DN_UT_AssertF(&result, DN_OS_PathIsDir(os_result), "result(%zu): %.*s", os_result.size, DN_Str8PrintFmt(os_result)); DN_UT_AssertF(&result, DN_OS_PathIsDir(os_result), "result(%zu): %.*s", os_result.size, DN_Str8PrintFmt(os_result));
DN_TCScratchEnd(&scratch);
} }
for (DN_UT_Test(&result, "DN_OS_PerfCounterNow")) { for (DN_UT_Test(&result, "DN_OS_PerfCounterNow")) {
@ -1895,8 +1853,8 @@ static DN_UTCore DN_Tests_OS()
DN_UT_Assert(&result, DN_OS_PathIsFile(SRC_FILE)); DN_UT_Assert(&result, DN_OS_PathIsFile(SRC_FILE));
// NOTE: Read step // NOTE: Read step
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 read_file = DN_OS_FileReadAllArena(tmem.arena, SRC_FILE, nullptr); DN_Str8 read_file = DN_OS_FileReadAllArena(scratch.arena, SRC_FILE, nullptr);
DN_UT_AssertF(&result, read_file.size, "Failed to load file"); DN_UT_AssertF(&result, read_file.size, "Failed to load file");
DN_UT_AssertF(&result, read_file.size == 4, "File read wrong amount of bytes (%zu)", read_file.size); DN_UT_AssertF(&result, read_file.size == 4, "File read wrong amount of bytes (%zu)", read_file.size);
DN_UT_AssertF(&result, DN_Str8Eq(read_file, DN_Str8Lit("1234")), "Read %zu bytes instead of the expected 4: '%.*s'", read_file.size, DN_Str8PrintFmt(read_file)); DN_UT_AssertF(&result, DN_Str8Eq(read_file, DN_Str8Lit("1234")), "Read %zu bytes instead of the expected 4: '%.*s'", read_file.size, DN_Str8PrintFmt(read_file));
@ -1925,6 +1883,7 @@ static DN_UTCore DN_Tests_OS()
DN_B32 delete_non_existent_moved_file = DN_OS_PathDelete(MOVE_FILE); DN_B32 delete_non_existent_moved_file = DN_OS_PathDelete(MOVE_FILE);
DN_UT_Assert(&result, delete_non_existent_moved_file == false); DN_UT_Assert(&result, delete_non_existent_moved_file == false);
DN_UT_Assert(&result, delete_non_existent_src_file == false); DN_UT_Assert(&result, delete_non_existent_src_file == false);
DN_TCScratchEnd(&scratch);
} }
} }
@ -2147,22 +2106,24 @@ static DN_UTCore DN_Tests_Str8()
} }
for (DN_UT_Test(&result, "Initialise with format string")) { for (DN_UT_Test(&result, "Initialise with format string")) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8FromFmtArena(tmem.arena, "%s", "AB"); DN_Str8 string = DN_Str8FromFmtArena(scratch.arena, "%s", "AB");
DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size); DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size);
DN_UT_AssertF(&result, string.data[0] == 'A', "string[0]: %c", string.data[0]); DN_UT_AssertF(&result, string.data[0] == 'A', "string[0]: %c", string.data[0]);
DN_UT_AssertF(&result, string.data[1] == 'B', "string[1]: %c", string.data[1]); DN_UT_AssertF(&result, string.data[1] == 'B', "string[1]: %c", string.data[1]);
DN_UT_AssertF(&result, string.data[2] == 0, "string[2]: %c", string.data[2]); DN_UT_AssertF(&result, string.data[2] == 0, "string[2]: %c", string.data[2]);
DN_TCScratchEnd(&scratch);
} }
for (DN_UT_Test(&result, "Copy string")) { for (DN_UT_Test(&result, "Copy string")) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8Lit("AB"); DN_Str8 string = DN_Str8Lit("AB");
DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, string); DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, string);
DN_UT_AssertF(&result, copy.size == 2, "size: %zu", copy.size); DN_UT_AssertF(&result, copy.size == 2, "size: %zu", copy.size);
DN_UT_AssertF(&result, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]); DN_UT_AssertF(&result, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]);
DN_UT_AssertF(&result, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]); DN_UT_AssertF(&result, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]);
DN_UT_AssertF(&result, copy.data[2] == 0, "copy[2]: %c", copy.data[2]); DN_UT_AssertF(&result, copy.data[2] == 0, "copy[2]: %c", copy.data[2]);
DN_TCScratchEnd(&scratch);
} }
for (DN_UT_Test(&result, "Trim whitespace around string")) { for (DN_UT_Test(&result, "Trim whitespace around string")) {
@ -2171,9 +2132,10 @@ static DN_UTCore DN_Tests_Str8()
} }
for (DN_UT_Test(&result, "Allocate string from arena")) { for (DN_UT_Test(&result, "Allocate string from arena")) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8FromArena(tmem.arena, 2, DN_ZMem_No); DN_Str8 string = DN_Str8FromArena(scratch.arena, 2, DN_ZMem_No);
DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size); DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size);
DN_TCScratchEnd(&scratch);
} }
// NOTE: TrimPrefix/Suffix ///////////////////////////////////////////////////////////////////// // NOTE: TrimPrefix/Suffix /////////////////////////////////////////////////////////////////////
@ -2448,28 +2410,28 @@ static DN_UTCore DN_Tests_Win()
#if defined(DN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
DN_UT_LogF(&result, "OS Win32\n"); DN_UT_LogF(&result, "OS Win32\n");
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 input8 = DN_Str8Lit("String"); DN_Str8 input8 = DN_Str8Lit("String");
DN_Str16 input16 = DN_Str16{(wchar_t *)(L"String"), sizeof(L"String") / sizeof(L"String"[0]) - 1}; DN_Str16 input16 = DN_Str16{(wchar_t *)(L"String"), sizeof(L"String") / sizeof(L"String"[0]) - 1};
for (DN_UT_Test(&result, "Str8 to Str16")) { for (DN_UT_Test(&result, "Str8 to Str16")) {
DN_Str16 str_result = DN_W32_Str8ToStr16(tmem.arena, input8); DN_Str16 str_result = DN_OS_W32Str8ToStr16(scratch.arena, input8);
DN_UT_Assert(&result, DN_Str16Eq(str_result, input16)); DN_UT_Assert(&result, DN_Str16Eq(str_result, input16));
} }
for (DN_UT_Test(&result, "Str16 to Str8")) { for (DN_UT_Test(&result, "Str16 to Str8")) {
DN_Str8 str_result = DN_W32_Str16ToStr8(tmem.arena, input16); DN_Str8 str_result = DN_OS_W32Str16ToStr8(scratch.arena, input16);
DN_UT_Assert(&result, DN_Str8Eq(str_result, input8)); DN_UT_Assert(&result, DN_Str8Eq(str_result, input8));
} }
for (DN_UT_Test(&result, "Str16 to Str8: Null terminates string")) { for (DN_UT_Test(&result, "Str16 to Str8: Null terminates string")) {
int size_required = DN_W32_Str16ToStr8Buffer(input16, nullptr, 0); int size_required = DN_OS_W32Str16ToStr8Buffer(input16, nullptr, 0);
char *string = DN_ArenaNewArray(tmem.arena, char, size_required + 1, DN_ZMem_No); char *string = DN_ArenaNewArray(scratch.arena, char, size_required + 1, DN_ZMem_No);
// Fill the string with error sentinels // Fill the string with error sentinels
DN_Memset(string, 'Z', size_required + 1); DN_Memset(string, 'Z', size_required + 1);
int size_returned = DN_W32_Str16ToStr8Buffer(input16, string, size_required + 1); int size_returned = DN_OS_W32Str16ToStr8Buffer(input16, string, size_required + 1);
char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0};
DN_UT_AssertF(&result, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); DN_UT_AssertF(&result, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned);
@ -2478,14 +2440,15 @@ static DN_UTCore DN_Tests_Win()
} }
for (DN_UT_Test(&result, "Str16 to Str8: Arena null terminates string")) { for (DN_UT_Test(&result, "Str16 to Str8: Arena null terminates string")) {
DN_Str8 string8 = DN_W32_Str16ToStr8(tmem.arena, input16); DN_Str8 string8 = DN_OS_W32Str16ToStr8(scratch.arena, input16);
int size_returned = DN_W32_Str16ToStr8Buffer(input16, nullptr, 0); int size_returned = DN_OS_W32Str16ToStr8Buffer(input16, nullptr, 0);
char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0};
DN_UT_AssertF(&result, DN_Cast(int) string8.size == size_returned, "string_size: %d, result: %d", DN_Cast(int) string8.size, size_returned); DN_UT_AssertF(&result, DN_Cast(int) string8.size == size_returned, "string_size: %d, result: %d", DN_Cast(int) string8.size, size_returned);
DN_UT_AssertF(&result, DN_Cast(int) string8.size == DN_ArrayCountU(EXPECTED) - 1, "string_size: %d, expected: %zu", DN_Cast(int) string8.size, DN_ArrayCountU(EXPECTED) - 1); DN_UT_AssertF(&result, DN_Cast(int) string8.size == DN_ArrayCountU(EXPECTED) - 1, "string_size: %d, expected: %zu", DN_Cast(int) string8.size, DN_ArrayCountU(EXPECTED) - 1);
DN_UT_Assert(&result, DN_Memcmp(EXPECTED, string8.data, sizeof(EXPECTED)) == 0); DN_UT_Assert(&result, DN_Memcmp(EXPECTED, string8.data, sizeof(EXPECTED)) == 0);
} }
DN_TCScratchEnd(&scratch);
} }
#endif // DN_PLATFORM_WIN32 #endif // DN_PLATFORM_WIN32
return result; return result;

View File

@ -2,7 +2,7 @@
#define DN_TYPE_INFO_H #define DN_TYPE_INFO_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
/* /*

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,8 @@
#define DN_OS_H #define DN_OS_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#endif #endif
#include <new> // operator new #include <new> // operator new
@ -197,8 +197,7 @@ typedef DN_I32(DN_OSThreadFunc)(struct DN_OSThread *);
struct DN_OSThread struct DN_OSThread
{ {
DN_Str8x64 name; DN_Str8x64 name;
DN_OSTLS tls; DN_TCCore context;
DN_OSTLSInitArgs tls_init_args;
void *handle; void *handle;
DN_U64 thread_id; DN_U64 thread_id;
void *user_context; void *user_context;
@ -229,7 +228,7 @@ struct DN_OSHttpResponse
// Synchronous HTTP response uses the TLS scratch arena whereas async // Synchronous HTTP response uses the TLS scratch arena whereas async
// calls use their own dedicated arena. // calls use their own dedicated arena.
DN_Arena tmp_arena; DN_Arena tmp_arena;
DN_Arena *tmem_arena; DN_Arena *scratch_arena;
DN_Str8Builder builder; DN_Str8Builder builder;
DN_OSSemaphore on_complete_semaphore; DN_OSSemaphore on_complete_semaphore;
@ -245,10 +244,9 @@ struct DN_OSHttpResponse
struct DN_OSCore struct DN_OSCore
{ {
DN_CPUReport cpu_report; DN_CPUReport cpu_report;
DN_OSTLS tls; // Thread local storage state for the main thread.
// NOTE: Logging // NOTE: Logging
DN_LOGEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine DN_LogEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine
void * log_user_data; // User pointer passed into 'log_callback' void * log_user_data; // User pointer passed into 'log_callback'
bool log_to_file; // Output logs to file as well as standard out bool log_to_file; // Output logs to file as well as standard out
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ? DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
@ -280,14 +278,19 @@ struct DN_OSDiskSpace
DN_U64 size; DN_U64 size;
}; };
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet (DN_ArenaMemFuncType type);
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults ();
DN_API DN_Arena DN_ArenaFromHeap (DN_U64 size, DN_ArenaFlags flags);
DN_API DN_Arena DN_ArenaFromVMem (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder);
DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os); DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os);
DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path); DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path);
DN_API DN_Str8 DN_OS_BytesFromHexPtrArenaFrame (void const *hex, DN_USize hex_count);
DN_API DN_Str8 DN_OS_BytesFromHexStr8ArenaFrame (DN_Str8 hex);
DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaFrame (void const *bytes, DN_USize bytes_count);
DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS (void const *bytes, DN_USize bytes_count);
DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags); DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags); DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags);
DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size); DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size);
@ -312,7 +315,6 @@ DN_API bool DN_OS_SetEnvVar (D
DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path); DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path);
DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena); DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena); DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena);
#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena())
DN_API void DN_OS_SleepMs (DN_UInt milliseconds); DN_API void DN_OS_SleepMs (DN_UInt milliseconds);
DN_API DN_U64 DN_OS_PerfCounterNow (); DN_API DN_U64 DN_OS_PerfCounterNow ();
@ -329,28 +331,28 @@ DN_API DN_F64 DN_OS_TimerUs (D
DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer); DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer);
DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency); DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency);
DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err); DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_ErrSink *err);
DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err); DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err);
DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err); DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_ErrSink *err);
DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err); DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *err);
DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err); DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_ErrSink *err);
DN_API void DN_OS_FileClose (DN_OSFile *file); DN_API void DN_OS_FileClose (DN_OSFile *file);
DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err); DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_ErrSink *err);
DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err); DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_ErrSink *err);
DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err); DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_ErrSink *err);
DN_API DN_Str8 DN_OS_FileReadAllTLS (DN_Str8 path, DN_OSErrSink *err);
DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path); DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path);
DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against); DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against);
@ -361,42 +363,25 @@ DN_API bool DN_OS_PathMakeDir (D
DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it); DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it);
DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
DN_API bool DN_OS_PathAddRefTLS (DN_OSPath *fs_path, DN_Str8 path);
DN_API bool DN_OS_PathAddRefFrame (DN_OSPath *fs_path, DN_Str8 path);
DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
#define DN_OS_PathAddFromTLS(...) DN_OS_PathAdd(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathAddFromFrame(...) DN_OS_PathAdd(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_OS_PathAddFFromTLS(...) DN_OS_PathAddF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathAddFFromFrame(...) DN_OS_PathAddF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API bool DN_OS_PathPop (DN_OSPath *fs_path); DN_API bool DN_OS_PathPop (DN_OSPath *fs_path);
DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator); DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator);
#define DN_OS_PathBuildWithSeperatorFromTLS(...) DN_OS_PathBuildWithSeperator(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathBuildWithSeperatorFromFrame(...) DN_OS_PathBuildWithSeperator(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor); DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor);
#define DN_OS_PathToFromTLS(...) DN_OS_PathTo(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathToFromFrame(...) DN_OS_PathTo(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_OS_PathToFFromTLS(...) DN_OS_PathToF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathToFFromFrame(...) DN_OS_PathToF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path); DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path);
#define DN_OS_PathFromTLS(...) DN_OS_Path(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathFromFrame(...) DN_OS_Path(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_OS_PathFFromTLS(...) DN_OS_PathF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathFFromFrame(...) DN_OS_PathF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
#define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("/")) #define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("/"))
#define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("\\")) #define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("\\"))
#define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString) #define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString)
DN_API void DN_OS_Exit (int32_t exit_code); DN_API void DN_OS_Exit (int32_t exit_code);
DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err); DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_ErrSink *err);
DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err); DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_ErrSink *err);
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err); DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_ErrSink *err);
DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err); DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_ErrSink *err);
DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena); DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
#define DN_OS_ExecOrAbortFromTLS (...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena())
DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count); DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count);
DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore); DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore);
@ -426,4 +411,104 @@ DN_API void DN_OS_HttpRequestAsync (D
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response); DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);
DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response); DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response);
DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
// NOTE: DN_OSPrint
enum DN_OSPrintDest
{
DN_OSPrintDest_Out,
DN_OSPrintDest_Err,
};
// NOTE: Print Macros
#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string)
#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args)
#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string)
#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args)
#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string)
#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args)
#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string);
#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args);
#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string)
#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args)
#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string)
#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args)
#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string)
#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args)
#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string);
#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args);
// NOTE: Print
DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string);
DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string);
DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string);
DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string);
DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
// NOTE: DN_VArray
// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS.
template <typename T> struct DN_VArray
{
T *data; // Pointer to the start of the array items in the block of memory
DN_USize size; // Number of items currently in the array
DN_USize max; // Maximum number of items this array can store
DN_USize commit; // Bytes committed
T *begin() { return data; }
T *end () { return data + size; }
T const *begin() const { return data; }
T const *end () const { return data + size; }
};
template <typename T> DN_VArray<T> DN_OS_VArrayInitByteSize (DN_USize byte_size);
template <typename T> DN_VArray<T> DN_OS_VArrayInit (DN_USize max);
template <typename T> DN_VArray<T> DN_OS_VArrayInitSlice (DN_Slice<T> slice, DN_USize max);
template <typename T, DN_USize N> DN_VArray<T> DN_OS_VArrayInitCArray (T const (&items)[N], DN_USize max);
template <typename T> void DN_OS_VArrayDeinit (DN_VArray<T> *array);
template <typename T> bool DN_OS_VArrayIsValid (DN_VArray<T> const *array);
template <typename T> bool DN_OS_VArrayReserve (DN_VArray<T> *array, DN_USize count);
template <typename T> T * DN_OS_VArrayAddArray (DN_VArray<T> *array, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_OS_VArrayAddCArray (DN_VArray<T> *array, T const (&items)[N]);
template <typename T> T * DN_OS_VArrayAdd (DN_VArray<T> *array, T const &item);
#define DN_OS_VArrayAddArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddArray(__VA_ARGS__))
#define DN_OS_VArrayAddCArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddCArray(__VA_ARGS__))
#define DN_OS_VArrayAddAssert(...) DN_HardAssert(DN_OS_VArrayAdd(__VA_ARGS__))
template <typename T> T * DN_OS_VArrayMakeArray (DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem);
template <typename T> T * DN_OS_VArrayMake (DN_VArray<T> *array, DN_ZMem z_mem);
#define DN_OS_VArrayMakeArrayAssert(...) DN_HardAssert(DN_OS_VArrayMakeArray(__VA_ARGS__))
#define DN_OS_VArrayMakeAssert(...) DN_HardAssert(DN_OS_VArrayMake(__VA_ARGS__))
template <typename T> T * DN_OS_VArrayInsertArray (DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_OS_VArrayInsertCArray (DN_VArray<T> *array, DN_USize index, T const (&items)[N]);
template <typename T> T * DN_OS_VArrayInsert (DN_VArray<T> *array, DN_USize index, T const &item);
#define DN_OS_VArrayInsertArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertArray(__VA_ARGS__))
#define DN_OS_VArrayInsertCArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertCArray(__VA_ARGS__))
#define DN_OS_VArrayInsertAssert(...) DN_HardAssert(DN_OS_VArrayInsert(__VA_ARGS__))
template <typename T> T DN_OS_VArrayPopFront (DN_VArray<T> *array, DN_USize count);
template <typename T> T DN_OS_VArrayPopBack (DN_VArray<T> *array, DN_USize count);
template <typename T> DN_ArrayEraseResult DN_OS_VArrayEraseRange (DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T> void DN_OS_VArrayClear (DN_VArray<T> *array, DN_ZMem z_mem);
#endif // !defined(DN_OS_H) #endif // !defined(DN_OS_H)

View File

@ -1,36 +0,0 @@
#define DN_OS_ALLOCATOR_CPP
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#include "../dn_inc.h"
#endif
static void *DN_ArenaBasicAllocFromOSHeap(DN_USize size)
{
void *result = DN_OS_MemAlloc(size, DN_ZMem_Yes);
return result;
}
DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags)
{
DN_ArenaMemFuncs mem_funcs = {};
mem_funcs.type = DN_ArenaMemFuncType_Basic;
mem_funcs.basic_alloc = DN_ArenaBasicAllocFromOSHeap;
mem_funcs.basic_dealloc = DN_OS_MemDealloc;
DN_Arena result = DN_ArenaFromMemFuncs(size, size, flags, mem_funcs);
return result;
}
DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags)
{
DN_ArenaMemFuncs mem_funcs = {};
mem_funcs.type = DN_ArenaMemFuncType_VMem;
mem_funcs.vmem_page_size = g_dn_->os.page_size;
mem_funcs.vmem_reserve = DN_OS_MemReserve;
mem_funcs.vmem_commit = DN_OS_MemCommit;
mem_funcs.vmem_release = DN_OS_MemRelease;
DN_Arena result = DN_ArenaFromMemFuncs(reserve, commit, flags, mem_funcs);
return result;
}

View File

@ -1,11 +0,0 @@
#if !defined(DN_OS_ALLOCATOR_H)
#define DN_OS_ALLOCATOR_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#endif
DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags);
DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
#endif // !defined(DN_OS_ALLOCATOR_H)

View File

@ -1,204 +0,0 @@
#define DN_OS_CONTAINERS_CPP
#include "dn_os_containers.h"
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$$\ $$$$$$\
// $$ __$$\ $$ __$$\ $$$\ $$ |\__$$ __|$$ __$$\ \_$$ _|$$$\ $$ |$$ _____|$$ __$$\ $$ __$$\
// $$ / \__|$$ / $$ |$$$$\ $$ | $$ | $$ / $$ | $$ | $$$$\ $$ |$$ | $$ | $$ |$$ / \__|
// $$ | $$ | $$ |$$ $$\$$ | $$ | $$$$$$$$ | $$ | $$ $$\$$ |$$$$$\ $$$$$$$ |\$$$$$$\
// $$ | $$ | $$ |$$ \$$$$ | $$ | $$ __$$ | $$ | $$ \$$$$ |$$ __| $$ __$$< \____$$\
// $$ | $$\ $$ | $$ |$$ |\$$$ | $$ | $$ | $$ | $$ | $$ |\$$$ |$$ | $$ | $$ |$$\ $$ |
// \$$$$$$ | $$$$$$ |$$ | \$$ | $$ | $$ | $$ |$$$$$$\ $$ | \$$ |$$$$$$$$\ $$ | $$ |\$$$$$$ |
// \______/ \______/ \__| \__| \__| \__| \__|\______|\__| \__|\________|\__| \__| \______/
//
// dn_containers.cpp
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
// NOTE: DN_VArray /////////////////////////////////////////////////////////////////////////////////
template <typename T>
DN_VArray<T> DN_VArray_InitByteSize(DN_USize byte_size)
{
DN_VArray<T> result = {};
result.data = DN_Cast(T *) DN_OS_MemReserve(byte_size, DN_MemCommit_No, DN_MemPage_ReadWrite);
if (result.data)
result.max = byte_size / sizeof(T);
return result;
}
template <typename T>
DN_VArray<T> DN_VArray_Init(DN_USize max)
{
DN_VArray<T> result = DN_VArray_InitByteSize<T>(max * sizeof(T));
DN_Assert(result.max >= max);
return result;
}
template <typename T>
DN_VArray<T> DN_VArray_InitSlice(DN_Slice<T> slice, DN_USize max)
{
DN_USize real_max = DN_Max(slice.size, max);
DN_VArray<T> result = DN_VArray_Init<T>(real_max);
if (DN_VArray_IsValid(&result))
DN_VArray_AddArray(&result, slice.data, slice.size);
return result;
}
template <typename T, DN_USize N>
DN_VArray<T> DN_VArray_InitCArray(T const (&items)[N], DN_USize max)
{
DN_USize real_max = DN_Max(N, max);
DN_VArray<T> result = DN_VArray_InitSlice(DN_Slice_Init(items, N), real_max);
return result;
}
template <typename T>
void DN_VArray_Deinit(DN_VArray<T> *array)
{
DN_OS_MemRelease(array->data, array->max * sizeof(T));
*array = {};
}
template <typename T>
bool DN_VArray_IsValid(DN_VArray<T> const *array)
{
bool result = array->data && array->size <= array->max;
return result;
}
template <typename T>
DN_Slice<T> DN_VArray_Slice(DN_VArray<T> const *array)
{
DN_Slice<T> result = {};
if (array)
result = DN_Slice_Init<T>(array->data, array->size);
return result;
}
template <typename T>
T *DN_VArray_AddArray(DN_VArray<T> *array, T const *items, DN_USize count)
{
T *result = DN_VArray_MakeArray(array, count, DN_ZMem_No);
if (result)
DN_Memcpy(result, items, count * sizeof(T));
return result;
}
template <typename T, DN_USize N>
T *DN_VArray_AddCArray(DN_VArray<T> *array, T const (&items)[N])
{
T *result = DN_VArray_AddArray(array, items, N);
return result;
}
template <typename T>
T *DN_VArray_Add(DN_VArray<T> *array, T const &item)
{
T *result = DN_VArray_AddArray(array, &item, 1);
return result;
}
template <typename T>
T *DN_VArray_MakeArray(DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem)
{
if (!DN_VArray_IsValid(array))
return nullptr;
if (!DN_CheckF((array->size + count) < array->max, "Array is out of space (user requested +%zu items, array has %zu/%zu items)", count, array->size, array->max))
return nullptr;
if (!DN_VArray_Reserve(array, count))
return nullptr;
// TODO: Use placement new
T *result = array->data + array->size;
array->size += count;
if (z_mem == DN_ZMem_Yes)
DN_Memset(result, 0, count * sizeof(T));
return result;
}
template <typename T>
T *DN_VArray_Make(DN_VArray<T> *array, DN_ZMem z_mem)
{
T *result = DN_VArray_MakeArray(array, 1, z_mem);
return result;
}
template <typename T>
T *DN_VArray_InsertArray(DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count)
{
T *result = nullptr;
if (!DN_VArray_IsValid(array))
return result;
if (DN_VArray_Reserve(array, array->size + count))
result = DN_CArray_InsertArray(array->data, &array->size, array->max, index, items, count);
return result;
}
template <typename T, DN_USize N>
T *DN_VArray_InsertCArray(DN_VArray<T> *array, DN_USize index, T const (&items)[N])
{
T *result = DN_VArray_InsertArray(array, index, items, N);
return result;
}
template <typename T>
T *DN_VArray_Insert(DN_VArray<T> *array, DN_USize index, T const &item)
{
T *result = DN_VArray_InsertArray(array, index, &item, 1);
return result;
}
template <typename T>
T *DN_VArray_PopFront(DN_VArray<T> *array, DN_USize count)
{
T *result = DN_CArray_PopFront(array->data, &array->size, count);
return result;
}
template <typename T>
T *DN_VArray_PopBack(DN_VArray<T> *array, DN_USize count)
{
T *result = DN_CArray_PopBack(array->data, &array->size, count);
return result;
}
template <typename T>
DN_ArrayEraseResult DN_VArray_EraseRange(DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase)
{
DN_ArrayEraseResult result = {};
if (!DN_VArray_IsValid(array))
return result;
result = DN_CArray_EraseRange<T>(array->data, &array->size, begin_index, count, erase);
return result;
}
template <typename T>
void DN_VArray_Clear(DN_VArray<T> *array, DN_ZMem z_mem)
{
if (array) {
if (z_mem == DN_ZMem_Yes)
DN_Memset(array->data, 0, array->size * sizeof(T));
array->size = 0;
}
}
template <typename T>
bool DN_VArray_Reserve(DN_VArray<T> *array, DN_USize count)
{
if (!DN_VArray_IsValid(array) || count == 0)
return false;
DN_USize real_commit = (array->size + count) * sizeof(T);
DN_USize aligned_commit = DN_AlignUpPowerOfTwo(real_commit, g_dn_->os.page_size);
if (array->commit >= aligned_commit)
return true;
bool result = DN_OS_MemCommit(array->data, aligned_commit, DN_MemPage_ReadWrite);
array->commit = aligned_commit;
return result;
}

View File

@ -1,51 +0,0 @@
#if !defined(DN_OS_CONTAINERS_H)
#define DN_OS_CONTAINERS_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#endif
// NOTE: DN_VArray
// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS.
template <typename T> struct DN_VArray
{
T *data; // Pointer to the start of the array items in the block of memory
DN_USize size; // Number of items currently in the array
DN_USize max; // Maximum number of items this array can store
DN_USize commit; // Bytes committed
T *begin() { return data; }
T *end () { return data + size; }
T const *begin() const { return data; }
T const *end () const { return data + size; }
};
template <typename T> DN_VArray<T> DN_VArray_InitByteSize (DN_USize byte_size);
template <typename T> DN_VArray<T> DN_VArray_Init (DN_USize max);
template <typename T> DN_VArray<T> DN_VArray_InitSlice (DN_Slice<T> slice, DN_USize max);
template <typename T, DN_USize N> DN_VArray<T> DN_VArray_InitCArray (T const (&items)[N], DN_USize max);
template <typename T> void DN_VArray_Deinit (DN_VArray<T> *array);
template <typename T> bool DN_VArray_IsValid (DN_VArray<T> const *array);
template <typename T> DN_Slice<T> DN_VArray_Slice (DN_VArray<T> const *array);
template <typename T> bool DN_VArray_Reserve (DN_VArray<T> *array, DN_USize count);
template <typename T> T * DN_VArray_AddArray (DN_VArray<T> *array, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_VArray_AddCArray (DN_VArray<T> *array, T const (&items)[N]);
template <typename T> T * DN_VArray_Add (DN_VArray<T> *array, T const &item);
#define DN_VArray_AddArrayAssert(...) DN_HardAssert(DN_VArray_AddArray(__VA_ARGS__))
#define DN_VArray_AddCArrayAssert(...) DN_HardAssert(DN_VArray_AddCArray(__VA_ARGS__))
#define DN_VArray_AddAssert(...) DN_HardAssert(DN_VArray_Add(__VA_ARGS__))
template <typename T> T * DN_VArray_MakeArray (DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem);
template <typename T> T * DN_VArray_Make (DN_VArray<T> *array, DN_ZMem z_mem);
#define DN_VArray_MakeArrayAssert(...) DN_HardAssert(DN_VArray_MakeArray(__VA_ARGS__))
#define DN_VArray_MakeAssert(...) DN_HardAssert(DN_VArray_Make(__VA_ARGS__))
template <typename T> T * DN_VArray_InsertArray (DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_VArray_InsertCArray (DN_VArray<T> *array, DN_USize index, T const (&items)[N]);
template <typename T> T * DN_VArray_Insert (DN_VArray<T> *array, DN_USize index, T const &item);
#define DN_VArray_InsertArrayAssert(...) DN_HardAssert(DN_VArray_InsertArray(__VA_ARGS__))
#define DN_VArray_InsertCArrayAssert(...) DN_HardAssert(DN_VArray_InsertCArray(__VA_ARGS__))
#define DN_VArray_InsertAssert(...) DN_HardAssert(DN_VArray_Insert(__VA_ARGS__))
template <typename T> T DN_VArray_PopFront (DN_VArray<T> *array, DN_USize count);
template <typename T> T DN_VArray_PopBack (DN_VArray<T> *array, DN_USize count);
template <typename T> DN_ArrayEraseResult DN_VArray_EraseRange (DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T> void DN_VArray_Clear (DN_VArray<T> *array, DN_ZMem z_mem);
#endif // !defined(DN_OS_CONTAINERS_H)

View File

@ -1,12 +1,14 @@
#define DN_OS_POSIX_CPP #define DN_OS_POSIX_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#include "dn_os_posix.h"
#endif #endif
#include <dirent.h> // readdir, opendir, closedir #include <dirent.h> // readdir, opendir, closedir
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <sys/mman.h>
// NOTE: DN_OSMem // NOTE: DN_OSMem
static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect) static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect)
@ -226,17 +228,20 @@ DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value)
DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path) DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_OSDiskSpace result = {}; DN_OSDiskSpace result = {};
DN_Str8 path_z_terminated = DN_Str8FromStr8Arena(tmem.arena, path); DN_Str8 path_z_terminated = DN_Str8FromStr8Arena(tmem.arena, path);
struct statvfs info = {}; struct statvfs info = {};
if (statvfs(path_z_terminated.data, &info) != 0) if (statvfs(path_z_terminated.data, &info) != 0) {
DN_TCScratchEnd(&tmem);
return result; return result;
}
result.success = true; result.success = true;
result.avail = info.f_bavail * info.f_frsize; result.avail = info.f_bavail * info.f_frsize;
result.size = info.f_blocks * info.f_frsize; result.size = info.f_blocks * info.f_frsize;
DN_TCScratchEnd(&tmem);
return result; return result;
} }
@ -313,23 +318,23 @@ DN_API DN_U64 DN_OS_PerfCounterFrequency()
return result; return result;
} }
static DN_POSIXCore *DN_OS_GetPOSIXCore_() static DN_OSPosixCore *DN_OS_GetPOSIXCore_()
{ {
DN_Assert(g_dn_ && g_dn_->os.platform_context); DN_Assert(g_dn_ && g_dn_->os.platform_context);
DN_POSIXCore *result = DN_Cast(DN_POSIXCore *)g_dn_->os.platform_context; DN_OSPosixCore *result = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context;
return result; return result;
} }
DN_API DN_U64 DN_OS_PerfCounterNow() DN_API DN_U64 DN_OS_PerfCounterNow()
{ {
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
struct timespec ts; struct timespec ts;
clock_gettime(posix->clock_monotonic_raw ? CLOCK_MONOTONIC_RAW : CLOCK_MONOTONIC, &ts); clock_gettime(posix->clock_monotonic_raw ? CLOCK_MONOTONIC_RAW : CLOCK_MONOTONIC, &ts);
DN_U64 result = DN_Cast(DN_U64) ts.tv_sec * 1'000'000'000 + DN_Cast(DN_U64) ts.tv_nsec; DN_U64 result = DN_Cast(DN_U64) ts.tv_sec * 1'000'000'000 + DN_Cast(DN_U64) ts.tv_nsec;
return result; return result;
} }
DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error)
{ {
bool result = false; bool result = false;
#if defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
@ -385,9 +390,9 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
result = (bytes_written == stat_existing.st_size); result = (bytes_written == stat_existing.st_size);
if (!result) { if (!result) {
int error_code = errno; int error_code = errno;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 file_size_str8 = DN_Str8FromByteCount(tmem.arena, stat_existing.st_size, DN_ByteCountType_Auto); DN_Str8 file_size_str8 = DN_Str8FromByteCount(scratch.arena, stat_existing.st_size, DN_ByteCountType_Auto);
DN_Str8 bytes_written_str8 = DN_Str8FromByteCount(tmem.arena, bytes_written, DN_ByteCountType_Auto); DN_Str8 bytes_written_str8 = DN_Str8FromByteCount(scratch.arena, bytes_written, DN_ByteCountType_Auto);
DN_OS_ErrSinkAppendF(error, DN_OS_ErrSinkAppendF(error,
error_code, error_code,
"Failed to copy file '%.*s' to '%.*s', we copied %.*s but the file " "Failed to copy file '%.*s' to '%.*s', we copied %.*s but the file "
@ -398,13 +403,14 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
DN_Str8PrintFmt(file_size_str8), DN_Str8PrintFmt(file_size_str8),
error_code, error_code,
strerror(error_code)); strerror(error_code));
DN_TCScratchEnd(&scratch);
} }
#endif #endif
return result; return result;
} }
DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error)
{ {
// See: https://github.com/gingerBill/gb/blob/master/gb.h // See: https://github.com/gingerBill/gb/blob/master/gb.h
bool result = false; bool result = false;
@ -435,7 +441,7 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path,
DN_OSFileOpen open_mode, DN_OSFileOpen open_mode,
DN_OSFileAccess access, DN_OSFileAccess access,
DN_OSErrSink *error) DN_ErrSink *error)
{ {
DN_OSFile result = {}; DN_OSFile result = {};
if (path.size == 0 || path.size <= 0) if (path.size == 0 || path.size <= 0)
@ -506,7 +512,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path,
return result; return result;
} }
DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err) DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err)
{ {
DN_OSFileRead result = {}; DN_OSFileRead result = {};
if (!file || !file->handle || file->error || !buffer || size <= 0) if (!file || !file->handle || file->error || !buffer || size <= 0)
@ -514,9 +520,10 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size
result.bytes_read = fread(buffer, 1, size, DN_Cast(FILE *) file->handle); result.bytes_read = fread(buffer, 1, size, DN_Cast(FILE *) file->handle);
if (feof(DN_Cast(FILE*)file->handle)) { if (feof(DN_Cast(FILE*)file->handle)) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
DN_OS_ErrSinkAppendF(err, 1, "Failed to read %S from file", buffer_size_str8); DN_OS_ErrSinkAppendF(err, 1, "Failed to read %S from file", buffer_size_str8);
DN_TCScratchEnd(&scratch);
return result; return result;
} }
@ -524,7 +531,7 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size
return result; return result;
} }
DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_OSErrSink *err) DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_ErrSink *err)
{ {
if (!file || !file->handle || file->error || !buffer || size <= 0) if (!file || !file->handle || file->error || !buffer || size <= 0)
return false; return false;
@ -532,14 +539,15 @@ DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize siz
fwrite(buffer, DN_Cast(DN_USize) size, 1 /*count*/, DN_Cast(FILE *) file->handle) == fwrite(buffer, DN_Cast(DN_USize) size, 1 /*count*/, DN_Cast(FILE *) file->handle) ==
1 /*count*/; 1 /*count*/;
if (!result) { if (!result) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
DN_OS_ErrSinkAppendF(err, 1, "Failed to write buffer (%s) to file handle", DN_Str8PrintFmt(buffer_size_str8)); DN_OS_ErrSinkAppendF(err, 1, "Failed to write buffer (%s) to file handle", DN_Str8PrintFmt(buffer_size_str8));
DN_TCScratchEnd(&scratch);
} }
return result; return result;
} }
DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_OSErrSink *err) DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_ErrSink *err)
{ {
// TODO: errno is not thread safe // TODO: errno is not thread safe
int fd = fileno(DN_Cast(FILE *) file->handle); int fd = fileno(DN_Cast(FILE *) file->handle);
@ -622,7 +630,7 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
DN_API bool DN_OS_PathMakeDir(DN_Str8 path) DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
bool result = true; bool result = true;
// TODO(doyle): Implement this without using the path indexes, it's not // TODO(doyle): Implement this without using the path indexes, it's not
@ -630,7 +638,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
DN_USize path_indexes_size = 0; DN_USize path_indexes_size = 0;
uint16_t path_indexes[64] = {}; uint16_t path_indexes[64] = {};
DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, path); DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, path);
for (DN_USize index = copy.size - 1; index < copy.size; index--) { for (DN_USize index = copy.size - 1; index < copy.size; index--) {
bool first_char = index == (copy.size - 1); bool first_char = index == (copy.size - 1);
char ch = copy.data[index]; char ch = copy.data[index];
@ -649,6 +657,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
// NOTE: There's something that exists in at this path, but // NOTE: There's something that exists in at this path, but
// it's not a directory. This request to make a directory is // it's not a directory. This request to make a directory is
// invalid. // invalid.
DN_TCScratchEnd(&scratch);
return false; return false;
} else if (DN_OS_PathIsDir(copy)) { } else if (DN_OS_PathIsDir(copy)) {
// NOTE: We found a directory, we can stop here and start // NOTE: We found a directory, we can stop here and start
@ -673,6 +682,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
if (index != 0) if (index != 0)
copy.data[path_index] = temp; copy.data[path_index] = temp;
} }
DN_TCScratchEnd(&scratch);
return result; return result;
} }
@ -723,7 +733,7 @@ enum DN_OSPipeType_
DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
DN_Arena *arena, DN_Arena *arena,
DN_OSErrSink *error) DN_ErrSink *error)
{ {
DN_OSExecResult result = {}; DN_OSExecResult result = {};
if (!handle.process || handle.os_error_code || handle.exit_code) { if (!handle.process || handle.os_error_code || handle.exit_code) {
@ -786,10 +796,10 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
// NOTE: Read the data from the read end of the pipe // NOTE: Read the data from the read end of the pipe
if (result.os_error_code == 0) { if (result.os_error_code == 0) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
if (arena && handle.stdout_read) { if (arena && handle.stdout_read) {
char buffer[4096]; char buffer[4096];
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena); DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena);
for (;;) { for (;;) {
ssize_t bytes_read = ssize_t bytes_read =
read(stdout_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer)); read(stdout_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer));
@ -803,7 +813,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
if (arena && handle.stderr_read) { if (arena && handle.stderr_read) {
char buffer[4096]; char buffer[4096];
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena); DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena);
for (;;) { for (;;) {
ssize_t bytes_read = ssize_t bytes_read =
read(stderr_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer)); read(stderr_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer));
@ -814,6 +824,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
result.stderr_text = DN_Str8BuilderBuild(&builder, arena); result.stderr_text = DN_Str8BuilderBuild(&builder, arena);
} }
DN_TCScratchEnd(&scratch);
} }
close(stdout_pipe[DN_OSPipeType__Read]); close(stdout_pipe[DN_OSPipeType__Read]);
@ -823,7 +834,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line, DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
DN_OSExecArgs *args, DN_OSExecArgs *args,
DN_OSErrSink *error) DN_ErrSink *error)
{ {
#if defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
DN_InvalidCodePathF("Unsupported operation"); DN_InvalidCodePathF("Unsupported operation");
@ -834,12 +845,13 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
if (cmd_line.size == 0) if (cmd_line.size == 0)
return result; return result;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 cmd_rendered = DN_Slice_Str8Render(tmem.arena, cmd_line, DN_Str8Lit(" ")); DN_DEFER { DN_TCScratchEnd(&scratch); };
DN_Str8 cmd_rendered = DN_Slice_Str8Render(scratch.arena, cmd_line, DN_Str8Lit(" "));
int stdout_pipe[DN_OSPipeType__Count] = {}; int stdout_pipe[DN_OSPipeType__Count] = {};
int stderr_pipe[DN_OSPipeType__Count] = {}; int stderr_pipe[DN_OSPipeType__Count] = {};
// NOTE: Open stdout pipe ////////////////////////////////////////////////////////////////////// // NOTE: Open stdout pipe
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) { if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) {
if (pipe(stdout_pipe) == -1) { if (pipe(stdout_pipe) == -1) {
result.os_error_code = errno; result.os_error_code = errno;
@ -929,7 +941,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
// NOTE: Convert the command into something suitable for execvp // NOTE: Convert the command into something suitable for execvp
char **argv = char **argv =
DN_ArenaNewArray(tmem.arena, char *, cmd_line.size + 1 /*null*/, DN_ZMem_Yes); DN_ArenaNewArray(scratch.arena, char *, cmd_line.size + 1 /*null*/, DN_ZMem_Yes);
if (!argv) { if (!argv) {
result.exit_code = -1; result.exit_code = -1;
DN_OS_ErrSinkAppendF( DN_OS_ErrSinkAppendF(
@ -942,7 +954,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
for (DN_ForIndexU(arg_index, cmd_line.size)) { for (DN_ForIndexU(arg_index, cmd_line.size)) {
DN_Str8 arg = cmd_line.data[arg_index]; DN_Str8 arg = cmd_line.data[arg_index];
argv[arg_index] = DN_Str8FromStr8Arena(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated argv[arg_index] = DN_Str8FromStr8Arena(scratch.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated
} }
// NOTE: Change the working directory if there is one // NOTE: Change the working directory if there is one
@ -960,7 +972,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
if (args->working_dir.size) { if (args->working_dir.size) {
prev_working_dir = get_current_dir_name(); prev_working_dir = get_current_dir_name();
DN_Str8 working_dir = DN_Str8FromStr8Arena(tmem.arena, args->working_dir); DN_Str8 working_dir = DN_Str8FromStr8Arena(scratch.arena, args->working_dir);
if (chdir(working_dir.data) == -1) { if (chdir(working_dir.data) == -1) {
result.os_error_code = errno; result.os_error_code = errno;
DN_OS_ErrSinkAppendF( DN_OS_ErrSinkAppendF(
@ -1014,21 +1026,21 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
char *stderr_buffer, char *stderr_buffer,
size_t *stderr_size, size_t *stderr_size,
DN_U32 timeout_ms, DN_U32 timeout_ms,
DN_OSErrSink *err) DN_ErrSink *err)
{ {
DN_InvalidCodePath; DN_InvalidCodePath;
DN_OSExecResult result = {}; DN_OSExecResult result = {};
return result; return result;
} }
static DN_POSIXSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64) static DN_OSPosixSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64)
{ {
DN_POSIXSyncPrimitive *result = nullptr; DN_OSPosixSyncPrimitive *result = nullptr;
DN_Memcpy(&result, &u64, sizeof(result)); DN_Memcpy(&result, &u64, sizeof(result));
return result; return result;
} }
static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive) static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_OSPosixSyncPrimitive *primitive)
{ {
DN_U64 result = 0; DN_U64 result = 0;
static_assert(sizeof(result) >= sizeof(primitive), "Pointer size mis-match"); static_assert(sizeof(result) >= sizeof(primitive), "Pointer size mis-match");
@ -1036,10 +1048,10 @@ static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive)
return result; return result;
} }
static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_() static DN_OSPosixSyncPrimitive *DN_POSIX_AllocSyncPrimitive_()
{ {
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
DN_POSIXSyncPrimitive *result = nullptr; DN_OSPosixSyncPrimitive *result = nullptr;
pthread_mutex_lock(&posix->sync_primitive_free_list_mutex); pthread_mutex_lock(&posix->sync_primitive_free_list_mutex);
{ {
if (posix->sync_primitive_free_list) { if (posix->sync_primitive_free_list) {
@ -1048,17 +1060,17 @@ static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_()
result->next = nullptr; result->next = nullptr;
} else { } else {
DN_OSCore *os = &g_dn_->os; DN_OSCore *os = &g_dn_->os;
result = DN_ArenaNew(&os->arena, DN_POSIXSyncPrimitive, DN_ZMem_Yes); result = DN_ArenaNew(&os->arena, DN_OSPosixSyncPrimitive, DN_ZMem_Yes);
} }
} }
pthread_mutex_unlock(&posix->sync_primitive_free_list_mutex); pthread_mutex_unlock(&posix->sync_primitive_free_list_mutex);
return result; return result;
} }
static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive) static void DN_POSIX_DeallocSyncPrimitive_(DN_OSPosixSyncPrimitive *primitive)
{ {
if (primitive) { if (primitive) {
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
pthread_mutex_lock(&posix->sync_primitive_free_list_mutex); pthread_mutex_lock(&posix->sync_primitive_free_list_mutex);
primitive->next = posix->sync_primitive_free_list; primitive->next = posix->sync_primitive_free_list;
posix->sync_primitive_free_list = primitive; posix->sync_primitive_free_list = primitive;
@ -1070,7 +1082,7 @@ static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive)
DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count)
{ {
DN_OSSemaphore result = {}; DN_OSSemaphore result = {};
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
if (primitive) { if (primitive) {
int pshared = 0; // Share the semaphore across all threads in the process int pshared = 0; // Share the semaphore across all threads in the process
if (sem_init(&primitive->sem, pshared, initial_count) == 0) if (sem_init(&primitive->sem, pshared, initial_count) == 0)
@ -1084,7 +1096,7 @@ DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count)
DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore)
{ {
if (semaphore && semaphore->handle != 0) { if (semaphore && semaphore->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
sem_destroy(&primitive->sem); sem_destroy(&primitive->sem);
DN_POSIX_DeallocSyncPrimitive_(primitive); DN_POSIX_DeallocSyncPrimitive_(primitive);
*semaphore = {}; *semaphore = {};
@ -1094,7 +1106,7 @@ DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore)
DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount) DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount)
{ {
if (semaphore && semaphore->handle != 0) { if (semaphore && semaphore->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
#if defined(DN_OS_WIN32) #if defined(DN_OS_WIN32)
sem_post_multiple(&primitive->sem, amount); // mingw extension sem_post_multiple(&primitive->sem, amount); // mingw extension
#else #else
@ -1111,7 +1123,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore,
if (!semaphore || semaphore->handle == 0) if (!semaphore || semaphore->handle == 0)
return result; return result;
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) { if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) {
int wait_result = 0; int wait_result = 0;
do { do {
@ -1138,7 +1150,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore,
// NOTE: DN_OSMutex //////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSMutex ////////////////////////////////////////////////////////////////////////////////
DN_API DN_OSMutex DN_OS_MutexInit() DN_API DN_OSMutex DN_OS_MutexInit()
{ {
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
DN_OSMutex result = {}; DN_OSMutex result = {};
if (primitive) { if (primitive) {
if (pthread_mutex_init(&primitive->mutex, nullptr) == 0) if (pthread_mutex_init(&primitive->mutex, nullptr) == 0)
@ -1152,7 +1164,7 @@ DN_API DN_OSMutex DN_OS_MutexInit()
DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex)
{ {
if (mutex && mutex->handle != 0) { if (mutex && mutex->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
pthread_mutex_destroy(&primitive->mutex); pthread_mutex_destroy(&primitive->mutex);
DN_POSIX_DeallocSyncPrimitive_(primitive); DN_POSIX_DeallocSyncPrimitive_(primitive);
*mutex = {}; *mutex = {};
@ -1162,7 +1174,7 @@ DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex)
DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) DN_API void DN_OS_MutexLock(DN_OSMutex *mutex)
{ {
if (mutex && mutex->handle != 0) { if (mutex && mutex->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
pthread_mutex_lock(&primitive->mutex); pthread_mutex_lock(&primitive->mutex);
} }
} }
@ -1170,14 +1182,14 @@ DN_API void DN_OS_MutexLock(DN_OSMutex *mutex)
DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex) DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex)
{ {
if (mutex && mutex->handle != 0) { if (mutex && mutex->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
pthread_mutex_unlock(&primitive->mutex); pthread_mutex_unlock(&primitive->mutex);
} }
} }
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit() DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit()
{ {
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
DN_OSConditionVariable result = {}; DN_OSConditionVariable result = {};
if (primitive) { if (primitive) {
if (pthread_cond_init(&primitive->cv, nullptr) == 0) if (pthread_cond_init(&primitive->cv, nullptr) == 0)
@ -1191,7 +1203,7 @@ DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit()
DN_API void DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv)
{ {
if (cv && cv->handle != 0) { if (cv && cv->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
pthread_cond_destroy(&primitive->cv); pthread_cond_destroy(&primitive->cv);
DN_POSIX_DeallocSyncPrimitive_(primitive); DN_POSIX_DeallocSyncPrimitive_(primitive);
*cv = {}; *cv = {};
@ -1202,8 +1214,8 @@ DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMu
{ {
bool result = false; bool result = false;
if (cv && mutex && mutex->handle != 0 && cv->handle != 0) { if (cv && mutex && mutex->handle != 0 && cv->handle != 0) {
DN_POSIXSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); DN_OSPosixSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
DN_POSIXSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); DN_OSPosixSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
struct timespec time = {}; struct timespec time = {};
time.tv_sec = end_ts_ms / 1'000; time.tv_sec = end_ts_ms / 1'000;
@ -1224,7 +1236,7 @@ DN_API bool DN_OS_ConditionVariableWait(DN_OSConditionVariable *cv, DN_OSMutex *
DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv)
{ {
if (cv && cv->handle != 0) { if (cv && cv->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
pthread_cond_signal(&primitive->cv); pthread_cond_signal(&primitive->cv);
} }
} }
@ -1232,7 +1244,7 @@ DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv)
DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv)
{ {
if (cv && cv->handle != 0) { if (cv && cv->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
pthread_cond_broadcast(&primitive->cv); pthread_cond_broadcast(&primitive->cv);
} }
} }
@ -1307,7 +1319,7 @@ DN_API DN_U32 DN_OS_ThreadID()
return DN_Cast(DN_U32) result; return DN_Cast(DN_U32) result;
} }
DN_API void DN_Posix_Init(DN_POSIXCore *posix) DN_API void DN_OS_PosixInit(DN_OSPosixCore *posix)
{ {
int mutex_init = pthread_mutex_init(&posix->sync_primitive_free_list_mutex, nullptr); int mutex_init = pthread_mutex_init(&posix->sync_primitive_free_list_mutex, nullptr);
DN_Assert(mutex_init == 0); DN_Assert(mutex_init == 0);
@ -1320,21 +1332,22 @@ DN_API void DN_Posix_Init(DN_POSIXCore *posix)
} }
} }
DN_API void DN_Posix_ThreadSetName(DN_Str8 name) DN_API void DN_OS_PosixThreadSetName(DN_Str8 name)
{ {
#if defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
(void)name; (void)name;
#else #else
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, name); DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, name);
pthread_t thread = pthread_self(); pthread_t thread = pthread_self();
pthread_setname_np(thread, (char *)copy.data); pthread_setname_np(thread, (char *)copy.data);
DN_TCScratchEnd(&tmem);
#endif #endif
} }
DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus() DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus()
{ {
DN_POSIXProcSelfStatus result = {}; DN_OSPosixProcSelfStatus result = {};
// NOTE: Example // NOTE: Example
// //
@ -1346,11 +1359,11 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
// //
// VmSize is the total virtual memory used // VmSize is the total virtual memory used
DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/proc/self/status"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, nullptr); DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/proc/self/status"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, nullptr);
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
if (!file.error) { if (!file.error) {
DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
char buf[256]; char buf[256];
DN_Str8Builder builder = DN_Str8BuilderFromTLS(); DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena);
for (;;) { for (;;) {
DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr); DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr);
if (!read.success || read.bytes_read == 0) if (!read.success || read.bytes_read == 0)
@ -1362,8 +1375,8 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
DN_Str8 const PID = DN_Str8Lit("Pid:"); DN_Str8 const PID = DN_Str8Lit("Pid:");
DN_Str8 const VM_PEAK = DN_Str8Lit("VmPeak:"); DN_Str8 const VM_PEAK = DN_Str8Lit("VmPeak:");
DN_Str8 const VM_SIZE = DN_Str8Lit("VmSize:"); DN_Str8 const VM_SIZE = DN_Str8Lit("VmSize:");
DN_Str8 status_buf = DN_Str8BuilderBuildFromTLS(&builder); DN_Str8 status_buf = DN_Str8BuilderBuild(&builder, tmem.arena);
DN_Str8SplitResult lines = DN_Str8SplitFromTLS(status_buf, DN_Str8Lit("\n"), DN_Str8SplitIncludeEmptyStrings_No); DN_Str8SplitResult lines = DN_Str8Split(tmem.arena, status_buf, DN_Str8Lit("\n"), DN_Str8SplitIncludeEmptyStrings_No);
for (DN_ForItSize(line_it, DN_Str8, lines.data, lines.count)) { for (DN_ForItSize(line_it, DN_Str8, lines.data, lines.count)) {
DN_Str8 line = DN_Str8TrimWhitespaceAround(*line_it.data); DN_Str8 line = DN_Str8TrimWhitespaceAround(*line_it.data);
@ -1392,6 +1405,7 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
DN_Assert(to_u64.success); DN_Assert(to_u64.success);
} }
} }
DN_TCScratchEnd(&tmem);
} }
DN_OS_FileClose(&file); DN_OS_FileClose(&file);
return result; return result;
@ -1406,7 +1420,7 @@ static EM_BOOL EMWebSocketOnOpenCallback(int type, const EmscriptenWebSocketOpen
(void)event; (void)event;
// EMSCRIPTEN_RESULT result = emscripten_websocket_send_utf8_text(event->socket, R"({"jsonrpc":"2.0","id":1,"method": "eth_subscribe","params":["newHeads"]})"); // EMSCRIPTEN_RESULT result = emscripten_websocket_send_utf8_text(event->socket, R"({"jsonrpc":"2.0","id":1,"method": "eth_subscribe","params":["newHeads"]})");
// if (result) // if (result)
// DN_LOG_InfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result); // DN_LogInfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result);
return EM_TRUE; return EM_TRUE;
} }
@ -1416,9 +1430,9 @@ static EM_BOOL EMWebSocketOnMsgCallback(int type, const EmscriptenWebSocketMessa
(void)user_context; (void)user_context;
(void)event; (void)event;
if (event->isText) { if (event->isText) {
DN_LOG_InfoF("Received: %.*s", event->numBytes, event->data); DN_LogInfoF("Received: %.*s", event->numBytes, event->data);
} else { } else {
DN_LOG_InfoF("Received: %d bytes", event->numBytes); DN_LogInfoF("Received: %d bytes", event->numBytes);
} }
return EM_TRUE; return EM_TRUE;
} }
@ -1486,12 +1500,13 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
response->arena = arena; response->arena = arena;
response->builder.arena = response->builder.arena =
response->tmem_arena ? response->tmem_arena : &response->tmp_arena; response->scratch_arena ? response->scratch_arena : &response->tmp_arena;
DN_Arena *tmem = response->tmem_arena; DN_Arena *scratch = response->scratch_arena;
DN_OSTLSTMem tmem_ = DN_OS_TLSTMem(arena); DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1);
if (!tmem) DN_DEFER { DN_TCScratchEnd(&scratch_); };
tmem = tmem_.arena; if (!scratch)
scratch = scratch_.arena;
#if defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
emscripten_fetch_attr_t fetch_attribs = {}; emscripten_fetch_attr_t fetch_attribs = {};
@ -1521,8 +1536,8 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
fetch_attribs.onerror = DN_OS_HttpRequestEMFetchOnErrorCallback; fetch_attribs.onerror = DN_OS_HttpRequestEMFetchOnErrorCallback;
fetch_attribs.userData = response; fetch_attribs.userData = response;
DN_Str8 url = DN_Str8FromFmtArena(tmem, "%.*s%.*s", DN_Str8PrintFmt(host), DN_Str8PrintFmt(path)); DN_Str8 url = DN_Str8FromFmtArena(scratch, "%.*s%.*s", DN_Str8PrintFmt(host), DN_Str8PrintFmt(path));
DN_LOG_InfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'", DN_LogInfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'",
fetch_attribs.requestMethod, fetch_attribs.requestMethod,
DN_Str8PrintFmt(url), DN_Str8PrintFmt(url),
DN_Str8PrintFmt(body)); DN_Str8PrintFmt(body));

View File

@ -2,30 +2,13 @@
#define DN_OS_POSIX_H #define DN_OS_POSIX_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
#include <pthread.h> #include <pthread.h>
#include <semaphore.h> #include <semaphore.h>
/* struct DN_OSPosixProcSelfStatus
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\
// $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ \_$$ _|$$ | $$ |
// $$ / $$ |$$ / \__| $$ | $$ |$$ / $$ |$$ / \__| $$ | \$$\ $$ |
// $$ | $$ |\$$$$$$\ $$$$$$$ |$$ | $$ |\$$$$$$\ $$ | \$$$$ /
// $$ | $$ | \____$$\ $$ ____/ $$ | $$ | \____$$\ $$ | $$ $$<
// $$ | $$ |$$\ $$ | $$ | $$ | $$ |$$\ $$ | $$ | $$ /\$$\
// $$$$$$ |\$$$$$$ | $$ | $$$$$$ |\$$$$$$ |$$$$$$\ $$ / $$ |
// \______/ \______/ \__| \______/ \______/ \______|\__| \__|
//
// dn_os_posix.h
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
struct DN_POSIXProcSelfStatus
{ {
char name[64]; char name[64];
DN_U8 name_size; DN_U8 name_size;
@ -52,15 +35,14 @@ struct DN_POSIXProcSelfStatus
// unlocking, or destroying the object is undefined. [...] The effect of // unlocking, or destroying the object is undefined. [...] The effect of
// referring to a copy of the object when locking, unlocking, or destroying it // referring to a copy of the object when locking, unlocking, or destroying it
// is undefined. // is undefined.
enum DN_OSPosixSyncPrimitiveType
enum DN_POSIXSyncPrimitiveType
{ {
DN_OSPOSIXSyncPrimitiveType_Semaphore, DN_OSPosixSyncPrimitiveType_Semaphore,
DN_OSPOSIXSyncPrimitiveType_Mutex, DN_OSPosixSyncPrimitiveType_Mutex,
DN_OSPOSIXSyncPrimitiveType_ConditionVariable, DN_OSPosixSyncPrimitiveType_ConditionVariable,
}; };
struct DN_POSIXSyncPrimitive struct DN_OSPosixSyncPrimitive
{ {
union union
{ {
@ -68,17 +50,17 @@ struct DN_POSIXSyncPrimitive
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t cv; pthread_cond_t cv;
}; };
DN_POSIXSyncPrimitive *next; DN_OSPosixSyncPrimitive *next;
}; };
struct DN_POSIXCore struct DN_OSPosixCore
{ {
DN_POSIXSyncPrimitive *sync_primitive_free_list; DN_OSPosixSyncPrimitive *sync_primitive_free_list;
pthread_mutex_t sync_primitive_free_list_mutex; pthread_mutex_t sync_primitive_free_list_mutex;
bool clock_monotonic_raw; bool clock_monotonic_raw;
}; };
DN_API void DN_Posix_Init(DN_POSIXCore *posix); DN_API void DN_OS_PosixInit (DN_OSPosixCore *posix);
DN_API void DN_Posix_ThreadSetName(DN_Str8 name); DN_API void DN_OS_PosixThreadSetName (DN_Str8 name);
DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus(); DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus();
#endif // !defined(DN_OS_POSIX_H) #endif // !defined(DN_OS_POSIX_H)

View File

@ -1,170 +0,0 @@
#define DN_OS_PRINT_CPP
DN_API DN_LOGStyle DN_OS_PrintStyleColour(uint8_t r, uint8_t g, uint8_t b, DN_LOGBold bold)
{
DN_LOGStyle result = {};
result.bold = bold;
result.colour = true;
result.r = r;
result.g = g;
result.b = b;
return result;
}
DN_API DN_LOGStyle DN_OS_PrintStyleColourU32(uint32_t rgb, DN_LOGBold bold)
{
uint8_t r = (rgb >> 24) & 0xFF;
uint8_t g = (rgb >> 16) & 0xFF;
uint8_t b = (rgb >> 8) & 0xFF;
DN_LOGStyle result = DN_OS_PrintStyleColour(r, g, b, bold);
return result;
}
DN_API DN_LOGStyle DN_OS_PrintStyleBold()
{
DN_LOGStyle result = {};
result.bold = DN_LOGBold_Yes;
return result;
}
DN_API void DN_OS_Print(DN_OSPrintDest dest, DN_Str8 string)
{
DN_Assert(dest == DN_OSPrintDest_Out || dest == DN_OSPrintDest_Err);
#if defined(DN_PLATFORM_WIN32)
// NOTE: Get the output handles from kernel ////////////////////////////////////////////////////
DN_THREAD_LOCAL void *std_out_print_handle = nullptr;
DN_THREAD_LOCAL void *std_err_print_handle = nullptr;
DN_THREAD_LOCAL bool std_out_print_to_console = false;
DN_THREAD_LOCAL bool std_err_print_to_console = false;
if (!std_out_print_handle) {
unsigned long mode = 0;
(void)mode;
std_out_print_handle = GetStdHandle(STD_OUTPUT_HANDLE);
std_out_print_to_console = GetConsoleMode(std_out_print_handle, &mode) != 0;
std_err_print_handle = GetStdHandle(STD_ERROR_HANDLE);
std_err_print_to_console = GetConsoleMode(std_err_print_handle, &mode) != 0;
}
// NOTE: Select the output handle //////////////////////////////////////////////////////////////
void *print_handle = std_out_print_handle;
bool print_to_console = std_out_print_to_console;
if (dest == DN_OSPrintDest_Err) {
print_handle = std_err_print_handle;
print_to_console = std_err_print_to_console;
}
// NOTE: Write the string //////////////////////////////////////////////////////////////////////
DN_Assert(string.size < DN_Cast(unsigned long) - 1);
unsigned long bytes_written = 0;
(void)bytes_written;
if (print_to_console)
WriteConsoleA(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr);
else
WriteFile(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr);
#else
fprintf(dest == DN_OSPrintDest_Out ? stdout : stderr, "%.*s", DN_Str8PrintFmt(string));
#endif
}
DN_API void DN_OS_PrintF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_PrintFV(dest, fmt, args);
va_end(args);
}
DN_API void DN_OS_PrintFStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_PrintFVStyle(dest, style, fmt, args);
va_end(args);
}
DN_API void DN_OS_PrintStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string)
{
if (string.data && string.size) {
if (style.colour)
DN_OS_Print(dest, DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b));
if (style.bold == DN_LOGBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_BoldEscapeCode));
DN_OS_Print(dest, string);
if (style.colour || style.bold == DN_LOGBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_ResetEscapeCode));
}
}
static char *DN_OS_PrintVSPrintfChunker_(const char *buf, void *user, int len)
{
DN_Str8 string = {};
string.data = DN_Cast(char *) buf;
string.size = len;
DN_OSPrintDest dest = DN_Cast(DN_OSPrintDest) DN_Cast(uintptr_t) user;
DN_OS_Print(dest, string);
return (char *)buf;
}
DN_API void DN_OS_PrintFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args)
{
char buffer[STB_SPRINTF_MIN];
STB_SPRINTF_DECORATE(vsprintfcb)
(DN_OS_PrintVSPrintfChunker_, DN_Cast(void *) DN_Cast(uintptr_t) dest, buffer, fmt, args);
}
DN_API void DN_OS_PrintFVStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args)
{
if (fmt) {
if (style.colour)
DN_OS_Print(dest, DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b));
if (style.bold == DN_LOGBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_BoldEscapeCode));
DN_OS_PrintFV(dest, fmt, args);
if (style.colour || style.bold == DN_LOGBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_ResetEscapeCode));
}
}
DN_API void DN_OS_PrintLn(DN_OSPrintDest dest, DN_Str8 string)
{
DN_OS_Print(dest, string);
DN_OS_Print(dest, DN_Str8Lit("\n"));
}
DN_API void DN_OS_PrintLnF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_PrintLnFV(dest, fmt, args);
va_end(args);
}
DN_API void DN_OS_PrintLnFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_OS_PrintFV(dest, fmt, args);
DN_OS_Print(dest, DN_Str8Lit("\n"));
}
DN_API void DN_OS_PrintLnStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string)
{
DN_OS_PrintStyle(dest, style, string);
DN_OS_Print(dest, DN_Str8Lit("\n"));
}
DN_API void DN_OS_PrintLnFStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_PrintLnFVStyle(dest, style, fmt, args);
va_end(args);
}
DN_API void DN_OS_PrintLnFVStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_OS_PrintFVStyle(dest, style, fmt, args);
DN_OS_Print(dest, DN_Str8Lit("\n"));
}

View File

@ -1,59 +0,0 @@
#if !defined(DN_OS_PRINT_H)
#define DN_OS_PRINT_H
enum DN_OSPrintDest
{
DN_OSPrintDest_Out,
DN_OSPrintDest_Err,
};
// NOTE: Print Macros
#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string)
#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args)
#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string)
#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args)
#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string)
#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args)
#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string);
#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args);
#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string)
#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args)
#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string)
#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args)
#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string)
#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args)
#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string);
#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args);
// NOTE: Print
DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string);
DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string);
DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string);
DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string);
DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
#endif // !defined(DN_OS_PRINT_H)

View File

@ -1,211 +0,0 @@
#define DN_CORE_DEBUG_CPP
#if defined(_CLANGD)
#define DN_H_WITH_OS 1
#include "../dn.h"
#endif
DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, uint16_t limit)
{
DN_StackTraceWalkResult result = {};
#if defined(DN_OS_WIN32)
if (!arena)
return result;
static DN_TicketMutex mutex = {};
DN_TicketMutex_Begin(&mutex);
HANDLE thread = GetCurrentThread();
result.process = GetCurrentProcess();
DN_W32Core *w32 = DN_OS_GetW32Core_();
if (!w32->sym_initialised) {
w32->sym_initialised = true;
SymSetOptions(SYMOPT_LOAD_LINES);
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
DN_W32Error error = DN_W32_LastError(tmem.arena);
DN_LOG_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_Str8PrintFmt(error.msg));
}
}
CONTEXT context;
RtlCaptureContext(&context);
STACKFRAME64 frame = {};
frame.AddrPC.Offset = context.Rip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Rbp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Rsp;
frame.AddrStack.Mode = AddrModeFlat;
DN_FArray<uint64_t, 256> raw_frames = {};
while (raw_frames.size < limit) {
if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64,
result.process,
thread,
&frame,
&context,
nullptr /*ReadMemoryRoutine*/,
SymFunctionTableAccess64,
SymGetModuleBase64,
nullptr /*TranslateAddress*/))
break;
// NOTE: It might be useful one day to use frame.AddrReturn.Offset.
// If AddrPC.Offset == AddrReturn.Offset then we can detect recursion.
DN_FArray_Add(&raw_frames, frame.AddrPC.Offset);
}
DN_TicketMutex_End(&mutex);
result.base_addr = DN_ArenaNewArray(arena, uint64_t, raw_frames.size, DN_ZMem_No);
result.size = DN_Cast(uint16_t) raw_frames.size;
DN_Memcpy(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0]));
#else
(void)limit;
(void)arena;
#endif
return result;
}
static void DN_StackTraceAddWalkToStr8Builder(DN_StackTraceWalkResult const *walk, DN_Str8Builder *builder, DN_USize skip)
{
DN_StackTraceRawFrame raw_frame = {};
raw_frame.process = walk->process;
for (DN_USize index = skip; index < walk->size; index++) {
raw_frame.base_addr = walk->base_addr[index];
DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(builder->arena, raw_frame);
DN_Str8BuilderAppendF(builder, "%.*s(%zu): %.*s%s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name), (DN_Cast(int) index == walk->size - 1) ? "" : "\n");
}
}
DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk)
{
bool result = false;
if (!it || !walk || !walk->base_addr || !walk->process)
return result;
if (it->index >= walk->size)
return false;
result = true;
it->raw_frame.process = walk->process;
it->raw_frame.base_addr = walk->base_addr[it->index++];
return result;
}
DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkResult const *walk, uint16_t skip)
{
DN_Str8 result{};
if (!walk || !arena)
return result;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena);
DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip);
result = DN_Str8BuilderBuild(&builder, arena);
return result;
}
DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, uint16_t limit, uint16_t skip)
{
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, limit);
DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip);
return result;
}
DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap(uint16_t limit, uint16_t skip)
{
// NOTE: We don't use WalkResultToStr8 because that uses the TLS arenas which
// does not use the OS heap.
DN_Arena arena = DN_ArenaFromHeap(DN_Kilobytes(64), DN_ArenaFlags_NoAllocTrack);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&arena);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&arena, limit);
DN_StackTraceAddWalkToStr8Builder(&walk, &builder, skip);
DN_Str8 result = DN_Str8BuilderBuildFromOSHeap(&builder);
DN_ArenaDeinit(&arena);
return result;
}
DN_API DN_Slice<DN_StackTraceFrame> DN_StackTraceGetFrames(DN_Arena *arena, uint16_t limit)
{
DN_Slice<DN_StackTraceFrame> result = {};
if (!arena)
return result;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, limit);
if (!walk.size)
return result;
DN_USize slice_index = 0;
result = DN_Slice_Alloc<DN_StackTraceFrame>(arena, walk.size, DN_ZMem_No);
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);)
result.data[slice_index++] = DN_StackTraceRawFrameToFrame(arena, it.raw_frame);
return result;
}
DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame(DN_Arena *arena, DN_StackTraceRawFrame raw_frame)
{
#if defined(DN_OS_WIN32)
// NOTE: Get line+filename
// TODO: Why does zero-initialising this with `line = {};` cause
// SymGetLineFromAddr64 function to fail once we are at
// __scrt_commain_main_seh and hit BaseThreadInitThunk frame? The
// line and file number are still valid in the result which we use, so,
// we silently ignore this error.
IMAGEHLP_LINEW64 line;
line.SizeOfStruct = sizeof(line);
DWORD line_displacement = 0;
if (!SymGetLineFromAddrW64(raw_frame.process, raw_frame.base_addr, &line_displacement, &line))
line = {};
// NOTE: Get function name
alignas(SYMBOL_INFOW) char buffer[sizeof(SYMBOL_INFOW) + (MAX_SYM_NAME * sizeof(wchar_t))] = {};
SYMBOL_INFOW *symbol = DN_Cast(SYMBOL_INFOW *) buffer;
symbol->SizeOfStruct = sizeof(*symbol);
symbol->MaxNameLen = sizeof(buffer) - sizeof(*symbol);
uint64_t symbol_displacement = 0; // Offset to the beginning of the symbol to the address
SymFromAddrW(raw_frame.process, raw_frame.base_addr, &symbol_displacement, symbol);
// NOTE: Construct result
DN_Str16 file_name16 = DN_Str16{line.FileName, DN_CStr16Size(line.FileName)};
DN_Str16 function_name16 = DN_Str16{symbol->Name, symbol->NameLen};
DN_StackTraceFrame result = {};
result.address = raw_frame.base_addr;
result.line_number = line.LineNumber;
result.file_name = DN_W32_Str16ToStr8(arena, file_name16);
result.function_name = DN_W32_Str16ToStr8(arena, function_name16);
if (result.function_name.size == 0)
result.function_name = DN_Str8Lit("<unknown function>");
if (result.file_name.size == 0)
result.file_name = DN_Str8Lit("<unknown file>");
#else
DN_StackTraceFrame result = {};
#endif
return result;
}
DN_API void DN_StackTracePrint(uint16_t limit)
{
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
DN_Slice<DN_StackTraceFrame> stack_trace = DN_StackTraceGetFrames(tmem.arena, limit);
for (DN_StackTraceFrame &frame : stack_trace)
DN_OS_PrintErrLnF("%.*s(%I64u): %.*s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name));
}
DN_API void DN_StackTraceReloadSymbols()
{
#if defined(DN_OS_WIN32)
HANDLE process = GetCurrentProcess();
SymRefreshModuleList(process);
#endif
}

View File

@ -1,305 +0,0 @@
#define DN_OS_STRING_CPP
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#endif
// NOTE: DN_Str8
DN_API DN_Str8 DN_Str8FromFmtArenaFrame(DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
DN_Str8 result = DN_Str8FromFmtVArena(frame_arena, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FromFmtVArenaFrame(DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
DN_Str8 result = DN_Str8FromFmtVArena(frame_arena, fmt, args);
return result;
}
DN_API DN_Str8 DN_Str8FromArenaFrame(DN_USize size, DN_ZMem z_mem)
{
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
DN_Str8 result = DN_Str8FromArena(frame_arena, size, z_mem);
return result;
}
DN_API DN_Str8 DN_Str8FromHeapF(DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_USize size = DN_FmtVSize(fmt, args);
DN_Str8 result = DN_Str8FromHeap(size, DN_ZMem_No);
DN_VSNPrintF(result.data, DN_Cast(int)(result.size + 1), fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FromHeap(DN_USize size, DN_ZMem z_mem)
{
DN_Str8 result = {};
result.data = DN_Cast(char *)DN_OS_MemAlloc(size + 1, z_mem);
if (result.data) {
result.size = size;
result.data[result.size] = 0;
}
return result;
}
DN_API DN_Str8 DN_Str8FromTLSFV(DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_Str8 result = DN_Str8FromFmtVArena(DN_OS_TLSTopArena(), fmt, args);
return result;
}
DN_API DN_Str8 DN_Str8FromTLSF(DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8FromFmtVArena(DN_OS_TLSTopArena(), fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FromTLS(DN_USize size, DN_ZMem z_mem)
{
DN_Str8 result = DN_Str8FromArena(DN_OS_TLSTopArena(), size, z_mem);
return result;
}
DN_API DN_Str8 DN_Str8FromStr8Frame(DN_Str8 string)
{
DN_Str8 result = DN_Str8FromStr8Arena(DN_OS_TLSGet()->frame_arena, string);
return result;
}
DN_API DN_Str8 DN_Str8FromStr8TLS(DN_Str8 string)
{
DN_Str8 result = DN_Str8FromStr8Arena(DN_OS_TLSTopArena(), string);
return result;
}
DN_API DN_Str8SplitResult DN_Str8SplitFromFrame(DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode)
{
DN_Str8SplitResult result = DN_Str8SplitArena(DN_OS_TLSGet()->frame_arena, string, delimiter, mode);
return result;
}
DN_API DN_Str8SplitResult DN_Str8SplitFromTLS(DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode)
{
DN_Str8SplitResult result = DN_Str8SplitArena(DN_OS_TLSTopArena(), string, delimiter, mode);
return result;
}
DN_API DN_Str8 DN_Str8SegmentFromFrame(DN_Str8 src, DN_USize segment_size, char segment_char)
{
DN_Str8 result = DN_Str8Segment(DN_OS_TLSGet()->frame_arena, src, segment_size, segment_char);
return result;
}
DN_API DN_Str8 DN_Str8SegmentFromTLS(DN_Str8 src, DN_USize segment_size, char segment_char)
{
DN_Str8 result = DN_Str8Segment(DN_OS_TLSTopArena(), src, segment_size, segment_char);
return result;
}
DN_API DN_Str8 DN_Str8ReverseSegmentFromFrame(DN_Str8 src, DN_USize segment_size, char segment_char)
{
DN_Str8 result = DN_Str8ReverseSegment(DN_OS_TLSGet()->frame_arena, src, segment_size, segment_char);
return result;
}
DN_API DN_Str8 DN_Str8ReverseSegmentFromTLS(DN_Str8 src, DN_USize segment_size, char segment_char)
{
DN_Str8 result = DN_Str8ReverseSegment(DN_OS_TLSTopArena(), src, segment_size, segment_char);
return result;
}
DN_API DN_Str8 DN_Str8AppendFFromFrame(DN_Str8 string, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8AppendFV(DN_OS_TLSGet()->frame_arena, string, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8AppendFFromTLS(DN_Str8 string, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8AppendFV(DN_OS_TLSTopArena(), string, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FillFFromFrame(DN_USize count, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8FillFV(DN_OS_TLSGet()->frame_arena, count, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FillFFromTLS(DN_USize count, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8FillFV(DN_OS_TLSTopArena(), count, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaFrame(DN_Str8 str8, uint32_t side_size, DN_Str8 truncator)
{
DN_Str8TruncateResult result = DN_Str8TruncateMiddle(DN_OS_TLSGet()->frame_arena, str8, side_size, truncator);
return result;
}
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaTLS(DN_Str8 str8, uint32_t side_size, DN_Str8 truncator)
{
DN_Str8TruncateResult result = DN_Str8TruncateMiddle(DN_OS_TLSTopArena(), str8, side_size, truncator);
return result;
}
DN_API DN_Str8 DN_Str8PadNewLines(DN_Arena *arena, DN_Str8 src, DN_Str8 pad)
{
// TODO: Implement this without requiring TLS so it can go into base strings
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
DN_Str8BSplitResult split = DN_Str8BSplit(src, DN_Str8Lit("\n"));
while (split.lhs.size) {
DN_Str8BuilderAppendRef(&builder, pad);
DN_Str8BuilderAppendRef(&builder, split.lhs);
split = DN_Str8BSplit(split.rhs, DN_Str8Lit("\n"));
if (split.lhs.size)
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
}
DN_Str8 result = DN_Str8BuilderBuild(&builder, arena);
return result;
}
DN_API DN_Str8 DN_Str8PadNewLinesFromFrame(DN_Str8 src, DN_Str8 pad)
{
DN_Str8 result = DN_Str8PadNewLines(DN_OS_TLSGet()->frame_arena, src, pad);
return result;
}
DN_API DN_Str8 DN_Str8PadNewLinesFromTLS(DN_Str8 src, DN_Str8 pad)
{
DN_Str8 result = DN_Str8PadNewLines(DN_OS_TLSTopArena(), src, pad);
return result;
}
DN_API DN_Str8 DN_Str8UpperFromFrame(DN_Str8 string)
{
DN_Str8 result = DN_Str8Upper(DN_OS_TLSGet()->frame_arena, string);
return result;
}
DN_API DN_Str8 DN_Str8UpperFromTLS(DN_Str8 string)
{
DN_Str8 result = DN_Str8Upper(DN_OS_TLSTopArena(), string);
return result;
}
DN_API DN_Str8 DN_Str8LowerFromFrame(DN_Str8 string)
{
DN_Str8 result = DN_Str8Lower(DN_OS_TLSGet()->frame_arena, string);
return result;
}
DN_API DN_Str8 DN_Str8LowerFromTLS(DN_Str8 string)
{
DN_Str8 result = DN_Str8Lower(DN_OS_TLSTopArena(), string);
return result;
}
DN_API DN_Str8 DN_Str8Replace(DN_Str8 string,
DN_Str8 find,
DN_Str8 replace,
DN_USize start_index,
DN_Arena *arena,
DN_Str8EqCase eq_case)
{
// TODO: Implement this without requiring TLS so it can go into base strings
DN_Str8 result = {};
if (string.size == 0 || find.size == 0 || find.size > string.size || find.size == 0 || string.size == 0) {
result = DN_Str8FromStr8Arena(arena, string);
return result;
}
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
DN_Str8Builder string_builder = DN_Str8BuilderFromArena(tmem.arena);
DN_USize max = string.size - find.size;
DN_USize head = start_index;
for (DN_USize tail = head; tail <= max; tail++) {
DN_Str8 check = DN_Str8Slice(string, tail, find.size);
if (!DN_Str8Eq(check, find, eq_case))
continue;
if (start_index > 0 && string_builder.string_size == 0) {
// User provided a hint in the string to start searching from, we
// need to add the string up to the hint. We only do this if there's
// a replacement action, otherwise we have a special case for no
// replacements, where the entire string gets copied.
DN_Str8 slice = DN_Str8FromPtr(string.data, head);
DN_Str8BuilderAppendRef(&string_builder, slice);
}
DN_Str8 range = DN_Str8Slice(string, head, (tail - head));
DN_Str8BuilderAppendRef(&string_builder, range);
DN_Str8BuilderAppendRef(&string_builder, replace);
head = tail + find.size;
tail += find.size - 1; // NOTE: -1 since the for loop will post increment us past the end of the find string
}
if (string_builder.string_size == 0) {
// NOTE: No replacement possible, so we just do a full-copy
result = DN_Str8FromStr8Arena(arena, string);
} else {
DN_Str8 remainder = DN_Str8FromPtr(string.data + head, string.size - head);
DN_Str8BuilderAppendRef(&string_builder, remainder);
result = DN_Str8BuilderBuild(&string_builder, arena);
}
return result;
}
DN_API DN_Str8 DN_Str8ReplaceInsensitive(DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena)
{
DN_Str8 result = DN_Str8Replace(string, find, replace, start_index, arena, DN_Str8EqCase_Insensitive);
return result;
}
// NOTE: DN_Str8Builder ////////////////////////////////////////////////////////////////////////////
DN_API DN_Str8 DN_Str8BuilderBuildFromOSHeap(DN_Str8Builder const *builder)
{
DN_Str8 result = DN_ZeroInit;
if (!builder || builder->string_size <= 0 || builder->count <= 0)
return result;
result.data = DN_Cast(char *) DN_OS_MemAlloc(builder->string_size + 1, DN_ZMem_No);
if (!result.data)
return result;
for (DN_Str8Link *link = builder->head; link; link = link->next) {
DN_Memcpy(result.data + result.size, link->string.data, link->string.size);
result.size += link->string.size;
}
result.data[result.size] = 0;
DN_Assert(result.size == builder->string_size);
return result;
}

View File

@ -1,76 +0,0 @@
#if !defined(DN_OS_STRING_H)
#define DN_OS_STRING_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#endif
// NOTE: DN_Str8
DN_API DN_Str8 DN_Str8FromFmtVArenaFrame (DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_Str8 DN_Str8FromFmtArenaFrame (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromArenaFrame (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8FromTLSFV (DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_Str8 DN_Str8FromTLSF (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromTLS (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8FromStr8Frame (DN_Str8 string);
DN_API DN_Str8 DN_Str8FromStr8TLS (DN_Str8 string);
DN_API DN_Str8SplitResult DN_Str8SplitFromFrame (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
DN_API DN_Str8SplitResult DN_Str8SplitFromTLS (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
DN_API DN_Str8 DN_Str8SegmentFromFrame (DN_Str8 src, DN_USize segment_size, char segment_char);
DN_API DN_Str8 DN_Str8SegmentFromTLS (DN_Str8 src, DN_USize segment_size, char segment_char);
DN_API DN_Str8 DN_Str8ReverseSegmentFromFrame (DN_Str8 src, DN_USize segment_size, char segment_char);
DN_API DN_Str8 DN_Str8ReverseSegmentFromTLS (DN_Str8 src, DN_USize segment_size, char segment_char);
DN_API DN_Str8 DN_Str8AppendFFromFrame (DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8 DN_Str8AppendFFromTLS (DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8 DN_Str8FillFFromFrame (DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8 DN_Str8FillFFromTLS (DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaFrame (DN_Str8 str8, uint32_t side_size, DN_Str8 truncator);
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaTLS (DN_Str8 str8, uint32_t side_size, DN_Str8 truncator);
DN_API DN_Str8 DN_Str8PadNewLines (DN_Arena *arena, DN_Str8 src, DN_Str8 pad);
DN_API DN_Str8 DN_Str8PadNewLinesFromFrame (DN_Str8 src, DN_Str8 pad);
DN_API DN_Str8 DN_Str8PadNewLinesFromTLS (DN_Str8 src, DN_Str8 pad);
DN_API DN_Str8 DN_Str8UpperFromFrame (DN_Str8 string);
DN_API DN_Str8 DN_Str8UpperFromTLS (DN_Str8 string);
DN_API DN_Str8 DN_Str8LowerFromFrame (DN_Str8 string);
DN_API DN_Str8 DN_Str8LowerFromTLS (DN_Str8 string);
DN_API DN_Str8 DN_Str8Replace (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DN_API DN_Str8 DN_Str8ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
// NOTE: DN_Str8Builder ////////////////////////////////////////////////////////////////////////////
DN_API DN_Str8Builder DN_Str8BuilderFromArena () { return DN_Str8BuilderFromArena(DN_OS_TLSGet()->frame_arena); }
DN_API DN_Str8Builder DN_Str8BuilderFromTLS () { return DN_Str8BuilderFromArena(DN_OS_TLSTopArena()); }
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRefFrame (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrRef(DN_OS_TLSGet()->frame_arena, strings, size); }
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRefTLS (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrRef(DN_OS_TLSTopArena(), strings, size); }
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopyFrame (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrCopy(DN_OS_TLSGet()->frame_arena, strings, size); }
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopyTLS (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrCopy(DN_OS_TLSTopArena(), strings, size); }
DN_API DN_Str8Builder DN_Str8BuilderFromBuilderFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderFromBuilder(DN_OS_TLSGet()->frame_arena, builder); }
DN_API DN_Str8Builder DN_Str8BuilderFromBuilderTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderFromBuilder(DN_OS_TLSTopArena(), builder); }
DN_API DN_Str8 DN_Str8BuilderBuildFromFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderBuild(builder, DN_OS_TLSGet()->frame_arena); }
DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder, DN_Arena *arena);
DN_API DN_Str8 DN_Str8BuilderBuildFromTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderBuild(builder, DN_OS_TLSTopArena()); }
DN_API DN_Str8 DN_Str8BuilderBuildDelimitedFromFrame(DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8BuilderBuildDelimited(builder, delimiter, DN_OS_TLSGet()->frame_arena); }
DN_API DN_Str8 DN_Str8BuilderBuildDelimitedFromTLS (DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8BuilderBuildDelimited(builder, delimiter, DN_OS_TLSTopArena()); }
DN_API DN_Slice<DN_Str8> DN_Str8BuilderBuildSliceFromFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderBuildSlice(builder, DN_OS_TLSGet()->frame_arena); }
DN_API DN_Slice<DN_Str8> DN_Str8BuilderBuildSliceFromTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderBuildSlice(builder, DN_OS_TLSTopArena()); }
#endif // !defined(DN_OS_STRING_H)

View File

@ -1,418 +0,0 @@
#define DN_OS_TLSCPP
#if defined(_CLANGD)
#include "dn_os_tls.h"
#endif
// NOTE: DN_OSTLS ////////////////////////////////////////////////////////////////////////////////////
DN_OSTLSTMem::DN_OSTLSTMem(DN_OSTLS *tls, DN_U8 arena_index, DN_OSTLSPushTMem push_tmem)
{
DN_Assert(arena_index == DN_OSTLSArena_TMem0 || arena_index == DN_OSTLSArena_TMem1);
arena = tls->arenas + arena_index;
temp_mem = DN_ArenaTempMemBegin(arena);
destructed = false;
push_arena = push_tmem;
if (push_arena)
DN_OS_TLSPushArena(arena);
}
DN_OSTLSTMem::~DN_OSTLSTMem()
{
DN_Assert(destructed == false);
DN_ArenaTempMemEnd(temp_mem);
destructed = true;
if (push_arena)
DN_OS_TLSPopArena();
}
DN_API void DN_OS_TLSInit(DN_OSTLS *tls, DN_OSTLSInitArgs args)
{
DN_Check(tls);
if (tls->init)
return;
DN_U64 reserve = args.reserve ? args.reserve : DN_Kilobytes(64);
DN_U64 err_sink_reserve = args.err_sink_reserve ? args.err_sink_reserve : DN_Kilobytes(64);
#if !defined(DN_PLATFORM_EMSCRIPTEN)
DN_U64 commit = args.commit ? args.commit : DN_Kilobytes(4);
DN_U64 err_sink_commit = args.err_sink_commit ? args.err_sink_commit : DN_Kilobytes(4);
#endif
// TODO: We shouldn't have the no alloc track flag here but the initial TLS
// init on OS init happens before CORE init. CORE init is the one responsible
// for setting up the alloc tracking data structures.
for (DN_ForItCArray(it, DN_Arena, tls->arenas)) {
DN_Arena *arena = it.data;
switch (DN_Cast(DN_OSTLSArena) it.index) {
default: {
#if defined(DN_PLATFORM_EMSCRIPTEN)
*arena = DN_ArenaFromHeap(reserve, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
#else
*arena = DN_ArenaFromVMem(reserve, commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
#endif
} break;
case DN_OSTLSArena_ErrorSink: {
#if defined(DN_PLATFORM_EMSCRIPTEN)
*arena = DN_ArenaFromHeap(err_sink_reserve, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
#else
*arena = DN_ArenaFromVMem(err_sink_reserve, err_sink_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
#endif
} break;
case DN_OSTLSArena_Count: DN_InvalidCodePath; break;
}
}
tls->thread_id = DN_OS_ThreadID();
tls->err_sink.arena = tls->arenas + DN_OSTLSArena_ErrorSink;
tls->init = true;
}
DN_API void DN_OS_TLSDeinit(DN_OSTLS *tls)
{
tls->init = false;
tls->err_sink = {};
tls->arena_stack_index = {};
for (DN_ForItCArray(it, DN_Arena, tls->arenas))
DN_ArenaDeinit(it.data);
}
DN_THREAD_LOCAL DN_OSTLS *g_dn_curr_thread_tls;
DN_API void DN_OS_TLSSetCurrentThreadTLS(DN_OSTLS *tls)
{
g_dn_curr_thread_tls = tls;
}
DN_API DN_OSTLS *DN_OS_TLSGet()
{
DN_RawAssert(g_dn_curr_thread_tls &&
"DN must be initialised (via DN_Core_Init) before calling any functions depending on "
"TLS if this is the main thread, OR, the created thread has not called "
"SetCurrentThreadTLS yet so the TLS data structure hasn't been assigned yet");
return g_dn_curr_thread_tls;
}
DN_API DN_Arena *DN_OS_TLSArena()
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Arena *result = tls->arenas + DN_OSTLSArena_Main;
return result;
}
// TODO: Is there a way to handle conflict arenas without the user needing to
// manually pass it in?
DN_API DN_OSTLSTMem DN_OS_TLSGetTMem(void const *conflict_arena, DN_OSTLSPushTMem push_tmem)
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_U8 tls_index = (DN_U8)-1;
for (DN_U8 index = DN_OSTLSArena_TMem0; index <= DN_OSTLSArena_TMem1; index++) {
DN_Arena *arena = tls->arenas + index;
if (!conflict_arena || arena != conflict_arena) {
tls_index = index;
break;
}
}
DN_Assert(tls_index != (DN_U8)-1);
return DN_OSTLSTMem(tls, tls_index, push_tmem);
}
DN_API void DN_OS_TLSPushArena(DN_Arena *arena)
{
DN_Assert(arena);
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Assert(tls->arena_stack_index < DN_ArrayCountU(tls->arena_stack));
tls->arena_stack[tls->arena_stack_index++] = arena;
}
DN_API void DN_OS_TLSPopArena()
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Assert(tls->arena_stack_index > 0);
tls->arena_stack_index--;
}
DN_API DN_Arena *DN_OS_TLSTopArena()
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Arena *result = nullptr;
if (tls->arena_stack_index)
result = tls->arena_stack[tls->arena_stack_index - 1];
return result;
}
DN_API void DN_OS_TLSBeginFrame(DN_Arena *frame_arena)
{
DN_OSTLS *tls = DN_OS_TLSGet();
tls->frame_arena = frame_arena;
}
DN_API DN_Arena *DN_OS_TLSFrameArena()
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Arena *result = tls->frame_arena;
DN_AssertF(result, "Frame arena must be set by calling DN_OS_TLSBeginFrame at the beginning of the frame");
return result;
}
// NOTE: DN_OSErrSink ////////////////////////////////////////////////////////////////////////////////
static void DN_OS_ErrSinkCheck_(DN_OSErrSink const *err)
{
DN_AssertF(err->arena, "Arena should be assigned in TLS init");
if (err->stack_size == 0)
return;
DN_OSErrSinkNode const *node = err->stack + (err->stack_size - 1);
DN_Assert(node->mode >= DN_OSErrSinkMode_Nil && node->mode <= DN_OSErrSinkMode_ExitOnError);
DN_Assert(node->msg_sentinel);
// NOTE: Walk the list ensuring we eventually terminate at the sentinel (e.g. we have a
// well formed doubly-linked-list terminated by a sentinel, or otherwise we will hit the
// walk limit or dereference a null pointer and assert)
size_t WALK_LIMIT = 99'999;
size_t walk = 0;
for (DN_OSErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next, walk++) {
DN_AssertF(it, "Encountered null pointer which should not happen in a sentinel DLL");
DN_Assert(walk < WALK_LIMIT);
}
}
DN_API DN_OSErrSink *DN_OS_ErrSinkBegin_(DN_OSErrSinkMode mode, DN_CallSite call_site)
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_OSErrSink *err = &tls->err_sink;
DN_OSErrSink *result = err;
DN_USize arena_pos = DN_ArenaPos(result->arena);
if (tls->err_sink.stack_size == DN_ArrayCountU(err->stack)) {
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
DN_USize counter = 0;
for (DN_ForItSize(it, DN_OSErrSinkNode, err->stack, err->stack_size)) {
DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(4) when a string is required in call to 'DN_Str8BuilderAppendF' Actual type: 'struct DN_Str8'.
DN_Str8BuilderAppendF(&builder, " [%04zu] %S:%u %S\n", counter++, it.data->call_site.file, it.data->call_site.line, it.data->call_site.function);
DN_MSVC_WARNING_POP
}
DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(6) when a string is required in call to 'DN_LOG_EmitFromType' Actual type: 'struct DN_Str8'.
DN_AssertF(tls->err_sink.stack_size < DN_ArrayCountU(err->stack),
"Error sink has run out of error scopes, potential leak. Scopes were\n%S", DN_Str8BuilderBuildFromTLS(&builder));
DN_MSVC_WARNING_POP
}
DN_OSErrSinkNode *node = tls->err_sink.stack + tls->err_sink.stack_size++;
node->arena_pos = arena_pos;
node->mode = mode;
node->call_site = call_site;
DN_DLList_InitArena(node->msg_sentinel, DN_OSErrSinkMsg, result->arena);
// NOTE: Handle allocation error
if (!DN_Check(node && node->msg_sentinel)) {
DN_ArenaPopTo(result->arena, arena_pos);
node->msg_sentinel = nullptr;
tls->err_sink.stack_size--;
}
return result;
}
DN_API bool DN_OS_ErrSinkHasError(DN_OSErrSink *err)
{
bool result = false;
if (err && err->stack_size) {
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
result = DN_DLList_HasItems(node->msg_sentinel);
}
return result;
}
DN_API DN_OSErrSinkMsg *DN_OS_ErrSinkEnd(DN_Arena *arena, DN_OSErrSink *err)
{
DN_OSErrSinkMsg *result = nullptr;
DN_OS_ErrSinkCheck_(err);
if (!err || err->stack_size == 0)
return result;
DN_AssertF(arena != err->arena,
"You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost");
// NOTE: Walk the list and allocate it onto the user's arena
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
DN_OSErrSinkMsg *prev = nullptr;
for (DN_OSErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next) {
DN_OSErrSinkMsg *entry = DN_ArenaNew(arena, DN_OSErrSinkMsg, DN_ZMem_Yes);
entry->msg = DN_Str8FromStr8Arena(arena, it->msg);
entry->call_site = it->call_site;
entry->error_code = it->error_code;
if (!result)
result = entry; // Assign first entry if we haven't yet
if (prev)
prev->next = entry; // Link the prev message to the current one
prev = entry; // Update prev to latest
}
// NOTE: Deallocate all the memory for this scope
err->stack_size--;
DN_ArenaPopTo(err->arena, node->arena_pos);
return result;
}
static void DN_OS_ErrSinkAddMsgToStr8Builder(DN_Str8Builder *builder, DN_OSErrSinkMsg *msg, DN_OSErrSinkMsg *end)
{
if (msg == end) // NOTE: No error messages to add
return;
if (msg->next == end) {
DN_OSErrSinkMsg *it = msg;
DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file);
DN_Str8BuilderAppendF(builder,
"%.*s:%05I32u:%.*s %.*s",
DN_Str8PrintFmt(file_name),
it->call_site.line,
DN_Str8PrintFmt(it->call_site.function),
DN_Str8PrintFmt(it->msg));
} else {
// NOTE: More than one message
for (DN_OSErrSinkMsg *it = msg; it != end; it = it->next) {
DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file);
DN_Str8BuilderAppendF(builder,
"%s - %.*s:%05I32u:%.*s%s%.*s",
it == msg ? "" : "\n",
DN_Str8PrintFmt(file_name),
it->call_site.line,
DN_Str8PrintFmt(it->call_site.function),
it->msg.size ? " " : "",
DN_Str8PrintFmt(it->msg));
}
}
}
DN_API DN_Str8 DN_OS_ErrSinkEndStr8(DN_Arena *arena, DN_OSErrSink *err)
{
DN_Str8 result = {};
DN_OS_ErrSinkCheck_(err);
if (!err || err->stack_size == 0)
return result;
DN_AssertF(arena != err->arena,
"You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost");
// NOTE: Walk the list and allocate it onto the user's arena
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
DN_OS_ErrSinkAddMsgToStr8Builder(&builder, node->msg_sentinel->next, node->msg_sentinel);
// NOTE: Deallocate all the memory for this scope
err->stack_size--;
DN_U64 arena_pos = node->arena_pos;
DN_ArenaPopTo(err->arena, arena_pos);
result = DN_Str8BuilderBuild(&builder, arena);
return result;
}
DN_API void DN_OS_ErrSinkEndAndIgnore(DN_OSErrSink *err)
{
DN_OS_ErrSinkEnd(nullptr, err);
}
DN_API bool DN_OS_ErrSinkEndAndLogError_(DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 err_msg)
{
DN_AssertF(err->stack_size, "Begin must be called before calling end");
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
DN_AssertF(node->msg_sentinel, "Begin must be called before calling end");
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
DN_OSErrSinkMode mode = node->mode;
DN_OSErrSinkMsg *msg = DN_OS_ErrSinkEnd(tmem.arena, err);
if (!msg)
return false;
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
if (err_msg.size) {
DN_Str8BuilderAppendRef(&builder, err_msg);
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit(":"));
} else {
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("Error(s) encountered:"));
}
if (msg->next) // NOTE: More than 1 message
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
DN_OS_ErrSinkAddMsgToStr8Builder(&builder, msg, nullptr);
DN_Str8 log = DN_Str8BuilderBuildFromTLS(&builder);
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), call_site, "%.*s", DN_Str8PrintFmt(log));
if (mode == DN_OSErrSinkMode_DebugBreakOnEndAndLog)
DN_DebugBreak;
return true;
}
DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_(DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
DN_Str8 log = DN_Str8FromFmtVArena(tmem.arena, fmt, args);
bool result = DN_OS_ErrSinkEndAndLogError_(err, call_site, log);
return result;
}
DN_API bool DN_OS_ErrSinkEndAndLogErrorF_(DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
DN_Str8 log = DN_Str8FromFmtVArena(tmem.arena, fmt, args);
bool result = DN_OS_ErrSinkEndAndLogError_(err, call_site, log);
va_end(args);
return result;
}
DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_(DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args)
{
if (DN_OS_ErrSinkEndAndLogErrorFV_(err, call_site, fmt, args)) {
DN_DebugBreak;
DN_OS_Exit(exit_val);
}
}
DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_(DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_ErrSinkEndAndExitIfErrorFV_(err, call_site, exit_val, fmt, args);
va_end(args);
}
DN_API void DN_OS_ErrSinkAppendFV_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args)
{
if (!err)
return;
DN_Assert(err && err->stack_size);
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
DN_AssertF(node, "Error sink must be begun by calling 'Begin' before using this function.");
DN_OSErrSinkMsg *msg = DN_ArenaNew(err->arena, DN_OSErrSinkMsg, DN_ZMem_Yes);
if (DN_Check(msg)) {
msg->msg = DN_Str8FromFmtVArena(err->arena, fmt, args);
msg->error_code = error_code;
msg->call_site = DN_OS_TLSGet()->call_site;
DN_DLList_Prepend(node->msg_sentinel, msg);
if (node->mode == DN_OSErrSinkMode_ExitOnError)
DN_OS_ErrSinkEndAndExitIfErrorF_(err, msg->call_site, error_code, "Fatal error %u", error_code);
}
}
DN_API void DN_OS_ErrSinkAppendF_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...)
{
if (!err)
return;
va_list args;
va_start(args, fmt);
DN_OS_ErrSinkAppendFV_(err, error_code, fmt, args);
va_end(args);
}

View File

@ -1,142 +0,0 @@
#if !defined(DN_OS_TLS_H)
#define DN_OS_TLS_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#endif
// NOTE: DN_OSErrSink
enum DN_OSErrSinkMode
{
DN_OSErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
DN_OSErrSinkMode_DebugBreakOnEndAndLog, // Debug break (int3) when error is encountered and the sink is ended by the 'end and log' functions.
DN_OSErrSinkMode_ExitOnError, // When an error is encountered, exit the program with the error code of the error that was caught.
};
struct DN_OSErrSinkMsg
{
DN_I32 error_code;
DN_Str8 msg;
DN_CallSite call_site;
DN_OSErrSinkMsg *next;
DN_OSErrSinkMsg *prev;
};
struct DN_OSErrSinkNode
{
DN_CallSite call_site; // Call site that the node was created
DN_OSErrSinkMode mode; // Controls how the sink behaves when an error is registered onto the sink.
DN_OSErrSinkMsg *msg_sentinel; // List of error messages accumulated for the current scope
DN_U64 arena_pos; // Position to reset the arena when the scope is ended
};
struct DN_OSErrSink
{
DN_Arena * arena; // Dedicated allocator from the thread's local storage
DN_OSErrSinkNode stack[128]; // Each entry contains errors accumulated between a [begin, end] region of the active sink.
DN_USize stack_size;
};
enum DN_OSTLSArena
{
DN_OSTLSArena_Main, // NOTE: Arena for permanent allocations
DN_OSTLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread
// NOTE: Per-thread scratch arenas (2 to prevent aliasing)
DN_OSTLSArena_TMem0,
DN_OSTLSArena_TMem1,
DN_OSTLSArena_Count,
};
struct DN_OSTLS
{
DN_B32 init; // Flag to track if TLS has been initialised
DN_U64 thread_id;
DN_CallSite call_site; // Stores call-site information when requested by thread
DN_OSErrSink err_sink; // Error handling state
DN_Arena arenas[DN_OSTLSArena_Count]; // Default arenas that the thread has access to implicitly
DN_Arena * arena_stack[8]; // Active stack of arenas push/popped arenas on into the TLS
DN_USize arena_stack_index;
DN_Arena * frame_arena;
char name[64];
DN_U8 name_size;
};
// Push the temporary memory arena when retrieved, popped when the arena goes
// out of scope. Pushed arenas are used automatically as the allocator in TLS
// suffixed function.
enum DN_OSTLSPushTMem
{
DN_OSTLSPushTMem_No,
DN_OSTLSPushTMem_Yes,
};
struct DN_OSTLSTMem
{
DN_OSTLSTMem(DN_OSTLS *context, uint8_t context_index, DN_OSTLSPushTMem push_scratch);
~DN_OSTLSTMem();
DN_Arena *arena;
DN_B32 destructed;
DN_OSTLSPushTMem push_arena;
DN_ArenaTempMem temp_mem;
};
struct DN_OSTLSInitArgs
{
DN_U64 reserve;
DN_U64 commit;
DN_U64 err_sink_reserve;
DN_U64 err_sink_commit;
};
DN_API void DN_OS_TLSInit (DN_OSTLS *tls, DN_OSTLSInitArgs args);
DN_API void DN_OS_TLSDeinit (DN_OSTLS *tls);
DN_API DN_OSTLS * DN_OS_TLSGet ();
DN_API void DN_OS_TLSSetCurrentThreadTLS (DN_OSTLS *tls);
DN_API DN_Arena * DN_OS_TLSArena ();
DN_API DN_OSTLSTMem DN_OS_TLSGetTMem (void const *conflict_arena, DN_OSTLSPushTMem push_tmp_mem);
DN_API void DN_OS_TLSPushArena (DN_Arena *arena);
DN_API void DN_OS_TLSPopArena ();
DN_API DN_Arena * DN_OS_TLSTopArena ();
DN_API void DN_OS_TLSBeginFrame (DN_Arena *frame_arena);
DN_API DN_Arena * DN_OS_TLSFrameArena ();
#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0)
#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No)
#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes)
DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site);
#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE)
#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil)
DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err);
DN_API DN_OSErrSinkMsg * DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err);
DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err);
DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err);
DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg);
DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg)
#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args)
#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args)
#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__)
#define DN_OS_ErrSinkAppendFV(error, error_code, fmt, args) \
do { \
DN_OS_TLSSaveCallSite; \
DN_OS_ErrSinkAppendFV_(error, error_code, fmt, args); \
} while (0)
#define DN_OS_ErrSinkAppendF(error, error_code, fmt, ...) \
do { \
DN_OS_TLSSaveCallSite; \
DN_OS_ErrSinkAppendF_(error, error_code, fmt, ##__VA_ARGS__); \
} while (0)
#endif // defined(DN_OS_TLS_H)

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,33 @@
#if !defined(DN_OS_WIN32_H) #if !defined(DN_OS_W32_H)
#define DN_OS_WIN32_H #define DN_OS_W32_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn.h"
#include "dn_os_windows.h" #include "dn_os_windows.h"
#endif #endif
struct DN_W32Error struct DN_OSW32Error
{ {
unsigned long code; unsigned long code;
DN_Str8 msg; DN_Str8 msg;
}; };
struct DN_W32FolderIteratorW struct DN_OSW32FolderIteratorW
{ {
void *handle; void *handle;
DN_Str16 file_name; DN_Str16 file_name;
wchar_t file_name_buf[512]; wchar_t file_name_buf[512];
}; };
enum DN_W32SyncPrimitiveType enum DN_OSW32SyncPrimitiveType
{ {
DN_OSW32SyncPrimitiveType_Semaphore, DN_OSW32SyncPrimitiveType_Semaphore,
DN_OSW32SyncPrimitiveType_Mutex, DN_OSW32SyncPrimitiveType_Mutex,
DN_OSW32SyncPrimitiveType_ConditionVariable, DN_OSW32SyncPrimitiveType_ConditionVariable,
}; };
struct DN_W32SyncPrimitive struct DN_OSW32SyncPrimitive
{ {
union union
{ {
@ -35,42 +36,43 @@ struct DN_W32SyncPrimitive
CONDITION_VARIABLE cv; CONDITION_VARIABLE cv;
}; };
DN_W32SyncPrimitive *next; DN_OSW32SyncPrimitive *next;
}; };
typedef HRESULT DN_W32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription); typedef HRESULT DN_OSW32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription);
struct DN_W32Core struct DN_OSW32Core
{ {
DN_W32SetThreadDescriptionFunc *set_thread_description; DN_OSW32SetThreadDescriptionFunc *set_thread_description;
LARGE_INTEGER qpc_frequency; LARGE_INTEGER qpc_frequency;
void *bcrypt_rng_handle; void *bcrypt_rng_handle;
bool bcrypt_init_success; bool bcrypt_init_success;
bool sym_initialised; bool sym_initialised;
CRITICAL_SECTION sync_primitive_free_list_mutex; CRITICAL_SECTION sync_primitive_free_list_mutex;
DN_W32SyncPrimitive *sync_primitive_free_list; DN_OSW32SyncPrimitive *sync_primitive_free_list;
}; };
DN_API void DN_W32_ThreadSetName (DN_Str8 name); DN_API DN_OSW32Core* DN_OS_W32GetCore ();
DN_API void DN_OS_W32ThreadSetName (DN_Str8 name);
DN_API DN_Str16 DN_W32_ErrorCodeToMsg16Alloc(DN_U32 error_code); DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code);
DN_API DN_W32Error DN_W32_ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code); DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code);
DN_API DN_W32Error DN_W32_ErrorCodeToMsgAlloc (DN_U32 error_code); DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsgAlloc (DN_U32 error_code);
DN_API DN_W32Error DN_W32_LastError (DN_Arena *arena); DN_API DN_OSW32Error DN_OS_W32LastError (DN_Arena *arena);
DN_API DN_W32Error DN_W32_LastErrorAlloc (); DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc ();
DN_API void DN_W32_MakeProcessDPIAware (); DN_API void DN_OS_W32MakeProcessDPIAware ();
// NOTE: Windows Str8 <-> Str16 //////////////////////////////////////////////////////////////////// // NOTE: Windows Str8 <-> Str16
DN_API DN_Str16 DN_W32_Str8ToStr16 (DN_Arena *arena, DN_Str8 src); DN_API DN_Str16 DN_OS_W32Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
DN_API int DN_W32_Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size); DN_API int DN_OS_W32Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
DN_API DN_Str8 DN_W32_Str16ToStr8 (DN_Arena *arena, DN_Str16 src); DN_API DN_Str8 DN_OS_W32Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
DN_API int DN_W32_Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size); DN_API int DN_OS_W32Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
DN_API DN_Str8 DN_W32_Str16ToStr8FromHeap(DN_Str16 src); DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap (DN_Str16 src);
// NOTE: Path navigation /////////////////////////////////////////////////////////////////////////// // NOTE: Path navigation
DN_API DN_Str16 DN_W32_EXEPathW (DN_Arena *arena); DN_API DN_Str16 DN_OS_W32EXEPathW (DN_Arena *arena);
DN_API DN_Str16 DN_W32_EXEDirW (DN_Arena *arena); DN_API DN_Str16 DN_OS_W32EXEDirW (DN_Arena *arena);
DN_API DN_Str8 DN_W32_WorkingDir (DN_Arena *arena, DN_Str8 suffix); DN_API DN_Str8 DN_OS_W32WorkingDir (DN_Arena *arena, DN_Str8 suffix);
DN_API DN_Str16 DN_W32_WorkingDirW (DN_Arena *arena, DN_Str16 suffix); DN_API DN_Str16 DN_OS_W32WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
DN_API bool DN_W32_DirWIterate (DN_Str16 path, DN_W32FolderIteratorW *it); DN_API bool DN_OS_W32DirWIterate (DN_Str16 path, DN_OSW32FolderIteratorW *it);
#endif // !defined(DN_OS_WIN32) #endif // !defined(DN_OS_W32_H)

View File

@ -2,7 +2,7 @@
#define DN_OS_WINDOWS_H #define DN_OS_WINDOWS_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) #if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)

View File

@ -45,6 +45,83 @@ DN_INIStr8 DN_INI_Str8FromPtr(char const *data, size_t count)
return result; return result;
} }
static void DN_INI_Str8BuilderAppend_(DN_INIStr8Builder *builder, char const *fmt, ...)
{
va_list args;
va_list args_copy;
va_start(args, fmt);
va_copy(args_copy, args);
int size_req = vsnprintf(0, 0, fmt, args);
va_end(args);
builder->size_req += size_req;
if (builder->used + size_req <= builder->max) {
vsnprintf(builder->data + builder->used, builder->max - builder->used, fmt, args_copy);
builder->used += size_req;
}
va_end(args_copy);
}
DN_INIStr8FromResult DN_INI_Str8FromINI(DN_INICore const *ini, char *buffer, size_t size)
{
DN_INIStr8FromResult result = {};
DN_INISection const *section_stack[64] = {};
size_t section_stack_count = 0;
if (ini->first_section.child_first)
section_stack[section_stack_count++] = &ini->first_section;
DN_INIStr8Builder builder = {};
builder.data = buffer;
builder.max = size;
DN_INISection *parent_stack[32] = {};
size_t parent_stack_count = 0;
for (; section_stack_count;) {
DN_INISection const *it = section_stack[--section_stack_count];
if (it != &ini->first_section) {
DN_INI_Str8BuilderAppend_(&builder, "[");
for (DN_INISection *parent = it->parent; parent; parent = parent->parent)
if (parent->name.size)
parent_stack[parent_stack_count++] = parent;
for (size_t index = parent_stack_count - 1; index < parent_stack_count; index--) {
DN_INISection *parent = parent_stack[index];
DN_INI_Str8BuilderAppend_(&builder, "%.*s.", (int)parent->name.size, parent->name.data);
}
parent_stack_count = 0;
DN_INI_Str8BuilderAppend_(&builder, "%.*s]\n", (int)it->name.size, it->name.data);
}
for (DN_INIField *field = it->first_field; field; field = field->next) {
DN_INI_Str8BuilderAppend_(&builder, "%.*s = ", (int)field->key.size, field->key.data);
switch (field->value_type) {
case DN_INIFieldType_String: DN_INI_Str8BuilderAppend_(&builder, "%.*s\n", (int)field->value.size, field->value.data); break;
case DN_INIFieldType_Bool: DN_INI_Str8BuilderAppend_(&builder, "%d\n", field->value_bool); break;
case DN_INIFieldType_USize: DN_INI_Str8BuilderAppend_(&builder, "%zu\n", field->value_usize); break;
}
}
if (it->next)
section_stack[section_stack_count++] = it->next;
if (it->child_first)
section_stack[section_stack_count++] = it->child_first;
if (section_stack_count && it != &ini->first_section)
DN_INI_Str8BuilderAppend_(&builder, "\n");
}
result.size_req = builder.size_req;
if (buffer) {
result.str8.data = builder.data;
result.str8.size = builder.used;
result.success = true;
} else {
result.success = true;
}
return result;
}
static bool DN_INI_Str8Eq(DN_INIStr8 lhs, DN_INIStr8 rhs) static bool DN_INI_Str8Eq(DN_INIStr8 lhs, DN_INIStr8 rhs)
{ {
bool result = lhs.size == rhs.size && DN_INI_Memcmp(lhs.data, rhs.data, lhs.size) == 0; bool result = lhs.size == rhs.size && DN_INI_Memcmp(lhs.data, rhs.data, lhs.size) == 0;
@ -651,6 +728,8 @@ DN_INISection *DN_INI_AppendSectionF(DN_INICore *ini, DN_INIArena *arena, DN_INI
result->name.data = (char *)DN_INI_ArenaAlloc(arena, size_req + 1); result->name.data = (char *)DN_INI_ArenaAlloc(arena, size_req + 1);
result->name.size = size_req; result->name.size = size_req;
vsnprintf(result->name.data, result->name.size + 1, fmt, args_copy); vsnprintf(result->name.data, result->name.size + 1, fmt, args_copy);
if (!section)
section = &ini->first_section;
if (result) { if (result) {
if (section) { if (section) {
@ -770,83 +849,6 @@ DN_INIField *DN_INI_AppendKeyF(DN_INICore *ini, DN_INIArena *arena, DN_INISectio
return result; return result;
} }
static void DN_INI_Str8BuilderAppend(DN_INIStr8Builder *builder, char const *fmt, ...)
{
va_list args;
va_list args_copy;
va_start(args, fmt);
va_copy(args_copy, args);
int size_req = vsnprintf(0, 0, fmt, args);
va_end(args);
builder->size_req += size_req;
if (builder->used + size_req <= builder->max) {
vsnprintf(builder->data + builder->used, builder->max - builder->used, fmt, args_copy);
builder->used += size_req;
}
va_end(args_copy);
}
DN_INIStr8FromResult DN_INI_Str8FromINI(DN_INICore const *ini, char *buffer, size_t size)
{
DN_INIStr8FromResult result = {};
DN_INISection const *section_stack[64] = {};
size_t section_stack_count = 0;
if (ini->first_section.child_first)
section_stack[section_stack_count++] = &ini->first_section;
DN_INIStr8Builder builder = {};
builder.data = buffer;
builder.max = size;
DN_INISection *parent_stack[32] = {};
size_t parent_stack_count = 0;
for (; section_stack_count;) {
DN_INISection const *it = section_stack[--section_stack_count];
if (it != &ini->first_section) {
DN_INI_Str8BuilderAppend(&builder, "[");
for (DN_INISection *parent = it->parent; parent; parent = parent->parent)
if (parent->name.size)
parent_stack[parent_stack_count++] = parent;
for (size_t index = parent_stack_count - 1; index < parent_stack_count; index--) {
DN_INISection *parent = parent_stack[index];
DN_INI_Str8BuilderAppend(&builder, "%.*s.", (int)parent->name.size, parent->name.data);
}
parent_stack_count = 0;
DN_INI_Str8BuilderAppend(&builder, "%.*s]\n", (int)it->name.size, it->name.data);
}
for (DN_INIField *field = it->first_field; field; field = field->next) {
DN_INI_Str8BuilderAppend(&builder, "%.*s = ", (int)field->key.size, field->key.data);
switch (field->value_type) {
case DN_INIFieldType_String: DN_INI_Str8BuilderAppend(&builder, "%.*s\n", (int)field->value.size, field->value.data); break;
case DN_INIFieldType_Bool: DN_INI_Str8BuilderAppend(&builder, "%d\n", field->value_bool); break;
case DN_INIFieldType_USize: DN_INI_Str8BuilderAppend(&builder, "%zu\n", field->value_usize); break;
}
}
if (it->next)
section_stack[section_stack_count++] = it->next;
if (it->child_first)
section_stack[section_stack_count++] = it->child_first;
if (section_stack_count)
DN_INI_Str8BuilderAppend(&builder, "\n");
}
result.size_req = builder.size_req;
if (buffer) {
result.str8.data = builder.data;
result.str8.size = builder.used;
result.success = true;
} else {
result.success = true;
}
return result;
}
#if defined(DN_INI_WITH_UNIT_TESTS) || 1 #if defined(DN_INI_WITH_UNIT_TESTS) || 1
void DN_INI_UnitTests() void DN_INI_UnitTests()
{ {

View File

@ -153,9 +153,12 @@ struct DN_INIFieldBool
// NOTE: Utilities // NOTE: Utilities
// Str8FromINI's `size` parameter must include space for the null-terminator, i.e:
// `DN_INIStr8FromResult.size_req + 1` bytes
int DN_INI_SNPrintF_ (char const *buffer, size_t size, char const *fmt, ...); int DN_INI_SNPrintF_ (char const *buffer, size_t size, char const *fmt, ...);
void * DN_INI_ArenaAlloc (DN_INIArena *arena, size_t size); void * DN_INI_ArenaAlloc (DN_INIArena *arena, size_t size);
DN_INIStr8 DN_INI_Str8FromPtr (char const *data, size_t count); DN_INIStr8 DN_INI_Str8FromPtr (char const *data, size_t count);
DN_INIStr8FromResult DN_INI_Str8FromINI (DN_INICore const *ini, char *buffer, size_t size);
// NOTE: Tokeniser/Parsing // NOTE: Tokeniser/Parsing
DN_INITokeniser DN_INI_TokeniserFromPtr (char const *buf, size_t count); DN_INITokeniser DN_INI_TokeniserFromPtr (char const *buf, size_t count);

View File

@ -1,16 +1,9 @@
#include "Base/dn_base.cpp" #include "Base/dn_base.cpp"
#include "Base/dn_base_containers.cpp" #include "Base/dn_base_containers.cpp"
#include "Base/dn_base_log.cpp"
#include "Base/dn_base_leak.cpp" #include "Base/dn_base_leak.cpp"
#if DN_H_WITH_OS #if DN_H_WITH_OS
#include "OS/dn_os_tls.cpp"
#include "OS/dn_os.cpp" #include "OS/dn_os.cpp"
#include "OS/dn_os_allocator.cpp"
#include "OS/dn_os_containers.cpp"
#include "OS/dn_os_print.cpp"
#include "OS/dn_os_string.cpp"
#if defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN)
#include "OS/dn_os_posix.cpp" #include "OS/dn_os_posix.cpp"
#elif defined(DN_PLATFORM_WIN32) #elif defined(DN_PLATFORM_WIN32)
@ -18,8 +11,6 @@
#else #else
#error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs #error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
#endif #endif
#include "OS/dn_os_stacktrace.cpp"
#endif #endif
#if DN_H_WITH_CORE #if DN_H_WITH_CORE
@ -30,10 +21,6 @@
#include "Extra/dn_math.cpp" #include "Extra/dn_math.cpp"
#endif #endif
#if DN_H_WITH_HASH
#include "Extra/dn_hash.cpp"
#endif
#if DN_H_WITH_HELPERS #if DN_H_WITH_HELPERS
#include "Extra/dn_helpers.cpp" #include "Extra/dn_helpers.cpp"
#endif #endif

View File

@ -9,7 +9,6 @@
#define DN_H_WITH_OS 1 #define DN_H_WITH_OS 1
#define DN_H_WITH_CORE 1 #define DN_H_WITH_CORE 1
#define DN_H_WITH_MATH 1 #define DN_H_WITH_MATH 1
#define DN_H_WITH_HASH 1
#define DN_H_WITH_HELPERS 1 #define DN_H_WITH_HELPERS 1
#define DN_H_WITH_ASYNC 1 #define DN_H_WITH_ASYNC 1
#define DN_H_WITH_NET 1 #define DN_H_WITH_NET 1
@ -66,11 +65,8 @@
// This means functionality that relies on the OS like printing, memory allocation, stack traces // This means functionality that relies on the OS like printing, memory allocation, stack traces
// and so forth are disabled. // and so forth are disabled.
#include "Base/dn_base_compiler.h"
#include "Base/dn_base.h" #include "Base/dn_base.h"
#include "Base/dn_base_os.h"
#include "Base/dn_base_assert.h" #include "Base/dn_base_assert.h"
#include "Base/dn_base_log.h"
#include "Base/dn_base_containers.h" #include "Base/dn_base_containers.h"
#include "Base/dn_base_leak.h" #include "Base/dn_base_leak.h"
@ -84,12 +80,7 @@
#error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs #error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
#endif #endif
#include "OS/dn_os_tls.h"
#include "OS/dn_os.h" #include "OS/dn_os.h"
#include "OS/dn_os_allocator.h"
#include "OS/dn_os_containers.h"
#include "OS/dn_os_print.h"
#include "OS/dn_os_string.h"
#endif #endif
#if DN_H_WITH_CORE #if DN_H_WITH_CORE
@ -100,10 +91,6 @@
#include "Extra/dn_math.h" #include "Extra/dn_math.h"
#endif #endif
#if DN_H_WITH_HASH
#include "Extra/dn_hash.h"
#endif
#if DN_H_WITH_HELPERS #if DN_H_WITH_HELPERS
#include "Extra/dn_helpers.h" #include "Extra/dn_helpers.h"
#endif #endif

View File

@ -1,12 +1,13 @@
#define DN_INC_CPP #define DN_INC_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#include "dn_inc.h" #include "../Base/dn_base.h"
#include "../OS/dn_os.h"
#endif #endif
DN_Core *g_dn_; DN_Core *g_dn_;
static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args) static void DN_InitOS_(DN_OSCore *os)
{ {
#if defined(DN_OS_H) && defined(DN_OS_CPP) #if defined(DN_OS_H) && defined(DN_OS_CPP)
// NOTE: OS // NOTE: OS
@ -40,19 +41,19 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args)
#endif #endif
#if defined(DN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
os->platform_context = DN_ArenaNew(&os->arena, DN_W32Core, DN_ZMem_Yes); os->platform_context = DN_ArenaNew(&os->arena, DN_OSW32Core, DN_ZMem_Yes);
#elif defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN) #elif defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN)
os->platform_context = DN_ArenaNew(&os->arena, DN_POSIXCore, DN_ZMem_Yes); os->platform_context = DN_ArenaNew(&os->arena, DN_OSPOSIXCore, DN_ZMem_Yes);
#endif #endif
#if defined(DN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
DN_W32Core *w32 = DN_Cast(DN_W32Core *) os->platform_context; DN_OSW32Core *w32 = DN_Cast(DN_OSW32Core *) os->platform_context;
InitializeCriticalSection(&w32->sync_primitive_free_list_mutex); InitializeCriticalSection(&w32->sync_primitive_free_list_mutex);
QueryPerformanceFrequency(&w32->qpc_frequency); QueryPerformanceFrequency(&w32->qpc_frequency);
HMODULE module = LoadLibraryA("kernel32.dll"); HMODULE module = LoadLibraryA("kernel32.dll");
if (module) { if (module) {
w32->set_thread_description = DN_Cast(DN_W32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription"); w32->set_thread_description = DN_Cast(DN_OSW32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription");
FreeLibrary(module); FreeLibrary(module);
} }
@ -62,27 +63,12 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args)
if (w32->bcrypt_rng_handle && init_status == 0) if (w32->bcrypt_rng_handle && init_status == 0)
w32->bcrypt_init_success = true; w32->bcrypt_init_success = true;
else else
DN_LOG_ErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status); DN_LogErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status);
#else #else
DN_Posix_Init(DN_Cast(DN_POSIXCore *)os->platform_context); DN_OS_PosixInit(DN_Cast(DN_OSPosixCore *)os->platform_context);
#endif #endif
} }
// NOTE: Initialise tmem arenas which allocate memory and will be
// recorded to the now initialised allocation table. The initialisation
// of tmem memory may request tmem memory itself in leak tracing mode.
// This is supported as the tmem arenas defer allocation tracking until
// initialisation is done.
DN_OSTLSInitArgs tls_init_args = {};
if (args) {
tls_init_args.commit = args->os_tls_commit;
tls_init_args.reserve = args->os_tls_reserve;
tls_init_args.err_sink_reserve = args->os_tls_err_sink_reserve;
tls_init_args.err_sink_commit = args->os_tls_err_sink_commit;
}
DN_OS_TLSInit(&os->tls, tls_init_args);
DN_OS_TLSSetCurrentThreadTLS(&os->tls);
os->cpu_report = DN_CPUGetReport(); os->cpu_report = DN_CPUGetReport();
#define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_Str8Lit(#label)}; #define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_Str8Lit(#label)};
@ -92,20 +78,19 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args)
#endif // defined(DN_OS_H) && defined(DN_OS_CPP) #endif // defined(DN_OS_H) && defined(DN_OS_CPP)
} }
DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags)
DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
{ {
g_dn_ = dn; g_dn_ = dn;
dn->init_flags = flags; dn->init_flags = flags;
if (flags & DN_InitFlags_OS) { if (flags & DN_InitFlags_OS) {
#if defined(DN_OS_H) && defined(DN_OS_CPP) #if defined(DN_OS_H) && defined(DN_OS_CPP)
DN_InitOS_(&dn->os, args); DN_InitOS_(&dn->os);
if (flags & DN_InitFlags_OSLeakTracker) { if (flags & DN_InitFlags_OSLeakTracker) {
// NOTE: Setup the allocation table with allocation tracking turned off on // NOTE: Setup the allocation table with allocation tracking turned off on
// the arena we're using to initialise the table. // the arena we're using to initialise the table.
dn->leak.alloc_table_arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak); dn->leak.alloc_table_arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak);
dn->leak.alloc_table = DN_DSMap_Init<DN_LeakAlloc>(&dn->leak.alloc_table_arena, 4096, DN_DSMapFlags_Nil); dn->leak.alloc_table = DN_DSMapInit<DN_LeakAlloc>(&dn->leak.alloc_table_arena, 4096, DN_DSMapFlags_Nil);
} }
#endif #endif
} }
@ -141,7 +126,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
#endif #endif
#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) #if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX)
DN_POSIXCore *posix = DN_Cast(DN_POSIXCore *)g_dn_->os.platform_context; DN_OSPosixCore *posix = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context;
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Clock GetTime: %S\n", posix->clock_monotonic_raw ? DN_Str8Lit("CLOCK_MONOTONIC_RAW") : DN_Str8Lit("CLOCK_MONOTONIC")); DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Clock GetTime: %S\n", posix->clock_monotonic_raw ? DN_Str8Lit("CLOCK_MONOTONIC_RAW") : DN_Str8Lit("CLOCK_MONOTONIC"));
#endif #endif
// TODO(doyle): Add stacktrace feature log // TODO(doyle): Add stacktrace feature log
@ -177,7 +162,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
} }
if (buf_size) if (buf_size)
DN_LOG_DebugF("%.*s", DN_Cast(int)buf_size, buf); DN_LogDebugF("%.*s", DN_Cast(int)buf_size, buf);
} }
DN_API void DN_BeginFrame() DN_API void DN_BeginFrame()

View File

@ -2,8 +2,8 @@
#define DN_INC_H #define DN_INC_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "dn_base_inc.h" #define DN_H_WITH_OS 1
#include "dn_os_inc.h" #include "dn.h"
#endif #endif
struct DN_InitArgs struct DN_InitArgs
@ -38,6 +38,7 @@ struct DN_Core
extern DN_Core *g_dn_; extern DN_Core *g_dn_;
DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args); DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args);
DN_API void DN_ThreadContextInit();
DN_API void DN_BeginFrame(); DN_API void DN_BeginFrame();
#endif // !defined(DN_INC_H) #endif // !defined(DN_INC_H)