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
+1029 -445
View File
File diff suppressed because it is too large Load Diff
+353 -175
View File
@@ -40,9 +40,11 @@
#if defined(DN_COMPILER_MSVC)
#define DN_MSVC_WARNING_PUSH __pragma(warning(push))
#define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__))
#define DN_MSVC_WARNING_ENABLE(...) __pragma(warning(default :##__VA_ARGS__))
#define DN_MSVC_WARNING_POP __pragma(warning(pop))
#else
#define DN_MSVC_WARNING_PUSH
#define DN_MSVC_WARNING_ENABLE(...)
#define DN_MSVC_WARNING_DISABLE(...)
#define DN_MSVC_WARNING_POP
#endif
@@ -162,6 +164,19 @@
#include <sanitizer/asan_interface.h>
#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
#define DN_Stringify(x) #x
#define DN_TokenCombine2(x, y) x ## y
@@ -191,10 +206,10 @@
#define DN_ForLinkedListIt(it, T, list) struct { DN_USize index; T *data; } it = {0, list}; it.data; it.index++, it.data = ((it).data->next)
#define DN_ForItCArray(it, T, array) struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < DN_ArrayCountU(array); it.index++, it.data = (array) + it.index
#define DN_AlignUpPowerOfTwo(value, pot) (((uintptr_t)(value) + ((uintptr_t)(pot) - 1)) & ~((uintptr_t)(pot) - 1))
#define DN_AlignDownPowerOfTwo(value, pot) ((uintptr_t)(value) & ~((uintptr_t)(pot) - 1))
#define DN_IsPowerOfTwo(value) ((((uintptr_t)(value)) & (((uintptr_t)(value)) - 1)) == 0)
#define DN_IsPowerOfTwoAligned(value, pot) ((((uintptr_t)value) & (((uintptr_t)pot) - 1)) == 0)
#define DN_AlignUpPowerOfTwo(value, pot) (((uintptr_t)(value) + ((uintptr_t)(pot) - 1)) & ~((uintptr_t)(pot) - 1))
#define DN_AlignDownPowerOfTwo(value, pot) ((uintptr_t)(value) & ~((uintptr_t)(pot) - 1))
#define DN_IsPowerOfTwo(value) ((((uintptr_t)(value)) & (((uintptr_t)(value)) - 1)) == 0)
#define DN_IsPowerOfTwoAligned(value, pot) ((((uintptr_t)value) & (((uintptr_t)pot) - 1)) == 0)
// NOTE: String.h Dependencies
#if !defined(DN_Memcpy) || !defined(DN_Memset) || !defined(DN_Memcmp) || !defined(DN_Memmove)
@@ -546,9 +561,9 @@ struct DN_TicketMutex
};
struct DN_Hex32 { char data[32]; };
struct DN_Hex64 { char data[64]; };
struct DN_Hex128 { char data[128]; };
struct DN_Hex32 { char data[32 + 1]; DN_USize size; };
struct DN_Hex64 { char data[64 + 1]; DN_USize size; };
struct DN_Hex128 { char data[128 + 1]; DN_USize size; };
struct DN_HexU64Str8
{
@@ -562,6 +577,11 @@ enum DN_HexFromU64Type
DN_HexFromU64Type_Uppercase,
};
enum DN_TrimLeadingZero
{
DN_TrimLeadingZero_No,
DN_TrimLeadingZero_Yes,
};
struct DN_U8x16 { DN_U8 data[16]; };
struct DN_U8x32 { DN_U8 data[32]; };
@@ -627,12 +647,57 @@ struct DN_U64FromResult
DN_U64 value;
};
struct DN_USizeFromResult
{
bool success;
DN_USize value;
};
struct DN_I64FromResult
{
bool success;
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
{
DN_MemCommit_No,
@@ -689,37 +754,40 @@ enum DN_MemPage_
#define DN_ARENA_COMMIT_SIZE DN_Kilobytes(64)
#endif
enum DN_Allocator
enum DN_MemFuncsType
{
DN_Allocator_Arena,
DN_Allocator_Pool,
DN_MemFuncsType_Nil,
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_U64 used;
DN_U64 commit;
DN_U64 reserve;
DN_U64 reserve_sum;
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;
};
typedef DN_U32 DN_ArenaFlags;
enum DN_ArenaFlags_
struct DN_MemBlock
{
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,
DN_MemBlock* prev;
DN_U64 used;
DN_U64 commit;
DN_U64 reserve;
DN_U64 reserve_sum;
};
struct DN_ArenaInfo
struct DN_MemListInfo
{
DN_U64 used;
DN_U64 commit;
@@ -727,10 +795,80 @@ struct DN_ArenaInfo
DN_U64 blocks;
};
struct DN_ArenaStats
struct DN_MemStats
{
DN_ArenaInfo info;
DN_ArenaInfo hwm;
DN_MemListInfo info;
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
@@ -739,51 +877,24 @@ struct DN_ArenaStatsStr8x64
DN_Str8x64 hwm;
};
enum DN_ArenaMemFuncType
enum DN_ArenaReset
{
DN_ArenaMemFuncType_Nil,
DN_ArenaMemFuncType_Basic,
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;
DN_ArenaReset_No,
DN_ArenaReset_Yes,
};
struct DN_Arena
{
DN_ArenaMemFuncs mem_funcs;
DN_ArenaBlock *curr;
DN_ArenaStats stats;
DN_ArenaFlags flags;
DN_Str8 label;
DN_Arena *prev, *next;
};
struct DN_ArenaTempMem
{
DN_Arena *arena;
DN_U64 used_sum;
};
struct DN_ArenaTempMemScope
{
DN_ArenaTempMemScope(DN_Arena *arena);
~DN_ArenaTempMemScope();
DN_ArenaTempMem mem;
DN_MemList* mem;
#if DN_ARENA_TEMP_MEM_UAF_GUARD
DN_U32 uaf_guard_id;
DN_MemListTemp* uaf_guard_temp_mem;
DN_U32 uaf_guard_prev_id;
DN_MemListTemp* uaf_guard_prev_temp_mem;
bool uaf_guard_is_being_checked;
#else
DN_MemListTemp temp_mem;
#endif
};
DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64);
@@ -857,6 +968,13 @@ struct DN_UTF8DecodeIterator
DN_U32 codepoint;
};
typedef DN_U32 DN_CodepointCountFlags;
enum DN_CodepointCountFlags_
{
DN_CodepointCountFlags_Nil = 0,
DN_CodepointCountFlags_SkipANSICode = 1 << 0,
};
struct DN_NibbleFromU8Result
{
char nibble0;
@@ -877,8 +995,11 @@ enum DN_Str8IsAllType
struct DN_Str8BSplitResult
{
DN_Str8 lhs;
DN_Str8 rhs;
// 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 rhs;
};
struct DN_Str8FindResult
@@ -902,16 +1023,18 @@ enum DN_Str8FindFlag_
DN_Str8FindFlag_AlphaNum = DN_Str8FindFlag_Alphabet | DN_Str8FindFlag_Digit,
};
enum DN_Str8SplitIncludeEmptyStrings
typedef DN_USize DN_Str8SplitFlags;
enum DN_Str8SplitFlags_
{
DN_Str8SplitIncludeEmptyStrings_No,
DN_Str8SplitIncludeEmptyStrings_Yes,
DN_Str8SplitFlags_ExcludeEmptyStrings = 1 << 0,
DN_Str8SplitFlags_HandleQuotedStrings = 1 << 1,
};
struct DN_Str8TruncateResult
struct DN_Str8TruncResult
{
bool truncated;
DN_Str8 str8;
bool truncated;
DN_Str8 str8;
DN_USize size_req; // Not including null-terminator
};
struct DN_Str8SplitResult
@@ -920,6 +1043,14 @@ struct DN_Str8SplitResult
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
{
DN_Str8 string; // The string
@@ -929,9 +1060,9 @@ struct DN_Str8Link
struct DN_Str8Builder
{
DN_Arena *arena; // Allocator to use to back the string list
DN_Str8Link *head; // First string in the linked list of strings
DN_Str8Link *tail; // Last string in the linked list of strings
DN_Arena* arena; // Allocator to use to back the string list
DN_Str8Link* head; // First string in the linked list of strings
DN_Str8Link* tail; // Last string in the linked list of strings
DN_USize string_size; // The size in bytes necessary to construct the current string
DN_USize count; // The number of links in the linked list of strings
};
@@ -1070,9 +1201,8 @@ struct DN_ErrSink
struct DN_TCScratch
{
DN_Arena* arena;
DN_ArenaTempMem temp_mem;
DN_B32 destructed;
DN_Arena arena;
DN_B32 destructed;
};
#if defined(__cplusplus)
@@ -1101,19 +1231,32 @@ struct DN_TCCore // (T)hread (C)ontext sitting in thread-local storage
DN_CallSite call_site;
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 temp_a_arena_;
DN_Arena temp_b_arena_;
DN_Arena err_sink_arena_;
DN_Arena* main_arena;
DN_Pool main_pool;
DN_Arena* temp_a_arena;
DN_Arena* temp_b_arena;
DN_ErrSink err_sink;
DN_Arena* frame_arena;
};
enum DN_TCDeinitArenas
{
DN_TCDeinitArenas_No,
DN_TCDeinitArenas_Yes,
};
struct DN_PCG32 { DN_U64 state; };
struct DN_MurmurHash3 { DN_U64 e[2]; };
@@ -1146,10 +1289,10 @@ struct DN_LogTypeParam
DN_Str8 str8;
};
enum DN_LogColourType
enum DN_ANSIColourMode
{
DN_LogColourType_Fg,
DN_LogColourType_Bg,
DN_ANSIColourMode_Fg,
DN_ANSIColourMode_Bg,
};
struct DN_LogDate
@@ -1169,40 +1312,15 @@ struct DN_LogPrefixSize
DN_USize padding;
};
struct DN_StackTraceFrame
typedef DN_U32 DN_LogFlags;
enum DN_LogFlags_
{
DN_U64 address;
DN_U64 line_number;
DN_Str8 file_name;
DN_Str8 function_name;
DN_LogFlags_Nil = 0,
DN_LogFlags_NoNewLine = 1 << 0,
DN_LogFlags_NoPrefix = 1 << 1,
};
struct DN_StackTraceFrameSlice
{
DN_StackTraceFrame *data;
DN_USize count;
};
struct DN_StackTraceRawFrame
{
void *process;
DN_U64 base_addr;
};
struct DN_StackTraceWalkResult
{
void *process; // [Internal] Windows handle to the process
DN_U64 *base_addr; // The addresses of the functions in the stack trace
DN_U16 size; // The number of `base_addr`'s stored from the walk
};
struct DN_StackTraceWalkResultIterator
{
DN_StackTraceRawFrame raw_frame;
DN_U16 index;
};
typedef void DN_LogPrintFunc(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
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_MSVC_WARNING_PUSH
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_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_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_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)) >> 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)
#define DN_ByteSwapUSize(val) DN_ByteSwap64(val)
#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_Arena DN_ArenaFromBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags);
DN_API DN_Arena DN_ArenaFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags, DN_ArenaMemFuncs mem_funcs);
DN_API void DN_ArenaDeinit (DN_Arena *arena);
DN_API bool DN_ArenaCommit (DN_Arena *arena, DN_U64 size);
DN_API bool DN_ArenaCommitTo (DN_Arena *arena, DN_U64 pos);
DN_API bool DN_ArenaGrow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit);
DN_API void * DN_ArenaAlloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem zmem);
DN_API void * DN_ArenaAllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem zmem);
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);
DN_API DN_MemStats DN_MemStatsSum (DN_MemStats lhs, DN_MemStats rhs);
DN_API DN_MemStats DN_MemStatsSumArray (DN_MemStats const *array, DN_USize size);
DN_API DN_MemList DN_MemListFromBuffer (void *buffer, DN_USize size, DN_MemFlags flags);
DN_API DN_MemList DN_MemListFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags, DN_MemFuncs mem_funcs);
DN_API void DN_MemListDeinit (DN_MemList *mem);
DN_API bool DN_MemListCommit (DN_MemList *mem, DN_U64 size);
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);
#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_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_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_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_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__)
DN_API void DN_TCInit (DN_TCCore *tc, DN_U64 thread_id, DN_Arena *main_arena, DN_Arena *temp_a_arena, DN_Arena *temp_b_arena, DN_Arena *err_sink_arena);
DN_API void DN_TCInitFromMemFuncs (DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_ArenaMemFuncs mem_funcs);
DN_API void DN_TCDeinit (DN_TCCore *tc);
DN_API void DN_TCInitFromMemFuncs (DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_MemFuncs mem_funcs);
DN_API void DN_TCDeinit (DN_TCCore *tc, DN_TCDeinitArenas deinit_arenas);
DN_API void DN_TCEquip (DN_TCCore *tc);
DN_API DN_TCCore* DN_TCGet ();
DN_API DN_Arena* DN_TCMainArena ();
DN_API DN_Arena* DN_TCTempArena (DN_Arena **conflicts, DN_USize count);
DN_API DN_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 void DN_TCScratchEnd (DN_TCScratch *scratch);
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_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_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_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_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 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_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);
@@ -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_Str8FromStruct(ptr) DN_Str8FromPtr((ptr)->data, (ptr)->size)
#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_Str8AllocPool (DN_Pool *pool, DN_USize size);
DN_API DN_Str8 DN_Str8AllocArena (DN_USize size, DN_ZMem z_mem, DN_Arena *arena);
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_Str8FromPtrArena (DN_Arena *arena, void const *data, DN_USize size);
DN_API DN_Str8 DN_Str8FromPtrPool (DN_Pool *pool, void const *data, DN_USize size);
DN_API DN_Str8 DN_Str8FromStr8Arena (DN_Arena *arena, DN_Str8 string);
DN_API DN_Str8 DN_Str8FromStr8Pool (DN_Pool *pool, DN_Str8 string);
DN_API DN_Str8 DN_Str8FromFmtArena (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromCStr8Arena (char const *src, DN_Arena *arena);
DN_API DN_Str8 DN_Str8FromPtrArena (void const *data, DN_USize size, DN_Arena *arena);
DN_API DN_Str8 DN_Str8FromPtrPool (void const *data, DN_USize size, DN_Pool *pool);
DN_API DN_Str8 DN_Str8FromStr8Arena (DN_Str8 string, DN_Arena *arena);
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_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_Str8FromByteCountType (DN_ByteCountType type);
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_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_USize DN_Str8Split (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode);
DN_API DN_Str8SplitResult DN_Str8SplitArena (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, 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_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_Str8FindStr8 (DN_Str8 string, DN_Str8 find, DN_Str8EqCase eq_case);
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_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 DN_Str8TruncateResult DN_Str8TruncateMiddle (DN_Arena *arena, DN_Str8 str8, DN_U32 side_size, DN_Str8 truncator);
DN_API DN_Str8 DN_Str8Lower (DN_Arena *arena, DN_Str8 string);
DN_API DN_Str8 DN_Str8Upper (DN_Arena *arena, DN_Str8 string);
DN_API DN_Str8 DN_Str8PadNewLines (DN_Arena *arena, DN_Str8 src, DN_Str8 pad);
DN_API DN_Str8TruncResult DN_Str8TruncMiddlePtr (DN_Str8 str8, DN_USize side_size, DN_Str8 truncator, char *dest, DN_USize dest_max);
DN_API DN_Str8TruncResult DN_Str8TruncMiddle (DN_Str8 str8, DN_USize side_size, DN_Str8 truncator, DN_Arena *arena);
DN_API DN_Str8 DN_Str8Lower (DN_Str8 string, DN_Arena *arena);
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_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_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_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_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 DN_UTF8DecodeResult DN_UTF8Decode (DN_Str8 stream);
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_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_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_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_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_USize DN_HexFromBytesPtr (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count);
DN_API DN_Str8 DN_HexFromBytesPtrArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena);
DN_API DN_Hex32 DN_HexFromBytes16Ptr (void const *bytes, DN_USize bytes_count);
DN_API DN_Hex64 DN_HexFromBytes32Ptr (void const *bytes, DN_USize bytes_count);
DN_API DN_Hex128 DN_HexFromBytes64Ptr (void const *bytes, DN_USize bytes_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_HexFromPtrBytesArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
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_Hex32 DN_Hex32FromPtr16b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
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_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)
#endif
#define DN_LogResetEscapeCode "\x1b[0m"
#define DN_LogBoldEscapeCode "\x1b[1m"
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB (DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b);
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromU32 (DN_LogColourType colour, DN_U32 value);
#define DN_ANSICodeBoldLit "\x1b[1m"
#define DN_ANSICodeResetLit "\x1b[0m"
DN_API DN_Str8x32 DN_Str8x32FromANSIColourCodeU8RGB (DN_ANSIColourMode mode, DN_U8 r, DN_U8 g, DN_U8 b);
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 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);
#define DN_LogDebugF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Debug), DN_CALL_SITE, 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_LogErrorF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Error), 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_LogDebugF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Debug), DN_CALL_SITE, DN_LogFlags_Nil, 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.
#if defined(DN_FREESTANDING)
+13 -14
View File
@@ -1,15 +1,13 @@
#define DN_BASE_CONTAINERS_CPP
#if defined(_CLANGD)
#include "../dn.h"
#include "../dn.h"
#endif
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)
{
void *result = *data;
*data = DN_ArenaAlloc(arena, size * elem_size, align, zmem);
if (*data) {
if (*data)
*slice_size_field = size;
}
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;
}
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)
{
@@ -324,7 +319,7 @@ void DN_DSMapDeinit(DN_DSMap<T> *map, DN_ZMem z_mem)
return;
// TODO(doyle): Use z_mem
(void)z_mem;
DN_ArenaDeinit(map->arena);
DN_MemListDeinit(map->arena->mem);
*map = {};
}
@@ -564,12 +559,16 @@ bool DN_DSMapResize(DN_DSMap<T> *map, DN_U32 size)
return false;
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 = {};
new_arena.mem_funcs = prev_arena->mem_funcs;
new_arena.flags = prev_arena->flags;
new_arena.label = prev_arena->label;
new_arena.prev = prev_arena->prev;
new_arena.next = prev_arena->next;
new_arena.mem = new_mem;
DN_DSMap<T> new_map = DN_DSMapInit<T>(&new_arena, size, map->flags);
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>
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 = {};
result.type = DN_DSMapKeyType_BufferAsU64NoHash;
+163 -110
View File
@@ -5,26 +5,46 @@
// it stupid simple, structs and functions. Minimal amount of container types with flexible
// construction leads to less duplicated container code and less template meta-programming.
//
// PArray => Pointer (to) Array
// LArray => Literal Array
// Define a C array and size. (P) array macros take a pointer to the aray, its size and its max
// capacity. The (L) array macros take the literal array and derives the max capacity
// automatically using DN_ArrayCountU(l_array).
// Arrays
//
// MyStruct buffer[TB_ASType_Count] = {};
// DN_USize size = 0;
// MyStruct *item_0 = DN_PArrayMake(buffer, &size, DN_ArrayCountU(buffer), DN_ZMem_No);
// MyStruct *item_1 = DN_LArrayMake(buffer, &size, DN_ZMem_No);
// Data structures that have a `T *data`, `DN_USize count` and `DN_USize max` capacity that can be
// dynamically shrunk or expanded.
//
// IArray => Intrusive Array
// Define a struct with the members `data`, `size` and `max`:
// 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
//
// struct MyArray {
// MyStruct *data;
// DN_USize size;
// DN_USize max;
// } my_array = {};
// MyStruct *item = DN_IArrayMake(&my_array, DN_ZMem_No);
// Variants
// PArray => Pointer (to) Array
// LArray => Literal Array
// Define a C array and size. (P) array macros take a pointer to the aray, its size and its max
// capacity. The (L) array macros take the literal array and derives the max capacity
// automatically using DN_ArrayCountU(l_array).
//
// MyStruct buffer[TB_ASType_Count] = {};
// DN_USize size = 0;
// MyStruct *item_0 = DN_PArrayMake(buffer, &size, DN_ArrayCountU(buffer), DN_ZMem_No);
// MyStruct *item_1 = DN_LArrayMake(buffer, &size, DN_ZMem_No);
//
// IArray => Intrusive Array
// Define a struct with the members `data`, `size` and `max`:
//
// struct MyArray {
// MyStruct *data;
// DN_USize size;
// DN_USize max;
// } my_array = {};
// DN_Arena arena = {};
// DN_IArrayResizeFromArena(&my_array, &arena, 256);
// 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
// Define a struct with the members `next`:
@@ -62,6 +82,26 @@
// DN_SentinelDoublyLLInit(&my_list);
// DN_SentinelDoublyLLAppend(&my_list, &new_item);
// 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)
#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_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_SentinelDoublyLLIsSentinel(list, item) ((list) == (item))
#define DN_SentinelDoublyLLIsEmpty(list) (!(list) || ((list) == (list)->next))
@@ -171,10 +221,10 @@ template <typename T> struct DN_DSMapResult
#define DN_SentinelDoublyLLHasItems(list) ((list) && ((list) != (list)->next))
#define DN_SentinelDoublyLLForEach(it, list) auto *it = (list)->next; (it) != (list); (it) = (it)->next
#define DN_SentinelDoublyLLInitArena(list, T, arena) \
do { \
(list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \
DN_SentinelDoublyLLInit(list); \
#define DN_SentinelDoublyLLInitArena(list, T, ptr_arena) \
do { \
(list) = DN_ArenaNew(ptr_arena, T, DN_ZMem_Yes); \
DN_SentinelDoublyLLInit(list); \
} while (0)
#define DN_SentinelDoublyLLInitPool(list, T, pool) \
@@ -286,100 +336,103 @@ template <typename T> struct DN_DSMapResult
#define DN_CppDeclType
#endif
#define DN_PArrayResizeFromPool(ptr, size, max, pool, new_max) DN_CArrayResizeFromPool((void **)&(ptr), size, 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_PArrayGrowFromPool(ptr, size, max, pool, new_max) DN_CArrayGrowFromPool((void **)&(ptr), size, 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_PArrayGrowIfNeededFromPool(ptr, size, max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, 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_PArrayMakeArray(ptr, size, max, count, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(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_PArrayMake(ptr, size, max, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(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_PArrayAddArray(ptr, size, max, items, count, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(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_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_PArrayAppend(ptr, size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(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_PArrayPrepend(ptr, size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(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_PArrayErase(ptr, size, index, erase) DN_CArrayEraseRange(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_PArrayInsert(ptr, size, max, index, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, size, max, sizeof((ptr)[0]), index, &item, 1)
#define DN_PArrayPopFront(ptr, size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopFront(ptr, size, sizeof((ptr)[0]), count)
#define DN_PArrayPopBack(ptr, size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopBack(ptr, size, sizeof((ptr)[0]), count)
#define DN_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, 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, ptr_max, pool, new_max) DN_CArrayGrowFromPool((void **)&(ptr), size, ptr_max, sizeof((ptr)[0]), pool, 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, ptr_max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, ptr_max, sizeof((*ptr)[0]), pool, 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, 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, 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, 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, ptr_size, max) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), 1, DN_ZMem_Yes)
#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, 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, 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, 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, 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, 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, ptr_size, begin_index, count, erase) DN_CArrayEraseRange(ptr, ptr_size, sizeof((ptr)[0]), begin_index, count, erase)
#define DN_PArrayErase(ptr, ptr_size, index, erase) DN_CArrayEraseRange(ptr, ptr_size, sizeof((ptr)[0]), index, 1, erase)
#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, 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, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopFront(ptr, 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_LArrayResizeFromArena(c_array, size, arena, new_max) DN_PArrayResizeFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max)
#define DN_LArrayGrowFromPool(c_array, size, pool, new_max) DN_PArrayGrowFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max)
#define DN_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_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_LArrayMakeArrayZ(c_array, size, count) DN_PArrayMakeArrayZ(c_array, 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_LArrayMakeZ(c_array, size) DN_PArrayMakeZ(c_array, 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_LArrayAdd(c_array, size, item, add) DN_PArrayAdd(c_array, 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_LArrayAppend(c_array, size, item) DN_PArrayAppend(c_array, 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_LArrayPrepend(c_array, size, item) DN_PArrayPrepend(c_array, 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_LArrayErase(c_array, size, index, erase) DN_PArrayErase(c_array, size, DN_ArrayCountU(c_array), 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_LArrayInsert(c_array, size, index, item) DN_PArrayInsert(c_array, size, DN_ArrayCountU(c_array), index, item)
#define DN_LArrayPopFront(c_array, size, count) DN_PArrayPopFront(c_array, size, DN_ArrayCountU(c_array), count)
#define DN_LArrayPopBack(c_array, size, count) DN_PArrayPopBack(c_array, size, DN_ArrayCountU(c_array), count)
#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_LArrayGrowFromPool(c_array, size, pool, new_max) DN_PArrayGrowFromPool(c_array, size, DN_ArrayCountU(c_array), pool, 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_LArrayGrowIfNeededFromArena(c_array, size, arena, add_count) DN_PArrayGrowIfNeededFromArena(c_array, size, DN_ArrayCountU(c_array), arena, add_count)
#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, ptr_size, count) DN_PArrayMakeArrayZ(c_array, ptr_size, DN_ArrayCountU(c_array), count)
#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, ptr_size) DN_PArrayMakeZ(c_array, ptr_size, DN_ArrayCountU(c_array))
#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, ptr_size, item, add) DN_PArrayAdd(c_array, ptr_size, DN_ArrayCountU(c_array), item, add)
#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, ptr_size, item) DN_PArrayAppend(c_array, ptr_size, DN_ArrayCountU(c_array), item)
#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, ptr_size, item) DN_PArrayPrepend(c_array, ptr_size, DN_ArrayCountU(c_array), item)
#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, ptr_size, index, erase) DN_PArrayErase(c_array, ptr_size, index, erase)
#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, ptr_size, index, item) DN_PArrayInsert(c_array, ptr_size, DN_ArrayCountU(c_array), index, item)
#define DN_LArrayPopFront(c_array, ptr_size, count) DN_PArrayPopFront(c_array, ptr_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_IArrayResizeFromArena(array, arena, new_max) DN_CArrayResizeFromArena((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((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_IArrayGrowFromArena(array, arena, new_max) DN_CArrayGrowFromArena((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((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_IArrayGrowIfNeededFromArena(array, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((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_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_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_IArrayMakeZ(array) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, DN_ZMem_Yes)
#define DN_IArrayAddArray(array, items, count, add) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, add)
#define DN_IArrayAdd(array, item, add) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, add)
#define DN_IArrayAppendArray(array, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Append)
#define DN_IArrayAppend(array, item) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Append)
#define DN_IArrayPrependArray(array, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Prepend)
#define DN_IArrayPrepend(array, item) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend)
#define DN_IArrayEraseRange(array, begin_index, count, erase) DN_CArrayEraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), begin_index, count, erase)
#define DN_IArrayErase(array, index, erase) DN_CArrayEraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), index, 1, erase)
#define DN_IArrayInsertArray(array, index, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayInsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, items, count)
#define DN_IArrayInsert(array, index, item, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayInsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, &item, 1)
#define DN_IArrayPopFront(array, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayPopFront((array)->data, &(array)->size, sizeof(((array)->data)[0]), count)
#define DN_IArrayPopBack(array, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayPopBack((array)->data, &(array)->size, sizeof(((array)->data)[0]), count)
#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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(ptr_array, index, erase) DN_CArrayEraseRange((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), index, 1, erase)
#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(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(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(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);
DN_API void* DN_CArrayInsertArray (void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count);
DN_API void* DN_CArrayPopFront (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
DN_API void* DN_CArrayPopBack (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
DN_API DN_ArrayEraseResult DN_CArrayEraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
DN_API void* DN_CArrayMakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem);
DN_API void* DN_CArrayAddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add);
DN_API bool DN_CArrayResizeFromPool (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayResizeFromArena (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Arena *arena, DN_USize new_max);
DN_API bool DN_CArrayGrowFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayGrowFromArena (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayGrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize add_count);
DN_API bool DN_CArrayGrowIfNeededFromArena (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Arena *pool, DN_USize add_count);
DN_API void* DN_CArrayInsertArray (void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count);
DN_API void* DN_CArrayPopFront (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
DN_API void* DN_CArrayPopBack (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
DN_API DN_ArrayEraseResult DN_CArrayEraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
DN_API void* DN_CArrayMakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem);
DN_API void* DN_CArrayAddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add);
DN_API bool DN_CArrayResizeFromPool (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayResizeFromArena (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Arena *arena, DN_USize new_max);
DN_API bool DN_CArrayGrowFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayGrowFromArena (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayGrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize add_count);
DN_API bool DN_CArrayGrowIfNeededFromArena (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Arena *pool, DN_USize add_count);
DN_API void* DN_SinglyLLDetach (void **link, void **next);
DN_API void* DN_SinglyLLDetach (void **link, void **next);
DN_API bool DN_RingHasSpace (DN_Ring const *ring, DN_U64 size);
DN_API bool DN_RingHasData (DN_Ring const *ring, DN_U64 size);
DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size);
#define DN_RingWriteStruct(ring, item) DN_RingWrite((ring), (item), sizeof(*(item)))
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)))
DN_API bool DN_RingHasSpace (DN_Ring const *ring, DN_U64 size);
DN_API bool DN_RingHasData (DN_Ring const *ring, DN_U64 size);
DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size);
#define DN_RingWriteStruct(ring, item) DN_RingWrite((ring), (item), sizeof(*(item)))
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)))
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> void DN_DSMapDeinit (DN_DSMap<T> *map, DN_ZMem z_mem);
@@ -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_DSMapEraseKeyU64 (DN_DSMap<T> *map, DN_U64 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_DSMapKeyBufferAsU64NoHash (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_USize size);
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);
#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_TicketMutex alloc_table_mutex;
DN_MemList alloc_table_mem;
DN_Arena alloc_table_arena;
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_OS_SemaphoreIncrement(&async->worker_sem, 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) {
+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) {
DN_Str8BuilderAppendBytesCopy(&pack->writer, string->data, string->size);
} else {
DN_Str8 src = DN_Str8Slice(pack->read, pack->read_index, string->size);
*string = DN_Str8FromStr8Arena(arena, src);
DN_Str8 src = DN_Str8Subset(pack->read, pack->read_index, string->size);
*string = DN_Str8FromStr8Arena(src, arena);
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) {
DN_Str8BuilderAppendBytesCopy(&pack->writer, string->data, string->size);
} else {
DN_Str8 src = DN_Str8Slice(pack->read, pack->read_index, string->size);
*string = DN_Str8FromStr8Pool(pool, src);
DN_Str8 src = DN_Str8Subset(pack->read, pack->read_index, string->size);
*string = DN_Str8FromStr8Pool(src, pool);
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) {
DN_Str8BuilderAppendBytesCopy(&pack->writer, ptr, size);
} 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_Memcpy(ptr, src.data, DN_Min(src.size, size));
pack->read_index += src.size;
+37 -39
View File
@@ -1,10 +1,8 @@
#define DN_CSV_CPP
#if defined(_CLANGD)
#include "dn_csv.h"
#endif
#include "dn_csv.h"
static DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter)
DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter)
{
DN_CSVTokeniser result = {};
result.string = string;
@@ -12,13 +10,21 @@ static DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter)
return result;
}
static bool DN_CSV_TokeniserValid(DN_CSVTokeniser *tokeniser)
bool DN_CSV_TokeniserValid(DN_CSVTokeniser *tokeniser)
{
bool result = tokeniser && !tokeniser->bad;
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;
if (DN_CSV_TokeniserValid(tokeniser) && tokeniser->string.size) {
@@ -37,7 +43,7 @@ static bool DN_CSV_TokeniserNextRow(DN_CSVTokeniser *tokeniser)
return result;
}
static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
{
DN_Str8 result = {};
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;
if (!tokeniser->it) {
tokeniser->it = tokeniser->string.data;
// NOTE: Skip any leading new lines
while (tokeniser->it[0] == '\n' || tokeniser->it[0] == '\r')
if (++tokeniser->it == string_end)
break;
DN_CSV_TokeniserEatNewLines_(tokeniser); // NOTE: Skip any leading new lines
}
// NOTE: Tokeniser pointing at end, no more valid data to parse.
@@ -68,8 +71,8 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
// 3. '\n' Last field in record, extract everything leading up the the new line.
char const *begin = tokeniser->it;
while (tokeniser->it != string_end && (tokeniser->it[0] != '"' &&
tokeniser->it[0] != tokeniser->delimiter &&
tokeniser->it[0] != '\n'))
tokeniser->it[0] != tokeniser->delimiter &&
tokeniser->it[0] != '\n'))
tokeniser->it++;
bool quoted_field = (tokeniser->it != string_end) && tokeniser->it[0] == '"';
@@ -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
// until we reach the field terminator.
if (quoted_field)
while (tokeniser->it != string_end && (tokeniser->it[0] != tokeniser->delimiter &&
tokeniser->it[0] != '\n'))
while (tokeniser->it != string_end && (tokeniser->it[0] != tokeniser->delimiter && tokeniser->it[0] != '\n'))
tokeniser->it++;
// NOTE: Advance the tokeniser past the field terminator.
@@ -120,7 +122,7 @@ static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser)
return result;
}
static DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser)
DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser)
{
DN_Str8 result = {};
if (!DN_CSV_TokeniserValid(tokeniser))
@@ -135,14 +137,14 @@ static DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser)
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)
DN_CSV_TokeniserNextColumn(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)
return 0;
@@ -150,34 +152,32 @@ static int DN_CSV_TokeniserNextN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, in
int result = 0;
for (; result < fields_size; result++) {
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;
}
return result;
}
DN_MSVC_WARNING_PUSH
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 DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size)
{
int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, true /*column_iterator*/);
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*/);
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++)
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) {
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) {
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_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);
}
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_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);
}
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_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);
}
static void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value)
void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value)
{
DN_U64 u64 = *value;
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);
}
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_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);
}
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_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;
}
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) {
DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser);
*str8 = DN_Str8FromStr8Arena(arena, csv_value);
*str8 = DN_Str8FromStr8Arena(csv_value, arena);
} else {
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) {
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)
*size = max;
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;
if (serialise == DN_CSVSerialise_Read) {
@@ -289,4 +288,3 @@ static bool DN_CSV_PackNewLine(DN_CSVPack *pack, DN_CSVSerialise serialise)
}
return result;
}
DN_MSVC_WARNING_POP
+35 -3
View File
@@ -1,9 +1,18 @@
#if !defined(DN_CSV_H)
#define DN_CSV_H
#if defined(_CLANGD)
#include "../dn.h"
#endif
// 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)
#include "../dn.h"
#endif
enum DN_CSVSerialise
{
@@ -27,4 +36,27 @@ struct DN_CSVPack
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)
+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_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_TCScratchEnd(&scratch);
}
-1
View File
@@ -41,7 +41,6 @@ struct DN_JSONBuilder
};
#endif // !defined(DN_NO_JSON_BUIDLER)
// NOTE: DN_BinarySearch ///////////////////////////////////////////////////////////////////////////
template <typename T>
using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
+16 -12
View File
@@ -1,6 +1,8 @@
#define DN_NET_CURL_CPP
#if defined(_CLANGD)
#define DN_H_WITH_OS 1
#include "../dn.h"
#include "dn_net.h"
#endif
@@ -43,7 +45,7 @@ DN_NETRequestHandle DN_NET_HandleFromRequest(DN_NETRequest *request)
void DN_NET_EndFinishedRequest_(DN_NETRequest *request)
{
// 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
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_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);
}
@@ -61,31 +64,32 @@ DN_NETRequestHandle DN_NET_SetupRequest_(DN_NETRequest *request, DN_Str8 url, DN
// NOTE: Setup request
DN_Assert(request);
if (request) {
if (!request->arena.curr)
request->arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(1), DN_ArenaFlags_Nil);
if (!request->mem.curr)
request->mem = DN_MemListFromVMem(DN_Megabytes(1), DN_Kilobytes(1), DN_MemFlags_Nil);
request->arena = DN_ArenaTempBeginFromMemList(&request->mem);
request->type = type;
request->gen = DN_Max(request->gen + 1, 1);
request->url = DN_Str8FromStr8Arena(&request->arena, url);
request->method = DN_Str8FromStr8Arena(&request->arena, DN_Str8TrimWhitespaceAround(method));
request->url = DN_Str8FromStr8Arena(url, &request->arena);
request->method = DN_Str8FromStr8Arena(DN_Str8TrimWhitespaceAround(method), &request->arena);
if (args) {
request->args.flags = args->flags;
request->args.username = DN_Str8FromStr8Arena(&request->arena, args->username);
request->args.password = DN_Str8FromStr8Arena(&request->arena, args->password);
request->args.username = DN_Str8FromStr8Arena(args->username, &request->arena);
request->args.password = DN_Str8FromStr8Arena(args->password, &request->arena);
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);
DN_Assert(request->args.headers);
if (request->args.headers) {
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->completion_sem = DN_OS_SemaphoreInit(0);
request->start_response_arena_pos = DN_ArenaPos(&request->arena);
request->completion_sem = DN_OS_SemaphoreInit(0);
request->start_response_arena = DN_ArenaTempBeginFromArena(&request->arena);
}
DN_NETRequestHandle result = DN_NET_HandleFromRequest(request);
+20 -17
View File
@@ -2,8 +2,8 @@
#define DN_NET_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#define DN_H_WITH_OS 1
#include "../dn.h"
#endif
enum DN_NETRequestType
@@ -74,8 +74,9 @@ struct DN_NETResponse
struct DN_NETRequest
{
DN_MemList mem;
DN_Arena arena;
DN_USize start_response_arena_pos;
DN_Arena start_response_arena;
DN_NETRequestType type;
DN_U64 gen;
DN_Str8 url;
@@ -88,22 +89,13 @@ struct DN_NETRequest
DN_U64 context[2];
};
struct DN_NETCore
{
char *base;
DN_U64 base_size;
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_NETInitFunc) (struct DN_NETCore *net, char *base, DN_U64 base_size);
typedef void (DN_NETDeinitFunc) (struct DN_NETCore *net);
typedef DN_NETRequestHandle(DN_NETDoHTTPFunc) (struct DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args);
typedef DN_NETRequestHandle(DN_NETDoWSFunc) (struct DN_NETCore *net, DN_Str8 url);
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_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
{
@@ -116,6 +108,17 @@ struct DN_NETInterface
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_NETRequest * DN_NET_RequestFromHandle (DN_NETRequestHandle handle);
DN_NETRequestHandle DN_NET_HandleFromRequest (DN_NETRequest *request);
+21 -20
View File
@@ -129,7 +129,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_Str8 payload = {};
for (DN_OS_MutexScope(&curl->ring_mutex)) {
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);
}
@@ -168,7 +168,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_NETRequest *request = DN_Cast(DN_NETRequest *) event.request.handle;
// NOTE: Release resources
DN_ArenaClear(&request->arena);
DN_ArenaTempEnd(&request->arena, DN_ArenaReset_Yes);
DN_OS_SemaphoreDeinit(&request->completion_sem);
curl_multi_remove_handle(curl->thread_curlm, curl_req->handle);
@@ -224,7 +224,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
}
} else {
req->response.error_str8 = DN_Str8FromFmtArena(&req->arena, "Failed to get HTTP response status (CURL %d): %s", msg->data.result, curl_easy_strerror(get_result));
req->response.state = DN_NETResponseState_Error;
req->response.state = DN_NETResponseState_Error;
}
} else {
DN_USize curl_extended_error_size = DN_CStr8Size(curl_req->error);
@@ -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)
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);
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);
@@ -353,13 +353,13 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_USize curl_extended_error_size = DN_CStr8Size(curl_req->error);
req->response.state = DN_NETResponseState_Error;
req->response.error_str8 = DN_Str8FromFmtArena(&req->arena,
"Websocket receive '%.*s' failed (CURL %d): %s%s%s%s",
DN_Str8PrintFmt(req->url),
receive_result,
curl_easy_strerror(receive_result),
curl_extended_error_size ? " (" : "",
curl_extended_error_size ? curl_req->error : "",
curl_extended_error_size ? ")" : "");
"Websocket receive '%.*s' failed (CURL %d): %s%s%s%s",
DN_Str8PrintFmt(req->url),
receive_result,
curl_easy_strerror(receive_result),
curl_extended_error_size ? " (" : "",
curl_extended_error_size ? curl_req->error : "",
curl_extended_error_size ? ")" : "");
}
}
@@ -394,10 +394,11 @@ DN_NETInterface DN_NET_CurlInterface()
void DN_NET_CurlInit(DN_NETCore *net, char *base, DN_U64 base_size)
{
DN_NET_BaseInit_(net, base, base_size);
DN_NETCurlCore *curl = DN_ArenaNew(&net->arena, DN_NETCurlCore, DN_ZMem_Yes);
net->context = curl;
DN_NETCurlCore *curl = DN_ArenaNew(&net->arena, DN_NETCurlCore, DN_ZMem_Yes);
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.base = DN_Cast(char *) DN_ArenaAlloc(&net->arena, curl->ring.size, /*align*/ 1, DN_ZMem_Yes);
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;
curl->kill_thread = true;
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)
@@ -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
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);
DN_NETCurlRequest *curl_req = DN_ArenaNew(&net->arena, DN_NETCurlRequest, DN_ZMem_Yes);
if (!req || !curl_req) {
DN_ArenaPopTo(&net->arena, arena_pos);
DN_MemListPopTo(net->arena.mem, arena_pos);
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);
req->response.request = result;
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
@@ -587,8 +588,8 @@ static DN_NETResponse DN_NET_CurlHandleFinishedRequest_(DN_NETCurlCore *curl, DN
DN_NETCurlRequest *curl_req = DN_NET_CurlRequestFromRequest_(req);
result.body = DN_Str8BuilderBuild(&curl_req->str8_builder, arena);
if (result.error_str8.size)
result.error_str8 = DN_Str8FromStr8Arena(arena, result.error_str8);
curl_req->str8_builder = DN_Str8BuilderFromArena(&req->arena);
result.error_str8 = DN_Str8FromStr8Arena(result.error_str8, arena);
curl_req->str8_builder = {}; // Clear it out, reinitialised on subsequent do request call
}
DN_NET_EndFinishedRequest_(req);
+375 -254
View File
File diff suppressed because it is too large Load Diff
+9 -7
View File
@@ -2,12 +2,14 @@
#define DN_NO_WINDOWS_H_REPLACEMENT_HEADER
#endif
#define DN_H_WITH_OS 1
#define DN_H_WITH_CORE 1
#define DN_H_WITH_HASH 1
#define DN_H_WITH_HELPERS 1
#define DN_H_WITH_ASYNC 1
#define DN_H_WITH_NET 1
#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_CORE 1
#define DN_H_WITH_HASH 1
#define DN_H_WITH_HELPERS 1
#define DN_H_WITH_ASYNC 1
#define DN_H_WITH_NET 1
#include "../dn.h"
#include "../dn.cpp"
@@ -35,7 +37,7 @@ int main(int, char**)
{
DN_Core dn = {};
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;
}
DN_MSVC_WARNING_POP
+168 -131
View File
@@ -11,61 +11,59 @@
#include <unistd.h> // getpagesize
#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);
return result;
}
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet(DN_ArenaMemFuncType type)
DN_API DN_MemFuncs DN_MemFuncsFromType(DN_MemFuncsType type)
{
DN_ArenaMemFuncs result = {};
result.type = type;
DN_MemFuncs result = {};
result.type = type;
switch (type) {
case DN_ArenaMemFuncType_Nil: break;
case DN_ArenaMemFuncType_Basic: {
result.type = DN_ArenaMemFuncType_Basic;
result.basic_alloc = DN_ArenaBasicAllocFromOSHeap;
result.basic_dealloc = DN_OS_MemDealloc;
case DN_MemFuncsType_Nil: break;
case DN_MemFuncsType_Heap: {
result.heap_alloc = DN_OS_MemFuncsHeapAllocShim_;
result.heap_dealloc = DN_OS_MemDealloc;
} break;
case DN_ArenaMemFuncType_VMem: {
case DN_MemFuncsType_Virtual: {
DN_Core *dn = DN_Get();
DN_Assert(dn->init_flags & DN_InitFlags_OS);
result.type = DN_ArenaMemFuncType_VMem;
result.vmem_page_size = dn->os.page_size;
result.vmem_reserve = DN_OS_MemReserve;
result.vmem_commit = DN_OS_MemCommit;
result.vmem_release = DN_OS_MemRelease;
result.virtual_page_size = dn->os.page_size;
result.virtual_reserve = DN_OS_MemReserve;
result.virtual_commit = DN_OS_MemCommit;
result.virtual_release = DN_OS_MemRelease;
} break;
}
return result;
}
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults()
DN_API DN_MemFuncs DN_MemFuncsDefault()
{
DN_Core *dn = DN_Get();
DN_ArenaMemFuncType type = DN_ArenaMemFuncType_Basic;
DN_Core *dn = DN_Get();
DN_MemFuncsType type = DN_MemFuncsType_Heap;
if (dn->os_init) {
#if !defined(DN_PLATFORM_EMSCRIPTEN)
type = DN_ArenaMemFuncType_VMem;
#endif
#if !defined(DN_PLATFORM_EMSCRIPTEN)
type = DN_MemFuncsType_Virtual;
#endif
}
DN_ArenaMemFuncs result = DN_ArenaMemFuncsGet(type);
DN_MemFuncs result = DN_MemFuncsFromType(type);
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_Arena result = DN_ArenaFromMemFuncs(size, size, flags, mem_funcs);
DN_MemFuncs mem_funcs = DN_MemFuncsFromType(DN_MemFuncsType_Heap);
DN_MemList result = DN_MemListFromMemFuncs(size, size, flags, mem_funcs);
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_Arena result = DN_ArenaFromMemFuncs(reserve, commit, flags, mem_funcs);
DN_MemFuncs mem_funcs = DN_MemFuncsFromType(DN_MemFuncsType_Virtual);
DN_MemList result = DN_MemListFromMemFuncs(reserve, commit, flags, mem_funcs);
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
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"));
while (split.lhs.size) {
DN_Str8BuilderAppendRef(&builder, pad);
@@ -129,7 +127,7 @@ DN_API DN_Str8 DN_Str8BuilderBuildFromHeap(DN_Str8Builder const *builder)
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_OSCore *os = DN_Cast(DN_OSCore *)user_data;
@@ -138,69 +136,82 @@ DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite ca
DN_TicketMutex_Begin(&os->log_file_mutex);
if (os->log_to_file && !os->log_file.handle && !os->log_file.error) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
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 exe_dir = DN_OS_EXEDir(&scratch.arena);
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);
DN_TCScratchEnd(&scratch);
}
DN_TicketMutex_End(&os->log_file_mutex);
DN_LogStyle style = {};
if (!os->log_no_colour) {
style.colour = true;
style.bold = DN_LogBold_Yes;
if (type.is_u32_enum) {
switch (type.u32) {
case DN_LogType_Debug: {
style.colour = false;
style.bold = DN_LogBold_No;
} break;
bool print_prefix = DN_BitIsNotSet(flags, DN_LogFlags_NoPrefix);
char prefix_buffer[128] = {};
DN_LogPrefixSize prefix_size = {};
if (print_prefix) {
DN_LogStyle style = {};
if (!os->log_no_colour) {
style.colour = true;
style.bold = DN_LogBold_Yes;
if (type.is_u32_enum) {
switch (type.u32) {
case DN_LogType_Debug: {
style.colour = false;
style.bold = DN_LogBold_No;
} break;
case DN_LogType_Info: {
style.g = 0x87;
style.b = 0xff;
} break;
case DN_LogType_Info: {
style.g = 0x87;
style.b = 0xff;
} break;
case DN_LogType_Warning: {
style.r = 0xff;
style.g = 0xff;
} break;
case DN_LogType_Warning: {
style.r = 0xff;
style.g = 0xff;
} break;
case DN_LogType_Error: {
style.r = 0xff;
} break;
case DN_LogType_Error: {
style.r = 0xff;
} break;
}
}
}
DN_Date os_date = DN_OS_DateLocalTimeNow();
DN_LogDate log_date = {};
log_date.year = os_date.year;
log_date.month = os_date.month;
log_date.day = os_date.day;
log_date.hour = os_date.hour;
log_date.minute = os_date.minutes;
log_date.second = os_date.seconds;
prefix_size = DN_LogMakePrefix(style, type, call_site, log_date, prefix_buffer, sizeof(prefix_buffer));
}
DN_Date os_date = DN_OS_DateLocalTimeNow();
DN_LogDate log_date = {};
log_date.year = os_date.year;
log_date.month = os_date.month;
log_date.day = os_date.day;
log_date.hour = os_date.hour;
log_date.minute = os_date.minutes;
log_date.second = os_date.seconds;
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_copy(args_copy, args);
DN_TicketMutex_Begin(&os->log_file_mutex);
{
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, "");
if (print_prefix) {
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_FileWriteFV(&os->log_file, nullptr, fmt, args_copy);
DN_OS_FileWrite(&os->log_file, DN_Str8Lit("\n"), nullptr);
if (!DN_BitIsSet(flags, DN_LogFlags_NoNewLine))
DN_OS_FileWrite(&os->log_file, DN_Str8Lit("\n"), nullptr);
}
DN_TicketMutex_End(&os->log_file_mutex);
va_end(args_copy);
DN_OSPrintDest dest = (type.is_u32_enum && type.u32 == DN_LogType_Error) ? DN_OSPrintDest_Err : DN_OSPrintDest_Out;
DN_OS_Print(dest, DN_Str8FromPtr(prefix_buffer, prefix_size.size));
DN_OS_PrintF(dest, "%*s ", DN_Cast(int)prefix_size.padding, "");
DN_OS_PrintLnFV(dest, fmt, args);
DN_TicketMutex_Begin(&os->log_mutex);
{
if (print_prefix)
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()
@@ -239,11 +250,11 @@ DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena)
DN_Str8 result = {};
if (!arena)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str8 exe_path = DN_OS_EXEPath(scratch.arena);
DN_Str8 separators[] = {DN_Str8Lit("/"), DN_Str8Lit("\\")};
DN_Str8BSplitResult split = DN_Str8BSplitLastArray(exe_path, separators, DN_ArrayCountU(separators));
result = DN_Str8FromStr8Arena(arena, split.lhs);
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str8 exe_path = DN_OS_EXEPath(&scratch.arena);
DN_Str8 separators[] = {DN_Str8Lit("/"), DN_Str8Lit("\\")};
DN_Str8BSplitResult split = DN_Str8BSplitLastArray(exe_path, separators, DN_ArrayCountU(separators));
result = DN_Str8FromStr8Arena(split.lhs, arena);
DN_TCScratchEnd(&scratch);
return result;
}
@@ -388,7 +399,7 @@ DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_ErrSink *error, DN_FMT_ATTRIB c
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
DN_Str8 result = {};
@@ -399,14 +410,14 @@ DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_St
}
// NOTE: Allocate
DN_ArenaTempMem arena_tmp = {};
if (alloc_type == DN_Allocator_Arena) {
DN_Arena *arena = DN_Cast(DN_Arena *) allocator;
arena_tmp = DN_ArenaTempMemBegin(arena);
result = DN_Str8AllocArena(arena, path_info.size, DN_ZMem_No);
DN_Arena temp_arena = {};
if (allocator.type == DN_AllocatorType_Arena) {
DN_Arena *arena = DN_Cast(DN_Arena *) allocator.context;
temp_arena = DN_ArenaTempBeginFromArena(arena);
result = DN_Str8AllocArena(path_info.size, DN_ZMem_No, &temp_arena);
} else {
DN_Pool *pool = DN_Cast(DN_Pool *) allocator;
result = DN_Str8AllocPool(pool, path_info.size);
DN_Pool *pool = DN_Cast(DN_Pool *) allocator.context;
result = DN_Str8AllocPool(path_info.size, pool);
}
if (!result.data) {
@@ -416,31 +427,41 @@ DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_St
}
// NOTE: Read all
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);
if (file.error || !read.success) {
if (alloc_type == DN_Allocator_Arena) {
DN_ArenaTempMemEnd(arena_tmp);
} else {
DN_Pool *pool = DN_Cast(DN_Pool *) allocator;
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);
bool failed = file.error || !read.success;
if (allocator.type == DN_AllocatorType_Arena) {
DN_ArenaTempEnd(&temp_arena, failed ? DN_ArenaReset_Yes : DN_ArenaReset_No);
} else {
if (failed) {
DN_Pool *pool = DN_Cast(DN_Pool *) allocator.context;
DN_PoolDealloc(pool, result.data);
}
result = {};
}
if (failed)
result = {};
DN_OS_FileClose(&file);
return result;
}
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;
}
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;
}
@@ -454,9 +475,9 @@ 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_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 buffer = DN_Str8FromFmtVArena(scratch.arena, fmt, args);
bool result = DN_OS_FileWriteAll(file_path, buffer, error);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 buffer = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
bool result = DN_OS_FileWriteAll(file_path, buffer, error);
DN_TCScratchEnd(&scratch);
return result;
}
@@ -472,8 +493,8 @@ 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_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 tmp_path = DN_Str8FromFmtArena(scratch.arena, "%.*s.tmp", DN_Str8PrintFmt(path));
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 tmp_path = DN_Str8FromFmtArena(&scratch.arena, "%.*s.tmp", DN_Str8PrintFmt(path));
if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) {
DN_TCScratchEnd(&scratch);
return false;
@@ -492,9 +513,9 @@ 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_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 buffer = DN_Str8FromFmtVArena(scratch.arena, fmt, args);
bool result = DN_OS_FileWriteAllSafe(path, buffer, error);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 buffer = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
bool result = DN_OS_FileWriteAllSafe(path, buffer, error);
DN_TCScratchEnd(&scratch);
return result;
}
@@ -507,6 +528,17 @@ DN_API bool DN_OS_FileWriteAllSafeF(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTR
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)
{
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_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);
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);
va_list args;
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);
DN_Str8 result = DN_OS_PathTo(arena, path, path_separator);
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);
va_list args;
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);
DN_Str8 result = DN_OS_Path(arena, path);
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 '\\'
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) {
char *dest = result.data;
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)
{
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_TCEquip(&thread->context);
if (thread->is_lane_set) {
@@ -800,9 +832,9 @@ DN_API void DN_OS_HttpRequestWait(DN_OSHttpResponse *response)
DN_API DN_OSHttpResponse DN_OS_HttpRequest(DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers)
{
// TODO(doyle): Revise the memory allocation and its lifetime
DN_OSHttpResponse result = {};
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
result.scratch_arena = scratch.arena;
DN_OSHttpResponse result = {};
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
result.scratch_arena = scratch.arena;
DN_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers);
DN_OS_HttpRequestWait(&result);
@@ -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)
{
if (string.data && string.size) {
if (style.colour)
DN_OS_Print(dest, DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType_Fg, style.r, style.g, style.b));
if (style.colour) {
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)
DN_OS_Print(dest, DN_Str8Lit(DN_LogBoldEscapeCode));
DN_OS_Print(dest, DN_Str8Lit(DN_ANSICodeBoldLit));
DN_OS_Print(dest, string);
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)
{
if (fmt) {
if (style.colour)
DN_OS_Print(dest, DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType_Fg, style.r, style.g, style.b));
if (style.colour) {
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)
DN_OS_Print(dest, DN_Str8Lit(DN_LogBoldEscapeCode));
DN_OS_Print(dest, DN_Str8Lit(DN_ANSICodeBoldLit));
DN_OS_PrintFV(dest, fmt, args);
if (style.colour || style.bold == DN_LogBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LogResetEscapeCode));
DN_OS_Print(dest, DN_Str8Lit(DN_ANSICodeResetLit));
}
}
@@ -1166,8 +1202,8 @@ DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, DN_U16 limit)
w32->sym_initialised = true;
SymSetOptions(SYMOPT_LOAD_LINES);
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_OSW32Error error = DN_OS_W32LastError(scratch.arena);
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
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_TCScratchEnd(&scratch);
}
@@ -1246,8 +1282,8 @@ DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkR
if (!walk || !arena)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena);
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip);
result = DN_Str8BuilderBuild(&builder, arena);
DN_TCScratchEnd(&scratch);
@@ -1256,9 +1292,9 @@ 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_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, limit);
DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip);
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&scratch.arena, limit);
DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip);
DN_TCScratchEnd(&scratch);
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
// 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_StackTraceWalkResult walk = DN_StackTraceWalk(&arena, limit);
DN_StackTraceAddWalkToStr8Builder(&walk, &builder, skip);
DN_Str8 result = DN_Str8BuilderBuildFromHeap(&builder);
DN_ArenaDeinit(&arena);
DN_MemListDeinit(&mem);
return result;
}
@@ -1283,9 +1320,9 @@ DN_API DN_StackTraceFrameSlice DN_StackTraceGetFrames(DN_Arena *arena, DN_U16 li
return result;
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 (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;
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);)
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_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)) {
DN_StackTraceFrame frame = *it.data;
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
// calls use their own dedicated arena.
DN_Arena tmp_arena;
DN_Arena *scratch_arena;
DN_Arena scratch_arena;
DN_Str8Builder builder;
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_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
DN_TicketMutex log_mutex;
// NOTE: OS
DN_U32 logical_processor_count;
@@ -280,6 +281,7 @@ struct DN_OSCore
DN_U64 mem_allocs_total;
DN_U64 mem_allocs_frame; // Total OS heap allocs since the last 'DN_Core_FrameBegin' was invoked
DN_MemList mem;
DN_Arena arena;
void *platform_context;
};
@@ -291,10 +293,10 @@ struct DN_OSDiskSpace
DN_U64 size;
};
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet (DN_ArenaMemFuncType type);
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults ();
DN_API DN_Arena DN_ArenaFromHeap (DN_U64 size, DN_ArenaFlags flags);
DN_API DN_Arena DN_ArenaFromVMem (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
DN_API DN_MemFuncs DN_MemFuncsFromType (DN_MemFuncsType type);
DN_API DN_MemFuncs DN_MemFuncsDefault ();
DN_API DN_MemList DN_MemListFromHeap (DN_U64 size, DN_MemFlags 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, ...);
@@ -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_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 bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against);
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 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 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;
}
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;
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;
thread->handle = {};
thread->thread_id = {};
DN_TCDeinit(&thread->context, deinit_arenas);
}
return result;
}
@@ -1535,8 +1536,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
return;
response->arena = arena;
response->builder.arena =
response->scratch_arena ? response->scratch_arena : &response->tmp_arena;
response->builder.arena = response->scratch_arena ? response->scratch_arena : &response->tmp_arena;
DN_Arena *scratch = response->scratch_arena;
DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1);
+108 -116
View File
@@ -209,9 +209,9 @@ DN_API void DN_OS_GenBytesSecure(void *buffer, DN_U32 size)
DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSDiskSpace result = {};
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSDiskSpace result = {};
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
ULARGE_INTEGER free_bytes_avail_to_caller;
ULARGE_INTEGER total_number_of_bytes;
@@ -233,9 +233,9 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 name16 = DN_OS_W32Str8ToStr16(scratch.arena, name);
DN_Str16 value16 = DN_OS_W32Str8ToStr16(scratch.arena, value);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 name16 = DN_OS_W32Str8ToStr16(&scratch.arena, name);
DN_Str16 value16 = DN_OS_W32Str8ToStr16(&scratch.arena, value);
bool result = SetEnvironmentVariableW(name16.data, value16.data) != 0;
DN_TCScratchEnd(&scratch);
return result;
@@ -246,8 +246,8 @@ DN_API DN_Str8 DN_OS_EXEPath(DN_Arena *arena)
DN_Str8 result = {};
if (!arena)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(scratch.arena);
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(&scratch.arena);
result = DN_OS_W32Str16ToStr8(arena, exe_dir16);
DN_TCScratchEnd(&scratch);
return result;
@@ -286,15 +286,15 @@ static DN_U64 DN_OS_W32FileTimeToSeconds_(FILETIME const *time)
DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err)
{
bool result = false;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 src16 = DN_OS_W32Str8ToStr16(scratch.arena, src);
DN_Str16 dest16 = DN_OS_W32Str8ToStr16(scratch.arena, dest);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 src16 = DN_OS_W32Str8ToStr16(&scratch.arena, src);
DN_Str16 dest16 = DN_OS_W32Str8ToStr16(&scratch.arena, dest);
int fail_if_exists = overwrite == false;
result = CopyFileW(src16.data, dest16.data, fail_if_exists) != 0;
if (!result) {
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 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;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 src16 = DN_OS_W32Str8ToStr16(scratch.arena, src);
DN_Str16 dest16 = DN_OS_W32Str8ToStr16(scratch.arena, dest);
DN_Str16 src16 = DN_OS_W32Str8ToStr16(&scratch.arena, src);
DN_Str16 dest16 = DN_OS_W32Str8ToStr16(&scratch.arena, dest);
unsigned long flags = MOVEFILE_COPY_ALLOWED;
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;
if (!result) {
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 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;
}
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 = {};
if (path.size == 0 || path.size <= 0)
@@ -366,18 +366,18 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 ac
access_mode |= GENERIC_EXECUTE;
}
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
void *handle = CreateFileW(/*LPCWSTR lpFileName*/ path16.data,
/*DWORD dwDesiredAccess*/ access_mode,
/*DWORD dwShareMode*/ FILE_SHARE_READ | FILE_SHARE_WRITE,
/*LPSECURITY_ATTRIBUTES lpSecurityAttributes*/ nullptr,
/*DWORD dwCreationDisposition*/ create_flag,
/*DWORD dwFlagsAndAttributes*/ FILE_ATTRIBUTE_NORMAL,
/*HANDLE hTemplateFile*/ nullptr);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
void *handle = CreateFileW(/*LPCWSTR lpFileName*/ path16.data,
/*DWORD dwDesiredAccess*/ access_mode,
/*DWORD dwShareMode*/ FILE_SHARE_READ | FILE_SHARE_WRITE,
/*LPSECURITY_ATTRIBUTES lpSecurityAttributes*/ nullptr,
/*DWORD dwCreationDisposition*/ create_flag,
/*DWORD dwFlagsAndAttributes*/ FILE_ATTRIBUTE_NORMAL,
/*HANDLE hTemplateFile*/ nullptr);
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;
DN_ErrSinkAppendF(err, win_error.code, "Failed to open file at '%.*s': '%.*s'", DN_Str8PrintFmt(path), DN_Str8PrintFmt(win_error.msg));
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,
/*LPOVERLAPPED lpOverlapped*/ nullptr);
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_TCScratchEnd(&scratch);
return result;
}
if (bytes_read != size) {
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena);
DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_ErrSinkAppendF(
err,
win_error.code,
@@ -455,9 +455,9 @@ DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize siz
}
if (!result) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena);
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
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_TCScratchEnd(&scratch);
}
@@ -471,8 +471,8 @@ DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_ErrSink *err)
BOOL result = FlushFileBuffers(DN_Cast(HANDLE) file->handle);
if (!result) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
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_TCScratchEnd(&scratch);
}
@@ -494,8 +494,8 @@ DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path)
if (path.size == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) {
@@ -530,8 +530,8 @@ DN_API bool DN_OS_PathDelete(DN_Str8 path)
if (path.size == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) {
result = DeleteFileW(path16.data);
if (!result)
@@ -547,8 +547,8 @@ DN_API bool DN_OS_PathIsFile(DN_Str8 path)
if (path.size == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) {
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
@@ -565,8 +565,8 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
if (path.size == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) {
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
@@ -580,9 +580,9 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
{
bool result = true;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
bool result = true;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
// 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
@@ -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
// character, add the glob and re-null terminate the buffer.
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
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
DN_TCScratchEnd(&scratch);
return false;
@@ -676,8 +676,6 @@ DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it)
return result;
}
// NOTE: DN_OSExec /////////////////////////////////////////////////////////////////////////////////
DN_API void DN_OS_Exit(int32_t 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);
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;
DN_ErrSinkAppendF(err, result.os_error_code, "Executed command failed to terminate: %.*s", DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch);
@@ -779,7 +777,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
if (GetExitCodeProcess(handle.process, &exit_status)) {
result.exit_code = exit_status;
} 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;
DN_ErrSinkAppendF(err,
result.os_error_code,
@@ -824,12 +822,12 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *are
return result;
}
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str8Builder stdout_builder = {};
DN_Str8Builder stderr_builder = {};
if (arena) {
stdout_builder.arena = scratch.arena;
stderr_builder.arena = scratch.arena;
stdout_builder = DN_Str8BuilderFromArena(&scratch.arena);
stderr_builder = DN_Str8BuilderFromArena(&scratch.arena);
}
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) {
size_t stdout_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 *stderr_buffer = DN_ArenaNewArray(scratch.arena, char, stderr_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);
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(&stderr_builder, result.stderr_text);
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.stderr_text = DN_Str8BuilderBuild(&stderr_builder, arena);
DN_TCScratchEnd(&scratch);
@@ -861,19 +859,19 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 cmd_rendered = DN_Str8SliceRender(cmd_line, DN_Str8Lit(" "), scratch.arena);
DN_Str16 cmd16 = DN_OS_W32Str8ToStr16(scratch.arena, cmd_rendered);
DN_Str16 working_dir16 = DN_OS_W32Str8ToStr16(scratch.arena, args->working_dir);
DN_Str8 cmd_rendered = DN_Str8SliceRender(cmd_line, DN_Str8Lit(" "), &scratch.arena);
DN_Str16 cmd16 = DN_OS_W32Str8ToStr16(&scratch.arena, cmd_rendered);
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);
if (env_builder.string_size)
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 = {};
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
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 (!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;
DN_ErrSinkAppendF(
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)) {
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;
DN_ErrSinkAppendF(err,
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;
} else {
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;
DN_ErrSinkAppendF(
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)) {
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;
DN_ErrSinkAppendF(err,
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 = {};
STARTUPINFOW startup_info = {};
startup_info.cb = sizeof(STARTUPINFOW);
@@ -982,14 +980,14 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
&startup_info,
&proc_info);
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;
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);
return result;
}
// NOTE: Post-amble ////////////////////////////////////////////////////////////////////////////
// NOTE: Post-amble
CloseHandle(proc_info.hThread);
result.process = proc_info.hProcess;
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;
}
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;
if (thread && thread->handle) {
@@ -1289,7 +1287,7 @@ DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread)
CloseHandle(thread->handle);
thread->handle = INVALID_HANDLE_VALUE;
thread->thread_id = {};
DN_TCDeinit(&thread->context);
DN_TCDeinit(&thread->context, deinit_arenas);
}
return result;
}
@@ -1309,7 +1307,7 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
DN_OSW32Core *w32 = DN_OS_W32GetCore();
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
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);
} else {
// NOTE: Fallback to throw-exception method to set thread name
@@ -1323,11 +1321,11 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
};
#pragma pack(pop)
DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, name);
DN_Str8 copy = DN_Str8FromStr8Arena(name, &scratch.arena);
DN_OSW32ThreadNameInfo info = {};
info.dwType = 0x1000;
info.szName = (char *)copy.data;
info.dwThreadID = DN_OS_ThreadID();
info.dwType = 0x1000;
info.szName = (char *)copy.data;
info.dwThreadID = DN_OS_ThreadID();
// TODO: Review warning 6320
DN_MSVC_WARNING_PUSH
@@ -1342,7 +1340,6 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
DN_TCScratchEnd(&scratch);
}
// NOTE: DN_OSHttp /////////////////////////////////////////////////////////////////////////////////
void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD dwInternetStatus, VOID *lpvStatusInformation, DWORD dwStatusInformationLength)
{
(void)session;
@@ -1449,13 +1446,12 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
if (!response || !arena)
return;
response->arena = arena;
response->builder.arena = response->scratch_arena ? response->scratch_arena : &response->tmp_arena;
response->arena = 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);
if (!scratch_arena)
scratch_arena = scratch_.arena;
DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1);
if (!response->scratch_arena.mem)
response->scratch_arena = scratch_.arena;
DN_OSW32Error error = {};
DN_DEFER
@@ -1489,28 +1485,28 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
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*/);
if (!response->w32_request_connection) {
error = DN_OS_W32LastError(&response->tmp_arena);
return;
}
DN_Str16 method16 = DN_OS_W32Str8ToStr16(scratch_arena, method);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch_arena, path);
DN_Str16 method16 = DN_OS_W32Str8ToStr16(&response->scratch_arena, method);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&response->scratch_arena, path);
response->w32_request_handle = WinHttpOpenRequest(response->w32_request_connection,
method16.data,
path16.data,
nullptr /*version*/,
nullptr /*referrer*/,
nullptr /*accept types*/,
secure ? WINHTTP_FLAG_SECURE : 0);
method16.data,
path16.data,
nullptr /*version*/,
nullptr /*referrer*/,
nullptr /*accept types*/,
secure ? WINHTTP_FLAG_SECURE : 0);
if (!response->w32_request_handle) {
error = DN_OS_W32LastError(&response->tmp_arena);
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);
if (!WinHttpSendRequest(response->w32_request_handle,
headers16.data,
@@ -1535,7 +1531,7 @@ DN_API void DN_OS_HttpRequestFree(DN_OSHttpResponse *response)
response->w32_request_session = nullptr;
response->w32_request_connection = nullptr;
response->w32_request_handle = nullptr;
DN_ArenaDeinit(&response->tmp_arena);
DN_MemListDeinit(response->tmp_arena.mem);
DN_OS_SemaphoreDeinit(&response->on_complete_semaphore);
*response = {};
@@ -1626,7 +1622,6 @@ DN_API void DN_OS_W32MakeProcessDPIAware()
set_process_dpi_aware();
}
// NOTE: Windows UTF8 to Str16 //////////////////////////////////////////////
DN_API DN_Str16 DN_OS_W32Str8ToStr16(DN_Arena *arena, DN_Str8 src)
{
DN_Str16 result = {};
@@ -1665,7 +1660,6 @@ DN_API int DN_OS_W32Str8ToStr16Buffer(DN_Str8 src, wchar_t *dest, int dest_size)
return result;
}
// NOTE: Windows Str16 To UTF8 //////////////////////////////////////////////////////////////////
DN_API int DN_OS_W32Str16ToStr8Buffer(DN_Str16 src, char *dest, int dest_size)
{
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
// null-termination already so no-need to +1 the required size
DN_ArenaTempMemScope temp_mem = DN_ArenaTempMemScope(arena);
DN_Str8 buffer = DN_Str8AllocArena(arena, required_size, DN_ZMem_No);
if (buffer.size == 0)
return result;
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)) {
result = buffer;
result.data[result.size] = 0;
temp_mem.mem = {};
DN_Arena temp = DN_ArenaTempBeginFromArena(arena);
DN_Str8 buffer = DN_Str8AllocArena(required_size, DN_ZMem_No, &temp);
if (buffer.size) {
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)) {
result = buffer;
result.data[result.size] = 0;
}
}
DN_ArenaTempEnd(&temp, result.size == DN_Cast(DN_USize)required_size ? DN_ArenaReset_No : DN_ArenaReset_Yes);
return result;
}
@@ -1757,7 +1749,7 @@ DN_API DN_Str16 DN_OS_W32EXEPathW(DN_Arena *arena)
wchar_t *module_path = nullptr;
do {
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) {
DN_TCScratchEnd(&scratch);
return result;
@@ -1786,7 +1778,7 @@ DN_API DN_Str16 DN_OS_W32EXEDirW(DN_Arena *arena)
wchar_t *module_path = nullptr;
do {
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) {
DN_TCScratchEnd(&scratch);
return result;
@@ -1808,10 +1800,10 @@ DN_API DN_Str16 DN_OS_W32EXEDirW(DN_Arena *arena)
DN_API DN_Str8 DN_OS_W32WorkingDir(DN_Arena *arena, DN_Str8 suffix)
{
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str16 suffix16 = DN_OS_W32Str8ToStr16(scratch.arena, suffix);
DN_Str16 dir16 = DN_OS_W32WorkingDirW(scratch.arena, suffix16);
DN_Str8 result = DN_OS_W32Str16ToStr8(arena, dir16);
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_Str16 suffix16 = DN_OS_W32Str8ToStr16(&scratch.arena, suffix);
DN_Str16 dir16 = DN_OS_W32WorkingDirW(&scratch.arena, suffix16);
DN_Str8 result = DN_OS_W32Str16ToStr8(arena, dir16);
DN_TCScratchEnd(&scratch);
return result;
}
@@ -1822,11 +1814,11 @@ DN_API DN_Str16 DN_OS_W32WorkingDirW(DN_Arena *arena, DN_Str16 suffix)
DN_Str16 result = {};
// NOTE: required_size is the size required *including* the null-terminator
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
unsigned long required_size = GetCurrentDirectoryW(0, nullptr);
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) {
DN_TCScratchEnd(&scratch);
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"))) {
result.next_p += 2;
} else if (DN_INI_Str8Eq(esc_str8, DN_INIStr8Lit("\\"))) {
// NOTE: Backespace is escaping a backspace
// NOTE: Backspace is escaping a backspace
} else {
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->data[pos] == ' ') // Value can have spaces in it without quotes
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) {
result.type = DN_INITokenType_Error;
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;
}
#if defined(DN_INI_WITH_UNIT_TESTS) || 1
#if defined(DN_INI_WITH_UNIT_TESTS)
void DN_INI_UnitTests()
{
// 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(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
+113 -20
View File
@@ -1,34 +1,127 @@
#if !defined(DN_INI_H)
#define DN_INI_H
#include <stdint.h> // size_t
// 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"
#if !defined(DN_INI_Assert)
#include <assert.h>
#define DN_INI_Assert(expr) assert(expr)
#endif
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"
);
#include <stdarg.h>
// 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);
#if !defined(DN_INI_VSNPrintF)
#include <stdio.h>
#define DN_INI_VSNPrintF(buffer, size, fmt, args) vsnprintf(buffer, size, fmt, args)
#endif
// 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);
#if !defined(DN_INI_Memset) || !defined(DN_INI_Memcmp) || !defined(DN_INI_Memcpy)
#include <string.h>
#if !defined(DN_INI_Memset)
#define DN_INI_Memset(ptr, val, size) memset(ptr, val, 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
#if !defined(DN_INI_Assert)
#include <assert.h>
#define DN_INI_Assert(expr) assert(expr)
#endif
#if !defined(DN_INI_Memcmp)
#define DN_INI_Memcmp(dest, src, size) memcmp(dest, src, size)
#include <stdarg.h>
#if !defined(DN_INI_VSNPrintF)
#include <stdio.h>
#define DN_INI_VSNPrintF(buffer, size, fmt, args) vsnprintf(buffer, size, fmt, args)
#endif
#if !defined(DN_INI_Memcpy)
#define DN_INI_Memcpy(dest, src, size) memcpy(dest, src, size)
#if !defined(DN_INI_Memset) || !defined(DN_INI_Memcmp) || !defined(DN_INI_Memcpy)
#include <string.h>
#if !defined(DN_INI_Memset)
#define DN_INI_Memset(ptr, val, size) memset(ptr, val, size)
#endif
#if !defined(DN_INI_Memcmp)
#define DN_INI_Memcmp(dest, src, size) memcmp(dest, src, size)
#endif
#if !defined(DN_INI_Memcpy)
#define DN_INI_Memcpy(dest, src, size) memcpy(dest, src, size)
#endif
#endif
#endif
typedef enum DN_INITokenType {
DN_INITokenType_Nil,
@@ -175,7 +268,7 @@ DN_INIFieldStr8 DN_INI_FieldStr8FromSectionStr8 (DN_INISection *section, DN
DN_INIFieldBool DN_INI_FieldBoolFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8);
DN_INICore DN_INI_ParseFromPtr (char const *buf, size_t count, char *base, size_t base_count);
// NOTE: Building
// NOTE: Building
DN_INISection * DN_INI_AppendSectionF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *fmt, ...);
DN_INIField * DN_INI_AppendKeyBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, bool value);
DN_INIField * DN_INI_AppendKeyPtrBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, bool value);
+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_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_BeginF(DN_UTCore *test, char const *fmt, ...);
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
}
{
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)
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
// NOTE: Setup the allocation table with allocation tracking turned off on
// 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);
#endif
}
@@ -106,7 +107,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
DN_Assert(dn->os_init);
#if DN_H_WITH_OS
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);
#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)) {
DN_Arena *arena = dn->main_tc.main_arena;
DN_Str8 mem_funcs = DN_Str8Lit("");
switch (arena->mem_funcs.type) {
case DN_ArenaMemFuncType_Nil: break;
case DN_ArenaMemFuncType_Basic: mem_funcs = DN_Str8Lit("Basic"); break;
case DN_ArenaMemFuncType_VMem: mem_funcs = DN_Str8Lit("VMem"); break;
switch (arena->mem->funcs.type) {
case DN_MemFuncsType_Nil: break;
case DN_MemFuncsType_Heap: mem_funcs = DN_Str8Lit("Heap"); 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_reserve = DN_ByteCountStr8x32(dn->main_tc.main_arena->curr->reserve);
DN_Str8x32 temp_commit = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->curr->commit);
DN_Str8x32 temp_reserve = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->curr->reserve);
DN_Str8x32 err_commit = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->curr->commit);
DN_Str8x32 err_reserve = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->curr->reserve);
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->mem->curr->reserve);
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->mem->curr->reserve);
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->mem->curr->reserve);
DN_FmtAppendTruncate(buf,
&buf_size,
sizeof(buf),
+64 -4
View File
@@ -82,6 +82,65 @@
//
// This means functionality that relies on the OS like printing, memory allocation, stack traces
// 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_assert.h"
@@ -110,10 +169,10 @@ enum DN_InitFlags_
{
DN_InitFlags_Nil = 0,
DN_InitFlags_OS = (1 << 0),
DN_InitFlags_LeakTracker = (1 << 1) | DN_InitFlags_OS,
DN_InitFlags_LogLibFeatures = (1 << 2),
DN_InitFlags_LogCPUFeatures = (1 << 3) | DN_InitFlags_OS,
DN_InitFlags_ThreadContext = (1 << 4) | DN_InitFlags_OS,
DN_InitFlags_ThreadContext = (1 << 1) | DN_InitFlags_OS,
DN_InitFlags_LeakTracker = (1 << 2) | DN_InitFlags_OS,
DN_InitFlags_LogLibFeatures = (1 << 3),
DN_InitFlags_LogCPUFeatures = (1 << 4) | DN_InitFlags_OS,
DN_InitFlags_LogAllFeatures = DN_InitFlags_LogLibFeatures | DN_InitFlags_LogCPUFeatures,
};
@@ -124,6 +183,7 @@ struct DN_Core
DN_USize mem_allocs_frame;
DN_LeakTracker leak;
DN_U32 log_level_to_show_from;
DN_LogPrintFunc* print_func;
void* print_func_context;