Fix single header build with updated DN lib
This commit is contained in:
+95
-21883
File diff suppressed because it is too large
Load Diff
+6517
-15195
File diff suppressed because it is too large
Load Diff
+1105
-521
File diff suppressed because it is too large
Load Diff
+343
-165
@@ -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
|
||||
@@ -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_MemFuncsType type;
|
||||
DN_MemHeapAllocFunc *heap_alloc;
|
||||
DN_MemHeapDeallocFunc *heap_dealloc;
|
||||
|
||||
DN_U32 virtual_page_size;
|
||||
DN_MemVirtualReserveFunc *virtual_reserve;
|
||||
DN_MemVirtualCommitFunc *virtual_commit;
|
||||
DN_MemVirtualReleaseFunc *virtual_release;
|
||||
};
|
||||
|
||||
struct DN_MemBlock
|
||||
{
|
||||
DN_MemBlock* prev;
|
||||
DN_U64 used;
|
||||
DN_U64 commit;
|
||||
DN_U64 reserve;
|
||||
DN_U64 reserve_sum;
|
||||
};
|
||||
|
||||
typedef DN_U32 DN_ArenaFlags;
|
||||
enum DN_ArenaFlags_
|
||||
{
|
||||
DN_ArenaFlags_Nil = 0,
|
||||
DN_ArenaFlags_NoGrow = 1 << 0,
|
||||
DN_ArenaFlags_NoPoison = 1 << 1,
|
||||
DN_ArenaFlags_NoAllocTrack = 1 << 2,
|
||||
DN_ArenaFlags_AllocCanLeak = 1 << 3,
|
||||
DN_ArenaFlags_SimAlloc = 1 << 4,
|
||||
|
||||
// NOTE: Internal flags. Do not use
|
||||
DN_ArenaFlags_UserBuffer = 1 << 4,
|
||||
DN_ArenaFlags_MemFuncs = 1 << 5,
|
||||
};
|
||||
|
||||
struct DN_ArenaInfo
|
||||
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,6 +995,9 @@ enum DN_Str8IsAllType
|
||||
|
||||
struct DN_Str8BSplitResult
|
||||
{
|
||||
// If there are multiple strings passed to split against, this is the index into that array of
|
||||
// which the string was split on. If no array was passed this is always 0.
|
||||
DN_USize input_index;
|
||||
DN_Str8 lhs;
|
||||
DN_Str8 rhs;
|
||||
};
|
||||
@@ -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;
|
||||
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,8 +1201,7 @@ struct DN_ErrSink
|
||||
|
||||
struct DN_TCScratch
|
||||
{
|
||||
DN_Arena* arena;
|
||||
DN_ArenaTempMem temp_mem;
|
||||
DN_Arena arena;
|
||||
DN_B32 destructed;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -5,6 +5,17 @@
|
||||
// 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.
|
||||
//
|
||||
// Arrays
|
||||
//
|
||||
// Data structures that have a `T *data`, `DN_USize count` and `DN_USize max` capacity that can be
|
||||
// dynamically shrunk or expanded.
|
||||
//
|
||||
// API
|
||||
// ResizeFrom: Resizes the array to `new_max` erase elements if resizing to a smaller size
|
||||
// GrowFrom: Expands the capacity of the array if `new_max > array.max` otherwise no-op
|
||||
// GrowIfNeeded: Expands the capacity of the array if `array.size + add_count > array.max` otherwise no-op
|
||||
//
|
||||
// Variants
|
||||
// PArray => Pointer (to) Array
|
||||
// LArray => Literal Array
|
||||
// Define a C array and size. (P) array macros take a pointer to the aray, its size and its max
|
||||
@@ -24,8 +35,17 @@
|
||||
// DN_USize size;
|
||||
// DN_USize 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,9 +221,9 @@ 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) \
|
||||
#define DN_SentinelDoublyLLInitArena(list, T, ptr_arena) \
|
||||
do { \
|
||||
(list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \
|
||||
(list) = DN_ArenaNew(ptr_arena, T, DN_ZMem_Yes); \
|
||||
DN_SentinelDoublyLLInit(list); \
|
||||
} while (0)
|
||||
|
||||
@@ -286,28 +336,28 @@ 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)
|
||||
@@ -315,47 +365,47 @@ template <typename T> struct DN_DSMapResult
|
||||
#define DN_LArrayGrowFromArena(c_array, size, arena, new_max) DN_PArrayGrowFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max)
|
||||
#define DN_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_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);
|
||||
|
||||
@@ -381,6 +431,9 @@ DN_API void DN_RingWrite
|
||||
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);
|
||||
template <typename T> bool DN_DSMapIsValid (DN_DSMap<T> const *map);
|
||||
@@ -399,8 +452,8 @@ template <typename T> bool DN_DSMapResize (DN_DSMap
|
||||
template <typename T> bool DN_DSMapErase (DN_DSMap<T> *map, DN_DSMapKey key);
|
||||
template <typename T> bool DN_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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
+35
-37
@@ -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.
|
||||
@@ -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
|
||||
|
||||
+34
-2
@@ -1,9 +1,18 @@
|
||||
#if !defined(DN_CSV_H)
|
||||
#define DN_CSV_H
|
||||
|
||||
#if defined(_CLANGD)
|
||||
// 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
|
||||
#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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+15
-11
@@ -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->start_response_arena = DN_ArenaTempBeginFromArena(&request->arena);
|
||||
}
|
||||
|
||||
DN_NETRequestHandle result = DN_NET_HandleFromRequest(request);
|
||||
|
||||
+20
-17
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -396,8 +396,9 @@ void DN_NET_CurlInit(DN_NETCore *net, char *base, DN_U64 base_size)
|
||||
DN_NET_BaseInit_(net, base, base_size);
|
||||
DN_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);
|
||||
|
||||
|
||||
+349
-228
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,8 @@
|
||||
#define DN_NO_WINDOWS_H_REPLACEMENT_HEADER
|
||||
#endif
|
||||
|
||||
#define DN_ARENA_TEMP_MEM_UAF_GUARD 1
|
||||
#define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 0
|
||||
#define DN_H_WITH_OS 1
|
||||
#define DN_H_WITH_CORE 1
|
||||
#define DN_H_WITH_HASH 1
|
||||
@@ -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
|
||||
|
||||
+116
-79
@@ -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 = {};
|
||||
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_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,13 +136,17 @@ DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite ca
|
||||
DN_TicketMutex_Begin(&os->log_file_mutex);
|
||||
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);
|
||||
|
||||
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;
|
||||
@@ -181,26 +183,35 @@ DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite ca
|
||||
log_date.hour = os_date.hour;
|
||||
log_date.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));
|
||||
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);
|
||||
{
|
||||
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_FileWriteF(&os->log_file, nullptr, "%*s ", DN_Cast(int) prefix_size.padding, "");
|
||||
}
|
||||
DN_OS_FileWriteFV(&os->log_file, nullptr, fmt, args_copy);
|
||||
if (!DN_BitIsSet(flags, DN_LogFlags_NoNewLine))
|
||||
DN_OS_FileWrite(&os->log_file, DN_Str8Lit("\n"), nullptr);
|
||||
}
|
||||
DN_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()
|
||||
@@ -240,10 +251,10 @@ DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena)
|
||||
if (!arena)
|
||||
return result;
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
|
||||
DN_Str8 exe_path = DN_OS_EXEPath(scratch.arena);
|
||||
DN_Str8 exe_path = DN_OS_EXEPath(&scratch.arena);
|
||||
DN_Str8 separators[] = {DN_Str8Lit("/"), DN_Str8Lit("\\")};
|
||||
DN_Str8BSplitResult split = DN_Str8BSplitLastArray(exe_path, separators, DN_ArrayCountU(separators));
|
||||
result = DN_Str8FromStr8Arena(arena, split.lhs);
|
||||
result = DN_Str8FromStr8Arena(split.lhs, arena);
|
||||
DN_TCScratchEnd(&scratch);
|
||||
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) {
|
||||
@@ -418,29 +429,39 @@ 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);
|
||||
bool failed = file.error || !read.success;
|
||||
|
||||
if (allocator.type == DN_AllocatorType_Arena) {
|
||||
DN_ArenaTempEnd(&temp_arena, failed ? DN_ArenaReset_Yes : DN_ArenaReset_No);
|
||||
} else {
|
||||
DN_Pool *pool = DN_Cast(DN_Pool *) allocator;
|
||||
if (failed) {
|
||||
DN_Pool *pool = DN_Cast(DN_Pool *) allocator.context;
|
||||
DN_PoolDealloc(pool, result.data);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -455,7 +476,7 @@ DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error)
|
||||
DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str8 buffer = DN_Str8FromFmtVArena(scratch.arena, fmt, args);
|
||||
DN_Str8 buffer = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
|
||||
bool result = DN_OS_FileWriteAll(file_path, buffer, error);
|
||||
DN_TCScratchEnd(&scratch);
|
||||
return result;
|
||||
@@ -473,7 +494,7 @@ DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATT
|
||||
DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error)
|
||||
{
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str8 tmp_path = DN_Str8FromFmtArena(scratch.arena, "%.*s.tmp", DN_Str8PrintFmt(path));
|
||||
DN_Str8 tmp_path = DN_Str8FromFmtArena(&scratch.arena, "%.*s.tmp", DN_Str8PrintFmt(path));
|
||||
if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) {
|
||||
DN_TCScratchEnd(&scratch);
|
||||
return false;
|
||||
@@ -493,7 +514,7 @@ DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err
|
||||
DN_API bool DN_OS_FileWriteAllSafeFV(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str8 buffer = DN_Str8FromFmtVArena(scratch.arena, fmt, args);
|
||||
DN_Str8 buffer = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
|
||||
bool result = DN_OS_FileWriteAllSafe(path, buffer, error);
|
||||
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) {
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,7 +1203,7 @@ DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, DN_U16 limit)
|
||||
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_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);
|
||||
}
|
||||
@@ -1247,7 +1283,7 @@ DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkR
|
||||
return result;
|
||||
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
|
||||
DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip);
|
||||
result = DN_Str8BuilderBuild(&builder, arena);
|
||||
DN_TCScratchEnd(&scratch);
|
||||
@@ -1257,7 +1293,7 @@ DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkR
|
||||
DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, DN_U16 limit, DN_U16 skip)
|
||||
{
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
|
||||
DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, limit);
|
||||
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&scratch.arena, limit);
|
||||
DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip);
|
||||
DN_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
@@ -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, ...);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+67
-75
@@ -211,7 +211,7 @@ 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_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
|
||||
|
||||
ULARGE_INTEGER free_bytes_avail_to_caller;
|
||||
ULARGE_INTEGER total_number_of_bytes;
|
||||
@@ -234,8 +234,8 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
|
||||
DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value)
|
||||
{
|
||||
DN_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_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;
|
||||
@@ -247,7 +247,7 @@ DN_API DN_Str8 DN_OS_EXEPath(DN_Arena *arena)
|
||||
if (!arena)
|
||||
return result;
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
|
||||
DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(scratch.arena);
|
||||
DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(&scratch.arena);
|
||||
result = DN_OS_W32Str16ToStr8(arena, exe_dir16);
|
||||
DN_TCScratchEnd(&scratch);
|
||||
return result;
|
||||
@@ -287,14 +287,14 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink
|
||||
{
|
||||
bool result = false;
|
||||
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);
|
||||
|
||||
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)
|
||||
@@ -367,7 +367,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 ac
|
||||
}
|
||||
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
|
||||
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,
|
||||
@@ -377,7 +377,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 ac
|
||||
/*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,
|
||||
@@ -456,7 +456,7 @@ 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_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);
|
||||
@@ -472,7 +472,7 @@ 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_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);
|
||||
}
|
||||
@@ -495,7 +495,7 @@ DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path)
|
||||
return result;
|
||||
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) {
|
||||
@@ -531,7 +531,7 @@ DN_API bool DN_OS_PathDelete(DN_Str8 path)
|
||||
return result;
|
||||
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
|
||||
if (path16.size) {
|
||||
result = DeleteFileW(path16.data);
|
||||
if (!result)
|
||||
@@ -548,7 +548,7 @@ DN_API bool DN_OS_PathIsFile(DN_Str8 path)
|
||||
return result;
|
||||
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
|
||||
if (path16.size) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
|
||||
@@ -566,7 +566,7 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
|
||||
return result;
|
||||
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
|
||||
if (path16.size) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
|
||||
if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data))
|
||||
@@ -582,7 +582,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
|
||||
{
|
||||
bool result = true;
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
|
||||
|
||||
// NOTE: Go back from the end of the string to all the directories in the
|
||||
// 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,
|
||||
@@ -828,8 +826,8 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *are
|
||||
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,7 +1321,7 @@ 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;
|
||||
@@ -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;
|
||||
@@ -1450,12 +1447,11 @@ 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 = 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;
|
||||
if (!response->scratch_arena.mem)
|
||||
response->scratch_arena = scratch_.arena;
|
||||
|
||||
DN_OSW32Error error = {};
|
||||
DN_DEFER
|
||||
@@ -1489,15 +1485,15 @@ 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,
|
||||
@@ -1510,7 +1506,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
|
||||
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;
|
||||
|
||||
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;
|
||||
temp_mem.mem = {};
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
@@ -1809,8 +1801,8 @@ DN_API DN_Str16 DN_OS_W32EXEDirW(DN_Arena *arena)
|
||||
DN_API DN_Str8 DN_OS_W32WorkingDir(DN_Arena *arena, DN_Str8 suffix)
|
||||
{
|
||||
DN_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_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;
|
||||
@@ -1826,7 +1818,7 @@ DN_API DN_Str16 DN_OS_W32WorkingDirW(DN_Arena *arena, DN_Str16 suffix)
|
||||
unsigned long required_size = GetCurrentDirectoryW(0, nullptr);
|
||||
unsigned long 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;
|
||||
|
||||
@@ -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
|
||||
|
||||
+101
-8
@@ -1,21 +1,114 @@
|
||||
#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)
|
||||
void main() {
|
||||
DN_INIStr8 ini_buffer = DN_INIStr8Lit(
|
||||
"[my_stuff]\n"
|
||||
"app=the_stuff # Comment on the stuff value\n"
|
||||
"\n"
|
||||
"[section]\n"
|
||||
"item=abc\n"
|
||||
"\n"
|
||||
"[section.foo.xyz]\n"
|
||||
"another=one\n"
|
||||
"multi_line_key=coolios \\\n"
|
||||
"from another line?!\n"
|
||||
);
|
||||
|
||||
// NOTE: Calculate the number of bytes required to parse the buffer and make one single
|
||||
// allocation
|
||||
DN_INICore ini = DN_INI_ParseFromPtr(ini_buffer.data, ini_buffer.size, NULL, 0);
|
||||
size_t parse_buffer_size = ini.memory_required;
|
||||
char* parse_buffer = calloc(1, parse_buffer_size);
|
||||
|
||||
// NOTE: Parse the buffer into the `ini` object from the single allocation. No additional
|
||||
// allocations are made
|
||||
ini = DN_INI_ParseFromPtr(ini_buffer.data, ini_buffer.size, parse_buffer, parse_buffer_size);
|
||||
|
||||
// NOTE: Process the ini file
|
||||
// The .INI file parsed into a tree, resembling
|
||||
//
|
||||
// [Root (Sentinel)] <-- This is ini.first_section, its children contains the .ini contents
|
||||
// |
|
||||
// +-- [my_stuff]
|
||||
// +-- [my_section]
|
||||
// |
|
||||
// +-- [foo]
|
||||
// |
|
||||
// +-- [xyz]
|
||||
//
|
||||
DN_INISection *my_stuff = DN_INI_ChildSectionFromStr8(&ini.first_section, DN_INIStr8Lit("my_stuff"));
|
||||
DN_INISection *my_section = DN_INI_ChildSectionFromStr8(&ini.first_section, DN_INIStr8Lit("my_section"));
|
||||
DN_INISection *my_section_foo = DN_INI_ChildSectionFromStr8(my_section, DN_INIStr8Lit("foo"));
|
||||
DN_INISection *my_section_foo_xyz = DN_INI_ChildSectionFromStr8(my_section_foo, DN_INIStr8Lit("xyz"));
|
||||
|
||||
printf("My Section Foo XYZ: %zu fields\n", my_section_foo_xyz->fields_count);
|
||||
for (DN_INIField *field = my_section_foo->first_field; field; field = field->next)
|
||||
printf(" %.*s: %.*s\n", (int)field->key.size, field->key.data, (int)field->value.size, field->value.data);
|
||||
|
||||
// Alternatively you can access the section directly by specifying the fully qualified path from
|
||||
// the section, e.g.:
|
||||
DN_INISection *my_section_foo_xyz_direct = DN_INI_ChildSectionFromStr8(&ini.first_section, DN_INIStr8Lit("my_section.foo.xyz"));
|
||||
if (my_section_foo_xyz_direct) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// You may also lookup the field directly by specifying the fully qualified path
|
||||
DN_INIField *my_section_item = DN_INI_FieldFromSectionStr8(&ini.first_section, DN_INIStr8Lit("my_section.item"));
|
||||
if (my_section_item)
|
||||
printf(" %.*s: %.*s\n", (int)my_section_item->key.size, my_section_item->key.data, (int)my_section_item->value.size, my_section_item->value.data);
|
||||
|
||||
// NOTE: Release memory, `ini` and its contents are invalidated and should not be used
|
||||
free(parse_buffer);
|
||||
}
|
||||
*/
|
||||
|
||||
#include <stdint.h> // size_t
|
||||
|
||||
#if !defined(DN_INI_Assert)
|
||||
#include <assert.h>
|
||||
#define DN_INI_Assert(expr) assert(expr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if !defined(DN_INI_VSNPrintF)
|
||||
#if !defined(DN_INI_VSNPrintF)
|
||||
#include <stdio.h>
|
||||
#define DN_INI_VSNPrintF(buffer, size, fmt, args) vsnprintf(buffer, size, fmt, args)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(DN_INI_Memset) || !defined(DN_INI_Memcmp) || !defined(DN_INI_Memcpy)
|
||||
#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)
|
||||
@@ -28,7 +121,7 @@
|
||||
#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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ pushd %build_dir%
|
||||
|
||||
where /q emcc && (
|
||||
echo [BUILD] Emscripten emcc detected, compiling ...
|
||||
call emcc -g -msimd128 -msse2 %flags% -o %build_dir%\dn_unit_tests_emcc.js -s FETCH=1 -pthread -s ASYNCIFY=1 -lwebsocket -Wall
|
||||
call emcc -g -msimd128 -msse2 %flags% -o %build_dir%\dn_unit_tests_emcc.js -s FETCH=1 -pthread -s ASYNCIFY=1 -lwebsocket -Wall || echo Failed&& exit /b 1
|
||||
)
|
||||
|
||||
where /q cl && (
|
||||
@@ -50,15 +50,16 @@ pushd %build_dir%
|
||||
)
|
||||
set msvc_cmd=!msvc_cmd! -link
|
||||
|
||||
powershell -Command "$time = Measure-Command { !msvc_cmd! | Out-Default }; Write-Host '[BUILD] msvc:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1
|
||||
call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -link
|
||||
call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single-Header
|
||||
powershell -Command "$time = Measure-Command { !msvc_cmd! | Out-Default }; Write-Host '[BUILD] msvc:'$time.TotalSeconds's'; exit $LASTEXITCODE" || echo MSVC build failed&& exit /b 1
|
||||
echo [BUILD] Single header generator ...
|
||||
call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -link || echo Single header generator build failed&& exit /b 1
|
||||
call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single-Header || echo Single header generation failed&& exit /b 1
|
||||
)
|
||||
|
||||
where /q clang-cl && (
|
||||
echo [BUILD] LLVM clang-cl detected, compiling ...
|
||||
set clang_cmd=clang-cl -MT %msvc_driver_flags% -fsanitize=undefined -Fe:dn_unit_tests_clang -link
|
||||
powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1
|
||||
powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || echo CLANG build failed&& exit /b 1
|
||||
)
|
||||
|
||||
exit /b 1
|
||||
|
||||
+49
-81
@@ -29,10 +29,12 @@ struct File
|
||||
|
||||
static void AppendCppFileLineByLine(DN_Str8Builder *dest, DN_Str8 cpp_path)
|
||||
{
|
||||
DN_OSErrSink *err = DN_OS_ErrSinkBeginDefault();
|
||||
DN_Str8 buffer = DN_OS_FileReadAllTLS(cpp_path, err);
|
||||
DN_OS_ErrSinkEndAndExitIfErrorF(err, -1, "Failed to load file from '%S' for appending", cpp_path);
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(&dest->arena, 1);
|
||||
DN_ErrSink *err = DN_TCErrSinkBeginDefault();
|
||||
DN_Str8 buffer = DN_OS_FileReadAllArena(&scratch.arena, cpp_path, err);
|
||||
DN_ErrSinkEndExitIfErrorF(err, -1, "Failed to load file from '%S' for appending", cpp_path);
|
||||
|
||||
bool inside_clangd_preprocessor_block = false;
|
||||
for (DN_Str8 inc_walker = buffer;;) {
|
||||
DN_Str8BSplitResult split = DN_Str8BSplit(inc_walker, DN_Str8Lit("\n"));
|
||||
if (split.lhs.size == 0)
|
||||
@@ -42,42 +44,59 @@ static void AppendCppFileLineByLine(DN_Str8Builder *dest, DN_Str8 cpp_path)
|
||||
// NOTE: Trim the whitespace, mainly for windows, the file we read will have \r\n whereas we just want to emit \n
|
||||
DN_Str8 line = DN_Str8TrimTailWhitespace(split.lhs);
|
||||
|
||||
// NOTE: Comment out any #include "../dn_.*" matches if we encounter one
|
||||
DN_Str8FindResult find = DN_Str8FindStr8(line, DN_Str8Lit("#include \"../dn_"), DN_Str8EqCase_Sensitive);
|
||||
{
|
||||
// NOTE: Detect if we're inside a clangd preprocessor block
|
||||
// TODO: This breaks if there's any nested #if's in the block (we naiively match on #endif)
|
||||
bool commented_out = false;
|
||||
if (!inside_clangd_preprocessor_block) {
|
||||
DN_Str8FindResult find = DN_Str8FindStr8(line, DN_Str8Lit("#if defined(_CLANGD)"), DN_Str8EqCase_Sensitive);
|
||||
if (find.found) {
|
||||
line = DN_Str8FromTLSF("%S// DN: Single header generator commented out this header => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
|
||||
|
||||
// The only time we use '../dn_.*' is for LSP purposes, so we
|
||||
// don't care about inlining it, hence we don't set 'include_file'
|
||||
line = DN_Str8FromFmtArena(&scratch.arena, "%S// DN: Single header generator commented out => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
|
||||
commented_out = true;
|
||||
inside_clangd_preprocessor_block = true;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Inline any other relative includes if we encounter one
|
||||
// (Right now DN only includes stb_sprintf with a relative path)
|
||||
// NOTE: Inline relative includes as long as we're not inside a CLANDG block
|
||||
DN_Str8 extra_include_path = {};
|
||||
if (!find.found) {
|
||||
find = DN_Str8FindStr8(line, DN_Str8Lit("#include \""), DN_Str8EqCase_Sensitive);
|
||||
if (!inside_clangd_preprocessor_block) {
|
||||
DN_Str8 ignore_patterns[] = {
|
||||
DN_Str8Lit("#include \"dn.h\""),
|
||||
DN_Str8Lit("#include \"dn.cpp\""),
|
||||
};
|
||||
|
||||
DN_Str8FindResult ignore = DN_Str8FindStr8Array(line, ignore_patterns, DN_ArrayCountU(ignore_patterns), DN_Str8EqCase_Sensitive);
|
||||
if (!ignore.found) {
|
||||
DN_Str8FindResult find = DN_Str8FindStr8(line, DN_Str8Lit("#include \""), DN_Str8EqCase_Sensitive);
|
||||
if (find.found) {
|
||||
line = DN_Str8FromTLSF("%S// DN: Single header generator commented out this header => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
|
||||
line = DN_Str8FromFmtArena(&scratch.arena, "%S// DN: Single header generator commented out => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
|
||||
DN_Str8 rel_include_path = DN_Str8TrimWhitespaceAround(find.after_match_to_end_of_buffer);
|
||||
DN_Str8 root_dir = DN_Str8FileDirectoryFromPath(cpp_path);
|
||||
extra_include_path = DN_OS_PathFFromTLS("%S/%S", root_dir, DN_Str8TrimSuffix(rel_include_path, DN_Str8Lit("\"")));
|
||||
extra_include_path = DN_OS_PathF(&scratch.arena, "%S/%S", root_dir, DN_Str8TrimSuffix(rel_include_path, DN_Str8Lit("\"")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DN_Str8BuilderAppendRef(dest, line);
|
||||
// NOTE: Detect if we're at the end of the CLAND block
|
||||
if (inside_clangd_preprocessor_block) {
|
||||
if (!commented_out)
|
||||
line = DN_Str8FromFmtArena(&scratch.arena, "// %S", line);
|
||||
if (DN_Str8FindStr8(line, DN_Str8Lit("#endif"), DN_Str8EqCase_Sensitive).found)
|
||||
inside_clangd_preprocessor_block = false;
|
||||
}
|
||||
|
||||
DN_Str8BuilderAppendCopy(dest, line);
|
||||
DN_Str8BuilderAppendRef(dest, DN_Str8Lit("\n"));
|
||||
|
||||
if (extra_include_path.size)
|
||||
AppendCppFileLineByLine(dest, extra_include_path);
|
||||
}
|
||||
DN_TCScratchEnd(&scratch);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DN_Core dn = {};
|
||||
DN_Init(&dn, DN_InitFlags_OS, nullptr);
|
||||
DN_Init(&dn, DN_InitFlags_OS | DN_InitFlags_ThreadContext, nullptr);
|
||||
|
||||
if (argc != 3) {
|
||||
DN_OS_PrintErrF("USAGE: %s <path/to/dn/Source> <output_dir>", argv[0]);
|
||||
@@ -91,81 +110,30 @@ int main(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
File const FILES[] = {
|
||||
{FileType_Header, DN_Str8Lit("dn.h")},
|
||||
{FileType_Impl, DN_Str8Lit("dn.cpp")},
|
||||
};
|
||||
|
||||
for (DN_ForIndexU(type, FileType_Count)) {
|
||||
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
|
||||
for (DN_ForItCArray(it, File const, FILES)) {
|
||||
if (it.data->type != type)
|
||||
continue;
|
||||
|
||||
// NOTE: Parse the include files in the *_inc.[h|cpp] files
|
||||
DN_Str8 path = DN_OS_PathFFromTLS("%S/%S", dn_root_dir, it.data->file_name);
|
||||
{
|
||||
DN_OSErrSink *err = DN_OS_ErrSinkBeginDefault();
|
||||
DN_Str8 file_buffer = DN_OS_FileReadAllTLS(path, err);
|
||||
DN_OS_ErrSinkEndAndExitIfErrorF(err, -1, "Failed to load file");
|
||||
|
||||
// NOTE: Walk the top-level dn_*_inc.[h|cpp] files
|
||||
for (DN_Str8 walker = file_buffer;;) {
|
||||
DN_Str8BSplitResult split = DN_Str8BSplit(walker, DN_Str8Lit("\n"));
|
||||
if (split.lhs.size == 0)
|
||||
break;
|
||||
|
||||
// NOTE: Parse the line, if it was a #include, extract it into this string
|
||||
DN_Str8 include_file = {};
|
||||
{
|
||||
walker = split.rhs;
|
||||
DN_Str8 line = DN_Str8TrimTailWhitespace(split.lhs);
|
||||
|
||||
// NOTE: Comment out any #include "dn_.*" matches if we encounter one
|
||||
DN_Str8FindResult find = DN_Str8FindStr8(line, DN_Str8Lit("#include \""), DN_Str8EqCase_Sensitive);
|
||||
{
|
||||
if (find.found && DN_Str8FindStr8(line, DN_Str8Lit("dn_"), DN_Str8EqCase_Sensitive).found) {
|
||||
line = DN_Str8FromTLSF("%S// DN: Single header generator inlined this file => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
|
||||
include_file = DN_Str8BSplit(find.after_match_to_end_of_buffer, DN_Str8Lit("\"")).lhs;
|
||||
DN_Assert(include_file.size);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Record the line
|
||||
DN_Str8BuilderAppendRef(&builder, line);
|
||||
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
|
||||
}
|
||||
|
||||
if (include_file.size) { // NOTE: If the line was a include file, we will inline the included file
|
||||
DN_Str8 include_path = DN_OS_PathFFromTLS("%S/%S", dn_root_dir, include_file);
|
||||
AppendCppFileLineByLine(&builder, include_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DN_Str8 extra_files[] = {
|
||||
DN_Str8Lit("Extra/dn_math"),
|
||||
DN_Str8 const REL_FILE_PATHS[] = {
|
||||
DN_Str8Lit("dn"),
|
||||
DN_Str8Lit("Extra/dn_async"),
|
||||
DN_Str8Lit("Extra/dn_bin_pack"),
|
||||
DN_Str8Lit("Extra/dn_csv"),
|
||||
DN_Str8Lit("Extra/dn_hash"),
|
||||
DN_Str8Lit("Extra/dn_helpers"),
|
||||
};
|
||||
|
||||
for (DN_ForIndexU(type, FileType_Count)) {
|
||||
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
|
||||
DN_Str8 suffix = type == FileType_Header ? DN_Str8Lit("h") : DN_Str8Lit("cpp");
|
||||
for (DN_ForItCArray(extra_it, DN_Str8, extra_files)) {
|
||||
DN_Str8 extra_path = DN_OS_PathFFromTLS("%S/%S.%S", dn_root_dir, *extra_it.data, suffix);
|
||||
for (DN_ForItCArray(extra_it, DN_Str8 const, REL_FILE_PATHS)) {
|
||||
DN_Str8 extra_path = DN_OS_PathF(&scratch.arena, "%S/%S.%S", dn_root_dir, *extra_it.data, suffix);
|
||||
AppendCppFileLineByLine(&builder, extra_path);
|
||||
}
|
||||
|
||||
DN_Date date = DN_OS_DateLocalTimeNow();
|
||||
DN_Str8BuilderPrependF(&builder, "// Generated by the DN single header generator %04u-%02u-%02u %02u:%02u:%02u\n\n", date.year, date.month, date.day, date.hour, date.minutes, date.seconds);
|
||||
|
||||
DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8BuilderBuildFromTLS(&builder));
|
||||
DN_Str8 single_header_path = DN_OS_PathFFromTLS("%S/dn_single_header.%S", output_dir, suffix);
|
||||
DN_OSErrSink *err = DN_OS_ErrSinkBeginDefault();
|
||||
DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8BuilderBuild(&builder, &scratch.arena));
|
||||
DN_Str8 single_header_path = DN_OS_PathF(&scratch.arena, "%S/dn_single_header.%S", output_dir, suffix);
|
||||
DN_ErrSink *err = DN_TCErrSinkBeginDefault();
|
||||
DN_OS_FileWriteAllSafe(single_header_path, buffer, err);
|
||||
DN_OS_ErrSinkEndAndExitIfErrorF(err, -1, "Failed to write Single header file '%S'", single_header_path);
|
||||
DN_ErrSinkEndExitIfErrorF(err, -1, "Failed to write Single header file '%S'", single_header_path);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user