Fix single header build with updated DN lib

This commit is contained in:
2026-05-18 11:19:15 +10:00
parent 0ff24117dd
commit 0905a10f61
31 changed files with 9674 additions and 38601 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1105 -521
View File
File diff suppressed because it is too large Load Diff
+339 -161
View File
@@ -40,9 +40,11 @@
#if defined(DN_COMPILER_MSVC) #if defined(DN_COMPILER_MSVC)
#define DN_MSVC_WARNING_PUSH __pragma(warning(push)) #define DN_MSVC_WARNING_PUSH __pragma(warning(push))
#define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__)) #define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__))
#define DN_MSVC_WARNING_ENABLE(...) __pragma(warning(default :##__VA_ARGS__))
#define DN_MSVC_WARNING_POP __pragma(warning(pop)) #define DN_MSVC_WARNING_POP __pragma(warning(pop))
#else #else
#define DN_MSVC_WARNING_PUSH #define DN_MSVC_WARNING_PUSH
#define DN_MSVC_WARNING_ENABLE(...)
#define DN_MSVC_WARNING_DISABLE(...) #define DN_MSVC_WARNING_DISABLE(...)
#define DN_MSVC_WARNING_POP #define DN_MSVC_WARNING_POP
#endif #endif
@@ -162,6 +164,19 @@
#include <sanitizer/asan_interface.h> #include <sanitizer/asan_interface.h>
#endif #endif
// NOTE: Memory
#if !defined(DN_ARENA_TEMP_MEM_UAF_GUARD)
#define DN_ARENA_TEMP_MEM_UAF_GUARD 0
#endif
#if !defined(DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT)
#define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 0
#endif
#if !defined(DN_SCRUB_UNINIT_MEM_BYTE)
#define DN_SCRUB_UNINIT_MEM_BYTE 0
#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
@@ -546,9 +561,9 @@ struct DN_TicketMutex
}; };
struct DN_Hex32 { char data[32]; }; struct DN_Hex32 { char data[32 + 1]; DN_USize size; };
struct DN_Hex64 { char data[64]; }; struct DN_Hex64 { char data[64 + 1]; DN_USize size; };
struct DN_Hex128 { char data[128]; }; struct DN_Hex128 { char data[128 + 1]; DN_USize size; };
struct DN_HexU64Str8 struct DN_HexU64Str8
{ {
@@ -562,6 +577,11 @@ enum DN_HexFromU64Type
DN_HexFromU64Type_Uppercase, DN_HexFromU64Type_Uppercase,
}; };
enum DN_TrimLeadingZero
{
DN_TrimLeadingZero_No,
DN_TrimLeadingZero_Yes,
};
struct DN_U8x16 { DN_U8 data[16]; }; struct DN_U8x16 { DN_U8 data[16]; };
struct DN_U8x32 { DN_U8 data[32]; }; struct DN_U8x32 { DN_U8 data[32]; };
@@ -627,12 +647,57 @@ struct DN_U64FromResult
DN_U64 value; DN_U64 value;
}; };
struct DN_USizeFromResult
{
bool success;
DN_USize value;
};
struct DN_I64FromResult struct DN_I64FromResult
{ {
bool success; bool success;
DN_I64 value; DN_I64 value;
}; };
struct DN_U8x32FromResult
{
bool success;
DN_U8x32 value;
};
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;
};
enum DN_MemCommit enum DN_MemCommit
{ {
DN_MemCommit_No, DN_MemCommit_No,
@@ -689,37 +754,40 @@ enum DN_MemPage_
#define DN_ARENA_COMMIT_SIZE DN_Kilobytes(64) #define DN_ARENA_COMMIT_SIZE DN_Kilobytes(64)
#endif #endif
enum DN_Allocator enum DN_MemFuncsType
{ {
DN_Allocator_Arena, DN_MemFuncsType_Nil,
DN_Allocator_Pool, DN_MemFuncsType_Heap,
DN_MemFuncsType_Virtual,
}; };
struct DN_ArenaBlock typedef void *(DN_MemHeapAllocFunc)(DN_USize size);
typedef void (DN_MemHeapDeallocFunc)(void *ptr);
typedef void *(DN_MemVirtualReserveFunc)(DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
typedef bool (DN_MemVirtualCommitFunc)(void *ptr, DN_USize size, DN_U32 page_flags);
typedef void (DN_MemVirtualReleaseFunc)(void *ptr, DN_USize size);
struct DN_MemFuncs
{ {
DN_ArenaBlock *prev; DN_MemFuncsType type;
DN_MemHeapAllocFunc *heap_alloc;
DN_MemHeapDeallocFunc *heap_dealloc;
DN_U32 virtual_page_size;
DN_MemVirtualReserveFunc *virtual_reserve;
DN_MemVirtualCommitFunc *virtual_commit;
DN_MemVirtualReleaseFunc *virtual_release;
};
struct DN_MemBlock
{
DN_MemBlock* prev;
DN_U64 used; DN_U64 used;
DN_U64 commit; DN_U64 commit;
DN_U64 reserve; DN_U64 reserve;
DN_U64 reserve_sum; DN_U64 reserve_sum;
}; };
typedef DN_U32 DN_ArenaFlags; struct DN_MemListInfo
enum DN_ArenaFlags_
{
DN_ArenaFlags_Nil = 0,
DN_ArenaFlags_NoGrow = 1 << 0,
DN_ArenaFlags_NoPoison = 1 << 1,
DN_ArenaFlags_NoAllocTrack = 1 << 2,
DN_ArenaFlags_AllocCanLeak = 1 << 3,
DN_ArenaFlags_SimAlloc = 1 << 4,
// NOTE: Internal flags. Do not use
DN_ArenaFlags_UserBuffer = 1 << 4,
DN_ArenaFlags_MemFuncs = 1 << 5,
};
struct DN_ArenaInfo
{ {
DN_U64 used; DN_U64 used;
DN_U64 commit; DN_U64 commit;
@@ -727,10 +795,80 @@ struct DN_ArenaInfo
DN_U64 blocks; DN_U64 blocks;
}; };
struct DN_ArenaStats struct DN_MemStats
{ {
DN_ArenaInfo info; DN_MemListInfo info;
DN_ArenaInfo hwm; DN_MemListInfo hwm;
};
typedef DN_U32 DN_MemFlags;
enum DN_MemFlags_
{
DN_MemFlags_Nil = 0,
DN_MemFlags_NoGrow = 1 << 0,
DN_MemFlags_NoPoison = 1 << 1,
DN_MemFlags_NoAllocTrack = 1 << 2,
DN_MemFlags_AllocCanLeak = 1 << 3,
DN_MemFlags_SimAlloc = 1 << 4,
// NOTE: Records stack traces of temp memory regions on construction to provide more diagnostics
// when UAF violation occurs in the use of a region (e.g. nested regions A and B, with A
// allocating whilst B is active would result in A's memory being wiped at the end of B). Tracing
// has a heavy performance penalty as each scratch/temp memory region triggers and stores the
// stack trace.
//
// Ignored if UAF guard is disabled at the preprocessor level
// (e.g.: #define DN_ARENA_TEMP_MEM_UAF_GUARD 0)
DN_MemFlags_TempMemUAFTrace = 1 << 5,
// NOTE: Forcibly disables TempMemUAFTrace for the arena irrespective of global settings. Globally
// UAF tracing can be enabled across all arenas via the preprocessor which turns the tracing
// feature (e.g.: #define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 1) into an opt-out situation
// where arenas have to specify this flag, specifically to not be traced.
//
// If both TempMemUAFTrace, TempMemUAFTraceDisable and or the global preprocessor flag is set
// disabling takes precedence, always if it is set.
DN_MemFlags_TempMemUAFTraceDisable = 1 << 6,
// NOTE: Internal flags. Do not use
DN_MemFlags_UserBuffer = 1 << 7,
DN_MemFlags_MemFuncs = 1 << 8,
};
struct DN_MemList
{
DN_MemBlock* curr;
DN_MemFlags flags;
DN_MemFuncs funcs;
DN_MemStats stats;
DN_Str8 label;
#if DN_ARENA_TEMP_MEM_UAF_GUARD
DN_U32 uaf_guard_next_id;
DN_U32 uaf_guard_active_id;
struct DN_MemListTemp* uaf_guard_active_temp_mem;
#endif
};
struct DN_MemListTemp
{
DN_MemList* mem;
DN_U64 used_sum;
#if DN_ARENA_TEMP_MEM_UAF_GUARD
DN_StackTraceWalkResult trace;
#endif
};
enum DN_AllocatorType
{
DN_AllocatorType_Arena,
DN_AllocatorType_Pool,
};
struct DN_Allocator
{
DN_AllocatorType type;
void* context;
}; };
struct DN_ArenaStatsStr8x64 struct DN_ArenaStatsStr8x64
@@ -739,51 +877,24 @@ struct DN_ArenaStatsStr8x64
DN_Str8x64 hwm; DN_Str8x64 hwm;
}; };
enum DN_ArenaMemFuncType enum DN_ArenaReset
{ {
DN_ArenaMemFuncType_Nil, DN_ArenaReset_No,
DN_ArenaMemFuncType_Basic, DN_ArenaReset_Yes,
DN_ArenaMemFuncType_VMem,
};
typedef void *(DN_ArenaMemBasicAllocFunc)(DN_USize size);
typedef void (DN_ArenaMemBasicDeallocFunc)(void *ptr);
typedef void *(DN_ArenaMemVMemReserveFunc)(DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
typedef bool (DN_ArenaMemVMemCommitFunc)(void *ptr, DN_USize size, DN_U32 page_flags);
typedef void (DN_ArenaMemVMemReleaseFunc)(void *ptr, DN_USize size);
struct DN_ArenaMemFuncs
{
DN_ArenaMemFuncType type;
DN_ArenaMemBasicAllocFunc *basic_alloc;
DN_ArenaMemBasicDeallocFunc *basic_dealloc;
DN_U32 vmem_page_size;
DN_ArenaMemVMemReserveFunc *vmem_reserve;
DN_ArenaMemVMemCommitFunc *vmem_commit;
DN_ArenaMemVMemReleaseFunc *vmem_release;
}; };
struct DN_Arena struct DN_Arena
{ {
DN_ArenaMemFuncs mem_funcs; DN_MemList* mem;
DN_ArenaBlock *curr; #if DN_ARENA_TEMP_MEM_UAF_GUARD
DN_ArenaStats stats; DN_U32 uaf_guard_id;
DN_ArenaFlags flags; DN_MemListTemp* uaf_guard_temp_mem;
DN_Str8 label; DN_U32 uaf_guard_prev_id;
DN_Arena *prev, *next; DN_MemListTemp* uaf_guard_prev_temp_mem;
}; bool uaf_guard_is_being_checked;
#else
struct DN_ArenaTempMem DN_MemListTemp temp_mem;
{ #endif
DN_Arena *arena;
DN_U64 used_sum;
};
struct DN_ArenaTempMemScope
{
DN_ArenaTempMemScope(DN_Arena *arena);
~DN_ArenaTempMemScope();
DN_ArenaTempMem mem;
}; };
DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64); DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64);
@@ -857,6 +968,13 @@ struct DN_UTF8DecodeIterator
DN_U32 codepoint; DN_U32 codepoint;
}; };
typedef DN_U32 DN_CodepointCountFlags;
enum DN_CodepointCountFlags_
{
DN_CodepointCountFlags_Nil = 0,
DN_CodepointCountFlags_SkipANSICode = 1 << 0,
};
struct DN_NibbleFromU8Result struct DN_NibbleFromU8Result
{ {
char nibble0; char nibble0;
@@ -877,6 +995,9 @@ enum DN_Str8IsAllType
struct DN_Str8BSplitResult struct DN_Str8BSplitResult
{ {
// If there are multiple strings passed to split against, this is the index into that array of
// which the string was split on. If no array was passed this is always 0.
DN_USize input_index;
DN_Str8 lhs; DN_Str8 lhs;
DN_Str8 rhs; DN_Str8 rhs;
}; };
@@ -902,16 +1023,18 @@ enum DN_Str8FindFlag_
DN_Str8FindFlag_AlphaNum = DN_Str8FindFlag_Alphabet | DN_Str8FindFlag_Digit, DN_Str8FindFlag_AlphaNum = DN_Str8FindFlag_Alphabet | DN_Str8FindFlag_Digit,
}; };
enum DN_Str8SplitIncludeEmptyStrings typedef DN_USize DN_Str8SplitFlags;
enum DN_Str8SplitFlags_
{ {
DN_Str8SplitIncludeEmptyStrings_No, DN_Str8SplitFlags_ExcludeEmptyStrings = 1 << 0,
DN_Str8SplitIncludeEmptyStrings_Yes, DN_Str8SplitFlags_HandleQuotedStrings = 1 << 1,
}; };
struct DN_Str8TruncateResult struct DN_Str8TruncResult
{ {
bool truncated; bool truncated;
DN_Str8 str8; DN_Str8 str8;
DN_USize size_req; // Not including null-terminator
}; };
struct DN_Str8SplitResult struct DN_Str8SplitResult
@@ -920,6 +1043,14 @@ struct DN_Str8SplitResult
DN_USize count; DN_USize count;
}; };
typedef DN_USize DN_Str8TableFlags;
enum DN_Str8TableFlags_
{
DN_Str8TableFlags_None = 0,
DN_Str8TableFlags_HasHeader = 1 << 0,
DN_Str8TableFlags_RowLines = 1 << 1,
};
struct DN_Str8Link struct DN_Str8Link
{ {
DN_Str8 string; // The string DN_Str8 string; // The string
@@ -1070,8 +1201,7 @@ struct DN_ErrSink
struct DN_TCScratch struct DN_TCScratch
{ {
DN_Arena* arena; DN_Arena arena;
DN_ArenaTempMem temp_mem;
DN_B32 destructed; DN_B32 destructed;
}; };
@@ -1101,19 +1231,32 @@ struct DN_TCCore // (T)hread (C)ontext sitting in thread-local storage
DN_CallSite call_site; DN_CallSite call_site;
char lane_opaque[sizeof(DN_U64) * 4]; char lane_opaque[sizeof(DN_U64) * 4];
DN_MemList main_arena_mem_;
DN_MemList temp_a_arena_mem_;
DN_MemList temp_b_arena_mem_;
DN_MemList err_sink_arena_mem_;
DN_Arena main_arena_; DN_Arena main_arena_;
DN_Arena temp_a_arena_; DN_Arena temp_a_arena_;
DN_Arena temp_b_arena_; DN_Arena temp_b_arena_;
DN_Arena err_sink_arena_; DN_Arena err_sink_arena_;
DN_Arena* main_arena; DN_Arena* main_arena;
DN_Pool main_pool;
DN_Arena* temp_a_arena; DN_Arena* temp_a_arena;
DN_Arena* temp_b_arena; DN_Arena* temp_b_arena;
DN_ErrSink err_sink; DN_ErrSink err_sink;
DN_Arena* frame_arena; DN_Arena* frame_arena;
}; };
enum DN_TCDeinitArenas
{
DN_TCDeinitArenas_No,
DN_TCDeinitArenas_Yes,
};
struct DN_PCG32 { DN_U64 state; }; struct DN_PCG32 { DN_U64 state; };
struct DN_MurmurHash3 { DN_U64 e[2]; }; struct DN_MurmurHash3 { DN_U64 e[2]; };
@@ -1146,10 +1289,10 @@ struct DN_LogTypeParam
DN_Str8 str8; DN_Str8 str8;
}; };
enum DN_LogColourType enum DN_ANSIColourMode
{ {
DN_LogColourType_Fg, DN_ANSIColourMode_Fg,
DN_LogColourType_Bg, DN_ANSIColourMode_Bg,
}; };
struct DN_LogDate struct DN_LogDate
@@ -1169,40 +1312,15 @@ struct DN_LogPrefixSize
DN_USize padding; DN_USize padding;
}; };
struct DN_StackTraceFrame typedef DN_U32 DN_LogFlags;
enum DN_LogFlags_
{ {
DN_U64 address; DN_LogFlags_Nil = 0,
DN_U64 line_number; DN_LogFlags_NoNewLine = 1 << 0,
DN_Str8 file_name; DN_LogFlags_NoPrefix = 1 << 1,
DN_Str8 function_name;
}; };
struct DN_StackTraceFrameSlice typedef void DN_LogPrintFunc(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_LogFlags flags, DN_FMT_ATTRIB char const *fmt, va_list args);
{
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_LogPrintFunc(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_MSVC_WARNING_PUSH DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
@@ -1346,7 +1464,9 @@ DN_MSVC_WARNING_POP
#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__) #define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
#define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__) #define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__)
DN_API bool DN_MemStartsWith (void const *lhs, DN_USize lhs_size, void const *rhs, DN_USize rhs_size);
DN_API bool DN_MemEq (void const *lhs, DN_USize lhs_size, void const *rhs, DN_USize rhs_size); DN_API bool DN_MemEq (void const *lhs, DN_USize lhs_size, void const *rhs, DN_USize rhs_size);
DN_API bool DN_MemEqUnsafe (void const *lhs, void const *rhs, DN_USize size);
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);
@@ -1371,6 +1491,15 @@ DN_API void DN_ByteSwapU64Ptr
(((((DN_U32)(val)) >> 8) & 0xFF) << 16) | \ (((((DN_U32)(val)) >> 8) & 0xFF) << 16) | \
(((((DN_U32)(val)) >> 0) & 0xFF) << 24) \ (((((DN_U32)(val)) >> 0) & 0xFF) << 24) \
) )
#define DN_ByteSwap24(val) ( \
(((((DN_U32)(val)) >> 16) & 0xFF) << 0) | \
(((((DN_U32)(val)) >> 8) & 0xFF) << 8) | \
(((((DN_U32)(val)) >> 0) & 0xFF) << 16) \
)
#define DN_ByteSwap16(val) ( \
(((((DN_U16)(val)) >> 8) & 0xFF) << 0) | \
(((((DN_U16)(val)) >> 0) & 0xFF) << 8) \
)
#if defined(DN_64_BIT) #if defined(DN_64_BIT)
#define DN_ByteSwapUSize(val) DN_ByteSwap64(val) #define DN_ByteSwapUSize(val) DN_ByteSwap64(val)
#else #else
@@ -1463,35 +1592,53 @@ DN_API void DN_ASanUnpoisonMemoryRegion
DN_API DN_F32 DN_EpsilonClampF32 (DN_F32 value, DN_F32 target, DN_F32 epsilon); DN_API DN_F32 DN_EpsilonClampF32 (DN_F32 value, DN_F32 target, DN_F32 epsilon);
DN_API DN_Arena DN_ArenaFromBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags); DN_API DN_MemStats DN_MemStatsSum (DN_MemStats lhs, DN_MemStats rhs);
DN_API DN_Arena DN_ArenaFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags, DN_ArenaMemFuncs mem_funcs); DN_API DN_MemStats DN_MemStatsSumArray (DN_MemStats const *array, DN_USize size);
DN_API void DN_ArenaDeinit (DN_Arena *arena);
DN_API bool DN_ArenaCommit (DN_Arena *arena, DN_U64 size); DN_API DN_MemList DN_MemListFromBuffer (void *buffer, DN_USize size, DN_MemFlags flags);
DN_API bool DN_ArenaCommitTo (DN_Arena *arena, DN_U64 pos); DN_API DN_MemList DN_MemListFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags, DN_MemFuncs mem_funcs);
DN_API bool DN_ArenaGrow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit); DN_API void DN_MemListDeinit (DN_MemList *mem);
DN_API void * DN_ArenaAlloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem zmem); DN_API bool DN_MemListCommit (DN_MemList *mem, DN_U64 size);
DN_API void * DN_ArenaAllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem zmem); DN_API bool DN_MemListCommitTo (DN_MemList *mem, DN_U64 pos);
DN_API bool DN_MemListGrow (DN_MemList *mem, DN_U64 reserve, DN_U64 commit);
DN_API void * DN_MemListAlloc (DN_MemList *mem, DN_U64 size, uint8_t align, DN_ZMem zmem);
DN_API void * DN_MemListAllocContiguous (DN_MemList *mem, DN_U64 size, uint8_t align, DN_ZMem zmem);
DN_API void * DN_MemListCopy (DN_MemList *mem, void const *data, DN_U64 size, uint8_t align);
DN_API void DN_MemListPopTo (DN_MemList *mem, DN_U64 init_used);
DN_API void DN_MemListPop (DN_MemList *mem, DN_U64 amount);
DN_API DN_U64 DN_MemListPos (DN_MemList const *mem);
DN_API void DN_MemListClear (DN_MemList *mem);
DN_API bool DN_MemListOwnsPtr (DN_MemList const *mem, void *ptr);
DN_API DN_Str8x64 DN_MemListInfoStr8x64 (DN_MemListInfo info);
DN_API DN_MemListTemp DN_MemListTempBegin (DN_MemList *mem);
DN_API void DN_MemListTempEnd (DN_MemListTemp mem);
#define DN_MemListNew(arena, T, zmem) (T *)DN_MemListAlloc(arena, sizeof(T), alignof(T), zmem)
#define DN_MemListNewZ(arena, T) (T *)DN_MemListAlloc(arena, sizeof(T), alignof(T), DN_ZMem_Yes)
#define DN_MemListNewContiguous(arena, T, zmem) (T *)DN_MemListAllocContiguous(arena, sizeof(T), alignof(T), zmem)
#define DN_MemListNewContiguousZ(arena, T) (T *)DN_MemListAllocContiguous(arena, sizeof(T), alignof(T), DN_ZMem_Yes)
#define DN_MemListNewArray(arena, T, count, zmem) (T *)DN_MemListAlloc(arena, sizeof(T) * (count), alignof(T), zmem)
#define DN_MemListNewArrayZ(arena, T, count) (T *)DN_MemListAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_Yes)
#define DN_MemListNewArrayNoZ(arena, T, count) (T *)DN_MemListAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_No)
#define DN_MemListNewCopy(arena, T, src) (T *)DN_MemListCopy(arena, (src), sizeof(T), alignof(T))
#define DN_MemListNewArrayCopy(arena, T, src, count) (T *)DN_MemListCopy(arena, (src), sizeof(T) * (count), alignof(T))
DN_API void DN_ArenaUAFCheck (DN_Arena *arena);
#define DN_ArenaDeref(arena_view) (DN_ArenaUAFCheck(arena_view), (arena_view)->arena)
DN_API DN_Arena DN_ArenaFromMemList (DN_MemList *mem);
DN_API DN_Arena DN_ArenaTempBeginFromMemList (DN_MemList *mem);
DN_API DN_Arena DN_ArenaTempBeginFromArena (DN_Arena *arena);
DN_API void DN_ArenaTempEnd (DN_Arena *arena, DN_ArenaReset reset);
DN_API void* DN_ArenaAlloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem z_mem);
DN_API void* DN_ArenaAllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem z_arena);
DN_API void* DN_ArenaCopy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align); DN_API void* DN_ArenaCopy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
DN_API void DN_ArenaPopTo (DN_Arena *arena, DN_U64 init_used);
DN_API void DN_ArenaPop (DN_Arena *arena, DN_U64 amount);
DN_API DN_U64 DN_ArenaPos (DN_Arena const *arena);
DN_API void DN_ArenaClear (DN_Arena *arena);
DN_API bool DN_ArenaOwnsPtr (DN_Arena const *arena, void *ptr);
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_ArenaSumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
DN_API DN_ArenaStats DN_ArenaSumArenaArrayToStats (DN_Arena const *array, DN_USize size);
DN_API DN_ArenaTempMem DN_ArenaTempMemBegin (DN_Arena *arena);
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)
#define DN_ArenaNewZ(arena, T) (T *)DN_ArenaAlloc(arena, sizeof(T), alignof(T), DN_ZMem_Yes) #define DN_ArenaNewZ(arena, T) (T *)DN_ArenaAlloc(arena, sizeof(T), alignof(T), DN_ZMem_Yes)
#define DN_ArenaNewContiguous(arena, T, zmem) (T *)DN_ArenaAllocContiguous(arena, sizeof(T), alignof(T), zmem) #define DN_ArenaNewContiguous(arena, T, zmem) (T *)DN_ArenaAllocContiguous(arena, sizeof(T), alignof(T), zmem)
#define DN_ArenaNewContiguousZ(arena, T) (T *)DN_ArenaAllocContiguous(arena, sizeof(T), alignof(T), DN_ZMem_Yes) #define DN_ArenaNewContiguousZ(arena, T) (T *)DN_ArenaAllocContiguous(arena, sizeof(T), alignof(T), DN_ZMem_Yes)
#define DN_ArenaNewArray(arena, T, count, zmem) (T *)DN_ArenaAlloc(arena, sizeof(T) * (count), alignof(T), zmem) #define DN_ArenaNewArray(arena, T, count, zmem) (T *)DN_ArenaAlloc(arena, sizeof(T) * (count), alignof(T), zmem)
#define DN_ArenaNewArrayZ(arena, T, count) (T *)DN_ArenaAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_Yes) #define DN_ArenaNewArrayZ(arena, T, count) (T *)DN_ArenaAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_Yes)
#define DN_ArenaNewArrayNoZ(arena, T, count) (T *)DN_ArenaAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_No)
#define DN_ArenaNewCopy(arena, T, src) (T *)DN_ArenaCopy(arena, (src), sizeof(T), alignof(T)) #define DN_ArenaNewCopy(arena, T, src) (T *)DN_ArenaCopy(arena, (src), sizeof(T), alignof(T))
#define DN_ArenaNewArrayCopy(arena, T, src, count) (T *)DN_ArenaCopy(arena, (src), sizeof(T) * (count), alignof(T)) #define DN_ArenaNewArrayCopy(arena, T, src, count) (T *)DN_ArenaCopy(arena, (src), sizeof(T) * (count), alignof(T))
@@ -1528,12 +1675,13 @@ DN_API void DN_ErrSinkAppendF_
#define DN_ErrSinkAppendF(error, error_code, fmt, ...) DN_ErrSinkAppendF_(error, error_code, DN_CALL_SITE, fmt, ##__VA_ARGS__) #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_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_TCInitFromMemFuncs (DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_MemFuncs mem_funcs);
DN_API void DN_TCDeinit (DN_TCCore *tc); DN_API void DN_TCDeinit (DN_TCCore *tc, DN_TCDeinitArenas deinit_arenas);
DN_API void DN_TCEquip (DN_TCCore *tc); DN_API void DN_TCEquip (DN_TCCore *tc);
DN_API DN_TCCore* DN_TCGet (); DN_API DN_TCCore* DN_TCGet ();
DN_API DN_Arena* DN_TCMainArena (); DN_API DN_Arena* DN_TCMainArena ();
DN_API DN_Arena* DN_TCTempArena (DN_Arena **conflicts, DN_USize count); DN_API DN_Pool* DN_TCMainPool ();
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 DN_TCScratch DN_TCScratchBegin (DN_Arena **conflicts, DN_USize count);
DN_API void DN_TCScratchEnd (DN_TCScratch *scratch); DN_API void DN_TCScratchEnd (DN_TCScratch *scratch);
DN_API void DN_TCSetFrameArena (DN_Arena *arena); DN_API void DN_TCSetFrameArena (DN_Arena *arena);
@@ -1558,13 +1706,19 @@ DN_API DN_U64 DN_U64FromHexPtrUnsafe
DN_API DN_U64FromResult DN_U64FromHexStr8 (DN_Str8 hex); DN_API DN_U64FromResult DN_U64FromHexStr8 (DN_Str8 hex);
DN_API DN_U64 DN_U64FromHexStr8Unsafe (DN_Str8 hex); DN_API DN_U64 DN_U64FromHexStr8Unsafe (DN_Str8 hex);
DN_API DN_U64 DN_U64FromU8x32HiBEUnsafe (DN_U8x32 const *val); // Get U64 stored in big-endian at the high bytes [24:32) DN_API DN_U64 DN_U64FromU8x32HiBEUnsafe (DN_U8x32 const *val); // Get U64 stored in big-endian at the high bytes [24:32)
DN_API DN_U64 DN_U64FromU8x32HiBE (DN_U8x32 const *val); // Checks [0:24) bytes aren't set before getting the U64 DN_API DN_U64FromResult DN_U64FromU8x32HiBE (DN_U8x32 const *val); // Checks [0:24) bytes aren't set before getting the U64
DN_API DN_USize DN_USizeFromU8x32HiBEUnsafe (DN_U8x32 const *val); // Get USize stored in big-endian at the high bytes [32 - sizeof USize:32) DN_API DN_USize DN_USizeFromU8x32HiBEUnsafe (DN_U8x32 const *val); // Get USize stored in big-endian at the high bytes [32 - sizeof USize:32)
DN_API DN_USize DN_USizeFromU8x32HiBE (DN_U8x32 const *val); // Checks [0:sizeof USize) bytes aren't set before getting the U64 DN_API DN_USizeFromResult DN_USizeFromU8x32HiBE (DN_U8x32 const *val); // Checks [0:sizeof USize) bytes aren't set before getting the U64
DN_API DN_I64FromResult DN_I64FromStr8 (DN_Str8 string, char separator); DN_API DN_I64FromResult DN_I64FromStr8 (DN_Str8 string, char separator);
DN_API DN_I64FromResult DN_I64FromPtr (void const *data, DN_USize size, char separator); DN_API DN_I64FromResult DN_I64FromPtr (void const *data, DN_USize size, char separator);
DN_API DN_I64 DN_I64FromPtrUnsafe (void const *data, DN_USize size, char separator); DN_API DN_I64 DN_I64FromPtrUnsafe (void const *data, DN_USize size, char separator);
DN_API bool DN_U8x32Eq (DN_U8x32 const *lhs, DN_U8x32 const *rhs);
DN_API DN_U8x32 DN_U8x32FromBytesLeftPadZ (DN_U8 const *ptr, DN_USize count);
DN_API DN_U8x32 DN_U8x32FromHexUnsafe (DN_Str8 hex_32b);
DN_API DN_U8x32FromResult DN_U8x32FromHex (DN_Str8 hex_32b);
DN_API DN_U8x32FromResult DN_U8x32FromDecimalStr8 (DN_Str8 decimal); // Write decimal string (e.g. "12345") as big-endian 256-bit value
DN_API DN_USize DN_FmtVSize (DN_FMT_ATTRIB char const *fmt, va_list args); DN_API DN_USize DN_FmtVSize (DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_USize DN_FmtSize (DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_USize DN_FmtSize (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_FmtAppendResult DN_FmtVAppend (char *buf, DN_USize *buf_size, DN_USize buf_max, char const *fmt, va_list args); DN_API DN_FmtAppendResult DN_FmtVAppend (char *buf, DN_USize *buf_size, DN_USize buf_max, char const *fmt, va_list args);
@@ -1581,15 +1735,17 @@ DN_API DN_USize DN_CStr16Size
#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)}
#define DN_Str8FromStruct(ptr) DN_Str8FromPtr((ptr)->data, (ptr)->size) #define DN_Str8FromStruct(ptr) DN_Str8FromPtr((ptr)->data, (ptr)->size)
#define DN_Str8FromLitArray(c_array) DN_Str8FromPtr(c_array, DN_ArrayCountU(c_array)) #define DN_Str8FromLitArray(c_array) DN_Str8FromPtr(c_array, DN_ArrayCountU(c_array))
DN_API DN_Str8 DN_Str8AllocArena (DN_Arena *arena, DN_USize size, DN_ZMem z_mem); DN_API DN_Str8 DN_Str8AllocArena (DN_USize size, DN_ZMem z_mem, DN_Arena *arena);
DN_API DN_Str8 DN_Str8AllocPool (DN_Pool *pool, DN_USize size); DN_API DN_Str8 DN_Str8AllocPool (DN_USize size, DN_Pool *pool);
DN_API DN_Str8 DN_Str8FromCStr8 (char const *src); DN_API DN_Str8 DN_Str8FromCStr8 (char const *src);
DN_API DN_Str8 DN_Str8FromPtrArena (DN_Arena *arena, void const *data, DN_USize size); DN_API DN_Str8 DN_Str8FromCStr8Arena (char const *src, DN_Arena *arena);
DN_API DN_Str8 DN_Str8FromPtrPool (DN_Pool *pool, void const *data, DN_USize size); DN_API DN_Str8 DN_Str8FromPtrArena (void const *data, DN_USize size, DN_Arena *arena);
DN_API DN_Str8 DN_Str8FromStr8Arena (DN_Arena *arena, DN_Str8 string); DN_API DN_Str8 DN_Str8FromPtrPool (void const *data, DN_USize size, DN_Pool *pool);
DN_API DN_Str8 DN_Str8FromStr8Pool (DN_Pool *pool, DN_Str8 string); DN_API DN_Str8 DN_Str8FromStr8Arena (DN_Str8 string, DN_Arena *arena);
DN_API DN_Str8 DN_Str8FromFmtArena (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_Str8FromStr8Pool (DN_Str8 string, DN_Pool *pool);
DN_API DN_Str8 DN_Str8FromFmtVArena (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args); DN_API DN_Str8 DN_Str8FromFmtVArena (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_Str8 DN_Str8FromFmtArena (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromFmtVPool (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_Str8 DN_Str8FromFmtPool (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_Str8FromFmtPool (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromByteCountType (DN_ByteCountType type); DN_API DN_Str8 DN_Str8FromByteCountType (DN_ByteCountType type);
DN_API DN_Str8x16 DN_Str8x16FromFmt (DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8x16 DN_Str8x16FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
@@ -1630,8 +1786,8 @@ DN_API DN_Str8BSplitResult DN_Str8BSplitArray
DN_API DN_Str8BSplitResult DN_Str8BSplit (DN_Str8 string, DN_Str8 find); DN_API DN_Str8BSplitResult DN_Str8BSplit (DN_Str8 string, DN_Str8 find);
DN_API DN_Str8BSplitResult DN_Str8BSplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); DN_API DN_Str8BSplitResult DN_Str8BSplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size);
DN_API DN_Str8BSplitResult DN_Str8BSplitLast (DN_Str8 string, DN_Str8 find); DN_API DN_Str8BSplitResult DN_Str8BSplitLast (DN_Str8 string, DN_Str8 find);
DN_API DN_USize DN_Str8Split (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode); DN_API DN_USize DN_Str8Split (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitFlags mode);
DN_API DN_Str8SplitResult DN_Str8SplitArena (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode); DN_API DN_Str8SplitResult DN_Str8SplitArena (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitFlags mode, DN_Arena *arena);
DN_API DN_Str8FindResult DN_Str8FindStr8Array (DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case); DN_API DN_Str8FindResult DN_Str8FindStr8Array (DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case);
DN_API DN_Str8FindResult DN_Str8FindStr8 (DN_Str8 string, DN_Str8 find, DN_Str8EqCase eq_case); DN_API DN_Str8FindResult DN_Str8FindStr8 (DN_Str8 string, DN_Str8 find, DN_Str8EqCase eq_case);
DN_API DN_Str8FindResult DN_Str8Find (DN_Str8 string, DN_Str8FindFlag flags); DN_API DN_Str8FindResult DN_Str8Find (DN_Str8 string, DN_Str8FindFlag flags);
@@ -1662,17 +1818,21 @@ DN_API DN_Str8 DN_Str8AppendFV
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, ...);
DN_API DN_Str8 DN_Str8FillFV (DN_Arena *arena, DN_USize count, char const *fmt, va_list args); DN_API DN_Str8 DN_Str8FillFV (DN_Arena *arena, DN_USize count, char const *fmt, va_list args);
DN_API void DN_Str8Remove (DN_Str8 *string, DN_USize offset, DN_USize size); DN_API void DN_Str8Remove (DN_Str8 *string, DN_USize offset, DN_USize size);
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddle (DN_Arena *arena, DN_Str8 str8, DN_U32 side_size, DN_Str8 truncator); DN_API DN_Str8TruncResult DN_Str8TruncMiddlePtr (DN_Str8 str8, DN_USize side_size, DN_Str8 truncator, char *dest, DN_USize dest_max);
DN_API DN_Str8 DN_Str8Lower (DN_Arena *arena, DN_Str8 string); DN_API DN_Str8TruncResult DN_Str8TruncMiddle (DN_Str8 str8, DN_USize side_size, DN_Str8 truncator, DN_Arena *arena);
DN_API DN_Str8 DN_Str8Upper (DN_Arena *arena, DN_Str8 string); DN_API DN_Str8 DN_Str8Lower (DN_Str8 string, DN_Arena *arena);
DN_API DN_Str8 DN_Str8PadNewLines (DN_Arena *arena, DN_Str8 src, DN_Str8 pad); DN_API DN_Str8 DN_Str8Upper (DN_Str8 string, DN_Arena *arena);
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_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_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_Str8 DN_Str8ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
DN_API DN_Str8 DN_Str8PadNewLines (DN_Str8 string, DN_Str8 pad_string, DN_Arena *arena);
DN_API DN_Str8 DN_Str8LineBreakStr8 (DN_Str8 src, DN_USize desired_width, DN_Arena *arena);
DN_API DN_Str8 DN_Str8Table (DN_Str8 const* rows, DN_USize num_rows, DN_USize num_cols, DN_Str8TableFlags flags, DN_Arena *arena);
DN_API DN_Str8 DN_Str8SliceRender (DN_Str8Slice array, DN_Str8 separator, DN_Arena *arena); DN_API DN_Str8 DN_Str8SliceRender (DN_Str8Slice array, DN_Str8 separator, DN_Arena *arena);
DN_API DN_Str8 DN_Str8RenderSpaceSep (DN_Str8Slice array, DN_Arena *arena); DN_API DN_Str8 DN_Str8RenderSpaceSep (DN_Str8Slice array, DN_Arena *arena);
DN_API bool DN_Str16Eq (DN_Str16 lhs, DN_Str16 rhs);
DN_API DN_Str16 DN_Str16SliceRender (DN_Str16Slice array, DN_Str16 separator, DN_Arena *arena); DN_API DN_Str16 DN_Str16SliceRender (DN_Str16Slice array, DN_Str16 separator, DN_Arena *arena);
DN_API DN_Str16 DN_Str16RenderSpaceSep (DN_Str16Slice array, DN_Arena *arena); DN_API DN_Str16 DN_Str16RenderSpaceSep (DN_Str16Slice array, DN_Arena *arena);
@@ -1712,6 +1872,7 @@ DN_API int DN_UTF8Encode
DN_API int DN_UTF16Encode (DN_U16 utf16[2], DN_U32 codepoint); DN_API int DN_UTF16Encode (DN_U16 utf16[2], DN_U32 codepoint);
DN_API DN_UTF8DecodeResult DN_UTF8Decode (DN_Str8 stream); DN_API DN_UTF8DecodeResult DN_UTF8Decode (DN_Str8 stream);
DN_API bool DN_UTF8DecodeIterate (DN_UTF8DecodeIterator *it, DN_Str8 utf8); DN_API bool DN_UTF8DecodeIterate (DN_UTF8DecodeIterator *it, DN_Str8 utf8);
DN_API DN_USize DN_USizeCodepointCountFromUTF8 (DN_Str8 str, DN_CodepointCountFlags flags);
DN_API DN_U8 DN_U8FromHexNibble (char hex); DN_API DN_U8 DN_U8FromHexNibble (char hex);
DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8); DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8);
@@ -1720,15 +1881,17 @@ DN_API DN_USize DN_BytesFromHex
DN_API DN_Str8 DN_BytesFromHexArena (DN_Str8 hex, DN_Arena *arena); DN_API DN_Str8 DN_BytesFromHexArena (DN_Str8 hex, DN_Arena *arena);
DN_API DN_USize DN_BytesFromHexPtr (char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count); DN_API DN_USize DN_BytesFromHexPtr (char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count);
DN_API DN_Str8 DN_BytesFromHexPtrArena (char const *hex, DN_USize hex_count, DN_Arena *arena); DN_API DN_Str8 DN_BytesFromHexPtrArena (char const *hex, DN_USize hex_count, DN_Arena *arena);
DN_API DN_Str8 DN_BytesFromHexPtrPool (char const *hex, DN_USize hex_count, DN_Pool *pool);
DN_API DN_U8x16 DN_BytesFromHex32Ptr (char const *hex, DN_USize hex_count); DN_API DN_U8x16 DN_BytesFromHex32Ptr (char const *hex, DN_USize hex_count);
DN_API DN_U8x32 DN_BytesFromHex64Ptr (char const *hex, DN_USize hex_count); DN_API DN_U8x32 DN_BytesFromHex64Ptr (char const *hex, DN_USize hex_count);
DN_API DN_HexU64Str8 DN_HexFromU64 (DN_U64 value, DN_HexFromU64Type type); DN_API DN_HexU64Str8 DN_HexFromU64 (DN_U64 value, DN_HexFromU64Type type);
DN_API DN_USize DN_HexFromBytesPtr (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count); DN_API DN_USize DN_HexFromPtrBytes (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
DN_API DN_Str8 DN_HexFromBytesPtrArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena); DN_API DN_Str8 DN_HexFromPtrBytesArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
DN_API DN_Hex32 DN_HexFromBytes16Ptr (void const *bytes, DN_USize bytes_count); DN_API DN_USize DN_HexFromStr8Bytes (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
DN_API DN_Hex64 DN_HexFromBytes32Ptr (void const *bytes, DN_USize bytes_count); DN_API DN_Hex32 DN_Hex32FromPtr16b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
DN_API DN_Hex128 DN_HexFromBytes64Ptr (void const *bytes, DN_USize bytes_count); DN_API DN_Hex64 DN_Hex64FromPtr32b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
DN_API DN_Hex128 DN_Hex128FromPtr64b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units);
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
@@ -1792,18 +1955,33 @@ DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX64
#define DN_MurmurHash3HashU32FromBytes(bytes, len, seed) DN_MurmurHash3HashU32FromBytesX86(bytes, len, seed) #define DN_MurmurHash3HashU32FromBytes(bytes, len, seed) DN_MurmurHash3HashU32FromBytesX86(bytes, len, seed)
#endif #endif
#define DN_LogResetEscapeCode "\x1b[0m" #define DN_ANSICodeBoldLit "\x1b[1m"
#define DN_LogBoldEscapeCode "\x1b[1m" #define DN_ANSICodeResetLit "\x1b[0m"
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB (DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b); DN_API DN_Str8x32 DN_Str8x32FromANSIColourCodeU8RGB (DN_ANSIColourMode mode, DN_U8 r, DN_U8 g, DN_U8 b);
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromU32 (DN_LogColourType colour, DN_U32 value); DN_API DN_Str8x32 DN_Str8x32FromANSIColourCodeV3F32RGB255 (DN_ANSIColourMode mode, DN_V3F32 rgb_255);
DN_API DN_Str8x32 DN_Str8x32FromANSIColourCodeU32RGB (DN_ANSIColourMode mode, DN_U32 value);
DN_API DN_Str8 DN_Str8FromStr8ANSIColourU8RGBArena (DN_ANSIColourMode mode, DN_Str8 str8, DN_U8 r, DN_U8 g, DN_U8 b, DN_Arena *arena);
DN_API DN_Str8 DN_Str8FromStr8ANSIColourV3F32RGB255Arena (DN_ANSIColourMode mode, DN_Str8 str8, DN_V3F32 rgb_255, DN_Arena *arena);
DN_API DN_Str8 DN_Str8FromFmtANSIColourU8RGBArena (DN_ANSIColourMode mode, DN_U8 r, DN_U8 g, DN_U8 b, DN_Arena *arena, char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromFmtANSIColourV3F32RGB255Arena (DN_ANSIColourMode mode, DN_V3F32 rgb_255, DN_Arena *arena, char const *fmt, ...);
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 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_LogSetPrintFunc (DN_LogPrintFunc *print_func, void *user_data); DN_API void DN_LogSetPrintFunc (DN_LogPrintFunc *print_func, void *user_data);
DN_API void DN_LogPrint (DN_LogTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); DN_API void DN_LogPrint (DN_LogTypeParam type, DN_CallSite call_site, DN_LogFlags flags, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_LogTypeParam DN_LogTypeParamFromType (DN_LogType type); DN_API DN_LogTypeParam DN_LogTypeParamFromType (DN_LogType type);
#define DN_LogDebugF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Debug), DN_CALL_SITE, fmt, ##__VA_ARGS__) #define DN_LogF(type, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(type), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
#define DN_LogInfoF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LogWarningF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__) #define DN_LogDebugF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Debug), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
#define DN_LogErrorF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__) #define DN_LogInfoF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Info), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
#define DN_LogWarningF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Warning), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
#define DN_LogErrorF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Error), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
#define DN_LogFlagF(type, flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(type), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
#define DN_LogFlagDebugF(flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Debug), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
#define DN_LogFlagInfoF(flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Info), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
#define DN_LogFlagWarningF(flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Warning), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
#define DN_LogFlagErrorF(flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Error), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
// NOTE: OS primitives that the OS layer can provide for the base layer but is optional. // NOTE: OS primitives that the OS layer can provide for the base layer but is optional.
#if defined(DN_FREESTANDING) #if defined(DN_FREESTANDING)
+12 -13
View File
@@ -1,4 +1,3 @@
#define DN_BASE_CONTAINERS_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn.h" #include "../dn.h"
#endif #endif
@@ -7,9 +6,8 @@ DN_API void *DN_SliceAllocArena(void **data, DN_USize *slice_size_field, DN_USiz
{ {
void *result = *data; void *result = *data;
*data = DN_ArenaAlloc(arena, size * elem_size, align, zmem); *data = DN_ArenaAlloc(arena, size * elem_size, align, zmem);
if (*data) { if (*data)
*slice_size_field = size; *slice_size_field = size;
}
return result; return result;
} }
@@ -292,9 +290,6 @@ DN_API void DN_RingRead(DN_Ring *ring, void *dest, DN_U64 dest_size)
ring->read_pos += dest_size; ring->read_pos += dest_size;
} }
DN_U32 const DN_DS_MAP_DEFAULT_HASH_SEED = 0x8a1ced49;
DN_U32 const DN_DS_MAP_SENTINEL_SLOT = 0;
template <typename T> template <typename T>
DN_DSMap<T> DN_DSMapInit(DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags) DN_DSMap<T> DN_DSMapInit(DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags)
{ {
@@ -324,7 +319,7 @@ void DN_DSMapDeinit(DN_DSMap<T> *map, DN_ZMem z_mem)
return; return;
// TODO(doyle): Use z_mem // TODO(doyle): Use z_mem
(void)z_mem; (void)z_mem;
DN_ArenaDeinit(map->arena); DN_MemListDeinit(map->arena->mem);
*map = {}; *map = {};
} }
@@ -564,12 +559,16 @@ bool DN_DSMapResize(DN_DSMap<T> *map, DN_U32 size)
return false; return false;
DN_Arena *prev_arena = map->arena; DN_Arena *prev_arena = map->arena;
DN_MemList *new_mem = prev_arena->mem;
DN_MemList prev_mem = *prev_arena->mem;
prev_arena->mem = &prev_mem;
*new_mem = {};
new_mem->funcs = prev_mem.funcs;
new_mem->flags = prev_mem.flags;
DN_Arena new_arena = {}; DN_Arena new_arena = {};
new_arena.mem_funcs = prev_arena->mem_funcs; new_arena.mem = new_mem;
new_arena.flags = prev_arena->flags;
new_arena.label = prev_arena->label;
new_arena.prev = prev_arena->prev;
new_arena.next = prev_arena->next;
DN_DSMap<T> new_map = DN_DSMapInit<T>(&new_arena, size, map->flags); DN_DSMap<T> new_map = DN_DSMapInit<T>(&new_arena, size, map->flags);
if (!DN_DSMapIsValid(&new_map)) if (!DN_DSMapIsValid(&new_map))
@@ -695,7 +694,7 @@ DN_DSMapKey DN_DSMapKeyBuffer(DN_DSMap<T> const *map, void const *data, DN_USize
} }
template <typename T> template <typename T>
DN_DSMapKey DN_DSMapKeyBufferAsU64NoHash(DN_DSMap<T> const *map, void const *data, DN_U32 size) DN_DSMapKey DN_DSMapKeyBufferAsU64NoHash(DN_DSMap<T> const *map, void const *data, DN_USize size)
{ {
DN_DSMapKey result = {}; DN_DSMapKey result = {};
result.type = DN_DSMapKeyType_BufferAsU64NoHash; result.type = DN_DSMapKeyType_BufferAsU64NoHash;
+118 -65
View File
@@ -5,6 +5,17 @@
// it stupid simple, structs and functions. Minimal amount of container types with flexible // 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. // construction leads to less duplicated container code and less template meta-programming.
// //
// Arrays
//
// Data structures that have a `T *data`, `DN_USize count` and `DN_USize max` capacity that can be
// dynamically shrunk or expanded.
//
// API
// ResizeFrom: Resizes the array to `new_max` erase elements if resizing to a smaller size
// GrowFrom: Expands the capacity of the array if `new_max > array.max` otherwise no-op
// GrowIfNeeded: Expands the capacity of the array if `array.size + add_count > array.max` otherwise no-op
//
// Variants
// PArray => Pointer (to) Array // PArray => Pointer (to) Array
// LArray => Literal Array // LArray => Literal Array
// Define a C array and size. (P) array macros take a pointer to the aray, its size and its max // Define a C array and size. (P) array macros take a pointer to the aray, its size and its max
@@ -24,8 +35,17 @@
// DN_USize size; // DN_USize size;
// DN_USize max; // DN_USize max;
// } my_array = {}; // } my_array = {};
// DN_Arena arena = {};
// DN_IArrayResizeFromArena(&my_array, &arena, 256);
// MyStruct *item = DN_IArrayMake(&my_array, DN_ZMem_No); // MyStruct *item = DN_IArrayMake(&my_array, DN_ZMem_No);
// //
// Slices
//
// Fixed size container allocated up front that have a `T *data` and `DN_USize count` elements.
//
// API
// AllocArena: Allocates the container with the requested `count` elements
//
// ISinglyLL => Intrusive Singly Linked List // ISinglyLL => Intrusive Singly Linked List
// Define a struct with the members `next`: // Define a struct with the members `next`:
// //
@@ -62,6 +82,26 @@
// DN_SentinelDoublyLLInit(&my_list); // DN_SentinelDoublyLLInit(&my_list);
// DN_SentinelDoublyLLAppend(&my_list, &new_item); // DN_SentinelDoublyLLAppend(&my_list, &new_item);
// DN_SentinelDoublyLLForEach(it, &my_list) { /* ... */ } // DN_SentinelDoublyLLForEach(it, &my_list) { /* ... */ }
//
// SinglyHeadTailLL => Singly Linked List with Head and Tail pointer (or First and Last pointer)
/*
struct MyLinkItem {
int data;
MyLinkItem *next;
} my_list = {};
struct MyContainer {
MyLinkItem *head;
MyLinkItem *tail;
};
MyLinkItem item = {};
MyContainer container = {};
DN_ISinglyHeadTailLLAppend(container, item);
// ... or alternatively, DN_SinglyHeadTailLLAppend(container.head, container.tail, item);
for (MyLinkItem *it = container.head; it; it = it->next) { }
*/
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn.h" #include "../dn.h"
@@ -164,6 +204,16 @@ template <typename T> struct DN_DSMapResult
#define DN_ISinglyLLDetach(list) (decltype(list))DN_SinglyLLDetach((void **)&(list), (void **)&(list)->next) #define DN_ISinglyLLDetach(list) (decltype(list))DN_SinglyLLDetach((void **)&(list), (void **)&(list)->next)
#define DN_SinglyHeadTailLLAppend(head, tail, to_append) \
do { \
if (!head) \
head = to_append; \
if (tail) \
tail->next = to_append; \
tail = to_append; \
} while (0)
#define DN_ISinglyHeadTailLLAppend(container_ptr, to_append) DN_SinglyHeadTailLLAppend((container_ptr)->head, (container_ptr)->tail, to_append)
#define DN_SentinelDoublyLLInit(list) (list)->next = (list)->prev = (list) #define DN_SentinelDoublyLLInit(list) (list)->next = (list)->prev = (list)
#define DN_SentinelDoublyLLIsSentinel(list, item) ((list) == (item)) #define DN_SentinelDoublyLLIsSentinel(list, item) ((list) == (item))
#define DN_SentinelDoublyLLIsEmpty(list) (!(list) || ((list) == (list)->next)) #define DN_SentinelDoublyLLIsEmpty(list) (!(list) || ((list) == (list)->next))
@@ -171,9 +221,9 @@ template <typename T> struct DN_DSMapResult
#define DN_SentinelDoublyLLHasItems(list) ((list) && ((list) != (list)->next)) #define DN_SentinelDoublyLLHasItems(list) ((list) && ((list) != (list)->next))
#define DN_SentinelDoublyLLForEach(it, list) auto *it = (list)->next; (it) != (list); (it) = (it)->next #define DN_SentinelDoublyLLForEach(it, list) auto *it = (list)->next; (it) != (list); (it) = (it)->next
#define DN_SentinelDoublyLLInitArena(list, T, arena) \ #define DN_SentinelDoublyLLInitArena(list, T, ptr_arena) \
do { \ do { \
(list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \ (list) = DN_ArenaNew(ptr_arena, T, DN_ZMem_Yes); \
DN_SentinelDoublyLLInit(list); \ DN_SentinelDoublyLLInit(list); \
} while (0) } while (0)
@@ -286,28 +336,28 @@ template <typename T> struct DN_DSMapResult
#define DN_CppDeclType #define DN_CppDeclType
#endif #endif
#define DN_PArrayResizeFromPool(ptr, size, max, pool, new_max) DN_CArrayResizeFromPool((void **)&(ptr), size, max, sizeof((*ptr)[0]), pool, new_max) #define DN_PArrayResizeFromPool(ptr, ptr_size, ptr_max, pool, new_max) DN_CArrayResizeFromPool((void **)&(ptr), ptr_size, ptr_max, sizeof((ptr)[0]), pool, new_max)
#define DN_PArrayResizeFromArena(ptr, size, max, arena, new_max) DN_CArrayResizeFromArena((void **)&(ptr), size, max, sizeof((*ptr)[0]), arena, new_max) #define DN_PArrayResizeFromArena(ptr, ptr_size, ptr_max, arena, new_max) DN_CArrayResizeFromArena((void **)&(ptr), ptr_size, ptr_max, sizeof((ptr)[0]), arena, 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_PArrayGrowFromPool(ptr, size, ptr_max, pool, new_max) DN_CArrayGrowFromPool((void **)&(ptr), size, ptr_max, sizeof((ptr)[0]), pool, new_max)
#define DN_PArrayGrowFromArena(ptr, size, max, arena, new_max) DN_CArrayGrowFromArena((void **)&(ptr), size, max, sizeof((*ptr)[0]), arena, new_max) #define DN_PArrayGrowFromArena(ptr, size, ptr_max, arena, new_max) DN_CArrayGrowFromArena((void **)&(ptr), size, ptr_max, sizeof((ptr)[0]), arena, new_max)
#define DN_PArrayGrowIfNeededFromPool(ptr, size, max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, max, sizeof((*ptr)[0]), pool, add_count) #define DN_PArrayGrowIfNeededFromPool(ptr, size, ptr_max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, ptr_max, sizeof((*ptr)[0]), pool, add_count)
#define DN_PArrayGrowIfNeededFromArena(ptr, size, max, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(ptr), size, max, sizeof((*ptr)[0]), arena, add_count) #define DN_PArrayGrowIfNeededFromArena(ptr, size, ptr_max, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(ptr), size, ptr_max, sizeof((*ptr)[0]), arena, add_count)
#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_PArrayMakeArray(ptr, ptr_size, max, count, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), count, z_mem)
#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_PArrayMakeArrayZ(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), count, DN_ZMem_Yes)
#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_PArrayMake(ptr, ptr_size, max, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), 1, z_mem)
#define DN_PArrayMakeZ(ptr, size, max) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), 1, DN_ZMem_Yes) #define DN_PArrayMakeZ(ptr, ptr_size, max) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), 1, DN_ZMem_Yes)
#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_PArrayAddArray(ptr, ptr_size, max, items, count, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, 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_PArrayAdd(ptr, ptr_size, max, item, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, add)
#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_PArrayAppendArray(ptr, ptr_size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, 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_PArrayAppend(ptr, ptr_size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Append)
#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_PArrayPrependArray(ptr, ptr_size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, 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_PArrayPrepend(ptr, ptr_size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Prepend)
#define DN_PArrayEraseRange(ptr, size, begin_index, count, erase) DN_CArrayEraseRange(ptr, size, sizeof((ptr)[0]), begin_index, count, erase) #define DN_PArrayEraseRange(ptr, ptr_size, begin_index, count, erase) DN_CArrayEraseRange(ptr, ptr_size, sizeof((ptr)[0]), begin_index, count, erase)
#define DN_PArrayErase(ptr, size, index, erase) DN_CArrayEraseRange(ptr, size, sizeof((ptr)[0]), index, 1, erase) #define DN_PArrayErase(ptr, ptr_size, index, erase) DN_CArrayEraseRange(ptr, ptr_size, sizeof((ptr)[0]), index, 1, erase)
#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_PArrayInsertArray(ptr, ptr_size, max, index, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, ptr_size, max, sizeof((ptr)[0]), index, items, count)
#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_PArrayInsert(ptr, ptr_size, max, index, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, 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_PArrayPopFront(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopFront(ptr, 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_PArrayPopBack(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopBack(ptr, ptr_size, sizeof((ptr)[0]), count)
#define DN_LArrayResizeFromPool(c_array, size, pool, new_max) DN_PArrayResizeFromPool(c_array, size, DN_ArrayCountU(c_array), 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_LArrayResizeFromArena(c_array, size, arena, new_max) DN_PArrayResizeFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max) #define DN_LArrayResizeFromArena(c_array, size, arena, new_max) DN_PArrayResizeFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max)
@@ -315,47 +365,47 @@ template <typename T> struct DN_DSMapResult
#define DN_LArrayGrowFromArena(c_array, size, arena, new_max) DN_PArrayGrowFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max) #define DN_LArrayGrowFromArena(c_array, size, arena, new_max) DN_PArrayGrowFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max)
#define DN_LArrayGrowIfNeededFromPool(c_array, size, pool, add_count) DN_PArrayGrowIfNeededFromPool(c_array, size, DN_ArrayCountU(c_array), 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_LArrayGrowIfNeededFromArena(c_array, size, arena, add_count) DN_PArrayGrowIfNeededFromArena(c_array, size, DN_ArrayCountU(c_array), arena, add_count) #define DN_LArrayGrowIfNeededFromArena(c_array, size, arena, add_count) DN_PArrayGrowIfNeededFromArena(c_array, size, DN_ArrayCountU(c_array), arena, add_count)
#define DN_LArrayMakeArray(c_array, size, count, z_mem) DN_PArrayMakeArray(c_array, size, DN_ArrayCountU(c_array), count, z_mem) #define DN_LArrayMakeArray(c_array, ptr_size, count, z_mem) DN_PArrayMakeArray(c_array, ptr_size, DN_ArrayCountU(c_array), count, z_mem)
#define DN_LArrayMakeArrayZ(c_array, size, count) DN_PArrayMakeArrayZ(c_array, size, DN_ArrayCountU(c_array), count) #define DN_LArrayMakeArrayZ(c_array, ptr_size, count) DN_PArrayMakeArrayZ(c_array, ptr_size, DN_ArrayCountU(c_array), count)
#define DN_LArrayMake(c_array, size, z_mem) DN_PArrayMake(c_array, size, DN_ArrayCountU(c_array), z_mem) #define DN_LArrayMake(c_array, ptr_size, z_mem) DN_PArrayMake(c_array, ptr_size, DN_ArrayCountU(c_array), z_mem)
#define DN_LArrayMakeZ(c_array, size) DN_PArrayMakeZ(c_array, size, DN_ArrayCountU(c_array)) #define DN_LArrayMakeZ(c_array, ptr_size) DN_PArrayMakeZ(c_array, ptr_size, DN_ArrayCountU(c_array))
#define DN_LArrayAddArray(c_array, size, items, count, add) DN_PArrayAddArray(c_array, size, DN_ArrayCountU(c_array), items, count, add) #define DN_LArrayAddArray(c_array, ptr_size, items, count, add) DN_PArrayAddArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count, add)
#define DN_LArrayAdd(c_array, size, item, add) DN_PArrayAdd(c_array, size, DN_ArrayCountU(c_array), item, add) #define DN_LArrayAdd(c_array, ptr_size, item, add) DN_PArrayAdd(c_array, ptr_size, DN_ArrayCountU(c_array), item, add)
#define DN_LArrayAppendArray(c_array, size, items, count) DN_PArrayAppendArray(c_array, size, DN_ArrayCountU(c_array), items, count) #define DN_LArrayAppendArray(c_array, ptr_size, items, count) DN_PArrayAppendArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count)
#define DN_LArrayAppend(c_array, size, item) DN_PArrayAppend(c_array, size, DN_ArrayCountU(c_array), item) #define DN_LArrayAppend(c_array, ptr_size, item) DN_PArrayAppend(c_array, ptr_size, DN_ArrayCountU(c_array), item)
#define DN_LArrayPrependArray(c_array, size, items, count) DN_PArrayPrependArray(c_array, size, DN_ArrayCountU(c_array), items, count) #define DN_LArrayPrependArray(c_array, ptr_size, items, count) DN_PArrayPrependArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count)
#define DN_LArrayPrepend(c_array, size, item) DN_PArrayPrepend(c_array, size, DN_ArrayCountU(c_array), item) #define DN_LArrayPrepend(c_array, ptr_size, item) DN_PArrayPrepend(c_array, ptr_size, DN_ArrayCountU(c_array), item)
#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_LArrayEraseRange(c_array, ptr_size, begin_index, count, erase) DN_PArrayEraseRange(c_array, ptr_size, begin_index, count, erase)
#define DN_LArrayErase(c_array, size, index, erase) DN_PArrayErase(c_array, size, DN_ArrayCountU(c_array), index, erase) #define DN_LArrayErase(c_array, ptr_size, index, erase) DN_PArrayErase(c_array, ptr_size, index, erase)
#define DN_LArrayInsertArray(c_array, size, index, items, count) DN_PArrayInsertArray(c_array, size, DN_ArrayCountU(c_array), index, items, count) #define DN_LArrayInsertArray(c_array, ptr_size, index, items, count) DN_PArrayInsertArray(c_array, ptr_size, DN_ArrayCountU(c_array), index, items, count)
#define DN_LArrayInsert(c_array, size, index, item) DN_PArrayInsert(c_array, size, DN_ArrayCountU(c_array), index, item) #define DN_LArrayInsert(c_array, ptr_size, index, item) DN_PArrayInsert(c_array, ptr_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_LArrayPopFront(c_array, ptr_size, count) DN_PArrayPopFront(c_array, ptr_size, DN_ArrayCountU(c_array), count)
#define DN_LArrayPopBack(c_array, size, count) DN_PArrayPopBack(c_array, size, DN_ArrayCountU(c_array), count) #define DN_LArrayPopBack(c_array, ptr_size, count) DN_PArrayPopBack(c_array, ptr_size, DN_ArrayCountU(c_array), count)
#define DN_IArrayResizeFromPool(array, pool, new_max) DN_CArrayResizeFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max) #define DN_IArrayResizeFromPool(ptr_array, pool, new_max) DN_CArrayResizeFromPool((void **)(&(ptr_array)->data), &(ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, new_max)
#define DN_IArrayResizeFromArena(array, arena, new_max) DN_CArrayResizeFromArena((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), arena, new_max) #define DN_IArrayResizeFromArena(ptr_array, arena, new_max) DN_CArrayResizeFromArena((void **)(&(ptr_array)->data), &(ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, new_max)
#define DN_IArrayGrowFromPool(array, pool, new_max) DN_CArrayGrowFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max) #define DN_IArrayGrowFromPool(ptr_array, pool, new_max) DN_CArrayGrowFromPool((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, new_max)
#define DN_IArrayGrowFromArena(array, arena, new_max) DN_CArrayGrowFromArena((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), arena, new_max) #define DN_IArrayGrowFromArena(ptr_array, arena, new_max) DN_CArrayGrowFromArena((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, new_max)
#define DN_IArrayGrowIfNeededFromPool(array, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, add_count) #define DN_IArrayGrowIfNeededFromPool(ptr_array, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, add_count)
#define DN_IArrayGrowIfNeededFromArena(array, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), arena, add_count) #define DN_IArrayGrowIfNeededFromArena(ptr_array, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, add_count)
#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) #define DN_IArrayMakeArray(ptr_array, count, z_mem) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), count, z_mem)
#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) #define DN_IArrayMakeArrayZ(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), count, DN_ZMem_Yes)
#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) #define DN_IArrayMake(ptr_array, z_mem) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), 1, z_mem)
#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_IArrayMakeZ(ptr_array) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayAddArray(ptr_array, items, count, add) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayAdd(ptr_array, item, add) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayAppendArray(ptr_array, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayAppend(ptr_array, item) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayPrependArray(ptr_array, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayPrepend(ptr_array, item) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayEraseRange(ptr_array, begin_index, count, erase) DN_CArrayEraseRange((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_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_IArrayErase(ptr_array, index, erase) DN_CArrayEraseRange((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_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_IArrayInsertArray(ptr_array, index, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayInsertArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayInsert(ptr_array, index, item, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayInsertArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_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_IArrayPopFront(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayPopFront((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_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) #define DN_IArrayPopBack(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayPopBack((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), count)
#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) #define DN_ISliceAllocArena(slice_ptr, count_, zmem, arena) (DN_CppDeclType(&((slice_ptr)->data[0])))DN_SliceAllocArena((void **)&((slice_ptr)->data), &((slice_ptr)->count), count_, sizeof((slice_ptr)->data[0]), alignof(DN_CppDeclType((slice_ptr)->data[0])), zmem, arena)
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); 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);
@@ -381,6 +431,9 @@ DN_API void DN_RingWrite
DN_API void DN_RingRead (DN_Ring *ring, void *dest, DN_U64 dest_size); DN_API void DN_RingRead (DN_Ring *ring, void *dest, DN_U64 dest_size);
#define DN_RingReadStruct(ring, dest) DN_RingRead((ring), (dest), sizeof(*(dest))) #define DN_RingReadStruct(ring, dest) DN_RingRead((ring), (dest), sizeof(*(dest)))
DN_U32 const DN_DS_MAP_DEFAULT_HASH_SEED = 0x8a1ced49;
DN_U32 const DN_DS_MAP_SENTINEL_SLOT = 0;
template <typename T> DN_DSMap<T> DN_DSMapInit (DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags); template <typename T> DN_DSMap<T> DN_DSMapInit (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_DSMapDeinit (DN_DSMap<T> *map, DN_ZMem z_mem);
template <typename T> bool DN_DSMapIsValid (DN_DSMap<T> const *map); template <typename T> bool DN_DSMapIsValid (DN_DSMap<T> const *map);
@@ -399,8 +452,8 @@ template <typename T> bool DN_DSMapResize (DN_DSMap
template <typename T> bool DN_DSMapErase (DN_DSMap<T> *map, DN_DSMapKey key); template <typename T> bool DN_DSMapErase (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_DSMapEraseKeyU64 (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_DSMapEraseKeyStr8 (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_DSMapKeyBuffer (DN_DSMap<T> const *map, void const *data, DN_USize 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_DSMapKeyBufferAsU64NoHash (DN_DSMap<T> const *map, void const *data, DN_USize size);
template <typename T> DN_DSMapKey DN_DSMapKeyU64 (DN_DSMap<T> const *map, DN_U64 u64); template <typename T> DN_DSMapKey DN_DSMapKeyU64 (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_DSMapKeyStr8 (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_DSMapKeyCStr8(map, string) DN_DSMapKeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1)
+1
View File
@@ -29,6 +29,7 @@ struct DN_LeakTracker
{ {
DN_DSMap<DN_LeakAlloc> alloc_table; DN_DSMap<DN_LeakAlloc> alloc_table;
DN_TicketMutex alloc_table_mutex; DN_TicketMutex alloc_table_mutex;
DN_MemList alloc_table_mem;
DN_Arena alloc_table_arena; DN_Arena alloc_table_arena;
DN_U64 alloc_table_bytes_allocated_for_stack_traces; DN_U64 alloc_table_bytes_allocated_for_stack_traces;
}; };
+1 -1
View File
@@ -63,7 +63,7 @@ DN_API void DN_ASYNC_Deinit(DN_ASYNCCore *async)
DN_AtomicSetValue32(&async->join_threads, true); DN_AtomicSetValue32(&async->join_threads, true);
DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count); DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count);
for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count)) for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count))
DN_OS_ThreadJoin(it.data); DN_OS_ThreadJoin(it.data, DN_TCDeinitArenas_Yes);
} }
static bool DN_ASYNC_QueueTask_(DN_ASYNCCore *async, DN_ASYNCTask const *task, DN_U64 wait_time_ms) { static bool DN_ASYNC_QueueTask_(DN_ASYNCCore *async, DN_ASYNCTask const *task, DN_U64 wait_time_ms) {
+5 -5
View File
@@ -128,8 +128,8 @@ DN_API void DN_BinPackStr8FromArena(DN_BinPack *pack, DN_Arena *arena, DN_BinPac
if (mode == DN_BinPackMode_Serialise) { if (mode == DN_BinPackMode_Serialise) {
DN_Str8BuilderAppendBytesCopy(&pack->writer, string->data, string->size); DN_Str8BuilderAppendBytesCopy(&pack->writer, string->data, string->size);
} else { } else {
DN_Str8 src = DN_Str8Slice(pack->read, pack->read_index, string->size); DN_Str8 src = DN_Str8Subset(pack->read, pack->read_index, string->size);
*string = DN_Str8FromStr8Arena(arena, src); *string = DN_Str8FromStr8Arena(src, arena);
pack->read_index += src.size; pack->read_index += src.size;
} }
} }
@@ -140,8 +140,8 @@ DN_API void DN_BinPackStr8FromPool(DN_BinPack *pack, DN_Pool *pool, DN_BinPackMo
if (mode == DN_BinPackMode_Serialise) { if (mode == DN_BinPackMode_Serialise) {
DN_Str8BuilderAppendBytesCopy(&pack->writer, string->data, string->size); DN_Str8BuilderAppendBytesCopy(&pack->writer, string->data, string->size);
} else { } else {
DN_Str8 src = DN_Str8Slice(pack->read, pack->read_index, string->size); DN_Str8 src = DN_Str8Subset(pack->read, pack->read_index, string->size);
*string = DN_Str8FromStr8Pool(pool, src); *string = DN_Str8FromStr8Pool(src, pool);
pack->read_index += src.size; pack->read_index += src.size;
} }
} }
@@ -175,7 +175,7 @@ DN_API void DN_BinPackCArray(DN_BinPack *pack, DN_BinPackMode mode, void *ptr, D
if (mode == DN_BinPackMode_Serialise) { if (mode == DN_BinPackMode_Serialise) {
DN_Str8BuilderAppendBytesCopy(&pack->writer, ptr, size); DN_Str8BuilderAppendBytesCopy(&pack->writer, ptr, size);
} else { } else {
DN_Str8 src = DN_Str8Slice(pack->read, pack->read_index, size); DN_Str8 src = DN_Str8Subset(pack->read, pack->read_index, size);
DN_Assert(src.size == size); DN_Assert(src.size == size);
DN_Memcpy(ptr, src.data, DN_Min(src.size, size)); DN_Memcpy(ptr, src.data, DN_Min(src.size, size));
pack->read_index += src.size; pack->read_index += src.size;
+34 -36
View File
@@ -1,10 +1,8 @@
#define DN_CSV_CPP #define DN_CSV_CPP
#if defined(_CLANGD)
#include "dn_csv.h" #include "dn_csv.h"
#endif
static DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter) DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter)
{ {
DN_CSVTokeniser result = {}; DN_CSVTokeniser result = {};
result.string = string; result.string = string;
@@ -12,13 +10,21 @@ static DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter)
return result; return result;
} }
static bool DN_CSV_TokeniserValid(DN_CSVTokeniser *tokeniser) bool DN_CSV_TokeniserValid(DN_CSVTokeniser *tokeniser)
{ {
bool result = tokeniser && !tokeniser->bad; bool result = tokeniser && !tokeniser->bad;
return result; return result;
} }
static bool DN_CSV_TokeniserNextRow(DN_CSVTokeniser *tokeniser) static void DN_CSV_TokeniserEatNewLines_(DN_CSVTokeniser *tokeniser)
{
char const *end = tokeniser->string.data + tokeniser->string.size;
while (tokeniser->it[0] == '\n' || tokeniser->it[0] == '\r')
if (++tokeniser->it == end)
break;
}
bool DN_CSV_TokeniserNextRow(DN_CSVTokeniser *tokeniser)
{ {
bool result = false; bool result = false;
if (DN_CSV_TokeniserValid(tokeniser) && tokeniser->string.size) { if (DN_CSV_TokeniserValid(tokeniser) && tokeniser->string.size) {
@@ -37,7 +43,7 @@ static bool DN_CSV_TokeniserNextRow(DN_CSVTokeniser *tokeniser)
return result; return result;
} }
static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser) DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
{ {
DN_Str8 result = {}; DN_Str8 result = {};
if (!DN_CSV_TokeniserValid(tokeniser)) if (!DN_CSV_TokeniserValid(tokeniser))
@@ -52,10 +58,7 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
char const *string_end = tokeniser->string.data + tokeniser->string.size; char const *string_end = tokeniser->string.data + tokeniser->string.size;
if (!tokeniser->it) { if (!tokeniser->it) {
tokeniser->it = tokeniser->string.data; tokeniser->it = tokeniser->string.data;
// NOTE: Skip any leading new lines DN_CSV_TokeniserEatNewLines_(tokeniser); // NOTE: Skip any leading new lines
while (tokeniser->it[0] == '\n' || tokeniser->it[0] == '\r')
if (++tokeniser->it == string_end)
break;
} }
// NOTE: Tokeniser pointing at end, no more valid data to parse. // NOTE: Tokeniser pointing at end, no more valid data to parse.
@@ -106,8 +109,7 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
// NOTE: Quoted fields may have whitespace after the closing quote, we skip // NOTE: Quoted fields may have whitespace after the closing quote, we skip
// until we reach the field terminator. // until we reach the field terminator.
if (quoted_field) if (quoted_field)
while (tokeniser->it != string_end && (tokeniser->it[0] != tokeniser->delimiter && while (tokeniser->it != string_end && (tokeniser->it[0] != tokeniser->delimiter && tokeniser->it[0] != '\n'))
tokeniser->it[0] != '\n'))
tokeniser->it++; tokeniser->it++;
// NOTE: Advance the tokeniser past the field terminator. // NOTE: Advance the tokeniser past the field terminator.
@@ -120,7 +122,7 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
return result; return result;
} }
static DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser) DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser)
{ {
DN_Str8 result = {}; DN_Str8 result = {};
if (!DN_CSV_TokeniserValid(tokeniser)) if (!DN_CSV_TokeniserValid(tokeniser))
@@ -135,14 +137,14 @@ static DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser)
return result; return result;
} }
static void DN_CSV_TokeniserSkipLine(DN_CSVTokeniser *tokeniser) void DN_CSV_TokeniserSkipLine(DN_CSVTokeniser *tokeniser)
{ {
while (DN_CSV_TokeniserValid(tokeniser) && !tokeniser->end_of_line) while (DN_CSV_TokeniserValid(tokeniser) && !tokeniser->end_of_line)
DN_CSV_TokeniserNextColumn(tokeniser); DN_CSV_TokeniserNextColumn(tokeniser);
DN_CSV_TokeniserNextRow(tokeniser); DN_CSV_TokeniserNextRow(tokeniser);
} }
static int DN_CSV_TokeniserNextN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size, bool column_iterator) int DN_CSV_TokeniserNextN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size, bool column_iterator)
{ {
if (!DN_CSV_TokeniserValid(tokeniser) || !fields || fields_size <= 0) if (!DN_CSV_TokeniserValid(tokeniser) || !fields || fields_size <= 0)
return 0; return 0;
@@ -150,34 +152,32 @@ static int DN_CSV_TokeniserNextN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, in
int result = 0; int result = 0;
for (; result < fields_size; result++) { for (; result < fields_size; result++) {
fields[result] = column_iterator ? DN_CSV_TokeniserNextColumn(tokeniser) : DN_CSV_TokeniserNextField(tokeniser); fields[result] = column_iterator ? DN_CSV_TokeniserNextColumn(tokeniser) : DN_CSV_TokeniserNextField(tokeniser);
if (!DN_CSV_TokeniserValid(tokeniser) || fields[result].size == 0) if (!DN_CSV_TokeniserValid(tokeniser) || !fields[result].data)
break; break;
} }
return result; return result;
} }
DN_MSVC_WARNING_PUSH int DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size)
DN_MSVC_WARNING_DISABLE(4505) // 'x': unreferenced function with internal linkage has been removed
static int DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size)
{ {
int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, true /*column_iterator*/); int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, true /*column_iterator*/);
return result; return result;
} }
static int DN_CSV_TokeniserNextFieldN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size) int DN_CSV_TokeniserNextFieldN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size)
{ {
int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, false /*column_iterator*/); int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, false /*column_iterator*/);
return result; return result;
} }
static void DN_CSV_TokeniserSkipLineN(DN_CSVTokeniser *tokeniser, int count) void DN_CSV_TokeniserSkipLineN(DN_CSVTokeniser *tokeniser, int count)
{ {
for (int i = 0; i < count && DN_CSV_TokeniserValid(tokeniser); i++) for (int i = 0; i < count && DN_CSV_TokeniserValid(tokeniser); i++)
DN_CSV_TokeniserSkipLine(tokeniser); DN_CSV_TokeniserSkipLine(tokeniser);
} }
static void DN_CSV_PackU64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *value) void DN_CSV_PackU64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *value)
{ {
if (serialise == DN_CSVSerialise_Read) { if (serialise == DN_CSVSerialise_Read) {
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser); DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
@@ -189,7 +189,7 @@ static void DN_CSV_PackU64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *
} }
} }
static void DN_CSV_PackI64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *value) void DN_CSV_PackI64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *value)
{ {
if (serialise == DN_CSVSerialise_Read) { if (serialise == DN_CSVSerialise_Read) {
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser); DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
@@ -201,7 +201,7 @@ static void DN_CSV_PackI64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *
} }
} }
static void DN_CSV_PackI32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *value) void DN_CSV_PackI32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *value)
{ {
DN_I64 u64 = *value; DN_I64 u64 = *value;
DN_CSV_PackI64(pack, serialise, &u64); DN_CSV_PackI64(pack, serialise, &u64);
@@ -209,7 +209,7 @@ static void DN_CSV_PackI32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *
*value = DN_SaturateCastI64ToI32(u64); *value = DN_SaturateCastI64ToI32(u64);
} }
static void DN_CSV_PackI16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *value) void DN_CSV_PackI16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *value)
{ {
DN_I64 u64 = *value; DN_I64 u64 = *value;
DN_CSV_PackI64(pack, serialise, &u64); DN_CSV_PackI64(pack, serialise, &u64);
@@ -217,7 +217,7 @@ static void DN_CSV_PackI16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *
*value = DN_SaturateCastI64ToI16(u64); *value = DN_SaturateCastI64ToI16(u64);
} }
static void DN_CSV_PackI8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *value) void DN_CSV_PackI8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *value)
{ {
DN_I64 u64 = *value; DN_I64 u64 = *value;
DN_CSV_PackI64(pack, serialise, &u64); DN_CSV_PackI64(pack, serialise, &u64);
@@ -225,8 +225,7 @@ static void DN_CSV_PackI8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *va
*value = DN_SaturateCastI64ToI8(u64); *value = DN_SaturateCastI64ToI8(u64);
} }
void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value)
static void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value)
{ {
DN_U64 u64 = *value; DN_U64 u64 = *value;
DN_CSV_PackU64(pack, serialise, &u64); DN_CSV_PackU64(pack, serialise, &u64);
@@ -234,7 +233,7 @@ static void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *
*value = DN_SaturateCastU64ToU32(u64); *value = DN_SaturateCastU64ToU32(u64);
} }
static void DN_CSV_PackU16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *value) void DN_CSV_PackU16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *value)
{ {
DN_U64 u64 = *value; DN_U64 u64 = *value;
DN_CSV_PackU64(pack, serialise, &u64); DN_CSV_PackU64(pack, serialise, &u64);
@@ -242,7 +241,7 @@ static void DN_CSV_PackU16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *
*value = DN_SaturateCastU64ToU16(u64); *value = DN_SaturateCastU64ToU16(u64);
} }
static void DN_CSV_PackBoolAsU64(DN_CSVPack *pack, DN_CSVSerialise serialise, bool *value) void DN_CSV_PackBoolAsU64(DN_CSVPack *pack, DN_CSVSerialise serialise, bool *value)
{ {
DN_U64 u64 = *value; DN_U64 u64 = *value;
DN_CSV_PackU64(pack, serialise, &u64); DN_CSV_PackU64(pack, serialise, &u64);
@@ -250,17 +249,17 @@ static void DN_CSV_PackBoolAsU64(DN_CSVPack *pack, DN_CSVSerialise serialise, bo
*value = u64 ? 1 : 0; *value = u64 ? 1 : 0;
} }
static void DN_CSV_PackStr8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_Str8 *str8, DN_Arena *arena) void DN_CSV_PackStr8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_Str8 *str8, DN_Arena *arena)
{ {
if (serialise == DN_CSVSerialise_Read) { if (serialise == DN_CSVSerialise_Read) {
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser); DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
*str8 = DN_Str8FromStr8Arena(arena, csv_value); *str8 = DN_Str8FromStr8Arena(csv_value, arena);
} else { } else {
DN_Str8BuilderAppendF(&pack->write_builder, "%s%.*s", pack->write_column++ ? "," : "", DN_Str8PrintFmt(*str8)); DN_Str8BuilderAppendF(&pack->write_builder, "%s%.*s", pack->write_column++ ? "," : "", DN_Str8PrintFmt(*str8));
} }
} }
static void DN_CSV_PackBuffer(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size) void DN_CSV_PackBuffer(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size)
{ {
if (serialise == DN_CSVSerialise_Read) { if (serialise == DN_CSVSerialise_Read) {
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser); DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
@@ -271,14 +270,14 @@ static void DN_CSV_PackBuffer(DN_CSVPack *pack, DN_CSVSerialise serialise, void
} }
} }
static void DN_CSV_PackBufferWithMax(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size, size_t max) void DN_CSV_PackBufferWithMax(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size, size_t max)
{ {
if (serialise == DN_CSVSerialise_Read) if (serialise == DN_CSVSerialise_Read)
*size = max; *size = max;
DN_CSV_PackBuffer(pack, serialise, dest, size); DN_CSV_PackBuffer(pack, serialise, dest, size);
} }
static bool DN_CSV_PackNewLine(DN_CSVPack *pack, DN_CSVSerialise serialise) bool DN_CSV_PackNewLine(DN_CSVPack *pack, DN_CSVSerialise serialise)
{ {
bool result = true; bool result = true;
if (serialise == DN_CSVSerialise_Read) { if (serialise == DN_CSVSerialise_Read) {
@@ -289,4 +288,3 @@ static bool DN_CSV_PackNewLine(DN_CSVPack *pack, DN_CSVSerialise serialise)
} }
return result; return result;
} }
DN_MSVC_WARNING_POP
+32
View File
@@ -1,6 +1,15 @@
#if !defined(DN_CSV_H) #if !defined(DN_CSV_H)
#define DN_CSV_H #define DN_CSV_H
// NOTE: Data structures to create and parse CSV files, supports Python style escaped quotes (e.g.
// Using "" to escape quotes inside a quoted string).
//
// API
// DN_CSV_TokeniserNextN: Reads the next N consecutive fields from the parser. If `column_iterator`
// is `false` then the read of the N consecutive fields does not proceed past the end of the
// current CSV row. If `true` then it reads the next N fields even if reading would progress onto
// the next row.
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn.h" #include "../dn.h"
#endif #endif
@@ -27,4 +36,27 @@ struct DN_CSVPack
DN_CSVTokeniser read_tokeniser; DN_CSVTokeniser read_tokeniser;
}; };
DN_CSVTokeniser DN_CSV_TokeniserInit (DN_Str8 string, char delimiter);
bool DN_CSV_TokeniserValid (DN_CSVTokeniser *tokeniser);
bool DN_CSV_TokeniserNextRow (DN_CSVTokeniser *tokeniser);
DN_Str8 DN_CSV_TokeniserNextField (DN_CSVTokeniser *tokeniser);
DN_Str8 DN_CSV_TokeniserNextColumn (DN_CSVTokeniser *tokeniser);
void DN_CSV_TokeniserSkipLine (DN_CSVTokeniser *tokeniser);
int DN_CSV_TokeniserNextN (DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size, bool column_iterator);
int DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size);
int DN_CSV_TokeniserNextFieldN (DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size);
void DN_CSV_TokeniserSkipLineN (DN_CSVTokeniser *tokeniser, int count);
void DN_CSV_PackU64 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *value);
void DN_CSV_PackI64 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *value);
void DN_CSV_PackI32 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *value);
void DN_CSV_PackI16 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *value);
void DN_CSV_PackI8 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *value);
void DN_CSV_PackU32 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value);
void DN_CSV_PackU16 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *value);
void DN_CSV_PackBoolAsU64 (DN_CSVPack *pack, DN_CSVSerialise serialise, bool *value);
void DN_CSV_PackStr8 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_Str8 *str8, DN_Arena *arena);
void DN_CSV_PackBuffer (DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size);
void DN_CSV_PackBufferWithMax (DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size, size_t max);
bool DN_CSV_PackNewLine (DN_CSVPack *pack, DN_CSVSerialise serialise);
#endif // !defined(DN_CSV_H) #endif // !defined(DN_CSV_H)
+1 -1
View File
@@ -72,7 +72,7 @@ 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_TCScratch scratch = DN_TCScratchBegin(&builder->string_builder.arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&builder->string_builder.arena, 1);
DN_Str8 value = DN_Str8FromFmtVArena(scratch.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_TCScratchEnd(&scratch);
} }
-1
View File
@@ -41,7 +41,6 @@ struct DN_JSONBuilder
}; };
#endif // !defined(DN_NO_JSON_BUIDLER) #endif // !defined(DN_NO_JSON_BUIDLER)
// NOTE: DN_BinarySearch ///////////////////////////////////////////////////////////////////////////
template <typename T> template <typename T>
using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs); using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
+15 -11
View File
@@ -1,6 +1,8 @@
#define DN_NET_CURL_CPP #define DN_NET_CURL_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#define DN_H_WITH_OS 1
#include "../dn.h"
#include "dn_net.h" #include "dn_net.h"
#endif #endif
@@ -43,7 +45,7 @@ DN_NETRequestHandle DN_NET_HandleFromRequest(DN_NETRequest *request)
void DN_NET_EndFinishedRequest_(DN_NETRequest *request) void DN_NET_EndFinishedRequest_(DN_NETRequest *request)
{ {
// NOTE: Deallocate the memory used in the request and reset the string builder // NOTE: Deallocate the memory used in the request and reset the string builder
DN_ArenaPopTo(&request->arena, request->start_response_arena_pos); DN_ArenaTempEnd(&request->start_response_arena, DN_ArenaReset_Yes);
// NOTE: Check that the request is completely detached // NOTE: Check that the request is completely detached
DN_Assert(request->next == nullptr); DN_Assert(request->next == nullptr);
} }
@@ -52,7 +54,8 @@ void DN_NET_BaseInit_(DN_NETCore *net, char *base, DN_U64 base_size)
{ {
net->base = base; net->base = base;
net->base_size = base_size; net->base_size = base_size;
net->arena = DN_ArenaFromBuffer(net->base, net->base_size, DN_ArenaFlags_Nil); net->mem = DN_MemListFromBuffer(net->base, net->base_size, DN_MemFlags_Nil);
net->arena = DN_ArenaFromMemList(&net->mem);
net->completion_sem = DN_OS_SemaphoreInit(0); net->completion_sem = DN_OS_SemaphoreInit(0);
} }
@@ -61,31 +64,32 @@ DN_NETRequestHandle DN_NET_SetupRequest_(DN_NETRequest *request, DN_Str8 url, DN
// NOTE: Setup request // NOTE: Setup request
DN_Assert(request); DN_Assert(request);
if (request) { if (request) {
if (!request->arena.curr) if (!request->mem.curr)
request->arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(1), DN_ArenaFlags_Nil); request->mem = DN_MemListFromVMem(DN_Megabytes(1), DN_Kilobytes(1), DN_MemFlags_Nil);
request->arena = DN_ArenaTempBeginFromMemList(&request->mem);
request->type = type; request->type = type;
request->gen = DN_Max(request->gen + 1, 1); request->gen = DN_Max(request->gen + 1, 1);
request->url = DN_Str8FromStr8Arena(&request->arena, url); request->url = DN_Str8FromStr8Arena(url, &request->arena);
request->method = DN_Str8FromStr8Arena(&request->arena, DN_Str8TrimWhitespaceAround(method)); request->method = DN_Str8FromStr8Arena(DN_Str8TrimWhitespaceAround(method), &request->arena);
if (args) { if (args) {
request->args.flags = args->flags; request->args.flags = args->flags;
request->args.username = DN_Str8FromStr8Arena(&request->arena, args->username); request->args.username = DN_Str8FromStr8Arena(args->username, &request->arena);
request->args.password = DN_Str8FromStr8Arena(&request->arena, args->password); request->args.password = DN_Str8FromStr8Arena(args->password, &request->arena);
if (type == DN_NETRequestType_HTTP) if (type == DN_NETRequestType_HTTP)
request->args.payload = DN_Str8FromStr8Arena(&request->arena, args->payload); request->args.payload = DN_Str8FromStr8Arena(args->payload, &request->arena);
request->args.headers = DN_ArenaNewArray(&request->arena, DN_Str8, args->headers_size, DN_ZMem_No); request->args.headers = DN_ArenaNewArray(&request->arena, DN_Str8, args->headers_size, DN_ZMem_No);
DN_Assert(request->args.headers); DN_Assert(request->args.headers);
if (request->args.headers) { if (request->args.headers) {
for (DN_ForItSize(it, DN_Str8, args->headers, args->headers_size)) for (DN_ForItSize(it, DN_Str8, args->headers, args->headers_size))
request->args.headers[it.index] = DN_Str8FromStr8Arena(&request->arena, *it.data); request->args.headers[it.index] = DN_Str8FromStr8Arena(*it.data, &request->arena);
request->args.headers_size = args->headers_size; request->args.headers_size = args->headers_size;
} }
} }
request->completion_sem = DN_OS_SemaphoreInit(0); request->completion_sem = DN_OS_SemaphoreInit(0);
request->start_response_arena_pos = DN_ArenaPos(&request->arena); request->start_response_arena = DN_ArenaTempBeginFromArena(&request->arena);
} }
DN_NETRequestHandle result = DN_NET_HandleFromRequest(request); DN_NETRequestHandle result = DN_NET_HandleFromRequest(request);
+20 -17
View File
@@ -2,8 +2,8 @@
#define DN_NET_H #define DN_NET_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_NETRequestType enum DN_NETRequestType
@@ -74,8 +74,9 @@ struct DN_NETResponse
struct DN_NETRequest struct DN_NETRequest
{ {
DN_MemList mem;
DN_Arena arena; DN_Arena arena;
DN_USize start_response_arena_pos; DN_Arena start_response_arena;
DN_NETRequestType type; DN_NETRequestType type;
DN_U64 gen; DN_U64 gen;
DN_Str8 url; DN_Str8 url;
@@ -88,22 +89,13 @@ struct DN_NETRequest
DN_U64 context[2]; DN_U64 context[2];
}; };
struct DN_NETCore typedef void (DN_NETInitFunc) (struct DN_NETCore *net, char *base, DN_U64 base_size);
{ typedef void (DN_NETDeinitFunc) (struct DN_NETCore *net);
char *base; typedef DN_NETRequestHandle(DN_NETDoHTTPFunc) (struct DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args);
DN_U64 base_size; typedef DN_NETRequestHandle(DN_NETDoWSFunc) (struct DN_NETCore *net, DN_Str8 url);
DN_Arena arena;
DN_OSSemaphore completion_sem;
void *context;
};
typedef void (DN_NETInitFunc) (DN_NETCore *net, char *base, DN_U64 base_size);
typedef void (DN_NETDeinitFunc) (DN_NETCore *net);
typedef DN_NETRequestHandle(DN_NETDoHTTPFunc) (DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args);
typedef DN_NETRequestHandle(DN_NETDoWSFunc) (DN_NETCore *net, DN_Str8 url);
typedef void (DN_NETDoWSSendFunc) (DN_NETRequestHandle handle, DN_Str8 data, DN_NETWSSend send); typedef void (DN_NETDoWSSendFunc) (DN_NETRequestHandle handle, DN_Str8 data, DN_NETWSSend send);
typedef DN_NETResponse (DN_NETWaitForResponseFunc) (DN_NETRequestHandle handle, DN_Arena *arena, DN_U32 timeout_ms); typedef DN_NETResponse (DN_NETWaitForResponseFunc) (DN_NETRequestHandle handle, DN_Arena *arena, DN_U32 timeout_ms);
typedef DN_NETResponse (DN_NETWaitForAnyResponseFunc)(DN_NETCore *net, DN_Arena *arena, DN_U32 timeout_ms); typedef DN_NETResponse (DN_NETWaitForAnyResponseFunc)(struct DN_NETCore *net, DN_Arena *arena, DN_U32 timeout_ms);
struct DN_NETInterface struct DN_NETInterface
{ {
@@ -116,6 +108,17 @@ struct DN_NETInterface
DN_NETWaitForAnyResponseFunc* wait_for_any_response; DN_NETWaitForAnyResponseFunc* wait_for_any_response;
}; };
struct DN_NETCore
{
char *base;
DN_U64 base_size;
DN_MemList mem;
DN_Arena arena;
DN_OSSemaphore completion_sem;
void *context;
DN_NETInterface api;
};
DN_Str8 DN_NET_Str8FromResponseState(DN_NETResponseState state); DN_Str8 DN_NET_Str8FromResponseState(DN_NETResponseState state);
DN_NETRequest * DN_NET_RequestFromHandle (DN_NETRequestHandle handle); DN_NETRequest * DN_NET_RequestFromHandle (DN_NETRequestHandle handle);
DN_NETRequestHandle DN_NET_HandleFromRequest (DN_NETRequest *request); DN_NETRequestHandle DN_NET_HandleFromRequest (DN_NETRequest *request);
+11 -10
View File
@@ -129,7 +129,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_Str8 payload = {}; DN_Str8 payload = {};
for (DN_OS_MutexScope(&curl->ring_mutex)) { for (DN_OS_MutexScope(&curl->ring_mutex)) {
DN_Assert(DN_RingHasData(&curl->ring, event.ws_send_size)); DN_Assert(DN_RingHasData(&curl->ring, event.ws_send_size));
payload = DN_Str8AllocArena(tmem.arena, event.ws_send_size, DN_ZMem_No); payload = DN_Str8AllocArena(event.ws_send_size, DN_ZMem_No, &tmem.arena);
DN_RingRead(&curl->ring, payload.data, payload.size); DN_RingRead(&curl->ring, payload.data, payload.size);
} }
@@ -168,7 +168,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_NETRequest *request = DN_Cast(DN_NETRequest *) event.request.handle; DN_NETRequest *request = DN_Cast(DN_NETRequest *) event.request.handle;
// NOTE: Release resources // NOTE: Release resources
DN_ArenaClear(&request->arena); DN_ArenaTempEnd(&request->arena, DN_ArenaReset_Yes);
DN_OS_SemaphoreDeinit(&request->completion_sem); DN_OS_SemaphoreDeinit(&request->completion_sem);
curl_multi_remove_handle(curl->thread_curlm, curl_req->handle); curl_multi_remove_handle(curl->thread_curlm, curl_req->handle);
@@ -302,7 +302,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
// NOTE: Allocate and read (we use meta->bytesleft as per comment from initial recv) // NOTE: Allocate and read (we use meta->bytesleft as per comment from initial recv)
if (meta->bytesleft) { if (meta->bytesleft) {
DN_Str8 buffer = DN_Str8AllocArena(&req->arena, meta->bytesleft, DN_ZMem_No); DN_Str8 buffer = DN_Str8AllocArena(meta->bytesleft, DN_ZMem_No, &req->arena);
DN_Assert(buffer.size == DN_Cast(DN_USize)meta->bytesleft); DN_Assert(buffer.size == DN_Cast(DN_USize)meta->bytesleft);
receive_result = curl_ws_recv(curl_req->handle, buffer.data, buffer.size, &buffer.size, &meta); receive_result = curl_ws_recv(curl_req->handle, buffer.data, buffer.size, &buffer.size, &meta);
DN_Assert(buffer.size == DN_Cast(DN_USize)meta->len); DN_Assert(buffer.size == DN_Cast(DN_USize)meta->len);
@@ -396,8 +396,9 @@ void DN_NET_CurlInit(DN_NETCore *net, char *base, DN_U64 base_size)
DN_NET_BaseInit_(net, base, base_size); DN_NET_BaseInit_(net, base, base_size);
DN_NETCurlCore *curl = DN_ArenaNew(&net->arena, DN_NETCurlCore, DN_ZMem_Yes); DN_NETCurlCore *curl = DN_ArenaNew(&net->arena, DN_NETCurlCore, DN_ZMem_Yes);
net->context = curl; net->context = curl;
net->api = DN_NET_CurlInterface();
DN_USize arena_bytes_avail = (net->arena.curr->reserve - net->arena.curr->used); DN_USize arena_bytes_avail = (net->arena.mem->curr->reserve - net->arena.mem->curr->used);
curl->ring.size = arena_bytes_avail / 2; curl->ring.size = arena_bytes_avail / 2;
curl->ring.base = DN_Cast(char *) DN_ArenaAlloc(&net->arena, curl->ring.size, /*align*/ 1, DN_ZMem_Yes); curl->ring.base = DN_Cast(char *) DN_ArenaAlloc(&net->arena, curl->ring.size, /*align*/ 1, DN_ZMem_Yes);
DN_Assert(curl->ring.base); DN_Assert(curl->ring.base);
@@ -415,7 +416,7 @@ void DN_NET_CurlDeinit(DN_NETCore *net)
DN_NETCurlCore *curl = DN_Cast(DN_NETCurlCore *) net->context; DN_NETCurlCore *curl = DN_Cast(DN_NETCurlCore *) net->context;
curl->kill_thread = true; curl->kill_thread = true;
curl_multi_wakeup(curl->thread_curlm); curl_multi_wakeup(curl->thread_curlm);
DN_OS_ThreadJoin(&curl->thread); DN_OS_ThreadJoin(&curl->thread, DN_TCDeinitArenas_Yes);
} }
static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type) static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type)
@@ -434,11 +435,11 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D
// NOTE None in the free list so allocate one // NOTE None in the free list so allocate one
if (!req) { if (!req) {
DN_U64 arena_pos = DN_ArenaPos(&net->arena); DN_U64 arena_pos = DN_MemListPos(net->arena.mem);
req = DN_ArenaNew(&net->arena, DN_NETRequest, DN_ZMem_Yes); req = DN_ArenaNew(&net->arena, DN_NETRequest, DN_ZMem_Yes);
DN_NETCurlRequest *curl_req = DN_ArenaNew(&net->arena, DN_NETCurlRequest, DN_ZMem_Yes); DN_NETCurlRequest *curl_req = DN_ArenaNew(&net->arena, DN_NETCurlRequest, DN_ZMem_Yes);
if (!req || !curl_req) { if (!req || !curl_req) {
DN_ArenaPopTo(&net->arena, arena_pos); DN_MemListPopTo(net->arena.mem, arena_pos);
return result; return result;
} }
@@ -453,7 +454,7 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D
result = DN_NET_SetupRequest_(req, url, method, args, type); result = DN_NET_SetupRequest_(req, url, method, args, type);
req->response.request = result; req->response.request = result;
req->context[1] = DN_Cast(DN_UPtr) net; req->context[1] = DN_Cast(DN_UPtr) net;
curl_req->str8_builder = DN_Str8BuilderFromArena(&req->arena); curl_req->str8_builder = DN_Str8BuilderFromArena(&req->start_response_arena);
} }
// NOTE: Setup the request for curl API // NOTE: Setup the request for curl API
@@ -587,8 +588,8 @@ static DN_NETResponse DN_NET_CurlHandleFinishedRequest_(DN_NETCurlCore *curl, DN
DN_NETCurlRequest *curl_req = DN_NET_CurlRequestFromRequest_(req); DN_NETCurlRequest *curl_req = DN_NET_CurlRequestFromRequest_(req);
result.body = DN_Str8BuilderBuild(&curl_req->str8_builder, arena); result.body = DN_Str8BuilderBuild(&curl_req->str8_builder, arena);
if (result.error_str8.size) if (result.error_str8.size)
result.error_str8 = DN_Str8FromStr8Arena(arena, result.error_str8); result.error_str8 = DN_Str8FromStr8Arena(result.error_str8, arena);
curl_req->str8_builder = DN_Str8BuilderFromArena(&req->arena); curl_req->str8_builder = {}; // Clear it out, reinitialised on subsequent do request call
} }
DN_NET_EndFinishedRequest_(req); DN_NET_EndFinishedRequest_(req);
+348 -227
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -2,6 +2,8 @@
#define DN_NO_WINDOWS_H_REPLACEMENT_HEADER #define DN_NO_WINDOWS_H_REPLACEMENT_HEADER
#endif #endif
#define DN_ARENA_TEMP_MEM_UAF_GUARD 1
#define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 0
#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_HASH 1 #define DN_H_WITH_HASH 1
@@ -35,7 +37,7 @@ int main(int, char**)
{ {
DN_Core dn = {}; DN_Core dn = {};
DN_Init(&dn, DN_InitFlags_LogAllFeatures | DN_InitFlags_OS | DN_InitFlags_ThreadContext, nullptr); DN_Init(&dn, DN_InitFlags_LogAllFeatures | DN_InitFlags_OS | DN_InitFlags_ThreadContext, nullptr);
DN_Tests_RunSuite(DN_TestsPrint_Yes); DN_TST_RunSuite(DN_TSTPrint_Yes);
return 0; return 0;
} }
DN_MSVC_WARNING_POP DN_MSVC_WARNING_POP
+113 -76
View File
@@ -11,61 +11,59 @@
#include <unistd.h> // getpagesize #include <unistd.h> // getpagesize
#endif #endif
static void *DN_ArenaBasicAllocFromOSHeap(DN_USize size) static void *DN_OS_MemFuncsHeapAllocShim_(DN_USize size)
{ {
void *result = DN_OS_MemAlloc(size, DN_ZMem_Yes); void *result = DN_OS_MemAlloc(size, DN_ZMem_Yes);
return result; return result;
} }
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet(DN_ArenaMemFuncType type) DN_API DN_MemFuncs DN_MemFuncsFromType(DN_MemFuncsType type)
{ {
DN_ArenaMemFuncs result = {}; DN_MemFuncs result = {};
result.type = type; result.type = type;
switch (type) { switch (type) {
case DN_ArenaMemFuncType_Nil: break; case DN_MemFuncsType_Nil: break;
case DN_ArenaMemFuncType_Basic: { case DN_MemFuncsType_Heap: {
result.type = DN_ArenaMemFuncType_Basic; result.heap_alloc = DN_OS_MemFuncsHeapAllocShim_;
result.basic_alloc = DN_ArenaBasicAllocFromOSHeap; result.heap_dealloc = DN_OS_MemDealloc;
result.basic_dealloc = DN_OS_MemDealloc;
} break; } break;
case DN_ArenaMemFuncType_VMem: { case DN_MemFuncsType_Virtual: {
DN_Core *dn = DN_Get(); DN_Core *dn = DN_Get();
DN_Assert(dn->init_flags & DN_InitFlags_OS); DN_Assert(dn->init_flags & DN_InitFlags_OS);
result.type = DN_ArenaMemFuncType_VMem; result.virtual_page_size = dn->os.page_size;
result.vmem_page_size = dn->os.page_size; result.virtual_reserve = DN_OS_MemReserve;
result.vmem_reserve = DN_OS_MemReserve; result.virtual_commit = DN_OS_MemCommit;
result.vmem_commit = DN_OS_MemCommit; result.virtual_release = DN_OS_MemRelease;
result.vmem_release = DN_OS_MemRelease;
} break; } break;
} }
return result; return result;
} }
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults() DN_API DN_MemFuncs DN_MemFuncsDefault()
{ {
DN_Core *dn = DN_Get(); DN_Core *dn = DN_Get();
DN_ArenaMemFuncType type = DN_ArenaMemFuncType_Basic; DN_MemFuncsType type = DN_MemFuncsType_Heap;
if (dn->os_init) { if (dn->os_init) {
#if !defined(DN_PLATFORM_EMSCRIPTEN) #if !defined(DN_PLATFORM_EMSCRIPTEN)
type = DN_ArenaMemFuncType_VMem; type = DN_MemFuncsType_Virtual;
#endif #endif
} }
DN_ArenaMemFuncs result = DN_ArenaMemFuncsGet(type); DN_MemFuncs result = DN_MemFuncsFromType(type);
return result; return result;
} }
DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags) DN_API DN_MemList DN_MemListFromHeap(DN_U64 size, DN_MemFlags flags)
{ {
DN_ArenaMemFuncs mem_funcs = DN_ArenaMemFuncsGet(DN_ArenaMemFuncType_Basic); DN_MemFuncs mem_funcs = DN_MemFuncsFromType(DN_MemFuncsType_Heap);
DN_Arena result = DN_ArenaFromMemFuncs(size, size, flags, mem_funcs); DN_MemList result = DN_MemListFromMemFuncs(size, size, flags, mem_funcs);
return result; return result;
} }
DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags) DN_API DN_MemList DN_MemListFromVMem(DN_U64 reserve, DN_U64 commit, DN_MemFlags flags)
{ {
DN_ArenaMemFuncs mem_funcs = DN_ArenaMemFuncsGet(DN_ArenaMemFuncType_VMem); DN_MemFuncs mem_funcs = DN_MemFuncsFromType(DN_MemFuncsType_Virtual);
DN_Arena result = DN_ArenaFromMemFuncs(reserve, commit, flags, mem_funcs); DN_MemList result = DN_MemListFromMemFuncs(reserve, commit, flags, mem_funcs);
return result; return result;
} }
@@ -95,7 +93,7 @@ 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 // TODO: Implement this without requiring TLS so it can go into base strings
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena); DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_Str8BSplitResult split = DN_Str8BSplit(src, DN_Str8Lit("\n")); DN_Str8BSplitResult split = DN_Str8BSplit(src, DN_Str8Lit("\n"));
while (split.lhs.size) { while (split.lhs.size) {
DN_Str8BuilderAppendRef(&builder, pad); DN_Str8BuilderAppendRef(&builder, pad);
@@ -129,7 +127,7 @@ DN_API DN_Str8 DN_Str8BuilderBuildFromHeap(DN_Str8Builder const *builder)
return result; return result;
} }
DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_LogFlags flags, DN_FMT_ATTRIB char const *fmt, va_list args)
{ {
DN_Assert(user_data); DN_Assert(user_data);
DN_OSCore *os = DN_Cast(DN_OSCore *)user_data; DN_OSCore *os = DN_Cast(DN_OSCore *)user_data;
@@ -138,13 +136,17 @@ DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite ca
DN_TicketMutex_Begin(&os->log_file_mutex); DN_TicketMutex_Begin(&os->log_file_mutex);
if (os->log_to_file && !os->log_file.handle && !os->log_file.error) { if (os->log_to_file && !os->log_file.handle && !os->log_file.error) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 exe_dir = DN_OS_EXEDir(scratch.arena); DN_Str8 exe_dir = DN_OS_EXEDir(&scratch.arena);
DN_Str8 log_path = DN_OS_PathF(scratch.arena, "%.*s/dn.log", DN_Str8PrintFmt(exe_dir)); DN_Str8 log_path = DN_OS_PathF(&scratch.arena, "%.*s/dn.log", DN_Str8PrintFmt(exe_dir));
os->log_file = DN_OS_FileOpen(log_path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_AppendOnly, nullptr); os->log_file = DN_OS_FileOpen(log_path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_AppendOnly, nullptr);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
} }
DN_TicketMutex_End(&os->log_file_mutex); DN_TicketMutex_End(&os->log_file_mutex);
bool print_prefix = DN_BitIsNotSet(flags, DN_LogFlags_NoPrefix);
char prefix_buffer[128] = {};
DN_LogPrefixSize prefix_size = {};
if (print_prefix) {
DN_LogStyle style = {}; DN_LogStyle style = {};
if (!os->log_no_colour) { if (!os->log_no_colour) {
style.colour = true; style.colour = true;
@@ -181,26 +183,35 @@ DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite ca
log_date.hour = os_date.hour; log_date.hour = os_date.hour;
log_date.minute = os_date.minutes; log_date.minute = os_date.minutes;
log_date.second = os_date.seconds; log_date.second = os_date.seconds;
prefix_size = DN_LogMakePrefix(style, type, call_site, log_date, prefix_buffer, sizeof(prefix_buffer));
char prefix_buffer[128] = {}; }
DN_LogPrefixSize prefix_size = DN_LogMakePrefix(style, type, call_site, log_date, prefix_buffer, sizeof(prefix_buffer));
va_list args_copy; va_list args_copy;
va_copy(args_copy, args); va_copy(args_copy, args);
DN_TicketMutex_Begin(&os->log_file_mutex); DN_TicketMutex_Begin(&os->log_file_mutex);
{ {
if (print_prefix) {
DN_OS_FileWrite(&os->log_file, DN_Str8FromPtr(prefix_buffer, prefix_size.size), nullptr); DN_OS_FileWrite(&os->log_file, DN_Str8FromPtr(prefix_buffer, prefix_size.size), nullptr);
DN_OS_FileWriteF(&os->log_file, nullptr, "%*s ", DN_Cast(int) prefix_size.padding, ""); DN_OS_FileWriteF(&os->log_file, nullptr, "%*s ", DN_Cast(int) prefix_size.padding, "");
}
DN_OS_FileWriteFV(&os->log_file, nullptr, fmt, args_copy); DN_OS_FileWriteFV(&os->log_file, nullptr, fmt, args_copy);
if (!DN_BitIsSet(flags, DN_LogFlags_NoNewLine))
DN_OS_FileWrite(&os->log_file, DN_Str8Lit("\n"), nullptr); DN_OS_FileWrite(&os->log_file, DN_Str8Lit("\n"), nullptr);
} }
DN_TicketMutex_End(&os->log_file_mutex); DN_TicketMutex_End(&os->log_file_mutex);
va_end(args_copy); va_end(args_copy);
DN_OSPrintDest dest = (type.is_u32_enum && type.u32 == DN_LogType_Error) ? DN_OSPrintDest_Err : DN_OSPrintDest_Out; DN_TicketMutex_Begin(&os->log_mutex);
DN_OS_Print(dest, DN_Str8FromPtr(prefix_buffer, prefix_size.size)); {
DN_OS_PrintF(dest, "%*s ", DN_Cast(int)prefix_size.padding, ""); if (print_prefix)
DN_OS_PrintLnFV(dest, fmt, args); DN_OS_PrintF(DN_OSPrintDest_Err, "%.*s%*s ", DN_Cast(int) prefix_size.size, prefix_buffer, DN_Cast(int) prefix_size.padding, "");
if (DN_BitIsSet(flags, DN_LogFlags_NoNewLine))
DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args);
else
DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args);
}
DN_TicketMutex_End(&os->log_mutex);
} }
DN_API void DN_OS_SetLogPrintFuncToOS() DN_API void DN_OS_SetLogPrintFuncToOS()
@@ -240,10 +251,10 @@ DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena)
if (!arena) if (!arena)
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str8 exe_path = DN_OS_EXEPath(scratch.arena); DN_Str8 exe_path = DN_OS_EXEPath(&scratch.arena);
DN_Str8 separators[] = {DN_Str8Lit("/"), DN_Str8Lit("\\")}; DN_Str8 separators[] = {DN_Str8Lit("/"), DN_Str8Lit("\\")};
DN_Str8BSplitResult split = DN_Str8BSplitLastArray(exe_path, separators, DN_ArrayCountU(separators)); DN_Str8BSplitResult split = DN_Str8BSplitLastArray(exe_path, separators, DN_ArrayCountU(separators));
result = DN_Str8FromStr8Arena(arena, split.lhs); result = DN_Str8FromStr8Arena(split.lhs, arena);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
} }
@@ -388,7 +399,7 @@ DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_ErrSink *error, DN_FMT_ATTRIB c
return result; return result;
} }
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_FileReadAll(DN_Allocator allocator, DN_Str8 path, DN_ErrSink *err)
{ {
// NOTE: Query file size // NOTE: Query file size
DN_Str8 result = {}; DN_Str8 result = {};
@@ -399,14 +410,14 @@ DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_St
} }
// NOTE: Allocate // NOTE: Allocate
DN_ArenaTempMem arena_tmp = {}; DN_Arena temp_arena = {};
if (alloc_type == DN_Allocator_Arena) { if (allocator.type == DN_AllocatorType_Arena) {
DN_Arena *arena = DN_Cast(DN_Arena *) allocator; DN_Arena *arena = DN_Cast(DN_Arena *) allocator.context;
arena_tmp = DN_ArenaTempMemBegin(arena); temp_arena = DN_ArenaTempBeginFromArena(arena);
result = DN_Str8AllocArena(arena, path_info.size, DN_ZMem_No); result = DN_Str8AllocArena(path_info.size, DN_ZMem_No, &temp_arena);
} else { } else {
DN_Pool *pool = DN_Cast(DN_Pool *) allocator; DN_Pool *pool = DN_Cast(DN_Pool *) allocator.context;
result = DN_Str8AllocPool(pool, path_info.size); result = DN_Str8AllocPool(path_info.size, pool);
} }
if (!result.data) { if (!result.data) {
@@ -418,29 +429,39 @@ DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_St
// NOTE: Read all // NOTE: Read all
DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, err); DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, err);
DN_OSFileRead read = DN_OS_FileRead(&file, result.data, result.size, err); DN_OSFileRead read = DN_OS_FileRead(&file, result.data, result.size, err);
if (file.error || !read.success) { bool failed = file.error || !read.success;
if (alloc_type == DN_Allocator_Arena) {
DN_ArenaTempMemEnd(arena_tmp); if (allocator.type == DN_AllocatorType_Arena) {
DN_ArenaTempEnd(&temp_arena, failed ? DN_ArenaReset_Yes : DN_ArenaReset_No);
} else { } else {
DN_Pool *pool = DN_Cast(DN_Pool *) allocator; if (failed) {
DN_Pool *pool = DN_Cast(DN_Pool *) allocator.context;
DN_PoolDealloc(pool, result.data); DN_PoolDealloc(pool, result.data);
} }
result = {};
} }
if (failed)
result = {};
DN_OS_FileClose(&file); DN_OS_FileClose(&file);
return result; return result;
} }
DN_API DN_Str8 DN_OS_FileReadAllArena(DN_Arena *arena, DN_Str8 path, DN_ErrSink *err) DN_API DN_Str8 DN_OS_FileReadAllArena(DN_Arena *arena, DN_Str8 path, DN_ErrSink *err)
{ {
DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, arena, path, err); DN_Allocator allocator = {};
allocator.type = DN_AllocatorType_Arena;
allocator.context = arena;
DN_Str8 result = DN_OS_FileReadAll(allocator, path, err);
return result; return result;
} }
DN_API DN_Str8 DN_OS_FileReadAllPool(DN_Pool *pool, DN_Str8 path, DN_ErrSink *err) DN_API DN_Str8 DN_OS_FileReadAllPool(DN_Pool *pool, DN_Str8 path, DN_ErrSink *err)
{ {
DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Pool, pool, path, err); DN_Allocator allocator = {};
allocator.type = DN_AllocatorType_Pool;
allocator.context = pool;
DN_Str8 result = DN_OS_FileReadAll(allocator, path, err);
return result; return result;
} }
@@ -455,7 +476,7 @@ DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error)
DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
{ {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 buffer = DN_Str8FromFmtVArena(scratch.arena, fmt, args); DN_Str8 buffer = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
bool result = DN_OS_FileWriteAll(file_path, buffer, error); bool result = DN_OS_FileWriteAll(file_path, buffer, error);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
@@ -473,7 +494,7 @@ DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATT
DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error) DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error)
{ {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 tmp_path = DN_Str8FromFmtArena(scratch.arena, "%.*s.tmp", DN_Str8PrintFmt(path)); DN_Str8 tmp_path = DN_Str8FromFmtArena(&scratch.arena, "%.*s.tmp", DN_Str8PrintFmt(path));
if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) { if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) {
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return false; return false;
@@ -493,7 +514,7 @@ 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_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) DN_API bool DN_OS_FileWriteAllSafeFV(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
{ {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 buffer = DN_Str8FromFmtVArena(scratch.arena, fmt, args); DN_Str8 buffer = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
bool result = DN_OS_FileWriteAllSafe(path, buffer, error); bool result = DN_OS_FileWriteAllSafe(path, buffer, error);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
@@ -507,6 +528,17 @@ DN_API bool DN_OS_FileWriteAllSafeF(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTR
return result; return result;
} }
DN_API DN_Str8 DN_OS_Str8FromPathInfoType(DN_OSPathInfoType type)
{
DN_Str8 result = DN_Str8Lit("BAD PATH INFO TYPE");
switch(type) {
case DN_OSPathInfoType_Unknown: result = DN_Str8Lit("Unknown"); break;
case DN_OSPathInfoType_Directory: result = DN_Str8Lit("Directory"); break;
case DN_OSPathInfoType_File: result = DN_Str8Lit("File"); break;
}
return result;
}
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)
{ {
if (!arena || !fs_path || path.size == 0) if (!arena || !fs_path || path.size == 0)
@@ -552,7 +584,7 @@ DN_API bool DN_OS_PathAddRef(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) DN_API bool DN_OS_PathAdd(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path)
{ {
DN_Str8 copy = DN_Str8FromStr8Arena(arena, path); DN_Str8 copy = DN_Str8FromStr8Arena(path, arena);
bool result = copy.size ? true : DN_OS_PathAddRef(arena, fs_path, copy); bool result = copy.size ? true : DN_OS_PathAddRef(arena, fs_path, copy);
return result; return result;
} }
@@ -601,7 +633,7 @@ DN_API DN_Str8 DN_OS_PathToF(DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATT
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
DN_Str8 path = DN_Str8FromFmtVArena(scratch.arena, fmt, args); DN_Str8 path = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
va_end(args); va_end(args);
DN_Str8 result = DN_OS_PathTo(arena, path, path_separator); DN_Str8 result = DN_OS_PathTo(arena, path, path_separator);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
@@ -619,7 +651,7 @@ DN_API DN_Str8 DN_OS_PathF(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...)
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
DN_Str8 path = DN_Str8FromFmtVArena(scratch.arena, fmt, args); DN_Str8 path = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
va_end(args); va_end(args);
DN_Str8 result = DN_OS_Path(arena, path); DN_Str8 result = DN_OS_Path(arena, path);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
@@ -634,7 +666,7 @@ DN_API DN_Str8 DN_OS_PathBuildWithSeparator(DN_Arena *arena, DN_OSPath const *fs
// NOTE: Each link except the last one needs the path separator appended to it, '/' or '\\' // NOTE: Each link except the last one needs the path separator appended to it, '/' or '\\'
DN_USize string_size = (fs_path->has_prefix_path_separator ? path_separator.size : 0) + fs_path->string_size + ((fs_path->links_size - 1) * path_separator.size); DN_USize string_size = (fs_path->has_prefix_path_separator ? path_separator.size : 0) + fs_path->string_size + ((fs_path->links_size - 1) * path_separator.size);
result = DN_Str8AllocArena(arena, string_size, DN_ZMem_No); result = DN_Str8AllocArena(string_size, DN_ZMem_No, arena);
if (result.data) { if (result.data) {
char *dest = result.data; char *dest = result.data;
if (fs_path->has_prefix_path_separator) { if (fs_path->has_prefix_path_separator) {
@@ -683,7 +715,7 @@ DN_API DN_OSExecResult DN_OS_ExecOrAbort(DN_Str8Slice cmd_line, DN_OSExecArgs *a
static void DN_OS_ThreadExecute_(void *user_context) static void DN_OS_ThreadExecute_(void *user_context)
{ {
DN_OSThread *thread = DN_Cast(DN_OSThread *) user_context; DN_OSThread *thread = DN_Cast(DN_OSThread *) user_context;
DN_ArenaMemFuncs mem_funcs = DN_ArenaMemFuncsGetDefaults(); DN_MemFuncs mem_funcs = DN_MemFuncsDefault();
DN_TCInitFromMemFuncs(&thread->context, thread->thread_id, /*args=*/nullptr, mem_funcs); DN_TCInitFromMemFuncs(&thread->context, thread->thread_id, /*args=*/nullptr, mem_funcs);
DN_TCEquip(&thread->context); DN_TCEquip(&thread->context);
if (thread->is_lane_set) { if (thread->is_lane_set) {
@@ -899,13 +931,15 @@ DN_API void DN_OS_PrintFStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATT
DN_API void DN_OS_PrintStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string) DN_API void DN_OS_PrintStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string)
{ {
if (string.data && string.size) { if (string.data && string.size) {
if (style.colour) if (style.colour) {
DN_OS_Print(dest, DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType_Fg, style.r, style.g, style.b)); DN_Str8x32 colour = DN_Str8x32FromANSIColourCodeU8RGB(DN_ANSIColourMode_Fg, style.r, style.g, style.b);
DN_OS_Print(dest, DN_Str8FromStruct(&colour));
}
if (style.bold == DN_LogBold_Yes) if (style.bold == DN_LogBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LogBoldEscapeCode)); DN_OS_Print(dest, DN_Str8Lit(DN_ANSICodeBoldLit));
DN_OS_Print(dest, string); DN_OS_Print(dest, string);
if (style.colour || style.bold == DN_LogBold_Yes) if (style.colour || style.bold == DN_LogBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LogResetEscapeCode)); DN_OS_Print(dest, DN_Str8Lit(DN_ANSICodeResetLit));
} }
} }
@@ -930,13 +964,15 @@ DN_API void DN_OS_PrintFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va
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_PrintFVStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args)
{ {
if (fmt) { if (fmt) {
if (style.colour) if (style.colour) {
DN_OS_Print(dest, DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType_Fg, style.r, style.g, style.b)); DN_Str8x32 colour = DN_Str8x32FromANSIColourCodeU8RGB(DN_ANSIColourMode_Fg, style.r, style.g, style.b);
DN_OS_Print(dest, DN_Str8FromStruct(&colour));
}
if (style.bold == DN_LogBold_Yes) if (style.bold == DN_LogBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LogBoldEscapeCode)); DN_OS_Print(dest, DN_Str8Lit(DN_ANSICodeBoldLit));
DN_OS_PrintFV(dest, fmt, args); DN_OS_PrintFV(dest, fmt, args);
if (style.colour || style.bold == DN_LogBold_Yes) if (style.colour || style.bold == DN_LogBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LogResetEscapeCode)); DN_OS_Print(dest, DN_Str8Lit(DN_ANSICodeResetLit));
} }
} }
@@ -1167,7 +1203,7 @@ DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, DN_U16 limit)
SymSetOptions(SYMOPT_LOAD_LINES); SymSetOptions(SYMOPT_LOAD_LINES);
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) { if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_OSW32Error error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error error = DN_OS_W32LastError(&scratch.arena);
DN_LogErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_Str8PrintFmt(error.msg)); DN_LogErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_Str8PrintFmt(error.msg));
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
} }
@@ -1247,7 +1283,7 @@ DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkR
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena); DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip); DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip);
result = DN_Str8BuilderBuild(&builder, arena); result = DN_Str8BuilderBuild(&builder, arena);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
@@ -1257,7 +1293,7 @@ DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkR
DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, DN_U16 limit, DN_U16 skip) DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, DN_U16 limit, DN_U16 skip)
{ {
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, limit); DN_StackTraceWalkResult walk = DN_StackTraceWalk(&scratch.arena, limit);
DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip); DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
@@ -1267,12 +1303,13 @@ DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap(DN_U16 limit, DN_U16 skip)
{ {
// NOTE: We don't use WalkResultToStr8 because that uses the TLS arenas which // NOTE: We don't use WalkResultToStr8 because that uses the TLS arenas which
// does not use the OS heap. // does not use the OS heap.
DN_Arena arena = DN_ArenaFromHeap(DN_Kilobytes(64), DN_ArenaFlags_NoAllocTrack); DN_MemList mem = DN_MemListFromHeap(DN_Kilobytes(64), DN_MemFlags_NoAllocTrack);
DN_Arena arena = DN_ArenaFromMemList(&mem);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&arena); DN_Str8Builder builder = DN_Str8BuilderFromArena(&arena);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&arena, limit); DN_StackTraceWalkResult walk = DN_StackTraceWalk(&arena, limit);
DN_StackTraceAddWalkToStr8Builder(&walk, &builder, skip); DN_StackTraceAddWalkToStr8Builder(&walk, &builder, skip);
DN_Str8 result = DN_Str8BuilderBuildFromHeap(&builder); DN_Str8 result = DN_Str8BuilderBuildFromHeap(&builder);
DN_ArenaDeinit(&arena); DN_MemListDeinit(&mem);
return result; return result;
} }
@@ -1283,9 +1320,9 @@ DN_API DN_StackTraceFrameSlice DN_StackTraceGetFrames(DN_Arena *arena, DN_U16 li
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, limit); DN_StackTraceWalkResult walk = DN_StackTraceWalk(&scratch.arena, limit);
if (walk.size) { if (walk.size) {
if (DN_ISliceAllocArena(DN_StackTraceFrameSlice, &result, walk.size, DN_ZMem_No, arena)) { if (DN_ISliceAllocArena(&result, walk.size, DN_ZMem_No, arena)) {
DN_USize slice_index = 0; DN_USize slice_index = 0;
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);) for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);)
result.data[slice_index++] = DN_StackTraceRawFrameToFrame(arena, it.raw_frame); result.data[slice_index++] = DN_StackTraceRawFrameToFrame(arena, it.raw_frame);
@@ -1345,7 +1382,7 @@ DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame(DN_Arena *arena, DN_Stack
DN_API void DN_StackTracePrint(DN_U16 limit) DN_API void DN_StackTracePrint(DN_U16 limit)
{ {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_StackTraceFrameSlice stack_trace = DN_StackTraceGetFrames(scratch.arena, limit); DN_StackTraceFrameSlice stack_trace = DN_StackTraceGetFrames(&scratch.arena, limit);
for (DN_ForItSize(it, DN_StackTraceFrame, stack_trace.data, stack_trace.count)) { for (DN_ForItSize(it, DN_StackTraceFrame, stack_trace.data, stack_trace.count)) {
DN_StackTraceFrame frame = *it.data; DN_StackTraceFrame frame = *it.data;
DN_OS_PrintErrLnF("%.*s(%I64u): %.*s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name)); DN_OS_PrintErrLnF("%.*s(%I64u): %.*s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name));
+9 -6
View File
@@ -243,7 +243,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 *scratch_arena; DN_Arena scratch_arena;
DN_Str8Builder builder; DN_Str8Builder builder;
DN_OSSemaphore on_complete_semaphore; DN_OSSemaphore on_complete_semaphore;
@@ -265,6 +265,7 @@ struct DN_OSCore
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ? DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
DN_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time DN_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time
bool log_no_colour; // Disable colours in the logging output bool log_no_colour; // Disable colours in the logging output
DN_TicketMutex log_mutex;
// NOTE: OS // NOTE: OS
DN_U32 logical_processor_count; DN_U32 logical_processor_count;
@@ -280,6 +281,7 @@ struct DN_OSCore
DN_U64 mem_allocs_total; DN_U64 mem_allocs_total;
DN_U64 mem_allocs_frame; // Total OS heap allocs since the last 'DN_Core_FrameBegin' was invoked DN_U64 mem_allocs_frame; // Total OS heap allocs since the last 'DN_Core_FrameBegin' was invoked
DN_MemList mem;
DN_Arena arena; DN_Arena arena;
void *platform_context; void *platform_context;
}; };
@@ -291,10 +293,10 @@ struct DN_OSDiskSpace
DN_U64 size; DN_U64 size;
}; };
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet (DN_ArenaMemFuncType type); DN_API DN_MemFuncs DN_MemFuncsFromType (DN_MemFuncsType type);
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults (); DN_API DN_MemFuncs DN_MemFuncsDefault ();
DN_API DN_Arena DN_ArenaFromHeap (DN_U64 size, DN_ArenaFlags flags); DN_API DN_MemList DN_MemListFromHeap (DN_U64 size, DN_MemFlags flags);
DN_API DN_Arena DN_ArenaFromVMem (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags); DN_API DN_MemList DN_MemListFromVMem (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags);
DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...);
@@ -367,6 +369,7 @@ DN_API bool DN_OS_FileWriteAllSafe (D
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_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_ErrSink *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_Str8 DN_OS_Str8FromPathInfoType (DN_OSPathInfoType type);
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);
DN_API bool DN_OS_PathDelete (DN_Str8 path); DN_API bool DN_OS_PathDelete (DN_Str8 path);
@@ -419,7 +422,7 @@ DN_API void DN_OS_ConditionVariableSignal (D
DN_API void DN_OS_ConditionVariableBroadcast (DN_OSConditionVariable *cv); DN_API void DN_OS_ConditionVariableBroadcast (DN_OSConditionVariable *cv);
DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, DN_OSThreadLane *lane, void *user_context); DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, DN_OSThreadLane *lane, void *user_context);
DN_API bool DN_OS_ThreadJoin (DN_OSThread *thread); DN_API bool DN_OS_ThreadJoin (DN_OSThread *thread, DN_TCDeinitArenas deinit_arenas);
DN_API DN_U32 DN_OS_ThreadID (); DN_API DN_U32 DN_OS_ThreadID ();
DN_API void DN_OS_ThreadSetNameFmt (char const *fmt, ...); DN_API void DN_OS_ThreadSetNameFmt (char const *fmt, ...);
+3 -3
View File
@@ -1333,7 +1333,7 @@ DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, DN_OSTh
return result; return result;
} }
DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread) DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread, DN_TCDeinitArenas deinit_arenas)
{ {
bool result = false; bool result = false;
if (thread && thread->handle) { if (thread && thread->handle) {
@@ -1344,6 +1344,7 @@ DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread)
result = pthread_join(thread_id, &return_val) == 0; result = pthread_join(thread_id, &return_val) == 0;
thread->handle = {}; thread->handle = {};
thread->thread_id = {}; thread->thread_id = {};
DN_TCDeinit(&thread->context, deinit_arenas);
} }
return result; return result;
} }
@@ -1535,8 +1536,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
return; return;
response->arena = arena; response->arena = arena;
response->builder.arena = response->builder.arena = response->scratch_arena ? response->scratch_arena : &response->tmp_arena;
response->scratch_arena ? response->scratch_arena : &response->tmp_arena;
DN_Arena *scratch = response->scratch_arena; DN_Arena *scratch = response->scratch_arena;
DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1);
+67 -75
View File
@@ -211,7 +211,7 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
{ {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSDiskSpace result = {}; DN_OSDiskSpace result = {};
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
ULARGE_INTEGER free_bytes_avail_to_caller; ULARGE_INTEGER free_bytes_avail_to_caller;
ULARGE_INTEGER total_number_of_bytes; ULARGE_INTEGER total_number_of_bytes;
@@ -234,8 +234,8 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value) DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value)
{ {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 name16 = DN_OS_W32Str8ToStr16(scratch.arena, name); DN_Str16 name16 = DN_OS_W32Str8ToStr16(&scratch.arena, name);
DN_Str16 value16 = DN_OS_W32Str8ToStr16(scratch.arena, value); DN_Str16 value16 = DN_OS_W32Str8ToStr16(&scratch.arena, value);
bool result = SetEnvironmentVariableW(name16.data, value16.data) != 0; bool result = SetEnvironmentVariableW(name16.data, value16.data) != 0;
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
@@ -247,7 +247,7 @@ DN_API DN_Str8 DN_OS_EXEPath(DN_Arena *arena)
if (!arena) if (!arena)
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(scratch.arena); DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(&scratch.arena);
result = DN_OS_W32Str16ToStr8(arena, exe_dir16); result = DN_OS_W32Str16ToStr8(arena, exe_dir16);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
@@ -287,14 +287,14 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink
{ {
bool result = false; bool result = false;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 src16 = DN_OS_W32Str8ToStr16(scratch.arena, src); DN_Str16 src16 = DN_OS_W32Str8ToStr16(&scratch.arena, src);
DN_Str16 dest16 = DN_OS_W32Str8ToStr16(scratch.arena, dest); DN_Str16 dest16 = DN_OS_W32Str8ToStr16(&scratch.arena, dest);
int fail_if_exists = overwrite == false; int fail_if_exists = overwrite == false;
result = CopyFileW(src16.data, dest16.data, fail_if_exists) != 0; result = CopyFileW(src16.data, dest16.data, fail_if_exists) != 0;
if (!result) { if (!result) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_ErrSinkAppendF(err, DN_ErrSinkAppendF(err,
win_error.code, win_error.code,
"Failed to copy file '%.*s' to '%.*s': (%u) %.*s", "Failed to copy file '%.*s' to '%.*s': (%u) %.*s",
@@ -311,8 +311,8 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink
{ {
bool result = false; bool result = false;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 src16 = DN_OS_W32Str8ToStr16(scratch.arena, src); DN_Str16 src16 = DN_OS_W32Str8ToStr16(&scratch.arena, src);
DN_Str16 dest16 = DN_OS_W32Str8ToStr16(scratch.arena, dest); DN_Str16 dest16 = DN_OS_W32Str8ToStr16(&scratch.arena, dest);
unsigned long flags = MOVEFILE_COPY_ALLOWED; unsigned long flags = MOVEFILE_COPY_ALLOWED;
if (overwrite) if (overwrite)
@@ -320,7 +320,7 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink
result = MoveFileExW(src16.data, dest16.data, flags) != 0; result = MoveFileExW(src16.data, dest16.data, flags) != 0;
if (!result) { if (!result) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_ErrSinkAppendF(err, DN_ErrSinkAppendF(err,
win_error.code, win_error.code,
"Failed to move file '%.*s' to '%.*s': (%u) %.*s", "Failed to move file '%.*s' to '%.*s': (%u) %.*s",
@@ -333,7 +333,7 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink
return result; return result;
} }
DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 access, DN_ErrSink *err) DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_ErrSink *err)
{ {
DN_OSFile result = {}; DN_OSFile result = {};
if (path.size == 0 || path.size <= 0) if (path.size == 0 || path.size <= 0)
@@ -367,7 +367,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 ac
} }
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
void *handle = CreateFileW(/*LPCWSTR lpFileName*/ path16.data, void *handle = CreateFileW(/*LPCWSTR lpFileName*/ path16.data,
/*DWORD dwDesiredAccess*/ access_mode, /*DWORD dwDesiredAccess*/ access_mode,
/*DWORD dwShareMode*/ FILE_SHARE_READ | FILE_SHARE_WRITE, /*DWORD dwShareMode*/ FILE_SHARE_READ | FILE_SHARE_WRITE,
@@ -377,7 +377,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 ac
/*HANDLE hTemplateFile*/ nullptr); /*HANDLE hTemplateFile*/ nullptr);
if (handle == INVALID_HANDLE_VALUE) { if (handle == INVALID_HANDLE_VALUE) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
result.error = true; result.error = true;
DN_ErrSinkAppendF(err, win_error.code, "Failed to open file at '%.*s': '%.*s'", DN_Str8PrintFmt(path), DN_Str8PrintFmt(win_error.msg)); DN_ErrSinkAppendF(err, win_error.code, "Failed to open file at '%.*s': '%.*s'", DN_Str8PrintFmt(path), DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
@@ -414,14 +414,14 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size
/*LPDWORD lpNumberOfByesRead*/ &bytes_read, /*LPDWORD lpNumberOfByesRead*/ &bytes_read,
/*LPOVERLAPPED lpOverlapped*/ nullptr); /*LPOVERLAPPED lpOverlapped*/ nullptr);
if (read_result == 0) { if (read_result == 0) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_ErrSinkAppendF(err, win_error.code, "Failed to read data from file: (%u) %.*s", win_error.code, DN_Str8PrintFmt(win_error.msg)); DN_ErrSinkAppendF(err, win_error.code, "Failed to read data from file: (%u) %.*s", win_error.code, DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
} }
if (bytes_read != size) { if (bytes_read != size) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_ErrSinkAppendF( DN_ErrSinkAppendF(
err, err,
win_error.code, win_error.code,
@@ -456,7 +456,7 @@ DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize siz
if (!result) { if (!result) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
DN_ErrSinkAppendF(err, win_error.code, "Failed to write buffer (%.*s) to file handle: %.*s", DN_Str8PrintFmt(buffer_size_str8), DN_Str8PrintFmt(win_error.msg)); DN_ErrSinkAppendF(err, win_error.code, "Failed to write buffer (%.*s) to file handle: %.*s", DN_Str8PrintFmt(buffer_size_str8), DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
@@ -472,7 +472,7 @@ DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_ErrSink *err)
BOOL result = FlushFileBuffers(DN_Cast(HANDLE) file->handle); BOOL result = FlushFileBuffers(DN_Cast(HANDLE) file->handle);
if (!result) { if (!result) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_ErrSinkAppendF(err, win_error.code, "Failed to flush file buffer to disk: %.*s", DN_Str8PrintFmt(win_error.msg)); DN_ErrSinkAppendF(err, win_error.code, "Failed to flush file buffer to disk: %.*s", DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
} }
@@ -495,7 +495,7 @@ DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path)
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) { if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) {
@@ -531,7 +531,7 @@ DN_API bool DN_OS_PathDelete(DN_Str8 path)
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) { if (path16.size) {
result = DeleteFileW(path16.data); result = DeleteFileW(path16.data);
if (!result) if (!result)
@@ -548,7 +548,7 @@ DN_API bool DN_OS_PathIsFile(DN_Str8 path)
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) { if (path16.size) {
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
@@ -566,7 +566,7 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) { if (path16.size) {
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
@@ -582,7 +582,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
{ {
bool result = true; bool result = true;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
// NOTE: Go back from the end of the string to all the directories in the // NOTE: Go back from the end of the string to all the directories in the
// string, and try to create them. Since Win32 API cannot create // string, and try to create them. Since Win32 API cannot create
@@ -653,12 +653,12 @@ DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it)
// add those characters in this branch, so overwrite the null // add those characters in this branch, so overwrite the null
// character, add the glob and re-null terminate the buffer. // character, add the glob and re-null terminate the buffer.
if (needs_asterisks) if (needs_asterisks)
adjusted_path = DN_OS_PathF(scratch.arena, "%.*s*", DN_Str8PrintFmt(path)); adjusted_path = DN_OS_PathF(&scratch.arena, "%.*s*", DN_Str8PrintFmt(path));
else else
adjusted_path = DN_OS_PathF(scratch.arena, "%.*s/*", DN_Str8PrintFmt(path)); adjusted_path = DN_OS_PathF(&scratch.arena, "%.*s/*", DN_Str8PrintFmt(path));
} }
path16 = DN_OS_W32Str8ToStr16(scratch.arena, adjusted_path); path16 = DN_OS_W32Str8ToStr16(&scratch.arena, adjusted_path);
if (path16.size <= 0) { // Conversion error if (path16.size <= 0) { // Conversion error
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return false; return false;
@@ -676,8 +676,6 @@ DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it)
return result; return result;
} }
// NOTE: DN_OSExec /////////////////////////////////////////////////////////////////////////////////
DN_API void DN_OS_Exit(int32_t exit_code) DN_API void DN_OS_Exit(int32_t exit_code)
{ {
ExitProcess(DN_Cast(UINT) exit_code); ExitProcess(DN_Cast(UINT) exit_code);
@@ -729,7 +727,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
exec_result = WaitForSingleObject(handle.process, timeout_ms); exec_result = WaitForSingleObject(handle.process, timeout_ms);
if (exec_result == WAIT_FAILED) { if (exec_result == WAIT_FAILED) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
result.os_error_code = win_error.code; result.os_error_code = win_error.code;
DN_ErrSinkAppendF(err, result.os_error_code, "Executed command failed to terminate: %.*s", DN_Str8PrintFmt(win_error.msg)); DN_ErrSinkAppendF(err, result.os_error_code, "Executed command failed to terminate: %.*s", DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
@@ -779,7 +777,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
if (GetExitCodeProcess(handle.process, &exit_status)) { if (GetExitCodeProcess(handle.process, &exit_status)) {
result.exit_code = exit_status; result.exit_code = exit_status;
} else { } else {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
result.os_error_code = win_error.code; result.os_error_code = win_error.code;
DN_ErrSinkAppendF(err, DN_ErrSinkAppendF(err,
result.os_error_code, result.os_error_code,
@@ -828,8 +826,8 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *are
DN_Str8Builder stdout_builder = {}; DN_Str8Builder stdout_builder = {};
DN_Str8Builder stderr_builder = {}; DN_Str8Builder stderr_builder = {};
if (arena) { if (arena) {
stdout_builder.arena = scratch.arena; stdout_builder = DN_Str8BuilderFromArena(&scratch.arena);
stderr_builder.arena = scratch.arena; stderr_builder = DN_Str8BuilderFromArena(&scratch.arena);
} }
DN_U32 const SLOW_WAIT_TIME_MS = 100; DN_U32 const SLOW_WAIT_TIME_MS = 100;
@@ -838,15 +836,15 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *are
while (!result.finished) { while (!result.finished) {
size_t stdout_size = DN_Kilobytes(8); size_t stdout_size = DN_Kilobytes(8);
size_t stderr_size = DN_Kilobytes(8); size_t stderr_size = DN_Kilobytes(8);
char *stdout_buffer = DN_ArenaNewArray(scratch.arena, char, stdout_size, DN_ZMem_No); char *stdout_buffer = DN_ArenaNewArray(&scratch.arena, char, stdout_size, DN_ZMem_No);
char *stderr_buffer = DN_ArenaNewArray(scratch.arena, char, stderr_size, DN_ZMem_No); char *stderr_buffer = DN_ArenaNewArray(&scratch.arena, char, stderr_size, DN_ZMem_No);
result = DN_OS_ExecPump(handle, stdout_buffer, &stdout_size, stderr_buffer, &stderr_size, wait_ms, err); result = DN_OS_ExecPump(handle, stdout_buffer, &stdout_size, stderr_buffer, &stderr_size, wait_ms, err);
DN_Str8BuilderAppendCopy(&stdout_builder, result.stdout_text); DN_Str8BuilderAppendCopy(&stdout_builder, result.stdout_text);
DN_Str8BuilderAppendCopy(&stderr_builder, result.stderr_text); DN_Str8BuilderAppendCopy(&stderr_builder, result.stderr_text);
wait_ms = (result.stdout_text.size || result.stderr_text.size) ? FAST_WAIT_TIME_MS : SLOW_WAIT_TIME_MS; wait_ms = (result.stdout_text.size || result.stderr_text.size) ? FAST_WAIT_TIME_MS : SLOW_WAIT_TIME_MS;
} }
// NOTE: Get stdout/stderr. If no arena is passed this is a no-op ////////////////////////////// // NOTE: Get stdout/stderr. If no arena is passed this is a no-op
result.stdout_text = DN_Str8BuilderBuild(&stdout_builder, arena); result.stdout_text = DN_Str8BuilderBuild(&stdout_builder, arena);
result.stderr_text = DN_Str8BuilderBuild(&stderr_builder, arena); result.stderr_text = DN_Str8BuilderBuild(&stderr_builder, arena);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
@@ -861,19 +859,19 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
return result; return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 cmd_rendered = DN_Str8SliceRender(cmd_line, DN_Str8Lit(" "), scratch.arena); DN_Str8 cmd_rendered = DN_Str8SliceRender(cmd_line, DN_Str8Lit(" "), &scratch.arena);
DN_Str16 cmd16 = DN_OS_W32Str8ToStr16(scratch.arena, cmd_rendered); DN_Str16 cmd16 = DN_OS_W32Str8ToStr16(&scratch.arena, cmd_rendered);
DN_Str16 working_dir16 = DN_OS_W32Str8ToStr16(scratch.arena, args->working_dir); DN_Str16 working_dir16 = DN_OS_W32Str8ToStr16(&scratch.arena, args->working_dir);
DN_Str8Builder env_builder = DN_Str8BuilderFromArena(scratch.arena); DN_Str8Builder env_builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_Str8BuilderAppendArrayRef(&env_builder, args->environment.data, args->environment.count); DN_Str8BuilderAppendArrayRef(&env_builder, args->environment.data, args->environment.count);
if (env_builder.string_size) if (env_builder.string_size)
DN_Str8BuilderAppendRef(&env_builder, DN_Str8Lit("\0")); DN_Str8BuilderAppendRef(&env_builder, DN_Str8Lit("\0"));
DN_Str8 env_block8 = DN_Str8BuilderBuildDelimited(&env_builder, DN_Str8Lit("\0"), scratch.arena); DN_Str8 env_block8 = DN_Str8BuilderBuildDelimited(&env_builder, DN_Str8Lit("\0"), &scratch.arena);
DN_Str16 env_block16 = {}; DN_Str16 env_block16 = {};
if (env_block8.size) if (env_block8.size)
env_block16 = DN_OS_W32Str8ToStr16(scratch.arena, env_block8); env_block16 = DN_OS_W32Str8ToStr16(&scratch.arena, env_block8);
// NOTE: Stdout/err security attributes // NOTE: Stdout/err security attributes
SECURITY_ATTRIBUTES save_std_security_attribs = {}; SECURITY_ATTRIBUTES save_std_security_attribs = {};
@@ -893,7 +891,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) { if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) {
if (!CreatePipe(&stdout_read, &stdout_write, &save_std_security_attribs, /*nSize*/ 0)) { if (!CreatePipe(&stdout_read, &stdout_write, &save_std_security_attribs, /*nSize*/ 0)) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
result.os_error_code = win_error.code; result.os_error_code = win_error.code;
DN_ErrSinkAppendF( DN_ErrSinkAppendF(
err, err,
@@ -906,7 +904,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
} }
if (!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0)) { if (!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0)) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
result.os_error_code = win_error.code; result.os_error_code = win_error.code;
DN_ErrSinkAppendF(err, DN_ErrSinkAppendF(err,
result.os_error_code, result.os_error_code,
@@ -936,7 +934,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
stderr_write = stdout_write; stderr_write = stdout_write;
} else { } else {
if (!CreatePipe(&stderr_read, &stderr_write, &save_std_security_attribs, /*nSize*/ 0)) { if (!CreatePipe(&stderr_read, &stderr_write, &save_std_security_attribs, /*nSize*/ 0)) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
result.os_error_code = win_error.code; result.os_error_code = win_error.code;
DN_ErrSinkAppendF( DN_ErrSinkAppendF(
err, err,
@@ -949,7 +947,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
} }
if (!SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0)) { if (!SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0)) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
result.os_error_code = win_error.code; result.os_error_code = win_error.code;
DN_ErrSinkAppendF(err, DN_ErrSinkAppendF(err,
result.os_error_code, result.os_error_code,
@@ -963,7 +961,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
} }
} }
// NOTE: Execute command /////////////////////////////////////////////////////////////////////// // NOTE: Execute command
PROCESS_INFORMATION proc_info = {}; PROCESS_INFORMATION proc_info = {};
STARTUPINFOW startup_info = {}; STARTUPINFOW startup_info = {};
startup_info.cb = sizeof(STARTUPINFOW); startup_info.cb = sizeof(STARTUPINFOW);
@@ -982,14 +980,14 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
&startup_info, &startup_info,
&proc_info); &proc_info);
if (!create_result) { if (!create_result) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
result.os_error_code = win_error.code; result.os_error_code = win_error.code;
DN_ErrSinkAppendF(err, result.os_error_code, "Failed to execute command '%.*s': %.*s", DN_Str8PrintFmt(cmd_rendered), DN_Str8PrintFmt(win_error.msg)); DN_ErrSinkAppendF(err, result.os_error_code, "Failed to execute command '%.*s': %.*s", DN_Str8PrintFmt(cmd_rendered), DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
} }
// NOTE: Post-amble //////////////////////////////////////////////////////////////////////////// // NOTE: Post-amble
CloseHandle(proc_info.hThread); CloseHandle(proc_info.hThread);
result.process = proc_info.hProcess; result.process = proc_info.hProcess;
result.stdout_read = stdout_read; result.stdout_read = stdout_read;
@@ -1280,7 +1278,7 @@ DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, DN_OSTh
return result; return result;
} }
DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread) DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread, DN_TCDeinitArenas deinit_arenas)
{ {
bool result = false; bool result = false;
if (thread && thread->handle) { if (thread && thread->handle) {
@@ -1289,7 +1287,7 @@ DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread)
CloseHandle(thread->handle); CloseHandle(thread->handle);
thread->handle = INVALID_HANDLE_VALUE; thread->handle = INVALID_HANDLE_VALUE;
thread->thread_id = {}; thread->thread_id = {};
DN_TCDeinit(&thread->context); DN_TCDeinit(&thread->context, deinit_arenas);
} }
return result; return result;
} }
@@ -1309,7 +1307,7 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
DN_OSW32Core *w32 = DN_OS_W32GetCore(); DN_OSW32Core *w32 = DN_OS_W32GetCore();
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
if (w32->set_thread_description) { if (w32->set_thread_description) {
DN_Str16 name16 = DN_OS_W32Str8ToStr16(scratch.arena, name); DN_Str16 name16 = DN_OS_W32Str8ToStr16(&scratch.arena, name);
w32->set_thread_description(GetCurrentThread(), (WCHAR *)name16.data); w32->set_thread_description(GetCurrentThread(), (WCHAR *)name16.data);
} else { } else {
// NOTE: Fallback to throw-exception method to set thread name // NOTE: Fallback to throw-exception method to set thread name
@@ -1323,7 +1321,7 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
}; };
#pragma pack(pop) #pragma pack(pop)
DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, name); DN_Str8 copy = DN_Str8FromStr8Arena(name, &scratch.arena);
DN_OSW32ThreadNameInfo info = {}; DN_OSW32ThreadNameInfo info = {};
info.dwType = 0x1000; info.dwType = 0x1000;
info.szName = (char *)copy.data; info.szName = (char *)copy.data;
@@ -1342,7 +1340,6 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_OSHttp /////////////////////////////////////////////////////////////////////////////////
void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD dwInternetStatus, VOID *lpvStatusInformation, DWORD dwStatusInformationLength) void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD dwInternetStatus, VOID *lpvStatusInformation, DWORD dwStatusInformationLength)
{ {
(void)session; (void)session;
@@ -1450,12 +1447,11 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
return; return;
response->arena = arena; response->arena = arena;
response->builder.arena = response->scratch_arena ? response->scratch_arena : &response->tmp_arena; response->builder = DN_Str8BuilderFromArena(response->scratch_arena.mem ? &response->scratch_arena : &response->tmp_arena);
DN_Arena *scratch_arena = response->scratch_arena;
DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1);
if (!scratch_arena) if (!response->scratch_arena.mem)
scratch_arena = scratch_.arena; response->scratch_arena = scratch_.arena;
DN_OSW32Error error = {}; DN_OSW32Error error = {};
DN_DEFER DN_DEFER
@@ -1489,15 +1485,15 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
return; return;
} }
DN_Str16 host16 = DN_OS_W32Str8ToStr16(scratch_arena, host); DN_Str16 host16 = DN_OS_W32Str8ToStr16(&response->scratch_arena, host);
response->w32_request_connection = WinHttpConnect(response->w32_request_session, host16.data, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0 /*reserved*/); response->w32_request_connection = WinHttpConnect(response->w32_request_session, host16.data, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0 /*reserved*/);
if (!response->w32_request_connection) { if (!response->w32_request_connection) {
error = DN_OS_W32LastError(&response->tmp_arena); error = DN_OS_W32LastError(&response->tmp_arena);
return; return;
} }
DN_Str16 method16 = DN_OS_W32Str8ToStr16(scratch_arena, method); DN_Str16 method16 = DN_OS_W32Str8ToStr16(&response->scratch_arena, method);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch_arena, path); DN_Str16 path16 = DN_OS_W32Str8ToStr16(&response->scratch_arena, path);
response->w32_request_handle = WinHttpOpenRequest(response->w32_request_connection, response->w32_request_handle = WinHttpOpenRequest(response->w32_request_connection,
method16.data, method16.data,
path16.data, path16.data,
@@ -1510,7 +1506,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
return; return;
} }
DN_Str16 headers16 = DN_OS_W32Str8ToStr16(scratch_arena, headers); DN_Str16 headers16 = DN_OS_W32Str8ToStr16(&response->scratch_arena, headers);
response->on_complete_semaphore = DN_OS_SemaphoreInit(0); response->on_complete_semaphore = DN_OS_SemaphoreInit(0);
if (!WinHttpSendRequest(response->w32_request_handle, if (!WinHttpSendRequest(response->w32_request_handle,
headers16.data, headers16.data,
@@ -1535,7 +1531,7 @@ DN_API void DN_OS_HttpRequestFree(DN_OSHttpResponse *response)
response->w32_request_session = nullptr; response->w32_request_session = nullptr;
response->w32_request_connection = nullptr; response->w32_request_connection = nullptr;
response->w32_request_handle = nullptr; response->w32_request_handle = nullptr;
DN_ArenaDeinit(&response->tmp_arena); DN_MemListDeinit(response->tmp_arena.mem);
DN_OS_SemaphoreDeinit(&response->on_complete_semaphore); DN_OS_SemaphoreDeinit(&response->on_complete_semaphore);
*response = {}; *response = {};
@@ -1626,7 +1622,6 @@ DN_API void DN_OS_W32MakeProcessDPIAware()
set_process_dpi_aware(); set_process_dpi_aware();
} }
// NOTE: Windows UTF8 to Str16 //////////////////////////////////////////////
DN_API DN_Str16 DN_OS_W32Str8ToStr16(DN_Arena *arena, DN_Str8 src) DN_API DN_Str16 DN_OS_W32Str8ToStr16(DN_Arena *arena, DN_Str8 src)
{ {
DN_Str16 result = {}; DN_Str16 result = {};
@@ -1665,7 +1660,6 @@ DN_API int DN_OS_W32Str8ToStr16Buffer(DN_Str8 src, wchar_t *dest, int dest_size)
return result; return result;
} }
// NOTE: Windows Str16 To UTF8 //////////////////////////////////////////////////////////////////
DN_API int DN_OS_W32Str16ToStr8Buffer(DN_Str16 src, char *dest, int dest_size) DN_API int DN_OS_W32Str16ToStr8Buffer(DN_Str16 src, char *dest, int dest_size)
{ {
int result = 0; int result = 0;
@@ -1701,18 +1695,16 @@ DN_API DN_Str8 DN_OS_W32Str16ToStr8(DN_Arena *arena, DN_Str16 src)
// NOTE: Str8 allocate ensures there's one extra byte for // NOTE: Str8 allocate ensures there's one extra byte for
// null-termination already so no-need to +1 the required size // null-termination already so no-need to +1 the required size
DN_ArenaTempMemScope temp_mem = DN_ArenaTempMemScope(arena); DN_Arena temp = DN_ArenaTempBeginFromArena(arena);
DN_Str8 buffer = DN_Str8AllocArena(arena, required_size, DN_ZMem_No); DN_Str8 buffer = DN_Str8AllocArena(required_size, DN_ZMem_No, &temp);
if (buffer.size == 0) if (buffer.size) {
return result;
int chars_written = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, src.data, src_size, buffer.data, DN_Cast(int) buffer.size, nullptr, nullptr); int chars_written = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, src.data, src_size, buffer.data, DN_Cast(int) buffer.size, nullptr, nullptr);
if (DN_Check(chars_written == required_size)) { if (DN_Check(chars_written == required_size)) {
result = buffer; result = buffer;
result.data[result.size] = 0; result.data[result.size] = 0;
temp_mem.mem = {};
} }
}
DN_ArenaTempEnd(&temp, result.size == DN_Cast(DN_USize)required_size ? DN_ArenaReset_No : DN_ArenaReset_Yes);
return result; return result;
} }
@@ -1757,7 +1749,7 @@ DN_API DN_Str16 DN_OS_W32EXEPathW(DN_Arena *arena)
wchar_t *module_path = nullptr; wchar_t *module_path = nullptr;
do { do {
module_size += 256; module_size += 256;
module_path = DN_ArenaNewArray(scratch.arena, wchar_t, module_size, DN_ZMem_No); module_path = DN_ArenaNewArray(&scratch.arena, wchar_t, module_size, DN_ZMem_No);
if (!module_path) { if (!module_path) {
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
@@ -1786,7 +1778,7 @@ DN_API DN_Str16 DN_OS_W32EXEDirW(DN_Arena *arena)
wchar_t *module_path = nullptr; wchar_t *module_path = nullptr;
do { do {
module_size += 256; module_size += 256;
module_path = DN_ArenaNewArray(scratch.arena, wchar_t, module_size, DN_ZMem_No); module_path = DN_ArenaNewArray(&scratch.arena, wchar_t, module_size, DN_ZMem_No);
if (!module_path) { if (!module_path) {
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
@@ -1809,8 +1801,8 @@ DN_API DN_Str16 DN_OS_W32EXEDirW(DN_Arena *arena)
DN_API DN_Str8 DN_OS_W32WorkingDir(DN_Arena *arena, DN_Str8 suffix) DN_API DN_Str8 DN_OS_W32WorkingDir(DN_Arena *arena, DN_Str8 suffix)
{ {
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str16 suffix16 = DN_OS_W32Str8ToStr16(scratch.arena, suffix); DN_Str16 suffix16 = DN_OS_W32Str8ToStr16(&scratch.arena, suffix);
DN_Str16 dir16 = DN_OS_W32WorkingDirW(scratch.arena, suffix16); DN_Str16 dir16 = DN_OS_W32WorkingDirW(&scratch.arena, suffix16);
DN_Str8 result = DN_OS_W32Str16ToStr8(arena, dir16); DN_Str8 result = DN_OS_W32Str16ToStr8(arena, dir16);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
@@ -1826,7 +1818,7 @@ DN_API DN_Str16 DN_OS_W32WorkingDirW(DN_Arena *arena, DN_Str16 suffix)
unsigned long required_size = GetCurrentDirectoryW(0, nullptr); unsigned long required_size = GetCurrentDirectoryW(0, nullptr);
unsigned long desired_size = required_size + DN_Cast(unsigned long) suffix.size; unsigned long desired_size = required_size + DN_Cast(unsigned long) suffix.size;
wchar_t *scratch_w_path = DN_ArenaNewArray(scratch.arena, wchar_t, desired_size, DN_ZMem_No); wchar_t *scratch_w_path = DN_ArenaNewArray(&scratch.arena, wchar_t, desired_size, DN_ZMem_No);
if (!scratch_w_path) { if (!scratch_w_path) {
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
return result; return result;
+37 -3
View File
@@ -318,7 +318,7 @@ DN_INIToken DN_INI_NextToken(DN_INITokeniser const *tokeniser)
if (DN_INI_Str8Eq(esc_str8, DN_INIStr8Lit("\n"))) { if (DN_INI_Str8Eq(esc_str8, DN_INIStr8Lit("\n"))) {
result.next_p += 2; result.next_p += 2;
} else if (DN_INI_Str8Eq(esc_str8, DN_INIStr8Lit("\\"))) { } else if (DN_INI_Str8Eq(esc_str8, DN_INIStr8Lit("\\"))) {
// NOTE: Backespace is escaping a backspace // NOTE: Backspace is escaping a backspace
} else { } else {
result.next_p += 1; result.next_p += 1;
} }
@@ -340,7 +340,19 @@ DN_INIToken DN_INI_NextToken(DN_INITokeniser const *tokeniser)
if (tokeniser->prev_token.type == DN_INITokenType_FieldSeparator || multiline_value || value) { if (tokeniser->prev_token.type == DN_INITokenType_FieldSeparator || multiline_value || value) {
if (tokeniser->data[pos] == ' ') // Value can have spaces in it without quotes if (tokeniser->data[pos] == ' ') // Value can have spaces in it without quotes
continue; continue;
result.type = tokeniser->prev_token.type == DN_INITokenType_FieldSeparator ? DN_INITokenType_Value : DN_INITokenType_MultilineValue;
if (tokeniser->prev_token.type == DN_INITokenType_FieldSeparator) {
if (result.line_start_new_line) {
// NOTE: The user has terminated the value component of the key with a newline
// (e.g. no value presented). For example: `their_key=\n` which means there's no
// value and instead they started a new key-value pair.
result.type = DN_INITokenType_Key;
} else {
result.type = DN_INITokenType_Value;
}
} else {
result.type = DN_INITokenType_MultilineValue;
}
} else if (tokeniser->prev_token.type == DN_INITokenType_Key) { } else if (tokeniser->prev_token.type == DN_INITokenType_Key) {
result.type = DN_INITokenType_Error; result.type = DN_INITokenType_Error;
result.error = DN_INIStr8Lit("Invalid unquoted string, multiple consecutive keys encountered"); result.error = DN_INIStr8Lit("Invalid unquoted string, multiple consecutive keys encountered");
@@ -849,7 +861,7 @@ DN_INIField *DN_INI_AppendKeyF(DN_INICore *ini, DN_INIArena *arena, DN_INISectio
return result; return result;
} }
#if defined(DN_INI_WITH_UNIT_TESTS) || 1 #if defined(DN_INI_WITH_UNIT_TESTS)
void DN_INI_UnitTests() void DN_INI_UnitTests()
{ {
// NOTE: Section and comments // NOTE: Section and comments
@@ -1106,5 +1118,27 @@ void DN_INI_UnitTests()
DN_INI_Assert(parse.error_token.type == DN_INITokenType_Nil); DN_INI_Assert(parse.error_token.type == DN_INITokenType_Nil);
DN_INI_Assert(DN_INI_Str8Eq(parse.first_section.child_first->first_field->key, DN_INIStr8Lit("foo"))); DN_INI_Assert(DN_INI_Str8Eq(parse.first_section.child_first->first_field->key, DN_INIStr8Lit("foo")));
} }
// NOTE: 2 empty key-values consecutively
{
char const EXAMPLE[] =
"[metadata]\n"
"foo=\n"
"bar=\n"
;
DN_INICore parse = DN_INI_ParseFromPtr(EXAMPLE, sizeof(EXAMPLE) - 1, 0, 0);
DN_INI_Assert(parse.error_token.type == DN_INITokenType_Nil);
DN_INI_Assert(parse.total_sections_count == 1);
DN_INI_Assert(parse.total_fields_count == 2);
char parse_memory[400];
DN_INI_Assert(parse.memory_required <= sizeof(parse_memory));
parse = DN_INI_ParseFromPtr(EXAMPLE, sizeof(EXAMPLE) - 1, parse_memory, sizeof(parse_memory));
DN_INI_Assert(parse.error_token.type == DN_INITokenType_Nil);
DN_INI_Assert(DN_INI_Str8Eq(parse.first_section.child_first->first_field->key, DN_INIStr8Lit("foo")));
DN_INI_Assert(DN_INI_Str8Eq(parse.first_section.child_first->first_field->next->key, DN_INIStr8Lit("bar")));
}
} }
#endif #endif
+93
View File
@@ -1,6 +1,99 @@
#if !defined(DN_INI_H) #if !defined(DN_INI_H)
#define DN_INI_H #define DN_INI_H
// NOTE: DN INI Configuration
// Getting Started
// This is a single header and implementation file library that implements .ini file handling.
// It supports the following .ini features:
//
// - Plain sections: [sections]
// - Arbitrarily nested sections delimited by '.': [sections.a] [sections.a.b] [sections.a.b....]
// - Repeated section names (the last section takes precedence)
// - Comments marked by #: [section] # Comment
// - Multi-line values for keys:
// [my_section]
// the_key = the_value \
// another line for the key \
// and another one
// the_next_key = that's cool
//
// Include both .h and .c in your translation unit or compile the .c separately and link against
// it to get started. The goals of the library are as follows:
//
// - Zero allocations to parse, accepts a NULL buffer to determine the amount of bytes required
// to parse the .ini buffer
// - Compile in C99 and compatible with C++
//
// Example
/*
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "dn_ini.h"
#include "dn_ini.c"
void main() {
DN_INIStr8 ini_buffer = DN_INIStr8Lit(
"[my_stuff]\n"
"app=the_stuff # Comment on the stuff value\n"
"\n"
"[section]\n"
"item=abc\n"
"\n"
"[section.foo.xyz]\n"
"another=one\n"
"multi_line_key=coolios \\\n"
"from another line?!\n"
);
// NOTE: Calculate the number of bytes required to parse the buffer and make one single
// allocation
DN_INICore ini = DN_INI_ParseFromPtr(ini_buffer.data, ini_buffer.size, NULL, 0);
size_t parse_buffer_size = ini.memory_required;
char* parse_buffer = calloc(1, parse_buffer_size);
// NOTE: Parse the buffer into the `ini` object from the single allocation. No additional
// allocations are made
ini = DN_INI_ParseFromPtr(ini_buffer.data, ini_buffer.size, parse_buffer, parse_buffer_size);
// NOTE: Process the ini file
// The .INI file parsed into a tree, resembling
//
// [Root (Sentinel)] <-- This is ini.first_section, its children contains the .ini contents
// |
// +-- [my_stuff]
// +-- [my_section]
// |
// +-- [foo]
// |
// +-- [xyz]
//
DN_INISection *my_stuff = DN_INI_ChildSectionFromStr8(&ini.first_section, DN_INIStr8Lit("my_stuff"));
DN_INISection *my_section = DN_INI_ChildSectionFromStr8(&ini.first_section, DN_INIStr8Lit("my_section"));
DN_INISection *my_section_foo = DN_INI_ChildSectionFromStr8(my_section, DN_INIStr8Lit("foo"));
DN_INISection *my_section_foo_xyz = DN_INI_ChildSectionFromStr8(my_section_foo, DN_INIStr8Lit("xyz"));
printf("My Section Foo XYZ: %zu fields\n", my_section_foo_xyz->fields_count);
for (DN_INIField *field = my_section_foo->first_field; field; field = field->next)
printf(" %.*s: %.*s\n", (int)field->key.size, field->key.data, (int)field->value.size, field->value.data);
// Alternatively you can access the section directly by specifying the fully qualified path from
// the section, e.g.:
DN_INISection *my_section_foo_xyz_direct = DN_INI_ChildSectionFromStr8(&ini.first_section, DN_INIStr8Lit("my_section.foo.xyz"));
if (my_section_foo_xyz_direct) {
// ...
}
// You may also lookup the field directly by specifying the fully qualified path
DN_INIField *my_section_item = DN_INI_FieldFromSectionStr8(&ini.first_section, DN_INIStr8Lit("my_section.item"));
if (my_section_item)
printf(" %.*s: %.*s\n", (int)my_section_item->key.size, my_section_item->key.data, (int)my_section_item->value.size, my_section_item->value.data);
// NOTE: Release memory, `ini` and its contents are invalidated and should not be used
free(parse_buffer);
}
*/
#include <stdint.h> // size_t #include <stdint.h> // size_t
#if !defined(DN_INI_Assert) #if !defined(DN_INI_Assert)
+299
View File
@@ -0,0 +1,299 @@
#include "dn_json_builder.h"
static void DN_JSB_Indent_(DN_JSBBuilder *builder, char *buf, size_t buf_size, size_t depth)
{
for (size_t i = 0; i < depth; i++) {
DN_JSB_AppendF_(builder, buf, buf_size, " ");
}
}
DN_JSBDepth *DN_JSB_PeekDepth_(DN_JSBBuilder *builder, size_t offset)
{
DN_JSBDepth *result = 0;
if (builder->depth_count > offset)
result = &builder->depth[builder->depth_count - (1 + offset)];
return result;
}
bool DN_JSB_PushDepth_(DN_JSBBuilder *builder, DN_JSBDepthType type)
{
bool result = false;
if (builder->depth_count < builder->depth_max) {
DN_JSBDepth *depth = &builder->depth[builder->depth_count++];
depth->last_action = DN_JSBAction_Nil;
depth->type = type;
result = true;
}
return result;
}
DN_JSBResult DN_JSB_PushObject(DN_JSBBuilder *builder, char *buf, size_t buf_size)
{
DN_JSBDepth *top_depth = DN_JSB_PeekDepth_(builder, 0);
if (top_depth && top_depth->type != DN_JSBDepthType_Array) {
if ((top_depth->last_action == DN_JSBAction_Value || top_depth->last_action == DN_JSBAction_PopArray || top_depth->last_action == DN_JSBAction_PushObject))
return DN_JSBResult_BadAPIUsage;
}
if (!DN_JSB_PushDepth_(builder, DN_JSBDepthType_Object))
return DN_JSBResult_DepthArrayOutOfMem;
bool leading_comma = top_depth && (top_depth->last_action != DN_JSBAction_Nil && top_depth->last_action != DN_JSBAction_Key);
if (builder->pretty && top_depth && top_depth->type == DN_JSBDepthType_Array) {
if (leading_comma) {
DN_JSB_AppendF_(builder, buf, buf_size, ",\n");
} else {
DN_JSB_AppendF_(builder, buf, buf_size, "\n");
}
DN_JSB_Indent_(builder, buf, buf_size, builder->depth_count - 1);
leading_comma = false;
}
DN_JSBResult result = DN_JSB_AppendF_(builder, buf, buf_size, "%s{", leading_comma ? "," : "");
if (top_depth)
top_depth->last_action = DN_JSBAction_PushObject; // Record the push on the now, previous depth
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_PopObject(DN_JSBBuilder *builder, char *buf, size_t buf_size)
{
DN_JSBDepth *top_depth = DN_JSB_PeekDepth_(builder, 0);
if (!top_depth || top_depth->type != DN_JSBDepthType_Object)
return DN_JSBResult_BadAPIUsage;
bool had_children = top_depth->last_action != DN_JSBAction_Nil;
builder->depth_count--; // Remove the depth entry from the stack
DN_JSBDepth *new_top = DN_JSB_PeekDepth_(builder, 0);
if (new_top)
new_top->last_action = DN_JSBAction_PopObject;
if (builder->pretty && had_children) {
DN_JSB_AppendF_(builder, buf, buf_size, "\n");
DN_JSB_Indent_(builder, buf, buf_size, builder->depth_count);
}
DN_JSBResult result = DN_JSB_AppendF_(builder, buf, buf_size, "}");
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_PushArray(DN_JSBBuilder *builder, char *buf, size_t buf_size)
{
DN_JSBDepth *top_depth = DN_JSB_PeekDepth_(builder, 0);
if (top_depth && top_depth->type != DN_JSBDepthType_Array) {
if (top_depth->last_action == DN_JSBAction_Value || top_depth->last_action == DN_JSBAction_PopArray || top_depth->last_action == DN_JSBAction_PushObject || top_depth->last_action == DN_JSBAction_PopObject)
return DN_JSBResult_BadAPIUsage;
}
if (!DN_JSB_PushDepth_(builder, DN_JSBDepthType_Array))
return DN_JSBResult_DepthArrayOutOfMem;
bool leading_comma = top_depth && (top_depth->last_action != DN_JSBAction_Nil && top_depth->last_action != DN_JSBAction_Key);
if (builder->pretty && top_depth && top_depth->type == DN_JSBDepthType_Array) {
if (leading_comma) {
DN_JSB_AppendF_(builder, buf, buf_size, ",\n");
} else {
DN_JSB_AppendF_(builder, buf, buf_size, "\n");
}
DN_JSB_Indent_(builder, buf, buf_size, builder->depth_count - 1);
leading_comma = false;
}
DN_JSBResult result = DN_JSB_AppendF_(builder, buf, buf_size, "%s[", leading_comma ? "," : "");
if (top_depth)
top_depth->last_action = DN_JSBAction_PushArray; // Record the push on the now, previous depth
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_PopArray(DN_JSBBuilder *builder, char *buf, size_t buf_size)
{
DN_JSBDepth *top_depth = DN_JSB_PeekDepth_(builder, 0);
if (!top_depth || top_depth->type != DN_JSBDepthType_Array)
return DN_JSBResult_BadAPIUsage;
bool had_children = top_depth->last_action != DN_JSBAction_Nil;
builder->depth_count--; // Remove the depth entry from the stack
DN_JSBDepth *new_top = DN_JSB_PeekDepth_(builder, 0);
if (new_top)
new_top->last_action = DN_JSBAction_PopArray;
if (builder->pretty && had_children) {
DN_JSB_AppendF_(builder, buf, buf_size, "\n");
DN_JSB_Indent_(builder, buf, buf_size, builder->depth_count);
}
DN_JSBResult result = DN_JSB_AppendF_(builder, buf, buf_size, "]");
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_KeyF(DN_JSBBuilder *builder, char *buf, size_t buf_size, char const *fmt, ...)
{
DN_JSBDepth *top_depth = DN_JSB_PeekDepth_(builder, 0);
if (!top_depth || top_depth->last_action == DN_JSBAction_Key || top_depth->last_action == DN_JSBAction_PushArray)
return DN_JSBResult_BadAPIUsage;
va_list args;
va_start(args, fmt);
if (builder->pretty) {
if (top_depth->last_action != DN_JSBAction_Nil) {
DN_JSB_AppendF_(builder, buf, buf_size, ",\n");
} else {
DN_JSB_AppendF_(builder, buf, buf_size, "\n");
}
DN_JSB_Indent_(builder, buf, buf_size, builder->depth_count);
DN_JSB_AppendF_(builder, buf, buf_size, "\"");
DN_JSB_AppendFV_(builder, buf, buf_size, fmt, args);
DN_JSBResult result = DN_JSB_AppendF_(builder, buf, buf_size, "\": ");
va_end(args);
if (result == DN_JSBResult_Success)
top_depth->last_action = DN_JSBAction_Key;
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSB_AppendF_(builder, buf, buf_size, "%s\"", top_depth->last_action != DN_JSBAction_Nil ? "," : "");
DN_JSB_AppendFV_(builder, buf, buf_size, fmt, args);
DN_JSBResult result = DN_JSB_AppendF_(builder, buf, buf_size, "\":");
va_end(args);
if (result == DN_JSBResult_Success)
top_depth->last_action = DN_JSBAction_Key;
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_ValueStringF(DN_JSBBuilder *builder, char *buf, size_t buf_size, char const *fmt, ...)
{
DN_JSBResult result = DN_JSB_BeginWriteValue_(builder, buf, buf_size);
if (result == DN_JSBResult_Success) {
DN_JSB_AppendF_(builder, buf, buf_size, "\"");
va_list args;
va_start(args, fmt);
DN_JSB_AppendFV_(builder, buf, buf_size, fmt, args);
va_end(args);
result = DN_JSB_AppendF_(builder, buf, buf_size, "\"");
DN_JSB_FinishWriteValue_(builder, result);
}
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_ValueNull(DN_JSBBuilder *builder, char *buf, size_t buf_size)
{
DN_JSBResult result = DN_JSB_BeginWriteValue_(builder, buf, buf_size);
if (result == DN_JSBResult_Success) {
result = DN_JSB_AppendF_(builder, buf, buf_size, "null");
DN_JSB_FinishWriteValue_(builder, result);
}
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_ValueBool(DN_JSBBuilder *builder, char *buf, size_t buf_size, bool flag)
{
DN_JSBResult result = DN_JSB_BeginWriteValue_(builder, buf, buf_size);
if (result == DN_JSBResult_Success) {
result = DN_JSB_AppendF_(builder, buf, buf_size, flag ? "true" : "false");
DN_JSB_FinishWriteValue_(builder, result);
}
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_ValueNumber(DN_JSBBuilder *builder, char *buf, size_t buf_size, double number)
{
DN_JSBResult result = DN_JSB_BeginWriteValue_(builder, buf, buf_size);
if (result == DN_JSBResult_Success) {
result = DN_JSB_AppendF_(builder, buf, buf_size, "%.17G", number);
DN_JSB_FinishWriteValue_(builder, result);
}
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_BeginWriteValue_(DN_JSBBuilder *builder, char *buf, size_t buf_size)
{
DN_JSBDepth *top = DN_JSB_PeekDepth_(builder, 0);
if (!top)
return DN_JSBResult_BadAPIUsage;
bool is_key = top->last_action == DN_JSBAction_Key;
bool is_array = top->type == DN_JSBDepthType_Array;
if (!is_key && !is_array)
return DN_JSBResult_BadAPIUsage;
DN_JSBResult result = DN_JSBResult_Success;
if (top->type == DN_JSBDepthType_Array) {
if (builder->pretty) {
if (top->last_action != DN_JSBAction_Nil) {
DN_JSB_AppendF_(builder, buf, buf_size, ",\n");
} else {
DN_JSB_AppendF_(builder, buf, buf_size, "\n");
}
DN_JSB_Indent_(builder, buf, buf_size, builder->depth_count);
} else if (top->last_action != DN_JSBAction_Nil) {
result = DN_JSB_AppendF_(builder, buf, buf_size, ",");
}
}
return result;
}
void DN_JSB_FinishWriteValue_(DN_JSBBuilder *builder, DN_JSBResult last_value_raw_str_result)
{
if (last_value_raw_str_result == DN_JSBResult_Success) {
DN_JSBDepth *top_depth = DN_JSB_PeekDepth_(builder, 0);
top_depth->last_action = DN_JSBAction_Value;
}
}
DN_JSBResult DN_JSB_AppendFV_(DN_JSBBuilder *builder, char *buf, size_t buf_size, char const *fmt, va_list args)
{
// NOTE: Calc size required
size_t size = 0;
{
va_list args_copy;
va_copy(args_copy, args);
size = DN_JSB_VSNPrintF(0, 0, fmt, args_copy);
va_end(args_copy);
}
// NOTE: Do the write
DN_JSBResult result = DN_JSBResult_Success;
if (buf) {
if (builder->p > buf_size)
return DN_JSBResult_BadAPIUsage;
char *dest = buf + builder->p;
size_t dest_size = (buf + buf_size) - dest;
if ((size + 1) <= dest_size) { // NOTE: +1 because vsnprintf always null-terminates the stream
DN_JSB_VSNPrintF(dest, dest_size, fmt, args);
} else {
result = DN_JSBResult_BufOutOfMem;
}
}
if (result == DN_JSBResult_Success)
builder->p += size;
if (builder->error == DN_JSBResult_Success)
builder->error = result;
return result;
}
DN_JSBResult DN_JSB_AppendF_(DN_JSBBuilder *builder, char *buf, size_t buf_size, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_JSBResult result = DN_JSB_AppendFV_(builder, buf, buf_size, fmt, args);
va_end(args);
return result;
}
+73
View File
@@ -0,0 +1,73 @@
#if !defined(DN_JSON_BUILDER_H)
#define DN_JSON_BUILDER_H
#include <stdarg.h>
#if !defined(__cplusplus)
#include <stdbool.h>
#endif
#if !defined(DN_JSB_VSNPrintF)
#include <stdio.h>
#define DN_JSB_VSNPrintF(buf, size, fmt, args) vsnprintf(buf, size, fmt, args)
#endif
typedef enum DN_JSBResult {
DN_JSBResult_Success,
DN_JSBResult_BadAPIUsage,
DN_JSBResult_DepthArrayOutOfMem,
DN_JSBResult_BufOutOfMem,
} DN_JSBResult;
typedef enum DN_JSBPrettify {
DN_JSBPrettify_No,
DN_JSBPrettify_Yes,
} DN_JSBPrettify;
typedef enum DN_JSBDepthType {
DN_JSBDepthType_Nil,
DN_JSBDepthType_Object,
DN_JSBDepthType_Array,
} DN_JSBDepthType;
typedef enum DN_JSBAction {
DN_JSBAction_Nil,
DN_JSBAction_PushObject,
DN_JSBAction_PopObject,
DN_JSBAction_PushArray,
DN_JSBAction_PopArray,
DN_JSBAction_Key,
DN_JSBAction_Value,
} DN_JSBAction;
typedef struct DN_JSBDepth {
DN_JSBDepthType type;
DN_JSBAction last_action;
} DN_JSBDepth;
typedef struct DN_JSBBuilder {
DN_JSBDepth* depth;
size_t depth_count;
size_t depth_max;
size_t p; // Size required not incl- the null-terminator (e.g. To build, pass in `p + 1` bytes)
DN_JSBResult error;
DN_JSBPrettify pretty;
} DN_JSBBuilder;
DN_JSBResult DN_JSB_PushObject (DN_JSBBuilder *builder, char *buf, size_t buf_size);
DN_JSBResult DN_JSB_PopObject (DN_JSBBuilder *builder, char *buf, size_t buf_size);
DN_JSBResult DN_JSB_PushArray (DN_JSBBuilder *builder, char *buf, size_t buf_size);
DN_JSBResult DN_JSB_PopArray (DN_JSBBuilder *builder, char *buf, size_t buf_size);
DN_JSBResult DN_JSB_KeyF (DN_JSBBuilder *builder, char *buf, size_t buf_size, char const *fmt, ...);
DN_JSBResult DN_JSB_ValueStringF (DN_JSBBuilder *builder, char *buf, size_t buf_size, char const *fmt, ...);
DN_JSBResult DN_JSB_ValueBool (DN_JSBBuilder *builder, char *buf, size_t buf_size, bool flag);
DN_JSBResult DN_JSB_ValueNull (DN_JSBBuilder *builder, char *buf, size_t buf_size);
DN_JSBResult DN_JSB_ValueNumber (DN_JSBBuilder *builder, char *buf, size_t buf_size, double number);
DN_JSBDepth * DN_JSB_PeekDepth_ (DN_JSBBuilder *builder, size_t offset);
bool DN_JSB_PushDepth_ (DN_JSBBuilder *builder, DN_JSBDepthType type);
DN_JSBResult DN_JSB_AppendFV_ (DN_JSBBuilder *builder, char *buf, size_t buf_size, char const *fmt, va_list args);
DN_JSBResult DN_JSB_AppendF_ (DN_JSBBuilder *builder, char *buf, size_t buf_size, char const *fmt, ...);
DN_JSBResult DN_JSB_BeginWriteValue_ (DN_JSBBuilder *builder, char *buf, size_t buf_size);
void DN_JSB_FinishWriteValue_(DN_JSBBuilder *builder, DN_JSBResult last_value_raw_str_result);
#endif // !defined(DN_JSON_BUILDER_H)
+3
View File
@@ -160,6 +160,9 @@ typedef struct DN_UTCore
DN_UTStr8Link *output; DN_UTStr8Link *output;
} DN_UTCore; } DN_UTCore;
DN_UTCore DN_UT_Init();
void DN_UT_Deinit(DN_UTCore *ut);
void DN_UT_BeginFV(DN_UTCore *test, char const *fmt, va_list args); void DN_UT_BeginFV(DN_UTCore *test, char const *fmt, va_list args);
void DN_UT_BeginF(DN_UTCore *test, char const *fmt, ...); void DN_UT_BeginF(DN_UTCore *test, char const *fmt, ...);
void DN_UT_End(DN_UTCore *test); void DN_UT_End(DN_UTCore *test);
+15 -14
View File
@@ -50,9 +50,9 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
#endif #endif
} }
{ {
os->arena = DN_ArenaFromMemFuncs(DN_Megabytes(1), DN_Kilobytes(4), DN_ArenaFlags_NoAllocTrack, DN_ArenaMemFuncsGetDefaults()); os->mem = DN_MemListFromMemFuncs(DN_Megabytes(1), DN_Kilobytes(4), DN_MemFlags_NoAllocTrack, DN_MemFuncsDefault());
os->arena = DN_ArenaFromMemList(&os->mem);
#if defined(DN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
os->platform_context = DN_ArenaNew(&os->arena, DN_OSW32Core, DN_ZMem_Yes); os->platform_context = DN_ArenaNew(&os->arena, DN_OSW32Core, DN_ZMem_Yes);
@@ -97,7 +97,8 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
#if DN_H_WITH_OS #if DN_H_WITH_OS
// 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_ArenaFromMemFuncs(DN_Megabytes(1), DN_Kilobytes(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak, DN_ArenaMemFuncsGetDefaults()); dn->leak.alloc_table_mem = DN_MemListFromMemFuncs(DN_Megabytes(1), DN_Kilobytes(512), DN_MemFlags_NoAllocTrack | DN_MemFlags_AllocCanLeak, DN_MemFuncsDefault());
dn->leak.alloc_table_arena = DN_ArenaFromMemList(&dn->leak.alloc_table_mem);
dn->leak.alloc_table = DN_DSMapInit<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
} }
@@ -106,7 +107,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
DN_Assert(dn->os_init); DN_Assert(dn->os_init);
#if DN_H_WITH_OS #if DN_H_WITH_OS
DN_TCInitArgs *tc_init_args = args ? &args->thread_context_init_args : nullptr; DN_TCInitArgs *tc_init_args = args ? &args->thread_context_init_args : nullptr;
DN_TCInitFromMemFuncs(&dn->main_tc, DN_OS_ThreadID(), tc_init_args, DN_ArenaMemFuncsGetDefaults()); DN_TCInitFromMemFuncs(&dn->main_tc, DN_OS_ThreadID(), tc_init_args, DN_MemFuncsDefault());
DN_TCEquip(&dn->main_tc); DN_TCEquip(&dn->main_tc);
#endif #endif
} }
@@ -133,17 +134,17 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
if (DN_BitIsSet(flags, DN_InitFlags_ThreadContext)) { if (DN_BitIsSet(flags, DN_InitFlags_ThreadContext)) {
DN_Arena *arena = dn->main_tc.main_arena; DN_Arena *arena = dn->main_tc.main_arena;
DN_Str8 mem_funcs = DN_Str8Lit(""); DN_Str8 mem_funcs = DN_Str8Lit("");
switch (arena->mem_funcs.type) { switch (arena->mem->funcs.type) {
case DN_ArenaMemFuncType_Nil: break; case DN_MemFuncsType_Nil: break;
case DN_ArenaMemFuncType_Basic: mem_funcs = DN_Str8Lit("Basic"); break; case DN_MemFuncsType_Heap: mem_funcs = DN_Str8Lit("Heap"); break;
case DN_ArenaMemFuncType_VMem: mem_funcs = DN_Str8Lit("VMem"); break; case DN_MemFuncsType_Virtual: mem_funcs = DN_Str8Lit("Virtual"); break;
} }
DN_Str8x32 main_commit = DN_ByteCountStr8x32(dn->main_tc.main_arena->curr->commit); DN_Str8x32 main_commit = DN_ByteCountStr8x32(dn->main_tc.main_arena->mem->curr->commit);
DN_Str8x32 main_reserve = DN_ByteCountStr8x32(dn->main_tc.main_arena->curr->reserve); DN_Str8x32 main_reserve = DN_ByteCountStr8x32(dn->main_tc.main_arena->mem->curr->reserve);
DN_Str8x32 temp_commit = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->curr->commit); DN_Str8x32 temp_commit = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->mem->curr->commit);
DN_Str8x32 temp_reserve = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->curr->reserve); DN_Str8x32 temp_reserve = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->mem->curr->reserve);
DN_Str8x32 err_commit = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->curr->commit); DN_Str8x32 err_commit = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->mem->curr->commit);
DN_Str8x32 err_reserve = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->curr->reserve); DN_Str8x32 err_reserve = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->mem->curr->reserve);
DN_FmtAppendTruncate(buf, DN_FmtAppendTruncate(buf,
&buf_size, &buf_size,
sizeof(buf), sizeof(buf),
+64 -4
View File
@@ -82,6 +82,65 @@
// //
// 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.
//
// ASAN Arena Poisoning
// When compiled with address sanitizer (.e.g -fsanitize=address) you can optionally enable
// memory region poisoning on the inbuilt arena's to catch in certain scenarios, use-after-free
//
// #define DN_ASAN_POISON 1
//
// Since arenas manage their own block of memory it does not automatically benefit from ASAN's
// memory markup that ASAN does and so it is implemented manually by using the ASAN user-level
// poisoning APIs. Similarly, since the arena recycles its own memory rather than release back
// to the OS, poisoning is not as effective for arenas but every little bit helps.
//
// Scrub Uninitialised Memory
// If this macro is defined, temp memory that is returned to an arena, or allocations freed by
// a pool are scrubbed to this specified byte, in absence of this bytes returned to the
// allocators are left as-is or memset to 0. For example to scrub bytes to 0xCD (MSVC's
// pattern) define as follows:
//
// #define DN_SCRUB_UNINIT_MEM_BYTE 0xCD
//
// Due to the recycling of memory in arenas and pool, similarly to ASAN poisoning this reduces
// the window in which a use-after-free can be detected using this guard, however every little
// bit helps.
//
// Arena temp memory use-after-free (UAF) tooling
// UAF Guard
// Set the following preprocessor value to 1 to enable UAF protection when using
// scratch/temporary memory functionality. Defaults to off, or 0 if not specified
//
// #define DN_ARENA_TEMP_MEM_UAF_GUARD 1
//
// This enables arenas to markup itself with the active memory region and subsequent
// allocations check if the allocation belongs to the same or different region. Different
// regions cause a UAF violation.
//
// More detailed diagnostics can be enabled by setting the flag DN_ArenaFlags_TempMemUAFGuard
// on the affected arenas. Note that this incurs a performance penalty as each memory region
// will store a stacktrace of its creation. It's recommended in development builds to always
// run with temp-memory guarding, if a violation occurs, then enable tracing on the arena to
// pinpoint the issue.
//
// Enabling memory guard incurs additional memory requirements from the arena's backing
// memory block and additional book-keeping fields on each arena and their temp memory
// instances.
//
// UAF Tracing
// Set the following preprocessor value to 1 to enable tracing when the UAF guard triggers.
// Defaults to off, or 0 if not specified.
//
// #define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 1
//
// This opts in all arenas to tracing functionality by default globally. Arenas can opt out
// by setting the flag DN_ArenaFlags_TempMemUAFTraceDisable on the arena. The disable flag
// takes precedence over all other settings including the global preprocessor macro and the
// enablement flag (DN_ArenaFlags_TempMemUAFTrace).
//
// Tracing incurs an additional much heavier performance penalty than the UAF guard due to
// the stacktrace that is stored per region to report to the user when a UAF guard violation
// occurs.
#include "Base/dn_base.h" #include "Base/dn_base.h"
#include "Base/dn_base_assert.h" #include "Base/dn_base_assert.h"
@@ -110,10 +169,10 @@ enum DN_InitFlags_
{ {
DN_InitFlags_Nil = 0, DN_InitFlags_Nil = 0,
DN_InitFlags_OS = (1 << 0), DN_InitFlags_OS = (1 << 0),
DN_InitFlags_LeakTracker = (1 << 1) | DN_InitFlags_OS, DN_InitFlags_ThreadContext = (1 << 1) | DN_InitFlags_OS,
DN_InitFlags_LogLibFeatures = (1 << 2), DN_InitFlags_LeakTracker = (1 << 2) | DN_InitFlags_OS,
DN_InitFlags_LogCPUFeatures = (1 << 3) | DN_InitFlags_OS, DN_InitFlags_LogLibFeatures = (1 << 3),
DN_InitFlags_ThreadContext = (1 << 4) | DN_InitFlags_OS, DN_InitFlags_LogCPUFeatures = (1 << 4) | DN_InitFlags_OS,
DN_InitFlags_LogAllFeatures = DN_InitFlags_LogLibFeatures | DN_InitFlags_LogCPUFeatures, DN_InitFlags_LogAllFeatures = DN_InitFlags_LogLibFeatures | DN_InitFlags_LogCPUFeatures,
}; };
@@ -124,6 +183,7 @@ struct DN_Core
DN_USize mem_allocs_frame; DN_USize mem_allocs_frame;
DN_LeakTracker leak; DN_LeakTracker leak;
DN_U32 log_level_to_show_from;
DN_LogPrintFunc* print_func; DN_LogPrintFunc* print_func;
void* print_func_context; void* print_func_context;
+6 -5
View File
@@ -39,7 +39,7 @@ pushd %build_dir%
where /q emcc && ( where /q emcc && (
echo [BUILD] Emscripten emcc detected, compiling ... echo [BUILD] Emscripten emcc detected, compiling ...
call emcc -g -msimd128 -msse2 %flags% -o %build_dir%\dn_unit_tests_emcc.js -s FETCH=1 -pthread -s ASYNCIFY=1 -lwebsocket -Wall call emcc -g -msimd128 -msse2 %flags% -o %build_dir%\dn_unit_tests_emcc.js -s FETCH=1 -pthread -s ASYNCIFY=1 -lwebsocket -Wall || echo Failed&& exit /b 1
) )
where /q cl && ( where /q cl && (
@@ -50,15 +50,16 @@ pushd %build_dir%
) )
set msvc_cmd=!msvc_cmd! -link set msvc_cmd=!msvc_cmd! -link
powershell -Command "$time = Measure-Command { !msvc_cmd! | Out-Default }; Write-Host '[BUILD] msvc:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1 powershell -Command "$time = Measure-Command { !msvc_cmd! | Out-Default }; Write-Host '[BUILD] msvc:'$time.TotalSeconds's'; exit $LASTEXITCODE" || echo MSVC build failed&& exit /b 1
call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -link echo [BUILD] Single header generator ...
call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single-Header call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -link || echo Single header generator build failed&& exit /b 1
call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single-Header || echo Single header generation failed&& exit /b 1
) )
where /q clang-cl && ( where /q clang-cl && (
echo [BUILD] LLVM clang-cl detected, compiling ... echo [BUILD] LLVM clang-cl detected, compiling ...
set clang_cmd=clang-cl -MT %msvc_driver_flags% -fsanitize=undefined -Fe:dn_unit_tests_clang -link set clang_cmd=clang-cl -MT %msvc_driver_flags% -fsanitize=undefined -Fe:dn_unit_tests_clang -link
powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1 powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || echo CLANG build failed&& exit /b 1
) )
exit /b 1 exit /b 1
+49 -81
View File
@@ -29,10 +29,12 @@ struct File
static void AppendCppFileLineByLine(DN_Str8Builder *dest, DN_Str8 cpp_path) static void AppendCppFileLineByLine(DN_Str8Builder *dest, DN_Str8 cpp_path)
{ {
DN_OSErrSink *err = DN_OS_ErrSinkBeginDefault(); DN_TCScratch scratch = DN_TCScratchBegin(&dest->arena, 1);
DN_Str8 buffer = DN_OS_FileReadAllTLS(cpp_path, err); DN_ErrSink *err = DN_TCErrSinkBeginDefault();
DN_OS_ErrSinkEndAndExitIfErrorF(err, -1, "Failed to load file from '%S' for appending", cpp_path); DN_Str8 buffer = DN_OS_FileReadAllArena(&scratch.arena, cpp_path, err);
DN_ErrSinkEndExitIfErrorF(err, -1, "Failed to load file from '%S' for appending", cpp_path);
bool inside_clangd_preprocessor_block = false;
for (DN_Str8 inc_walker = buffer;;) { for (DN_Str8 inc_walker = buffer;;) {
DN_Str8BSplitResult split = DN_Str8BSplit(inc_walker, DN_Str8Lit("\n")); DN_Str8BSplitResult split = DN_Str8BSplit(inc_walker, DN_Str8Lit("\n"));
if (split.lhs.size == 0) if (split.lhs.size == 0)
@@ -42,42 +44,59 @@ static void AppendCppFileLineByLine(DN_Str8Builder *dest, DN_Str8 cpp_path)
// NOTE: Trim the whitespace, mainly for windows, the file we read will have \r\n whereas we just want to emit \n // NOTE: Trim the whitespace, mainly for windows, the file we read will have \r\n whereas we just want to emit \n
DN_Str8 line = DN_Str8TrimTailWhitespace(split.lhs); DN_Str8 line = DN_Str8TrimTailWhitespace(split.lhs);
// NOTE: Comment out any #include "../dn_.*" matches if we encounter one // NOTE: Detect if we're inside a clangd preprocessor block
DN_Str8FindResult find = DN_Str8FindStr8(line, DN_Str8Lit("#include \"../dn_"), DN_Str8EqCase_Sensitive); // TODO: This breaks if there's any nested #if's in the block (we naiively match on #endif)
{ bool commented_out = false;
if (!inside_clangd_preprocessor_block) {
DN_Str8FindResult find = DN_Str8FindStr8(line, DN_Str8Lit("#if defined(_CLANGD)"), DN_Str8EqCase_Sensitive);
if (find.found) { if (find.found) {
line = DN_Str8FromTLSF("%S// DN: Single header generator commented out this header => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer)); line = DN_Str8FromFmtArena(&scratch.arena, "%S// DN: Single header generator commented out => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
commented_out = true;
// The only time we use '../dn_.*' is for LSP purposes, so we inside_clangd_preprocessor_block = true;
// don't care about inlining it, hence we don't set 'include_file'
} }
} }
// NOTE: Inline any other relative includes if we encounter one // NOTE: Inline relative includes as long as we're not inside a CLANDG block
// (Right now DN only includes stb_sprintf with a relative path)
DN_Str8 extra_include_path = {}; DN_Str8 extra_include_path = {};
if (!find.found) { if (!inside_clangd_preprocessor_block) {
find = DN_Str8FindStr8(line, DN_Str8Lit("#include \""), DN_Str8EqCase_Sensitive); DN_Str8 ignore_patterns[] = {
DN_Str8Lit("#include \"dn.h\""),
DN_Str8Lit("#include \"dn.cpp\""),
};
DN_Str8FindResult ignore = DN_Str8FindStr8Array(line, ignore_patterns, DN_ArrayCountU(ignore_patterns), DN_Str8EqCase_Sensitive);
if (!ignore.found) {
DN_Str8FindResult find = DN_Str8FindStr8(line, DN_Str8Lit("#include \""), DN_Str8EqCase_Sensitive);
if (find.found) { if (find.found) {
line = DN_Str8FromTLSF("%S// DN: Single header generator commented out this header => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer)); line = DN_Str8FromFmtArena(&scratch.arena, "%S// DN: Single header generator commented out => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
DN_Str8 rel_include_path = DN_Str8TrimWhitespaceAround(find.after_match_to_end_of_buffer); DN_Str8 rel_include_path = DN_Str8TrimWhitespaceAround(find.after_match_to_end_of_buffer);
DN_Str8 root_dir = DN_Str8FileDirectoryFromPath(cpp_path); DN_Str8 root_dir = DN_Str8FileDirectoryFromPath(cpp_path);
extra_include_path = DN_OS_PathFFromTLS("%S/%S", root_dir, DN_Str8TrimSuffix(rel_include_path, DN_Str8Lit("\""))); extra_include_path = DN_OS_PathF(&scratch.arena, "%S/%S", root_dir, DN_Str8TrimSuffix(rel_include_path, DN_Str8Lit("\"")));
}
} }
} }
DN_Str8BuilderAppendRef(dest, line); // NOTE: Detect if we're at the end of the CLAND block
if (inside_clangd_preprocessor_block) {
if (!commented_out)
line = DN_Str8FromFmtArena(&scratch.arena, "// %S", line);
if (DN_Str8FindStr8(line, DN_Str8Lit("#endif"), DN_Str8EqCase_Sensitive).found)
inside_clangd_preprocessor_block = false;
}
DN_Str8BuilderAppendCopy(dest, line);
DN_Str8BuilderAppendRef(dest, DN_Str8Lit("\n")); DN_Str8BuilderAppendRef(dest, DN_Str8Lit("\n"));
if (extra_include_path.size) if (extra_include_path.size)
AppendCppFileLineByLine(dest, extra_include_path); AppendCppFileLineByLine(dest, extra_include_path);
} }
DN_TCScratchEnd(&scratch);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
DN_Core dn = {}; DN_Core dn = {};
DN_Init(&dn, DN_InitFlags_OS, nullptr); DN_Init(&dn, DN_InitFlags_OS | DN_InitFlags_ThreadContext, nullptr);
if (argc != 3) { if (argc != 3) {
DN_OS_PrintErrF("USAGE: %s <path/to/dn/Source> <output_dir>", argv[0]); DN_OS_PrintErrF("USAGE: %s <path/to/dn/Source> <output_dir>", argv[0]);
@@ -91,81 +110,30 @@ int main(int argc, char **argv)
return -1; return -1;
} }
File const FILES[] = { DN_Str8 const REL_FILE_PATHS[] = {
{FileType_Header, DN_Str8Lit("dn.h")}, DN_Str8Lit("dn"),
{FileType_Impl, DN_Str8Lit("dn.cpp")},
};
for (DN_ForIndexU(type, FileType_Count)) {
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
for (DN_ForItCArray(it, File const, FILES)) {
if (it.data->type != type)
continue;
// NOTE: Parse the include files in the *_inc.[h|cpp] files
DN_Str8 path = DN_OS_PathFFromTLS("%S/%S", dn_root_dir, it.data->file_name);
{
DN_OSErrSink *err = DN_OS_ErrSinkBeginDefault();
DN_Str8 file_buffer = DN_OS_FileReadAllTLS(path, err);
DN_OS_ErrSinkEndAndExitIfErrorF(err, -1, "Failed to load file");
// NOTE: Walk the top-level dn_*_inc.[h|cpp] files
for (DN_Str8 walker = file_buffer;;) {
DN_Str8BSplitResult split = DN_Str8BSplit(walker, DN_Str8Lit("\n"));
if (split.lhs.size == 0)
break;
// NOTE: Parse the line, if it was a #include, extract it into this string
DN_Str8 include_file = {};
{
walker = split.rhs;
DN_Str8 line = DN_Str8TrimTailWhitespace(split.lhs);
// NOTE: Comment out any #include "dn_.*" matches if we encounter one
DN_Str8FindResult find = DN_Str8FindStr8(line, DN_Str8Lit("#include \""), DN_Str8EqCase_Sensitive);
{
if (find.found && DN_Str8FindStr8(line, DN_Str8Lit("dn_"), DN_Str8EqCase_Sensitive).found) {
line = DN_Str8FromTLSF("%S// DN: Single header generator inlined this file => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
include_file = DN_Str8BSplit(find.after_match_to_end_of_buffer, DN_Str8Lit("\"")).lhs;
DN_Assert(include_file.size);
}
}
// NOTE: Record the line
DN_Str8BuilderAppendRef(&builder, line);
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
}
if (include_file.size) { // NOTE: If the line was a include file, we will inline the included file
DN_Str8 include_path = DN_OS_PathFFromTLS("%S/%S", dn_root_dir, include_file);
AppendCppFileLineByLine(&builder, include_path);
}
}
}
}
DN_Str8 extra_files[] = {
DN_Str8Lit("Extra/dn_math"),
DN_Str8Lit("Extra/dn_async"), DN_Str8Lit("Extra/dn_async"),
DN_Str8Lit("Extra/dn_bin_pack"), DN_Str8Lit("Extra/dn_bin_pack"),
DN_Str8Lit("Extra/dn_csv"), DN_Str8Lit("Extra/dn_csv"),
DN_Str8Lit("Extra/dn_hash"),
DN_Str8Lit("Extra/dn_helpers"), DN_Str8Lit("Extra/dn_helpers"),
}; };
for (DN_ForIndexU(type, FileType_Count)) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_Str8 suffix = type == FileType_Header ? DN_Str8Lit("h") : DN_Str8Lit("cpp"); DN_Str8 suffix = type == FileType_Header ? DN_Str8Lit("h") : DN_Str8Lit("cpp");
for (DN_ForItCArray(extra_it, DN_Str8, extra_files)) { for (DN_ForItCArray(extra_it, DN_Str8 const, REL_FILE_PATHS)) {
DN_Str8 extra_path = DN_OS_PathFFromTLS("%S/%S.%S", dn_root_dir, *extra_it.data, suffix); DN_Str8 extra_path = DN_OS_PathF(&scratch.arena, "%S/%S.%S", dn_root_dir, *extra_it.data, suffix);
AppendCppFileLineByLine(&builder, extra_path); AppendCppFileLineByLine(&builder, extra_path);
} }
DN_Date date = DN_OS_DateLocalTimeNow(); DN_Date date = DN_OS_DateLocalTimeNow();
DN_Str8BuilderPrependF(&builder, "// Generated by the DN single header generator %04u-%02u-%02u %02u:%02u:%02u\n\n", date.year, date.month, date.day, date.hour, date.minutes, date.seconds); DN_Str8BuilderPrependF(&builder, "// Generated by the DN single header generator %04u-%02u-%02u %02u:%02u:%02u\n\n", date.year, date.month, date.day, date.hour, date.minutes, date.seconds);
DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8BuilderBuildFromTLS(&builder)); DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8BuilderBuild(&builder, &scratch.arena));
DN_Str8 single_header_path = DN_OS_PathFFromTLS("%S/dn_single_header.%S", output_dir, suffix); DN_Str8 single_header_path = DN_OS_PathF(&scratch.arena, "%S/dn_single_header.%S", output_dir, suffix);
DN_OSErrSink *err = DN_OS_ErrSinkBeginDefault(); DN_ErrSink *err = DN_TCErrSinkBeginDefault();
DN_OS_FileWriteAllSafe(single_header_path, buffer, err); DN_OS_FileWriteAllSafe(single_header_path, buffer, err);
DN_OS_ErrSinkEndAndExitIfErrorF(err, -1, "Failed to write Single header file '%S'", single_header_path); DN_ErrSinkEndExitIfErrorF(err, -1, "Failed to write Single header file '%S'", single_header_path);
} }
} }