diff --git a/Source/Base/dn_base.cpp b/Source/Base/dn_base.cpp index 4cadb73..eb14d1b 100644 --- a/Source/Base/dn_base.cpp +++ b/Source/Base/dn_base.cpp @@ -1,7 +1,7 @@ #define DN_BASE_CPP #if defined(_CLANGD) - #include "../dn_base_inc.h" + #include "../dn_base.h" #endif DN_API bool DN_MemEq(void const *lhs, DN_USize lhs_size, void const *rhs, DN_USize rhs_size) @@ -52,6 +52,28 @@ DN_API DN_U32 DN_AtomicSetValue32(DN_U32 volatile *target, DN_U32 value) #endif } +DN_API DN_USize DN_AlignUpPowerOfTwoUSize(DN_USize val) +{ + DN_USize leading_zeros = DN_CountLeadingZerosUSize(val); + DN_USize bits = sizeof(DN_USize) * 8 - 1; + DN_USize result = leading_zeros == 0 ? SIZE_MAX : 1ULL << (bits - leading_zeros + 1); + return result; +} + +DN_API DN_U64 DN_AlignUpPowerOfTwoU64(DN_U64 val) +{ + DN_U64 leading_zeros = DN_CountLeadingZerosU64(val); + DN_U64 result = leading_zeros == 0 ? UINT64_MAX : 1ULL << (63 - leading_zeros + 1); + return result; +} + +DN_API DN_U32 DN_AlignUpPowerOfTwoU32(DN_U32 val) +{ + DN_U32 leading_zeros = DN_CountLeadingZerosU32(val); + DN_U32 result = leading_zeros == 0 ? UINT32_MAX : 1ULL << (31 - leading_zeros + 1); + return result; +} + DN_API DN_CPUIDResult DN_CPUID(DN_CPUIDArgs args) { DN_CPUIDResult result = {}; @@ -1007,7 +1029,7 @@ DN_API void *DN_ArenaAlloc(DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem char *commit_ptr = DN_Cast(char *) curr + curr->commit; if (!arena->mem_funcs.vmem_commit(commit_ptr, commit_size, DN_MemPage_ReadWrite)) return nullptr; - if (poison) + if (poison && DN_BitIsNotSet(arena->flags, DN_ArenaFlags_SimAlloc)) DN_ASanPoisonMemoryRegion(commit_ptr, commit_size); curr->commit = end_commit; arena->stats.info.commit += commit_size; @@ -1018,9 +1040,11 @@ DN_API void *DN_ArenaAlloc(DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem curr->used += alloc_size; arena->stats.info.used += alloc_size; arena->stats.hwm.used = DN_Max(arena->stats.hwm.used, arena->stats.info.used); - DN_ASanUnpoisonMemoryRegion(result, size); - if (z_mem == DN_ZMem_Yes) { + if (DN_BitIsNotSet(arena->flags, DN_ArenaFlags_SimAlloc)) + DN_ASanUnpoisonMemoryRegion(result, size); + + if (z_mem == DN_ZMem_Yes && DN_BitIsNotSet(arena->flags, DN_ArenaFlags_SimAlloc)) { DN_USize reused_bytes = DN_Min(prev_arena_commit - offset_pos, size); DN_Memset(result, 0, reused_bytes); } @@ -1281,6 +1305,372 @@ DN_API void DN_PoolDealloc(DN_Pool *pool, void *ptr) pool->slots[slot_index] = slot; } +static void DN_ErrSinkCheck_(DN_ErrSink const *err) +{ + DN_Assert(err->arena); + if (err->stack_size == 0) + return; + + DN_ErrSinkNode const *node = err->stack + (err->stack_size - 1); + DN_Assert(node->mode >= DN_ErrSinkMode_Nil && node->mode <= DN_ErrSinkMode_ExitOnError); + DN_Assert(node->msg_sentinel); + + // NOTE: Walk the list ensuring we eventually terminate at the sentinel (e.g. we have a + // well formed doubly-linked-list terminated by a sentinel, or otherwise we will hit the + // walk limit or dereference a null pointer and assert) + size_t WALK_LIMIT = 99'999; + size_t walk = 0; + for (DN_ErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next, walk++) { + DN_AssertF(it, "Encountered null pointer which should not happen in a sentinel DLL"); + DN_Assert(walk < WALK_LIMIT); + } +} + +DN_API DN_ErrSink* DN_ErrSinkBegin_(DN_ErrSink *err, DN_ErrSinkMode mode, DN_CallSite call_site) +{ + DN_USize arena_pos = DN_ArenaPos(err->arena); + if (err->stack_size == DN_ArrayCountU(err->stack)) { + DN_Str8Builder builder = DN_Str8BuilderFromArena(err->arena); + for (DN_ForItSize(it, DN_ErrSinkNode, err->stack, err->stack_size)) + DN_Str8BuilderAppendF(&builder, " [%04zu] %S:%u %.*s\n", it.index, it.data->call_site.file, it.data->call_site.line, DN_Str8PrintFmt(it.data->call_site.function)); + DN_Str8 msg = DN_Str8BuilderBuild(&builder, err->arena); + DN_AssertF(err->stack_size < DN_ArrayCountU(err->stack), "Error sink has run out of error scopes, potential leak. Scopes were\n%.*s", DN_Str8PrintFmt(msg)); + DN_ArenaPopTo(err->arena, arena_pos); + } + + DN_ErrSinkNode *node = err->stack + err->stack_size++; + node->arena_pos = arena_pos; + node->mode = mode; + node->call_site = call_site; + DN_SentinelDoublyLLInitArena(node->msg_sentinel, DN_ErrSinkMsg, err->arena); + + // NOTE: Handle allocation error + if (!DN_Check(node && node->msg_sentinel)) { + DN_ArenaPopTo(err->arena, arena_pos); + node->msg_sentinel = nullptr; + err->stack_size--; + } + DN_ErrSink *result = err; + return result; +} + +DN_API bool DN_ErrSinkHasError(DN_ErrSink *err) +{ + bool result = false; + if (err && err->stack_size) { + DN_ErrSinkNode *node = err->stack + (err->stack_size - 1); + result = DN_SentinelDoublyLLHasItems(node->msg_sentinel); + } + return result; +} + +DN_API DN_ErrSinkMsg *DN_ErrSinkEnd(DN_Arena *arena, DN_ErrSink *err) +{ + DN_ErrSinkMsg *result = nullptr; + DN_ErrSinkCheck_(err); + DN_AssertF(arena != err->arena, "You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost"); + + // NOTE: Walk the list and allocate it onto the user's arena + DN_ErrSinkNode *node = err->stack + (err->stack_size - 1); + DN_ErrSinkMsg *prev = nullptr; + for (DN_ErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next) { + DN_ErrSinkMsg *entry = DN_ArenaNew(arena, DN_ErrSinkMsg, DN_ZMem_Yes); + entry->msg = DN_Str8FromStr8Arena(arena, it->msg); + entry->call_site = it->call_site; + entry->error_code = it->error_code; + if (!result) + result = entry; // Assign first entry if we haven't yet + if (prev) + prev->next = entry; // Link the prev message to the current one + prev = entry; // Update prev to latest + } + + // NOTE: Deallocate all the memory for this scope + err->stack_size--; + DN_ArenaPopTo(err->arena, node->arena_pos); + return result; +} + +static void DN_ErrSinkAddMsgToStr8Builder_(DN_Str8Builder *builder, DN_ErrSinkMsg *msg, DN_ErrSinkMsg *end) +{ + if (msg == end) // NOTE: No error messages to add + return; + + if (msg->next == end) { + DN_ErrSinkMsg *it = msg; + DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file); + DN_Str8BuilderAppendF(builder, + "%.*s:%05I32u:%.*s %.*s", + DN_Str8PrintFmt(file_name), + it->call_site.line, + DN_Str8PrintFmt(it->call_site.function), + DN_Str8PrintFmt(it->msg)); + } else { + // NOTE: More than one message + for (DN_ErrSinkMsg *it = msg; it != end; it = it->next) { + DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file); + DN_Str8BuilderAppendF(builder, + "%s - %.*s:%05I32u:%.*s%s%.*s", + it == msg ? "" : "\n", + DN_Str8PrintFmt(file_name), + it->call_site.line, + DN_Str8PrintFmt(it->call_site.function), + it->msg.size ? " " : "", + DN_Str8PrintFmt(it->msg)); + } + } +} + +DN_API DN_Str8 DN_ErrSinkEndStr8(DN_Arena *arena, DN_ErrSink *err) +{ + DN_Str8 result = {}; + DN_ErrSinkCheck_(err); + if (err->stack_size == 0) + return result; + + DN_AssertF(arena != err->arena, "You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost"); + + // NOTE: Walk the list and allocate it onto the user's arena + DN_Str8Builder builder = DN_Str8BuilderFromArena(err->arena); + DN_ErrSinkNode *node = err->stack + (err->stack_size - 1); + DN_ErrSinkAddMsgToStr8Builder_(&builder, node->msg_sentinel->next, node->msg_sentinel); + + // NOTE: Deallocate all the memory for this scope + err->stack_size--; + DN_U64 arena_pos = node->arena_pos; + DN_ArenaPopTo(err->arena, arena_pos); + + result = DN_Str8BuilderBuild(&builder, arena); + return result; +} + +DN_API void DN_ErrSinkEndIgnore(DN_ErrSink *err) +{ + DN_ErrSinkEnd(nullptr, err); +} + +DN_API bool DN_ErrSinkEndLogError_(DN_ErrSink *err, DN_CallSite call_site, DN_Str8 err_msg) +{ + DN_ErrSinkNode *node = err->stack + (err->stack_size - 1); + DN_AssertF(err->stack_size, "Begin must be called before calling end"); + DN_AssertF(node->msg_sentinel, "Begin must be called before calling end"); + bool result = false; + if (node->msg_sentinel != node->msg_sentinel->next) { + result = true; + // NOTE: Build the error string + DN_Str8Builder builder = DN_Str8BuilderFromArena(err->arena); + { + if (err_msg.size) { + DN_Str8BuilderAppendRef(&builder, err_msg); + DN_Str8BuilderAppendRef(&builder, DN_Str8Lit(":")); + } else { + DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("Error(s) encountered:")); + } + if (node->msg_sentinel->next->next != node->msg_sentinel) // NOTE: More than 1 message + DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n")); + DN_ErrSinkAddMsgToStr8Builder_(&builder, node->msg_sentinel->next, node->msg_sentinel); + } + + // NOTE: Log the error + DN_Str8 log = DN_Str8BuilderBuild(&builder, err->arena); + DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Error), call_site, "%.*s", DN_Str8PrintFmt(log)); + + if (node->mode == DN_ErrSinkMode_DebugBreakOnErrorLog) + DN_DebugBreak; + + // NOTE: Deallocate the error node's memory and pop it from the stack + DN_ArenaPopTo(err->arena, node->arena_pos); + err->stack_size--; + } + return result; +} + +DN_API bool DN_ErrSinkEndLogErrorFV_(DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_Str8 log = DN_Str8FromFmtVArena(err->arena, fmt, args); + bool result = DN_ErrSinkEndLogError_(err, call_site, log); + return result; +} + +DN_API bool DN_ErrSinkEndLogErrorF_(DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_Str8 log = DN_Str8FromFmtVArena(err->arena, fmt, args); + bool result = DN_ErrSinkEndLogError_(err, call_site, log); + va_end(args); + return result; +} + +DN_API void DN_ErrSinkEndExitIfErrorFV_(DN_ErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + if (DN_ErrSinkEndLogErrorFV_(err, call_site, fmt, args)) { + DN_DebugBreak; + DN_OS_Exit(exit_val); + } +} + +DN_API void DN_ErrSinkEndExitIfErrorF_(DN_ErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_ErrSinkEndExitIfErrorFV_(err, call_site, exit_val, fmt, args); + va_end(args); +} + +DN_API void DN_ErrSinkAppendFV_(DN_ErrSink *err, DN_U32 error_code, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_Assert(err && err->stack_size); + DN_ErrSinkNode *node = err->stack + (err->stack_size - 1); + DN_AssertF(node, "Error sink must be begun by calling 'Begin' before using this function."); + + DN_ErrSinkMsg *msg = DN_ArenaNew(err->arena, DN_ErrSinkMsg, DN_ZMem_Yes); + if (DN_Check(msg)) { + msg->msg = DN_Str8FromFmtVArena(err->arena, fmt, args); + msg->error_code = error_code; + msg->call_site = call_site; + DN_SentinelDoublyLLPrepend(node->msg_sentinel, msg); + if (node->mode == DN_ErrSinkMode_ExitOnError) + DN_ErrSinkEndExitIfErrorF_(err, msg->call_site, error_code, "Fatal error %u", error_code); + } +} + +DN_API void DN_ErrSinkAppendF_(DN_ErrSink *err, DN_U32 error_code, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_ErrSinkAppendFV_(err, error_code, call_site, fmt, args); + va_end(args); +} + +DN_THREAD_LOCAL DN_TCCore *g_dn_thread_context; + +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) +{ + tc->thread_id = thread_id; + tc->main_arena = main_arena; + tc->temp_a_arena = temp_a_arena; + tc->temp_b_arena = temp_b_arena; + tc->err_sink.arena = err_sink_arena; +} + +DN_API void DN_TCInitFromMemFuncs(DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_ArenaMemFuncs mem_funcs) +{ + DN_U64 main_reserve = (args && args->main_reserve) ? args->main_reserve : DN_Kilobytes(64); + DN_U64 main_commit = (args && args->main_commit) ? args->main_commit : DN_Kilobytes(4); + DN_U64 temp_reserve = (args && args->temp_reserve) ? args->temp_reserve : DN_Kilobytes(64); + DN_U64 temp_commit = (args && args->temp_commit) ? args->temp_commit : DN_Kilobytes(4); + DN_U64 err_sink_reserve = (args && args->err_sink_reserve) ? args->err_sink_reserve : DN_Kilobytes(64); + DN_U64 err_sink_commit = (args && args->err_sink_commit) ? args->err_sink_commit : DN_Kilobytes(4); + + tc->main_arena_ = DN_ArenaFromMemFuncs(main_reserve, main_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack, mem_funcs); + tc->temp_a_arena_ = DN_ArenaFromMemFuncs(temp_reserve, temp_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack, mem_funcs); + tc->temp_b_arena_ = DN_ArenaFromMemFuncs(temp_reserve, temp_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack, mem_funcs); + tc->err_sink_arena_ = DN_ArenaFromMemFuncs(err_sink_reserve, err_sink_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack, mem_funcs); + + DN_TCInit(tc, thread_id, &tc->main_arena_, &tc->temp_a_arena_, &tc->temp_b_arena_, &tc->err_sink_arena_); +} + +DN_API void DN_TCDeinit(DN_TCCore *tc) +{ + DN_ArenaDeinit(tc->main_arena); + DN_ArenaDeinit(tc->temp_a_arena); + DN_ArenaDeinit(tc->temp_b_arena); + DN_ArenaDeinit(tc->err_sink.arena); +} + +DN_API void DN_TCEquip(DN_TCCore *tc) +{ + g_dn_thread_context = tc; +} + +DN_API DN_TCCore *DN_TCGet() +{ + DN_RawAssert(g_dn_thread_context && + "This thread's thread context has not been equipped yet. Ensure that DN_TCInit(...) " + "has been called to create a thread context and call DN_TCEquip(...) in the current " + "thread to make it retrievable via this function"); + return g_dn_thread_context; +} + +DN_API DN_Arena *DN_TCMainArena() +{ + DN_TCCore *tc = DN_TCGet(); + DN_Arena *result = tc->main_arena; + return result; +} + +DN_API DN_Arena *DN_TCTempArena(DN_Arena **conflicts, DN_U64 count) +{ + DN_TCCore *tc = DN_TCGet(); + DN_Arena *candidates[] = {tc->temp_a_arena, tc->temp_b_arena}; + DN_Arena *result = nullptr; + for (DN_ForItCArray(it, DN_Arena *, candidates)) { + bool is_usable = false; + for (DN_ForItSize(conflict_it, DN_Arena *, conflicts, count)) { + if (*conflict_it.data == *it.data) + continue; + is_usable = true; + break; + } + + if (count == 0 || is_usable) { + result = *it.data; + break; + } + } + return result; +} + +#if defined(__cplusplus) +DN_TCScratchCpp::DN_TCScratchCpp(DN_Arena **conflicts, DN_USize count) +{ + this->data = DN_TCScratchBegin(conflicts, count); +} + +DN_TCScratchCpp::~DN_TCScratchCpp() +{ + DN_TCScratchEnd(&this->data); +} +#endif + +DN_API DN_TCScratch DN_TCScratchBegin(DN_Arena **conflicts, DN_U64 count) +{ + DN_TCScratch result = {}; + result.arena = DN_TCTempArena(conflicts, count); + result.temp_mem = DN_ArenaTempMemBegin(result.arena); + return result; +} + +DN_API void DN_TCScratchEnd(DN_TCScratch *scratch) +{ + DN_Assert(scratch->destructed == false); + DN_ArenaTempMemEnd(scratch->temp_mem); + scratch->destructed = true; + scratch->arena = nullptr; + scratch->temp_mem = {}; +} + +DN_API void DN_TCSetFrameArena(DN_Arena *arena) +{ + DN_TCCore *tc = DN_TCGet(); + tc->frame_arena = arena; +} + +DN_API DN_Arena *DN_TCFrameArena() +{ + DN_TCCore *tc = DN_TCGet(); + DN_Arena *result = tc->frame_arena; + return result; +} + +DN_API DN_ErrSink *DN_TCErrSink() +{ + DN_TCCore *tc = DN_TCGet(); + DN_ErrSink *result = &tc->err_sink; + return result; +} + DN_API void *DN_PoolCopy(DN_Pool *pool, void const *data, DN_U64 size, uint8_t align) { if (!pool || !data || size == 0) @@ -1771,6 +2161,71 @@ DN_API DN_Str8x256 DN_Str8x256FromFmtV(DN_FMT_ATTRIB char const *fmt, va_list ar return result; } +DN_API void DN_Str8x16AppendFmt(DN_Str8x16 *str, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_Str8x16AppendFmtV(str, fmt, args); + va_end(args); +} + +DN_API void DN_Str8x16AppendFmtV(DN_Str8x16 *str, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_FmtVAppend(str->data, &str->size, sizeof(str->data), fmt, args); +} + +DN_API void DN_Str8x32AppendFmt(DN_Str8x32 *str, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_Str8x32AppendFmtV(str, fmt, args); + va_end(args); +} + +DN_API void DN_Str8x32AppendFmtV(DN_Str8x32 *str, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_FmtVAppend(str->data, &str->size, sizeof(str->data), fmt, args); +} + +DN_API void DN_Str8x64AppendFmt(DN_Str8x64 *str, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_Str8x64AppendFmtV(str, fmt, args); + va_end(args); +} + +DN_API void DN_Str8x64AppendFmtV(DN_Str8x64 *str, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_FmtVAppend(str->data, &str->size, sizeof(str->data), fmt, args); +} + +DN_API void DN_Str8x128AppendFmt(DN_Str8x128 *str, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_Str8x128AppendFmtV(str, fmt, args); + va_end(args); +} + +DN_API void DN_Str8x128AppendFmtV(DN_Str8x128 *str, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_FmtVAppend(str->data, &str->size, sizeof(str->data), fmt, args); +} + +DN_API void DN_Str8x256AppendFmt(DN_Str8x256 *str, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_Str8x256AppendFmtV(str, fmt, args); + va_end(args); +} + +DN_API void DN_Str8x256AppendFmtV(DN_Str8x256 *str, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_FmtVAppend(str->data, &str->size, sizeof(str->data), fmt, args); +} + DN_API DN_Str8x32 DN_Str8x32FromU64(DN_U64 val, char separator) { DN_Str8x32 result = {}; @@ -1823,7 +2278,7 @@ DN_API char *DN_Str8End(DN_Str8 string) return result; } -DN_API DN_Str8 DN_Str8Slice(DN_Str8 string, DN_USize offset, DN_USize size) +DN_API DN_Str8 DN_Str8Subset(DN_Str8 string, DN_USize offset, DN_USize size) { DN_Str8 result = DN_Str8FromPtr(string.data, 0); if (string.size == 0) @@ -1838,7 +2293,7 @@ DN_API DN_Str8 DN_Str8Slice(DN_Str8 string, DN_USize offset, DN_USize size) DN_API DN_Str8 DN_Str8Advance(DN_Str8 string, DN_USize amount) { - DN_Str8 result = DN_Str8Slice(string, amount, DN_USIZE_MAX); + DN_Str8 result = DN_Str8Subset(string, amount, DN_USIZE_MAX); return result; } @@ -1858,7 +2313,7 @@ DN_API DN_Str8BSplitResult DN_Str8BSplitArray(DN_Str8 string, DN_Str8 const *fin for (size_t index = 0; !result.rhs.data && index < string.size; index++) { for (DN_USize find_index = 0; find_index < find_size; find_index++) { DN_Str8 find_item = find[find_index]; - DN_Str8 string_slice = DN_Str8Slice(string, index, find_item.size); + DN_Str8 string_slice = DN_Str8Subset(string, index, find_item.size); if (DN_Str8Eq(string_slice, find_item)) { result.lhs.size = index; result.rhs.data = string_slice.data + find_item.size; @@ -1887,7 +2342,7 @@ DN_API DN_Str8BSplitResult DN_Str8BSplitLastArray(DN_Str8 string, DN_Str8 const for (size_t index = string.size - 1; !result.rhs.data && index < string.size; index--) { for (DN_USize find_index = 0; find_index < find_size; find_index++) { DN_Str8 find_item = find[find_index]; - DN_Str8 string_slice = DN_Str8Slice(string, index, find_item.size); + DN_Str8 string_slice = DN_Str8Subset(string, index, find_item.size); if (DN_Str8Eq(string_slice, find_item)) { result.lhs.size = index; result.rhs.data = string_slice.data + find_item.size; @@ -1945,7 +2400,7 @@ DN_API DN_Str8FindResult DN_Str8FindStr8Array(DN_Str8 string, DN_Str8 const *fin for (DN_USize index = 0; !result.found && index < string.size; index++) { for (DN_USize find_index = 0; find_index < find_size; find_index++) { DN_Str8 find_item = find[find_index]; - DN_Str8 string_slice = DN_Str8Slice(string, index, find_item.size); + DN_Str8 string_slice = DN_Str8Subset(string, index, find_item.size); if (DN_Str8Eq(string_slice, find_item, eq_case)) { result.found = true; result.index = index; @@ -2287,8 +2742,8 @@ DN_API DN_Str8TruncateResult DN_Str8TruncateMiddle(DN_Arena *arena, DN_Str8 str8 return result; } - DN_Str8 head = DN_Str8Slice(str8, 0, side_size); - DN_Str8 tail = DN_Str8Slice(str8, str8.size - side_size, side_size); + DN_Str8 head = DN_Str8Subset(str8, 0, side_size); + DN_Str8 tail = DN_Str8Subset(str8, str8.size - side_size, side_size); DN_MSVC_WARNING_PUSH DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(3) when a string is required in call to 'DN_Str8FromFmtArena' Actual type: 'struct DN_Str8' result.str8 = DN_Str8FromFmtArena(arena, "%S%S%S", head, truncator, tail); @@ -2313,6 +2768,70 @@ DN_API DN_Str8 DN_Str8Upper(DN_Arena *arena, DN_Str8 string) return result; } +DN_API DN_Str8 DN_Str8Replace(DN_Str8 string, + DN_Str8 find, + DN_Str8 replace, + DN_USize start_index, + DN_Arena *arena, + DN_Str8EqCase eq_case) +{ + // TODO: Implement this without requiring TLS so it can go into base strings + DN_Str8 result = {}; + if (string.size == 0 || find.size == 0 || find.size > string.size || find.size == 0 || string.size == 0) { + result = DN_Str8FromStr8Arena(arena, string); + return result; + } + + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); + DN_Str8Builder string_builder = DN_Str8BuilderFromArena(scratch.arena); + DN_USize max = string.size - find.size; + DN_USize head = start_index; + + for (DN_USize tail = head; tail <= max; tail++) { + DN_Str8 check = DN_Str8Subset(string, tail, find.size); + if (!DN_Str8Eq(check, find, eq_case)) + continue; + + if (start_index > 0 && string_builder.string_size == 0) { + // User provided a hint in the string to start searching from, we + // need to add the string up to the hint. We only do this if there's + // a replacement action, otherwise we have a special case for no + // replacements, where the entire string gets copied. + DN_Str8 slice = DN_Str8FromPtr(string.data, head); + DN_Str8BuilderAppendRef(&string_builder, slice); + } + + DN_Str8 range = DN_Str8Subset(string, head, (tail - head)); + DN_Str8BuilderAppendRef(&string_builder, range); + DN_Str8BuilderAppendRef(&string_builder, replace); + head = tail + find.size; + tail += find.size - 1; // NOTE: -1 since the for loop will post increment us past the end of the find string + } + + if (string_builder.string_size == 0) { + // NOTE: No replacement possible, so we just do a full-copy + result = DN_Str8FromStr8Arena(arena, string); + } else { + DN_Str8 remainder = DN_Str8FromPtr(string.data + head, string.size - head); + DN_Str8BuilderAppendRef(&string_builder, remainder); + result = DN_Str8BuilderBuild(&string_builder, arena); + } + DN_TCScratchEnd(&scratch); + return result; +} + +DN_API DN_Str8 DN_Str8ReplaceSensitive(DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena) +{ + DN_Str8 result = DN_Str8Replace(string, find, replace, start_index, arena, DN_Str8EqCase_Sensitive); + return result; +} + +DN_API DN_Str8 DN_Str8ReplaceInsensitive(DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena) +{ + DN_Str8 result = DN_Str8Replace(string, find, replace, start_index, arena, DN_Str8EqCase_Insensitive); + return result; +} + DN_API DN_Str8Builder DN_Str8BuilderFromArena(DN_Arena *arena) { DN_Str8Builder result = {}; @@ -2591,14 +3110,13 @@ DN_API DN_Str8 DN_Str8BuilderBuildDelimited(DN_Str8Builder const *builder, DN_St return result; } -DN_API DN_Slice DN_Str8BuilderBuildSlice(DN_Str8Builder const *builder, DN_Arena *arena) +DN_API DN_Str8Slice DN_Str8BuilderBuildSlice(DN_Str8Builder const *builder, DN_Arena *arena) { - DN_Slice result = DN_ZeroInit; + DN_Str8Slice result = {}; if (!builder || builder->string_size <= 0 || builder->count <= 0) return result; - result = DN_Slice_Alloc(arena, builder->count, DN_ZMem_No); - if (!result.data) + if (!DN_ISliceAllocArena(DN_Str8, &result, builder->count, DN_ZMem_No, arena)) return result; DN_USize slice_index = 0; @@ -2609,9 +3127,8 @@ DN_API DN_Slice DN_Str8BuilderBuildSlice(DN_Str8Builder const *builder, return result; } -// NOTE: DN_Char /////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_UTF //////////////////////////////////////////////////////////////////////////////////// -DN_API int DN_UTF8_EncodeCodepoint(uint8_t utf8[4], uint32_t codepoint) +// NOTE: DN_UTF +DN_API int DN_UTF8EncodeCodepoint(uint8_t utf8[4], uint32_t codepoint) { // NOTE: Table from https://www.reedbeta.com/blog/programmers-intro-to-unicode/ // ----------------------------------------+----------------------------+--------------------+ @@ -2652,7 +3169,7 @@ DN_API int DN_UTF8_EncodeCodepoint(uint8_t utf8[4], uint32_t codepoint) return 0; } -DN_API int DN_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint) +DN_API int DN_UTF16EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint) { // NOTE: Table from https://www.reedbeta.com/blog/programmers-intro-to-unicode/ // ----------------------------------------+------------------------------------+------------------+ @@ -3224,3 +3741,448 @@ DN_API DN_F64 DN_ProfilerMsFromTSC(DN_Profiler *profiler, DN_U64 duration_tsc) DN_F64 result = DN_Cast(DN_F64)duration_tsc / profiler->tsc_frequency * 1000.0; return result; } + +#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL +#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL +DN_API DN_PCG32 DN_PCG32Init(DN_U64 seed) +{ + DN_PCG32 result = {}; + DN_PCG32Next(&result); + result.state += seed; + DN_PCG32Next(&result); + return result; +} + +DN_API DN_U32 DN_PCG32Next(DN_PCG32 *rng) +{ + DN_U64 state = rng->state; + rng->state = state * DN_PCG_DEFAULT_MULTIPLIER_64 + DN_PCG_DEFAULT_INCREMENT_64; + + // XSH-RR + DN_U32 value = (DN_U32)((state ^ (state >> 18)) >> 27); + int rot = state >> 59; + return rot ? (value >> rot) | (value << (32 - rot)) : value; +} + +DN_API DN_U64 DN_PCG32Next64(DN_PCG32 *rng) +{ + DN_U64 value = DN_PCG32Next(rng); + value <<= 32; + value |= DN_PCG32Next(rng); + return value; +} + +DN_API DN_U32 DN_PCG32Range(DN_PCG32 *rng, DN_U32 low, DN_U32 high) +{ + DN_U32 bound = high - low; + DN_U32 threshold = -(int32_t)bound % bound; + + for (;;) { + DN_U32 r = DN_PCG32Next(rng); + if (r >= threshold) + return low + (r % bound); + } +} + +DN_API DN_F32 DN_PCG32NextF32(DN_PCG32 *rng) +{ + DN_U32 x = DN_PCG32Next(rng); + return (DN_F32)(int32_t)(x >> 8) * 0x1.0p-24f; +} + +DN_API DN_F64 DN_PCG32NextF64(DN_PCG32 *rng) +{ + DN_U64 x = DN_PCG32Next64(rng); + return (DN_F64)(int64_t)(x >> 11) * 0x1.0p-53; +} + +DN_API void DN_PCG32Advance(DN_PCG32 *rng, DN_U64 delta) +{ + DN_U64 cur_mult = DN_PCG_DEFAULT_MULTIPLIER_64; + DN_U64 cur_plus = DN_PCG_DEFAULT_INCREMENT_64; + + DN_U64 acc_mult = 1; + DN_U64 acc_plus = 0; + + while (delta != 0) { + if (delta & 1) { + acc_mult *= cur_mult; + acc_plus = acc_plus * cur_mult + cur_plus; + } + cur_plus = (cur_mult + 1) * cur_plus; + cur_mult *= cur_mult; + delta >>= 1; + } + + rng->state = acc_mult * rng->state + acc_plus; +} + +// Default values recommended by: http://isthe.com/chongo/tech/comp/fnv/ +DN_API DN_U32 DN_FNV1AHashU32FromBytes(void const *bytes, DN_USize size, DN_U32 hash) +{ + auto buffer = DN_Cast(DN_U8 const *)bytes; + for (DN_USize i = 0; i < size; i++) + hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/; + return hash; +} + +DN_API DN_U64 DN_FNV1AHashU64FromBytes(void const *bytes, DN_USize size, DN_U64 hash) +{ + auto buffer = DN_Cast(DN_U8 const *)bytes; + for (DN_USize i = 0; i < size; i++) + hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/; + return hash; +} + +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) + #define DN_MMH3_ROTL32(x, y) _rotl(x, y) + #define DN_MMH3_ROTL64(x, y) _rotl64(x, y) +#else + #define DN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y))) + #define DN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y))) +#endif + +//----------------------------------------------------------------------------- +// Block read - if your platform needs to do endian-swapping or can only +// handle aligned reads, do the conversion here +DN_FORCE_INLINE DN_U32 DN_MurmurHash3GetBlock32_(DN_U32 const *p, int i) +{ + return p[i]; +} + +DN_FORCE_INLINE DN_U64 DN_MurmurHash3GetBlock64_(DN_U64 const *p, int i) +{ + return p[i]; +} + +//----------------------------------------------------------------------------- +// Finalization mix - force all bits of a hash block to avalanche + +DN_FORCE_INLINE DN_U32 DN_MurmurHash3FMix32_(DN_U32 h) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; +} + +DN_FORCE_INLINE DN_U64 DN_MurmurHash3FMix64_(DN_U64 k) +{ + k ^= k >> 33; + k *= 0xff51afd7ed558ccd; + k ^= k >> 33; + k *= 0xc4ceb9fe1a85ec53; + k ^= k >> 33; + return k; +} + +DN_API DN_U32 DN_MurmurHash3HashU128FromBytesX86(void const *bytes, int len, DN_U32 seed) +{ + const DN_U8 *data = (const DN_U8 *)bytes; + const int nblocks = len / 4; + + DN_U32 h1 = seed; + + const DN_U32 c1 = 0xcc9e2d51; + const DN_U32 c2 = 0x1b873593; + + //---------- + // body + + const DN_U32 *blocks = (const DN_U32 *)(data + nblocks * 4); + + for (int i = -nblocks; i; i++) + { + DN_U32 k1 = DN_MurmurHash3GetBlock32_(blocks, i); + + k1 *= c1; + k1 = DN_MMH3_ROTL32(k1, 15); + k1 *= c2; + + h1 ^= k1; + h1 = DN_MMH3_ROTL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; + } + + //---------- + // tail + + const DN_U8 *tail = (const DN_U8 *)(data + nblocks * 4); + + DN_U32 k1 = 0; + + switch (len & 3) + { + case 3: + k1 ^= tail[2] << 16; + case 2: + k1 ^= tail[1] << 8; + case 1: + k1 ^= tail[0]; + k1 *= c1; + k1 = DN_MMH3_ROTL32(k1, 15); + k1 *= c2; + h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; + + h1 = DN_MurmurHash3FMix32_(h1); + + return h1; +} + +DN_API DN_MurmurHash3 DN_MurmurHash3HashU128FromBytesX64(void const *bytes, int len, DN_U32 seed) +{ + const DN_U8 *data = (const DN_U8 *)bytes; + const int nblocks = len / 16; + + DN_U64 h1 = seed; + DN_U64 h2 = seed; + + const DN_U64 c1 = 0x87c37b91114253d5; + const DN_U64 c2 = 0x4cf5ad432745937f; + + //---------- + // body + + const DN_U64 *blocks = (const DN_U64 *)(data); + + for (int i = 0; i < nblocks; i++) + { + DN_U64 k1 = DN_MurmurHash3GetBlock64_(blocks, i * 2 + 0); + DN_U64 k2 = DN_MurmurHash3GetBlock64_(blocks, i * 2 + 1); + + k1 *= c1; + k1 = DN_MMH3_ROTL64(k1, 31); + k1 *= c2; + h1 ^= k1; + + h1 = DN_MMH3_ROTL64(h1, 27); + h1 += h2; + h1 = h1 * 5 + 0x52dce729; + + k2 *= c2; + k2 = DN_MMH3_ROTL64(k2, 33); + k2 *= c1; + h2 ^= k2; + + h2 = DN_MMH3_ROTL64(h2, 31); + h2 += h1; + h2 = h2 * 5 + 0x38495ab5; + } + + //---------- + // tail + + const DN_U8 *tail = (const DN_U8 *)(data + nblocks * 16); + + DN_U64 k1 = 0; + DN_U64 k2 = 0; + + switch (len & 15) + { + case 15: + k2 ^= ((DN_U64)tail[14]) << 48; + case 14: + k2 ^= ((DN_U64)tail[13]) << 40; + case 13: + k2 ^= ((DN_U64)tail[12]) << 32; + case 12: + k2 ^= ((DN_U64)tail[11]) << 24; + case 11: + k2 ^= ((DN_U64)tail[10]) << 16; + case 10: + k2 ^= ((DN_U64)tail[9]) << 8; + case 9: + k2 ^= ((DN_U64)tail[8]) << 0; + k2 *= c2; + k2 = DN_MMH3_ROTL64(k2, 33); + k2 *= c1; + h2 ^= k2; + + case 8: + k1 ^= ((DN_U64)tail[7]) << 56; + case 7: + k1 ^= ((DN_U64)tail[6]) << 48; + case 6: + k1 ^= ((DN_U64)tail[5]) << 40; + case 5: + k1 ^= ((DN_U64)tail[4]) << 32; + case 4: + k1 ^= ((DN_U64)tail[3]) << 24; + case 3: + k1 ^= ((DN_U64)tail[2]) << 16; + case 2: + k1 ^= ((DN_U64)tail[1]) << 8; + case 1: + k1 ^= ((DN_U64)tail[0]) << 0; + k1 *= c1; + k1 = DN_MMH3_ROTL64(k1, 31); + k1 *= c2; + h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; + h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = DN_MurmurHash3FMix64_(h1); + h2 = DN_MurmurHash3FMix64_(h2); + + h1 += h2; + h2 += h1; + + DN_MurmurHash3 result = {}; + result.e[0] = h1; + result.e[1] = h2; + return result; +} + +DN_API DN_U64 DN_MurmurHash3HashU64FromBytesX64(void const *bytes, int len, DN_U32 seed) +{ + DN_MurmurHash3 hash = DN_MurmurHash3HashU128FromBytesX64(bytes, len, seed); + DN_U64 result = hash.e[0]; + return result; +} + +DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX64(void const *bytes, int len, DN_U32 seed) +{ + DN_MurmurHash3 hash = DN_MurmurHash3HashU128FromBytesX64(bytes, len, seed); + DN_U32 result = DN_Cast(DN_U32)hash.e[0]; + return result; +} + +static DN_LogEmitFromTypeFVFunc *g_dn_base_log_emit_from_type_fv_func_; +static void *g_dn_base_log_emit_from_type_fv_user_context_; +DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b) +{ + DN_THREAD_LOCAL char buffer[32]; + buffer[0] = 0; + DN_Str8 result = {}; + result.size = DN_SNPrintF(buffer, + DN_ArrayCountU(buffer), + "\x1b[%d;2;%u;%u;%um", + colour == DN_LogColourType_Fg ? 38 : 48, + r, + g, + b); + result.data = buffer; + return result; +} + +DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromU32(DN_LogColourType colour, DN_U32 value) +{ + DN_U8 r = DN_Cast(DN_U8)(value >> 24); + DN_U8 g = DN_Cast(DN_U8)(value >> 16); + DN_U8 b = DN_Cast(DN_U8)(value >> 8); + DN_Str8 result = DN_LogColourEscapeCodeStr8FromRGB(colour, r, g, b); + return result; +} + +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_Str8 type_str8 = type.str8; + if (type.is_u32_enum) { + switch (type.u32) { + case DN_LogType_Debug: type_str8 = DN_Str8Lit("DEBUG"); break; + case DN_LogType_Info: type_str8 = DN_Str8Lit("INFO "); break; + case DN_LogType_Warning: type_str8 = DN_Str8Lit("WARN"); break; + case DN_LogType_Error: type_str8 = DN_Str8Lit("ERROR"); break; + case DN_LogType_Count: type_str8 = DN_Str8Lit("BADXX"); break; + } + } + + static DN_USize max_type_length = 0; + max_type_length = DN_Max(max_type_length, type_str8.size); + int type_padding = DN_Cast(int)(max_type_length - type_str8.size); + + DN_Str8 colour_esc = {}; + DN_Str8 bold_esc = {}; + DN_Str8 reset_esc = {}; + if (style.colour) { + bold_esc = DN_Str8Lit(DN_LogBoldEscapeCode); + reset_esc = DN_Str8Lit(DN_LogResetEscapeCode); + colour_esc = DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType_Fg, style.r, style.g, style.b); + } + + DN_Str8 file_name = DN_Str8FileNameFromPath(call_site.file); + DN_GCC_WARNING_PUSH + DN_GCC_WARNING_DISABLE(-Wformat) + DN_GCC_WARNING_DISABLE(-Wformat-extra-args) + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(4477) + int size = DN_SNPrintF(dest, + DN_Cast(int)dest_size, + "%04u-%02u-%02uT%02u:%02u:%02u" // date + "%S" // colour + "%S" // bold + " %S" // type + "%.*s" // type padding + "%S" // reset + " %S" // file name + ":%05I32u " // line number + , + date.year, + date.month, + date.day, + date.hour, + date.minute, + date.second, + colour_esc, // colour + bold_esc, // bold + type_str8, // type + DN_Cast(int) type_padding, + "", // type padding + reset_esc, // reset + file_name, // file name + call_site.line); // line number + DN_MSVC_WARNING_POP // '%S' requires an argument of type 'wchar_t *', but variadic argument 7 has type 'DN_Str8' + DN_GCC_WARNING_POP + + static DN_USize max_header_length = 0; + DN_USize size_no_ansi_codes = size - colour_esc.size - reset_esc.size - bold_esc.size; + max_header_length = DN_Max(max_header_length, size_no_ansi_codes); + DN_USize header_padding = max_header_length - size_no_ansi_codes; + + DN_LogPrefixSize result = {}; + result.size = size; + result.padding = header_padding; + return result; +} + +DN_API void DN_LogSetEmitFromTypeFVFunc(DN_LogEmitFromTypeFVFunc *print_func, void *user_data) +{ + g_dn_base_log_emit_from_type_fv_func_ = print_func; + g_dn_base_log_emit_from_type_fv_user_context_ = user_data; +} + +DN_API void DN_LogEmitFromType(DN_LogTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) +{ + DN_LogEmitFromTypeFVFunc *func = g_dn_base_log_emit_from_type_fv_func_; + void *user_context = g_dn_base_log_emit_from_type_fv_user_context_; + if (func) { + va_list args; + va_start(args, fmt); + func(type, user_context, call_site, fmt, args); + va_end(args); + } +} + +DN_API DN_LogTypeParam DN_LogMakeU32LogTypeParam(DN_LogType type) +{ + DN_LogTypeParam result = {}; + result.is_u32_enum = true; + result.u32 = type; + return result; +} diff --git a/Source/Base/dn_base.h b/Source/Base/dn_base.h index 259c749..bbfa83c 100644 --- a/Source/Base/dn_base.h +++ b/Source/Base/dn_base.h @@ -5,11 +5,174 @@ #include "../dn.h" #endif +// NOTE: Compiler identification +// Warning! Order is important here, clang-cl on Windows defines _MSC_VER +#if defined(_MSC_VER) + #if defined(__clang__) + #define DN_COMPILER_CLANG_CL + #define DN_COMPILER_CLANG + #else + #define DN_COMPILER_MSVC + #endif +#elif defined(__clang__) + #define DN_COMPILER_CLANG +#elif defined(__GNUC__) + #define DN_COMPILER_GCC +#endif + +// NOTE: __has_feature +// MSVC for example does not support the feature detection macro for instance so we compile it out +#if defined(__has_feature) + #define DN_HAS_FEATURE(expr) __has_feature(expr) +#else + #define DN_HAS_FEATURE(expr) 0 +#endif + +// NOTE: __has_builtin +// MSVC for example does not support the feature detection macro for instance so we compile it out +#if defined(__has_builtin) + #define DN_HAS_BUILTIN(expr) __has_builtin(expr) +#else + #define DN_HAS_BUILTIN(expr) 0 +#endif + +// NOTE: Warning suppression macros +#if defined(DN_COMPILER_MSVC) + #define DN_MSVC_WARNING_PUSH __pragma(warning(push)) + #define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__)) + #define DN_MSVC_WARNING_POP __pragma(warning(pop)) +#else + #define DN_MSVC_WARNING_PUSH + #define DN_MSVC_WARNING_DISABLE(...) + #define DN_MSVC_WARNING_POP +#endif + +#if defined(DN_COMPILER_CLANG) || defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG_CL) + #define DN_GCC_WARNING_PUSH _Pragma("GCC diagnostic push") + #define DN_GCC_WARNING_DISABLE_HELPER_0(x) #x + #define DN_GCC_WARNING_DISABLE_HELPER_1(y) DN_GCC_WARNING_DISABLE_HELPER_0(GCC diagnostic ignored #y) + #define DN_GCC_WARNING_DISABLE(warning) _Pragma(DN_GCC_WARNING_DISABLE_HELPER_1(warning)) + #define DN_GCC_WARNING_POP _Pragma("GCC diagnostic pop") +#else + #define DN_GCC_WARNING_PUSH + #define DN_GCC_WARNING_DISABLE(...) + #define DN_GCC_WARNING_POP +#endif + +// NOTE: Host OS identification +#if defined(_WIN32) + #define DN_OS_WIN32 +#elif defined(__gnu_linux__) || defined(__linux__) + #define DN_OS_UNIX +#endif + +// NOTE: Platform identification +#if !defined(DN_PLATFORM_EMSCRIPTEN) && \ + !defined(DN_PLATFORM_POSIX) && \ + !defined(DN_PLATFORM_WIN32) + #if defined(__aarch64__) || defined(_M_ARM64) + #define DN_PLATFORM_ARM64 + #elif defined(__EMSCRIPTEN__) + #define DN_PLATFORM_EMSCRIPTEN + #elif defined(DN_OS_WIN32) + #define DN_PLATFORM_WIN32 + #else + #define DN_PLATFORM_POSIX + #endif +#endif + +// NOTE: Windows crap +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) + #if defined(_CRT_SECURE_NO_WARNINGS) + #define DN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED + #else + #define _CRT_SECURE_NO_WARNINGS + #endif +#endif + +// NOTE: Force Inline +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) + #define DN_FORCE_INLINE __forceinline +#else + #define DN_FORCE_INLINE inline __attribute__((always_inline)) +#endif + +// NOTE: Function/Variable Annotations +#if defined(DN_STATIC_API) + #define DN_API static +#else + #define DN_API +#endif + +// NOTE: C/CPP Literals +// Declare struct literals that work in both C and C++ because the syntax is different between +// languages. +#if 0 + struct Foo { int a; } + struct Foo foo = DN_LITERAL(Foo){32}; // Works on both C and C++ +#endif + +#if defined(__cplusplus) + #define DN_Literal(T) T +#else + #define DN_Literal(T) (T) +#endif + +// NOTE: Thread Locals +#if defined(__cplusplus) + #define DN_THREAD_LOCAL thread_local +#else + #define DN_THREAD_LOCAL _Thread_local +#endif + +// NOTE: C variadic argument annotations +// TODO: Other compilers +#if defined(DN_COMPILER_MSVC) + #define DN_FMT_ATTRIB _Printf_format_string_ +#else + #define DN_FMT_ATTRIB +#endif + +// NOTE: Type Cast +#define DN_Cast(val) (val) + +// NOTE: Zero initialisation macro +#if defined(__cplusplus) + #define DN_ZeroInit {} +#else + #define DN_ZeroInit {0} +#endif + +// NOTE: Address sanitizer +#if !defined(DN_ASAN_POISON) + #define DN_ASAN_POISON 0 +#endif + +#if !defined(DN_ASAN_VET_POISON) + #define DN_ASAN_VET_POISON 0 +#endif + +#define DN_ASAN_POISON_ALIGNMENT 8 + +#if !defined(DN_ASAN_POISON_GUARD_SIZE) + #define DN_ASAN_POISON_GUARD_SIZE 128 +#endif + +#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) + #include +#endif + // NOTE: Macros #define DN_Stringify(x) #x #define DN_TokenCombine2(x, y) x ## y #define DN_TokenCombine(x, y) DN_TokenCombine2(x, y) +#if defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) + #define DN_64_BIT +#else + #define DN_32_BIT +#endif + #include // va_list #include #include @@ -70,8 +233,8 @@ // NOTE: Math #define DN_PiF32 3.14159265359f -#define DN_DegreesToRadians(degrees) ((degrees) * (DN_PI / 180.0f)) -#define DN_RadiansToDegrees(radians) ((radians) * (180.f * DN_PI)) +#define DN_DegreesToRadsF32(degrees) ((degrees) * (DN_PiF32 / 180.0f)) +#define DN_RadsToDegreesF32(radians) ((radians) * (180.f * DN_PiF32)) #define DN_Abs(val) (((val) < 0) ? (-(val)) : (val)) #define DN_Max(a, b) (((a) > (b)) ? (a) : (b)) @@ -138,6 +301,23 @@ ((((u64) >> 8) & 0xFF) << 48) | \ ((((u64) >> 0) & 0xFF) << 56)) +// NOTE: Helper macros to declare an array data structure for a given `Type` +#define DN_DArrayStructDecl(Type) \ + struct Type##Array \ + { \ + Type* data; \ + DN_USize count; \ + DN_USize max; \ + } + +#define DN_FixedArrayStructDecl(Type, capacity) \ + struct Type##x##capacity##Array \ + { \ + Type data[capacity]; \ + DN_USize count; \ + DN_USize max; \ + } + // NOTE: Types typedef intptr_t DN_ISize; typedef uintptr_t DN_USize; @@ -178,6 +358,12 @@ struct DN_Str8 DN_USize size; // The number of bytes in the string }; +struct DN_Str8Slice +{ + DN_Str8 *data; + DN_USize count; +}; + struct DN_Str8x16 { char data[16]; DN_USize size; }; struct DN_Str8x32 { char data[32]; DN_USize size; }; struct DN_Str8x64 { char data[64]; DN_USize size; }; @@ -314,7 +500,7 @@ struct DN_DeferHelper #error "Compiler not supported" #endif -#if defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) +#if defined(DN_64_BIT) #define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU64(value) #else #define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU32(value) @@ -516,6 +702,7 @@ enum DN_ArenaFlags_ 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, @@ -823,6 +1010,172 @@ struct DN_Profiler DN_F64 frame_avg_tsc; }; +enum DN_ErrSinkMode +{ + DN_ErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink + DN_ErrSinkMode_DebugBreakOnErrorLog, // Debug break (int3) when error is encountered and the sink is ended by the 'end and log' functions. + DN_ErrSinkMode_ExitOnError, // When an error is encountered, exit the program with the error code of the error that was caught. +}; + +struct DN_ErrSinkMsg +{ + DN_I32 error_code; + DN_Str8 msg; + DN_CallSite call_site; + DN_ErrSinkMsg *next; + DN_ErrSinkMsg *prev; +}; + +struct DN_ErrSinkNode +{ + DN_CallSite call_site; // Call site that the node was created + DN_ErrSinkMode mode; // Controls how the sink behaves when an error is registered onto the sink. + DN_ErrSinkMsg *msg_sentinel; // List of error messages accumulated for the current scope + DN_U64 arena_pos; // Position to reset the arena when the scope is ended +}; + +struct DN_ErrSink +{ + DN_Arena* arena; // Dedicated allocator from the thread's local storage + DN_ErrSinkNode stack[128]; // Each entry contains errors accumulated between a [begin, end] region of the active sink. + DN_USize stack_size; +}; + +struct DN_TCScratch +{ + DN_Arena* arena; + DN_ArenaTempMem temp_mem; + DN_B32 destructed; +}; + +#if defined(__cplusplus) +struct DN_TCScratchCpp +{ + DN_TCScratchCpp(DN_Arena **conflicts, DN_USize count); + ~DN_TCScratchCpp(); + DN_TCScratch data; +}; +#endif + +struct DN_TCInitArgs +{ + DN_U64 main_reserve; + DN_U64 main_commit; + DN_U64 temp_reserve; + DN_U64 temp_commit; + DN_U64 err_sink_reserve; + DN_U64 err_sink_commit; +}; + +struct DN_TCCore // (T)hread (C)ontext sitting in thread-local storage +{ + DN_Str8x64 name; + DN_U64 thread_id; + DN_CallSite call_site; + + DN_Arena main_arena_; + DN_Arena temp_a_arena_; + DN_Arena temp_b_arena_; + DN_Arena err_sink_arena_; + + DN_Arena* main_arena; + DN_Arena* temp_a_arena; + DN_Arena* temp_b_arena; + DN_ErrSink err_sink; + + DN_Arena* frame_arena; +}; + +struct DN_PCG32 { DN_U64 state; }; +struct DN_MurmurHash3 { DN_U64 e[2]; }; + +enum DN_LogType +{ + DN_LogType_Debug, + DN_LogType_Info, + DN_LogType_Warning, + DN_LogType_Error, + DN_LogType_Count, +}; + +enum DN_LogBold +{ + DN_LogBold_No, + DN_LogBold_Yes, +}; + +struct DN_LogStyle +{ + DN_LogBold bold; + bool colour; + DN_U8 r, g, b; +}; + +struct DN_LogTypeParam +{ + bool is_u32_enum; + DN_U32 u32; + DN_Str8 str8; +}; + +enum DN_LogColourType +{ + DN_LogColourType_Fg, + DN_LogColourType_Bg, +}; + +struct DN_LogDate +{ + DN_U16 year; + DN_U8 month; + DN_U8 day; + + DN_U8 hour; + DN_U8 minute; + DN_U8 second; +}; + +struct DN_LogPrefixSize +{ + DN_USize size; + DN_USize padding; +}; + +struct DN_StackTraceFrame +{ + DN_U64 address; + DN_U64 line_number; + DN_Str8 file_name; + DN_Str8 function_name; +}; + +struct DN_StackTraceFrameSlice +{ + DN_StackTraceFrame *data; + DN_USize count; +}; + +struct DN_StackTraceRawFrame +{ + void *process; + DN_U64 base_addr; +}; + +struct DN_StackTraceWalkResult +{ + void *process; // [Internal] Windows handle to the process + DN_U64 *base_addr; // The addresses of the functions in the stack trace + DN_U16 size; // The number of `base_addr`'s stored from the walk +}; + +struct DN_StackTraceWalkResultIterator +{ + DN_StackTraceRawFrame raw_frame; + DN_U16 index; +}; + +typedef void DN_LogEmitFromTypeFVFunc(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); + #if !defined(DN_STB_SPRINTF_HEADER_ONLY) #define STB_SPRINTF_IMPLEMENTATION #define STB_SPRINTF_STATIC @@ -836,326 +1189,448 @@ DN_GCC_WARNING_DISABLE(-Wunused-function) DN_GCC_WARNING_POP DN_MSVC_WARNING_POP -DN_API void DN_BeginFrame (); +DN_API void DN_BeginFrame (); -#define DN_SPrintF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__) -#define DN_SNPrintF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__) -#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__) -#define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__) +#define DN_SPrintF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__) +#define DN_SNPrintF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__) +#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__) +#define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__) -DN_API bool DN_MemEq (void const *lhs, DN_USize lhs_size, void const *rhs, DN_USize rhs_size); +DN_API bool DN_MemEq (void const *lhs, DN_USize lhs_size, void const *rhs, DN_USize rhs_size); -DN_API DN_U64 DN_AtomicSetValue64 (DN_U64 volatile *target, DN_U64 value); -DN_API DN_U32 DN_AtomicSetValue32 (DN_U32 volatile *target, DN_U32 value); +DN_API DN_U64 DN_AtomicSetValue64 (DN_U64 volatile *target, DN_U64 value); +DN_API DN_U32 DN_AtomicSetValue32 (DN_U32 volatile *target, DN_U32 value); +DN_API DN_USize DN_AlignUpPowerOfTwoUSize (DN_USize val); +DN_API DN_U64 DN_AlignUpPowerOfTwoU64 (DN_U64 val); +DN_API DN_U32 DN_AlignUpPowerOfTwoU32 (DN_U32 val); -DN_API DN_CPUIDResult DN_CPUID (DN_CPUIDArgs args); -DN_API DN_USize DN_CPUHasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size); -DN_API bool DN_CPUHasFeature (DN_CPUReport const *report, DN_CPUFeature feature); -DN_API bool DN_CPUHasAllFeatures (DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size); -DN_API void DN_CPUSetFeature (DN_CPUReport *report, DN_CPUFeature feature); -DN_API DN_CPUReport DN_CPUGetReport (); +DN_API DN_CPUIDResult DN_CPUID (DN_CPUIDArgs args); +DN_API DN_USize DN_CPUHasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size); +DN_API bool DN_CPUHasFeature (DN_CPUReport const *report, DN_CPUFeature feature); +DN_API bool DN_CPUHasAllFeatures (DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size); +DN_API void DN_CPUSetFeature (DN_CPUReport *report, DN_CPUFeature feature); +DN_API DN_CPUReport DN_CPUGetReport (); -DN_API void DN_TicketMutex_Begin (DN_TicketMutex *mutex); -DN_API void DN_TicketMutex_End (DN_TicketMutex *mutex); -DN_API DN_UInt DN_TicketMutex_MakeTicket (DN_TicketMutex *mutex); -DN_API void DN_TicketMutex_BeginTicket (DN_TicketMutex const *mutex, DN_UInt ticket); -DN_API bool DN_TicketMutex_CanLock (DN_TicketMutex const *mutex, DN_UInt ticket); +DN_API void DN_TicketMutex_Begin (DN_TicketMutex *mutex); +DN_API void DN_TicketMutex_End (DN_TicketMutex *mutex); +DN_API DN_UInt DN_TicketMutex_MakeTicket (DN_TicketMutex *mutex); +DN_API void DN_TicketMutex_BeginTicket (DN_TicketMutex const *mutex, DN_UInt ticket); +DN_API bool DN_TicketMutex_CanLock (DN_TicketMutex const *mutex, DN_UInt ticket); -DN_API void DN_BitUnsetInplace (DN_USize *flags, DN_USize bitfield); -DN_API void DN_BitSetInplace (DN_USize *flags, DN_USize bitfield); -DN_API bool DN_BitIsSet (DN_USize bits, DN_USize bits_to_set); -DN_API bool DN_BitIsNotSet (DN_USize bits, DN_USize bits_to_check); -#define DN_BitClearNextLSB(value) (value) & ((value) - 1) +DN_API void DN_BitUnsetInplace (DN_USize *flags, DN_USize bitfield); +DN_API void DN_BitSetInplace (DN_USize *flags, DN_USize bitfield); +DN_API bool DN_BitIsSet (DN_USize bits, DN_USize bits_to_set); +DN_API bool DN_BitIsNotSet (DN_USize bits, DN_USize bits_to_check); +#define DN_BitClearNextLSB(value) (value) & ((value) - 1) -DN_API DN_I64 DN_SafeAddI64 (DN_I64 a, DN_I64 b); -DN_API DN_I64 DN_SafeMulI64 (DN_I64 a, DN_I64 b); +DN_API DN_I64 DN_SafeAddI64 (DN_I64 a, DN_I64 b); +DN_API DN_I64 DN_SafeMulI64 (DN_I64 a, DN_I64 b); -DN_API DN_U64 DN_SafeAddU64 (DN_U64 a, DN_U64 b); -DN_API DN_U64 DN_SafeMulU64 (DN_U64 a, DN_U64 b); +DN_API DN_U64 DN_SafeAddU64 (DN_U64 a, DN_U64 b); +DN_API DN_U64 DN_SafeMulU64 (DN_U64 a, DN_U64 b); -DN_API DN_U64 DN_SafeSubU64 (DN_U64 a, DN_U64 b); -DN_API DN_U32 DN_SafeSubU32 (DN_U32 a, DN_U32 b); +DN_API DN_U64 DN_SafeSubU64 (DN_U64 a, DN_U64 b); +DN_API DN_U32 DN_SafeSubU32 (DN_U32 a, DN_U32 b); -DN_API int DN_SaturateCastUSizeToInt (DN_USize val); -DN_API DN_I8 DN_SaturateCastUSizeToI8 (DN_USize val); -DN_API DN_I16 DN_SaturateCastUSizeToI16 (DN_USize val); -DN_API DN_I32 DN_SaturateCastUSizeToI32 (DN_USize val); -DN_API DN_I64 DN_SaturateCastUSizeToI64 (DN_USize val); +DN_API int DN_SaturateCastUSizeToInt (DN_USize val); +DN_API DN_I8 DN_SaturateCastUSizeToI8 (DN_USize val); +DN_API DN_I16 DN_SaturateCastUSizeToI16 (DN_USize val); +DN_API DN_I32 DN_SaturateCastUSizeToI32 (DN_USize val); +DN_API DN_I64 DN_SaturateCastUSizeToI64 (DN_USize val); -DN_API int DN_SaturateCastU64ToInt (DN_U64 val); -DN_API DN_I8 DN_SaturateCastU8ToI8 (DN_U64 val); -DN_API DN_I16 DN_SaturateCastU16ToI16 (DN_U64 val); -DN_API DN_I32 DN_SaturateCastU32ToI32 (DN_U64 val); -DN_API DN_I64 DN_SaturateCastU64ToI64 (DN_U64 val); -DN_API DN_UInt DN_SaturateCastU64ToUInt (DN_U64 val); -DN_API DN_U8 DN_SaturateCastU64ToU8 (DN_U64 val); -DN_API DN_U16 DN_SaturateCastU64ToU16 (DN_U64 val); -DN_API DN_U32 DN_SaturateCastU64ToU32 (DN_U64 val); +DN_API int DN_SaturateCastU64ToInt (DN_U64 val); +DN_API DN_I8 DN_SaturateCastU8ToI8 (DN_U64 val); +DN_API DN_I16 DN_SaturateCastU16ToI16 (DN_U64 val); +DN_API DN_I32 DN_SaturateCastU32ToI32 (DN_U64 val); +DN_API DN_I64 DN_SaturateCastU64ToI64 (DN_U64 val); +DN_API DN_UInt DN_SaturateCastU64ToUInt (DN_U64 val); +DN_API DN_U8 DN_SaturateCastU64ToU8 (DN_U64 val); +DN_API DN_U16 DN_SaturateCastU64ToU16 (DN_U64 val); +DN_API DN_U32 DN_SaturateCastU64ToU32 (DN_U64 val); -DN_API DN_U8 DN_SaturateCastUSizeToU8 (DN_USize val); -DN_API DN_U16 DN_SaturateCastUSizeToU16 (DN_USize val); -DN_API DN_U32 DN_SaturateCastUSizeToU32 (DN_USize val); -DN_API DN_U64 DN_SaturateCastUSizeToU64 (DN_USize val); +DN_API DN_U8 DN_SaturateCastUSizeToU8 (DN_USize val); +DN_API DN_U16 DN_SaturateCastUSizeToU16 (DN_USize val); +DN_API DN_U32 DN_SaturateCastUSizeToU32 (DN_USize val); +DN_API DN_U64 DN_SaturateCastUSizeToU64 (DN_USize val); -DN_API int DN_SaturateCastISizeToInt (DN_ISize val); -DN_API DN_I8 DN_SaturateCastISizeToI8 (DN_ISize val); -DN_API DN_I16 DN_SaturateCastISizeToI16 (DN_ISize val); -DN_API DN_I32 DN_SaturateCastISizeToI32 (DN_ISize val); -DN_API DN_I64 DN_SaturateCastISizeToI64 (DN_ISize val); +DN_API int DN_SaturateCastISizeToInt (DN_ISize val); +DN_API DN_I8 DN_SaturateCastISizeToI8 (DN_ISize val); +DN_API DN_I16 DN_SaturateCastISizeToI16 (DN_ISize val); +DN_API DN_I32 DN_SaturateCastISizeToI32 (DN_ISize val); +DN_API DN_I64 DN_SaturateCastISizeToI64 (DN_ISize val); -DN_API DN_UInt DN_SaturateCastISizeToUInt (DN_ISize val); -DN_API DN_U8 DN_SaturateCastISizeToU8 (DN_ISize val); -DN_API DN_U16 DN_SaturateCastISizeToU16 (DN_ISize val); -DN_API DN_U32 DN_SaturateCastISizeToU32 (DN_ISize val); -DN_API DN_U64 DN_SaturateCastISizeToU64 (DN_ISize val); +DN_API DN_UInt DN_SaturateCastISizeToUInt (DN_ISize val); +DN_API DN_U8 DN_SaturateCastISizeToU8 (DN_ISize val); +DN_API DN_U16 DN_SaturateCastISizeToU16 (DN_ISize val); +DN_API DN_U32 DN_SaturateCastISizeToU32 (DN_ISize val); +DN_API DN_U64 DN_SaturateCastISizeToU64 (DN_ISize val); -DN_API DN_ISize DN_SaturateCastI64ToISize (DN_I64 val); -DN_API DN_I8 DN_SaturateCastI64ToI8 (DN_I64 val); -DN_API DN_I16 DN_SaturateCastI64ToI16 (DN_I64 val); -DN_API DN_I32 DN_SaturateCastI64ToI32 (DN_I64 val); +DN_API DN_ISize DN_SaturateCastI64ToISize (DN_I64 val); +DN_API DN_I8 DN_SaturateCastI64ToI8 (DN_I64 val); +DN_API DN_I16 DN_SaturateCastI64ToI16 (DN_I64 val); +DN_API DN_I32 DN_SaturateCastI64ToI32 (DN_I64 val); -DN_API DN_UInt DN_SaturateCastI64ToUInt (DN_I64 val); -DN_API DN_ISize DN_SaturateCastI64ToUSize (DN_I64 val); -DN_API DN_U8 DN_SaturateCastI64ToU8 (DN_I64 val); -DN_API DN_U16 DN_SaturateCastI64ToU16 (DN_I64 val); -DN_API DN_U32 DN_SaturateCastI64ToU32 (DN_I64 val); -DN_API DN_U64 DN_SaturateCastI64ToU64 (DN_I64 val); +DN_API DN_UInt DN_SaturateCastI64ToUInt (DN_I64 val); +DN_API DN_ISize DN_SaturateCastI64ToUSize (DN_I64 val); +DN_API DN_U8 DN_SaturateCastI64ToU8 (DN_I64 val); +DN_API DN_U16 DN_SaturateCastI64ToU16 (DN_I64 val); +DN_API DN_U32 DN_SaturateCastI64ToU32 (DN_I64 val); +DN_API DN_U64 DN_SaturateCastI64ToU64 (DN_I64 val); -DN_API DN_I8 DN_SaturateCastIntToI8 (int val); -DN_API DN_I16 DN_SaturateCastIntToI16 (int val); -DN_API DN_U8 DN_SaturateCastIntToU8 (int val); -DN_API DN_U16 DN_SaturateCastIntToU16 (int val); -DN_API DN_U32 DN_SaturateCastIntToU32 (int val); -DN_API DN_U64 DN_SaturateCastIntToU64 (int val); +DN_API DN_I8 DN_SaturateCastIntToI8 (int val); +DN_API DN_I16 DN_SaturateCastIntToI16 (int val); +DN_API DN_U8 DN_SaturateCastIntToU8 (int val); +DN_API DN_U16 DN_SaturateCastIntToU16 (int val); +DN_API DN_U32 DN_SaturateCastIntToU32 (int val); +DN_API DN_U64 DN_SaturateCastIntToU64 (int val); -DN_API void DN_ASanPoisonMemoryRegion (void const volatile *ptr, DN_USize size); -DN_API void DN_ASanUnpoisonMemoryRegion (void const volatile *ptr, DN_USize size); +DN_API void DN_ASanPoisonMemoryRegion (void const volatile *ptr, DN_USize size); +DN_API void DN_ASanUnpoisonMemoryRegion (void const volatile *ptr, DN_USize size); -DN_API DN_F32 DN_EpsilonClampF32 (DN_F32 value, DN_F32 target, DN_F32 epsilon); +DN_API DN_F32 DN_EpsilonClampF32 (DN_F32 value, DN_F32 target, DN_F32 epsilon); -DN_API DN_Arena DN_ArenaFromBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags); -DN_API DN_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); -#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) +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); +#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_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_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_ArenaNewCopy(arena, T, src) (T *)DN_ArenaCopy (arena, (src), sizeof(T), alignof(T)) -#define DN_ArenaNewArrayCopy(arena, T, src, count) (T *)DN_ArenaCopy (arena, (src), sizeof(T) * (count), alignof(T)) +#define DN_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)) -DN_API DN_Pool DN_PoolFromArena (DN_Arena *arena, DN_U8 align); -DN_API bool DN_PoolIsValid (DN_Pool const *pool); -DN_API void * DN_PoolAlloc (DN_Pool *pool, DN_USize size); -DN_API void DN_PoolDealloc (DN_Pool *pool, void *ptr); -DN_API void * DN_PoolCopy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align); -#define DN_PoolNew(pool, T) (T *)DN_PoolAlloc(pool, sizeof(T)) -#define DN_PoolNewArray(pool, T, count) (T *)DN_PoolAlloc(pool, count * sizeof(T)) -#define DN_PoolNewCopy(pool, T, src) (T *)DN_PoolCopy (pool, (src), sizeof(T), alignof(T)) -#define DN_PoolNewArrayCopy(pool, T, src, count) (T *)DN_PoolCopy (pool, (src), sizeof(T) * (count), alignof(T)) +DN_API DN_Pool DN_PoolFromArena (DN_Arena *arena, DN_U8 align); +DN_API bool DN_PoolIsValid (DN_Pool const *pool); +DN_API void * DN_PoolAlloc (DN_Pool *pool, DN_USize size); +DN_API void DN_PoolDealloc (DN_Pool *pool, void *ptr); +DN_API void * DN_PoolCopy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align); +#define DN_PoolNew(pool, T) (T *)DN_PoolAlloc(pool, sizeof(T)) +#define DN_PoolNewArray(pool, T, count) (T *)DN_PoolAlloc(pool, count * sizeof(T)) +#define DN_PoolNewCopy(pool, T, src) (T *)DN_PoolCopy (pool, (src), sizeof(T), alignof(T)) +#define DN_PoolNewArrayCopy(pool, T, src, count) (T *)DN_PoolCopy (pool, (src), sizeof(T) * (count), alignof(T)) -DN_API bool DN_CharIsAlphabet (char ch); -DN_API bool DN_CharIsDigit (char ch); -DN_API bool DN_CharIsAlphaNum (char ch); -DN_API bool DN_CharIsWhitespace (char ch); -DN_API bool DN_CharIsHex (char ch); -DN_API char DN_CharToLower (char ch); -DN_API char DN_CharToUpper (char ch); +DN_API DN_ErrSink* DN_ErrSinkBegin_ (DN_ErrSink *err, DN_ErrSinkMode mode, DN_CallSite call_site); +#define DN_ErrSinkBegin(err, mode) DN_ErrSinkBegin_(err, mode, DN_CALL_SITE) +#define DN_ErrSinkBeginDefault(err) DN_ErrSinkBegin(err, DN_ErrSinkMode_Nil) +DN_API bool DN_ErrSinkHasError (DN_ErrSink *err); +DN_API DN_ErrSinkMsg* DN_ErrSinkEnd (DN_Arena *arena, DN_ErrSink *err); +DN_API DN_Str8 DN_ErrSinkEndStr8 (DN_Arena *arena, DN_ErrSink *err); +DN_API void DN_ErrSinkEndIgnore (DN_ErrSink *err); +DN_API bool DN_ErrSinkEndLogError_ (DN_ErrSink *err, DN_CallSite call_site, DN_Str8 msg); +#define DN_ErrSinkEndLogError(err, err_msg) DN_ErrSinkEndLogError_(err, DN_CALL_SITE, err_msg) +DN_API bool DN_ErrSinkEndLogErrorFV_ (DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); +#define DN_ErrSinkEndLogErrorFV(err, fmt, args) DN_ErrSinkEndLogErrorFV_(err, DN_CALL_SITE, fmt, args) +DN_API bool DN_ErrSinkEndLogErrorF_ (DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); +#define DN_ErrSinkEndLogErrorF(err, fmt, ...) DN_ErrSinkEndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__) +DN_API void DN_ErrSinkEndExitIfErrorF_ (DN_ErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...); +#define DN_ErrSinkEndExitIfErrorF(err, exit_val, fmt, ...) DN_ErrSinkEndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__) +DN_API void DN_ErrSinkEndExitIfErrorFV_ (DN_ErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args); +#define DN_ErrSinkEndExitIfErrorFV(err, exit_val, fmt, args) DN_ErrSinkEndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args) +DN_API void DN_ErrSinkAppendFV_ (DN_ErrSink *err, DN_U32 error_code, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); +#define DN_ErrSinkAppendFV(error, error_code, fmt, args) DN_ErrSinkAppendFV_(error, error_code, DN_CALL_SITE, fmt, args) +DN_API void DN_ErrSinkAppendF_ (DN_ErrSink *err, DN_U32 error_code, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); +#define DN_ErrSinkAppendF(error, error_code, fmt, ...) DN_ErrSinkAppendF_(error, error_code, DN_CALL_SITE, fmt, ##__VA_ARGS__) -DN_API DN_U64FromResult DN_U64FromStr8 (DN_Str8 string, char separator); -DN_API DN_U64FromResult DN_U64FromPtr (void const *data, DN_USize size, char separator); -DN_API DN_U64 DN_U64FromPtrUnsafe (void const *data, DN_USize size, char separator); -DN_API DN_U64FromResult DN_U64FromHexPtr (void const *hex, DN_USize hex_count); -DN_API DN_U64 DN_U64FromHexPtrUnsafe (void const *hex, DN_USize hex_count); -DN_API DN_U64FromResult DN_U64FromHexStr8 (DN_Str8 hex); -DN_API DN_U64 DN_U64FromHexStr8Unsafe (DN_Str8 hex); -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 void DN_TCInit (DN_TCCore *tc, DN_U64 thread_id, DN_Arena *main_arena, DN_Arena *temp_a_arena, DN_Arena *temp_b_arena, DN_Arena *err_sink_arena); +DN_API void DN_TCInitFromMemFuncs (DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_ArenaMemFuncs mem_funcs); +DN_API void DN_TCDeinit (DN_TCCore *tc); +DN_API void DN_TCEquip (DN_TCCore *tc); +DN_API DN_TCCore* DN_TCGet (); +DN_API DN_Arena* DN_TCMainArena (); +DN_API DN_Arena* DN_TCTempArena (DN_Arena **conflicts, DN_USize count); +DN_API DN_TCScratch DN_TCScratchBegin (DN_Arena **conflicts, DN_USize count); +DN_API void DN_TCScratchEnd (DN_TCScratch *scratch); +DN_API void DN_TCSetFrameArena (DN_Arena *arena); +DN_API DN_Arena* DN_TCFrameArena (); +DN_API DN_ErrSink* DN_TCErrSink (); +#define DN_TCErrSinkBegin(mode) DN_ErrSinkBegin(DN_TCErrSink(), mode) +#define DN_TCErrSinkBeginDefault() DN_ErrSinkBeginDefault(DN_TCErrSink()) -DN_API 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); -DN_API DN_FmtAppendResult DN_FmtAppend (char *buf, DN_USize *buf_size, DN_USize buf_max, char const *fmt, ...); -DN_API DN_FmtAppendResult DN_FmtAppendTruncate (char *buf, DN_USize *buf_size, DN_USize buf_max, DN_Str8 truncator, char const *fmt, ...); -DN_API DN_USize DN_CStr8Size (char const *src); -DN_API DN_USize DN_CStr16Size (wchar_t const *src); +DN_API bool DN_CharIsAlphabet (char ch); +DN_API bool DN_CharIsDigit (char ch); +DN_API bool DN_CharIsAlphaNum (char ch); +DN_API bool DN_CharIsWhitespace (char ch); +DN_API bool DN_CharIsHex (char ch); +DN_API char DN_CharToLower (char ch); +DN_API char DN_CharToUpper (char ch); -#define DN_Str16Lit(string) DN_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1} -#define DN_Str8Lit(c_str) DN_Literal(DN_Str8){(char *)(c_str), sizeof(c_str) - 1} -#define DN_Str8PrintFmt(string) (int)((string).size), (string).data -#define DN_Str8FromPtr(data, size) DN_Literal(DN_Str8){(char *)(data), (DN_USize)(size)} -#define DN_Str8FromStruct(ptr) DN_Str8FromPtr((ptr)->data, (ptr)->size) -DN_API DN_Str8 DN_Str8FromCStr8 (char const *src); -DN_API DN_Str8 DN_Str8FromArena (DN_Arena *arena, DN_USize size, DN_ZMem z_mem); -DN_API DN_Str8 DN_Str8FromPool (DN_Pool *pool, DN_USize size); -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_Str8FromFmtVArena (DN_Arena *arena, 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, ...); -DN_API DN_Str8x16 DN_Str8x16FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API DN_Str8x32 DN_Str8x32FromFmt (DN_FMT_ATTRIB char const *fmt, ...); -DN_API DN_Str8x32 DN_Str8x32FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API DN_Str8x64 DN_Str8x64FromFmt (DN_FMT_ATTRIB char const *fmt, ...); -DN_API DN_Str8x64 DN_Str8x64FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API DN_Str8x128 DN_Str8x128FromFmt (DN_FMT_ATTRIB char const *fmt, ...); -DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API DN_Str8x256 DN_Str8x256FromFmt (DN_FMT_ATTRIB char const *fmt, ...); -DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API DN_Str8x32 DN_Str8x32FromU64 (DN_U64 val, char separator); -DN_API bool DN_Str8IsAll (DN_Str8 string, DN_Str8IsAllType is_all); -DN_API char * DN_Str8End (DN_Str8 string); -DN_API DN_Str8 DN_Str8Slice (DN_Str8 string, DN_USize offset, DN_USize size); -DN_API DN_Str8 DN_Str8Advance (DN_Str8 string, DN_USize amount); -DN_API DN_Str8 DN_Str8NextLine (DN_Str8 string); -DN_API DN_Str8BSplitResult DN_Str8BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); -DN_API DN_Str8BSplitResult DN_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_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, uint32_t flags); -DN_API DN_Str8 DN_Str8Segment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char); -DN_API DN_Str8 DN_Str8ReverseSegment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char); -DN_API bool DN_Str8Eq (DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); -DN_API bool DN_Str8EqInsensitive (DN_Str8 lhs, DN_Str8 rhs); -DN_API bool DN_Str8StartsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); -DN_API bool DN_Str8StartsWithInsensitive(DN_Str8 string, DN_Str8 prefix); -DN_API bool DN_Str8EndsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); -DN_API bool DN_Str8EndsWithInsensitive (DN_Str8 string, DN_Str8 prefix); -DN_API bool DN_Str8HasChar (DN_Str8 string, char ch); -DN_API DN_Str8 DN_Str8TrimPrefix (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); -DN_API DN_Str8 DN_Str8TrimHexPrefix (DN_Str8 string); -DN_API DN_Str8 DN_Str8TrimSuffix (DN_Str8 string, DN_Str8 suffix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); -DN_API DN_Str8 DN_Str8TrimAround (DN_Str8 string, DN_Str8 trim_string); -DN_API DN_Str8 DN_Str8TrimHeadWhitespace (DN_Str8 string); -DN_API DN_Str8 DN_Str8TrimTailWhitespace (DN_Str8 string); -DN_API DN_Str8 DN_Str8TrimWhitespaceAround (DN_Str8 string); -DN_API DN_Str8 DN_Str8TrimByteOrderMark (DN_Str8 string); -DN_API DN_Str8 DN_Str8FileNameFromPath (DN_Str8 path); -DN_API DN_Str8 DN_Str8FileNameNoExtension (DN_Str8 path); -DN_API DN_Str8 DN_Str8FilePathNoExtension (DN_Str8 path); -DN_API DN_Str8 DN_Str8FileExtension (DN_Str8 path); -DN_API DN_Str8 DN_Str8FileDirectoryFromPath(DN_Str8 path); -DN_API DN_Str8 DN_Str8AppendF (DN_Arena *arena, DN_Str8 string, char const *fmt, ...); -DN_API DN_Str8 DN_Str8AppendFV (DN_Arena *arena, DN_Str8 string, char const *fmt, va_list args); -DN_API DN_Str8 DN_Str8FillF (DN_Arena *arena, DN_USize count, char const *fmt, ...); -DN_API DN_Str8 DN_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_U64FromResult DN_U64FromStr8 (DN_Str8 string, char separator); +DN_API DN_U64FromResult DN_U64FromPtr (void const *data, DN_USize size, char separator); +DN_API DN_U64 DN_U64FromPtrUnsafe (void const *data, DN_USize size, char separator); +DN_API DN_U64FromResult DN_U64FromHexPtr (void const *hex, DN_USize hex_count); +DN_API DN_U64 DN_U64FromHexPtrUnsafe (void const *hex, DN_USize hex_count); +DN_API DN_U64FromResult DN_U64FromHexStr8 (DN_Str8 hex); +DN_API DN_U64 DN_U64FromHexStr8Unsafe (DN_Str8 hex); +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 DN_Str8Builder DN_Str8BuilderFromArena (DN_Arena *arena); -DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRef (DN_Arena *arena, DN_Str8 const *strings, DN_USize size); -DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopy (DN_Arena *arena, DN_Str8 const *strings, DN_USize size); -DN_API DN_Str8Builder DN_Str8BuilderFromBuilder (DN_Arena *arena, DN_Str8Builder const *builder); -DN_API bool DN_Str8BuilderAddArrayRef (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add); -DN_API bool DN_Str8BuilderAddArrayCopy (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add); -DN_API bool DN_Str8BuilderAddFV (DN_Str8Builder *builder, DN_Str8BuilderAdd add, DN_FMT_ATTRIB char const *fmt, va_list args); -#define DN_Str8BuilderAppendArrayRef(builder, strings, size) DN_Str8BuilderAddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Append) -#define DN_Str8BuilderAppendArrayCopy(builder, strings, size) DN_Str8BuilderAddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Append) -#define DN_Str8BuilderAppendSliceRef(builder, slice) DN_Str8BuilderAddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append) -#define DN_Str8BuilderAppendSliceCopy(builder, slice) DN_Str8BuilderAddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append) -DN_API bool DN_Str8BuilderAppendRef (DN_Str8Builder *builder, DN_Str8 string); -DN_API bool DN_Str8BuilderAppendCopy (DN_Str8Builder *builder, DN_Str8 string); -#define DN_Str8BuilderAppendFV(builder, fmt, args) DN_Str8BuilderAddFV(builder, DN_Str8BuilderAdd_Append, fmt, args) -DN_API bool DN_Str8BuilderAppendF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...); -DN_API bool DN_Str8BuilderAppendBytesRef (DN_Str8Builder *builder, void const *ptr, DN_USize size); -DN_API bool DN_Str8BuilderAppendBytesCopy (DN_Str8Builder *builder, void const *ptr, DN_USize size); -DN_API bool DN_Str8BuilderAppendBuilderRef (DN_Str8Builder *dest, DN_Str8Builder const *src); -DN_API bool DN_Str8BuilderAppendBuilderCopy (DN_Str8Builder *dest, DN_Str8Builder const *src); +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); +DN_API DN_FmtAppendResult DN_FmtAppend (char *buf, DN_USize *buf_size, DN_USize buf_max, char const *fmt, ...); +DN_API DN_FmtAppendResult DN_FmtAppendTruncate (char *buf, DN_USize *buf_size, DN_USize buf_max, DN_Str8 truncator, char const *fmt, ...); +DN_API DN_USize DN_CStr8Size (char const *src); +DN_API DN_USize DN_CStr16Size (wchar_t const *src); + +#define DN_Str16Lit(string) DN_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1} +#define DN_Str16FromPtr(data, size) DN_Literal(DN_Str16){(wchar_t *)(data), (DN_USize)(size)} + +#define DN_Str8Lit(c_str) DN_Literal(DN_Str8){(char *)(c_str), sizeof(c_str) - 1} +#define DN_Str8PrintFmt(string) (int)((string).size), (string).data +#define DN_Str8FromPtr(data, size) DN_Literal(DN_Str8){(char *)(data), (DN_USize)(size)} +#define DN_Str8FromStruct(ptr) DN_Str8FromPtr((ptr)->data, (ptr)->size) +DN_API DN_Str8 DN_Str8FromCStr8 (char const *src); +DN_API DN_Str8 DN_Str8FromArena (DN_Arena *arena, DN_USize size, DN_ZMem z_mem); +DN_API DN_Str8 DN_Str8FromPool (DN_Pool *pool, DN_USize size); +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_Str8FromFmtVArena (DN_Arena *arena, 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, ...); +DN_API DN_Str8x16 DN_Str8x16FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Str8x32 DN_Str8x32FromFmt (DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_Str8x32 DN_Str8x32FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Str8x64 DN_Str8x64FromFmt (DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_Str8x64 DN_Str8x64FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Str8x128 DN_Str8x128FromFmt (DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Str8x256 DN_Str8x256FromFmt (DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Str8x16AppendFmt (DN_Str8x16 *str, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Str8x16AppendFmtV (DN_Str8x16 *str, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Str8x32AppendFmt (DN_Str8x32 *str, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Str8x32AppendFmtV (DN_Str8x32 *str, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Str8x64AppendFmt (DN_Str8x64 *str, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Str8x64AppendFmtV (DN_Str8x64 *str, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Str8x128AppendFmt (DN_Str8x128 *str, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Str8x128AppendFmtV (DN_Str8x128 *str, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Str8x256AppendFmt (DN_Str8x256 *str, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Str8x256AppendFmtV (DN_Str8x256 *str, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Str8x32 DN_Str8x32FromU64 (DN_U64 val, char separator); +DN_API bool DN_Str8IsAll (DN_Str8 string, DN_Str8IsAllType is_all); +DN_API char * DN_Str8End (DN_Str8 string); +DN_API DN_Str8 DN_Str8Subset (DN_Str8 string, DN_USize offset, DN_USize size); +DN_API DN_Str8 DN_Str8Advance (DN_Str8 string, DN_USize amount); +DN_API DN_Str8 DN_Str8NextLine (DN_Str8 string); +DN_API DN_Str8BSplitResult DN_Str8BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); +DN_API DN_Str8BSplitResult DN_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_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, uint32_t flags); +DN_API DN_Str8 DN_Str8Segment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char); +DN_API DN_Str8 DN_Str8ReverseSegment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char); +DN_API bool DN_Str8Eq (DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API bool DN_Str8EqInsensitive (DN_Str8 lhs, DN_Str8 rhs); +DN_API bool DN_Str8StartsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API bool DN_Str8StartsWithInsensitive (DN_Str8 string, DN_Str8 prefix); +DN_API bool DN_Str8EndsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API bool DN_Str8EndsWithInsensitive (DN_Str8 string, DN_Str8 prefix); +DN_API bool DN_Str8HasChar (DN_Str8 string, char ch); +DN_API DN_Str8 DN_Str8TrimPrefix (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API DN_Str8 DN_Str8TrimHexPrefix (DN_Str8 string); +DN_API DN_Str8 DN_Str8TrimSuffix (DN_Str8 string, DN_Str8 suffix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API DN_Str8 DN_Str8TrimAround (DN_Str8 string, DN_Str8 trim_string); +DN_API DN_Str8 DN_Str8TrimHeadWhitespace (DN_Str8 string); +DN_API DN_Str8 DN_Str8TrimTailWhitespace (DN_Str8 string); +DN_API DN_Str8 DN_Str8TrimWhitespaceAround (DN_Str8 string); +DN_API DN_Str8 DN_Str8TrimByteOrderMark (DN_Str8 string); +DN_API DN_Str8 DN_Str8FileNameFromPath (DN_Str8 path); +DN_API DN_Str8 DN_Str8FileNameNoExtension (DN_Str8 path); +DN_API DN_Str8 DN_Str8FilePathNoExtension (DN_Str8 path); +DN_API DN_Str8 DN_Str8FileExtension (DN_Str8 path); +DN_API DN_Str8 DN_Str8FileDirectoryFromPath (DN_Str8 path); +DN_API DN_Str8 DN_Str8AppendF (DN_Arena *arena, DN_Str8 string, char const *fmt, ...); +DN_API DN_Str8 DN_Str8AppendFV (DN_Arena *arena, DN_Str8 string, char const *fmt, va_list args); +DN_API DN_Str8 DN_Str8FillF (DN_Arena *arena, DN_USize count, char const *fmt, ...); +DN_API DN_Str8 DN_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_Str8 DN_Str8Replace (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena, DN_Str8EqCase eq_case); +DN_API DN_Str8 DN_Str8ReplaceSensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena); +DN_API DN_Str8 DN_Str8ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena); + +DN_API DN_Str8Builder DN_Str8BuilderFromArena (DN_Arena *arena); +DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRef (DN_Arena *arena, DN_Str8 const *strings, DN_USize size); +DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopy (DN_Arena *arena, DN_Str8 const *strings, DN_USize size); +DN_API DN_Str8Builder DN_Str8BuilderFromBuilder (DN_Arena *arena, DN_Str8Builder const *builder); +DN_API bool DN_Str8BuilderAddArrayRef (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add); +DN_API bool DN_Str8BuilderAddArrayCopy (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add); +DN_API bool DN_Str8BuilderAddFV (DN_Str8Builder *builder, DN_Str8BuilderAdd add, DN_FMT_ATTRIB char const *fmt, va_list args); +#define DN_Str8BuilderAppendArrayRef(builder, strings, size) DN_Str8BuilderAddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Append) +#define DN_Str8BuilderAppendArrayCopy(builder, strings, size) DN_Str8BuilderAddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Append) +#define DN_Str8BuilderAppendSliceRef(builder, slice) DN_Str8BuilderAddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append) +#define DN_Str8BuilderAppendSliceCopy(builder, slice) DN_Str8BuilderAddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append) +DN_API bool DN_Str8BuilderAppendRef (DN_Str8Builder *builder, DN_Str8 string); +DN_API bool DN_Str8BuilderAppendCopy (DN_Str8Builder *builder, DN_Str8 string); +#define DN_Str8BuilderAppendFV(builder, fmt, args) DN_Str8BuilderAddFV(builder, DN_Str8BuilderAdd_Append, fmt, args) +DN_API bool DN_Str8BuilderAppendF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_Str8BuilderAppendBytesRef (DN_Str8Builder *builder, void const *ptr, DN_USize size); +DN_API bool DN_Str8BuilderAppendBytesCopy (DN_Str8Builder *builder, void const *ptr, DN_USize size); +DN_API bool DN_Str8BuilderAppendBuilderRef (DN_Str8Builder *dest, DN_Str8Builder const *src); +DN_API bool DN_Str8BuilderAppendBuilderCopy (DN_Str8Builder *dest, DN_Str8Builder const *src); #define DN_Str8BuilderPrependArrayRef(builder, strings, size) DN_Str8BuilderAddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Prepend) #define DN_Str8BuilderPrependArrayCopy(builder, strings, size) DN_Str8BuilderAddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Prepend) #define DN_Str8BuilderPrependSliceRef(builder, slice) DN_Str8BuilderAddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Prepend) #define DN_Str8BuilderPrependSliceCopy(builder, slice) DN_Str8BuilderAddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Prepend) -DN_API bool DN_Str8BuilderPrependRef (DN_Str8Builder *builder, DN_Str8 string); -DN_API bool DN_Str8BuilderPrependCopy (DN_Str8Builder *builder, DN_Str8 string); +DN_API bool DN_Str8BuilderPrependRef (DN_Str8Builder *builder, DN_Str8 string); +DN_API bool DN_Str8BuilderPrependCopy (DN_Str8Builder *builder, DN_Str8 string); #define DN_Str8BuilderPrependFV(builder, fmt, args) DN_Str8BuilderAddFV(builder, DN_Str8BuilderAdd_Prepend, fmt, args) -DN_API bool DN_Str8BuilderPrependF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...); -DN_API bool DN_Str8BuilderErase (DN_Str8Builder *builder, DN_Str8 string); -DN_API DN_Str8 DN_Str8BuilderBuild (DN_Str8Builder const *builder, DN_Arena *arena); -DN_API DN_Str8 DN_Str8BuilderBuildDelimited (DN_Str8Builder const *builder, DN_Str8 delimiter, DN_Arena *arena); -DN_API DN_Slice DN_Str8BuilderBuildSlice (DN_Str8Builder const *builder, DN_Arena *arena); +DN_API bool DN_Str8BuilderPrependF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_Str8BuilderErase (DN_Str8Builder *builder, DN_Str8 string); +DN_API DN_Str8 DN_Str8BuilderBuild (DN_Str8Builder const *builder, DN_Arena *arena); +DN_API DN_Str8 DN_Str8BuilderBuildDelimited (DN_Str8Builder const *builder, DN_Str8 delimiter, DN_Arena *arena); +DN_API DN_Str8Slice DN_Str8BuilderBuildSlice (DN_Str8Builder const *builder, DN_Arena *arena); -DN_API int DN_EncodeUTF8Codepoint (uint8_t utf8[4], uint32_t codepoint); -DN_API int DN_EncodeUTF16Codepoint (uint16_t utf16[2], uint32_t codepoint); +DN_API int DN_EncodeUTF8Codepoint (uint8_t utf8[4], uint32_t codepoint); +DN_API int DN_EncodeUTF16Codepoint (uint16_t utf16[2], uint32_t codepoint); -DN_API DN_U8 DN_U8FromHexNibble (char hex); -DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8); +DN_API DN_U8 DN_U8FromHexNibble (char hex); +DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8); -DN_API DN_USize DN_BytesFromHexPtr (void const *hex, DN_USize hex_count, void *dest, DN_USize dest_count); -DN_API DN_Str8 DN_BytesFromHexPtrArena (void const *hex, DN_USize hex_count, DN_Arena *arena); -DN_API DN_USize DN_BytesFromHexStr8 (DN_Str8 hex, void *dest, DN_USize dest_count); -DN_API DN_Str8 DN_BytesFromHexStr8Arena (DN_Str8 hex, DN_Arena *arena); -DN_API DN_U8x16 DN_BytesFromHex32Ptr (void const *hex, DN_USize hex_count); -DN_API DN_U8x32 DN_BytesFromHex64Ptr (void const *hex, DN_USize hex_count); +DN_API DN_USize DN_BytesFromHexPtr (void const *hex, DN_USize hex_count, void *dest, DN_USize dest_count); +DN_API DN_Str8 DN_BytesFromHexPtrArena (void const *hex, DN_USize hex_count, DN_Arena *arena); +DN_API DN_USize DN_BytesFromHexStr8 (DN_Str8 hex, void *dest, DN_USize dest_count); +DN_API DN_Str8 DN_BytesFromHexStr8Arena (DN_Str8 hex, DN_Arena *arena); +DN_API DN_U8x16 DN_BytesFromHex32Ptr (void const *hex, DN_USize hex_count); +DN_API DN_U8x32 DN_BytesFromHex64Ptr (void 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_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_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units); -DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); -DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); +DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units); +DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units); +DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units); -DN_API int DN_IsLeapYear (int year); -DN_API bool DN_DateIsValid (DN_Date date); -DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms); -DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date); +DN_API int DN_IsLeapYear (int year); +DN_API bool DN_DateIsValid (DN_Date date); +DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms); +DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date); -DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); -#define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) -DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); -#define DN_ByteCountStr8x32(bytes) DN_ByteCountStr8x32FromType(bytes, DN_ByteCountType_Auto) +DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type); +#define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto) +DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type); +#define DN_ByteCountStr8x32(bytes) DN_ByteCountStr8x32FromType(bytes, DN_ByteCountType_Auto) #define DN_ProfilerZoneLoop(prof, name, index) \ DN_ProfilerZone DN_UniqueName(zone_) = DN_ProfilerBeginZone(prof, DN_Str8Lit(name), index), DN_UniqueName(dummy_) = {}; \ - DN_UniqueName(dummy_).begin_tsc == 0; \ + DN_UniqueName(dummy_).begin_tsc == 0; \ DN_ProfilerEndZone(prof, DN_UniqueName(zone_)), DN_UniqueName(dummy_).begin_tsc = 1 -#define DN_ProfilerZoneLoopAuto(prof, name) DN_ProfilerZoneLoop(prof, name, __COUNTER__ + 1) -DN_API DN_Profiler DN_ProfilerInit (DN_ProfilerAnchor *anchors, DN_USize count, DN_USize anchors_per_frame, DN_ProfilerTSCNowFunc *tsc_now, DN_U64 tsc_frequency); -DN_API DN_ProfilerZone DN_ProfilerBeginZone (DN_Profiler *profiler, DN_Str8 name, DN_U16 anchor_index); -#define DN_ProfilerBeginZoneAuto(prof, name) DN_ProfilerBeginZone(prof, DN_Str8Lit(name), __COUNTER__ + 1) -DN_API void DN_ProfilerEndZone (DN_Profiler *profiler, DN_ProfilerZone zone); -DN_API DN_USize DN_ProfilerFrameCount (DN_Profiler const *profiler); -DN_API DN_ProfilerAnchorArray DN_ProfilerFrameAnchorsFromIndex (DN_Profiler *profiler, DN_USize frame_index); -DN_API DN_ProfilerAnchorArray DN_ProfilerFrameAnchors (DN_Profiler *profiler); -DN_API void DN_ProfilerNewFrame (DN_Profiler *profiler); -DN_API void DN_ProfilerDump (DN_Profiler *profiler); -DN_API DN_F64 DN_ProfilerSecFromTSC (DN_Profiler *profiler, DN_U64 duration_tsc); -DN_API DN_F64 DN_ProfilerMsFromTSC (DN_Profiler *profiler, DN_U64 duration_tsc); +#define DN_ProfilerZoneLoopAuto(prof, name) DN_ProfilerZoneLoop(prof, name, __COUNTER__ + 1) +DN_API DN_Profiler DN_ProfilerInit (DN_ProfilerAnchor *anchors, DN_USize count, DN_USize anchors_per_frame, DN_ProfilerTSCNowFunc *tsc_now, DN_U64 tsc_frequency); +DN_API DN_ProfilerZone DN_ProfilerBeginZone (DN_Profiler *profiler, DN_Str8 name, DN_U16 anchor_index); +#define DN_ProfilerBeginZoneAuto(prof, name) DN_ProfilerBeginZone(prof, DN_Str8Lit(name), __COUNTER__ + 1) +DN_API void DN_ProfilerEndZone (DN_Profiler *profiler, DN_ProfilerZone zone); +DN_API DN_USize DN_ProfilerFrameCount (DN_Profiler const *profiler); +DN_API DN_ProfilerAnchorArray DN_ProfilerFrameAnchorsFromIndex (DN_Profiler *profiler, DN_USize frame_index); +DN_API DN_ProfilerAnchorArray DN_ProfilerFrameAnchors (DN_Profiler *profiler); +DN_API void DN_ProfilerNewFrame (DN_Profiler *profiler); +DN_API void DN_ProfilerDump (DN_Profiler *profiler); +DN_API DN_F64 DN_ProfilerSecFromTSC (DN_Profiler *profiler, DN_U64 duration_tsc); +DN_API DN_F64 DN_ProfilerMsFromTSC (DN_Profiler *profiler, DN_U64 duration_tsc); +DN_API DN_PCG32 DN_PCG32Init (DN_U64 seed); +DN_API DN_U32 DN_PCG32Next (DN_PCG32 *rng); +DN_API DN_U64 DN_PCG32Next64 (DN_PCG32 *rng); +DN_API DN_U32 DN_PCG32Range (DN_PCG32 *rng, DN_U32 low, DN_U32 high); +DN_API DN_F32 DN_PCG32NextF32 (DN_PCG32 *rng); +DN_API DN_F64 DN_PCG32NextF64 (DN_PCG32 *rng); +DN_API void DN_PCG32Advance (DN_PCG32 *rng, DN_U64 delta); + +#if !defined(DN_FNV1A32_SEED) + #define DN_FNV1A32_SEED 2166136261U +#endif + +#if !defined(DN_FNV1A64_SEED) + #define DN_FNV1A64_SEED 14695981039346656037ULL +#endif + +DN_API DN_U32 DN_FNV1AHashU32FromBytes (void const *bytes, DN_USize size, DN_U32 seed); +DN_API DN_U64 DN_FNV1AHashU64FromBytes (void const *bytes, DN_USize size, DN_U64 seed); + +DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX86 (void const *bytes, int len, DN_U32 seed); +DN_API DN_MurmurHash3 DN_MurmurHash3HashU128FromBytesX64 (void const *bytes, int len, DN_U32 seed); +DN_API DN_U64 DN_MurmurHash3HashU64FromBytesX64 (void const *bytes, int len, DN_U32 seed); +DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX64 (void const *bytes, int len, DN_U32 seed); + +#if defined(DN_64_BIT) + #define DN_MurmurHash3HashU32FromBytes(bytes, len, seed) DN_MurmurHash3HashU32FromBytesX64(bytes, len, seed) +#else + #define DN_MurmurHash3HashU32FromBytes(bytes, len, seed) DN_MurmurHash3HashU32FromBytesX86(bytes, len, seed) +#endif + +#define DN_LogResetEscapeCode "\x1b[0m" +#define DN_LogBoldEscapeCode "\x1b[1m" +DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB (DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b); +DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromU32 (DN_LogColourType colour, DN_U32 value); +DN_API DN_LogPrefixSize DN_LogMakePrefix (DN_LogStyle style, DN_LogTypeParam type, DN_CallSite call_site, DN_LogDate date, char *dest, DN_USize dest_size); +DN_API void DN_LogSetEmitFromTypeFVFunc (DN_LogEmitFromTypeFVFunc *print_func, void *user_data); +DN_API void DN_LogEmitFromType (DN_LogTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_LogTypeParam DN_LogMakeU32LogTypeParam (DN_LogType type); +#define DN_LogDebugF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Debug), DN_CALL_SITE, fmt, ##__VA_ARGS__) +#define DN_LogInfoF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__) +#define DN_LogWarningF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__) +#define DN_LogErrorF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__) + +// NOTE: OS primitives that the OS layer can provide for the base layer but is optional. +#if defined(DN_FREESTANDING) +#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A") +#define DN_StackTraceWalk(...) +#define DN_StackTraceWalkResultIterate(...) +#define DN_StackTraceWalkResultToStr8(...) DN_Str8Lit("N/A") +#define DN_StackTraceWalkStr8(...) DN_Str8Lit("N/A") +#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A") +#define DN_StackTraceGetFrames(...) +#define DN_StackTraceRawFrameToFrame(...) +#define DN_StackTracePrint(...) +#define DN_StackTraceReloadSymbols(...) +#else +DN_API DN_StackTraceWalkResult DN_StackTraceWalk (DN_Arena *arena, DN_U16 limit); +DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk); +DN_API DN_Str8 DN_StackTraceWalkResultToStr8 (DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip); +DN_API DN_Str8 DN_StackTraceWalkStr8 (DN_Arena *arena, DN_U16 limit, DN_U16 skip); +DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap (DN_U16 limit, DN_U16 skip); +DN_API DN_StackTraceFrameSlice DN_StackTraceGetFrames (DN_Arena *arena, DN_U16 limit); +DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame (DN_Arena *arena, DN_StackTraceRawFrame raw_frame); +DN_API void DN_StackTracePrint (DN_U16 limit); +DN_API void DN_StackTraceReloadSymbols (); +#endif #endif // !defined(DN_BASE_H) diff --git a/Source/Base/dn_base_assert.h b/Source/Base/dn_base_assert.h index fc28428..85793d3 100644 --- a/Source/Base/dn_base_assert.h +++ b/Source/Base/dn_base_assert.h @@ -1,15 +1,15 @@ #if !defined(DN_BASE_ASSERT_H) #define DN_BASE_ASSERT_H -#define DN_HardAssertF(expr, fmt, ...) \ - do { \ - if (!(expr)) { \ +#define DN_HardAssertF(expr, fmt, ...) \ + do { \ + if (!(expr)) { \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ - DN_LOG_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ - DN_Str8PrintFmt(stack_trace_), \ - ##__VA_ARGS__); \ - DN_DebugBreak; \ - } \ + DN_LogErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ + DN_Str8PrintFmt(stack_trace_), \ + ##__VA_ARGS__); \ + DN_DebugBreak; \ + } \ } while (0) #define DN_HardAssert(expr) DN_HardAssertF(expr, "") @@ -33,7 +33,7 @@ do { \ if (!(expr)) { \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ - DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ + DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ DN_Str8PrintFmt(stack_trace_), \ ##__VA_ARGS__); \ DN_DebugBreak; \ @@ -46,7 +46,7 @@ if (!(expr) && once) { \ once = false; \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ - DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ + DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ DN_Str8PrintFmt(stack_trace_), \ ##__VA_ARGS__); \ DN_DebugBreak; \ @@ -68,10 +68,10 @@ #define DN_Check(expr) DN_CheckF(expr, "") #if defined(DN_NO_CHECK_BREAK) #define DN_CheckF(expr, fmt, ...) \ - ((expr) ? true : (DN_LOG_WarningF(fmt, ##__VA_ARGS__), false)) + ((expr) ? true : (DN_LogWarningF(fmt, ##__VA_ARGS__), false)) #else #define DN_CheckF(expr, fmt, ...) \ - ((expr) ? true : (DN_LOG_ErrorF(fmt, ##__VA_ARGS__), DN_StackTracePrint(128 /*limit*/), DN_DebugBreak, false)) + ((expr) ? true : (DN_LogErrorF(fmt, ##__VA_ARGS__), DN_StackTracePrint(128 /*limit*/), DN_DebugBreak, false)) #endif #endif diff --git a/Source/Base/dn_base_compiler.h b/Source/Base/dn_base_compiler.h deleted file mode 100644 index efd33da..0000000 --- a/Source/Base/dn_base_compiler.h +++ /dev/null @@ -1,160 +0,0 @@ -#if !defined(DN_BASE_COMPILER_H) -#define DN_BASE_COMPILER_H - -// NOTE: Compiler identification -// Warning! Order is important here, clang-cl on Windows defines _MSC_VER -#if defined(_MSC_VER) - #if defined(__clang__) - #define DN_COMPILER_CLANG_CL - #define DN_COMPILER_CLANG - #else - #define DN_COMPILER_MSVC - #endif -#elif defined(__clang__) - #define DN_COMPILER_CLANG -#elif defined(__GNUC__) - #define DN_COMPILER_GCC -#endif - -// NOTE: __has_feature -// MSVC for example does not support the feature detection macro for instance so we compile it out -#if defined(__has_feature) - #define DN_HAS_FEATURE(expr) __has_feature(expr) -#else - #define DN_HAS_FEATURE(expr) 0 -#endif - -// NOTE: __has_builtin -// MSVC for example does not support the feature detection macro for instance so we compile it out -#if defined(__has_builtin) - #define DN_HAS_BUILTIN(expr) __has_builtin(expr) -#else - #define DN_HAS_BUILTIN(expr) 0 -#endif - -// NOTE: Warning suppression macros -#if defined(DN_COMPILER_MSVC) - #define DN_MSVC_WARNING_PUSH __pragma(warning(push)) - #define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__)) - #define DN_MSVC_WARNING_POP __pragma(warning(pop)) -#else - #define DN_MSVC_WARNING_PUSH - #define DN_MSVC_WARNING_DISABLE(...) - #define DN_MSVC_WARNING_POP -#endif - -#if defined(DN_COMPILER_CLANG) || defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG_CL) - #define DN_GCC_WARNING_PUSH _Pragma("GCC diagnostic push") - #define DN_GCC_WARNING_DISABLE_HELPER_0(x) #x - #define DN_GCC_WARNING_DISABLE_HELPER_1(y) DN_GCC_WARNING_DISABLE_HELPER_0(GCC diagnostic ignored #y) - #define DN_GCC_WARNING_DISABLE(warning) _Pragma(DN_GCC_WARNING_DISABLE_HELPER_1(warning)) - #define DN_GCC_WARNING_POP _Pragma("GCC diagnostic pop") -#else - #define DN_GCC_WARNING_PUSH - #define DN_GCC_WARNING_DISABLE(...) - #define DN_GCC_WARNING_POP -#endif - -// NOTE: Host OS identification -#if defined(_WIN32) - #define DN_OS_WIN32 -#elif defined(__gnu_linux__) || defined(__linux__) - #define DN_OS_UNIX -#endif - -// NOTE: Platform identification -#if !defined(DN_PLATFORM_EMSCRIPTEN) && \ - !defined(DN_PLATFORM_POSIX) && \ - !defined(DN_PLATFORM_WIN32) - #if defined(__aarch64__) || defined(_M_ARM64) - #define DN_PLATFORM_ARM64 - #elif defined(__EMSCRIPTEN__) - #define DN_PLATFORM_EMSCRIPTEN - #elif defined(DN_OS_WIN32) - #define DN_PLATFORM_WIN32 - #else - #define DN_PLATFORM_POSIX - #endif -#endif - -// NOTE: Windows crap -#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) - #if defined(_CRT_SECURE_NO_WARNINGS) - #define DN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED - #else - #define _CRT_SECURE_NO_WARNINGS - #endif -#endif - -// NOTE: Force Inline -#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) - #define DN_FORCE_INLINE __forceinline -#else - #define DN_FORCE_INLINE inline __attribute__((always_inline)) -#endif - -// NOTE: Function/Variable Annotations -#if defined(DN_STATIC_API) - #define DN_API static -#else - #define DN_API -#endif - -// NOTE: C/CPP Literals -// Declare struct literals that work in both C and C++ because the syntax is different between -// languages. -#if 0 - struct Foo { int a; } - struct Foo foo = DN_LITERAL(Foo){32}; // Works on both C and C++ -#endif - -#if defined(__cplusplus) - #define DN_Literal(T) T -#else - #define DN_Literal(T) (T) -#endif - -// NOTE: Thread Locals -#if defined(__cplusplus) - #define DN_THREAD_LOCAL thread_local -#else - #define DN_THREAD_LOCAL _Thread_local -#endif - -// NOTE: C variadic argument annotations -// TODO: Other compilers -#if defined(DN_COMPILER_MSVC) - #define DN_FMT_ATTRIB _Printf_format_string_ -#else - #define DN_FMT_ATTRIB -#endif - -// NOTE: Type Cast -#define DN_Cast(val) (val) - -// NOTE: Zero initialisation macro -#if defined(__cplusplus) - #define DN_ZeroInit {} -#else - #define DN_ZeroInit {0} -#endif - -// NOTE: Address sanitizer -#if !defined(DN_ASAN_POISON) - #define DN_ASAN_POISON 0 -#endif - -#if !defined(DN_ASAN_VET_POISON) - #define DN_ASAN_VET_POISON 0 -#endif - -#define DN_ASAN_POISON_ALIGNMENT 8 - -#if !defined(DN_ASAN_POISON_GUARD_SIZE) - #define DN_ASAN_POISON_GUARD_SIZE 128 -#endif - -#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) - #include -#endif -#endif // !defined(DN_BASE_COMPILER_H) diff --git a/Source/Base/dn_base_containers.cpp b/Source/Base/dn_base_containers.cpp index 0afcc74..3efeb4b 100644 --- a/Source/Base/dn_base_containers.cpp +++ b/Source/Base/dn_base_containers.cpp @@ -3,7 +3,17 @@ #include "../dn.h" #endif -DN_API void *DN_CArray2_InsertArray(void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count) +DN_API void *DN_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) { + *slice_size_field = size; + } + return result; +} + +DN_API void *DN_CArrayInsertArray(void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count) { void *result = nullptr; if (!data || !size || !items || count <= 0 || ((*size + count) > max)) @@ -24,7 +34,37 @@ DN_API void *DN_CArray2_InsertArray(void *data, DN_USize *size, DN_USize max, DN return result; } -DN_API DN_ArrayEraseResult DN_CArray2_EraseRange(void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase) +DN_API void *DN_CArrayPopFront(void *data, DN_USize *size, DN_USize elem_size, DN_USize count) +{ + if (!data || !size || *size == 0 || count == 0) + return nullptr; + + DN_USize pop_count = DN_Min(count, *size); + void *result = data; + + if (pop_count < *size) { + char *src = DN_Cast(char *)data + (pop_count * elem_size); + char *dest = DN_Cast(char *)data; + DN_USize bytes_to_move = (*size - pop_count) * elem_size; + DN_Memmove(dest, src, bytes_to_move); + } + + *size -= pop_count; + return result; +} + +DN_API void *DN_CArrayPopBack(void *data, DN_USize *size, DN_USize elem_size, DN_USize count) +{ + if (!data || !size || *size == 0 || count == 0) + return nullptr; + + DN_USize pop_count = DN_Min(count, *size); + *size -= pop_count; + + return DN_Cast(char *)data + (*size * elem_size); +} + +DN_API DN_ArrayEraseResult DN_CArrayEraseRange(void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase) { DN_ArrayEraseResult result = {}; if (!data || !size || *size == 0 || count == 0) @@ -33,9 +73,12 @@ DN_API DN_ArrayEraseResult DN_CArray2_EraseRange(void *data, DN_USize *size, DN_ // Compute the range to erase DN_USize start = 0, end = 0; if (count < 0) { + // Erase backwards from begin_index, inclusive of begin_index + // Range: [begin_index + count + 1, begin_index + 1) + // Which is: [begin_index - abs(count) + 1, begin_index + 1) DN_USize abs_count = DN_Abs(count); - start = begin_index >= abs_count ? begin_index - abs_count + 1 : 0; - end = begin_index >= abs_count ? begin_index + 1 : 0; + start = (begin_index + 1 > abs_count) ? (begin_index + 1 - abs_count) : 0; + end = begin_index + 1; } else { start = begin_index; end = begin_index + count; @@ -67,7 +110,7 @@ DN_API DN_ArrayEraseResult DN_CArray2_EraseRange(void *data, DN_USize *size, DN_ return result; } -DN_API void *DN_CArray2_MakeArray(void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem) +DN_API void *DN_CArrayMakeArray(void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem) { void *result = nullptr; DN_USize new_size = *size + make_size; @@ -81,9 +124,9 @@ DN_API void *DN_CArray2_MakeArray(void *data, DN_USize *size, DN_USize max, DN_U return result; } -DN_API void *DN_CArray2_AddArray(void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add) +DN_API void *DN_CArrayAddArray(void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add) { - void *result = DN_CArray2_MakeArray(data, size, max, data_size, elems_count, DN_ZMem_No); + void *result = DN_CArrayMakeArray(data, size, max, data_size, elems_count, DN_ZMem_No); if (result) { if (add == DN_ArrayAdd_Append) { DN_Memcpy(result, elems, elems_count * data_size); @@ -97,7 +140,7 @@ DN_API void *DN_CArray2_AddArray(void *data, DN_USize *size, DN_USize max, DN_US return result; } -DN_API bool DN_CArray2_ResizeFromPool(void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max) +DN_API bool DN_CArrayResizeFromPool(void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max) { bool result = true; if (new_max != *max) { @@ -118,26 +161,26 @@ DN_API bool DN_CArray2_ResizeFromPool(void **data, DN_USize *size, DN_USize *max return result; } -DN_API bool DN_CArray2_GrowFromPool(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max) +DN_API bool DN_CArrayGrowFromPool(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max) { bool result = true; if (new_max > *max) - result = DN_CArray2_ResizeFromPool(data, &size, max, data_size, pool, new_max); + result = DN_CArrayResizeFromPool(data, &size, max, data_size, pool, new_max); return result; } -DN_API bool DN_CArray2_GrowIfNeededFromPool(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize add_count) +DN_API bool DN_CArrayGrowIfNeededFromPool(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize add_count) { bool result = true; DN_USize new_size = size + add_count; if (new_size > *max) { DN_USize new_max = DN_Max(DN_Max(*max * 2, new_size), 8); - result = DN_CArray2_ResizeFromPool(data, &size, max, data_size, pool, new_max); + result = DN_CArrayResizeFromPool(data, &size, max, data_size, pool, new_max); } return result; } -DN_API void *DN_CSLList_Detach(void **link, void **next) +DN_API void *DN_SinglyLLDetach(void **link, void **next) { void *result = *link; if (*link) { @@ -147,7 +190,7 @@ DN_API void *DN_CSLList_Detach(void **link, void **next) return result; } -DN_API bool DN_Ring_HasSpace(DN_Ring const *ring, DN_U64 size) +DN_API bool DN_RingHasSpace(DN_Ring const *ring, DN_U64 size) { DN_U64 avail = ring->write_pos - ring->read_pos; DN_U64 space = ring->size - avail; @@ -155,14 +198,14 @@ DN_API bool DN_Ring_HasSpace(DN_Ring const *ring, DN_U64 size) return result; } -DN_API bool DN_Ring_HasData(DN_Ring const *ring, DN_U64 size) +DN_API bool DN_RingHasData(DN_Ring const *ring, DN_U64 size) { DN_U64 data = ring->write_pos - ring->read_pos; bool result = data >= size; return result; } -DN_API void DN_Ring_Write(DN_Ring *ring, void const *src, DN_U64 src_size) +DN_API void DN_RingWrite(DN_Ring *ring, void const *src, DN_U64 src_size) { DN_Assert(src_size <= ring->size); DN_U64 offset = ring->write_pos % ring->size; @@ -176,7 +219,7 @@ DN_API void DN_Ring_Write(DN_Ring *ring, void const *src, DN_U64 src_size) ring->write_pos += src_size; } -DN_API void DN_Ring_Read(DN_Ring *ring, void *dest, DN_U64 dest_size) +DN_API void DN_RingRead(DN_Ring *ring, void *dest, DN_U64 dest_size) { DN_Assert(dest_size <= ring->size); DN_U64 offset = ring->read_pos % ring->size; @@ -188,501 +231,11 @@ DN_API void DN_Ring_Read(DN_Ring *ring, void *dest, DN_U64 dest_size) ring->read_pos += dest_size; } -// NOTE: DN_CArray ///////////////////////////////////////////////////////////////////////////////// -template -DN_ArrayEraseResult DN_CArray_EraseRange(T *data, DN_USize *size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase) -{ - DN_ArrayEraseResult result = {}; - if (!data || !size || *size == 0 || count == 0) - return result; - - DN_AssertF(count != -1, "There's a bug with negative element erases, see the DN_VArray section in dn_docs.cpp"); - - // NOTE: Caculate the end index of the erase range - DN_ISize abs_count = DN_Abs(count); - DN_USize end_index = 0; - if (count < 0) { - end_index = begin_index - (abs_count - 1); - if (end_index > begin_index) - end_index = 0; - } else { - end_index = begin_index + (abs_count - 1); - if (end_index < begin_index) - end_index = (*size) - 1; - } - - // NOTE: Ensure begin_index < one_past_end_index - if (end_index < begin_index) { - DN_USize tmp = begin_index; - begin_index = end_index; - end_index = tmp; - } - - // NOTE: Ensure indexes are within valid bounds - begin_index = DN_Min(begin_index, *size); - end_index = DN_Min(end_index, *size - 1); - - // NOTE: Erase the items in the range [begin_index, one_past_end_index) - DN_USize one_past_end_index = end_index + 1; - DN_USize erase_count = one_past_end_index - begin_index; - if (erase_count) { - T *end = data + *size; - T *dest = data + begin_index; - if (erase == DN_ArrayErase_Stable) { - T *src = dest + erase_count; - DN_Memmove(dest, src, (end - src) * sizeof(T)); - } else { - T *src = end - erase_count; - DN_Memcpy(dest, src, (end - src) * sizeof(T)); - } - *size -= erase_count; - } - - result.items_erased = erase_count; - result.it_index = begin_index; - return result; -} - -template -T *DN_CArray_MakeArray(T *data, DN_USize *size, DN_USize max, DN_USize count, DN_ZMem z_mem) -{ - if (!data || !size || count == 0) - return nullptr; - - if (!DN_CheckF((*size + count) <= max, "Array is out of space (user requested +%zu items, array has %zu/%zu items)", count, *size, max)) - return nullptr; - - // TODO: Use placement new? Why doesn't this work? - T *result = data + *size; - *size += count; - if (z_mem == DN_ZMem_Yes) - DN_Memset(result, 0, sizeof(*result) * count); - return result; -} - -template -T *DN_CArray_InsertArray(T *data, DN_USize *size, DN_USize max, DN_USize index, T const *items, DN_USize count) -{ - T *result = nullptr; - if (!data || !size || !items || count <= 0 || ((*size + count) > max)) - return result; - - DN_USize clamped_index = DN_Min(index, *size); - if (clamped_index != *size) { - char const *src = DN_Cast(char *)(data + clamped_index); - char const *dest = DN_Cast(char *)(data + (clamped_index + count)); - char const *end = DN_Cast(char *)(data + (*size)); - DN_USize bytes_to_move = end - src; - DN_Memmove(DN_Cast(void *) dest, src, bytes_to_move); - } - - result = data + clamped_index; - DN_Memcpy(result, items, sizeof(T) * count); - *size += count; - return result; -} - -template -T DN_CArray_PopFront(T *data, DN_USize *size, DN_USize count) -{ - T result = {}; - if (!data || !size || *size <= 0) - return result; - - result = data[0]; - DN_USize pop_count = DN_Min(count, *size); - DN_Memmove(data, data + pop_count, (*size - pop_count) * sizeof(T)); - *size -= pop_count; - return result; -} - -template -T DN_CArray_PopBack(T *data, DN_USize *size, DN_USize count) -{ - T result = {}; - if (!data || !size || *size <= 0) - return result; - - DN_USize pop_count = DN_Min(count, *size); - result = data[(*size - 1)]; - *size -= pop_count; - return result; -} - -template -DN_ArrayFindResult DN_CArray_Find(T *data, DN_USize size, T const &value) -{ - DN_ArrayFindResult result = {}; - if (!data || size <= 0) - return result; - - for (DN_USize index = 0; !result.data && index < size; index++) { - T *item = data + index; - if (*item == value) { - result.data = item; - result.index = index; - } - } - - return result; -} - -#if !defined(DN_NO_SARRAY) -// NOTE: DN_SArray ///////////////////////////////////////////////////////////////////////////////// -template -DN_SArray DN_SArray_Init(DN_Arena *arena, DN_USize size, DN_ZMem z_mem) -{ - DN_SArray result = {}; - if (!arena || !size) - return result; - result.data = DN_ArenaNewArray(arena, T, size, z_mem); - if (result.data) - result.max = size; - return result; -} - -template -DN_SArray DN_SArray_InitSlice(DN_Arena *arena, DN_Slice slice, DN_USize size, DN_ZMem z_mem) -{ - DN_USize max = DN_Max(slice.size, size); - DN_SArray result = DN_SArray_Init(arena, max, DN_ZMem_No); - if (DN_SArray_IsValid(&result)) { - DN_SArray_AddArray(&result, slice.data, slice.size); - if (z_mem == DN_ZMem_Yes) - DN_Memset(result.data + result.size, 0, (result.max - result.size) * sizeof(T)); - } - return result; -} - -template -DN_SArray DN_SArray_InitCArray(DN_Arena *arena, T const (&array)[N], DN_USize size, DN_ZMem z_mem) -{ - DN_SArray result = DN_SArray_InitSlice(arena, DN_Slice_Init(DN_Cast(T *) array, N), size, z_mem); - return result; -} - -template -DN_SArray DN_SArray_InitBuffer(T *buffer, DN_USize size) -{ - DN_SArray result = {}; - result.data = buffer; - result.max = size; - return result; -} - -template -bool DN_SArray_IsValid(DN_SArray const *array) -{ - bool result = array && array->data && array->size <= array->max; - return result; -} - -template -DN_Slice DN_SArray_Slice(DN_SArray const *array) -{ - DN_Slice result = {}; - if (array) - result = DN_Slice_Init(DN_Cast(T *) array->data, array->size); - return result; -} - -template -T *DN_SArray_MakeArray(DN_SArray *array, DN_USize count, DN_ZMem z_mem) -{ - if (!DN_SArray_IsValid(array)) - return nullptr; - T *result = DN_CArray_MakeArray(array->data, &array->size, array->max, count, z_mem); - return result; -} - -template -T *DN_SArray_Make(DN_SArray *array, DN_ZMem z_mem) -{ - T *result = DN_SArray_MakeArray(array, 1, z_mem); - return result; -} - -template -T *DN_SArray_AddArray(DN_SArray *array, T const *items, DN_USize count) -{ - T *result = DN_SArray_MakeArray(array, count, DN_ZMem_No); - if (result) - DN_Memcpy(result, items, count * sizeof(T)); - return result; -} - -template -T *DN_SArray_AddCArray(DN_SArray *array, T const (&items)[N]) -{ - T *result = DN_SArray_AddArray(array, items, N); - return result; -} - -template -T *DN_SArray_Add(DN_SArray *array, T const &item) -{ - T *result = DN_SArray_AddArray(array, &item, 1); - return result; -} - -template -T *DN_SArray_InsertArray(DN_SArray *array, DN_USize index, T const *items, DN_USize count) -{ - T *result = nullptr; - if (!DN_SArray_IsValid(array)) - return result; - result = DN_CArray_InsertArray(array->data, &array->size, array->max, index, items, count); - return result; -} - -template -T *DN_SArray_InsertCArray(DN_SArray *array, DN_USize index, T const (&items)[N]) -{ - T *result = DN_SArray_InsertArray(array, index, items, N); - return result; -} - -template -T *DN_SArray_Insert(DN_SArray *array, DN_USize index, T const &item) -{ - T *result = DN_SArray_InsertArray(array, index, &item, 1); - return result; -} - -template -T DN_SArray_PopFront(DN_SArray *array, DN_USize count) -{ - T result = DN_CArray_PopFront(array->data, &array->size, count); - return result; -} - -template -T DN_SArray_PopBack(DN_SArray *array, DN_USize count) -{ - T result = DN_CArray_PopBack(array->data, &array->size, count); - return result; -} - -template -DN_ArrayEraseResult DN_SArray_EraseRange(DN_SArray *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase) -{ - DN_ArrayEraseResult result = {}; - if (!DN_SArray_IsValid(array) || array->size == 0 || count == 0) - return result; - result = DN_CArray_EraseRange(array->data, &array->size, begin_index, count, erase); - return result; -} - -template -void DN_SArray_Clear(DN_SArray *array) -{ - if (array) - array->size = 0; -} -#endif // !defined(DN_NO_SARRAY) - -#if !defined(DN_NO_FARRAY) -// NOTE: DN_FArray ///////////////////////////////////////////////////////////////////////////////// -template -DN_FArray DN_FArray_Init(T const *array, DN_USize count) -{ - DN_FArray result = {}; - bool added = DN_FArray_AddArray(&result, array, count); - DN_Assert(added); - return result; -} - -template -DN_FArray DN_FArray_InitSlice(DN_Slice slice) -{ - DN_FArray result = DN_FArray_Init(slice.data, slice.size); - return result; -} - -template -DN_FArray DN_FArray_InitCArray(T const (&items)[K]) -{ - DN_FArray result = DN_FArray_Init(items, K); - return result; -} - -template -bool DN_FArray_IsValid(DN_FArray const *array) -{ - bool result = array && array->size <= DN_ArrayCountU(array->data); - return result; -} - -template -DN_Slice DN_FArray_Slice(DN_FArray const *array) -{ - DN_Slice result = {}; - if (array) - result = DN_Slice_Init(DN_Cast(T *) array->data, array->size); - return result; -} - -template -T *DN_FArray_AddArray(DN_FArray *array, T const *items, DN_USize count) -{ - T *result = DN_FArray_MakeArray(array, count, DN_ZMem_No); - if (result) - DN_Memcpy(result, items, count * sizeof(T)); - return result; -} - -template -T *DN_FArray_AddCArray(DN_FArray *array, T const (&items)[K]) -{ - T *result = DN_FArray_MakeArray(array, K, DN_ZMem_No); - if (result) - DN_Memcpy(result, items, K * sizeof(T)); - return result; -} - -template -T *DN_FArray_Add(DN_FArray *array, T const &item) -{ - T *result = DN_FArray_AddArray(array, &item, 1); - return result; -} - -template -T *DN_FArray_MakeArray(DN_FArray *array, DN_USize count, DN_ZMem z_mem) -{ - if (!DN_FArray_IsValid(array)) - return nullptr; - T *result = DN_CArray_MakeArray(array->data, &array->size, N, count, z_mem); - return result; -} - -template -T *DN_FArray_Make(DN_FArray *array, DN_ZMem z_mem) -{ - T *result = DN_FArray_MakeArray(array, 1, z_mem); - return result; -} - -template -T *DN_FArray_InsertArray(DN_FArray *array, DN_USize index, T const *items, DN_USize count) -{ - T *result = nullptr; - if (!DN_FArray_IsValid(array)) - return result; - result = DN_CArray_InsertArray(array->data, &array->size, N, index, items, count); - return result; -} - -template -T *DN_FArray_InsertCArray(DN_FArray *array, DN_USize index, T const (&items)[K]) -{ - T *result = DN_FArray_InsertArray(array, index, items, K); - return result; -} - -template -T *DN_FArray_Insert(DN_FArray *array, DN_USize index, T const &item) -{ - T *result = DN_FArray_InsertArray(array, index, &item, 1); - return result; -} - -template -T DN_FArray_PopFront(DN_FArray *array, DN_USize count) -{ - T result = DN_CArray_PopFront(array->data, &array->size, count); - return result; -} - -template -T DN_FArray_PopBack(DN_FArray *array, DN_USize count) -{ - T result = DN_CArray_PopBack(array->data, &array->size, count); - return result; -} - -template -DN_ArrayFindResult DN_FArray_Find(DN_FArray *array, T const &find) -{ - DN_ArrayFindResult result = DN_CArray_Find(array->data, array->size, find); - return result; -} - -template -DN_ArrayEraseResult DN_FArray_EraseRange(DN_FArray *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase) -{ - DN_ArrayEraseResult result = {}; - if (!DN_FArray_IsValid(array) || array->size == 0 || count == 0) - return result; - result = DN_CArray_EraseRange(array->data, &array->size, begin_index, count, erase); - return result; -} - -template -void DN_FArray_Clear(DN_FArray *array) -{ - if (array) - array->size = 0; -} -#endif // !defined(DN_NO_FARRAY) - -#if !defined(DN_NO_SLICE) -template -DN_Slice DN_Slice_Init(T *const data, DN_USize size) -{ - DN_Slice result = {}; - if (data) { - result.data = data; - result.size = size; - } - return result; -} - -template -DN_Slice DN_Slice_InitCArrayCopy(DN_Arena *arena, T const (&array)[N]) -{ - DN_Slice result = DN_Slice_Alloc(arena, N, DN_ZMem_No); - if (result.data) - DN_Memcpy(result.data, array, sizeof(T) * N); - return result; -} - -template -DN_Slice DN_Slice_CopyPtr(DN_Arena *arena, T *const data, DN_USize size) -{ - T *copy = DN_ArenaNewArrayCopy(arena, T, data, size); - DN_Slice result = DN_Slice_Init(copy, copy ? size : 0); - return result; -} - -template -DN_Slice DN_Slice_Copy(DN_Arena *arena, DN_Slice slice) -{ - DN_Slice result = DN_Slice_CopyPtr(arena, slice.data, slice.size); - return result; -} - -template -DN_Slice DN_Slice_Alloc(DN_Arena *arena, DN_USize size, DN_ZMem z_mem) -{ - DN_Slice result = {}; - if (!arena || size == 0) - return result; - result.data = DN_ArenaNewArray(arena, T, size, z_mem); - if (result.data) - result.size = size; - return result; -} - -#endif // !defined(DN_NO_SLICE) - -#if !defined(DN_NO_DSMAP) -// NOTE: DN_DSMap ////////////////////////////////////////////////////////////////////////////////// DN_U32 const DN_DS_MAP_DEFAULT_HASH_SEED = 0x8a1ced49; DN_U32 const DN_DS_MAP_SENTINEL_SLOT = 0; template -DN_DSMap DN_DSMap_Init(DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags) +DN_DSMap DN_DSMapInit(DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags) { DN_DSMap result = {}; if (!DN_CheckF(DN_IsPowerOfTwo(size), "Power-of-two size required, given size was '%u'", size)) @@ -704,7 +257,7 @@ DN_DSMap DN_DSMap_Init(DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags) } template -void DN_DSMap_Deinit(DN_DSMap *map, DN_ZMem z_mem) +void DN_DSMapDeinit(DN_DSMap *map, DN_ZMem z_mem) { if (!map) return; @@ -715,7 +268,7 @@ void DN_DSMap_Deinit(DN_DSMap *map, DN_ZMem z_mem) } template -bool DN_DSMap_IsValid(DN_DSMap const *map) +bool DN_DSMapIsValid(DN_DSMap const *map) { bool result = map && map->arena && @@ -727,7 +280,7 @@ bool DN_DSMap_IsValid(DN_DSMap const *map) } template -DN_U32 DN_DSMap_Hash(DN_DSMap const *map, DN_DSMapKey key) +DN_U32 DN_DSMapHash(DN_DSMap const *map, DN_DSMapKey key) { DN_U32 result = 0; if (!map) @@ -806,11 +359,11 @@ DN_U32 DN_DSMap_Hash(DN_DSMap const *map, DN_DSMapKey key) } template -DN_U32 DN_DSMap_HashToSlotIndex(DN_DSMap const *map, DN_DSMapKey key) +DN_U32 DN_DSMapHashToSlotIndex(DN_DSMap const *map, DN_DSMapKey key) { DN_Assert(key.type != DN_DSMapKeyType_Invalid); DN_U32 result = DN_DS_MAP_SENTINEL_SLOT; - if (!DN_DSMap_IsValid(map)) + if (!DN_DSMapIsValid(map)) return result; result = key.hash & (map->size - 1); @@ -830,11 +383,11 @@ DN_U32 DN_DSMap_HashToSlotIndex(DN_DSMap const *map, DN_DSMapKey key) } template -DN_DSMapResult DN_DSMap_Find(DN_DSMap const *map, DN_DSMapKey key) +DN_DSMapResult DN_DSMapFind(DN_DSMap const *map, DN_DSMapKey key) { DN_DSMapResult result = {}; - if (DN_DSMap_IsValid(map)) { - DN_U32 index = DN_DSMap_HashToSlotIndex(map, key); + if (DN_DSMapIsValid(map)) { + DN_U32 index = DN_DSMapHashToSlotIndex(map, key); if (index != DN_DS_MAP_SENTINEL_SLOT && map->hash_to_slot[index] == DN_DS_MAP_SENTINEL_SLOT) { result.slot = map->slots; // NOTE: Set to sentinel value } else { @@ -847,13 +400,13 @@ DN_DSMapResult DN_DSMap_Find(DN_DSMap const *map, DN_DSMapKey key) } template -DN_DSMapResult DN_DSMap_Make(DN_DSMap *map, DN_DSMapKey key) +DN_DSMapResult DN_DSMapMake(DN_DSMap *map, DN_DSMapKey key) { DN_DSMapResult result = {}; - if (!DN_DSMap_IsValid(map)) + if (!DN_DSMapIsValid(map)) return result; - DN_U32 index = DN_DSMap_HashToSlotIndex(map, key); + DN_U32 index = DN_DSMapHashToSlotIndex(map, key); if (map->hash_to_slot[index] == DN_DS_MAP_SENTINEL_SLOT) { // NOTE: Create the slot if (index != DN_DS_MAP_SENTINEL_SLOT) @@ -862,9 +415,9 @@ DN_DSMapResult DN_DSMap_Make(DN_DSMap *map, DN_DSMapKey key) // NOTE: Check if resize is required bool map_is_75pct_full = (map->occupied * 4) > (map->size * 3); if (map_is_75pct_full) { - if (!DN_DSMap_Resize(map, map->size * 2)) + if (!DN_DSMapResize(map, map->size * 2)) return result; - result = DN_DSMap_Make(map, key); + result = DN_DSMapMake(map, key); } else { result.slot = map->slots + map->hash_to_slot[index]; result.slot->key = key; // NOTE: Assign key to new slot @@ -884,69 +437,69 @@ DN_DSMapResult DN_DSMap_Make(DN_DSMap *map, DN_DSMapKey key) } template -DN_DSMapResult DN_DSMap_Set(DN_DSMap *map, DN_DSMapKey key, T const &value) +DN_DSMapResult DN_DSMapSet(DN_DSMap *map, DN_DSMapKey key, T const &value) { DN_DSMapResult result = {}; - if (!DN_DSMap_IsValid(map)) + if (!DN_DSMapIsValid(map)) return result; - result = DN_DSMap_Make(map, key); + result = DN_DSMapMake(map, key); result.slot->value = value; return result; } template -DN_DSMapResult DN_DSMap_FindKeyU64(DN_DSMap const *map, DN_U64 key) +DN_DSMapResult DN_DSMapFindKeyU64(DN_DSMap const *map, DN_U64 key) { - DN_DSMapKey map_key = DN_DSMap_KeyU64(map, key); - DN_DSMapResult result = DN_DSMap_Find(map, map_key); + DN_DSMapKey map_key = DN_DSMapKeyU64(map, key); + DN_DSMapResult result = DN_DSMapFind(map, map_key); return result; } template -DN_DSMapResult DN_DSMap_MakeKeyU64(DN_DSMap *map, DN_U64 key) +DN_DSMapResult DN_DSMapMakeKeyU64(DN_DSMap *map, DN_U64 key) { - DN_DSMapKey map_key = DN_DSMap_KeyU64(map, key); - DN_DSMapResult result = DN_DSMap_Make(map, map_key); + DN_DSMapKey map_key = DN_DSMapKeyU64(map, key); + DN_DSMapResult result = DN_DSMapMake(map, map_key); return result; } template -DN_DSMapResult DN_DSMap_SetKeyU64(DN_DSMap *map, DN_U64 key, T const &value) +DN_DSMapResult DN_DSMapSetKeyU64(DN_DSMap *map, DN_U64 key, T const &value) { - DN_DSMapKey map_key = DN_DSMap_KeyU64(map, key); - DN_DSMapResult result = DN_DSMap_Set(map, map_key, value); + DN_DSMapKey map_key = DN_DSMapKeyU64(map, key); + DN_DSMapResult result = DN_DSMapSet(map, map_key, value); return result; } template -DN_DSMapResult DN_DSMap_FindKeyStr8(DN_DSMap const *map, DN_Str8 key) +DN_DSMapResult DN_DSMapFindKeyStr8(DN_DSMap const *map, DN_Str8 key) { - DN_DSMapKey map_key = DN_DSMap_KeyStr8(map, key); - DN_DSMapResult result = DN_DSMap_Find(map, map_key); + DN_DSMapKey map_key = DN_DSMapKeyStr8(map, key); + DN_DSMapResult result = DN_DSMapFind(map, map_key); return result; } template -DN_DSMapResult DN_DSMap_MakeKeyStr8(DN_DSMap *map, DN_Str8 key) +DN_DSMapResult DN_DSMapMakeKeyStr8(DN_DSMap *map, DN_Str8 key) { - DN_DSMapKey map_key = DN_DSMap_KeyStr8(map, key); - DN_DSMapResult result = DN_DSMap_Make(map, map_key); + DN_DSMapKey map_key = DN_DSMapKeyStr8(map, key); + DN_DSMapResult result = DN_DSMapMake(map, map_key); return result; } template -DN_DSMapResult DN_DSMap_SetKeyStr8(DN_DSMap *map, DN_Str8 key, T const &value) +DN_DSMapResult DN_DSMapSetKeyStr8(DN_DSMap *map, DN_Str8 key, T const &value) { - DN_DSMapKey map_key = DN_DSMap_KeyStr8(map, key); - DN_DSMapResult result = DN_DSMap_Set(map, map_key); + DN_DSMapKey map_key = DN_DSMapKeyStr8(map, key); + DN_DSMapResult result = DN_DSMapSet(map, map_key); return result; } template -bool DN_DSMap_Resize(DN_DSMap *map, DN_U32 size) +bool DN_DSMapResize(DN_DSMap *map, DN_U32 size) { - if (!DN_DSMap_IsValid(map) || size < map->occupied || size < map->initial_size) + if (!DN_DSMapIsValid(map) || size < map->occupied || size < map->initial_size) return false; DN_Arena *prev_arena = map->arena; @@ -957,8 +510,8 @@ bool DN_DSMap_Resize(DN_DSMap *map, DN_U32 size) new_arena.prev = prev_arena->prev; new_arena.next = prev_arena->next; - DN_DSMap new_map = DN_DSMap_Init(&new_arena, size, map->flags); - if (!DN_DSMap_IsValid(&new_map)) + DN_DSMap new_map = DN_DSMapInit(&new_arena, size, map->flags); + if (!DN_DSMapIsValid(&new_map)) return false; new_map.initial_size = map->initial_size; @@ -967,11 +520,11 @@ bool DN_DSMap_Resize(DN_DSMap *map, DN_U32 size) DN_DSMapKey old_key = old_slot->key; if (old_key.type == DN_DSMapKeyType_Invalid) continue; - DN_DSMap_Set(&new_map, old_key, old_slot->value); + DN_DSMapSet(&new_map, old_key, old_slot->value); } if ((map->flags & DN_DSMapFlags_DontFreeArenaOnResize) == 0) - DN_DSMap_Deinit(map, DN_ZMem_No); + DN_DSMapDeinit(map, DN_ZMem_No); *map = new_map; // Update the map inplace map->arena = prev_arena; // Restore the previous arena pointer, it's been de-init-ed *map->arena = new_arena; // Re-init the old arena with the new data @@ -980,12 +533,12 @@ bool DN_DSMap_Resize(DN_DSMap *map, DN_U32 size) } template -bool DN_DSMap_Erase(DN_DSMap *map, DN_DSMapKey key) +bool DN_DSMapErase(DN_DSMap *map, DN_DSMapKey key) { - if (!DN_DSMap_IsValid(map)) + if (!DN_DSMapIsValid(map)) return false; - DN_U32 index = DN_DSMap_HashToSlotIndex(map, key); + DN_U32 index = DN_DSMapHashToSlotIndex(map, key); if (index == 0) return true; @@ -1037,7 +590,7 @@ bool DN_DSMap_Erase(DN_DSMap *map, DN_DSMapKey key) map->slots[slot_index] = *last_slot; // NOTE: Update the hash-to-slot mapping for the value that was copied in - DN_U32 hash_to_slot_index = DN_DSMap_HashToSlotIndex(map, last_slot->key); + DN_U32 hash_to_slot_index = DN_DSMapHashToSlotIndex(map, last_slot->key); map->hash_to_slot[hash_to_slot_index] = slot_index; *last_slot = {}; // TODO: Optional? } @@ -1047,41 +600,41 @@ bool DN_DSMap_Erase(DN_DSMap *map, DN_DSMapKey key) map->occupied--; bool map_is_below_25pct_full = (map->occupied * 4) < (map->size * 1); if (map_is_below_25pct_full && (map->size / 2) >= map->initial_size) - DN_DSMap_Resize(map, map->size / 2); + DN_DSMapResize(map, map->size / 2); return true; } template -bool DN_DSMap_EraseKeyU64(DN_DSMap *map, DN_U64 key) +bool DN_DSMapEraseKeyU64(DN_DSMap *map, DN_U64 key) { - DN_DSMapKey map_key = DN_DSMap_KeyU64(map, key); - bool result = DN_DSMap_Erase(map, map_key); + DN_DSMapKey map_key = DN_DSMapKeyU64(map, key); + bool result = DN_DSMapErase(map, map_key); return result; } template -bool DN_DSMap_EraseKeyStr8(DN_DSMap *map, DN_Str8 key) +bool DN_DSMapEraseKeyStr8(DN_DSMap *map, DN_Str8 key) { - DN_DSMapKey map_key = DN_DSMap_KeyStr8(map, key); - bool result = DN_DSMap_Erase(map, map_key); + DN_DSMapKey map_key = DN_DSMapKeyStr8(map, key); + bool result = DN_DSMapErase(map, map_key); return result; } template -DN_DSMapKey DN_DSMap_KeyBuffer(DN_DSMap const *map, void const *data, DN_USize size) +DN_DSMapKey DN_DSMapKeyBuffer(DN_DSMap const *map, void const *data, DN_USize size) { DN_Assert(size > 0 && size <= UINT32_MAX); DN_DSMapKey result = {}; result.type = DN_DSMapKeyType_Buffer; result.buffer_data = data; result.buffer_size = DN_Cast(DN_U32) size; - result.hash = DN_DSMap_Hash(map, result); + result.hash = DN_DSMapHash(map, result); return result; } template -DN_DSMapKey DN_DSMap_KeyBufferAsU64NoHash(DN_DSMap const *map, void const *data, DN_U32 size) +DN_DSMapKey DN_DSMapKeyBufferAsU64NoHash(DN_DSMap const *map, void const *data, DN_U32 size) { DN_DSMapKey result = {}; result.type = DN_DSMapKeyType_BufferAsU64NoHash; @@ -1093,278 +646,22 @@ DN_DSMapKey DN_DSMap_KeyBufferAsU64NoHash(DN_DSMap const *map, void const *da } template -DN_DSMapKey DN_DSMap_KeyU64(DN_DSMap const *map, DN_U64 u64) +DN_DSMapKey DN_DSMapKeyU64(DN_DSMap const *map, DN_U64 u64) { DN_DSMapKey result = {}; result.type = DN_DSMapKeyType_U64; result.u64 = u64; - result.hash = DN_DSMap_Hash(map, result); + result.hash = DN_DSMapHash(map, result); return result; } template -DN_DSMapKey DN_DSMap_KeyStr8(DN_DSMap const *map, DN_Str8 string) +DN_DSMapKey DN_DSMapKeyStr8(DN_DSMap const *map, DN_Str8 string) { - DN_DSMapKey result = DN_DSMap_KeyBuffer(map, string.data, string.size); - return result; -} -#endif // !defined(DN_NO_DSMAP) - -#if !defined(DN_NO_LIST) -// NOTE: DN_List /////////////////////////////////////////////////////////////////////////////////// -template -DN_List DN_List_Init(DN_USize chunk_size) -{ - DN_List result = {}; - result.chunk_size = chunk_size; + DN_DSMapKey result = DN_DSMapKeyBuffer(map, string.data, string.size); return result; } -template -DN_List DN_List_InitCArray(DN_Arena *arena, DN_USize chunk_size, T const (&array)[N]) -{ - DN_List result = DN_List_Init(arena, chunk_size); - for (DN_ForIndexU(index, N)) - DN_List_Add(&result, array[index]); - return result; -} - -template -DN_List DN_List_InitSliceCopy(DN_Arena *arena, DN_USize chunk_size, DN_Slice slice) -{ - DN_List result = DN_List_Init(arena, chunk_size); - for (DN_ForIndexU(index, slice.size)) - DN_List_Add(&result, slice.data[index]); - return result; -} - -template -DN_API bool DN_List_AttachTail_(DN_List *list, DN_ListChunk *tail) -{ - if (!tail) - return false; - - if (list->tail) { - list->tail->next = tail; - tail->prev = list->tail; - } - - list->tail = tail; - - if (!list->head) - list->head = list->tail; - return true; -} - -template -DN_API DN_ListChunk *DN_List_AllocArena_(DN_List *list, DN_Arena *arena, DN_USize count) -{ - auto *result = DN_ArenaNew(arena, DN_ListChunk, DN_ZMem_Yes); - DN_ArenaTempMem tmem = DN_ArenaTempMemBegin(arena); - if (!result) - return nullptr; - - DN_USize items = DN_Max(list->chunk_size, count); - result->data = DN_ArenaNewArray(arena, T, items, DN_ZMem_Yes); - result->size = items; - if (!result->data) { - DN_ArenaTempMemEnd(tmem); - result = nullptr; - } - - DN_List_AttachTail_(list, result); - return result; -} - -template -DN_API DN_ListChunk *DN_List_AllocPool_(DN_List *list, DN_Pool *pool, DN_USize count) -{ - auto *result = DN_PoolNew(pool, DN_ListChunk); - if (!result) - return nullptr; - - DN_USize items = DN_Max(list->chunk_size, count); - result->data = DN_PoolNewArray(pool, T, items); - result->size = items; - if (!result->data) { - DN_PoolDealloc(result); - result = nullptr; - } - - DN_List_AttachTail_(list, result); - return result; -} - -template -DN_API T *DN_List_MakeArena(DN_List *list, DN_Arena *arena, DN_USize count) -{ - if (list->chunk_size == 0) - list->chunk_size = 128; - - if (!list->tail || (list->tail->count + count) > list->tail->size) { - if (!DN_List_AllocArena_(list, arena, count)) - return nullptr; - } - - T *result = list->tail->data + list->tail->count; - list->tail->count += count; - list->count += count; - return result; -} - -template -DN_API T *DN_List_MakePool(DN_List *list, DN_Pool *pool, DN_USize count) -{ - if (list->chunk_size == 0) - list->chunk_size = 128; - - if (!list->tail || (list->tail->count + count) > list->tail->size) { - if (!DN_List_AllocPool_(list, pool, count)) - return nullptr; - } - - T *result = list->tail->data + list->tail->count; - list->tail->count += count; - list->count += count; - return result; -} - -template -DN_API T *DN_List_AddArena(DN_List *list, DN_Arena *arena, T const &value) -{ - T *result = DN_List_MakeArena(list, arena, 1); - *result = value; - return result; -} - -template -DN_API T *DN_List_AddPool(DN_List *list, DN_Pool *pool, T const &value) -{ - T *result = DN_List_MakePool(list, pool, 1); - *result = value; - return result; -} - -template -DN_API bool DN_List_AddCArray(DN_List *list, T const (&array)[N]) -{ - if (!list) - return false; - for (T const &item : array) - if (!DN_List_Add(list, item)) - return false; - return true; -} - -template -DN_API void DN_List_AddListArena(DN_List *list, DN_Arena *arena, DN_List other) -{ - if (!list) - return; - // TODO(doyle): Copy chunk by chunk - for (DN_ListIterator it = {}; DN_List_Iterate(&other, &it, 0 /*start_index*/);) - DN_List_AddArena(list, arena, *it.data); -} - -template -DN_API void DN_List_AddListPool(DN_List *list, DN_Pool *pool, DN_List other) -{ - if (!list) - return; - // TODO(doyle): Copy chunk by chunk - for (DN_ListIterator it = {}; DN_List_Iterate(&other, &it, 0 /*start_index*/);) - DN_List_AddPool(list, pool, *it.data); -} - -template -void DN_List_Clear(DN_List *list) -{ - if (!list) - return; - list->head = list->tail = nullptr; - list->count = 0; -} - -template -DN_API bool DN_List_Iterate(DN_List *list, DN_ListIterator *it, DN_USize start_index) -{ - bool result = false; - if (!list || !it || list->chunk_size <= 0) - return result; - - if (it->init) { - it->index++; - } else { - *it = {}; - if (start_index == 0) { - it->chunk = list->head; - } else { - DN_List_At(list, start_index, &it->chunk); - if (list->chunk_size > 0) - it->chunk_data_index = start_index % list->chunk_size; - } - - it->init = true; - } - - if (it->chunk) { - if (it->chunk_data_index >= it->chunk->count) { - it->chunk = it->chunk->next; - it->chunk_data_index = 0; - } - - if (it->chunk) { - it->data = it->chunk->data + it->chunk_data_index++; - result = true; - } - } - - if (!it->chunk) - DN_Assert(result == false); - return result; -} - -template -DN_API T *DN_List_At(DN_List *list, DN_USize index, DN_ListChunk **at_chunk) -{ - if (!list || index >= list->count || !list->head) - return nullptr; - - // NOTE: Scan forwards to the chunk we need. We don't have random access to chunks - DN_ListChunk **chunk = &list->head; - DN_USize running_index = index; - for (; (*chunk) && running_index >= (*chunk)->size; chunk = &((*chunk)->next)) - running_index -= (*chunk)->size; - - T *result = nullptr; - if (*chunk) - result = (*chunk)->data + running_index; - - if (result && at_chunk) - *at_chunk = *chunk; - - return result; -} - -template -DN_Slice DN_List_ToSliceCopy(DN_List const *list, DN_Arena *arena) -{ - // TODO(doyle): Chunk memcopies is much faster - DN_Slice result = DN_Slice_Alloc(arena, list->count, DN_ZMem_No); - if (result.size) { - DN_USize slice_index = 0; - DN_MSVC_WARNING_PUSH - DN_MSVC_WARNING_DISABLE(6011) // Dereferencing NULL pointer 'x' - for (DN_ListIterator it = {}; DN_List_Iterate(DN_Cast(DN_List *) list, &it, 0);) - result.data[slice_index++] = *it.data; - DN_MSVC_WARNING_POP - DN_Assert(slice_index == result.size); - } - return result; -} -#endif // !defined(DN_NO_LIST) - -// NOTE: DN_Slice ////////////////////////////////////////////////////////////////////////////////// DN_API DN_Str8 DN_Slice_Str8Render(DN_Arena *arena, DN_Slice array, DN_Str8 separator) { DN_Str8 result = {}; @@ -1441,7 +738,7 @@ DN_API DN_Str16 DN_Slice_Str16RenderSpaceSeparated(DN_Arena *arena, DN_Slice Pointer (to) Array +// LArray => Literal Array +// Define a C array and size. (P) array macros take a pointer to the aray, its size and its max +// capacity. The (L) array macros take the literal array and derives the max capacity +// automatically using DN_ArrayCountU(l_array). +// +// MyStruct buffer[TB_ASType_Count] = {}; +// DN_USize size = 0; +// MyStruct *item_0 = DN_PArrayMake(buffer, &size, DN_ArrayCountU(buffer), DN_ZMem_No); +// MyStruct *item_1 = DN_LArrayMake(buffer, &size, DN_ZMem_No); +// +// IArray => Intrusive Array +// Define a struct with the members `data`, `size` and `max`: +// +// struct MyArray { +// MyStruct *data; +// DN_USize size; +// DN_USize max; +// } my_array = {}; +// MyStruct *item = DN_IArrayMake(&my_array, DN_ZMem_No); +// +// ISinglyLL => Intrusive Singly Linked List +// Define a struct with the members `next`: +// +// struct MyLinkItem { +// int data; +// MyLinkItem *next; +// } my_link = {}; +// +// MyLinkItem *first_item = DN_ISinglyLLDetach(&my_link, MyLinkItem); +// +// DoublyLL => Doubly Linked List +// Define a struct with the members `next` and `prev`. This list has null pointers for head->prev +// and tail->next. +// +// struct MyLinkItem { +// int data; +// MyLinkItem *next; +// MyLinkItem *prev; +// } my_link = {}; +// +// MyLinkItem first_item = {}, second_item = {}; +// DN_DoublyLLAppend(&first_item, &second_item); // first_item -> second_item +// +// SentinelDoublyLL => Sentinel Doubly Linked List +// Uses a sentinel/dummy node as the list head. The sentinel points to itself when empty. +// Define a struct with the members `next` and `prev`: +// +// struct MyLinkItem { +// int data; +// MyLinkItem *next; +// MyLinkItem *prev; +// } my_list = {}; +// +// DN_SentinelDoublyLLInit(&my_list); +// DN_SentinelDoublyLLAppend(&my_list, &new_item); +// DN_SentinelDoublyLLForEach(it, &my_list) { /* ... */ } #if defined(_CLANGD) -#include "../dn.h" + #include "../dn.h" #endif struct DN_Ring @@ -13,7 +75,6 @@ struct DN_Ring DN_U64 read_pos; }; -// NOTE: DN_CArray ///////////////////////////////////////////////////////////////////////////////// enum DN_ArrayErase { DN_ArrayErase_Unstable, @@ -45,42 +106,6 @@ template struct DN_ArrayFindResult DN_USize index; // Index to the value if a match is found, 0 otherwise }; -#if !defined(DN_NO_SARRAY) -// NOTE: DN_SArray ///////////////////////////////////////////////////////////////////////////////// -template struct DN_SArray -{ - T *data; // Pointer to the start of the array items in the block of memory - DN_USize size; // Number of items currently in the array - DN_USize max; // Maximum number of items this array can store - - T *begin() { return data; } - T *end () { return data + size; } - T const *begin() const { return data; } - T const *end () const { return data + size; } -}; -#endif // !defined(DN_NO_SARRAY) - -#if !defined(DN_NO_FARRAY) -// NOTE: DN_FArray ///////////////////////////////////////////////////////////////////////////////// -template struct DN_FArray -{ - T data[N]; // Pointer to the start of the array items in the block of memory - DN_USize size; // Number of items currently in the array - - T *begin() { return data; } - T *end () { return data + size; } - T const *begin() const { return data; } - T const *end () const { return data + size; } -}; - -template using DN_FArray8 = DN_FArray; -template using DN_FArray16 = DN_FArray; -template using DN_FArray32 = DN_FArray; -template using DN_FArray64 = DN_FArray; -#endif // !defined(DN_NO_FARRAY) - -#if !defined(DN_NO_DSMAP) -// NOTE: DN_DSMap ////////////////////////////////////////////////////////////////////////////////// enum DN_DSMapKeyType { // Key | Key Hash | Map Index @@ -136,93 +161,29 @@ template struct DN_DSMapResult DN_DSMapSlot *slot; T *value; }; -#endif // !defined(DN_NO_DSMAP) -#if !defined(DN_NO_LIST) -// NOTE: DN_List /////////////////////////////////////////////////////////////////////////////////// -template struct DN_ListChunk -{ - T *data; - DN_USize size; - DN_USize count; - DN_ListChunk *next; - DN_ListChunk *prev; -}; +#define DN_ISinglyLLDetach(list) (decltype(list))DN_SinglyLLDetach((void **)&(list), (void **)&(list)->next) -template struct DN_ListIterator -{ - DN_B32 init; // True if DN_List_Iterate has been called at-least once on this iterator - DN_ListChunk *chunk; // The chunk that the iterator is reading from - DN_USize chunk_data_index; // The index in the chunk the iterator is referencing - DN_USize index; // The index of the item in the list as if it was flat array - T *data; // Pointer to the data the iterator is referencing. Nullptr if invalid. -}; +#define DN_SentinelDoublyLLInit(list) (list)->next = (list)->prev = (list) +#define DN_SentinelDoublyLLIsSentinel(list, item) ((list) == (item)) +#define DN_SentinelDoublyLLIsEmpty(list) (!(list) || ((list) == (list)->next)) +#define DN_SentinelDoublyLLIsInit(list) ((list)->next && (list)->prev) +#define DN_SentinelDoublyLLHasItems(list) ((list) && ((list) != (list)->next)) +#define DN_SentinelDoublyLLForEach(it, list) auto *it = (list)->next; (it) != (list); (it) = (it)->next -template struct DN_List -{ - DN_USize count; // Cumulative count of all items made across all list chunks - DN_USize chunk_size; // When new ListChunk's are required, the minimum 'data' entries to allocate for that node. - DN_ListChunk *head; - DN_ListChunk *tail; -}; -#endif // !defined(DN_NO_LIST) - -// NOTE: Macros for operating on data structures that are embedded into a C style struct or from a -// set of defined variables from the available scope. Keep it stupid simple, structs and functions. -// Minimal amount of container types with flexible construction leads to less duplicated container -// code and less template meta-programming. -// -// LArray => Literal Array -// Define a C array and size: -// -// ``` -// MyStruct buffer[TB_ASType_Count] = {}; -// DN_USize size = 0; -// MyStruct *item = DN_LArray_Make(buffer, size, DN_ArrayCountU(buffer), DN_ZMem_No); -// ``` -// -// IArray => Intrusive Array -// Define a struct with the members 'data', 'size' and 'max': -// -// ``` -// struct MyArray { -// MyStruct *data; -// DN_USize size; -// DN_USize max; -// } my_array = {}; -// -// MyStruct *item = DN_IArray_Make(&my_array, MyArray, DN_ZMem_No); -// ``` -// ISLList => Intrusive Singly Linked List -// Define a struct with the members 'next': -// -// ``` -// struct MyLinkItem { -// int data; -// MyLinkItem *next; -// } my_link = {}; -// -// MyLinkItem *first_item = DN_ISLList_Detach(&my_link, MyLinkItem); -// ``` - -#define DN_DLList_Init(list) \ - (list)->next = (list)->prev = (list) - -#define DN_DLList_IsSentinel(list, item) ((list) == (item)) - -#define DN_DLList_InitArena(list, T, arena) \ +#define DN_SentinelDoublyLLInitArena(list, T, arena) \ do { \ - (list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \ - DN_DLList_Init(list); \ + (list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \ + DN_SentinelDoublyLLInit(list); \ } while (0) -#define DN_DLList_InitPool(list, T, pool) \ - do { \ - (list) = DN_PoolNew(pool, T); \ - DN_DLList_Init(list); \ +#define DN_SentinelDoublyLLInitPool(list, T, pool) \ + do { \ + (list) = DN_PoolNew(pool, T); \ + DN_SentinelDoublyLLInit(list); \ } while (0) -#define DN_DLList_Detach(item) \ +#define DN_SentinelDoublyLLDetach(item) \ do { \ if (item) { \ (item)->prev->next = (item)->next; \ @@ -232,47 +193,47 @@ template struct DN_List } \ } while (0) -#define DN_DLList_Dequeue(list, dest_ptr) \ - if (DN_DLList_HasItems(list)) { \ - dest_ptr = (list)->next; \ - DN_DLList_Detach(dest_ptr); \ +#define DN_SentinelDoublyLLDequeue(list, dest_ptr) \ + if (DN_SentinelDoublyLLHasItems(list)) { \ + dest_ptr = (list)->next; \ + DN_SentinelDoublyLLDetach(dest_ptr); \ } -#define DN_DLList_Append(list, item) \ - do { \ - if (item) { \ - if ((item)->next) \ - DN_DLList_Detach(item); \ - (item)->next = (list)->next; \ - (item)->prev = (list); \ - (item)->next->prev = (item); \ - (item)->prev->next = (item); \ - } \ +#define DN_SentinelDoublyLLAppend(list, item) \ + do { \ + if (item) { \ + if ((item)->next) \ + DN_SentinelDoublyLLDetach(item); \ + (item)->next = (list)->next; \ + (item)->prev = (list); \ + (item)->next->prev = (item); \ + (item)->prev->next = (item); \ + } \ } while (0) -#define DN_DLList_Prepend(list, item) \ - do { \ - if (item) { \ - if ((item)->next) \ - DN_DLList_Detach(item); \ - (item)->next = (list); \ - (item)->prev = (list)->prev; \ - (item)->next->prev = (item); \ - (item)->prev->next = (item); \ - } \ +#define DN_SentinelDoublyLLPrepend(list, item) \ + do { \ + if (item) { \ + if ((item)->next) \ + DN_SentinelDoublyLLDetach(item); \ + (item)->next = (list); \ + (item)->prev = (list)->prev; \ + (item)->next->prev = (item); \ + (item)->prev->next = (item); \ + } \ } while (0) -#define DN_DLList_IsEmpty(list) \ - (!(list) || ((list) == (list)->next)) - -#define DN_DLList_IsInit(list) \ - ((list)->next && (list)->prev) - -#define DN_DLList_HasItems(list) \ - ((list) && ((list) != (list)->next)) - -#define DN_DLList_ForEach(it, list) \ - auto *it = (list)->next; (it) != (list); (it) = (it)->next +// DoublyLL => Non-intrusive Doubly Linked List +// A simple doubly linked list where each node has `next` and `prev` pointers. +// The head is passed as a pointer-to-pointer to allow head updates. +// +// struct MyLinkItem { +// int data; +// MyLinkItem *next; +// MyLinkItem *prev; +// } *head = nullptr; +// DN_DoublyLLAppend(&head, new_item); +// for (MyLinkItem *it = head; it; it = it->next) { /* ... */ } #define DN_DoublyLLDetach(head, ptr) \ do { \ @@ -317,182 +278,121 @@ template struct DN_List } \ } while (0) -#define DN_ISLList_Detach(list) (decltype(list))DN_CSLList_Detach((void **)&(list), (void **)&(list)->next) +// NOTE: For C++ we need to cast the void* returned in these functions to the concrete type. In C, +// no cast is needed. +#if defined(__cplusplus) + #define DN_CppDeclType(x) decltype(x) +#else + #define DN_CppDeclType +#endif -#define DN_LArray_ResizeFromPool(c_array, size, max, pool, new_max) DN_CArray2_ResizeFromPool((void **)&(c_array), size, max, sizeof((c_array)[0]), pool, new_max) -#define DN_LArray_GrowFromPool(c_array, size, max, pool, new_max) DN_CArray2_GrowFromPool((void **)&(c_array), size, max, sizeof((c_array)[0]), pool, new_max) -#define DN_LArray_GrowIfNeededFromPool(c_array, size, max, pool, add_count) DN_CArray2_GrowIfNeededFromPool((void **)(c_array), size, max, sizeof((c_array)[0]), pool, add_count) -#define DN_LArray_MakeArray(c_array, size, max, count, z_mem) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), count, z_mem) -#define DN_LArray_MakeArrayZ(c_array, size, max, count) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), count, DN_ZMem_Yes) -#define DN_LArray_Make(c_array, size, max, z_mem) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), 1, z_mem) -#define DN_LArray_MakeZ(c_array, size, max) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), 1, DN_ZMem_Yes) -#define DN_LArray_AddArray(c_array, size, max, items, count, add) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, add) -#define DN_LArray_Add(c_array, size, max, item, add) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, add) -#define DN_LArray_AppendArray(c_array, size, max, items, count) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, DN_ArrayAdd_Append) -#define DN_LArray_Append(c_array, size, max, item) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, DN_ArrayAdd_Append) -#define DN_LArray_PrependArray(c_array, size, max, items, count) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, DN_ArrayAdd_Prepend) -#define DN_LArray_Prepend(c_array, size, max, item) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, DN_ArrayAdd_Prepend) -#define DN_LArray_EraseRange(c_array, size, begin_index, count, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), begin_index, count, erase) -#define DN_LArray_Erase(c_array, size, index, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), index, 1, erase) -#define DN_LArray_InsertArray(c_array, size, max, index, items, count) (decltype(&(c_array)[0]))DN_CArray2_InsertArray(c_array, size, max, sizeof((c_array)[0]), index, items, count) -#define DN_LArray_Insert(c_array, size, max, index, item) (decltype(&(c_array)[0]))DN_CArray2_InsertArray(c_array, size, max, sizeof((c_array)[0]), index, &item, 1) +#define DN_PArrayResizeFromPool(ptr, size, max, pool, new_max) DN_CArrayResizeFromPool((void **)&(ptr), size, max, sizeof((ptr)[0]), pool, new_max) +#define DN_PArrayGrowFromPool(ptr, size, max, pool, new_max) DN_CArrayGrowFromPool((void **)&(ptr), size, max, sizeof((ptr)[0]), pool, new_max) +#define DN_PArrayGrowIfNeededFromPool(ptr, size, max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, max, sizeof((ptr)[0]), pool, 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_IArray_ResizeFromPool(array, pool, new_max) DN_CArray2_ResizeFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max) -#define DN_IArray_GrowFromPool(array, pool, new_max) DN_CArray2_GrowFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max) -#define DN_IArray_GrowIfNeededFromPool(array, pool, add_count) DN_CArray2_GrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, add_count) -#define DN_IArray_MakeArray(array, count, z_mem) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, z_mem) -#define DN_IArray_MakeArrayZ(array, count) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, DN_ZMem_Yes) -#define DN_IArray_Make(array, z_mem) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, z_mem) -#define DN_IArray_MakeZ(array) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, DN_ZMem_Yes) -#define DN_IArray_AddArray(array, items, count, add) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, add) -#define DN_IArray_Add(array, item, add) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, add) -#define DN_IArray_AppendArray(array, items, count) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Append) -#define DN_IArray_Append(array, item) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Append) -#define DN_IArray_PrependArray(array, items, count) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Prepend) -#define DN_IArray_Prepend(array, item) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend) -#define DN_IArray_EraseRange(array, begin_index, count, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), begin_index, count, erase) -#define DN_IArray_Erase(array, index, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), index, 1, erase) -#define DN_IArray_InsertArray(array, index, items, count) (decltype(&((array)->data)[0]))DN_CArray2_InsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, items, count) -#define DN_IArray_Insert(array, index, item, count) (decltype(&((array)->data)[0]))DN_CArray2_InsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, &item, 1) +#define DN_LArrayResizeFromPool(c_array, size, pool, new_max) DN_PArrayResizeFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max) +#define DN_LArrayGrowFromPool(c_array, size, pool, new_max) DN_PArrayGrowFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max) +#define DN_LArrayGrowIfNeededFromPool(c_array, size, pool, add_count) DN_PArrayGrowIfNeededFromPool(c_array, size, DN_ArrayCountU(c_array), pool, 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, max) DN_PArrayMakeZ(c_array, size, DN_ArrayCountU(c_array), max) +#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) -DN_API DN_ArrayEraseResult DN_CArray2_EraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); -DN_API void *DN_CArray2_MakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem); -DN_API void *DN_CArray2_AddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add); -DN_API bool DN_CArray2_Resize (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max); -DN_API bool DN_CArray2_Grow (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max); -DN_API bool DN_CArray2_GrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool); -DN_API void *DN_CSLList_Detach (void **link, void **next); +#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_IArrayGrowFromPool(array, pool, new_max) DN_CArrayGrowFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, 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_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) -DN_API bool DN_Ring_HasSpace (DN_Ring const *ring, DN_U64 size); -DN_API bool DN_Ring_HasData (DN_Ring const *ring, DN_U64 size); -DN_API void DN_Ring_Write (DN_Ring *ring, void const *src, DN_U64 src_size); -#define DN_Ring_WriteStruct(ring, item) DN_Ring_Write((ring), (item), sizeof(*(item))) -DN_API void DN_Ring_Read (DN_Ring *ring, void *dest, DN_U64 dest_size); -#define DN_Ring_ReadStruct(ring, dest) DN_Ring_Read((ring), (dest), sizeof(*(dest))) +#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) -template DN_ArrayEraseResult DN_CArray_EraseRange (T *data, DN_USize *size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); -template T * DN_CArray_MakeArray (T *data, DN_USize *size, DN_USize max, DN_USize count, DN_ZMem z_mem); -template T * DN_CArray_InsertArray (T *data, DN_USize *size, DN_USize max, DN_USize index, T const *items, DN_USize count); -template T DN_CArray_PopFront (T *data, DN_USize *size, DN_USize count); -template T DN_CArray_PopBack (T *data, DN_USize *size, DN_USize count); -template DN_ArrayFindResult DN_CArray_Find (T *data, DN_USize size, T const &value); +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); -// NOTE: DN_SArray ///////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_SARRAY) -template DN_SArray DN_SArray_Init (DN_Arena *arena, DN_USize size, DN_ZMem z_mem); -template DN_SArray DN_SArray_InitSlice (DN_Arena *arena, DN_Slice slice, DN_USize size, DN_ZMem z_mem); -template DN_SArray DN_SArray_InitCArray (DN_Arena *arena, T const (&array)[N], DN_USize size, DN_ZMem); -template DN_SArray DN_SArray_InitBuffer (T* buffer, DN_USize size); -template bool DN_SArray_IsValid (DN_SArray const *array); -template DN_Slice DN_SArray_Slice (DN_SArray const *array); -template T * DN_SArray_AddArray (DN_SArray *array, T const *items, DN_USize count); -template T * DN_SArray_AddCArray (DN_SArray *array, T const (&items)[N]); -template T * DN_SArray_Add (DN_SArray *array, T const &item); -#define DN_SArray_AddArrayAssert(...) DN_HardAssert(DN_SArray_AddArray(__VA_ARGS__)) -#define DN_SArray_AddCArrayAssert(...) DN_HardAssert(DN_SArray_AddCArray(__VA_ARGS__)) -#define DN_SArray_AddAssert(...) DN_HardAssert(DN_SArray_Add(__VA_ARGS__)) -template T * DN_SArray_MakeArray (DN_SArray *array, DN_USize count, DN_ZMem z_mem); -template T * DN_SArray_Make (DN_SArray *array, DN_ZMem z_mem); -#define DN_SArray_MakeArrayAssert(...) DN_HardAssert(DN_SArray_MakeArray(__VA_ARGS__)) -#define DN_SArray_MakeAssert(...) DN_HardAssert(DN_SArray_Make(__VA_ARGS__)) -template T * DN_SArray_InsertArray (DN_SArray *array, DN_USize index, T const *items, DN_USize count); -template T * DN_SArray_InsertCArray (DN_SArray *array, DN_USize index, T const (&items)[N]); -template T * DN_SArray_Insert (DN_SArray *array, DN_USize index, T const &item); -#define DN_SArray_InsertArrayAssert(...) DN_HardAssert(DN_SArray_InsertArray(__VA_ARGS__)) -#define DN_SArray_InsertCArrayAssert(...) DN_HardAssert(DN_SArray_InsertCArray(__VA_ARGS__)) -#define DN_SArray_InsertAssert(...) DN_HardAssert(DN_SArray_Insert(__VA_ARGS__)) -template T DN_SArray_PopFront (DN_SArray *array, DN_USize count); -template T DN_SArray_PopBack (DN_SArray *array, DN_USize count); -template DN_ArrayEraseResult DN_SArray_EraseRange (DN_SArray *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); -template void DN_SArray_Clear (DN_SArray *array); -#endif // !defined(DN_NO_SARRAY) +DN_API void* DN_CArrayInsertArray (void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count); +DN_API void* DN_CArrayPopFront (void *data, DN_USize *size, DN_USize elem_size, DN_USize count); +DN_API void* DN_CArrayPopBack (void *data, DN_USize *size, DN_USize elem_size, DN_USize count); +DN_API DN_ArrayEraseResult DN_CArrayEraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); +DN_API void* DN_CArrayMakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem); +DN_API void* DN_CArrayAddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add); +DN_API bool DN_CArrayResizeFromPool (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max); +DN_API bool DN_CArrayGrowFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max); +DN_API bool DN_CArrayGrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool); -#if !defined(DN_NO_FARRAY) -#define DN_FArray_ToSArray(array) DN_SArray_InitBuffer((array)->data, DN_ArrayCountU((array)->data)) -template DN_FArray DN_FArray_Init (T const *array, DN_USize count); -#define DN_FArray_HasData(array) ((array).data && (array).size) -template DN_FArray DN_FArray_InitSlice (DN_Slice slice); -template DN_FArray DN_FArray_InitCArray (T const (&items)[K]); -template bool DN_FArray_IsValid (DN_FArray const *array); -template DN_USize DN_FArray_Max (DN_FArray const *) { return N; } -template DN_Slice DN_FArray_Slice (DN_FArray const *array); -template T * DN_FArray_AddArray (DN_FArray *array, T const *items, DN_USize count); -template T * DN_FArray_AddCArray (DN_FArray *array, T const (&items)[K]); -template T * DN_FArray_Add (DN_FArray *array, T const &item); -#define DN_FArray_AddArrayAssert(...) DN_HardAssert(DN_FArray_AddArray(__VA_ARGS__)) -#define DN_FArray_AddCArrayAssert(...) DN_HardAssert(DN_FArray_AddCArray(__VA_ARGS__)) -#define DN_FArray_AddAssert(...) DN_HardAssert(DN_FArray_Add(__VA_ARGS__)) -template T * DN_FArray_MakeArray (DN_FArray *array, DN_USize count, DN_ZMem z_mem); -template T * DN_FArray_Make (DN_FArray *array, DN_ZMem z_mem); -#define DN_FArray_MakeArrayAssert(...) DN_HardAssert(DN_FArray_MakeArray(__VA_ARGS__)) -#define DN_FArray_MakeAssert(...) DN_HardAssert(DN_FArray_Make(__VA_ARGS__)) -template T * DN_FArray_InsertArray (DN_FArray *array, T const &item, DN_USize index); -template T * DN_FArray_InsertCArray (DN_FArray *array, DN_USize index, T const (&items)[K]); -template T * DN_FArray_Insert (DN_FArray *array, DN_USize index, T const &item); -#define DN_FArray_InsertArrayAssert(...) DN_HardAssert(DN_FArray_InsertArray(__VA_ARGS__)) -#define DN_FArray_InsertAssert(...) DN_HardAssert(DN_FArray_Insert(__VA_ARGS__)) -template T DN_FArray_PopFront (DN_FArray *array, DN_USize count); -template T DN_FArray_PopBack (DN_FArray *array, DN_USize count); -template DN_ArrayFindResult DN_FArray_Find (DN_FArray *array, T const &find); -template DN_ArrayEraseResult DN_FArray_EraseRange (DN_FArray *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); -template void DN_FArray_Clear (DN_FArray *array); -#endif // !defined(DN_NO_FARRAY) +DN_API void* DN_SinglyLLDetach (void **link, void **next); -#if !defined(DN_NO_SLICE) -#define DN_TO_SLICE(val) DN_Slice_Init((val)->data, (val)->size) -#define DN_Slice_InitCArray(array) DN_Slice_Init(array, DN_ArrayCountU(array)) -template DN_Slice DN_Slice_Init (T* const data, DN_USize size); -template DN_Slice DN_Slice_InitCArrayCopy (DN_Arena *arena, T const (&array)[N]); -template DN_Slice DN_Slice_Copy (DN_Arena *arena, DN_Slice slice); -template DN_Slice DN_Slice_CopyPtr (DN_Arena *arena, T* const data, DN_USize size); -template DN_Slice DN_Slice_Alloc (DN_Arena *arena, DN_USize size, DN_ZMem z_mem); - DN_Str8 DN_Slice_Str8Render (DN_Arena *arena, DN_Slice array, DN_Str8 separator); - DN_Str8 DN_Slice_Str8RenderSpaceSeparated (DN_Arena *arena, DN_Slice array); - DN_Str16 DN_Slice_Str16Render (DN_Arena *arena, DN_Slice array, DN_Str16 separator); - DN_Str16 DN_Slice_Str16RenderSpaceSeparated(DN_Arena *arena, DN_Slice array); -#endif // !defined(DN_NO_SLICE) +DN_API bool DN_RingHasSpace (DN_Ring const *ring, DN_U64 size); +DN_API bool DN_RingHasData (DN_Ring const *ring, DN_U64 size); +DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size); +#define DN_RingWriteStruct(ring, item) DN_RingWrite((ring), (item), sizeof(*(item))) +DN_API void DN_RingRead (DN_Ring *ring, void *dest, DN_U64 dest_size); +#define DN_RingReadStruct(ring, dest) DN_RingRead((ring), (dest), sizeof(*(dest))) -#if !defined(DN_NO_DSMAP) -template DN_DSMap DN_DSMap_Init (DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags); -template void DN_DSMap_Deinit (DN_DSMap *map, DN_ZMem z_mem); -template bool DN_DSMap_IsValid (DN_DSMap const *map); -template DN_U32 DN_DSMap_Hash (DN_DSMap const *map, DN_DSMapKey key); -template DN_U32 DN_DSMap_HashToSlotIndex (DN_DSMap const *map, DN_DSMapKey key); -template DN_DSMapResult DN_DSMap_Find (DN_DSMap const *map, DN_DSMapKey key); -template DN_DSMapResult DN_DSMap_Make (DN_DSMap *map, DN_DSMapKey key); -template DN_DSMapResult DN_DSMap_Set (DN_DSMap *map, DN_DSMapKey key, T const &value); -template DN_DSMapResult DN_DSMap_FindKeyU64 (DN_DSMap const *map, DN_U64 key); -template DN_DSMapResult DN_DSMap_MakeKeyU64 (DN_DSMap *map, DN_U64 key); -template DN_DSMapResult DN_DSMap_SetKeyU64 (DN_DSMap *map, DN_U64 key, T const &value); -template DN_DSMapResult DN_DSMap_FindKeyStr8 (DN_DSMap const *map, DN_Str8 key); -template DN_DSMapResult DN_DSMap_MakeKeyStr8 (DN_DSMap *map, DN_Str8 key); -template DN_DSMapResult DN_DSMap_SetKeyStr8 (DN_DSMap *map, DN_Str8 key, T const &value); -template bool DN_DSMap_Resize (DN_DSMap *map, DN_U32 size); -template bool DN_DSMap_Erase (DN_DSMap *map, DN_DSMapKey key); -template bool DN_DSMap_EraseKeyU64 (DN_DSMap *map, DN_U64 key); -template bool DN_DSMap_EraseKeyStr8 (DN_DSMap *map, DN_Str8 key); -template DN_DSMapKey DN_DSMap_KeyBuffer (DN_DSMap const *map, void const *data, DN_U32 size); -template DN_DSMapKey DN_DSMap_KeyBufferAsU64NoHash (DN_DSMap const *map, void const *data, DN_U32 size); -template DN_DSMapKey DN_DSMap_KeyU64 (DN_DSMap const *map, DN_U64 u64); -template DN_DSMapKey DN_DSMap_KeyStr8 (DN_DSMap const *map, DN_Str8 string); -#define DN_DSMap_KeyCStr8(map, string) DN_DSMap_KeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1) -DN_API DN_DSMapKey DN_DSMap_KeyU64NoHash (DN_U64 u64); -DN_API bool DN_DSMap_KeyEquals (DN_DSMapKey lhs, DN_DSMapKey rhs); -DN_API bool operator== (DN_DSMapKey lhs, DN_DSMapKey rhs); -#endif // !defined(DN_NO_DSMAP) - -#if !defined(DN_NO_LIST) -template DN_List DN_List_Init (DN_USize chunk_size); -template DN_List DN_List_InitCArray (DN_Arena *arena, DN_USize chunk_size, T const (&array)[N]); -template T * DN_List_At (DN_List *list, DN_USize index, DN_ListChunk **at_chunk); -template void DN_List_Clear (DN_List *list); -template bool DN_List_Iterate (DN_List *list, DN_ListIterator *it, DN_USize start_index); -template T * DN_List_MakeArena (DN_List *list, DN_Arena *arena, DN_USize count); -template T * DN_List_MakePool (DN_List *list, DN_Pool *pool, DN_USize count); -template T * DN_List_AddArena (DN_List *list, DN_Arena *arena, T const &value); -template T * DN_List_AddPool (DN_List *list, DN_Pool *pool, T const &value); -template void DN_List_AddListArena (DN_List *list, DN_Arena *arena, DN_List other); -template void DN_List_AddListArena (DN_List *list, DN_Pool *pool, DN_List other); -template DN_Slice DN_List_ToSliceCopy (DN_List const *list, DN_Arena* arena); -#endif // !defined(DN_NO_LIST) +template DN_DSMap DN_DSMapInit (DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags); +template void DN_DSMapDeinit (DN_DSMap *map, DN_ZMem z_mem); +template bool DN_DSMapIsValid (DN_DSMap const *map); +template DN_U32 DN_DSMapHash (DN_DSMap const *map, DN_DSMapKey key); +template DN_U32 DN_DSMapHashToSlotIndex (DN_DSMap const *map, DN_DSMapKey key); +template DN_DSMapResult DN_DSMapFind (DN_DSMap const *map, DN_DSMapKey key); +template DN_DSMapResult DN_DSMapMake (DN_DSMap *map, DN_DSMapKey key); +template DN_DSMapResult DN_DSMapSet (DN_DSMap *map, DN_DSMapKey key, T const &value); +template DN_DSMapResult DN_DSMapFindKeyU64 (DN_DSMap const *map, DN_U64 key); +template DN_DSMapResult DN_DSMapMakeKeyU64 (DN_DSMap *map, DN_U64 key); +template DN_DSMapResult DN_DSMapSetKeyU64 (DN_DSMap *map, DN_U64 key, T const &value); +template DN_DSMapResult DN_DSMapFindKeyStr8 (DN_DSMap const *map, DN_Str8 key); +template DN_DSMapResult DN_DSMapMakeKeyStr8 (DN_DSMap *map, DN_Str8 key); +template DN_DSMapResult DN_DSMapSetKeyStr8 (DN_DSMap *map, DN_Str8 key, T const &value); +template bool DN_DSMapResize (DN_DSMap *map, DN_U32 size); +template bool DN_DSMapErase (DN_DSMap *map, DN_DSMapKey key); +template bool DN_DSMapEraseKeyU64 (DN_DSMap *map, DN_U64 key); +template bool DN_DSMapEraseKeyStr8 (DN_DSMap *map, DN_Str8 key); +template DN_DSMapKey DN_DSMapKeyBuffer (DN_DSMap const *map, void const *data, DN_U32 size); +template DN_DSMapKey DN_DSMapKeyBufferAsU64NoHash (DN_DSMap const *map, void const *data, DN_U32 size); +template DN_DSMapKey DN_DSMapKeyU64 (DN_DSMap const *map, DN_U64 u64); +template DN_DSMapKey DN_DSMapKeyStr8 (DN_DSMap const *map, DN_Str8 string); +#define DN_DSMapKeyCStr8(map, string) DN_DSMapKeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1) +DN_API DN_DSMapKey DN_DSMapKeyU64NoHash (DN_U64 u64); +DN_API bool DN_DSMapKeyEquals (DN_DSMapKey lhs, DN_DSMapKey rhs); +DN_API bool operator== (DN_DSMapKey lhs, DN_DSMapKey rhs); #endif // !defined(DN_CONTAINER_H) diff --git a/Source/Base/dn_base_leak.cpp b/Source/Base/dn_base_leak.cpp index 1234c2d..12fd748 100644 --- a/Source/Base/dn_base_leak.cpp +++ b/Source/Base/dn_base_leak.cpp @@ -15,12 +15,9 @@ DN_API void DN_LeakTrackAlloc_(DN_LeakTracker *leak, void *ptr, DN_USize size, b DN_TicketMutex_End(&leak->alloc_table_mutex); }; - // NOTE: If the entry was not added, we are reusing a pointer that has been freed. - // TODO: Add API for always making the item but exposing a var to indicate if the item was newly created or it - // already existed. DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/); DN_DSMap *alloc_table = &leak->alloc_table; - DN_DSMapResult alloc_entry = DN_DSMap_MakeKeyU64(alloc_table, DN_Cast(DN_U64) ptr); + DN_DSMapResult alloc_entry = DN_DSMapMakeKeyU64(alloc_table, DN_Cast(DN_U64) ptr); DN_LeakAlloc *alloc = alloc_entry.value; if (alloc_entry.found) { if ((alloc->flags & DN_LeakAllocFlag_Freed) == 0) { @@ -76,7 +73,7 @@ DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr) DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/); DN_DSMap *alloc_table = &leak->alloc_table; - DN_DSMapResult alloc_entry = DN_DSMap_FindKeyU64(alloc_table, DN_Cast(uintptr_t) ptr); + DN_DSMapResult alloc_entry = DN_DSMapFindKeyU64(alloc_table, DN_Cast(uintptr_t) ptr); DN_HardAssertF(alloc_entry.found, "Allocated pointer can not be removed as it does not exist in the " "allocation table. When this memory was allocated, the pointer was " @@ -128,7 +125,7 @@ DN_API void DN_LeakDump_(DN_LeakTracker *leak) leaked_bytes += alloc->size; leak_count++; DN_Str8x32 alloc_size = DN_ByteCountStr8x32(alloc->size); - DN_LOG_WarningF( + DN_LogWarningF( "Pointer (0x%p) leaked %.*s at:\n" "%.*s", alloc->ptr, @@ -139,6 +136,6 @@ DN_API void DN_LeakDump_(DN_LeakTracker *leak) if (leak_count) { DN_Str8x32 leak_size = DN_ByteCountStr8x32(leaked_bytes); - DN_LOG_WarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_Str8PrintFmt(leak_size)); + DN_LogWarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_Str8PrintFmt(leak_size)); } } diff --git a/Source/Base/dn_base_leak.h b/Source/Base/dn_base_leak.h index 08c423f..70a911f 100644 --- a/Source/Base/dn_base_leak.h +++ b/Source/Base/dn_base_leak.h @@ -2,7 +2,7 @@ #define DN_BASE_LEAK_H #if defined(_CLANGD) - #include "../dn_base_inc.h" + #include "../dn.h" #endif enum DN_LeakAllocFlag diff --git a/Source/Base/dn_base_log.cpp b/Source/Base/dn_base_log.cpp deleted file mode 100644 index a818ed6..0000000 --- a/Source/Base/dn_base_log.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#define DN_BASE_LOG_CPP - -#if defined(_CLANDG) -#include "../dn.h" -#endif - -static DN_LOGEmitFromTypeFVFunc *g_dn_base_log_emit_from_type_fv_func_; -static void *g_dn_base_log_emit_from_type_fv_user_context_; - -DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType colour, DN_U8 r, DN_U8 g, DN_U8 b) -{ - DN_THREAD_LOCAL char buffer[32]; - buffer[0] = 0; - DN_Str8 result = {}; - result.size = DN_SNPrintF(buffer, - DN_ArrayCountU(buffer), - "\x1b[%d;2;%u;%u;%um", - colour == DN_LOGColourType_Fg ? 38 : 48, - r, - g, - b); - result.data = buffer; - return result; -} - -DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromU32(DN_LOGColourType colour, DN_U32 value) -{ - DN_U8 r = DN_Cast(DN_U8)(value >> 24); - DN_U8 g = DN_Cast(DN_U8)(value >> 16); - DN_U8 b = DN_Cast(DN_U8)(value >> 8); - DN_Str8 result = DN_LOG_ColourEscapeCodeStr8FromRGB(colour, r, g, b); - return result; -} - -DN_API DN_LOGPrefixSize DN_LOG_MakePrefix(DN_LOGStyle style, DN_LOGTypeParam type, DN_CallSite call_site, DN_LOGDate date, char *dest, DN_USize dest_size) -{ - DN_Str8 type_str8 = type.str8; - if (type.is_u32_enum) { - switch (type.u32) { - case DN_LOGType_Debug: type_str8 = DN_Str8Lit("DEBUG"); break; - case DN_LOGType_Info: type_str8 = DN_Str8Lit("INFO "); break; - case DN_LOGType_Warning: type_str8 = DN_Str8Lit("WARN"); break; - case DN_LOGType_Error: type_str8 = DN_Str8Lit("ERROR"); break; - case DN_LOGType_Count: type_str8 = DN_Str8Lit("BADXX"); break; - } - } - - static DN_USize max_type_length = 0; - max_type_length = DN_Max(max_type_length, type_str8.size); - int type_padding = DN_Cast(int)(max_type_length - type_str8.size); - - DN_Str8 colour_esc = {}; - DN_Str8 bold_esc = {}; - DN_Str8 reset_esc = {}; - if (style.colour) { - bold_esc = DN_Str8Lit(DN_LOG_BoldEscapeCode); - reset_esc = DN_Str8Lit(DN_LOG_ResetEscapeCode); - colour_esc = DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b); - } - - DN_Str8 file_name = DN_Str8FileNameFromPath(call_site.file); - DN_GCC_WARNING_PUSH - DN_GCC_WARNING_DISABLE(-Wformat) - DN_GCC_WARNING_DISABLE(-Wformat-extra-args) - DN_MSVC_WARNING_PUSH - DN_MSVC_WARNING_DISABLE(4477) - int size = DN_SNPrintF(dest, - DN_Cast(int)dest_size, - "%04u-%02u-%02uT%02u:%02u:%02u" // date - "%S" // colour - "%S" // bold - " %S" // type - "%.*s" // type padding - "%S" // reset - " %S" // file name - ":%05I32u " // line number - , - date.year, - date.month, - date.day, - date.hour, - date.minute, - date.second, - colour_esc, // colour - bold_esc, // bold - type_str8, // type - DN_Cast(int) type_padding, - "", // type padding - reset_esc, // reset - file_name, // file name - call_site.line); // line number - DN_MSVC_WARNING_POP // '%S' requires an argument of type 'wchar_t *', but variadic argument 7 has type 'DN_Str8' - DN_GCC_WARNING_POP - - static DN_USize max_header_length = 0; - DN_USize size_no_ansi_codes = size - colour_esc.size - reset_esc.size - bold_esc.size; - max_header_length = DN_Max(max_header_length, size_no_ansi_codes); - DN_USize header_padding = max_header_length - size_no_ansi_codes; - - DN_LOGPrefixSize result = {}; - result.size = size; - result.padding = header_padding; - return result; -} - -DN_API void DN_LOG_SetEmitFromTypeFVFunc(DN_LOGEmitFromTypeFVFunc *print_func, void *user_data) -{ - g_dn_base_log_emit_from_type_fv_func_ = print_func; - g_dn_base_log_emit_from_type_fv_user_context_ = user_data; -} - -DN_API void DN_LOG_EmitFromType(DN_LOGTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) -{ - DN_LOGEmitFromTypeFVFunc *func = g_dn_base_log_emit_from_type_fv_func_; - void *user_context = g_dn_base_log_emit_from_type_fv_user_context_; - if (func) { - va_list args; - va_start(args, fmt); - func(type, user_context, call_site, fmt, args); - va_end(args); - } -} - -DN_API DN_LOGTypeParam DN_LOG_MakeU32LogTypeParam(DN_LOGType type) -{ - DN_LOGTypeParam result = {}; - result.is_u32_enum = true; - result.u32 = type; - return result; -} diff --git a/Source/Base/dn_base_log.h b/Source/Base/dn_base_log.h deleted file mode 100644 index 880a7d9..0000000 --- a/Source/Base/dn_base_log.h +++ /dev/null @@ -1,74 +0,0 @@ -#if !defined(DN_BASE_LOG_H) -#define DN_BASE_LOG_H - -#if defined(_CLANGD) -#include "../dn.h" -#endif - -enum DN_LOGType -{ - DN_LOGType_Debug, - DN_LOGType_Info, - DN_LOGType_Warning, - DN_LOGType_Error, - DN_LOGType_Count, -}; - -enum DN_LOGBold -{ - DN_LOGBold_No, - DN_LOGBold_Yes, -}; - -struct DN_LOGStyle -{ - DN_LOGBold bold; - bool colour; - DN_U8 r, g, b; -}; - -struct DN_LOGTypeParam -{ - bool is_u32_enum; - DN_U32 u32; - DN_Str8 str8; -}; - -enum DN_LOGColourType -{ - DN_LOGColourType_Fg, - DN_LOGColourType_Bg, -}; - -struct DN_LOGDate -{ - DN_U16 year; - DN_U8 month; - DN_U8 day; - - DN_U8 hour; - DN_U8 minute; - DN_U8 second; -}; - -struct DN_LOGPrefixSize -{ - DN_USize size; - DN_USize padding; -}; - -typedef void DN_LOGEmitFromTypeFVFunc(DN_LOGTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); - -#define DN_LOG_ResetEscapeCode "\x1b[0m" -#define DN_LOG_BoldEscapeCode "\x1b[1m" -DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType colour, DN_U8 r, DN_U8 g, DN_U8 b); -DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromU32(DN_LOGColourType colour, DN_U32 value); -DN_API DN_LOGPrefixSize DN_LOG_MakePrefix (DN_LOGStyle style, DN_LOGTypeParam type, DN_CallSite call_site, DN_LOGDate date, char *dest, DN_USize dest_size); -DN_API void DN_LOG_SetEmitFromTypeFVFunc (DN_LOGEmitFromTypeFVFunc *print_func, void *user_data); -DN_API void DN_LOG_EmitFromType (DN_LOGTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); -DN_API DN_LOGTypeParam DN_LOG_MakeU32LogTypeParam (DN_LOGType type); -#define DN_LOG_DebugF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Debug), DN_CALL_SITE, fmt, ##__VA_ARGS__) -#define DN_LOG_InfoF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__) -#define DN_LOG_WarningF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__) -#define DN_LOG_ErrorF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__) -#endif // !defined(DN_BASE_LOG_H) diff --git a/Source/Base/dn_base_os.h b/Source/Base/dn_base_os.h deleted file mode 100644 index c5ef8b4..0000000 --- a/Source/Base/dn_base_os.h +++ /dev/null @@ -1,60 +0,0 @@ -#if !defined(DN_BASE_OS_H) -#define DN_BASE_OS_H - -#if defined(_CLANGD) -#include "../dn.h" -#endif - -// NOTE: OS primitives that the OS layer can provide for the base layer but is optional. - -struct DN_StackTraceFrame -{ - DN_U64 address; - DN_U64 line_number; - DN_Str8 file_name; - DN_Str8 function_name; -}; - -struct DN_StackTraceRawFrame -{ - void *process; - DN_U64 base_addr; -}; - -struct DN_StackTraceWalkResult -{ - void *process; // [Internal] Windows handle to the process - DN_U64 *base_addr; // The addresses of the functions in the stack trace - DN_U16 size; // The number of `base_addr`'s stored from the walk -}; - -struct DN_StackTraceWalkResultIterator -{ - DN_StackTraceRawFrame raw_frame; - DN_U16 index; -}; - - -#if defined(DN_FREESTANDING) -#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A") -#define DN_StackTraceWalk(...) -#define DN_StackTraceWalkResultIterate(...) -#define DN_StackTraceWalkResultToStr8(...) DN_Str8Lit("N/A") -#define DN_StackTraceWalkStr8(...) DN_Str8Lit("N/A") -#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A") -#define DN_StackTraceGetFrames(...) -#define DN_StackTraceRawFrameToFrame(...) -#define DN_StackTracePrint(...) -#define DN_StackTraceReloadSymbols(...) -#else -DN_API DN_StackTraceWalkResult DN_StackTraceWalk (struct DN_Arena *arena, DN_U16 limit); -DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk); -DN_API DN_Str8 DN_StackTraceWalkResultToStr8 (struct DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip); -DN_API DN_Str8 DN_StackTraceWalkStr8 (struct DN_Arena *arena, DN_U16 limit, DN_U16 skip); -DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap (DN_U16 limit, DN_U16 skip); -DN_API DN_Slice DN_StackTraceGetFrames (struct DN_Arena *arena, DN_U16 limit); -DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame (struct DN_Arena *arena, DN_StackTraceRawFrame raw_frame); -DN_API void DN_StackTracePrint (DN_U16 limit); -DN_API void DN_StackTraceReloadSymbols (); -#endif -#endif // !defined(DN_BASE_OS_H) diff --git a/Source/Extra/dn_async.cpp b/Source/Extra/dn_async.cpp index ddf557f..c85098a 100644 --- a/Source/Extra/dn_async.cpp +++ b/Source/Extra/dn_async.cpp @@ -1,8 +1,8 @@ #define DN_ASYNC_CPP #if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" + #define DN_H_WITH_OS 1 + #include "../dn.h" #include "dn_async.h" #endif @@ -18,8 +18,8 @@ static DN_I32 DN_ASYNC_ThreadEntryPoint_(DN_OSThread *thread) DN_ASYNCTask task = {}; for (DN_OS_MutexScope(&async->ring_mutex)) { - if (DN_Ring_HasData(ring, sizeof(task))) - DN_Ring_Read(ring, &task, sizeof(task)); + if (DN_RingHasData(ring, sizeof(task))) + DN_RingRead(ring, &task, sizeof(task)); } if (task.work.func) { @@ -72,8 +72,8 @@ static bool DN_ASYNC_QueueTask_(DN_ASYNCCore *async, DN_ASYNCTask const *task, D bool result = false; for (DN_OS_MutexScope(&async->ring_mutex)) { for (;;) { - if (DN_Ring_HasSpace(&async->ring, sizeof(*task))) { - DN_Ring_WriteStruct(&async->ring, task); + if (DN_RingHasSpace(&async->ring, sizeof(*task))) { + DN_RingWriteStruct(&async->ring, task); result = true; break; } diff --git a/Source/Extra/dn_async.h b/Source/Extra/dn_async.h index 82144a8..0ed17c1 100644 --- a/Source/Extra/dn_async.h +++ b/Source/Extra/dn_async.h @@ -2,8 +2,8 @@ #define DN_ASYNC_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_ASYNCPriority diff --git a/Source/Extra/dn_bin_pack.h b/Source/Extra/dn_bin_pack.h index 3f678dd..b139ad8 100644 --- a/Source/Extra/dn_bin_pack.h +++ b/Source/Extra/dn_bin_pack.h @@ -2,11 +2,7 @@ #define DN_BIN_PACK_H #if defined(_CLANGD) - #include "../dn_base_inc.h" -#endif - -#if !defined(DN_BASE_INC_H) - #error dn_base_inc.h must be included before this + #include "../dn.h" #endif enum DN_BinPackMode diff --git a/Source/Extra/dn_cgen.cpp b/Source/Extra/dn_cgen.cpp index 5f4eb18..0c4d5a1 100644 --- a/Source/Extra/dn_cgen.cpp +++ b/Source/Extra/dn_cgen.cpp @@ -63,7 +63,7 @@ DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST[] DN_CGenTableHeaderType_Name, }; -static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_OSErrSink *err) +static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_ErrSink *err) { bool result = false; if (!cgen || !cgen->file_list || !cgen->arena) @@ -283,7 +283,7 @@ static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_OSErrSink *err) return result; } -DN_API DN_CGen DN_CGen_FromFilesArgV(int argc, char const **argv, DN_OSErrSink *err) +DN_API DN_CGen DN_CGen_FromFilesArgV(int argc, char const **argv, DN_ErrSink *err) { DN_CGen result = {}; result.arena = MD_ArenaAlloc(); @@ -341,7 +341,7 @@ DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_ if (result.enum_val == 0) { MD_CodeLoc loc = MD_CodeLocFromNode(DN_Cast(MD_Node *) node); - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); va_list args; va_start(args, fmt); DN_Str8 user_msg = DN_Str8FromFmtVArena(tmem.arena, fmt, args); @@ -357,6 +357,7 @@ DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_ } DN_Str8 error_msg = DN_Str8BuilderBuild(&builder, tmem.arena); + DN_TCScratchEnd(&tmem); MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Error, DN_Cast(char *) "%.*s", DN_Str8PrintFmt(error_msg)); DN_OS_Exit(DN_Cast(uint32_t) - 1); } @@ -371,13 +372,14 @@ DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node) return result; } -DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err, char const *fmt, ...) +DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_ErrSink *err, char const *fmt, ...) { if (!err) return; - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); - DN_Str8Builder builder = DN_Str8BuilderFromTLS(); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); + DN_Str8Builder builder = {}; + builder.arena = tmem.arena; MD_String8 kind_string = MD_StringFromMessageKind(kind); MD_CodeLoc loc = MD_CodeLocFromNode(node); @@ -388,14 +390,15 @@ DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err, DN_Str8BuilderAppendFV(&builder, fmt, args); va_end(args); - DN_Str8 msg = DN_Str8BuilderBuild(&builder, tmem.arena); + DN_Str8 msg = DN_Str8BuilderBuild(&builder, err->arena); + DN_TCScratchEnd(&tmem); DN_OS_ErrSinkAppendF(err, DN_Cast(uint32_t) - 1, "%.*s", DN_Str8PrintFmt(msg)); } -DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_OSErrSink *err) +DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_ErrSink *err) { bool result = true; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_Str8Builder builder = {}; builder.arena = tmem.arena; @@ -419,6 +422,7 @@ DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *he DN_Str8PrintFmt(missing_headers)); } + DN_TCScratchEnd(&tmem); return result; } @@ -515,13 +519,14 @@ static void DN_CGen_EmitRowWhitespace_(DN_CGenTableRow const *row, DN_CppFile *c if (tag->comment.size <= 0) break; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_Str8 prefix = DN_Str8FromFmtArena(tmem.arena, "// NOTE: %.*s ", MD_S8VArg(tag->comment)); int line_padding = DN_Max(100 - (DN_Cast(int) prefix.size + (DN_CppSpacePerIndent(cpp) * cpp->indent)), 0); DN_CppPrint(cpp, "%.*s", DN_Str8PrintFmt(prefix)); for (int index = 0; index < line_padding; index++) DN_CppAppend(cpp, "/"); DN_CppAppend(cpp, "\n"); + DN_TCScratchEnd(&tmem); } break; case DN_CGenTableRowTagType_EmptyLine: { @@ -533,17 +538,18 @@ static void DN_CGen_EmitRowWhitespace_(DN_CGenTableRow const *row, DN_CppFile *c DN_Str8 DN_CGen_ConvertTemplatesToEmittableLiterals_(DN_Arena *arena, DN_Str8 type) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch tmem = DN_TCScratchBegin(&arena, 1); DN_Str8 result = DN_Str8TrimWhitespaceAround(type); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("<"), /*replace*/ DN_Str8Lit("_"), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(">"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8TrimWhitespaceAround(result); + DN_TCScratchEnd(&tmem); return result; } DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch tmem = DN_TCScratchBegin(&arena, 1); DN_Str8 result = DN_Str8TrimWhitespaceAround(type); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("*"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("constexpr"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); @@ -551,6 +557,7 @@ DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type) result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("static"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(" "), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8TrimWhitespaceAround(result); + DN_TCScratchEnd(&tmem); return result; } @@ -563,9 +570,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil DN_CppLine(cpp, "%.*sType_Nil,", DN_Str8PrintFmt(emit_prefix)); for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string); DN_CppLine(cpp, "%.*sType_%.*s,", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(enum_name)); + DN_TCScratchEnd(&tmem); } DN_CppLine(cpp, "%.*sType_Count,", DN_Str8PrintFmt(emit_prefix)); } @@ -582,9 +590,9 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil case DN_CGenTableType_CodeGenStruct: { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { // TODO(doyle): Verify the codegen table has the headers from the table it references - int longest_type_name = 0; + int longest_type_name = 0; for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_CGenTableRow const *row = it.table->rows + row_index; DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppType].string, row); @@ -594,6 +602,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil length += emit_prefix.size; longest_type_name = DN_Max(longest_type_name, DN_Cast(int) length); + DN_TCScratchEnd(&tmem); } DN_CppStructBlock(cpp, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(it.cgen_table_column[DN_CGenTableHeaderType_Name].string)) @@ -606,8 +615,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil if (cpp_name.column.string.size <= 0 || cpp_type.column.string.size <= 0) continue; - // NOTE: Generate cpp array size /////////////////////////////////// - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + // NOTE: Generate cpp array size + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_Str8 array_size = {}; if (cpp_array_size.column.string.size) array_size = DN_Str8FromFmtArena(tmem.arena, "[%.*s]", DN_Str8PrintFmt(cpp_array_size.column.string)); @@ -620,6 +629,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil if (DN_CGen_WillCodeGenTypeName(cgen, find_name)) emit_cpp_type = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type.column.string)); } + DN_TCScratchEnd(&tmem); int name_to_type_padding = 1 + longest_type_name - DN_Cast(int) emit_cpp_type.size; @@ -803,7 +813,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil // for types that are declared in the same mdesk file. We will also // calculate the longest type name that we will generate for whitespace // padding purposes. - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_USize longest_cpp_type_name = 0; auto cpp_type_list = DN_SArray_Init(tmem.arena, it.table->row_count, DN_ZMem_Yes); @@ -814,7 +824,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil // NOTE: CHeck the length of the string after turning it into emittable code DN_Str8 cpp_type_name = DN_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string); if (DN_CGen_WillCodeGenTypeName(cgen, cpp_type_name)) - cpp_type_name = DN_Str8FromTLSF("%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type_name)); + cpp_type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type_name)); DN_Str8 cpp_type_name_no_templates = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, cpp_type_name); longest_cpp_type_name = DN_Max(longest_cpp_type_name, cpp_type_name_no_templates.size); @@ -849,7 +859,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil index_the_field_references = sub_row_index; } cpp_array_size_field_str8 = - DN_Str8FromTLSF("&g_%.*s%.*s_type_fields[%zu]", + DN_Str8FromFmtArena(tmem.arena, "&g_%.*s%.*s_type_fields[%zu]", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(struct_name.string), index_the_field_references); @@ -862,7 +872,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; DN_USize cpp_type_padding = 1 + longest_cpp_type_name - cpp_type_name.size; - DN_Str8 cpp_type_enum = DN_Str8FromTLSF("%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(orig_cpp_type_no_templates)); + DN_Str8 cpp_type_enum = DN_Str8FromFmtArena(tmem.arena, "%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(orig_cpp_type_no_templates)); DN_USize cpp_type_enum_padding = cpp_type_padding + (orig_cpp_type.size - cpp_type_name.size); DN_Str8 cpp_label_str8 = cpp_name.column.string; @@ -960,10 +970,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil if (cpp_name.column.string.size <= 0) continue; - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; - DN_Str8 cpp_value_str8 = cpp_value.column.string.size ? cpp_value.column.string : DN_Str8FromTLSF("%zu", row_index); - DN_Str8 cpp_type_enum = DN_Str8FromTLSF("%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(struct_or_enum_name)); + DN_Str8 cpp_value_str8 = cpp_value.column.string.size ? cpp_value.column.string : DN_Str8FromFmtArena(tmem.arena, "%zu", row_index); + DN_Str8 cpp_type_enum = DN_Str8FromFmtArena(tmem.arena, "%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(struct_or_enum_name)); DN_Str8 cpp_label_str8 = cpp_name.column.string; DN_USize cpp_label_str8_padding = cpp_name_padding; @@ -972,7 +982,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil cpp_label_str8_padding = 1 + it.table->headers[cpp_label.index].longest_string - cpp_label.column.string.size; } - DN_Str8Builder builder = DN_Str8BuilderFromTLS(); + DN_Str8Builder builder = {}; + builder.arena = tmem.arena; // NOTE: row DN_Str8BuilderAppendF(&builder, "{%2d, ", row_index); @@ -1015,23 +1026,26 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil DN_Str8BuilderAppendF(&builder, "/*array_size*/ 0, "); DN_Str8BuilderAppendF(&builder, "/*array_size_field*/ NULL},"); - DN_Str8 line = DN_Str8BuilderBuildFromTLS(&builder); + DN_Str8 line = DN_Str8BuilderBuild(&builder, tmem.arena); + DN_TCScratchEnd(&tmem); DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line)); } } + DN_TCScratchEnd(&tmem); } } } - int longest_name_across_all_tables = 0; + int longest_name_across_all_tables = 0; for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); longest_name_across_all_tables = DN_Max(longest_name_across_all_tables, DN_Cast(int) type_name.size); + DN_TCScratchEnd(&tmem); } } @@ -1042,20 +1056,21 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil DN_USize longest_type_name = 0; for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); longest_type_name = DN_Max(longest_type_name, type_name.size); + DN_TCScratchEnd(&tmem); } } for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) - type_name = DN_Str8FromTLSF("%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); + type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); int name_padding = 1 + longest_name_across_all_tables - DN_Cast(int) type_name.size; DN_Str8 type_info_kind = {}; @@ -1080,9 +1095,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil DN_Str8 fields_count = DN_Str8Lit("0"); if (!DN_Str8Eq(fields, DN_Str8Lit("NULL"))) - fields_count = DN_Str8FromTLSF("sizeof(%.*s)/sizeof(%.*s[0])", DN_Str8PrintFmt(fields), DN_Str8PrintFmt(fields)); + fields_count = DN_Str8FromFmtArena(tmem.arena, "sizeof(%.*s)/sizeof(%.*s[0])", DN_Str8PrintFmt(fields), DN_Str8PrintFmt(fields)); - DN_Str8Builder builder = DN_Str8BuilderFromTLS(); + DN_Str8Builder builder = {}; + builder.arena = tmem.arena; // NOTE: name DN_Str8BuilderAppendF(&builder, "{DN_Str8Lit(\"%.*s\"),%*s", DN_Str8PrintFmt(type_name), name_padding, ""); @@ -1101,7 +1117,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil // NOTE: DN_TypeField length DN_Str8BuilderAppendF(&builder, "/*count*/ %.*s},", DN_Str8PrintFmt(fields_count)); - DN_Str8 line = DN_Str8BuilderBuildFromTLS(&builder); + DN_Str8 line = DN_Str8BuilderBuild(&builder, tmem.arena); + DN_TCScratchEnd(&tmem); DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line)); } } @@ -1115,7 +1132,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil { DN_CppLine(cpp, "case %.*sType_Nil: break;", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "case %.*sType_Count: break;", DN_Str8PrintFmt(emit_prefix)); - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string); @@ -1129,6 +1146,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil DN_CppLine(cpp, "case %.*s: result = g_%.*stypes + %.*s; break;", DN_Str8PrintFmt(full_enum_name), DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(full_enum_name)); } } + DN_TCScratchEnd(&tmem); } DN_CppLine(cpp, "return result;"); } diff --git a/Source/Extra/dn_cgen.h b/Source/Extra/dn_cgen.h index 88c7062..bfcb6e4 100644 --- a/Source/Extra/dn_cgen.h +++ b/Source/Extra/dn_cgen.h @@ -2,8 +2,8 @@ #define DN_CGEN_H #if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" + #define DN_H_WITH_OS 1 + #include "../dn.h" #include "../Standalone/dn_cpp_file.h" #endif @@ -38,27 +38,6 @@ #error Metadesk 'md.h' must be included before 'dn_cgen.h' #endif -#if !defined(DN_BASE_INC_H) - #error dn_base_inc.h must be included before this -#endif - -/* -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// $$$$$$\ $$$$$$\ $$$$$$$$\ $$\ $$\ -// $$ __$$\ $$ __$$\ $$ _____|$$$\ $$ | -// $$ / \__|$$ / \__|$$ | $$$$\ $$ | -// $$ | $$ |$$$$\ $$$$$\ $$ $$\$$ | -// $$ | $$ |\_$$ |$$ __| $$ \$$$$ | -// $$ | $$\ $$ | $$ |$$ | $$ |\$$$ | -// \$$$$$$ |\$$$$$$ |$$$$$$$$\ $$ | \$$ | -// \______/ \______/ \________|\__| \__| -// -// dn_cgen.h -- C/C++ code generation from table data in Metadesk files -// -//////////////////////////////////////////////////////////////////////////////////////////////////// -*/ - enum DN_CGenTableKeyType { DN_CGenTableKeyType_Nil, @@ -194,12 +173,12 @@ enum DN_CGenEmit (str8).size \ } -DN_API DN_CGen DN_CGen_InitFilesArgV(int argc, char const **argv, DN_OSErrSink *err); +DN_API DN_CGen DN_CGen_InitFilesArgV(int argc, char const **argv, DN_ErrSink *err); DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8(DN_CGenTableHeaderType type); DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_CGenMapNodeToEnum const *valid_keys, DN_USize valid_keys_size, char const *fmt, ...); DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node); -DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err, char const *fmt, ...); -DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_OSErrSink *err); +DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_ErrSink *err, char const *fmt, ...); +DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_ErrSink *err); DN_API DN_CGenLookupColumnAtHeader DN_CGen_LookupColumnAtHeader(DN_CGenTable *table, DN_Str8 header, DN_CGenTableRow const *row); DN_API bool DN_CGen_LookupNextTableInCodeGenTable(DN_CGen *cgen, DN_CGenTable *cgen_table, DN_CGenLookupTableIterator *it); DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFile *cpp, DN_Str8 emit_prefix); diff --git a/Source/Extra/dn_csv.h b/Source/Extra/dn_csv.h index 6b4e366..c9bbf6f 100644 --- a/Source/Extra/dn_csv.h +++ b/Source/Extra/dn_csv.h @@ -2,7 +2,7 @@ #define DN_CSV_H #if defined(_CLANGD) - #include "../dn_base_inc.h" + #include "../dn.h" #endif enum DN_CSVSerialise diff --git a/Source/Extra/dn_demo.cpp b/Source/Extra/dn_demo.cpp index b5c2d44..1690934 100644 --- a/Source/Extra/dn_demo.cpp +++ b/Source/Extra/dn_demo.cpp @@ -1,6 +1,5 @@ #if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" + #include "../dn.h" #endif DN_MSVC_WARNING_PUSH @@ -31,10 +30,11 @@ void DN_Demo() // NOTE: DN_HexFromBytes { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); unsigned char bytes[2] = {0xFA, 0xCE}; - DN_Str8 hex = DN_HexFromBytesPtrArena(bytes, sizeof(bytes), tmem.arena); + DN_Str8 hex = DN_HexFromBytesPtrArena(bytes, sizeof(bytes), scratch.arena); DN_Assert(DN_Str8Eq(hex, DN_Str8Lit("face"))); // NOTE: Guaranteed to be null-terminated + DN_TCScratchEnd(&scratch); } // NOTE: DN_BytesFromHex @@ -119,8 +119,8 @@ void DN_Demo() // buffer, this buffer must be valid throughout the lifetime of the hash // table! { - // NOTE: DN_DSMap_Init - // NOTE: DN_DSMap_Deinit + // NOTE: DN_DSMapInit + // NOTE: DN_DSMapDeinit // // Initialise a hash table where the table size *must* be a // power-of-two, otherwise an assert will be triggered. If @@ -139,15 +139,15 @@ void DN_Demo() // A 'Deinit' of the map will similarly deallocate the passed in arena (as // the map takes ownership of the arena). DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); - DN_DSMap map = DN_DSMap_Init(&arena, /*size*/ 1024, DN_DSMapFlags_Nil); // Size must be PoT! - DN_Assert(DN_DSMap_IsValid(&map)); // Valid if no initialisation failure (e.g. mem alloc failure) + DN_DSMap map = DN_DSMapInit(&arena, /*size*/ 1024, DN_DSMapFlags_Nil); // Size must be PoT! + DN_Assert(DN_DSMapIsValid(&map)); // Valid if no initialisation failure (e.g. mem alloc failure) - // NOTE: DN_DSMap_KeyCStringLit - // NOTE: DN_DSMap_KeyU64 - // NOTE: DN_DSMap_KeyU64NoHash - // NOTE: DN_DSMap_KeyBuffer - // NOTE: DN_DSMap_KeyStr8 - // NOTE: DN_DSMap_KeyStr8Copy + // NOTE: DN_DSMapKeyCStringLit + // NOTE: DN_DSMapKeyU64 + // NOTE: DN_DSMapKeyU64NoHash + // NOTE: DN_DSMapKeyBuffer + // NOTE: DN_DSMapKeyStr8 + // NOTE: DN_DSMapKeyStr8Copy // Create a hash-table key where: // // KeyCStringLit: Uses a Hash(cstring literal) @@ -168,11 +168,11 @@ void DN_Demo() // already sufficiently uniformly distributed already (e.g. using 8 // bytes taken from a SHA256 hash as the key) and the first 4 bytes // will be used verbatim. - DN_DSMapKey key = DN_DSMap_KeyStr8(&map, DN_Str8Lit("Sample Key")); + DN_DSMapKey key = DN_DSMapKeyStr8(&map, DN_Str8Lit("Sample Key")); - // NOTE: DN_DSMap_Find - // NOTE: DN_DSMap_Make - // NOTE: DN_DSMap_Set + // NOTE: DN_DSMapFind + // NOTE: DN_DSMapMake + // NOTE: DN_DSMapSet // // Query or commit key-value pair to the table, where: // @@ -190,7 +190,7 @@ void DN_Demo() // the table will be grown to 2x the current the size before insertion // completes. { - DN_DSMapResult set_result = DN_DSMap_Set(&map, key, 0xCAFE); + DN_DSMapResult set_result = DN_DSMapSet(&map, key, 0xCAFE); DN_Assert(!set_result.found); // First time we are setting the key-value pair, it wasn't previously in the table DN_Assert(map.occupied == 2); // Sentinel + new element == 2 } @@ -206,38 +206,38 @@ void DN_Demo() DN_Assert(DN_Str8Eq(DN_Str8FromPtr(it_key.buffer_data, it_key.buffer_size), DN_Str8Lit("Sample Key"))); } - // NOTE: DN_DSMap_Erase + // NOTE: DN_DSMapErase // // Remove the key-value pair from the table. If by erasing the key-value // pair from the table puts the table under 25% load, the table will be // shrunk by 1/2 the current size after erasing. The table will not shrink // below the initial size that the table was initialised as. { - bool erased = DN_DSMap_Erase(&map, key); + bool erased = DN_DSMapErase(&map, key); DN_Assert(erased); DN_Assert(map.occupied == 1); // Sentinel element } - DN_DSMap_Deinit(&map, DN_ZMem_Yes); // Deallocates the 'arena' for us! + DN_DSMapDeinit(&map, DN_ZMem_Yes); // Deallocates the 'arena' for us! } -// NOTE: DN_DSMap_Hash +// NOTE: DN_DSMapHash // // Hash the input key using the custom hash function if it's set on the map, // otherwise uses the default hashing function (32bit Murmur3). -// NOTE: DN_DSMap_HashToSlotIndex +// NOTE: DN_DSMapHashToSlotIndex // // Calculate the index into the map's 'slots' array from the given hash. -// NOTE: DN_DSMap_Resize +// NOTE: DN_DSMapResize // // Resize the table and move all elements to the new map, note that the new // size must be a power of two. This function wil fail on memory allocation // failure, or the requested size is smaller than the current number of // elements in the map to resize. -// NOTE: DN_OSErrSink +// NOTE: DN_ErrSink // // Error sinks are a way of accumulating errors from API calls related or // unrelated into 1 unified error handling pattern. The implemenation of a @@ -273,11 +273,11 @@ void DN_Demo() // (B) Error handling using pipelining and and error proof APIs. APIs that // produce errors take in the error sink as a parameter. if (0) { - DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); + DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil); DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error); DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error); DN_OS_FileClose(&file); - if (DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to file")) { + if (DN_ErrSinkEndLogErrorF(error, "Failed to write to file")) { // Do error handling! } } @@ -297,7 +297,7 @@ void DN_Demo() // be populated by the first error encountered in that scope. if (0) { - DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); + DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil); DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error); DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error); DN_OS_FileClose(&file); @@ -305,12 +305,12 @@ void DN_Demo() { // NOTE: My error sinks are thread-local, so the returned 'error' is // the same as the 'error' value above. - DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); + DN_TCErrSinkBegin(DN_ErrSinkMode_Nil); DN_OS_FileWriteAll(DN_Str8Lit("/path/to/another/file"), DN_Str8Lit("123"), error); - DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to another file"); + DN_ErrSinkEndLogErrorF(error, "Failed to write to another file"); } - if (DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to file")) { + if (DN_ErrSinkEndLogErrorF(error, "Failed to write to file")) { // Do error handling! } } @@ -357,16 +357,6 @@ void DN_Demo() // // And the non-named version emit just the 'value' portion - // NOTE: DN_List_Iterate - { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_List list = DN_List_Init(/*chunk_size*/ 128); - for (DN_ListIterator it = {}; DN_List_Iterate(&list, &it, 0);) { - int *item = it.data; - (void)item; - } - } - // NOTE: DN_LOGProc // // Function prototype of the logging interface exposed by this library. Logs @@ -438,10 +428,11 @@ void DN_Demo() // If 'tmp_path' is written to successfuly, the file will be copied over into // 'path'. if (0) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil); DN_OS_FileWriteAllSafe(/*path*/ DN_Str8Lit("C:/Home/my.txt"), /*buffer*/ DN_Str8Lit("Hello world"), error); - DN_OS_ErrSinkEndAndLogErrorF(error, ""); + DN_ErrSinkEndLogErrorF(error, ""); + DN_TCScratchEnd(&scratch); } // NOTE: DN_OS_EstimateTSCPerSecond @@ -630,7 +621,7 @@ void DN_Demo() // Int -> U32: 0 or UINT32_MAX // Int -> U64: 0 or UINT64_MAX - // NOTE: DN_StackTrace + // NOTE: DN_OS_StackTrace // Emit stack traces at the calling site that these functions are invoked // from. // @@ -647,15 +638,15 @@ void DN_Demo() // the debug APIs are aware of how to resolve the new addresses imported // into the address space. { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); - // NOTE: DN_StackTraceWalk + // NOTE: DN_OS_StackTraceWalk // // Generate a stack trace as a series of addresses to the base of the // functions on the call-stack at the current instruction pointer. The // addresses are stored in order from the current executing function // first to the most ancestor function last in the walk. - DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, /*depth limit*/ 128); + DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, /*depth limit*/ 128); // Loop over the addresses produced in the stack trace for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);) { @@ -663,7 +654,7 @@ void DN_Demo() // // Converts the base address into a human readable stack trace // entry (e.g. address, line number, file and function name). - DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(tmem.arena, it.raw_frame); + DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(scratch.arena, it.raw_frame); // You may then print out the frame like so if (0) @@ -675,13 +666,15 @@ void DN_Demo() // to resolve the new addresses. DN_StackTraceReloadSymbols(); - // NOTE: DN_StackTraceGetFrames + // NOTE: DN_OS_StackTraceGetFrames // // Helper function to create a stack trace and automatically convert the // raw frames into human readable frames. This function effectively // calls 'Walk' followed by 'RawFrameToFrame'. - DN_Slice frames = DN_StackTraceGetFrames(tmem.arena, /*depth limit*/ 128); + DN_StackTraceFrameSlice frames = DN_StackTraceGetFrames(scratch.arena, /*depth limit*/ 128); (void)frames; + + DN_TCScratchEnd(&scratch); } // NOTE: DN_Str8FromArena @@ -693,10 +686,11 @@ void DN_Demo() // The returned string's 'size' member variable does *not* include this // additional null-terminating byte. { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 string = DN_Str8FromArena(tmem.arena, /*size*/ 1, DN_ZMem_Yes); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 string = DN_Str8FromArena(scratch.arena, /*size*/ 1, DN_ZMem_Yes); DN_Assert(string.size == 1); DN_Assert(string.data[string.size] == 0); // It is null-terminated! + DN_TCScratchEnd(&scratch); } // NOTE: DN_Str8BSplit @@ -773,14 +767,15 @@ void DN_Demo() // always be a newly allocated copy, irrespective of if any replacements // were done or not. { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_Str8 string = DN_Str8Replace(/*string*/ DN_Str8Lit("Foo Foo Bar"), /*find*/ DN_Str8Lit("Foo"), /*replace*/ DN_Str8Lit("Moo"), /*start_index*/ 1, - /*arena*/ tmem.arena, + /*arena*/ scratch.arena, /*eq_case*/ DN_Str8EqCase_Sensitive); DN_Assert(DN_Str8Eq(string, DN_Str8Lit("Foo Moo Bar"))); + DN_TCScratchEnd(&scratch); } // NOTE: DN_Str8Segment @@ -791,18 +786,19 @@ void DN_Demo() // Reverse segment delimits the string counting 'segment_size' from the back // of the string. { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 string = DN_Str8Segment(tmem.arena, /*string*/ DN_Str8Lit("123456789"), /*segment_size*/ 3, /*segment_char*/ ','); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 string = DN_Str8Segment(scratch.arena, /*string*/ DN_Str8Lit("123456789"), /*segment_size*/ 3, /*segment_char*/ ','); DN_Assert(DN_Str8Eq(string, DN_Str8Lit("123,456,789"))); + DN_TCScratchEnd(&scratch); } // NOTE: DN_Str8Split { // Splits the string at each delimiter into substrings occuring prior and // after until the next delimiter. - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); { - DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ tmem.arena, + DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ scratch.arena, /*string*/ DN_Str8Lit("192.168.8.1"), /*delimiter*/ DN_Str8Lit("."), /*mode*/ DN_Str8SplitIncludeEmptyStrings_No); @@ -816,7 +812,7 @@ void DN_Demo() // You can include empty strings that occur when splitting by setting // the split mode to include empty strings. { - DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ tmem.arena, + DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ scratch.arena, /*string*/ DN_Str8Lit("a--b"), /*delimiter*/ DN_Str8Lit("-"), /*mode*/ DN_Str8SplitIncludeEmptyStrings_Yes); @@ -825,6 +821,8 @@ void DN_Demo() DN_Str8Eq(splits.data[1], DN_Str8Lit("")) && DN_Str8Eq(splits.data[2], DN_Str8Lit("b"))); } + + DN_TCScratchEnd(&scratch); } // NOTE: DN_I64FromStr8, DN_U64FromStr8 @@ -931,7 +929,7 @@ void DN_Demo() // NOTE: DN_ThreadContext // - // Each thread is assigned in their thread-local storage (TLS) tmem and + // Each thread is assigned in their thread-local storage (TLS) scratch and // permanent arena allocators. These can be used for allocations with a // lifetime scoped to the lexical scope or for storing data permanently // using the arena paradigm. @@ -939,40 +937,43 @@ void DN_Demo() // TLS in this implementation is implemented using the `thread_local` C/C++ // keyword. // - // 99% of the time you will want DN_OS_TLSTMem(...) which returns you a + // 99% of the time you will want DN_OS_TLSTMem...) which returns you a // temporary arena for function lifetime allocations. On scope exit, the // arena is cleared out. // - // This library's paradigm revolves heavily around arenas including tmem + // This library's paradigm revolves heavily around arenas including scratch // arenas into child functions for temporary calculations. If an arena is // passed into a function, this poses a problem sometimes known as // 'arena aliasing'. // // If an arena aliases another arena (e.g. the arena passed in) is the same - // as the tmem arena requested in the function, we risk the tmem arena + // as the scratch arena requested in the function, we risk the scratch arena // on scope exit deallocating memory belonging to the caller. // - // To avoid this we the 'DN_OS_TLSTMem(...)' API takes in a list of arenas - // to ensure that we provide a tmem arena that *won't* alias with the + // To avoid this we the 'DN_OS_TLSTMem...)' API takes in a list of arenas + // to ensure that we provide a scratch arena that *won't* alias with the // caller's arena. If arena aliasing occurs, with ASAN on, generally // the library will trap and report use-after-poison once violated. { - DN_OSTLSTMem tmem_a = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch_a = DN_TCScratchBegin(nullptr, 0); - // Now imagine we call a function where we pass tmem_a.arena down - // into it .. If we call tmem again, we need to pass in the arena + // Now imagine we call a function where we pass scratch_a.arena down + // into it .. If we call scratch again, we need to pass in the arena // to prevent aliasing. - DN_OSTLSTMem tmem_b = DN_OS_TLSTMem(tmem_a.arena); - DN_Assert(tmem_a.arena != tmem_b.arena); + DN_TCScratch scratch_b = DN_TCScratchBegin(&scratch_a.arena, 1); + DN_Assert(scratch_a.arena != scratch_b.arena); + + DN_TCScratchEnd(&scratch_b); + DN_TCScratchEnd(&scratch_a); } - // @proc DN_Thread_GetTMem + // @proc DN_Thread_Getscratch // @desc Retrieve the per-thread temporary arena allocator that is reset on scope // exit. - // The tmem arena must be deconflicted with any existing arenas in the + // The scratch arena must be deconflicted with any existing arenas in the // function to avoid trampling over each other's memory. Consider the situation - // where the tmem arena is passed into the function. Inside the function, if + // where the scratch arena is passed into the function. Inside the function, if // the same arena is reused then, if both arenas allocate, when the inner arena // is reset, this will undo the passed in arena's allocations in the function. @@ -988,9 +989,10 @@ void DN_Demo() // NOTE: DN_CVT_AgeFromU64 { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_Str8x128 string = DN_AgeStr8FromSecF64(DN_SecFromHours(2) + DN_SecFromMins(30), DN_AgeUnit_All); DN_Assert(DN_Str8Eq(DN_Str8FromStruct(&string), DN_Str8Lit("2h 30m"))); + DN_TCScratchEnd(&scratch); } // NOTE: DN_VArray @@ -1017,21 +1019,21 @@ void DN_Demo() // In addition to no realloc on expansion or shrinking. // { - // NOTE: DN_VArray_Init - // NOTE: DN_VArray_InitByteSize + // NOTE: DN_OS_VArrayInit + // NOTE: DN_OS_VArrayInitByteSize // // Initialise an array with the requested byte size or item capacity // respectively. The returned array may have a higher capacity than the // requested amount since requested memory from the OS may have a certain // alignment requirement (e.g. on Windows reserve/commit are 64k/4k // aligned). - DN_VArray array = DN_VArray_Init(1024); + DN_VArray array = DN_OS_VArrayInit(1024); DN_Assert(array.size == 0 && array.max >= 1024); - // NOTE: DN_VArray_Make - // NOTE: DN_VArray_Add - // NOTE: DN_VArray_MakeArray - // NOTE: DN_VArray_AddArray + // NOTE: DN_OS_VArrayMake + // NOTE: DN_OS_VArrayAdd + // NOTE: DN_OS_VArrayMakeArray + // NOTE: DN_OS_VArrayAddArray // // Allocate items from the array where: // @@ -1040,11 +1042,11 @@ void DN_Demo() // // If the array has run out of capacity or was never initialised, a null // pointer is returned. - int *item = DN_VArray_Add(&array, 0xCAFE); + int *item = DN_OS_VArrayAdd(&array, 0xCAFE); DN_Assert(*item == 0xCAFE && array.size == 1); - // NOTE: DN_VArray_AddCArray - DN_VArray_AddCArray(&array, {1, 2, 3}); + // NOTE: DN_OS_VArrayAddCArray + DN_OS_VArrayAddCArray(&array, {1, 2, 3}); DN_Assert(array.size == 4); // TODO(doyle): There's a bug here with the negative erase! @@ -1054,7 +1056,7 @@ void DN_Demo() if (index != 1) continue; - // NOTE: DN_VArray_EraseRange + // NOTE: DN_OS_VArrayEraseRange // // Erase the next 'count' items at 'begin_index' in the array. // 'count' can be positive or negative which dictates the if we @@ -1072,7 +1074,7 @@ void DN_Demo() // TODO(doyle): There's a bug here! This doesn't work. // Erase index 0 with the negative count! - DN_ArrayEraseResult erase_result = DN_VArray_EraseRange(&array, + DN_ArrayEraseResult erase_result = DN_OS_VArrayEraseRange(&array, /*begin_index*/ index, /*count*/ -1, /*erase*/ DN_ArrayErase_Stable); @@ -1089,7 +1091,7 @@ void DN_Demo() array.data[2] == 3); #endif - // NOTE: DN_VArray_Reserve + // NOTE: DN_OS_VArrayReserve // // Ensure that the requested number of items are backed by physical pages // from the OS. Calling this pre-emptively will minimise syscalls into the @@ -1097,9 +1099,9 @@ void DN_Demo() // in bytes to the allocation granularity of OS allocation APIs hence the // reserved space may be greater than the requested amount (e.g. this is 4k // on Windows). - DN_VArray_Reserve(&array, /*count*/ 8); + DN_OS_VArrayReserve(&array, /*count*/ 8); - DN_VArray_Deinit(&array); + DN_OS_VArrayDeinit(&array); } // NOTE: DN_W32_LastError @@ -1108,13 +1110,14 @@ void DN_Demo() if (0) { // Generate the error string for the last Win32 API called that return // an error value. - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_W32Error get_last_error = DN_W32_LastError(tmem.arena); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_OSW32Error get_last_error = DN_OS_W32LastError(scratch.arena); printf("Error (%lu): %.*s", get_last_error.code, DN_Str8PrintFmt(get_last_error.msg)); // Alternatively, pass in the error code directly - DN_W32Error error_msg_for_code = DN_W32_ErrorCodeToMsg(tmem.arena, /*error_code*/ 0); + DN_OSW32Error error_msg_for_code = DN_OS_W32ErrorCodeToMsg(scratch.arena, /*error_code*/ 0); printf("Error (%lu): %.*s", error_msg_for_code.code, DN_Str8PrintFmt(error_msg_for_code.msg)); + DN_TCScratchEnd(&scratch); } // NOTE: DN_W32_MakeProcessDPIAware diff --git a/Source/Extra/dn_hash.cpp b/Source/Extra/dn_hash.cpp deleted file mode 100644 index bafc69a..0000000 --- a/Source/Extra/dn_hash.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#define DN_HASH_CPP - -#if defined(_CLANGD) - #include "dn_hash.h" -#endif - -/* -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// $$\ $$\ $$$$$$\ $$$$$$\ $$\ $$\ -// $$ | $$ |$$ __$$\ $$ __$$\ $$ | $$ | -// $$ | $$ |$$ / $$ |$$ / \__|$$ | $$ | -// $$$$$$$$ |$$$$$$$$ |\$$$$$$\ $$$$$$$$ | -// $$ __$$ |$$ __$$ | \____$$\ $$ __$$ | -// $$ | $$ |$$ | $$ |$$\ $$ |$$ | $$ | -// $$ | $$ |$$ | $$ |\$$$$$$ |$$ | $$ | -// \__| \__|\__| \__| \______/ \__| \__| -// -// dn_hash.cpp -// -//////////////////////////////////////////////////////////////////////////////////////////////////// -*/ - -// NOTE: DN_FNV1A -// Default values recommended by: http://isthe.com/chongo/tech/comp/fnv/ -DN_API DN_U32 DN_FNV1A32_Iterate(void const *bytes, DN_USize size, DN_U32 hash) -{ - auto buffer = DN_Cast(DN_U8 const *)bytes; - for (DN_USize i = 0; i < size; i++) - hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/; - return hash; -} - -DN_API DN_U32 DN_FNV1A32_Hash(void const *bytes, DN_USize size) -{ - DN_U32 result = DN_FNV1A32_Iterate(bytes, size, DN_FNV1A32_SEED); - return result; -} - -DN_API DN_U64 DN_FNV1A64_Iterate(void const *bytes, DN_USize size, DN_U64 hash) -{ - auto buffer = DN_Cast(DN_U8 const *)bytes; - for (DN_USize i = 0; i < size; i++) - hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/; - return hash; -} - -DN_API DN_U64 DN_FNV1A64_Hash(void const *bytes, DN_USize size) -{ - DN_U64 result = DN_FNV1A64_Iterate(bytes, size, DN_FNV1A64_SEED); - return result; -} - -// NOTE: DN_MurmurHash3 //////////////////////////////////////////////////////////////////////////// -#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) - #define DN_MMH3_ROTL32(x, y) _rotl(x, y) - #define DN_MMH3_ROTL64(x, y) _rotl64(x, y) -#else - #define DN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y))) - #define DN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y))) -#endif - -//----------------------------------------------------------------------------- -// Block read - if your platform needs to do endian-swapping or can only -// handle aligned reads, do the conversion here - -DN_FORCE_INLINE DN_U32 DN_MurmurHash3_GetBlock32(DN_U32 const *p, int i) -{ - return p[i]; -} - -DN_FORCE_INLINE DN_U64 DN_MurmurHash3_GetBlock64(DN_U64 const *p, int i) -{ - return p[i]; -} - -//----------------------------------------------------------------------------- -// Finalization mix - force all bits of a hash block to avalanche - -DN_FORCE_INLINE DN_U32 DN_MurmurHash3_FMix32(DN_U32 h) -{ - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - return h; -} - -DN_FORCE_INLINE DN_U64 DN_MurmurHash3_FMix64(DN_U64 k) -{ - k ^= k >> 33; - k *= 0xff51afd7ed558ccd; - k ^= k >> 33; - k *= 0xc4ceb9fe1a85ec53; - k ^= k >> 33; - return k; -} - -DN_API DN_U32 DN_MurmurHash3_x86U32(void const *key, int len, DN_U32 seed) -{ - const DN_U8 *data = (const DN_U8 *)key; - const int nblocks = len / 4; - - DN_U32 h1 = seed; - - const DN_U32 c1 = 0xcc9e2d51; - const DN_U32 c2 = 0x1b873593; - - //---------- - // body - - const DN_U32 *blocks = (const DN_U32 *)(data + nblocks * 4); - - for (int i = -nblocks; i; i++) - { - DN_U32 k1 = DN_MurmurHash3_GetBlock32(blocks, i); - - k1 *= c1; - k1 = DN_MMH3_ROTL32(k1, 15); - k1 *= c2; - - h1 ^= k1; - h1 = DN_MMH3_ROTL32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - } - - //---------- - // tail - - const DN_U8 *tail = (const DN_U8 *)(data + nblocks * 4); - - DN_U32 k1 = 0; - - switch (len & 3) - { - case 3: - k1 ^= tail[2] << 16; - case 2: - k1 ^= tail[1] << 8; - case 1: - k1 ^= tail[0]; - k1 *= c1; - k1 = DN_MMH3_ROTL32(k1, 15); - k1 *= c2; - h1 ^= k1; - }; - - //---------- - // finalization - - h1 ^= len; - - h1 = DN_MurmurHash3_FMix32(h1); - - return h1; -} - -DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128(void const *key, int len, DN_U32 seed) -{ - const DN_U8 *data = (const DN_U8 *)key; - const int nblocks = len / 16; - - DN_U64 h1 = seed; - DN_U64 h2 = seed; - - const DN_U64 c1 = 0x87c37b91114253d5; - const DN_U64 c2 = 0x4cf5ad432745937f; - - //---------- - // body - - const DN_U64 *blocks = (const DN_U64 *)(data); - - for (int i = 0; i < nblocks; i++) - { - DN_U64 k1 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 0); - DN_U64 k2 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 1); - - k1 *= c1; - k1 = DN_MMH3_ROTL64(k1, 31); - k1 *= c2; - h1 ^= k1; - - h1 = DN_MMH3_ROTL64(h1, 27); - h1 += h2; - h1 = h1 * 5 + 0x52dce729; - - k2 *= c2; - k2 = DN_MMH3_ROTL64(k2, 33); - k2 *= c1; - h2 ^= k2; - - h2 = DN_MMH3_ROTL64(h2, 31); - h2 += h1; - h2 = h2 * 5 + 0x38495ab5; - } - - //---------- - // tail - - const DN_U8 *tail = (const DN_U8 *)(data + nblocks * 16); - - DN_U64 k1 = 0; - DN_U64 k2 = 0; - - switch (len & 15) - { - case 15: - k2 ^= ((DN_U64)tail[14]) << 48; - case 14: - k2 ^= ((DN_U64)tail[13]) << 40; - case 13: - k2 ^= ((DN_U64)tail[12]) << 32; - case 12: - k2 ^= ((DN_U64)tail[11]) << 24; - case 11: - k2 ^= ((DN_U64)tail[10]) << 16; - case 10: - k2 ^= ((DN_U64)tail[9]) << 8; - case 9: - k2 ^= ((DN_U64)tail[8]) << 0; - k2 *= c2; - k2 = DN_MMH3_ROTL64(k2, 33); - k2 *= c1; - h2 ^= k2; - - case 8: - k1 ^= ((DN_U64)tail[7]) << 56; - case 7: - k1 ^= ((DN_U64)tail[6]) << 48; - case 6: - k1 ^= ((DN_U64)tail[5]) << 40; - case 5: - k1 ^= ((DN_U64)tail[4]) << 32; - case 4: - k1 ^= ((DN_U64)tail[3]) << 24; - case 3: - k1 ^= ((DN_U64)tail[2]) << 16; - case 2: - k1 ^= ((DN_U64)tail[1]) << 8; - case 1: - k1 ^= ((DN_U64)tail[0]) << 0; - k1 *= c1; - k1 = DN_MMH3_ROTL64(k1, 31); - k1 *= c2; - h1 ^= k1; - }; - - //---------- - // finalization - - h1 ^= len; - h2 ^= len; - - h1 += h2; - h2 += h1; - - h1 = DN_MurmurHash3_FMix64(h1); - h2 = DN_MurmurHash3_FMix64(h2); - - h1 += h2; - h2 += h1; - - DN_MurmurHash3 result = {}; - result.e[0] = h1; - result.e[1] = h2; - return result; -} diff --git a/Source/Extra/dn_hash.h b/Source/Extra/dn_hash.h deleted file mode 100644 index e7b3f74..0000000 --- a/Source/Extra/dn_hash.h +++ /dev/null @@ -1,49 +0,0 @@ -#if !defined(DN_HASH_H) -#define DN_HASH_H - -#if defined(_CLANGD) - #include "../dn_base_inc.h" -#endif - -/* -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// $$\ $$\ $$$$$$\ $$$$$$\ $$\ $$\ -// $$ | $$ |$$ __$$\ $$ __$$\ $$ | $$ | -// $$ | $$ |$$ / $$ |$$ / \__|$$ | $$ | -// $$$$$$$$ |$$$$$$$$ |\$$$$$$\ $$$$$$$$ | -// $$ __$$ |$$ __$$ | \____$$\ $$ __$$ | -// $$ | $$ |$$ | $$ |$$\ $$ |$$ | $$ | -// $$ | $$ |$$ | $$ |\$$$$$$ |$$ | $$ | -// \__| \__|\__| \__| \______/ \__| \__| -// -// dn_hash.h -- Hashing functions -// -//////////////////////////////////////////////////////////////////////////////////////////////////// -*/ - -// NOTE: DN_FNV1A ////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_FNV1A32_SEED) - #define DN_FNV1A32_SEED 2166136261U -#endif - -#if !defined(DN_FNV1A64_SEED) - #define DN_FNV1A64_SEED 14695981039346656037ULL -#endif - -// NOTE: DN_MurmurHash3 //////////////////////////////////////////////////////////////////////////// -struct DN_MurmurHash3 { uint64_t e[2]; }; - -// NOTE: DN_FNV1A ////////////////////////////////////////////////////////////////////////////////// -DN_API uint32_t DN_FNV1A32_Hash (void const *bytes, DN_USize size); -DN_API uint64_t DN_FNV1A64_Hash (void const *bytes, DN_USize size); -DN_API uint32_t DN_FNV1A32_Iterate (void const *bytes, DN_USize size, uint32_t hash); -DN_API uint64_t DN_FNV1A64_Iterate (void const *bytes, DN_USize size, uint64_t hash); - -// NOTE: DN_MurmurHash3 //////////////////////////////////////////////////////////////////////////// -DN_API uint32_t DN_MurmurHash3_x86U32 (void const *key, int len, uint32_t seed); -DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128 (void const *key, int len, uint32_t seed); -#define DN_MurmurHash3_x64U128AsU64(key, len, seed) (DN_MurmurHash3_x64U128(key, len, seed).e[0]) -#define DN_MurmurHash3_x64U128AsU32(key, len, seed) (DN_Cast(uint32_t)DN_MurmurHash3_x64U128(key, len, seed).e[0]) - -#endif // !defined(DN_HASH_H) diff --git a/Source/Extra/dn_helpers.cpp b/Source/Extra/dn_helpers.cpp index dc57223..e3c2ba4 100644 --- a/Source/Extra/dn_helpers.cpp +++ b/Source/Extra/dn_helpers.cpp @@ -4,102 +4,6 @@ #include "dn_helpers.h" #endif -/* -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// $$\ $$\ $$$$$$$$\ $$\ $$$$$$$\ $$$$$$$$\ $$$$$$$\ $$$$$$\ -// $$ | $$ |$$ _____|$$ | $$ __$$\ $$ _____|$$ __$$\ $$ __$$\ -// $$ | $$ |$$ | $$ | $$ | $$ |$$ | $$ | $$ |$$ / \__| -// $$$$$$$$ |$$$$$\ $$ | $$$$$$$ |$$$$$\ $$$$$$$ |\$$$$$$\ -// $$ __$$ |$$ __| $$ | $$ ____/ $$ __| $$ __$$< \____$$\ -// $$ | $$ |$$ | $$ | $$ | $$ | $$ | $$ |$$\ $$ | -// $$ | $$ |$$$$$$$$\ $$$$$$$$\ $$ | $$$$$$$$\ $$ | $$ |\$$$$$$ | -// \__| \__|\________|\________|\__| \________|\__| \__| \______/ -// -// dn_helpers.cpp -// -//////////////////////////////////////////////////////////////////////////////////////////////////// -*/ - -// NOTE: DN_PCG32 ////////////////////////////////////////////////////////////////////////////////// -#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL -#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL - -DN_API DN_PCG32 DN_PCG32_Init(uint64_t seed) -{ - DN_PCG32 result = {}; - DN_PCG32_Next(&result); - result.state += seed; - DN_PCG32_Next(&result); - return result; -} - -DN_API uint32_t DN_PCG32_Next(DN_PCG32 *rng) -{ - uint64_t state = rng->state; - rng->state = state * DN_PCG_DEFAULT_MULTIPLIER_64 + DN_PCG_DEFAULT_INCREMENT_64; - - // XSH-RR - uint32_t value = (uint32_t)((state ^ (state >> 18)) >> 27); - int rot = state >> 59; - return rot ? (value >> rot) | (value << (32 - rot)) : value; -} - -DN_API uint64_t DN_PCG32_Next64(DN_PCG32 *rng) -{ - uint64_t value = DN_PCG32_Next(rng); - value <<= 32; - value |= DN_PCG32_Next(rng); - return value; -} - -DN_API uint32_t DN_PCG32_Range(DN_PCG32 *rng, uint32_t low, uint32_t high) -{ - uint32_t bound = high - low; - uint32_t threshold = -(int32_t)bound % bound; - - for (;;) { - uint32_t r = DN_PCG32_Next(rng); - if (r >= threshold) - return low + (r % bound); - } -} - -DN_API float DN_PCG32_NextF32(DN_PCG32 *rng) -{ - uint32_t x = DN_PCG32_Next(rng); - return (float)(int32_t)(x >> 8) * 0x1.0p-24f; -} - -DN_API double DN_PCG32_NextF64(DN_PCG32 *rng) -{ - uint64_t x = DN_PCG32_Next64(rng); - return (double)(int64_t)(x >> 11) * 0x1.0p-53; -} - -DN_API void DN_PCG32_Advance(DN_PCG32 *rng, uint64_t delta) -{ - uint64_t cur_mult = DN_PCG_DEFAULT_MULTIPLIER_64; - uint64_t cur_plus = DN_PCG_DEFAULT_INCREMENT_64; - - uint64_t acc_mult = 1; - uint64_t acc_plus = 0; - - while (delta != 0) { - if (delta & 1) { - acc_mult *= cur_mult; - acc_plus = acc_plus * cur_mult + cur_plus; - } - cur_plus = (cur_mult + 1) * cur_plus; - cur_mult *= cur_mult; - delta >>= 1; - } - - rng->state = acc_mult * rng->state + acc_plus; -} - -#if !defined(DN_NO_JSON_BUILDER) -// NOTE: DN_JSONBuilder //////////////////////////////////////////////////////////////////////////// DN_API DN_JSONBuilder DN_JSONBuilder_Init(DN_Arena *arena, int spaces_per_indent) { DN_JSONBuilder result = {}; @@ -167,9 +71,10 @@ DN_API void DN_JSONBuilder_KeyValue(DN_JSONBuilder *builder, DN_Str8 key, DN_Str DN_API void DN_JSONBuilder_KeyValueFV(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, va_list args) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(builder->string_builder.arena); - DN_Str8 value = DN_Str8FromFmtVArena(tmem.arena, value_fmt, args); + DN_TCScratch scratch = DN_TCScratchBegin(&builder->string_builder.arena, 1); + DN_Str8 value = DN_Str8FromFmtVArena(scratch.arena, value_fmt, args); DN_JSONBuilder_KeyValue(builder, key, value); + DN_TCScratchEnd(&scratch); } DN_API void DN_JSONBuilder_KeyValueF(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...) @@ -246,4 +151,3 @@ DN_API void DN_JSONBuilder_BoolNamed(DN_JSONBuilder *builder, DN_Str8 key, bool DN_Str8 value_string = value ? DN_Str8Lit("true") : DN_Str8Lit("false"); DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data); } -#endif // !defined(DN_NO_JSON_BUILDER) diff --git a/Source/Extra/dn_helpers.h b/Source/Extra/dn_helpers.h index 2341bd3..688aefa 100644 --- a/Source/Extra/dn_helpers.h +++ b/Source/Extra/dn_helpers.h @@ -2,16 +2,7 @@ #define DN_HELPERS_H #if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "dn_math.h" -#endif - -#if !defined(DN_BASE_H) - #error dn_base_inc.h must be included before this -#endif - -#if !defined(DN_MATH_H) - #error dn_math.h must be included before this + #include "../dn.h" #endif /* @@ -31,11 +22,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: DN_PCG32 ////////////////////////////////////////////////////////////////////////////////// -struct DN_PCG32 { uint64_t state; }; - #if !defined(DN_NO_JSON_BUILDER) -// NOTE: DN_JSONBuilder //////////////////////////////////////////////////////////////////////////// enum DN_JSONBuilderItem { DN_JSONBuilderItem_Empty, @@ -100,15 +87,6 @@ struct DN_BinarySearchResult template using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context); -// NOTE: DN_PCG32 ////////////////////////////////////////////////////////////////////////////////// -DN_API DN_PCG32 DN_PCG32_Init (uint64_t seed); -DN_API uint32_t DN_PCG32_Next (DN_PCG32 *rng); -DN_API uint64_t DN_PCG32_Next64 (DN_PCG32 *rng); -DN_API uint32_t DN_PCG32_Range (DN_PCG32 *rng, uint32_t low, uint32_t high); -DN_API DN_F32 DN_PCG32_NextF32 (DN_PCG32 *rng); -DN_API DN_F64 DN_PCG32_NextF64 (DN_PCG32 *rng); -DN_API void DN_PCG32_Advance (DN_PCG32 *rng, uint64_t delta); - #if !defined(DN_NO_JSON_BUILDER) // NOTE: DN_JSONBuilder //////////////////////////////////////////////////////////////////////////// #define DN_JSONBuilder_Object(builder) \ diff --git a/Source/Extra/dn_json.cpp b/Source/Extra/dn_json.cpp index d9175d2..6a78812 100644 --- a/Source/Extra/dn_json.cpp +++ b/Source/Extra/dn_json.cpp @@ -407,7 +407,7 @@ void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site) json_string_s const *key = curr->name; if (it->flags & json_parse_flags_allow_location_information) { json_string_ex_s const *info = DN_Cast(json_string_ex_s const *)key; - DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), + DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning), call_site, "Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]", info->line_no, @@ -417,7 +417,7 @@ void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site) DN_Cast(int) value_type_size, value_type); } else { - DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), + DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning), call_site, "Unknown key-value pair in object [key=%.*s, value=%.*s]", DN_Cast(int) key->string_size, diff --git a/Source/Extra/dn_json.h b/Source/Extra/dn_json.h index 45c65b6..1021a47 100644 --- a/Source/Extra/dn_json.h +++ b/Source/Extra/dn_json.h @@ -2,7 +2,7 @@ #define DN_JSON_H #if defined(_CLANGD) - #include "../dn_base_inc.h" + #include "../dn.h" #include "../External/json.h" #endif @@ -10,13 +10,13 @@ #error Sheredom json.h (github.com/sheredom/json.h) must be included before this file #endif -// NOTE: DN_JSON ////////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_JSON void *DN_JSON_ArenaAllocFunc (void *user_data, size_t count); char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size); bool DN_JSON_String8Cmp (json_string_s const *lhs, DN_Str8 rhs); -// NOTE: DN_JSON_It ///////////////////////////////////////////////////////////////////////// +// NOTE: DN_JSON_It enum DN_JSONItEntryType { DN_JSON_ItEntryTypeObjElement, @@ -42,7 +42,7 @@ struct DN_JSONIt DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json); -// NOTE: DN_JSON_ItPush/Pop ///////////////////////////////////////////////////////////////// +// NOTE: DN_JSON_ItPush/Pop bool DN_JSON_ItPushObjElement (DN_JSONIt *it, json_object_element_s *element); bool DN_JSON_ItPushObj (DN_JSONIt *it, json_object_s *obj); bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element); @@ -50,7 +50,7 @@ bool DN_JSON_ItPushArray (DN_JSONIt *it, json_value_s *value); bool DN_JSON_ItPushValue (DN_JSONIt *it, json_value_s *value); void DN_JSON_ItPop (DN_JSONIt *it); -// NOTE: DN_JSON_It tree navigation ///////////////////////////////////////////////////////// +// NOTE: DN_JSON_It tree navigation json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it); bool DN_JSON_ItNext(DN_JSONIt *it); @@ -58,12 +58,12 @@ bool DN_JSON_ItNext(DN_JSONIt *it); for(void *DN_UniqueName(ptr) = DN_JSON_ItPushCurrValue(it); DN_UniqueName(ptr); DN_JSON_ItPop(it), DN_UniqueName(ptr) = nullptr) \ while (DN_JSON_ItNext(it)) -// NOTE: DN_JSON_ItCurr ///////////////////////////////////////////////////////////////////// +// NOTE: DN_JSON_ItCurr DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it); json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it); json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it); -// NOTE: DN_JSON_ItValueIs ////////////////////////////////////////////////////////////////// +// NOTE: DN_JSON_ItValueIs json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type); json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it); json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it); @@ -74,7 +74,7 @@ json_value_s *DN_JSON_ItValueIsNull(DN_JSONIt *it); size_t DN_JSON_ItValueArraySize(DN_JSONIt *it); -// NOTE: DN_JSON_ItKeyValueIs /////////////////////////////////////////////////////////////// +// NOTE: DN_JSON_ItKeyValueIs DN_Str8 DN_JSON_ItKey(DN_JSONIt *it); bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key); json_object_s *DN_JSON_ItKeyValueIsObj(DN_JSONIt *it, DN_Str8 key); @@ -84,7 +84,7 @@ json_number_s *DN_JSON_ItKeyValueIsNumber(DN_JSONIt *it, DN_Str8 key); json_value_s *DN_JSON_ItKeyValueIsBool(DN_JSONIt *it, DN_Str8 key); json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key); -// NOTE: DN_JSON_ItValueTo ////////////////////////////////////////////////////////////////// +// NOTE: DN_JSON_ItValueTo DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it); int64_t DN_JSON_ItValueToI64(DN_JSONIt *it); uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it); diff --git a/Source/Extra/dn_math.cpp b/Source/Extra/dn_math.cpp index 9d34f83..efee942 100644 --- a/Source/Extra/dn_math.cpp +++ b/Source/Extra/dn_math.cpp @@ -1255,18 +1255,18 @@ DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset) return result; } +DN_API DN_V2F32 DN_M2x3_ScaleGet(DN_M2x3 m2x3) +{ + DN_V2F32 result = DN_V2F32_From2N(m2x3.row[0][0], m2x3.row[1][1]); + return result; +} + DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) { - DN_M2x3 result = { - { - scale.x, - 0, - 0, - 0, - scale.y, - 0, - } - }; + DN_M2x3 result = {{ + scale.x, 0, 0, + 0, scale.y, 0, + }}; return result; } diff --git a/Source/Extra/dn_math.h b/Source/Extra/dn_math.h index 6d365d5..03bce9c 100644 --- a/Source/Extra/dn_math.h +++ b/Source/Extra/dn_math.h @@ -2,7 +2,7 @@ #define DN_MATH_H #if defined(_CLANGD) - #include "../dn_base_inc.h" + #include "../dn.h" #endif DN_MSVC_WARNING_PUSH @@ -34,25 +34,25 @@ union DN_V2F32 struct { DN_F32 w, h; }; DN_F32 data[2]; }; +DN_DArrayStructDecl(DN_V2F32); union DN_V3F32 { struct { DN_F32 x, y, z; }; struct { DN_F32 r, g, b; }; - DN_F32 data[3]; + DN_V2F32 xy; + DN_F32 data[3]; }; - union DN_V4F32 { struct { DN_F32 x, y, z, w; }; struct { DN_F32 r, g, b, a; }; - #if !defined(DN_NO_V3) DN_V3F32 rgb; DN_V3F32 xyz; - #endif - DN_F32 data[4]; + DN_F32 data[4]; }; +DN_DArrayStructDecl(DN_V4F32); DN_MSVC_WARNING_POP struct DN_M4 @@ -137,10 +137,10 @@ DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); -#define DN_V2U16_Zero DN_Literal(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_Literal(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} +#define DN_V2U16_Zero DN_Literal(DN_V2U16){{(DN_U16)(0), (DN_U16)(0)}} +#define DN_V2U16_One DN_Literal(DN_V2U16){{(DN_U16)(1), (DN_U16)(1)}} +#define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(DN_U16)(x), (DN_U16)(x)}} +#define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(DN_U16)(x), (DN_U16)(y)}} DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); @@ -165,6 +165,11 @@ DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); +#define DN_V2U32_Zero DN_Literal(DN_V2U32){{(DN_U32)(0), (DN_U32)(0)}} +#define DN_V2U32_One DN_Literal(DN_V2U32){{(DN_U32)(1), (DN_U32)(1)}} +#define DN_V2U32_From1N(x) DN_Literal(DN_V2U32){{(DN_U32)(x), (DN_U32)(x)}} +#define DN_V2U32_From2N(x, y) DN_Literal(DN_V2U32){{(DN_U32)(x), (DN_U32)(y)}} + #define DN_V2F32_Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} #define DN_V2F32_One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} #define DN_V2F32_From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} @@ -315,6 +320,7 @@ DN_API bool operator== (DN_M2x3 const DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); DN_API DN_M2x3 DN_M2x3_Identity (); DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); +DN_API DN_V2F32 DN_M2x3_ScaleGet (DN_M2x3 m2x3); DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); @@ -323,6 +329,7 @@ DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN #define DN_Rect_From2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)} #define DN_Rect_From4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}} +#define DN_Rect_Zero DN_Rect_From4N(0, 0, 0, 0) DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); diff --git a/Source/Extra/dn_net_curl.cpp b/Source/Extra/dn_net_curl.cpp index 3dc910f..e94db2d 100644 --- a/Source/Extra/dn_net_curl.cpp +++ b/Source/Extra/dn_net_curl.cpp @@ -91,14 +91,14 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread) DN_OS_ThreadSetName(DN_Str8FromPtr(curl->thread.name.data, curl->thread.name.size)); while (!curl->kill_thread) { - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); // NOTE: Handle events sitting in the ring queue for (bool dequeue_ring = true; dequeue_ring;) { DN_NETCurlRingEvent event = {}; for (DN_OS_MutexScope(&curl->ring_mutex)) { - if (DN_Ring_HasData(&curl->ring, sizeof(event))) - DN_Ring_Read(&curl->ring, &event, sizeof(event)); + if (DN_RingHasData(&curl->ring, sizeof(event))) + DN_RingRead(&curl->ring, &event, sizeof(event)); } DN_NETRequest *req = DN_NET_RequestFromHandle(event.request); @@ -126,9 +126,9 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread) case DN_NETCurlRingEventType_SendWS: { DN_Str8 payload = {}; for (DN_OS_MutexScope(&curl->ring_mutex)) { - DN_Assert(DN_Ring_HasData(&curl->ring, event.ws_send_size)); + DN_Assert(DN_RingHasData(&curl->ring, event.ws_send_size)); payload = DN_Str8FromArena(tmem.arena, event.ws_send_size, DN_ZMem_No); - DN_Ring_Read(&curl->ring, payload.data, payload.size); + DN_RingRead(&curl->ring, payload.data, payload.size); } DN_U32 curlws_flag = 0; @@ -370,6 +370,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread) DN_I32 sleep_time_ms = ws_count > 0 ? 16 : INT32_MAX; curl_multi_poll(curl->thread_curlm, nullptr, 0, sleep_time_ms, nullptr); + DN_TCScratchEnd(&tmem); } return 0; @@ -526,7 +527,7 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D event.type = DN_NETCurlRingEventType_DoRequest; event.request = result; for (DN_OS_MutexScope(&curl_core->ring_mutex)) - DN_Ring_WriteStruct(&curl_core->ring, &event); + DN_RingWriteStruct(&curl_core->ring, &event); curl_multi_wakeup(curl_core->thread_curlm); } @@ -569,9 +570,9 @@ void DN_NET_CurlDoWSSend(DN_NETRequestHandle handle, DN_Str8 payload, DN_NETWSSe event.ws_send = send; for (DN_OS_MutexScope(&curl->ring_mutex)) { - DN_Assert(DN_Ring_HasSpace(&curl->ring, payload.size)); - DN_Ring_WriteStruct(&curl->ring, &event); - DN_Ring_Write(&curl->ring, payload.data, payload.size); + DN_Assert(DN_RingHasSpace(&curl->ring, payload.size)); + DN_RingWriteStruct(&curl->ring, &event); + DN_RingWrite(&curl->ring, payload.data, payload.size); } curl_multi_wakeup(curl->thread_curlm); } @@ -627,7 +628,7 @@ static DN_NETResponse DN_NET_CurlHandleFinishedRequest_(DN_NETCurlCore *curl, DN } for (DN_OS_MutexScope(&curl->ring_mutex)) - DN_Ring_WriteStruct(&curl->ring, &event); + DN_RingWriteStruct(&curl->ring, &event); curl_multi_wakeup(curl->thread_curlm); return result; diff --git a/Source/Extra/dn_tests.cpp b/Source/Extra/dn_tests.cpp index f035c9b..d25403e 100644 --- a/Source/Extra/dn_tests.cpp +++ b/Source/Extra/dn_tests.cpp @@ -1,6 +1,6 @@ #if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" + #define DN_H_WITH_OS 1 + #include "../dn.h" #endif #if !defined(DN_UT_H) @@ -440,7 +440,7 @@ static DN_UTCore DN_Tests_Arena() static DN_UTCore DN_Tests_Bin() { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_UTCore test = DN_UT_Init(); DN_UT_LogF(&test, "DN_Bin\n"); { @@ -502,25 +502,26 @@ static DN_UTCore DN_Tests_Bin() uint32_t number = 0xd095f6; for (DN_UT_Test(&test, "Convert %x to string", number)) { - DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), tmem.arena); + DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), scratch.arena); DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("f695d000")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex)); } number = 0xf6ed00; for (DN_UT_Test(&test, "Convert %x to string", number)) { - DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), tmem.arena); + DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), scratch.arena); DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("00edf600")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex)); } DN_Str8 hex = DN_Str8Lit("0xf6ed00"); for (DN_UT_Test(&test, "Convert %.*s to bytes", DN_Str8PrintFmt(hex))) { - DN_Str8 bytes = DN_BytesFromHexStr8Arena(hex, tmem.arena); + DN_Str8 bytes = DN_BytesFromHexStr8Arena(hex, scratch.arena); DN_UT_AssertF(&test, DN_Str8Eq(bytes, DN_Str8Lit("\xf6\xed\x00")), "number_hex=%.*s", - DN_Str8PrintFmt(DN_HexFromBytesPtrArena(bytes.data, bytes.size, tmem.arena))); + DN_Str8PrintFmt(DN_HexFromBytesPtrArena(bytes.data, bytes.size, scratch.arena))); } } + DN_TCScratchEnd(&scratch); return test; } @@ -838,40 +839,40 @@ static DN_UTCore DN_Tests_BaseContainers() DN_UT_LogF(&result, "DN_DSMap\n"); { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); { DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); uint32_t const MAP_SIZE = 64; - DN_DSMap map = DN_DSMap_Init(&arena, MAP_SIZE, DN_DSMapFlags_Nil); + DN_DSMap map = DN_DSMapInit(&arena, MAP_SIZE, DN_DSMapFlags_Nil); DN_DEFER { - DN_DSMap_Deinit(&map, DN_ZMem_Yes); + DN_DSMapDeinit(&map, DN_ZMem_Yes); }; for (DN_UT_Test(&result, "Find non-existent value")) { - DN_DSMapResult find = DN_DSMap_FindKeyStr8(&map, DN_Str8Lit("Foo")); + DN_DSMapResult find = DN_DSMapFindKeyStr8(&map, DN_Str8Lit("Foo")); DN_UT_Assert(&result, !find.found); DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); } - DN_DSMapKey key = DN_DSMap_KeyCStr8(&map, "Bar"); + DN_DSMapKey key = DN_DSMapKeyCStr8(&map, "Bar"); for (DN_UT_Test(&result, "Insert value and lookup")) { uint64_t desired_value = 0xF00BAA; - uint64_t *slot_value = DN_DSMap_Set(&map, key, desired_value).value; + uint64_t *slot_value = DN_DSMapSet(&map, key, desired_value).value; DN_UT_Assert(&result, slot_value); DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.occupied == 2); - uint64_t *value = DN_DSMap_Find(&map, key).value; + uint64_t *value = DN_DSMapFind(&map, key).value; DN_UT_Assert(&result, value); DN_UT_Assert(&result, *value == desired_value); } for (DN_UT_Test(&result, "Remove key")) { - DN_DSMap_Erase(&map, key); + DN_DSMapErase(&map, key); DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); @@ -892,13 +893,13 @@ static DN_UTCore DN_Tests_BaseContainers() case DSMapTestType_MakeSlot: prefix = DN_Str8Lit("Make slot"); break; } - DN_ArenaTempMemScope temp_mem_scope = DN_ArenaTempMemScope(tmem.arena); + DN_ArenaTempMemScope temp_mem_scope = DN_ArenaTempMemScope(scratch.arena); DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); uint32_t const MAP_SIZE = 64; - DN_DSMap map = DN_DSMap_Init(&arena, MAP_SIZE, DN_DSMapFlags_Nil); + DN_DSMap map = DN_DSMapInit(&arena, MAP_SIZE, DN_DSMapFlags_Nil); DN_DEFER { - DN_DSMap_Deinit(&map, DN_ZMem_Yes); + DN_DSMapDeinit(&map, DN_ZMem_Yes); }; for (DN_UT_Test(&result, "%.*s: Test growing", DN_Str8PrintFmt(prefix))) { @@ -906,27 +907,27 @@ static DN_UTCore DN_Tests_BaseContainers() uint64_t value = 0; uint64_t grow_threshold = map_start_size * 3 / 4; for (; map.occupied != grow_threshold; value++) { - DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); - DN_UT_Assert(&result, !DN_DSMap_Find(&map, key).found); + DN_DSMapKey key = DN_DSMapKeyU64(&map, value); + DN_UT_Assert(&result, !DN_DSMapFind(&map, key).found); DN_DSMapResult make_result = {}; if (result_type == DSMapTestType_Set) - make_result = DN_DSMap_Set(&map, key, value); + make_result = DN_DSMapSet(&map, key, value); else - make_result = DN_DSMap_Make(&map, key); + make_result = DN_DSMapMake(&map, key); DN_UT_Assert(&result, !make_result.found); - DN_UT_Assert(&result, DN_DSMap_Find(&map, key).value); + DN_UT_Assert(&result, DN_DSMapFind(&map, key).value); } DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.size == map_start_size); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/ + value); { // NOTE: One more item should cause the table to grow by 2x - DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); + DN_DSMapKey key = DN_DSMapKeyU64(&map, value); DN_DSMapResult make_result = {}; if (result_type == DSMapTestType_Set) - make_result = DN_DSMap_Set(&map, key, value); + make_result = DN_DSMapSet(&map, key, value); else - make_result = DN_DSMap_Make(&map, key); + make_result = DN_DSMapMake(&map, key); value++; DN_UT_Assert(&result, !make_result.found); @@ -948,16 +949,16 @@ static DN_UTCore DN_Tests_BaseContainers() // NOTE: Validate each slot value uint64_t value_result = index - 1; - DN_DSMapKey key = DN_DSMap_KeyU64(&map, value_result); - DN_UT_Assert(&result, DN_DSMap_KeyEquals(slot->key, key)); + DN_DSMapKey key = DN_DSMapKeyU64(&map, value_result); + DN_UT_Assert(&result, DN_DSMapKeyEquals(slot->key, key)); if (result_type == DSMapTestType_Set) DN_UT_Assert(&result, slot->value == value_result); else DN_UT_Assert(&result, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 - DN_UT_Assert(&result, slot->key.hash == DN_DSMap_Hash(&map, slot->key)); + DN_UT_Assert(&result, slot->key.hash == DN_DSMapHash(&map, slot->key)); // NOTE: Check the reverse lookup is correct - DN_DSMapResult check = DN_DSMap_Find(&map, slot->key); + DN_DSMapResult check = DN_DSMapFind(&map, slot->key); DN_UT_Assert(&result, slot->value == *check.value); } } @@ -968,17 +969,17 @@ static DN_UTCore DN_Tests_BaseContainers() uint64_t value = 0; uint64_t shrink_threshold = map.size * 1 / 4; for (; map.occupied != shrink_threshold; value++) { - DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); - DN_UT_Assert(&result, DN_DSMap_Find(&map, key).found); - DN_DSMap_Erase(&map, key); - DN_UT_Assert(&result, !DN_DSMap_Find(&map, key).found); + DN_DSMapKey key = DN_DSMapKeyU64(&map, value); + DN_UT_Assert(&result, DN_DSMapFind(&map, key).found); + DN_DSMapErase(&map, key); + DN_UT_Assert(&result, !DN_DSMapFind(&map, key).found); } DN_UT_Assert(&result, map.size == start_map_size); DN_UT_Assert(&result, map.occupied == start_map_occupied - value); { // NOTE: One more item should cause the table to shrink by 2x - DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); - DN_DSMap_Erase(&map, key); + DN_DSMapKey key = DN_DSMapKeyU64(&map, value); + DN_DSMapErase(&map, key); value++; DN_UT_Assert(&result, map.size == start_map_size / 2); @@ -995,34 +996,35 @@ static DN_UTCore DN_Tests_BaseContainers() for (uint64_t index = 1 /*Sentinel*/; index < map.occupied; index++) { // NOTE: Generate the key uint64_t value_result = value + (index - 1); - DN_DSMapKey key = DN_DSMap_KeyU64(&map, value_result); + DN_DSMapKey key = DN_DSMapKeyU64(&map, value_result); // NOTE: Validate each slot value - DN_DSMapResult find_result = DN_DSMap_Find(&map, key); + DN_DSMapResult find_result = DN_DSMapFind(&map, key); DN_UT_Assert(&result, find_result.value); DN_UT_Assert(&result, find_result.slot->key == key); if (result_type == DSMapTestType_Set) DN_UT_Assert(&result, *find_result.value == value_result); else DN_UT_Assert(&result, *find_result.value == 0); // NOTE: Make slot does not set the key so should be 0 - DN_UT_Assert(&result, find_result.slot->key.hash == DN_DSMap_Hash(&map, find_result.slot->key)); + DN_UT_Assert(&result, find_result.slot->key.hash == DN_DSMapHash(&map, find_result.slot->key)); // NOTE: Check the reverse lookup is correct - DN_DSMapResult check = DN_DSMap_Find(&map, find_result.slot->key); + DN_DSMapResult check = DN_DSMapFind(&map, find_result.slot->key); DN_UT_Assert(&result, *find_result.value == *check.value); } for (; map.occupied != 1; value++) { // NOTE: Remove all items from the table - DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); - DN_UT_Assert(&result, DN_DSMap_Find(&map, key).found); - DN_DSMap_Erase(&map, key); - DN_UT_Assert(&result, !DN_DSMap_Find(&map, key).found); + DN_DSMapKey key = DN_DSMapKeyU64(&map, value); + DN_UT_Assert(&result, DN_DSMapFind(&map, key).found); + DN_DSMapErase(&map, key); + DN_UT_Assert(&result, !DN_DSMapFind(&map, key).found); } DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.size == map.initial_size); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); } } + DN_TCScratchEnd(&scratch); } DN_UT_LogF(&result, "DN_IArray\n"); @@ -1040,7 +1042,7 @@ static DN_UTCore DN_Tests_BaseContainers() array.max = DN_ArrayCountU(array_buffer); for (DN_UT_Test(&result, "Make item")) { - int *item = DN_IArray_Make(&array, DN_ZMem_Yes); + int *item = DN_IArrayMake(&array, DN_ZMem_Yes); DN_UT_Assert(&result, item && array.size == 1); } } @@ -1050,7 +1052,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Positive count, middle of array, stable erase")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Stable); int expected[] = {0, 1, 2, 5, 6, 7, 8, 9}; DN_UT_Assert(&result, erase.items_erased == 2); DN_UT_Assert(&result, erase.it_index == 3); @@ -1061,7 +1063,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Negative count, middle of array, stable erase")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Stable); int expected[] = {0, 1, 2, 6, 7, 8, 9}; DN_UT_Assert(&result, erase.items_erased == 3); DN_UT_Assert(&result, erase.it_index == 3); @@ -1072,7 +1074,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "count = -1, stable erase")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -1, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -1, DN_ArrayErase_Stable); int expected[] = {0, 1, 2, 3, 4, 6, 7, 8, 9}; DN_UT_Assert(&result, erase.items_erased == 1); DN_UT_Assert(&result, erase.it_index == 5); @@ -1083,7 +1085,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Positive count, unstable erase")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Unstable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Unstable); int expected[] = {0, 1, 2, 8, 9, 5, 6, 7}; DN_UT_Assert(&result, erase.items_erased == 2); DN_UT_Assert(&result, erase.it_index == 3); @@ -1094,7 +1096,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Negative count, unstable erase")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Unstable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Unstable); int expected[] = {0, 1, 2, 7, 8, 9, 6}; DN_UT_Assert(&result, erase.items_erased == 3); DN_UT_Assert(&result, erase.it_index == 3); @@ -1105,18 +1107,18 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Edge case - begin_index at start, negative count")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 0, -2, DN_ArrayErase_Stable); - int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - DN_UT_Assert(&result, erase.items_erased == 0); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 0, -2, DN_ArrayErase_Stable); + int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + DN_UT_Assert(&result, erase.items_erased == 1); DN_UT_Assert(&result, erase.it_index == 0); - DN_UT_Assert(&result, size == 10); + DN_UT_Assert(&result, size == 9); DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0); } for (DN_UT_Test(&result, "Edge case - begin_index at end, positive count")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 9, 2, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 9, 2, DN_ArrayErase_Stable); int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; DN_UT_Assert(&result, erase.items_erased == 1); DN_UT_Assert(&result, erase.it_index == 9); @@ -1127,7 +1129,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Invalid input - count = 0")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, 0, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 0, DN_ArrayErase_Stable); int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.it_index == 0); @@ -1137,7 +1139,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Invalid input - null data")) { DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(nullptr, &size, sizeof(int), 5, 2, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(nullptr, &size, sizeof(int), 5, 2, DN_ArrayErase_Stable); DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, size == 10); @@ -1145,7 +1147,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Invalid input - null size")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, NULL, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, NULL, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable); DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.it_index == 0); } @@ -1153,7 +1155,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Invalid input - empty array")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 0; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable); DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, size == 0); @@ -1162,7 +1164,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Out-of-bounds begin_index")) { int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_USize size = 10; - DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 15, 2, DN_ArrayErase_Stable); + DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 15, 2, DN_ArrayErase_Stable); int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.it_index == 10); @@ -1171,77 +1173,31 @@ static DN_UTCore DN_Tests_BaseContainers() } } - DN_UT_LogF(&result, "DN_FArray\n"); - { - for (DN_UT_Test(&result, "Initialise from raw array")) { - int raw_array[] = {1, 2}; - auto array = DN_FArray_Init(raw_array, DN_ArrayCountU(raw_array)); - DN_UT_Assert(&result, array.size == 2); - DN_UT_Assert(&result, array.data[0] == 1); - DN_UT_Assert(&result, array.data[1] == 2); - } - - for (DN_UT_Test(&result, "Erase stable 1 element from array")) { - int raw_array[] = {1, 2, 3}; - auto array = DN_FArray_Init(raw_array, DN_ArrayCountU(raw_array)); - DN_FArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable); - DN_UT_Assert(&result, array.size == 2); - DN_UT_Assert(&result, array.data[0] == 1); - DN_UT_Assert(&result, array.data[1] == 3); - } - - for (DN_UT_Test(&result, "Erase unstable 1 element from array")) { - int raw_array[] = {1, 2, 3}; - auto array = DN_FArray_Init(raw_array, DN_ArrayCountU(raw_array)); - DN_FArray_EraseRange(&array, 0 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable); - DN_UT_Assert(&result, array.size == 2); - DN_UT_Assert(&result, array.data[0] == 3); - DN_UT_Assert(&result, array.data[1] == 2); - } - - for (DN_UT_Test(&result, "Add 1 element to array")) { - int const ITEM = 2; - int raw_array[] = {1}; - auto array = DN_FArray_Init(raw_array, DN_ArrayCountU(raw_array)); - DN_FArray_Add(&array, ITEM); - DN_UT_Assert(&result, array.size == 2); - DN_UT_Assert(&result, array.data[0] == 1); - DN_UT_Assert(&result, array.data[1] == ITEM); - } - - for (DN_UT_Test(&result, "Clear array")) { - int raw_array[] = {1}; - auto array = DN_FArray_Init(raw_array, DN_ArrayCountU(raw_array)); - DN_FArray_Clear(&array); - DN_UT_Assert(&result, array.size == 0); - } - } - DN_UT_LogF(&result, "DN_VArray\n"); { { - DN_VArray array = DN_VArray_InitByteSize(DN_Kilobytes(64)); + DN_VArray array = DN_OS_VArrayInitByteSize(DN_Kilobytes(64)); DN_DEFER { - DN_VArray_Deinit(&array); + DN_OS_VArrayDeinit(&array); }; for (DN_UT_Test(&result, "Test adding an array of items to the array")) { uint32_t array_literal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - DN_VArray_AddArray(&array, array_literal, DN_ArrayCountU(array_literal)); + DN_OS_VArrayAddArray(&array, array_literal, DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); } for (DN_UT_Test(&result, "Test stable erase, 1 item, the '2' value from the array")) { - DN_VArray_EraseRange(&array, 2 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable); + DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable); uint32_t array_literal[] = {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); } for (DN_UT_Test(&result, "Test unstable erase, 1 item, the '1' value from the array")) { - DN_VArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable); + DN_OS_VArrayEraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable); uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); @@ -1251,49 +1207,49 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Test un/stable erase, OOB")) { for (DN_ArrayErase erase : erase_enums) { uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; - DN_VArray_EraseRange(&array, DN_ArrayCountU(array_literal) /*begin_index*/, DN_ArrayCountU(array_literal) + 100 /*count*/, erase); + DN_OS_VArrayEraseRange(&array, DN_ArrayCountU(array_literal) /*begin_index*/, DN_ArrayCountU(array_literal) + 100 /*count*/, erase); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); } } for (DN_UT_Test(&result, "Test flipped begin/end index stable erase, 2 items, the '15, 3' value from the array")) { - DN_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Stable); + DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Stable); uint32_t array_literal[] = {0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); } for (DN_UT_Test(&result, "Test flipped begin/end index unstable erase, 2 items, the '4, 5' value from the array")) { - DN_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Unstable); + DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Unstable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10, 11, 12}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); } for (DN_UT_Test(&result, "Test stable erase range, 2+1 (oob) item, the '13, 14, +1 OOB' value from the array")) { - DN_VArray_EraseRange(&array, 8 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Stable); + DN_OS_VArrayEraseRange(&array, 8 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Stable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); } for (DN_UT_Test(&result, "Test unstable erase range, 3+1 (oob) item, the '11, 12, +1 OOB' value from the array")) { - DN_VArray_EraseRange(&array, 6 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Unstable); + DN_OS_VArrayEraseRange(&array, 6 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Unstable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); } for (DN_UT_Test(&result, "Test stable erase -overflow OOB, erasing the '0, 13' value from the array")) { - DN_VArray_EraseRange(&array, 1 /*begin_index*/, -DN_ISIZE_MAX /*count*/, DN_ArrayErase_Stable); + DN_OS_VArrayEraseRange(&array, 1 /*begin_index*/, -DN_ISIZE_MAX /*count*/, DN_ArrayErase_Stable); uint32_t array_literal[] = {14, 6, 7, 8}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); } for (DN_UT_Test(&result, "Test unstable erase +overflow OOB, erasing the '7, 8' value from the array")) { - DN_VArray_EraseRange(&array, 2 /*begin_index*/, DN_ISIZE_MAX /*count*/, DN_ArrayErase_Unstable); + DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, DN_ISIZE_MAX /*count*/, DN_ArrayErase_Unstable); uint32_t array_literal[] = {14, 6}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); @@ -1301,7 +1257,7 @@ static DN_UTCore DN_Tests_BaseContainers() for (DN_UT_Test(&result, "Test adding an array of items after erase")) { uint32_t array_literal[] = {0, 1, 2, 3}; - DN_VArray_AddArray(&array, array_literal, DN_ArrayCountU(array_literal)); + DN_OS_VArrayAddArray(&array, array_literal, DN_ArrayCountU(array_literal)); uint32_t expected_literal[] = {14, 6, 0, 1, 2, 3}; DN_UT_Assert(&result, array.size == DN_ArrayCountU(expected_literal)); @@ -1331,16 +1287,16 @@ static DN_UTCore DN_Tests_BaseContainers() DN_MSVC_WARNING_POP - DN_VArray array = DN_VArray_InitByteSize(DN_Kilobytes(64)); + DN_VArray array = DN_OS_VArrayInitByteSize(DN_Kilobytes(64)); DN_DEFER { - DN_VArray_Deinit(&array); + DN_OS_VArrayDeinit(&array); }; // NOTE: Verify that the items returned from the data array are // contiguous in memory. - UnalignedObject *make_item_a = DN_VArray_MakeArray(&array, 1, DN_ZMem_Yes); - UnalignedObject *make_item_b = DN_VArray_MakeArray(&array, 1, DN_ZMem_Yes); + UnalignedObject *make_item_a = DN_OS_VArrayMakeArray(&array, 1, DN_ZMem_Yes); + UnalignedObject *make_item_b = DN_OS_VArrayMakeArray(&array, 1, DN_ZMem_Yes); DN_Memset(make_item_a->data, 'a', sizeof(make_item_a->data)); DN_Memset(make_item_b->data, 'b', sizeof(make_item_b->data)); DN_UT_Assert(&result, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1)); @@ -1642,8 +1598,8 @@ DN_Str8 const DN_UT_HASH_STRING_[] = void DN_Tests_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 input_hex = DN_HexFromBytesPtrArena(input.data, input.size, tmem.arena); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 input_hex = DN_HexFromBytesPtrArena(input.data, input.size, scratch.arena); switch (hash_type) { case Hash_SHA3_224: { @@ -1754,10 +1710,11 @@ void DN_Tests_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input) "\nhash: %.*s" "\nexpect: %.*s", DN_Str8PrintFmt(input_hex), - DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&hash).data), - DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&expect).data)); + DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&hash).data), + DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&expect).data)); } break; } + DN_TCScratchEnd(&scratch); } #endif // defined(DN_UNIT_TESTS_WITH_KECCAK) @@ -1845,10 +1802,11 @@ static DN_UTCore DN_Tests_OS() } for (DN_UT_Test(&result, "Query executable directory")) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 os_result = DN_OS_EXEDir(tmem.arena); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 os_result = DN_OS_EXEDir(scratch.arena); DN_UT_Assert(&result, os_result.size); DN_UT_AssertF(&result, DN_OS_PathIsDir(os_result), "result(%zu): %.*s", os_result.size, DN_Str8PrintFmt(os_result)); + DN_TCScratchEnd(&scratch); } for (DN_UT_Test(&result, "DN_OS_PerfCounterNow")) { @@ -1895,8 +1853,8 @@ static DN_UTCore DN_Tests_OS() DN_UT_Assert(&result, DN_OS_PathIsFile(SRC_FILE)); // NOTE: Read step - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 read_file = DN_OS_FileReadAllArena(tmem.arena, SRC_FILE, nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 read_file = DN_OS_FileReadAllArena(scratch.arena, SRC_FILE, nullptr); DN_UT_AssertF(&result, read_file.size, "Failed to load file"); DN_UT_AssertF(&result, read_file.size == 4, "File read wrong amount of bytes (%zu)", read_file.size); DN_UT_AssertF(&result, DN_Str8Eq(read_file, DN_Str8Lit("1234")), "Read %zu bytes instead of the expected 4: '%.*s'", read_file.size, DN_Str8PrintFmt(read_file)); @@ -1925,6 +1883,7 @@ static DN_UTCore DN_Tests_OS() DN_B32 delete_non_existent_moved_file = DN_OS_PathDelete(MOVE_FILE); DN_UT_Assert(&result, delete_non_existent_moved_file == false); DN_UT_Assert(&result, delete_non_existent_src_file == false); + DN_TCScratchEnd(&scratch); } } @@ -2147,22 +2106,24 @@ static DN_UTCore DN_Tests_Str8() } for (DN_UT_Test(&result, "Initialise with format string")) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 string = DN_Str8FromFmtArena(tmem.arena, "%s", "AB"); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 string = DN_Str8FromFmtArena(scratch.arena, "%s", "AB"); DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size); DN_UT_AssertF(&result, string.data[0] == 'A', "string[0]: %c", string.data[0]); DN_UT_AssertF(&result, string.data[1] == 'B', "string[1]: %c", string.data[1]); DN_UT_AssertF(&result, string.data[2] == 0, "string[2]: %c", string.data[2]); + DN_TCScratchEnd(&scratch); } for (DN_UT_Test(&result, "Copy string")) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_Str8 string = DN_Str8Lit("AB"); - DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, string); + DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, string); DN_UT_AssertF(&result, copy.size == 2, "size: %zu", copy.size); DN_UT_AssertF(&result, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]); DN_UT_AssertF(&result, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]); DN_UT_AssertF(&result, copy.data[2] == 0, "copy[2]: %c", copy.data[2]); + DN_TCScratchEnd(&scratch); } for (DN_UT_Test(&result, "Trim whitespace around string")) { @@ -2171,9 +2132,10 @@ static DN_UTCore DN_Tests_Str8() } for (DN_UT_Test(&result, "Allocate string from arena")) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 string = DN_Str8FromArena(tmem.arena, 2, DN_ZMem_No); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 string = DN_Str8FromArena(scratch.arena, 2, DN_ZMem_No); DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size); + DN_TCScratchEnd(&scratch); } // NOTE: TrimPrefix/Suffix ///////////////////////////////////////////////////////////////////// @@ -2448,28 +2410,28 @@ static DN_UTCore DN_Tests_Win() #if defined(DN_PLATFORM_WIN32) DN_UT_LogF(&result, "OS Win32\n"); { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_Str8 input8 = DN_Str8Lit("String"); DN_Str16 input16 = DN_Str16{(wchar_t *)(L"String"), sizeof(L"String") / sizeof(L"String"[0]) - 1}; for (DN_UT_Test(&result, "Str8 to Str16")) { - DN_Str16 str_result = DN_W32_Str8ToStr16(tmem.arena, input8); + DN_Str16 str_result = DN_OS_W32Str8ToStr16(scratch.arena, input8); DN_UT_Assert(&result, DN_Str16Eq(str_result, input16)); } for (DN_UT_Test(&result, "Str16 to Str8")) { - DN_Str8 str_result = DN_W32_Str16ToStr8(tmem.arena, input16); + DN_Str8 str_result = DN_OS_W32Str16ToStr8(scratch.arena, input16); DN_UT_Assert(&result, DN_Str8Eq(str_result, input8)); } for (DN_UT_Test(&result, "Str16 to Str8: Null terminates string")) { - int size_required = DN_W32_Str16ToStr8Buffer(input16, nullptr, 0); - char *string = DN_ArenaNewArray(tmem.arena, char, size_required + 1, DN_ZMem_No); + int size_required = DN_OS_W32Str16ToStr8Buffer(input16, nullptr, 0); + char *string = DN_ArenaNewArray(scratch.arena, char, size_required + 1, DN_ZMem_No); // Fill the string with error sentinels DN_Memset(string, 'Z', size_required + 1); - int size_returned = DN_W32_Str16ToStr8Buffer(input16, string, size_required + 1); + int size_returned = DN_OS_W32Str16ToStr8Buffer(input16, string, size_required + 1); char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; DN_UT_AssertF(&result, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); @@ -2478,14 +2440,15 @@ static DN_UTCore DN_Tests_Win() } for (DN_UT_Test(&result, "Str16 to Str8: Arena null terminates string")) { - DN_Str8 string8 = DN_W32_Str16ToStr8(tmem.arena, input16); - int size_returned = DN_W32_Str16ToStr8Buffer(input16, nullptr, 0); + DN_Str8 string8 = DN_OS_W32Str16ToStr8(scratch.arena, input16); + int size_returned = DN_OS_W32Str16ToStr8Buffer(input16, nullptr, 0); char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; DN_UT_AssertF(&result, DN_Cast(int) string8.size == size_returned, "string_size: %d, result: %d", DN_Cast(int) string8.size, size_returned); DN_UT_AssertF(&result, DN_Cast(int) string8.size == DN_ArrayCountU(EXPECTED) - 1, "string_size: %d, expected: %zu", DN_Cast(int) string8.size, DN_ArrayCountU(EXPECTED) - 1); DN_UT_Assert(&result, DN_Memcmp(EXPECTED, string8.data, sizeof(EXPECTED)) == 0); } + DN_TCScratchEnd(&scratch); } #endif // DN_PLATFORM_WIN32 return result; diff --git a/Source/Extra/dn_type_info.h b/Source/Extra/dn_type_info.h index 0782575..fe72119 100644 --- a/Source/Extra/dn_type_info.h +++ b/Source/Extra/dn_type_info.h @@ -2,7 +2,7 @@ #define DN_TYPE_INFO_H #if defined(_CLANGD) - #include "../dn_base_inc.h" + #include "../dn.h" #endif /* diff --git a/Source/OS/dn_os.cpp b/Source/OS/dn_os.cpp index f3dd014..00f72c5 100644 --- a/Source/OS/dn_os.cpp +++ b/Source/OS/dn_os.cpp @@ -1,8 +1,9 @@ #define DN_OS_CPP #if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" + #include "../Base/dn_base.h" + #include "../dn_os.h" + #include "../dn_os_w32.h" #endif #if defined(DN_PLATFORM_POSIX) @@ -10,45 +11,166 @@ #include // getpagesize #endif -static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) +static void *DN_ArenaBasicAllocFromOSHeap(DN_USize size) +{ + void *result = DN_OS_MemAlloc(size, DN_ZMem_Yes); + return result; +} + +DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet(DN_ArenaMemFuncType type) +{ + DN_ArenaMemFuncs 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_ArenaMemFuncType_VMem: { + result.type = DN_ArenaMemFuncType_VMem; + result.vmem_page_size = g_dn_->os.page_size; + result.vmem_reserve = DN_OS_MemReserve; + result.vmem_commit = DN_OS_MemCommit; + result.vmem_release = DN_OS_MemRelease; + } break; + } + return result; +} + +DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults() +{ + DN_ArenaMemFuncs result = {}; + #if defined(DN_PLATFORM_EMSCRIPTEN) + result = DN_ArenaMemFuncsGet(DN_ArenaMemFuncType_Basic); + #else + result = DN_ArenaMemFuncsGet(DN_ArenaMemFuncType_VMem); + #endif + return result; +} + +DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags) +{ + DN_ArenaMemFuncs mem_funcs = {}; + mem_funcs.type = DN_ArenaMemFuncType_Basic; + mem_funcs.basic_alloc = DN_ArenaBasicAllocFromOSHeap; + mem_funcs.basic_dealloc = DN_OS_MemDealloc; + DN_Arena result = DN_ArenaFromMemFuncs(size, size, flags, mem_funcs); + return result; +} + +DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags) +{ + DN_ArenaMemFuncs mem_funcs = {}; + mem_funcs.type = DN_ArenaMemFuncType_VMem; + mem_funcs.vmem_page_size = g_dn_->os.page_size; + mem_funcs.vmem_reserve = DN_OS_MemReserve; + mem_funcs.vmem_commit = DN_OS_MemCommit; + mem_funcs.vmem_release = DN_OS_MemRelease; + DN_Arena result = DN_ArenaFromMemFuncs(reserve, commit, flags, mem_funcs); + return result; +} + +DN_API DN_Str8 DN_Str8FromHeapF(DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_USize size = DN_FmtVSize(fmt, args); + DN_Str8 result = DN_Str8FromHeap(size, DN_ZMem_No); + DN_VSNPrintF(result.data, DN_Cast(int)(result.size + 1), fmt, args); + va_end(args); + return result; +} + +DN_API DN_Str8 DN_Str8FromHeap(DN_USize size, DN_ZMem z_mem) +{ + DN_Str8 result = {}; + result.data = DN_Cast(char *)DN_OS_MemAlloc(size + 1, z_mem); + if (result.data) { + result.size = size; + result.data[result.size] = 0; + } + return result; +} + +DN_API DN_Str8 DN_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_Str8BSplitResult split = DN_Str8BSplit(src, DN_Str8Lit("\n")); + while (split.lhs.size) { + DN_Str8BuilderAppendRef(&builder, pad); + DN_Str8BuilderAppendRef(&builder, split.lhs); + split = DN_Str8BSplit(split.rhs, DN_Str8Lit("\n")); + if (split.lhs.size) + DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n")); + } + DN_Str8 result = DN_Str8BuilderBuild(&builder, arena); + DN_TCScratchEnd(&scratch); + return result; +} + +DN_API DN_Str8 DN_Str8BuilderBuildFromHeap(DN_Str8Builder const *builder) +{ + DN_Str8 result = DN_ZeroInit; + if (!builder || builder->string_size <= 0 || builder->count <= 0) + return result; + + result.data = DN_Cast(char *) DN_OS_MemAlloc(builder->string_size + 1, DN_ZMem_No); + if (!result.data) + return result; + + for (DN_Str8Link *link = builder->head; link; link = link->next) { + DN_Memcpy(result.data + result.size, link->string.data, link->string.size); + result.size += link->string.size; + } + + result.data[result.size] = 0; + DN_Assert(result.size == builder->string_size); + return result; +} + +static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) { DN_Assert(user_data); DN_OSCore *core = DN_Cast(DN_OSCore *)user_data; - // NOTE: Open log file for appending if requested //////////////////////////////////////////////// + // NOTE: Open log file for appending if requested DN_TicketMutex_Begin(&core->log_file_mutex); if (core->log_to_file && !core->log_file.handle && !core->log_file.error) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_MSVC_WARNING_PUSH - DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(3) when a string is required in call to 'DN_OS_PathF' Actual type: 'struct DN_Str8'. - DN_Str8 log_path = DN_OS_PathF(tmem.arena, "%S/dn.log", DN_OS_EXEDir(tmem.arena)); - DN_MSVC_WARNING_POP + 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)); core->log_file = DN_OS_FileOpen(log_path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_AppendOnly, nullptr); + DN_TCScratchEnd(&scratch); } DN_TicketMutex_End(&core->log_file_mutex); - DN_LOGStyle style = {}; + DN_LogStyle style = {}; if (!core->log_no_colour) { style.colour = true; - style.bold = DN_LOGBold_Yes; + style.bold = DN_LogBold_Yes; if (type.is_u32_enum) { switch (type.u32) { - case DN_LOGType_Debug: { + case DN_LogType_Debug: { style.colour = false; - style.bold = DN_LOGBold_No; + style.bold = DN_LogBold_No; } break; - case DN_LOGType_Info: { + case DN_LogType_Info: { style.g = 0x87; style.b = 0xff; } break; - case DN_LOGType_Warning: { + case DN_LogType_Warning: { style.r = 0xff; style.g = 0xff; } break; - case DN_LOGType_Error: { + case DN_LogType_Error: { style.r = 0xff; } break; } @@ -56,7 +178,7 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data, } DN_Date os_date = DN_OS_DateLocalTimeNow(); - DN_LOGDate log_date = {}; + DN_LogDate log_date = {}; log_date.year = os_date.year; log_date.month = os_date.month; log_date.day = os_date.day; @@ -65,7 +187,7 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data, log_date.second = os_date.seconds; char prefix_buffer[128] = {}; - DN_LOGPrefixSize prefix_size = DN_LOG_MakePrefix(style, type, call_site, log_date, prefix_buffer, sizeof(prefix_buffer)); + DN_LogPrefixSize prefix_size = DN_LogMakePrefix(style, type, call_site, log_date, prefix_buffer, sizeof(prefix_buffer)); va_list args_copy; va_copy(args_copy, args); @@ -79,7 +201,7 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data, DN_TicketMutex_End(&core->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_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); @@ -88,7 +210,7 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data, DN_API void DN_OS_EmitLogsWithOSPrintFunctions(DN_OSCore *os) { DN_Assert(os); - DN_LOG_SetEmitFromTypeFVFunc(DN_OS_LOGEmitFromTypeTypeFV_, os); + DN_LogSetEmitFromTypeFVFunc(DN_OS_LOGEmitFromTypeTypeFV_, os); } DN_API void DN_OS_DumpThreadContextArenaStat(DN_Str8 file_path) @@ -98,14 +220,14 @@ DN_API void DN_OS_DumpThreadContextArenaStat(DN_Str8 file_path) FILE *file = nullptr; fopen_s(&file, file_path.data, "a+b"); if (file) { - DN_LOG_ErrorF("Failed to dump thread context arenas [file=%.*s]", DN_Str8PrintFmt(file_path)); + DN_LogErrorF("Failed to dump thread context arenas [file=%.*s]", DN_Str8PrintFmt(file_path)); return; } // NOTE: Copy the stats from library book-keeping // NOTE: Extremely short critical section, copy the stats then do our // work on it. - DN_ArenaStat stats[DN_CArray_CountI(g_dn_core->thread_context_arena_stats)]; + DN_ArenaStat stats[DN_ArrayCountU(g_dn_core->thread_context_arena_stats)]; int stats_size = 0; DN_TicketMutex_Begin(&g_dn_core->thread_context_mutex); @@ -151,39 +273,12 @@ DN_API void DN_OS_DumpThreadContextArenaStat(DN_Str8 file_path) } fclose(file); - DN_LOG_InfoF("Dumped thread context arenas [file=%.*s]", DN_Str8PrintFmt(file_path)); + DN_LogInfoF("Dumped thread context arenas [file=%.*s]", DN_Str8PrintFmt(file_path)); #else (void)file_path; #endif // #if defined(DN_DEBUG_THREAD_CONTEXT) } -DN_API DN_Str8 DN_OS_BytesFromHexPtrArenaFrame(void const *hex, DN_USize hex_count) -{ - DN_Arena *frame_arena = DN_OS_TLSFrameArena(); - DN_Str8 result = DN_BytesFromHexPtrArena(hex, hex_count, frame_arena); - return result; -} - -DN_API DN_Str8 DN_OS_BytesFromHexStr8ArenaFrame(DN_Str8 hex) -{ - DN_Str8 result = DN_OS_BytesFromHexPtrArenaFrame(hex.data, hex.size); - return result; -} - -DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaFrame(void const *bytes, DN_USize bytes_count) -{ - DN_Arena *frame_arena = DN_OS_TLSFrameArena(); - DN_Str8 result = DN_HexFromBytesPtrArena(bytes, bytes_count, frame_arena); - return result; -} - -DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS(void const *bytes, DN_USize bytes_count) -{ - DN_Arena *tls_arena = DN_OS_TLSArena(); - DN_Str8 result = DN_HexFromBytesPtrArena(bytes, bytes_count, tls_arena); - return result; -} - // NOTE: Date DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8(DN_Date time, char date_separator, char hms_separator) { @@ -214,11 +309,12 @@ DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena) DN_Str8 result = {}; if (!arena) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); - DN_Str8 exe_path = DN_OS_EXEPath(tmem.arena); - DN_Str8 separators[] = {DN_Str8Lit("/"), DN_Str8Lit("\\")}; - DN_Str8BSplitResult split = DN_Str8BSplitLastArray(exe_path, separators, DN_ArrayCountU(separators)); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); + DN_Str8 exe_path = DN_OS_EXEPath(scratch.arena); + DN_Str8 separators[] = {DN_Str8Lit("/"), DN_Str8Lit("\\")}; + DN_Str8BSplitResult split = DN_Str8BSplitLastArray(exe_path, separators, DN_ArrayCountU(separators)); result = DN_Str8FromStr8Arena(arena, split.lhs); + DN_TCScratchEnd(&scratch); return result; } @@ -316,7 +412,7 @@ DN_API bool DN_OS_PathIsOlderThan(DN_Str8 path, DN_Str8 check_against) return result; } -DN_API bool DN_OS_FileWrite(DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *error) +DN_API bool DN_OS_FileWrite(DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *error) { bool result = DN_OS_FileWritePtr(file, buffer.data, buffer.size, error); return result; @@ -324,7 +420,7 @@ DN_API bool DN_OS_FileWrite(DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *error struct DN_OSFileWriteChunker_ { - DN_OSErrSink *err; + DN_ErrSink *err; DN_OSFile *file; bool success; }; @@ -337,7 +433,7 @@ static char *DN_OS_FileWriteChunker_(const char *buf, void *user, int len) return result; } -DN_API bool DN_OS_FileWriteFV(DN_OSFile *file, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_FileWriteFV(DN_OSFile *file, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { bool result = false; if (!file || !fmt) @@ -353,7 +449,7 @@ DN_API bool DN_OS_FileWriteFV(DN_OSFile *file, DN_OSErrSink *error, DN_FMT_ATTRI return result; } -DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); @@ -362,13 +458,13 @@ DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_OSErrSink *error, DN_FMT_ATTRIB return result; } -DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err) +DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_ErrSink *err) { // NOTE: Query file size DN_Str8 result = {}; DN_OSPathInfo path_info = DN_OS_PathInfo(path); if (!path_info.exists) { - DN_OS_ErrSinkAppendF(err, 1, "File does not exist/could not be queried for reading '%.*s'", DN_Str8PrintFmt(path)); + DN_ErrSinkAppendF(err, 1, "File does not exist/could not be queried for reading '%.*s'", DN_Str8PrintFmt(path)); return result; } @@ -385,7 +481,7 @@ DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_St if (!result.data) { DN_Str8x32 bytes_str = DN_ByteCountStr8x32(path_info.size); - DN_OS_ErrSinkAppendF(err, 1 /*err_code*/, "Failed to allocate %.*s for reading file '%.*s'", DN_Str8PrintFmt(bytes_str), DN_Str8PrintFmt(path)); + DN_ErrSinkAppendF(err, 1 /*err_code*/, "Failed to allocate %.*s for reading file '%.*s'", DN_Str8PrintFmt(bytes_str), DN_Str8PrintFmt(path)); return result; } @@ -406,25 +502,19 @@ DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_St return result; } -DN_API DN_Str8 DN_OS_FileReadAllArena(DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err) +DN_API DN_Str8 DN_OS_FileReadAllArena(DN_Arena *arena, DN_Str8 path, DN_ErrSink *err) { DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, arena, path, err); return result; } -DN_API DN_Str8 DN_OS_FileReadAllPool(DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err) +DN_API DN_Str8 DN_OS_FileReadAllPool(DN_Pool *pool, DN_Str8 path, DN_ErrSink *err) { DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Pool, pool, path, err); return result; } -DN_API DN_Str8 DN_OS_FileReadAllTLS(DN_Str8 path, DN_OSErrSink *err) -{ - DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, DN_OS_TLSArena(), path, err); - return result; -} - -DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) +DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error) { DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_Write, error); bool result = DN_OS_FileWrite(&file, buffer, error); @@ -432,15 +522,16 @@ DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error return result; } -DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 buffer = DN_Str8FromFmtVArena(tmem.arena, fmt, args); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 buffer = DN_Str8FromFmtVArena(scratch.arena, fmt, args); bool result = DN_OS_FileWriteAll(file_path, buffer, error); + DN_TCScratchEnd(&scratch); return result; } -DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); @@ -449,28 +540,36 @@ DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_A return result; } -DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) +DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 tmp_path = DN_Str8FromFmtArena(tmem.arena, "%.*s.tmp", DN_Str8PrintFmt(path)); - if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 tmp_path = DN_Str8FromFmtArena(scratch.arena, "%.*s.tmp", DN_Str8PrintFmt(path)); + if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) { + DN_TCScratchEnd(&scratch); return false; - if (!DN_OS_FileCopy(tmp_path, path, true /*overwrite*/, error)) + } + if (!DN_OS_FileCopy(tmp_path, path, true /*overwrite*/, error)) { + DN_TCScratchEnd(&scratch); return false; - if (!DN_OS_PathDelete(tmp_path)) + } + if (!DN_OS_PathDelete(tmp_path)) { + DN_TCScratchEnd(&scratch); return false; + } + DN_TCScratchEnd(&scratch); return true; } -DN_API bool DN_OS_FileWriteAllSafeFV(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_FileWriteAllSafeFV(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 buffer = DN_Str8FromFmtVArena(tmem.arena, fmt, args); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 buffer = DN_Str8FromFmtVArena(scratch.arena, fmt, args); bool result = DN_OS_FileWriteAllSafe(path, buffer, error); + DN_TCScratchEnd(&scratch); return result; } -DN_API bool DN_OS_FileWriteAllSafeF(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_FileWriteAllSafeF(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); @@ -521,18 +620,6 @@ DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) return true; } -DN_API bool DN_OS_PathAddRefTLS(DN_OSPath *fs_path, DN_Str8 path) -{ - bool result = DN_OS_PathAddRef(DN_OS_TLSTopArena(), fs_path, path); - return result; -} - -DN_API bool DN_OS_PathAddRefFrame(DN_OSPath *fs_path, DN_Str8 path) -{ - bool result = DN_OS_PathAddRef(DN_OS_TLSFrameArena(), fs_path, path); - return result; -} - DN_API bool DN_OS_PathAdd(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) { DN_Str8 copy = DN_Str8FromStr8Arena(arena, path); @@ -581,12 +668,13 @@ DN_API DN_Str8 DN_OS_PathTo(DN_Arena *arena, DN_Str8 path, DN_Str8 path_separato DN_API DN_Str8 DN_OS_PathToF(DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); va_list args; va_start(args, fmt); - DN_Str8 path = DN_Str8FromFmtVArena(tmem.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); return result; } @@ -598,12 +686,13 @@ DN_API DN_Str8 DN_OS_Path(DN_Arena *arena, DN_Str8 path) DN_API DN_Str8 DN_OS_PathF(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); va_list args; va_start(args, fmt); - DN_Str8 path = DN_Str8FromFmtVArena(tmem.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); return result; } @@ -639,11 +728,11 @@ DN_API DN_Str8 DN_OS_PathBuildWithSeparator(DN_Arena *arena, DN_OSPath const *fs return result; } -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSExec DN_API DN_OSExecResult DN_OS_Exec(DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena, - DN_OSErrSink *error) + DN_ErrSink *error) { DN_OSExecAsyncHandle async_handle = DN_OS_ExecAsync(cmd_line, args, error); DN_OSExecResult result = DN_OS_ExecWait(async_handle, arena, error); @@ -652,38 +741,36 @@ DN_API DN_OSExecResult DN_OS_Exec(DN_Slice cmd_line, DN_API DN_OSExecResult DN_OS_ExecOrAbort(DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena) { - DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); + DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil); DN_OSExecResult result = DN_OS_Exec(cmd_line, args, arena, error); if (result.os_error_code) - DN_OS_ErrSinkEndAndExitIfErrorF(error, result.os_error_code, "OS failed to execute the requested command returning the error code %u", result.os_error_code); + DN_ErrSinkEndExitIfErrorF(error, result.os_error_code, "OS failed to execute the requested command returning the error code %u", result.os_error_code); if (result.exit_code) - DN_OS_ErrSinkEndAndExitIfErrorF(error, result.exit_code, "OS executed command and returned non-zero exit code %u", result.exit_code); - DN_OS_ErrSinkEndAndIgnore(error); + DN_ErrSinkEndExitIfErrorF(error, result.exit_code, "OS executed command and returned non-zero exit code %u", result.exit_code); + DN_ErrSinkEndIgnore(error); return result; } -// NOTE: DN_OSThread /////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSThread static void DN_OS_ThreadExecute_(void *user_context) { - DN_OSThread *thread = DN_Cast(DN_OSThread *) user_context; - DN_OS_TLSInit(&thread->tls, thread->tls_init_args); - DN_OS_TLSSetCurrentThreadTLS(&thread->tls); + DN_OSThread *thread = DN_Cast(DN_OSThread *) user_context; + DN_ArenaMemFuncs mem_funcs = DN_ArenaMemFuncsGetDefaults(); + DN_TCInitFromMemFuncs(&thread->context, thread->thread_id, /*args=*/nullptr, mem_funcs); + DN_TCEquip(&thread->context); DN_OS_SemaphoreWait(&thread->init_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); thread->func(thread); } DN_API void DN_OS_ThreadSetName(DN_Str8 name) { - DN_OSTLS *tls = DN_OS_TLSGet(); - tls->name_size = DN_Cast(uint8_t) DN_Min(name.size, sizeof(tls->name) - 1); - DN_Memcpy(tls->name, name.data, tls->name_size); - tls->name[tls->name_size] = 0; - + DN_TCCore *tls = DN_TCGet(); + tls->name = DN_Str8x64FromFmt("%.*s", DN_Str8PrintFmt(name)); #if defined(DN_PLATFORM_WIN32) - DN_W32_ThreadSetName(name); + DN_OS_W32ThreadSetName(name); #else - DN_Posix_ThreadSetName(name); + DN_OS_PosixThreadSetName(name); #endif } @@ -698,10 +785,570 @@ DN_API DN_OSHttpResponse DN_OS_HttpRequest(DN_Arena *arena, DN_Str8 host, DN_Str { // TODO(doyle): Revise the memory allocation and its lifetime DN_OSHttpResponse result = {}; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); - result.tmem_arena = tmem.arena; + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); + result.scratch_arena = scratch.arena; DN_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers); DN_OS_HttpRequestWait(&result); + DN_TCScratchEnd(&scratch); return result; } + +// NOTE: DN_OSPrint +DN_API DN_LogStyle DN_OS_PrintStyleColour(uint8_t r, uint8_t g, uint8_t b, DN_LogBold bold) +{ + DN_LogStyle result = {}; + result.bold = bold; + result.colour = true; + result.r = r; + result.g = g; + result.b = b; + return result; +} + +DN_API DN_LogStyle DN_OS_PrintStyleColourU32(uint32_t rgb, DN_LogBold bold) +{ + uint8_t r = (rgb >> 24) & 0xFF; + uint8_t g = (rgb >> 16) & 0xFF; + uint8_t b = (rgb >> 8) & 0xFF; + DN_LogStyle result = DN_OS_PrintStyleColour(r, g, b, bold); + return result; +} + +DN_API DN_LogStyle DN_OS_PrintStyleBold() +{ + DN_LogStyle result = {}; + result.bold = DN_LogBold_Yes; + return result; +} + +DN_API void DN_OS_Print(DN_OSPrintDest dest, DN_Str8 string) +{ + DN_Assert(dest == DN_OSPrintDest_Out || dest == DN_OSPrintDest_Err); + +#if defined(DN_PLATFORM_WIN32) + // NOTE: Get the output handles from kernel + DN_THREAD_LOCAL void *std_out_print_handle = nullptr; + DN_THREAD_LOCAL void *std_err_print_handle = nullptr; + DN_THREAD_LOCAL bool std_out_print_to_console = false; + DN_THREAD_LOCAL bool std_err_print_to_console = false; + + if (!std_out_print_handle) { + unsigned long mode = 0; + (void)mode; + std_out_print_handle = GetStdHandle(STD_OUTPUT_HANDLE); + std_out_print_to_console = GetConsoleMode(std_out_print_handle, &mode) != 0; + + std_err_print_handle = GetStdHandle(STD_ERROR_HANDLE); + std_err_print_to_console = GetConsoleMode(std_err_print_handle, &mode) != 0; + } + + // NOTE: Select the output handle + void *print_handle = std_out_print_handle; + bool print_to_console = std_out_print_to_console; + if (dest == DN_OSPrintDest_Err) { + print_handle = std_err_print_handle; + print_to_console = std_err_print_to_console; + } + + // NOTE: Write the string + DN_Assert(string.size < DN_Cast(unsigned long) - 1); + unsigned long bytes_written = 0; + (void)bytes_written; + if (print_to_console) + WriteConsoleA(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr); + else + WriteFile(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr); +#else + fprintf(dest == DN_OSPrintDest_Out ? stdout : stderr, "%.*s", DN_Str8PrintFmt(string)); +#endif +} + +DN_API void DN_OS_PrintF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_OS_PrintFV(dest, fmt, args); + va_end(args); +} + +DN_API void DN_OS_PrintFStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_OS_PrintFVStyle(dest, style, fmt, args); + va_end(args); +} + +DN_API void DN_OS_PrintStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string) +{ + if (string.data && string.size) { + if (style.colour) + DN_OS_Print(dest, DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType_Fg, style.r, style.g, style.b)); + if (style.bold == DN_LogBold_Yes) + DN_OS_Print(dest, DN_Str8Lit(DN_LogBoldEscapeCode)); + DN_OS_Print(dest, string); + if (style.colour || style.bold == DN_LogBold_Yes) + DN_OS_Print(dest, DN_Str8Lit(DN_LogResetEscapeCode)); + } +} + +static char *DN_OS_PrintVSPrintfChunker_(const char *buf, void *user, int len) +{ + DN_Str8 string = {}; + string.data = DN_Cast(char *) buf; + string.size = len; + + DN_OSPrintDest dest = DN_Cast(DN_OSPrintDest) DN_Cast(uintptr_t) user; + DN_OS_Print(dest, string); + return (char *)buf; +} + +DN_API void DN_OS_PrintFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + char buffer[STB_SPRINTF_MIN]; + STB_SPRINTF_DECORATE(vsprintfcb) + (DN_OS_PrintVSPrintfChunker_, DN_Cast(void *) DN_Cast(uintptr_t) dest, buffer, fmt, args); +} + +DN_API void DN_OS_PrintFVStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + if (fmt) { + if (style.colour) + DN_OS_Print(dest, DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType_Fg, style.r, style.g, style.b)); + if (style.bold == DN_LogBold_Yes) + DN_OS_Print(dest, DN_Str8Lit(DN_LogBoldEscapeCode)); + DN_OS_PrintFV(dest, fmt, args); + if (style.colour || style.bold == DN_LogBold_Yes) + DN_OS_Print(dest, DN_Str8Lit(DN_LogResetEscapeCode)); + } +} + +DN_API void DN_OS_PrintLn(DN_OSPrintDest dest, DN_Str8 string) +{ + DN_OS_Print(dest, string); + DN_OS_Print(dest, DN_Str8Lit("\n")); +} + +DN_API void DN_OS_PrintLnF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_OS_PrintLnFV(dest, fmt, args); + va_end(args); +} + +DN_API void DN_OS_PrintLnFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_OS_PrintFV(dest, fmt, args); + DN_OS_Print(dest, DN_Str8Lit("\n")); +} + +DN_API void DN_OS_PrintLnStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string) +{ + DN_OS_PrintStyle(dest, style, string); + DN_OS_Print(dest, DN_Str8Lit("\n")); +} + +DN_API void DN_OS_PrintLnFStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_OS_PrintLnFVStyle(dest, style, fmt, args); + va_end(args); +} + +DN_API void DN_OS_PrintLnFVStyle(DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_OS_PrintFVStyle(dest, style, fmt, args); + DN_OS_Print(dest, DN_Str8Lit("\n")); +} + +// NOTE: DN_VArray +template +DN_VArray DN_OS_VArrayInitByteSize(DN_USize byte_size) +{ + DN_VArray result = {}; + result.data = DN_Cast(T *) DN_OS_MemReserve(byte_size, DN_MemCommit_No, DN_MemPage_ReadWrite); + if (result.data) + result.max = byte_size / sizeof(T); + return result; +} + +template +DN_VArray DN_OS_VArrayInit(DN_USize max) +{ + DN_VArray result = DN_OS_VArrayInitByteSize(max * sizeof(T)); + DN_Assert(result.max >= max); + return result; +} + +template +DN_VArray DN_OS_VArrayInitSlice(DN_Slice slice, DN_USize max) +{ + DN_USize real_max = DN_Max(slice.size, max); + DN_VArray result = DN_OS_VArrayInit(real_max); + if (DN_OS_VArrayIsValid(&result)) + DN_OS_VArrayAddArray(&result, slice.data, slice.size); + return result; +} + +template +DN_VArray DN_OS_VArrayInitCArray(T const (&items)[N], DN_USize max) +{ + DN_USize real_max = DN_Max(N, max); + DN_VArray result = DN_OS_VArrayInitSlice(DN_Slice_Init(items, N), real_max); + return result; +} + +template +void DN_OS_VArrayDeinit(DN_VArray *array) +{ + DN_OS_MemRelease(array->data, array->max * sizeof(T)); + *array = {}; +} + +template +bool DN_OS_VArrayIsValid(DN_VArray const *array) +{ + bool result = array->data && array->size <= array->max; + return result; +} + +template +T *DN_OS_VArrayAddArray(DN_VArray *array, T const *items, DN_USize count) +{ + T *result = DN_OS_VArrayMakeArray(array, count, DN_ZMem_No); + if (result) + DN_Memcpy(result, items, count * sizeof(T)); + return result; +} + +template +T *DN_OS_VArrayAddCArray(DN_VArray *array, T const (&items)[N]) +{ + T *result = DN_OS_VArrayAddArray(array, items, N); + return result; +} + +template +T *DN_OS_VArrayAdd(DN_VArray *array, T const &item) +{ + T *result = DN_OS_VArrayAddArray(array, &item, 1); + return result; +} + +template +T *DN_OS_VArrayMakeArray(DN_VArray *array, DN_USize count, DN_ZMem z_mem) +{ + if (!DN_OS_VArrayIsValid(array)) + return nullptr; + + if (!DN_CheckF((array->size + count) < array->max, "Array is out of space (user requested +%zu items, array has %zu/%zu items)", count, array->size, array->max)) + return nullptr; + + if (!DN_OS_VArrayReserve(array, count)) + return nullptr; + + // TODO: Use placement new + T *result = array->data + array->size; + array->size += count; + if (z_mem == DN_ZMem_Yes) + DN_Memset(result, 0, count * sizeof(T)); + return result; +} + +template +T *DN_OS_VArrayMake(DN_VArray *array, DN_ZMem z_mem) +{ + T *result = DN_OS_VArrayMakeArray(array, 1, z_mem); + return result; +} + +template +T *DN_OS_VArrayInsertArray(DN_VArray *array, DN_USize index, T const *items, DN_USize count) +{ + T *result = nullptr; + if (!DN_OS_VArrayIsValid(array)) + return result; + if (DN_OS_VArrayReserve(array, array->size + count)) + result = DN_CArrayInsertArray(array->data, &array->size, array->max, index, items, count); + return result; +} + +template +T *DN_OS_VArrayInsertCArray(DN_VArray *array, DN_USize index, T const (&items)[N]) +{ + T *result = DN_OS_VArrayInsertArray(array, index, items, N); + return result; +} + +template +T *DN_OS_VArrayInsert(DN_VArray *array, DN_USize index, T const &item) +{ + T *result = DN_OS_VArrayInsertArray(array, index, &item, 1); + return result; +} + +template +T *DN_OS_VArrayPopFront(DN_VArray *array, DN_USize count) +{ + T *result = DN_Cast(T *)DN_CArrayPopFront(array->data, &array->size, sizeof(T), count); + return result; +} + +template +T *DN_OS_VArrayPopBack(DN_VArray *array, DN_USize count) +{ + T *result = DN_Cast(T *)DN_CArrayPopBack(array->data, &array->size, sizeof(T), count); + return result; +} + +template +DN_ArrayEraseResult DN_OS_VArrayEraseRange(DN_VArray *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase) +{ + DN_ArrayEraseResult result = {}; + if (!DN_OS_VArrayIsValid(array)) + return result; + result = DN_CArrayEraseRange(array->data, &array->size, sizeof(T), begin_index, count, erase); + return result; +} + +template +void DN_OS_VArrayClear(DN_VArray *array, DN_ZMem z_mem) +{ + if (array) { + if (z_mem == DN_ZMem_Yes) + DN_Memset(array->data, 0, array->size * sizeof(T)); + array->size = 0; + } +} + +template +bool DN_OS_VArrayReserve(DN_VArray *array, DN_USize count) +{ + if (!DN_OS_VArrayIsValid(array) || count == 0) + return false; + + DN_USize real_commit = (array->size + count) * sizeof(T); + DN_USize aligned_commit = DN_AlignUpPowerOfTwo(real_commit, g_dn_->os.page_size); + if (array->commit >= aligned_commit) + return true; + bool result = DN_OS_MemCommit(array->data, aligned_commit, DN_MemPage_ReadWrite); + array->commit = aligned_commit; + return result; +} + +// NOTE: Stack Trace +DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, DN_U16 limit) +{ + DN_StackTraceWalkResult result = {}; +#if defined(DN_OS_WIN32) + if (!arena) + return result; + + static DN_TicketMutex mutex = {}; + DN_TicketMutex_Begin(&mutex); + + HANDLE thread = GetCurrentThread(); + result.process = GetCurrentProcess(); + + DN_OSW32Core *w32 = DN_OS_W32GetCore(); + if (!w32->sym_initialised) { + w32->sym_initialised = true; + SymSetOptions(SYMOPT_LOAD_LINES); + if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) { + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); + DN_OSW32Error error = DN_OS_W32LastError(scratch.arena); + DN_LogErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_Str8PrintFmt(error.msg)); + DN_TCScratchEnd(&scratch); + } + } + + CONTEXT context; + RtlCaptureContext(&context); + + STACKFRAME64 frame = {}; + frame.AddrPC.Offset = context.Rip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Rbp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Rsp; + frame.AddrStack.Mode = AddrModeFlat; + + DN_U64 raw_frames[256] = {}; + DN_USize raw_frames_count = 0; + while (raw_frames_count < limit) { + if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64, + result.process, + thread, + &frame, + &context, + nullptr /*ReadMemoryRoutine*/, + SymFunctionTableAccess64, + SymGetModuleBase64, + nullptr /*TranslateAddress*/)) + break; + + // NOTE: It might be useful one day to use frame.AddrReturn.Offset. + // If AddrPC.Offset == AddrReturn.Offset then we can detect recursion. + DN_LArrayAppend(raw_frames, &raw_frames_count, frame.AddrPC.Offset); + } + DN_TicketMutex_End(&mutex); + + result.base_addr = DN_ArenaNewArray(arena, DN_U64, raw_frames_count, DN_ZMem_No); + result.size = DN_Cast(DN_U16) raw_frames_count; + DN_Memcpy(result.base_addr, raw_frames, raw_frames_count * sizeof(raw_frames[0])); +#else + (void)limit; + (void)arena; +#endif + return result; +} + +static void DN_StackTraceAddWalkToStr8Builder(DN_StackTraceWalkResult const *walk, DN_Str8Builder *builder, DN_USize skip) +{ + DN_StackTraceRawFrame raw_frame = {}; + raw_frame.process = walk->process; + for (DN_USize index = skip; index < walk->size; index++) { + raw_frame.base_addr = walk->base_addr[index]; + DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(builder->arena, raw_frame); + DN_Str8BuilderAppendF(builder, "%.*s(%zu): %.*s%s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name), (DN_Cast(int) index == walk->size - 1) ? "" : "\n"); + } +} + +DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk) +{ + bool result = false; + if (!it || !walk || !walk->base_addr || !walk->process) + return result; + + if (it->index >= walk->size) + return false; + + result = true; + it->raw_frame.process = walk->process; + it->raw_frame.base_addr = walk->base_addr[it->index++]; + return result; +} + +DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip) +{ + DN_Str8 result{}; + if (!walk || !arena) + return result; + + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); + DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena); + DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip); + result = DN_Str8BuilderBuild(&builder, arena); + DN_TCScratchEnd(&scratch); + return result; +} + +DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, DN_U16 limit, DN_U16 skip) +{ + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); + DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, limit); + DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip); + DN_TCScratchEnd(&scratch); + return result; +} + +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_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); + return result; +} + +DN_API DN_StackTraceFrameSlice DN_StackTraceGetFrames(DN_Arena *arena, DN_U16 limit) +{ + DN_StackTraceFrameSlice result = {}; + if (!arena) + return result; + + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); + DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, limit); + if (walk.size) { + if (DN_ISliceAllocArena(DN_StackTraceFrameSlice, &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); + } + } + DN_TCScratchEnd(&scratch); + return result; +} + +DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame(DN_Arena *arena, DN_StackTraceRawFrame raw_frame) +{ +#if defined(DN_OS_WIN32) + // NOTE: Get line+filename + + // TODO: Why does zero-initialising this with `line = {};` cause + // SymGetLineFromAddr64 function to fail once we are at + // __scrt_commain_main_seh and hit BaseThreadInitThunk frame? The + // line and file number are still valid in the result which we use, so, + // we silently ignore this error. + IMAGEHLP_LINEW64 line; + line.SizeOfStruct = sizeof(line); + DWORD line_displacement = 0; + if (!SymGetLineFromAddrW64(raw_frame.process, raw_frame.base_addr, &line_displacement, &line)) + line = {}; + + // NOTE: Get function name + + alignas(SYMBOL_INFOW) char buffer[sizeof(SYMBOL_INFOW) + (MAX_SYM_NAME * sizeof(wchar_t))] = {}; + SYMBOL_INFOW *symbol = DN_Cast(SYMBOL_INFOW *) buffer; + symbol->SizeOfStruct = sizeof(*symbol); + symbol->MaxNameLen = sizeof(buffer) - sizeof(*symbol); + + uint64_t symbol_displacement = 0; // Offset to the beginning of the symbol to the address + SymFromAddrW(raw_frame.process, raw_frame.base_addr, &symbol_displacement, symbol); + + // NOTE: Construct result + + DN_Str16 file_name16 = DN_Str16FromPtr(line.FileName, DN_CStr16Size(line.FileName)); + DN_Str16 function_name16 = DN_Str16FromPtr(symbol->Name, symbol->NameLen); + + DN_StackTraceFrame result = {}; + result.address = raw_frame.base_addr; + result.line_number = line.LineNumber; + result.file_name = DN_OS_W32Str16ToStr8(arena, file_name16); + result.function_name = DN_OS_W32Str16ToStr8(arena, function_name16); + + if (result.function_name.size == 0) + result.function_name = DN_Str8Lit(""); + if (result.file_name.size == 0) + result.file_name = DN_Str8Lit(""); +#else + DN_StackTraceFrame result = {}; +#endif + return result; +} + +DN_API void DN_StackTracePrint(DN_U16 limit) +{ + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + 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)); + } + DN_TCScratchEnd(&scratch); +} + +DN_API void DN_StackTraceReloadSymbols() +{ +#if defined(DN_OS_WIN32) + HANDLE process = GetCurrentProcess(); + SymRefreshModuleList(process); +#endif +} diff --git a/Source/OS/dn_os.h b/Source/OS/dn_os.h index d77f1f6..90d9a88 100644 --- a/Source/OS/dn_os.h +++ b/Source/OS/dn_os.h @@ -2,8 +2,8 @@ #define DN_OS_H #if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" + #define DN_H_WITH_OS 1 + #include "../dn.h" #endif #include // operator new @@ -123,7 +123,7 @@ struct DN_OSPath DN_OSPathLink *head; DN_OSPathLink *tail; DN_USize string_size; - DN_U16 links_size; + DN_U16 links_size; }; // NOTE: DN_OSExec @@ -197,8 +197,7 @@ typedef DN_I32(DN_OSThreadFunc)(struct DN_OSThread *); struct DN_OSThread { DN_Str8x64 name; - DN_OSTLS tls; - DN_OSTLSInitArgs tls_init_args; + DN_TCCore context; void *handle; DN_U64 thread_id; void *user_context; @@ -229,7 +228,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 *tmem_arena; + DN_Arena *scratch_arena; DN_Str8Builder builder; DN_OSSemaphore on_complete_semaphore; @@ -245,10 +244,9 @@ struct DN_OSHttpResponse struct DN_OSCore { DN_CPUReport cpu_report; - DN_OSTLS tls; // Thread local storage state for the main thread. // NOTE: Logging - DN_LOGEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine + DN_LogEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine void * log_user_data; // User pointer passed into 'log_callback' bool log_to_file; // Output logs to file as well as standard out DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ? @@ -280,14 +278,19 @@ 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_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem); +DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder); + DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os); DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path); -DN_API DN_Str8 DN_OS_BytesFromHexPtrArenaFrame (void const *hex, DN_USize hex_count); -DN_API DN_Str8 DN_OS_BytesFromHexStr8ArenaFrame (DN_Str8 hex); -DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaFrame (void const *bytes, DN_USize bytes_count); -DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS (void const *bytes, DN_USize bytes_count); - DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags); DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags); DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size); @@ -312,7 +315,6 @@ DN_API bool DN_OS_SetEnvVar (D DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path); DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena); DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena); -#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena()) DN_API void DN_OS_SleepMs (DN_UInt milliseconds); DN_API DN_U64 DN_OS_PerfCounterNow (); @@ -329,28 +331,28 @@ DN_API DN_F64 DN_OS_TimerUs (D DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer); DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency); -DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); -DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); +DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err); +DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err); -DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err); -DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err); -DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err); -DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); -DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err); +DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_ErrSink *err); +DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err); +DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_ErrSink *err); +DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *err); +DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_ErrSink *err); DN_API void DN_OS_FileClose (DN_OSFile *file); -DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err); -DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err); -DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err); -DN_API DN_Str8 DN_OS_FileReadAllTLS (DN_Str8 path, DN_OSErrSink *err); -DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); -DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_ErrSink *err); +DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_ErrSink *err); +DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_ErrSink *err); + +DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err); +DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err); +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_OSPathInfo DN_OS_PathInfo (DN_Str8 path); DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against); @@ -361,42 +363,25 @@ DN_API bool DN_OS_PathMakeDir (D DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it); DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); -DN_API bool DN_OS_PathAddRefTLS (DN_OSPath *fs_path, DN_Str8 path); -DN_API bool DN_OS_PathAddRefFrame (DN_OSPath *fs_path, DN_Str8 path); DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); -#define DN_OS_PathAddFromTLS(...) DN_OS_PathAdd(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathAddFromFrame(...) DN_OS_PathAdd(DN_OS_TLSFrameArena(), ##__VA_ARGS__) DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...); -#define DN_OS_PathAddFFromTLS(...) DN_OS_PathAddF(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathAddFFromFrame(...) DN_OS_PathAddF(DN_OS_TLSFrameArena(), ##__VA_ARGS__) DN_API bool DN_OS_PathPop (DN_OSPath *fs_path); DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator); -#define DN_OS_PathBuildWithSeperatorFromTLS(...) DN_OS_PathBuildWithSeperator(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathBuildWithSeperatorFromFrame(...) DN_OS_PathBuildWithSeperator(DN_OS_TLSFrameArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor); -#define DN_OS_PathToFromTLS(...) DN_OS_PathTo(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathToFromFrame(...) DN_OS_PathTo(DN_OS_TLSFrameArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...); -#define DN_OS_PathToFFromTLS(...) DN_OS_PathToF(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathToFFromFrame(...) DN_OS_PathToF(DN_OS_TLSFrameArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path); -#define DN_OS_PathFromTLS(...) DN_OS_Path(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathFromFrame(...) DN_OS_Path(DN_OS_TLSFrameArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); -#define DN_OS_PathFFromTLS(...) DN_OS_PathF(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathFFromFrame(...) DN_OS_PathF(DN_OS_TLSFrameArena(), ##__VA_ARGS__) #define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("/")) #define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("\\")) #define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString) DN_API void DN_OS_Exit (int32_t exit_code); -DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err); -DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err); -DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err); -DN_API DN_OSExecResult DN_OS_Exec (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err); +DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_ErrSink *err); +DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_ErrSink *err); +DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice cmd_line, DN_OSExecArgs *args, DN_ErrSink *err); +DN_API DN_OSExecResult DN_OS_Exec (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_ErrSink *err); DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena); -#define DN_OS_ExecOrAbortFromTLS (...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena()) DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count); DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore); @@ -426,4 +411,104 @@ DN_API void DN_OS_HttpRequestAsync (D DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response); DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response); DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); + +// NOTE: DN_OSPrint +enum DN_OSPrintDest +{ + DN_OSPrintDest_Out, + DN_OSPrintDest_Err, +}; + +// NOTE: Print Macros +#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string) +#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__) +#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args) + +#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string) +#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__) +#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args) + +#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string) +#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__) +#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args) + +#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string); +#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__) +#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args); + +#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string) +#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__) +#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args) + +#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string) +#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__) +#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args) + +#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string) +#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__) +#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args) + +#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string); +#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__) +#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args); + +// NOTE: Print +DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string); +DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args); + +DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string); +DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args); + +DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string); +DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args); + +DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string); +DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args); + +// NOTE: DN_VArray +// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS. +template struct DN_VArray +{ + T *data; // Pointer to the start of the array items in the block of memory + DN_USize size; // Number of items currently in the array + DN_USize max; // Maximum number of items this array can store + DN_USize commit; // Bytes committed + + T *begin() { return data; } + T *end () { return data + size; } + T const *begin() const { return data; } + T const *end () const { return data + size; } +}; + +template DN_VArray DN_OS_VArrayInitByteSize (DN_USize byte_size); +template DN_VArray DN_OS_VArrayInit (DN_USize max); +template DN_VArray DN_OS_VArrayInitSlice (DN_Slice slice, DN_USize max); +template DN_VArray DN_OS_VArrayInitCArray (T const (&items)[N], DN_USize max); +template void DN_OS_VArrayDeinit (DN_VArray *array); +template bool DN_OS_VArrayIsValid (DN_VArray const *array); +template bool DN_OS_VArrayReserve (DN_VArray *array, DN_USize count); +template T * DN_OS_VArrayAddArray (DN_VArray *array, T const *items, DN_USize count); +template T * DN_OS_VArrayAddCArray (DN_VArray *array, T const (&items)[N]); +template T * DN_OS_VArrayAdd (DN_VArray *array, T const &item); +#define DN_OS_VArrayAddArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddArray(__VA_ARGS__)) +#define DN_OS_VArrayAddCArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddCArray(__VA_ARGS__)) +#define DN_OS_VArrayAddAssert(...) DN_HardAssert(DN_OS_VArrayAdd(__VA_ARGS__)) +template T * DN_OS_VArrayMakeArray (DN_VArray *array, DN_USize count, DN_ZMem z_mem); +template T * DN_OS_VArrayMake (DN_VArray *array, DN_ZMem z_mem); +#define DN_OS_VArrayMakeArrayAssert(...) DN_HardAssert(DN_OS_VArrayMakeArray(__VA_ARGS__)) +#define DN_OS_VArrayMakeAssert(...) DN_HardAssert(DN_OS_VArrayMake(__VA_ARGS__)) +template T * DN_OS_VArrayInsertArray (DN_VArray *array, DN_USize index, T const *items, DN_USize count); +template T * DN_OS_VArrayInsertCArray (DN_VArray *array, DN_USize index, T const (&items)[N]); +template T * DN_OS_VArrayInsert (DN_VArray *array, DN_USize index, T const &item); +#define DN_OS_VArrayInsertArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertArray(__VA_ARGS__)) +#define DN_OS_VArrayInsertCArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertCArray(__VA_ARGS__)) +#define DN_OS_VArrayInsertAssert(...) DN_HardAssert(DN_OS_VArrayInsert(__VA_ARGS__)) +template T DN_OS_VArrayPopFront (DN_VArray *array, DN_USize count); +template T DN_OS_VArrayPopBack (DN_VArray *array, DN_USize count); +template DN_ArrayEraseResult DN_OS_VArrayEraseRange (DN_VArray *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); +template void DN_OS_VArrayClear (DN_VArray *array, DN_ZMem z_mem); #endif // !defined(DN_OS_H) diff --git a/Source/OS/dn_os_allocator.cpp b/Source/OS/dn_os_allocator.cpp deleted file mode 100644 index 963c126..0000000 --- a/Source/OS/dn_os_allocator.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#define DN_OS_ALLOCATOR_CPP - -#if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" - #include "../dn_inc.h" -#endif - -static void *DN_ArenaBasicAllocFromOSHeap(DN_USize size) -{ - void *result = DN_OS_MemAlloc(size, DN_ZMem_Yes); - return result; -} - -DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags) -{ - DN_ArenaMemFuncs mem_funcs = {}; - mem_funcs.type = DN_ArenaMemFuncType_Basic; - mem_funcs.basic_alloc = DN_ArenaBasicAllocFromOSHeap; - mem_funcs.basic_dealloc = DN_OS_MemDealloc; - DN_Arena result = DN_ArenaFromMemFuncs(size, size, flags, mem_funcs); - return result; -} - -DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags) -{ - DN_ArenaMemFuncs mem_funcs = {}; - mem_funcs.type = DN_ArenaMemFuncType_VMem; - mem_funcs.vmem_page_size = g_dn_->os.page_size; - mem_funcs.vmem_reserve = DN_OS_MemReserve; - mem_funcs.vmem_commit = DN_OS_MemCommit; - mem_funcs.vmem_release = DN_OS_MemRelease; - DN_Arena result = DN_ArenaFromMemFuncs(reserve, commit, flags, mem_funcs); - return result; -} - diff --git a/Source/OS/dn_os_allocator.h b/Source/OS/dn_os_allocator.h deleted file mode 100644 index 2541e57..0000000 --- a/Source/OS/dn_os_allocator.h +++ /dev/null @@ -1,11 +0,0 @@ -#if !defined(DN_OS_ALLOCATOR_H) -#define DN_OS_ALLOCATOR_H - -#if defined(_CLANGD) - #include "../dn_base_inc.h" -#endif - -DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags); -DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags); - -#endif // !defined(DN_OS_ALLOCATOR_H) diff --git a/Source/OS/dn_os_containers.cpp b/Source/OS/dn_os_containers.cpp deleted file mode 100644 index 0779c1e..0000000 --- a/Source/OS/dn_os_containers.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#define DN_OS_CONTAINERS_CPP - -#include "dn_os_containers.h" - -/* -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$$\ $$$$$$\ -// $$ __$$\ $$ __$$\ $$$\ $$ |\__$$ __|$$ __$$\ \_$$ _|$$$\ $$ |$$ _____|$$ __$$\ $$ __$$\ -// $$ / \__|$$ / $$ |$$$$\ $$ | $$ | $$ / $$ | $$ | $$$$\ $$ |$$ | $$ | $$ |$$ / \__| -// $$ | $$ | $$ |$$ $$\$$ | $$ | $$$$$$$$ | $$ | $$ $$\$$ |$$$$$\ $$$$$$$ |\$$$$$$\ -// $$ | $$ | $$ |$$ \$$$$ | $$ | $$ __$$ | $$ | $$ \$$$$ |$$ __| $$ __$$< \____$$\ -// $$ | $$\ $$ | $$ |$$ |\$$$ | $$ | $$ | $$ | $$ | $$ |\$$$ |$$ | $$ | $$ |$$\ $$ | -// \$$$$$$ | $$$$$$ |$$ | \$$ | $$ | $$ | $$ |$$$$$$\ $$ | \$$ |$$$$$$$$\ $$ | $$ |\$$$$$$ | -// \______/ \______/ \__| \__| \__| \__| \__|\______|\__| \__|\________|\__| \__| \______/ -// -// dn_containers.cpp -// -//////////////////////////////////////////////////////////////////////////////////////////////////// -*/ - -// NOTE: DN_VArray ///////////////////////////////////////////////////////////////////////////////// -template -DN_VArray DN_VArray_InitByteSize(DN_USize byte_size) -{ - DN_VArray result = {}; - result.data = DN_Cast(T *) DN_OS_MemReserve(byte_size, DN_MemCommit_No, DN_MemPage_ReadWrite); - if (result.data) - result.max = byte_size / sizeof(T); - return result; -} - -template -DN_VArray DN_VArray_Init(DN_USize max) -{ - DN_VArray result = DN_VArray_InitByteSize(max * sizeof(T)); - DN_Assert(result.max >= max); - return result; -} - -template -DN_VArray DN_VArray_InitSlice(DN_Slice slice, DN_USize max) -{ - DN_USize real_max = DN_Max(slice.size, max); - DN_VArray result = DN_VArray_Init(real_max); - if (DN_VArray_IsValid(&result)) - DN_VArray_AddArray(&result, slice.data, slice.size); - return result; -} - -template -DN_VArray DN_VArray_InitCArray(T const (&items)[N], DN_USize max) -{ - DN_USize real_max = DN_Max(N, max); - DN_VArray result = DN_VArray_InitSlice(DN_Slice_Init(items, N), real_max); - return result; -} - -template -void DN_VArray_Deinit(DN_VArray *array) -{ - DN_OS_MemRelease(array->data, array->max * sizeof(T)); - *array = {}; -} - -template -bool DN_VArray_IsValid(DN_VArray const *array) -{ - bool result = array->data && array->size <= array->max; - return result; -} - -template -DN_Slice DN_VArray_Slice(DN_VArray const *array) -{ - DN_Slice result = {}; - if (array) - result = DN_Slice_Init(array->data, array->size); - return result; -} - -template -T *DN_VArray_AddArray(DN_VArray *array, T const *items, DN_USize count) -{ - T *result = DN_VArray_MakeArray(array, count, DN_ZMem_No); - if (result) - DN_Memcpy(result, items, count * sizeof(T)); - return result; -} - -template -T *DN_VArray_AddCArray(DN_VArray *array, T const (&items)[N]) -{ - T *result = DN_VArray_AddArray(array, items, N); - return result; -} - -template -T *DN_VArray_Add(DN_VArray *array, T const &item) -{ - T *result = DN_VArray_AddArray(array, &item, 1); - return result; -} - -template -T *DN_VArray_MakeArray(DN_VArray *array, DN_USize count, DN_ZMem z_mem) -{ - if (!DN_VArray_IsValid(array)) - return nullptr; - - if (!DN_CheckF((array->size + count) < array->max, "Array is out of space (user requested +%zu items, array has %zu/%zu items)", count, array->size, array->max)) - return nullptr; - - if (!DN_VArray_Reserve(array, count)) - return nullptr; - - // TODO: Use placement new - T *result = array->data + array->size; - array->size += count; - if (z_mem == DN_ZMem_Yes) - DN_Memset(result, 0, count * sizeof(T)); - return result; -} - -template -T *DN_VArray_Make(DN_VArray *array, DN_ZMem z_mem) -{ - T *result = DN_VArray_MakeArray(array, 1, z_mem); - return result; -} - -template -T *DN_VArray_InsertArray(DN_VArray *array, DN_USize index, T const *items, DN_USize count) -{ - T *result = nullptr; - if (!DN_VArray_IsValid(array)) - return result; - if (DN_VArray_Reserve(array, array->size + count)) - result = DN_CArray_InsertArray(array->data, &array->size, array->max, index, items, count); - return result; -} - -template -T *DN_VArray_InsertCArray(DN_VArray *array, DN_USize index, T const (&items)[N]) -{ - T *result = DN_VArray_InsertArray(array, index, items, N); - return result; -} - -template -T *DN_VArray_Insert(DN_VArray *array, DN_USize index, T const &item) -{ - T *result = DN_VArray_InsertArray(array, index, &item, 1); - return result; -} - -template -T *DN_VArray_PopFront(DN_VArray *array, DN_USize count) -{ - T *result = DN_CArray_PopFront(array->data, &array->size, count); - return result; -} - -template -T *DN_VArray_PopBack(DN_VArray *array, DN_USize count) -{ - T *result = DN_CArray_PopBack(array->data, &array->size, count); - return result; -} - -template -DN_ArrayEraseResult DN_VArray_EraseRange(DN_VArray *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase) -{ - DN_ArrayEraseResult result = {}; - if (!DN_VArray_IsValid(array)) - return result; - result = DN_CArray_EraseRange(array->data, &array->size, begin_index, count, erase); - return result; -} - -template -void DN_VArray_Clear(DN_VArray *array, DN_ZMem z_mem) -{ - if (array) { - if (z_mem == DN_ZMem_Yes) - DN_Memset(array->data, 0, array->size * sizeof(T)); - array->size = 0; - } -} - -template -bool DN_VArray_Reserve(DN_VArray *array, DN_USize count) -{ - if (!DN_VArray_IsValid(array) || count == 0) - return false; - - DN_USize real_commit = (array->size + count) * sizeof(T); - DN_USize aligned_commit = DN_AlignUpPowerOfTwo(real_commit, g_dn_->os.page_size); - if (array->commit >= aligned_commit) - return true; - bool result = DN_OS_MemCommit(array->data, aligned_commit, DN_MemPage_ReadWrite); - array->commit = aligned_commit; - return result; -} diff --git a/Source/OS/dn_os_containers.h b/Source/OS/dn_os_containers.h deleted file mode 100644 index 10b06f5..0000000 --- a/Source/OS/dn_os_containers.h +++ /dev/null @@ -1,51 +0,0 @@ -#if !defined(DN_OS_CONTAINERS_H) -#define DN_OS_CONTAINERS_H - -#if defined(_CLANGD) - #include "../dn_base_inc.h" -#endif - -// NOTE: DN_VArray -// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS. -template struct DN_VArray -{ - T *data; // Pointer to the start of the array items in the block of memory - DN_USize size; // Number of items currently in the array - DN_USize max; // Maximum number of items this array can store - DN_USize commit; // Bytes committed - - T *begin() { return data; } - T *end () { return data + size; } - T const *begin() const { return data; } - T const *end () const { return data + size; } -}; - -template DN_VArray DN_VArray_InitByteSize (DN_USize byte_size); -template DN_VArray DN_VArray_Init (DN_USize max); -template DN_VArray DN_VArray_InitSlice (DN_Slice slice, DN_USize max); -template DN_VArray DN_VArray_InitCArray (T const (&items)[N], DN_USize max); -template void DN_VArray_Deinit (DN_VArray *array); -template bool DN_VArray_IsValid (DN_VArray const *array); -template DN_Slice DN_VArray_Slice (DN_VArray const *array); -template bool DN_VArray_Reserve (DN_VArray *array, DN_USize count); -template T * DN_VArray_AddArray (DN_VArray *array, T const *items, DN_USize count); -template T * DN_VArray_AddCArray (DN_VArray *array, T const (&items)[N]); -template T * DN_VArray_Add (DN_VArray *array, T const &item); -#define DN_VArray_AddArrayAssert(...) DN_HardAssert(DN_VArray_AddArray(__VA_ARGS__)) -#define DN_VArray_AddCArrayAssert(...) DN_HardAssert(DN_VArray_AddCArray(__VA_ARGS__)) -#define DN_VArray_AddAssert(...) DN_HardAssert(DN_VArray_Add(__VA_ARGS__)) -template T * DN_VArray_MakeArray (DN_VArray *array, DN_USize count, DN_ZMem z_mem); -template T * DN_VArray_Make (DN_VArray *array, DN_ZMem z_mem); -#define DN_VArray_MakeArrayAssert(...) DN_HardAssert(DN_VArray_MakeArray(__VA_ARGS__)) -#define DN_VArray_MakeAssert(...) DN_HardAssert(DN_VArray_Make(__VA_ARGS__)) -template T * DN_VArray_InsertArray (DN_VArray *array, DN_USize index, T const *items, DN_USize count); -template T * DN_VArray_InsertCArray (DN_VArray *array, DN_USize index, T const (&items)[N]); -template T * DN_VArray_Insert (DN_VArray *array, DN_USize index, T const &item); -#define DN_VArray_InsertArrayAssert(...) DN_HardAssert(DN_VArray_InsertArray(__VA_ARGS__)) -#define DN_VArray_InsertCArrayAssert(...) DN_HardAssert(DN_VArray_InsertCArray(__VA_ARGS__)) -#define DN_VArray_InsertAssert(...) DN_HardAssert(DN_VArray_Insert(__VA_ARGS__)) -template T DN_VArray_PopFront (DN_VArray *array, DN_USize count); -template T DN_VArray_PopBack (DN_VArray *array, DN_USize count); -template DN_ArrayEraseResult DN_VArray_EraseRange (DN_VArray *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); -template void DN_VArray_Clear (DN_VArray *array, DN_ZMem z_mem); -#endif // !defined(DN_OS_CONTAINERS_H) diff --git a/Source/OS/dn_os_posix.cpp b/Source/OS/dn_os_posix.cpp index 2630950..323d249 100644 --- a/Source/OS/dn_os_posix.cpp +++ b/Source/OS/dn_os_posix.cpp @@ -1,12 +1,14 @@ #define DN_OS_POSIX_CPP #if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" + #define DN_H_WITH_OS 1 + #include "../dn.h" + #include "dn_os_posix.h" #endif #include // readdir, opendir, closedir #include +#include // NOTE: DN_OSMem static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect) @@ -226,17 +228,20 @@ DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value) DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path) { - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_OSDiskSpace result = {}; DN_Str8 path_z_terminated = DN_Str8FromStr8Arena(tmem.arena, path); struct statvfs info = {}; - if (statvfs(path_z_terminated.data, &info) != 0) + if (statvfs(path_z_terminated.data, &info) != 0) { + DN_TCScratchEnd(&tmem); return result; + } result.success = true; result.avail = info.f_bavail * info.f_frsize; result.size = info.f_blocks * info.f_frsize; + DN_TCScratchEnd(&tmem); return result; } @@ -313,23 +318,23 @@ DN_API DN_U64 DN_OS_PerfCounterFrequency() return result; } -static DN_POSIXCore *DN_OS_GetPOSIXCore_() +static DN_OSPosixCore *DN_OS_GetPOSIXCore_() { DN_Assert(g_dn_ && g_dn_->os.platform_context); - DN_POSIXCore *result = DN_Cast(DN_POSIXCore *)g_dn_->os.platform_context; + DN_OSPosixCore *result = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context; return result; } DN_API DN_U64 DN_OS_PerfCounterNow() { - DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); + DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_(); struct timespec ts; clock_gettime(posix->clock_monotonic_raw ? CLOCK_MONOTONIC_RAW : CLOCK_MONOTONIC, &ts); DN_U64 result = DN_Cast(DN_U64) ts.tv_sec * 1'000'000'000 + DN_Cast(DN_U64) ts.tv_nsec; return result; } -DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) +DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error) { bool result = false; #if defined(DN_PLATFORM_EMSCRIPTEN) @@ -385,9 +390,9 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi result = (bytes_written == stat_existing.st_size); if (!result) { int error_code = errno; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 file_size_str8 = DN_Str8FromByteCount(tmem.arena, stat_existing.st_size, DN_ByteCountType_Auto); - DN_Str8 bytes_written_str8 = DN_Str8FromByteCount(tmem.arena, bytes_written, DN_ByteCountType_Auto); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 file_size_str8 = DN_Str8FromByteCount(scratch.arena, stat_existing.st_size, DN_ByteCountType_Auto); + DN_Str8 bytes_written_str8 = DN_Str8FromByteCount(scratch.arena, bytes_written, DN_ByteCountType_Auto); DN_OS_ErrSinkAppendF(error, error_code, "Failed to copy file '%.*s' to '%.*s', we copied %.*s but the file " @@ -398,13 +403,14 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi DN_Str8PrintFmt(file_size_str8), error_code, strerror(error_code)); + DN_TCScratchEnd(&scratch); } #endif return result; } -DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) +DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error) { // See: https://github.com/gingerBill/gb/blob/master/gb.h bool result = false; @@ -435,7 +441,7 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, - DN_OSErrSink *error) + DN_ErrSink *error) { DN_OSFile result = {}; if (path.size == 0 || path.size <= 0) @@ -506,7 +512,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, return result; } -DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err) +DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err) { DN_OSFileRead result = {}; if (!file || !file->handle || file->error || !buffer || size <= 0) @@ -514,9 +520,10 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size result.bytes_read = fread(buffer, 1, size, DN_Cast(FILE *) file->handle); if (feof(DN_Cast(FILE*)file->handle)) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); DN_OS_ErrSinkAppendF(err, 1, "Failed to read %S from file", buffer_size_str8); + DN_TCScratchEnd(&scratch); return result; } @@ -524,7 +531,7 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size return result; } -DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_OSErrSink *err) +DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_ErrSink *err) { if (!file || !file->handle || file->error || !buffer || size <= 0) return false; @@ -532,14 +539,15 @@ DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize siz fwrite(buffer, DN_Cast(DN_USize) size, 1 /*count*/, DN_Cast(FILE *) file->handle) == 1 /*count*/; if (!result) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); DN_OS_ErrSinkAppendF(err, 1, "Failed to write buffer (%s) to file handle", DN_Str8PrintFmt(buffer_size_str8)); + DN_TCScratchEnd(&scratch); } return result; } -DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_OSErrSink *err) +DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_ErrSink *err) { // TODO: errno is not thread safe int fd = fileno(DN_Cast(FILE *) file->handle); @@ -622,7 +630,7 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path) DN_API bool DN_OS_PathMakeDir(DN_Str8 path) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); bool result = true; // TODO(doyle): Implement this without using the path indexes, it's not @@ -630,7 +638,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path) DN_USize path_indexes_size = 0; uint16_t path_indexes[64] = {}; - DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, path); + DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, path); for (DN_USize index = copy.size - 1; index < copy.size; index--) { bool first_char = index == (copy.size - 1); char ch = copy.data[index]; @@ -649,6 +657,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path) // NOTE: There's something that exists in at this path, but // it's not a directory. This request to make a directory is // invalid. + DN_TCScratchEnd(&scratch); return false; } else if (DN_OS_PathIsDir(copy)) { // NOTE: We found a directory, we can stop here and start @@ -673,6 +682,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path) if (index != 0) copy.data[path_index] = temp; } + DN_TCScratchEnd(&scratch); return result; } @@ -723,7 +733,7 @@ enum DN_OSPipeType_ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *arena, - DN_OSErrSink *error) + DN_ErrSink *error) { DN_OSExecResult result = {}; if (!handle.process || handle.os_error_code || handle.exit_code) { @@ -786,10 +796,10 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, // NOTE: Read the data from the read end of the pipe if (result.os_error_code == 0) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); if (arena && handle.stdout_read) { char buffer[4096]; - DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena); + DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena); for (;;) { ssize_t bytes_read = read(stdout_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer)); @@ -803,7 +813,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, if (arena && handle.stderr_read) { char buffer[4096]; - DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena); + DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena); for (;;) { ssize_t bytes_read = read(stderr_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer)); @@ -814,6 +824,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, result.stderr_text = DN_Str8BuilderBuild(&builder, arena); } + DN_TCScratchEnd(&scratch); } close(stdout_pipe[DN_OSPipeType__Read]); @@ -823,7 +834,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, DN_OSExecArgs *args, - DN_OSErrSink *error) + DN_ErrSink *error) { #if defined(DN_PLATFORM_EMSCRIPTEN) DN_InvalidCodePathF("Unsupported operation"); @@ -834,12 +845,13 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, if (cmd_line.size == 0) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 cmd_rendered = DN_Slice_Str8Render(tmem.arena, cmd_line, DN_Str8Lit(" ")); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_DEFER { DN_TCScratchEnd(&scratch); }; + DN_Str8 cmd_rendered = DN_Slice_Str8Render(scratch.arena, cmd_line, DN_Str8Lit(" ")); int stdout_pipe[DN_OSPipeType__Count] = {}; int stderr_pipe[DN_OSPipeType__Count] = {}; - // NOTE: Open stdout pipe ////////////////////////////////////////////////////////////////////// + // NOTE: Open stdout pipe if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) { if (pipe(stdout_pipe) == -1) { result.os_error_code = errno; @@ -929,7 +941,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, // NOTE: Convert the command into something suitable for execvp char **argv = - DN_ArenaNewArray(tmem.arena, char *, cmd_line.size + 1 /*null*/, DN_ZMem_Yes); + DN_ArenaNewArray(scratch.arena, char *, cmd_line.size + 1 /*null*/, DN_ZMem_Yes); if (!argv) { result.exit_code = -1; DN_OS_ErrSinkAppendF( @@ -942,7 +954,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, for (DN_ForIndexU(arg_index, cmd_line.size)) { DN_Str8 arg = cmd_line.data[arg_index]; - argv[arg_index] = DN_Str8FromStr8Arena(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated + argv[arg_index] = DN_Str8FromStr8Arena(scratch.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated } // NOTE: Change the working directory if there is one @@ -960,7 +972,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, if (args->working_dir.size) { prev_working_dir = get_current_dir_name(); - DN_Str8 working_dir = DN_Str8FromStr8Arena(tmem.arena, args->working_dir); + DN_Str8 working_dir = DN_Str8FromStr8Arena(scratch.arena, args->working_dir); if (chdir(working_dir.data) == -1) { result.os_error_code = errno; DN_OS_ErrSinkAppendF( @@ -1014,21 +1026,21 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, - DN_OSErrSink *err) + DN_ErrSink *err) { DN_InvalidCodePath; DN_OSExecResult result = {}; return result; } -static DN_POSIXSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64) +static DN_OSPosixSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64) { - DN_POSIXSyncPrimitive *result = nullptr; + DN_OSPosixSyncPrimitive *result = nullptr; DN_Memcpy(&result, &u64, sizeof(result)); return result; } -static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive) +static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_OSPosixSyncPrimitive *primitive) { DN_U64 result = 0; static_assert(sizeof(result) >= sizeof(primitive), "Pointer size mis-match"); @@ -1036,10 +1048,10 @@ static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive) return result; } -static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_() +static DN_OSPosixSyncPrimitive *DN_POSIX_AllocSyncPrimitive_() { - DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); - DN_POSIXSyncPrimitive *result = nullptr; + DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_(); + DN_OSPosixSyncPrimitive *result = nullptr; pthread_mutex_lock(&posix->sync_primitive_free_list_mutex); { if (posix->sync_primitive_free_list) { @@ -1048,17 +1060,17 @@ static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_() result->next = nullptr; } else { DN_OSCore *os = &g_dn_->os; - result = DN_ArenaNew(&os->arena, DN_POSIXSyncPrimitive, DN_ZMem_Yes); + result = DN_ArenaNew(&os->arena, DN_OSPosixSyncPrimitive, DN_ZMem_Yes); } } pthread_mutex_unlock(&posix->sync_primitive_free_list_mutex); return result; } -static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive) +static void DN_POSIX_DeallocSyncPrimitive_(DN_OSPosixSyncPrimitive *primitive) { if (primitive) { - DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); + DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_(); pthread_mutex_lock(&posix->sync_primitive_free_list_mutex); primitive->next = posix->sync_primitive_free_list; posix->sync_primitive_free_list = primitive; @@ -1070,7 +1082,7 @@ static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive) DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) { DN_OSSemaphore result = {}; - DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); + DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); if (primitive) { int pshared = 0; // Share the semaphore across all threads in the process if (sem_init(&primitive->sem, pshared, initial_count) == 0) @@ -1084,7 +1096,7 @@ DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) { if (semaphore && semaphore->handle != 0) { - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); sem_destroy(&primitive->sem); DN_POSIX_DeallocSyncPrimitive_(primitive); *semaphore = {}; @@ -1094,7 +1106,7 @@ DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount) { if (semaphore && semaphore->handle != 0) { - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); #if defined(DN_OS_WIN32) sem_post_multiple(&primitive->sem, amount); // mingw extension #else @@ -1111,7 +1123,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, if (!semaphore || semaphore->handle == 0) return result; - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) { int wait_result = 0; do { @@ -1138,7 +1150,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, // NOTE: DN_OSMutex //////////////////////////////////////////////////////////////////////////////// DN_API DN_OSMutex DN_OS_MutexInit() { - DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); + DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); DN_OSMutex result = {}; if (primitive) { if (pthread_mutex_init(&primitive->mutex, nullptr) == 0) @@ -1152,7 +1164,7 @@ DN_API DN_OSMutex DN_OS_MutexInit() DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); pthread_mutex_destroy(&primitive->mutex); DN_POSIX_DeallocSyncPrimitive_(primitive); *mutex = {}; @@ -1162,7 +1174,7 @@ DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); pthread_mutex_lock(&primitive->mutex); } } @@ -1170,14 +1182,14 @@ DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); pthread_mutex_unlock(&primitive->mutex); } } DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit() { - DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); + DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); DN_OSConditionVariable result = {}; if (primitive) { if (pthread_cond_init(&primitive->cv, nullptr) == 0) @@ -1191,7 +1203,7 @@ DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit() DN_API void DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); pthread_cond_destroy(&primitive->cv); DN_POSIX_DeallocSyncPrimitive_(primitive); *cv = {}; @@ -1202,8 +1214,8 @@ DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMu { bool result = false; if (cv && mutex && mutex->handle != 0 && cv->handle != 0) { - DN_POSIXSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); - DN_POSIXSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); + DN_OSPosixSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); + DN_OSPosixSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); struct timespec time = {}; time.tv_sec = end_ts_ms / 1'000; @@ -1224,7 +1236,7 @@ DN_API bool DN_OS_ConditionVariableWait(DN_OSConditionVariable *cv, DN_OSMutex * DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); pthread_cond_signal(&primitive->cv); } } @@ -1232,7 +1244,7 @@ DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); pthread_cond_broadcast(&primitive->cv); } } @@ -1307,7 +1319,7 @@ DN_API DN_U32 DN_OS_ThreadID() return DN_Cast(DN_U32) result; } -DN_API void DN_Posix_Init(DN_POSIXCore *posix) +DN_API void DN_OS_PosixInit(DN_OSPosixCore *posix) { int mutex_init = pthread_mutex_init(&posix->sync_primitive_free_list_mutex, nullptr); DN_Assert(mutex_init == 0); @@ -1320,21 +1332,22 @@ DN_API void DN_Posix_Init(DN_POSIXCore *posix) } } -DN_API void DN_Posix_ThreadSetName(DN_Str8 name) +DN_API void DN_OS_PosixThreadSetName(DN_Str8 name) { #if defined(DN_PLATFORM_EMSCRIPTEN) (void)name; #else - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, name); pthread_t thread = pthread_self(); pthread_setname_np(thread, (char *)copy.data); + DN_TCScratchEnd(&tmem); #endif } -DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus() +DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus() { - DN_POSIXProcSelfStatus result = {}; + DN_OSPosixProcSelfStatus result = {}; // NOTE: Example // @@ -1346,11 +1359,11 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus() // // VmSize is the total virtual memory used DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/proc/self/status"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, nullptr); - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); if (!file.error) { + DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0); char buf[256]; - DN_Str8Builder builder = DN_Str8BuilderFromTLS(); + DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena); for (;;) { DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr); if (!read.success || read.bytes_read == 0) @@ -1362,8 +1375,8 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus() DN_Str8 const PID = DN_Str8Lit("Pid:"); DN_Str8 const VM_PEAK = DN_Str8Lit("VmPeak:"); DN_Str8 const VM_SIZE = DN_Str8Lit("VmSize:"); - DN_Str8 status_buf = DN_Str8BuilderBuildFromTLS(&builder); - DN_Str8SplitResult lines = DN_Str8SplitFromTLS(status_buf, DN_Str8Lit("\n"), DN_Str8SplitIncludeEmptyStrings_No); + DN_Str8 status_buf = DN_Str8BuilderBuild(&builder, tmem.arena); + DN_Str8SplitResult lines = DN_Str8Split(tmem.arena, status_buf, DN_Str8Lit("\n"), DN_Str8SplitIncludeEmptyStrings_No); for (DN_ForItSize(line_it, DN_Str8, lines.data, lines.count)) { DN_Str8 line = DN_Str8TrimWhitespaceAround(*line_it.data); @@ -1392,6 +1405,7 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus() DN_Assert(to_u64.success); } } + DN_TCScratchEnd(&tmem); } DN_OS_FileClose(&file); return result; @@ -1406,7 +1420,7 @@ static EM_BOOL EMWebSocketOnOpenCallback(int type, const EmscriptenWebSocketOpen (void)event; // EMSCRIPTEN_RESULT result = emscripten_websocket_send_utf8_text(event->socket, R"({"jsonrpc":"2.0","id":1,"method": "eth_subscribe","params":["newHeads"]})"); // if (result) - // DN_LOG_InfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result); + // DN_LogInfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result); return EM_TRUE; } @@ -1416,9 +1430,9 @@ static EM_BOOL EMWebSocketOnMsgCallback(int type, const EmscriptenWebSocketMessa (void)user_context; (void)event; if (event->isText) { - DN_LOG_InfoF("Received: %.*s", event->numBytes, event->data); + DN_LogInfoF("Received: %.*s", event->numBytes, event->data); } else { - DN_LOG_InfoF("Received: %d bytes", event->numBytes); + DN_LogInfoF("Received: %d bytes", event->numBytes); } return EM_TRUE; } @@ -1486,12 +1500,13 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, response->arena = arena; response->builder.arena = - response->tmem_arena ? response->tmem_arena : &response->tmp_arena; + response->scratch_arena ? response->scratch_arena : &response->tmp_arena; - DN_Arena *tmem = response->tmem_arena; - DN_OSTLSTMem tmem_ = DN_OS_TLSTMem(arena); - if (!tmem) - tmem = tmem_.arena; + DN_Arena *scratch = response->scratch_arena; + DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1); + DN_DEFER { DN_TCScratchEnd(&scratch_); }; + if (!scratch) + scratch = scratch_.arena; #if defined(DN_PLATFORM_EMSCRIPTEN) emscripten_fetch_attr_t fetch_attribs = {}; @@ -1521,8 +1536,8 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, fetch_attribs.onerror = DN_OS_HttpRequestEMFetchOnErrorCallback; fetch_attribs.userData = response; - DN_Str8 url = DN_Str8FromFmtArena(tmem, "%.*s%.*s", DN_Str8PrintFmt(host), DN_Str8PrintFmt(path)); - DN_LOG_InfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'", + DN_Str8 url = DN_Str8FromFmtArena(scratch, "%.*s%.*s", DN_Str8PrintFmt(host), DN_Str8PrintFmt(path)); + DN_LogInfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'", fetch_attribs.requestMethod, DN_Str8PrintFmt(url), DN_Str8PrintFmt(body)); diff --git a/Source/OS/dn_os_posix.h b/Source/OS/dn_os_posix.h index ea8d0ab..75eeb95 100644 --- a/Source/OS/dn_os_posix.h +++ b/Source/OS/dn_os_posix.h @@ -2,30 +2,13 @@ #define DN_OS_POSIX_H #if defined(_CLANGD) - #include "../dn_base_inc.h" + #include "../dn.h" #endif #include #include -/* -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// $$$$$$\ $$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ -// $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ \_$$ _|$$ | $$ | -// $$ / $$ |$$ / \__| $$ | $$ |$$ / $$ |$$ / \__| $$ | \$$\ $$ | -// $$ | $$ |\$$$$$$\ $$$$$$$ |$$ | $$ |\$$$$$$\ $$ | \$$$$ / -// $$ | $$ | \____$$\ $$ ____/ $$ | $$ | \____$$\ $$ | $$ $$< -// $$ | $$ |$$\ $$ | $$ | $$ | $$ |$$\ $$ | $$ | $$ /\$$\ -// $$$$$$ |\$$$$$$ | $$ | $$$$$$ |\$$$$$$ |$$$$$$\ $$ / $$ | -// \______/ \______/ \__| \______/ \______/ \______|\__| \__| -// -// dn_os_posix.h -// -//////////////////////////////////////////////////////////////////////////////////////////////////// -*/ - -struct DN_POSIXProcSelfStatus +struct DN_OSPosixProcSelfStatus { char name[64]; DN_U8 name_size; @@ -52,15 +35,14 @@ struct DN_POSIXProcSelfStatus // unlocking, or destroying the object is undefined. [...] The effect of // referring to a copy of the object when locking, unlocking, or destroying it // is undefined. - -enum DN_POSIXSyncPrimitiveType +enum DN_OSPosixSyncPrimitiveType { - DN_OSPOSIXSyncPrimitiveType_Semaphore, - DN_OSPOSIXSyncPrimitiveType_Mutex, - DN_OSPOSIXSyncPrimitiveType_ConditionVariable, + DN_OSPosixSyncPrimitiveType_Semaphore, + DN_OSPosixSyncPrimitiveType_Mutex, + DN_OSPosixSyncPrimitiveType_ConditionVariable, }; -struct DN_POSIXSyncPrimitive +struct DN_OSPosixSyncPrimitive { union { @@ -68,17 +50,17 @@ struct DN_POSIXSyncPrimitive pthread_mutex_t mutex; pthread_cond_t cv; }; - DN_POSIXSyncPrimitive *next; + DN_OSPosixSyncPrimitive *next; }; -struct DN_POSIXCore +struct DN_OSPosixCore { - DN_POSIXSyncPrimitive *sync_primitive_free_list; - pthread_mutex_t sync_primitive_free_list_mutex; - bool clock_monotonic_raw; + DN_OSPosixSyncPrimitive *sync_primitive_free_list; + pthread_mutex_t sync_primitive_free_list_mutex; + bool clock_monotonic_raw; }; -DN_API void DN_Posix_Init(DN_POSIXCore *posix); -DN_API void DN_Posix_ThreadSetName(DN_Str8 name); -DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus(); +DN_API void DN_OS_PosixInit (DN_OSPosixCore *posix); +DN_API void DN_OS_PosixThreadSetName (DN_Str8 name); +DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus(); #endif // !defined(DN_OS_POSIX_H) diff --git a/Source/OS/dn_os_print.cpp b/Source/OS/dn_os_print.cpp deleted file mode 100644 index 1c88e01..0000000 --- a/Source/OS/dn_os_print.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#define DN_OS_PRINT_CPP - -DN_API DN_LOGStyle DN_OS_PrintStyleColour(uint8_t r, uint8_t g, uint8_t b, DN_LOGBold bold) -{ - DN_LOGStyle result = {}; - result.bold = bold; - result.colour = true; - result.r = r; - result.g = g; - result.b = b; - return result; -} - -DN_API DN_LOGStyle DN_OS_PrintStyleColourU32(uint32_t rgb, DN_LOGBold bold) -{ - uint8_t r = (rgb >> 24) & 0xFF; - uint8_t g = (rgb >> 16) & 0xFF; - uint8_t b = (rgb >> 8) & 0xFF; - DN_LOGStyle result = DN_OS_PrintStyleColour(r, g, b, bold); - return result; -} - -DN_API DN_LOGStyle DN_OS_PrintStyleBold() -{ - DN_LOGStyle result = {}; - result.bold = DN_LOGBold_Yes; - return result; -} - -DN_API void DN_OS_Print(DN_OSPrintDest dest, DN_Str8 string) -{ - DN_Assert(dest == DN_OSPrintDest_Out || dest == DN_OSPrintDest_Err); - -#if defined(DN_PLATFORM_WIN32) - // NOTE: Get the output handles from kernel //////////////////////////////////////////////////// - DN_THREAD_LOCAL void *std_out_print_handle = nullptr; - DN_THREAD_LOCAL void *std_err_print_handle = nullptr; - DN_THREAD_LOCAL bool std_out_print_to_console = false; - DN_THREAD_LOCAL bool std_err_print_to_console = false; - - if (!std_out_print_handle) { - unsigned long mode = 0; - (void)mode; - std_out_print_handle = GetStdHandle(STD_OUTPUT_HANDLE); - std_out_print_to_console = GetConsoleMode(std_out_print_handle, &mode) != 0; - - std_err_print_handle = GetStdHandle(STD_ERROR_HANDLE); - std_err_print_to_console = GetConsoleMode(std_err_print_handle, &mode) != 0; - } - - // NOTE: Select the output handle ////////////////////////////////////////////////////////////// - void *print_handle = std_out_print_handle; - bool print_to_console = std_out_print_to_console; - if (dest == DN_OSPrintDest_Err) { - print_handle = std_err_print_handle; - print_to_console = std_err_print_to_console; - } - - // NOTE: Write the string ////////////////////////////////////////////////////////////////////// - DN_Assert(string.size < DN_Cast(unsigned long) - 1); - unsigned long bytes_written = 0; - (void)bytes_written; - if (print_to_console) - WriteConsoleA(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr); - else - WriteFile(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr); -#else - fprintf(dest == DN_OSPrintDest_Out ? stdout : stderr, "%.*s", DN_Str8PrintFmt(string)); -#endif -} - -DN_API void DN_OS_PrintF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_OS_PrintFV(dest, fmt, args); - va_end(args); -} - -DN_API void DN_OS_PrintFStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_OS_PrintFVStyle(dest, style, fmt, args); - va_end(args); -} - -DN_API void DN_OS_PrintStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string) -{ - if (string.data && string.size) { - if (style.colour) - DN_OS_Print(dest, DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b)); - if (style.bold == DN_LOGBold_Yes) - DN_OS_Print(dest, DN_Str8Lit(DN_LOG_BoldEscapeCode)); - DN_OS_Print(dest, string); - if (style.colour || style.bold == DN_LOGBold_Yes) - DN_OS_Print(dest, DN_Str8Lit(DN_LOG_ResetEscapeCode)); - } -} - -static char *DN_OS_PrintVSPrintfChunker_(const char *buf, void *user, int len) -{ - DN_Str8 string = {}; - string.data = DN_Cast(char *) buf; - string.size = len; - - DN_OSPrintDest dest = DN_Cast(DN_OSPrintDest) DN_Cast(uintptr_t) user; - DN_OS_Print(dest, string); - return (char *)buf; -} - -DN_API void DN_OS_PrintFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args) -{ - char buffer[STB_SPRINTF_MIN]; - STB_SPRINTF_DECORATE(vsprintfcb) - (DN_OS_PrintVSPrintfChunker_, DN_Cast(void *) DN_Cast(uintptr_t) dest, buffer, fmt, args); -} - -DN_API void DN_OS_PrintFVStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args) -{ - if (fmt) { - if (style.colour) - DN_OS_Print(dest, DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b)); - if (style.bold == DN_LOGBold_Yes) - DN_OS_Print(dest, DN_Str8Lit(DN_LOG_BoldEscapeCode)); - DN_OS_PrintFV(dest, fmt, args); - if (style.colour || style.bold == DN_LOGBold_Yes) - DN_OS_Print(dest, DN_Str8Lit(DN_LOG_ResetEscapeCode)); - } -} - -DN_API void DN_OS_PrintLn(DN_OSPrintDest dest, DN_Str8 string) -{ - DN_OS_Print(dest, string); - DN_OS_Print(dest, DN_Str8Lit("\n")); -} - -DN_API void DN_OS_PrintLnF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_OS_PrintLnFV(dest, fmt, args); - va_end(args); -} - -DN_API void DN_OS_PrintLnFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args) -{ - DN_OS_PrintFV(dest, fmt, args); - DN_OS_Print(dest, DN_Str8Lit("\n")); -} - -DN_API void DN_OS_PrintLnStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string) -{ - DN_OS_PrintStyle(dest, style, string); - DN_OS_Print(dest, DN_Str8Lit("\n")); -} - -DN_API void DN_OS_PrintLnFStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_OS_PrintLnFVStyle(dest, style, fmt, args); - va_end(args); -} - -DN_API void DN_OS_PrintLnFVStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args) -{ - DN_OS_PrintFVStyle(dest, style, fmt, args); - DN_OS_Print(dest, DN_Str8Lit("\n")); -} diff --git a/Source/OS/dn_os_print.h b/Source/OS/dn_os_print.h deleted file mode 100644 index bc42cd5..0000000 --- a/Source/OS/dn_os_print.h +++ /dev/null @@ -1,59 +0,0 @@ -#if !defined(DN_OS_PRINT_H) -#define DN_OS_PRINT_H - -enum DN_OSPrintDest -{ - DN_OSPrintDest_Out, - DN_OSPrintDest_Err, -}; - -// NOTE: Print Macros -#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string) -#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__) -#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args) - -#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string) -#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__) -#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args) - -#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string) -#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__) -#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args) - -#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string); -#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__) -#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args); - -#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string) -#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__) -#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args) - -#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string) -#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__) -#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args) - -#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string) -#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__) -#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args) - -#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string); -#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__) -#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args); - -// NOTE: Print -DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string); -DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args); - -DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string); -DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args); - -DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string); -DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args); - -DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string); -DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args); -#endif // !defined(DN_OS_PRINT_H) diff --git a/Source/OS/dn_os_stacktrace.cpp b/Source/OS/dn_os_stacktrace.cpp deleted file mode 100644 index 7d44d91..0000000 --- a/Source/OS/dn_os_stacktrace.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#define DN_CORE_DEBUG_CPP - -#if defined(_CLANGD) -#define DN_H_WITH_OS 1 -#include "../dn.h" -#endif - -DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, uint16_t limit) -{ - DN_StackTraceWalkResult result = {}; -#if defined(DN_OS_WIN32) - if (!arena) - return result; - - static DN_TicketMutex mutex = {}; - DN_TicketMutex_Begin(&mutex); - - HANDLE thread = GetCurrentThread(); - result.process = GetCurrentProcess(); - - DN_W32Core *w32 = DN_OS_GetW32Core_(); - if (!w32->sym_initialised) { - w32->sym_initialised = true; - SymSetOptions(SYMOPT_LOAD_LINES); - if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); - DN_W32Error error = DN_W32_LastError(tmem.arena); - DN_LOG_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_Str8PrintFmt(error.msg)); - } - } - - CONTEXT context; - RtlCaptureContext(&context); - - STACKFRAME64 frame = {}; - frame.AddrPC.Offset = context.Rip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrFrame.Offset = context.Rbp; - frame.AddrFrame.Mode = AddrModeFlat; - frame.AddrStack.Offset = context.Rsp; - frame.AddrStack.Mode = AddrModeFlat; - - DN_FArray raw_frames = {}; - while (raw_frames.size < limit) { - if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64, - result.process, - thread, - &frame, - &context, - nullptr /*ReadMemoryRoutine*/, - SymFunctionTableAccess64, - SymGetModuleBase64, - nullptr /*TranslateAddress*/)) - break; - - // NOTE: It might be useful one day to use frame.AddrReturn.Offset. - // If AddrPC.Offset == AddrReturn.Offset then we can detect recursion. - DN_FArray_Add(&raw_frames, frame.AddrPC.Offset); - } - DN_TicketMutex_End(&mutex); - - result.base_addr = DN_ArenaNewArray(arena, uint64_t, raw_frames.size, DN_ZMem_No); - result.size = DN_Cast(uint16_t) raw_frames.size; - DN_Memcpy(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0])); -#else - (void)limit; - (void)arena; -#endif - return result; -} - -static void DN_StackTraceAddWalkToStr8Builder(DN_StackTraceWalkResult const *walk, DN_Str8Builder *builder, DN_USize skip) -{ - DN_StackTraceRawFrame raw_frame = {}; - raw_frame.process = walk->process; - for (DN_USize index = skip; index < walk->size; index++) { - raw_frame.base_addr = walk->base_addr[index]; - DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(builder->arena, raw_frame); - DN_Str8BuilderAppendF(builder, "%.*s(%zu): %.*s%s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name), (DN_Cast(int) index == walk->size - 1) ? "" : "\n"); - } -} - -DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk) -{ - bool result = false; - if (!it || !walk || !walk->base_addr || !walk->process) - return result; - - if (it->index >= walk->size) - return false; - - result = true; - it->raw_frame.process = walk->process; - it->raw_frame.base_addr = walk->base_addr[it->index++]; - return result; -} - -DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkResult const *walk, uint16_t skip) -{ - DN_Str8 result{}; - if (!walk || !arena) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); - DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena); - DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip); - result = DN_Str8BuilderBuild(&builder, arena); - return result; -} - -DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, uint16_t limit, uint16_t skip) -{ - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena); - DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, limit); - DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip); - return result; -} - -DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap(uint16_t limit, uint16_t skip) -{ - // NOTE: We don't use WalkResultToStr8 because that uses the TLS arenas which - // does not use the OS heap. - DN_Arena arena = DN_ArenaFromHeap(DN_Kilobytes(64), DN_ArenaFlags_NoAllocTrack); - DN_Str8Builder builder = DN_Str8BuilderFromArena(&arena); - DN_StackTraceWalkResult walk = DN_StackTraceWalk(&arena, limit); - DN_StackTraceAddWalkToStr8Builder(&walk, &builder, skip); - DN_Str8 result = DN_Str8BuilderBuildFromOSHeap(&builder); - DN_ArenaDeinit(&arena); - return result; -} - -DN_API DN_Slice DN_StackTraceGetFrames(DN_Arena *arena, uint16_t limit) -{ - DN_Slice result = {}; - if (!arena) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); - DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, limit); - if (!walk.size) - return result; - - DN_USize slice_index = 0; - result = DN_Slice_Alloc(arena, walk.size, DN_ZMem_No); - for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);) - result.data[slice_index++] = DN_StackTraceRawFrameToFrame(arena, it.raw_frame); - return result; -} - -DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame(DN_Arena *arena, DN_StackTraceRawFrame raw_frame) -{ -#if defined(DN_OS_WIN32) - // NOTE: Get line+filename - - // TODO: Why does zero-initialising this with `line = {};` cause - // SymGetLineFromAddr64 function to fail once we are at - // __scrt_commain_main_seh and hit BaseThreadInitThunk frame? The - // line and file number are still valid in the result which we use, so, - // we silently ignore this error. - IMAGEHLP_LINEW64 line; - line.SizeOfStruct = sizeof(line); - DWORD line_displacement = 0; - if (!SymGetLineFromAddrW64(raw_frame.process, raw_frame.base_addr, &line_displacement, &line)) - line = {}; - - // NOTE: Get function name - - alignas(SYMBOL_INFOW) char buffer[sizeof(SYMBOL_INFOW) + (MAX_SYM_NAME * sizeof(wchar_t))] = {}; - SYMBOL_INFOW *symbol = DN_Cast(SYMBOL_INFOW *) buffer; - symbol->SizeOfStruct = sizeof(*symbol); - symbol->MaxNameLen = sizeof(buffer) - sizeof(*symbol); - - uint64_t symbol_displacement = 0; // Offset to the beginning of the symbol to the address - SymFromAddrW(raw_frame.process, raw_frame.base_addr, &symbol_displacement, symbol); - - // NOTE: Construct result - - DN_Str16 file_name16 = DN_Str16{line.FileName, DN_CStr16Size(line.FileName)}; - DN_Str16 function_name16 = DN_Str16{symbol->Name, symbol->NameLen}; - - DN_StackTraceFrame result = {}; - result.address = raw_frame.base_addr; - result.line_number = line.LineNumber; - result.file_name = DN_W32_Str16ToStr8(arena, file_name16); - result.function_name = DN_W32_Str16ToStr8(arena, function_name16); - - if (result.function_name.size == 0) - result.function_name = DN_Str8Lit(""); - if (result.file_name.size == 0) - result.file_name = DN_Str8Lit(""); -#else - DN_StackTraceFrame result = {}; -#endif - return result; -} - -DN_API void DN_StackTracePrint(uint16_t limit) -{ - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Slice stack_trace = DN_StackTraceGetFrames(tmem.arena, limit); - for (DN_StackTraceFrame &frame : stack_trace) - DN_OS_PrintErrLnF("%.*s(%I64u): %.*s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name)); -} - -DN_API void DN_StackTraceReloadSymbols() -{ -#if defined(DN_OS_WIN32) - HANDLE process = GetCurrentProcess(); - SymRefreshModuleList(process); -#endif -} diff --git a/Source/OS/dn_os_string.cpp b/Source/OS/dn_os_string.cpp deleted file mode 100644 index 5936e23..0000000 --- a/Source/OS/dn_os_string.cpp +++ /dev/null @@ -1,305 +0,0 @@ -#define DN_OS_STRING_CPP - -#if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" -#endif - -// NOTE: DN_Str8 -DN_API DN_Str8 DN_Str8FromFmtArenaFrame(DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena; - DN_Str8 result = DN_Str8FromFmtVArena(frame_arena, fmt, args); - va_end(args); - return result; -} - -DN_API DN_Str8 DN_Str8FromFmtVArenaFrame(DN_FMT_ATTRIB char const *fmt, va_list args) -{ - DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena; - DN_Str8 result = DN_Str8FromFmtVArena(frame_arena, fmt, args); - return result; -} - -DN_API DN_Str8 DN_Str8FromArenaFrame(DN_USize size, DN_ZMem z_mem) -{ - DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena; - DN_Str8 result = DN_Str8FromArena(frame_arena, size, z_mem); - return result; -} - -DN_API DN_Str8 DN_Str8FromHeapF(DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_USize size = DN_FmtVSize(fmt, args); - DN_Str8 result = DN_Str8FromHeap(size, DN_ZMem_No); - DN_VSNPrintF(result.data, DN_Cast(int)(result.size + 1), fmt, args); - va_end(args); - return result; -} - -DN_API DN_Str8 DN_Str8FromHeap(DN_USize size, DN_ZMem z_mem) -{ - DN_Str8 result = {}; - result.data = DN_Cast(char *)DN_OS_MemAlloc(size + 1, z_mem); - if (result.data) { - result.size = size; - result.data[result.size] = 0; - } - return result; -} - -DN_API DN_Str8 DN_Str8FromTLSFV(DN_FMT_ATTRIB char const *fmt, va_list args) -{ - DN_Str8 result = DN_Str8FromFmtVArena(DN_OS_TLSTopArena(), fmt, args); - return result; -} - - -DN_API DN_Str8 DN_Str8FromTLSF(DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_Str8 result = DN_Str8FromFmtVArena(DN_OS_TLSTopArena(), fmt, args); - va_end(args); - return result; -} - -DN_API DN_Str8 DN_Str8FromTLS(DN_USize size, DN_ZMem z_mem) -{ - DN_Str8 result = DN_Str8FromArena(DN_OS_TLSTopArena(), size, z_mem); - return result; -} - -DN_API DN_Str8 DN_Str8FromStr8Frame(DN_Str8 string) -{ - DN_Str8 result = DN_Str8FromStr8Arena(DN_OS_TLSGet()->frame_arena, string); - return result; -} - -DN_API DN_Str8 DN_Str8FromStr8TLS(DN_Str8 string) -{ - DN_Str8 result = DN_Str8FromStr8Arena(DN_OS_TLSTopArena(), string); - return result; -} - -DN_API DN_Str8SplitResult DN_Str8SplitFromFrame(DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode) -{ - DN_Str8SplitResult result = DN_Str8SplitArena(DN_OS_TLSGet()->frame_arena, string, delimiter, mode); - return result; -} - -DN_API DN_Str8SplitResult DN_Str8SplitFromTLS(DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode) -{ - DN_Str8SplitResult result = DN_Str8SplitArena(DN_OS_TLSTopArena(), string, delimiter, mode); - return result; -} - -DN_API DN_Str8 DN_Str8SegmentFromFrame(DN_Str8 src, DN_USize segment_size, char segment_char) -{ - DN_Str8 result = DN_Str8Segment(DN_OS_TLSGet()->frame_arena, src, segment_size, segment_char); - return result; -} - -DN_API DN_Str8 DN_Str8SegmentFromTLS(DN_Str8 src, DN_USize segment_size, char segment_char) -{ - DN_Str8 result = DN_Str8Segment(DN_OS_TLSTopArena(), src, segment_size, segment_char); - return result; -} - -DN_API DN_Str8 DN_Str8ReverseSegmentFromFrame(DN_Str8 src, DN_USize segment_size, char segment_char) -{ - DN_Str8 result = DN_Str8ReverseSegment(DN_OS_TLSGet()->frame_arena, src, segment_size, segment_char); - return result; -} - -DN_API DN_Str8 DN_Str8ReverseSegmentFromTLS(DN_Str8 src, DN_USize segment_size, char segment_char) -{ - DN_Str8 result = DN_Str8ReverseSegment(DN_OS_TLSTopArena(), src, segment_size, segment_char); - return result; -} - -DN_API DN_Str8 DN_Str8AppendFFromFrame(DN_Str8 string, char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_Str8 result = DN_Str8AppendFV(DN_OS_TLSGet()->frame_arena, string, fmt, args); - va_end(args); - return result; -} - -DN_API DN_Str8 DN_Str8AppendFFromTLS(DN_Str8 string, char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_Str8 result = DN_Str8AppendFV(DN_OS_TLSTopArena(), string, fmt, args); - va_end(args); - return result; -} - -DN_API DN_Str8 DN_Str8FillFFromFrame(DN_USize count, char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_Str8 result = DN_Str8FillFV(DN_OS_TLSGet()->frame_arena, count, fmt, args); - va_end(args); - return result; -} - -DN_API DN_Str8 DN_Str8FillFFromTLS(DN_USize count, char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_Str8 result = DN_Str8FillFV(DN_OS_TLSTopArena(), count, fmt, args); - va_end(args); - return result; -} - -DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaFrame(DN_Str8 str8, uint32_t side_size, DN_Str8 truncator) -{ - DN_Str8TruncateResult result = DN_Str8TruncateMiddle(DN_OS_TLSGet()->frame_arena, str8, side_size, truncator); - return result; -} - -DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaTLS(DN_Str8 str8, uint32_t side_size, DN_Str8 truncator) -{ - DN_Str8TruncateResult result = DN_Str8TruncateMiddle(DN_OS_TLSTopArena(), str8, side_size, truncator); - return result; -} - -DN_API DN_Str8 DN_Str8PadNewLines(DN_Arena *arena, DN_Str8 src, DN_Str8 pad) -{ - // TODO: Implement this without requiring TLS so it can go into base strings - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena); - DN_Str8Builder builder = DN_Str8BuilderFromTLS(); - - DN_Str8BSplitResult split = DN_Str8BSplit(src, DN_Str8Lit("\n")); - while (split.lhs.size) { - DN_Str8BuilderAppendRef(&builder, pad); - DN_Str8BuilderAppendRef(&builder, split.lhs); - split = DN_Str8BSplit(split.rhs, DN_Str8Lit("\n")); - if (split.lhs.size) - DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n")); - } - - DN_Str8 result = DN_Str8BuilderBuild(&builder, arena); - return result; -} - -DN_API DN_Str8 DN_Str8PadNewLinesFromFrame(DN_Str8 src, DN_Str8 pad) -{ - DN_Str8 result = DN_Str8PadNewLines(DN_OS_TLSGet()->frame_arena, src, pad); - return result; -} - -DN_API DN_Str8 DN_Str8PadNewLinesFromTLS(DN_Str8 src, DN_Str8 pad) -{ - DN_Str8 result = DN_Str8PadNewLines(DN_OS_TLSTopArena(), src, pad); - return result; -} - -DN_API DN_Str8 DN_Str8UpperFromFrame(DN_Str8 string) -{ - DN_Str8 result = DN_Str8Upper(DN_OS_TLSGet()->frame_arena, string); - return result; -} - -DN_API DN_Str8 DN_Str8UpperFromTLS(DN_Str8 string) -{ - DN_Str8 result = DN_Str8Upper(DN_OS_TLSTopArena(), string); - return result; -} - -DN_API DN_Str8 DN_Str8LowerFromFrame(DN_Str8 string) -{ - DN_Str8 result = DN_Str8Lower(DN_OS_TLSGet()->frame_arena, string); - return result; -} - -DN_API DN_Str8 DN_Str8LowerFromTLS(DN_Str8 string) -{ - DN_Str8 result = DN_Str8Lower(DN_OS_TLSTopArena(), string); - return result; -} - -DN_API DN_Str8 DN_Str8Replace(DN_Str8 string, - DN_Str8 find, - DN_Str8 replace, - DN_USize start_index, - DN_Arena *arena, - DN_Str8EqCase eq_case) -{ - // TODO: Implement this without requiring TLS so it can go into base strings - DN_Str8 result = {}; - if (string.size == 0 || find.size == 0 || find.size > string.size || find.size == 0 || string.size == 0) { - result = DN_Str8FromStr8Arena(arena, string); - return result; - } - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); - DN_Str8Builder string_builder = DN_Str8BuilderFromArena(tmem.arena); - DN_USize max = string.size - find.size; - DN_USize head = start_index; - - for (DN_USize tail = head; tail <= max; tail++) { - DN_Str8 check = DN_Str8Slice(string, tail, find.size); - if (!DN_Str8Eq(check, find, eq_case)) - continue; - - if (start_index > 0 && string_builder.string_size == 0) { - // User provided a hint in the string to start searching from, we - // need to add the string up to the hint. We only do this if there's - // a replacement action, otherwise we have a special case for no - // replacements, where the entire string gets copied. - DN_Str8 slice = DN_Str8FromPtr(string.data, head); - DN_Str8BuilderAppendRef(&string_builder, slice); - } - - DN_Str8 range = DN_Str8Slice(string, head, (tail - head)); - DN_Str8BuilderAppendRef(&string_builder, range); - DN_Str8BuilderAppendRef(&string_builder, replace); - head = tail + find.size; - tail += find.size - 1; // NOTE: -1 since the for loop will post increment us past the end of the find string - } - - if (string_builder.string_size == 0) { - // NOTE: No replacement possible, so we just do a full-copy - result = DN_Str8FromStr8Arena(arena, string); - } else { - DN_Str8 remainder = DN_Str8FromPtr(string.data + head, string.size - head); - DN_Str8BuilderAppendRef(&string_builder, remainder); - result = DN_Str8BuilderBuild(&string_builder, arena); - } - - return result; -} - -DN_API DN_Str8 DN_Str8ReplaceInsensitive(DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena) -{ - DN_Str8 result = DN_Str8Replace(string, find, replace, start_index, arena, DN_Str8EqCase_Insensitive); - return result; -} - -// NOTE: DN_Str8Builder //////////////////////////////////////////////////////////////////////////// -DN_API DN_Str8 DN_Str8BuilderBuildFromOSHeap(DN_Str8Builder const *builder) -{ - DN_Str8 result = DN_ZeroInit; - if (!builder || builder->string_size <= 0 || builder->count <= 0) - return result; - - result.data = DN_Cast(char *) DN_OS_MemAlloc(builder->string_size + 1, DN_ZMem_No); - if (!result.data) - return result; - - for (DN_Str8Link *link = builder->head; link; link = link->next) { - DN_Memcpy(result.data + result.size, link->string.data, link->string.size); - result.size += link->string.size; - } - - result.data[result.size] = 0; - DN_Assert(result.size == builder->string_size); - return result; -} diff --git a/Source/OS/dn_os_string.h b/Source/OS/dn_os_string.h deleted file mode 100644 index af8f8da..0000000 --- a/Source/OS/dn_os_string.h +++ /dev/null @@ -1,76 +0,0 @@ -#if !defined(DN_OS_STRING_H) -#define DN_OS_STRING_H - -#if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" -#endif - -// NOTE: DN_Str8 - -DN_API DN_Str8 DN_Str8FromFmtVArenaFrame (DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API DN_Str8 DN_Str8FromFmtArenaFrame (DN_FMT_ATTRIB char const *fmt, ...); -DN_API DN_Str8 DN_Str8FromArenaFrame (DN_USize size, DN_ZMem z_mem); -DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...); -DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem); -DN_API DN_Str8 DN_Str8FromTLSFV (DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API DN_Str8 DN_Str8FromTLSF (DN_FMT_ATTRIB char const *fmt, ...); -DN_API DN_Str8 DN_Str8FromTLS (DN_USize size, DN_ZMem z_mem); -DN_API DN_Str8 DN_Str8FromStr8Frame (DN_Str8 string); -DN_API DN_Str8 DN_Str8FromStr8TLS (DN_Str8 string); - -DN_API DN_Str8SplitResult DN_Str8SplitFromFrame (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode); -DN_API DN_Str8SplitResult DN_Str8SplitFromTLS (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode); - -DN_API DN_Str8 DN_Str8SegmentFromFrame (DN_Str8 src, DN_USize segment_size, char segment_char); -DN_API DN_Str8 DN_Str8SegmentFromTLS (DN_Str8 src, DN_USize segment_size, char segment_char); - -DN_API DN_Str8 DN_Str8ReverseSegmentFromFrame (DN_Str8 src, DN_USize segment_size, char segment_char); -DN_API DN_Str8 DN_Str8ReverseSegmentFromTLS (DN_Str8 src, DN_USize segment_size, char segment_char); - -DN_API DN_Str8 DN_Str8AppendFFromFrame (DN_Str8 string, char const *fmt, ...); -DN_API DN_Str8 DN_Str8AppendFFromTLS (DN_Str8 string, char const *fmt, ...); - -DN_API DN_Str8 DN_Str8FillFFromFrame (DN_Str8 string, char const *fmt, ...); -DN_API DN_Str8 DN_Str8FillFFromTLS (DN_Str8 string, char const *fmt, ...); - -DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaFrame (DN_Str8 str8, uint32_t side_size, DN_Str8 truncator); -DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaTLS (DN_Str8 str8, uint32_t side_size, DN_Str8 truncator); - -DN_API DN_Str8 DN_Str8PadNewLines (DN_Arena *arena, DN_Str8 src, DN_Str8 pad); -DN_API DN_Str8 DN_Str8PadNewLinesFromFrame (DN_Str8 src, DN_Str8 pad); -DN_API DN_Str8 DN_Str8PadNewLinesFromTLS (DN_Str8 src, DN_Str8 pad); - -DN_API DN_Str8 DN_Str8UpperFromFrame (DN_Str8 string); -DN_API DN_Str8 DN_Str8UpperFromTLS (DN_Str8 string); - -DN_API DN_Str8 DN_Str8LowerFromFrame (DN_Str8 string); -DN_API DN_Str8 DN_Str8LowerFromTLS (DN_Str8 string); - -DN_API DN_Str8 DN_Str8Replace (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); -DN_API DN_Str8 DN_Str8ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena); - -// NOTE: DN_Str8Builder //////////////////////////////////////////////////////////////////////////// - -DN_API DN_Str8Builder DN_Str8BuilderFromArena () { return DN_Str8BuilderFromArena(DN_OS_TLSGet()->frame_arena); } -DN_API DN_Str8Builder DN_Str8BuilderFromTLS () { return DN_Str8BuilderFromArena(DN_OS_TLSTopArena()); } - -DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRefFrame (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrRef(DN_OS_TLSGet()->frame_arena, strings, size); } -DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRefTLS (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrRef(DN_OS_TLSTopArena(), strings, size); } -DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopyFrame (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrCopy(DN_OS_TLSGet()->frame_arena, strings, size); } -DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopyTLS (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrCopy(DN_OS_TLSTopArena(), strings, size); } - -DN_API DN_Str8Builder DN_Str8BuilderFromBuilderFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderFromBuilder(DN_OS_TLSGet()->frame_arena, builder); } -DN_API DN_Str8Builder DN_Str8BuilderFromBuilderTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderFromBuilder(DN_OS_TLSTopArena(), builder); } - -DN_API DN_Str8 DN_Str8BuilderBuildFromFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderBuild(builder, DN_OS_TLSGet()->frame_arena); } -DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder, DN_Arena *arena); -DN_API DN_Str8 DN_Str8BuilderBuildFromTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderBuild(builder, DN_OS_TLSTopArena()); } - -DN_API DN_Str8 DN_Str8BuilderBuildDelimitedFromFrame(DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8BuilderBuildDelimited(builder, delimiter, DN_OS_TLSGet()->frame_arena); } -DN_API DN_Str8 DN_Str8BuilderBuildDelimitedFromTLS (DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8BuilderBuildDelimited(builder, delimiter, DN_OS_TLSTopArena()); } - -DN_API DN_Slice DN_Str8BuilderBuildSliceFromFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderBuildSlice(builder, DN_OS_TLSGet()->frame_arena); } -DN_API DN_Slice DN_Str8BuilderBuildSliceFromTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderBuildSlice(builder, DN_OS_TLSTopArena()); } - -#endif // !defined(DN_OS_STRING_H) diff --git a/Source/OS/dn_os_tls.cpp b/Source/OS/dn_os_tls.cpp deleted file mode 100644 index 74fd333..0000000 --- a/Source/OS/dn_os_tls.cpp +++ /dev/null @@ -1,418 +0,0 @@ -#define DN_OS_TLSCPP - -#if defined(_CLANGD) - #include "dn_os_tls.h" -#endif - -// NOTE: DN_OSTLS //////////////////////////////////////////////////////////////////////////////////// -DN_OSTLSTMem::DN_OSTLSTMem(DN_OSTLS *tls, DN_U8 arena_index, DN_OSTLSPushTMem push_tmem) -{ - DN_Assert(arena_index == DN_OSTLSArena_TMem0 || arena_index == DN_OSTLSArena_TMem1); - arena = tls->arenas + arena_index; - temp_mem = DN_ArenaTempMemBegin(arena); - destructed = false; - push_arena = push_tmem; - if (push_arena) - DN_OS_TLSPushArena(arena); -} - -DN_OSTLSTMem::~DN_OSTLSTMem() -{ - DN_Assert(destructed == false); - DN_ArenaTempMemEnd(temp_mem); - destructed = true; - if (push_arena) - DN_OS_TLSPopArena(); -} - -DN_API void DN_OS_TLSInit(DN_OSTLS *tls, DN_OSTLSInitArgs args) -{ - DN_Check(tls); - if (tls->init) - return; - - DN_U64 reserve = args.reserve ? args.reserve : DN_Kilobytes(64); - DN_U64 err_sink_reserve = args.err_sink_reserve ? args.err_sink_reserve : DN_Kilobytes(64); - - #if !defined(DN_PLATFORM_EMSCRIPTEN) - DN_U64 commit = args.commit ? args.commit : DN_Kilobytes(4); - DN_U64 err_sink_commit = args.err_sink_commit ? args.err_sink_commit : DN_Kilobytes(4); - #endif - - // TODO: We shouldn't have the no alloc track flag here but the initial TLS - // init on OS init happens before CORE init. CORE init is the one responsible - // for setting up the alloc tracking data structures. - for (DN_ForItCArray(it, DN_Arena, tls->arenas)) { - DN_Arena *arena = it.data; - switch (DN_Cast(DN_OSTLSArena) it.index) { - default: { - #if defined(DN_PLATFORM_EMSCRIPTEN) - *arena = DN_ArenaFromHeap(reserve, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack); - #else - *arena = DN_ArenaFromVMem(reserve, commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack); - #endif - } break; - - case DN_OSTLSArena_ErrorSink: { - #if defined(DN_PLATFORM_EMSCRIPTEN) - *arena = DN_ArenaFromHeap(err_sink_reserve, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack); - #else - *arena = DN_ArenaFromVMem(err_sink_reserve, err_sink_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack); - #endif - } break; - - case DN_OSTLSArena_Count: DN_InvalidCodePath; break; - } - } - - tls->thread_id = DN_OS_ThreadID(); - tls->err_sink.arena = tls->arenas + DN_OSTLSArena_ErrorSink; - tls->init = true; -} - -DN_API void DN_OS_TLSDeinit(DN_OSTLS *tls) -{ - tls->init = false; - tls->err_sink = {}; - tls->arena_stack_index = {}; - for (DN_ForItCArray(it, DN_Arena, tls->arenas)) - DN_ArenaDeinit(it.data); -} - -DN_THREAD_LOCAL DN_OSTLS *g_dn_curr_thread_tls; -DN_API void DN_OS_TLSSetCurrentThreadTLS(DN_OSTLS *tls) -{ - g_dn_curr_thread_tls = tls; -} - -DN_API DN_OSTLS *DN_OS_TLSGet() -{ - DN_RawAssert(g_dn_curr_thread_tls && - "DN must be initialised (via DN_Core_Init) before calling any functions depending on " - "TLS if this is the main thread, OR, the created thread has not called " - "SetCurrentThreadTLS yet so the TLS data structure hasn't been assigned yet"); - return g_dn_curr_thread_tls; -} - -DN_API DN_Arena *DN_OS_TLSArena() -{ - DN_OSTLS *tls = DN_OS_TLSGet(); - DN_Arena *result = tls->arenas + DN_OSTLSArena_Main; - return result; -} - -// TODO: Is there a way to handle conflict arenas without the user needing to -// manually pass it in? -DN_API DN_OSTLSTMem DN_OS_TLSGetTMem(void const *conflict_arena, DN_OSTLSPushTMem push_tmem) -{ - DN_OSTLS *tls = DN_OS_TLSGet(); - DN_U8 tls_index = (DN_U8)-1; - for (DN_U8 index = DN_OSTLSArena_TMem0; index <= DN_OSTLSArena_TMem1; index++) { - DN_Arena *arena = tls->arenas + index; - if (!conflict_arena || arena != conflict_arena) { - tls_index = index; - break; - } - } - - DN_Assert(tls_index != (DN_U8)-1); - return DN_OSTLSTMem(tls, tls_index, push_tmem); -} - -DN_API void DN_OS_TLSPushArena(DN_Arena *arena) -{ - DN_Assert(arena); - DN_OSTLS *tls = DN_OS_TLSGet(); - DN_Assert(tls->arena_stack_index < DN_ArrayCountU(tls->arena_stack)); - tls->arena_stack[tls->arena_stack_index++] = arena; -} - -DN_API void DN_OS_TLSPopArena() -{ - DN_OSTLS *tls = DN_OS_TLSGet(); - DN_Assert(tls->arena_stack_index > 0); - tls->arena_stack_index--; -} - -DN_API DN_Arena *DN_OS_TLSTopArena() -{ - DN_OSTLS *tls = DN_OS_TLSGet(); - DN_Arena *result = nullptr; - if (tls->arena_stack_index) - result = tls->arena_stack[tls->arena_stack_index - 1]; - return result; -} - -DN_API void DN_OS_TLSBeginFrame(DN_Arena *frame_arena) -{ - DN_OSTLS *tls = DN_OS_TLSGet(); - tls->frame_arena = frame_arena; -} - -DN_API DN_Arena *DN_OS_TLSFrameArena() -{ - DN_OSTLS *tls = DN_OS_TLSGet(); - DN_Arena *result = tls->frame_arena; - DN_AssertF(result, "Frame arena must be set by calling DN_OS_TLSBeginFrame at the beginning of the frame"); - return result; -} - -// NOTE: DN_OSErrSink //////////////////////////////////////////////////////////////////////////////// -static void DN_OS_ErrSinkCheck_(DN_OSErrSink const *err) -{ - DN_AssertF(err->arena, "Arena should be assigned in TLS init"); - if (err->stack_size == 0) - return; - - DN_OSErrSinkNode const *node = err->stack + (err->stack_size - 1); - DN_Assert(node->mode >= DN_OSErrSinkMode_Nil && node->mode <= DN_OSErrSinkMode_ExitOnError); - DN_Assert(node->msg_sentinel); - - // NOTE: Walk the list ensuring we eventually terminate at the sentinel (e.g. we have a - // well formed doubly-linked-list terminated by a sentinel, or otherwise we will hit the - // walk limit or dereference a null pointer and assert) - size_t WALK_LIMIT = 99'999; - size_t walk = 0; - for (DN_OSErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next, walk++) { - DN_AssertF(it, "Encountered null pointer which should not happen in a sentinel DLL"); - DN_Assert(walk < WALK_LIMIT); - } -} - -DN_API DN_OSErrSink *DN_OS_ErrSinkBegin_(DN_OSErrSinkMode mode, DN_CallSite call_site) -{ - DN_OSTLS *tls = DN_OS_TLSGet(); - DN_OSErrSink *err = &tls->err_sink; - DN_OSErrSink *result = err; - DN_USize arena_pos = DN_ArenaPos(result->arena); - - if (tls->err_sink.stack_size == DN_ArrayCountU(err->stack)) { - DN_Str8Builder builder = DN_Str8BuilderFromTLS(); - DN_USize counter = 0; - for (DN_ForItSize(it, DN_OSErrSinkNode, err->stack, err->stack_size)) { - DN_MSVC_WARNING_PUSH - DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(4) when a string is required in call to 'DN_Str8BuilderAppendF' Actual type: 'struct DN_Str8'. - DN_Str8BuilderAppendF(&builder, " [%04zu] %S:%u %S\n", counter++, it.data->call_site.file, it.data->call_site.line, it.data->call_site.function); - DN_MSVC_WARNING_POP - } - - DN_MSVC_WARNING_PUSH - DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(6) when a string is required in call to 'DN_LOG_EmitFromType' Actual type: 'struct DN_Str8'. - DN_AssertF(tls->err_sink.stack_size < DN_ArrayCountU(err->stack), - "Error sink has run out of error scopes, potential leak. Scopes were\n%S", DN_Str8BuilderBuildFromTLS(&builder)); - DN_MSVC_WARNING_POP - } - - DN_OSErrSinkNode *node = tls->err_sink.stack + tls->err_sink.stack_size++; - node->arena_pos = arena_pos; - node->mode = mode; - node->call_site = call_site; - DN_DLList_InitArena(node->msg_sentinel, DN_OSErrSinkMsg, result->arena); - - // NOTE: Handle allocation error - if (!DN_Check(node && node->msg_sentinel)) { - DN_ArenaPopTo(result->arena, arena_pos); - node->msg_sentinel = nullptr; - tls->err_sink.stack_size--; - } - - return result; -} - -DN_API bool DN_OS_ErrSinkHasError(DN_OSErrSink *err) -{ - bool result = false; - if (err && err->stack_size) { - DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1); - result = DN_DLList_HasItems(node->msg_sentinel); - } - return result; -} - -DN_API DN_OSErrSinkMsg *DN_OS_ErrSinkEnd(DN_Arena *arena, DN_OSErrSink *err) -{ - DN_OSErrSinkMsg *result = nullptr; - DN_OS_ErrSinkCheck_(err); - if (!err || err->stack_size == 0) - return result; - - DN_AssertF(arena != err->arena, - "You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost"); - // NOTE: Walk the list and allocate it onto the user's arena - DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1); - DN_OSErrSinkMsg *prev = nullptr; - for (DN_OSErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next) { - DN_OSErrSinkMsg *entry = DN_ArenaNew(arena, DN_OSErrSinkMsg, DN_ZMem_Yes); - entry->msg = DN_Str8FromStr8Arena(arena, it->msg); - entry->call_site = it->call_site; - entry->error_code = it->error_code; - if (!result) - result = entry; // Assign first entry if we haven't yet - if (prev) - prev->next = entry; // Link the prev message to the current one - prev = entry; // Update prev to latest - } - - // NOTE: Deallocate all the memory for this scope - err->stack_size--; - DN_ArenaPopTo(err->arena, node->arena_pos); - return result; -} - -static void DN_OS_ErrSinkAddMsgToStr8Builder(DN_Str8Builder *builder, DN_OSErrSinkMsg *msg, DN_OSErrSinkMsg *end) -{ - if (msg == end) // NOTE: No error messages to add - return; - - if (msg->next == end) { - DN_OSErrSinkMsg *it = msg; - DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file); - DN_Str8BuilderAppendF(builder, - "%.*s:%05I32u:%.*s %.*s", - DN_Str8PrintFmt(file_name), - it->call_site.line, - DN_Str8PrintFmt(it->call_site.function), - DN_Str8PrintFmt(it->msg)); - } else { - // NOTE: More than one message - for (DN_OSErrSinkMsg *it = msg; it != end; it = it->next) { - DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file); - DN_Str8BuilderAppendF(builder, - "%s - %.*s:%05I32u:%.*s%s%.*s", - it == msg ? "" : "\n", - DN_Str8PrintFmt(file_name), - it->call_site.line, - DN_Str8PrintFmt(it->call_site.function), - it->msg.size ? " " : "", - DN_Str8PrintFmt(it->msg)); - } - } -} - -DN_API DN_Str8 DN_OS_ErrSinkEndStr8(DN_Arena *arena, DN_OSErrSink *err) -{ - DN_Str8 result = {}; - DN_OS_ErrSinkCheck_(err); - if (!err || err->stack_size == 0) - return result; - - DN_AssertF(arena != err->arena, - "You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost"); - - // NOTE: Walk the list and allocate it onto the user's arena - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena); - DN_Str8Builder builder = DN_Str8BuilderFromTLS(); - DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1); - DN_OS_ErrSinkAddMsgToStr8Builder(&builder, node->msg_sentinel->next, node->msg_sentinel); - - // NOTE: Deallocate all the memory for this scope - err->stack_size--; - DN_U64 arena_pos = node->arena_pos; - DN_ArenaPopTo(err->arena, arena_pos); - - result = DN_Str8BuilderBuild(&builder, arena); - return result; -} - -DN_API void DN_OS_ErrSinkEndAndIgnore(DN_OSErrSink *err) -{ - DN_OS_ErrSinkEnd(nullptr, err); -} - -DN_API bool DN_OS_ErrSinkEndAndLogError_(DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 err_msg) -{ - DN_AssertF(err->stack_size, "Begin must be called before calling end"); - DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1); - DN_AssertF(node->msg_sentinel, "Begin must be called before calling end"); - - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); - DN_OSErrSinkMode mode = node->mode; - DN_OSErrSinkMsg *msg = DN_OS_ErrSinkEnd(tmem.arena, err); - if (!msg) - return false; - - DN_Str8Builder builder = DN_Str8BuilderFromTLS(); - if (err_msg.size) { - DN_Str8BuilderAppendRef(&builder, err_msg); - DN_Str8BuilderAppendRef(&builder, DN_Str8Lit(":")); - } else { - DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("Error(s) encountered:")); - } - - if (msg->next) // NOTE: More than 1 message - DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n")); - DN_OS_ErrSinkAddMsgToStr8Builder(&builder, msg, nullptr); - - DN_Str8 log = DN_Str8BuilderBuildFromTLS(&builder); - DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), call_site, "%.*s", DN_Str8PrintFmt(log)); - - if (mode == DN_OSErrSinkMode_DebugBreakOnEndAndLog) - DN_DebugBreak; - return true; -} - -DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_(DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) -{ - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 log = DN_Str8FromFmtVArena(tmem.arena, fmt, args); - bool result = DN_OS_ErrSinkEndAndLogError_(err, call_site, log); - return result; -} - -DN_API bool DN_OS_ErrSinkEndAndLogErrorF_(DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 log = DN_Str8FromFmtVArena(tmem.arena, fmt, args); - bool result = DN_OS_ErrSinkEndAndLogError_(err, call_site, log); - va_end(args); - return result; -} - -DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_(DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args) -{ - if (DN_OS_ErrSinkEndAndLogErrorFV_(err, call_site, fmt, args)) { - DN_DebugBreak; - DN_OS_Exit(exit_val); - } -} - -DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_(DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - DN_OS_ErrSinkEndAndExitIfErrorFV_(err, call_site, exit_val, fmt, args); - va_end(args); -} - -DN_API void DN_OS_ErrSinkAppendFV_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args) -{ - if (!err) - return; - DN_Assert(err && err->stack_size); - DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1); - DN_AssertF(node, "Error sink must be begun by calling 'Begin' before using this function."); - - DN_OSErrSinkMsg *msg = DN_ArenaNew(err->arena, DN_OSErrSinkMsg, DN_ZMem_Yes); - if (DN_Check(msg)) { - msg->msg = DN_Str8FromFmtVArena(err->arena, fmt, args); - msg->error_code = error_code; - msg->call_site = DN_OS_TLSGet()->call_site; - DN_DLList_Prepend(node->msg_sentinel, msg); - - if (node->mode == DN_OSErrSinkMode_ExitOnError) - DN_OS_ErrSinkEndAndExitIfErrorF_(err, msg->call_site, error_code, "Fatal error %u", error_code); - } -} - -DN_API void DN_OS_ErrSinkAppendF_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...) -{ - if (!err) - return; - va_list args; - va_start(args, fmt); - DN_OS_ErrSinkAppendFV_(err, error_code, fmt, args); - va_end(args); -} - diff --git a/Source/OS/dn_os_tls.h b/Source/OS/dn_os_tls.h deleted file mode 100644 index b71e232..0000000 --- a/Source/OS/dn_os_tls.h +++ /dev/null @@ -1,142 +0,0 @@ -#if !defined(DN_OS_TLS_H) -#define DN_OS_TLS_H - -#if defined(_CLANGD) - #include "../dn_base_inc.h" - #include "../dn_os_inc.h" -#endif - -// NOTE: DN_OSErrSink -enum DN_OSErrSinkMode -{ - DN_OSErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink - DN_OSErrSinkMode_DebugBreakOnEndAndLog, // Debug break (int3) when error is encountered and the sink is ended by the 'end and log' functions. - DN_OSErrSinkMode_ExitOnError, // When an error is encountered, exit the program with the error code of the error that was caught. -}; - -struct DN_OSErrSinkMsg -{ - DN_I32 error_code; - DN_Str8 msg; - DN_CallSite call_site; - DN_OSErrSinkMsg *next; - DN_OSErrSinkMsg *prev; -}; - -struct DN_OSErrSinkNode -{ - DN_CallSite call_site; // Call site that the node was created - DN_OSErrSinkMode mode; // Controls how the sink behaves when an error is registered onto the sink. - DN_OSErrSinkMsg *msg_sentinel; // List of error messages accumulated for the current scope - DN_U64 arena_pos; // Position to reset the arena when the scope is ended -}; - -struct DN_OSErrSink -{ - DN_Arena * arena; // Dedicated allocator from the thread's local storage - DN_OSErrSinkNode stack[128]; // Each entry contains errors accumulated between a [begin, end] region of the active sink. - DN_USize stack_size; -}; - -enum DN_OSTLSArena -{ - DN_OSTLSArena_Main, // NOTE: Arena for permanent allocations - DN_OSTLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread - - // NOTE: Per-thread scratch arenas (2 to prevent aliasing) - DN_OSTLSArena_TMem0, - DN_OSTLSArena_TMem1, - - DN_OSTLSArena_Count, -}; - -struct DN_OSTLS -{ - DN_B32 init; // Flag to track if TLS has been initialised - DN_U64 thread_id; - DN_CallSite call_site; // Stores call-site information when requested by thread - DN_OSErrSink err_sink; // Error handling state - DN_Arena arenas[DN_OSTLSArena_Count]; // Default arenas that the thread has access to implicitly - DN_Arena * arena_stack[8]; // Active stack of arenas push/popped arenas on into the TLS - DN_USize arena_stack_index; - - DN_Arena * frame_arena; - char name[64]; - DN_U8 name_size; -}; - -// Push the temporary memory arena when retrieved, popped when the arena goes -// out of scope. Pushed arenas are used automatically as the allocator in TLS -// suffixed function. -enum DN_OSTLSPushTMem -{ - DN_OSTLSPushTMem_No, - DN_OSTLSPushTMem_Yes, -}; - -struct DN_OSTLSTMem -{ - DN_OSTLSTMem(DN_OSTLS *context, uint8_t context_index, DN_OSTLSPushTMem push_scratch); - ~DN_OSTLSTMem(); - DN_Arena *arena; - DN_B32 destructed; - DN_OSTLSPushTMem push_arena; - DN_ArenaTempMem temp_mem; -}; - -struct DN_OSTLSInitArgs -{ - DN_U64 reserve; - DN_U64 commit; - DN_U64 err_sink_reserve; - DN_U64 err_sink_commit; -}; - -DN_API void DN_OS_TLSInit (DN_OSTLS *tls, DN_OSTLSInitArgs args); -DN_API void DN_OS_TLSDeinit (DN_OSTLS *tls); -DN_API DN_OSTLS * DN_OS_TLSGet (); -DN_API void DN_OS_TLSSetCurrentThreadTLS (DN_OSTLS *tls); -DN_API DN_Arena * DN_OS_TLSArena (); -DN_API DN_OSTLSTMem DN_OS_TLSGetTMem (void const *conflict_arena, DN_OSTLSPushTMem push_tmp_mem); -DN_API void DN_OS_TLSPushArena (DN_Arena *arena); -DN_API void DN_OS_TLSPopArena (); -DN_API DN_Arena * DN_OS_TLSTopArena (); -DN_API void DN_OS_TLSBeginFrame (DN_Arena *frame_arena); -DN_API DN_Arena * DN_OS_TLSFrameArena (); -#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0) -#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No) -#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes) - -DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site); -#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE) -#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil) -DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err); -DN_API DN_OSErrSinkMsg * DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err); -DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err); -DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err); -DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg); -DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...); -#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg) -#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args) -#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__) -#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args) -#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__) - -#define DN_OS_ErrSinkAppendFV(error, error_code, fmt, args) \ - do { \ - DN_OS_TLSSaveCallSite; \ - DN_OS_ErrSinkAppendFV_(error, error_code, fmt, args); \ - } while (0) - -#define DN_OS_ErrSinkAppendF(error, error_code, fmt, ...) \ - do { \ - DN_OS_TLSSaveCallSite; \ - DN_OS_ErrSinkAppendF_(error, error_code, fmt, ##__VA_ARGS__); \ - } while (0) - -#endif // defined(DN_OS_TLS_H) diff --git a/Source/OS/dn_os_w32.cpp b/Source/OS/dn_os_w32.cpp index cb492aa..1c890b6 100644 --- a/Source/OS/dn_os_w32.cpp +++ b/Source/OS/dn_os_w32.cpp @@ -1,23 +1,12 @@ -#define DN_OS_WIN32_CPP +#define DN_OS_W32_CPP -/* -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$\ $$\ $$\ $$$$$$\ $$$$$$\ -// $$ __$$\ $$ __$$\ $$ | $\ $$ |\_$$ _|$$$\ $$ |$$ ___$$\ $$ __$$\ -// $$ / $$ |$$ / \__| $$ |$$$\ $$ | $$ | $$$$\ $$ |\_/ $$ |\__/ $$ | -// $$ | $$ |\$$$$$$\ $$ $$ $$\$$ | $$ | $$ $$\$$ | $$$$$ / $$$$$$ | -// $$ | $$ | \____$$\ $$$$ _$$$$ | $$ | $$ \$$$$ | \___$$\ $$ ____/ -// $$ | $$ |$$\ $$ | $$$ / \$$$ | $$ | $$ |\$$$ |$$\ $$ |$$ | -// $$$$$$ |\$$$$$$ | $$ / \$$ |$$$$$$\ $$ | \$$ |\$$$$$$ |$$$$$$$$\ -// \______/ \______/ \__/ \__|\______|\__| \__| \______/ \________| -// -// dn_os_w32.cpp -// -//////////////////////////////////////////////////////////////////////////////////////////////////// -*/ +#if defined(_CLANGD) + #define DN_H_WITH_CORE 1 + #include "../dn.h" + #include "dn_os_w32.h" +#endif -// NOTE: DN_Mem /////////////////////////////////////////////////////////////////////////// +// NOTE: DN_Mem static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect) { DN_Assert((protect & ~DN_MemPage_All) == 0); @@ -31,7 +20,7 @@ static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect) } else if (protect & DN_MemPage_Read) { result = PAGE_READONLY; } else if (protect & DN_MemPage_Write) { - DN_LOG_WarningF("Windows does not support write-only pages, granting read+write access"); + DN_LogWarningF("Windows does not support write-only pages, granting read+write access"); result = PAGE_READWRITE; } @@ -210,7 +199,7 @@ DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS(DN_U64 unix_ts_s) DN_API void DN_OS_GenBytesSecure(void *buffer, DN_U32 size) { DN_Assert(g_dn_); - DN_W32Core *w32 = DN_Cast(DN_W32Core *) g_dn_->os.platform_context; + DN_OSW32Core *w32 = DN_Cast(DN_OSW32Core *) g_dn_->os.platform_context; DN_Assert(w32->bcrypt_init_success); long gen_status = BCryptGenRandom(w32->bcrypt_rng_handle, DN_Cast(unsigned char *) buffer, size, 0 /*flags*/); @@ -221,9 +210,9 @@ DN_API void DN_OS_GenBytesSecure(void *buffer, DN_U32 size) DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path) { - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_OSDiskSpace result = {}; - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); ULARGE_INTEGER free_bytes_avail_to_caller; ULARGE_INTEGER total_number_of_bytes; @@ -231,21 +220,25 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path) if (!GetDiskFreeSpaceExW(path16.data, &free_bytes_avail_to_caller, &total_number_of_bytes, - &total_number_of_free_bytes)) + &total_number_of_free_bytes)) { + DN_TCScratchEnd(&scratch); return result; + } result.success = true; result.avail = free_bytes_avail_to_caller.QuadPart; result.size = total_number_of_bytes.QuadPart; + DN_TCScratchEnd(&scratch); return result; } DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value) { - DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); - DN_Str16 name16 = DN_W32_Str8ToStr16(tmem.arena, name); - DN_Str16 value16 = DN_W32_Str8ToStr16(tmem.arena, value); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); +DN_Str16 name16 = DN_OS_W32Str8ToStr16(scratch.arena, name); + DN_Str16 value16 = DN_OS_W32Str8ToStr16(scratch.arena, value); bool result = SetEnvironmentVariableW(name16.data, value16.data) != 0; + DN_TCScratchEnd(&scratch); return result; } @@ -254,9 +247,10 @@ DN_API DN_Str8 DN_OS_EXEPath(DN_Arena *arena) DN_Str8 result = {}; if (!arena) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); - DN_Str16 exe_dir16 = DN_W32_EXEPathW(tmem.arena); - result = DN_W32_Str16ToStr8(arena, exe_dir16); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); +DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(scratch.arena); + result = DN_OS_W32Str16ToStr8(arena, exe_dir16); + DN_TCScratchEnd(&scratch); return result; } @@ -268,7 +262,7 @@ DN_API void DN_OS_SleepMs(DN_UInt milliseconds) DN_API DN_U64 DN_OS_PerfCounterFrequency() { DN_Assert(g_dn_); - DN_W32Core *w32 = DN_Cast(DN_W32Core *) g_dn_->os.platform_context; + DN_OSW32Core *w32 = DN_Cast(DN_OSW32Core *) g_dn_->os.platform_context; DN_Assert(w32->qpc_frequency.QuadPart); DN_U64 result = w32->qpc_frequency.QuadPart; return result; @@ -282,7 +276,7 @@ DN_API DN_U64 DN_OS_PerfCounterNow() return result; } -static DN_U64 DN_W32_FileTimeToSeconds_(FILETIME const *time) +static DN_U64 DN_OS_W32FileTimeToSeconds_(FILETIME const *time) { ULARGE_INTEGER time_large_int = {}; time_large_int.u.LowPart = time->dwLowDateTime; @@ -291,19 +285,19 @@ static DN_U64 DN_W32_FileTimeToSeconds_(FILETIME const *time) return result; } -DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) +DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err) { bool result = false; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 src16 = DN_W32_Str8ToStr16(tmem.arena, src); - DN_Str16 dest16 = DN_W32_Str8ToStr16(tmem.arena, dest); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); +DN_Str16 src16 = DN_OS_W32Str8ToStr16(scratch.arena, src); + DN_Str16 dest16 = DN_OS_W32Str8ToStr16(scratch.arena, dest); int fail_if_exists = overwrite == false; result = CopyFileW(src16.data, dest16.data, fail_if_exists) != 0; if (!result) { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); - DN_OS_ErrSinkAppendF(err, + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); + DN_ErrSinkAppendF(err, win_error.code, "Failed to copy file '%.*s' to '%.*s': (%u) %.*s", DN_Str8PrintFmt(src), @@ -311,15 +305,16 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi win_error.code, DN_Str8PrintFmt(win_error.msg)); } + DN_TCScratchEnd(&scratch); return result; } -DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) +DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err) { bool result = false; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 src16 = DN_W32_Str8ToStr16(tmem.arena, src); - DN_Str16 dest16 = DN_W32_Str8ToStr16(tmem.arena, dest); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str16 src16 = DN_OS_W32Str8ToStr16(scratch.arena, src); + DN_Str16 dest16 = DN_OS_W32Str8ToStr16(scratch.arena, dest); unsigned long flags = MOVEFILE_COPY_ALLOWED; if (overwrite) @@ -327,8 +322,8 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi result = MoveFileExW(src16.data, dest16.data, flags) != 0; if (!result) { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); - DN_OS_ErrSinkAppendF(err, + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); + DN_ErrSinkAppendF(err, win_error.code, "Failed to move file '%.*s' to '%.*s': (%u) %.*s", DN_Str8PrintFmt(src), @@ -336,10 +331,11 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi win_error.code, DN_Str8PrintFmt(win_error.msg)); } + DN_TCScratchEnd(&scratch); return result; } -DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 access, DN_OSErrSink *err) +DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 access, DN_ErrSink *err) { DN_OSFile result = {}; if (path.size == 0 || path.size <= 0) @@ -372,8 +368,8 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 ac access_mode |= GENERIC_EXECUTE; } - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); void *handle = CreateFileW(/*LPCWSTR lpFileName*/ path16.data, /*DWORD dwDesiredAccess*/ access_mode, /*DWORD dwShareMode*/ FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -383,30 +379,33 @@ 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_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); result.error = true; - DN_OS_ErrSinkAppendF(err, win_error.code, "Failed to open file at '%.*s': '%.*s'", DN_Str8PrintFmt(path), DN_Str8PrintFmt(win_error.msg)); + DN_ErrSinkAppendF(err, win_error.code, "Failed to open file at '%.*s': '%.*s'", DN_Str8PrintFmt(path), DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); return result; } result.handle = handle; + DN_TCScratchEnd(&scratch); return result; } -DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err) +DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err) { DN_OSFileRead result = {}; if (!file || !file->handle || file->error || !buffer || size <= 0) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); if (!DN_Check(size <= (unsigned long)-1)) { DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); - DN_OS_ErrSinkAppendF( + DN_ErrSinkAppendF( err, 1 /*error_code*/, "Current implementation doesn't support reading >4GiB file (requested %.*s), implement Win32 overlapped IO", DN_Str8PrintFmt(buffer_size_str8)); + DN_TCScratchEnd(&scratch); return result; } @@ -417,14 +416,15 @@ 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_W32Error win_error = DN_W32_LastError(tmem.arena); - DN_OS_ErrSinkAppendF(err, win_error.code, "Failed to read data from file: (%u) %.*s", win_error.code, DN_Str8PrintFmt(win_error.msg)); + 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_W32Error win_error = DN_W32_LastError(tmem.arena); - DN_OS_ErrSinkAppendF( + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); + DN_ErrSinkAppendF( err, win_error.code, "Failed to read the desired number of bytes from file, we read %uB but we expected %uB: (%u) %.*s", @@ -432,15 +432,17 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size DN_Cast(unsigned long) size, win_error.code, DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); return result; } result.bytes_read = bytes_read; result.success = true; + DN_TCScratchEnd(&scratch); return result; } -DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_OSErrSink *err) +DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_ErrSink *err) { if (!file || !file->handle || file->error || !buffer || size <= 0) return false; @@ -455,24 +457,26 @@ DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize siz } if (!result) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); - DN_OS_ErrSinkAppendF(err, win_error.code, "Failed to write buffer (%.*s) to file handle: %.*s", DN_Str8PrintFmt(buffer_size_str8), DN_Str8PrintFmt(win_error.msg)); + DN_ErrSinkAppendF(err, win_error.code, "Failed to write buffer (%.*s) to file handle: %.*s", DN_Str8PrintFmt(buffer_size_str8), DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); } return result; } -DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_OSErrSink *err) +DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_ErrSink *err) { if (!file || !file->handle || file->error) return false; BOOL result = FlushFileBuffers(DN_Cast(HANDLE) file->handle); if (!result) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_W32Error win_error = DN_W32_LastError(tmem.arena); - DN_OS_ErrSinkAppendF(err, win_error.code, "Failed to flush file buffer to disk: %.*s", DN_Str8PrintFmt(win_error.msg)); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); + DN_ErrSinkAppendF(err, win_error.code, "Failed to flush file buffer to disk: %.*s", DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); } return DN_Cast(bool) result; @@ -492,17 +496,19 @@ DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) if (path.size == 0) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) + if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) { + DN_TCScratchEnd(&scratch); return result; + } result.exists = true; - result.create_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftCreationTime); - result.last_access_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastAccessTime); - result.last_write_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastWriteTime); +result.create_time_in_s = DN_OS_W32FileTimeToSeconds_(&attrib_data.ftCreationTime); + result.last_access_time_in_s = DN_OS_W32FileTimeToSeconds_(&attrib_data.ftLastAccessTime); + result.last_write_time_in_s = DN_OS_W32FileTimeToSeconds_(&attrib_data.ftLastWriteTime); LARGE_INTEGER large_int = {}; large_int.u.HighPart = DN_Cast(int32_t) attrib_data.nFileSizeHigh; @@ -516,6 +522,7 @@ DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) result.type = DN_OSPathInfoType_File; } + DN_TCScratchEnd(&scratch); return result; } @@ -525,13 +532,14 @@ DN_API bool DN_OS_PathDelete(DN_Str8 path) if (path.size == 0) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); if (path16.size) { result = DeleteFileW(path16.data); if (!result) result = RemoveDirectoryW(path16.data); } + DN_TCScratchEnd(&scratch); return result; } @@ -541,14 +549,15 @@ DN_API bool DN_OS_PathIsFile(DN_Str8 path) if (path.size == 0) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); if (path16.size) { WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && !(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); } + DN_TCScratchEnd(&scratch); return result; } @@ -558,8 +567,8 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path) if (path.size == 0) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); if (path16.size) { WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) @@ -567,14 +576,15 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path) (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); } + DN_TCScratchEnd(&scratch); return result; } DN_API bool DN_OS_PathMakeDir(DN_Str8 path) { bool result = true; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch.arena, path); // NOTE: Go back from the end of the string to all the directories in the // string, and try to create them. Since Win32 API cannot create @@ -606,6 +616,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path) // NOTE: There's some kind of file that exists at the path // but it's not a directory. This request to make a // directory is invalid. + DN_TCScratchEnd(&scratch); return false; } } else { @@ -618,6 +629,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path) path16.data[index] = temp; // Undo null termination } } + DN_TCScratchEnd(&scratch); return result; } @@ -626,8 +638,8 @@ DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it) if (path.size == 0 || !it || path.size <= 0) return false; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_W32FolderIteratorW wide_it = {}; + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_OSW32FolderIteratorW wide_it = {}; DN_Str16 path16 = {}; if (it->handle) { wide_it.handle = it->handle; @@ -643,23 +655,26 @@ 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(tmem.arena, "%.*s*", DN_Str8PrintFmt(path)); + adjusted_path = DN_OS_PathF(scratch.arena, "%.*s*", DN_Str8PrintFmt(path)); else - adjusted_path = DN_OS_PathF(tmem.arena, "%.*s/*", DN_Str8PrintFmt(path)); + adjusted_path = DN_OS_PathF(scratch.arena, "%.*s/*", DN_Str8PrintFmt(path)); } - path16 = DN_W32_Str8ToStr16(tmem.arena, adjusted_path); - if (path16.size <= 0) // Conversion error + path16 = DN_OS_W32Str8ToStr16(scratch.arena, adjusted_path); + if (path16.size <= 0) { // Conversion error + DN_TCScratchEnd(&scratch); return false; + } } - bool result = DN_W32_DirWIterate(path16, &wide_it); + bool result = DN_OS_W32DirWIterate(path16, &wide_it); it->handle = wide_it.handle; if (result) { - int size = DN_W32_Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ArrayCountU(it->buffer)); + int size = DN_OS_W32Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ArrayCountU(it->buffer)); it->file_name = DN_Str8FromPtr(it->buffer, size); } + DN_TCScratchEnd(&scratch); return result; } @@ -676,7 +691,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, char *stderr_buffer, DN_USize *stderr_size, DN_U32 timeout_ms, - DN_OSErrSink *err) + DN_ErrSink *err) { DN_OSExecResult result = {}; size_t stdout_buffer_size = 0; @@ -705,7 +720,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, return result; } - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DWORD stdout_bytes_available = 0; DWORD stderr_bytes_available = 0; PeekNamedPipe(handle.stdout_read, nullptr, 0, nullptr, &stdout_bytes_available, nullptr); @@ -716,9 +731,11 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, exec_result = WaitForSingleObject(handle.process, timeout_ms); if (exec_result == WAIT_FAILED) { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); result.os_error_code = win_error.code; - DN_OS_ErrSinkAppendF(err, result.os_error_code, "Executed command failed to terminate: %.*s", DN_Str8PrintFmt(win_error.msg)); + DN_ErrSinkAppendF(err, result.os_error_code, "Executed command failed to terminate: %.*s", DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); + return result; } else if (DN_Check(exec_result == WAIT_TIMEOUT || exec_result == WAIT_OBJECT_0)) { // NOTE: Read stdout from process // If the pipes are full, the process will block. We periodically @@ -735,7 +752,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, if (stdout_size) *stdout_size = bytes_read; } else { - DN_OS_ErrSinkAppendF(err, 1, "Failed to read bytes from stdout"); + DN_ErrSinkAppendF(err, 1, "Failed to read bytes from stdout"); } } } @@ -752,7 +769,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, if (stderr_size) *stderr_size = bytes_read; } else { - DN_OS_ErrSinkAppendF(err, 1, "Failed to read bytes from stderr"); + DN_ErrSinkAppendF(err, 1, "Failed to read bytes from stderr"); } } } @@ -764,9 +781,9 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, if (GetExitCodeProcess(handle.process, &exit_status)) { result.exit_code = exit_status; } else { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); result.os_error_code = win_error.code; - DN_OS_ErrSinkAppendF(err, + DN_ErrSinkAppendF(err, result.os_error_code, "Failed to retrieve command exit code: %.*s", DN_Str8PrintFmt(win_error.msg)); @@ -787,10 +804,11 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, result.stdout_text = DN_Str8FromPtr(stdout_buffer, stdout_size ? *stdout_size : 0); result.stderr_text = DN_Str8FromPtr(stderr_buffer, stderr_size ? *stderr_size : 0); + DN_TCScratchEnd(&scratch); return result; } -DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err) +DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_ErrSink *err) { DN_OSExecResult result = {}; if (!handle.process || handle.os_error_code || handle.exit_code) { @@ -808,12 +826,12 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *are return result; } - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_Str8Builder stdout_builder = {}; DN_Str8Builder stderr_builder = {}; if (arena) { - stdout_builder.arena = tmem.arena; - stderr_builder.arena = tmem.arena; + stdout_builder.arena = scratch.arena; + stderr_builder.arena = scratch.arena; } DN_U32 const SLOW_WAIT_TIME_MS = 100; @@ -822,8 +840,8 @@ 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(tmem.arena, char, stdout_size, DN_ZMem_No); - char *stderr_buffer = DN_ArenaNewArray(tmem.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); @@ -833,37 +851,38 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *are // 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); return result; } -DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err) +DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, DN_OSExecArgs *args, DN_ErrSink *err) { - // NOTE: Pre-amble ///////////////////////////////////////////////////////////////////////////// + // NOTE: Pre-amble DN_OSExecAsyncHandle result = {}; if (cmd_line.size == 0) return result; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 cmd_rendered = DN_Slice_Str8Render(tmem.arena, cmd_line, DN_Str8Lit(" ")); - DN_Str16 cmd16 = DN_W32_Str8ToStr16(tmem.arena, cmd_rendered); - DN_Str16 working_dir16 = DN_W32_Str8ToStr16(tmem.arena, args->working_dir); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); + DN_Str8 cmd_rendered = DN_Slice_Str8Render(scratch.arena, cmd_line, DN_Str8Lit(" ")); +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_Str8BuilderFromTLS(); + DN_Str8Builder env_builder = DN_Str8BuilderFromArena(scratch.arena); DN_Str8BuilderAppendArrayRef(&env_builder, args->environment.data, args->environment.size); if (env_builder.string_size) DN_Str8BuilderAppendRef(&env_builder, DN_Str8Lit("\0")); - DN_Str8 env_block8 = DN_Str8BuilderBuildDelimitedFromTLS(&env_builder, DN_Str8Lit("\0")); + DN_Str8 env_block8 = DN_Str8BuilderBuildDelimited(&env_builder, DN_Str8Lit("\0"), scratch.arena); DN_Str16 env_block16 = {}; if (env_block8.size) - env_block16 = DN_W32_Str8ToStr16(tmem.arena, env_block8); + env_block16 = DN_OS_W32Str8ToStr16(scratch.arena, env_block8); - // NOTE: Stdout/err security attributes //////////////////////////////////////////////////////// + // NOTE: Stdout/err security attributes SECURITY_ATTRIBUTES save_std_security_attribs = {}; save_std_security_attribs.nLength = sizeof(save_std_security_attribs); save_std_security_attribs.bInheritHandle = true; - // NOTE: Redirect stdout /////////////////////////////////////////////////////////////////////// + // NOTE: Redirect stdout HANDLE stdout_read = {}; HANDLE stdout_write = {}; DN_DEFER @@ -876,26 +895,28 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, DN_OSExe if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) { if (!CreatePipe(&stdout_read, &stdout_write, &save_std_security_attribs, /*nSize*/ 0)) { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); result.os_error_code = win_error.code; - DN_OS_ErrSinkAppendF( + DN_ErrSinkAppendF( err, result.os_error_code, "Failed to create stdout pipe to redirect the output of the command '%.*s': %.*s", DN_Str8PrintFmt(cmd_rendered), DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); return result; } if (!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0)) { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); result.os_error_code = win_error.code; - DN_OS_ErrSinkAppendF(err, + DN_ErrSinkAppendF(err, result.os_error_code, "Failed to make stdout 'read' pipe non-inheritable when trying to " "execute command '%.*s': %.*s", DN_Str8PrintFmt(cmd_rendered), DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); return result; } } @@ -917,26 +938,28 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, DN_OSExe stderr_write = stdout_write; } else { if (!CreatePipe(&stderr_read, &stderr_write, &save_std_security_attribs, /*nSize*/ 0)) { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); result.os_error_code = win_error.code; - DN_OS_ErrSinkAppendF( + DN_ErrSinkAppendF( err, result.os_error_code, "Failed to create stderr pipe to redirect the output of the command '%.*s': %.*s", DN_Str8PrintFmt(cmd_rendered), DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); return result; } if (!SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0)) { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); result.os_error_code = win_error.code; - DN_OS_ErrSinkAppendF(err, - result.os_error_code, - "Failed to make stderr 'read' pipe non-inheritable when trying to " - "execute command '%.*s': %.*s", - DN_Str8PrintFmt(cmd_rendered), - DN_Str8PrintFmt(win_error.msg)); + DN_ErrSinkAppendF(err, + result.os_error_code, + "Failed to make stderr 'read' pipe non-inheritable when trying to " + "execute command '%.*s': %.*s", + DN_Str8PrintFmt(cmd_rendered), + DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); return result; } } @@ -961,13 +984,10 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, DN_OSExe &startup_info, &proc_info); if (!create_result) { - DN_W32Error win_error = DN_W32_LastError(tmem.arena); + DN_OSW32Error win_error = DN_OS_W32LastError(scratch.arena); result.os_error_code = win_error.code; - DN_OS_ErrSinkAppendF(err, - result.os_error_code, - "Failed to execute command '%.*s': %.*s", - DN_Str8PrintFmt(cmd_rendered), - DN_Str8PrintFmt(win_error.msg)); + DN_ErrSinkAppendF(err, result.os_error_code, "Failed to execute command '%.*s': %.*s", DN_Str8PrintFmt(cmd_rendered), DN_Str8PrintFmt(win_error.msg)); + DN_TCScratchEnd(&scratch); return result; } @@ -981,24 +1001,25 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, DN_OSExe result.stderr_write = stderr_write; } result.exec_flags = args->flags; + DN_TCScratchEnd(&scratch); return result; } -static DN_W32Core *DN_OS_GetW32Core_() +DN_API DN_OSW32Core *DN_OS_W32GetCore() { DN_Assert(g_dn_ && g_dn_->os.platform_context); - DN_W32Core *result = DN_Cast(DN_W32Core *)g_dn_->os.platform_context; + DN_OSW32Core *result = DN_Cast(DN_OSW32Core *)g_dn_->os.platform_context; return result; } -static DN_W32SyncPrimitive *DN_OS_U64ToW32SyncPrimitive_(DN_U64 u64) +static DN_OSW32SyncPrimitive *DN_OS_U64ToW32SyncPrimitive_(DN_U64 u64) { - DN_W32SyncPrimitive *result = nullptr; + DN_OSW32SyncPrimitive *result = nullptr; DN_Memcpy(&result, &u64, sizeof(u64)); return result; } -static DN_U64 DN_W32_SyncPrimitiveToU64(DN_W32SyncPrimitive *primitive) +static DN_U64 DN_OSW32SyncPrimitiveToU64(DN_OSW32SyncPrimitive *primitive) { DN_U64 result = 0; static_assert(sizeof(result) == sizeof(primitive), "Pointer size mis-match"); @@ -1006,10 +1027,10 @@ static DN_U64 DN_W32_SyncPrimitiveToU64(DN_W32SyncPrimitive *primitive) return result; } -static DN_W32SyncPrimitive *DN_W32_AllocSyncPrimitive_() +static DN_OSW32SyncPrimitive *DN_OS_W32AllocSyncPrimitive_() { - DN_W32Core *w32 = DN_OS_GetW32Core_(); - DN_W32SyncPrimitive *result = nullptr; + DN_OSW32Core *w32 = DN_OS_W32GetCore(); + DN_OSW32SyncPrimitive *result = nullptr; EnterCriticalSection(&w32->sync_primitive_free_list_mutex); { if (w32->sync_primitive_free_list) { @@ -1018,17 +1039,17 @@ static DN_W32SyncPrimitive *DN_W32_AllocSyncPrimitive_() result->next = nullptr; } else { DN_OSCore *os = &g_dn_->os; - result = DN_ArenaNew(&os->arena, DN_W32SyncPrimitive, DN_ZMem_Yes); + result = DN_ArenaNew(&os->arena, DN_OSW32SyncPrimitive, DN_ZMem_Yes); } } LeaveCriticalSection(&w32->sync_primitive_free_list_mutex); return result; } -static void DN_W32_DeallocSyncPrimitive_(DN_W32SyncPrimitive *primitive) +static void DN_OS_W32DeallocSyncPrimitive_(DN_OSW32SyncPrimitive *primitive) { if (primitive) { - DN_W32Core *w32 = DN_OS_GetW32Core_(); + DN_OSW32Core *w32 = DN_OS_W32GetCore(); EnterCriticalSection(&w32->sync_primitive_free_list_mutex); primitive->next = w32->sync_primitive_free_list; w32->sync_primitive_free_list = primitive; @@ -1040,14 +1061,14 @@ static void DN_W32_DeallocSyncPrimitive_(DN_W32SyncPrimitive *primitive) DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) { DN_OSSemaphore result = {}; - DN_W32SyncPrimitive *primitive = DN_W32_AllocSyncPrimitive_(); + DN_OSW32SyncPrimitive *primitive = DN_OS_W32AllocSyncPrimitive_(); if (primitive) { SECURITY_ATTRIBUTES security_attribs = {}; primitive->sem = CreateSemaphoreA(&security_attribs, initial_count, INT32_MAX, nullptr /*name*/); if (primitive->sem) - result.handle = DN_W32_SyncPrimitiveToU64(primitive); + result.handle = DN_OSW32SyncPrimitiveToU64(primitive); if (!primitive->sem) - DN_W32_DeallocSyncPrimitive_(primitive); + DN_OS_W32DeallocSyncPrimitive_(primitive); } return result; } @@ -1055,9 +1076,9 @@ DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) { if (semaphore && semaphore->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(semaphore->handle); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(semaphore->handle); CloseHandle(primitive->sem); - DN_W32_DeallocSyncPrimitive_(primitive); + DN_OS_W32DeallocSyncPrimitive_(primitive); *semaphore = {}; } } @@ -1065,7 +1086,7 @@ DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount) { if (semaphore && semaphore->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(semaphore->handle); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(semaphore->handle); LONG prev_count = 0; ReleaseSemaphore(primitive->sem, amount, &prev_count); } @@ -1075,7 +1096,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, D { DN_OSSemaphoreWaitResult result = {}; if (semaphore && semaphore->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(semaphore->handle); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(semaphore->handle); DWORD wait_result = WaitForSingleObject(primitive->sem, timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT ? INFINITE : timeout_ms); if (wait_result == WAIT_TIMEOUT) result = DN_OSSemaphoreWaitResult_Timeout; @@ -1088,20 +1109,20 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, D // NOTE: DN_OSMutex //////////////////////////////////////////////////////////////////////////////// DN_API DN_OSMutex DN_OS_MutexInit() { - DN_W32SyncPrimitive *primitive = DN_W32_AllocSyncPrimitive_(); + DN_OSW32SyncPrimitive *primitive = DN_OS_W32AllocSyncPrimitive_(); if (primitive) InitializeCriticalSection(&primitive->mutex); DN_OSMutex result = {}; - result.handle = DN_W32_SyncPrimitiveToU64(primitive); + result.handle = DN_OSW32SyncPrimitiveToU64(primitive); return result; } DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(mutex->handle); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(mutex->handle); DeleteCriticalSection(&primitive->mutex); - DN_W32_DeallocSyncPrimitive_(primitive); + DN_OS_W32DeallocSyncPrimitive_(primitive); *mutex = {}; } } @@ -1109,7 +1130,7 @@ DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(mutex->handle); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(mutex->handle); EnterCriticalSection(&primitive->mutex); } } @@ -1117,7 +1138,7 @@ DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(mutex->handle); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(mutex->handle); LeaveCriticalSection(&primitive->mutex); } } @@ -1125,19 +1146,19 @@ DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex) // NOTE: DN_OSConditionVariable //////////////////////////////////////////////////////////////////// DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit() { - DN_W32SyncPrimitive *primitive = DN_W32_AllocSyncPrimitive_(); + DN_OSW32SyncPrimitive *primitive = DN_OS_W32AllocSyncPrimitive_(); if (primitive) InitializeConditionVariable(&primitive->cv); DN_OSConditionVariable result = {}; - result.handle = DN_W32_SyncPrimitiveToU64(primitive); + result.handle = DN_OSW32SyncPrimitiveToU64(primitive); return result; } DN_API void DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(cv->handle); - DN_W32_DeallocSyncPrimitive_(primitive); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(cv->handle); + DN_OS_W32DeallocSyncPrimitive_(primitive); *cv = {}; } } @@ -1157,8 +1178,8 @@ DN_API bool DN_OS_ConditionVariableWait(DN_OSConditionVariable *cv, DN_OSMutex * { bool result = false; if (mutex && cv && mutex->handle != 0 && cv->handle != 0 && sleep_ms > 0) { - DN_W32SyncPrimitive *mutex_primitive = DN_OS_U64ToW32SyncPrimitive_(mutex->handle); - DN_W32SyncPrimitive *cv_primitive = DN_OS_U64ToW32SyncPrimitive_(cv->handle); + DN_OSW32SyncPrimitive *mutex_primitive = DN_OS_U64ToW32SyncPrimitive_(mutex->handle); + DN_OSW32SyncPrimitive *cv_primitive = DN_OS_U64ToW32SyncPrimitive_(cv->handle); result = SleepConditionVariableCS(&cv_primitive->cv, &mutex_primitive->mutex, DN_Cast(DWORD) sleep_ms); } return result; @@ -1167,7 +1188,7 @@ DN_API bool DN_OS_ConditionVariableWait(DN_OSConditionVariable *cv, DN_OSMutex * DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(cv->handle); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(cv->handle); WakeConditionVariable(&primitive->cv); } } @@ -1175,7 +1196,7 @@ DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_W32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(cv->handle); + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(cv->handle); WakeAllConditionVariable(&primitive->cv); } } @@ -1231,7 +1252,7 @@ DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread) CloseHandle(thread->handle); thread->handle = INVALID_HANDLE_VALUE; thread->thread_id = {}; - DN_OS_TLSDeinit(&thread->tls); + DN_TCDeinit(&thread->context); } DN_API DN_U32 DN_OS_ThreadID() @@ -1240,53 +1261,46 @@ DN_API DN_U32 DN_OS_ThreadID() return result; } -DN_API void DN_W32_ThreadSetName(DN_Str8 name) +DN_API void DN_OS_W32ThreadSetName(DN_Str8 name) { - DN_OSTLS *tls = DN_OS_TLSGet(); - DN_ArenaTempMem tmem = DN_ArenaTempMemBegin(tls->arenas + DN_OSTLSArena_TMem0); - // NOTE: SetThreadDescription is only available in // Windows Server 2016, Windows 10 LTSB 2016 and Windows 10 version 1607 // // See: https://learn.microsoft.com/en-us/windows/w32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription - DN_W32Core *w32 = DN_OS_GetW32Core_(); + DN_OSW32Core *w32 = DN_OS_W32GetCore(); + DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); if (w32->set_thread_description) { - DN_Str16 name16 = DN_W32_Str8ToStr16(tmem.arena, name); + DN_Str16 name16 = DN_OS_W32Str8ToStr16(scratch.arena, name); w32->set_thread_description(GetCurrentThread(), (WCHAR *)name16.data); - DN_ArenaTempMemEnd(tmem); - return; + } else { + // NOTE: Fallback to throw-exception method to set thread name + #pragma pack(push, 8) + struct DN_OSW32ThreadNameInfo + { + DN_U32 dwType; + char *szName; + DN_U32 dwThreadID; + DN_U32 dwFlags; + }; + #pragma pack(pop) + + DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, name); + DN_OSW32ThreadNameInfo info = {}; + info.dwType = 0x1000; + info.szName = (char *)copy.data; + info.dwThreadID = DN_OS_ThreadID(); + + // TODO: Review warning 6320 + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(6320) // Exception-filter expression is the constant EXCEPTION_EXECUTE_HANDLER. This might mask exceptions that were not intended to be handled + DN_MSVC_WARNING_DISABLE(6322) // Empty _except block + __try { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { + } + DN_MSVC_WARNING_POP } - - // NOTE: Fallback to throw-exception method to set thread name - #pragma pack(push, 8) - - struct DN_W32ThreadNameInfo - { - DN_U32 dwType; - char *szName; - DN_U32 dwThreadID; - DN_U32 dwFlags; - }; - - #pragma pack(pop) - - DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, name); - DN_W32ThreadNameInfo info = {}; - info.dwType = 0x1000; - info.szName = (char *)copy.data; - info.dwThreadID = DN_OS_ThreadID(); - - // TODO: Review warning 6320 - DN_MSVC_WARNING_PUSH - DN_MSVC_WARNING_DISABLE(6320) // Exception-filter expression is the constant EXCEPTION_EXECUTE_HANDLER. This might mask exceptions that were not intended to be handled - DN_MSVC_WARNING_DISABLE(6322) // Empty _except block - __try { - RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); - } __except (EXCEPTION_EXECUTE_HANDLER) { - } - DN_MSVC_WARNING_POP - - DN_ArenaTempMemEnd(tmem); + DN_TCScratchEnd(&scratch); } // NOTE: DN_OSHttp ///////////////////////////////////////////////////////////////////////////////// @@ -1297,7 +1311,7 @@ void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD d DN_OSHttpResponse *response = DN_Cast(DN_OSHttpResponse *) dwContext; HINTERNET request = DN_Cast(HINTERNET) response->w32_request_handle; - DN_W32Error error = {}; + DN_OSW32Error error = {}; DWORD const READ_BUFFER_SIZE = DN_Megabytes(1); if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_RESOLVING_NAME) { @@ -1340,9 +1354,9 @@ void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD d // to prevent unnecessary allocation on the user side. void *buffer = DN_ArenaAlloc(response->builder.arena, READ_BUFFER_SIZE, 1 /*align*/, DN_ZMem_No); if (!WinHttpReadData(request, buffer, READ_BUFFER_SIZE, nullptr)) - error = DN_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); } else { - error = DN_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); } } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE) { } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_READ_COMPLETE) { @@ -1353,15 +1367,15 @@ void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD d void *buffer = DN_ArenaAlloc(response->builder.arena, READ_BUFFER_SIZE, 1 /*align*/, DN_ZMem_No); if (!WinHttpReadData(request, buffer, READ_BUFFER_SIZE, nullptr)) - error = DN_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); } } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE) { } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) { WINHTTP_ASYNC_RESULT *async_result = DN_Cast(WINHTTP_ASYNC_RESULT *) lpvStatusInformation; - error = DN_W32_ErrorCodeToMsg(&response->tmp_arena, DN_Cast(DN_U32) async_result->dwError); + error = DN_OS_W32ErrorCodeToMsg(&response->tmp_arena, DN_Cast(DN_U32) async_result->dwError); } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE) { if (!WinHttpReceiveResponse(request, 0)) - error = DN_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); } // NOTE: If the request handle is missing, then, the response has been freed. @@ -1397,14 +1411,14 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, return; response->arena = arena; - response->builder.arena = response->tmem_arena ? response->tmem_arena : &response->tmp_arena; + response->builder.arena = response->scratch_arena ? response->scratch_arena : &response->tmp_arena; - DN_Arena *tmem_arena = response->tmem_arena; - DN_OSTLSTMem tmem_ = DN_OS_TLSTMem(arena); - if (!tmem_arena) - tmem_arena = tmem_.arena; + DN_Arena *scratch_arena = response->scratch_arena; + DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1); + if (!scratch_arena) + scratch_arena = scratch_.arena; - DN_W32Error error = {}; + DN_OSW32Error error = {}; DN_DEFER { response->error_msg = error.msg; @@ -1415,11 +1429,12 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_OS_HttpRequestWait(response); DN_AtomicAddU32(&response->done, 1); } + DN_TCScratchEnd(&scratch_); }; response->w32_request_session = WinHttpOpen(nullptr /*user agent*/, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC); if (!response->w32_request_session) { - error = DN_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); return; } @@ -1431,19 +1446,19 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_Cast(WINHTTP_STATUS_CALLBACK) DN_OS_HttpRequestWin32Callback, callback_flags, DN_Cast(DWORD_PTR) nullptr /*dwReserved*/) == WINHTTP_INVALID_STATUS_CALLBACK) { - error = DN_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); return; } - DN_Str16 host16 = DN_W32_Str8ToStr16(tmem_arena, host); + DN_Str16 host16 = DN_OS_W32Str8ToStr16(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_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); return; } - DN_Str16 method16 = DN_W32_Str8ToStr16(tmem_arena, method); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem_arena, path); + DN_Str16 method16 = DN_OS_W32Str8ToStr16(scratch_arena, method); + DN_Str16 path16 = DN_OS_W32Str8ToStr16(scratch_arena, path); response->w32_request_handle = WinHttpOpenRequest(response->w32_request_connection, method16.data, path16.data, @@ -1452,11 +1467,11 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, nullptr /*accept types*/, secure ? WINHTTP_FLAG_SECURE : 0); if (!response->w32_request_handle) { - error = DN_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); return; } - DN_Str16 headers16 = DN_W32_Str8ToStr16(tmem_arena, headers); + DN_Str16 headers16 = DN_OS_W32Str8ToStr16(scratch_arena, headers); response->on_complete_semaphore = DN_OS_SemaphoreInit(0); if (!WinHttpSendRequest(response->w32_request_handle, headers16.data, @@ -1465,7 +1480,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_Cast(DWORD) body.size /*optional length*/, DN_Cast(DWORD) body.size /*total content length*/, DN_Cast(DWORD_PTR) response)) { - error = DN_W32_LastError(&response->tmp_arena); + error = DN_OS_W32LastError(&response->tmp_arena); return; } } @@ -1487,8 +1502,8 @@ DN_API void DN_OS_HttpRequestFree(DN_OSHttpResponse *response) *response = {}; } -// NOTE: DN_W32 //////////////////////////////////////////////////////////////////////////////////// -DN_API DN_Str16 DN_W32_ErrorCodeToMsg16Alloc(DN_U32 error_code) +// NOTE: DN_OS_W32 +DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code) { DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; void *module_to_get_errors_from = nullptr; @@ -1512,45 +1527,45 @@ DN_API DN_Str16 DN_W32_ErrorCodeToMsg16Alloc(DN_U32 error_code) return result; } -DN_API DN_W32Error DN_W32_ErrorCodeToMsgAlloc(DN_U32 error_code) +DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsgAlloc(DN_U32 error_code) { - DN_W32Error result = {}; + DN_OSW32Error result = {}; result.code = error_code; - DN_Str16 error16 = DN_W32_ErrorCodeToMsg16Alloc(error_code); + DN_Str16 error16 = DN_OS_W32ErrorCodeToMsg16Alloc(error_code); if (error16.size) - result.msg = DN_W32_Str16ToStr8FromHeap(error16); + result.msg = DN_OS_W32Str16ToStr8FromHeap(error16); if (error16.data) LocalFree(error16.data); return result; } -DN_API DN_W32Error DN_W32_ErrorCodeToMsg(DN_Arena *arena, DN_U32 error_code) +DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg(DN_Arena *arena, DN_U32 error_code) { - DN_W32Error result = {}; + DN_OSW32Error result = {}; result.code = error_code; if (arena) { - DN_Str16 error16 = DN_W32_ErrorCodeToMsg16Alloc(error_code); + DN_Str16 error16 = DN_OS_W32ErrorCodeToMsg16Alloc(error_code); if (error16.size) - result.msg = DN_W32_Str16ToStr8(arena, error16); + result.msg = DN_OS_W32Str16ToStr8(arena, error16); if (error16.data) LocalFree(error16.data); } return result; } -DN_API DN_W32Error DN_W32_LastError(DN_Arena *arena) +DN_API DN_OSW32Error DN_OS_W32LastError(DN_Arena *arena) { - DN_W32Error result = DN_W32_ErrorCodeToMsg(arena, GetLastError()); + DN_OSW32Error result = DN_OS_W32ErrorCodeToMsg(arena, GetLastError()); return result; } -DN_API DN_W32Error DN_W32_LastErrorAlloc() +DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc() { - DN_W32Error result = DN_W32_ErrorCodeToMsgAlloc(GetLastError()); + DN_OSW32Error result = DN_OS_W32ErrorCodeToMsgAlloc(GetLastError()); return result; } -DN_API void DN_W32_MakeProcessDPIAware() +DN_API void DN_OS_W32MakeProcessDPIAware() { typedef bool SetProcessDpiAwareProc(void); typedef bool SetProcessDpiAwarenessProc(DPI_AWARENESS); @@ -1573,7 +1588,7 @@ DN_API void DN_W32_MakeProcessDPIAware() } // NOTE: Windows UTF8 to Str16 ////////////////////////////////////////////// -DN_API DN_Str16 DN_W32_Str8ToStr16(DN_Arena *arena, DN_Str8 src) +DN_API DN_Str16 DN_OS_W32Str8ToStr16(DN_Arena *arena, DN_Str8 src) { DN_Str16 result = {}; if (!arena || src.size == 0) @@ -1596,7 +1611,7 @@ DN_API DN_Str16 DN_W32_Str8ToStr16(DN_Arena *arena, DN_Str8 src) return result; } -DN_API int DN_W32_Str8ToStr16Buffer(DN_Str8 src, wchar_t *dest, int dest_size) +DN_API int DN_OS_W32Str8ToStr16Buffer(DN_Str8 src, wchar_t *dest, int dest_size) { int result = 0; if (src.size == 0) @@ -1612,7 +1627,7 @@ DN_API int DN_W32_Str8ToStr16Buffer(DN_Str8 src, wchar_t *dest, int dest_size) } // NOTE: Windows Str16 To UTF8 ////////////////////////////////////////////////////////////////// -DN_API int DN_W32_Str16ToStr8Buffer(DN_Str16 src, char *dest, int dest_size) +DN_API int DN_OS_W32Str16ToStr8Buffer(DN_Str16 src, char *dest, int dest_size) { int result = 0; if (src.size == 0) @@ -1631,7 +1646,7 @@ DN_API int DN_W32_Str16ToStr8Buffer(DN_Str16 src, char *dest, int dest_size) return result; } -DN_API DN_Str8 DN_W32_Str16ToStr8(DN_Arena *arena, DN_Str16 src) +DN_API DN_Str8 DN_OS_W32Str16ToStr8(DN_Arena *arena, DN_Str16 src) { DN_Str8 result = {}; if (!arena || src.size == 0) @@ -1662,7 +1677,7 @@ DN_API DN_Str8 DN_W32_Str16ToStr8(DN_Arena *arena, DN_Str16 src) return result; } -DN_API DN_Str8 DN_W32_Str16ToStr8FromHeap(DN_Str16 src) +DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap(DN_Str16 src) { DN_Str8 result = {}; if (src.size == 0) @@ -1695,17 +1710,19 @@ DN_API DN_Str8 DN_W32_Str16ToStr8FromHeap(DN_Str16 src) } // NOTE: Windows Executable Directory ////////////////////////////////////////// -DN_API DN_Str16 DN_W32_EXEPathW(DN_Arena *arena) +DN_API DN_Str16 DN_OS_W32EXEPathW(DN_Arena *arena) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_Str16 result = {}; DN_USize module_size = 0; wchar_t *module_path = nullptr; do { module_size += 256; - module_path = DN_ArenaNewArray(tmem.arena, wchar_t, module_size, DN_ZMem_No); - if (!module_path) + module_path = DN_ArenaNewArray(scratch.arena, wchar_t, module_size, DN_ZMem_No); + if (!module_path) { + DN_TCScratchEnd(&scratch); return result; + } module_size = DN_Cast(DN_USize) GetModuleFileNameW(nullptr /*module*/, module_path, DN_Cast(int) module_size); } while (GetLastError() == ERROR_INSUFFICIENT_BUFFER); @@ -1717,21 +1734,24 @@ DN_API DN_Str16 DN_W32_EXEPathW(DN_Arena *arena) result.size = module_size; DN_Memcpy(result.data, module_path, sizeof(wchar_t) * result.size); result.data[result.size] = 0; + DN_TCScratchEnd(&scratch); return result; } -DN_API DN_Str16 DN_W32_EXEDirW(DN_Arena *arena) +DN_API DN_Str16 DN_OS_W32EXEDirW(DN_Arena *arena) { // TODO(doyle): Implement a DN_Str16_BinarySearchReverse - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); DN_Str16 result = {}; DN_USize module_size = 0; wchar_t *module_path = nullptr; do { module_size += 256; - module_path = DN_ArenaNewArray(tmem.arena, wchar_t, module_size, DN_ZMem_No); - if (!module_path) + module_path = DN_ArenaNewArray(scratch.arena, wchar_t, module_size, DN_ZMem_No); + if (!module_path) { + DN_TCScratchEnd(&scratch); return result; + } module_size = DN_Cast(DN_USize) GetModuleFileNameW(nullptr /*module*/, module_path, DN_Cast(int) module_size); } while (GetLastError() == ERROR_INSUFFICIENT_BUFFER); @@ -1743,53 +1763,61 @@ DN_API DN_Str16 DN_W32_EXEDirW(DN_Arena *arena) result.size = index_of_last_slash; DN_Memcpy(result.data, module_path, sizeof(wchar_t) * result.size); result.data[result.size] = 0; + DN_TCScratchEnd(&scratch); return result; } -DN_API DN_Str8 DN_W32_WorkingDir(DN_Arena *arena, DN_Str8 suffix) +DN_API DN_Str8 DN_OS_W32WorkingDir(DN_Arena *arena, DN_Str8 suffix) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); - DN_Str16 suffix16 = DN_W32_Str8ToStr16(tmem.arena, suffix); - DN_Str16 dir16 = DN_W32_WorkingDirW(tmem.arena, suffix16); - DN_Str8 result = DN_W32_Str16ToStr8(arena, dir16); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); + DN_Str16 suffix16 = DN_OS_W32Str8ToStr16(scratch.arena, suffix); + DN_Str16 dir16 = DN_OS_W32WorkingDirW(scratch.arena, suffix16); + DN_Str8 result = DN_OS_W32Str16ToStr8(arena, dir16); + DN_TCScratchEnd(&scratch); return result; } -DN_API DN_Str16 DN_W32_WorkingDirW(DN_Arena *arena, DN_Str16 suffix) +DN_API DN_Str16 DN_OS_W32WorkingDirW(DN_Arena *arena, DN_Str16 suffix) { DN_Assert(suffix.size >= 0); DN_Str16 result = {}; // NOTE: required_size is the size required *including* the null-terminator - DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); + DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1); unsigned long required_size = GetCurrentDirectoryW(0, nullptr); unsigned long desired_size = required_size + DN_Cast(unsigned long) suffix.size; - wchar_t *tmem_w_path = DN_ArenaNewArray(tmem.arena, wchar_t, desired_size, DN_ZMem_No); - if (!tmem_w_path) + 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; + } - unsigned long bytes_written_wo_null_terminator = GetCurrentDirectoryW(desired_size, tmem_w_path); + unsigned long bytes_written_wo_null_terminator = GetCurrentDirectoryW(desired_size, scratch_w_path); if ((bytes_written_wo_null_terminator + 1) != required_size) { // TODO(dn): Error + DN_TCScratchEnd(&scratch); return result; } wchar_t *w_path = DN_ArenaNewArray(arena, wchar_t, desired_size, DN_ZMem_No); - if (!w_path) + if (!w_path) { + DN_TCScratchEnd(&scratch); return result; + } if (suffix.size) { - DN_Memcpy(w_path, tmem_w_path, sizeof(*tmem_w_path) * bytes_written_wo_null_terminator); + DN_Memcpy(w_path, scratch_w_path, sizeof(*scratch_w_path) * bytes_written_wo_null_terminator); DN_Memcpy(w_path + bytes_written_wo_null_terminator, suffix.data, sizeof(suffix.data[0]) * suffix.size); w_path[desired_size] = 0; } result = DN_Str16{w_path, DN_Cast(DN_USize)(desired_size - 1)}; + DN_TCScratchEnd(&scratch); return result; } -DN_API bool DN_W32_DirWIterate(DN_Str16 path, DN_W32FolderIteratorW *it) +DN_API bool DN_OS_W32DirWIterate(DN_Str16 path, DN_OSW32FolderIteratorW *it) { WIN32_FIND_DATAW find_data = {}; if (it->handle) { diff --git a/Source/OS/dn_os_w32.h b/Source/OS/dn_os_w32.h index fdea160..387246e 100644 --- a/Source/OS/dn_os_w32.h +++ b/Source/OS/dn_os_w32.h @@ -1,32 +1,33 @@ -#if !defined(DN_OS_WIN32_H) -#define DN_OS_WIN32_H +#if !defined(DN_OS_W32_H) +#define DN_OS_W32_H #if defined(_CLANGD) - #include "../dn_base_inc.h" + #define DN_H_WITH_OS 1 + #include "../dn.h" #include "dn_os_windows.h" #endif -struct DN_W32Error +struct DN_OSW32Error { unsigned long code; DN_Str8 msg; }; -struct DN_W32FolderIteratorW +struct DN_OSW32FolderIteratorW { void *handle; DN_Str16 file_name; wchar_t file_name_buf[512]; }; -enum DN_W32SyncPrimitiveType +enum DN_OSW32SyncPrimitiveType { DN_OSW32SyncPrimitiveType_Semaphore, DN_OSW32SyncPrimitiveType_Mutex, DN_OSW32SyncPrimitiveType_ConditionVariable, }; -struct DN_W32SyncPrimitive +struct DN_OSW32SyncPrimitive { union { @@ -35,42 +36,43 @@ struct DN_W32SyncPrimitive CONDITION_VARIABLE cv; }; - DN_W32SyncPrimitive *next; + DN_OSW32SyncPrimitive *next; }; -typedef HRESULT DN_W32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription); -struct DN_W32Core +typedef HRESULT DN_OSW32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription); +struct DN_OSW32Core { - DN_W32SetThreadDescriptionFunc *set_thread_description; + DN_OSW32SetThreadDescriptionFunc *set_thread_description; LARGE_INTEGER qpc_frequency; void *bcrypt_rng_handle; bool bcrypt_init_success; bool sym_initialised; CRITICAL_SECTION sync_primitive_free_list_mutex; - DN_W32SyncPrimitive *sync_primitive_free_list; + DN_OSW32SyncPrimitive *sync_primitive_free_list; }; -DN_API void DN_W32_ThreadSetName (DN_Str8 name); +DN_API DN_OSW32Core* DN_OS_W32GetCore (); +DN_API void DN_OS_W32ThreadSetName (DN_Str8 name); -DN_API DN_Str16 DN_W32_ErrorCodeToMsg16Alloc(DN_U32 error_code); -DN_API DN_W32Error DN_W32_ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code); -DN_API DN_W32Error DN_W32_ErrorCodeToMsgAlloc (DN_U32 error_code); -DN_API DN_W32Error DN_W32_LastError (DN_Arena *arena); -DN_API DN_W32Error DN_W32_LastErrorAlloc (); -DN_API void DN_W32_MakeProcessDPIAware (); +DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code); +DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code); +DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsgAlloc (DN_U32 error_code); +DN_API DN_OSW32Error DN_OS_W32LastError (DN_Arena *arena); +DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc (); +DN_API void DN_OS_W32MakeProcessDPIAware (); -// NOTE: Windows Str8 <-> Str16 //////////////////////////////////////////////////////////////////// -DN_API DN_Str16 DN_W32_Str8ToStr16 (DN_Arena *arena, DN_Str8 src); -DN_API int DN_W32_Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size); -DN_API DN_Str8 DN_W32_Str16ToStr8 (DN_Arena *arena, DN_Str16 src); -DN_API int DN_W32_Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size); -DN_API DN_Str8 DN_W32_Str16ToStr8FromHeap(DN_Str16 src); +// NOTE: Windows Str8 <-> Str16 +DN_API DN_Str16 DN_OS_W32Str8ToStr16 (DN_Arena *arena, DN_Str8 src); +DN_API int DN_OS_W32Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size); +DN_API DN_Str8 DN_OS_W32Str16ToStr8 (DN_Arena *arena, DN_Str16 src); +DN_API int DN_OS_W32Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size); +DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap (DN_Str16 src); -// NOTE: Path navigation /////////////////////////////////////////////////////////////////////////// -DN_API DN_Str16 DN_W32_EXEPathW (DN_Arena *arena); -DN_API DN_Str16 DN_W32_EXEDirW (DN_Arena *arena); -DN_API DN_Str8 DN_W32_WorkingDir (DN_Arena *arena, DN_Str8 suffix); -DN_API DN_Str16 DN_W32_WorkingDirW (DN_Arena *arena, DN_Str16 suffix); -DN_API bool DN_W32_DirWIterate (DN_Str16 path, DN_W32FolderIteratorW *it); -#endif // !defined(DN_OS_WIN32) +// NOTE: Path navigation +DN_API DN_Str16 DN_OS_W32EXEPathW (DN_Arena *arena); +DN_API DN_Str16 DN_OS_W32EXEDirW (DN_Arena *arena); +DN_API DN_Str8 DN_OS_W32WorkingDir (DN_Arena *arena, DN_Str8 suffix); +DN_API DN_Str16 DN_OS_W32WorkingDirW (DN_Arena *arena, DN_Str16 suffix); +DN_API bool DN_OS_W32DirWIterate (DN_Str16 path, DN_OSW32FolderIteratorW *it); +#endif // !defined(DN_OS_W32_H) diff --git a/Source/OS/dn_os_windows.h b/Source/OS/dn_os_windows.h index 3ed69fc..fcb5f69 100644 --- a/Source/OS/dn_os_windows.h +++ b/Source/OS/dn_os_windows.h @@ -2,7 +2,7 @@ #define DN_OS_WINDOWS_H #if defined(_CLANGD) - #include "../dn_base_inc.h" + #include "../dn.h" #endif #if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) diff --git a/Source/Standalone/dn_ini.c b/Source/Standalone/dn_ini.c index 83ff16b..328c0a8 100644 --- a/Source/Standalone/dn_ini.c +++ b/Source/Standalone/dn_ini.c @@ -45,6 +45,83 @@ DN_INIStr8 DN_INI_Str8FromPtr(char const *data, size_t count) return result; } +static void DN_INI_Str8BuilderAppend_(DN_INIStr8Builder *builder, char const *fmt, ...) +{ + va_list args; + va_list args_copy; + va_start(args, fmt); + va_copy(args_copy, args); + int size_req = vsnprintf(0, 0, fmt, args); + va_end(args); + + builder->size_req += size_req; + if (builder->used + size_req <= builder->max) { + vsnprintf(builder->data + builder->used, builder->max - builder->used, fmt, args_copy); + builder->used += size_req; + } + va_end(args_copy); +} + +DN_INIStr8FromResult DN_INI_Str8FromINI(DN_INICore const *ini, char *buffer, size_t size) +{ + DN_INIStr8FromResult result = {}; + DN_INISection const *section_stack[64] = {}; + size_t section_stack_count = 0; + if (ini->first_section.child_first) + section_stack[section_stack_count++] = &ini->first_section; + + DN_INIStr8Builder builder = {}; + builder.data = buffer; + builder.max = size; + + DN_INISection *parent_stack[32] = {}; + size_t parent_stack_count = 0; + for (; section_stack_count;) { + DN_INISection const *it = section_stack[--section_stack_count]; + + if (it != &ini->first_section) { + DN_INI_Str8BuilderAppend_(&builder, "["); + for (DN_INISection *parent = it->parent; parent; parent = parent->parent) + if (parent->name.size) + parent_stack[parent_stack_count++] = parent; + for (size_t index = parent_stack_count - 1; index < parent_stack_count; index--) { + DN_INISection *parent = parent_stack[index]; + DN_INI_Str8BuilderAppend_(&builder, "%.*s.", (int)parent->name.size, parent->name.data); + } + parent_stack_count = 0; + DN_INI_Str8BuilderAppend_(&builder, "%.*s]\n", (int)it->name.size, it->name.data); + } + + for (DN_INIField *field = it->first_field; field; field = field->next) { + DN_INI_Str8BuilderAppend_(&builder, "%.*s = ", (int)field->key.size, field->key.data); + switch (field->value_type) { + case DN_INIFieldType_String: DN_INI_Str8BuilderAppend_(&builder, "%.*s\n", (int)field->value.size, field->value.data); break; + case DN_INIFieldType_Bool: DN_INI_Str8BuilderAppend_(&builder, "%d\n", field->value_bool); break; + case DN_INIFieldType_USize: DN_INI_Str8BuilderAppend_(&builder, "%zu\n", field->value_usize); break; + } + } + + if (it->next) + section_stack[section_stack_count++] = it->next; + if (it->child_first) + section_stack[section_stack_count++] = it->child_first; + + if (section_stack_count && it != &ini->first_section) + DN_INI_Str8BuilderAppend_(&builder, "\n"); + } + + result.size_req = builder.size_req; + if (buffer) { + result.str8.data = builder.data; + result.str8.size = builder.used; + result.success = true; + } else { + result.success = true; + } + + return result; +} + static bool DN_INI_Str8Eq(DN_INIStr8 lhs, DN_INIStr8 rhs) { bool result = lhs.size == rhs.size && DN_INI_Memcmp(lhs.data, rhs.data, lhs.size) == 0; @@ -442,8 +519,8 @@ DN_INICore DN_INI_ParseFromPtr(char const *buf, size_t count, char *base, size_t arena.max = base_count; DN_INICore result = {}; - DN_INISection *curr_section = &result.first_section; - DN_INIField *field = 0; + DN_INISection *curr_section = &result.first_section; + DN_INIField *field = 0; for (;;) { DN_INIToken token = DN_INI_NextToken(&tokeniser); if (token.type == DN_INITokenType_EndOfStream) @@ -651,6 +728,8 @@ DN_INISection *DN_INI_AppendSectionF(DN_INICore *ini, DN_INIArena *arena, DN_INI result->name.data = (char *)DN_INI_ArenaAlloc(arena, size_req + 1); result->name.size = size_req; vsnprintf(result->name.data, result->name.size + 1, fmt, args_copy); + if (!section) + section = &ini->first_section; if (result) { if (section) { @@ -770,83 +849,6 @@ DN_INIField *DN_INI_AppendKeyF(DN_INICore *ini, DN_INIArena *arena, DN_INISectio return result; } -static void DN_INI_Str8BuilderAppend(DN_INIStr8Builder *builder, char const *fmt, ...) -{ - va_list args; - va_list args_copy; - va_start(args, fmt); - va_copy(args_copy, args); - int size_req = vsnprintf(0, 0, fmt, args); - va_end(args); - - builder->size_req += size_req; - if (builder->used + size_req <= builder->max) { - vsnprintf(builder->data + builder->used, builder->max - builder->used, fmt, args_copy); - builder->used += size_req; - } - va_end(args_copy); -} - -DN_INIStr8FromResult DN_INI_Str8FromINI(DN_INICore const *ini, char *buffer, size_t size) -{ - DN_INIStr8FromResult result = {}; - DN_INISection const *section_stack[64] = {}; - size_t section_stack_count = 0; - if (ini->first_section.child_first) - section_stack[section_stack_count++] = &ini->first_section; - - DN_INIStr8Builder builder = {}; - builder.data = buffer; - builder.max = size; - - DN_INISection *parent_stack[32] = {}; - size_t parent_stack_count = 0; - for (; section_stack_count;) { - DN_INISection const *it = section_stack[--section_stack_count]; - - if (it != &ini->first_section) { - DN_INI_Str8BuilderAppend(&builder, "["); - for (DN_INISection *parent = it->parent; parent; parent = parent->parent) - if (parent->name.size) - parent_stack[parent_stack_count++] = parent; - for (size_t index = parent_stack_count - 1; index < parent_stack_count; index--) { - DN_INISection *parent = parent_stack[index]; - DN_INI_Str8BuilderAppend(&builder, "%.*s.", (int)parent->name.size, parent->name.data); - } - parent_stack_count = 0; - DN_INI_Str8BuilderAppend(&builder, "%.*s]\n", (int)it->name.size, it->name.data); - } - - for (DN_INIField *field = it->first_field; field; field = field->next) { - DN_INI_Str8BuilderAppend(&builder, "%.*s = ", (int)field->key.size, field->key.data); - switch (field->value_type) { - case DN_INIFieldType_String: DN_INI_Str8BuilderAppend(&builder, "%.*s\n", (int)field->value.size, field->value.data); break; - case DN_INIFieldType_Bool: DN_INI_Str8BuilderAppend(&builder, "%d\n", field->value_bool); break; - case DN_INIFieldType_USize: DN_INI_Str8BuilderAppend(&builder, "%zu\n", field->value_usize); break; - } - } - - if (it->next) - section_stack[section_stack_count++] = it->next; - if (it->child_first) - section_stack[section_stack_count++] = it->child_first; - - if (section_stack_count) - DN_INI_Str8BuilderAppend(&builder, "\n"); - } - - result.size_req = builder.size_req; - if (buffer) { - result.str8.data = builder.data; - result.str8.size = builder.used; - result.success = true; - } else { - result.success = true; - } - - return result; -} - #if defined(DN_INI_WITH_UNIT_TESTS) || 1 void DN_INI_UnitTests() { diff --git a/Source/Standalone/dn_ini.h b/Source/Standalone/dn_ini.h index 18b7507..024f6d4 100644 --- a/Source/Standalone/dn_ini.h +++ b/Source/Standalone/dn_ini.h @@ -153,34 +153,37 @@ struct DN_INIFieldBool // NOTE: Utilities -int DN_INI_SNPrintF_ (char const *buffer, size_t size, char const *fmt, ...); -void * DN_INI_ArenaAlloc (DN_INIArena *arena, size_t size); -DN_INIStr8 DN_INI_Str8FromPtr (char const *data, size_t count); +// Str8FromINI's `size` parameter must include space for the null-terminator, i.e: +// `DN_INIStr8FromResult.size_req + 1` bytes +int DN_INI_SNPrintF_ (char const *buffer, size_t size, char const *fmt, ...); +void * DN_INI_ArenaAlloc (DN_INIArena *arena, size_t size); +DN_INIStr8 DN_INI_Str8FromPtr (char const *data, size_t count); +DN_INIStr8FromResult DN_INI_Str8FromINI (DN_INICore const *ini, char *buffer, size_t size); // NOTE: Tokeniser/Parsing -DN_INITokeniser DN_INI_TokeniserFromPtr (char const *buf, size_t count); -DN_INIToken DN_INI_NextToken (DN_INITokeniser const *tokeniser); -void DN_INI_EatToken (DN_INITokeniser *tokeniser, DN_INIToken token); +DN_INITokeniser DN_INI_TokeniserFromPtr (char const *buf, size_t count); +DN_INIToken DN_INI_NextToken (DN_INITokeniser const *tokeniser); +void DN_INI_EatToken (DN_INITokeniser *tokeniser, DN_INIToken token); // NOTE: Lookup -DN_INISection * DN_INI_ChildSectionFromStr8 (DN_INISection *section, DN_INIStr8 str8); -DN_INISection * DN_INI_ChildSectionFromCStr (DN_INISection *section, char const *name, size_t name_size); -DN_INIField * DN_INI_FieldFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); -DN_INIField * DN_INI_FieldFromSection (DN_INISection *section, char const *key, size_t key_size); -DN_INIFieldUSize DN_INI_FieldUSizeFromSectionStr8(DN_INISection *section, DN_INIStr8 str8); -DN_INIFieldStr8 DN_INI_FieldStr8FromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); -DN_INIFieldBool DN_INI_FieldBoolFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); -DN_INICore DN_INI_ParseFromPtr (char const *buf, size_t count, char *base, size_t base_count); +DN_INISection * DN_INI_ChildSectionFromStr8 (DN_INISection *section, DN_INIStr8 str8); +DN_INISection * DN_INI_ChildSectionFromCStr (DN_INISection *section, char const *name, size_t name_size); +DN_INIField * DN_INI_FieldFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); +DN_INIField * DN_INI_FieldFromSection (DN_INISection *section, char const *key, size_t key_size); +DN_INIFieldUSize DN_INI_FieldUSizeFromSectionStr8(DN_INISection *section, DN_INIStr8 str8); +DN_INIFieldStr8 DN_INI_FieldStr8FromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); +DN_INIFieldBool DN_INI_FieldBoolFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); +DN_INICore DN_INI_ParseFromPtr (char const *buf, size_t count, char *base, size_t base_count); -// NOTE: Building -DN_INISection * DN_INI_AppendSectionF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *fmt, ...); -DN_INIField * DN_INI_AppendKeyBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, bool value); -DN_INIField * DN_INI_AppendKeyPtrBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, bool value); -DN_INIField * DN_INI_AppendKeyUSize (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, size_t value); -DN_INIField * DN_INI_AppendKeyPtrUSize (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, size_t value); -DN_INIField * DN_INI_AppendKeyCStr8 (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, char const *value, size_t value_size); -DN_INIField * DN_INI_AppendKeyF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, char const *fmt, ...); -void DN_INI_AppendField (DN_INISection *section, DN_INIField *field); +// NOTE: Building +DN_INISection * DN_INI_AppendSectionF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *fmt, ...); +DN_INIField * DN_INI_AppendKeyBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, bool value); +DN_INIField * DN_INI_AppendKeyPtrBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, bool value); +DN_INIField * DN_INI_AppendKeyUSize (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, size_t value); +DN_INIField * DN_INI_AppendKeyPtrUSize (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, size_t value); +DN_INIField * DN_INI_AppendKeyCStr8 (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, char const *value, size_t value_size); +DN_INIField * DN_INI_AppendKeyF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, char const *fmt, ...); +void DN_INI_AppendField (DN_INISection *section, DN_INIField *field); #if defined(DN_INI_WITH_UNIT_TESTS) void DN_INI_UnitTests (); diff --git a/Source/dn.cpp b/Source/dn.cpp index fd9a950..b1c57b6 100644 --- a/Source/dn.cpp +++ b/Source/dn.cpp @@ -1,16 +1,9 @@ #include "Base/dn_base.cpp" #include "Base/dn_base_containers.cpp" -#include "Base/dn_base_log.cpp" #include "Base/dn_base_leak.cpp" #if DN_H_WITH_OS -#include "OS/dn_os_tls.cpp" #include "OS/dn_os.cpp" -#include "OS/dn_os_allocator.cpp" -#include "OS/dn_os_containers.cpp" -#include "OS/dn_os_print.cpp" -#include "OS/dn_os_string.cpp" - #if defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN) #include "OS/dn_os_posix.cpp" #elif defined(DN_PLATFORM_WIN32) @@ -18,8 +11,6 @@ #else #error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs #endif - -#include "OS/dn_os_stacktrace.cpp" #endif #if DN_H_WITH_CORE @@ -30,10 +21,6 @@ #include "Extra/dn_math.cpp" #endif -#if DN_H_WITH_HASH -#include "Extra/dn_hash.cpp" -#endif - #if DN_H_WITH_HELPERS #include "Extra/dn_helpers.cpp" #endif diff --git a/Source/dn.h b/Source/dn.h index f79aac8..d14742a 100644 --- a/Source/dn.h +++ b/Source/dn.h @@ -9,7 +9,6 @@ #define DN_H_WITH_OS 1 #define DN_H_WITH_CORE 1 #define DN_H_WITH_MATH 1 - #define DN_H_WITH_HASH 1 #define DN_H_WITH_HELPERS 1 #define DN_H_WITH_ASYNC 1 #define DN_H_WITH_NET 1 @@ -66,11 +65,8 @@ // This means functionality that relies on the OS like printing, memory allocation, stack traces // and so forth are disabled. -#include "Base/dn_base_compiler.h" #include "Base/dn_base.h" -#include "Base/dn_base_os.h" #include "Base/dn_base_assert.h" -#include "Base/dn_base_log.h" #include "Base/dn_base_containers.h" #include "Base/dn_base_leak.h" @@ -84,12 +80,7 @@ #error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs #endif -#include "OS/dn_os_tls.h" #include "OS/dn_os.h" -#include "OS/dn_os_allocator.h" -#include "OS/dn_os_containers.h" -#include "OS/dn_os_print.h" -#include "OS/dn_os_string.h" #endif #if DN_H_WITH_CORE @@ -100,10 +91,6 @@ #include "Extra/dn_math.h" #endif -#if DN_H_WITH_HASH -#include "Extra/dn_hash.h" -#endif - #if DN_H_WITH_HELPERS #include "Extra/dn_helpers.h" #endif diff --git a/Source/dn_core.cpp b/Source/dn_core.cpp index 25226a7..c88a6c0 100644 --- a/Source/dn_core.cpp +++ b/Source/dn_core.cpp @@ -1,12 +1,13 @@ #define DN_INC_CPP #if defined(_CLANGD) - #include "dn_inc.h" + #include "../Base/dn_base.h" + #include "../OS/dn_os.h" #endif DN_Core *g_dn_; -static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args) +static void DN_InitOS_(DN_OSCore *os) { #if defined(DN_OS_H) && defined(DN_OS_CPP) // NOTE: OS @@ -40,19 +41,19 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args) #endif #if defined(DN_PLATFORM_WIN32) - os->platform_context = DN_ArenaNew(&os->arena, DN_W32Core, DN_ZMem_Yes); + os->platform_context = DN_ArenaNew(&os->arena, DN_OSW32Core, DN_ZMem_Yes); #elif defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN) - os->platform_context = DN_ArenaNew(&os->arena, DN_POSIXCore, DN_ZMem_Yes); + os->platform_context = DN_ArenaNew(&os->arena, DN_OSPOSIXCore, DN_ZMem_Yes); #endif #if defined(DN_PLATFORM_WIN32) - DN_W32Core *w32 = DN_Cast(DN_W32Core *) os->platform_context; + DN_OSW32Core *w32 = DN_Cast(DN_OSW32Core *) os->platform_context; InitializeCriticalSection(&w32->sync_primitive_free_list_mutex); QueryPerformanceFrequency(&w32->qpc_frequency); HMODULE module = LoadLibraryA("kernel32.dll"); if (module) { - w32->set_thread_description = DN_Cast(DN_W32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription"); + w32->set_thread_description = DN_Cast(DN_OSW32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription"); FreeLibrary(module); } @@ -62,27 +63,12 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args) if (w32->bcrypt_rng_handle && init_status == 0) w32->bcrypt_init_success = true; else - DN_LOG_ErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status); + DN_LogErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status); #else - DN_Posix_Init(DN_Cast(DN_POSIXCore *)os->platform_context); + DN_OS_PosixInit(DN_Cast(DN_OSPosixCore *)os->platform_context); #endif } - // NOTE: Initialise tmem arenas which allocate memory and will be - // recorded to the now initialised allocation table. The initialisation - // of tmem memory may request tmem memory itself in leak tracing mode. - // This is supported as the tmem arenas defer allocation tracking until - // initialisation is done. - DN_OSTLSInitArgs tls_init_args = {}; - if (args) { - tls_init_args.commit = args->os_tls_commit; - tls_init_args.reserve = args->os_tls_reserve; - tls_init_args.err_sink_reserve = args->os_tls_err_sink_reserve; - tls_init_args.err_sink_commit = args->os_tls_err_sink_commit; - } - - DN_OS_TLSInit(&os->tls, tls_init_args); - DN_OS_TLSSetCurrentThreadTLS(&os->tls); os->cpu_report = DN_CPUGetReport(); #define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_Str8Lit(#label)}; @@ -92,20 +78,19 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args) #endif // defined(DN_OS_H) && defined(DN_OS_CPP) } - -DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args) +DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags) { g_dn_ = dn; dn->init_flags = flags; if (flags & DN_InitFlags_OS) { #if defined(DN_OS_H) && defined(DN_OS_CPP) - DN_InitOS_(&dn->os, args); + DN_InitOS_(&dn->os); if (flags & DN_InitFlags_OSLeakTracker) { // 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_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak); - dn->leak.alloc_table = DN_DSMap_Init(&dn->leak.alloc_table_arena, 4096, DN_DSMapFlags_Nil); + dn->leak.alloc_table = DN_DSMapInit(&dn->leak.alloc_table_arena, 4096, DN_DSMapFlags_Nil); } #endif } @@ -141,7 +126,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args) #endif #if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) - DN_POSIXCore *posix = DN_Cast(DN_POSIXCore *)g_dn_->os.platform_context; + DN_OSPosixCore *posix = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context; DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Clock GetTime: %S\n", posix->clock_monotonic_raw ? DN_Str8Lit("CLOCK_MONOTONIC_RAW") : DN_Str8Lit("CLOCK_MONOTONIC")); #endif // TODO(doyle): Add stacktrace feature log @@ -177,7 +162,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args) } if (buf_size) - DN_LOG_DebugF("%.*s", DN_Cast(int)buf_size, buf); + DN_LogDebugF("%.*s", DN_Cast(int)buf_size, buf); } DN_API void DN_BeginFrame() diff --git a/Source/dn_core.h b/Source/dn_core.h index b8c7be4..c2f62d0 100644 --- a/Source/dn_core.h +++ b/Source/dn_core.h @@ -2,8 +2,8 @@ #define DN_INC_H #if defined(_CLANGD) - #include "dn_base_inc.h" - #include "dn_os_inc.h" + #define DN_H_WITH_OS 1 + #include "dn.h" #endif struct DN_InitArgs @@ -38,6 +38,7 @@ struct DN_Core extern DN_Core *g_dn_; DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args); +DN_API void DN_ThreadContextInit(); DN_API void DN_BeginFrame(); #endif // !defined(DN_INC_H)