From 04b5e26ff30b7671bd30bf006152c8e8703cb5ec Mon Sep 17 00:00:00 2001 From: doyle Date: Thu, 31 Aug 2023 22:10:47 +1000 Subject: [PATCH] dqn: Add more container types --- Misc/dqn_unit_tests.cpp | 32 ++- build.bat | 14 +- dqn.h | 62 +++--- dqn_base.cpp | 163 +++++++++++++++ dqn_base.h | 103 ++++++++- dqn_containers.h | 451 ++++++++++++++++++++++++---------------- dqn_debug.cpp | 164 ++------------- dqn_debug.h | 101 +-------- dqn_memory.cpp | 21 -- dqn_memory.h | 19 -- 10 files changed, 612 insertions(+), 518 deletions(-) diff --git a/Misc/dqn_unit_tests.cpp b/Misc/dqn_unit_tests.cpp index 44b4a82..a8ca0e7 100644 --- a/Misc/dqn_unit_tests.cpp +++ b/Misc/dqn_unit_tests.cpp @@ -695,7 +695,7 @@ static Dqn_UTest Dqn_Test_FixedArray() DQN_UTEST_TEST("Erase stable 1 element from array") { int raw_array[] = {1, 2, 3}; auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); - Dqn_FArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, Dqn_FArrayErase_Stable); + Dqn_FArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, Dqn_ArrayErase_Stable); DQN_UTEST_ASSERT(&test, array.size == 2); DQN_UTEST_ASSERT(&test, array.data[0] == 1); DQN_UTEST_ASSERT(&test, array.data[1] == 3); @@ -704,7 +704,7 @@ static Dqn_UTest Dqn_Test_FixedArray() DQN_UTEST_TEST("Erase unstable 1 element from array") { int raw_array[] = {1, 2, 3}; auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); - Dqn_FArray_EraseRange(&array, 0 /*begin_index*/, 1 /*count*/, Dqn_FArrayErase_Unstable); + Dqn_FArray_EraseRange(&array, 0 /*begin_index*/, 1 /*count*/, Dqn_ArrayErase_Unstable); DQN_UTEST_ASSERT(&test, array.size == 2); DQN_UTEST_ASSERT(&test, array.data[0] == 3); DQN_UTEST_ASSERT(&test, array.data[1] == 2); @@ -1578,22 +1578,22 @@ static Dqn_UTest Dqn_Test_VArray() } DQN_UTEST_TEST("Test stable erase, 1 item, the '2' value from the array") { - Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, 1 /*count*/, Dqn_VArrayErase_Stable); + Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, 1 /*count*/, Dqn_ArrayErase_Stable); uint32_t array_literal[] = {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } DQN_UTEST_TEST("Test unstable erase, 1 item, the '1' value from the array") { - Dqn_VArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, Dqn_VArrayErase_Unstable); + Dqn_VArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, Dqn_ArrayErase_Unstable); uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - Dqn_VArrayErase erase_enums[] = {Dqn_VArrayErase_Stable, Dqn_VArrayErase_Unstable}; + Dqn_ArrayErase erase_enums[] = {Dqn_ArrayErase_Stable, Dqn_ArrayErase_Unstable}; DQN_UTEST_TEST("Test un/stable erase, OOB") { - for (Dqn_VArrayErase erase : erase_enums) { + for (Dqn_ArrayErase erase : erase_enums) { uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; Dqn_VArray_EraseRange(&array, DQN_ARRAY_UCOUNT(array_literal) /*begin_index*/, DQN_ARRAY_UCOUNT(array_literal) + 100 /*count*/, erase); DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); @@ -1602,42 +1602,42 @@ static Dqn_UTest Dqn_Test_VArray() } DQN_UTEST_TEST("Test flipped begin/end index stable erase, 2 items, the '15, 3' value from the array") { - Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, Dqn_VArrayErase_Stable); + Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, Dqn_ArrayErase_Stable); uint32_t array_literal[] = {0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } DQN_UTEST_TEST("Test flipped begin/end index unstable erase, 2 items, the '4, 5' value from the array") { - Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, Dqn_VArrayErase_Unstable); + Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, Dqn_ArrayErase_Unstable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10, 11, 12}; DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } DQN_UTEST_TEST("Test stable erase range, 2+1 (oob) item, the '13, 14, +1 OOB' value from the array") { - Dqn_VArray_EraseRange(&array, 8 /*begin_index*/, 3 /*count*/, Dqn_VArrayErase_Stable); + Dqn_VArray_EraseRange(&array, 8 /*begin_index*/, 3 /*count*/, Dqn_ArrayErase_Stable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10}; DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } DQN_UTEST_TEST("Test unstable erase range, 3+1 (oob) item, the '11, 12, +1 OOB' value from the array") { - Dqn_VArray_EraseRange(&array, 6 /*begin_index*/, 3 /*count*/, Dqn_VArrayErase_Unstable); + Dqn_VArray_EraseRange(&array, 6 /*begin_index*/, 3 /*count*/, Dqn_ArrayErase_Unstable); uint32_t array_literal[] = {0, 13, 14, 6, 7, 8}; DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } DQN_UTEST_TEST("Test stable erase -overflow OOB, erasing the '0, 13' value from the array") { - Dqn_VArray_EraseRange(&array, 1 /*begin_index*/, -DQN_ISIZE_MAX /*count*/, Dqn_VArrayErase_Stable); + Dqn_VArray_EraseRange(&array, 1 /*begin_index*/, -DQN_ISIZE_MAX /*count*/, Dqn_ArrayErase_Stable); uint32_t array_literal[] = {14, 6, 7, 8}; DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } DQN_UTEST_TEST("Test unstable erase +overflow OOB, erasing the '7, 8' value from the array") { - Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, DQN_ISIZE_MAX /*count*/, Dqn_VArrayErase_Unstable); + Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, DQN_ISIZE_MAX /*count*/, Dqn_ArrayErase_Unstable); uint32_t array_literal[] = {14, 6}; DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(array_literal)); DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); @@ -1843,14 +1843,6 @@ int main(int argc, char *argv[]) { (void)argv; (void)argc; Dqn_Library_Init(); - - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_StackTraceFrames stack_trace = Dqn_StackTrace_GetFrames(scratch.arena, 128 /*limit*/); - DQN_FOR_UINDEX (index, stack_trace.size) { - Dqn_StackTraceFrame frame = stack_trace.data[index]; - Dqn_Print_LnF("%.*s(%I64u): %.*s", DQN_STRING_FMT(frame.file_name), frame.line_number, DQN_STRING_FMT(frame.function_name)); - } - Dqn_Test_RunSuite(); return 0; } diff --git a/build.bat b/build.bat index f5e1f8a..87b0d2d 100644 --- a/build.bat +++ b/build.bat @@ -36,13 +36,13 @@ pushd Build ) REM REM clang-cl =================================================================================== - REM set has_clang_cl=1 - REM where /q clang-cl || set has_clang_cl=0 - REM if %has_clang_cl% == 1 ( - REM echo [BUILD] clang-cl detected, compiling ... - REM set clang_cmd=clang-cl %clang_compile_flags% %clang_link_flags% - REM powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1 - REM ) + set has_clang_cl=1 + where /q clang-cl || set has_clang_cl=0 + if %has_clang_cl% == 1 ( + echo [BUILD] clang-cl detected, compiling ... + set clang_cmd=clang-cl %clang_compile_flags% %clang_link_flags% + powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1 + ) REM zig ======================================================================================== REM TODO(doyle):Can't build "Misc\dqn_unit_tests.cpp|1 col 1| error: unable to build C object: FileNotFound" diff --git a/dqn.h b/dqn.h index 1df60cc..c06bcec 100644 --- a/dqn.h +++ b/dqn.h @@ -36,7 +36,9 @@ #if !defined(DQN_H) #if defined(DQN_ONLY_VARRAY) || \ + defined(DQN_ONLY_SARRAY) || \ defined(DQN_ONLY_FARRAY) || \ + defined(DQN_ONLY_SLICE) || \ defined(DQN_ONLY_DSMAP) || \ defined(DQN_ONLY_LIST) || \ defined(DQN_ONLY_FSTRING8) || \ @@ -58,6 +60,12 @@ #if !defined(DQN_ONLY_FARRAY) #define DQN_NO_FARRAY #endif + #if !defined(DQN_ONLY_SARRAY) + #define DQN_NO_SARRAY + #endif + #if !defined(DQN_ONLY_SLICE) + #define DQN_NO_SLICE + #endif #if !defined(DQN_ONLY_DSMAP) #define DQN_NO_DSMAP #endif @@ -115,8 +123,11 @@ // [$MACR] Macros | | Define macros used in the library // [$TYPE] Types | | Basic types and typedefs // [$INTR] Intrinsics | | Atomics, cpuid, ticket mutex +// [$CALL] Dqn_CallSite | | Source code location/tracing // [$TMUT] Dqn_TicketMutex | | Userland mutex via spinlocking atomics +// [$ALLO] Dqn_Allocator | | Generic allocator interface // [$PRIN] Dqn_Print | | Console printing +// [$LLOG] Dqn_Log | | Console logging macros // NOTE: Additional Configuration // - Override the default heap-allocation routine that is called when the @@ -166,7 +177,6 @@ #include "dqn_base.h" // NOTE: Dqn_External ============================================================================== -// [$BSTK] b_stacktrace | | Generating call stacktraces // [$OS_H] OS Headers | | Headers from the operating system // [$STBS] stb_sprintf | | Portable sprintf #include "dqn_external.h" @@ -186,18 +196,36 @@ // DQN_STB_SPRINTF_HEADER_ONLY // NOTE: Dqn_Memory ================================================================================ -// [$ALLO] Dqn_Allocator | | Generic allocator interface // [$VMEM] Dqn_VMem | | Virtual memory allocation // [$MEMB] Dqn_MemBlock | | Virtual memory blocks // [$AREN] Dqn_Arena | | Growing bump allocator // [$ACAT] Dqn_ArenaCatalog | | Collate, create & manage arenas in a catalog #include "dqn_memory.h" +// NOTE: Dqn_Strings =============================================================================== +// [$CSTR] Dqn_CString8 | | C-string helpers +// [$STR8] Dqn_String8 | | Pointer and length strings +// [$FSTR] Dqn_FString8 | DQN_FSTRING8 | Fixed-size strings +// [$STRB] Dqn_String8Builder | | +// [$CHAR] Dqn_Char | | Character ascii/digit.. helpers +// [$UTFX] Dqn_UTF | | Unicode helpers +#include "dqn_strings.h" + +// NOTE: Dqn_Containers ============================================================================ +// [$CARR] Dqn_CArray | | Basic operations on C arrays for VArray/SArray/FArray to reuse +// [$VARR] Dqn_VArray | DQN_VARRAY | Array backed by virtual memory arena +// [$SARR] Dqn_SArray | DQN_SARRAY | Array that are allocated but cannot resize +// [$FARR] Dqn_FArray | DQN_FARRAY | Fixed-size arrays +// [$SLIC] Dqn_Slice | DQN_SLICE | Pointe and length container of data +// [$DMAP] Dqn_DSMap | DQN_DSMAP | Hashtable, 70% max load, PoT size, linear probe, chain repair +// [$LIST] Dqn_List | DQN_LIST | Chunked linked lists, append only +#include "dqn_containers.h" + // NOTE: Dqn_Debug ================================================================================= // [$DEBM] Debug Macros | | -// [$CALL] Dqn_CallSite | | Source code location/tracing +// [$ASAN] Dqn_Asan | | Helpers to manually poison memory using ASAN +// [$STKT] Dqn_StackTrace | | Create stack traces // [$DEBG] Dqn_Debug | | Debugging tools/helpers -// [$LLOG] Dqn_Log | | Console logging macros #include "dqn_debug.h" // NOTE: Additional Configuration @@ -248,22 +276,6 @@ // // DQN_ASAN_POISON_GUARD_SIZE 128 -// NOTE: Dqn_Strings =============================================================================== -// [$CSTR] Dqn_CString8 | | C-string helpers -// [$STR8] Dqn_String8 | | Pointer and length strings -// [$FSTR] Dqn_FString8 | DQN_FSTRING8 | Fixed-size strings -// [$STRB] Dqn_String8Builder | | -// [$CHAR] Dqn_Char | | Character ascii/digit.. helpers -// [$UTFX] Dqn_UTF | | Unicode helpers -#include "dqn_strings.h" - -// NOTE: Dqn_Containers ============================================================================ -// [$VARR] Dqn_VArray | DQN_VARRAY | Array backed by virtual memory arena -// [$FARR] Dqn_FArray | DQN_FARRAY | Fixed-size arrays -// [$DMAP] Dqn_DSMap | DQN_DSMAP | Hashtable, 70% max load, PoT size, linear probe, chain repair -// [$LIST] Dqn_List | DQN_LIST | Chunked linked lists, append only -#include "dqn_containers.h" - // NOTE: Dqn_Platform ============================================================================== // [$FSYS] Dqn_Fs | DQN_FS | Filesystem helpers // [$DATE] Dqn_Date | | Date-time helpers @@ -271,16 +283,6 @@ // [$WINN] Dqn_WinNet | DQN_WINNET | Windows internet download/query helpers // [$OSYS] Dqn_OS | DQN_WIN | Operating-system APIs // [$TCTX] Dqn_ThreadContext | | Per-thread data structure e.g. temp arenas - -// NOTE: Additional Configuration -// - When compiling with ASAN, set this macro to `1` to enable poisoning of the -// memory allocated and freed by memory arenas in the library. By default this -// is set to `0`. By enabling this, all allocations will be guarded by a page, -// before and after the returned pointer. All allocations will be aligned to -// and padded to atleast DQN_ASAN_POISON_ALIGNMENT (e.g. 8 bytes). -// -// DQN_ASAN_POISON 1 - #include "dqn_platform.h" // NOTE: Dqn_Math ================================================================================== diff --git a/dqn_base.cpp b/dqn_base.cpp index b6d4c4a..4effe55 100644 --- a/dqn_base.cpp +++ b/dqn_base.cpp @@ -18,6 +18,27 @@ Dqn_CPUIDRegisters Dqn_CPUID(int function_id) } #endif // !defined(DQN_OS_ARM64) +// NOTE: [$ALLO] Dqn_Allocator ===================================================================== +DQN_API void *Dqn_Allocator_Alloc(Dqn_Allocator allocator, size_t size, uint8_t align, Dqn_ZeroMem zero_mem) +{ + void *result = NULL; + if (allocator.alloc) { + result = allocator.alloc(size, align, zero_mem, allocator.user_context); + } else { + result = DQN_ALLOC(size); + } + return result; +} + +DQN_API void Dqn_Allocator_Dealloc(Dqn_Allocator allocator, void *ptr, size_t size) +{ + if (allocator.dealloc) { + allocator.dealloc(ptr, size, allocator.user_context); + } else { + DQN_DEALLOC(ptr, size); + } +} + // NOTE: [$TMUT] Dqn_TicketMutex =================================================================== DQN_API void Dqn_TicketMutex_Begin(Dqn_TicketMutex *mutex) { @@ -252,3 +273,145 @@ DQN_API Dqn_String8 Dqn_Print_ESCColourU32String(Dqn_PrintESCColour colour, uint return result; } +// NOTE: [$LLOG] Dqn_Log ========================================================================== +DQN_API Dqn_String8 Dqn_Log_MakeString(Dqn_Allocator allocator, + bool colour, + Dqn_String8 type, + int log_type, + Dqn_CallSite call_site, + char const *fmt, + va_list args) +{ + Dqn_usize header_size_no_ansi_codes = 0; + Dqn_String8 header = {}; + { + DQN_LOCAL_PERSIST Dqn_usize max_type_length = 0; + max_type_length = DQN_MAX(max_type_length, type.size); + int type_padding = DQN_CAST(int)(max_type_length - type.size); + + Dqn_String8 colour_esc = {}; + Dqn_String8 bold_esc = {}; + Dqn_String8 reset_esc = {}; + if (colour) { + bold_esc = Dqn_Print_ESCBoldString; + reset_esc = Dqn_Print_ESCResetString; + switch (log_type) { + case Dqn_LogType_Debug: break; + case Dqn_LogType_Info: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Info); break; + case Dqn_LogType_Warning: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Warning); break; + case Dqn_LogType_Error: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Error); break; + } + } + + Dqn_String8 file_name = Dqn_String8_FileNameFromPath(call_site.file); + Dqn_DateHMSTimeString const time = Dqn_Date_HMSLocalTimeStringNow(); + header = Dqn_String8_InitF(allocator, + "%.*s " // date + "%.*s " // hms + "%.*s" // colour + "%.*s" // bold + "%.*s" // type + "%*s" // type padding + "%.*s" // reset + " %.*s" // file name + ":%05u ", // line number + DQN_CAST(uint32_t)time.date_size - 2, time.date + 2, // date + DQN_CAST(uint32_t)time.hms_size, time.hms, // hms + DQN_CAST(uint32_t)colour_esc.size, colour_esc.data, // colour + DQN_CAST(uint32_t)bold_esc.size, bold_esc.data, // bold + DQN_CAST(uint32_t)type.size, type.data, // type + DQN_CAST(uint32_t)type_padding, "", // type padding + DQN_CAST(uint32_t)reset_esc.size, reset_esc.data, // reset + DQN_CAST(uint32_t)file_name.size, file_name.data, // file name + call_site.line); // line number + header_size_no_ansi_codes = header.size - colour_esc.size - Dqn_Print_ESCResetString.size; + } + + // NOTE: Header padding ======================================================================== + Dqn_usize header_padding = 0; + { + DQN_LOCAL_PERSIST Dqn_usize max_header_length = 0; + max_header_length = DQN_MAX(max_header_length, header_size_no_ansi_codes); + header_padding = max_header_length - header_size_no_ansi_codes; + } + + // NOTE: Construct final log =================================================================== + Dqn_String8 user_msg = Dqn_String8_InitFV(allocator, fmt, args); + Dqn_String8 result = Dqn_String8_Allocate(allocator, header.size + header_padding + user_msg.size, Dqn_ZeroMem_No); + DQN_MEMCPY(result.data, header.data, header.size); + DQN_MEMSET(result.data + header.size, ' ', header_padding); + DQN_MEMCPY(result.data + header.size + header_padding, user_msg.data, user_msg.size); + return result; +} + +DQN_FILE_SCOPE void Dqn_Log_FVDefault_(Dqn_String8 type, int log_type, void *user_data, Dqn_CallSite call_site, char const *fmt, va_list args) +{ + Dqn_Library *lib = g_dqn_library; + (void)log_type; + (void)user_data; + + // NOTE: Open log file for appending if requested ========================== + Dqn_TicketMutex_Begin(&lib->log_file_mutex); + if (lib->log_to_file && !lib->log_file.handle && lib->log_file.error_size == 0) { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 log_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/dqn.log", DQN_STRING_FMT(lib->exe_dir)); + lib->log_file = Dqn_Fs_OpenFile(log_path, Dqn_FsFileOpen_CreateAlways, Dqn_FsFileAccess_AppendOnly); + } + Dqn_TicketMutex_End(&lib->log_file_mutex); + + // NOTE: Generate the log header =========================================== + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 log_line = Dqn_Log_MakeString(scratch.allocator, + !lib->log_no_colour, + type, + log_type, + call_site, + fmt, + args); + + // NOTE: Print log ========================================================= + Dqn_Print_StdLn(Dqn_PrintStd_Out, log_line); + + Dqn_TicketMutex_Begin(&lib->log_file_mutex); + Dqn_Fs_WriteFile(&lib->log_file, log_line); + Dqn_Fs_WriteFile(&lib->log_file, DQN_STRING8("\n")); + Dqn_TicketMutex_End(&lib->log_file_mutex); +} + +DQN_API void Dqn_Log_FVCallSite(Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, va_list args) +{ + Dqn_LogProc *logging_function = g_dqn_library->log_callback ? g_dqn_library->log_callback : Dqn_Log_FVDefault_; + logging_function(type, -1 /*log_type*/, g_dqn_library->log_user_data, call_site, fmt, args); +} + +DQN_API void Dqn_Log_FCallSite(Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Dqn_Log_FVCallSite(type, call_site, fmt, args); + va_end(args); +} + +DQN_API void Dqn_Log_TypeFVCallSite(Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, va_list args) +{ + Dqn_String8 type_string = DQN_STRING8("DQN-BAD-LOG-TYPE"); + switch (type) { + case Dqn_LogType_Error: type_string = DQN_STRING8("ERROR"); break; + case Dqn_LogType_Info: type_string = DQN_STRING8("INFO"); break; + case Dqn_LogType_Warning: type_string = DQN_STRING8("WARN"); break; + case Dqn_LogType_Debug: type_string = DQN_STRING8("DEBUG"); break; + case Dqn_LogType_Count: type_string = DQN_STRING8("BADXX"); break; + } + + Dqn_LogProc *logging_function = g_dqn_library->log_callback ? g_dqn_library->log_callback : Dqn_Log_FVDefault_; + logging_function(type_string, type /*log_type*/, g_dqn_library->log_user_data, call_site, fmt, args); +} + +DQN_API void Dqn_Log_TypeFCallSite(Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Dqn_Log_TypeFVCallSite(type, call_site, fmt, args); + va_end(args); +} + diff --git a/dqn_base.h b/dqn_base.h index 51db4a5..996936f 100644 --- a/dqn_base.h +++ b/dqn_base.h @@ -182,12 +182,34 @@ #define DQN_DAYS_TO_S(val) (DQN_HOURS_TO_S(val) * 24ULL) #define DQN_YEARS_TO_S(val) (DQN_DAYS_TO_S(val) * 365ULL) +// NOTE: Debug Break =============================================================================== +#if !defined(DQN_DEBUG_BREAK) + #if defined(NDEBUG) + #define DQN_DEBUG_BREAK + #else + #if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) + #define DQN_DEBUG_BREAK __debugbreak() + #elif defined(DQN_COMPILER_CLANG) + #define DQN_DEBUG_BREAK __builtin_debugtrap() + #elif defined(DQN_COMPILER_CLANG) || defined(DQN_COMPILER_GCC) + #include + #define DQN_DEBUG_BREAK raise(SIGTRAP) + #elif + #error "Unhandled compiler" + #endif + #endif +#endif + +#if !defined(DQN_MEMSET_BYTE) + #define DQN_MEMSET_BYTE 0 +#endif + // NOTE: Assert Macros ============================================================================= #define DQN_HARD_ASSERT(expr) DQN_HARD_ASSERTF(expr, "") #define DQN_HARD_ASSERTF(expr, fmt, ...) \ if (!(expr)) { \ Dqn_Log_ErrorF("Hard assert triggered " #expr ". " fmt, ##__VA_ARGS__); \ - DQN_DUMP_STACK_TRACE; \ + Dqn_StackTrace_Print(128 /*limit*/); \ DQN_DEBUG_BREAK; \ } @@ -199,7 +221,7 @@ #define DQN_ASSERTF(expr, fmt, ...) \ if (!(expr)) { \ Dqn_Log_ErrorF("Assert triggered " #expr ". " fmt, ##__VA_ARGS__); \ - DQN_DUMP_STACK_TRACE; \ + Dqn_StackTrace_Print(128 /*limit*/); \ DQN_DEBUG_BREAK; \ } #endif @@ -307,6 +329,15 @@ struct Dqn_String8 char *end () { return data + size; } }; +// NOTE: [$CALL] Dqn_CallSite ====================================================================== +struct Dqn_CallSite +{ + Dqn_String8 file; + Dqn_String8 function; + unsigned int line; +}; +#define DQN_CALL_SITE Dqn_CallSite{DQN_STRING8(__FILE__), DQN_STRING8(__func__), __LINE__} + // NOTE: [$INTR] Intrinsics ======================================================================== // Platform agnostic functions for CPU level instructions like atomics, barriers // and timestamp counters. @@ -446,6 +477,25 @@ Dqn_uint Dqn_TicketMutex_MakeTicket (Dqn_TicketMutex *mutex); void Dqn_TicketMutex_BeginTicket(Dqn_TicketMutex const *mutex, Dqn_uint ticket); bool Dqn_TicketMutex_CanLock (Dqn_TicketMutex const *mutex, Dqn_uint ticket); +// NOTE: [$ALLO] Dqn_Allocator ===================================================================== +typedef void *Dqn_Allocator_AllocProc(size_t size, uint8_t align, Dqn_ZeroMem zero_mem, void *user_context); +typedef void Dqn_Allocator_DeallocProc(void *ptr, size_t size, void *user_context); + +struct Dqn_Allocator +{ + void *user_context; // User assigned pointer that is passed into the allocator functions + Dqn_Allocator_AllocProc *alloc; // Memory allocating routine + Dqn_Allocator_DeallocProc *dealloc; // Memory deallocating routine +}; + +// NOTE: Macros ==================================================================================== +#define Dqn_Allocator_NewArray(allocator, Type, count, zero_mem) (Type *)Dqn_Allocator_Alloc(allocator, sizeof(Type) * count, alignof(Type), zero_mem) +#define Dqn_Allocator_New(allocator, Type, zero_mem) (Type *)Dqn_Allocator_Alloc(allocator, sizeof(Type), alignof(Type), zero_mem) + +// NOTE: API ======================================================================================= +void *Dqn_Allocator_Alloc (Dqn_Allocator allocator, size_t size, uint8_t align, Dqn_ZeroMem zero_mem); +void Dqn_Allocator_Dealloc(Dqn_Allocator allocator, void *ptr, size_t size); + // NOTE: [$PRIN] Dqn_Print ========================================================================= enum Dqn_PrintStd { @@ -547,3 +597,52 @@ Dqn_String8 Dqn_Print_ESCColourU32String(Dqn_PrintESCColour colour, u #define Dqn_Print_ESCResetString DQN_STRING8(Dqn_Print_ESCReset) #define Dqn_Print_ESCBoldString DQN_STRING8(Dqn_Print_ESCBold) +// NOTE: [$LLOG] Dqn_Log ========================================================================== +// NOTE: API +// @proc Dqn_LogProc +// @desc The logging procedure of the library. Users can override the default +// logging function by setting the logging function pointer in Dqn_Library. +// This function will be invoked every time a log is recorded using the +// following functions. +// +// @param[in] log_type This value is one of the Dqn_LogType values if the log +// was generated from one of the default categories. -1 if the log is not from +// one of the default categories. + +enum Dqn_LogType +{ + Dqn_LogType_Debug, + Dqn_LogType_Info, + Dqn_LogType_Warning, + Dqn_LogType_Error, + Dqn_LogType_Count, +}; + +/// RGBA +#define Dqn_LogTypeColourU32_Info 0x00'87'ff'ff // Blue +#define Dqn_LogTypeColourU32_Warning 0xff'ff'00'ff // Yellow +#define Dqn_LogTypeColourU32_Error 0xff'00'00'ff // Red + +typedef void Dqn_LogProc(Dqn_String8 type, int log_type, void *user_data, Dqn_CallSite call_site, char const *fmt, va_list va); + +#define Dqn_Log_DebugF(fmt, ...) Dqn_Log_TypeFCallSite(Dqn_LogType_Debug, DQN_CALL_SITE, fmt, ## __VA_ARGS__) +#define Dqn_Log_InfoF(fmt, ...) Dqn_Log_TypeFCallSite(Dqn_LogType_Info, DQN_CALL_SITE, fmt, ## __VA_ARGS__) +#define Dqn_Log_WarningF(fmt, ...) Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, DQN_CALL_SITE, fmt, ## __VA_ARGS__) +#define Dqn_Log_ErrorF(fmt, ...) Dqn_Log_TypeFCallSite(Dqn_LogType_Error, DQN_CALL_SITE, fmt, ## __VA_ARGS__) + +#define Dqn_Log_DebugFV(fmt, args) Dqn_Log_TypeFVCallSite(Dqn_LogType_Debug, DQN_CALL_SITE, fmt, args) +#define Dqn_Log_InfoFV(fmt, args) Dqn_Log_TypeFVCallSite(Dqn_LogType_Info, DQN_CALL_SITE, fmt, args) +#define Dqn_Log_WarningFV(fmt, args) Dqn_Log_TypeFVCallSite(Dqn_LogType_Warning, DQN_CALL_SITE, fmt, args) +#define Dqn_Log_ErrorFV(fmt, args) Dqn_Log_TypeFVCallSite(Dqn_LogType_Error, DQN_CALL_SITE, fmt, args) + +#define Dqn_Log_TypeFV(type, fmt, args) Dqn_Log_TypeFVCallSite(type, DQN_CALL_SITE, fmt, args) +#define Dqn_Log_TypeF(type, fmt, ...) Dqn_Log_TypeFCallSite(type, DQN_CALL_SITE, fmt, ## __VA_ARGS__) + +#define Dqn_Log_FV(type, fmt, args) Dqn_Log_FVCallSite(type, DQN_CALL_SITE, fmt, args) +#define Dqn_Log_F(type, fmt, ...) Dqn_Log_FCallSite(type, DQN_CALL_SITE, fmt, ## __VA_ARGS__) + +DQN_API Dqn_String8 Dqn_Log_MakeString (Dqn_Allocator allocator, bool colour, Dqn_String8 type, int log_type, Dqn_CallSite call_site, char const *fmt, va_list args); +DQN_API void Dqn_Log_TypeFVCallSite(Dqn_LogType type, Dqn_CallSite call_site, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list va); +DQN_API void Dqn_Log_TypeFCallSite (Dqn_LogType type, Dqn_CallSite call_site, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); +DQN_API void Dqn_Log_FVCallSite (Dqn_String8 type, Dqn_CallSite call_site, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list va); +DQN_API void Dqn_Log_FCallSite (Dqn_String8 type, Dqn_CallSite call_site, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); diff --git a/dqn_containers.h b/dqn_containers.h index 28d13d8..0a1dab2 100644 --- a/dqn_containers.h +++ b/dqn_containers.h @@ -1,3 +1,13 @@ +// NOTE: [$CARR] Dqn_CArray ======================================================================== +enum Dqn_ArrayErase +{ + Dqn_ArrayErase_Unstable, + Dqn_ArrayErase_Stable, +}; + +template Dqn_usize Dqn_CArray_EraseRange(T* data, Dqn_usize *size, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase); +template T * Dqn_CArray_Make (T* data, Dqn_usize *size, Dqn_usize max, Dqn_usize count, Dqn_ZeroMem zero_mem); + #if !defined(DQN_NO_VARRAY) // NOTE: [$VARR] Dqn_VArray ======================================================================== // An array that is backed by virtual memory by reserving addressing space and @@ -74,12 +84,6 @@ template struct Dqn_VArray T const *end () const { return data + size; } }; -enum Dqn_VArrayErase -{ - Dqn_VArrayErase_Unstable, - Dqn_VArrayErase_Stable, -}; - // NOTE: Setup ===================================================================================== DQN_API template Dqn_VArray Dqn_VArray_InitByteSize(Dqn_Arena *arena, Dqn_usize byte_size); DQN_API template Dqn_VArray Dqn_VArray_Init (Dqn_Arena *arena, Dqn_usize max); @@ -91,10 +95,83 @@ DQN_API template T * Dqn_VArray_Make (Dqn_VArray T * Dqn_VArray_Add (Dqn_VArray *array, T const *items, Dqn_usize count); // NOTE: Modify ==================================================================================== -DQN_API template void Dqn_VArray_EraseRange (Dqn_VArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_VArrayErase erase); +DQN_API template void Dqn_VArray_EraseRange (Dqn_VArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase); DQN_API template void Dqn_VArray_Clear (Dqn_VArray *array); #endif // !defined(DQN_NO_VARRAY) +#if !defined(DQN_NO_SARRAY) +// NOTE: [$SARR] Dqn_SArray ======================================================================== +template struct Dqn_SArray +{ + T *data; // Pointer to the start of the array items in the block of memory + Dqn_usize size; // Number of items currently in the array + Dqn_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; } +}; + +// NOTE: Setup ===================================================================================== +DQN_API template Dqn_SArray Dqn_SArray_Init (Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem); +DQN_API template bool Dqn_SArray_IsValid (Dqn_SArray const *array); + +// NOTE: Insert ==================================================================================== +DQN_API template T * Dqn_SArray_Make (Dqn_SArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem); +DQN_API template T * Dqn_SArray_AddArray(Dqn_SArray *array, T const *items, Dqn_usize count); +DQN_API template T * Dqn_SArray_Add (Dqn_SArray *array, T const &item); + +// NOTE: Modify ==================================================================================== +DQN_API template void Dqn_SArray_EraseRange(Dqn_SArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase); +DQN_API template void Dqn_SArray_Clear (Dqn_SArray *array); +#endif // !defined(DQN_NO_SARRAY) + +#if !defined(DQN_NO_FARRAY) +// NOTE: [$FARR] Dqn_FArray ======================================================================== +template struct Dqn_FArray +{ + T data[N]; // Pointer to the start of the array items in the block of memory + Dqn_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; } +}; + +// NOTE: Setup ===================================================================================== +DQN_API template Dqn_FArray Dqn_FArray_Init (T const *array, Dqn_usize count); +DQN_API template bool Dqn_FArray_IsValid (Dqn_FArray const *array); + +// NOTE: Insert ==================================================================================== +DQN_API template T * Dqn_FArray_Make (Dqn_FArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem); +DQN_API template T * Dqn_FArray_Add (Dqn_FArray *array, T const *items, Dqn_usize count); + +// NOTE: Modify ==================================================================================== +DQN_API template void Dqn_FArray_EraseRange(Dqn_FArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase); +DQN_API template void Dqn_FArray_Clear (Dqn_FArray *array); +#endif // !defined(DQN_NO_FARRAY) + +#if !defined(DQN_NO_SLICE) +// NOTE: [$SLIC] Dqn_Slice ========================================================================= +// A pointer and length container of data + +template struct Dqn_Slice +{ + T *data; + Dqn_usize size; + + T *begin() { return data; } + T *end () { return data + size; } + T const *begin() const { return data; } + T const *end () const { return data + size; } +}; + +template Dqn_Slice Dqn_Slice_Init (T* const data, Dqn_usize size); +template Dqn_Slice Dqn_Slice_Alloc(Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem); +#endif // !defined(DQN_NO_SLICE) + #if !defined(DQN_NO_DSMAP) // NOTE: [$DMAP] Dqn_DSMap ========================================================================= // A hash table configured using the presets recommended by Demitri Spanos @@ -295,38 +372,6 @@ DQN_API bool Dqn_DSMap_KeyEquals (Dqn_DS DQN_API bool operator== (Dqn_DSMapKey lhs, Dqn_DSMapKey rhs); #endif // !defined(DQN_NO_DSMAP) -#if !defined(DQN_NO_FARRAY) -// NOTE: [$FARR] Dqn_FArray ======================================================================== -template struct Dqn_FArray -{ - T data[N]; // Pointer to the start of the array items in the block of memory - Dqn_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; } -}; - -enum Dqn_FArrayErase -{ - Dqn_FArrayErase_Unstable, - Dqn_FArrayErase_Stable, -}; - -// NOTE: Setup ===================================================================================== -DQN_API template Dqn_FArray Dqn_FArray_Init (T const *array, Dqn_usize count); -DQN_API template bool Dqn_FArray_IsValid (Dqn_FArray const *array); - -// NOTE: Insert ==================================================================================== -DQN_API template T * Dqn_FArray_Make (Dqn_FArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem); -DQN_API template T * Dqn_FArray_Add (Dqn_FArray *array, T const *items, Dqn_usize count); - -// NOTE: Modify ==================================================================================== -DQN_API template void Dqn_FArray_EraseRange(Dqn_FArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_FArrayErase erase); -DQN_API template void Dqn_FArray_Clear (Dqn_FArray *array); -#endif // !defined(DQN_NO_FARRAY) - #if !defined(DQN_NO_LIST) // NOTE: [$LIST] Dqn_List ========================================================================== // @@ -384,6 +429,73 @@ template T * Dqn_List_Make (Dqn_List *list, Dqn_usize template T * Dqn_List_Add (Dqn_List *list, T const &value); #endif // !defined(DQN_NO_LIST) +// NOTE: [$CARR] Dqn_CArray ======================================================================== +template Dqn_usize Dqn_CArray_EraseRange(T* data, Dqn_usize *size, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase) +{ + Dqn_usize result = 0; + if (!data || !size || *size == 0 || count == 0) + return result; + + // NOTE: Caculate the end index of the erase range + Dqn_isize abs_count = DQN_ABS(count); + Dqn_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) { + Dqn_usize tmp = begin_index; + begin_index = end_index; + end_index = tmp; + } + + // NOTE: Ensure indexes are within valid bounds + begin_index = DQN_MIN(begin_index, *size); + end_index = DQN_MIN(end_index, *size - 1); + + // NOTE: Erase the items in the range [begin_index, one_past_end_index) + Dqn_usize one_past_end_index = end_index + 1; + Dqn_usize erase_count = one_past_end_index - begin_index; + if (erase_count) { + T *end = data + *size; + T *dest = data + begin_index; + if (erase == Dqn_ArrayErase_Stable) { + T *src = dest + erase_count; + DQN_MEMMOVE(dest, src, (end - src) * sizeof(T)); + } else { + T *src = end - erase_count; + DQN_MEMCPY(dest, src, (end - src) * sizeof(T)); + } + *size -= erase_count; + } + + result = erase_count; + return result; +} + +template T *Dqn_CArray_Make(T* data, Dqn_usize *size, Dqn_usize max, Dqn_usize count, Dqn_ZeroMem zero_mem) +{ + if (!data || !size || count == 0) + return nullptr; + + if (!DQN_CHECKF((*size + count) < max, "Array is out of memory")) + return nullptr; + + // TODO: Use placement new? Why doesn't this work? + T *result = data + *size; + *size += count; + if (zero_mem == Dqn_ZeroMem_Yes) + DQN_MEMSET(result, DQN_MEMSET_BYTE, sizeof(*result) * count); + return result; +} + #if !defined(DQN_NO_VARRAY) // NOTE: [$VARR] Dqn_VArray ======================================================================== DQN_API template Dqn_VArray Dqn_VArray_InitByteSize(Dqn_Arena *arena, Dqn_usize byte_size) @@ -431,51 +543,12 @@ DQN_API template T *Dqn_VArray_Add(Dqn_VArray *array, T const *i return result; } -DQN_API template void Dqn_VArray_EraseRange(Dqn_VArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_VArrayErase erase) +DQN_API template void Dqn_VArray_EraseRange(Dqn_VArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase) { - if (!Dqn_VArray_IsValid(array) || array->size == 0 || count == 0) + if (!Dqn_VArray_IsValid(array)) return; - - // NOTE: Caculate the end index of the erase range - Dqn_isize abs_count = DQN_ABS(count); - Dqn_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 = array->size - 1; - } - - // NOTE: Ensure begin_index < one_past_end_index - if (end_index < begin_index) { - Dqn_usize tmp = begin_index; - begin_index = end_index; - end_index = tmp; - } - - // NOTE: Ensure indexes are within valid bounds - begin_index = DQN_MIN(begin_index, array->size); - end_index = DQN_MIN(end_index, array->size - 1); - - // NOTE: Erase the items in the range [begin_index, one_past_end_index) - Dqn_usize one_past_end_index = end_index + 1; - Dqn_usize erase_count = one_past_end_index - begin_index; - if (erase_count) { - T *end = array->data + array->size; - T *dest = array->data + begin_index; - if (erase == Dqn_VArrayErase_Stable) { - T *src = dest + erase_count; - DQN_MEMMOVE(dest, src, (end - src) * sizeof(T)); - } else { - T *src = end - erase_count; - DQN_MEMCPY(dest, src, (end - src) * sizeof(T)); - } - array->size -= erase_count; - Dqn_MemBlock_Pop(array->block, erase_count * sizeof(T)); - } + Dqn_usize erase_count = Dqn_CArray_EraseRange(array->data, &array->size, begin_index, count, erase); + Dqn_MemBlock_Pop(array->block, erase_count * sizeof(T)); } DQN_API template void Dqn_VArray_Clear(Dqn_VArray *array) @@ -493,6 +566,128 @@ DQN_API template void Dqn_VArray_Reserve(Dqn_VArray *array, Dqn_ } #endif // !defined(DQN_NO_VARRAY) +#if !defined(DQN_NO_SARRAY) +// NOTE: [$FARR] Dqn_SArray ======================================================================== +DQN_API template Dqn_SArray Dqn_SArray_Init(Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem) +{ + Dqn_SArray result = {}; + if (!arena || !count) + return result; + + result.data = Dqn_Arena_NewArray(arena, T, size, zero_mem); + if (result.data) + result.max = size; + return result; +} +DQN_API template bool Dqn_SArray_IsValid(Dqn_SArray const *array) +{ + bool result = array && array->data && array->size <= array->max; + return result; +} + +DQN_API template T *Dqn_SArray_Make(Dqn_SArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem) +{ + if (!Dqn_SArray_IsValid(array)) + return nullptr; + T *result = Dqn_CArray_Make(array->data, &array->size, array->max, count, zero_mem); + return result; +} + +DQN_API template T *Dqn_SArray_AddArray(Dqn_SArray *array, T const *items, Dqn_usize count) +{ + T *result = Dqn_SArray_Make(array, count, Dqn_ZeroMem_No); + if (result) + DQN_MEMCPY(result, items, count * sizeof(T)); +} + +DQN_API template T *Dqn_SArray_Add(Dqn_SArray *array, T const &item) +{ + T *result = Dqn_SArray_AddArray(array, &item, 1); + return result; +} + +DQN_API template void Dqn_SArray_EraseRange(Dqn_SArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase) +{ + if (!Dqn_SArray_IsValid(array) || array->size == 0 || count == 0) + return; + Dqn_CArray_EraseRange(array->data, &array->size, being_index, count, erase); +} + +DQN_API template void Dqn_SArray_Clear(Dqn_SArray *array) +{ + if (array) + array->size = 0; +} +#endif // !defined(DQN_NO_SARRAY) + +#if !defined(DQN_NO_FARRAY) +// NOTE: [$FARR] Dqn_FArray ======================================================================== +DQN_API template Dqn_FArray Dqn_FArray_Init(T const *array, Dqn_usize count) +{ + Dqn_FArray result = {}; + bool added = Dqn_FArray_Add(&result, array, count); + DQN_ASSERT(added); + return result; +} +DQN_API template bool Dqn_FArray_IsValid(Dqn_FArray const *array) +{ + bool result = array && array->size <= DQN_ARRAY_UCOUNT(array->data); + return result; +} + +DQN_API template T *Dqn_FArray_Make(Dqn_FArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem) +{ + if (!Dqn_FArray_IsValid(array)) + return nullptr; + T *result = Dqn_CArray_Make(array->data, &array->size, N, count, zero_mem); + return result; +} + +DQN_API template T *Dqn_FArray_Add(Dqn_FArray *array, T const *items, Dqn_usize count) +{ + T *result = Dqn_FArray_Make(array, count, Dqn_ZeroMem_No); + if (result) + DQN_MEMCPY(result, items, count * sizeof(T)); + return result; +} + +DQN_API template void Dqn_FArray_EraseRange(Dqn_FArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase) +{ + if (!Dqn_FArray_IsValid(array) || array->size == 0 || count == 0) + return; + Dqn_CArray_EraseRange(array->data, &array->size, begin_index, count, erase); +} + +DQN_API template void Dqn_FArray_Clear(Dqn_FArray *array) +{ + if (array) + array->size = 0; +} +#endif // !defined(DQN_NO_FARRAY) + +#if !defined(DQN_NO_SLICE) +template Dqn_Slice Dqn_Slice_Init(T* const data, Dqn_usize size) +{ + Dqn_Slice result = {}; + if (data) { + result.data = data; + result.size = size; + } + return result; +} + +template Dqn_Slice Dqn_Slice_Alloc(Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem) +{ + Dqn_Slice result = {}; + if (!arena || size == 0) + return result; + result.data = Dqn_Arena_NewArray(arena, T, size, zero_mem); + if (result.data) + result.size = size; + return result; +} +#endif // !defined(DQN_NO_SLICE) + #if !defined(DQN_NO_DSMAP) // NOTE: [$DMAP] Dqn_DSMap ========================================================================= uint32_t const DQN_DS_MAP_DEFAULT_HASH_SEED = 0x8a1ced49; @@ -845,98 +1040,6 @@ DQN_API Dqn_DSMapKey Dqn_DSMap_KeyString8Copy(Dqn_DSMap const *map, Dqn_Alloc } #endif // !defined(DQN_NO_DSMAP) -#if !defined(DQN_NO_FARRAY) -// NOTE: [$FARR] Dqn_FArray ======================================================================== -DQN_API template Dqn_FArray Dqn_FArray_Init(T const *array, Dqn_usize count) -{ - Dqn_FArray result = {}; - bool added = Dqn_FArray_Add(&result, array, count); - DQN_ASSERT(added); - return result; -} -DQN_API template bool Dqn_FArray_IsValid(Dqn_FArray const *array) -{ - bool result = array && array->size <= DQN_ARRAY_UCOUNT(array->data); - return result; -} - -DQN_API template T *Dqn_FArray_Make(Dqn_FArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem) -{ - if (!Dqn_FArray_IsValid(array)) - return nullptr; - - if (!DQN_CHECKF((array->size + count) < DQN_ARRAY_UCOUNT(array->data), "Array is out of memory")) - return nullptr; - - // TODO: Use placement new? Why doesn't this work? - T *result = array->data + array->size; - array->size += count; - if (zero_mem == Dqn_ZeroMem_Yes) - DQN_MEMSET(result, DQN_MEMSET_BYTE, sizeof(*result) * count); - return result; -} - -DQN_API template T *Dqn_FArray_Add(Dqn_FArray *array, T const *items, Dqn_usize count) -{ - T *result = Dqn_FArray_Make(array, count, Dqn_ZeroMem_No); - if (result) - DQN_MEMCPY(result, items, count * sizeof(T)); - return result; -} - -DQN_API template void Dqn_FArray_EraseRange(Dqn_FArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_FArrayErase erase) -{ - if (!Dqn_FArray_IsValid(array) || array->size == 0 || count == 0) - return; - - // NOTE: Caculate the end index of the erase range - Dqn_isize abs_count = DQN_ABS(count); - Dqn_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 = array->size - 1; - } - - // NOTE: Ensure begin_index < one_past_end_index - if (end_index < begin_index) { - Dqn_usize tmp = begin_index; - begin_index = end_index; - end_index = tmp; - } - - // NOTE: Ensure indexes are within valid bounds - begin_index = DQN_MIN(begin_index, array->size); - end_index = DQN_MIN(end_index, array->size - 1); - - // NOTE: Erase the items in the range [begin_index, one_past_end_index) - Dqn_usize one_past_end_index = end_index + 1; - Dqn_usize erase_count = one_past_end_index - begin_index; - if (erase_count) { - T *end = array->data + array->size; - T *dest = array->data + begin_index; - if (erase == Dqn_FArrayErase_Stable) { - T *src = dest + erase_count; - DQN_MEMMOVE(dest, src, (end - src) * sizeof(T)); - } else { - T *src = end - erase_count; - DQN_MEMCPY(dest, src, (end - src) * sizeof(T)); - } - array->size -= erase_count; - } -} - -DQN_API template void Dqn_FArray_Clear(Dqn_FArray *array) -{ - if (array) - array->size = 0; -} -#endif // !defined(DQN_NO_FARRAY) - #if !defined(DQN_NO_LIST) // NOTE: [$LIST] Dqn_List ========================================================================== template DQN_API Dqn_List Dqn_List_Init(Dqn_Arena *arena, Dqn_usize chunk_size) diff --git a/dqn_debug.cpp b/dqn_debug.cpp index 363370f..7189ce1 100644 --- a/dqn_debug.cpp +++ b/dqn_debug.cpp @@ -146,22 +146,31 @@ DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame(Dqn_Arena *arena, Dqn return result; } -DQN_API Dqn_StackTraceFrames Dqn_StackTrace_GetFrames(Dqn_Arena *arena, uint16_t limit) +DQN_API Dqn_Slice Dqn_StackTrace_GetFrames(Dqn_Arena *arena, uint16_t limit) { - Dqn_StackTraceFrames result = {}; - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(arena); - Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(scratch.arena, limit); + Dqn_Slice result = {}; + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(arena); + Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(scratch.arena, limit); if (!walk.size) return result; - result.data = Dqn_Arena_NewArray(arena, Dqn_StackTraceFrame, walk.size, Dqn_ZeroMem_No); + Dqn_usize slice_index = 0; + result = Dqn_Slice_Alloc(arena, walk.size, Dqn_ZeroMem_No); for (Dqn_StackTraceWalkResultIterator it = {}; Dqn_StackTrace_WalkResultIterate(&it, &walk); ) { - result.data[result.size++] = Dqn_StackTrace_RawFrameToFrame(arena, it.raw_frame); + result.data[slice_index++] = Dqn_StackTrace_RawFrameToFrame(arena, it.raw_frame); } return result; } +DQN_API void Dqn_StackTrace_Print(uint16_t limit) +{ + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Slice stack_trace = Dqn_StackTrace_GetFrames(scratch.arena, limit); + for (Dqn_StackTraceFrame& frame : stack_trace) + Dqn_Print_ErrLnF("%.*s(%I64u): %.*s", DQN_STRING_FMT(frame.file_name), frame.line_number, DQN_STRING_FMT(frame.function_name)); +} + // NOTE: [$DEBG] Dqn_Debug ========================================================================= #if defined(DQN_LEAK_TRACING) DQN_API void Dqn_Debug_TrackAlloc_(Dqn_String8 stack_trace, void *ptr, Dqn_usize size, bool leak_permitted) @@ -315,146 +324,3 @@ DQN_API void Dqn_Debug_DumpLeaks() } } #endif // defined(DQN_LEAK_TRACING) - -// NOTE: [$LLOG] Dqn_Log ========================================================================== -DQN_API Dqn_String8 Dqn_Log_MakeString(Dqn_Allocator allocator, - bool colour, - Dqn_String8 type, - int log_type, - Dqn_CallSite call_site, - char const *fmt, - va_list args) -{ - Dqn_usize header_size_no_ansi_codes = 0; - Dqn_String8 header = {}; - { - DQN_LOCAL_PERSIST Dqn_usize max_type_length = 0; - max_type_length = DQN_MAX(max_type_length, type.size); - int type_padding = DQN_CAST(int)(max_type_length - type.size); - - Dqn_String8 colour_esc = {}; - Dqn_String8 bold_esc = {}; - Dqn_String8 reset_esc = {}; - if (colour) { - bold_esc = Dqn_Print_ESCBoldString; - reset_esc = Dqn_Print_ESCResetString; - switch (log_type) { - case Dqn_LogType_Debug: break; - case Dqn_LogType_Info: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Info); break; - case Dqn_LogType_Warning: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Warning); break; - case Dqn_LogType_Error: colour_esc = Dqn_Print_ESCColourFgU32String(Dqn_LogTypeColourU32_Error); break; - } - } - - Dqn_String8 file_name = Dqn_String8_FileNameFromPath(call_site.file); - Dqn_DateHMSTimeString const time = Dqn_Date_HMSLocalTimeStringNow(); - header = Dqn_String8_InitF(allocator, - "%.*s " // date - "%.*s " // hms - "%.*s" // colour - "%.*s" // bold - "%.*s" // type - "%*s" // type padding - "%.*s" // reset - " %.*s" // file name - ":%05u ", // line number - DQN_CAST(uint32_t)time.date_size - 2, time.date + 2, // date - DQN_CAST(uint32_t)time.hms_size, time.hms, // hms - DQN_CAST(uint32_t)colour_esc.size, colour_esc.data, // colour - DQN_CAST(uint32_t)bold_esc.size, bold_esc.data, // bold - DQN_CAST(uint32_t)type.size, type.data, // type - DQN_CAST(uint32_t)type_padding, "", // type padding - DQN_CAST(uint32_t)reset_esc.size, reset_esc.data, // reset - DQN_CAST(uint32_t)file_name.size, file_name.data, // file name - call_site.line); // line number - header_size_no_ansi_codes = header.size - colour_esc.size - Dqn_Print_ESCResetString.size; - } - - // NOTE: Header padding ======================================================================== - Dqn_usize header_padding = 0; - { - DQN_LOCAL_PERSIST Dqn_usize max_header_length = 0; - max_header_length = DQN_MAX(max_header_length, header_size_no_ansi_codes); - header_padding = max_header_length - header_size_no_ansi_codes; - } - - // NOTE: Construct final log =================================================================== - Dqn_String8 user_msg = Dqn_String8_InitFV(allocator, fmt, args); - Dqn_String8 result = Dqn_String8_Allocate(allocator, header.size + header_padding + user_msg.size, Dqn_ZeroMem_No); - DQN_MEMCPY(result.data, header.data, header.size); - DQN_MEMSET(result.data + header.size, ' ', header_padding); - DQN_MEMCPY(result.data + header.size + header_padding, user_msg.data, user_msg.size); - return result; -} - -DQN_FILE_SCOPE void Dqn_Log_FVDefault_(Dqn_String8 type, int log_type, void *user_data, Dqn_CallSite call_site, char const *fmt, va_list args) -{ - Dqn_Library *lib = g_dqn_library; - (void)log_type; - (void)user_data; - - // NOTE: Open log file for appending if requested ========================== - Dqn_TicketMutex_Begin(&lib->log_file_mutex); - if (lib->log_to_file && !lib->log_file.handle && lib->log_file.error_size == 0) { - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_String8 log_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/dqn.log", DQN_STRING_FMT(lib->exe_dir)); - lib->log_file = Dqn_Fs_OpenFile(log_path, Dqn_FsFileOpen_CreateAlways, Dqn_FsFileAccess_AppendOnly); - } - Dqn_TicketMutex_End(&lib->log_file_mutex); - - // NOTE: Generate the log header =========================================== - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_String8 log_line = Dqn_Log_MakeString(scratch.allocator, - !lib->log_no_colour, - type, - log_type, - call_site, - fmt, - args); - - // NOTE: Print log ========================================================= - Dqn_Print_StdLn(Dqn_PrintStd_Out, log_line); - - Dqn_TicketMutex_Begin(&lib->log_file_mutex); - Dqn_Fs_WriteFile(&lib->log_file, log_line); - Dqn_Fs_WriteFile(&lib->log_file, DQN_STRING8("\n")); - Dqn_TicketMutex_End(&lib->log_file_mutex); -} - -DQN_API void Dqn_Log_FVCallSite(Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, va_list args) -{ - Dqn_LogProc *logging_function = g_dqn_library->log_callback ? g_dqn_library->log_callback : Dqn_Log_FVDefault_; - logging_function(type, -1 /*log_type*/, g_dqn_library->log_user_data, call_site, fmt, args); -} - -DQN_API void Dqn_Log_FCallSite(Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_Log_FVCallSite(type, call_site, fmt, args); - va_end(args); -} - -DQN_API void Dqn_Log_TypeFVCallSite(Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, va_list args) -{ - Dqn_String8 type_string = DQN_STRING8("DQN-BAD-LOG-TYPE"); - switch (type) { - case Dqn_LogType_Error: type_string = DQN_STRING8("ERROR"); break; - case Dqn_LogType_Info: type_string = DQN_STRING8("INFO"); break; - case Dqn_LogType_Warning: type_string = DQN_STRING8("WARN"); break; - case Dqn_LogType_Debug: type_string = DQN_STRING8("DEBUG"); break; - case Dqn_LogType_Count: type_string = DQN_STRING8("BADXX"); break; - } - - Dqn_LogProc *logging_function = g_dqn_library->log_callback ? g_dqn_library->log_callback : Dqn_Log_FVDefault_; - logging_function(type_string, type /*log_type*/, g_dqn_library->log_user_data, call_site, fmt, args); -} - -DQN_API void Dqn_Log_TypeFCallSite(Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_Log_TypeFVCallSite(type, call_site, fmt, args); - va_end(args); -} - diff --git a/dqn_debug.h b/dqn_debug.h index 5bd94e5..9bab413 100644 --- a/dqn_debug.h +++ b/dqn_debug.h @@ -1,30 +1,3 @@ -// NOTE: Debug Macros ============================================================================== -#if !defined(DQN_DEBUG_BREAK) - #if defined(NDEBUG) - #define DQN_DEBUG_BREAK - #else - #if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) - #define DQN_DEBUG_BREAK __debugbreak() - #elif defined(DQN_COMPILER_CLANG) - #define DQN_DEBUG_BREAK __builtin_debugtrap() - #elif defined(DQN_COMPILER_CLANG) || defined(DQN_COMPILER_GCC) - #include - #define DQN_DEBUG_BREAK raise(SIGTRAP) - #elif - #error "Unhandled compiler" - #endif - #endif -#endif - -#if !defined(DQN_MEMSET_BYTE) - #define DQN_MEMSET_BYTE 0 -#endif - -// TODO(doyle): Use our new stacktrace library -#if !defined(DQN_DUMP_STACK_TRACE) - #define DQN_DUMP_STACK_TRACE -#endif - #if !defined(DQN_ASAN_POISON) #define DQN_ASAN_POISON 0 #endif @@ -115,25 +88,11 @@ struct Dqn_StackTraceWalkResultIterator uint16_t index; }; -struct Dqn_StackTraceFrames -{ - Dqn_StackTraceFrame *data; - uint16_t size; -}; - -DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk (Dqn_Arena *arena, uint16_t limit); -DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator *it, Dqn_StackTraceWalkResult *walk); -DQN_API Dqn_StackTraceFrames Dqn_StackTrace_GetFrames (Dqn_Arena *arena, uint16_t limit); -DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame (Dqn_Arena *arena, Dqn_StackTraceRawFrame raw_frame); - -// NOTE: [$CALL] Dqn_CallSite ====================================================================== -struct Dqn_CallSite -{ - Dqn_String8 file; - Dqn_String8 function; - unsigned int line; -}; -#define DQN_CALL_SITE Dqn_CallSite{DQN_STRING8(__FILE__), DQN_STRING8(__func__), __LINE__} +DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk (Dqn_Arena *arena, uint16_t limit); +DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator *it, Dqn_StackTraceWalkResult *walk); +DQN_API Dqn_Slice Dqn_StackTrace_GetFrames (Dqn_Arena *arena, uint16_t limit); +DQN_API void Dqn_StackTrace_Print (uint16_t limit); +DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame (Dqn_Arena *arena, Dqn_StackTraceRawFrame raw_frame); // NOTE: [$DEBG] Dqn_Debug ========================================================================= enum Dqn_AllocRecordFlag @@ -171,53 +130,3 @@ DQN_API void Dqn_Debug_DumpLeaks(); #define Dqn_Debug_TrackDealloc(...) #define Dqn_Debug_DumpLeaks(...) #endif - -// NOTE: [$LLOG] Dqn_Log ========================================================================== -// NOTE: API -// @proc Dqn_LogProc -// @desc The logging procedure of the library. Users can override the default -// logging function by setting the logging function pointer in Dqn_Library. -// This function will be invoked every time a log is recorded using the -// following functions. -// -// @param[in] log_type This value is one of the Dqn_LogType values if the log -// was generated from one of the default categories. -1 if the log is not from -// one of the default categories. - -enum Dqn_LogType -{ - Dqn_LogType_Debug, - Dqn_LogType_Info, - Dqn_LogType_Warning, - Dqn_LogType_Error, - Dqn_LogType_Count, -}; - -/// RGBA -#define Dqn_LogTypeColourU32_Info 0x00'87'ff'ff // Blue -#define Dqn_LogTypeColourU32_Warning 0xff'ff'00'ff // Yellow -#define Dqn_LogTypeColourU32_Error 0xff'00'00'ff // Red - -typedef void Dqn_LogProc(Dqn_String8 type, int log_type, void *user_data, Dqn_CallSite call_site, char const *fmt, va_list va); - -#define Dqn_Log_DebugF(fmt, ...) Dqn_Log_TypeFCallSite(Dqn_LogType_Debug, DQN_CALL_SITE, fmt, ## __VA_ARGS__) -#define Dqn_Log_InfoF(fmt, ...) Dqn_Log_TypeFCallSite(Dqn_LogType_Info, DQN_CALL_SITE, fmt, ## __VA_ARGS__) -#define Dqn_Log_WarningF(fmt, ...) Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, DQN_CALL_SITE, fmt, ## __VA_ARGS__) -#define Dqn_Log_ErrorF(fmt, ...) Dqn_Log_TypeFCallSite(Dqn_LogType_Error, DQN_CALL_SITE, fmt, ## __VA_ARGS__) - -#define Dqn_Log_DebugFV(fmt, args) Dqn_Log_TypeFVCallSite(Dqn_LogType_Debug, DQN_CALL_SITE, fmt, args) -#define Dqn_Log_InfoFV(fmt, args) Dqn_Log_TypeFVCallSite(Dqn_LogType_Info, DQN_CALL_SITE, fmt, args) -#define Dqn_Log_WarningFV(fmt, args) Dqn_Log_TypeFVCallSite(Dqn_LogType_Warning, DQN_CALL_SITE, fmt, args) -#define Dqn_Log_ErrorFV(fmt, args) Dqn_Log_TypeFVCallSite(Dqn_LogType_Error, DQN_CALL_SITE, fmt, args) - -#define Dqn_Log_TypeFV(type, fmt, args) Dqn_Log_TypeFVCallSite(type, DQN_CALL_SITE, fmt, args) -#define Dqn_Log_TypeF(type, fmt, ...) Dqn_Log_TypeFCallSite(type, DQN_CALL_SITE, fmt, ## __VA_ARGS__) - -#define Dqn_Log_FV(type, fmt, args) Dqn_Log_FVCallSite(type, DQN_CALL_SITE, fmt, args) -#define Dqn_Log_F(type, fmt, ...) Dqn_Log_FCallSite(type, DQN_CALL_SITE, fmt, ## __VA_ARGS__) - -DQN_API Dqn_String8 Dqn_Log_MakeString (Dqn_Allocator allocator, bool colour, Dqn_String8 type, int log_type, Dqn_CallSite call_site, char const *fmt, va_list args); -DQN_API void Dqn_Log_TypeFVCallSite(Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, va_list va); -DQN_API void Dqn_Log_TypeFCallSite (Dqn_LogType type, Dqn_CallSite call_site, char const *fmt, ...); -DQN_API void Dqn_Log_FVCallSite (Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, va_list va); -DQN_API void Dqn_Log_FCallSite (Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, ...); diff --git a/dqn_memory.cpp b/dqn_memory.cpp index fb83bae..c984d65 100644 --- a/dqn_memory.cpp +++ b/dqn_memory.cpp @@ -1,24 +1,3 @@ -// NOTE: [$ALLO] Dqn_Allocator ===================================================================== -DQN_API void *Dqn_Allocator_Alloc(Dqn_Allocator allocator, size_t size, uint8_t align, Dqn_ZeroMem zero_mem) -{ - void *result = NULL; - if (allocator.alloc) { - result = allocator.alloc(size, align, zero_mem, allocator.user_context); - } else { - result = DQN_ALLOC(size); - } - return result; -} - -DQN_API void Dqn_Allocator_Dealloc(Dqn_Allocator allocator, void *ptr, size_t size) -{ - if (allocator.dealloc) { - allocator.dealloc(ptr, size, allocator.user_context); - } else { - DQN_DEALLOC(ptr, size); - } -} - // NOTE: [$VMEM] Dqn_VMem ========================================================================== DQN_FILE_SCOPE uint32_t Dqn_VMem_ConvertPageToOSFlags_(uint32_t protect) { diff --git a/dqn_memory.h b/dqn_memory.h index 778e7f9..a86cd81 100644 --- a/dqn_memory.h +++ b/dqn_memory.h @@ -1,22 +1,3 @@ -// NOTE: [$ALLO] Dqn_Allocator ===================================================================== -typedef void *Dqn_Allocator_AllocProc(size_t size, uint8_t align, Dqn_ZeroMem zero_mem, void *user_context); -typedef void Dqn_Allocator_DeallocProc(void *ptr, size_t size, void *user_context); - -struct Dqn_Allocator -{ - void *user_context; // User assigned pointer that is passed into the allocator functions - Dqn_Allocator_AllocProc *alloc; // Memory allocating routine - Dqn_Allocator_DeallocProc *dealloc; // Memory deallocating routine -}; - -// NOTE: Macros ==================================================================================== -#define Dqn_Allocator_NewArray(allocator, Type, count, zero_mem) (Type *)Dqn_Allocator_Alloc(allocator, sizeof(Type) * count, alignof(Type), zero_mem) -#define Dqn_Allocator_New(allocator, Type, zero_mem) (Type *)Dqn_Allocator_Alloc(allocator, sizeof(Type), alignof(Type), zero_mem) - -// NOTE: API ======================================================================================= -void *Dqn_Allocator_Alloc (Dqn_Allocator allocator, size_t size, uint8_t align, Dqn_ZeroMem zero_mem); -void Dqn_Allocator_Dealloc(Dqn_Allocator allocator, void *ptr, size_t size); - // NOTE: [$VMEM] Dqn_VMem ========================================================================== enum Dqn_VMemCommit {