From a844d2b992bc30a465cb439203bd5aa1ecf286f6 Mon Sep 17 00:00:00 2001 From: doylet Date: Fri, 14 Feb 2025 00:27:42 +1100 Subject: [PATCH] Get latest DQN lib from side projects --- Standalone/dqn_cpp_file.h | 248 ++-- Standalone/dqn_keccak.h | 472 +++---- Standalone/dqn_utest.h | 156 +-- build.bat | 2 +- dqn.cpp | 38 +- dqn.h | 237 ++-- dqn_allocator.cpp | 544 ++++---- dqn_allocator.h | 289 ++-- dqn_avx512f.cpp | 126 +- dqn_avx512f.h | 18 +- dqn_base.cpp | 885 ++++++------ dqn_base.h | 1013 ++++++++------ dqn_cgen.cpp | 1195 ++++++++-------- dqn_cgen.h | 194 +-- dqn_containers.cpp | 1360 +++++++++++++++++- dqn_containers.h | 1739 ++++------------------- dqn_cppbuild.h | 204 --- dqn_debug.cpp | 381 ++++-- dqn_debug.h | 106 +- dqn_docs.cpp | 609 ++++---- dqn_external.cpp | 4 +- dqn_external.h | 34 +- dqn_hash.cpp | 78 +- dqn_hash.h | 38 +- dqn_helpers.cpp | 1241 +++++++++-------- dqn_helpers.h | 693 +++++----- dqn_json.cpp | 288 ++-- dqn_json.h | 118 +- dqn_math.cpp | 1154 ++++++++-------- dqn_math.h | 618 +++++---- dqn_os.cpp | 367 ++--- dqn_os.h | 499 +++---- dqn_os_posix.cpp | 786 ++++++----- dqn_os_posix.h | 21 + dqn_os_win32.cpp | 1300 ++++++++++-------- dqn_os_win32.h | 48 +- dqn_string.cpp | 916 +++++++------ dqn_string.h | 574 ++++---- dqn_tls.cpp | 122 +- dqn_tls.h | 75 +- dqn_type_info.cpp | 10 +- dqn_type_info.h | 58 +- dqn_unit_tests.cpp | 2741 ++++++++++++++++++------------------- dqn_unit_tests_main.cpp | 12 + dqn_win32.h | 91 +- 45 files changed, 11343 insertions(+), 10359 deletions(-) delete mode 100644 dqn_cppbuild.h create mode 100644 dqn_os_posix.h create mode 100644 dqn_unit_tests_main.cpp diff --git a/Standalone/dqn_cpp_file.h b/Standalone/dqn_cpp_file.h index 15efdc2..c794ce7 100644 --- a/Standalone/dqn_cpp_file.h +++ b/Standalone/dqn_cpp_file.h @@ -10,257 +10,257 @@ // \$$$$$$ |$$ | $$ | $$ | $$$$$$\ $$$$$$$$\ $$$$$$$$\ // \______/ \__| \__| \__| \______|\________|\________| // -// dqn_cpp_file.h -- Functions to emit C++ formatted code +// dn_cpp_file.h -- Functions to emit C++ formatted code // //////////////////////////////////////////////////////////////////////////////// */ -#if !defined(DQN_CPP_FILE_H) -#define DQN_CPP_FILE_H +#if !defined(DN_CPP_FILE_H) +#define DN_CPP_FILE_H #include /// printf, fputc #include /// va_list... #include /// assert -typedef struct Dqn_CppFile { ///< Maintains state for printing C++ style formatted files +typedef struct DN_CppFile { ///< Maintains state for printing C++ style formatted files FILE *file; ///< (Write) File to print to int indent; ///< Current indent level of the printer int space_per_indent; ///< (Write) Number of spaces per indent unsigned char if_chain[256]; /// unsigned char if_chain_size; /// -} Dqn_CppFile; +} DN_CppFile; -#define Dqn_CppSpacePerIndent(cpp) ((cpp) && (cpp)->space_per_indent) ? ((cpp)->space_per_indent) : 4 +#define DN_CppSpacePerIndent(cpp) ((cpp) && (cpp)->space_per_indent) ? ((cpp)->space_per_indent) : 4 /// Print the format string indented and terminate the string with a new-line. -void Dqn_CppLineV(Dqn_CppFile *cpp, char const *fmt, va_list args); -void Dqn_CppLine(Dqn_CppFile *cpp, char const *fmt, ...); +void DN_CppLineV(DN_CppFile *cpp, char const *fmt, va_list args); +void DN_CppLine(DN_CppFile *cpp, char const *fmt, ...); /// Print the format string indented -void Dqn_CppPrintV(Dqn_CppFile *cpp, char const *fmt, va_list args); -void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...); +void DN_CppPrintV(DN_CppFile *cpp, char const *fmt, va_list args); +void DN_CppPrint(DN_CppFile *cpp, char const *fmt, ...); /// Print the format string -#define Dqn_CppAppend(cpp, fmt, ...) fprintf((cpp)->file, fmt, ##__VA_ARGS__) -#define Dqn_CppAppendV(cpp, fmt, args) vfprintf((cpp)->file, fmt, args) +#define DN_CppAppend(cpp, fmt, ...) fprintf((cpp)->file, fmt, ##__VA_ARGS__) +#define DN_CppAppendV(cpp, fmt, args) vfprintf((cpp)->file, fmt, args) /// End the current line, useful after CppPrint and CppAppend -#define Dqn_CppNewLine(cpp) fputc('\n', (cpp)->file) +#define DN_CppNewLine(cpp) fputc('\n', (cpp)->file) /// Manually modify the indent level -#define Dqn_CppIndent(cpp) (cpp)->indent++ -#define Dqn_CppUnindent(cpp) (cpp)->indent--; assert((cpp)->indent >= 0) +#define DN_CppIndent(cpp) (cpp)->indent++ +#define DN_CppUnindent(cpp) (cpp)->indent--; assert((cpp)->indent >= 0) /// Block scope functions that execute a function on entry and exit of the /// scope by exploiting the comma operator and a for loop. /// /// @code -/// Dqn_CppEnumBlock(cpp, "abc") { +/// DN_CppEnumBlock(cpp, "abc") { /// printf("Hello world!"); /// } /// /// // Is equivalent to /// -/// Dqn_CppBeginBlock(cpp, "abc"); +/// DN_CppBeginBlock(cpp, "abc"); /// printf("Hello world!"); -/// Dqn_CppEndEnumBlock(cpp); +/// DN_CppEndEnumBlock(cpp); /// @endcode -#define Dqn_CppEnumBlock(cpp, fmt, ...) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginEnumBlock(cpp, fmt, ##__VA_ARGS__), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndEnumBlock(cpp), false)) +#define DN_CppEnumBlock(cpp, fmt, ...) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginEnumBlock(cpp, fmt, ##__VA_ARGS__), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndEnumBlock(cpp), false)) -#define Dqn_CppForBlock(cpp, fmt, ...) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginForBlock(cpp, fmt, ##__VA_ARGS__), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndForBlock(cpp), false)) +#define DN_CppForBlock(cpp, fmt, ...) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginForBlock(cpp, fmt, ##__VA_ARGS__), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndForBlock(cpp), false)) -#define Dqn_CppWhileBlock(cpp, fmt, ...) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginWhileBlock(cpp, fmt, ##__VA_ARGS__), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndWhileBlock(cpp), false)) +#define DN_CppWhileBlock(cpp, fmt, ...) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginWhileBlock(cpp, fmt, ##__VA_ARGS__), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndWhileBlock(cpp), false)) -#define Dqn_CppIfOrElseIfBlock(cpp, fmt, ...) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginIfOrElseIfBlock(cpp, fmt, ##__VA_ARGS__), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndIfOrElseIfBlock(cpp), false)) +#define DN_CppIfOrElseIfBlock(cpp, fmt, ...) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginIfOrElseIfBlock(cpp, fmt, ##__VA_ARGS__), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndIfOrElseIfBlock(cpp), false)) -#define Dqn_CppElseBlock(cpp) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginElseBlock(cpp), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndElseBlock(cpp), false)) +#define DN_CppElseBlock(cpp) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginElseBlock(cpp), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndElseBlock(cpp), false)) -#define Dqn_CppFuncBlock(cpp, fmt, ...) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginFuncBlock(cpp, fmt, ##__VA_ARGS__), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndFuncBlock(cpp), false)) +#define DN_CppFuncBlock(cpp, fmt, ...) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginFuncBlock(cpp, fmt, ##__VA_ARGS__), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndFuncBlock(cpp), false)) -#define Dqn_CppStructBlock(cpp, fmt, ...) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginStructBlock(cpp, fmt, ##__VA_ARGS__), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndStructBlock(cpp), false)) +#define DN_CppStructBlock(cpp, fmt, ...) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginStructBlock(cpp, fmt, ##__VA_ARGS__), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndStructBlock(cpp), false)) -#define Dqn_CppSwitchBlock(cpp, fmt, ...) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginSwitchBlock(cpp, fmt, ##__VA_ARGS__), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndSwitchBlock(cpp), false)) +#define DN_CppSwitchBlock(cpp, fmt, ...) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginSwitchBlock(cpp, fmt, ##__VA_ARGS__), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndSwitchBlock(cpp), false)) -#define Dqn_CppBlock(cpp, ending, fmt, ...) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ - (Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndBlock(cpp, ending), false)) +#define DN_CppBlock(cpp, ending, fmt, ...) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ + (DN_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndBlock(cpp, ending), false)) -#define Dqn_CppIfChain(cpp) \ - for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppBeginIfChain(cpp), true); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ - DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndIfChain(cpp), false)) +#define DN_CppIfChain(cpp) \ + for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppBeginIfChain(cpp), true); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__); \ + DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndIfChain(cpp), false)) /// Print the format string followed by a "{" and enter a new line whilst /// increasing the indent level after the brace. -void Dqn_CppBeginBlock (Dqn_CppFile *cpp, bool append, char const *fmt, ...); -void Dqn_CppBeginBlockV(Dqn_CppFile *cpp, bool append, char const *fmt, va_list args); -void Dqn_CppEndBlock (Dqn_CppFile *cpp, char const *ending); +void DN_CppBeginBlock (DN_CppFile *cpp, bool append, char const *fmt, ...); +void DN_CppBeginBlockV(DN_CppFile *cpp, bool append, char const *fmt, va_list args); +void DN_CppEndBlock (DN_CppFile *cpp, char const *ending); /// Begin/End a block, specifically for the following language constructs. -#define Dqn_CppBeginEnumBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "enum " fmt, ##__VA_ARGS__) -#define Dqn_CppEndEnumBlock(cpp) Dqn_CppEndBlock(cpp, ";\n") +#define DN_CppBeginEnumBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "enum " fmt, ##__VA_ARGS__) +#define DN_CppEndEnumBlock(cpp) DN_CppEndBlock(cpp, ";\n") -#define Dqn_CppBeginWhileBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "while (" fmt ")", ##__VA_ARGS__) -#define Dqn_CppEndWhileBlock(cpp) Dqn_CppEndBlock(cpp, "\n") +#define DN_CppBeginWhileBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "while (" fmt ")", ##__VA_ARGS__) +#define DN_CppEndWhileBlock(cpp) DN_CppEndBlock(cpp, "\n") -#define Dqn_CppBeginForBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "for (" fmt ")", ##__VA_ARGS__) -#define Dqn_CppEndForBlock(cpp) Dqn_CppEndBlock(cpp, "\n") +#define DN_CppBeginForBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "for (" fmt ")", ##__VA_ARGS__) +#define DN_CppEndForBlock(cpp) DN_CppEndBlock(cpp, "\n") -#define Dqn_CppBeginFuncBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__) -#define Dqn_CppEndFuncBlock(cpp) Dqn_CppEndBlock(cpp, "\n") +#define DN_CppBeginFuncBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__) +#define DN_CppEndFuncBlock(cpp) DN_CppEndBlock(cpp, "\n") -#define Dqn_CppBeginStructBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "struct " fmt, ##__VA_ARGS__) -#define Dqn_CppEndStructBlock(cpp) Dqn_CppEndBlock(cpp, ";\n") +#define DN_CppBeginStructBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "struct " fmt, ##__VA_ARGS__) +#define DN_CppEndStructBlock(cpp) DN_CppEndBlock(cpp, ";\n") -#define Dqn_CppBeginSwitchBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "switch (" fmt ")", ##__VA_ARGS__) -#define Dqn_CppEndSwitchBlock(cpp) Dqn_CppEndBlock(cpp, "\n") +#define DN_CppBeginSwitchBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "switch (" fmt ")", ##__VA_ARGS__) +#define DN_CppEndSwitchBlock(cpp) DN_CppEndBlock(cpp, "\n") -void Dqn_CppBeginIfOrElseIfBlock (Dqn_CppFile *cpp, char const *fmt, ...); -#define Dqn_CppEndIfOrElseIfBlock(cpp) Dqn_CppEndBlock(cpp, "") +void DN_CppBeginIfOrElseIfBlock (DN_CppFile *cpp, char const *fmt, ...); +#define DN_CppEndIfOrElseIfBlock(cpp) DN_CppEndBlock(cpp, "") -void Dqn_CppBeginElseBlock (Dqn_CppFile *cpp); -void Dqn_CppEndElseBlock (Dqn_CppFile *cpp); +void DN_CppBeginElseBlock (DN_CppFile *cpp); +void DN_CppEndElseBlock (DN_CppFile *cpp); -#define DQN_CPP_TOKEN_PASTE2_(x, y) x ## y -#define DQN_CPP_TOKEN_PASTE_(x, y) DQN_CPP_TOKEN_PASTE2_(x, y) -#endif // DQN_CPP_FILE_H +#define DN_CPP_TOKEN_PASTE2_(x, y) x ## y +#define DN_CPP_TOKEN_PASTE_(x, y) DN_CPP_TOKEN_PASTE2_(x, y) +#endif // DN_CPP_FILE_H -#if defined(DQN_CPP_FILE_IMPLEMENTATION) -void Dqn_CppLineV(Dqn_CppFile *cpp, char const *fmt, va_list args) +#if defined(DN_CPP_FILE_IMPLEMENTATION) +void DN_CppLineV(DN_CppFile *cpp, char const *fmt, va_list args) { - Dqn_CppPrintV(cpp, fmt, args); - Dqn_CppNewLine(cpp); + DN_CppPrintV(cpp, fmt, args); + DN_CppNewLine(cpp); } -void Dqn_CppLine(Dqn_CppFile *cpp, char const *fmt, ...) +void DN_CppLine(DN_CppFile *cpp, char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_CppLineV(cpp, fmt, args); + DN_CppLineV(cpp, fmt, args); va_end(args); } -void Dqn_CppPrintV(Dqn_CppFile *cpp, char const *fmt, va_list args) +void DN_CppPrintV(DN_CppFile *cpp, char const *fmt, va_list args) { - int space_per_indent = Dqn_CppSpacePerIndent(cpp); + int space_per_indent = DN_CppSpacePerIndent(cpp); int spaces = fmt ? (cpp->indent * space_per_indent) : 0; fprintf(cpp->file, "%*s", spaces, ""); vfprintf(cpp->file, fmt, args); } -void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...) +void DN_CppPrint(DN_CppFile *cpp, char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_CppPrintV(cpp, fmt, args); + DN_CppPrintV(cpp, fmt, args); va_end(args); } -void Dqn_CppBeginBlock(Dqn_CppFile *cpp, bool append, char const *fmt, ...) +void DN_CppBeginBlock(DN_CppFile *cpp, bool append, char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_CppBeginBlockV(cpp, append, fmt, args); + DN_CppBeginBlockV(cpp, append, fmt, args); va_end(args); } -void Dqn_CppBeginBlockV(Dqn_CppFile *cpp, bool append, char const *fmt, va_list args) +void DN_CppBeginBlockV(DN_CppFile *cpp, bool append, char const *fmt, va_list args) { if (append) - Dqn_CppAppendV(cpp, fmt, args); + DN_CppAppendV(cpp, fmt, args); else - Dqn_CppPrintV(cpp, fmt, args); + DN_CppPrintV(cpp, fmt, args); bool empty_fmt = fmt == nullptr || strlen(fmt) == 0; - Dqn_CppAppend(cpp, "%s{\n", empty_fmt ? "" : " "); - Dqn_CppIndent(cpp); + DN_CppAppend(cpp, "%s{\n", empty_fmt ? "" : " "); + DN_CppIndent(cpp); } -void Dqn_CppEndBlock(Dqn_CppFile *cpp, char const *ending) +void DN_CppEndBlock(DN_CppFile *cpp, char const *ending) { - Dqn_CppUnindent(cpp); - Dqn_CppPrint(cpp, "}%s", ending); + DN_CppUnindent(cpp); + DN_CppPrint(cpp, "}%s", ending); } -void Dqn_CppBeginIfOrElseIfBlock(Dqn_CppFile *cpp, char const *fmt, ...) +void DN_CppBeginIfOrElseIfBlock(DN_CppFile *cpp, char const *fmt, ...) { va_list args; va_start(args, fmt); assert(cpp->if_chain_size); if (cpp->if_chain[cpp->if_chain_size - 1] == 0) - Dqn_CppPrint(cpp, "if"); + DN_CppPrint(cpp, "if"); else - Dqn_CppAppend(cpp, " else if"); + DN_CppAppend(cpp, " else if"); - Dqn_CppAppend(cpp, " ("); - Dqn_CppAppendV(cpp, fmt, args); - Dqn_CppAppend(cpp, ") {\n"); - Dqn_CppIndent(cpp); + DN_CppAppend(cpp, " ("); + DN_CppAppendV(cpp, fmt, args); + DN_CppAppend(cpp, ") {\n"); + DN_CppIndent(cpp); va_end(args); cpp->if_chain[cpp->if_chain_size - 1]++; } -void Dqn_CppBeginElseBlock(Dqn_CppFile *cpp) +void DN_CppBeginElseBlock(DN_CppFile *cpp) { assert(cpp->if_chain_size); if (cpp->if_chain[cpp->if_chain_size - 1] >= 1) - Dqn_CppBeginBlock(cpp, true /*append*/, " else"); + DN_CppBeginBlock(cpp, true /*append*/, " else"); } -void Dqn_CppEndElseBlock(Dqn_CppFile *cpp) +void DN_CppEndElseBlock(DN_CppFile *cpp) { if (cpp->if_chain[cpp->if_chain_size - 1] >= 1) - Dqn_CppEndBlock(cpp, ""); + DN_CppEndBlock(cpp, ""); } -void Dqn_CppBeginIfChain(Dqn_CppFile *cpp) +void DN_CppBeginIfChain(DN_CppFile *cpp) { assert(cpp->if_chain_size < sizeof(cpp->if_chain)/sizeof(cpp->if_chain[0])); cpp->if_chain_size++; } -void Dqn_CppEndIfChain(Dqn_CppFile *cpp) +void DN_CppEndIfChain(DN_CppFile *cpp) { assert(cpp->if_chain_size); if (cpp->if_chain[cpp->if_chain_size - 1] >= 1) { - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); } cpp->if_chain[cpp->if_chain_size - 1] = 0; cpp->if_chain_size--; } -#endif // DQN_CPP_FILE_IMPLEMENTATION +#endif // DN_CPP_FILE_IMPLEMENTATION diff --git a/Standalone/dqn_keccak.h b/Standalone/dqn_keccak.h index 7d854fe..b18d62f 100644 --- a/Standalone/dqn_keccak.h +++ b/Standalone/dqn_keccak.h @@ -1,5 +1,5 @@ -#if !defined(DQN_KECCAK_H) -#define DQN_KECCAK_H +#if !defined(DN_KECCAK_H) +#define DN_KECCAK_H /* //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -13,7 +13,7 @@ // $$ | \$$\ $$$$$$$$\ \$$$$$$ |\$$$$$$ |$$ | $$ |$$ | \$$\ // \__| \__|\________| \______/ \______/ \__| \__|\__| \__| // -// dqn_keccak.h -- FIPS202 SHA3 + non-finalized SHA3 (aka. Keccak) hashing algorithms +// dn_keccak.h -- FIPS202 SHA3 + non-finalized SHA3 (aka. Keccak) hashing algorithms // //////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -65,31 +65,31 @@ // - Define this in one and only one C++ file to enable the implementation // code of the header file. // -// #define DQN_KECCAK_IMPLEMENTATION +// #define DN_KECCAK_IMPLEMENTATION // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -#if !defined(DQN_KECCAK_MEMCPY) +#if !defined(DN_KECCAK_MEMCPY) #include - #define DQN_KECCAK_MEMCPY(dest, src, count) memcpy(dest, src, count) + #define DN_KECCAK_MEMCPY(dest, src, count) memcpy(dest, src, count) #endif -#if !defined(DQN_KECCAK_MEMCMP) +#if !defined(DN_KECCAK_MEMCMP) #include - #define DQN_KECCAK_MEMCMP(dest, src, count) memcmp(dest, src, count) + #define DN_KECCAK_MEMCMP(dest, src, count) memcmp(dest, src, count) #endif -#if !defined(DQN_KECCAK_MEMSET) +#if !defined(DN_KECCAK_MEMSET) #include - #define DQN_KECCAK_MEMSET(dest, byte, count) memset(dest, byte, count) + #define DN_KECCAK_MEMSET(dest, byte, count) memset(dest, byte, count) #endif -#if !defined(DQN_KECCAK_ASSERT) +#if !defined(DN_KECCAK_ASSERT) #if defined(NDEBUG) - #define DQN_KECCAK_ASSERT(expr) + #define DN_KECCAK_ASSERT(expr) #else - #define DQN_KECCAK_ASSERT(expr) \ + #define DN_KECCAK_ASSERT(expr) \ do \ { \ if (!(expr)) \ @@ -102,43 +102,43 @@ // Use this macro in a printf-like function, /* - Dqn_KeccakString64 string = {}; - printf("%.*s\n", DQN_KECCAK_STRING64_FMT(string)); + DN_KeccakString64 string = {}; + printf("%.*s\n", DN_KECCAK_STRING64_FMT(string)); */ -#define DQN_KECCAK_STRING56_FMT(string) 56, string -#define DQN_KECCAK_STRING64_FMT(string) 64, string -#define DQN_KECCAK_STRING96_FMT(string) 96, string -#define DQN_KECCAK_STRING128_FMT(string) 128, string +#define DN_KECCAK_STRING56_FMT(string) 56, string +#define DN_KECCAK_STRING64_FMT(string) 64, string +#define DN_KECCAK_STRING96_FMT(string) 96, string +#define DN_KECCAK_STRING128_FMT(string) 128, string -typedef unsigned char Dqn_KeccakU8; -typedef unsigned short Dqn_KeccakU16; -typedef unsigned int Dqn_KeccakU32; -typedef unsigned int Dqn_KeccakUint; +typedef unsigned char DN_KeccakU8; +typedef unsigned short DN_KeccakU16; +typedef unsigned int DN_KeccakU32; +typedef unsigned int DN_KeccakUint; #ifdef _MSC_VER - typedef unsigned __int64 Dqn_KeccakU64; + typedef unsigned __int64 DN_KeccakU64; #else - typedef unsigned long long Dqn_KeccakU64; + typedef unsigned long long DN_KeccakU64; #endif -typedef struct Dqn_KeccakBytes28 { char data[28]; } Dqn_KeccakBytes28; // 224 bit -typedef struct Dqn_KeccakBytes32 { char data[32]; } Dqn_KeccakBytes32; // 256 bit -typedef struct Dqn_KeccakBytes48 { char data[48]; } Dqn_KeccakBytes48; // 384 bit -typedef struct Dqn_KeccakBytes64 { char data[64]; } Dqn_KeccakBytes64; // 512 bit +typedef struct DN_KeccakBytes28 { char data[28]; } DN_KeccakBytes28; // 224 bit +typedef struct DN_KeccakBytes32 { char data[32]; } DN_KeccakBytes32; // 256 bit +typedef struct DN_KeccakBytes48 { char data[48]; } DN_KeccakBytes48; // 384 bit +typedef struct DN_KeccakBytes64 { char data[64]; } DN_KeccakBytes64; // 512 bit -typedef struct Dqn_KeccakString56 { char data[(sizeof(Dqn_KeccakBytes28) * 2) + 1]; } Dqn_KeccakString56; -typedef struct Dqn_KeccakString64 { char data[(sizeof(Dqn_KeccakBytes32) * 2) + 1]; } Dqn_KeccakString64; -typedef struct Dqn_KeccakString96 { char data[(sizeof(Dqn_KeccakBytes48) * 2) + 1]; } Dqn_KeccakString96; -typedef struct Dqn_KeccakString128 { char data[(sizeof(Dqn_KeccakBytes64) * 2) + 1]; } Dqn_KeccakString128; +typedef struct DN_KeccakString56 { char data[(sizeof(DN_KeccakBytes28) * 2) + 1]; } DN_KeccakString56; +typedef struct DN_KeccakString64 { char data[(sizeof(DN_KeccakBytes32) * 2) + 1]; } DN_KeccakString64; +typedef struct DN_KeccakString96 { char data[(sizeof(DN_KeccakBytes48) * 2) + 1]; } DN_KeccakString96; +typedef struct DN_KeccakString128 { char data[(sizeof(DN_KeccakBytes64) * 2) + 1]; } DN_KeccakString128; -#define DQN_KECCAK_LANE_SIZE_U64 5 -typedef struct Dqn_KeccakState +#define DN_KECCAK_LANE_SIZE_U64 5 +typedef struct DN_KeccakState { - Dqn_KeccakU8 state[DQN_KECCAK_LANE_SIZE_U64 * DQN_KECCAK_LANE_SIZE_U64 * sizeof(Dqn_KeccakU64)]; + DN_KeccakU8 state[DN_KECCAK_LANE_SIZE_U64 * DN_KECCAK_LANE_SIZE_U64 * sizeof(DN_KeccakU64)]; int state_size; // The number of bytes written to the state int absorb_size; // The amount of bytes to absorb/sponge in/from the state int hash_size_bits; // The size of the hash the context was initialised for in bits char delimited_suffix; // The delimited suffix of the current hash -} Dqn_KeccakState; +} DN_KeccakState; // NOTE: SHA3/Keccak Streaming API ///////////////////////////////////////////////////////////////// // Setup a hashing state for either @@ -152,92 +152,92 @@ typedef struct Dqn_KeccakState // // sha3: If true, setup the state for FIPS 202 SHA3, otherwise the non-finalized version // hash_size_bits: The number of bits to setup the context for, available sizes are 224, 256, 384 and 512. -Dqn_KeccakState Dqn_KeccakSHA3Init(bool sha3, int hash_size_bits); +DN_KeccakState DN_KeccakSHA3Init(bool sha3, int hash_size_bits); -// After initialising a 'Dqn_KeccakState' via 'Dqn_KeccakSHA3Init', iteratively -// update the hash with new data by calling 'Dqn_KeccakUpdate'. On completion, -// call 'Dqn_KeccakFinish' to generate the hash from the state. The 'dest_size' -// must be at-least the (bit-size / 8), i.e. for 'Dqn_Keccak512Init' it must be +// After initialising a 'DN_KeccakState' via 'DN_KeccakSHA3Init', iteratively +// update the hash with new data by calling 'DN_KeccakUpdate'. On completion, +// call 'DN_KeccakFinish' to generate the hash from the state. The 'dest_size' +// must be at-least the (bit-size / 8), i.e. for 'DN_Keccak512Init' it must be // atleast (512 / 8) bytes, 64 bytes. -void Dqn_KeccakUpdate(Dqn_KeccakState *keccak, void const *data, Dqn_KeccakU64 data_size); -void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size); +void DN_KeccakUpdate(DN_KeccakState *keccak, void const *data, DN_KeccakU64 data_size); +void DN_KeccakFinish(DN_KeccakState *keccak, void *dest, int dest_size); // NOTE: Simple API //////////////////////////////////////////////////////////////////////////////// // Helper function that combines the Init, Update and Finish step in one shot, // i.e. hashing a singlular contiguous buffer. Use the streaming API if data // is split across different buffers. -void Dqn_KeccakSHA3Hash(bool sha3, int hash_size_bits, void const *src, Dqn_KeccakU64 src_size, void *dest, int dest_size); +void DN_KeccakSHA3Hash(bool sha3, int hash_size_bits, void const *src, DN_KeccakU64 src_size, void *dest, int dest_size); -#define Dqn_SHA3Hash(hash_size_bits, src, src_size, dest, dest_size) Dqn_KeccakSHA3Hash(true /*sha3*/, hash_size_bits, src, src_size, dest, dest_size) -#define Dqn_SHA3_224(src, src_size, dest, dest_size) Dqn_SHA3Hash(224, src, src_size, dest, dest_size) -#define Dqn_SHA3_256(src, src_size, dest, dest_size) Dqn_SHA3Hash(256, src, src_size, dest, dest_size) -#define Dqn_SHA3_384(src, src_size, dest, dest_size) Dqn_SHA3Hash(384, src, src_size, dest, dest_size) -#define Dqn_SHA3_512(src, src_size, dest, dest_size) Dqn_SHA3Hash(512, src, src_size, dest, dest_size) +#define DN_SHA3Hash(hash_size_bits, src, src_size, dest, dest_size) DN_KeccakSHA3Hash(true /*sha3*/, hash_size_bits, src, src_size, dest, dest_size) +#define DN_SHA3_224(src, src_size, dest, dest_size) DN_SHA3Hash(224, src, src_size, dest, dest_size) +#define DN_SHA3_256(src, src_size, dest, dest_size) DN_SHA3Hash(256, src, src_size, dest, dest_size) +#define DN_SHA3_384(src, src_size, dest, dest_size) DN_SHA3Hash(384, src, src_size, dest, dest_size) +#define DN_SHA3_512(src, src_size, dest, dest_size) DN_SHA3Hash(512, src, src_size, dest, dest_size) -#define Dqn_KeccakHash(hash_size_bits, src, src_size, dest, dest_size) Dqn_KeccakSHA3Hash(false /*sha3*/, hash_size_bits, src, src_size, dest, dest_size) -#define Dqn_Keccak224(src, src_size, dest, dest_size) Dqn_KeccakHash(224, src, src_size, dest, dest_size) -#define Dqn_Keccak256(src, src_size, dest, dest_size) Dqn_KeccakHash(256, src, src_size, dest, dest_size) -#define Dqn_Keccak384(src, src_size, dest, dest_size) Dqn_KeccakHash(384, src, src_size, dest, dest_size) -#define Dqn_Keccak512(src, src_size, dest, dest_size) Dqn_KeccakHash(512, src, src_size, dest, dest_size) +#define DN_KeccakHash(hash_size_bits, src, src_size, dest, dest_size) DN_KeccakSHA3Hash(false /*sha3*/, hash_size_bits, src, src_size, dest, dest_size) +#define DN_Keccak224(src, src_size, dest, dest_size) DN_KeccakHash(224, src, src_size, dest, dest_size) +#define DN_Keccak256(src, src_size, dest, dest_size) DN_KeccakHash(256, src, src_size, dest, dest_size) +#define DN_Keccak384(src, src_size, dest, dest_size) DN_KeccakHash(384, src, src_size, dest, dest_size) +#define DN_Keccak512(src, src_size, dest, dest_size) DN_KeccakHash(512, src, src_size, dest, dest_size) // NOTE: SHA3 Helpers ////////////////////////////////////////////////////////////////////////////// -Dqn_KeccakBytes28 Dqn_SHA3_224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size); -Dqn_KeccakBytes32 Dqn_SHA3_256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size); -Dqn_KeccakBytes48 Dqn_SHA3_384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size); -Dqn_KeccakBytes64 Dqn_SHA3_512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size); +DN_KeccakBytes28 DN_SHA3_224ToBytes28(void *bytes, DN_KeccakU64 bytes_size); +DN_KeccakBytes32 DN_SHA3_256ToBytes32(void *bytes, DN_KeccakU64 bytes_size); +DN_KeccakBytes48 DN_SHA3_384ToBytes48(void *bytes, DN_KeccakU64 bytes_size); +DN_KeccakBytes64 DN_SHA3_512ToBytes64(void *bytes, DN_KeccakU64 bytes_size); // NOTE: Keccak Helpers //////////////////////////////////////////////////////////////////////////// -Dqn_KeccakBytes28 Dqn_Keccak224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size); -Dqn_KeccakBytes32 Dqn_Keccak256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size); -Dqn_KeccakBytes48 Dqn_Keccak384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size); -Dqn_KeccakBytes64 Dqn_Keccak512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size); +DN_KeccakBytes28 DN_Keccak224ToBytes28(void *bytes, DN_KeccakU64 bytes_size); +DN_KeccakBytes32 DN_Keccak256ToBytes32(void *bytes, DN_KeccakU64 bytes_size); +DN_KeccakBytes48 DN_Keccak384ToBytes48(void *bytes, DN_KeccakU64 bytes_size); +DN_KeccakBytes64 DN_Keccak512ToBytes64(void *bytes, DN_KeccakU64 bytes_size); -#if defined(DQN_H) -// NOTE: SHA3 - Helpers for Dqn data structures //////////////////////////////////////////////////// -Dqn_KeccakBytes28 Dqn_SHA3_224StringToBytes28(Dqn_Str8 string); -Dqn_KeccakBytes32 Dqn_SHA3_256StringToBytes32(Dqn_Str8 string); -Dqn_KeccakBytes48 Dqn_SHA3_384StringToBytes48(Dqn_Str8 string); -Dqn_KeccakBytes64 Dqn_SHA3_512StringToBytes64(Dqn_Str8 string); +#if defined(DN_H) +// NOTE: SHA3 - Helpers for DN data structures //////////////////////////////////////////////////// +DN_KeccakBytes28 DN_SHA3_224StringToBytes28(DN_Str8 string); +DN_KeccakBytes32 DN_SHA3_256StringToBytes32(DN_Str8 string); +DN_KeccakBytes48 DN_SHA3_384StringToBytes48(DN_Str8 string); +DN_KeccakBytes64 DN_SHA3_512StringToBytes64(DN_Str8 string); -// NOTE: Keccak - Helpers for Dqn data structures ////////////////////////////////////////////////// -Dqn_KeccakBytes28 Dqn_Keccak224StringToBytes28(Dqn_Str8 string); -Dqn_KeccakBytes32 Dqn_Keccak256StringToBytes32(Dqn_Str8 string); -Dqn_KeccakBytes48 Dqn_Keccak384StringToBytes48(Dqn_Str8 string); -Dqn_KeccakBytes64 Dqn_Keccak512StringToBytes64(Dqn_Str8 string); -#endif // DQN_H +// NOTE: Keccak - Helpers for DN data structures ////////////////////////////////////////////////// +DN_KeccakBytes28 DN_Keccak224StringToBytes28(DN_Str8 string); +DN_KeccakBytes32 DN_Keccak256StringToBytes32(DN_Str8 string); +DN_KeccakBytes48 DN_Keccak384StringToBytes48(DN_Str8 string); +DN_KeccakBytes64 DN_Keccak512StringToBytes64(DN_Str8 string); +#endif // DN_H // NOTE: Helper functions ////////////////////////////////////////////////////////////////////////// // Convert a binary buffer into its hex representation into dest. The dest // buffer must be large enough to contain the hex representation, i.e. // atleast src_size * 2). This function does *not* null-terminate the buffer. -void Dqn_KeccakBytesToHex(void const *src, Dqn_KeccakU64 src_size, char *dest, Dqn_KeccakU64 dest_size); +void DN_KeccakBytesToHex(void const *src, DN_KeccakU64 src_size, char *dest, DN_KeccakU64 dest_size); // Converts a fixed amount of bytes into a hexadecimal string. Helper functions -// that call into Dqn_KeccakBytesToHex. +// that call into DN_KeccakBytesToHex. // return: The hexadecimal string of the bytes, null-terminated. -Dqn_KeccakString56 Dqn_KeccakBytes28ToHex(Dqn_KeccakBytes28 const *bytes); -Dqn_KeccakString64 Dqn_KeccakBytes32ToHex(Dqn_KeccakBytes32 const *bytes); -Dqn_KeccakString96 Dqn_KeccakBytes48ToHex(Dqn_KeccakBytes48 const *bytes); -Dqn_KeccakString128 Dqn_KeccakBytes64ToHex(Dqn_KeccakBytes64 const *bytes); +DN_KeccakString56 DN_KeccakBytes28ToHex(DN_KeccakBytes28 const *bytes); +DN_KeccakString64 DN_KeccakBytes32ToHex(DN_KeccakBytes32 const *bytes); +DN_KeccakString96 DN_KeccakBytes48ToHex(DN_KeccakBytes48 const *bytes); +DN_KeccakString128 DN_KeccakBytes64ToHex(DN_KeccakBytes64 const *bytes); // Compares byte data structures for byte equality (via memcmp). // return: 1 if the contents are equal otherwise 0. -int Dqn_KeccakBytes28Equals(Dqn_KeccakBytes28 const *a, Dqn_KeccakBytes28 const *b); -int Dqn_KeccakBytes32Equals(Dqn_KeccakBytes32 const *a, Dqn_KeccakBytes32 const *b); -int Dqn_KeccakBytes48Equals(Dqn_KeccakBytes48 const *a, Dqn_KeccakBytes48 const *b); -int Dqn_KeccakBytes64Equals(Dqn_KeccakBytes64 const *a, Dqn_KeccakBytes64 const *b); +int DN_KeccakBytes28Equals(DN_KeccakBytes28 const *a, DN_KeccakBytes28 const *b); +int DN_KeccakBytes32Equals(DN_KeccakBytes32 const *a, DN_KeccakBytes32 const *b); +int DN_KeccakBytes48Equals(DN_KeccakBytes48 const *a, DN_KeccakBytes48 const *b); +int DN_KeccakBytes64Equals(DN_KeccakBytes64 const *a, DN_KeccakBytes64 const *b); -#if defined(DQN_H) && defined(DQN_WITH_HEX) -// NOTE: Other helper functions for Dqn data structures //////////////////////////////////////////// +#if defined(DN_H) && defined(DN_WITH_HEX) +// NOTE: Other helper functions for DN data structures //////////////////////////////////////////// // Converts a 64 character hex string into the 32 byte binary representation. // Invalid hex characters in the string will be represented as 0. // hex: Must be exactly a 64 character hex string. -Dqn_KeccakBytes32 Dqn_KeccakHex64StringToBytes(Dqn_Str8 hex); -#endif // DQN_H && DQN_WITH_HEX -#endif // DQN_KECCAK_H +DN_KeccakBytes32 DN_KeccakHex64StringToBytes(DN_Str8 hex); +#endif // DN_H && DN_WITH_HEX +#endif // DN_KECCAK_H -#if defined(DQN_KECCAK_IMPLEMENTATION) -Dqn_KeccakU64 const DQN_KECCAK_ROUNDS[] = { +#if defined(DN_KECCAK_IMPLEMENTATION) +DN_KeccakU64 const DN_KECCAK_ROUNDS[] = { 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, @@ -245,7 +245,7 @@ Dqn_KeccakU64 const DQN_KECCAK_ROUNDS[] = { 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, }; -Dqn_KeccakU64 const DQN_KECCAK_ROTATIONS[][5] = +DN_KeccakU64 const DN_KECCAK_ROTATIONS[][5] = { {0, 36, 3, 41, 18}, {1, 44, 10, 45, 2}, @@ -254,21 +254,21 @@ Dqn_KeccakU64 const DQN_KECCAK_ROTATIONS[][5] = {27, 20, 39, 8, 14}, }; -#define DQN_KECCAK_ROL64(val, rotate) (((val) << (rotate)) | (((val) >> (64 - (rotate))))) +#define DN_KECCAK_ROL64(val, rotate) (((val) << (rotate)) | (((val) >> (64 - (rotate))))) -static void Dqn_Keccak__Permute(void *state) +static void DN_Keccak__Permute(void *state) { - // TODO(dqn): Do some profiling on unrolling and can we SIMD some part of + // TODO(dn): Do some profiling on unrolling and can we SIMD some part of // this? Unroll loop, look at data dependencies and investigate. - Dqn_KeccakU64 *lanes_u64 = (Dqn_KeccakU64 *)state; + DN_KeccakU64 *lanes_u64 = (DN_KeccakU64 *)state; for (int round_index = 0; round_index < 24; round_index++) { - #define LANE_INDEX(x, y) ((x) + ((y) * DQN_KECCAK_LANE_SIZE_U64)) - // θ step ////////////////////////////////////////////////////////////////////////////////// + #define LANE_INDEX(x, y) ((x) + ((y) * DN_KECCAK_LANE_SIZE_U64)) + // ?? step ////////////////////////////////////////////////////////////////////////////////// #if 1 - Dqn_KeccakU64 c[DQN_KECCAK_LANE_SIZE_U64]; - for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++) + DN_KeccakU64 c[DN_KECCAK_LANE_SIZE_U64]; + for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++) { c[x] = lanes_u64[LANE_INDEX(x, 0)] ^ lanes_u64[LANE_INDEX(x, 1)] ^ @@ -277,87 +277,87 @@ static void Dqn_Keccak__Permute(void *state) lanes_u64[LANE_INDEX(x, 4)]; } - Dqn_KeccakU64 d[DQN_KECCAK_LANE_SIZE_U64]; - for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++) - d[x] = c[(x + 4) % DQN_KECCAK_LANE_SIZE_U64] ^ DQN_KECCAK_ROL64(c[(x + 1) % DQN_KECCAK_LANE_SIZE_U64], 1); + DN_KeccakU64 d[DN_KECCAK_LANE_SIZE_U64]; + for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++) + d[x] = c[(x + 4) % DN_KECCAK_LANE_SIZE_U64] ^ DN_KECCAK_ROL64(c[(x + 1) % DN_KECCAK_LANE_SIZE_U64], 1); - for (int y = 0; y < DQN_KECCAK_LANE_SIZE_U64; y++) - for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++) + for (int y = 0; y < DN_KECCAK_LANE_SIZE_U64; y++) + for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++) lanes_u64[LANE_INDEX(x, y)] ^= d[x]; #else - Dqn_KeccakU64 c[5], d[5]; + DN_KeccakU64 c[5], d[5]; c[0] = lanes_u64[0 * 5 + 0] ^ lanes_u64[1 * 5 + 0] ^ lanes_u64[2 * 5 + 0] ^ lanes_u64[3 * 5 + 0] ^ lanes_u64[4 * 5 + 0]; c[1] = lanes_u64[0 * 5 + 1] ^ lanes_u64[1 * 5 + 1] ^ lanes_u64[2 * 5 + 1] ^ lanes_u64[3 * 5 + 1] ^ lanes_u64[4 * 5 + 1]; c[2] = lanes_u64[0 * 5 + 2] ^ lanes_u64[1 * 5 + 2] ^ lanes_u64[2 * 5 + 2] ^ lanes_u64[3 * 5 + 2] ^ lanes_u64[4 * 5 + 2]; c[3] = lanes_u64[0 * 5 + 3] ^ lanes_u64[1 * 5 + 3] ^ lanes_u64[2 * 5 + 3] ^ lanes_u64[3 * 5 + 3] ^ lanes_u64[4 * 5 + 3]; c[4] = lanes_u64[0 * 5 + 4] ^ lanes_u64[1 * 5 + 4] ^ lanes_u64[2 * 5 + 4] ^ lanes_u64[3 * 5 + 4] ^ lanes_u64[4 * 5 + 4]; - d[0] = c[4] ^ DQN_KECCAK_ROL64(c[1], 1); - d[1] = c[0] ^ DQN_KECCAK_ROL64(c[2], 1); - d[2] = c[1] ^ DQN_KECCAK_ROL64(c[3], 1); - d[3] = c[2] ^ DQN_KECCAK_ROL64(c[4], 1); - d[4] = c[3] ^ DQN_KECCAK_ROL64(c[0], 1); + d[0] = c[4] ^ DN_KECCAK_ROL64(c[1], 1); + d[1] = c[0] ^ DN_KECCAK_ROL64(c[2], 1); + d[2] = c[1] ^ DN_KECCAK_ROL64(c[3], 1); + d[3] = c[2] ^ DN_KECCAK_ROL64(c[4], 1); + d[4] = c[3] ^ DN_KECCAK_ROL64(c[0], 1); #endif - // ρ and π steps /////////////////////////////////////////////////////////////////////////// - Dqn_KeccakU64 b[DQN_KECCAK_LANE_SIZE_U64 * DQN_KECCAK_LANE_SIZE_U64]; - for (int y = 0; y < DQN_KECCAK_LANE_SIZE_U64; y++) + // ?? and ?? steps /////////////////////////////////////////////////////////////////////////// + DN_KeccakU64 b[DN_KECCAK_LANE_SIZE_U64 * DN_KECCAK_LANE_SIZE_U64]; + for (int y = 0; y < DN_KECCAK_LANE_SIZE_U64; y++) { - for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++) + for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++) { - Dqn_KeccakU64 lane = lanes_u64[LANE_INDEX(x, y)]; - Dqn_KeccakU64 rotate_count = DQN_KECCAK_ROTATIONS[x][y]; - b[LANE_INDEX(y, (2 * x + 3 * y) % 5)] = DQN_KECCAK_ROL64(lane, rotate_count); + DN_KeccakU64 lane = lanes_u64[LANE_INDEX(x, y)]; + DN_KeccakU64 rotate_count = DN_KECCAK_ROTATIONS[x][y]; + b[LANE_INDEX(y, (2 * x + 3 * y) % 5)] = DN_KECCAK_ROL64(lane, rotate_count); } } - // χ step ////////////////////////////////////////////////////////////////////////////////// - for (int y = 0; y < DQN_KECCAK_LANE_SIZE_U64; y++) + // ?? step ////////////////////////////////////////////////////////////////////////////////// + for (int y = 0; y < DN_KECCAK_LANE_SIZE_U64; y++) { - for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++) + for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++) { - Dqn_KeccakU64 rhs = ~b[LANE_INDEX((x + 1) % 5, y)] & + DN_KeccakU64 rhs = ~b[LANE_INDEX((x + 1) % 5, y)] & b[LANE_INDEX((x + 2) % 5, y)]; lanes_u64[LANE_INDEX(x, y)] = b[LANE_INDEX(x, y)] ^ rhs; } } - // ι step ////////////////////////////////////////////////////////////////////////////////// - lanes_u64[LANE_INDEX(0, 0)] ^= DQN_KECCAK_ROUNDS[round_index]; + // ?? step ////////////////////////////////////////////////////////////////////////////////// + lanes_u64[LANE_INDEX(0, 0)] ^= DN_KECCAK_ROUNDS[round_index]; #undef LANE_INDEX - #undef DQN_KECCAK_ROL64 + #undef DN_KECCAK_ROL64 } } // NOTE: Streaming API ///////////////////////////////////////////////////////////////////////////// -Dqn_KeccakState Dqn_KeccakSHA3Init(bool sha3, int hash_size_bits) +DN_KeccakState DN_KeccakSHA3Init(bool sha3, int hash_size_bits) { char const SHA3_DELIMITED_SUFFIX = 0x06; char const KECCAK_DELIMITED_SUFFIX = 0x01; int const bitrate = 1600 - (hash_size_bits * 2); #if defined(__cplusplus) - Dqn_KeccakState result = {}; + DN_KeccakState result = {}; #else - Dqn_KeccakState result = {0}; + DN_KeccakState result = {0}; #endif result.hash_size_bits = hash_size_bits; result.absorb_size = bitrate / 8; result.delimited_suffix = sha3 ? SHA3_DELIMITED_SUFFIX : KECCAK_DELIMITED_SUFFIX; - DQN_KECCAK_ASSERT(bitrate + (hash_size_bits * 2) /*capacity*/ == 1600); + DN_KECCAK_ASSERT(bitrate + (hash_size_bits * 2) /*capacity*/ == 1600); return result; } -void Dqn_KeccakUpdate(Dqn_KeccakState *keccak, void const *data, Dqn_KeccakU64 data_size) +void DN_KeccakUpdate(DN_KeccakState *keccak, void const *data, DN_KeccakU64 data_size) { - Dqn_KeccakU8 *state = keccak->state; - Dqn_KeccakU8 const *ptr = (Dqn_KeccakU8 *)data; - Dqn_KeccakU64 ptr_size = data_size; + DN_KeccakU8 *state = keccak->state; + DN_KeccakU8 const *ptr = (DN_KeccakU8 *)data; + DN_KeccakU64 ptr_size = data_size; while (ptr_size > 0) { - Dqn_KeccakU64 space = keccak->absorb_size - keccak->state_size; + DN_KeccakU64 space = keccak->absorb_size - keccak->state_size; int bytes_to_absorb = (int)(space < ptr_size ? space : ptr_size); for (int index = 0; index < bytes_to_absorb; index++) @@ -369,23 +369,23 @@ void Dqn_KeccakUpdate(Dqn_KeccakState *keccak, void const *data, Dqn_KeccakU64 d if (keccak->state_size >= keccak->absorb_size) { - DQN_KECCAK_ASSERT(keccak->state_size == keccak->absorb_size); - Dqn_Keccak__Permute(state); + DN_KECCAK_ASSERT(keccak->state_size == keccak->absorb_size); + DN_Keccak__Permute(state); keccak->state_size = 0; } } } -void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size) +void DN_KeccakFinish(DN_KeccakState *keccak, void *dest, int dest_size) { - DQN_KECCAK_ASSERT(dest_size >= keccak->hash_size_bits / 8); + DN_KECCAK_ASSERT(dest_size >= keccak->hash_size_bits / 8); // Sponge Finalization Step: Final padding bit ///////////////////////////////////////////////// int const INDEX_OF_0X80_BYTE = keccak->absorb_size - 1; int const delimited_suffix_index = keccak->state_size; - DQN_KECCAK_ASSERT(delimited_suffix_index < keccak->absorb_size); + DN_KECCAK_ASSERT(delimited_suffix_index < keccak->absorb_size); - Dqn_KeccakU8 *state = keccak->state; + DN_KeccakU8 *state = keccak->state; state[delimited_suffix_index] ^= keccak->delimited_suffix; // NOTE: In the reference implementation, it checks that if the @@ -398,16 +398,16 @@ void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size) // this from the implementation here. state[INDEX_OF_0X80_BYTE] ^= 0x80; - Dqn_Keccak__Permute(state); + DN_Keccak__Permute(state); // Squeeze Step: Squeeze bytes from the state into our hash //////////////////////////////////// - Dqn_KeccakU8 *dest_u8 = (Dqn_KeccakU8 *)dest; + DN_KeccakU8 *dest_u8 = (DN_KeccakU8 *)dest; int const squeeze_count = dest_size / keccak->absorb_size; int squeeze_index = 0; for (; squeeze_index < squeeze_count; squeeze_index++) { - if (squeeze_index) Dqn_Keccak__Permute(state); - DQN_KECCAK_MEMCPY(dest_u8, state, keccak->absorb_size); + if (squeeze_index) DN_Keccak__Permute(state); + DN_KECCAK_MEMCPY(dest_u8, state, keccak->absorb_size); dest_u8 += keccak->absorb_size; } @@ -415,147 +415,147 @@ void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size) int const remainder = dest_size % keccak->absorb_size; if (remainder) { - if (squeeze_index) Dqn_Keccak__Permute(state); - DQN_KECCAK_MEMCPY(dest_u8, state, remainder); + if (squeeze_index) DN_Keccak__Permute(state); + DN_KECCAK_MEMCPY(dest_u8, state, remainder); } } -void Dqn_KeccakSHA3Hash(bool sha3, int hash_size_bits, void const *src, Dqn_KeccakU64 src_size, void *dest, int dest_size) +void DN_KeccakSHA3Hash(bool sha3, int hash_size_bits, void const *src, DN_KeccakU64 src_size, void *dest, int dest_size) { - Dqn_KeccakState keccak = Dqn_KeccakSHA3Init(sha3, hash_size_bits); - Dqn_KeccakUpdate(&keccak, src, src_size); - Dqn_KeccakFinish(&keccak, dest, dest_size); + DN_KeccakState keccak = DN_KeccakSHA3Init(sha3, hash_size_bits); + DN_KeccakUpdate(&keccak, src, src_size); + DN_KeccakFinish(&keccak, dest, dest_size); } // NOTE: SHA3 Helpers ////////////////////////////////////////////////////////////////////////////// -Dqn_KeccakBytes28 Dqn_SHA3_224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size) +DN_KeccakBytes28 DN_SHA3_224ToBytes28(void *bytes, DN_KeccakU64 bytes_size) { - Dqn_KeccakBytes28 result; - Dqn_SHA3_224(bytes, bytes_size, result.data, sizeof(result)); + DN_KeccakBytes28 result; + DN_SHA3_224(bytes, bytes_size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes32 Dqn_SHA3_256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size) +DN_KeccakBytes32 DN_SHA3_256ToBytes32(void *bytes, DN_KeccakU64 bytes_size) { - Dqn_KeccakBytes32 result; - Dqn_SHA3_256(bytes, bytes_size, result.data, sizeof(result)); + DN_KeccakBytes32 result; + DN_SHA3_256(bytes, bytes_size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes48 Dqn_SHA3_384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size) +DN_KeccakBytes48 DN_SHA3_384ToBytes48(void *bytes, DN_KeccakU64 bytes_size) { - Dqn_KeccakBytes48 result; - Dqn_SHA3_384(bytes, bytes_size, result.data, sizeof(result)); + DN_KeccakBytes48 result; + DN_SHA3_384(bytes, bytes_size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes64 Dqn_SHA3_512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size) +DN_KeccakBytes64 DN_SHA3_512ToBytes64(void *bytes, DN_KeccakU64 bytes_size) { - Dqn_KeccakBytes64 result; - Dqn_SHA3_512(bytes, bytes_size, result.data, sizeof(result)); + DN_KeccakBytes64 result; + DN_SHA3_512(bytes, bytes_size, result.data, sizeof(result)); return result; } // NOTE: Keccak Helpers //////////////////////////////////////////////////////////////////////////// -Dqn_KeccakBytes28 Dqn_Keccak224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size) +DN_KeccakBytes28 DN_Keccak224ToBytes28(void *bytes, DN_KeccakU64 bytes_size) { - Dqn_KeccakBytes28 result; - Dqn_Keccak224(bytes, bytes_size, result.data, sizeof(result)); + DN_KeccakBytes28 result; + DN_Keccak224(bytes, bytes_size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes32 Dqn_Keccak256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size) +DN_KeccakBytes32 DN_Keccak256ToBytes32(void *bytes, DN_KeccakU64 bytes_size) { - Dqn_KeccakBytes32 result; - Dqn_Keccak256(bytes, bytes_size, result.data, sizeof(result)); + DN_KeccakBytes32 result; + DN_Keccak256(bytes, bytes_size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes48 Dqn_Keccak384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size) +DN_KeccakBytes48 DN_Keccak384ToBytes48(void *bytes, DN_KeccakU64 bytes_size) { - Dqn_KeccakBytes48 result; - Dqn_Keccak384(bytes, bytes_size, result.data, sizeof(result)); + DN_KeccakBytes48 result; + DN_Keccak384(bytes, bytes_size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes64 Dqn_Keccak512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size) +DN_KeccakBytes64 DN_Keccak512ToBytes64(void *bytes, DN_KeccakU64 bytes_size) { - Dqn_KeccakBytes64 result; - Dqn_Keccak512(bytes, bytes_size, result.data, sizeof(result)); + DN_KeccakBytes64 result; + DN_Keccak512(bytes, bytes_size, result.data, sizeof(result)); return result; } -#if defined(DQN_H) -// NOTE: SHA3 - Helpers for Dqn data structures //////////////////////////////////////////////////// -Dqn_KeccakBytes28 Dqn_SHA3_224StringToBytes28(Dqn_Str8 string) +#if defined(DN_H) +// NOTE: SHA3 - Helpers for DN data structures //////////////////////////////////////////////////// +DN_KeccakBytes28 DN_SHA3_224StringToBytes28(DN_Str8 string) { - Dqn_KeccakBytes28 result; - Dqn_SHA3_224(string.data, string.size, result.data, sizeof(result)); + DN_KeccakBytes28 result; + DN_SHA3_224(string.data, string.size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes32 Dqn_SHA3_256StringToBytes32(Dqn_Str8 string) +DN_KeccakBytes32 DN_SHA3_256StringToBytes32(DN_Str8 string) { - Dqn_KeccakBytes32 result; - Dqn_SHA3_256(string.data, string.size, result.data, sizeof(result)); + DN_KeccakBytes32 result; + DN_SHA3_256(string.data, string.size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes48 Dqn_SHA3_384StringToBytes48(Dqn_Str8 string) +DN_KeccakBytes48 DN_SHA3_384StringToBytes48(DN_Str8 string) { - Dqn_KeccakBytes48 result; - Dqn_SHA3_384(string.data, string.size, result.data, sizeof(result)); + DN_KeccakBytes48 result; + DN_SHA3_384(string.data, string.size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes64 Dqn_SHA3_512StringToBytes64(Dqn_Str8 string) +DN_KeccakBytes64 DN_SHA3_512StringToBytes64(DN_Str8 string) { - Dqn_KeccakBytes64 result; - Dqn_SHA3_512(string.data, string.size, result.data, sizeof(result)); + DN_KeccakBytes64 result; + DN_SHA3_512(string.data, string.size, result.data, sizeof(result)); return result; } -#endif // DQN_H +#endif // DN_H -#if defined(DQN_H) -// NOTE: Keccak - Helpers for Dqn data structures ////////////////////////////////////////////////// -Dqn_KeccakBytes28 Dqn_Keccak224StringToBytes28(Dqn_Str8 string) +#if defined(DN_H) +// NOTE: Keccak - Helpers for DN data structures ////////////////////////////////////////////////// +DN_KeccakBytes28 DN_Keccak224StringToBytes28(DN_Str8 string) { - Dqn_KeccakBytes28 result; - Dqn_Keccak224(string.data, string.size, result.data, sizeof(result)); + DN_KeccakBytes28 result; + DN_Keccak224(string.data, string.size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes32 Dqn_Keccak256StringToBytes32(Dqn_Str8 string) +DN_KeccakBytes32 DN_Keccak256StringToBytes32(DN_Str8 string) { - Dqn_KeccakBytes32 result; - Dqn_Keccak256(string.data, string.size, result.data, sizeof(result)); + DN_KeccakBytes32 result; + DN_Keccak256(string.data, string.size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes48 Dqn_Keccak384StringToBytes48(Dqn_Str8 string) +DN_KeccakBytes48 DN_Keccak384StringToBytes48(DN_Str8 string) { - Dqn_KeccakBytes48 result; - Dqn_Keccak384(string.data, string.size, result.data, sizeof(result)); + DN_KeccakBytes48 result; + DN_Keccak384(string.data, string.size, result.data, sizeof(result)); return result; } -Dqn_KeccakBytes64 Dqn_Keccak512StringToBytes64(Dqn_Str8 string) +DN_KeccakBytes64 DN_Keccak512StringToBytes64(DN_Str8 string) { - Dqn_KeccakBytes64 result; - Dqn_Keccak512(string.data, string.size, result.data, sizeof(result)); + DN_KeccakBytes64 result; + DN_Keccak512(string.data, string.size, result.data, sizeof(result)); return result; } -#endif // DQN_H +#endif // DN_H // NOTE: Helper functions ////////////////////////////////////////////////////////////////////////// -void Dqn_KeccakBytesToHex(void const *src, Dqn_KeccakU64 src_size, char *dest, Dqn_KeccakU64 dest_size) +void DN_KeccakBytesToHex(void const *src, DN_KeccakU64 src_size, char *dest, DN_KeccakU64 dest_size) { (void)src_size; (void)dest_size; - DQN_KECCAK_ASSERT(dest_size >= src_size * 2); + DN_KECCAK_ASSERT(dest_size >= src_size * 2); unsigned char *src_u8 = (unsigned char *)src; - for (Dqn_KeccakU64 src_index = 0, dest_index = 0; + for (DN_KeccakU64 src_index = 0, dest_index = 0; src_index < src_size; src_index += 1, dest_index += 2) { @@ -567,70 +567,70 @@ void Dqn_KeccakBytesToHex(void const *src, Dqn_KeccakU64 src_size, char *dest, D } } -Dqn_KeccakString56 Dqn_KeccakBytes28ToHex(Dqn_KeccakBytes28 const *bytes) +DN_KeccakString56 DN_KeccakBytes28ToHex(DN_KeccakBytes28 const *bytes) { - Dqn_KeccakString56 result; - Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); + DN_KeccakString56 result; + DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); result.data[sizeof(result.data) - 1] = 0; return result; } -Dqn_KeccakString64 Dqn_KeccakBytes32ToHex(Dqn_KeccakBytes32 const *bytes) +DN_KeccakString64 DN_KeccakBytes32ToHex(DN_KeccakBytes32 const *bytes) { - Dqn_KeccakString64 result; - Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); + DN_KeccakString64 result; + DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); result.data[sizeof(result.data) - 1] = 0; return result; } -Dqn_KeccakString96 Dqn_KeccakBytes48ToHex(Dqn_KeccakBytes48 const *bytes) +DN_KeccakString96 DN_KeccakBytes48ToHex(DN_KeccakBytes48 const *bytes) { - Dqn_KeccakString96 result; - Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); + DN_KeccakString96 result; + DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); result.data[sizeof(result.data) - 1] = 0; return result; } -Dqn_KeccakString128 Dqn_KeccakBytes64ToHex(Dqn_KeccakBytes64 const *bytes) +DN_KeccakString128 DN_KeccakBytes64ToHex(DN_KeccakBytes64 const *bytes) { - Dqn_KeccakString128 result; - Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); + DN_KeccakString128 result; + DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); result.data[sizeof(result.data) - 1] = 0; return result; } -int Dqn_KeccakBytes28Equals(Dqn_KeccakBytes28 const *a, Dqn_KeccakBytes28 const *b) +int DN_KeccakBytes28Equals(DN_KeccakBytes28 const *a, DN_KeccakBytes28 const *b) { - int result = DQN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0; + int result = DN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0; return result; } -int Dqn_KeccakBytes32Equals(Dqn_KeccakBytes32 const *a, Dqn_KeccakBytes32 const *b) +int DN_KeccakBytes32Equals(DN_KeccakBytes32 const *a, DN_KeccakBytes32 const *b) { - int result = DQN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0; + int result = DN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0; return result; } -int Dqn_KeccakBytes48Equals(Dqn_KeccakBytes48 const *a, Dqn_KeccakBytes48 const *b) +int DN_KeccakBytes48Equals(DN_KeccakBytes48 const *a, DN_KeccakBytes48 const *b) { - int result = DQN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0; + int result = DN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0; return result; } -int Dqn_KeccakBytes64Equals(Dqn_KeccakBytes64 const *a, Dqn_KeccakBytes64 const *b) +int DN_KeccakBytes64Equals(DN_KeccakBytes64 const *a, DN_KeccakBytes64 const *b) { - int result = DQN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0; + int result = DN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0; return result; } -#if defined(DQN_H) && defined(DQN_WITH_HEX) -// NOTE: Other helper functions for Dqn data structures //////////////////////////////////////////// -Dqn_KeccakBytes32 Dqn_KeccakHex64StringToBytes(Dqn_Str8 hex) +#if defined(DN_H) && defined(DN_WITH_HEX) +// NOTE: Other helper functions for DN data structures //////////////////////////////////////////// +DN_KeccakBytes32 DN_KeccakHex64StringToBytes(DN_Str8 hex) { - DQN_KECCAK_ASSERT(hex.size == 64); - Dqn_KeccakBytes32 result; - Dqn_Hex_CString8ToByteBuffer(hex.data, hex.size, result.data, sizeof(result)); + DN_KECCAK_ASSERT(hex.size == 64); + DN_KeccakBytes32 result; + DN_Hex_CString8ToByteBuffer(hex.data, hex.size, result.data, sizeof(result)); return result; } -#endif // DQN_H && DQN_WITH_HEX -#endif // DQN_KECCAK_IMPLEMENTATION +#endif // DN_H && DN_WITH_HEX +#endif // DN_KECCAK_IMPLEMENTATION diff --git a/Standalone/dqn_utest.h b/Standalone/dqn_utest.h index 31eee1b..0057294 100644 --- a/Standalone/dqn_utest.h +++ b/Standalone/dqn_utest.h @@ -1,5 +1,5 @@ -#if !defined(DQN_UTEST_H) -#define DQN_UTEST_H +#if !defined(DN_UTEST_H) +#define DN_UTEST_H /* //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -13,7 +13,7 @@ // \$$$$$$ | $$ | $$$$$$$$\ \$$$$$$ | $$ | // \______/ \__| \________| \______/ \__| // -// dqn_utest.h -- Extremely minimal unit testing framework +// dn_utest.h -- Extremely minimal unit testing framework // //////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -22,28 +22,28 @@ // // NOTE: Configuration ///////////////////////////////////////////////////////////////////////////// // -// #define DQN_UTEST_IMPLEMENTATION +// #define DN_UTEST_IMPLEMENTATION // Define this in one and only one C++ file to enable the implementation // code of the header file. This will also automatically enable the JSMN // implementation. // -// #define DQN_UTEST_RESULT_LPAD +// #define DN_UTEST_RESULT_LPAD // Define this to a number to specify how much to pad the output of the test // result line before the test result is printed. // -// #define DQN_UTEST_RESULT_PAD_CHAR +// #define DN_UTEST_RESULT_PAD_CHAR // Define this to a character to specify the default character to use for // padding. By default this is '.' // -// #define DQN_UTEST_SPACING +// #define DN_UTEST_SPACING // Define this to a number to specify the number of spaces between the group // declaration and the test output in the group. // -// #define DQN_UTEST_BAD_COLOR +// #define DN_UTEST_BAD_COLOR // Define this to a terminal color code to specify what color errors will be // presented as. // -// #define DQN_UTEST_GOOD_COLOR +// #define DN_UTEST_GOOD_COLOR // Define this to a terminal color code to specify what color sucess will be // presented as. // @@ -56,114 +56,114 @@ #include #include -#if !defined(DQN_UTEST_RESULT_LPAD) - #define DQN_UTEST_RESULT_LPAD 90 +#if !defined(DN_UTEST_RESULT_LPAD) + #define DN_UTEST_RESULT_LPAD 90 #endif -#if !defined(DQN_UTEST_RESULT_PAD_CHAR) - #define DQN_UTEST_RESULT_PAD_CHAR '.' +#if !defined(DN_UTEST_RESULT_PAD_CHAR) + #define DN_UTEST_RESULT_PAD_CHAR '.' #endif -#if !defined(DQN_UTEST_SPACING) - #define DQN_UTEST_SPACING 2 +#if !defined(DN_UTEST_SPACING) + #define DN_UTEST_SPACING 2 #endif -#if !defined(DQN_UTEST_BAD_COLOR) - #define DQN_UTEST_BAD_COLOR "\x1b[31m" +#if !defined(DN_UTEST_BAD_COLOR) + #define DN_UTEST_BAD_COLOR "\x1b[31m" #endif -#if !defined(DQN_UTEST_GOOD_COLOR) - #define DQN_UTEST_GOOD_COLOR "\x1b[32m" +#if !defined(DN_UTEST_GOOD_COLOR) + #define DN_UTEST_GOOD_COLOR "\x1b[32m" #endif -#define DQN_UTEST_COLOR_RESET "\x1b[0m" +#define DN_UTEST_COLOR_RESET "\x1b[0m" -#define DQN_UTEST_GROUP(test, fmt, ...) \ - for (Dqn_UTest *test_var_ = (printf(fmt "\n", ## __VA_ARGS__), &test); \ +#define DN_UTEST_GROUP(test, fmt, ...) \ + for (DN_UTest *test_var_ = (printf(fmt "\n", ## __VA_ARGS__), &test); \ test_var_ != nullptr; \ - Dqn_UTest_PrintStats(&test), test_var_ = nullptr) + DN_UTest_PrintStats(&test), test_var_ = nullptr) -#define DQN_UTEST_TEST(fmt, ...) \ - for (int dummy_ = (Dqn_UTest_Begin(test_var_, fmt, ## __VA_ARGS__), 0); \ - (void)dummy_, test_var_->state == Dqn_UTestState_TestBegun; \ - Dqn_UTest_End(test_var_)) +#define DN_UTEST_TEST(fmt, ...) \ + for (int dummy_ = (DN_UTest_Begin(test_var_, fmt, ## __VA_ARGS__), 0); \ + (void)dummy_, test_var_->state == DN_UTestState_TestBegun; \ + DN_UTest_End(test_var_)) -#define DQN_UTEST_ASSERTF(test, expr, fmt, ...) \ - DQN_UTEST_ASSERTF_AT((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__) +#define DN_UTEST_ASSERTF(test, expr, fmt, ...) \ + DN_UTEST_ASSERTF_AT((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__) -#define DQN_UTEST_ASSERT(test, expr) \ - DQN_UTEST_ASSERT_AT((test), __FILE__, __LINE__, (expr)) +#define DN_UTEST_ASSERT(test, expr) \ + DN_UTEST_ASSERT_AT((test), __FILE__, __LINE__, (expr)) // TODO: Fix the logs. They print before the tests, we should accumulate logs // per test, then, dump them on test on. But to do this nicely without crappy // mem management we need to implement an arena. -#define DQN_UTEST_LOG(fmt, ...) \ - fprintf(stdout, "%*s" fmt "\n", DQN_UTEST_SPACING * 2, "", ##__VA_ARGS__) +#define DN_UTEST_LOG(fmt, ...) \ + fprintf(stdout, "%*s" fmt "\n", DN_UTEST_SPACING * 2, "", ##__VA_ARGS__) -#define DQN_UTEST_ASSERTF_AT(test, file, line, expr, fmt, ...) \ +#define DN_UTEST_ASSERTF_AT(test, file, line, expr, fmt, ...) \ do { \ if (!(expr)) { \ - (test)->state = Dqn_UTestState_TestFailed; \ + (test)->state = DN_UTestState_TestFailed; \ fprintf(stderr, \ "%*sAssertion Triggered\n" \ "%*sFile: %s:%d\n" \ "%*sExpression: [" #expr "]\n" \ "%*sReason: " fmt "\n\n", \ - DQN_UTEST_SPACING * 2, \ + DN_UTEST_SPACING * 2, \ "", \ - DQN_UTEST_SPACING * 3, \ + DN_UTEST_SPACING * 3, \ "", \ file, \ line, \ - DQN_UTEST_SPACING * 3, \ + DN_UTEST_SPACING * 3, \ "", \ - DQN_UTEST_SPACING * 3, \ + DN_UTEST_SPACING * 3, \ "", \ ##__VA_ARGS__); \ } \ } while (0) -#define DQN_UTEST_ASSERT_AT(test, file, line, expr) \ +#define DN_UTEST_ASSERT_AT(test, file, line, expr) \ do { \ if (!(expr)) { \ - (test)->state = Dqn_UTestState_TestFailed; \ + (test)->state = DN_UTestState_TestFailed; \ fprintf(stderr, \ "%*sFile: %s:%d\n" \ "%*sExpression: [" #expr "]\n\n", \ - DQN_UTEST_SPACING * 2, \ + DN_UTEST_SPACING * 2, \ "", \ file, \ line, \ - DQN_UTEST_SPACING * 2, \ + DN_UTEST_SPACING * 2, \ ""); \ } \ } while (0) // NOTE: Header //////////////////////////////////////////////////////////////////////////////////// -typedef enum Dqn_UTestState { - Dqn_UTestState_Nil, - Dqn_UTestState_TestBegun, - Dqn_UTestState_TestFailed, -} Dqn_UTestState; +typedef enum DN_UTestState { + DN_UTestState_Nil, + DN_UTestState_TestBegun, + DN_UTestState_TestFailed, +} DN_UTestState; -typedef struct Dqn_UTest { +typedef struct DN_UTest { int num_tests_in_group; int num_tests_ok_in_group; - Dqn_UTestState state; + DN_UTestState state; bool finished; char name[256]; size_t name_size; -} Dqn_UTest; +} DN_UTest; -void Dqn_UTest_PrintStats(Dqn_UTest *test); -void Dqn_UTest_BeginV(Dqn_UTest *test, char const *fmt, va_list args); -void Dqn_UTest_Begin(Dqn_UTest *test, char const *fmt, ...); -void Dqn_UTest_End(Dqn_UTest *test); -#endif // DQN_UTEST_H +void DN_UTest_PrintStats(DN_UTest *test); +void DN_UTest_BeginV(DN_UTest *test, char const *fmt, va_list args); +void DN_UTest_Begin(DN_UTest *test, char const *fmt, ...); +void DN_UTest_End(DN_UTest *test); +#endif // DN_UTEST_H // NOTE: Implementation //////////////////////////////////////////////////////////////////////////// -#if defined(DQN_UTEST_IMPLEMENTATION) -void Dqn_UTest_PrintStats(Dqn_UTest *test) +#if defined(DN_UTEST_IMPLEMENTATION) +void DN_UTest_PrintStats(DN_UTest *test) { if (test->finished) return; @@ -171,21 +171,21 @@ void Dqn_UTest_PrintStats(Dqn_UTest *test) test->finished = true; bool all_clear = test->num_tests_ok_in_group == test->num_tests_in_group; fprintf(stdout, - "%s\n %02d/%02d tests passed -- %s\n\n" DQN_UTEST_COLOR_RESET, - all_clear ? DQN_UTEST_GOOD_COLOR : DQN_UTEST_BAD_COLOR, + "%s\n %02d/%02d tests passed -- %s\n\n" DN_UTEST_COLOR_RESET, + all_clear ? DN_UTEST_GOOD_COLOR : DN_UTEST_BAD_COLOR, test->num_tests_ok_in_group, test->num_tests_in_group, all_clear ? "OK" : "FAILED"); } -void Dqn_UTest_BeginV(Dqn_UTest *test, char const *fmt, va_list args) +void DN_UTest_BeginV(DN_UTest *test, char const *fmt, va_list args) { - assert(test->state == Dqn_UTestState_Nil && + assert(test->state == DN_UTestState_Nil && "Nesting a unit test within another unit test is not allowed, ensure" - "the first test has finished by calling Dqn_UTest_End"); + "the first test has finished by calling DN_UTest_End"); test->num_tests_in_group++; - test->state = Dqn_UTestState_TestBegun; + test->state = DN_UTestState_TestBegun; test->name_size = 0; { @@ -199,32 +199,32 @@ void Dqn_UTest_BeginV(Dqn_UTest *test, char const *fmt, va_list args) vsnprintf(test->name, sizeof(test->name), fmt, args); } -void Dqn_UTest_Begin(Dqn_UTest *test, char const *fmt, ...) +void DN_UTest_Begin(DN_UTest *test, char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_UTest_BeginV(test, fmt, args); + DN_UTest_BeginV(test, fmt, args); va_end(args); } -void Dqn_UTest_End(Dqn_UTest *test) +void DN_UTest_End(DN_UTest *test) { - assert(test->state != Dqn_UTestState_Nil && "Test was marked as ended but a test was never commenced using Dqn_UTest_Begin"); - size_t pad_size = DQN_UTEST_RESULT_LPAD - (DQN_UTEST_SPACING + test->name_size); + assert(test->state != DN_UTestState_Nil && "Test was marked as ended but a test was never commenced using DN_UTest_Begin"); + size_t pad_size = DN_UTEST_RESULT_LPAD - (DN_UTEST_SPACING + test->name_size); if (pad_size < 0) pad_size = 0; - char pad_buffer[DQN_UTEST_RESULT_LPAD] = {}; - memset(pad_buffer, DQN_UTEST_RESULT_PAD_CHAR, pad_size); + char pad_buffer[DN_UTEST_RESULT_LPAD] = {}; + memset(pad_buffer, DN_UTEST_RESULT_PAD_CHAR, pad_size); - printf("%*s%.*s%.*s", DQN_UTEST_SPACING, "", (int)test->name_size, test->name, (int)pad_size, pad_buffer); - if (test->state == Dqn_UTestState_TestFailed) { - printf(DQN_UTEST_BAD_COLOR " FAILED"); + printf("%*s%.*s%.*s", DN_UTEST_SPACING, "", (int)test->name_size, test->name, (int)pad_size, pad_buffer); + if (test->state == DN_UTestState_TestFailed) { + printf(DN_UTEST_BAD_COLOR " FAILED"); } else { - printf(DQN_UTEST_GOOD_COLOR " OK"); + printf(DN_UTEST_GOOD_COLOR " OK"); test->num_tests_ok_in_group++; } - printf(DQN_UTEST_COLOR_RESET "\n"); - test->state = Dqn_UTestState_Nil; + printf(DN_UTEST_COLOR_RESET "\n"); + test->state = DN_UTestState_Nil; } -#endif // DQN_UTEST_IMPLEMENTATION +#endif // DN_UTEST_IMPLEMENTATION diff --git a/build.bat b/build.bat index cf97194..e9ce6f1 100644 --- a/build.bat +++ b/build.bat @@ -13,7 +13,7 @@ pushd Build REM O2 Optimisation Level 2 REM Oi Use CPU Intrinsics REM Z7 Combine multi-debug files to one debug file - set common_flags=-D DQN_UNIT_TESTS_WITH_MAIN -D DQN_UNIT_TESTS_WITH_KECCAK -D DQN_USE_STD_PRINTF /Tp %script_dir%\dqn.cpp + set common_flags=-D DN_UNIT_TESTS_WITH_KECCAK -D DN_USE_STD_PRINTF %script_dir%\dqn_unit_tests_main.cpp set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo diff --git a/dqn.cpp b/dqn.cpp index 60eb796..e803c97 100644 --- a/dqn.cpp +++ b/dqn.cpp @@ -1,5 +1,7 @@ #include "dqn.h" +#define DN_CPP + /* //////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -17,29 +19,29 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -#if defined(DQN_WITH_CGEN) - #if !defined(DQN_NO_METADESK) - DQN_MSVC_WARNING_PUSH - DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: '': unreferenced function with internal linkage has been removed +#if defined(DN_WITH_CGEN) + #if !defined(DN_NO_METADESK) + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(4505) // warning C4505: '': unreferenced function with internal linkage has been removed - DQN_GCC_WARNING_PUSH - DQN_GCC_WARNING_DISABLE(-Wwrite-strings) - DQN_GCC_WARNING_DISABLE(-Wunused-but-set-variable) - DQN_GCC_WARNING_DISABLE(-Wsign-compare) - DQN_GCC_WARNING_DISABLE(-Wunused-function) - DQN_GCC_WARNING_DISABLE(-Wunused-result) + DN_GCC_WARNING_PUSH + DN_GCC_WARNING_DISABLE(-Wwrite-strings) + DN_GCC_WARNING_DISABLE(-Wunused-but-set-variable) + DN_GCC_WARNING_DISABLE(-Wsign-compare) + DN_GCC_WARNING_DISABLE(-Wunused-function) + DN_GCC_WARNING_DISABLE(-Wunused-result) #include "External/metadesk/md.c" - DQN_GCC_WARNING_POP - DQN_MSVC_WARNING_POP + DN_GCC_WARNING_POP + DN_MSVC_WARNING_POP #endif - #define DQN_CPP_FILE_IMPLEMENTATION + #define DN_CPP_FILE_IMPLEMENTATION #include "Standalone/dqn_cpp_file.h" #include "dqn_cgen.cpp" #endif -#if defined(DQN_WITH_JSON) +#if defined(DN_WITH_JSON) #include "dqn_json.cpp" #endif @@ -52,12 +54,12 @@ #include "dqn_type_info.cpp" #include "dqn_os.cpp" -#if defined(DQN_PLATFORM_EMSCRIPTEN) || defined(DQN_PLATFORM_POSIX) || defined(DQN_PLATFORM_ARM64) +#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_ARM64) #include "dqn_os_posix.cpp" -#elif defined(DQN_PLATFORM_WIN32) +#elif defined(DN_PLATFORM_WIN32) #include "dqn_os_win32.cpp" #else - #error Please define a platform e.g. 'DQN_PLATFORM_WIN32' to enable the correct implementation for platform APIs + #error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs #endif #include "dqn_tls.cpp" @@ -65,7 +67,7 @@ #include "dqn_hash.cpp" #include "dqn_helpers.cpp" -#if defined(DQN_WITH_UNIT_TESTS) +#if defined(DN_WITH_UNIT_TESTS) #include "dqn_unit_tests.cpp" #endif diff --git a/dqn.h b/dqn.h index f469835..8b97631 100644 --- a/dqn.h +++ b/dqn.h @@ -1,5 +1,5 @@ #pragma once -#define DQN_H +#define DN_H /* //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -14,7 +14,7 @@ // \_______/ \___$$$\ \__| \__| // \___| // -// dqn.h -- Personal standard library -- MIT License -- git.doylet.dev/dqn +// dqn.h -- Personal standard library -- MIT License -- git.doylet.dev/dn // ASCII -- BigMoney-NW by Nathan Bloomfild // //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -43,21 +43,21 @@ // // -- Compiling -- // -// Compile dqn.cpp or include it into one of your translation units. +// Compile dn.cpp or include it into one of your translation units. // // Additionally, this library supports including/excluding specific sections // of the library by using #define on the name of the section. These names are // documented in the section table of contents at the #define column, for // example: // -// #define DQN_ONLY_VARRAY -// #define DQN_ONLY_WIN +// #define DN_ONLY_VARRAY +// #define DN_ONLY_WIN // // Compiles the library with all optional APIs turned off except virtual arrays // and the Win32 helpers. Alternatively: // -// #define DQN_NO_VARRAY -// #define DQN_NO_WIN +// #define DN_NO_VARRAY +// #define DN_NO_WIN // // Compiles the library with all optional APIs turned on except the previously // mentioned APIs. @@ -69,7 +69,7 @@ // drowning out the library interface with code comments like many other // documentation systems. // -// Instead, documentation is laid out in dqn_docs.cpp in alphabetical order +// Instead, documentation is laid out in dn_docs.cpp in alphabetical order // which provides self-contained examples in one contiguous top-down block of // source code with comments. // @@ -91,51 +91,51 @@ // - Override these routines from the CRT by redefining them. By default we wrap // the CRT functions from and , e.g: // -// #define DQN_MEMCPY(dest, src, count) memcpy(dest, src, value) -// #define DQN_MEMSET(dest, value, count) memset(dest, value, count) -// #define DQN_MEMCMP(lhs, rhs, count) memcpy(lhs, rhs, count) -// #define DQN_MEMMOVE(dest, src, count) memmove(dest, src, count) -// #define DQN_SQRTF(val) sqrtf(val) -// #define DQN_SINF(val) sinf(val) -// #define DQN_COSF(val) cosf(val) -// #define DQN_TANF(val) tanf(val) +// #define DN_MEMCPY(dest, src, count) memcpy(dest, src, value) +// #define DN_MEMSET(dest, value, count) memset(dest, value, count) +// #define DN_MEMCMP(lhs, rhs, count) memcpy(lhs, rhs, count) +// #define DN_MEMMOVE(dest, src, count) memmove(dest, src, count) +// #define DN_SQRTF(val) sqrtf(val) +// #define DN_SINF(val) sinf(val) +// #define DN_COSF(val) cosf(val) +// #define DN_TANF(val) tanf(val) // -// - Redefine 'DQN_API' to change the prefix of all declared functions in the library +// - Redefine 'DN_API' to change the prefix of all declared functions in the library // -// #define DQN_API +// #define DN_API // -// - Define 'DQN_STATIC_API' to apply 'static' to all function definitions and -// disable external linkage to other translation units by redefining 'DQN_API' to +// - Define 'DN_STATIC_API' to apply 'static' to all function definitions and +// disable external linkage to other translation units by redefining 'DN_API' to // 'static'. // -// #define DQN_STATIC_API +// #define DN_STATIC_API // // - Turn all assertion macros to no-ops except for hard asserts (which are // always enabled and represent unrecoverable errors in the library). // -// #define DQN_NO_ASSERT +// #define DN_NO_ASSERT // -// - Augment DQN_CHECK(expr) macro's behaviour. By default when the check fails a +// - Augment DN_CHECK(expr) macro's behaviour. By default when the check fails a // debug break is emitted. If this macro is defined, the check will not trigger // a debug break. // -// #define DQN_NO_CHECK_BREAK +// #define DN_NO_CHECK_BREAK // // - Define this macro to enable memory leak tracking on arena's that are // configured to track allocations. // // Allocations are stored in a global hash-table and their respective stack // traces for the allocation location. Memory leaks can be dumped at the end -// of the program or some epoch by calling Dqn_Debug_DumpLeaks() +// of the program or some epoch by calling DN_Debug_DumpLeaks() // -// #define DQN_LEAK_TRACKING +// #define DN_LEAK_TRACKING // // - Define this to revert to the family of printf functions from // instead of using stb_sprintf in this library. stb_sprintf is 5-6x faster // than printf with a smaller binary footprint and has deterministic behaviour // across all supported platforms. // -// #define DQN_USE_STD_PRINTF +// #define DN_USE_STD_PRINTF // // However, if you are compiling with ASAN on MSVC, MSVC's implementation of // __declspec(no_sanitize_address) is unable to suppress warnings in some @@ -148,17 +148,17 @@ // intend to #include yourself to avoid symbol conflicts with // the redefined declarations in this library. // -// #define DQN_NO_WIN32_MIN_HEADER +// #define DN_NO_WIN32_MIN_HEADER // // - Define this to stop this library from defining STB_SPRINTF_IMPLEMENTATION. // Useful if another library uses and includes "stb_sprintf.h" // -// #define DQN_STB_SPRINTF_HEADER_ONLY +// #define DN_STB_SPRINTF_HEADER_ONLY // // - Override the default break into the active debugger function. By default // we use __debugbreak() on Windows and raise(SIGTRAP) on other platforms. // -// #define DQN_DEBUG_BREAK +// #define DN_DEBUG_BREAK // // - Define this macro to 1 to enable poisoning of memory from arenas when ASAN // `-fsanitize=address` is enabled. Enabling this will detect memory overwrite @@ -166,181 +166,188 @@ // a use-after-poison in ASAN on read/write. This is a no-op if the library is // not compiled with ASAN. // -// #define DQN_ASAN_POISON 1 +// #define DN_ASAN_POISON 1 // // - Define this macro 1 to enable sanity checks for manually poisoned memory in // this library when ASAN `-fsanitize=address` is enabled. These sanity checks // ensure that memory from arenas are correctly un/poisoned when pointers are // allocated and returned to the memory arena's. This is a no-op if we are not -// compiled with ASAN or `DQN_ASAN_POISON` is not set to `1`. +// compiled with ASAN or `DN_ASAN_POISON` is not set to `1`. // -// #define DQN_ASAN_VET_POISON 1 +// #define DN_ASAN_VET_POISON 1 // // - Define this macro to the size of the guard memory reserved before and after // allocations made that are poisoned to protect against out-of-bounds memory // accesses. By default the library sets the guard to 128 bytes. // -// #define DQN_ASAN_POISON_GUARD_SIZE 128 +// #define DN_ASAN_POISON_GUARD_SIZE 128 // -// - Enable 'Dqn_CGen' a parser that can emit run-time type information and +// - Enable 'DN_CGen' a parser that can emit run-time type information and // allow arbitrary querying of data definitions expressed in Excel-like tables // using text files encoded in Dion-System's Metadesk grammar. // -// This option automatically includes 'dqn_cpp_file.h' to assist with code +// This option automatically includes 'dn_cpp_file.h' to assist with code // generation and Metadesk's 'md.h' and its implementation library. // -// #define DQN_WITH_CGEN +// #define DN_WITH_CGEN // -// Optionally define 'DQN_NO_METADESK' to disable the inclusion of Metadesk +// Optionally define 'DN_NO_METADESK' to disable the inclusion of Metadesk // in the library. This might be useful if you are including the librarin in // your project yourself. This library must still be defined and visible // before this header. // -// - Enable 'Dqn_JSON' a json parser. This option requires Sheredom's 'json.h' +// - Enable 'DN_JSON' a json parser. This option requires Sheredom's 'json.h' // to be included prior to this file. // -// #define DQN_WITH_JSON +// #define DN_WITH_JSON // -// Optionally define 'DQN_NO_SHEREDOM_JSON' to prevent Sheredom's 'json.h' +// Optionally define 'DN_NO_SHEREDOM_JSON' to prevent Sheredom's 'json.h' // library from being included. This might be useful if you are including the // library in your project yourself. The library must still be defined and // visible before this header. // // - Enable compilation of unit tests with the library. // -// #define DQN_WITH_UNIT_TESTS +// #define DN_WITH_UNIT_TESTS // // - Increase the capacity of the job queue, default is 128. // -// #define DQN_JOB_QUEUE_SPMC_SIZE 128 +// #define DN_JOB_QUEUE_SPMC_SIZE 128 */ -#if defined(DQN_ONLY_VARRAY) || \ - defined(DQN_ONLY_SARRAY) || \ - defined(DQN_ONLY_FARRAY) || \ - defined(DQN_ONLY_DSMAP) || \ - defined(DQN_ONLY_LIST) || \ - defined(DQN_ONLY_FSTR8) || \ - defined(DQN_ONLY_FS) || \ - defined(DQN_ONLY_WINNET) || \ - defined(DQN_ONLY_WIN) || \ - defined(DQN_ONLY_SEMAPHORE) || \ - defined(DQN_ONLY_THREAD) || \ - defined(DQN_ONLY_V2) || \ - defined(DQN_ONLY_V3) || \ - defined(DQN_ONLY_V4) || \ - defined(DQN_ONLY_M4) || \ - defined(DQN_ONLY_RECT) || \ - defined(DQN_ONLY_JSON_BUILDER) || \ - defined(DQN_ONLY_BIN) || \ - defined(DQN_ONLY_PROFILER) +#if defined(DN_ONLY_VARRAY) || \ + defined(DN_ONLY_SARRAY) || \ + defined(DN_ONLY_FARRAY) || \ + defined(DN_ONLY_DSMAP) || \ + defined(DN_ONLY_LIST) || \ + defined(DN_ONLY_FSTR8) || \ + defined(DN_ONLY_FS) || \ + defined(DN_ONLY_WINNET) || \ + defined(DN_ONLY_WIN) || \ + defined(DN_ONLY_SEMAPHORE) || \ + defined(DN_ONLY_THREAD) || \ + defined(DN_ONLY_V2) || \ + defined(DN_ONLY_V3) || \ + defined(DN_ONLY_V4) || \ + defined(DN_ONLY_M4) || \ + defined(DN_ONLY_RECT) || \ + defined(DN_ONLY_JSON_BUILDER) || \ + defined(DN_ONLY_BIN) || \ + defined(DN_ONLY_PROFILER) - #if !defined(DQN_ONLY_VARRAY) - #define DQN_NO_VARRAY + #if !defined(DN_ONLY_VARRAY) + #define DN_NO_VARRAY #endif - #if !defined(DQN_ONLY_FARRAY) - #define DQN_NO_FARRAY + #if !defined(DN_ONLY_FARRAY) + #define DN_NO_FARRAY #endif - #if !defined(DQN_ONLY_SARRAY) - #define DQN_NO_SARRAY + #if !defined(DN_ONLY_SARRAY) + #define DN_NO_SARRAY #endif - #if !defined(DQN_ONLY_DSMAP) - #define DQN_NO_DSMAP + #if !defined(DN_ONLY_DSMAP) + #define DN_NO_DSMAP #endif - #if !defined(DQN_ONLY_LIST) - #define DQN_NO_LIST + #if !defined(DN_ONLY_LIST) + #define DN_NO_LIST #endif - #if !defined(DQN_ONLY_FSTR8) - #define DQN_NO_FSTR8 + #if !defined(DN_ONLY_FSTR8) + #define DN_NO_FSTR8 #endif - #if !defined(DQN_ONLY_FS) - #define DQN_NO_FS + #if !defined(DN_ONLY_FS) + #define DN_NO_FS #endif - #if !defined(DQN_ONLY_WINNET) - #define DQN_NO_WINNET + #if !defined(DN_ONLY_WINNET) + #define DN_NO_WINNET #endif - #if !defined(DQN_ONLY_WIN) - #define DQN_NO_WIN + #if !defined(DN_ONLY_WIN) + #define DN_NO_WIN #endif - #if !defined(DQN_ONLY_SEMAPHORE) - #define DQN_NO_SEMAPHORE + #if !defined(DN_ONLY_SEMAPHORE) + #define DN_NO_SEMAPHORE #endif - #if !defined(DQN_ONLY_THREAD) - #define DQN_NO_THREAD + #if !defined(DN_ONLY_THREAD) + #define DN_NO_THREAD #endif - #if !defined(DQN_ONLY_V2) - #define DQN_NO_V2 + #if !defined(DN_ONLY_V2) + #define DN_NO_V2 #endif - #if !defined(DQN_ONLY_V3) - #define DQN_NO_V3 + #if !defined(DN_ONLY_V3) + #define DN_NO_V3 #endif - #if !defined(DQN_ONLY_V4) - #define DQN_NO_V4 + #if !defined(DN_ONLY_V4) + #define DN_NO_V4 #endif - #if !defined(DQN_ONLY_M4) - #define DQN_NO_M4 + #if !defined(DN_ONLY_M4) + #define DN_NO_M4 #endif - #if !defined(DQN_ONLY_RECT) - #define DQN_NO_RECT + #if !defined(DN_ONLY_RECT) + #define DN_NO_RECT #endif - #if !defined(DQN_ONLY_JSON_BUILDER) - #define DQN_NO_JSON_BUILDER + #if !defined(DN_ONLY_JSON_BUILDER) + #define DN_NO_JSON_BUILDER #endif - #if !defined(DQN_ONLY_BIN) - #define DQN_NO_BIN + #if !defined(DN_ONLY_BIN) + #define DN_NO_BIN #endif - #if !defined(DQN_ONLY_PROFILER) - #define DQN_NO_PROFILER + #if !defined(DN_ONLY_PROFILER) + #define DN_NO_PROFILER #endif #endif -#if defined(DQN_WITH_CGEN) - #if !defined(DQN_NO_METADESK) +#include "dqn_base.h" +#if defined(DN_WITH_CGEN) + #if !defined(DN_NO_METADESK) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS - #define DQN_UNDO_CRT_SECURE_NO_WARNINGS + #define DN_UNDO_CRT_SECURE_NO_WARNINGS #endif + + // NOTE: Metadesk does not have the header for 'size_t' + #if defined(DN_COMPILER_GCC) + #include + #endif + #define MD_DEFAULT_SPRINTF 0 - #define MD_IMPL_Vsnprintf DQN_VSNPRINTF + #define MD_IMPL_Vsnprintf DN_VSNPRINTF #include "External/metadesk/md.h" - #if defined(DQN_UNDO_CRT_SECURE_NO_WARNINGS) + #if defined(DN_UNDO_CRT_SECURE_NO_WARNINGS) #undef _CRT_SECURE_NO_WARNINGS #endif #endif // Metadesk includes Windows.h - #define DQN_NO_WIN32_MIN_HEADER + #define DN_NO_WIN32_MIN_HEADER #endif -#include "dqn_base.h" #include "dqn_external.h" -#if defined(DQN_PLATFORM_WIN32) +#if defined(DN_PLATFORM_WIN32) #include "dqn_win32.h" #endif #include "dqn_allocator.h" #include "dqn_tls.h" #include "dqn_debug.h" #include "dqn_string.h" -#include "dqn_containers.h" -#if defined(DQN_PLATFORM_EMSCRIPTEN) || defined(DQN_PLATFORM_POSIX) || defined(DQN_PLATFORM_ARM64) -#elif defined(DQN_PLATFORM_WIN32) +#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_ARM64) + #include "dqn_os_posix.h" +#elif defined(DN_PLATFORM_WIN32) #include "dqn_os_win32.h" #else - #error Please define a platform e.g. 'DQN_PLATFORM_WIN32' to enable the correct implementation for platform APIs + #error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs #endif #include "dqn_os.h" +#include "dqn_containers.h" #include "dqn_math.h" #include "dqn_hash.h" #include "dqn_helpers.h" #include "dqn_type_info.h" -#if defined(DQN_WITH_CGEN) +#if defined(DN_WITH_CGEN) #include "Standalone/dqn_cpp_file.h" #include "dqn_cgen.h" #endif -#if defined(DQN_WITH_JSON) - #if !defined(DQN_NO_SHEREDOM_JSON) +#if defined(DN_WITH_JSON) + #if !defined(DN_NO_SHEREDOM_JSON) #include "External/json.h" #endif #include "dqn_json.h" diff --git a/dqn_allocator.cpp b/dqn_allocator.cpp index aabc222..37c9bab 100644 --- a/dqn_allocator.cpp +++ b/dqn_allocator.cpp @@ -15,265 +15,303 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$AREN] Dqn_Arena ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_ArenaBlock *Dqn_Arena_BlockInit(uint64_t reserve, uint64_t commit, bool track_alloc, bool alloc_can_leak) +// NOTE: [$AREN] DN_Arena ///////////////////////////////////////////////////////////////////////// +DN_API DN_ArenaBlock *DN_Arena_BlockInit(DN_U64 reserve, DN_U64 commit, bool track_alloc, bool alloc_can_leak) { - Dqn_usize const page_size = g_dqn_library->os_page_size; - uint64_t real_reserve = reserve ? reserve : DQN_ARENA_RESERVE_SIZE; - uint64_t real_commit = commit ? commit : DQN_ARENA_COMMIT_SIZE; - real_reserve = Dqn_AlignUpPowerOfTwo(real_reserve, page_size); - real_commit = DQN_MIN(Dqn_AlignUpPowerOfTwo(real_commit, page_size), real_reserve); + DN_USize const page_size = g_dn_core->os_page_size; + DN_U64 real_reserve = reserve ? reserve : DN_ARENA_RESERVE_SIZE; + DN_U64 real_commit = commit ? commit : DN_ARENA_COMMIT_SIZE; + real_reserve = DN_AlignUpPowerOfTwo(real_reserve, page_size); + real_commit = DN_MIN(DN_AlignUpPowerOfTwo(real_commit, page_size), real_reserve); - DQN_ASSERTF(DQN_ARENA_HEADER_SIZE < real_commit && real_commit <= real_reserve, "%I64u < %I64u <= %I64u", DQN_ARENA_HEADER_SIZE, real_commit, real_reserve); - DQN_ASSERTF(page_size, "Call Dqn_Library_Init() to initialise the known page size"); + DN_ASSERTF(DN_ARENA_HEADER_SIZE < real_commit && real_commit <= real_reserve, "%I64u < %I64u <= %I64u", DN_ARENA_HEADER_SIZE, real_commit, real_reserve); + DN_ASSERTF(page_size, "Call DN_Library_Init() to initialise the known page size"); - Dqn_OSMemCommit mem_commit = real_reserve == real_commit ? Dqn_OSMemCommit_Yes : Dqn_OSMemCommit_No; - Dqn_ArenaBlock *result = DQN_CAST(Dqn_ArenaBlock *)Dqn_OS_MemReserve(real_reserve, mem_commit, Dqn_OSMemPage_ReadWrite); + DN_OSMemCommit mem_commit = real_reserve == real_commit ? DN_OSMemCommit_Yes : DN_OSMemCommit_No; + DN_ArenaBlock *result = DN_CAST(DN_ArenaBlock *)DN_OS_MemReserve(real_reserve, mem_commit, DN_OSMemPage_ReadWrite); if (!result) return result; - if (mem_commit == Dqn_OSMemCommit_No && !Dqn_OS_MemCommit(result, real_commit, Dqn_OSMemPage_ReadWrite)) { - Dqn_OS_MemRelease(result, real_reserve); + if (mem_commit == DN_OSMemCommit_No && !DN_OS_MemCommit(result, real_commit, DN_OSMemPage_ReadWrite)) { + DN_OS_MemRelease(result, real_reserve); return result; } - result->used = DQN_ARENA_HEADER_SIZE; + result->used = DN_ARENA_HEADER_SIZE; result->commit = real_commit; result->reserve = real_reserve; if (track_alloc) - Dqn_Debug_TrackAlloc(result, result->reserve, alloc_can_leak); + DN_Debug_TrackAlloc(result, result->reserve, alloc_can_leak); return result; } -DQN_API Dqn_ArenaBlock *Dqn_Arena_BlockInitFlags(uint64_t reserve, uint64_t commit, uint8_t arena_flags) +DN_API DN_ArenaBlock *DN_Arena_BlockInitFlags(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags) { - bool track_alloc = (arena_flags & Dqn_ArenaFlag_NoAllocTrack) == 0; - bool alloc_can_leak = arena_flags & Dqn_ArenaFlag_AllocCanLeak; - Dqn_ArenaBlock *result = Dqn_Arena_BlockInit(reserve, commit, track_alloc, alloc_can_leak); - if (result && ((arena_flags & Dqn_ArenaFlag_NoPoison) == 0)) - Dqn_ASAN_PoisonMemoryRegion(DQN_CAST(char *)result + DQN_ARENA_HEADER_SIZE, result->commit - DQN_ARENA_HEADER_SIZE); + bool track_alloc = (flags & DN_ArenaFlags_NoAllocTrack) == 0; + bool alloc_can_leak = flags & DN_ArenaFlags_AllocCanLeak; + DN_ArenaBlock *result = DN_Arena_BlockInit(reserve, commit, track_alloc, alloc_can_leak); + if (result && ((flags & DN_ArenaFlags_NoPoison) == 0)) + DN_ASAN_PoisonMemoryRegion(DN_CAST(char *)result + DN_ARENA_HEADER_SIZE, result->commit - DN_ARENA_HEADER_SIZE); return result; } -static void Dqn_Arena_UpdateStatsOnNewBlock_(Dqn_Arena *arena, Dqn_ArenaBlock const *block) +static void DN_Arena_UpdateStatsOnNewBlock_(DN_Arena *arena, DN_ArenaBlock const *block) { - DQN_ASSERT(arena); + DN_ASSERT(arena); if (block) { arena->stats.info.used += block->used; arena->stats.info.commit += block->commit; arena->stats.info.reserve += block->reserve; arena->stats.info.blocks += 1; - arena->stats.hwm.used = DQN_MAX(arena->stats.hwm.used, arena->stats.info.used); - arena->stats.hwm.commit = DQN_MAX(arena->stats.hwm.commit, arena->stats.info.commit); - arena->stats.hwm.reserve = DQN_MAX(arena->stats.hwm.reserve, arena->stats.info.reserve); - arena->stats.hwm.blocks = DQN_MAX(arena->stats.hwm.blocks, arena->stats.info.blocks); + arena->stats.hwm.used = DN_MAX(arena->stats.hwm.used, arena->stats.info.used); + arena->stats.hwm.commit = DN_MAX(arena->stats.hwm.commit, arena->stats.info.commit); + arena->stats.hwm.reserve = DN_MAX(arena->stats.hwm.reserve, arena->stats.info.reserve); + arena->stats.hwm.blocks = DN_MAX(arena->stats.hwm.blocks, arena->stats.info.blocks); } } -DQN_API Dqn_Arena Dqn_Arena_InitSize(uint64_t reserve, uint64_t commit, uint8_t flags) +DN_API DN_Arena DN_Arena_InitBuffer(void *buffer, DN_USize size, DN_ArenaFlags flags) { - Dqn_Arena result = {}; - result.flags = flags; - result.curr = Dqn_Arena_BlockInitFlags(reserve, commit, flags); - Dqn_Arena_UpdateStatsOnNewBlock_(&result, result.curr); + DN_ASSERT(buffer); + DN_ASSERTF(DN_ARENA_HEADER_SIZE < size, "Buffer (%zu bytes) too small, need atleast %zu bytes to store arena metadata", size, DN_ARENA_HEADER_SIZE); + DN_ASSERTF(DN_IsPowerOfTwo(size), "Buffer (%zu bytes) must be a power-of-two", size); + + // NOTE: Init block + DN_ArenaBlock *block = DN_CAST(DN_ArenaBlock *) buffer; + block->commit = size; + block->reserve = size; + block->used = DN_ARENA_HEADER_SIZE; + if (block && ((flags & DN_ArenaFlags_NoPoison) == 0)) { + DN_ASAN_PoisonMemoryRegion(DN_CAST(char *)block + DN_ARENA_HEADER_SIZE, block->commit - DN_ARENA_HEADER_SIZE); + } + + DN_Arena result = {}; + result.flags = flags | DN_ArenaFlags_NoGrow | DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_UserBuffer; + result.curr = block; + DN_Arena_UpdateStatsOnNewBlock_(&result, result.curr); return result; } -static void Dqn_Arena_BlockDeinit_(Dqn_Arena const *arena, Dqn_ArenaBlock *block) +DN_API DN_Arena DN_Arena_InitSize(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags) { - Dqn_usize release_size = block->reserve; - if (Dqn_Bit_IsNotSet(arena->flags, Dqn_ArenaFlag_NoAllocTrack)) - Dqn_Debug_TrackDealloc(block); - Dqn_ASAN_UnpoisonMemoryRegion(block, block->commit); - Dqn_OS_MemRelease(block, release_size); + DN_Arena result = {}; + result.flags = flags; + result.curr = DN_Arena_BlockInitFlags(reserve, commit, flags); + DN_Arena_UpdateStatsOnNewBlock_(&result, result.curr); + return result; } -DQN_API void Dqn_Arena_Deinit(Dqn_Arena *arena) +static void DN_Arena_BlockDeinit_(DN_Arena const *arena, DN_ArenaBlock *block) { - for (Dqn_ArenaBlock *block = arena ? arena->curr : nullptr; block; ) { - Dqn_ArenaBlock *block_to_free = block; + DN_USize release_size = block->reserve; + if (DN_Bit_IsNotSet(arena->flags, DN_ArenaFlags_NoAllocTrack)) + DN_Debug_TrackDealloc(block); + DN_ASAN_UnpoisonMemoryRegion(block, block->commit); + DN_OS_MemRelease(block, release_size); +} + +DN_API void DN_Arena_Deinit(DN_Arena *arena) +{ + for (DN_ArenaBlock *block = arena ? arena->curr : nullptr; block; ) { + DN_ArenaBlock *block_to_free = block; block = block->prev; - Dqn_Arena_BlockDeinit_(arena, block_to_free); + DN_Arena_BlockDeinit_(arena, block_to_free); } + if (arena) + *arena = {}; } -DQN_API bool Dqn_Arena_CommitTo(Dqn_Arena *arena, uint64_t pos) +DN_API bool DN_Arena_CommitTo(DN_Arena *arena, DN_U64 pos) { if (!arena || !arena->curr) return false; - Dqn_ArenaBlock *curr = arena->curr; + DN_ArenaBlock *curr = arena->curr; if (pos <= curr->commit) return true; - uint64_t real_pos = pos; - if (!DQN_CHECK(pos <= curr->reserve)) + DN_U64 real_pos = pos; + if (!DN_CHECK(pos <= curr->reserve)) real_pos = curr->reserve; - Dqn_usize end_commit = Dqn_AlignUpPowerOfTwo(real_pos, g_dqn_library->os_page_size); - Dqn_usize commit_size = end_commit - curr->commit; - char *commit_ptr = DQN_CAST(char *) curr + curr->commit; - if (!Dqn_OS_MemCommit(commit_ptr, commit_size, Dqn_OSMemPage_ReadWrite)) + DN_USize end_commit = DN_AlignUpPowerOfTwo(real_pos, g_dn_core->os_page_size); + DN_USize commit_size = end_commit - curr->commit; + char *commit_ptr = DN_CAST(char *) curr + curr->commit; + if (!DN_OS_MemCommit(commit_ptr, commit_size, DN_OSMemPage_ReadWrite)) return false; - bool poison = DQN_ASAN_POISON && ((arena->flags & Dqn_ArenaFlag_NoPoison) == 0); + bool poison = DN_ASAN_POISON && ((arena->flags & DN_ArenaFlags_NoPoison) == 0); if (poison) - Dqn_ASAN_PoisonMemoryRegion(commit_ptr, commit_size); + DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size); curr->commit = end_commit; return true; } -DQN_API bool Dqn_Arena_Commit(Dqn_Arena *arena, uint64_t size) +DN_API bool DN_Arena_Commit(DN_Arena *arena, DN_U64 size) { if (!arena || !arena->curr) return false; - uint64_t pos = arena->curr->commit + size; - bool result = Dqn_Arena_CommitTo(arena, pos); + DN_U64 pos = arena->curr->commit + size; + bool result = DN_Arena_CommitTo(arena, pos); return result; } -DQN_API void *Dqn_Arena_Alloc(Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem) +DN_API bool DN_Arena_Grow(DN_Arena *arena, DN_U64 reserve, DN_U64 commit) +{ + if (arena->flags & (DN_ArenaFlags_NoGrow | DN_ArenaFlags_UserBuffer)) + return false; + + DN_ArenaBlock *new_block = DN_Arena_BlockInitFlags(reserve, commit, arena->flags); + if (new_block) { + new_block->prev = arena->curr; + arena->curr = new_block; + new_block->reserve_sum = new_block->prev->reserve_sum + new_block->prev->reserve; + DN_Arena_UpdateStatsOnNewBlock_(arena, arena->curr); + } + bool result = new_block; + return result; +} + +DN_API void *DN_Arena_Alloc(DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem) { if (!arena) return nullptr; if (!arena->curr) { - arena->curr = Dqn_Arena_BlockInitFlags(DQN_ARENA_RESERVE_SIZE, DQN_ARENA_COMMIT_SIZE, arena->flags); - Dqn_Arena_UpdateStatsOnNewBlock_(arena, arena->curr); + arena->curr = DN_Arena_BlockInitFlags(DN_ARENA_RESERVE_SIZE, DN_ARENA_COMMIT_SIZE, arena->flags); + DN_Arena_UpdateStatsOnNewBlock_(arena, arena->curr); } if (!arena->curr) return nullptr; try_alloc_again: - Dqn_ArenaBlock *curr = arena->curr; - bool poison = DQN_ASAN_POISON && ((arena->flags & Dqn_ArenaFlag_NoPoison) == 0); - uint8_t real_align = poison ? DQN_MAX(align, DQN_ASAN_POISON_ALIGNMENT) : align; - uint64_t offset_pos = Dqn_AlignUpPowerOfTwo(curr->used, real_align) + (poison ? DQN_ASAN_POISON_GUARD_SIZE : 0); - uint64_t end_pos = offset_pos + size; + DN_ArenaBlock *curr = arena->curr; + bool poison = DN_ASAN_POISON && ((arena->flags & DN_ArenaFlags_NoPoison) == 0); + uint8_t real_align = poison ? DN_MAX(align, DN_ASAN_POISON_ALIGNMENT) : align; + DN_U64 offset_pos = DN_AlignUpPowerOfTwo(curr->used, real_align) + (poison ? DN_ASAN_POISON_GUARD_SIZE : 0); + DN_U64 end_pos = offset_pos + size; + DN_U64 alloc_size = end_pos - curr->used; if (end_pos > curr->reserve) { - if (arena->flags & Dqn_ArenaFlag_NoGrow) + if (arena->flags & (DN_ArenaFlags_NoGrow | DN_ArenaFlags_UserBuffer)) return nullptr; - Dqn_usize new_reserve = DQN_MAX(DQN_ARENA_HEADER_SIZE + size, DQN_ARENA_RESERVE_SIZE); - Dqn_usize new_commit = DQN_MAX(DQN_ARENA_HEADER_SIZE + size, DQN_ARENA_COMMIT_SIZE); - Dqn_ArenaBlock *new_block = Dqn_Arena_BlockInitFlags(new_reserve, new_commit, arena->flags); - if (!new_block) + DN_USize new_reserve = DN_MAX(DN_ARENA_HEADER_SIZE + alloc_size, DN_ARENA_RESERVE_SIZE); + DN_USize new_commit = DN_MAX(DN_ARENA_HEADER_SIZE + alloc_size, DN_ARENA_COMMIT_SIZE); + if (!DN_Arena_Grow(arena, new_reserve, new_commit)) return nullptr; - new_block->prev = arena->curr; - arena->curr = new_block; - new_block->reserve_sum = new_block->prev->reserve_sum + new_block->prev->reserve; - Dqn_Arena_UpdateStatsOnNewBlock_(arena, arena->curr); goto try_alloc_again; } - Dqn_usize prev_arena_commit = curr->commit; + DN_USize prev_arena_commit = curr->commit; if (end_pos > curr->commit) { - Dqn_usize end_commit = Dqn_AlignUpPowerOfTwo(end_pos, g_dqn_library->os_page_size); - Dqn_usize commit_size = end_commit - curr->commit; - char *commit_ptr = DQN_CAST(char *)curr + curr->commit; - if (!Dqn_OS_MemCommit(commit_ptr, commit_size, Dqn_OSMemPage_ReadWrite)) + DN_ASSERT((arena->flags & DN_ArenaFlags_UserBuffer) == 0); + DN_USize end_commit = DN_AlignUpPowerOfTwo(end_pos, g_dn_core->os_page_size); + DN_USize commit_size = end_commit - curr->commit; + char *commit_ptr = DN_CAST(char *) curr + curr->commit; + if (!DN_OS_MemCommit(commit_ptr, commit_size, DN_OSMemPage_ReadWrite)) return nullptr; if (poison) - Dqn_ASAN_PoisonMemoryRegion(commit_ptr, commit_size); + DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size); curr->commit = end_commit; arena->stats.info.commit += commit_size; - arena->stats.hwm.commit = DQN_MAX(arena->stats.hwm.commit, arena->stats.info.commit); + arena->stats.hwm.commit = DN_MAX(arena->stats.hwm.commit, arena->stats.info.commit); } - void *result = DQN_CAST(char *) curr + offset_pos; - Dqn_usize alloc_size = end_pos - curr->used; + void *result = DN_CAST(char *) curr + offset_pos; curr->used += alloc_size; arena->stats.info.used += alloc_size; - arena->stats.hwm.used = DQN_MAX(arena->stats.hwm.used, arena->stats.info.used); - Dqn_ASAN_UnpoisonMemoryRegion(result, size); + arena->stats.hwm.used = DN_MAX(arena->stats.hwm.used, arena->stats.info.used); + DN_ASAN_UnpoisonMemoryRegion(result, size); - if (zero_mem == Dqn_ZeroMem_Yes) { - Dqn_usize reused_bytes = DQN_MIN(prev_arena_commit - offset_pos, size); - DQN_MEMSET(result, 0, reused_bytes); + if (zero_mem == DN_ZeroMem_Yes) { + DN_USize reused_bytes = DN_MIN(prev_arena_commit - offset_pos, size); + DN_MEMSET(result, 0, reused_bytes); } - DQN_ASSERT(arena->stats.hwm.used >= arena->stats.info.used); - DQN_ASSERT(arena->stats.hwm.commit >= arena->stats.info.commit); - DQN_ASSERT(arena->stats.hwm.reserve >= arena->stats.info.reserve); - DQN_ASSERT(arena->stats.hwm.blocks >= arena->stats.info.blocks); + DN_ASSERT(arena->stats.hwm.used >= arena->stats.info.used); + DN_ASSERT(arena->stats.hwm.commit >= arena->stats.info.commit); + DN_ASSERT(arena->stats.hwm.reserve >= arena->stats.info.reserve); + DN_ASSERT(arena->stats.hwm.blocks >= arena->stats.info.blocks); return result; } -DQN_API void *Dqn_Arena_AllocContiguous(Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem) +DN_API void *DN_Arena_AllocContiguous(DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem) { - uint8_t prev_flags = arena->flags; - arena->flags |= (Dqn_ArenaFlag_NoGrow | Dqn_ArenaFlag_NoPoison); - void *memory = Dqn_Arena_Alloc(arena, size, align, zero_mem); - arena->flags = prev_flags; + DN_ArenaFlags prev_flags = arena->flags; + arena->flags |= (DN_ArenaFlags_NoGrow | DN_ArenaFlags_NoPoison); + void *memory = DN_Arena_Alloc(arena, size, align, zero_mem); + arena->flags = prev_flags; return memory; } -DQN_API void *Dqn_Arena_Copy(Dqn_Arena *arena, void const *data, uint64_t size, uint8_t align) +DN_API void *DN_Arena_Copy(DN_Arena *arena, void const *data, DN_U64 size, uint8_t align) { if (!arena || !data || size == 0) return nullptr; - void *result = Dqn_Arena_Alloc(arena, size, align, Dqn_ZeroMem_No); + void *result = DN_Arena_Alloc(arena, size, align, DN_ZeroMem_No); if (result) - DQN_MEMCPY(result, data, size); + DN_MEMCPY(result, data, size); return result; } -DQN_API void Dqn_Arena_PopTo(Dqn_Arena *arena, uint64_t init_used) +DN_API void DN_Arena_PopTo(DN_Arena *arena, DN_U64 init_used) { if (!arena || !arena->curr) return; - uint64_t used = DQN_MAX(DQN_ARENA_HEADER_SIZE, init_used); - Dqn_ArenaBlock *curr = arena->curr; + DN_U64 used = DN_MAX(DN_ARENA_HEADER_SIZE, init_used); + DN_ArenaBlock *curr = arena->curr; while (curr->reserve_sum >= used) { - Dqn_ArenaBlock *block_to_free = curr; + DN_ArenaBlock *block_to_free = curr; arena->stats.info.used -= block_to_free->used; arena->stats.info.commit -= block_to_free->commit; arena->stats.info.reserve -= block_to_free->reserve; arena->stats.info.blocks -= 1; + if (arena->flags & DN_ArenaFlags_UserBuffer) + break; curr = curr->prev; - Dqn_Arena_BlockDeinit_(arena, block_to_free); + DN_Arena_BlockDeinit_(arena, block_to_free); } arena->stats.info.used -= curr->used; arena->curr = curr; curr->used = used - curr->reserve_sum; - char *poison_ptr = (char *)curr + Dqn_AlignUpPowerOfTwo(curr->used, DQN_ASAN_POISON_ALIGNMENT); - Dqn_usize poison_size = ((char *)curr + curr->commit) - poison_ptr; - Dqn_ASAN_PoisonMemoryRegion(poison_ptr, poison_size); + char *poison_ptr = (char *)curr + DN_AlignUpPowerOfTwo(curr->used, DN_ASAN_POISON_ALIGNMENT); + DN_USize poison_size = ((char *)curr + curr->commit) - poison_ptr; + DN_ASAN_PoisonMemoryRegion(poison_ptr, poison_size); arena->stats.info.used += curr->used; } -DQN_API void Dqn_Arena_Pop(Dqn_Arena *arena, uint64_t amount) +DN_API void DN_Arena_Pop(DN_Arena *arena, DN_U64 amount) { - Dqn_ArenaBlock *curr = arena->curr; - Dqn_usize used_sum = curr->reserve_sum + curr->used; - if (!DQN_CHECK(amount <= used_sum)) + DN_ArenaBlock *curr = arena->curr; + DN_USize used_sum = curr->reserve_sum + curr->used; + if (!DN_CHECK(amount <= used_sum)) amount = used_sum; - Dqn_usize pop_to = used_sum - amount; - Dqn_Arena_PopTo(arena, pop_to); + DN_USize pop_to = used_sum - amount; + DN_Arena_PopTo(arena, pop_to); } -DQN_API uint64_t Dqn_Arena_Pos(Dqn_Arena const *arena) +DN_API DN_U64 DN_Arena_Pos(DN_Arena const *arena) { - uint64_t result = (arena && arena->curr) ? arena->curr->reserve_sum + arena->curr->used : 0; + DN_U64 result = (arena && arena->curr) ? arena->curr->reserve_sum + arena->curr->used : 0; return result; } -DQN_API void Dqn_Arena_Clear(Dqn_Arena *arena) +DN_API void DN_Arena_Clear(DN_Arena *arena) { - Dqn_Arena_PopTo(arena, 0); + DN_Arena_PopTo(arena, 0); } -DQN_API bool Dqn_Arena_OwnsPtr(Dqn_Arena const *arena, void *ptr) +DN_API bool DN_Arena_OwnsPtr(DN_Arena const *arena, void *ptr) { bool result = false; - uintptr_t uint_ptr = DQN_CAST(uintptr_t)ptr; - for (Dqn_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; block = block->prev) { - uintptr_t begin = DQN_CAST(uintptr_t) block + DQN_ARENA_HEADER_SIZE; + uintptr_t uint_ptr = DN_CAST(uintptr_t)ptr; + for (DN_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; block = block->prev) { + uintptr_t begin = DN_CAST(uintptr_t) block + DN_ARENA_HEADER_SIZE; uintptr_t end = begin + block->reserve; result = uint_ptr >= begin && uint_ptr <= end; } @@ -281,120 +319,118 @@ DQN_API bool Dqn_Arena_OwnsPtr(Dqn_Arena const *arena, void *ptr) } -DQN_API Dqn_ArenaStats Dqn_Arena_SumStatsArray(Dqn_ArenaStats const *array, Dqn_usize size) +DN_API DN_ArenaStats DN_Arena_SumStatsArray(DN_ArenaStats const *array, DN_USize size) { - Dqn_ArenaStats result = {}; - DQN_FOR_UINDEX(index, size) { - Dqn_ArenaStats stats = array[index]; + DN_ArenaStats result = {}; + DN_FOR_UINDEX(index, size) { + DN_ArenaStats stats = array[index]; result.info.used += stats.info.used; result.info.commit += stats.info.commit; result.info.reserve += stats.info.reserve; result.info.blocks += stats.info.blocks; - result.hwm.used = DQN_MAX(result.hwm.used, result.info.used); - result.hwm.commit = DQN_MAX(result.hwm.commit, result.info.commit); - result.hwm.reserve = DQN_MAX(result.hwm.reserve, result.info.reserve); - result.hwm.blocks = DQN_MAX(result.hwm.blocks, result.info.blocks); + result.hwm.used = DN_MAX(result.hwm.used, result.info.used); + result.hwm.commit = DN_MAX(result.hwm.commit, result.info.commit); + result.hwm.reserve = DN_MAX(result.hwm.reserve, result.info.reserve); + result.hwm.blocks = DN_MAX(result.hwm.blocks, result.info.blocks); } return result; } -DQN_API Dqn_ArenaStats Dqn_Arena_SumStats(Dqn_ArenaStats lhs, Dqn_ArenaStats rhs) +DN_API DN_ArenaStats DN_Arena_SumStats(DN_ArenaStats lhs, DN_ArenaStats rhs) { - Dqn_ArenaStats array[] = {lhs, rhs}; - Dqn_ArenaStats result = Dqn_Arena_SumStatsArray(array, DQN_ARRAY_UCOUNT(array)); + DN_ArenaStats array[] = {lhs, rhs}; + DN_ArenaStats result = DN_Arena_SumStatsArray(array, DN_ARRAY_UCOUNT(array)); return result; } -DQN_API Dqn_ArenaStats Dqn_Arena_SumArenaArrayToStats(Dqn_Arena const *array, Dqn_usize size) +DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats(DN_Arena const *array, DN_USize size) { - Dqn_ArenaStats result = {}; - for (Dqn_usize index = 0; index < size; index++) { - Dqn_Arena const *arena = array + index; - result = Dqn_Arena_SumStats(result, arena->stats); + DN_ArenaStats result = {}; + for (DN_USize index = 0; index < size; index++) { + DN_Arena const *arena = array + index; + result = DN_Arena_SumStats(result, arena->stats); } return result; } -DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin(Dqn_Arena *arena) +DN_API DN_ArenaTempMem DN_Arena_TempMemBegin(DN_Arena *arena) { - Dqn_ArenaTempMem result = {}; + DN_ArenaTempMem result = {}; if (arena) { - Dqn_ArenaBlock *curr = arena->curr; - result = {arena, curr ? curr->reserve_sum + curr->used : 0}; + DN_ArenaBlock *curr = arena->curr; + result = {arena, curr ? curr->reserve_sum + curr->used : 0}; } return result; }; -DQN_API void Dqn_Arena_TempMemEnd(Dqn_ArenaTempMem mem) +DN_API void DN_Arena_TempMemEnd(DN_ArenaTempMem mem) { - Dqn_Arena_PopTo(mem.arena, mem.used_sum); + DN_Arena_PopTo(mem.arena, mem.used_sum); }; -Dqn_ArenaTempMemScope::Dqn_ArenaTempMemScope(Dqn_Arena *arena) +DN_ArenaTempMemScope::DN_ArenaTempMemScope(DN_Arena *arena) { - mem = Dqn_Arena_TempMemBegin(arena); + mem = DN_Arena_TempMemBegin(arena); } -Dqn_ArenaTempMemScope::~Dqn_ArenaTempMemScope() +DN_ArenaTempMemScope::~DN_ArenaTempMemScope() { - Dqn_Arena_TempMemEnd(mem); + DN_Arena_TempMemEnd(mem); } -// NOTE: [$CHUN] Dqn_ChunkPool ///////////////////////////////////////////////////////////////////// -DQN_API Dqn_ChunkPool Dqn_ChunkPool_Init(Dqn_Arena *arena, uint8_t align) +// NOTE: [$POOL] DN_Pool ////////////////////////////////////////////////////////////////////////// +DN_API DN_Pool DN_Pool_Init(DN_Arena *arena, uint8_t align) { - Dqn_ChunkPool result = {}; + DN_Pool result = {}; if (arena) { result.arena = arena; - result.align = align; - if (result.align == 0) - result.align = DQN_CHUNK_POOL_DEFAULT_ALIGN; + result.align = align ? align : DN_POOL_DEFAULT_ALIGN; } return result; } -DQN_API bool Dqn_ChunkPool_IsValid(Dqn_ChunkPool const *pool) +DN_API bool DN_Pool_IsValid(DN_Pool const *pool) { bool result = pool && pool->arena && pool->align; return result; } -DQN_API void *Dqn_ChunkPool_Alloc(Dqn_ChunkPool *pool, Dqn_usize size) +DN_API void *DN_Pool_Alloc(DN_Pool *pool, DN_USize size) { void *result = nullptr; - if (!Dqn_ChunkPool_IsValid(pool)) + if (!DN_Pool_IsValid(pool)) return result; - Dqn_usize const required_size = sizeof(Dqn_ChunkPoolSlot) + pool->align + size; - Dqn_usize const size_to_slot_offset = 5; // __lzcnt64(32) e.g. Dqn_ChunkPoolSlotSize_32B - Dqn_usize slot_index = 0; + DN_USize const required_size = sizeof(DN_PoolSlot) + pool->align + size; + DN_USize const size_to_slot_offset = 5; // __lzcnt64(32) e.g. DN_PoolSlotSize_32B + DN_USize slot_index = 0; if (required_size > 32) { // NOTE: Round up if not PoT as the low bits are set. - Dqn_usize dist_to_next_msb = Dqn_CountLeadingZerosU64(required_size) + 1; - dist_to_next_msb -= DQN_CAST(Dqn_usize)(!Dqn_IsPowerOfTwo(required_size)); + DN_USize dist_to_next_msb = DN_CountLeadingZerosU64(required_size) + 1; + dist_to_next_msb -= DN_CAST(DN_USize)(!DN_IsPowerOfTwo(required_size)); - Dqn_usize const register_size = sizeof(Dqn_usize) * 8; - DQN_ASSERT(register_size >= dist_to_next_msb + size_to_slot_offset); + DN_USize const register_size = sizeof(DN_USize) * 8; + DN_ASSERT(register_size >= dist_to_next_msb + size_to_slot_offset); slot_index = register_size - dist_to_next_msb - size_to_slot_offset; } - if (!DQN_CHECKF(slot_index < Dqn_ChunkPoolSlotSize_Count, "Chunk pool does not support the requested allocation size")) + if (!DN_CHECKF(slot_index < DN_PoolSlotSize_Count, "Chunk pool does not support the requested allocation size")) return result; - Dqn_usize slot_size_in_bytes = 1ULL << (slot_index + size_to_slot_offset); - DQN_ASSERT(required_size <= (slot_size_in_bytes << 0)); - DQN_ASSERT(required_size >= (slot_size_in_bytes >> 1)); + DN_USize slot_size_in_bytes = 1ULL << (slot_index + size_to_slot_offset); + DN_ASSERT(required_size <= (slot_size_in_bytes << 0)); + DN_ASSERT(required_size >= (slot_size_in_bytes >> 1)); - Dqn_ChunkPoolSlot *slot = nullptr; + DN_PoolSlot *slot = nullptr; if (pool->slots[slot_index]) { slot = pool->slots[slot_index]; pool->slots[slot_index] = slot->next; - DQN_MEMSET(slot->data, 0, size); - DQN_ASSERT(Dqn_IsPowerOfTwoAligned(slot->data, pool->align)); + DN_MEMSET(slot->data, 0, size); + DN_ASSERT(DN_IsPowerOfTwoAligned(slot->data, pool->align)); } else { - void *bytes = Dqn_Arena_Alloc(pool->arena, slot_size_in_bytes, alignof(Dqn_ChunkPoolSlot), Dqn_ZeroMem_Yes); - slot = DQN_CAST(Dqn_ChunkPoolSlot *) bytes; + void *bytes = DN_Arena_Alloc(pool->arena, slot_size_in_bytes, alignof(DN_PoolSlot), DN_ZeroMem_Yes); + slot = DN_CAST(DN_PoolSlot *) bytes; // NOTE: The raw pointer is round up to the next 'pool->align'-ed // address ensuring at least 1 byte of padding between the raw pointer @@ -403,215 +439,215 @@ DQN_API void *Dqn_ChunkPool_Alloc(Dqn_ChunkPool *pool, Dqn_usize size) // // This allows us to smuggle 1 byte behind the user pointer that has // the offset to the original pointer. - slot->data = DQN_CAST(void *)Dqn_AlignDownPowerOfTwo(DQN_CAST(uintptr_t)slot + sizeof(Dqn_ChunkPoolSlot) + pool->align, pool->align); + slot->data = DN_CAST(void *)DN_AlignDownPowerOfTwo(DN_CAST(uintptr_t)slot + sizeof(DN_PoolSlot) + pool->align, pool->align); - uintptr_t offset_to_original_ptr = DQN_CAST(uintptr_t)slot->data - DQN_CAST(uintptr_t)bytes; - DQN_ASSERT(slot->data > bytes); - DQN_ASSERT(offset_to_original_ptr <= sizeof(Dqn_ChunkPoolSlot) + pool->align); + uintptr_t offset_to_original_ptr = DN_CAST(uintptr_t)slot->data - DN_CAST(uintptr_t)bytes; + DN_ASSERT(slot->data > bytes); + DN_ASSERT(offset_to_original_ptr <= sizeof(DN_PoolSlot) + pool->align); // NOTE: Store the offset to the original pointer behind the user's // pointer. - char *offset_to_original_storage = DQN_CAST(char *)slot->data - 1; - DQN_MEMCPY(offset_to_original_storage, &offset_to_original_ptr, 1); + char *offset_to_original_storage = DN_CAST(char *)slot->data - 1; + DN_MEMCPY(offset_to_original_storage, &offset_to_original_ptr, 1); } // NOTE: Smuggle the slot type in the next pointer so that we know, when the // pointer gets returned which free list to return the pointer to. result = slot->data; - slot->next = DQN_CAST(Dqn_ChunkPoolSlot *)slot_index; + slot->next = DN_CAST(DN_PoolSlot *)slot_index; return result; } -DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8FV(Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API DN_Str8 DN_Pool_AllocStr8FV(DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_Str8 result = {}; - if (!Dqn_ChunkPool_IsValid(pool)) + DN_Str8 result = {}; + if (!DN_Pool_IsValid(pool)) return result; - Dqn_usize size_required = Dqn_CStr8_FVSize(fmt, args); - result.data = DQN_CAST(char *) Dqn_ChunkPool_Alloc(pool, size_required + 1); + DN_USize size_required = DN_CStr8_FVSize(fmt, args); + result.data = DN_CAST(char *) DN_Pool_Alloc(pool, size_required + 1); if (result.data) { result.size = size_required; - DQN_VSNPRINTF(result.data, DQN_CAST(int)(result.size + 1), fmt, args); + DN_VSNPRINTF(result.data, DN_CAST(int)(result.size + 1), fmt, args); } return result; } -DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8F(Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API DN_Str8 DN_Pool_AllocStr8F(DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_Str8 result = Dqn_ChunkPool_AllocStr8FV(pool, fmt, args); + DN_Str8 result = DN_Pool_AllocStr8FV(pool, fmt, args); va_end(args); return result; } -DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8Copy(Dqn_ChunkPool *pool, Dqn_Str8 string) +DN_API DN_Str8 DN_Pool_AllocStr8Copy(DN_Pool *pool, DN_Str8 string) { - Dqn_Str8 result = {}; - if (!Dqn_ChunkPool_IsValid(pool)) + DN_Str8 result = {}; + if (!DN_Pool_IsValid(pool)) return result; - if (!Dqn_Str8_HasData(string)) + if (!DN_Str8_HasData(string)) return result; - char *data = DQN_CAST(char *)Dqn_ChunkPool_Alloc(pool, string.size + 1); + char *data = DN_CAST(char *)DN_Pool_Alloc(pool, string.size + 1); if (!data) return result; - DQN_MEMCPY(data, string.data, string.size); + DN_MEMCPY(data, string.data, string.size); data[string.size] = 0; - result = Dqn_Str8_Init(data, string.size); + result = DN_Str8_Init(data, string.size); return result; } -DQN_API void Dqn_ChunkPool_Dealloc(Dqn_ChunkPool *pool, void *ptr) +DN_API void DN_Pool_Dealloc(DN_Pool *pool, void *ptr) { - if (!Dqn_ChunkPool_IsValid(pool) || !ptr) + if (!DN_Pool_IsValid(pool) || !ptr) return; - DQN_ASSERT(Dqn_Arena_OwnsPtr(pool->arena, ptr)); + DN_ASSERT(DN_Arena_OwnsPtr(pool->arena, ptr)); - char const *one_byte_behind_ptr = DQN_CAST(char *) ptr - 1; - Dqn_usize offset_to_original_ptr = 0; - DQN_MEMCPY(&offset_to_original_ptr, one_byte_behind_ptr, 1); - DQN_ASSERT(offset_to_original_ptr <= sizeof(Dqn_ChunkPoolSlot) + pool->align); + char const *one_byte_behind_ptr = DN_CAST(char *) ptr - 1; + DN_USize offset_to_original_ptr = 0; + DN_MEMCPY(&offset_to_original_ptr, one_byte_behind_ptr, 1); + DN_ASSERT(offset_to_original_ptr <= sizeof(DN_PoolSlot) + pool->align); - char *original_ptr = DQN_CAST(char *)ptr - offset_to_original_ptr; - Dqn_ChunkPoolSlot *slot = DQN_CAST(Dqn_ChunkPoolSlot *)original_ptr; - Dqn_ChunkPoolSlotSize slot_index = DQN_CAST(Dqn_ChunkPoolSlotSize)(DQN_CAST(uintptr_t)slot->next); - DQN_ASSERT(slot_index < Dqn_ChunkPoolSlotSize_Count); + char *original_ptr = DN_CAST(char *) ptr - offset_to_original_ptr; + DN_PoolSlot *slot = DN_CAST(DN_PoolSlot *) original_ptr; + DN_PoolSlotSize slot_index = DN_CAST(DN_PoolSlotSize)(DN_CAST(uintptr_t) slot->next); + DN_ASSERT(slot_index < DN_PoolSlotSize_Count); slot->next = pool->slots[slot_index]; pool->slots[slot_index] = slot; } -DQN_API void *Dqn_ChunkPool_Copy(Dqn_ChunkPool *pool, void const *data, uint64_t size, uint8_t align) +DN_API void *DN_Pool_Copy(DN_Pool *pool, void const *data, DN_U64 size, uint8_t align) { if (!pool || !data || size == 0) return nullptr; // TODO: Hmm should align be part of the alloc interface in general? I'm not going to worry // about this until we crash because of misalignment. - DQN_ASSERT(pool->align >= align); + DN_ASSERT(pool->align >= align); - void *result = Dqn_ChunkPool_Alloc(pool, size); + void *result = DN_Pool_Alloc(pool, size); if (result) - DQN_MEMCPY(result, data, size); + DN_MEMCPY(result, data, size); return result; } -// NOTE: [$ACAT] Dqn_ArenaCatalog ////////////////////////////////////////////////////////////////// -DQN_API void Dqn_ArenaCatalog_Init(Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool) +// NOTE: [$ACAT] DN_ArenaCatalog ////////////////////////////////////////////////////////////////// +DN_API void DN_ArenaCatalog_Init(DN_ArenaCatalog *catalog, DN_Pool *pool) { catalog->pool = pool; catalog->sentinel.next = &catalog->sentinel; catalog->sentinel.prev = &catalog->sentinel; } -DQN_API Dqn_ArenaCatalogItem *Dqn_ArenaCatalog_Find(Dqn_ArenaCatalog *catalog, Dqn_Str8 label) +DN_API DN_ArenaCatalogItem *DN_ArenaCatalog_Find(DN_ArenaCatalog *catalog, DN_Str8 label) { - Dqn_TicketMutex_Begin(&catalog->ticket_mutex); - Dqn_ArenaCatalogItem *result = &catalog->sentinel; - for (Dqn_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) { + DN_TicketMutex_Begin(&catalog->ticket_mutex); + DN_ArenaCatalogItem *result = &catalog->sentinel; + for (DN_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) { if (item->label == label) { result = item; break; } } - Dqn_TicketMutex_End(&catalog->ticket_mutex); + DN_TicketMutex_End(&catalog->ticket_mutex); return result; } -static void Dqn_ArenaCatalog_AddInternal_(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_Str8 label, bool arena_pool_allocated) +static void DN_ArenaCatalog_AddInternal_(DN_ArenaCatalog *catalog, DN_Arena *arena, DN_Str8 label, bool arena_pool_allocated) { // NOTE: We could use an atomic for appending to the sentinel but it is such // a rare operation to append to the catalog that we don't bother. - Dqn_TicketMutex_Begin(&catalog->ticket_mutex); + DN_TicketMutex_Begin(&catalog->ticket_mutex); // NOTE: Create item in the catalog - Dqn_ArenaCatalogItem *result = Dqn_ChunkPool_New(catalog->pool, Dqn_ArenaCatalogItem); + DN_ArenaCatalogItem *result = DN_Pool_New(catalog->pool, DN_ArenaCatalogItem); if (result) { result->arena = arena; result->label = label; result->arena_pool_allocated = arena_pool_allocated; // NOTE: Add to the catalog (linked list) - Dqn_ArenaCatalogItem *sentinel = &catalog->sentinel; + DN_ArenaCatalogItem *sentinel = &catalog->sentinel; result->next = sentinel; result->prev = sentinel->prev; result->next->prev = result; result->prev->next = result; - Dqn_Atomic_AddU32(&catalog->arena_count, 1); + DN_Atomic_AddU32(&catalog->arena_count, 1); } - Dqn_TicketMutex_End(&catalog->ticket_mutex); + DN_TicketMutex_End(&catalog->ticket_mutex); } -DQN_API void Dqn_ArenaCatalog_AddF(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API void DN_ArenaCatalog_AddF(DN_ArenaCatalog *catalog, DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_TicketMutex_Begin(&catalog->ticket_mutex); - Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args); - Dqn_TicketMutex_End(&catalog->ticket_mutex); + DN_TicketMutex_Begin(&catalog->ticket_mutex); + DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args); + DN_TicketMutex_End(&catalog->ticket_mutex); va_end(args); - Dqn_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/); + DN_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/); } -DQN_API void Dqn_ArenaCatalog_AddFV(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API void DN_ArenaCatalog_AddFV(DN_ArenaCatalog *catalog, DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_TicketMutex_Begin(&catalog->ticket_mutex); - Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args); - Dqn_TicketMutex_End(&catalog->ticket_mutex); - Dqn_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/); + DN_TicketMutex_Begin(&catalog->ticket_mutex); + DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args); + DN_TicketMutex_End(&catalog->ticket_mutex); + DN_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/); } -DQN_API Dqn_Arena *Dqn_ArenaCatalog_AllocFV(Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API DN_Arena *DN_ArenaCatalog_AllocFV(DN_ArenaCatalog *catalog, DN_USize reserve, DN_USize commit, uint8_t arena_flags, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_TicketMutex_Begin(&catalog->ticket_mutex); - Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args); - Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena); - Dqn_TicketMutex_End(&catalog->ticket_mutex); + DN_TicketMutex_Begin(&catalog->ticket_mutex); + DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args); + DN_Arena *result = DN_Pool_New(catalog->pool, DN_Arena); + DN_TicketMutex_End(&catalog->ticket_mutex); - *result = Dqn_Arena_InitSize(reserve, commit, arena_flags); - Dqn_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/); + *result = DN_Arena_InitSize(reserve, commit, arena_flags); + DN_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/); return result; } -DQN_API Dqn_Arena *Dqn_ArenaCatalog_AllocF(Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API DN_Arena *DN_ArenaCatalog_AllocF(DN_ArenaCatalog *catalog, DN_USize reserve, DN_USize commit, uint8_t arena_flags, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_TicketMutex_Begin(&catalog->ticket_mutex); - Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args); - Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena); - Dqn_TicketMutex_End(&catalog->ticket_mutex); + DN_TicketMutex_Begin(&catalog->ticket_mutex); + DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args); + DN_Arena *result = DN_Pool_New(catalog->pool, DN_Arena); + DN_TicketMutex_End(&catalog->ticket_mutex); va_end(args); - *result = Dqn_Arena_InitSize(reserve, commit, arena_flags); - Dqn_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/); + *result = DN_Arena_InitSize(reserve, commit, arena_flags); + DN_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/); return result; } -DQN_API bool Dqn_ArenaCatalog_Erase(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena) +DN_API bool DN_ArenaCatalog_Erase(DN_ArenaCatalog *catalog, DN_Arena *arena, DN_ArenaCatalogFreeArena free_arena) { bool result = false; - Dqn_TicketMutex_Begin(&catalog->ticket_mutex); - for (Dqn_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) { + DN_TicketMutex_Begin(&catalog->ticket_mutex); + for (DN_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) { if (item->arena == arena) { item->next->prev = item->prev; item->prev->next = item->next; if (item->arena_pool_allocated) { - if (free_arena == Dqn_ArenaCatalogFreeArena_Yes) - Dqn_Arena_Deinit(item->arena); - Dqn_ChunkPool_Dealloc(catalog->pool, item->arena); + if (free_arena == DN_ArenaCatalogFreeArena_Yes) + DN_Arena_Deinit(item->arena); + DN_Pool_Dealloc(catalog->pool, item->arena); } - Dqn_ChunkPool_Dealloc(catalog->pool, item->label.data); - Dqn_ChunkPool_Dealloc(catalog->pool, item); + DN_Pool_Dealloc(catalog->pool, item->label.data); + DN_Pool_Dealloc(catalog->pool, item); result = true; break; } } - Dqn_TicketMutex_End(&catalog->ticket_mutex); + DN_TicketMutex_End(&catalog->ticket_mutex); return result; } diff --git a/dqn_allocator.h b/dqn_allocator.h index 7c50b7c..0c9bab9 100644 --- a/dqn_allocator.h +++ b/dqn_allocator.h @@ -17,197 +17,204 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // -// [$AREN] Dqn_Arena -- Growing bump allocator -// [$CHUN] Dqn_ChunkPool -- Allocates reusable, free-able memory in PoT chunks -// [$ACAT] Dqn_ArenaCatalog -- Collate, create & manage arenas in a catalog +// [$AREN] DN_Arena -- Growing bump allocator +// [$CHUN] DN_Pool -- Allocates reusable, free-able memory in PoT chunks +// [$POOL] DN_Pool -- TODO +// [$ACAT] DN_ArenaCatalog -- Collate, create & manage arenas in a catalog // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$AREN] Dqn_Arena ///////////////////////////////////////////////////////////////////////// -#if !defined(DQN_ARENA_RESERVE_SIZE) - #define DQN_ARENA_RESERVE_SIZE DQN_MEGABYTES(64) +// NOTE: [$AREN] DN_Arena ///////////////////////////////////////////////////////////////////////// +#if !defined(DN_ARENA_RESERVE_SIZE) + #define DN_ARENA_RESERVE_SIZE DN_MEGABYTES(64) #endif -#if !defined(DQN_ARENA_COMMIT_SIZE) - #define DQN_ARENA_COMMIT_SIZE DQN_KILOBYTES(64) +#if !defined(DN_ARENA_COMMIT_SIZE) + #define DN_ARENA_COMMIT_SIZE DN_KILOBYTES(64) #endif -struct Dqn_ArenaBlock +struct DN_ArenaBlock { - Dqn_ArenaBlock *prev; - uint64_t used; - uint64_t commit; - uint64_t reserve; - uint64_t reserve_sum; + DN_ArenaBlock *prev; + DN_U64 used; + DN_U64 commit; + DN_U64 reserve; + DN_U64 reserve_sum; }; -enum Dqn_ArenaFlag +typedef uint32_t DN_ArenaFlags; +enum DN_ArenaFlags_ { - Dqn_ArenaFlag_Nil = 0, - Dqn_ArenaFlag_NoGrow = 1 << 0, - Dqn_ArenaFlag_NoPoison = 1 << 1, - Dqn_ArenaFlag_NoAllocTrack = 1 << 2, - Dqn_ArenaFlag_AllocCanLeak = 1 << 3, + DN_ArenaFlags_Nil = 0, + DN_ArenaFlags_NoGrow = 1 << 0, + DN_ArenaFlags_NoPoison = 1 << 1, + DN_ArenaFlags_NoAllocTrack = 1 << 2, + DN_ArenaFlags_AllocCanLeak = 1 << 3, + DN_ArenaFlags_UserBuffer = 1 << 4, }; -struct Dqn_ArenaInfo +struct DN_ArenaInfo { - uint64_t used; - uint64_t commit; - uint64_t reserve; - uint64_t blocks; + DN_U64 used; + DN_U64 commit; + DN_U64 reserve; + DN_U64 blocks; }; -struct Dqn_ArenaStats +struct DN_ArenaStats { - Dqn_ArenaInfo info; - Dqn_ArenaInfo hwm; + DN_ArenaInfo info; + DN_ArenaInfo hwm; }; -struct Dqn_Arena +struct DN_Arena { - Dqn_ArenaBlock *curr; - Dqn_ArenaStats stats; - Dqn_TicketMutex mutex; // For user code to lock the arena, the arena itself does not use. - uint8_t flags; + DN_ArenaBlock *curr; + DN_ArenaStats stats; + DN_ArenaFlags flags; + DN_Str8 label; + DN_Arena *prev, *next; }; -struct Dqn_ArenaTempMem +struct DN_ArenaTempMem { - Dqn_Arena *arena; - uint64_t used_sum; + DN_Arena *arena; + DN_U64 used_sum; }; -struct Dqn_ArenaTempMemScope +struct DN_ArenaTempMemScope { - Dqn_ArenaTempMemScope(Dqn_Arena *arena); - ~Dqn_ArenaTempMemScope(); - Dqn_ArenaTempMem mem; + DN_ArenaTempMemScope(DN_Arena *arena); + ~DN_ArenaTempMemScope(); + DN_ArenaTempMem mem; }; -Dqn_usize const DQN_ARENA_HEADER_SIZE = Dqn_AlignUpPowerOfTwo(sizeof(Dqn_Arena), 64); +DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64); -// NOTE: [$CHUN] Dqn_ChunkPool ///////////////////////////////////////////////////////////////////// -#if !defined(DQN_CHUNK_POOL_DEFAULT_ALIGN) - #define DQN_CHUNK_POOL_DEFAULT_ALIGN 16 +// NOTE: [$CHUN] DN_Pool ///////////////////////////////////////////////////////////////////// +#if !defined(DN_POOL_DEFAULT_ALIGN) + #define DN_POOL_DEFAULT_ALIGN 16 #endif -struct Dqn_ChunkPoolSlot +struct DN_PoolSlot { - void *data; - Dqn_ChunkPoolSlot *next; + void *data; + DN_PoolSlot *next; }; -enum Dqn_ChunkPoolSlotSize +enum DN_PoolSlotSize { - Dqn_ChunkPoolSlotSize_32B, - Dqn_ChunkPoolSlotSize_64B, - Dqn_ChunkPoolSlotSize_128B, - Dqn_ChunkPoolSlotSize_256B, - Dqn_ChunkPoolSlotSize_512B, - Dqn_ChunkPoolSlotSize_1KiB, - Dqn_ChunkPoolSlotSize_2KiB, - Dqn_ChunkPoolSlotSize_4KiB, - Dqn_ChunkPoolSlotSize_8KiB, - Dqn_ChunkPoolSlotSize_16KiB, - Dqn_ChunkPoolSlotSize_32KiB, - Dqn_ChunkPoolSlotSize_64KiB, - Dqn_ChunkPoolSlotSize_128KiB, - Dqn_ChunkPoolSlotSize_256KiB, - Dqn_ChunkPoolSlotSize_512KiB, - Dqn_ChunkPoolSlotSize_1MiB, - Dqn_ChunkPoolSlotSize_2MiB, - Dqn_ChunkPoolSlotSize_4MiB, - Dqn_ChunkPoolSlotSize_8MiB, - Dqn_ChunkPoolSlotSize_16MiB, - Dqn_ChunkPoolSlotSize_32MiB, - Dqn_ChunkPoolSlotSize_64MiB, - Dqn_ChunkPoolSlotSize_128MiB, - Dqn_ChunkPoolSlotSize_256MiB, - Dqn_ChunkPoolSlotSize_512MiB, - Dqn_ChunkPoolSlotSize_1GiB, - Dqn_ChunkPoolSlotSize_2GiB, - Dqn_ChunkPoolSlotSize_4GiB, - Dqn_ChunkPoolSlotSize_8GiB, - Dqn_ChunkPoolSlotSize_16GiB, - Dqn_ChunkPoolSlotSize_32GiB, - Dqn_ChunkPoolSlotSize_Count, + DN_PoolSlotSize_32B, + DN_PoolSlotSize_64B, + DN_PoolSlotSize_128B, + DN_PoolSlotSize_256B, + DN_PoolSlotSize_512B, + DN_PoolSlotSize_1KiB, + DN_PoolSlotSize_2KiB, + DN_PoolSlotSize_4KiB, + DN_PoolSlotSize_8KiB, + DN_PoolSlotSize_16KiB, + DN_PoolSlotSize_32KiB, + DN_PoolSlotSize_64KiB, + DN_PoolSlotSize_128KiB, + DN_PoolSlotSize_256KiB, + DN_PoolSlotSize_512KiB, + DN_PoolSlotSize_1MiB, + DN_PoolSlotSize_2MiB, + DN_PoolSlotSize_4MiB, + DN_PoolSlotSize_8MiB, + DN_PoolSlotSize_16MiB, + DN_PoolSlotSize_32MiB, + DN_PoolSlotSize_64MiB, + DN_PoolSlotSize_128MiB, + DN_PoolSlotSize_256MiB, + DN_PoolSlotSize_512MiB, + DN_PoolSlotSize_1GiB, + DN_PoolSlotSize_2GiB, + DN_PoolSlotSize_4GiB, + DN_PoolSlotSize_8GiB, + DN_PoolSlotSize_16GiB, + DN_PoolSlotSize_32GiB, + DN_PoolSlotSize_Count, }; -struct Dqn_ChunkPool +struct DN_Pool { - Dqn_Arena *arena; - Dqn_ChunkPoolSlot *slots[Dqn_ChunkPoolSlotSize_Count]; - uint8_t align; + DN_Arena *arena; + DN_PoolSlot *slots[DN_PoolSlotSize_Count]; + uint8_t align; }; -// NOTE: [$ACAT] Dqn_ArenaCatalog ////////////////////////////////////////////////////////////////// -struct Dqn_ArenaCatalogItem +// NOTE: [$ACAT] DN_ArenaCatalog ////////////////////////////////////////////////////////////////// +struct DN_ArenaCatalogItem { - Dqn_Arena *arena; - Dqn_Str8 label; + DN_Arena *arena; + DN_Str8 label; bool arena_pool_allocated; - Dqn_ArenaCatalogItem *next; - Dqn_ArenaCatalogItem *prev; + DN_ArenaCatalogItem *next; + DN_ArenaCatalogItem *prev; }; -struct Dqn_ArenaCatalog +struct DN_ArenaCatalog { - Dqn_TicketMutex ticket_mutex; // Mutex for adding to the linked list of arenas - struct Dqn_ChunkPool *pool; - Dqn_ArenaCatalogItem sentinel; - uint16_t arena_count; + DN_TicketMutex ticket_mutex; // Mutex for adding to the linked list of arenas + DN_Pool *pool; + DN_ArenaCatalogItem sentinel; + uint16_t arena_count; }; -enum Dqn_ArenaCatalogFreeArena +enum DN_ArenaCatalogFreeArena { - Dqn_ArenaCatalogFreeArena_No, - Dqn_ArenaCatalogFreeArena_Yes, + DN_ArenaCatalogFreeArena_No, + DN_ArenaCatalogFreeArena_Yes, }; -// NOTE: [$AREN] Dqn_Arena ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Arena Dqn_Arena_InitSize (uint64_t reserve, uint64_t commit, uint8_t flags); -DQN_API void Dqn_Arena_Deinit (Dqn_Arena *arena); -DQN_API bool Dqn_Arena_Commit (Dqn_Arena *arena, uint64_t size); -DQN_API bool Dqn_Arena_CommitTo (Dqn_Arena *arena, uint64_t pos); -DQN_API void * Dqn_Arena_Alloc (Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem); -DQN_API void * Dqn_Arena_AllocContiguous (Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem); -DQN_API void * Dqn_Arena_Copy (Dqn_Arena *arena, void const *data, uint64_t size, uint8_t align); -DQN_API void Dqn_Arena_PopTo (Dqn_Arena *arena, uint64_t init_used); -DQN_API void Dqn_Arena_Pop (Dqn_Arena *arena, uint64_t amount); -DQN_API uint64_t Dqn_Arena_Pos (Dqn_Arena const *arena); -DQN_API void Dqn_Arena_Clear (Dqn_Arena *arena); -DQN_API bool Dqn_Arena_OwnsPtr (Dqn_Arena const *arena, void *ptr); -DQN_API Dqn_ArenaStats Dqn_Arena_SumStatsArray (Dqn_ArenaStats const *array, Dqn_usize size); -DQN_API Dqn_ArenaStats Dqn_Arena_SumStats (Dqn_ArenaStats lhs, Dqn_ArenaStats rhs); -DQN_API Dqn_ArenaStats Dqn_Arena_SumArenaArrayToStats (Dqn_Arena const *array, Dqn_usize size); -DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin (Dqn_Arena *arena); -DQN_API void Dqn_Arena_TempMemEnd (Dqn_ArenaTempMem mem); -#define Dqn_Arena_New(arena, T, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem) -#define Dqn_Arena_NewArray(arena, T, count, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem) -#define Dqn_Arena_NewCopy(arena, T, src) (T *)Dqn_Arena_Copy (arena, (src), sizeof(T), alignof(T)) -#define Dqn_Arena_NewArrayCopy(arena, T, src, count) (T *)Dqn_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T)) +// NOTE: [$AREN] DN_Arena ///////////////////////////////////////////////////////////////////////// +DN_API DN_Arena DN_Arena_InitBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags); +DN_API DN_Arena DN_Arena_InitSize (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags); +DN_API void DN_Arena_Deinit (DN_Arena *arena); +DN_API bool DN_Arena_Commit (DN_Arena *arena, DN_U64 size); +DN_API bool DN_Arena_CommitTo (DN_Arena *arena, DN_U64 pos); +DN_API bool DN_Arena_Grow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit); +DN_API void * DN_Arena_Alloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem); +DN_API void * DN_Arena_AllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem); +DN_API void * DN_Arena_Copy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align); +DN_API void DN_Arena_PopTo (DN_Arena *arena, DN_U64 init_used); +DN_API void DN_Arena_Pop (DN_Arena *arena, DN_U64 amount); +DN_API DN_U64 DN_Arena_Pos (DN_Arena const *arena); +DN_API void DN_Arena_Clear (DN_Arena *arena); +DN_API bool DN_Arena_OwnsPtr (DN_Arena const *arena, void *ptr); +DN_API DN_ArenaStats DN_Arena_SumStatsArray (DN_ArenaStats const *array, DN_USize size); +DN_API DN_ArenaStats DN_Arena_SumStats (DN_ArenaStats lhs, DN_ArenaStats rhs); +DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats (DN_Arena const *array, DN_USize size); +DN_API DN_ArenaTempMem DN_Arena_TempMemBegin (DN_Arena *arena); +DN_API void DN_Arena_TempMemEnd (DN_ArenaTempMem mem); +#define DN_Arena_New_Frame(T, zero_mem) (T *)DN_Arena_Alloc(DN_TLS_Get()->frame_arena, sizeof(T), alignof(T), zero_mem) +#define DN_Arena_New(arena, T, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem) +#define DN_Arena_NewArray(arena, T, count, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem) +#define DN_Arena_NewCopy(arena, T, src) (T *)DN_Arena_Copy (arena, (src), sizeof(T), alignof(T)) +#define DN_Arena_NewArrayCopy(arena, T, src, count) (T *)DN_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T)) -// NOTE: [$CHUN] Dqn_ChunkPool ///////////////////////////////////////////////////////////////////// -DQN_API Dqn_ChunkPool Dqn_ChunkPool_Init (Dqn_Arena *arena, uint8_t align); -DQN_API bool Dqn_ChunkPool_IsValid (Dqn_ChunkPool const *pool); -DQN_API void * Dqn_ChunkPool_Alloc (Dqn_ChunkPool *pool, Dqn_usize size); -DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8FV (Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8F (Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8Copy (Dqn_ChunkPool *pool, Dqn_Str8 string); -DQN_API void Dqn_ChunkPool_Dealloc (Dqn_ChunkPool *pool, void *ptr); -DQN_API void * Dqn_ChunkPool_Copy (Dqn_ChunkPool *pool, void const *data, uint64_t size, uint8_t align); +// NOTE: [$CHUN] DN_Pool ///////////////////////////////////////////////////////////////////// +DN_API DN_Pool DN_Pool_Init (DN_Arena *arena, uint8_t align); +DN_API bool DN_Pool_IsValid (DN_Pool const *pool); +DN_API void * DN_Pool_Alloc (DN_Pool *pool, DN_USize size); +DN_API DN_Str8 DN_Pool_AllocStr8FV (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Str8 DN_Pool_AllocStr8F (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_Str8 DN_Pool_AllocStr8Copy (DN_Pool *pool, DN_Str8 string); +DN_API void DN_Pool_Dealloc (DN_Pool *pool, void *ptr); +DN_API void * DN_Pool_Copy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align); -#define Dqn_ChunkPool_New(pool, T) (T *)Dqn_ChunkPool_Alloc(pool, sizeof(T)) -#define Dqn_ChunkPool_NewArray(pool, T, count) (T *)Dqn_ChunkPool_Alloc(pool, count * sizeof(T)) -#define Dqn_ChunkPool_NewCopy(arena, T, src) (T *)Dqn_ChunkPool_Copy (arena, (src), sizeof(T), alignof(T)) -#define Dqn_ChunkPool_NewArrayCopy(arena, T, src, count) (T *)Dqn_ChunkPool_Copy (arena, (src), sizeof(T) * (count), alignof(T)) +#define DN_Pool_New(pool, T) (T *)DN_Pool_Alloc(pool, sizeof(T)) +#define DN_Pool_NewArray(pool, T, count) (T *)DN_Pool_Alloc(pool, count * sizeof(T)) +#define DN_Pool_NewCopy(arena, T, src) (T *)DN_Pool_Copy (arena, (src), sizeof(T), alignof(T)) +#define DN_Pool_NewArrayCopy(arena, T, src, count) (T *)DN_Pool_Copy (arena, (src), sizeof(T) * (count), alignof(T)) -// NOTE: [$ACAT] Dqn_ArenaCatalog ////////////////////////////////////////////////////////////////// -DQN_API void Dqn_ArenaCatalog_Init (Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool); -DQN_API Dqn_ArenaCatalogItem *Dqn_ArenaCatalog_Find (Dqn_ArenaCatalog *catalog, Dqn_Str8 label); -DQN_API void Dqn_ArenaCatalog_AddF (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_ArenaCatalog_AddFV (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocFV (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocF (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API bool Dqn_ArenaCatalog_Erase (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena); +// NOTE: [$ACAT] DN_ArenaCatalog ////////////////////////////////////////////////////////////////// +DN_API void DN_ArenaCatalog_Init (DN_ArenaCatalog *catalog, DN_Pool *pool); +DN_API DN_ArenaCatalogItem *DN_ArenaCatalog_Find (DN_ArenaCatalog *catalog, DN_Str8 label); +DN_API void DN_ArenaCatalog_AddF (DN_ArenaCatalog *catalog, DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_ArenaCatalog_AddFV (DN_ArenaCatalog *catalog, DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Arena * DN_ArenaCatalog_AllocFV (DN_ArenaCatalog *catalog, DN_USize reserve, DN_USize commit, uint8_t arena_flags, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Arena * DN_ArenaCatalog_AllocF (DN_ArenaCatalog *catalog, DN_USize reserve, DN_USize commit, uint8_t arena_flags, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_ArenaCatalog_Erase (DN_ArenaCatalog *catalog, DN_Arena *arena, DN_ArenaCatalogFreeArena free_arena); diff --git a/dqn_avx512f.cpp b/dqn_avx512f.cpp index 18d0451..eb369d7 100644 --- a/dqn_avx512f.cpp +++ b/dqn_avx512f.cpp @@ -19,19 +19,19 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F(Dqn_Str8 string, Dqn_Str8 find) +DN_API DN_Str8FindResult DN_Str8_FindStr8AVX512F(DN_Str8 string, DN_Str8 find) { // NOTE: Algorithm as described in http://0x80.pl/articles/simd-strfind.html - Dqn_Str8FindResult result = {}; - if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(find) || find.size > string.size) + DN_Str8FindResult result = {}; + if (!DN_Str8_HasData(string) || !DN_Str8_HasData(find) || find.size > string.size) return result; __m512i const find_first_ch = _mm512_set1_epi8(find.data[0]); __m512i const find_last_ch = _mm512_set1_epi8(find.data[find.size - 1]); - Dqn_usize const search_size = string.size - find.size; - Dqn_usize simd_iterations = search_size / sizeof(__m512i); - char const *ptr = string.data; + DN_USize const search_size = string.size - find.size; + DN_USize simd_iterations = search_size / sizeof(__m512i); + char const *ptr = string.data; while (simd_iterations--) { __m512i find_first_ch_block = _mm512_loadu_si512(ptr); @@ -79,41 +79,43 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F(Dqn_Str8 string, Dqn_Str8 fi uint64_t const lsb_zero_pos = _tzcnt_u64(zero_byte_mask); char const *base_ptr = ptr + (4 * lsb_zero_pos); - if (DQN_MEMCMP(base_ptr + 0, find.data, find.size) == 0) { + if (DN_MEMCMP(base_ptr + 0, find.data, find.size) == 0) { result.found = true; result.index = base_ptr - string.data; - } else if (DQN_MEMCMP(base_ptr + 1, find.data, find.size) == 0) { + } else if (DN_MEMCMP(base_ptr + 1, find.data, find.size) == 0) { result.found = true; result.index = base_ptr - string.data + 1; - } else if (DQN_MEMCMP(base_ptr + 2, find.data, find.size) == 0) { + } else if (DN_MEMCMP(base_ptr + 2, find.data, find.size) == 0) { result.found = true; result.index = base_ptr - string.data + 2; - } else if (DQN_MEMCMP(base_ptr + 3, find.data, find.size) == 0) { + } else if (DN_MEMCMP(base_ptr + 3, find.data, find.size) == 0) { result.found = true; result.index = base_ptr - string.data + 3; } if (result.found) { - result.start_to_before_match = Dqn_Str8_Init(string.data, result.index); - result.match = Dqn_Str8_Init(string.data + result.index, find.size); - result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - result.index); + result.start_to_before_match = DN_Str8_Init(string.data, result.index); + result.match = DN_Str8_Init(string.data + result.index, find.size); + result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - result.index); + result.after_match_to_end_of_buffer = DN_Str8_Advance(result.match_to_end_of_buffer, find.size); return result; } - zero_byte_mask = Dqn_Bit_ClearNextLSB(zero_byte_mask); + zero_byte_mask = DN_Bit_ClearNextLSB(zero_byte_mask); } ptr += sizeof(__m512i); } - for (Dqn_usize index = ptr - string.data; index < string.size; index++) { - Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find.size); - if (Dqn_Str8_Eq(string_slice, find)) { - result.found = true; - result.index = index; - result.start_to_before_match = Dqn_Str8_Init(string.data, index); - result.match = Dqn_Str8_Init(string.data + index, find.size); - result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - index); + for (DN_USize index = ptr - string.data; index < string.size; index++) { + DN_Str8 string_slice = DN_Str8_Slice(string, index, find.size); + if (DN_Str8_Eq(string_slice, find)) { + result.found = true; + result.index = index; + result.start_to_before_match = DN_Str8_Init(string.data, index); + result.match = DN_Str8_Init(string.data + index, find.size); + result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - index); + result.after_match_to_end_of_buffer = DN_Str8_Advance(result.match_to_end_of_buffer, find.size); return result; } } @@ -121,18 +123,18 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F(Dqn_Str8 string, Dqn_Str8 fi return result; } -DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F(Dqn_Str8 string, Dqn_Str8 find) +DN_API DN_Str8FindResult DN_Str8_FindLastStr8AVX512F(DN_Str8 string, DN_Str8 find) { // NOTE: Algorithm as described in http://0x80.pl/articles/simd-strfind.html - Dqn_Str8FindResult result = {}; - if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(find) || find.size > string.size) + DN_Str8FindResult result = {}; + if (!DN_Str8_HasData(string) || !DN_Str8_HasData(find) || find.size > string.size) return result; __m512i const find_first_ch = _mm512_set1_epi8(find.data[0]); __m512i const find_last_ch = _mm512_set1_epi8(find.data[find.size - 1]); - Dqn_usize const search_size = string.size - find.size; - Dqn_usize simd_iterations = search_size / sizeof(__m512i); + DN_USize const search_size = string.size - find.size; + DN_USize simd_iterations = search_size / sizeof(__m512i); char const *ptr = string.data + search_size + 1; while (simd_iterations--) { @@ -182,39 +184,39 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F(Dqn_Str8 string, Dqn_Str uint64_t const lsb_zero_pos = _tzcnt_u64(zero_byte_mask); char const *base_ptr = ptr + (4 * lsb_zero_pos); - if (DQN_MEMCMP(base_ptr + 0, find.data, find.size) == 0) { + if (DN_MEMCMP(base_ptr + 0, find.data, find.size) == 0) { result.found = true; result.index = base_ptr - string.data; - } else if (DQN_MEMCMP(base_ptr + 1, find.data, find.size) == 0) { + } else if (DN_MEMCMP(base_ptr + 1, find.data, find.size) == 0) { result.found = true; result.index = base_ptr - string.data + 1; - } else if (DQN_MEMCMP(base_ptr + 2, find.data, find.size) == 0) { + } else if (DN_MEMCMP(base_ptr + 2, find.data, find.size) == 0) { result.found = true; result.index = base_ptr - string.data + 2; - } else if (DQN_MEMCMP(base_ptr + 3, find.data, find.size) == 0) { + } else if (DN_MEMCMP(base_ptr + 3, find.data, find.size) == 0) { result.found = true; result.index = base_ptr - string.data + 3; } if (result.found) { - result.start_to_before_match = Dqn_Str8_Init(string.data, result.index); - result.match = Dqn_Str8_Init(string.data + result.index, find.size); - result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - result.index); + result.start_to_before_match = DN_Str8_Init(string.data, result.index); + result.match = DN_Str8_Init(string.data + result.index, find.size); + result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - result.index); return result; } - zero_byte_mask = Dqn_Bit_ClearNextLSB(zero_byte_mask); + zero_byte_mask = DN_Bit_ClearNextLSB(zero_byte_mask); } } - for (Dqn_usize index = ptr - string.data - 1; index < string.size; index--) { - Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find.size); - if (Dqn_Str8_Eq(string_slice, find)) { + for (DN_USize index = ptr - string.data - 1; index < string.size; index--) { + DN_Str8 string_slice = DN_Str8_Slice(string, index, find.size); + if (DN_Str8_Eq(string_slice, find)) { result.found = true; result.index = index; - result.start_to_before_match = Dqn_Str8_Init(string.data, index); - result.match = Dqn_Str8_Init(string.data + index, find.size); - result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - index); + result.start_to_before_match = DN_Str8_Init(string.data, index); + result.match = DN_Str8_Init(string.data + index, find.size); + result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - index); return result; } } @@ -222,14 +224,14 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F(Dqn_Str8 string, Dqn_Str return result; } -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitAVX512F(Dqn_Str8 string, Dqn_Str8 find) +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitAVX512F(DN_Str8 string, DN_Str8 find) { - Dqn_Str8BinarySplitResult result = {}; - Dqn_Str8FindResult find_result = Dqn_Str8_FindStr8AVX512F(string, find); + DN_Str8BinarySplitResult result = {}; + DN_Str8FindResult find_result = DN_Str8_FindStr8AVX512F(string, find); if (find_result.found) { result.lhs.data = string.data; result.lhs.size = find_result.index; - result.rhs = Dqn_Str8_Advance(find_result.match_to_end_of_buffer, find.size); + result.rhs = DN_Str8_Advance(find_result.match_to_end_of_buffer, find.size); } else { result.lhs = string; } @@ -237,14 +239,14 @@ DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitAVX512F(Dqn_Str8 string, D return result; } -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastAVX512F(Dqn_Str8 string, Dqn_Str8 find) +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLastAVX512F(DN_Str8 string, DN_Str8 find) { - Dqn_Str8BinarySplitResult result = {}; - Dqn_Str8FindResult find_result = Dqn_Str8_FindLastStr8AVX512F(string, find); + DN_Str8BinarySplitResult result = {}; + DN_Str8FindResult find_result = DN_Str8_FindLastStr8AVX512F(string, find); if (find_result.found) { result.lhs.data = string.data; result.lhs.size = find_result.index; - result.rhs = Dqn_Str8_Advance(find_result.match_to_end_of_buffer, find.size); + result.rhs = DN_Str8_Advance(find_result.match_to_end_of_buffer, find.size); } else { result.lhs = string; } @@ -252,17 +254,17 @@ DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastAVX512F(Dqn_Str8 strin return result; } -DQN_API Dqn_usize Dqn_Str8_SplitAVX512F(Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8 *splits, Dqn_usize splits_count, Dqn_Str8SplitIncludeEmptyStrings mode) +DN_API DN_USize DN_Str8_SplitAVX512F(DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode) { - Dqn_usize result = 0; // The number of splits in the actual string. - if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(delimiter) || delimiter.size <= 0) + DN_USize result = 0; // The number of splits in the actual string. + if (!DN_Str8_HasData(string) || !DN_Str8_HasData(delimiter) || delimiter.size <= 0) return result; - Dqn_Str8BinarySplitResult split = {}; - Dqn_Str8 first = string; + DN_Str8BinarySplitResult split = {}; + DN_Str8 first = string; do { - split = Dqn_Str8_BinarySplitAVX512F(first, delimiter); - if (split.lhs.size || mode == Dqn_Str8SplitIncludeEmptyStrings_Yes) { + split = DN_Str8_BinarySplitAVX512F(first, delimiter); + if (split.lhs.size || mode == DN_Str8SplitIncludeEmptyStrings_Yes) { if (splits && result < splits_count) splits[result] = split.lhs; result++; @@ -273,14 +275,14 @@ DQN_API Dqn_usize Dqn_Str8_SplitAVX512F(Dqn_Str8 string, Dqn_Str8 delimiter, Dqn return result; } -DQN_API Dqn_Slice Dqn_Str8_SplitAllocAVX512F(Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8SplitIncludeEmptyStrings mode) +DN_API DN_Slice DN_Str8_SplitAllocAVX512F(DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode) { - Dqn_Slice result = {}; - Dqn_usize splits_required = Dqn_Str8_SplitAVX512F(string, delimiter, /*splits*/ nullptr, /*count*/ 0, mode); - result.data = Dqn_Arena_NewArray(arena, Dqn_Str8, splits_required, Dqn_ZeroMem_No); + DN_Slice result = {}; + DN_USize splits_required = DN_Str8_SplitAVX512F(string, delimiter, /*splits*/ nullptr, /*count*/ 0, mode); + result.data = DN_Arena_NewArray(arena, DN_Str8, splits_required, DN_ZeroMem_No); if (result.data) { - result.size = Dqn_Str8_SplitAVX512F(string, delimiter, result.data, splits_required, mode); - DQN_ASSERT(splits_required == result.size); + result.size = DN_Str8_SplitAVX512F(string, delimiter, result.data, splits_required, mode); + DN_ASSERT(splits_required == result.size); } return result; } diff --git a/dqn_avx512f.h b/dqn_avx512f.h index 771f23c..b286e0c 100644 --- a/dqn_avx512f.h +++ b/dqn_avx512f.h @@ -1,5 +1,5 @@ -#if !defined(DQN_AVX512F_H) -#define DQN_AVX512F_H +#if !defined(DN_AVX512F_H) +#define DN_AVX512F_H /* //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -20,11 +20,11 @@ #include "dqn.h" -DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F (Dqn_Str8 string, Dqn_Str8 find); -DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F (Dqn_Str8 string, Dqn_Str8 find); -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitAVX512F (Dqn_Str8 string, Dqn_Str8 find); -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastAVX512F(Dqn_Str8 string, Dqn_Str8 find); -DQN_API Dqn_usize Dqn_Str8_SplitAVX512F (Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8 *splits, Dqn_usize splits_count, Dqn_Str8SplitIncludeEmptyStrings mode); -DQN_API Dqn_Slice Dqn_Str8_SplitAllocAVX512F (Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8SplitIncludeEmptyStrings mode); +DN_API DN_Str8FindResult DN_Str8_FindStr8AVX512F (DN_Str8 string, DN_Str8 find); +DN_API DN_Str8FindResult DN_Str8_FindLastStr8AVX512F (DN_Str8 string, DN_Str8 find); +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitAVX512F (DN_Str8 string, DN_Str8 find); +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLastAVX512F(DN_Str8 string, DN_Str8 find); +DN_API DN_USize DN_Str8_SplitAVX512F (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode); +DN_API DN_Slice DN_Str8_SplitAllocAVX512F (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode); -#endif // DQN_AVX512F_H +#endif // DN_AVX512F_H diff --git a/dqn_base.cpp b/dqn_base.cpp index 1125697..f9bdbac 100644 --- a/dqn_base.cpp +++ b/dqn_base.cpp @@ -13,87 +13,87 @@ // $$$$$$$ |\$$$$$$$ |$$$$$$$ |\$$$$$$$\ // \_______/ \_______|\_______/ \_______| // -// dqn_base.cpp +// dn_base.cpp // //////////////////////////////////////////////////////////////////////////////////////////////////// */ // NOTE: [$INTR] Intrinsics //////////////////////////////////////////////////////////////////////// -#if !defined(DQN_PLATFORM_ARM64) && !defined(DQN_PLATFORM_EMSCRIPTEN) -#if defined(DQN_COMPILER_GCC) || defined(DQN_COMPILER_CLANG) +#if !defined(DN_PLATFORM_ARM64) && !defined(DN_PLATFORM_EMSCRIPTEN) +#if defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG) #include #endif -Dqn_CPUFeatureDecl g_dqn_cpu_feature_decl[Dqn_CPUFeature_Count]; +DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; -DQN_API Dqn_CPUIDResult Dqn_CPU_ID(Dqn_CPUIDArgs args) +DN_API DN_CPUIDResult DN_CPU_ID(DN_CPUIDArgs args) { - Dqn_CPUIDResult result = {}; + DN_CPUIDResult result = {}; __cpuidex(result.values, args.eax, args.ecx); return result; } -DQN_API Dqn_usize Dqn_CPU_HasFeatureArray(Dqn_CPUReport const *report, Dqn_CPUFeatureQuery *features, Dqn_usize features_size) +DN_API DN_USize DN_CPU_HasFeatureArray(DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size) { - Dqn_usize result = 0; - Dqn_usize const BITS = sizeof(report->features[0]) * 8; - DQN_FOR_UINDEX(feature_index, features_size) { - Dqn_CPUFeatureQuery *query = features + feature_index; - Dqn_usize chunk_index = query->feature / BITS; - Dqn_usize chunk_bit = query->feature % BITS; + DN_USize result = 0; + DN_USize const BITS = sizeof(report->features[0]) * 8; + DN_FOR_UINDEX(feature_index, features_size) { + DN_CPUFeatureQuery *query = features + feature_index; + DN_USize chunk_index = query->feature / BITS; + DN_USize chunk_bit = query->feature % BITS; uint64_t chunk = report->features[chunk_index]; query->available = chunk & (1ULL << chunk_bit); - result += DQN_CAST(int)query->available; + result += DN_CAST(int)query->available; } return result; } -DQN_API bool Dqn_CPU_HasFeature(Dqn_CPUReport const *report, Dqn_CPUFeature feature) +DN_API bool DN_CPU_HasFeature(DN_CPUReport const *report, DN_CPUFeature feature) { - Dqn_CPUFeatureQuery query = {}; + DN_CPUFeatureQuery query = {}; query.feature = feature; - bool result = Dqn_CPU_HasFeatureArray(report, &query, 1) == 1; + bool result = DN_CPU_HasFeatureArray(report, &query, 1) == 1; return result; } -DQN_API bool Dqn_CPU_HasAllFeatures(Dqn_CPUReport const *report, Dqn_CPUFeature const *features, Dqn_usize features_size) +DN_API bool DN_CPU_HasAllFeatures(DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size) { bool result = true; - for (Dqn_usize index = 0; result && index < features_size; index++) - result &= Dqn_CPU_HasFeature(report, features[index]); + for (DN_USize index = 0; result && index < features_size; index++) + result &= DN_CPU_HasFeature(report, features[index]); return result; } -DQN_API void Dqn_CPU_SetFeature(Dqn_CPUReport *report, Dqn_CPUFeature feature) +DN_API void DN_CPU_SetFeature(DN_CPUReport *report, DN_CPUFeature feature) { - DQN_ASSERT(feature < Dqn_CPUFeature_Count); - Dqn_usize const BITS = sizeof(report->features[0]) * 8; - Dqn_usize chunk_index = feature / BITS; - Dqn_usize chunk_bit = feature % BITS; + DN_ASSERT(feature < DN_CPUFeature_Count); + DN_USize const BITS = sizeof(report->features[0]) * 8; + DN_USize chunk_index = feature / BITS; + DN_USize chunk_bit = feature % BITS; report->features[chunk_index] |= (1ULL << chunk_bit); } -DQN_API Dqn_CPUReport Dqn_CPU_Report() +DN_API DN_CPUReport DN_CPU_Report() { - Dqn_CPUReport result = {}; - Dqn_CPUIDResult fn_0000_[512] = {}; - Dqn_CPUIDResult fn_8000_[512] = {}; + DN_CPUReport result = {}; + DN_CPUIDResult fn_0000_[500] = {}; + DN_CPUIDResult fn_8000_[500] = {}; int const EXTENDED_FUNC_BASE_EAX = 0x8000'0000; int const REGISTER_SIZE = sizeof(fn_0000_[0].reg.eax); // NOTE: Query standard/extended numbers /////////////////////////////////////////////////////// { - Dqn_CPUIDArgs args = {}; + DN_CPUIDArgs args = {}; // NOTE: Query standard function (e.g. eax = 0x0) for function count + cpu vendor args = {}; - fn_0000_[0] = Dqn_CPU_ID(args); + fn_0000_[0] = DN_CPU_ID(args); // NOTE: Query extended function (e.g. eax = 0x8000'0000) for function count + cpu vendor args = {}; - args.eax = DQN_CAST(int) EXTENDED_FUNC_BASE_EAX; - fn_8000_[0] = Dqn_CPU_ID(args); + args.eax = DN_CAST(int) EXTENDED_FUNC_BASE_EAX; + fn_8000_[0] = DN_CPU_ID(args); } // NOTE: Extract function count //////////////////////////////////////////////////////////////// @@ -102,145 +102,145 @@ DQN_API Dqn_CPUReport Dqn_CPU_Report() // NOTE: Enumerate all CPUID results for the known function counts ///////////////////////////// { - DQN_ASSERTF((STANDARD_FUNC_MAX_EAX + 1) <= DQN_ARRAY_ICOUNT(fn_0000_), - "Max standard count is %zu", STANDARD_FUNC_MAX_EAX + 1); - DQN_ASSERTF((DQN_CAST(Dqn_isize)EXTENDED_FUNC_MAX_EAX - EXTENDED_FUNC_BASE_EAX + 1) <= DQN_ARRAY_ICOUNT(fn_8000_), - "Max extended count is %zu", DQN_CAST(Dqn_isize)EXTENDED_FUNC_MAX_EAX - EXTENDED_FUNC_BASE_EAX + 1); + DN_ASSERTF((STANDARD_FUNC_MAX_EAX + 1) <= DN_ARRAY_ICOUNT(fn_0000_), + "Max standard count is %d", STANDARD_FUNC_MAX_EAX + 1); + DN_ASSERTF((DN_CAST(DN_ISize)EXTENDED_FUNC_MAX_EAX - EXTENDED_FUNC_BASE_EAX + 1) <= DN_ARRAY_ICOUNT(fn_8000_), + "Max extended count is %zu", DN_CAST(DN_ISize)EXTENDED_FUNC_MAX_EAX - EXTENDED_FUNC_BASE_EAX + 1); for (int eax = 1; eax <= STANDARD_FUNC_MAX_EAX; eax++) { - Dqn_CPUIDArgs args = {}; + DN_CPUIDArgs args = {}; args.eax = eax; - fn_0000_[eax] = Dqn_CPU_ID(args); + fn_0000_[eax] = DN_CPU_ID(args); } for (int eax = EXTENDED_FUNC_BASE_EAX + 1, index = 1; eax <= EXTENDED_FUNC_MAX_EAX; eax++, index++) { - Dqn_CPUIDArgs args = {}; + DN_CPUIDArgs args = {}; args.eax = eax; - fn_8000_[index] = Dqn_CPU_ID(args); + fn_8000_[index] = DN_CPU_ID(args); } } // NOTE: Query CPU vendor ////////////////////////////////////////////////////////////////////// { - DQN_MEMCPY(result.vendor + 0, &fn_8000_[0x0000].reg.ebx, REGISTER_SIZE); - DQN_MEMCPY(result.vendor + 4, &fn_8000_[0x0000].reg.edx, REGISTER_SIZE); - DQN_MEMCPY(result.vendor + 8, &fn_8000_[0x0000].reg.ecx, REGISTER_SIZE); + DN_MEMCPY(result.vendor + 0, &fn_8000_[0x0000].reg.ebx, REGISTER_SIZE); + DN_MEMCPY(result.vendor + 4, &fn_8000_[0x0000].reg.edx, REGISTER_SIZE); + DN_MEMCPY(result.vendor + 8, &fn_8000_[0x0000].reg.ecx, REGISTER_SIZE); } // NOTE: Query CPU brand /////////////////////////////////////////////////////////////////////// if (EXTENDED_FUNC_MAX_EAX >= (EXTENDED_FUNC_BASE_EAX + 4)) { - DQN_MEMCPY(result.brand + 0, &fn_8000_[0x0002].reg.eax, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 4, &fn_8000_[0x0002].reg.ebx, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 8, &fn_8000_[0x0002].reg.ecx, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 12, &fn_8000_[0x0002].reg.edx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 0, &fn_8000_[0x0002].reg.eax, REGISTER_SIZE); + DN_MEMCPY(result.brand + 4, &fn_8000_[0x0002].reg.ebx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 8, &fn_8000_[0x0002].reg.ecx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 12, &fn_8000_[0x0002].reg.edx, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 16, &fn_8000_[0x0003].reg.eax, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 20, &fn_8000_[0x0003].reg.ebx, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 24, &fn_8000_[0x0003].reg.ecx, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 28, &fn_8000_[0x0003].reg.edx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 16, &fn_8000_[0x0003].reg.eax, REGISTER_SIZE); + DN_MEMCPY(result.brand + 20, &fn_8000_[0x0003].reg.ebx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 24, &fn_8000_[0x0003].reg.ecx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 28, &fn_8000_[0x0003].reg.edx, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 32, &fn_8000_[0x0004].reg.eax, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 36, &fn_8000_[0x0004].reg.ebx, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 40, &fn_8000_[0x0004].reg.ecx, REGISTER_SIZE); - DQN_MEMCPY(result.brand + 44, &fn_8000_[0x0004].reg.edx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 32, &fn_8000_[0x0004].reg.eax, REGISTER_SIZE); + DN_MEMCPY(result.brand + 36, &fn_8000_[0x0004].reg.ebx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 40, &fn_8000_[0x0004].reg.ecx, REGISTER_SIZE); + DN_MEMCPY(result.brand + 44, &fn_8000_[0x0004].reg.edx, REGISTER_SIZE); - DQN_ASSERT(result.brand[sizeof(result.brand) - 1] == 0); + DN_ASSERT(result.brand[sizeof(result.brand) - 1] == 0); } // NOTE: Query CPU features ////////////////////////////////////////////////////////////////// - for (Dqn_usize ext_index = 0; ext_index < Dqn_CPUFeature_Count; ext_index++) { + for (DN_USize ext_index = 0; ext_index < DN_CPUFeature_Count; ext_index++) { bool available = false; // NOTE: Mask bits taken from various manuals // - AMD64 Architecture Programmer's Manual, Volumes 1-5 // - https://en.wikipedia.org/wiki/CPUID#Calling_CPUID - switch (DQN_CAST(Dqn_CPUFeature)ext_index) { - case Dqn_CPUFeature_3DNow: available = (fn_8000_[0x0001].reg.edx & (1 << 31)); break; - case Dqn_CPUFeature_3DNowExt: available = (fn_8000_[0x0001].reg.edx & (1 << 30)); break; - case Dqn_CPUFeature_ABM: available = (fn_8000_[0x0001].reg.ecx & (1 << 5)); break; - case Dqn_CPUFeature_AES: available = (fn_0000_[0x0001].reg.ecx & (1 << 25)); break; - case Dqn_CPUFeature_AVX: available = (fn_0000_[0x0001].reg.ecx & (1 << 28)); break; - case Dqn_CPUFeature_AVX2: available = (fn_0000_[0x0007].reg.ebx & (1 << 0)); break; - case Dqn_CPUFeature_AVX512F: available = (fn_0000_[0x0007].reg.ebx & (1 << 16)); break; - case Dqn_CPUFeature_AVX512DQ: available = (fn_0000_[0x0007].reg.ebx & (1 << 17)); break; - case Dqn_CPUFeature_AVX512IFMA: available = (fn_0000_[0x0007].reg.ebx & (1 << 21)); break; - case Dqn_CPUFeature_AVX512PF: available = (fn_0000_[0x0007].reg.ebx & (1 << 26)); break; - case Dqn_CPUFeature_AVX512ER: available = (fn_0000_[0x0007].reg.ebx & (1 << 27)); break; - case Dqn_CPUFeature_AVX512CD: available = (fn_0000_[0x0007].reg.ebx & (1 << 28)); break; - case Dqn_CPUFeature_AVX512BW: available = (fn_0000_[0x0007].reg.ebx & (1 << 30)); break; - case Dqn_CPUFeature_AVX512VL: available = (fn_0000_[0x0007].reg.ebx & (1 << 31)); break; - case Dqn_CPUFeature_AVX512VBMI: available = (fn_0000_[0x0007].reg.ecx & (1 << 1)); break; - case Dqn_CPUFeature_AVX512VBMI2: available = (fn_0000_[0x0007].reg.ecx & (1 << 6)); break; - case Dqn_CPUFeature_AVX512VNNI: available = (fn_0000_[0x0007].reg.ecx & (1 << 11)); break; - case Dqn_CPUFeature_AVX512BITALG: available = (fn_0000_[0x0007].reg.ecx & (1 << 12)); break; - case Dqn_CPUFeature_AVX512VPOPCNTDQ: available = (fn_0000_[0x0007].reg.ecx & (1 << 14)); break; - case Dqn_CPUFeature_AVX5124VNNIW: available = (fn_0000_[0x0007].reg.edx & (1 << 2)); break; - case Dqn_CPUFeature_AVX5124FMAPS: available = (fn_0000_[0x0007].reg.edx & (1 << 3)); break; - case Dqn_CPUFeature_AVX512VP2INTERSECT: available = (fn_0000_[0x0007].reg.edx & (1 << 8)); break; - case Dqn_CPUFeature_AVX512FP16: available = (fn_0000_[0x0007].reg.edx & (1 << 23)); break; - case Dqn_CPUFeature_CLZERO: available = (fn_8000_[0x0008].reg.ebx & (1 << 0)); break; - case Dqn_CPUFeature_CMPXCHG8B: available = (fn_0000_[0x0001].reg.edx & (1 << 8)); break; - case Dqn_CPUFeature_CMPXCHG16B: available = (fn_0000_[0x0001].reg.ecx & (1 << 13)); break; - case Dqn_CPUFeature_F16C: available = (fn_0000_[0x0001].reg.ecx & (1 << 29)); break; - case Dqn_CPUFeature_FMA: available = (fn_0000_[0x0001].reg.ecx & (1 << 12)); break; - case Dqn_CPUFeature_FMA4: available = (fn_8000_[0x0001].reg.ecx & (1 << 16)); break; - case Dqn_CPUFeature_FP128: available = (fn_8000_[0x001A].reg.eax & (1 << 0)); break; - case Dqn_CPUFeature_FP256: available = (fn_8000_[0x001A].reg.eax & (1 << 2)); break; - case Dqn_CPUFeature_FPU: available = (fn_0000_[0x0001].reg.edx & (1 << 0)); break; - case Dqn_CPUFeature_MMX: available = (fn_0000_[0x0001].reg.edx & (1 << 23)); break; - case Dqn_CPUFeature_MONITOR: available = (fn_0000_[0x0001].reg.ecx & (1 << 3)); break; - case Dqn_CPUFeature_MOVBE: available = (fn_0000_[0x0001].reg.ecx & (1 << 22)); break; - case Dqn_CPUFeature_MOVU: available = (fn_8000_[0x001A].reg.eax & (1 << 1)); break; - case Dqn_CPUFeature_MmxExt: available = (fn_8000_[0x0001].reg.edx & (1 << 22)); break; - case Dqn_CPUFeature_PCLMULQDQ: available = (fn_0000_[0x0001].reg.ecx & (1 << 1)); break; - case Dqn_CPUFeature_POPCNT: available = (fn_0000_[0x0001].reg.ecx & (1 << 23)); break; - case Dqn_CPUFeature_RDRAND: available = (fn_0000_[0x0001].reg.ecx & (1 << 30)); break; - case Dqn_CPUFeature_RDSEED: available = (fn_0000_[0x0007].reg.ebx & (1 << 18)); break; - case Dqn_CPUFeature_RDTSCP: available = (fn_8000_[0x0001].reg.edx & (1 << 27)); break; - case Dqn_CPUFeature_SHA: available = (fn_0000_[0x0007].reg.ebx & (1 << 29)); break; - case Dqn_CPUFeature_SSE: available = (fn_0000_[0x0001].reg.edx & (1 << 25)); break; - case Dqn_CPUFeature_SSE2: available = (fn_0000_[0x0001].reg.edx & (1 << 26)); break; - case Dqn_CPUFeature_SSE3: available = (fn_0000_[0x0001].reg.ecx & (1 << 0)); break; - case Dqn_CPUFeature_SSE41: available = (fn_0000_[0x0001].reg.ecx & (1 << 19)); break; - case Dqn_CPUFeature_SSE42: available = (fn_0000_[0x0001].reg.ecx & (1 << 20)); break; - case Dqn_CPUFeature_SSE4A: available = (fn_8000_[0x0001].reg.ecx & (1 << 6)); break; - case Dqn_CPUFeature_SSSE3: available = (fn_0000_[0x0001].reg.ecx & (1 << 9)); break; - case Dqn_CPUFeature_TSC: available = (fn_0000_[0x0001].reg.edx & (1 << 4)); break; - case Dqn_CPUFeature_TscInvariant: available = (fn_8000_[0x0007].reg.edx & (1 << 8)); break; - case Dqn_CPUFeature_VAES: available = (fn_0000_[0x0007].reg.ecx & (1 << 9)); break; - case Dqn_CPUFeature_VPCMULQDQ: available = (fn_0000_[0x0007].reg.ecx & (1 << 10)); break; - case Dqn_CPUFeature_Count: DQN_INVALID_CODE_PATH; break; + switch (DN_CAST(DN_CPUFeature)ext_index) { + case DN_CPUFeature_3DNow: available = (fn_8000_[0x0001].reg.edx & (1 << 31)); break; + case DN_CPUFeature_3DNowExt: available = (fn_8000_[0x0001].reg.edx & (1 << 30)); break; + case DN_CPUFeature_ABM: available = (fn_8000_[0x0001].reg.ecx & (1 << 5)); break; + case DN_CPUFeature_AES: available = (fn_0000_[0x0001].reg.ecx & (1 << 25)); break; + case DN_CPUFeature_AVX: available = (fn_0000_[0x0001].reg.ecx & (1 << 28)); break; + case DN_CPUFeature_AVX2: available = (fn_0000_[0x0007].reg.ebx & (1 << 0)); break; + case DN_CPUFeature_AVX512F: available = (fn_0000_[0x0007].reg.ebx & (1 << 16)); break; + case DN_CPUFeature_AVX512DQ: available = (fn_0000_[0x0007].reg.ebx & (1 << 17)); break; + case DN_CPUFeature_AVX512IFMA: available = (fn_0000_[0x0007].reg.ebx & (1 << 21)); break; + case DN_CPUFeature_AVX512PF: available = (fn_0000_[0x0007].reg.ebx & (1 << 26)); break; + case DN_CPUFeature_AVX512ER: available = (fn_0000_[0x0007].reg.ebx & (1 << 27)); break; + case DN_CPUFeature_AVX512CD: available = (fn_0000_[0x0007].reg.ebx & (1 << 28)); break; + case DN_CPUFeature_AVX512BW: available = (fn_0000_[0x0007].reg.ebx & (1 << 30)); break; + case DN_CPUFeature_AVX512VL: available = (fn_0000_[0x0007].reg.ebx & (1 << 31)); break; + case DN_CPUFeature_AVX512VBMI: available = (fn_0000_[0x0007].reg.ecx & (1 << 1)); break; + case DN_CPUFeature_AVX512VBMI2: available = (fn_0000_[0x0007].reg.ecx & (1 << 6)); break; + case DN_CPUFeature_AVX512VNNI: available = (fn_0000_[0x0007].reg.ecx & (1 << 11)); break; + case DN_CPUFeature_AVX512BITALG: available = (fn_0000_[0x0007].reg.ecx & (1 << 12)); break; + case DN_CPUFeature_AVX512VPOPCNTDQ: available = (fn_0000_[0x0007].reg.ecx & (1 << 14)); break; + case DN_CPUFeature_AVX5124VNNIW: available = (fn_0000_[0x0007].reg.edx & (1 << 2)); break; + case DN_CPUFeature_AVX5124FMAPS: available = (fn_0000_[0x0007].reg.edx & (1 << 3)); break; + case DN_CPUFeature_AVX512VP2INTERSECT: available = (fn_0000_[0x0007].reg.edx & (1 << 8)); break; + case DN_CPUFeature_AVX512FP16: available = (fn_0000_[0x0007].reg.edx & (1 << 23)); break; + case DN_CPUFeature_CLZERO: available = (fn_8000_[0x0008].reg.ebx & (1 << 0)); break; + case DN_CPUFeature_CMPXCHG8B: available = (fn_0000_[0x0001].reg.edx & (1 << 8)); break; + case DN_CPUFeature_CMPXCHG16B: available = (fn_0000_[0x0001].reg.ecx & (1 << 13)); break; + case DN_CPUFeature_F16C: available = (fn_0000_[0x0001].reg.ecx & (1 << 29)); break; + case DN_CPUFeature_FMA: available = (fn_0000_[0x0001].reg.ecx & (1 << 12)); break; + case DN_CPUFeature_FMA4: available = (fn_8000_[0x0001].reg.ecx & (1 << 16)); break; + case DN_CPUFeature_FP128: available = (fn_8000_[0x001A].reg.eax & (1 << 0)); break; + case DN_CPUFeature_FP256: available = (fn_8000_[0x001A].reg.eax & (1 << 2)); break; + case DN_CPUFeature_FPU: available = (fn_0000_[0x0001].reg.edx & (1 << 0)); break; + case DN_CPUFeature_MMX: available = (fn_0000_[0x0001].reg.edx & (1 << 23)); break; + case DN_CPUFeature_MONITOR: available = (fn_0000_[0x0001].reg.ecx & (1 << 3)); break; + case DN_CPUFeature_MOVBE: available = (fn_0000_[0x0001].reg.ecx & (1 << 22)); break; + case DN_CPUFeature_MOVU: available = (fn_8000_[0x001A].reg.eax & (1 << 1)); break; + case DN_CPUFeature_MmxExt: available = (fn_8000_[0x0001].reg.edx & (1 << 22)); break; + case DN_CPUFeature_PCLMULQDQ: available = (fn_0000_[0x0001].reg.ecx & (1 << 1)); break; + case DN_CPUFeature_POPCNT: available = (fn_0000_[0x0001].reg.ecx & (1 << 23)); break; + case DN_CPUFeature_RDRAND: available = (fn_0000_[0x0001].reg.ecx & (1 << 30)); break; + case DN_CPUFeature_RDSEED: available = (fn_0000_[0x0007].reg.ebx & (1 << 18)); break; + case DN_CPUFeature_RDTSCP: available = (fn_8000_[0x0001].reg.edx & (1 << 27)); break; + case DN_CPUFeature_SHA: available = (fn_0000_[0x0007].reg.ebx & (1 << 29)); break; + case DN_CPUFeature_SSE: available = (fn_0000_[0x0001].reg.edx & (1 << 25)); break; + case DN_CPUFeature_SSE2: available = (fn_0000_[0x0001].reg.edx & (1 << 26)); break; + case DN_CPUFeature_SSE3: available = (fn_0000_[0x0001].reg.ecx & (1 << 0)); break; + case DN_CPUFeature_SSE41: available = (fn_0000_[0x0001].reg.ecx & (1 << 19)); break; + case DN_CPUFeature_SSE42: available = (fn_0000_[0x0001].reg.ecx & (1 << 20)); break; + case DN_CPUFeature_SSE4A: available = (fn_8000_[0x0001].reg.ecx & (1 << 6)); break; + case DN_CPUFeature_SSSE3: available = (fn_0000_[0x0001].reg.ecx & (1 << 9)); break; + case DN_CPUFeature_TSC: available = (fn_0000_[0x0001].reg.edx & (1 << 4)); break; + case DN_CPUFeature_TscInvariant: available = (fn_8000_[0x0007].reg.edx & (1 << 8)); break; + case DN_CPUFeature_VAES: available = (fn_0000_[0x0007].reg.ecx & (1 << 9)); break; + case DN_CPUFeature_VPCMULQDQ: available = (fn_0000_[0x0007].reg.ecx & (1 << 10)); break; + case DN_CPUFeature_Count: DN_INVALID_CODE_PATH; break; } if (available) - Dqn_CPU_SetFeature(&result, DQN_CAST(Dqn_CPUFeature)ext_index); + DN_CPU_SetFeature(&result, DN_CAST(DN_CPUFeature)ext_index); } return result; } -#endif // !defined(DQN_PLATFORM_ARM64) && !defined(DQN_PLATFORM_EMSCRIPTEN) +#endif // !defined(DN_PLATFORM_ARM64) && !defined(DN_PLATFORM_EMSCRIPTEN) -// NOTE: [$TMUT] Dqn_TicketMutex /////////////////////////////////////////////////////////////////// -DQN_API void Dqn_TicketMutex_Begin(Dqn_TicketMutex *mutex) +// NOTE: [$TMUT] DN_TicketMutex /////////////////////////////////////////////////////////////////// +DN_API void DN_TicketMutex_Begin(DN_TicketMutex *mutex) { - unsigned int ticket = Dqn_Atomic_AddU32(&mutex->ticket, 1); - Dqn_TicketMutex_BeginTicket(mutex, ticket); + unsigned int ticket = DN_Atomic_AddU32(&mutex->ticket, 1); + DN_TicketMutex_BeginTicket(mutex, ticket); } -DQN_API void Dqn_TicketMutex_End(Dqn_TicketMutex *mutex) +DN_API void DN_TicketMutex_End(DN_TicketMutex *mutex) { - Dqn_Atomic_AddU32(&mutex->serving, 1); + DN_Atomic_AddU32(&mutex->serving, 1); } -DQN_API Dqn_uint Dqn_TicketMutex_MakeTicket(Dqn_TicketMutex *mutex) +DN_API DN_UInt DN_TicketMutex_MakeTicket(DN_TicketMutex *mutex) { - Dqn_uint result = Dqn_Atomic_AddU32(&mutex->ticket, 1); + DN_UInt result = DN_Atomic_AddU32(&mutex->ticket, 1); return result; } -DQN_API void Dqn_TicketMutex_BeginTicket(Dqn_TicketMutex const *mutex, Dqn_uint ticket) +DN_API void DN_TicketMutex_BeginTicket(DN_TicketMutex const *mutex, DN_UInt ticket) { - DQN_ASSERTF(mutex->serving <= ticket, + DN_ASSERTF(mutex->serving <= ticket, "Mutex skipped ticket? Was ticket generated by the correct mutex via MakeTicket? ticket = %u, " "mutex->serving = %u", ticket, @@ -251,22 +251,22 @@ DQN_API void Dqn_TicketMutex_BeginTicket(Dqn_TicketMutex const *mutex, Dqn_uint } } -DQN_API bool Dqn_TicketMutex_CanLock(Dqn_TicketMutex const *mutex, Dqn_uint ticket) +DN_API bool DN_TicketMutex_CanLock(DN_TicketMutex const *mutex, DN_UInt ticket) { bool result = (ticket == mutex->serving); return result; } -#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) - #if !defined(DQN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED) +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) + #if !defined(DN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED) #undef _CRT_SECURE_NO_WARNINGS #endif #endif -// NOTE: [$PRIN] Dqn_Print ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_PrintStyle Dqn_Print_StyleColour(uint8_t r, uint8_t g, uint8_t b, Dqn_PrintBold bold) +// NOTE: [$PRIN] DN_Print ///////////////////////////////////////////////////////////////////////// +DN_API DN_PrintStyle DN_Print_StyleColour(uint8_t r, uint8_t g, uint8_t b, DN_PrintBold bold) { - Dqn_PrintStyle result = {}; + DN_PrintStyle result = {}; result.bold = bold; result.colour = true; result.r = r; @@ -275,32 +275,32 @@ DQN_API Dqn_PrintStyle Dqn_Print_StyleColour(uint8_t r, uint8_t g, uint8_t b, Dq return result; } -DQN_API Dqn_PrintStyle Dqn_Print_StyleColourU32(uint32_t rgb, Dqn_PrintBold bold) +DN_API DN_PrintStyle DN_Print_StyleColourU32(uint32_t rgb, DN_PrintBold bold) { uint8_t r = (rgb >> 24) & 0xFF; uint8_t g = (rgb >> 16) & 0xFF; uint8_t b = (rgb >> 8) & 0xFF; - Dqn_PrintStyle result = Dqn_Print_StyleColour(r, g, b, bold); + DN_PrintStyle result = DN_Print_StyleColour(r, g, b, bold); return result; } -DQN_API Dqn_PrintStyle Dqn_Print_StyleBold() +DN_API DN_PrintStyle DN_Print_StyleBold() { - Dqn_PrintStyle result = {}; - result.bold = Dqn_PrintBold_Yes; + DN_PrintStyle result = {}; + result.bold = DN_PrintBold_Yes; return result; } -DQN_API void Dqn_Print_Std(Dqn_PrintStd std_handle, Dqn_Str8 string) +DN_API void DN_Print_Std(DN_PrintStd std_handle, DN_Str8 string) { - DQN_ASSERT(std_handle == Dqn_PrintStd_Out || std_handle == Dqn_PrintStd_Err); + DN_ASSERT(std_handle == DN_PrintStd_Out || std_handle == DN_PrintStd_Err); - #if defined(DQN_OS_WIN32) + #if defined(DN_OS_WIN32) // NOTE: Get the output handles from kernel //////////////////////////////////////////////////// - DQN_THREAD_LOCAL void *std_out_print_handle = nullptr; - DQN_THREAD_LOCAL void *std_err_print_handle = nullptr; - DQN_THREAD_LOCAL bool std_out_print_to_console = false; - DQN_THREAD_LOCAL bool std_err_print_to_console = false; + 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; @@ -314,182 +314,182 @@ DQN_API void Dqn_Print_Std(Dqn_PrintStd std_handle, Dqn_Str8 string) // NOTE: Select the output handle ////////////////////////////////////////////////////////////// void *print_handle = std_out_print_handle; bool print_to_console = std_out_print_to_console; - if (std_handle == Dqn_PrintStd_Err) { + if (std_handle == DN_PrintStd_Err) { print_handle = std_err_print_handle; print_to_console = std_err_print_to_console; } // NOTE: Write the string ////////////////////////////////////////////////////////////////////// - DQN_ASSERT(string.size < DQN_CAST(unsigned long)-1); + 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, DQN_CAST(unsigned long)string.size, &bytes_written, nullptr); + WriteConsoleA(print_handle, string.data, DN_CAST(unsigned long)string.size, &bytes_written, nullptr); } else { - WriteFile(print_handle, string.data, DQN_CAST(unsigned long)string.size, &bytes_written, nullptr); + WriteFile(print_handle, string.data, DN_CAST(unsigned long)string.size, &bytes_written, nullptr); } #else - fprintf(std_handle == Dqn_PrintStd_Out ? stdout : stderr, "%.*s", DQN_STR_FMT(string)); + fprintf(std_handle == DN_PrintStd_Out ? stdout : stderr, "%.*s", DN_STR_FMT(string)); #endif } -DQN_API void Dqn_Print_StdStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_Str8 string) +DN_API void DN_Print_StdStyle(DN_PrintStd std_handle, DN_PrintStyle style, DN_Str8 string) { if (string.data && string.size) { if (style.colour) - Dqn_Print_Std(std_handle, Dqn_Print_ESCColourFgStr8(style.r, style.g, style.b)); - if (style.bold == Dqn_PrintBold_Yes) - Dqn_Print_Std(std_handle, Dqn_Print_ESCBoldStr8); - Dqn_Print_Std(std_handle, string); - if (style.colour || style.bold == Dqn_PrintBold_Yes) - Dqn_Print_Std(std_handle, Dqn_Print_ESCResetStr8); + DN_Print_Std(std_handle, DN_Print_ESCColourFgStr8(style.r, style.g, style.b)); + if (style.bold == DN_PrintBold_Yes) + DN_Print_Std(std_handle, DN_Print_ESCBoldStr8); + DN_Print_Std(std_handle, string); + if (style.colour || style.bold == DN_PrintBold_Yes) + DN_Print_Std(std_handle, DN_Print_ESCResetStr8); } } -DQN_API void Dqn_Print_StdF(Dqn_PrintStd std_handle, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API void DN_Print_StdF(DN_PrintStd std_handle, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_Print_StdFV(std_handle, fmt, args); + DN_Print_StdFV(std_handle, fmt, args); va_end(args); } -DQN_API void Dqn_Print_StdFStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API void DN_Print_StdFStyle(DN_PrintStd std_handle, DN_PrintStyle style, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_Print_StdFVStyle(std_handle, style, fmt, args); + DN_Print_StdFVStyle(std_handle, style, fmt, args); va_end(args); } -#if !defined(DQN_USE_STD_PRINTF) -DQN_FILE_SCOPE char *Dqn_Print_VSPrintfChunker_(const char *buf, void *user, int len) +#if !defined(DN_USE_STD_PRINTF) +DN_FILE_SCOPE char *DN_Print_VSPrintfChunker_(const char *buf, void *user, int len) { - Dqn_Str8 string = {}; - string.data = DQN_CAST(char *)buf; + DN_Str8 string = {}; + string.data = DN_CAST(char *)buf; string.size = len; - Dqn_PrintStd std_handle = DQN_CAST(Dqn_PrintStd)DQN_CAST(uintptr_t)user; - Dqn_Print_Std(std_handle, string); + DN_PrintStd std_handle = DN_CAST(DN_PrintStd)DN_CAST(uintptr_t)user; + DN_Print_Std(std_handle, string); return (char *)buf; } #endif -DQN_API void Dqn_Print_StdFV(Dqn_PrintStd std_handle, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API void DN_Print_StdFV(DN_PrintStd std_handle, DN_FMT_ATTRIB char const *fmt, va_list args) { - #if defined(DQN_USE_STD_PRINTF) - vfprintf(std_handle == Dqn_PrintStd_Out ? stdout : stderr, fmt, args); + #if defined(DN_USE_STD_PRINTF) + vfprintf(std_handle == DN_PrintStd_Out ? stdout : stderr, fmt, args); #else char buffer[STB_SPRINTF_MIN]; - STB_SPRINTF_DECORATE(vsprintfcb)(Dqn_Print_VSPrintfChunker_, DQN_CAST(void *)DQN_CAST(uintptr_t)std_handle, buffer, fmt, args); + STB_SPRINTF_DECORATE(vsprintfcb)(DN_Print_VSPrintfChunker_, DN_CAST(void *)DN_CAST(uintptr_t)std_handle, buffer, fmt, args); #endif } -DQN_API void Dqn_Print_StdFVStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API void DN_Print_StdFVStyle(DN_PrintStd std_handle, DN_PrintStyle style, DN_FMT_ATTRIB char const *fmt, va_list args) { if (fmt) { if (style.colour) - Dqn_Print_Std(std_handle, Dqn_Print_ESCColourFgStr8(style.r, style.g, style.b)); - if (style.bold == Dqn_PrintBold_Yes) - Dqn_Print_Std(std_handle, Dqn_Print_ESCBoldStr8); - Dqn_Print_StdFV(std_handle, fmt, args); - if (style.colour || style.bold == Dqn_PrintBold_Yes) - Dqn_Print_Std(std_handle, Dqn_Print_ESCResetStr8); + DN_Print_Std(std_handle, DN_Print_ESCColourFgStr8(style.r, style.g, style.b)); + if (style.bold == DN_PrintBold_Yes) + DN_Print_Std(std_handle, DN_Print_ESCBoldStr8); + DN_Print_StdFV(std_handle, fmt, args); + if (style.colour || style.bold == DN_PrintBold_Yes) + DN_Print_Std(std_handle, DN_Print_ESCResetStr8); } } -DQN_API void Dqn_Print_StdLn(Dqn_PrintStd std_handle, Dqn_Str8 string) +DN_API void DN_Print_StdLn(DN_PrintStd std_handle, DN_Str8 string) { - Dqn_Print_Std(std_handle, string); - Dqn_Print_Std(std_handle, DQN_STR8("\n")); + DN_Print_Std(std_handle, string); + DN_Print_Std(std_handle, DN_STR8("\n")); } -DQN_API void Dqn_Print_StdLnF(Dqn_PrintStd std_handle, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API void DN_Print_StdLnF(DN_PrintStd std_handle, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_Print_StdLnFV(std_handle, fmt, args); + DN_Print_StdLnFV(std_handle, fmt, args); va_end(args); } -DQN_API void Dqn_Print_StdLnFV(Dqn_PrintStd std_handle, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API void DN_Print_StdLnFV(DN_PrintStd std_handle, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_Print_StdFV(std_handle, fmt, args); - Dqn_Print_Std(std_handle, DQN_STR8("\n")); + DN_Print_StdFV(std_handle, fmt, args); + DN_Print_Std(std_handle, DN_STR8("\n")); } -DQN_API void Dqn_Print_StdLnStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_Str8 string) +DN_API void DN_Print_StdLnStyle(DN_PrintStd std_handle, DN_PrintStyle style, DN_Str8 string) { - Dqn_Print_StdStyle(std_handle, style, string); - Dqn_Print_Std(std_handle, DQN_STR8("\n")); + DN_Print_StdStyle(std_handle, style, string); + DN_Print_Std(std_handle, DN_STR8("\n")); } -DQN_API void Dqn_Print_StdLnFStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API void DN_Print_StdLnFStyle(DN_PrintStd std_handle, DN_PrintStyle style, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_Print_StdLnFVStyle(std_handle, style, fmt, args); + DN_Print_StdLnFVStyle(std_handle, style, fmt, args); va_end(args); } -DQN_API void Dqn_Print_StdLnFVStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API void DN_Print_StdLnFVStyle(DN_PrintStd std_handle, DN_PrintStyle style, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_Print_StdFVStyle(std_handle, style, fmt, args); - Dqn_Print_Std(std_handle, DQN_STR8("\n")); + DN_Print_StdFVStyle(std_handle, style, fmt, args); + DN_Print_Std(std_handle, DN_STR8("\n")); } -DQN_API Dqn_Str8 Dqn_Print_ESCColourStr8(Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b) +DN_API DN_Str8 DN_Print_ESCColourStr8(DN_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b) { - DQN_THREAD_LOCAL char buffer[32]; + DN_THREAD_LOCAL char buffer[32]; buffer[0] = 0; - Dqn_Str8 result = {}; - result.size = DQN_SNPRINTF(buffer, - DQN_ARRAY_UCOUNT(buffer), + DN_Str8 result = {}; + result.size = DN_SNPRINTF(buffer, + DN_ARRAY_UCOUNT(buffer), "\x1b[%d;2;%u;%u;%um", - colour == Dqn_PrintESCColour_Fg ? 38 : 48, + colour == DN_PrintESCColour_Fg ? 38 : 48, r, g, b); result.data = buffer; return result; } -DQN_API Dqn_Str8 Dqn_Print_ESCColourU32Str8(Dqn_PrintESCColour colour, uint32_t value) +DN_API DN_Str8 DN_Print_ESCColourU32Str8(DN_PrintESCColour colour, uint32_t value) { - uint8_t r = DQN_CAST(uint8_t)(value >> 24); - uint8_t g = DQN_CAST(uint8_t)(value >> 16); - uint8_t b = DQN_CAST(uint8_t)(value >> 8); - Dqn_Str8 result = Dqn_Print_ESCColourStr8(colour, r, g, b); + uint8_t r = DN_CAST(uint8_t)(value >> 24); + uint8_t g = DN_CAST(uint8_t)(value >> 16); + uint8_t b = DN_CAST(uint8_t)(value >> 8); + DN_Str8 result = DN_Print_ESCColourStr8(colour, r, g, b); return result; } -// NOTE: [$LLOG] Dqn_Log /////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8 Dqn_Log_MakeStr8(Dqn_Arena *arena, +// NOTE: [$LLOG] DN_Log /////////////////////////////////////////////////////////////////////////// +DN_API DN_Str8 DN_Log_MakeStr8(DN_Arena *arena, bool colour, - Dqn_Str8 type, + DN_Str8 type, int log_type, - Dqn_CallSite call_site, - DQN_FMT_ATTRIB char const *fmt, + DN_CallSite call_site, + DN_FMT_ATTRIB char const *fmt, va_list args) { - 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); + DN_LOCAL_PERSIST DN_USize max_type_length = 0; + max_type_length = DN_MAX(max_type_length, type.size); + int type_padding = DN_CAST(int)(max_type_length - type.size); - Dqn_Str8 colour_esc = {}; - Dqn_Str8 bold_esc = {}; - Dqn_Str8 reset_esc = {}; + DN_Str8 colour_esc = {}; + DN_Str8 bold_esc = {}; + DN_Str8 reset_esc = {}; if (colour) { - bold_esc = Dqn_Print_ESCBoldStr8; - reset_esc = Dqn_Print_ESCResetStr8; + bold_esc = DN_Print_ESCBoldStr8; + reset_esc = DN_Print_ESCResetStr8; switch (log_type) { - case Dqn_LogType_Debug: break; - case Dqn_LogType_Info: colour_esc = Dqn_Print_ESCColourFgU32Str8(Dqn_LogTypeColourU32_Info); break; - case Dqn_LogType_Warning: colour_esc = Dqn_Print_ESCColourFgU32Str8(Dqn_LogTypeColourU32_Warning); break; - case Dqn_LogType_Error: colour_esc = Dqn_Print_ESCColourFgU32Str8(Dqn_LogTypeColourU32_Error); break; + case DN_LogType_Debug: break; + case DN_LogType_Info: colour_esc = DN_Print_ESCColourFgU32Str8(DN_LogTypeColourU32_Info); break; + case DN_LogType_Warning: colour_esc = DN_Print_ESCColourFgU32Str8(DN_LogTypeColourU32_Warning); break; + case DN_LogType_Error: colour_esc = DN_Print_ESCColourFgU32Str8(DN_LogTypeColourU32_Error); break; } } - Dqn_Str8 file_name = Dqn_Str8_FileNameFromPath(call_site.file); - Dqn_OSDateTimeStr8 const time = Dqn_OS_DateLocalTimeStr8Now(); - Dqn_Str8 header = Dqn_Str8_InitF(arena, + DN_Str8 file_name = DN_Str8_FileNameFromPath(call_site.file); + DN_OSDateTimeStr8 const time = DN_OS_DateLocalTimeStr8Now(); + DN_Str8 header = DN_Str8_InitF(arena, "%.*s " // date "%.*s " // hms "%.*s" // colour @@ -500,219 +500,338 @@ DQN_API Dqn_Str8 Dqn_Log_MakeStr8(Dqn_Arena *arena, " %.*s" // file name ":%05I32u " // line number , - DQN_CAST(int)time.date_size - 2, time.date + 2, // date - DQN_CAST(int)time.hms_size, time.hms, // hms - DQN_STR_FMT(colour_esc), // colour - DQN_STR_FMT(bold_esc), // bold - DQN_STR_FMT(type), // type - DQN_CAST(int)type_padding, "", // type padding - DQN_STR_FMT(reset_esc), // reset - DQN_STR_FMT(file_name), // file name + DN_CAST(int)time.date_size - 2, time.date + 2, // date + DN_CAST(int)time.hms_size, time.hms, // hms + DN_STR_FMT(colour_esc), // colour + DN_STR_FMT(bold_esc), // bold + DN_STR_FMT(type), // type + DN_CAST(int)type_padding, "", // type padding + DN_STR_FMT(reset_esc), // reset + DN_STR_FMT(file_name), // file name call_site.line); // line number - Dqn_usize header_size_no_ansi_codes = header.size - colour_esc.size - Dqn_Print_ESCResetStr8.size; + DN_USize header_size_no_ansi_codes = header.size - colour_esc.size - DN_Print_ESCResetStr8.size; // NOTE: Header padding //////////////////////////////////////////////////////////////////////// - DQN_LOCAL_PERSIST Dqn_usize max_header_length = 0; - max_header_length = DQN_MAX(max_header_length, header_size_no_ansi_codes); - Dqn_usize header_padding = max_header_length - header_size_no_ansi_codes; + DN_LOCAL_PERSIST DN_USize max_header_length = 0; + max_header_length = DN_MAX(max_header_length, header_size_no_ansi_codes); + DN_USize header_padding = max_header_length - header_size_no_ansi_codes; // NOTE: Construct final log /////////////////////////////////////////////////////////////////// - Dqn_Str8 user_msg = Dqn_Str8_InitFV(arena, fmt, args); - Dqn_Str8 result = Dqn_Str8_Alloc(arena, header.size + header_padding + user_msg.size, Dqn_ZeroMem_No); - if (Dqn_Str8_HasData(result)) { - DQN_MEMCPY(result.data, header.data, header.size); - DQN_MEMSET(result.data + header.size, ' ', header_padding); - if (Dqn_Str8_HasData(user_msg)) - DQN_MEMCPY(result.data + header.size + header_padding, user_msg.data, user_msg.size); + DN_Str8 user_msg = DN_Str8_InitFV(arena, fmt, args); + DN_Str8 result = DN_Str8_Alloc(arena, header.size + header_padding + user_msg.size, DN_ZeroMem_No); + if (DN_Str8_HasData(result)) { + DN_MEMCPY(result.data, header.data, header.size); + DN_MEMSET(result.data + header.size, ' ', header_padding); + if (DN_Str8_HasData(user_msg)) + DN_MEMCPY(result.data + header.size + header_padding, user_msg.data, user_msg.size); } return result; } -DQN_FILE_SCOPE void Dqn_Log_FVDefault_(Dqn_Str8 type, int log_type, void *user_data, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_FILE_SCOPE void DN_Log_FVDefault_(DN_Str8 type, int log_type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_Library *lib = g_dqn_library; + DN_Core *core = g_dn_core; (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) { - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 log_path = Dqn_OS_PathF(t_mem.arena, "%.*s/dqn.log", DQN_STR_FMT(lib->exe_dir)); - lib->log_file = Dqn_OS_FileOpen(log_path, Dqn_OSFileOpen_CreateAlways, Dqn_OSFileAccess_AppendOnly, nullptr); + DN_TicketMutex_Begin(&core->log_file_mutex); + if (core->log_to_file && !core->log_file.handle && !core->log_file.error) { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 log_path = DN_OS_PathF(tmem.arena, "%.*s/dn.log", DN_STR_FMT(core->exe_dir)); + core->log_file = DN_OS_FileOpen(log_path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_AppendOnly, nullptr); } - Dqn_TicketMutex_End(&lib->log_file_mutex); + DN_TicketMutex_End(&core->log_file_mutex); // NOTE: Generate the log header /////////////////////////////////////////// - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 log_line = Dqn_Log_MakeStr8(t_mem.arena, !lib->log_no_colour, type, log_type, call_site, fmt, args); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 log_line = DN_Log_MakeStr8(tmem.arena, !core->log_no_colour, type, log_type, call_site, fmt, args); // NOTE: Print log ///////////////////////////////////////////////////////// - Dqn_Print_StdLn(Dqn_PrintStd_Out, log_line); + DN_Print_StdLn(log_type == DN_LogType_Error ? DN_PrintStd_Err : DN_PrintStd_Out, log_line); - Dqn_TicketMutex_Begin(&lib->log_file_mutex); - Dqn_OS_FileWrite(&lib->log_file, log_line, nullptr); - Dqn_OS_FileWrite(&lib->log_file, DQN_STR8("\n"), nullptr); - Dqn_TicketMutex_End(&lib->log_file_mutex); + DN_TicketMutex_Begin(&core->log_file_mutex); + DN_OS_FileWrite(&core->log_file, log_line, nullptr); + DN_OS_FileWrite(&core->log_file, DN_STR8("\n"), nullptr); + DN_TicketMutex_End(&core->log_file_mutex); } -DQN_API void Dqn_Log_FVCallSite(Dqn_Str8 type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API void DN_Log_FVCallSite(DN_Str8 type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) { - if (g_dqn_library) { - 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); + if (g_dn_core) { + DN_LogProc *logging_function = g_dn_core->log_callback ? g_dn_core->log_callback : DN_Log_FVDefault_; + logging_function(type, -1 /*log_type*/, g_dn_core->log_user_data, call_site, fmt, args); } else { // NOTE: Rarely taken branch, only when trying to use this library without initialising it - Dqn_Print_StdLnFV(Dqn_PrintStd_Out, fmt, args); + DN_Print_StdLnFV(DN_PrintStd_Out, fmt, args); } } -DQN_API void Dqn_Log_FCallSite(Dqn_Str8 type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API void DN_Log_FCallSite(DN_Str8 type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_Log_FVCallSite(type, call_site, fmt, args); + DN_Log_FVCallSite(type, call_site, fmt, args); va_end(args); } -DQN_API void Dqn_Log_TypeFVCallSite(Dqn_LogType type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API void DN_Log_TypeFVCallSite(DN_LogType type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_Str8 type_string = DQN_STR8("DQN-BAD-LOG-TYPE"); + DN_Str8 type_string = DN_STR8("DN-BAD-LOG-TYPE"); switch (type) { - case Dqn_LogType_Error: type_string = DQN_STR8("ERROR"); break; - case Dqn_LogType_Info: type_string = DQN_STR8("INFO"); break; - case Dqn_LogType_Warning: type_string = DQN_STR8("WARN"); break; - case Dqn_LogType_Debug: type_string = DQN_STR8("DEBUG"); break; - case Dqn_LogType_Count: type_string = DQN_STR8("BADXX"); break; + case DN_LogType_Error: type_string = DN_STR8("ERROR"); break; + case DN_LogType_Info: type_string = DN_STR8("INFO"); break; + case DN_LogType_Warning: type_string = DN_STR8("WARN"); break; + case DN_LogType_Debug: type_string = DN_STR8("DEBUG"); break; + case DN_LogType_Count: type_string = DN_STR8("BADXX"); break; } - Dqn_Log_FVCallSite(type_string, call_site, fmt, args); + DN_Log_FVCallSite(type_string, call_site, fmt, args); } -DQN_API void Dqn_Log_TypeFCallSite(Dqn_LogType type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API void DN_Log_TypeFCallSite(DN_LogType type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_Log_TypeFVCallSite(type, call_site, fmt, args); + DN_Log_TypeFVCallSite(type, call_site, fmt, args); va_end(args); } -// NOTE: [$ERRS] Dqn_ErrorSink ///////////////////////////////////////////////////////////////////// -DQN_API Dqn_ErrorSink *Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode mode) +// NOTE: [$ERRS] DN_ErrSink ///////////////////////////////////////////////////////////////////// +DN_FILE_SCOPE void DN_ErrSink_Check_(DN_ErrSink const *err) { - Dqn_TLS *tls = Dqn_TLS_Get(); - Dqn_ErrorSink *result = &tls->error_sink; - Dqn_usize arena_pos = Dqn_Arena_Pos(result->arena); - Dqn_ErrorSinkNode *node = Dqn_Arena_New(result->arena, Dqn_ErrorSinkNode, Dqn_ZeroMem_Yes); - node->next = result->stack; - node->arena_pos = arena_pos; - node->mode = mode; - result->stack = node; - return result; -} - -DQN_API bool Dqn_ErrorSink_HasError(Dqn_ErrorSink *error) -{ - bool result = error && error->stack->error; - return result; -} - -DQN_API Dqn_ErrorSinkNode Dqn_ErrorSink_End(Dqn_Arena *arena, Dqn_ErrorSink *error) -{ - Dqn_ErrorSinkNode result = {}; - if (!error) - return result; - - Dqn_ErrorSinkNode *node = error->stack; - if (!node) - return result; - - DQN_ASSERTF(arena != error->arena, - "You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost"); - result = *error->stack; - result.next = nullptr; - result.msg = Dqn_Str8_Copy(arena, result.msg); - error->stack = error->stack->next; - Dqn_Arena_PopTo(error->arena, result.arena_pos); - return result; -} - -DQN_API void Dqn_ErrorSink_EndAndIgnore(Dqn_ErrorSink *error) -{ - Dqn_ErrorSink_End(nullptr, error); -} - -DQN_API bool Dqn_ErrorSink_EndAndLogError(Dqn_ErrorSink *error, Dqn_Str8 error_msg) -{ - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_ErrorSinkNode node = Dqn_ErrorSink_End(t_mem.arena, error); - if (node.error) { - if (Dqn_Str8_HasData(error_msg)) { - Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s: %.*s", DQN_STR_FMT(error_msg), DQN_STR_FMT(node.msg)); - } else { - Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s", DQN_STR_FMT(node.msg)); - } - } - bool result = node.error; - return result; -} - -DQN_API bool Dqn_ErrorSink_EndAndLogErrorFV(Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args) -{ - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 log = Dqn_Str8_InitFV(t_mem.arena, fmt, args); - bool result = Dqn_ErrorSink_EndAndLogError(error, log); - return result; -} - -DQN_API bool Dqn_ErrorSink_EndAndLogErrorF(Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 log = Dqn_Str8_InitFV(t_mem.arena, fmt, args); - bool result = Dqn_ErrorSink_EndAndLogError(error, log); - va_end(args); - return result; -} - -DQN_API void Dqn_ErrorSink_EndAndExitIfErrorFV(Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, va_list args) -{ - if (Dqn_ErrorSink_EndAndLogErrorFV(error, fmt, args)) { - DQN_DEBUG_BREAK; - Dqn_OS_Exit(exit_code); - } -} - -DQN_API void Dqn_ErrorSink_EndAndExitIfErrorF(Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_ErrorSink_EndAndExitIfErrorFV(error, exit_code, fmt, args); - va_end(args); -} - -DQN_API void Dqn_ErrorSink_MakeFV_(Dqn_ErrorSink *error, uint32_t error_code, DQN_FMT_ATTRIB char const *fmt, va_list args) -{ - if (!error) + DN_ASSERTF(err->arena, "Arena should be assigned in TLS init"); + if (!err->stack) return; - Dqn_ErrorSinkNode *node = error->stack; - DQN_ASSERTF(node, "Error sink must be begun by calling 'Begin' before using this function."); - if (!node->error) { // NOTE: Only preserve the first error - node->msg = Dqn_Str8_InitFV(error->arena, fmt, args); - node->error_code = error_code; - node->error = true; - node->call_site = Dqn_TLS_Get()->call_site; - if (node->mode == Dqn_ErrorSinkMode_ExitOnError) - Dqn_ErrorSink_EndAndExitIfErrorF(error, error_code, "Fatal error %u", error_code); + DN_ErrSinkNode *node = err->stack; + DN_ASSERT(node->mode >= DN_ErrSinkMode_Nil && node->mode <= DN_ErrSinkMode_ExitOnError); + DN_ASSERTF(node->next != node, "Error nodes cannot point to themselves"); + 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); } } -DQN_API void Dqn_ErrorSink_MakeF_(Dqn_ErrorSink *error, uint32_t error_code, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API DN_ErrSink *DN_ErrSink_Begin(DN_ErrSinkMode mode) +{ + DN_TLS *tls = DN_TLS_Get(); + DN_ErrSink *result = &tls->err_sink; + DN_USize arena_pos = DN_Arena_Pos(result->arena); + DN_ErrSinkNode *node = DN_Arena_New(result->arena, DN_ErrSinkNode, DN_ZeroMem_Yes); + if (node) { + node->next = result->stack; + node->arena_pos = arena_pos; + node->mode = mode; + DN_SentinelDLL_InitArena(node->msg_sentinel, DN_ErrSinkMsg, result->arena); + + // NOTE: Put the node at the front of the stack (e.g. sorted newest to oldest) + result->stack = node; + result->debug_open_close_counter++; + } + + // NOTE: Handle allocation error + if (!DN_CHECK(node && node->msg_sentinel)) + DN_Arena_PopTo(result->arena, arena_pos); + + return result; +} + +DN_API bool DN_ErrSink_HasError(DN_ErrSink *err) +{ + bool result = err && DN_SentinelDLL_HasItems(err->stack->msg_sentinel); + return result; +} + +DN_API DN_ErrSinkMsg *DN_ErrSink_End(DN_Arena *arena, DN_ErrSink *err) +{ + DN_ErrSinkMsg *result = nullptr; + DN_ErrSink_Check_(err); + if (!err || !err->stack) + 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_ErrSinkNode *node = err->stack; + DN_ErrSinkMsg *prev = nullptr; + for (DN_ErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next) { + DN_ErrSinkMsg *entry = DN_Arena_New(arena, DN_ErrSinkMsg, DN_ZeroMem_Yes); + entry->msg = DN_Str8_Copy(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 = err->stack->next; + DN_ASSERT(err->debug_open_close_counter); + err->debug_open_close_counter--; + DN_Arena_PopTo(err->arena, node->arena_pos); + return result; +} + +static void DN_ErrSink_AddMsgToStr8Builder_(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_Str8_FileNameFromPath(it->call_site.file); + DN_Str8Builder_AppendF(builder, + "%.*s:%05I32u:%.*s %.*s", + DN_STR_FMT(file_name), + it->call_site.line, + DN_STR_FMT(it->call_site.function), + DN_STR_FMT(it->msg)); + } else { + // NOTE: More than one message + for (DN_ErrSinkMsg *it = msg; it != end; it = it->next) { + DN_Str8 file_name = DN_Str8_FileNameFromPath(it->call_site.file); + DN_Str8Builder_AppendF(builder, + "%s - %.*s:%05I32u:%.*s%s%.*s", + it == msg ? "" : "\n", + DN_STR_FMT(file_name), + it->call_site.line, + DN_STR_FMT(it->call_site.function), + DN_Str8_HasData(it->msg) ? " " : "", + DN_STR_FMT(it->msg)); + } + } +} + +DN_API DN_Str8 DN_ErrSink_EndStr8(DN_Arena *arena, DN_ErrSink *err) +{ + DN_Str8 result = {}; + DN_ErrSink_Check_(err); + if (!err || !err->stack) + 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_TLSTMem tmem = DN_TLS_PushTMem(arena); + DN_Str8Builder builder = DN_Str8Builder_Init_TLS(); + DN_ErrSink_AddMsgToStr8Builder_(&builder, err->stack->msg_sentinel->next, err->stack->msg_sentinel); + + // NOTE: Deallocate all the memory for this scope + uint64_t arena_pos = err->stack->arena_pos; + err->stack = err->stack->next; + DN_Arena_PopTo(err->arena, arena_pos); + DN_ASSERT(err->debug_open_close_counter); + err->debug_open_close_counter--; + + result = DN_Str8Builder_Build(&builder, arena); + return result; +} + +DN_API void DN_ErrSink_EndAndIgnore(DN_ErrSink *err) +{ + DN_ErrSink_End(nullptr, err); +} + +DN_API bool DN_ErrSink_EndAndLogError_(DN_ErrSink *err, DN_CallSite call_site, DN_Str8 err_msg) +{ + DN_ASSERTF(err->stack && err->stack->msg_sentinel, "Begin must be called before calling end"); + DN_TLSTMem tmem = DN_TLS_PushTMem(nullptr); + DN_ErrSinkMode mode = err->stack->mode; + DN_ErrSinkMsg *msg = DN_ErrSink_End(tmem.arena, err); + if (!msg) + return false; + + DN_Str8Builder builder = DN_Str8Builder_Init_TLS(); + if (DN_Str8_HasData(err_msg)) { + DN_Str8Builder_AppendRef(&builder, err_msg); + DN_Str8Builder_AppendRef(&builder, DN_STR8(":")); + } else { + DN_Str8Builder_AppendRef(&builder, DN_STR8("Error(s) encountered:")); + } + + if (msg->next) // NOTE: More than 1 message + DN_Str8Builder_AppendRef(&builder, DN_STR8("\n")); + DN_ErrSink_AddMsgToStr8Builder_(&builder, msg, nullptr); + + DN_Str8 log = DN_Str8Builder_Build_TLS(&builder); + DN_Log_TypeFCallSite(DN_LogType_Error, call_site, "%.*s", DN_STR_FMT(log)); + + if (mode == DN_ErrSinkMode_DebugBreakOnEndAndLog) { + DN_DEBUG_BREAK; + } + return true; +} + +DN_API bool DN_ErrSink_EndAndLogErrorFV_(DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 log = DN_Str8_InitFV(tmem.arena, fmt, args); + bool result = DN_ErrSink_EndAndLogError_(err, call_site, log); + return result; +} + +DN_API bool DN_ErrSink_EndAndLogErrorF_(DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_ErrorSink_MakeFV_(error, error_code, fmt, args); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 log = DN_Str8_InitFV(tmem.arena, fmt, args); + bool result = DN_ErrSink_EndAndLogError_(err, call_site, log); + va_end(args); + return result; +} + +DN_API void DN_ErrSink_EndAndExitIfErrorFV_(DN_ErrSink *err, DN_CallSite call_site, uint32_t exit_val, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + if (DN_ErrSink_EndAndLogErrorFV_(err, call_site, fmt, args)) { + DN_DEBUG_BREAK; + DN_OS_Exit(exit_val); + } +} + +DN_API void DN_ErrSink_EndAndExitIfErrorF_(DN_ErrSink *err, DN_CallSite call_site, uint32_t exit_val, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_ErrSink_EndAndExitIfErrorFV_(err, call_site, exit_val, fmt, args); va_end(args); } +DN_API void DN_ErrSink_AppendFV_(DN_ErrSink *err, uint32_t error_code, DN_FMT_ATTRIB char const *fmt, va_list args) +{ + if (!err) + return; + + DN_ErrSinkNode *node = err->stack; + DN_ASSERTF(node, "Error sink must be begun by calling 'Begin' before using this function."); + + DN_ErrSinkMsg *msg = DN_Arena_New(err->arena, DN_ErrSinkMsg, DN_ZeroMem_Yes); + if (DN_CHECK(msg)) { + msg->msg = DN_Str8_InitFV(err->arena, fmt, args); + msg->error_code = error_code; + msg->call_site = DN_TLS_Get()->call_site; + DN_SentinelDLL_Prepend(node->msg_sentinel, msg); + + if (node->mode == DN_ErrSinkMode_ExitOnError) + DN_ErrSink_EndAndExitIfErrorF_(err, msg->call_site, error_code, "Fatal error %u", error_code); + } +} + +DN_API void DN_ErrSink_AppendF_(DN_ErrSink *err, uint32_t error_code, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_ErrSink_AppendFV_(err, error_code, fmt, args); + va_end(args); +} diff --git a/dqn_base.h b/dqn_base.h index 00d5d34..26a9bcb 100644 --- a/dqn_base.h +++ b/dqn_base.h @@ -16,57 +16,58 @@ // // [$MACR] Macros -- General macros // [$TYPE] Types -- Basic types and typedefs +// [$SDLL] DN_SentinelDLL -- Doubly linked list w/ sentinel macros // [$INTR] Intrinsics -- Platform agnostic functions for CPU instructions (e.g. atomics, cpuid, ...) -// [$CALL] Dqn_CallSite -- Source code location/tracing -// [$TMUT] Dqn_TicketMutex -- Userland mutex via spinlocking atomics -// [$PRIN] Dqn_Print -- Console printing -// [$LLOG] Dqn_Log -- Console logging macros +// [$CALL] DN_CallSite -- Source code location/tracing +// [$TMUT] DN_TicketMutex -- Userland mutex via spinlocking atomics +// [$PRIN] DN_Print -- Console printing +// [$LLOG] DN_Log -- Console logging macros // //////////////////////////////////////////////////////////////////////////////////////////////////// */ // NOTE: [$MACR] Macros //////////////////////////////////////////////////////////////////////////// -#define DQN_STRINGIFY(x) #x -#define DQN_TOKEN_COMBINE2(x, y) x ## y -#define DQN_TOKEN_COMBINE(x, y) DQN_TOKEN_COMBINE2(x, y) +#define DN_STRINGIFY(x) #x +#define DN_TOKEN_COMBINE2(x, y) x ## y +#define DN_TOKEN_COMBINE(x, y) DN_TOKEN_COMBINE2(x, y) // NOTE: Warning! Order is important here, clang-cl on Windows defines _MSC_VER #if defined(_MSC_VER) #if defined(__clang__) - #define DQN_COMPILER_CLANG_CL - #define DQN_COMPILER_CLANG + #define DN_COMPILER_CLANG_CL + #define DN_COMPILER_CLANG #else - #define DQN_COMPILER_MSVC + #define DN_COMPILER_MSVC #endif #elif defined(__clang__) - #define DQN_COMPILER_CLANG + #define DN_COMPILER_CLANG #elif defined(__GNUC__) - #define DQN_COMPILER_GCC + #define DN_COMPILER_GCC #endif // NOTE: 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 = DQN_LITERAL(Foo){32}; // Works on both C and C++ + struct Foo foo = DN_LITERAL(Foo){32}; // Works on both C and C++ #endif #if defined(__cplusplus) - #define DQN_LITERAL(T) T + #define DN_LITERAL(T) T #else - #define DQN_LITERAL(T) (T) + #define DN_LITERAL(T) (T) #endif #if defined(__cplusplus) - #define DQN_THREAD_LOCAL thread_local + #define DN_THREAD_LOCAL thread_local #else - #define DQN_THREAD_LOCAL _Thread_local + #define DN_THREAD_LOCAL _Thread_local #endif #if defined(_WIN32) - #define DQN_OS_WIN32 + #define DN_OS_WIN32 #elif defined(__gnu_linux__) || defined(__linux__) - #define DQN_OS_UNIX + #define DN_OS_UNIX #endif #include @@ -75,119 +76,123 @@ #include #include // PRIu64... -#if !defined(DQN_OS_WIN32) +#if !defined(DN_OS_WIN32) #include // exit() #endif -#if !defined(DQN_PLATFORM_EMSCRIPTEN) && \ - !defined(DQN_PLATFORM_POSIX) && \ - !defined(DQN_PLATFORM_WIN32) +#if !defined(DN_PLATFORM_EMSCRIPTEN) && \ + !defined(DN_PLATFORM_POSIX) && \ + !defined(DN_PLATFORM_WIN32) #if defined(__aarch64__) || defined(_M_ARM64) - #define DQN_PLATFORM_ARM64 + #define DN_PLATFORM_ARM64 #elif defined(__EMSCRIPTEN__) - #define DQN_PLATFORM_EMSCRIPTEN - #elif defined(DQN_OS_WIN32) - #define DQN_PLATFORM_WIN32 + #define DN_PLATFORM_EMSCRIPTEN + #elif defined(DN_OS_WIN32) + #define DN_PLATFORM_WIN32 #else - #define DQN_PLATFORM_POSIX + #define DN_PLATFORM_POSIX #endif #endif -#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) #if defined(_CRT_SECURE_NO_WARNINGS) - #define DQN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED + #define DN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED #else #define _CRT_SECURE_NO_WARNINGS #endif #endif -#if defined(DQN_COMPILER_MSVC) - #define DQN_FMT_ATTRIB _Printf_format_string_ - #define DQN_MSVC_WARNING_PUSH __pragma(warning(push)) - #define DQN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable: ##__VA_ARGS__)) - #define DQN_MSVC_WARNING_POP __pragma(warning(pop)) +#if defined(DN_COMPILER_MSVC) + #define DN_FMT_ATTRIB _Printf_format_string_ + #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 DQN_FMT_ATTRIB - #define DQN_MSVC_WARNING_PUSH - #define DQN_MSVC_WARNING_DISABLE(...) - #define DQN_MSVC_WARNING_POP + #define DN_FMT_ATTRIB + #define DN_MSVC_WARNING_PUSH + #define DN_MSVC_WARNING_DISABLE(...) + #define DN_MSVC_WARNING_POP #endif -#if defined(DQN_COMPILER_CLANG) || defined(DQN_COMPILER_GCC) || defined(DQN_COMPILER_CLANG_CL) - #define DQN_GCC_WARNING_PUSH _Pragma("GCC diagnostic push") - #define DQN_GCC_WARNING_DISABLE_HELPER_0(x) #x - #define DQN_GCC_WARNING_DISABLE_HELPER_1(y) DQN_GCC_WARNING_DISABLE_HELPER_0(GCC diagnostic ignored #y) - #define DQN_GCC_WARNING_DISABLE(warning) _Pragma(DQN_GCC_WARNING_DISABLE_HELPER_1(warning)) - #define DQN_GCC_WARNING_POP _Pragma("GCC diagnostic pop") +#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 DQN_GCC_WARNING_PUSH - #define DQN_GCC_WARNING_DISABLE(...) - #define DQN_GCC_WARNING_POP + #define DN_GCC_WARNING_PUSH + #define DN_GCC_WARNING_DISABLE(...) + #define DN_GCC_WARNING_POP #endif // NOTE: MSVC does not support the feature detection macro for instance so we // compile it out #if defined(__has_feature) - #define DQN_HAS_FEATURE(expr) __has_feature(expr) + #define DN_HAS_FEATURE(expr) __has_feature(expr) #else - #define DQN_HAS_FEATURE(expr) 0 + #define DN_HAS_FEATURE(expr) 0 #endif -#define DQN_FOR_UINDEX(index, size) for (Dqn_usize index = 0; index < size; index++) -#define DQN_FOR_IINDEX(index, size) for (Dqn_isize index = 0; index < size; index++) +#define DN_FOR_UINDEX(index, size) for (DN_USize index = 0; index < size; index++) +#define DN_FOR_IINDEX(index, size) for (DN_isize index = 0; index < size; index++) -#define Dqn_AlignUpPowerOfTwo(value, pot) (((uintptr_t)(value) + ((uintptr_t)(pot) - 1)) & ~((uintptr_t)(pot) - 1)) -#define Dqn_AlignDownPowerOfTwo(value, pot) ((uintptr_t)(value) & ~((uintptr_t)(pot) - 1)) -#define Dqn_IsPowerOfTwo(value) ((((uintptr_t)(value)) & (((uintptr_t)(value)) - 1)) == 0) -#define Dqn_IsPowerOfTwoAligned(value, pot) ((((uintptr_t)value) & (((uintptr_t)pot) - 1)) == 0) +#define DN_ForItSize(it, T, array, size) for (struct { USize index; T *data; } it = {0, &(array)[0]}; it.index < (size); it.index++, it.data++) +#define DN_ForIt(it, T, array) for (struct { USize index; T *data; } it = {0, &(array)->data[0]}; it.index < (array)->size; it.index++, it.data++) +#define DN_ForItCArray(it, T, array) for (struct { USize index; T *data; } it = {0, &(array)[0]}; it.index < DN_ARRAY_UCOUNT(array); it.index++, it.data++) + +#define DN_AlignUpPowerOfTwo(value, pot) (((uintptr_t)(value) + ((uintptr_t)(pot) - 1)) & ~((uintptr_t)(pot) - 1)) +#define DN_AlignDownPowerOfTwo(value, pot) ((uintptr_t)(value) & ~((uintptr_t)(pot) - 1)) +#define DN_IsPowerOfTwo(value) ((((uintptr_t)(value)) & (((uintptr_t)(value)) - 1)) == 0) +#define DN_IsPowerOfTwoAligned(value, pot) ((((uintptr_t)value) & (((uintptr_t)pot) - 1)) == 0) // NOTE: String.h Dependencies ///////////////////////////////////////////////////////////////////// -#if !defined(DQN_MEMCPY) || !defined(DQN_MEMSET) || !defined(DQN_MEMCMP) || !defined(DQN_MEMMOVE) +#if !defined(DN_MEMCPY) || !defined(DN_MEMSET) || !defined(DN_MEMCMP) || !defined(DN_MEMMOVE) #include - #if !defined(DQN_MEMCPY) - #define DQN_MEMCPY(dest, src, count) memcpy((dest), (src), (count)) + #if !defined(DN_MEMCPY) + #define DN_MEMCPY(dest, src, count) memcpy((dest), (src), (count)) #endif - #if !defined(DQN_MEMSET) - #define DQN_MEMSET(dest, value, count) memset((dest), (value), (count)) + #if !defined(DN_MEMSET) + #define DN_MEMSET(dest, value, count) memset((dest), (value), (count)) #endif - #if !defined(DQN_MEMCMP) - #define DQN_MEMCMP(lhs, rhs, count) memcmp((lhs), (rhs), (count)) + #if !defined(DN_MEMCMP) + #define DN_MEMCMP(lhs, rhs, count) memcmp((lhs), (rhs), (count)) #endif - #if !defined(DQN_MEMMOVE) - #define DQN_MEMMOVE(dest, src, count) memmove((dest), (src), (count)) + #if !defined(DN_MEMMOVE) + #define DN_MEMMOVE(dest, src, count) memmove((dest), (src), (count)) #endif #endif // NOTE: Math.h Dependencies /////////////////////////////////////////////////////////////////////// -#if !defined(DQN_SQRTF) || !defined(DQN_SINF) || !defined(DQN_COSF) || !defined(DQN_TANF) +#if !defined(DN_SQRTF) || !defined(DN_SINF) || !defined(DN_COSF) || !defined(DN_TANF) #include - #if !defined(DQN_SQRTF) - #define DQN_SQRTF(val) sqrtf(val) + #if !defined(DN_SQRTF) + #define DN_SQRTF(val) sqrtf(val) #endif - #if !defined(DQN_SINF) - #define DQN_SINF(val) sinf(val) + #if !defined(DN_SINF) + #define DN_SINF(val) sinf(val) #endif - #if !defined(DQN_COSF) - #define DQN_COSF(val) cosf(val) + #if !defined(DN_COSF) + #define DN_COSF(val) cosf(val) #endif - #if !defined(DQN_TANF) - #define DQN_TANF(val) tanf(val) + #if !defined(DN_TANF) + #define DN_TANF(val) tanf(val) #endif #endif // NOTE: Math ////////////////////////////////////////////////////////////////////////////////////// -#define DQN_PI 3.14159265359f +#define DN_PI 3.14159265359f -#define DQN_DEGREE_TO_RADIAN(degrees) ((degrees) * (DQN_PI / 180.0f)) -#define DQN_RADIAN_TO_DEGREE(radians) ((radians) * (180.f * DQN_PI)) +#define DN_DEGREE_TO_RADIAN(degrees) ((degrees) * (DN_PI / 180.0f)) +#define DN_RADIAN_TO_DEGREE(radians) ((radians) * (180.f * DN_PI)) -#define DQN_ABS(val) (((val) < 0) ? (-(val)) : (val)) -#define DQN_MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define DQN_MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define DQN_CLAMP(val, lo, hi) DQN_MAX(DQN_MIN(val, hi), lo) -#define DQN_SQUARED(val) ((val) * (val)) +#define DN_ABS(val) (((val) < 0) ? (-(val)) : (val)) +#define DN_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define DN_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define DN_CLAMP(val, lo, hi) DN_MAX(DN_MIN(val, hi), lo) +#define DN_SQUARED(val) ((val) * (val)) -#define DQN_SWAP(a, b) \ +#define DN_SWAP(a, b) \ do \ { \ auto temp = a; \ @@ -196,173 +201,200 @@ } while (0) // NOTE: Function/Variable Annotations ///////////////////////////////////////////////////////////// -#if defined(DQN_STATIC_API) - #define DQN_API static +#if defined(DN_STATIC_API) + #define DN_API static #else - #define DQN_API + #define DN_API #endif -#define DQN_LOCAL_PERSIST static -#define DQN_FILE_SCOPE static -#define DQN_CAST(val) (val) +#define DN_LOCAL_PERSIST static +#define DN_FILE_SCOPE static +#define DN_CAST(val) (val) -#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) - #define DQN_FORCE_INLINE __forceinline +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) + #define DN_FORCE_INLINE __forceinline #else - #define DQN_FORCE_INLINE inline __attribute__((always_inline)) + #define DN_FORCE_INLINE inline __attribute__((always_inline)) #endif // NOTE: Size ////////////////////////////////////////////////////////////////////////////////////// -#define DQN_ISIZEOF(val) DQN_CAST(ptrdiff_t)sizeof(val) -#define DQN_ARRAY_UCOUNT(array) (sizeof(array)/(sizeof((array)[0]))) -#define DQN_ARRAY_ICOUNT(array) (Dqn_isize)DQN_ARRAY_UCOUNT(array) -#define DQN_CHAR_COUNT(string) (sizeof(string) - 1) +#define DN_ISIZEOF(val) DN_CAST(ptrdiff_t)sizeof(val) +#define DN_ARRAY_UCOUNT(array) (sizeof(array)/(sizeof((array)[0]))) +#define DN_ARRAY_ICOUNT(array) (DN_ISize)DN_ARRAY_UCOUNT(array) +#define DN_CHAR_COUNT(string) (sizeof(string) - 1) // NOTE: SI Byte /////////////////////////////////////////////////////////////////////////////////// -#define DQN_BYTES(val) ((uint64_t)val) -#define DQN_KILOBYTES(val) ((uint64_t)1024 * DQN_BYTES(val)) -#define DQN_MEGABYTES(val) ((uint64_t)1024 * DQN_KILOBYTES(val)) -#define DQN_GIGABYTES(val) ((uint64_t)1024 * DQN_MEGABYTES(val)) +#define DN_BYTES(val) ((uint64_t)val) +#define DN_KILOBYTES(val) ((uint64_t)1024 * DN_BYTES(val)) +#define DN_MEGABYTES(val) ((uint64_t)1024 * DN_KILOBYTES(val)) +#define DN_GIGABYTES(val) ((uint64_t)1024 * DN_MEGABYTES(val)) // NOTE: Time ////////////////////////////////////////////////////////////////////////////////////// -#define DQN_SECONDS_TO_MS(val) ((val) * 1000) -#define DQN_MINS_TO_S(val) ((val) * 60ULL) -#define DQN_HOURS_TO_S(val) (DQN_MINS_TO_S(val) * 60ULL) -#define DQN_DAYS_TO_S(val) (DQN_HOURS_TO_S(val) * 24ULL) -#define DQN_WEEKS_TO_S(val) (DQN_DAYS_TO_S(val) * 7ULL) -#define DQN_YEARS_TO_S(val) (DQN_WEEKS_TO_S(val) * 52ULL) +#define DN_SECONDS_TO_MS(val) ((val) * 1000) +#define DN_MINS_TO_S(val) ((val) * 60ULL) +#define DN_HOURS_TO_S(val) (DN_MINS_TO_S(val) * 60ULL) +#define DN_DAYS_TO_S(val) (DN_HOURS_TO_S(val) * 24ULL) +#define DN_WEEKS_TO_S(val) (DN_DAYS_TO_S(val) * 7ULL) +#define DN_YEARS_TO_S(val) (DN_WEEKS_TO_S(val) * 52ULL) #if defined(__has_builtin) - #define DQN_HAS_BUILTIN(expr) __has_builtin(expr) + #define DN_HAS_BUILTIN(expr) __has_builtin(expr) #else - #define DQN_HAS_BUILTIN(expr) 0 + #define DN_HAS_BUILTIN(expr) 0 #endif // NOTE: Debug Break /////////////////////////////////////////////////////////////////////////////// -#if !defined(DQN_DEBUG_BREAK) +#if !defined(DN_DEBUG_BREAK) #if defined(NDEBUG) - #define DQN_DEBUG_BREAK + #define DN_DEBUG_BREAK #else - #if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) - #define DQN_DEBUG_BREAK __debugbreak() - #elif DQN_HAS_BUILTIN(__builtin_debugtrap) - #define DQN_DEBUG_BREAK __builtin_debugtrap() - #elif DQN_HAS_BUILTIN(__builtin_trap) || defined(DQN_COMPILER_GCC) - #define DQN_DEBUG_BREAK __builtin_trap() + #if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) + #define DN_DEBUG_BREAK __debugbreak() + #elif DN_HAS_BUILTIN(__builtin_debugtrap) + #define DN_DEBUG_BREAK __builtin_debugtrap() + #elif DN_HAS_BUILTIN(__builtin_trap) || defined(DN_COMPILER_GCC) + #define DN_DEBUG_BREAK __builtin_trap() #else #include #if defined(SIGTRAP) - #define DQN_DEBUG_BREAK raise(SIGTRAP) + #define DN_DEBUG_BREAK raise(SIGTRAP) #else - #define DQN_DEBUG_BREAK raise(SIGABRT) + #define DN_DEBUG_BREAK raise(SIGABRT) #endif #endif #endif #endif // NOTE: Assert Macros ///////////////////////////////////////////////////////////////////////////// -#define DQN_HARD_ASSERT(expr) DQN_HARD_ASSERTF(expr, "") -#define DQN_HARD_ASSERTF(expr, fmt, ...) \ +#define DN_HARD_ASSERT(expr) DN_HARD_ASSERTF(expr, "") +#define DN_HARD_ASSERTF(expr, fmt, ...) \ do { \ if (!(expr)) { \ - Dqn_Str8 stack_trace_ = Dqn_StackTrace_WalkStr8CRT(128 /*limit*/, 2 /*skip*/); \ - Dqn_Log_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ - DQN_STR_FMT(stack_trace_), \ + DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8CRT(128 /*limit*/, 2 /*skip*/); \ + DN_Log_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ + DN_STR_FMT(stack_trace_), \ ##__VA_ARGS__); \ - DQN_DEBUG_BREAK; \ + DN_DEBUG_BREAK; \ } \ } while (0) -#if defined(DQN_NO_ASSERT) - #define DQN_ASSERTF(...) - #define DQN_ASSERT(...) +#if defined(DN_NO_ASSERT) + #define DN_ASSERT(...) + #define DN_ASSERT_ONCE(...) + #define DN_ASSERTF(...) + #define DN_ASSERTF_ONCE(...) #else - #define DQN_ASSERT(expr) DQN_ASSERTF((expr), "") - #define DQN_ASSERTF(expr, fmt, ...) \ + #define DN_ASSERT(expr) DN_ASSERTF((expr), "") + #define DN_ASSERT_ONCE(expr) DN_ASSERTF_ONCE((expr), "") + + #define DN_ASSERTF(expr, fmt, ...) \ do { \ if (!(expr)) { \ - Dqn_Str8 stack_trace_ = Dqn_StackTrace_WalkStr8CRT(128 /*limit*/, 2 /*skip*/); \ - Dqn_Log_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ - DQN_STR_FMT(stack_trace_), \ + DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8CRT(128 /*limit*/, 2 /*skip*/); \ + DN_Log_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ + DN_STR_FMT(stack_trace_), \ ##__VA_ARGS__); \ - DQN_DEBUG_BREAK; \ + DN_DEBUG_BREAK; \ + } \ + } while (0) + + #define DN_ASSERTF_ONCE(expr, fmt, ...) \ + do { \ + static bool once = true; \ + if (!(expr) && once) { \ + DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8CRT(128 /*limit*/, 2 /*skip*/); \ + DN_Log_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ + DN_STR_FMT(stack_trace_), \ + ##__VA_ARGS__); \ + once = false; \ + DN_DEBUG_BREAK; \ } \ } while (0) #endif -#define DQN_INVALID_CODE_PATHF(fmt, ...) DQN_HARD_ASSERTF(0, fmt, ##__VA_ARGS__) -#define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered") +#define DN_INVALID_CODE_PATHF(fmt, ...) DN_HARD_ASSERTF(0, fmt, ##__VA_ARGS__) +#define DN_INVALID_CODE_PATH DN_INVALID_CODE_PATHF("Invalid code path triggered") // NOTE: Check macro /////////////////////////////////////////////////////////////////////////////// -#define DQN_CHECK(expr) DQN_CHECKF(expr, "") +#define DN_CHECK(expr) DN_CHECKF(expr, "") -#if defined(DQN_NO_CHECK_BREAK) - #define DQN_CHECKF(expr, fmt, ...) \ - ((expr) ? true : (Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, DQN_CALL_SITE, fmt, ## __VA_ARGS__), false)) +#if defined(DN_NO_CHECK_BREAK) + #define DN_CHECKF(expr, fmt, ...) \ + ((expr) ? true : (DN_Log_TypeFCallSite(DN_LogType_Warning, DN_CALL_SITE, fmt, ## __VA_ARGS__), false)) #else - #define DQN_CHECKF(expr, fmt, ...) \ - ((expr) ? true : (Dqn_Log_TypeFCallSite(Dqn_LogType_Error, DQN_CALL_SITE, fmt, ## __VA_ARGS__), Dqn_StackTrace_Print(128 /*limit*/), DQN_DEBUG_BREAK, false)) + #define DN_CHECKF(expr, fmt, ...) \ + ((expr) ? true : (DN_Log_TypeFCallSite(DN_LogType_Error, DN_CALL_SITE, fmt, ## __VA_ARGS__), DN_StackTrace_Print(128 /*limit*/), DN_DEBUG_BREAK, false)) #endif // NOTE: Zero initialisation macro ///////////////////////////////////////////////////////////////// #if defined(__cplusplus) - #define DQN_ZERO_INIT {} + #define DN_ZERO_INIT {} #else - #define DQN_ZERO_INIT {0} + #define DN_ZERO_INIT {0} #endif // NOTE: Defer Macro /////////////////////////////////////////////////////////////////////////////// #if defined(__cplusplus) template -struct Dqn_Defer +struct DN_Defer { Procedure proc; - Dqn_Defer(Procedure p) : proc(p) {} - ~Dqn_Defer() { proc(); } + DN_Defer(Procedure p) : proc(p) {} + ~DN_Defer() { proc(); } }; -struct Dqn_DeferHelper +struct DN_DeferHelper { template - Dqn_Defer operator+(Lambda lambda) { return Dqn_Defer(lambda); }; + DN_Defer operator+(Lambda lambda) { return DN_Defer(lambda); }; }; -#define DQN_UNIQUE_NAME(prefix) DQN_TOKEN_COMBINE(prefix, __LINE__) -#define DQN_DEFER const auto DQN_UNIQUE_NAME(defer_lambda_) = Dqn_DeferHelper() + [&]() +#define DN_UNIQUE_NAME(prefix) DN_TOKEN_COMBINE(prefix, __LINE__) +#define DN_DEFER const auto DN_UNIQUE_NAME(defer_lambda_) = DN_DeferHelper() + [&]() #endif // defined(__cplusplus) -#define DQN_DEFER_LOOP(begin, end) \ - for (bool DQN_UNIQUE_NAME(once) = (begin, true); \ - DQN_UNIQUE_NAME(once); \ - end, DQN_UNIQUE_NAME(once) = false) +#define DN_DEFER_LOOP(begin, end) \ + for (bool DN_UNIQUE_NAME(once) = (begin, true); \ + DN_UNIQUE_NAME(once); \ + end, DN_UNIQUE_NAME(once) = false) // NOTE: [$TYPE] Types ///////////////////////////////////////////////////////////////////////////// -typedef intptr_t Dqn_isize; -typedef uintptr_t Dqn_usize; -typedef intptr_t Dqn_isize; -typedef float Dqn_f32; -typedef double Dqn_f64; -typedef unsigned int Dqn_uint; -typedef int32_t Dqn_b32; +typedef intptr_t DN_ISize; +typedef uintptr_t DN_USize; -#define DQN_F32_MAX 3.402823466e+38F -#define DQN_F32_MIN 1.175494351e-38F -#define DQN_F64_MAX 1.7976931348623158e+308 -#define DQN_F64_MIN 2.2250738585072014e-308 -#define DQN_USIZE_MAX UINTPTR_MAX -#define DQN_ISIZE_MAX INTPTR_MAX -#define DQN_ISIZE_MIN INTPTR_MIN +typedef int8_t DN_I8; +typedef int16_t DN_I16; +typedef int32_t DN_I32; +typedef int64_t DN_I64; -enum Dqn_ZeroMem +typedef uint8_t DN_U8; +typedef uint16_t DN_U16; +typedef uint32_t DN_U32; +typedef uint64_t DN_U64; + +typedef float DN_F32; +typedef double DN_F64; +typedef unsigned int DN_UInt; +typedef int32_t DN_B32; + +#define DN_F32_MAX 3.402823466e+38F +#define DN_F32_MIN 1.175494351e-38F +#define DN_F64_MAX 1.7976931348623158e+308 +#define DN_F64_MIN 2.2250738585072014e-308 +#define DN_USIZE_MAX UINTPTR_MAX +#define DN_ISIZE_MAX INTPTR_MAX +#define DN_ISIZE_MIN INTPTR_MIN + +enum DN_ZeroMem { - Dqn_ZeroMem_No, // Memory can be handed out without zero-ing it out - Dqn_ZeroMem_Yes, // Memory should be zero-ed out before giving to the callee + DN_ZeroMem_No, // Memory can be handed out without zero-ing it out + DN_ZeroMem_Yes, // Memory should be zero-ed out before giving to the callee }; -struct Dqn_Str8 +struct DN_Str8 { char *data; // The bytes of the string - Dqn_usize size; // The number of bytes in the string + DN_USize size; // The number of bytes in the string char const *begin() const { return data; } char const *end () const { return data + size; } @@ -370,10 +402,10 @@ struct Dqn_Str8 char *end () { return data + size; } }; -template struct Dqn_Slice // A pointer and length container of data +template struct DN_Slice // A pointer and length container of data { T *data; - Dqn_usize size; + DN_USize size; T *begin() { return data; } T *end () { return data + size; } @@ -381,87 +413,110 @@ template struct Dqn_Slice // A pointer and length container of data T const *end () const { return data + size; } }; -// NOTE: [$CALL] Dqn_CallSite ////////////////////////////////////////////////////////////////////// -struct Dqn_CallSite +// NOTE: [$CALL] DN_CallSite ////////////////////////////////////////////////////////////////////// +struct DN_CallSite { - Dqn_Str8 file; - Dqn_Str8 function; + DN_Str8 file; + DN_Str8 function; uint32_t line; }; -#define DQN_CALL_SITE Dqn_CallSite{DQN_STR8(__FILE__), DQN_STR8(__func__), __LINE__} +#define DN_CALL_SITE DN_CallSite{DN_STR8(__FILE__), DN_STR8(__func__), __LINE__} -// NOTE: [$ERRS] Dqn_ErrorSink ///////////////////////////////////////////////////////////////////// -enum Dqn_ErrorSinkMode +// NOTE: [$ErrS] DN_ErrSink ///////////////////////////////////////////////////////////////////// +enum DN_ErrSinkMode { - Dqn_ErrorSinkMode_Nil, - Dqn_ErrorSinkMode_ExitOnError, + // Default behaviour to accumulate errors into the sink + DN_ErrSinkMode_Nil, + + // Break into the debugger (int3) when error is encountered and the sink is + // ended by the 'end and log' functions. + DN_ErrSinkMode_DebugBreakOnEndAndLog, + + // When an error is encountered, exit the program with the error code of the + // error that was caught. + DN_ErrSinkMode_ExitOnError, }; -struct Dqn_ErrorSinkNode +struct DN_ErrSinkMsg { - Dqn_ErrorSinkMode mode; - bool error; - int32_t error_code; - Dqn_Str8 msg; - Dqn_CallSite call_site; - Dqn_ErrorSinkNode *next; - uint64_t arena_pos; + int32_t error_code; + DN_Str8 msg; + DN_CallSite call_site; + DN_ErrSinkMsg *next; + DN_ErrSinkMsg *prev; }; -struct Dqn_ErrorSink +struct DN_ErrSinkNode { - struct Dqn_Arena *arena; - Dqn_ErrorSinkNode *stack; + 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_ErrSinkNode *next; // Next error scope + uint64_t arena_pos; // Position to reset the arena when the scope is ended +}; + +struct DN_ErrSink +{ + // Arena solely for handling errors take from the thread's TLS + struct DN_Arena *arena; + + // Each entry in the stack represents the errors accumulated in the scope + // between a begin and end scope of the stink. The base sink is stored in + // the thread's TLS. + // + // The stack has the latest error scope at the front. + DN_ErrSinkNode *stack; + + size_t debug_open_close_counter; }; // NOTE: [$INTR] Intrinsics //////////////////////////////////////////////////////////////////////// -// NOTE: Dqn_Atomic_Add/Exchange return the previous value store in the target -#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) +// NOTE: DN_Atomic_Add/Exchange return the previous value store in the target +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) #include - #define Dqn_Atomic_CompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val) - #define Dqn_Atomic_CompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val) - #define Dqn_Atomic_AddU32(target, value) _InterlockedExchangeAdd((long volatile *)target, value) - #define Dqn_Atomic_AddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value) - #define Dqn_Atomic_SubU32(target, value) Dqn_Atomic_AddU32(DQN_CAST(long volatile *)target, (long)-value) - #define Dqn_Atomic_SubU64(target, value) Dqn_Atomic_AddU64(target, (uint64_t)-value) + #define DN_Atomic_CompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val) + #define DN_Atomic_CompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val) + #define DN_Atomic_AddU32(target, value) _InterlockedExchangeAdd((long volatile *)target, value) + #define DN_Atomic_AddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value) + #define DN_Atomic_SubU32(target, value) DN_Atomic_AddU32(DN_CAST(long volatile *)target, (long)-value) + #define DN_Atomic_SubU64(target, value) DN_Atomic_AddU64(target, (uint64_t)-value) - #define Dqn_CountLeadingZerosU64(value) __lzcnt64(value) + #define DN_CountLeadingZerosU64(value) __lzcnt64(value) - #define Dqn_CPU_TSC() __rdtsc() - #define Dqn_CompilerReadBarrierAndCPUReadFence _ReadBarrier(); _mm_lfence() - #define Dqn_CompilerWriteBarrierAndCPUWriteFence _WriteBarrier(); _mm_sfence() -#elif defined(DQN_COMPILER_GCC) || defined(DQN_COMPILER_CLANG) + #define DN_CPU_TSC() __rdtsc() + #define DN_CompilerReadBarrierAndCPUReadFence _ReadBarrier(); _mm_lfence() + #define DN_CompilerWriteBarrierAndCPUWriteFence _WriteBarrier(); _mm_sfence() +#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG) #if defined(__ANDROID__) - #elif defined(DQN_PLATFORM_EMSCRIPTEN) + #elif defined(DN_PLATFORM_EMSCRIPTEN) #include #else #include #endif - #define Dqn_Atomic_AddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL) - #define Dqn_Atomic_AddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL) - #define Dqn_Atomic_SubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL) - #define Dqn_Atomic_SubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL) + #define DN_Atomic_AddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL) + #define DN_Atomic_AddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL) + #define DN_Atomic_SubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL) + #define DN_Atomic_SubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL) - #define Dqn_CountLeadingZerosU64(value) __builtin_clzll(value) - #if defined(DQN_COMPILER_GCC) - #define Dqn_CPU_TSC() __rdtsc() + #define DN_CountLeadingZerosU64(value) __builtin_clzll(value) + #if defined(DN_COMPILER_GCC) + #define DN_CPU_TSC() __rdtsc() #else - #define Dqn_CPU_TSC() __builtin_readcyclecounter() + #define DN_CPU_TSC() __builtin_readcyclecounter() #endif - #if defined(DQN_PLATFORM_EMSCRIPTEN) - #define Dqn_CompilerReadBarrierAndCPUReadFence - #define Dqn_CompilerWriteBarrierAndCPUWriteFence + #if defined(DN_PLATFORM_EMSCRIPTEN) + #define DN_CompilerReadBarrierAndCPUReadFence + #define DN_CompilerWriteBarrierAndCPUWriteFence #else - #define Dqn_CompilerReadBarrierAndCPUReadFence asm volatile("lfence" ::: "memory") - #define Dqn_CompilerWriteBarrierAndCPUWriteFence asm volatile("sfence" ::: "memory") + #define DN_CompilerReadBarrierAndCPUReadFence asm volatile("lfence" ::: "memory") + #define DN_CompilerWriteBarrierAndCPUWriteFence asm volatile("sfence" ::: "memory") #endif #else #error "Compiler not supported" #endif -#if !defined(DQN_PLATFORM_ARM64) -struct Dqn_CPURegisters +#if !defined(DN_PLATFORM_ARM64) +struct DN_CPURegisters { int eax; int ebx; @@ -469,115 +524,115 @@ struct Dqn_CPURegisters int edx; }; -union Dqn_CPUIDResult +union DN_CPUIDResult { - Dqn_CPURegisters reg; + DN_CPURegisters reg; int values[4]; }; -struct Dqn_CPUIDArgs +struct DN_CPUIDArgs { int eax; int ecx; }; -#define DQN_CPU_FEAT_XMACRO \ - DQN_CPU_FEAT_XENTRY(3DNow) \ - DQN_CPU_FEAT_XENTRY(3DNowExt) \ - DQN_CPU_FEAT_XENTRY(ABM) \ - DQN_CPU_FEAT_XENTRY(AES) \ - DQN_CPU_FEAT_XENTRY(AVX) \ - DQN_CPU_FEAT_XENTRY(AVX2) \ - DQN_CPU_FEAT_XENTRY(AVX512F) \ - DQN_CPU_FEAT_XENTRY(AVX512DQ) \ - DQN_CPU_FEAT_XENTRY(AVX512IFMA) \ - DQN_CPU_FEAT_XENTRY(AVX512PF) \ - DQN_CPU_FEAT_XENTRY(AVX512ER) \ - DQN_CPU_FEAT_XENTRY(AVX512CD) \ - DQN_CPU_FEAT_XENTRY(AVX512BW) \ - DQN_CPU_FEAT_XENTRY(AVX512VL) \ - DQN_CPU_FEAT_XENTRY(AVX512VBMI) \ - DQN_CPU_FEAT_XENTRY(AVX512VBMI2) \ - DQN_CPU_FEAT_XENTRY(AVX512VNNI) \ - DQN_CPU_FEAT_XENTRY(AVX512BITALG) \ - DQN_CPU_FEAT_XENTRY(AVX512VPOPCNTDQ) \ - DQN_CPU_FEAT_XENTRY(AVX5124VNNIW) \ - DQN_CPU_FEAT_XENTRY(AVX5124FMAPS) \ - DQN_CPU_FEAT_XENTRY(AVX512VP2INTERSECT) \ - DQN_CPU_FEAT_XENTRY(AVX512FP16) \ - DQN_CPU_FEAT_XENTRY(CLZERO) \ - DQN_CPU_FEAT_XENTRY(CMPXCHG8B) \ - DQN_CPU_FEAT_XENTRY(CMPXCHG16B) \ - DQN_CPU_FEAT_XENTRY(F16C) \ - DQN_CPU_FEAT_XENTRY(FMA) \ - DQN_CPU_FEAT_XENTRY(FMA4) \ - DQN_CPU_FEAT_XENTRY(FP128) \ - DQN_CPU_FEAT_XENTRY(FP256) \ - DQN_CPU_FEAT_XENTRY(FPU) \ - DQN_CPU_FEAT_XENTRY(MMX) \ - DQN_CPU_FEAT_XENTRY(MONITOR) \ - DQN_CPU_FEAT_XENTRY(MOVBE) \ - DQN_CPU_FEAT_XENTRY(MOVU) \ - DQN_CPU_FEAT_XENTRY(MmxExt) \ - DQN_CPU_FEAT_XENTRY(PCLMULQDQ) \ - DQN_CPU_FEAT_XENTRY(POPCNT) \ - DQN_CPU_FEAT_XENTRY(RDRAND) \ - DQN_CPU_FEAT_XENTRY(RDSEED) \ - DQN_CPU_FEAT_XENTRY(RDTSCP) \ - DQN_CPU_FEAT_XENTRY(SHA) \ - DQN_CPU_FEAT_XENTRY(SSE) \ - DQN_CPU_FEAT_XENTRY(SSE2) \ - DQN_CPU_FEAT_XENTRY(SSE3) \ - DQN_CPU_FEAT_XENTRY(SSE41) \ - DQN_CPU_FEAT_XENTRY(SSE42) \ - DQN_CPU_FEAT_XENTRY(SSE4A) \ - DQN_CPU_FEAT_XENTRY(SSSE3) \ - DQN_CPU_FEAT_XENTRY(TSC) \ - DQN_CPU_FEAT_XENTRY(TscInvariant) \ - DQN_CPU_FEAT_XENTRY(VAES) \ - DQN_CPU_FEAT_XENTRY(VPCMULQDQ) +#define DN_CPU_FEAT_XMACRO \ + DN_CPU_FEAT_XENTRY(3DNow) \ + DN_CPU_FEAT_XENTRY(3DNowExt) \ + DN_CPU_FEAT_XENTRY(ABM) \ + DN_CPU_FEAT_XENTRY(AES) \ + DN_CPU_FEAT_XENTRY(AVX) \ + DN_CPU_FEAT_XENTRY(AVX2) \ + DN_CPU_FEAT_XENTRY(AVX512F) \ + DN_CPU_FEAT_XENTRY(AVX512DQ) \ + DN_CPU_FEAT_XENTRY(AVX512IFMA) \ + DN_CPU_FEAT_XENTRY(AVX512PF) \ + DN_CPU_FEAT_XENTRY(AVX512ER) \ + DN_CPU_FEAT_XENTRY(AVX512CD) \ + DN_CPU_FEAT_XENTRY(AVX512BW) \ + DN_CPU_FEAT_XENTRY(AVX512VL) \ + DN_CPU_FEAT_XENTRY(AVX512VBMI) \ + DN_CPU_FEAT_XENTRY(AVX512VBMI2) \ + DN_CPU_FEAT_XENTRY(AVX512VNNI) \ + DN_CPU_FEAT_XENTRY(AVX512BITALG) \ + DN_CPU_FEAT_XENTRY(AVX512VPOPCNTDQ) \ + DN_CPU_FEAT_XENTRY(AVX5124VNNIW) \ + DN_CPU_FEAT_XENTRY(AVX5124FMAPS) \ + DN_CPU_FEAT_XENTRY(AVX512VP2INTERSECT) \ + DN_CPU_FEAT_XENTRY(AVX512FP16) \ + DN_CPU_FEAT_XENTRY(CLZERO) \ + DN_CPU_FEAT_XENTRY(CMPXCHG8B) \ + DN_CPU_FEAT_XENTRY(CMPXCHG16B) \ + DN_CPU_FEAT_XENTRY(F16C) \ + DN_CPU_FEAT_XENTRY(FMA) \ + DN_CPU_FEAT_XENTRY(FMA4) \ + DN_CPU_FEAT_XENTRY(FP128) \ + DN_CPU_FEAT_XENTRY(FP256) \ + DN_CPU_FEAT_XENTRY(FPU) \ + DN_CPU_FEAT_XENTRY(MMX) \ + DN_CPU_FEAT_XENTRY(MONITOR) \ + DN_CPU_FEAT_XENTRY(MOVBE) \ + DN_CPU_FEAT_XENTRY(MOVU) \ + DN_CPU_FEAT_XENTRY(MmxExt) \ + DN_CPU_FEAT_XENTRY(PCLMULQDQ) \ + DN_CPU_FEAT_XENTRY(POPCNT) \ + DN_CPU_FEAT_XENTRY(RDRAND) \ + DN_CPU_FEAT_XENTRY(RDSEED) \ + DN_CPU_FEAT_XENTRY(RDTSCP) \ + DN_CPU_FEAT_XENTRY(SHA) \ + DN_CPU_FEAT_XENTRY(SSE) \ + DN_CPU_FEAT_XENTRY(SSE2) \ + DN_CPU_FEAT_XENTRY(SSE3) \ + DN_CPU_FEAT_XENTRY(SSE41) \ + DN_CPU_FEAT_XENTRY(SSE42) \ + DN_CPU_FEAT_XENTRY(SSE4A) \ + DN_CPU_FEAT_XENTRY(SSSE3) \ + DN_CPU_FEAT_XENTRY(TSC) \ + DN_CPU_FEAT_XENTRY(TscInvariant) \ + DN_CPU_FEAT_XENTRY(VAES) \ + DN_CPU_FEAT_XENTRY(VPCMULQDQ) -enum Dqn_CPUFeature +enum DN_CPUFeature { - #define DQN_CPU_FEAT_XENTRY(label) Dqn_CPUFeature_##label, - DQN_CPU_FEAT_XMACRO - #undef DQN_CPU_FEAT_XENTRY - Dqn_CPUFeature_Count, + #define DN_CPU_FEAT_XENTRY(label) DN_CPUFeature_##label, + DN_CPU_FEAT_XMACRO + #undef DN_CPU_FEAT_XENTRY + DN_CPUFeature_Count, }; -struct Dqn_CPUFeatureDecl +struct DN_CPUFeatureDecl { - Dqn_CPUFeature value; - Dqn_Str8 label; + DN_CPUFeature value; + DN_Str8 label; }; -struct Dqn_CPUFeatureQuery +struct DN_CPUFeatureQuery { - Dqn_CPUFeature feature; + DN_CPUFeature feature; bool available; }; -struct Dqn_CPUReport +struct DN_CPUReport { char vendor [4 /*bytes*/ * 3 /*EDX, ECX, EBX*/ + 1 /*null*/]; char brand [48]; - uint64_t features[(Dqn_CPUFeature_Count / (sizeof(uint64_t) * 8)) + 1]; + uint64_t features[(DN_CPUFeature_Count / (sizeof(uint64_t) * 8)) + 1]; }; -extern Dqn_CPUFeatureDecl g_dqn_cpu_feature_decl[Dqn_CPUFeature_Count]; -#endif // DQN_PLATFORM_ARM64 +extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count]; +#endif // DN_PLATFORM_ARM64 -// NOTE: [$TMUT] Dqn_TicketMutex /////////////////////////////////////////////////////////////////// -struct Dqn_TicketMutex +// NOTE: [$TMUT] DN_TicketMutex /////////////////////////////////////////////////////////////////// +struct DN_TicketMutex { unsigned int volatile ticket; // The next ticket to give out to the thread taking the mutex unsigned int volatile serving; // The ticket ID to block the mutex on until it is returned }; -// NOTE: [$MUTX] Dqn_OSMutex /////////////////////////////////////////////////////////////////////// -struct Dqn_OSMutex +// NOTE: [$MUTX] DN_OSMutex /////////////////////////////////////////////////////////////////////// +struct DN_OSMutex { - #if defined(DQN_OS_WIN32) && !defined(DQN_OS_WIN32_USE_PTHREADS) + #if defined(DN_OS_WIN32) && !defined(DN_OS_WIN32_USE_PTHREADS) char win32_handle[48]; #else pthread_mutex_t posix_handle; @@ -585,193 +640,271 @@ struct Dqn_OSMutex #endif }; -// NOTE: [$PRIN] Dqn_Print ///////////////////////////////////////////////////////////////////////// -enum Dqn_PrintStd +// NOTE: [$PRIN] DN_Print ///////////////////////////////////////////////////////////////////////// +enum DN_PrintStd { - Dqn_PrintStd_Out, - Dqn_PrintStd_Err, + DN_PrintStd_Out, + DN_PrintStd_Err, }; -enum Dqn_PrintBold +enum DN_PrintBold { - Dqn_PrintBold_No, - Dqn_PrintBold_Yes, + DN_PrintBold_No, + DN_PrintBold_Yes, }; -struct Dqn_PrintStyle +struct DN_PrintStyle { - Dqn_PrintBold bold; + DN_PrintBold bold; bool colour; uint8_t r, g, b; }; -enum Dqn_PrintESCColour +enum DN_PrintESCColour { - Dqn_PrintESCColour_Fg, - Dqn_PrintESCColour_Bg, + DN_PrintESCColour_Fg, + DN_PrintESCColour_Bg, }; -// NOTE: [$LLOG] Dqn_Log /////////////////////////////////////////////////////////////////////////// -enum Dqn_LogType +// NOTE: [$LLOG] DN_Log /////////////////////////////////////////////////////////////////////////// +enum DN_LogType { - Dqn_LogType_Debug, - Dqn_LogType_Info, - Dqn_LogType_Warning, - Dqn_LogType_Error, - Dqn_LogType_Count, + DN_LogType_Debug, + DN_LogType_Info, + DN_LogType_Warning, + DN_LogType_Error, + DN_LogType_Count, }; -typedef void Dqn_LogProc(Dqn_Str8 type, +typedef void DN_LogProc(DN_Str8 type, int log_type, void *user_data, - Dqn_CallSite call_site, - DQN_FMT_ATTRIB char const *fmt, + DN_CallSite call_site, + DN_FMT_ATTRIB char const *fmt, va_list va); // NOTE: [$INTR] Intrinsics //////////////////////////////////////////////////////////////////////// -DQN_FORCE_INLINE uint64_t Dqn_Atomic_SetValue64 (uint64_t volatile *target, uint64_t value); -DQN_FORCE_INLINE long Dqn_Atomic_SetValue32 (long volatile *target, long value); -#if !defined(DQN_PLATFORM_ARM64) -DQN_API Dqn_CPUIDResult Dqn_CPU_ID (Dqn_CPUIDArgs args); -DQN_API Dqn_usize Dqn_CPU_HasFeatureArray (Dqn_CPUReport const *report, Dqn_CPUFeatureQuery *features, Dqn_usize features_size); -DQN_API bool Dqn_CPU_HasFeature (Dqn_CPUReport const *report, Dqn_CPUFeature feature); -DQN_API bool Dqn_CPU_HasAllFeatures (Dqn_CPUReport const *report, Dqn_CPUFeature const *features, Dqn_usize features_size); -template bool Dqn_CPU_HasAllFeaturesCArray (Dqn_CPUReport const *report, Dqn_CPUFeature const (&features)[N]); -DQN_API void Dqn_CPU_SetFeature (Dqn_CPUReport *report, Dqn_CPUFeature feature); -DQN_API Dqn_CPUReport Dqn_CPU_Report (); +DN_FORCE_INLINE uint64_t DN_Atomic_SetValue64 (uint64_t volatile *target, uint64_t value); +DN_FORCE_INLINE long DN_Atomic_SetValue32 (long volatile *target, long value); +#if !defined(DN_PLATFORM_ARM64) +DN_API DN_CPUIDResult DN_CPU_ID (DN_CPUIDArgs args); +DN_API DN_USize DN_CPU_HasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size); +DN_API bool DN_CPU_HasFeature (DN_CPUReport const *report, DN_CPUFeature feature); +DN_API bool DN_CPU_HasAllFeatures (DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size); +template bool DN_CPU_HasAllFeaturesCArray (DN_CPUReport const *report, DN_CPUFeature const (&features)[N]); +DN_API void DN_CPU_SetFeature (DN_CPUReport *report, DN_CPUFeature feature); +DN_API DN_CPUReport DN_CPU_Report (); #endif -// NOTE: [$TMUT] Dqn_TicketMutex /////////////////////////////////////////////////////////////////// -DQN_API void Dqn_TicketMutex_Begin (Dqn_TicketMutex *mutex); -DQN_API void Dqn_TicketMutex_End (Dqn_TicketMutex *mutex); -DQN_API Dqn_uint Dqn_TicketMutex_MakeTicket (Dqn_TicketMutex *mutex); -DQN_API void Dqn_TicketMutex_BeginTicket (Dqn_TicketMutex const *mutex, Dqn_uint ticket); -DQN_API bool Dqn_TicketMutex_CanLock (Dqn_TicketMutex const *mutex, Dqn_uint ticket); +// NOTE: [$TMUT] DN_TicketMutex /////////////////////////////////////////////////////////////////// +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); -// NOTE: [$PRIN] Dqn_Print ///////////////////////////////////////////////////////////////////////// +// NOTE: [$PRIN] DN_Print ///////////////////////////////////////////////////////////////////////// // NOTE: Print Style /////////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_PrintStyle Dqn_Print_StyleColour (uint8_t r, uint8_t g, uint8_t b, Dqn_PrintBold bold); -DQN_API Dqn_PrintStyle Dqn_Print_StyleColourU32 (uint32_t rgb, Dqn_PrintBold bold); -DQN_API Dqn_PrintStyle Dqn_Print_StyleBold (); +DN_API DN_PrintStyle DN_Print_StyleColour (uint8_t r, uint8_t g, uint8_t b, DN_PrintBold bold); +DN_API DN_PrintStyle DN_Print_StyleColourU32 (uint32_t rgb, DN_PrintBold bold); +DN_API DN_PrintStyle DN_Print_StyleBold (); // NOTE: Print Macros ////////////////////////////////////////////////////////////////////////////// -#define Dqn_Print(string) Dqn_Print_Std(Dqn_PrintStd_Out, string) -#define Dqn_Print_F(fmt, ...) Dqn_Print_StdF(Dqn_PrintStd_Out, fmt, ## __VA_ARGS__) -#define Dqn_Print_FV(fmt, args) Dqn_Print_StdFV(Dqn_PrintStd_Out, fmt, args) +#define DN_Print(string) DN_Print_Std(DN_PrintStd_Out, string) +#define DN_Print_F(fmt, ...) DN_Print_StdF(DN_PrintStd_Out, fmt, ## __VA_ARGS__) +#define DN_Print_FV(fmt, args) DN_Print_StdFV(DN_PrintStd_Out, fmt, args) -#define Dqn_Print_Style(style, string) Dqn_Print_StdStyle(Dqn_PrintStd_Out, style, string) -#define Dqn_Print_FStyle(style, fmt, ...) Dqn_Print_StdFStyle(Dqn_PrintStd_Out, style, fmt, ## __VA_ARGS__) -#define Dqn_Print_FVStyle(style, fmt, args, ...) Dqn_Print_StdFVStyle(Dqn_PrintStd_Out, style, fmt, args) +#define DN_Print_Style(style, string) DN_Print_StdStyle(DN_PrintStd_Out, style, string) +#define DN_Print_FStyle(style, fmt, ...) DN_Print_StdFStyle(DN_PrintStd_Out, style, fmt, ## __VA_ARGS__) +#define DN_Print_FVStyle(style, fmt, args, ...) DN_Print_StdFVStyle(DN_PrintStd_Out, style, fmt, args) -#define Dqn_Print_Ln(string) Dqn_Print_StdLn(Dqn_PrintStd_Out, string) -#define Dqn_Print_LnF(fmt, ...) Dqn_Print_StdLnF(Dqn_PrintStd_Out, fmt, ## __VA_ARGS__) -#define Dqn_Print_LnFV(fmt, args) Dqn_Print_StdLnFV(Dqn_PrintStd_Out, fmt, args) +#define DN_Print_Ln(string) DN_Print_StdLn(DN_PrintStd_Out, string) +#define DN_Print_LnF(fmt, ...) DN_Print_StdLnF(DN_PrintStd_Out, fmt, ## __VA_ARGS__) +#define DN_Print_LnFV(fmt, args) DN_Print_StdLnFV(DN_PrintStd_Out, fmt, args) -#define Dqn_Print_LnStyle(style, string) Dqn_Print_StdLnStyle(Dqn_PrintStd_Out, style, string); -#define Dqn_Print_LnFStyle(style, fmt, ...) Dqn_Print_StdLnFStyle(Dqn_PrintStd_Out, style, fmt, ## __VA_ARGS__); -#define Dqn_Print_LnFVStyle(style, fmt, args) Dqn_Print_StdLnFVStyle(Dqn_PrintStd_Out, style, fmt, args); +#define DN_Print_LnStyle(style, string) DN_Print_StdLnStyle(DN_PrintStd_Out, style, string); +#define DN_Print_LnFStyle(style, fmt, ...) DN_Print_StdLnFStyle(DN_PrintStd_Out, style, fmt, ## __VA_ARGS__); +#define DN_Print_LnFVStyle(style, fmt, args) DN_Print_StdLnFVStyle(DN_PrintStd_Out, style, fmt, args); -#define Dqn_Print_Err(string) Dqn_Print_Std(Dqn_PrintStd_Err, string) -#define Dqn_Print_ErrF(fmt, ...) Dqn_Print_StdF(Dqn_PrintStd_Err, fmt, ## __VA_ARGS__) -#define Dqn_Print_ErrFV(fmt, args) Dqn_Print_StdFV(Dqn_PrintStd_Err, fmt, args) +#define DN_Print_Err(string) DN_Print_Std(DN_PrintStd_Err, string) +#define DN_Print_ErrF(fmt, ...) DN_Print_StdF(DN_PrintStd_Err, fmt, ## __VA_ARGS__) +#define DN_Print_ErrFV(fmt, args) DN_Print_StdFV(DN_PrintStd_Err, fmt, args) -#define Dqn_Print_ErrStyle(style, string) Dqn_Print_StdStyle(Dqn_PrintStd_Err, style, string) -#define Dqn_Print_ErrFStyle(style, fmt, ...) Dqn_Print_StdFStyle(Dqn_PrintStd_Err, style, fmt, ## __VA_ARGS__) -#define Dqn_Print_ErrFVStyle(style, fmt, args, ...) Dqn_Print_StdFVStyle(Dqn_PrintStd_Err, style, fmt, args) +#define DN_Print_ErrStyle(style, string) DN_Print_StdStyle(DN_PrintStd_Err, style, string) +#define DN_Print_ErrFStyle(style, fmt, ...) DN_Print_StdFStyle(DN_PrintStd_Err, style, fmt, ## __VA_ARGS__) +#define DN_Print_ErrFVStyle(style, fmt, args, ...) DN_Print_StdFVStyle(DN_PrintStd_Err, style, fmt, args) -#define Dqn_Print_ErrLn(string) Dqn_Print_StdLn(Dqn_PrintStd_Err, string) -#define Dqn_Print_ErrLnF(fmt, ...) Dqn_Print_StdLnF(Dqn_PrintStd_Err, fmt, ## __VA_ARGS__) -#define Dqn_Print_ErrLnFV(fmt, args) Dqn_Print_StdLnFV(Dqn_PrintStd_Err, fmt, args) +#define DN_Print_ErrLn(string) DN_Print_StdLn(DN_PrintStd_Err, string) +#define DN_Print_ErrLnF(fmt, ...) DN_Print_StdLnF(DN_PrintStd_Err, fmt, ## __VA_ARGS__) +#define DN_Print_ErrLnFV(fmt, args) DN_Print_StdLnFV(DN_PrintStd_Err, fmt, args) -#define Dqn_Print_ErrLnStyle(style, string) Dqn_Print_StdLnStyle(Dqn_PrintStd_Err, style, string); -#define Dqn_Print_ErrLnFStyle(style, fmt, ...) Dqn_Print_StdLnFStyle(Dqn_PrintStd_Err, style, fmt, ## __VA_ARGS__); -#define Dqn_Print_ErrLnFVStyle(style, fmt, args) Dqn_Print_StdLnFVStyle(Dqn_PrintStd_Err, style, fmt, args); +#define DN_Print_ErrLnStyle(style, string) DN_Print_StdLnStyle(DN_PrintStd_Err, style, string); +#define DN_Print_ErrLnFStyle(style, fmt, ...) DN_Print_StdLnFStyle(DN_PrintStd_Err, style, fmt, ## __VA_ARGS__); +#define DN_Print_ErrLnFVStyle(style, fmt, args) DN_Print_StdLnFVStyle(DN_PrintStd_Err, style, fmt, args); // NOTE: Print ///////////////////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_Print_Std (Dqn_PrintStd std_handle, Dqn_Str8 string); -DQN_API void Dqn_Print_StdF (Dqn_PrintStd std_handle, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_Print_StdFV (Dqn_PrintStd std_handle, DQN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Print_Std (DN_PrintStd std_handle, DN_Str8 string); +DN_API void DN_Print_StdF (DN_PrintStd std_handle, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Print_StdFV (DN_PrintStd std_handle, DN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API void Dqn_Print_StdStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_Str8 string); -DQN_API void Dqn_Print_StdFStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_Print_StdFVStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Print_StdStyle (DN_PrintStd std_handle, DN_PrintStyle style, DN_Str8 string); +DN_API void DN_Print_StdFStyle (DN_PrintStd std_handle, DN_PrintStyle style, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Print_StdFVStyle (DN_PrintStd std_handle, DN_PrintStyle style, DN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API void Dqn_Print_StdLn (Dqn_PrintStd std_handle, Dqn_Str8 string); -DQN_API void Dqn_Print_StdLnF (Dqn_PrintStd std_handle, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_Print_StdLnFV (Dqn_PrintStd std_handle, DQN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Print_StdLn (DN_PrintStd std_handle, DN_Str8 string); +DN_API void DN_Print_StdLnF (DN_PrintStd std_handle, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Print_StdLnFV (DN_PrintStd std_handle, DN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API void Dqn_Print_StdLnStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_Str8 string); -DQN_API void Dqn_Print_StdLnFStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_Print_StdLnFVStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Print_StdLnStyle (DN_PrintStd std_handle, DN_PrintStyle style, DN_Str8 string); +DN_API void DN_Print_StdLnFStyle (DN_PrintStd std_handle, DN_PrintStyle style, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Print_StdLnFVStyle (DN_PrintStd std_handle, DN_PrintStyle style, DN_FMT_ATTRIB char const *fmt, va_list args); // NOTE: ANSI Formatting Codes ///////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8 Dqn_Print_ESCColourStr8 (Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b); -DQN_API Dqn_Str8 Dqn_Print_ESCColourU32Str8 (Dqn_PrintESCColour colour, uint32_t value); +DN_API DN_Str8 DN_Print_ESCColourStr8 (DN_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b); +DN_API DN_Str8 DN_Print_ESCColourU32Str8 (DN_PrintESCColour colour, uint32_t value); -#define Dqn_Print_ESCColourFgStr8(r, g, b) Dqn_Print_ESCColourStr8(Dqn_PrintESCColour_Fg, r, g, b) -#define Dqn_Print_ESCColourBgStr8(r, g, b) Dqn_Print_ESCColourStr8(Dqn_PrintESCColour_Bg, r, g, b) -#define Dqn_Print_ESCColourFg(r, g, b) Dqn_Print_ESCColourStr8(Dqn_PrintESCColour_Fg, r, g, b).data -#define Dqn_Print_ESCColourBg(r, g, b) Dqn_Print_ESCColourStr8(Dqn_PrintESCColour_Bg, r, g, b).data +#define DN_Print_ESCColourFgStr8(r, g, b) DN_Print_ESCColourStr8(DN_PrintESCColour_Fg, r, g, b) +#define DN_Print_ESCColourBgStr8(r, g, b) DN_Print_ESCColourStr8(DN_PrintESCColour_Bg, r, g, b) +#define DN_Print_ESCColourFg(r, g, b) DN_Print_ESCColourStr8(DN_PrintESCColour_Fg, r, g, b).data +#define DN_Print_ESCColourBg(r, g, b) DN_Print_ESCColourStr8(DN_PrintESCColour_Bg, r, g, b).data -#define Dqn_Print_ESCColourFgU32Str8(value) Dqn_Print_ESCColourU32Str8(Dqn_PrintESCColour_Fg, value) -#define Dqn_Print_ESCColourBgU32Str8(value) Dqn_Print_ESCColourU32Str8(Dqn_PrintESCColour_Bg, value) -#define Dqn_Print_ESCColourFgU32(value) Dqn_Print_ESCColourU32Str8(Dqn_PrintESCColour_Fg, value).data -#define Dqn_Print_ESCColourBgU32(value) Dqn_Print_ESCColourU32Str8(Dqn_PrintESCColour_Bg, value).data +#define DN_Print_ESCColourFgU32Str8(value) DN_Print_ESCColourU32Str8(DN_PrintESCColour_Fg, value) +#define DN_Print_ESCColourBgU32Str8(value) DN_Print_ESCColourU32Str8(DN_PrintESCColour_Bg, value) +#define DN_Print_ESCColourFgU32(value) DN_Print_ESCColourU32Str8(DN_PrintESCColour_Fg, value).data +#define DN_Print_ESCColourBgU32(value) DN_Print_ESCColourU32Str8(DN_PrintESCColour_Bg, value).data -#define Dqn_Print_ESCReset "\x1b[0m" -#define Dqn_Print_ESCBold "\x1b[1m" -#define Dqn_Print_ESCResetStr8 DQN_STR8(Dqn_Print_ESCReset) -#define Dqn_Print_ESCBoldStr8 DQN_STR8(Dqn_Print_ESCBold) -// NOTE: [$LLOG] Dqn_Log /////////////////////////////////////////////////////////////////////////// -#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 +#define DN_Print_ESCReset "\x1b[0m" +#define DN_Print_ESCBold "\x1b[1m" +#define DN_Print_ESCResetStr8 DN_STR8(DN_Print_ESCReset) +#define DN_Print_ESCBoldStr8 DN_STR8(DN_Print_ESCBold) +// NOTE: [$LLOG] DN_Log /////////////////////////////////////////////////////////////////////////// +#define DN_LogTypeColourU32_Info 0x00'87'ff'ff // Blue +#define DN_LogTypeColourU32_Warning 0xff'ff'00'ff // Yellow +#define DN_LogTypeColourU32_Error 0xff'00'00'ff // Red -#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__) +#define DN_Log_DebugF(fmt, ...) DN_Log_TypeFCallSite (DN_LogType_Debug, DN_CALL_SITE, fmt, ## __VA_ARGS__) +#define DN_Log_InfoF(fmt, ...) DN_Log_TypeFCallSite (DN_LogType_Info, DN_CALL_SITE, fmt, ## __VA_ARGS__) +#define DN_Log_WarningF(fmt, ...) DN_Log_TypeFCallSite (DN_LogType_Warning, DN_CALL_SITE, fmt, ## __VA_ARGS__) +#define DN_Log_ErrorF(fmt, ...) DN_Log_TypeFCallSite (DN_LogType_Error, DN_CALL_SITE, fmt, ## __VA_ARGS__) +#define DN_Log_DebugFV(fmt, args) DN_Log_TypeFVCallSite(DN_LogType_Debug, DN_CALL_SITE, fmt, args) +#define DN_Log_InfoFV(fmt, args) DN_Log_TypeFVCallSite(DN_LogType_Info, DN_CALL_SITE, fmt, args) +#define DN_Log_WarningFV(fmt, args) DN_Log_TypeFVCallSite(DN_LogType_Warning, DN_CALL_SITE, fmt, args) +#define DN_Log_ErrorFV(fmt, args) DN_Log_TypeFVCallSite(DN_LogType_Error, DN_CALL_SITE, fmt, args) +#define DN_Log_TypeFV(type, fmt, args) DN_Log_TypeFVCallSite(type, DN_CALL_SITE, fmt, args) +#define DN_Log_TypeF(type, fmt, ...) DN_Log_TypeFCallSite (type, DN_CALL_SITE, fmt, ## __VA_ARGS__) +#define DN_Log_FV(type, fmt, args) DN_Log_FVCallSite (type, DN_CALL_SITE, fmt, args) +#define DN_Log_F(type, fmt, ...) DN_Log_FCallSite (type, DN_CALL_SITE, fmt, ## __VA_ARGS__) -DQN_API Dqn_Str8 Dqn_Log_MakeStr8 (struct Dqn_Arena *arena, bool colour, Dqn_Str8 type, int log_type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API void Dqn_Log_TypeFVCallSite (Dqn_LogType type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, va_list va); -DQN_API void Dqn_Log_TypeFCallSite (Dqn_LogType type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_Log_FVCallSite (Dqn_Str8 type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, va_list va); -DQN_API void Dqn_Log_FCallSite (Dqn_Str8 type, Dqn_CallSite call_site, DQN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_Str8 DN_Log_MakeStr8 (struct DN_Arena *arena, bool colour, DN_Str8 type, int log_type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_Log_TypeFVCallSite (DN_LogType type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list va); +DN_API void DN_Log_TypeFCallSite (DN_LogType type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_Log_FVCallSite (DN_Str8 type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list va); +DN_API void DN_Log_FCallSite (DN_Str8 type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); -// NOTE: [$ERRS] Dqn_ErrorSink ///////////////////////////////////////////////////////////////////// -DQN_API Dqn_ErrorSink * Dqn_ErrorSink_Begin (Dqn_ErrorSinkMode mode); -DQN_API bool Dqn_ErrorSink_HasError (Dqn_ErrorSink *error); -DQN_API Dqn_ErrorSinkNode Dqn_ErrorSink_End (Dqn_Arena *arena, Dqn_ErrorSink *error); -DQN_API void Dqn_ErrorSink_EndAndIgnore (Dqn_ErrorSink *error); -DQN_API bool Dqn_ErrorSink_EndAndLogError (Dqn_ErrorSink *error, Dqn_Str8 error_msg); -DQN_API bool Dqn_ErrorSink_EndAndLogErrorFV (Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API bool Dqn_ErrorSink_EndAndLogErrorF (Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_ErrorSink_EndAndExitIfErrorF (Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_ErrorSink_EndAndExitIfErrorFV (Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, va_list args); +// NOTE: [$ERRS] DN_ErrSink ///////////////////////////////////////////////////////////////////// +DN_API DN_ErrSink * DN_ErrSink_Begin (DN_ErrSinkMode mode); +#define DN_ErrSink_BeginDefault() DN_ErrSink_Begin(DN_ErrSinkMode_Nil) +DN_API bool DN_ErrSink_HasError (DN_ErrSink *err); +DN_API DN_ErrSinkMsg* DN_ErrSink_End (DN_Arena *arena, DN_ErrSink *err); +DN_API DN_Str8 DN_ErrSink_EndStr8 (DN_Arena *arena, DN_ErrSink *err); +DN_API void DN_ErrSink_EndAndIgnore (DN_ErrSink *err); + +#define DN_ErrSink_EndAndLogError(err, err_msg) DN_ErrSink_EndAndLogError_ (err, DN_CALL_SITE, err_msg) +#define DN_ErrSink_EndAndLogErrorFV(err, fmt, args) DN_ErrSink_EndAndLogErrorFV_ (err, DN_CALL_SITE, fmt, args) +#define DN_ErrSink_EndAndLogErrorF(err, fmt, ...) DN_ErrSink_EndAndLogErrorF_ (err, DN_CALL_SITE, fmt, ##__VA_ARGS__) +#define DN_ErrSink_EndAndExitIfErrorFV(err, exit_val, fmt, args) DN_ErrSink_EndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args) +#define DN_ErrSink_EndAndExitIfErrorF(err, exit_val, fmt, ...) DN_ErrSink_EndAndExitIfErrorF_ (err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__) + +DN_API bool DN_ErrSink_EndAndLogError_ (DN_ErrSink *err, DN_CallSite call_site, DN_Str8 msg); +DN_API bool DN_ErrSink_EndAndLogErrorFV_ (DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_ErrSink_EndAndLogErrorF_ (DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_ErrSink_EndAndExitIfErrorF_ (DN_ErrSink *err, DN_CallSite call_site, uint32_t exit_val, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_ErrSink_EndAndExitIfErrorFV_ (DN_ErrSink *err, DN_CallSite call_site, uint32_t exit_val, DN_FMT_ATTRIB char const *fmt, va_list args); + +#define DN_ErrSink_AppendFV(error, error_code, fmt, args) do { DN_TLS_SaveCallSite; DN_ErrSink_AppendFV_(error, error_code, fmt, args); } while (0) +#define DN_ErrSink_AppendF(error, error_code, fmt, ...) do { DN_TLS_SaveCallSite; DN_ErrSink_AppendF_(error, error_code, fmt, ## __VA_ARGS__); } while (0) +DN_API void DN_ErrSink_AppendFV_ (DN_ErrSink *err, uint32_t error_code, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_ErrSink_AppendF_ (DN_ErrSink *err, uint32_t error_code, DN_FMT_ATTRIB char const *fmt, ...); + +// NOTE: [$SDLL] DN_SentinelDLL /////////////////////////////////////////////////////////////////// +#define DN_SentinelDLL_Init(list) \ + (list)->next = (list)->prev = (list) + +#define DN_SentinelDLL_InitArena(list, T, arena) \ + do { \ + (list) = DN_Arena_New(arena, T, DN_ZeroMem_Yes); \ + DN_SentinelDLL_Init(list); \ + } while (0) + +#define DN_SentinelDLL_InitPool(list, T, pool) \ + do { \ + (list) = DN_Pool_New(pool, T); \ + DN_SentinelDLL_Init(list); \ + } while (0) + +#define DN_SentinelDLL_Detach(item) \ + do { \ + if (item) { \ + (item)->prev->next = (item)->next; \ + (item)->next->prev = (item)->prev; \ + (item)->next = nullptr; \ + (item)->prev = nullptr; \ + } \ + } while (0) + +#define DN_SentinelDLL_Dequeue(list, dest_ptr) \ + if (DN_SentinelDLL_HasItems(list)) { \ + dest_ptr = (list)->next; \ + DN_SentinelDLL_Detach(dest_ptr); \ + } + +#define DN_SentinelDLL_Append(list, item) \ + do { \ + if (item) { \ + if ((item)->next) \ + DN_SentinelDLL_Detach(item); \ + (item)->next = (list)->next; \ + (item)->prev = (list); \ + (item)->next->prev = (item); \ + (item)->prev->next = (item); \ + } \ + } while (0) + +#define DN_SentinelDLL_Prepend(list, item) \ + do { \ + if (item) { \ + if ((item)->next) \ + DN_SentinelDLL_Detach(item); \ + (item)->next = (list); \ + (item)->prev = (list)->prev; \ + (item)->next->prev = (item); \ + (item)->prev->next = (item); \ + } \ + } while (0) + +#define DN_SentinelDLL_IsEmpty(list) \ + (!(list) || ((list) == (list)->next)) + +#define DN_SentinelDLL_IsInit(list) \ + ((list)->next && (list)->prev) + +#define DN_SentinelDLL_HasItems(list) \ + ((list) && ((list) != (list)->next)) + +#define DN_SentinelDLL_ForEach(it_name, list) \ + auto *it_name = (list)->next; (it_name) != (list); (it_name) = (it_name)->next -#define Dqn_ErrorSink_MakeFV(error, error_code, fmt, args) do { Dqn_TLS_SaveCallSite; Dqn_ErrorSink_MakeFV_(error, error_code, fmt, args); } while (0) -#define Dqn_ErrorSink_MakeF(error, error_code, fmt, ...) do { Dqn_TLS_SaveCallSite; Dqn_ErrorSink_MakeF_(error, error_code, fmt, ## __VA_ARGS__); } while (0) -DQN_API void Dqn_ErrorSink_MakeFV_ (Dqn_ErrorSink *error, uint32_t error_code, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API void Dqn_ErrorSink_MakeF_ (Dqn_ErrorSink *error, uint32_t error_code, DQN_FMT_ATTRIB char const *fmt, ...); // NOTE: [$INTR] Intrinsics //////////////////////////////////////////////////////////////////////// -DQN_FORCE_INLINE uint64_t Dqn_Atomic_SetValue64(uint64_t volatile *target, uint64_t value) +DN_FORCE_INLINE uint64_t DN_Atomic_SetValue64(uint64_t volatile *target, uint64_t value) { - #if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) + #if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) __int64 result; do { result = *target; - } while (Dqn_Atomic_CompareExchange64(target, value, result) != result); - return DQN_CAST(uint64_t)result; - #elif defined(DQN_COMPILER_GCC) || defined(DQN_COMPILER_CLANG) + } while (DN_Atomic_CompareExchange64(target, value, result) != result); + return DN_CAST(uint64_t)result; + #elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG) uint64_t result = __sync_lock_test_and_set(target, value); return result; #else @@ -779,15 +912,15 @@ DQN_FORCE_INLINE uint64_t Dqn_Atomic_SetValue64(uint64_t volatile *target, uint6 #endif } -DQN_FORCE_INLINE long Dqn_Atomic_SetValue32(long volatile *target, long value) +DN_FORCE_INLINE long DN_Atomic_SetValue32(long volatile *target, long value) { - #if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) + #if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) long result; do { result = *target; - } while (Dqn_Atomic_CompareExchange32(target, value, result) != result); + } while (DN_Atomic_CompareExchange32(target, value, result) != result); return result; - #elif defined(DQN_COMPILER_GCC) || defined(DQN_COMPILER_CLANG) + #elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG) long result = __sync_lock_test_and_set(target, value); return result; #else @@ -795,8 +928,10 @@ DQN_FORCE_INLINE long Dqn_Atomic_SetValue32(long volatile *target, long value) #endif } -template bool Dqn_CPU_HasAllFeaturesCArray(Dqn_CPUReport const *report, Dqn_CPUFeature const (&features)[N]) +template bool DN_CPU_HasAllFeaturesCArray(DN_CPUReport const *report, DN_CPUFeature const (&features)[N]) { - bool result = Dqn_CPU_HasAllFeatures(report, features, N); + bool result = DN_CPU_HasAllFeatures(report, features, N); return result; } + +extern struct DN_Core *g_dn_core; diff --git a/dqn_cgen.cpp b/dqn_cgen.cpp index 6de2a4b..be69ffd 100644 --- a/dqn_cgen.cpp +++ b/dqn_cgen.cpp @@ -15,62 +15,62 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -Dqn_CGenMapNodeToEnum const DQN_CGEN_TABLE_KEY_LIST[] = +DN_CGenMapNodeToEnum const DN_CGEN_TABLE_KEY_LIST[] = { - {Dqn_CGenTableKeyType_Name, DQN_STR8("name")}, - {Dqn_CGenTableKeyType_Type, DQN_STR8("type")}, + {DN_CGenTableKeyType_Name, DN_STR8("name")}, + {DN_CGenTableKeyType_Type, DN_STR8("type")}, }; -Dqn_CGenMapNodeToEnum const DQN_CGEN_TABLE_TYPE_LIST[] = +DN_CGenMapNodeToEnum const DN_CGEN_TABLE_TYPE_LIST[] = { - {Dqn_CGenTableType_Data, DQN_STR8("data") }, - {Dqn_CGenTableType_CodeGenBuiltinTypes, DQN_STR8("code_gen_builtin_types")}, - {Dqn_CGenTableType_CodeGenStruct, DQN_STR8("code_gen_struct") }, - {Dqn_CGenTableType_CodeGenEnum, DQN_STR8("code_gen_enum") }, + {DN_CGenTableType_Data, DN_STR8("data") }, + {DN_CGenTableType_CodeGenBuiltinTypes, DN_STR8("code_gen_builtin_types")}, + {DN_CGenTableType_CodeGenStruct, DN_STR8("code_gen_struct") }, + {DN_CGenTableType_CodeGenEnum, DN_STR8("code_gen_enum") }, }; -Dqn_CGenMapNodeToEnum const DQN_CGEN_TABLE_ROW_TAG_LIST[] = +DN_CGenMapNodeToEnum const DN_CGEN_TABLE_ROW_TAG_LIST[] = { - {Dqn_CGenTableRowTagType_CommentDivider, DQN_STR8("comment_divider")}, - {Dqn_CGenTableRowTagType_EmptyLine, DQN_STR8("empty_line")}, + {DN_CGenTableRowTagType_CommentDivider, DN_STR8("comment_divider")}, + {DN_CGenTableRowTagType_EmptyLine, DN_STR8("empty_line")}, }; -Dqn_CGenMapNodeToEnum const DQN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST[] = +DN_CGenMapNodeToEnum const DN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST[] = { - {Dqn_CGenTableRowTagCommentDivider_Label, DQN_STR8("label")}, + {DN_CGenTableRowTagCommentDivider_Label, DN_STR8("label")}, }; -Dqn_CGenTableHeaderType const DQN_CGEN_TABLE_CODE_GEN_STRUCT_HEADER_LIST[] = +DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_STRUCT_HEADER_LIST[] = { - Dqn_CGenTableHeaderType_Name, - Dqn_CGenTableHeaderType_Table, - Dqn_CGenTableHeaderType_CppType, - Dqn_CGenTableHeaderType_CppName, - Dqn_CGenTableHeaderType_CppIsPtr, - Dqn_CGenTableHeaderType_CppOpEquals, - Dqn_CGenTableHeaderType_CppArraySize, - Dqn_CGenTableHeaderType_CppArraySizeField, - Dqn_CGenTableHeaderType_CppLabel, - Dqn_CGenTableHeaderType_GenTypeInfo, + DN_CGenTableHeaderType_Name, + DN_CGenTableHeaderType_Table, + DN_CGenTableHeaderType_CppType, + DN_CGenTableHeaderType_CppName, + DN_CGenTableHeaderType_CppIsPtr, + DN_CGenTableHeaderType_CppOpEquals, + DN_CGenTableHeaderType_CppArraySize, + DN_CGenTableHeaderType_CppArraySizeField, + DN_CGenTableHeaderType_CppLabel, + DN_CGenTableHeaderType_GenTypeInfo, }; -Dqn_CGenTableHeaderType const DQN_CGEN_TABLE_CODE_GEN_ENUM_HEADER_LIST[] = +DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_ENUM_HEADER_LIST[] = { - Dqn_CGenTableHeaderType_Name, - Dqn_CGenTableHeaderType_Table, - Dqn_CGenTableHeaderType_CppName, - Dqn_CGenTableHeaderType_CppValue, - Dqn_CGenTableHeaderType_CppLabel, - Dqn_CGenTableHeaderType_GenTypeInfo, - Dqn_CGenTableHeaderType_GenEnumCount, + DN_CGenTableHeaderType_Name, + DN_CGenTableHeaderType_Table, + DN_CGenTableHeaderType_CppName, + DN_CGenTableHeaderType_CppValue, + DN_CGenTableHeaderType_CppLabel, + DN_CGenTableHeaderType_GenTypeInfo, + DN_CGenTableHeaderType_GenEnumCount, }; -Dqn_CGenTableHeaderType const DQN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST[] = +DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST[] = { - Dqn_CGenTableHeaderType_Name, + DN_CGenTableHeaderType_Name, }; -static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error) +static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_ErrSink *err) { bool result = false; if (!cgen || !cgen->file_list || !cgen->arena) @@ -85,33 +85,33 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error) if (MD_NodeIsNil(table_tag)) continue; - Dqn_CGenTable *table = MD_PushArray(cgen->arena, Dqn_CGenTable, 1); + DN_CGenTable *table = MD_PushArray(cgen->arena, DN_CGenTable, 1); table->node = node; - table->name = Dqn_CGen_MDToDqnStr8(table_tag->first_child->first_child->string); - MD_MapInsert(cgen->arena, &cgen->table_map, MD_MapKeyStr(Dqn_CGen_DqnToMDStr8(table->name)), table); + table->name = DN_CGen_MDToDNStr8(table_tag->first_child->first_child->string); + MD_MapInsert(cgen->arena, &cgen->table_map, MD_MapKeyStr(DN_CGen_DNToMDStr8(table->name)), table); MD_QueuePush(cgen->first_table, cgen->last_table, table); for (MD_EachNode(key, table_tag->first_child)) { - Dqn_CGenMapNodeToEnum key_mapping = Dqn_CGen_MapNodeToEnumOrExit(key, - DQN_CGEN_TABLE_KEY_LIST, - DQN_ARRAY_UCOUNT(DQN_CGEN_TABLE_KEY_LIST), + DN_CGenMapNodeToEnum key_mapping = DN_CGen_MapNodeToEnumOrExit(key, + DN_CGEN_TABLE_KEY_LIST, + DN_ARRAY_UCOUNT(DN_CGEN_TABLE_KEY_LIST), "Table specified invalid key"); - switch (DQN_CAST(Dqn_CGenTableKeyType)key_mapping.enum_val) { - case Dqn_CGenTableKeyType_Nil: DQN_INVALID_CODE_PATH; + switch (DN_CAST(DN_CGenTableKeyType)key_mapping.enum_val) { + case DN_CGenTableKeyType_Nil: DN_INVALID_CODE_PATH; - case Dqn_CGenTableKeyType_Name: { - table->name = Dqn_CGen_MDToDqnStr8(key->first_child->string); + case DN_CGenTableKeyType_Name: { + table->name = DN_CGen_MDToDNStr8(key->first_child->string); } break; - case Dqn_CGenTableKeyType_Type: { + case DN_CGenTableKeyType_Type: { MD_Node *table_type_value = key->first_child; - Dqn_CGenMapNodeToEnum table_type_validator = Dqn_CGen_MapNodeToEnumOrExit(table_type_value, - DQN_CGEN_TABLE_TYPE_LIST, - DQN_ARRAY_UCOUNT(DQN_CGEN_TABLE_TYPE_LIST), + DN_CGenMapNodeToEnum table_type_validator = DN_CGen_MapNodeToEnumOrExit(table_type_value, + DN_CGEN_TABLE_TYPE_LIST, + DN_ARRAY_UCOUNT(DN_CGEN_TABLE_TYPE_LIST), "Table 'type' specified invalid value"); - table->type = DQN_CAST(Dqn_CGenTableType) table_type_validator.enum_val; + table->type = DN_CAST(DN_CGenTableType) table_type_validator.enum_val; - DQN_ASSERT(table->type <= Dqn_CGenTableType_Count); + DN_ASSERT(table->type <= DN_CGenTableType_Count); cgen->table_counts[table->type]++; } break; } @@ -120,8 +120,8 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error) } // NOTE: Parse the tables ////////////////////////////////////////////////////////////////////// - Dqn_usize const BEGIN_COLUMN_INDEX = 1; /*Reserve 0th slot for nil-entry*/ - for (Dqn_CGenTable *table = cgen->first_table; table; table = table->next) { + DN_USize const BEGIN_COLUMN_INDEX = 1; /*Reserve 0th slot for nil-entry*/ + for (DN_CGenTable *table = cgen->first_table; table; table = table->next) { table->column_count = BEGIN_COLUMN_INDEX; table->headers_node = table->node->first_child; for (MD_EachNode(column_node, table->headers_node->first_child)) @@ -134,65 +134,65 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error) for (MD_EachNode(row_node, row_it)) table->row_count++; - table->rows = MD_PushArray(cgen->arena, Dqn_CGenTableRow, table->row_count); - table->headers = MD_PushArray(cgen->arena, Dqn_CGenTableHeader, table->column_count); - for (Dqn_usize index = 0; index < table->row_count; index++) { - Dqn_CGenTableRow *row = table->rows + index; - row->columns = MD_PushArray(cgen->arena, Dqn_CGenTableColumn, table->column_count); + table->rows = MD_PushArray(cgen->arena, DN_CGenTableRow, table->row_count); + table->headers = MD_PushArray(cgen->arena, DN_CGenTableHeader, table->column_count); + for (DN_USize index = 0; index < table->row_count; index++) { + DN_CGenTableRow *row = table->rows + index; + row->columns = MD_PushArray(cgen->arena, DN_CGenTableColumn, table->column_count); } // NOTE: Collect table headers ///////////////////////////////////////////////////////////// table->headers_map = MD_MapMake(cgen->arena); - Dqn_usize column_index = BEGIN_COLUMN_INDEX; + DN_USize column_index = BEGIN_COLUMN_INDEX; for (MD_EachNode(header_column, table->headers_node->first_child)) { - DQN_ASSERT(column_index < table->column_count); + DN_ASSERT(column_index < table->column_count); // NOTE: Detect builtin headers and cache the index for that table ///////////////////// - for (Dqn_usize enum_index = 0; enum_index < Dqn_CGenTableHeaderType_Count; enum_index++) { - Dqn_Str8 decl_str8 = Dqn_CGen_TableHeaderTypeToDeclStr8(DQN_CAST(Dqn_CGenTableHeaderType)enum_index); - if (decl_str8 != Dqn_Str8_Init(header_column->string.str, header_column->string.size)) + for (DN_USize enum_index = 0; enum_index < DN_CGenTableHeaderType_Count; enum_index++) { + DN_Str8 decl_str8 = DN_CGen_TableHeaderTypeToDeclStr8(DN_CAST(DN_CGenTableHeaderType)enum_index); + if (decl_str8 != DN_Str8_Init(header_column->string.str, header_column->string.size)) continue; table->column_indexes[enum_index] = column_index; break; } - MD_MapInsert(cgen->arena, &table->headers_map, MD_MapKeyStr(header_column->string), DQN_CAST(void *)column_index); + MD_MapInsert(cgen->arena, &table->headers_map, MD_MapKeyStr(header_column->string), DN_CAST(void *)column_index); table->headers[column_index++].name = header_column->string; } // NOTE: Validate table headers //////////////////////////////////////////////////////////// switch (table->type) { - case Dqn_CGenTableType_Nil: DQN_INVALID_CODE_PATH; - case Dqn_CGenTableType_Count: DQN_INVALID_CODE_PATH; + case DN_CGenTableType_Nil: DN_INVALID_CODE_PATH; + case DN_CGenTableType_Count: DN_INVALID_CODE_PATH; - case Dqn_CGenTableType_Data: { + case DN_CGenTableType_Data: { } break; - case Dqn_CGenTableType_CodeGenStruct: { - for (Dqn_CGenTableHeaderType enum_val : DQN_CGEN_TABLE_CODE_GEN_STRUCT_HEADER_LIST) { + case DN_CGenTableType_CodeGenStruct: { + for (DN_CGenTableHeaderType enum_val : DN_CGEN_TABLE_CODE_GEN_STRUCT_HEADER_LIST) { if (table->column_indexes[enum_val] == 0) { - Dqn_Str8 expected_value = Dqn_CGen_TableHeaderTypeToDeclStr8(enum_val); - Dqn_CGen_LogF(MD_MessageKind_Error, table->headers_node, error, "Struct code generation table is missing column '%.*s'", DQN_STR_FMT(expected_value)); + DN_Str8 expected_value = DN_CGen_TableHeaderTypeToDeclStr8(enum_val); + DN_CGen_LogF(MD_MessageKind_Error, table->headers_node, err, "Struct code generation table is missing column '%.*s'", DN_STR_FMT(expected_value)); return false; } } } break; - case Dqn_CGenTableType_CodeGenEnum: { - for (Dqn_CGenTableHeaderType enum_val : DQN_CGEN_TABLE_CODE_GEN_ENUM_HEADER_LIST) { + case DN_CGenTableType_CodeGenEnum: { + for (DN_CGenTableHeaderType enum_val : DN_CGEN_TABLE_CODE_GEN_ENUM_HEADER_LIST) { if (table->column_indexes[enum_val] == 0) { - Dqn_Str8 expected_value = Dqn_CGen_TableHeaderTypeToDeclStr8(enum_val); - Dqn_CGen_LogF(MD_MessageKind_Error, table->headers_node, error, "Enum code generation table is missing column '%.*s'", DQN_STR_FMT(expected_value)); + DN_Str8 expected_value = DN_CGen_TableHeaderTypeToDeclStr8(enum_val); + DN_CGen_LogF(MD_MessageKind_Error, table->headers_node, err, "Enum code generation table is missing column '%.*s'", DN_STR_FMT(expected_value)); return false; } } } break; - case Dqn_CGenTableType_CodeGenBuiltinTypes: { - for (Dqn_CGenTableHeaderType enum_val : DQN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST) { + case DN_CGenTableType_CodeGenBuiltinTypes: { + for (DN_CGenTableHeaderType enum_val : DN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST) { if (table->column_indexes[enum_val] == 0) { - Dqn_Str8 expected_value = Dqn_CGen_TableHeaderTypeToDeclStr8(enum_val); - Dqn_CGen_LogF(MD_MessageKind_Error, table->headers_node, error, "Enum code generation table is missing column '%.*s'", DQN_STR_FMT(expected_value)); + DN_Str8 expected_value = DN_CGen_TableHeaderTypeToDeclStr8(enum_val); + DN_CGen_LogF(MD_MessageKind_Error, table->headers_node, err, "Enum code generation table is missing column '%.*s'", DN_STR_FMT(expected_value)); return false; } } @@ -200,47 +200,47 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error) } // NOTE: Parse each row in table /////////////////////////////////////////////////////////// - Dqn_usize row_index = 0; + DN_USize row_index = 0; for (MD_EachNode(row_node, row_it)) { column_index = BEGIN_COLUMN_INDEX; - DQN_ASSERT(row_index < table->row_count); + DN_ASSERT(row_index < table->row_count); // NOTE: Parse any tags set on the row ///////////////////////////////////////////////// - Dqn_CGenTableRow *row = table->rows + row_index++; + DN_CGenTableRow *row = table->rows + row_index++; for (MD_EachNode(row_tag, row_node->first_tag)) { - Dqn_CGenMapNodeToEnum row_mapping = Dqn_CGen_MapNodeToEnumOrExit(row_tag, - DQN_CGEN_TABLE_ROW_TAG_LIST, - DQN_ARRAY_UCOUNT(DQN_CGEN_TABLE_ROW_TAG_LIST), + DN_CGenMapNodeToEnum row_mapping = DN_CGen_MapNodeToEnumOrExit(row_tag, + DN_CGEN_TABLE_ROW_TAG_LIST, + DN_ARRAY_UCOUNT(DN_CGEN_TABLE_ROW_TAG_LIST), "Table specified invalid row tag"); - Dqn_CGenTableRowTag *tag = MD_PushArray(cgen->arena, Dqn_CGenTableRowTag, 1); - tag->type = DQN_CAST(Dqn_CGenTableRowTagType) row_mapping.enum_val; + DN_CGenTableRowTag *tag = MD_PushArray(cgen->arena, DN_CGenTableRowTag, 1); + tag->type = DN_CAST(DN_CGenTableRowTagType) row_mapping.enum_val; MD_QueuePush(row->first_tag, row->last_tag, tag); switch (tag->type) { - case Dqn_CGenTableRowTagType_Nil: DQN_INVALID_CODE_PATH; + case DN_CGenTableRowTagType_Nil: DN_INVALID_CODE_PATH; - case Dqn_CGenTableRowTagType_CommentDivider: { + case DN_CGenTableRowTagType_CommentDivider: { for (MD_EachNode(tag_key, row_tag->first_child)) { - Dqn_CGenMapNodeToEnum tag_mapping = Dqn_CGen_MapNodeToEnumOrExit(tag_key, - DQN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST, - DQN_ARRAY_UCOUNT(DQN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST), + DN_CGenMapNodeToEnum tag_mapping = DN_CGen_MapNodeToEnumOrExit(tag_key, + DN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST, + DN_ARRAY_UCOUNT(DN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST), "Table specified invalid row tag"); - switch (DQN_CAST(Dqn_CGenTableRowTagCommentDivider)tag_mapping.enum_val) { - case Dqn_CGenTableRowTagCommentDivider_Nil: DQN_INVALID_CODE_PATH; - case Dqn_CGenTableRowTagCommentDivider_Label: { + switch (DN_CAST(DN_CGenTableRowTagCommentDivider)tag_mapping.enum_val) { + case DN_CGenTableRowTagCommentDivider_Nil: DN_INVALID_CODE_PATH; + case DN_CGenTableRowTagCommentDivider_Label: { tag->comment = tag_key->first_child->string; } break; } } } break; - case Dqn_CGenTableRowTagType_EmptyLine: break; + case DN_CGenTableRowTagType_EmptyLine: break; } } for (MD_EachNode(column_node, row_node->first_child)) { - table->headers[column_index].longest_string = DQN_MAX(table->headers[column_index].longest_string, DQN_CAST(int) column_node->string.size); - row->columns[column_index].string = Dqn_CGen_MDToDqnStr8(column_node->string); + table->headers[column_index].longest_string = DN_MAX(table->headers[column_index].longest_string, DN_CAST(int) column_node->string.size); + row->columns[column_index].string = DN_CGen_MDToDNStr8(column_node->string); row->columns[column_index].node = column_node; column_index++; } @@ -248,20 +248,20 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error) } // NOTE: Validate codegen ////////////////////////////////////////////////////////////////////// - Dqn_CGenTableHeaderType const CHECK_COLUMN_LINKS[] = { - Dqn_CGenTableHeaderType_CppName, - Dqn_CGenTableHeaderType_CppType, - Dqn_CGenTableHeaderType_CppValue, - Dqn_CGenTableHeaderType_CppIsPtr, - Dqn_CGenTableHeaderType_CppArraySize, - Dqn_CGenTableHeaderType_CppArraySizeField, + DN_CGenTableHeaderType const CHECK_COLUMN_LINKS[] = { + DN_CGenTableHeaderType_CppName, + DN_CGenTableHeaderType_CppType, + DN_CGenTableHeaderType_CppValue, + DN_CGenTableHeaderType_CppIsPtr, + DN_CGenTableHeaderType_CppArraySize, + DN_CGenTableHeaderType_CppArraySizeField, }; result = true; - for (Dqn_CGenTable *table = cgen->first_table; table; table = table->next) { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - for (Dqn_CGenTableHeaderType check_column : CHECK_COLUMN_LINKS) { - Dqn_CGenTableColumn column = it.cgen_table_row->columns[table->column_indexes[check_column]]; + for (DN_CGenTable *table = cgen->first_table; table; table = table->next) { + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + for (DN_CGenTableHeaderType check_column : CHECK_COLUMN_LINKS) { + DN_CGenTableColumn column = it.cgen_table_row->columns[table->column_indexes[check_column]]; if (column.string.size == 0) { // NOTE: The code generation table did not bind a code generation parameter to // a column in the target table. We skip it. @@ -269,21 +269,21 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error) } // NOTE: Check if the column to bind to exists in the target table. - if (!MD_MapLookup(&it.table->headers_map, MD_MapKeyStr(Dqn_CGen_DqnToMDStr8(column.string)))) { + if (!MD_MapLookup(&it.table->headers_map, MD_MapKeyStr(DN_CGen_DNToMDStr8(column.string)))) { result = false; - Dqn_Str8 header_type_str8 = Dqn_CGen_TableHeaderTypeToDeclStr8(check_column); - Dqn_CGen_LogF(MD_MessageKind_Error, column.node, error, + DN_Str8 header_type_str8 = DN_CGen_TableHeaderTypeToDeclStr8(check_column); + DN_CGen_LogF(MD_MessageKind_Error, column.node, err, "Code generation table binds '%.*s' to '%.*s', but the column '%.*s' does not exist in table '%.*s'\n" "NOTE: If you want '%.*s' to omit the column '%.*s' you can bind to the empty string `` to skip it, otherwise, please ensure the table '%.*s' has the column '%.*s'" , - DQN_STR_FMT(column.string), - DQN_STR_FMT(header_type_str8), - DQN_STR_FMT(column.string), - DQN_STR_FMT(it.table->name), - DQN_STR_FMT(it.table->name), - DQN_STR_FMT(header_type_str8), - DQN_STR_FMT(it.table->name), - DQN_STR_FMT(header_type_str8)); + DN_STR_FMT(column.string), + DN_STR_FMT(header_type_str8), + DN_STR_FMT(column.string), + DN_STR_FMT(it.table->name), + DN_STR_FMT(it.table->name), + DN_STR_FMT(header_type_str8), + DN_STR_FMT(it.table->name), + DN_STR_FMT(header_type_str8)); } } } @@ -292,163 +292,163 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error) return result; } -DQN_API Dqn_CGen Dqn_CGen_InitFilesArgV(int argc, char const **argv, Dqn_ErrorSink *error) +DN_API DN_CGen DN_CGen_InitFilesArgV(int argc, char const **argv, DN_ErrSink *err) { - Dqn_CGen result = {}; + DN_CGen result = {}; result.arena = MD_ArenaAlloc(); result.file_list = MD_MakeList(result.arena); result.table_map = MD_MapMake(result.arena); bool has_error = false; - for (Dqn_isize arg_index = 0; arg_index < argc; arg_index++) { - MD_String8 file_name = MD_S8CString(DQN_CAST(char *)argv[arg_index]); + for (DN_ISize arg_index = 0; arg_index < argc; arg_index++) { + MD_String8 file_name = MD_S8CString(DN_CAST(char *)argv[arg_index]); MD_ParseResult parse_result = MD_ParseWholeFile(result.arena, file_name); for (MD_Message *message = parse_result.errors.first; message != 0; message = message->next) { has_error = true; - Dqn_CGen_LogF(message->kind, message->node, error, "%.*s", MD_S8VArg(message->string)); + DN_CGen_LogF(message->kind, message->node, err, "%.*s", MD_S8VArg(message->string)); } MD_PushNewReference(result.arena, result.file_list, parse_result.node); } if (!has_error) - Dqn_CGen_GatherTables_(&result, error); + DN_CGen_GatherTables_(&result, err); return result; } -DQN_API Dqn_Str8 Dqn_CGen_TableHeaderTypeToDeclStr8(Dqn_CGenTableHeaderType type) +DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8(DN_CGenTableHeaderType type) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; switch (type) { - case Dqn_CGenTableHeaderType_Name: result = DQN_STR8("name"); break; - case Dqn_CGenTableHeaderType_Table: result = DQN_STR8("table"); break; - case Dqn_CGenTableHeaderType_CppType: result = DQN_STR8("cpp_type"); break; - case Dqn_CGenTableHeaderType_CppName: result = DQN_STR8("cpp_name"); break; - case Dqn_CGenTableHeaderType_CppValue: result = DQN_STR8("cpp_value"); break; - case Dqn_CGenTableHeaderType_CppIsPtr: result = DQN_STR8("cpp_is_ptr"); break; - case Dqn_CGenTableHeaderType_CppOpEquals: result = DQN_STR8("cpp_op_equals"); break; - case Dqn_CGenTableHeaderType_CppArraySize: result = DQN_STR8("cpp_array_size"); break; - case Dqn_CGenTableHeaderType_CppArraySizeField: result = DQN_STR8("cpp_array_size_field"); break; - case Dqn_CGenTableHeaderType_CppLabel: result = DQN_STR8("cpp_label"); break; - case Dqn_CGenTableHeaderType_GenTypeInfo: result = DQN_STR8("gen_type_info"); break; - case Dqn_CGenTableHeaderType_GenEnumCount: result = DQN_STR8("gen_enum_count"); break; - case Dqn_CGenTableHeaderType_Count: result = DQN_STR8("XX BAD ENUM VALUE XX"); break; - default: result = DQN_STR8("XX INVALID ENUM VALUE XX"); break; + case DN_CGenTableHeaderType_Name: result = DN_STR8("name"); break; + case DN_CGenTableHeaderType_Table: result = DN_STR8("table"); break; + case DN_CGenTableHeaderType_CppType: result = DN_STR8("cpp_type"); break; + case DN_CGenTableHeaderType_CppName: result = DN_STR8("cpp_name"); break; + case DN_CGenTableHeaderType_CppValue: result = DN_STR8("cpp_value"); break; + case DN_CGenTableHeaderType_CppIsPtr: result = DN_STR8("cpp_is_ptr"); break; + case DN_CGenTableHeaderType_CppOpEquals: result = DN_STR8("cpp_op_equals"); break; + case DN_CGenTableHeaderType_CppArraySize: result = DN_STR8("cpp_array_size"); break; + case DN_CGenTableHeaderType_CppArraySizeField: result = DN_STR8("cpp_array_size_field"); break; + case DN_CGenTableHeaderType_CppLabel: result = DN_STR8("cpp_label"); break; + case DN_CGenTableHeaderType_GenTypeInfo: result = DN_STR8("gen_type_info"); break; + case DN_CGenTableHeaderType_GenEnumCount: result = DN_STR8("gen_enum_count"); break; + case DN_CGenTableHeaderType_Count: result = DN_STR8("XX BAD ENUM VALUE XX"); break; + default: result = DN_STR8("XX INVALID ENUM VALUE XX"); break; } return result; } -DQN_API Dqn_CGenMapNodeToEnum Dqn_CGen_MapNodeToEnumOrExit(MD_Node const *node, Dqn_CGenMapNodeToEnum const *valid_keys, Dqn_usize valid_keys_size, char const *fmt, ...) +DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_CGenMapNodeToEnum const *valid_keys, DN_USize valid_keys_size, char const *fmt, ...) { - Dqn_CGenMapNodeToEnum result = {}; - for (Dqn_usize index = 0; index < valid_keys_size; index++) { - Dqn_CGenMapNodeToEnum const *validator = valid_keys + index; - if (Dqn_Str8_Init(node->string.str, node->string.size) == validator->node_string) { + DN_CGenMapNodeToEnum result = {}; + for (DN_USize index = 0; index < valid_keys_size; index++) { + DN_CGenMapNodeToEnum const *validator = valid_keys + index; + if (DN_Str8_Init(node->string.str, node->string.size) == validator->node_string) { result = *validator; break; } } if (result.enum_val == 0) { - MD_CodeLoc loc = MD_CodeLocFromNode(DQN_CAST(MD_Node *)node); - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); + MD_CodeLoc loc = MD_CodeLocFromNode(DN_CAST(MD_Node *)node); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); va_list args; va_start(args, fmt); - Dqn_Str8 user_msg = Dqn_Str8_InitFV(tmem.arena, fmt, args); + DN_Str8 user_msg = DN_Str8_InitFV(tmem.arena, fmt, args); va_end(args); - Dqn_Str8Builder builder = {}; + DN_Str8Builder builder = {}; builder.arena = tmem.arena; - Dqn_Str8Builder_AddF(&builder, "%.*s: '%.*s' is not recognised, the supported values are ", DQN_STR_FMT(user_msg), MD_S8VArg(node->string)); - for (Dqn_usize index = 0; index < valid_keys_size; index++) { - Dqn_CGenMapNodeToEnum const *validator = valid_keys + index; - Dqn_Str8Builder_AddF(&builder, DQN_CAST(char *)"%s'%.*s'", index ? ", " : "", DQN_STR_FMT(validator->node_string)); + DN_Str8Builder_AppendF(&builder, "%.*s: '%.*s' is not recognised, the supported values are ", DN_STR_FMT(user_msg), MD_S8VArg(node->string)); + for (DN_USize index = 0; index < valid_keys_size; index++) { + DN_CGenMapNodeToEnum const *validator = valid_keys + index; + DN_Str8Builder_AppendF(&builder, DN_CAST(char *)"%s'%.*s'", index ? ", " : "", DN_STR_FMT(validator->node_string)); } - Dqn_Str8 error_msg = Dqn_Str8Builder_Build(&builder, tmem.arena); - MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Error, DQN_CAST(char *) "%.*s", DQN_STR_FMT(error_msg)); - Dqn_OS_Exit(DQN_CAST(uint32_t)-1); + DN_Str8 error_msg = DN_Str8Builder_Build(&builder, tmem.arena); + MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Error, DN_CAST(char *) "%.*s", DN_STR_FMT(error_msg)); + DN_OS_Exit(DN_CAST(uint32_t)-1); } return result; } -DQN_API Dqn_usize Dqn_CGen_NodeChildrenCount(MD_Node const *node) +DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node) { - Dqn_usize result = 0; + DN_USize result = 0; for (MD_EachNode(item, node->first_child)) result++; return result; } -DQN_API void Dqn_CGen_LogF(MD_MessageKind kind, MD_Node *node, Dqn_ErrorSink *error, char const *fmt, ...) +DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_ErrSink *err, char const *fmt, ...) { - if (!error) + if (!err) return; - Dqn_TLSTMem tmem = Dqn_TLS_PushTMem(nullptr); - Dqn_Str8Builder builder = Dqn_Str8Builder_Init_TLS(); + DN_TLSTMem tmem = DN_TLS_PushTMem(nullptr); + DN_Str8Builder builder = DN_Str8Builder_Init_TLS(); MD_String8 kind_string = MD_StringFromMessageKind(kind); MD_CodeLoc loc = MD_CodeLocFromNode(node); - Dqn_Str8Builder_AddF(&builder, "" MD_FmtCodeLoc " %.*s: ", MD_CodeLocVArg(loc), MD_S8VArg(kind_string)); + DN_Str8Builder_AppendF(&builder, "" MD_FmtCodeLoc " %.*s: ", MD_CodeLocVArg(loc), MD_S8VArg(kind_string)); va_list args; va_start(args, fmt); - Dqn_Str8Builder_AddFV(&builder, fmt, args); + DN_Str8Builder_AppendFV(&builder, fmt, args); va_end(args); - Dqn_Str8 msg = Dqn_Str8Builder_Build(&builder, tmem.arena); - Dqn_ErrorSink_MakeF(error, DQN_CAST(uint32_t)-1, "%.*s", DQN_STR_FMT(msg)); + DN_Str8 msg = DN_Str8Builder_Build(&builder, tmem.arena); + DN_ErrSink_AppendF(err, DN_CAST(uint32_t)-1, "%.*s", DN_STR_FMT(msg)); } -DQN_API bool Dqn_CGen_TableHasHeaders(Dqn_CGenTable const *table, Dqn_Str8 const *headers, Dqn_usize header_count, Dqn_ErrorSink *error) +DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_ErrSink *err) { bool result = true; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8Builder builder = {}; + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8Builder builder = {}; builder.arena = tmem.arena; - for (Dqn_usize index = 0; index < header_count; index++) { - Dqn_Str8 header = headers[index]; - MD_String8 header_md = {DQN_CAST(MD_u8 *) header.data, header.size}; - MD_MapSlot *slot = MD_MapLookup(DQN_CAST(MD_Map *)&table->headers_map, MD_MapKeyStr(header_md)); + for (DN_USize index = 0; index < header_count; index++) { + DN_Str8 header = headers[index]; + MD_String8 header_md = {DN_CAST(MD_u8 *) header.data, header.size}; + MD_MapSlot *slot = MD_MapLookup(DN_CAST(MD_Map *)&table->headers_map, MD_MapKeyStr(header_md)); if (!slot) { result = false; - Dqn_Str8Builder_AddF(&builder, "%s%.*s", builder.count ? ", " : "", DQN_STR_FMT(header)); + DN_Str8Builder_AppendF(&builder, "%s%.*s", builder.count ? ", " : "", DN_STR_FMT(header)); } } if (!result) { - Dqn_Str8 missing_headers = Dqn_Str8Builder_Build(&builder, tmem.arena); - Dqn_CGen_LogF(MD_MessageKind_Error, + DN_Str8 missing_headers = DN_Str8Builder_Build(&builder, tmem.arena); + DN_CGen_LogF(MD_MessageKind_Error, table->headers_node, - error, + err, "Table '%.*s' is missing the header(s): %.*s", - DQN_STR_FMT(table->name), - DQN_STR_FMT(missing_headers)); + DN_STR_FMT(table->name), + DN_STR_FMT(missing_headers)); } return result; } -DQN_API Dqn_CGenLookupColumnAtHeader Dqn_CGen_LookupColumnAtHeader(Dqn_CGenTable *table, Dqn_Str8 header, Dqn_CGenTableRow const *row) +DN_API DN_CGenLookupColumnAtHeader DN_CGen_LookupColumnAtHeader(DN_CGenTable *table, DN_Str8 header, DN_CGenTableRow const *row) { - Dqn_CGenLookupColumnAtHeader result = {}; + DN_CGenLookupColumnAtHeader result = {}; if (!table || !row) return result; - MD_String8 header_md = {DQN_CAST(MD_u8 *) header.data, header.size}; + MD_String8 header_md = {DN_CAST(MD_u8 *) header.data, header.size}; MD_MapSlot *slot = MD_MapLookup(&table->headers_map, MD_MapKeyStr(header_md)); if (!slot) return result; - Dqn_usize column_index = DQN_CAST(Dqn_usize) slot->val; - DQN_ASSERT(column_index < table->column_count); + DN_USize column_index = DN_CAST(DN_USize) slot->val; + DN_ASSERT(column_index < table->column_count); { - Dqn_usize begin = DQN_CAST(uintptr_t)(table->rows); - Dqn_usize end = DQN_CAST(uintptr_t)(table->rows + table->row_count); - Dqn_usize ptr = DQN_CAST(uintptr_t)row; - DQN_ASSERTF(ptr >= begin && ptr <= end, "The row to lookup does not belong to the table passed in"); + DN_USize begin = DN_CAST(uintptr_t)(table->rows); + DN_USize end = DN_CAST(uintptr_t)(table->rows + table->row_count); + DN_USize ptr = DN_CAST(uintptr_t)row; + DN_ASSERTF(ptr >= begin && ptr <= end, "The row to lookup does not belong to the table passed in"); } result.index = column_index; @@ -457,7 +457,7 @@ DQN_API Dqn_CGenLookupColumnAtHeader Dqn_CGen_LookupColumnAtHeader(Dqn_CGenTable return result; } -DQN_API bool Dqn_CGen_LookupNextTableInCodeGenTable(Dqn_CGen *cgen, Dqn_CGenTable *cgen_table, Dqn_CGenLookupTableIterator *it) +DN_API bool DN_CGen_LookupNextTableInCodeGenTable(DN_CGen *cgen, DN_CGenTable *cgen_table, DN_CGenLookupTableIterator *it) { if (!cgen_table) return false; @@ -465,7 +465,7 @@ DQN_API bool Dqn_CGen_LookupNextTableInCodeGenTable(Dqn_CGen *cgen, Dqn_CGenTabl if (it->row_index >= cgen_table->row_count) return false; - if (cgen_table->type != Dqn_CGenTableType_CodeGenEnum && cgen_table->type != Dqn_CGenTableType_CodeGenStruct && cgen_table->type != Dqn_CGenTableType_CodeGenBuiltinTypes) + if (cgen_table->type != DN_CGenTableType_CodeGenEnum && cgen_table->type != DN_CGenTableType_CodeGenStruct && cgen_table->type != DN_CGenTableType_CodeGenBuiltinTypes) return false; // NOTE: Lookup the table in this row that we will code generate from. Not @@ -473,39 +473,39 @@ DQN_API bool Dqn_CGen_LookupNextTableInCodeGenTable(Dqn_CGen *cgen, Dqn_CGenTabl // in-line into the code generation table itself. it->cgen_table = cgen_table; it->cgen_table_row = cgen_table->rows + it->row_index++; - if (cgen_table->type != Dqn_CGenTableType_CodeGenBuiltinTypes) { - Dqn_CGenTableColumn cgen_table_column = it->cgen_table_row->columns[cgen_table->column_indexes[Dqn_CGenTableHeaderType_Table]]; - MD_String8 key = {DQN_CAST(MD_u8 *)cgen_table_column.string.data, cgen_table_column.string.size}; + if (cgen_table->type != DN_CGenTableType_CodeGenBuiltinTypes) { + DN_CGenTableColumn cgen_table_column = it->cgen_table_row->columns[cgen_table->column_indexes[DN_CGenTableHeaderType_Table]]; + MD_String8 key = {DN_CAST(MD_u8 *)cgen_table_column.string.data, cgen_table_column.string.size}; MD_MapSlot *table_slot = MD_MapLookup(&cgen->table_map, MD_MapKeyStr(key)); if (!table_slot) { MD_CodeLoc loc = MD_CodeLocFromNode(cgen_table_column.node); MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Warning, - DQN_CAST(char *) "Code generation table references non-existent table '%.*s'", - DQN_STR_FMT(cgen_table_column.string)); + DN_CAST(char *) "Code generation table references non-existent table '%.*s'", + DN_STR_FMT(cgen_table_column.string)); return false; } - it->table = DQN_CAST(Dqn_CGenTable *) table_slot->val; + it->table = DN_CAST(DN_CGenTable *) table_slot->val; } - for (Dqn_usize type = 0; type < Dqn_CGenTableHeaderType_Count; type++) + for (DN_USize type = 0; type < DN_CGenTableHeaderType_Count; type++) it->cgen_table_column[type] = it->cgen_table_row->columns[cgen_table->column_indexes[type]]; return true; } -DQN_API bool Dqn_CGen_WillCodeGenTypeName(Dqn_CGen const *cgen, Dqn_Str8 name) +DN_API bool DN_CGen_WillCodeGenTypeName(DN_CGen const *cgen, DN_Str8 name) { - if (!Dqn_Str8_HasData(name)) + if (!DN_Str8_HasData(name)) return false; - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - if (table->type != Dqn_CGenTableType_CodeGenStruct && table->type != Dqn_CGenTableType_CodeGenEnum) + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + if (table->type != DN_CGenTableType_CodeGenStruct && table->type != DN_CGenTableType_CodeGenEnum) continue; - for (Dqn_usize row_index = 0; row_index < table->row_count; row_index++) { - Dqn_CGenTableRow const *row = table->rows + row_index; - Dqn_CGenTableColumn const *column = row->columns + table->column_indexes[Dqn_CGenTableHeaderType_Name]; + for (DN_USize row_index = 0; row_index < table->row_count; row_index++) { + DN_CGenTableRow const *row = table->rows + row_index; + DN_CGenTableColumn const *column = row->columns + table->column_indexes[DN_CGenTableHeaderType_Name]; if (column->string == name) return true; } @@ -514,481 +514,487 @@ DQN_API bool Dqn_CGen_WillCodeGenTypeName(Dqn_CGen const *cgen, Dqn_Str8 name) return false; } -static void Dqn_CGen_EmitRowWhitespace_(Dqn_CGenTableRow const *row, Dqn_CppFile *cpp) +static void DN_CGen_EmitRowWhitespace_(DN_CGenTableRow const *row, DN_CppFile *cpp) { - for (Dqn_CGenTableRowTag *tag = row->first_tag; tag; tag = tag->next) { + for (DN_CGenTableRowTag *tag = row->first_tag; tag; tag = tag->next) { switch (tag->type) { - case Dqn_CGenTableRowTagType_Nil: DQN_INVALID_CODE_PATH; + case DN_CGenTableRowTagType_Nil: DN_INVALID_CODE_PATH; - case Dqn_CGenTableRowTagType_CommentDivider: { + case DN_CGenTableRowTagType_CommentDivider: { if (tag->comment.size <= 0) break; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 prefix = Dqn_Str8_InitF(tmem.arena, "// NOTE: %.*s ", MD_S8VArg(tag->comment)); - int line_padding = DQN_MAX(100 - (DQN_CAST(int) prefix.size + (Dqn_CppSpacePerIndent(cpp) * cpp->indent)), 0); - Dqn_CppPrint(cpp, "%.*s", DQN_STR_FMT(prefix)); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 prefix = DN_Str8_InitF(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_STR_FMT(prefix)); for (int index = 0; index < line_padding; index++) - Dqn_CppAppend(cpp, "/"); - Dqn_CppAppend(cpp, "\n"); + DN_CppAppend(cpp, "/"); + DN_CppAppend(cpp, "\n"); } break; - case Dqn_CGenTableRowTagType_EmptyLine: { - Dqn_CppAppend(cpp, "\n"); + case DN_CGenTableRowTagType_EmptyLine: { + DN_CppAppend(cpp, "\n"); } break; } } } -Dqn_Str8 Dqn_CGen_StripQualifiersOnCppType_(Dqn_Arena *arena, Dqn_Str8 type) +DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); - Dqn_Str8 result = Dqn_Str8_TrimWhitespaceAround(type); - result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8("*"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, tmem.arena, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8("constexpr"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, tmem.arena, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8("const"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, tmem.arena, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8("static"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, tmem.arena, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8(" "), /*replace*/ DQN_STR8(""), /*start_index*/ 0, arena, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_TrimWhitespaceAround(result); + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str8 result = DN_Str8_TrimWhitespaceAround(type); + result = DN_Str8_Replace(result, /*find*/ DN_STR8("*"), /*replace*/ DN_STR8(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); + result = DN_Str8_Replace(result, /*find*/ DN_STR8("constexpr"), /*replace*/ DN_STR8(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); + result = DN_Str8_Replace(result, /*find*/ DN_STR8("const"), /*replace*/ DN_STR8(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); + result = DN_Str8_Replace(result, /*find*/ DN_STR8("static"), /*replace*/ DN_STR8(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); + result = DN_Str8_Replace(result, /*find*/ DN_STR8(" "), /*replace*/ DN_STR8(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); + result = DN_Str8_TrimWhitespaceAround(result); return result; } -DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_CppFile *cpp, Dqn_Str8 emit_prefix) +DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFile *cpp, DN_Str8 emit_prefix) { - if (emit & Dqn_CGenEmit_Prototypes) { + if (emit & DN_CGenEmit_Prototypes) { // NOTE: Generate type info enums ////////////////////////////////////////////////////////// - Dqn_CppEnumBlock(cpp, "%.*sType", DQN_STR_FMT(emit_prefix)) { - Dqn_CppLine(cpp, "%.*sType_Nil,", DQN_STR_FMT(emit_prefix)); - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) - Dqn_CppLine(cpp, "%.*sType_%.*s,", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string)); + DN_CppEnumBlock(cpp, "%.*sType", DN_STR_FMT(emit_prefix)) { + DN_CppLine(cpp, "%.*sType_Nil,", DN_STR_FMT(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_CppLine(cpp, "%.*sType_%.*s,", DN_STR_FMT(emit_prefix), DN_STR_FMT(it.cgen_table_column[DN_CGenTableHeaderType_Name].string)); } - Dqn_CppLine(cpp, "%.*sType_Count,", DQN_STR_FMT(emit_prefix)); + DN_CppLine(cpp, "%.*sType_Count,", DN_STR_FMT(emit_prefix)); } - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); // NOTE: Generate structs + enums ////////////////////////////////////////////////////////////// - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { switch (table->type) { - case Dqn_CGenTableType_Nil: DQN_INVALID_CODE_PATH; - case Dqn_CGenTableType_Count: DQN_INVALID_CODE_PATH; - case Dqn_CGenTableType_CodeGenBuiltinTypes: continue; - case Dqn_CGenTableType_Data: continue; + case DN_CGenTableType_Nil: DN_INVALID_CODE_PATH; + case DN_CGenTableType_Count: DN_INVALID_CODE_PATH; + case DN_CGenTableType_CodeGenBuiltinTypes: continue; + case DN_CGenTableType_Data: continue; - case Dqn_CGenTableType_CodeGenStruct: { + case DN_CGenTableType_CodeGenStruct: { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it); ) { + 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; - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_type = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppType].string, row); + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + 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); - Dqn_usize length = cpp_type.column.string.size; - Dqn_Str8 find_name = Dqn_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string); - if (Dqn_CGen_WillCodeGenTypeName(cgen, find_name)) + DN_USize length = cpp_type.column.string.size; + DN_Str8 find_name = DN_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string); + if (DN_CGen_WillCodeGenTypeName(cgen, find_name)) length += emit_prefix.size; - longest_type_name = DQN_MAX(longest_type_name, DQN_CAST(int)length); + longest_type_name = DN_MAX(longest_type_name, DN_CAST(int)length); } - Dqn_CppStructBlock(cpp, "%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string)) { - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row); - Dqn_CGenLookupColumnAtHeader cpp_type = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppType].string, row); - Dqn_CGenLookupColumnAtHeader cpp_array_size = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppArraySize].string, row); + DN_CppStructBlock(cpp, "%.*s%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(it.cgen_table_column[DN_CGenTableHeaderType_Name].string)) { + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + DN_CGenTableRow const *row = it.table->rows + row_index; + DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppName].string, row); + DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppType].string, row); + DN_CGenLookupColumnAtHeader cpp_array_size = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppArraySize].string, row); if (cpp_name.column.string.size <= 0 || cpp_type.column.string.size <= 0) continue; // NOTE: Generate cpp array size /////////////////////////////////// - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 array_size = {}; + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 array_size = {}; if (cpp_array_size.column.string.size) - array_size = Dqn_Str8_InitF(tmem.arena, "[%.*s]", DQN_STR_FMT(cpp_array_size.column.string)); + array_size = DN_Str8_InitF(tmem.arena, "[%.*s]", DN_STR_FMT(cpp_array_size.column.string)); // NOTE: Check if we're referencing a code generated type. If we // are, append the `emit_prefix` - Dqn_Str8 emit_cpp_type = cpp_type.column.string; + DN_Str8 emit_cpp_type = cpp_type.column.string; { - Dqn_Str8 find_name = Dqn_CGen_StripQualifiersOnCppType_(tmem.arena, emit_cpp_type); - if (Dqn_CGen_WillCodeGenTypeName(cgen, find_name)) - emit_cpp_type = Dqn_Str8_InitF(tmem.arena, "%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(cpp_type.column.string)); + DN_Str8 find_name = DN_CGen_StripQualifiersOnCppType_(tmem.arena, emit_cpp_type); + if (DN_CGen_WillCodeGenTypeName(cgen, find_name)) + emit_cpp_type = DN_Str8_InitF(tmem.arena, "%.*s%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(cpp_type.column.string)); } - int name_to_type_padding = 1 + longest_type_name - DQN_CAST(int) emit_cpp_type.size; + int name_to_type_padding = 1 + longest_type_name - DN_CAST(int) emit_cpp_type.size; // NOTE: Emit decl ///////////////////////////////////////////////// - Dqn_CGen_EmitRowWhitespace_(row, cpp); - Dqn_CppLine(cpp, + DN_CGen_EmitRowWhitespace_(row, cpp); + DN_CppLine(cpp, "%.*s%*s%.*s%.*s;", - DQN_STR_FMT(emit_cpp_type), + DN_STR_FMT(emit_cpp_type), name_to_type_padding, "", - DQN_STR_FMT(cpp_name.column.string), - DQN_STR_FMT(array_size)); + DN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(array_size)); } } - Dqn_CppNewLine(cpp); - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); + DN_CppNewLine(cpp); } } break; - case Dqn_CGenTableType_CodeGenEnum: { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it); ) { - Dqn_CppEnumBlock(cpp, "%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string)) { - Dqn_usize enum_count = 0; - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row); - Dqn_CGenLookupColumnAtHeader cpp_value = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppValue].string, row); + case DN_CGenTableType_CodeGenEnum: { + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it); ) { + DN_CppEnumBlock(cpp, "%.*s%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(it.cgen_table_column[DN_CGenTableHeaderType_Name].string)) { + DN_USize enum_count = 0; + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + DN_CGenTableRow const *row = it.table->rows + row_index; + DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppName].string, row); + DN_CGenLookupColumnAtHeader cpp_value = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppValue].string, row); if (cpp_name.column.string.size <= 0) continue; - Dqn_CGen_EmitRowWhitespace_(row, cpp); + DN_CGen_EmitRowWhitespace_(row, cpp); if (cpp_value.column.string.size) { - Dqn_CppLine(cpp, + DN_CppLine(cpp, "%.*s%.*s_%.*s = %.*s,", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string), - DQN_STR_FMT(cpp_name.column.string), - DQN_STR_FMT(cpp_value.column.string)); + DN_STR_FMT(emit_prefix), + DN_STR_FMT(it.cgen_table_column[DN_CGenTableHeaderType_Name].string), + DN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(cpp_value.column.string)); } else { - Dqn_CppLine(cpp, + DN_CppLine(cpp, "%.*s%.*s_%.*s = %zu,", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string), - DQN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(emit_prefix), + DN_STR_FMT(it.cgen_table_column[DN_CGenTableHeaderType_Name].string), + DN_STR_FMT(cpp_name.column.string), row_index); } enum_count++; } - Dqn_CGenTableColumn gen_enum_count_column = it.cgen_table_column[Dqn_CGenTableHeaderType_GenEnumCount]; + DN_CGenTableColumn gen_enum_count_column = it.cgen_table_column[DN_CGenTableHeaderType_GenEnumCount]; if (gen_enum_count_column.string.size) - Dqn_CppLine(cpp, + DN_CppLine(cpp, "%.*s%.*s_%.*s = %zu,", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string), - DQN_STR_FMT(gen_enum_count_column.string), + DN_STR_FMT(emit_prefix), + DN_STR_FMT(it.cgen_table_column[DN_CGenTableHeaderType_Name].string), + DN_STR_FMT(gen_enum_count_column.string), enum_count); } - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); } } break; } } // NOTE: Generate enums for struct fields ////////////////////////////////////////////////// - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { switch (table->type) { - case Dqn_CGenTableType_Nil: DQN_INVALID_CODE_PATH; - case Dqn_CGenTableType_Count: DQN_INVALID_CODE_PATH; - case Dqn_CGenTableType_Data: continue; - case Dqn_CGenTableType_CodeGenBuiltinTypes: continue; - case Dqn_CGenTableType_CodeGenEnum: continue; + case DN_CGenTableType_Nil: DN_INVALID_CODE_PATH; + case DN_CGenTableType_Count: DN_INVALID_CODE_PATH; + case DN_CGenTableType_Data: continue; + case DN_CGenTableType_CodeGenBuiltinTypes: continue; + case DN_CGenTableType_CodeGenEnum: continue; - case Dqn_CGenTableType_CodeGenStruct: { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it); ) { - Dqn_Str8 struct_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - Dqn_CppEnumBlock(cpp, "%.*s%.*sTypeField", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_name)) { - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row); + case DN_CGenTableType_CodeGenStruct: { + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it); ) { + DN_Str8 struct_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + DN_CppEnumBlock(cpp, "%.*s%.*sTypeField", DN_STR_FMT(emit_prefix), DN_STR_FMT(struct_name)) { + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + DN_CGenTableRow const *row = it.table->rows + row_index; + DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppName].string, row); if (cpp_name.column.string.size <= 0) continue; - Dqn_CGen_EmitRowWhitespace_(row, cpp); - Dqn_CppLine(cpp, "%.*s%.*sTypeField_%.*s,", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_name), DQN_STR_FMT(cpp_name.column.string)); + DN_CGen_EmitRowWhitespace_(row, cpp); + DN_CppLine(cpp, "%.*s%.*sTypeField_%.*s,", DN_STR_FMT(emit_prefix), DN_STR_FMT(struct_name), DN_STR_FMT(cpp_name.column.string)); } - Dqn_CppLine(cpp, "%.*s%.*sTypeField_Count,", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_name)); + DN_CppLine(cpp, "%.*s%.*sTypeField_Count,", DN_STR_FMT(emit_prefix), DN_STR_FMT(struct_name)); } - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); } } break; } } // NOTE: Str8 to enum conversion //////////////////////////////////////////////////////////// - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - if (table->type != Dqn_CGenTableType_CodeGenEnum) + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + if (table->type != DN_CGenTableType_CodeGenEnum) continue; - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - Dqn_CppStructBlock(cpp, "%.*s%.*sStr8ToEnumResult", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)) { - Dqn_CppLine(cpp, "bool success;"); - Dqn_CppLine(cpp, "%.*s%.*s value;", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)); + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + DN_CppStructBlock(cpp, "%.*s%.*sStr8ToEnumResult", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)) { + DN_CppLine(cpp, "bool success;"); + DN_CppLine(cpp, "%.*s%.*s value;", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); } - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); } } - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - if (table->type != Dqn_CGenTableType_CodeGenEnum) + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + if (table->type != DN_CGenTableType_CodeGenEnum) continue; - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - Dqn_CppLine(cpp, - "%.*s%.*sStr8ToEnumResult %.*s%.*s_Str8ToEnum(Dqn_Str8 string);", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(type_name), - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(type_name)); + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + DN_CppLine(cpp, + "%.*s%.*sStr8ToEnumResult %.*s%.*s_NameStr8ToEnum(DN_Str8 string);", + DN_STR_FMT(emit_prefix), + DN_STR_FMT(type_name), + DN_STR_FMT(emit_prefix), + DN_STR_FMT(type_name)); + DN_CppLine(cpp, + "%.*s%.*sStr8ToEnumResult %.*s%.*s_LabelStr8ToEnum(DN_Str8 string);", + DN_STR_FMT(emit_prefix), + DN_STR_FMT(type_name), + DN_STR_FMT(emit_prefix), + DN_STR_FMT(type_name)); } } // NOTE: Operator == and != //////////////////////////////////////////////////////////////// - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - if (table->type != Dqn_CGenTableType_CodeGenStruct) + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + if (table->type != DN_CGenTableType_CodeGenStruct) continue; - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - Dqn_Str8 cpp_op_equals = it.cgen_table_column[Dqn_CGenTableHeaderType_CppOpEquals].string; - if (cpp_op_equals != DQN_STR8("true")) + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + DN_Str8 cpp_op_equals = it.cgen_table_column[DN_CGenTableHeaderType_CppOpEquals].string; + if (cpp_op_equals != DN_STR8("true")) continue; - Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - Dqn_CppLine(cpp, + DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + DN_CppLine(cpp, "bool operator==(%.*s%.*s const &lhs, %.*s%.*s const &rhs);", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(type_name), - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(type_name)); - Dqn_CppLine(cpp, + DN_STR_FMT(emit_prefix), + DN_STR_FMT(type_name), + DN_STR_FMT(emit_prefix), + DN_STR_FMT(type_name)); + DN_CppLine(cpp, "bool operator!=(%.*s%.*s const &lhs, %.*s%.*s const &rhs);", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(type_name), - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(type_name)); + DN_STR_FMT(emit_prefix), + DN_STR_FMT(type_name), + DN_STR_FMT(emit_prefix), + DN_STR_FMT(type_name)); } } } - if (emit & Dqn_CGenEmit_Implementation) { + if (emit & DN_CGenEmit_Implementation) { // NOTE: Generate type info //////////////////////////////////////////////////////////////////// - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - if (table->type == Dqn_CGenTableType_CodeGenBuiltinTypes) + if (table->type == DN_CGenTableType_CodeGenBuiltinTypes) continue; - Dqn_Str8 struct_or_enum_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - Dqn_CppBlock(cpp, ";\n\n", "Dqn_TypeField const g_%.*s%.*s_type_fields[] =", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_or_enum_name)) { - if (table->type == Dqn_CGenTableType_CodeGenStruct) { + DN_Str8 struct_or_enum_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + DN_CppBlock(cpp, ";\n\n", "DN_TypeField const g_%.*s%.*s_type_fields[] =", DN_STR_FMT(emit_prefix), DN_STR_FMT(struct_or_enum_name)) { + if (table->type == DN_CGenTableType_CodeGenStruct) { // NOTE: Construct the cpp type string first. We will prepend `emit_prefix` // 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. - Dqn_TLSTMem tmem = Dqn_TLS_PushTMem(nullptr); - Dqn_usize longest_cpp_type_name = 0; - auto cpp_type_list = Dqn_SArray_Init(tmem.arena, it.table->row_count, Dqn_ZeroMem_Yes); + DN_TLSTMem tmem = DN_TLS_PushTMem(nullptr); + DN_USize longest_cpp_type_name = 0; + auto cpp_type_list = DN_SArray_Init(tmem.arena, it.table->row_count, DN_ZeroMem_Yes); - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_type = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppType].string, row); - Dqn_Str8 cpp_type_name = Dqn_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string); - if (Dqn_CGen_WillCodeGenTypeName(cgen, cpp_type_name)) - cpp_type_name = Dqn_Str8_InitF_TLS("%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(cpp_type_name)); + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + 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); + 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_Str8_InitF_TLS("%.*s%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(cpp_type_name)); - longest_cpp_type_name = DQN_MAX(longest_cpp_type_name, cpp_type_name.size); - Dqn_SArray_Add(&cpp_type_list, cpp_type_name); + longest_cpp_type_name = DN_MAX(longest_cpp_type_name, cpp_type_name.size); + DN_SArray_Add(&cpp_type_list, cpp_type_name); } // NOTE: Iterate each row and emit the C++ declarations //////////////////// - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row); - Dqn_CGenLookupColumnAtHeader cpp_type = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppType].string, row); - Dqn_CGenLookupColumnAtHeader cpp_is_ptr = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppIsPtr].string, row); - Dqn_CGenLookupColumnAtHeader cpp_array_size = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppArraySize].string, row); - Dqn_CGenLookupColumnAtHeader cpp_array_size_field = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppArraySizeField].string, row); - Dqn_CGenLookupColumnAtHeader cpp_label = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppLabel].string, row); + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + DN_CGenTableRow const *row = it.table->rows + row_index; + DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppName].string, row); + DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppType].string, row); + DN_CGenLookupColumnAtHeader cpp_is_ptr = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppIsPtr].string, row); + DN_CGenLookupColumnAtHeader cpp_array_size = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppArraySize].string, row); + DN_CGenLookupColumnAtHeader cpp_array_size_field = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppArraySizeField].string, row); + DN_CGenLookupColumnAtHeader cpp_label = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppLabel].string, row); - bool cpp_is_ptr_b32 = cpp_is_ptr.column.string == DQN_STR8("true"); - Dqn_Str8 cpp_array_size_str8 = Dqn_Str8_HasData(cpp_array_size.column.string) ? cpp_array_size.column.string : DQN_STR8("0"); + bool cpp_is_ptr_b32 = cpp_is_ptr.column.string == DN_STR8("true"); + DN_Str8 cpp_array_size_str8 = DN_Str8_HasData(cpp_array_size.column.string) ? cpp_array_size.column.string : DN_STR8("0"); - Dqn_CGenTableColumn struct_name = it.cgen_table_row->columns[table->column_indexes[Dqn_CGenTableHeaderType_Name]]; - Dqn_Str8 cpp_array_size_field_str8 = DQN_STR8("NULL"); + DN_CGenTableColumn struct_name = it.cgen_table_row->columns[table->column_indexes[DN_CGenTableHeaderType_Name]]; + DN_Str8 cpp_array_size_field_str8 = DN_STR8("NULL"); if (cpp_array_size_field.column.string.size) { // TODO(doyle): Check that array_size_field references a valid field in the table // NOTE: We use a raw index for the reference because the struct might // not have type info being generated so we can't rely on the enum. - Dqn_usize index_the_field_references = 0; - for (Dqn_usize sub_row_index = 0; sub_row_index < it.table->row_count; sub_row_index++) { - Dqn_CGenTableRow const *sub_row = it.table->rows + sub_row_index; - Dqn_CGenTableColumn sub_cpp_name = sub_row->columns[cpp_name.index]; + DN_USize index_the_field_references = 0; + for (DN_USize sub_row_index = 0; sub_row_index < it.table->row_count; sub_row_index++) { + DN_CGenTableRow const *sub_row = it.table->rows + sub_row_index; + DN_CGenTableColumn sub_cpp_name = sub_row->columns[cpp_name.index]; if (sub_cpp_name.string == cpp_array_size_field.column.string) index_the_field_references = sub_row_index; } cpp_array_size_field_str8 = - Dqn_Str8_InitF_TLS("&g_%.*s%.*s_type_fields[%zu]", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(struct_name.string), + DN_Str8_InitF_TLS("&g_%.*s%.*s_type_fields[%zu]", + DN_STR_FMT(emit_prefix), + DN_STR_FMT(struct_name.string), index_the_field_references); } - Dqn_Str8 cpp_type_name = cpp_type_list.data[row_index]; - Dqn_Str8 orig_cpp_type = Dqn_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string); + DN_Str8 cpp_type_name = cpp_type_list.data[row_index]; + DN_Str8 orig_cpp_type = DN_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string); - Dqn_usize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; - Dqn_usize cpp_type_padding = 1 + longest_cpp_type_name - cpp_type_name.size; + 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; - Dqn_Str8 cpp_type_enum = Dqn_Str8_InitF_TLS("%.*sType_%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(orig_cpp_type)); - Dqn_usize cpp_type_enum_padding = cpp_type_padding + (orig_cpp_type.size - cpp_type_name.size); + DN_Str8 cpp_type_enum = DN_Str8_InitF_TLS("%.*sType_%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(orig_cpp_type)); + DN_USize cpp_type_enum_padding = cpp_type_padding + (orig_cpp_type.size - cpp_type_name.size); - Dqn_Str8 cpp_label_str8 = cpp_name.column.string; - Dqn_usize cpp_label_str8_padding = cpp_name_padding; + DN_Str8 cpp_label_str8 = cpp_name.column.string; + DN_USize cpp_label_str8_padding = cpp_name_padding; if (cpp_label.column.string.size) { cpp_label_str8 = cpp_label.column.string; cpp_label_str8_padding = 1 + it.table->headers[cpp_label.index].longest_string - cpp_label.column.string.size; } - Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena); + DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena); // NOTE: row - Dqn_Str8Builder_AddF(&builder, "{%2d, ", row_index); + DN_Str8Builder_AppendF(&builder, "{%2d, ", row_index); // NOTE: name - Dqn_Str8Builder_AddF(&builder, - "DQN_STR8(\"%.*s\"),%*s", - DQN_STR_FMT(cpp_name.column.string), + DN_Str8Builder_AppendF(&builder, + "DN_STR8(\"%.*s\"),%*s", + DN_STR_FMT(cpp_name.column.string), cpp_name_padding, ""); // NOTE: label - Dqn_Str8Builder_AddF(&builder, - "DQN_STR8(\"%.*s\"),%*s", - DQN_STR_FMT(cpp_label_str8), + DN_Str8Builder_AppendF(&builder, + "DN_STR8(\"%.*s\"),%*s", + DN_STR_FMT(cpp_label_str8), cpp_label_str8_padding, ""); // NOTE: value - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "/*value*/ 0, "); // NOTE: offsetof(a, b) - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "offsetof(%.*s%.*s, %.*s),%*s", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(struct_or_enum_name), - DQN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(emit_prefix), + DN_STR_FMT(struct_or_enum_name), + DN_STR_FMT(cpp_name.column.string), cpp_name_padding, ""); // NOTE: sizeof(a->b) - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "sizeof(((%.*s%.*s*)0)->%.*s),%*s", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(struct_or_enum_name), - DQN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(emit_prefix), + DN_STR_FMT(struct_or_enum_name), + DN_STR_FMT(cpp_name.column.string), cpp_name_padding, ""); // NOTE: alignof(a) - if (cpp_type_name == DQN_STR8("void")) { - Dqn_Str8 proxy_type = DQN_STR8("char"); - Dqn_usize proxy_type_padding = 1 + longest_cpp_type_name - proxy_type.size; - Dqn_Str8Builder_AddF(&builder, "alignof(%.*s),%*s", DQN_STR_FMT(proxy_type), proxy_type_padding, ""); + if (cpp_type_name == DN_STR8("void")) { + DN_Str8 proxy_type = DN_STR8("char"); + DN_USize proxy_type_padding = 1 + longest_cpp_type_name - proxy_type.size; + DN_Str8Builder_AppendF(&builder, "alignof(%.*s),%*s", DN_STR_FMT(proxy_type), proxy_type_padding, ""); } else { - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "alignof(%.*s),%*s", - DQN_STR_FMT(cpp_type_name), + DN_STR_FMT(cpp_type_name), cpp_type_padding, ""); } // NOTE: Type string - Dqn_Str8Builder_AddF(&builder, - "DQN_STR8(\"%.*s\"),%*s", - DQN_STR_FMT(cpp_type_name), + DN_Str8Builder_AppendF(&builder, + "DN_STR8(\"%.*s\"),%*s", + DN_STR_FMT(cpp_type_name), cpp_type_padding, ""); // NOTE: Type as enum - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "%.*s,%*s", - DQN_STR_FMT(cpp_type_enum), + DN_STR_FMT(cpp_type_enum), cpp_type_enum_padding, ""); - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "/*is_pointer*/ %s,%s /*array_size*/ %.*s, /*array_size_field*/ %.*s},", cpp_is_ptr_b32 ? "true" : "false", cpp_is_ptr_b32 ? " " : "", - DQN_STR_FMT(cpp_array_size_str8), - DQN_STR_FMT(cpp_array_size_field_str8)); + DN_STR_FMT(cpp_array_size_str8), + DN_STR_FMT(cpp_array_size_field_str8)); - Dqn_Str8 line = Dqn_Str8Builder_Build(&builder, tmem.arena); - Dqn_CppLine(cpp, "%.*s", DQN_STR_FMT(line)); + DN_Str8 line = DN_Str8Builder_Build(&builder, tmem.arena); + DN_CppLine(cpp, "%.*s", DN_STR_FMT(line)); } } else { - DQN_ASSERT(table->type == Dqn_CGenTableType_CodeGenEnum); - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row); - Dqn_CGenLookupColumnAtHeader cpp_value = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppValue].string, row); - Dqn_CGenLookupColumnAtHeader cpp_label = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppLabel].string, row); + DN_ASSERT(table->type == DN_CGenTableType_CodeGenEnum); + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + DN_CGenTableRow const *row = it.table->rows + row_index; + DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppName].string, row); + DN_CGenLookupColumnAtHeader cpp_value = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppValue].string, row); + DN_CGenLookupColumnAtHeader cpp_label = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppLabel].string, row); if (cpp_name.column.string.size <= 0) continue; - Dqn_TLSTMem tmem = Dqn_TLS_PushTMem(nullptr); - Dqn_usize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; - Dqn_Str8 cpp_value_str8 = Dqn_Str8_HasData(cpp_value.column.string) ? cpp_value.column.string : Dqn_Str8_InitF_TLS("%zu", row_index); - Dqn_Str8 cpp_type_enum = Dqn_Str8_InitF_TLS("%.*sType_%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_or_enum_name)); + DN_TLSTMem tmem = DN_TLS_PushTMem(nullptr); + DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; + DN_Str8 cpp_value_str8 = DN_Str8_HasData(cpp_value.column.string) ? cpp_value.column.string : DN_Str8_InitF_TLS("%zu", row_index); + DN_Str8 cpp_type_enum = DN_Str8_InitF_TLS("%.*sType_%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(struct_or_enum_name)); - Dqn_Str8 cpp_label_str8 = cpp_name.column.string; - Dqn_usize cpp_label_str8_padding = cpp_name_padding; + DN_Str8 cpp_label_str8 = cpp_name.column.string; + DN_USize cpp_label_str8_padding = cpp_name_padding; if (cpp_label.column.string.size) { cpp_label_str8 = cpp_label.column.string; cpp_label_str8_padding = 1 + it.table->headers[cpp_label.index].longest_string - cpp_label.column.string.size; } - Dqn_Str8Builder builder = Dqn_Str8Builder_Init_TLS(); + DN_Str8Builder builder = DN_Str8Builder_Init_TLS(); // NOTE: row - Dqn_Str8Builder_AddF(&builder, "{%2d, ", row_index); + DN_Str8Builder_AppendF(&builder, "{%2d, ", row_index); // NOTE: name - Dqn_Str8Builder_AddF(&builder, - "DQN_STR8(\"%.*s\"),%*s", - DQN_STR_FMT(cpp_name.column.string), + DN_Str8Builder_AppendF(&builder, + "DN_STR8(\"%.*s\"),%*s", + DN_STR_FMT(cpp_name.column.string), cpp_name_padding, ""); // NOTE: label - Dqn_Str8Builder_AddF(&builder, - "DQN_STR8(\"%.*s\"),%*s", - DQN_STR_FMT(cpp_label_str8), + DN_Str8Builder_AppendF(&builder, + "DN_STR8(\"%.*s\"),%*s", + DN_STR_FMT(cpp_label_str8), cpp_label_str8_padding, ""); // NOTE: value - Dqn_Str8Builder_AddF(&builder, "/*value*/ %.*s, ", DQN_STR_FMT(cpp_value_str8)); + DN_Str8Builder_AppendF(&builder, "/*value*/ %.*s, ", DN_STR_FMT(cpp_value_str8)); // NOTE: offsetof(a, b) - Dqn_Str8Builder_AddF(&builder, "/*offsetof*/ 0, "); + DN_Str8Builder_AppendF(&builder, "/*offsetof*/ 0, "); // NOTE: sizeof(a->b) - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "sizeof(%.*s%.*s), ", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(struct_or_enum_name)); + DN_STR_FMT(emit_prefix), + DN_STR_FMT(struct_or_enum_name)); // NOTE: alignof(a->b) - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "alignof(%.*s%.*s), ", - DQN_STR_FMT(emit_prefix), - DQN_STR_FMT(struct_or_enum_name)); + DN_STR_FMT(emit_prefix), + DN_STR_FMT(struct_or_enum_name)); // TODO: Type string - Dqn_Str8Builder_AddF(&builder, "DQN_STR8(\"\"), "); + DN_Str8Builder_AppendF(&builder, "DN_STR8(\"\"), "); // NOTE: Type as enum - Dqn_Str8Builder_AddF(&builder, "%.*s, ", DQN_STR_FMT(cpp_type_enum)); + DN_Str8Builder_AppendF(&builder, "%.*s, ", DN_STR_FMT(cpp_type_enum)); - Dqn_Str8Builder_AddF(&builder, "/*is_pointer*/ false, "); - Dqn_Str8Builder_AddF(&builder, "/*array_size*/ 0, "); - Dqn_Str8Builder_AddF(&builder, "/*array_size_field*/ NULL},"); + DN_Str8Builder_AppendF(&builder, "/*is_pointer*/ false, "); + DN_Str8Builder_AppendF(&builder, "/*array_size*/ 0, "); + DN_Str8Builder_AppendF(&builder, "/*array_size_field*/ NULL},"); - Dqn_Str8 line = Dqn_Str8Builder_Build_TLS(&builder); - Dqn_CppLine(cpp, "%.*s", DQN_STR_FMT(line)); + DN_Str8 line = DN_Str8Builder_Build_TLS(&builder); + DN_CppLine(cpp, "%.*s", DN_STR_FMT(line)); } } } @@ -996,221 +1002,236 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C } int longest_name_across_all_tables = 0; - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - if (Dqn_CGen_WillCodeGenTypeName(cgen, type_name)) - type_name = Dqn_Str8_InitF(tmem.arena, "%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) + type_name = DN_Str8_InitF(tmem.arena, "%.*s%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); - longest_name_across_all_tables = DQN_MAX(longest_name_across_all_tables, DQN_CAST(int)type_name.size); + longest_name_across_all_tables = DN_MAX(longest_name_across_all_tables, DN_CAST(int)type_name.size); } } - Dqn_CppBlock(cpp, ";\n\n", "Dqn_TypeInfo const g_%.*stypes[] =", DQN_STR_FMT(emit_prefix)) { - Dqn_CppLine(cpp, "{DQN_STR8(\"\"),%*sDqn_TypeKind_Nil, 0, /*fields*/ NULL, /*count*/ 0},", 1 + longest_name_across_all_tables, ""); + DN_CppBlock(cpp, ";\n\n", "DN_TypeInfo const g_%.*stypes[] =", DN_STR_FMT(emit_prefix)) { + DN_CppLine(cpp, "{DN_STR8(\"\"),%*sDN_TypeKind_Nil, 0, /*fields*/ NULL, /*count*/ 0},", 1 + longest_name_across_all_tables, ""); - Dqn_usize longest_type_name = 0; - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - if (Dqn_CGen_WillCodeGenTypeName(cgen, type_name)) - type_name = Dqn_Str8_InitF(tmem.arena, "%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)); - longest_type_name = DQN_MAX(longest_type_name, type_name.size); + 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_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) + type_name = DN_Str8_InitF(tmem.arena, "%.*s%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); + longest_type_name = DN_MAX(longest_type_name, type_name.size); } } - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - Dqn_TLSTMem tmem = Dqn_TLS_PushTMem(nullptr); - Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - if (Dqn_CGen_WillCodeGenTypeName(cgen, type_name)) - type_name = Dqn_Str8_InitF_TLS("%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)); + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + DN_TLSTMem tmem = DN_TLS_PushTMem(nullptr); + DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) + type_name = DN_Str8_InitF_TLS("%.*s%.*s", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); - int name_padding = 1 + longest_name_across_all_tables - DQN_CAST(int) type_name.size; - Dqn_Str8 type_info_kind = {}; + int name_padding = 1 + longest_name_across_all_tables - DN_CAST(int) type_name.size; + DN_Str8 type_info_kind = {}; char const *type_info_kind_padding = ""; - if (table->type == Dqn_CGenTableType_CodeGenEnum) { - type_info_kind = DQN_STR8("Dqn_TypeKind_Enum"); + if (table->type == DN_CGenTableType_CodeGenEnum) { + type_info_kind = DN_STR8("DN_TypeKind_Enum"); type_info_kind_padding = " "; - } else if (table->type == Dqn_CGenTableType_CodeGenStruct) { - type_info_kind = DQN_STR8("Dqn_TypeKind_Struct"); + } else if (table->type == DN_CGenTableType_CodeGenStruct) { + type_info_kind = DN_STR8("DN_TypeKind_Struct"); } else { - DQN_ASSERT(table->type == Dqn_CGenTableType_CodeGenBuiltinTypes); - type_info_kind = DQN_STR8("Dqn_TypeKind_Basic"); + DN_ASSERT(table->type == DN_CGenTableType_CodeGenBuiltinTypes); + type_info_kind = DN_STR8("DN_TypeKind_Basic"); type_info_kind_padding = " "; } - Dqn_Str8 fields_count = {}; - if (table->type == Dqn_CGenTableType_CodeGenBuiltinTypes) { - fields_count = DQN_STR8("0"); + DN_Str8 fields_count = {}; + if (table->type == DN_CGenTableType_CodeGenBuiltinTypes) { + fields_count = DN_STR8("0"); } else { - DQN_ASSERT(table->type == Dqn_CGenTableType_CodeGenStruct || table->type == Dqn_CGenTableType_CodeGenEnum); + DN_ASSERT(table->type == DN_CGenTableType_CodeGenStruct || table->type == DN_CGenTableType_CodeGenEnum); int fields_count_int = 0; - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row); - fields_count_int += Dqn_Str8_HasData(cpp_name.column.string); + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + DN_CGenTableRow const *row = it.table->rows + row_index; + DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppName].string, row); + fields_count_int += DN_Str8_HasData(cpp_name.column.string); } - fields_count = Dqn_Str8_InitF_TLS("%d", fields_count_int); + fields_count = DN_Str8_InitF_TLS("%d", fields_count_int); } - Dqn_Str8 fields = DQN_STR8("NULL"); + DN_Str8 fields = DN_STR8("NULL"); int fields_padding = 1; - if (table->type != Dqn_CGenTableType_CodeGenBuiltinTypes) { + if (table->type != DN_CGenTableType_CodeGenBuiltinTypes) { fields_padding = name_padding; - fields = Dqn_Str8_InitF(tmem.arena, "g_%.*s_type_fields", DQN_STR_FMT(type_name)); + fields = DN_Str8_InitF(tmem.arena, "g_%.*s_type_fields", DN_STR_FMT(type_name)); } - Dqn_Str8Builder builder = Dqn_Str8Builder_Init_TLS(); + DN_Str8Builder builder = DN_Str8Builder_Init_TLS(); // NOTE: name - Dqn_Str8Builder_AddF(&builder, - "{DQN_STR8(\"%.*s\"),%*s", - DQN_STR_FMT(type_name), + DN_Str8Builder_AppendF(&builder, + "{DN_STR8(\"%.*s\"),%*s", + DN_STR_FMT(type_name), name_padding, ""); - // NOTE: Dqn_TypeKind_{Nil|Basic|Enum|Struct} - Dqn_Str8Builder_AddF(&builder, + // NOTE: DN_TypeKind_{Nil|Basic|Enum|Struct} + DN_Str8Builder_AppendF(&builder, "%.*s,%s", - DQN_STR_FMT(type_info_kind), + DN_STR_FMT(type_info_kind), type_info_kind_padding); // NOTE: sizeof(T) - if (type_name == DQN_STR8("void")) { - Dqn_Str8Builder_AddF(&builder, "0,%*s", name_padding, ""); + if (type_name == DN_STR8("void")) { + DN_Str8Builder_AppendF(&builder, "0,%*s", name_padding, ""); } else { - Dqn_Str8Builder_AddF(&builder, + DN_Str8Builder_AppendF(&builder, "sizeof(%.*s),%*s", - DQN_STR_FMT(type_name), + DN_STR_FMT(type_name), name_padding, ""); } - // NOTE: Pointer to Dqn_TypeField[] - Dqn_Str8Builder_AddF(&builder, + // NOTE: Pointer to DN_TypeField[] + DN_Str8Builder_AppendF(&builder, "/*fields*/ %.*s,%*s", - DQN_STR_FMT(fields), + DN_STR_FMT(fields), fields_padding, ""); - // NOTE: Dqn_TypeField length - Dqn_Str8Builder_AddF(&builder, + // NOTE: DN_TypeField length + DN_Str8Builder_AppendF(&builder, "/*count*/ %.*s},", - DQN_STR_FMT(fields_count)); + DN_STR_FMT(fields_count)); - Dqn_Str8 line = Dqn_Str8Builder_Build_TLS(&builder); - Dqn_CppLine(cpp, "%.*s", DQN_STR_FMT(line)); + DN_Str8 line = DN_Str8Builder_Build_TLS(&builder); + DN_CppLine(cpp, "%.*s", DN_STR_FMT(line)); } } } // NOTE: Str8 to enum conversion //////////////////////////////////////////////////////////// - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - if (table->type != Dqn_CGenTableType_CodeGenEnum) + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + if (table->type != DN_CGenTableType_CodeGenEnum) continue; - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; - Dqn_CppFuncBlock(cpp, "%.*s%.*sStr8ToEnumResult %.*s%.*s_Str8ToEnum(Dqn_Str8 string)", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name), DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)) { - Dqn_CppLine(cpp, "%.*s%.*sStr8ToEnumResult result = {};", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)); - Dqn_CppForBlock(cpp, "Dqn_usize index = 0; !result.success && index < DQN_ARRAY_UCOUNT(g_%.*s%.*s_type_fields); index++", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)) { - Dqn_CppIfChain(cpp) { - Dqn_CppLine(cpp, "Dqn_TypeField field = g_%.*s%.*s_type_fields[index];", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)); - Dqn_CppIfOrElseIfBlock(cpp, "string == field.name") { - Dqn_CppLine(cpp, "result.success = true;"); - Dqn_CppLine(cpp, "result.value = (%.*s%.*s)index;", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)); + DN_CppFuncBlock(cpp, "%.*s%.*sStr8ToEnumResult %.*s%.*s_NameStr8ToEnum(DN_Str8 string)", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name), DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)) { + DN_CppLine(cpp, "%.*s%.*sStr8ToEnumResult result = {};", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); + DN_CppForBlock(cpp, "DN_USize index = 0; !result.success && index < DN_ARRAY_UCOUNT(g_%.*s%.*s_type_fields); index++", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)) { + DN_CppIfChain(cpp) { + DN_CppLine(cpp, "DN_TypeField field = g_%.*s%.*s_type_fields[index];", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); + DN_CppIfOrElseIfBlock(cpp, "DN_Str8_EqInsensitive(string, field.name)") { + DN_CppLine(cpp, "result.success = true;"); + DN_CppLine(cpp, "result.value = (%.*s%.*s)index;", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); } } } - Dqn_CppLine(cpp, "return result;"); + DN_CppLine(cpp, "return result;"); } - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); + + DN_CppFuncBlock(cpp, "%.*s%.*sStr8ToEnumResult %.*s%.*s_LabelStr8ToEnum(DN_Str8 string)", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name), DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)) { + DN_CppLine(cpp, "%.*s%.*sStr8ToEnumResult result = {};", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); + DN_CppForBlock(cpp, "DN_USize index = 0; !result.success && index < DN_ARRAY_UCOUNT(g_%.*s%.*s_type_fields); index++", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)) { + DN_CppIfChain(cpp) { + DN_CppLine(cpp, "DN_TypeField field = g_%.*s%.*s_type_fields[index];", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); + DN_CppIfOrElseIfBlock(cpp, "DN_Str8_EqInsensitive(string, field.label)") { + DN_CppLine(cpp, "result.success = true;"); + DN_CppLine(cpp, "result.value = (%.*s%.*s)index;", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)); + } + } + } + DN_CppLine(cpp, "return result;"); + } + DN_CppNewLine(cpp); } } // NOTE: Operator == and != //////////////////////////////////////////////////////////////// - for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { - if (table->type != Dqn_CGenTableType_CodeGenStruct) + for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { + if (table->type != DN_CGenTableType_CodeGenStruct) continue; - for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { - Dqn_Str8 cpp_op_equals = it.cgen_table_column[Dqn_CGenTableHeaderType_CppOpEquals].string; - if (cpp_op_equals != DQN_STR8("true")) + for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { + DN_Str8 cpp_op_equals = it.cgen_table_column[DN_CGenTableHeaderType_CppOpEquals].string; + if (cpp_op_equals != DN_STR8("true")) continue; - Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; - Dqn_CppFuncBlock(cpp, "bool operator==(%.*s%.*s const &lhs, %.*s%.*s const &rhs)", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name), DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)) { - for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) { - Dqn_CGenTableRow const *row = it.table->rows + row_index; - Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row); - Dqn_CGenLookupColumnAtHeader cpp_is_ptr = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppIsPtr].string, row); - Dqn_CGenLookupColumnAtHeader cpp_array_size = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppArraySize].string, row); - Dqn_CGenLookupColumnAtHeader cpp_array_size_field = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppArraySizeField].string, row); + DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; + DN_CppFuncBlock(cpp, "bool operator==(%.*s%.*s const &lhs, %.*s%.*s const &rhs)", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name), DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)) { + for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { + DN_CGenTableRow const *row = it.table->rows + row_index; + DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppName].string, row); + DN_CGenLookupColumnAtHeader cpp_is_ptr = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppIsPtr].string, row); + DN_CGenLookupColumnAtHeader cpp_array_size = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppArraySize].string, row); + DN_CGenLookupColumnAtHeader cpp_array_size_field = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppArraySizeField].string, row); // TODO(doyle): Check if we're an integral type or not to double check if we // can use memcmp or operator== - if (Dqn_Str8_HasData(cpp_array_size_field.column.string)) { - Dqn_CppIfChain(cpp) { - Dqn_CppIfOrElseIfBlock(cpp, + if (DN_Str8_HasData(cpp_array_size_field.column.string)) { + DN_CppIfChain(cpp) { + DN_CppIfOrElseIfBlock(cpp, "lhs.%.*s != rhs.%.*s", - DQN_STR_FMT(cpp_array_size_field.column.string), - DQN_STR_FMT(cpp_array_size_field.column.string)) { - Dqn_CppLine(cpp, "return false;"); + DN_STR_FMT(cpp_array_size_field.column.string), + DN_STR_FMT(cpp_array_size_field.column.string)) { + DN_CppLine(cpp, "return false;"); } } - Dqn_CppIfChain(cpp) { - Dqn_CppIfOrElseIfBlock(cpp, - "DQN_MEMCMP(lhs.%.*s, rhs.%.*s, lhs.%.*s) != 0", - DQN_STR_FMT(cpp_name.column.string), - DQN_STR_FMT(cpp_name.column.string), - DQN_STR_FMT(cpp_array_size_field.column.string)) { - Dqn_CppLine(cpp, "return false;"); + DN_CppIfChain(cpp) { + DN_CppIfOrElseIfBlock(cpp, + "DN_MEMCMP(lhs.%.*s, rhs.%.*s, lhs.%.*s) != 0", + DN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(cpp_array_size_field.column.string)) { + DN_CppLine(cpp, "return false;"); } } - } else if (Dqn_Str8_HasData(cpp_array_size.column.string)) { - Dqn_CppIfChain(cpp) { - Dqn_CppIfOrElseIfBlock(cpp, - "DQN_MEMCMP(lhs.%.*s, rhs.%.*s, %.*s) != 0", - DQN_STR_FMT(cpp_name.column.string), - DQN_STR_FMT(cpp_name.column.string), - DQN_STR_FMT(cpp_array_size.column.string)) { - Dqn_CppLine(cpp, "return false;"); + } else if (DN_Str8_HasData(cpp_array_size.column.string)) { + DN_CppIfChain(cpp) { + DN_CppIfOrElseIfBlock(cpp, + "DN_MEMCMP(lhs.%.*s, rhs.%.*s, %.*s) != 0", + DN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(cpp_array_size.column.string)) { + DN_CppLine(cpp, "return false;"); } } - } else if (cpp_is_ptr.column.string == DQN_STR8("true")) { - Dqn_CppIfChain(cpp) { - Dqn_CppIfOrElseIfBlock(cpp, + } else if (cpp_is_ptr.column.string == DN_STR8("true")) { + DN_CppIfChain(cpp) { + DN_CppIfOrElseIfBlock(cpp, "*lhs.%.*s != *rhs.%.*s", - DQN_STR_FMT(cpp_name.column.string), - DQN_STR_FMT(cpp_name.column.string)) { - Dqn_CppLine(cpp, "return false;"); + DN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(cpp_name.column.string)) { + DN_CppLine(cpp, "return false;"); } } } else { - Dqn_CppIfChain(cpp) { - Dqn_CppIfOrElseIfBlock(cpp, + DN_CppIfChain(cpp) { + DN_CppIfOrElseIfBlock(cpp, "lhs.%.*s != rhs.%.*s", - DQN_STR_FMT(cpp_name.column.string), - DQN_STR_FMT(cpp_name.column.string)) { - Dqn_CppLine(cpp, "return false;"); + DN_STR_FMT(cpp_name.column.string), + DN_STR_FMT(cpp_name.column.string)) { + DN_CppLine(cpp, "return false;"); } } } } - Dqn_CppLine(cpp, "return true;"); + DN_CppLine(cpp, "return true;"); } - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); - Dqn_CppFuncBlock(cpp, "bool operator!=(%.*s%.*s const &lhs, %.*s%.*s const &rhs)", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name), DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)) { - Dqn_CppLine(cpp, "bool result = !(lhs == rhs);"); - Dqn_CppLine(cpp, "return result;"); + DN_CppFuncBlock(cpp, "bool operator!=(%.*s%.*s const &lhs, %.*s%.*s const &rhs)", DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name), DN_STR_FMT(emit_prefix), DN_STR_FMT(type_name)) { + DN_CppLine(cpp, "bool result = !(lhs == rhs);"); + DN_CppLine(cpp, "return result;"); } - Dqn_CppNewLine(cpp); + DN_CppNewLine(cpp); } } } diff --git a/dqn_cgen.h b/dqn_cgen.h index 6acab6f..e2d4044 100644 --- a/dqn_cgen.h +++ b/dqn_cgen.h @@ -1,5 +1,5 @@ -#if !defined(DQN_CGEN_H) -#define DQN_CGEN_H +#if !defined(DN_CGEN_H) +#define DN_CGEN_H /* //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -18,157 +18,157 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$CGEN] Dqn_CGen ////////////////////////////////////////////////////////////////////////// +// NOTE: [$CGEN] DN_CGen ////////////////////////////////////////////////////////////////////////// #if !defined(MD_H) -#error Metadesk 'md.h' must be included before 'dqn_cgen.h' +#error Metadesk 'md.h' must be included before 'dn_cgen.h' #endif -#if !defined(DQN_H) -#error 'dqn.h' must be included before 'dqn_cgen.h' +#if !defined(DN_H) +#error 'dqn.h' must be included before 'dn_cgen.h' #endif -#if !defined(DQN_CPP_FILE_H) -#error 'dqn_cpp_file.h' must be included before 'dqn_cgen.h' +#if !defined(DN_CPP_FILE_H) +#error 'dn_cpp_file.h' must be included before 'dn_cgen.h' #endif -enum Dqn_CGenTableKeyType +enum DN_CGenTableKeyType { - Dqn_CGenTableKeyType_Nil, - Dqn_CGenTableKeyType_Name, - Dqn_CGenTableKeyType_Type, + DN_CGenTableKeyType_Nil, + DN_CGenTableKeyType_Name, + DN_CGenTableKeyType_Type, }; -enum Dqn_CGenTableType +enum DN_CGenTableType { - Dqn_CGenTableType_Nil, - Dqn_CGenTableType_Data, - Dqn_CGenTableType_CodeGenBuiltinTypes, - Dqn_CGenTableType_CodeGenStruct, - Dqn_CGenTableType_CodeGenEnum, - Dqn_CGenTableType_Count, + DN_CGenTableType_Nil, + DN_CGenTableType_Data, + DN_CGenTableType_CodeGenBuiltinTypes, + DN_CGenTableType_CodeGenStruct, + DN_CGenTableType_CodeGenEnum, + DN_CGenTableType_Count, }; -enum Dqn_CGenTableRowTagType +enum DN_CGenTableRowTagType { - Dqn_CGenTableRowTagType_Nil, - Dqn_CGenTableRowTagType_CommentDivider, - Dqn_CGenTableRowTagType_EmptyLine, + DN_CGenTableRowTagType_Nil, + DN_CGenTableRowTagType_CommentDivider, + DN_CGenTableRowTagType_EmptyLine, }; -enum Dqn_CGenTableRowTagCommentDivider +enum DN_CGenTableRowTagCommentDivider { - Dqn_CGenTableRowTagCommentDivider_Nil, - Dqn_CGenTableRowTagCommentDivider_Label, + DN_CGenTableRowTagCommentDivider_Nil, + DN_CGenTableRowTagCommentDivider_Label, }; -enum Dqn_CGenTableHeaderType +enum DN_CGenTableHeaderType { - Dqn_CGenTableHeaderType_Name, - Dqn_CGenTableHeaderType_Table, - Dqn_CGenTableHeaderType_CppType, - Dqn_CGenTableHeaderType_CppName, - Dqn_CGenTableHeaderType_CppValue, - Dqn_CGenTableHeaderType_CppIsPtr, - Dqn_CGenTableHeaderType_CppOpEquals, - Dqn_CGenTableHeaderType_CppArraySize, - Dqn_CGenTableHeaderType_CppArraySizeField, - Dqn_CGenTableHeaderType_CppLabel, - Dqn_CGenTableHeaderType_GenTypeInfo, - Dqn_CGenTableHeaderType_GenEnumCount, - Dqn_CGenTableHeaderType_Count, + DN_CGenTableHeaderType_Name, + DN_CGenTableHeaderType_Table, + DN_CGenTableHeaderType_CppType, + DN_CGenTableHeaderType_CppName, + DN_CGenTableHeaderType_CppValue, + DN_CGenTableHeaderType_CppIsPtr, + DN_CGenTableHeaderType_CppOpEquals, + DN_CGenTableHeaderType_CppArraySize, + DN_CGenTableHeaderType_CppArraySizeField, + DN_CGenTableHeaderType_CppLabel, + DN_CGenTableHeaderType_GenTypeInfo, + DN_CGenTableHeaderType_GenEnumCount, + DN_CGenTableHeaderType_Count, }; -struct Dqn_CGenTableHeader +struct DN_CGenTableHeader { MD_String8 name; int longest_string; }; -struct Dqn_CGenTableRowTag +struct DN_CGenTableRowTag { - Dqn_CGenTableRowTagType type; + DN_CGenTableRowTagType type; MD_String8 comment; - Dqn_CGenTableRowTag *next; + DN_CGenTableRowTag *next; }; -struct Dqn_CGenTableColumn +struct DN_CGenTableColumn { MD_Node *node; - Dqn_Str8 string; + DN_Str8 string; }; -struct Dqn_CGenTableRow +struct DN_CGenTableRow { - Dqn_CGenTableRowTag *first_tag; - Dqn_CGenTableRowTag *last_tag; - Dqn_CGenTableColumn *columns; + DN_CGenTableRowTag *first_tag; + DN_CGenTableRowTag *last_tag; + DN_CGenTableColumn *columns; }; -struct Dqn_CGenTable +struct DN_CGenTable { - Dqn_CGenTableType type; - Dqn_Str8 name; - MD_Map headers_map; - Dqn_CGenTableHeader *headers; - Dqn_CGenTableRow *rows; - size_t column_count; - size_t row_count; + DN_CGenTableType type; + DN_Str8 name; + MD_Map headers_map; + DN_CGenTableHeader *headers; + DN_CGenTableRow *rows; + size_t column_count; + size_t row_count; - MD_Node *node; - MD_Node *headers_node; - Dqn_usize column_indexes[Dqn_CGenTableHeaderType_Count]; - Dqn_CGenTable *next; + MD_Node *node; + MD_Node *headers_node; + DN_USize column_indexes[DN_CGenTableHeaderType_Count]; + DN_CGenTable *next; }; -struct Dqn_CGen +struct DN_CGen { - MD_Arena *arena; - MD_Node *file_list; - MD_Map table_map; - Dqn_CGenTable *first_table; - Dqn_CGenTable *last_table; - Dqn_usize table_counts[Dqn_CGenTableType_Count]; + MD_Arena *arena; + MD_Node *file_list; + MD_Map table_map; + DN_CGenTable *first_table; + DN_CGenTable *last_table; + DN_USize table_counts[DN_CGenTableType_Count]; }; -struct Dqn_CGenMapNodeToEnum +struct DN_CGenMapNodeToEnum { uint32_t enum_val; - Dqn_Str8 node_string; + DN_Str8 node_string; }; -struct Dqn_CGenLookupTableIterator +struct DN_CGenLookupTableIterator { - Dqn_CGenTable *cgen_table; - Dqn_CGenTableRow *cgen_table_row; - Dqn_CGenTableColumn cgen_table_column[Dqn_CGenTableHeaderType_Count]; - Dqn_CGenTable *table; - Dqn_usize row_index; + DN_CGenTable *cgen_table; + DN_CGenTableRow *cgen_table_row; + DN_CGenTableColumn cgen_table_column[DN_CGenTableHeaderType_Count]; + DN_CGenTable *table; + DN_USize row_index; }; -struct Dqn_CGenLookupColumnAtHeader +struct DN_CGenLookupColumnAtHeader { - Dqn_usize index; - Dqn_CGenTableHeader header; - Dqn_CGenTableColumn column; + DN_USize index; + DN_CGenTableHeader header; + DN_CGenTableColumn column; }; -enum Dqn_CGenEmit +enum DN_CGenEmit { - Dqn_CGenEmit_Prototypes = 1 << 0, - Dqn_CGenEmit_Implementation = 1 << 1, + DN_CGenEmit_Prototypes = 1 << 0, + DN_CGenEmit_Implementation = 1 << 1, }; -// NOTE: [$CGEN] Dqn_CGen ////////////////////////////////////////////////////////////////////////// -#define Dqn_CGen_MDToDqnStr8(str8) Dqn_Str8_Init((str8).str, (str8).size) -#define Dqn_CGen_DqnToMDStr8(str8) {DQN_CAST(MD_u8 *)(str8).data, (str8).size} -DQN_API Dqn_CGen Dqn_CGen_InitFilesArgV (int argc, char const **argv, Dqn_ErrorSink *error); -DQN_API Dqn_Str8 Dqn_CGen_TableHeaderTypeToDeclStr8 (Dqn_CGenTableHeaderType type); -DQN_API Dqn_CGenMapNodeToEnum Dqn_CGen_MapNodeToEnumOrExit (MD_Node const *node, Dqn_CGenMapNodeToEnum const *valid_keys, Dqn_usize valid_keys_size, char const *fmt, ...); -DQN_API Dqn_usize Dqn_CGen_NodeChildrenCount (MD_Node const *node); -DQN_API void Dqn_CGen_LogF (MD_MessageKind kind, MD_Node *node, Dqn_ErrorSink *error, char const *fmt, ...); -DQN_API bool Dqn_CGen_TableHasHeaders (Dqn_CGenTable const *table, Dqn_Str8 const *headers, Dqn_usize header_count, Dqn_ErrorSink *error); -DQN_API Dqn_CGenLookupColumnAtHeader Dqn_CGen_LookupColumnAtHeader (Dqn_CGenTable *table, Dqn_Str8 header, Dqn_CGenTableRow const *row); -DQN_API bool Dqn_CGen_LookupNextTableInCodeGenTable(Dqn_CGen *cgen, Dqn_CGenTable *cgen_table, Dqn_CGenLookupTableIterator *it); -DQN_API void Dqn_CGen_EmitCodeForTables (Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_CppFile *cpp, Dqn_Str8 emit_prefix); -#endif // DQN_CGEN_H +// NOTE: [$CGEN] DN_CGen ////////////////////////////////////////////////////////////////////////// +#define DN_CGen_MDToDNStr8(str8) DN_Str8_Init((str8).str, (str8).size) +#define DN_CGen_DNToMDStr8(str8) {DN_CAST(MD_u8 *)(str8).data, (str8).size} +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_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); +#endif // DN_CGEN_H diff --git a/dqn_containers.cpp b/dqn_containers.cpp index d637e9d..7190eae 100644 --- a/dqn_containers.cpp +++ b/dqn_containers.cpp @@ -18,31 +18,1305 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$SLIC] Dqn_Slice ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8 Dqn_Slice_Str8Render(Dqn_Arena *arena, Dqn_Slice array, Dqn_Str8 separator) +// NOTE: [$CARR] DN_CArray //////////////////////////////////////////////////////////////////////// +template DN_ArrayEraseResult DN_CArray_EraseRange(T* data, DN_USize *size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase) { - Dqn_Str8 result = {}; + 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_ZeroMem zero_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 (zero_mem == DN_ZeroMem_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_VARRAY) +// NOTE: [$VARR] 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_OSMemCommit_No, DN_OSMemPage_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_ZeroMem_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_ZeroMem zero_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 (zero_mem == DN_ZeroMem_Yes) + DN_MEMSET(result, 0, count * sizeof(T)); + return result; +} + +template T *DN_VArray_Make(DN_VArray *array, DN_ZeroMem zero_mem) +{ + T *result = DN_VArray_MakeArray(array, 1, zero_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_ZeroMem zero_mem) +{ + if (array) { + if (zero_mem == DN_ZeroMem_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_core->os_page_size); + if (array->commit >= aligned_commit) + return true; + bool result = DN_OS_MemCommit(array->data, aligned_commit, DN_OSMemPage_ReadWrite); + array->commit = aligned_commit; + return result; +} +#endif // !defined(DN_NO_VARRAY) + +#if !defined(DN_NO_SARRAY) +// NOTE: [$SARR] DN_SArray //////////////////////////////////////////////////////////////////////// +template DN_SArray DN_SArray_Init(DN_Arena *arena, DN_USize size, DN_ZeroMem zero_mem) +{ + DN_SArray result = {}; + if (!arena || !size) + return result; + result.data = DN_Arena_NewArray(arena, T, size, zero_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_ZeroMem zero_mem) +{ + DN_USize max = DN_MAX(slice.size, size); + DN_SArray result = DN_SArray_Init(arena, max, DN_ZeroMem_No); + if (DN_SArray_IsValid(&result)) { + DN_SArray_AddArray(&result, slice.data, slice.size); + if (zero_mem == DN_ZeroMem_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_ZeroMem zero_mem) +{ + DN_SArray result = DN_SArray_InitSlice(arena, DN_Slice_Init(DN_CAST(T *)array, N), size, zero_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_ZeroMem zero_mem) +{ + if (!DN_SArray_IsValid(array)) + return nullptr; + T *result = DN_CArray_MakeArray(array->data, &array->size, array->max, count, zero_mem); + return result; +} + +template T *DN_SArray_Make(DN_SArray *array, DN_ZeroMem zero_mem) +{ + T *result = DN_SArray_MakeArray(array, 1, zero_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_ZeroMem_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: [$FARR] 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_ARRAY_UCOUNT(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_ZeroMem_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_ZeroMem_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_ZeroMem zero_mem) +{ + if (!DN_FArray_IsValid(array)) + return nullptr; + T *result = DN_CArray_MakeArray(array->data, &array->size, N, count, zero_mem); + return result; +} + +template T *DN_FArray_Make(DN_FArray *array, DN_ZeroMem zero_mem) +{ + T *result = DN_FArray_MakeArray(array, 1, zero_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_InitCArray(DN_Arena *arena, T const (&array)[N]) +{ + DN_Slice result = DN_Slice_Alloc(arena, N, DN_ZeroMem_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_Arena_NewArrayCopy(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_ZeroMem zero_mem) +{ + DN_Slice result = {}; + if (!arena || size == 0) + return result; + result.data = DN_Arena_NewArray(arena, T, size, zero_mem); + if (result.data) + result.size = size; + return result; +} + +#endif // !defined(DN_NO_SLICE) + +#if !defined(DN_NO_DSMAP) +// NOTE: [$DMAP] 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 result = {}; + if (!DN_CHECKF(DN_IsPowerOfTwo(size), "Power-of-two size required, given size was '%u'", size)) + return result; + if (size <= 0) + return result; + if (!DN_CHECK(arena)) + return result; + result.arena = arena; + result.pool = DN_Pool_Init(arena, DN_POOL_DEFAULT_ALIGN); + result.hash_to_slot = DN_Arena_NewArray(result.arena, DN_U32, size, DN_ZeroMem_Yes); + result.slots = DN_Arena_NewArray(result.arena, DN_DSMapSlot, size, DN_ZeroMem_Yes); + result.occupied = 1; // For sentinel + result.size = size; + result.initial_size = size; + result.flags = flags; + DN_ASSERTF(result.hash_to_slot && result.slots, "We pre-allocated a block of memory sufficient in size for the 2 arrays. Maybe the pointers needed extra space because of natural alignment?"); + return result; +} + +template +void DN_DSMap_Deinit(DN_DSMap *map, DN_ZeroMem zero_mem) +{ + if (!map) + return; + // TODO(doyle): Use zero_mem + (void)zero_mem; + DN_Arena_Deinit(map->arena); + *map = {}; +} + +template +bool DN_DSMap_IsValid(DN_DSMap const *map) +{ + bool result = map && + map->arena && + map->hash_to_slot && // Hash to slot mapping array must be allocated + map->slots && // Slots array must be allocated + (map->size & (map->size - 1)) == 0 && // Must be power of two size + map->occupied >= 1; // DN_DS_MAP_SENTINEL_SLOT takes up one slot + return result; +} + +template +DN_U32 DN_DSMap_Hash(DN_DSMap const *map, DN_DSMapKey key) +{ + DN_U32 result = 0; + if (!map) + return result; + + if (key.type == DN_DSMapKeyType_U64NoHash) { + result = DN_CAST(DN_U32)key.u64; + return result; + } + + if (key.type == DN_DSMapKeyType_BufferAsU64NoHash) { + result = key.hash; + return result; + } + + DN_U32 seed = map->hash_seed ? map->hash_seed : DN_DS_MAP_DEFAULT_HASH_SEED; + if (map->hash_function) { + map->hash_function(key, seed); + } else { + // NOTE: Courtesy of Demetri Spanos (which this hash table was inspired + // from), the following is a hashing function snippet provided for + // reliable, quick and simple quality hashing functions for hash table + // use. + // Source: https://github.com/demetri/scribbles/blob/c475464756c104c91bab83ed4e14badefef12ab5/hashing/ub_aware_hash_functions.c + + char const *key_ptr = nullptr; + DN_U32 len = 0; + DN_U32 h = seed; + switch (key.type) { + case DN_DSMapKeyType_BufferAsU64NoHash: /*FALLTHRU*/ + case DN_DSMapKeyType_U64NoHash: DN_INVALID_CODE_PATH; /*FALLTHRU*/ + case DN_DSMapKeyType_Invalid: break; + + case DN_DSMapKeyType_Buffer: + key_ptr = DN_CAST(char const *)key.buffer_data; + len = key.buffer_size; + break; + + case DN_DSMapKeyType_U64: + key_ptr = DN_CAST(char const *)&key.u64; + len = sizeof(key.u64); + break; + } + + // Murmur3 32-bit without UB unaligned accesses + // DN_U32 mur3_32_no_UB(const void *key, int len, DN_U32 h) + + // main body, work on 32-bit blocks at a time + for (DN_U32 i = 0; i < len / 4; i++) { + DN_U32 k; + memcpy(&k, &key_ptr[i * 4], sizeof(k)); + + k *= 0xcc9e2d51; + k = ((k << 15) | (k >> 17)) * 0x1b873593; + h = (((h ^ k) << 13) | ((h ^ k) >> 19)) * 5 + 0xe6546b64; + } + + // load/mix up to 3 remaining tail bytes into a tail block + DN_U32 t = 0; + uint8_t *tail = ((uint8_t *)key_ptr) + 4 * (len / 4); + switch (len & 3) { + case 3: t ^= tail[2] << 16; + case 2: t ^= tail[1] << 8; + case 1: { + t ^= tail[0] << 0; + h ^= ((0xcc9e2d51 * t << 15) | (0xcc9e2d51 * t >> 17)) * 0x1b873593; + } + } + + // finalization mix, including key length + h = ((h ^ len) ^ ((h ^ len) >> 16)) * 0x85ebca6b; + h = (h ^ (h >> 13)) * 0xc2b2ae35; + result = h ^ (h >> 16); + } + return result; +} + +template +DN_U32 DN_DSMap_HashToSlotIndex(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)) + return result; + + result = key.hash & (map->size - 1); + for (;;) { + if (result == DN_DS_MAP_SENTINEL_SLOT) // Sentinel is reserved + result++; + + if (map->hash_to_slot[result] == DN_DS_MAP_SENTINEL_SLOT) // Slot is vacant, can use + return result; + + DN_DSMapSlot *slot = map->slots + map->hash_to_slot[result]; + if (slot->key.type == DN_DSMapKeyType_Invalid || (slot->key.hash == key.hash && slot->key == key)) + return result; + + result = (result + 1) & (map->size - 1); + } +} + +template +DN_DSMapResult DN_DSMap_Find(DN_DSMap const *map, DN_DSMapKey key) +{ + DN_DSMapResult result = {}; + if (DN_DSMap_IsValid(map)) { + DN_U32 index = DN_DSMap_HashToSlotIndex(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 { + result.slot = map->slots + map->hash_to_slot[index]; + result.found = true; + } + result.value = &result.slot->value; + } + return result; +} + +template +DN_DSMapResult DN_DSMap_Make(DN_DSMap *map, DN_DSMapKey key) +{ + DN_DSMapResult result = {}; + if (!DN_DSMap_IsValid(map)) + return result; + + DN_U32 index = DN_DSMap_HashToSlotIndex(map, key); + if (map->hash_to_slot[index] == DN_DS_MAP_SENTINEL_SLOT) { + // NOTE: Create the slot + if (index != DN_DS_MAP_SENTINEL_SLOT) + map->hash_to_slot[index] = map->occupied++; + + // 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)) + return result; + result = DN_DSMap_Make(map, key); + } else { + result.slot = map->slots + map->hash_to_slot[index]; + result.slot->key = key; // NOTE: Assign key to new slot + if ((key.type == DN_DSMapKeyType_Buffer || + key.type == DN_DSMapKeyType_BufferAsU64NoHash) && + !key.no_copy_buffer) { + result.slot->key.buffer_data = DN_Pool_NewArrayCopy(&map->pool, char, key.buffer_data, key.buffer_size); + } + } + } else { + result.slot = map->slots + map->hash_to_slot[index]; + result.found = true; + } + + result.value = &result.slot->value; + DN_ASSERT(result.slot->key.type != DN_DSMapKeyType_Invalid); + return result; +} + +template +DN_DSMapResult DN_DSMap_Set(DN_DSMap *map, DN_DSMapKey key, T const &value) +{ + DN_DSMapResult result = {}; + if (!DN_DSMap_IsValid(map)) + return result; + + result = DN_DSMap_Make(map, key); + result.slot->value = value; + return result; +} + +template +DN_DSMapResult DN_DSMap_FindKeyU64(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); + return result; +} + +template +DN_DSMapResult DN_DSMap_MakeKeyU64(DN_DSMap *map, DN_U64 key) +{ + DN_DSMapKey map_key = DN_DSMap_KeyU64(map, key); + DN_DSMapResult result = DN_DSMap_Make(map, map_key); + return result; +} + +template +DN_DSMapResult DN_DSMap_SetKeyU64(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); + return result; +} + +template +DN_DSMapResult DN_DSMap_FindKeyStr8(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); + return result; +} + +template +DN_DSMapResult DN_DSMap_MakeKeyStr8(DN_DSMap *map, DN_Str8 key) +{ + DN_DSMapKey map_key = DN_DSMap_KeyStr8(map, key); + DN_DSMapResult result = DN_DSMap_Make(map, map_key); + return result; +} + +template +DN_DSMapResult DN_DSMap_SetKeyStr8(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); + return result; +} + +template +bool DN_DSMap_Resize(DN_DSMap *map, DN_U32 size) +{ + if (!DN_DSMap_IsValid(map) || size < map->occupied || size < map->initial_size) + return false; + + DN_Arena *prev_arena = map->arena; + DN_Arena new_arena = {}; + new_arena.flags = prev_arena->flags; + new_arena.label = prev_arena->label; + new_arena.prev = prev_arena->prev; + new_arena.next = prev_arena->next; + + DN_DSMap new_map = DN_DSMap_Init(&new_arena, size, map->flags); + if (!DN_DSMap_IsValid(&new_map)) + return false; + + new_map.initial_size = map->initial_size; + for (DN_U32 old_index = 1 /*Sentinel*/; old_index < map->occupied; old_index++) { + DN_DSMapSlot *old_slot = map->slots + old_index; + 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); + } + + if ((map->flags & DN_DSMapFlags_DontFreeArenaOnResize) == 0) + DN_DSMap_Deinit(map, DN_ZeroMem_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 + map->pool.arena = map->arena; + return true; +} + +template +bool DN_DSMap_Erase(DN_DSMap *map, DN_DSMapKey key) +{ + if (!DN_DSMap_IsValid(map)) + return false; + + DN_U32 index = DN_DSMap_HashToSlotIndex(map, key); + if (index == 0) + return true; + + DN_U32 slot_index = map->hash_to_slot[index]; + if (slot_index == DN_DS_MAP_SENTINEL_SLOT) + return false; + + // NOTE: Mark the slot as unoccupied + map->hash_to_slot[index] = DN_DS_MAP_SENTINEL_SLOT; + + DN_DSMapSlot *slot = map->slots + slot_index; + if (!slot->key.no_copy_buffer) + DN_Pool_Dealloc(&map->pool, DN_CAST(void *)slot->key.buffer_data); + *slot = {}; // TODO: Optional? + + if (map->occupied > 1 /*Sentinel*/) { + // NOTE: Repair the hash chain, e.g. rehash all the items after the removed + // element and reposition them if necessary. + for (DN_U32 probe_index = index;;) { + probe_index = (probe_index + 1) & (map->size - 1); + if (map->hash_to_slot[probe_index] == DN_DS_MAP_SENTINEL_SLOT) + break; + + DN_DSMapSlot *probe = map->slots + map->hash_to_slot[probe_index]; + DN_U32 new_index = probe->key.hash & (map->size - 1); + if (index <= probe_index) { + if (index < new_index && new_index <= probe_index) + continue; + } else { + if (index < new_index || new_index <= probe_index) + continue; + } + + map->hash_to_slot[index] = map->hash_to_slot[probe_index]; + map->hash_to_slot[probe_index] = DN_DS_MAP_SENTINEL_SLOT; + index = probe_index; + } + + // NOTE: We have erased a slot from the hash table, this leaves a gap + // in our contiguous array. After repairing the chain, the hash mapping + // is correct. + // We will now fill in the vacant spot that we erased using the last + // element in the slot list. + if (map->occupied >= 3 /*Ignoring sentinel, at least 2 other elements to unstable erase*/) { + DN_U32 last_index = map->occupied - 1; + if (last_index != slot_index) { + // NOTE: Copy in last slot to the erase slot + DN_DSMapSlot *last_slot = map->slots + last_index; + 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); + map->hash_to_slot[hash_to_slot_index] = slot_index; + *last_slot = {}; // TODO: Optional? + } + } + } + + 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); + + return true; +} + +template bool DN_DSMap_EraseKeyU64(DN_DSMap *map, DN_U64 key) +{ + DN_DSMapKey map_key = DN_DSMap_KeyU64(map, key); + bool result = DN_DSMap_Erase(map, map_key); + return result; +} + +template bool DN_DSMap_EraseKeyStr8(DN_DSMap *map, DN_Str8 key) +{ + DN_DSMapKey map_key = DN_DSMap_KeyStr8(map, key); + bool result = DN_DSMap_Erase(map, map_key); + return result; +} + +template +DN_DSMapKey DN_DSMap_KeyBuffer(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); + return result; +} + +template +DN_DSMapKey DN_DSMap_KeyBufferAsU64NoHash(DN_DSMap const *map, void const *data, DN_U32 size) +{ + DN_DSMapKey result = {}; + result.type = DN_DSMapKeyType_BufferAsU64NoHash; + result.buffer_data = data; + result.buffer_size = DN_CAST(DN_U32) size; + DN_ASSERT(size >= sizeof(result.hash)); + DN_MEMCPY(&result.hash, data, sizeof(result.hash)); + return result; +} + +template DN_DSMapKey DN_DSMap_KeyU64(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); + return result; +} + +template DN_DSMapKey DN_DSMap_KeyStr8(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: [$LIST] DN_List ////////////////////////////////////////////////////////////////////////// +template DN_List DN_List_Init(DN_USize chunk_size) +{ + DN_List result = {}; + result.chunk_size = chunk_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); + DN_FOR_UINDEX (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); + DN_FOR_UINDEX (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_Arena_New(arena, DN_ListChunk, DN_ZeroMem_Yes); + DN_ArenaTempMem tmem = DN_Arena_TempMemBegin(arena); + if (!result) + return nullptr; + + DN_USize items = DN_MAX(list->chunk_size, count); + result->data = DN_Arena_NewArray(arena, T, items, DN_ZeroMem_Yes); + result->size = items; + if (!result->data) { + DN_Arena_TempMemEnd(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_Pool_New(pool, DN_ListChunk); + if (!result) + return nullptr; + + DN_USize items = DN_MAX(list->chunk_size, count); + result->data = DN_Pool_NewArray(pool, T, items); + result->size = items; + if (!result->data) { + DN_Pool_Dealloc(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_ZeroMem_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: [$SLIC] DN_Slice ///////////////////////////////////////////////////////////////////////// +DN_API DN_Str8 DN_Slice_Str8Render(DN_Arena *arena, DN_Slice array, DN_Str8 separator) +{ + DN_Str8 result = {}; if (!arena) return result; - Dqn_usize total_size = 0; - for (Dqn_usize index = 0; index < array.size; index++) { + DN_USize total_size = 0; + for (DN_USize index = 0; index < array.size; index++) { if (index) total_size += separator.size; - Dqn_Str8 item = array.data[index]; + DN_Str8 item = array.data[index]; total_size += item.size; } - result = Dqn_Str8_Alloc(arena, total_size, Dqn_ZeroMem_No); + result = DN_Str8_Alloc(arena, total_size, DN_ZeroMem_No); if (result.data) { - Dqn_usize write_index = 0; - for (Dqn_usize index = 0; index < array.size; index++) { + DN_USize write_index = 0; + for (DN_USize index = 0; index < array.size; index++) { if (index) { - DQN_MEMCPY(result.data + write_index, separator.data, separator.size); + DN_MEMCPY(result.data + write_index, separator.data, separator.size); write_index += separator.size; } - Dqn_Str8 item = array.data[index]; - DQN_MEMCPY(result.data + write_index, item.data, item.size); + DN_Str8 item = array.data[index]; + DN_MEMCPY(result.data + write_index, item.data, item.size); write_index += item.size; } } @@ -50,36 +1324,36 @@ DQN_API Dqn_Str8 Dqn_Slice_Str8Render(Dqn_Arena *arena, Dqn_Slice arra return result; } -DQN_API Dqn_Str8 Dqn_Slice_Str8RenderSpaceSeparated(Dqn_Arena *arena, Dqn_Slice array) +DN_API DN_Str8 DN_Slice_Str8RenderSpaceSeparated(DN_Arena *arena, DN_Slice array) { - Dqn_Str8 result = Dqn_Slice_Str8Render(arena, array, DQN_STR8(" ")); + DN_Str8 result = DN_Slice_Str8Render(arena, array, DN_STR8(" ")); return result; } -DQN_API Dqn_Str16 Dqn_Slice_Str16Render(Dqn_Arena *arena, Dqn_Slice array, Dqn_Str16 separator) +DN_API DN_Str16 DN_Slice_Str16Render(DN_Arena *arena, DN_Slice array, DN_Str16 separator) { - Dqn_Str16 result = {}; + DN_Str16 result = {}; if (!arena) return result; - Dqn_usize total_size = 0; - for (Dqn_usize index = 0; index < array.size; index++) { + DN_USize total_size = 0; + for (DN_USize index = 0; index < array.size; index++) { if (index) total_size += separator.size; - Dqn_Str16 item = array.data[index]; + DN_Str16 item = array.data[index]; total_size += item.size; } - result = {Dqn_Arena_NewArray(arena, wchar_t, total_size + 1, Dqn_ZeroMem_No), total_size}; + result = {DN_Arena_NewArray(arena, wchar_t, total_size + 1, DN_ZeroMem_No), total_size}; if (result.data) { - Dqn_usize write_index = 0; - for (Dqn_usize index = 0; index < array.size; index++) { + DN_USize write_index = 0; + for (DN_USize index = 0; index < array.size; index++) { if (index) { - DQN_MEMCPY(result.data + write_index, separator.data, separator.size * sizeof(result.data[0])); + DN_MEMCPY(result.data + write_index, separator.data, separator.size * sizeof(result.data[0])); write_index += separator.size; } - Dqn_Str16 item = array.data[index]; - DQN_MEMCPY(result.data + write_index, item.data, item.size * sizeof(result.data[0])); + DN_Str16 item = array.data[index]; + DN_MEMCPY(result.data + write_index, item.data, item.size * sizeof(result.data[0])); write_index += item.size; } } @@ -88,45 +1362,45 @@ DQN_API Dqn_Str16 Dqn_Slice_Str16Render(Dqn_Arena *arena, Dqn_Slice a return result; } -DQN_API Dqn_Str16 Dqn_Slice_Str16RenderSpaceSeparated(Dqn_Arena *arena, Dqn_Slice array) +DN_API DN_Str16 DN_Slice_Str16RenderSpaceSeparated(DN_Arena *arena, DN_Slice array) { - Dqn_Str16 result = Dqn_Slice_Str16Render(arena, array, DQN_STR16(L" ")); + DN_Str16 result = DN_Slice_Str16Render(arena, array, DN_STR16(L" ")); return result; } -#if !defined(DQN_NO_DSMAP) -// NOTE: [$DMAP] Dqn_DSMap ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_DSMapKey Dqn_DSMap_KeyU64NoHash(uint64_t u64) +#if !defined(DN_NO_DSMAP) +// NOTE: [$DMAP] DN_DSMap ///////////////////////////////////////////////////////////////////////// +DN_API DN_DSMapKey DN_DSMap_KeyU64NoHash(DN_U64 u64) { - Dqn_DSMapKey result = {}; - result.type = Dqn_DSMapKeyType_U64NoHash; + DN_DSMapKey result = {}; + result.type = DN_DSMapKeyType_U64NoHash; result.u64 = u64; - result.hash = DQN_CAST(uint32_t) u64; + result.hash = DN_CAST(DN_U32) u64; return result; } -DQN_API bool Dqn_DSMap_KeyEquals(Dqn_DSMapKey lhs, Dqn_DSMapKey rhs) +DN_API bool DN_DSMap_KeyEquals(DN_DSMapKey lhs, DN_DSMapKey rhs) { bool result = false; if (lhs.type == rhs.type && lhs.hash == rhs.hash) { switch (lhs.type) { - case Dqn_DSMapKeyType_Invalid: result = true; break; - case Dqn_DSMapKeyType_U64NoHash: result = true; break; - case Dqn_DSMapKeyType_U64: result = lhs.u64 == rhs.u64; break; + case DN_DSMapKeyType_Invalid: result = true; break; + case DN_DSMapKeyType_U64NoHash: result = true; break; + case DN_DSMapKeyType_U64: result = lhs.u64 == rhs.u64; break; - case Dqn_DSMapKeyType_BufferAsU64NoHash: /*FALLTHRU*/ - case Dqn_DSMapKeyType_Buffer: { + case DN_DSMapKeyType_BufferAsU64NoHash: /*FALLTHRU*/ + case DN_DSMapKeyType_Buffer: { if (lhs.buffer_size == rhs.buffer_size) - result = DQN_MEMCMP(lhs.buffer_data, rhs.buffer_data, lhs.buffer_size) == 0; + result = DN_MEMCMP(lhs.buffer_data, rhs.buffer_data, lhs.buffer_size) == 0; } break; } } return result; } -DQN_API bool operator==(Dqn_DSMapKey lhs, Dqn_DSMapKey rhs) +DN_API bool operator==(DN_DSMapKey lhs, DN_DSMapKey rhs) { - bool result = Dqn_DSMap_KeyEquals(lhs, rhs); + bool result = DN_DSMap_KeyEquals(lhs, rhs); return result; } -#endif // !defined(DQN_NO_DSMAP) +#endif // !defined(DN_NO_DSMAP) diff --git a/dqn_containers.h b/dqn_containers.h index 9043beb..967f194 100644 --- a/dqn_containers.h +++ b/dqn_containers.h @@ -17,82 +17,82 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // -// [$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 -- -- 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 +// [$CARR] DN_CArray -- -- Basic operations on C arrays for VArray/SArray/FArray to reuse +// [$VARR] DN_VArray -- DN_VARRAY -- Array backed by virtual memory arena +// [$SARR] DN_SArray -- DN_SARRAY -- Array that are allocated but cannot resize +// [$FARR] DN_FArray -- DN_FARRAY -- Fixed-size arrays +// [$SLIC] DN_Slice -- -- Pointe and length container of data +// [$DMAP] DN_DSMap -- DN_DSMAP -- Hashtable, 70% max load, PoT size, linear probe, chain repair +// [$LIST] DN_List -- DN_LIST -- Chunked linked lists, append only // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$CARR] Dqn_CArray //////////////////////////////////////////////////////////////////////// -enum Dqn_ArrayErase +// NOTE: [$CARR] DN_CArray //////////////////////////////////////////////////////////////////////// +enum DN_ArrayErase { - Dqn_ArrayErase_Unstable, - Dqn_ArrayErase_Stable, + DN_ArrayErase_Unstable, + DN_ArrayErase_Stable, }; -struct Dqn_ArrayEraseResult +struct DN_ArrayEraseResult { // The next index your for-index should be set to such that you can continue // to iterate the remainder of the array, e.g: // - // for (Dqn_usize index = 0; index < array.size; index++) { + // for (DN_USize index = 0; index < array.size; index++) { // if (erase) - // index = Dqn_FArray_EraseRange(&array, index, -3, Dqn_ArrayErase_Unstable); + // index = DN_FArray_EraseRange(&array, index, -3, DN_ArrayErase_Unstable); // } - Dqn_usize it_index; - Dqn_usize items_erased; // The number of items erased + DN_USize it_index; + DN_USize items_erased; // The number of items erased }; -template struct Dqn_ArrayFindResult +template struct DN_ArrayFindResult { T *data; // Pointer to the value if a match is found, null pointer otherwise - Dqn_usize index; // Index to the value if a match is found, 0 otherwise + DN_USize index; // Index to the value if a match is found, 0 otherwise }; -#if !defined(DQN_NO_VARRAY) -// NOTE: [$VARR] Dqn_VArray //////////////////////////////////////////////////////////////////////// +#if !defined(DN_NO_VARRAY) +// NOTE: [$VARR] DN_VArray //////////////////////////////////////////////////////////////////////// // TODO(doyle): Add an API for shrinking the array by decomitting pages back to // the OS. -template struct Dqn_VArray +template struct DN_VArray { - Dqn_Arena arena; // Allocator for the array - 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 *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; } }; -#endif // !defined(DQN_NO_VARRAY) +#endif // !defined(DN_NO_VARRAY) -#if !defined(DQN_NO_SARRAY) -// NOTE: [$SARR] Dqn_SArray //////////////////////////////////////////////////////////////////////// -template struct Dqn_SArray +#if !defined(DN_NO_SARRAY) +// NOTE: [$SARR] DN_SArray //////////////////////////////////////////////////////////////////////// +template struct DN_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 *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(DQN_NO_SARRAY) +#endif // !defined(DN_NO_SARRAY) -#if !defined(DQN_NO_FARRAY) -// NOTE: [$FARR] Dqn_FArray //////////////////////////////////////////////////////////////////////// -template struct Dqn_FArray +#if !defined(DN_NO_FARRAY) +// NOTE: [$FARR] DN_FArray //////////////////////////////////////////////////////////////////////// +template struct DN_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 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; } @@ -100,1483 +100,248 @@ template struct Dqn_FArray T const *end () const { return data + size; } }; -template using Dqn_FArray8 = Dqn_FArray; -template using Dqn_FArray16 = Dqn_FArray; -template using Dqn_FArray32 = Dqn_FArray; -template using Dqn_FArray64 = Dqn_FArray; -#endif // !defined(DQN_NO_FARRAY) +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(DQN_NO_DSMAP) -// NOTE: [$DMAP] Dqn_DSMap ///////////////////////////////////////////////////////////////////////// -enum Dqn_DSMapKeyType +#if !defined(DN_NO_DSMAP) +// NOTE: [$DMAP] DN_DSMap ///////////////////////////////////////////////////////////////////////// +enum DN_DSMapKeyType { - // Key | Key Hash | Map Index - Dqn_DSMapKeyType_Invalid, - Dqn_DSMapKeyType_U64, // U64 | Hash(U64) | Hash(U64) % map_size - Dqn_DSMapKeyType_U64NoHash, // U64 | U64 | U64 % map_size - Dqn_DSMapKeyType_Buffer, // Buffer | Hash(buffer) | Hash(buffer) % map_size - Dqn_DSMapKeyType_BufferAsU64NoHash, // Buffer | U64(buffer[0:4]) | U64(buffer[0:4]) % map_size + // Key | Key Hash | Map Index + DN_DSMapKeyType_Invalid, + DN_DSMapKeyType_U64, // U64 | Hash(U64) | Hash(U64) % map_size + DN_DSMapKeyType_U64NoHash, // U64 | U64 | U64 % map_size + DN_DSMapKeyType_Buffer, // Buffer | Hash(buffer) | Hash(buffer) % map_size + DN_DSMapKeyType_BufferAsU64NoHash, // Buffer | U64(buffer[0:4]) | U64(buffer[0:4]) % map_size }; -struct Dqn_DSMapKey +struct DN_DSMapKey { - Dqn_DSMapKeyType type; - uint32_t hash; // Hash to lookup in the map. If it equals, we check that the original key payload matches + DN_DSMapKeyType type; + DN_U32 hash; // Hash to lookup in the map. If it equals, we check that the original key payload matches void const *buffer_data; - uint32_t buffer_size; - uint64_t u64; + DN_U32 buffer_size; + DN_U64 u64; bool no_copy_buffer; }; template -struct Dqn_DSMapSlot +struct DN_DSMapSlot { - Dqn_DSMapKey key; ///< Hash table lookup key - T value; ///< Hash table value + DN_DSMapKey key; // Hash table lookup key + T value; // Hash table value }; -typedef uint32_t Dqn_DSMapFlags; -enum Dqn_DSMapFlags_ +typedef DN_U32 DN_DSMapFlags; +enum DN_DSMapFlags_ { - Dqn_DSMapFlags_Nil = 0, - Dqn_DSMapFlags_DontFreeArenaOnResize = 1 << 0, + DN_DSMapFlags_Nil = 0, + DN_DSMapFlags_DontFreeArenaOnResize = 1 << 0, }; -using Dqn_DSMapHashFunction = uint32_t(Dqn_DSMapKey key, uint32_t seed); -template struct Dqn_DSMap +using DN_DSMapHashFunction = DN_U32(DN_DSMapKey key, DN_U32 seed); +template struct DN_DSMap { - uint32_t *hash_to_slot; // Mapping from hash to a index in the slots array - Dqn_DSMapSlot *slots; // Values of the array stored contiguously, non-sorted order - uint32_t size; // Total capacity of the map and is a power of two - uint32_t occupied; // Number of slots used in the hash table - Dqn_Arena *arena; // Backing arena for the hash table - uint32_t initial_size; // Initial map size, map cannot shrink on erase below this size - Dqn_DSMapHashFunction *hash_function; // Custom hashing function to use if field is set - uint32_t hash_seed; // Seed for the hashing function, when 0, DQN_DS_MAP_DEFAULT_HASH_SEED is used - Dqn_DSMapFlags flags; + DN_U32 *hash_to_slot; // Mapping from hash to a index in the slots array + DN_DSMapSlot *slots; // Values of the array stored contiguously, non-sorted order + DN_U32 size; // Total capacity of the map and is a power of two + DN_U32 occupied; // Number of slots used in the hash table + DN_Arena *arena; // Backing arena for the hash table + DN_Pool pool; // Allocator for keys that are variable-sized buffers + DN_U32 initial_size; // Initial map size, map cannot shrink on erase below this size + DN_DSMapHashFunction *hash_function; // Custom hashing function to use if field is set + DN_U32 hash_seed; // Seed for the hashing function, when 0, DN_DS_MAP_DEFAULT_HASH_SEED is used + DN_DSMapFlags flags; }; -template struct Dqn_DSMapResult +template struct DN_DSMapResult { - bool found; - Dqn_DSMapSlot *slot; - T *value; + bool found; + DN_DSMapSlot *slot; + T *value; }; -#endif // !defined(DQN_NO_DSMAP) +#endif // !defined(DN_NO_DSMAP) -#if !defined(DQN_NO_LIST) -// NOTE: [$LIST] Dqn_List ////////////////////////////////////////////////////////////////////////// -template struct Dqn_ListChunk +#if !defined(DN_NO_LIST) +// NOTE: [$LIST] DN_List ////////////////////////////////////////////////////////////////////////// +template struct DN_ListChunk { - T *data; - Dqn_usize size; - Dqn_usize count; - Dqn_ListChunk *next; - Dqn_ListChunk *prev; + T *data; + DN_USize size; + DN_USize count; + DN_ListChunk *next; + DN_ListChunk *prev; }; -template struct Dqn_ListIterator +template struct DN_ListIterator { - Dqn_b32 init; // True if Dqn_List_Iterate has been called at-least once on this iterator - Dqn_ListChunk *chunk; // The chunk that the iterator is reading from - Dqn_usize chunk_data_index; // The index in the chunk the iterator is referencing - Dqn_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. + 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. }; -template struct Dqn_List +template struct DN_List { - Dqn_usize count; // Cumulative count of all items made across all list chunks - Dqn_usize chunk_size; // When new ListChunk's are required, the minimum 'data' entries to allocate for that node. - Dqn_ListChunk *head; - Dqn_ListChunk *tail; + 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(DQN_NO_LIST) +#endif // !defined(DN_NO_LIST) + +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_ZeroMem zero_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); + +#if !defined(DN_NO_VARRAY) +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_HARD_ASSERT(DN_VArray_AddArray(__VA_ARGS__)) +#define DN_VArray_AddCArrayAssert(...) DN_HARD_ASSERT(DN_VArray_AddCArray(__VA_ARGS__)) +#define DN_VArray_AddAssert(...) DN_HARD_ASSERT(DN_VArray_Add(__VA_ARGS__)) +template T * DN_VArray_MakeArray (DN_VArray *array, DN_USize count, DN_ZeroMem zero_mem); +template T * DN_VArray_Make (DN_VArray *array, DN_ZeroMem zero_mem); +#define DN_VArray_MakeArrayAssert(...) DN_HARD_ASSERT(DN_VArray_MakeArray(__VA_ARGS__)) +#define DN_VArray_MakeAssert(...) DN_HARD_ASSERT(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_HARD_ASSERT(DN_VArray_InsertArray(__VA_ARGS__)) +#define DN_VArray_InsertCArrayAssert(...) DN_HARD_ASSERT(DN_VArray_InsertCArray(__VA_ARGS__)) +#define DN_VArray_InsertAssert(...) DN_HARD_ASSERT(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_ZeroMem zero_mem); +#endif // !defined(DN_NO_VARRAY) +// NOTE: [$SARR] DN_SArray //////////////////////////////////////////////////////////////////////// +#if !defined(DN_NO_SARRAY) +template DN_SArray DN_SArray_Init (DN_Arena *arena, DN_USize size, DN_ZeroMem zero_mem); +template DN_SArray DN_SArray_InitSlice (DN_Arena *arena, DN_Slice slice, DN_USize size, DN_ZeroMem zero_mem); +template DN_SArray DN_SArray_InitCArray (DN_Arena *arena, T const (&array)[N], DN_USize size, DN_ZeroMem); +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_HARD_ASSERT(DN_SArray_AddArray(__VA_ARGS__)) +#define DN_SArray_AddCArrayAssert(...) DN_HARD_ASSERT(DN_SArray_AddCArray(__VA_ARGS__)) +#define DN_SArray_AddAssert(...) DN_HARD_ASSERT(DN_SArray_Add(__VA_ARGS__)) +template T * DN_SArray_MakeArray (DN_SArray *array, DN_USize count, DN_ZeroMem zero_mem); +template T * DN_SArray_Make (DN_SArray *array, DN_ZeroMem zero_mem); +#define DN_SArray_MakeArrayAssert(...) DN_HARD_ASSERT(DN_SArray_MakeArray(__VA_ARGS__)) +#define DN_SArray_MakeAssert(...) DN_HARD_ASSERT(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_HARD_ASSERT(DN_SArray_InsertArray(__VA_ARGS__)) +#define DN_SArray_InsertCArrayAssert(...) DN_HARD_ASSERT(DN_SArray_InsertCArray(__VA_ARGS__)) +#define DN_SArray_InsertAssert(...) DN_HARD_ASSERT(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) +#if !defined(DN_NO_FARRAY) +#define DN_FArray_ToSArray(array) DN_SArray_InitBuffer((array)->data, DN_ARRAY_UCOUNT((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_HARD_ASSERT(DN_FArray_AddArray(__VA_ARGS__)) +#define DN_FArray_AddCArrayAssert(...) DN_HARD_ASSERT(DN_FArray_AddCArray(__VA_ARGS__)) +#define DN_FArray_AddAssert(...) DN_HARD_ASSERT(DN_FArray_Add(__VA_ARGS__)) +template T * DN_FArray_MakeArray (DN_FArray *array, DN_USize count, DN_ZeroMem zero_mem); +template T * DN_FArray_Make (DN_FArray *array, DN_ZeroMem zero_mem); +#define DN_FArray_MakeArrayAssert(...) DN_HARD_ASSERT(DN_FArray_MakeArray(__VA_ARGS__)) +#define DN_FArray_MakeAssert(...) DN_HARD_ASSERT(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_HARD_ASSERT(DN_FArray_InsertArray(__VA_ARGS__)) +#define DN_FArray_InsertAssert(...) DN_HARD_ASSERT(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) +#if !defined(DN_NO_SLICE) +#define DN_TO_SLICE(val) DN_Slice_Init((val)->data, (val)->size) +template DN_Slice DN_Slice_Init (T* const data, DN_USize size); +template DN_Slice DN_Slice_InitCArray (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_ZeroMem zero_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) +#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_ZeroMem zero_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 Dqn_ArrayEraseResult Dqn_CArray_EraseRange (T *data, Dqn_usize *size, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase); -template T * Dqn_CArray_MakeArray (T *data, Dqn_usize *size, Dqn_usize max, Dqn_usize count, Dqn_ZeroMem zero_mem); -template T * Dqn_CArray_InsertArray (T *data, Dqn_usize *size, Dqn_usize max, Dqn_usize index, T const *items, Dqn_usize count); -template T Dqn_CArray_PopFront (T *data, Dqn_usize *size, Dqn_usize count); -template T Dqn_CArray_PopBack (T *data, Dqn_usize *size, Dqn_usize count); -template Dqn_ArrayFindResult Dqn_CArray_Find (T *data, Dqn_usize size, T const &value); - -#if !defined(DQN_NO_VARRAY) -template Dqn_VArray Dqn_VArray_InitByteSize (Dqn_usize byte_size, uint8_t arena_flags); -template Dqn_VArray Dqn_VArray_Init (Dqn_usize max, uint8_t arena_flags); -template Dqn_VArray Dqn_VArray_InitSlice (Dqn_Slice slice, Dqn_usize max, uint8_t arena_flags); -template Dqn_VArray Dqn_VArray_InitCArray (T const (&items)[N], Dqn_usize max, uint8_t arena_flags); -template void Dqn_VArray_Deinit (Dqn_VArray *array); -template bool Dqn_VArray_IsValid (Dqn_VArray const *array); -template Dqn_Slice Dqn_VArray_Slice (Dqn_VArray const *array); -template bool Dqn_VArray_Reserve (Dqn_VArray *array, Dqn_usize count); -template T * Dqn_VArray_AddArray (Dqn_VArray *array, T const *items, Dqn_usize count); -template T * Dqn_VArray_AddCArray (Dqn_VArray *array, T const (&items)[N]); -template T * Dqn_VArray_Add (Dqn_VArray *array, T const &item); -#define Dqn_VArray_AddArrayAssert(...) DQN_HARD_ASSERT(Dqn_VArray_AddArray(__VA_ARGS__)) -#define Dqn_VArray_AddCArrayAssert(...) DQN_HARD_ASSERT(Dqn_VArray_AddCArray(__VA_ARGS__)) -#define Dqn_VArray_AddAssert(...) DQN_HARD_ASSERT(Dqn_VArray_Add(__VA_ARGS__)) -template T * Dqn_VArray_MakeArray (Dqn_VArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem); -template T * Dqn_VArray_Make (Dqn_VArray *array, Dqn_ZeroMem zero_mem); -#define Dqn_VArray_MakeArrayAssert(...) DQN_HARD_ASSERT(Dqn_VArray_MakeArray(__VA_ARGS__)) -#define Dqn_VArray_MakeAssert(...) DQN_HARD_ASSERT(Dqn_VArray_Make(__VA_ARGS__)) -template T * Dqn_VArray_InsertArray (Dqn_VArray *array, Dqn_usize index, T const *items, Dqn_usize count); -template T * Dqn_VArray_InsertCArray (Dqn_VArray *array, Dqn_usize index, T const (&items)[N]); -template T * Dqn_VArray_Insert (Dqn_VArray *array, Dqn_usize index, T const &item); -#define Dqn_VArray_InsertArrayAssert(...) DQN_HARD_ASSERT(Dqn_VArray_InsertArray(__VA_ARGS__)) -#define Dqn_VArray_InsertCArrayAssert(...) DQN_HARD_ASSERT(Dqn_VArray_InsertCArray(__VA_ARGS__)) -#define Dqn_VArray_InsertAssert(...) DQN_HARD_ASSERT(Dqn_VArray_Insert(__VA_ARGS__)) -template T Dqn_VArray_PopFront (Dqn_VArray *array, Dqn_usize count); -template T Dqn_VArray_PopBack (Dqn_VArray *array, Dqn_usize count); -template Dqn_ArrayEraseResult Dqn_VArray_EraseRange (Dqn_VArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase); -template void Dqn_VArray_Clear (Dqn_VArray *array, Dqn_ZeroMem zero_mem); -#endif // !defined(DQN_NO_VARRAY) -// NOTE: [$SARR] Dqn_SArray //////////////////////////////////////////////////////////////////////// -#if !defined(DQN_NO_SARRAY) -template Dqn_SArray Dqn_SArray_Init (Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem); -template Dqn_SArray Dqn_SArray_InitSlice (Dqn_Arena *arena, Dqn_Slice slice, Dqn_usize size, Dqn_ZeroMem zero_mem); -template Dqn_SArray Dqn_SArray_InitCArray (Dqn_Arena *arena, T const (&array)[N], Dqn_usize size, Dqn_ZeroMem); -template bool Dqn_SArray_IsValid (Dqn_SArray const *array); -template Dqn_Slice Dqn_SArray_Slice (Dqn_SArray const *array); -template T * Dqn_SArray_AddArray (Dqn_SArray *array, T const *items, Dqn_usize count); -template T * Dqn_SArray_AddCArray (Dqn_SArray *array, T const (&items)[N]); -template T * Dqn_SArray_Add (Dqn_SArray *array, T const &item); -#define Dqn_SArray_AddArrayAssert(...) DQN_HARD_ASSERT(Dqn_SArray_AddArray(__VA_ARGS__)) -#define Dqn_SArray_AddCArrayAssert(...) DQN_HARD_ASSERT(Dqn_SArray_AddCArray(__VA_ARGS__)) -#define Dqn_SArray_AddAssert(...) DQN_HARD_ASSERT(Dqn_SArray_Add(__VA_ARGS__)) -template T * Dqn_SArray_MakeArray (Dqn_SArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem); -template T * Dqn_SArray_Make (Dqn_SArray *array, Dqn_ZeroMem zero_mem); -#define Dqn_SArray_MakeArrayAssert(...) DQN_HARD_ASSERT(Dqn_SArray_MakeArray(__VA_ARGS__)) -#define Dqn_SArray_MakeAssert(...) DQN_HARD_ASSERT(Dqn_SArray_Make(__VA_ARGS__)) -template T * Dqn_SArray_InsertArray (Dqn_SArray *array, Dqn_usize index, T const *items, Dqn_usize count); -template T * Dqn_SArray_InsertCArray (Dqn_SArray *array, Dqn_usize index, T const (&items)[N]); -template T * Dqn_SArray_Insert (Dqn_SArray *array, Dqn_usize index, T const &item); -#define Dqn_SArray_InsertArrayAssert(...) DQN_HARD_ASSERT(Dqn_SArray_InsertArray(__VA_ARGS__)) -#define Dqn_SArray_InsertCArrayAssert(...) DQN_HARD_ASSERT(Dqn_SArray_InsertCArray(__VA_ARGS__)) -#define Dqn_SArray_InsertAssert(...) DQN_HARD_ASSERT(Dqn_SArray_Insert(__VA_ARGS__)) -template T Dqn_SArray_PopFront (Dqn_SArray *array, Dqn_usize count); -template T Dqn_SArray_PopBack (Dqn_SArray *array, Dqn_usize count); -template Dqn_ArrayEraseResult Dqn_SArray_EraseRange (Dqn_SArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase); -template void Dqn_SArray_Clear (Dqn_SArray *array); -#endif // !defined(DQN_NO_SARRAY) -#if !defined(DQN_NO_FARRAY) -template Dqn_FArray Dqn_FArray_Init (T const *array, Dqn_usize count); -#define Dqn_FArray_HasData(array) ((array).data && (array).size) -template Dqn_FArray Dqn_FArray_InitSlice (Dqn_Slice slice); -template Dqn_FArray Dqn_FArray_InitCArray (T const (&items)[K]); -template bool Dqn_FArray_IsValid (Dqn_FArray const *array); -template Dqn_usize Dqn_FArray_Max (Dqn_FArray const *) { return N; } -template Dqn_Slice Dqn_FArray_Slice (Dqn_FArray const *array); -template T * Dqn_FArray_AddArray (Dqn_FArray *array, T const *items, Dqn_usize count); -template T * Dqn_FArray_AddCArray (Dqn_FArray *array, T const (&items)[K]); -template T * Dqn_FArray_Add (Dqn_FArray *array, T const &item); -#define Dqn_FArray_AddArrayAssert(...) DQN_HARD_ASSERT(Dqn_FArray_AddArray(__VA_ARGS__)) -#define Dqn_FArray_AddCArrayAssert(...) DQN_HARD_ASSERT(Dqn_FArray_AddCArray(__VA_ARGS__)) -#define Dqn_FArray_AddAssert(...) DQN_HARD_ASSERT(Dqn_FArray_Add(__VA_ARGS__)) -template T * Dqn_FArray_MakeArray (Dqn_FArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem); -template T * Dqn_FArray_Make (Dqn_FArray *array, Dqn_ZeroMem zero_mem); -#define Dqn_FArray_MakeArrayAssert(...) DQN_HARD_ASSERT(Dqn_FArray_MakeArray(__VA_ARGS__)) -#define Dqn_FArray_MakeAssert(...) DQN_HARD_ASSERT(Dqn_FArray_Make(__VA_ARGS__)) -template T * Dqn_FArray_InsertArray (Dqn_FArray *array, T const &item, Dqn_usize index); -template T * Dqn_FArray_InsertCArray (Dqn_FArray *array, Dqn_usize index, T const (&items)[K]); -template T * Dqn_FArray_Insert (Dqn_FArray *array, Dqn_usize index, T const &item); -#define Dqn_FArray_InsertArrayAssert(...) DQN_HARD_ASSERT(Dqn_FArray_InsertArray(__VA_ARGS__)) -#define Dqn_FArray_InsertAssert(...) DQN_HARD_ASSERT(Dqn_FArray_Insert(__VA_ARGS__)) -template T Dqn_FArray_PopFront (Dqn_FArray *array, Dqn_usize count); -template T Dqn_FArray_PopBack (Dqn_FArray *array, Dqn_usize count); -template Dqn_ArrayFindResult Dqn_FArray_Find (Dqn_FArray *array, T const &find); -template Dqn_ArrayEraseResult Dqn_FArray_EraseRange (Dqn_FArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase); -template void Dqn_FArray_Clear (Dqn_FArray *array); -#endif // !defined(DQN_NO_FARRAY) -#if !defined(DQN_NO_SLICE) -#define DQN_TO_SLICE(val) Dqn_Slice_Init((val)->data, (val)->size) -template Dqn_Slice Dqn_Slice_Init (T* const data, Dqn_usize size); -template Dqn_Slice Dqn_Slice_InitCArray (Dqn_Arena *arena, T const (&array)[N]); -template Dqn_Slice Dqn_Slice_Copy (Dqn_Arena *arena, Dqn_Slice slice); -template Dqn_Slice Dqn_Slice_CopyPtr (Dqn_Arena *arena, T* const data, Dqn_usize size); -template Dqn_Slice Dqn_Slice_Alloc (Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem); - Dqn_Str8 Dqn_Slice_Str8Render (Dqn_Arena *arena, Dqn_Slice array, Dqn_Str8 separator); - Dqn_Str8 Dqn_Slice_Str8RenderSpaceSeparated (Dqn_Arena *arena, Dqn_Slice array); - Dqn_Str16 Dqn_Slice_Str16Render (Dqn_Arena *arena, Dqn_Slice array, Dqn_Str16 separator); - Dqn_Str16 Dqn_Slice_Str16RenderSpaceSeparated(Dqn_Arena *arena, Dqn_Slice array); -#endif // !defined(DQN_NO_SLICE) -#if !defined(DQN_NO_DSMAP) -template Dqn_DSMap Dqn_DSMap_Init (Dqn_Arena *arena, uint32_t size, Dqn_DSMapFlags flags); -template void Dqn_DSMap_Deinit (Dqn_DSMap *map, Dqn_ZeroMem zero_mem); -template bool Dqn_DSMap_IsValid (Dqn_DSMap const *map); -template uint32_t Dqn_DSMap_Hash (Dqn_DSMap const *map, Dqn_DSMapKey key); -template uint32_t Dqn_DSMap_HashToSlotIndex (Dqn_DSMap const *map, Dqn_DSMapKey key); -template Dqn_DSMapResult Dqn_DSMap_Find (Dqn_DSMap const *map, Dqn_DSMapKey key); -template Dqn_DSMapResult Dqn_DSMap_Make (Dqn_DSMap *map, Dqn_DSMapKey key); -template Dqn_DSMapResult Dqn_DSMap_Set (Dqn_DSMap *map, Dqn_DSMapKey key, T const &value); -template Dqn_DSMapResult Dqn_DSMap_FindKeyU64 (Dqn_DSMap const *map, uint64_t key); -template Dqn_DSMapResult Dqn_DSMap_MakeKeyU64 (Dqn_DSMap *map, uint64_t key); -template Dqn_DSMapResult Dqn_DSMap_SetKeyU64 (Dqn_DSMap *map, uint64_t key, T const &value); -template Dqn_DSMapResult Dqn_DSMap_FindKeyStr8 (Dqn_DSMap const *map, Dqn_Str8 key); -template Dqn_DSMapResult Dqn_DSMap_MakeKeyStr8 (Dqn_DSMap *map, Dqn_Str8 key); -template Dqn_DSMapResult Dqn_DSMap_SetKeyStr8 (Dqn_DSMap *map, Dqn_Str8 key, T const &value); -template bool Dqn_DSMap_Resize (Dqn_DSMap *map, uint32_t size); -template bool Dqn_DSMap_Erase (Dqn_DSMap *map, Dqn_DSMapKey key); -template Dqn_DSMapKey Dqn_DSMap_KeyBuffer (Dqn_DSMap const *map, void const *data, uint32_t size); -template Dqn_DSMapKey Dqn_DSMap_KeyBufferAsU64NoHash (Dqn_DSMap const *map, void const *data, uint32_t size); -template Dqn_DSMapKey Dqn_DSMap_KeyU64 (Dqn_DSMap const *map, uint64_t u64); -template Dqn_DSMapKey Dqn_DSMap_KeyStr8 (Dqn_DSMap const *map, Dqn_Str8 string); -#define Dqn_DSMap_KeyCStr8(map, string) Dqn_DSMap_KeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1) -DQN_API Dqn_DSMapKey Dqn_DSMap_KeyU64NoHash (uint64_t u64); -DQN_API bool Dqn_DSMap_KeyEquals (Dqn_DSMapKey lhs, Dqn_DSMapKey rhs); -DQN_API bool operator== (Dqn_DSMapKey lhs, Dqn_DSMapKey rhs); -#endif // !defined(DQN_NO_DSMAP) -#if !defined(DQN_NO_LIST) -template Dqn_List Dqn_List_Init (Dqn_usize chunk_size); -template Dqn_List Dqn_List_InitCArray (Dqn_Arena *arena, Dqn_usize chunk_size, T const (&array)[N]); -template T * Dqn_List_At (Dqn_List *list, Dqn_usize index, Dqn_ListChunk *at_chunk); -template bool Dqn_List_Iterate (Dqn_List *list, Dqn_ListIterator *it, Dqn_usize start_index); -template T * Dqn_List_MakeArena (Dqn_List *list, Dqn_Arena *arena, Dqn_usize count); -template T * Dqn_List_MakePool (Dqn_List *list, Dqn_ChunkPool *pool, Dqn_usize count); -template T * Dqn_List_AddArena (Dqn_List *list, Dqn_Arena *arena, T const &value); -template T * Dqn_List_AddPool (Dqn_List *list, Dqn_ChunkPool *pool, T const &value); -template void Dqn_List_AddListArena (Dqn_List *list, Dqn_Arena *arena, Dqn_List other); -template void Dqn_List_AddListArena (Dqn_List *list, Dqn_ChunkPool *pool, Dqn_List other); -template Dqn_Slice Dqn_List_ToSliceCopy (Dqn_List const *list, Dqn_Arena* arena); -#endif // !defined(DQN_NO_LIST) - -// NOTE: [$CARR] Dqn_CArray //////////////////////////////////////////////////////////////////////// -template Dqn_ArrayEraseResult Dqn_CArray_EraseRange(T* data, Dqn_usize *size, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase) -{ - Dqn_ArrayEraseResult result = {}; - if (!data || !size || *size == 0 || count == 0) - return result; - - DQN_ASSERTF(count != -1, "There's a bug with negative element erases, see the Dqn_VArray section in dqn_docs.cpp"); - - // 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.items_erased = erase_count; - result.it_index = begin_index; - return result; -} - -template T *Dqn_CArray_MakeArray(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 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 (zero_mem == Dqn_ZeroMem_Yes) - DQN_MEMSET(result, 0, sizeof(*result) * count); - return result; -} - -template T *Dqn_CArray_InsertArray(T *data, Dqn_usize *size, Dqn_usize max, Dqn_usize index, T const *items, Dqn_usize count) -{ - T *result = nullptr; - if (!data || !size || !items || count <= 0 || ((*size + count) > max)) - return result; - - Dqn_usize clamped_index = DQN_MIN(index, *size); - if (clamped_index != *size) { - char const *src = DQN_CAST(char *)(data + clamped_index); - char const *dest = DQN_CAST(char *)(data + (clamped_index + count)); - char const *end = DQN_CAST(char *)(data + (*size)); - Dqn_usize bytes_to_move = end - src; - DQN_MEMMOVE(DQN_CAST(void *) dest, src, bytes_to_move); - } - - result = data + clamped_index; - DQN_MEMCPY(result, items, sizeof(T) * count); - *size += count; - return result; -} - -template T Dqn_CArray_PopFront(T* data, Dqn_usize *size, Dqn_usize count) -{ - T result = {}; - if (!data || !size || *size <= 0) - return result; - - result = data[0]; - Dqn_usize pop_count = DQN_MIN(count, *size); - DQN_MEMMOVE(data, data + pop_count, (*size - pop_count) * sizeof(T)); - *size -= pop_count; - return result; -} - -template T Dqn_CArray_PopBack(T* data, Dqn_usize *size, Dqn_usize count) -{ - T result = {}; - if (!data || !size || *size <= 0) - return result; - - Dqn_usize pop_count = DQN_MIN(count, *size); - result = data[(*size - 1)]; - *size -= pop_count; - return result; -} - -template Dqn_ArrayFindResult Dqn_CArray_Find(T *data, Dqn_usize size, T const &value) -{ - Dqn_ArrayFindResult result = {}; - if (!data || size <= 0) - return result; - - for (Dqn_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(DQN_NO_VARRAY) -// NOTE: [$VARR] Dqn_VArray //////////////////////////////////////////////////////////////////////// -template Dqn_VArray Dqn_VArray_InitByteSize(Dqn_usize byte_size, uint8_t arena_flags) -{ - Dqn_VArray result = {}; - result.arena = Dqn_Arena_InitSize(DQN_ARENA_HEADER_SIZE + byte_size, 0 /*commit*/, arena_flags | Dqn_ArenaFlag_NoGrow | Dqn_ArenaFlag_NoPoison); - if (result.arena.curr) { - result.data = DQN_CAST(T *)(DQN_CAST(char *)result.arena.curr + result.arena.curr->used); - result.max = (result.arena.curr->reserve - result.arena.curr->used) / sizeof(T); - } - return result; -} - -template Dqn_VArray Dqn_VArray_Init(Dqn_usize max, uint8_t arena_flags) -{ - Dqn_VArray result = Dqn_VArray_InitByteSize(max * sizeof(T), arena_flags); - DQN_ASSERT(result.max >= max); - return result; -} - -template Dqn_VArray Dqn_VArray_InitSlice(Dqn_Slice slice, Dqn_usize max, uint8_t arena_flags) -{ - Dqn_usize real_max = DQN_MAX(slice.size, max); - Dqn_VArray result = Dqn_VArray_Init(real_max, arena_flags); - if (Dqn_VArray_IsValid(&result)) - Dqn_VArray_AddArray(&result, slice.data, slice.size); - return result; -} - -template Dqn_VArray Dqn_VArray_InitCArray(T const (&items)[N], Dqn_usize max, uint8_t arena_flags) -{ - Dqn_usize real_max = DQN_MAX(N, max); - Dqn_VArray result = Dqn_VArray_InitSlice(Dqn_Slice_Init(items, N), real_max, arena_flags); - return result; -} - -template void Dqn_VArray_Deinit(Dqn_VArray *array) -{ - Dqn_Arena_Deinit(&array->arena); - *array = {}; -} - -template bool Dqn_VArray_IsValid(Dqn_VArray const *array) -{ - bool result = array && array->data && array->size <= array->max && array->arena.curr; - return result; -} - -template Dqn_Slice Dqn_VArray_Slice(Dqn_VArray const *array) -{ - Dqn_Slice result = {}; - if (array) - result = Dqn_Slice_Init(array->data, array->size); - return result; -} - -template T *Dqn_VArray_AddArray(Dqn_VArray *array, T const *items, Dqn_usize count) -{ - T *result = Dqn_VArray_MakeArray(array, count, Dqn_ZeroMem_No); - if (result) - DQN_MEMCPY(result, items, count * sizeof(T)); - return result; -} - -template T *Dqn_VArray_AddCArray(Dqn_VArray *array, T const (&items)[N]) -{ - T *result = Dqn_VArray_AddArray(array, items, N); - return result; -} - -template T *Dqn_VArray_Add(Dqn_VArray *array, T const &item) -{ - T *result = Dqn_VArray_AddArray(array, &item, 1); - return result; -} - -template T *Dqn_VArray_MakeArray(Dqn_VArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem) -{ - if (!Dqn_VArray_IsValid(array)) - return nullptr; - - if (!DQN_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; - - // TODO: Use placement new? Why doesn't this work? - - uint8_t prev_flags = array->arena.flags; - array->arena.flags |= (Dqn_ArenaFlag_NoGrow | Dqn_ArenaFlag_NoPoison); - T *result = Dqn_Arena_NewArray(&array->arena, T, count, zero_mem); - array->arena.flags = prev_flags; - if (result) - array->size += count; - return result; -} - -template T *Dqn_VArray_Make(Dqn_VArray *array, Dqn_ZeroMem zero_mem) -{ - T *result = Dqn_VArray_MakeArray(array, 1, zero_mem); - return result; -} - -template T *Dqn_VArray_InsertArray(Dqn_VArray *array, Dqn_usize index, T const *items, Dqn_usize count) -{ - T *result = nullptr; - if (!Dqn_VArray_IsValid(array)) - return result; - if (Dqn_VArray_Reserve(array, array->size + count)) - result = Dqn_CArray_InsertArray(array->data, &array->size, array->max, index, items, count); - return result; -} - -template T *Dqn_VArray_InsertCArray(Dqn_VArray *array, Dqn_usize index, T const (&items)[N]) -{ - T *result = Dqn_VArray_InsertArray(array, index, items, N); - return result; -} - -template T *Dqn_VArray_Insert(Dqn_VArray *array, Dqn_usize index, T const &item) -{ - T *result = Dqn_VArray_InsertArray(array, index, &item, 1); - return result; -} - -template T *Dqn_VArray_PopFront(Dqn_VArray *array, Dqn_usize count) -{ - T *result = Dqn_CArray_PopFront(array->data, &array->size, count); - return result; -} - -template T *Dqn_VArray_PopBack(Dqn_VArray *array, Dqn_usize count) -{ - T *result = Dqn_CArray_PopBack(array->data, &array->size, count); - return result; -} - -template Dqn_ArrayEraseResult Dqn_VArray_EraseRange(Dqn_VArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase) -{ - Dqn_ArrayEraseResult result = {}; - if (!Dqn_VArray_IsValid(array)) - return result; - result = Dqn_CArray_EraseRange(array->data, &array->size, begin_index, count, erase); - Dqn_Arena_Pop(&array->arena, result.items_erased * sizeof(T)); - return result; -} - -template void Dqn_VArray_Clear(Dqn_VArray *array, Dqn_ZeroMem zero_mem) -{ - if (array) { - if (zero_mem == Dqn_ZeroMem_Yes) - DQN_MEMSET(array->data, 0, array->size * sizeof(T)); - Dqn_Arena_PopTo(&array->arena, 0); - array->size = 0; - } -} - -template bool Dqn_VArray_Reserve(Dqn_VArray *array, Dqn_usize count) -{ - if (!Dqn_VArray_IsValid(array) || count == 0) - return false; - bool result = Dqn_Arena_CommitTo(&array->arena, DQN_ARENA_HEADER_SIZE + (count * sizeof(T))); - return result; -} -#endif // !defined(DQN_NO_VARRAY) - -#if !defined(DQN_NO_SARRAY) -// NOTE: [$SARR] Dqn_SArray //////////////////////////////////////////////////////////////////////// -template Dqn_SArray Dqn_SArray_Init(Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem) -{ - Dqn_SArray result = {}; - if (!arena || !size) - return result; - result.data = Dqn_Arena_NewArray(arena, T, size, zero_mem); - if (result.data) - result.max = size; - return result; -} - -template Dqn_SArray Dqn_SArray_InitSlice(Dqn_Arena *arena, Dqn_Slice slice, Dqn_usize size, Dqn_ZeroMem zero_mem) -{ - Dqn_usize max = DQN_MAX(slice.size, size); - Dqn_SArray result = Dqn_SArray_Init(arena, max, Dqn_ZeroMem_No); - if (Dqn_SArray_IsValid(&result)) { - Dqn_SArray_AddArray(&result, slice.data, slice.size); - if (zero_mem == Dqn_ZeroMem_Yes) - DQN_MEMSET(result.data + result.size, 0, (result.max - result.size) * sizeof(T)); - } - return result; -} - -template Dqn_SArray Dqn_SArray_InitCArray(Dqn_Arena *arena, T const (&array)[N], Dqn_usize size, Dqn_ZeroMem zero_mem) -{ - Dqn_SArray result = Dqn_SArray_InitSlice(arena, Dqn_Slice_Init(DQN_CAST(T *)array, N), size, zero_mem); - return result; -} - -template bool Dqn_SArray_IsValid(Dqn_SArray const *array) -{ - bool result = array && array->data && array->size <= array->max; - return result; -} - -template Dqn_Slice Dqn_SArray_Slice(Dqn_SArray const *array) -{ - Dqn_Slice result = {}; - if (array) - result = Dqn_Slice_Init(DQN_CAST(T *)array->data, array->size); - return result; -} - -template T *Dqn_SArray_MakeArray(Dqn_SArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem) -{ - if (!Dqn_SArray_IsValid(array)) - return nullptr; - T *result = Dqn_CArray_MakeArray(array->data, &array->size, array->max, count, zero_mem); - return result; -} - -template T *Dqn_SArray_Make(Dqn_SArray *array, Dqn_ZeroMem zero_mem) -{ - T *result = Dqn_SArray_MakeArray(array, 1, zero_mem); - return result; -} - -template T *Dqn_SArray_AddArray(Dqn_SArray *array, T const *items, Dqn_usize count) -{ - T *result = Dqn_SArray_MakeArray(array, count, Dqn_ZeroMem_No); - if (result) - DQN_MEMCPY(result, items, count * sizeof(T)); - return result; -} - -template T *Dqn_SArray_AddCArray(Dqn_SArray *array, T const (&items)[N]) -{ - T *result = Dqn_SArray_AddArray(array, items, N); - return result; -} - -template T *Dqn_SArray_Add(Dqn_SArray *array, T const &item) -{ - T *result = Dqn_SArray_AddArray(array, &item, 1); - return result; -} - -template T *Dqn_SArray_InsertArray(Dqn_SArray *array, Dqn_usize index, T const *items, Dqn_usize count) -{ - T *result = nullptr; - if (!Dqn_SArray_IsValid(array)) - return result; - result = Dqn_CArray_InsertArray(array->data, &array->size, array->max, index, items, count); - return result; -} - -template T *Dqn_SArray_InsertCArray(Dqn_SArray *array, Dqn_usize index, T const (&items)[N]) -{ - T *result = Dqn_SArray_InsertArray(array, index, items, N); - return result; -} - -template T *Dqn_SArray_Insert(Dqn_SArray *array, Dqn_usize index, T const &item) -{ - T *result = Dqn_SArray_InsertArray(array, index, &item, 1); - return result; -} - -template T Dqn_SArray_PopFront(Dqn_SArray *array, Dqn_usize count) -{ - T result = Dqn_CArray_PopFront(array->data, &array->size, count); - return result; -} - -template T Dqn_SArray_PopBack(Dqn_SArray *array, Dqn_usize count) -{ - T result = Dqn_CArray_PopBack(array->data, &array->size, count); - return result; -} - -template Dqn_ArrayEraseResult Dqn_SArray_EraseRange(Dqn_SArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase) -{ - Dqn_ArrayEraseResult result = {}; - if (!Dqn_SArray_IsValid(array) || array->size == 0 || count == 0) - return result; - result = Dqn_CArray_EraseRange(array->data, &array->size, begin_index, count, erase); - return result; -} - -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 //////////////////////////////////////////////////////////////////////// -template Dqn_FArray Dqn_FArray_Init(T const *array, Dqn_usize count) -{ - Dqn_FArray result = {}; - bool added = Dqn_FArray_AddArray(&result, array, count); - DQN_ASSERT(added); - return result; -} - -template Dqn_FArray Dqn_FArray_InitSlice(Dqn_Slice slice) -{ - Dqn_FArray result = Dqn_FArray_Init(slice.data, slice.size); - return result; -} - -template Dqn_FArray Dqn_FArray_InitCArray(T const (&items)[K]) -{ - Dqn_FArray result = Dqn_FArray_Init(items, K); - return result; -} - -template bool Dqn_FArray_IsValid(Dqn_FArray const *array) -{ - bool result = array && array->size <= DQN_ARRAY_UCOUNT(array->data); - return result; -} - -template Dqn_Slice Dqn_FArray_Slice(Dqn_FArray const *array) -{ - Dqn_Slice result = {}; - if (array) - result = Dqn_Slice_Init(DQN_CAST(T *)array->data, array->size); - return result; -} - -template T *Dqn_FArray_AddArray(Dqn_FArray *array, T const *items, Dqn_usize count) -{ - T *result = Dqn_FArray_MakeArray(array, count, Dqn_ZeroMem_No); - if (result) - DQN_MEMCPY(result, items, count * sizeof(T)); - return result; -} - -template T *Dqn_FArray_AddCArray(Dqn_FArray *array, T const (&items)[K]) -{ - T *result = Dqn_FArray_MakeArray(array, K, Dqn_ZeroMem_No); - if (result) - DQN_MEMCPY(result, items, K * sizeof(T)); - return result; -} - -template T *Dqn_FArray_Add(Dqn_FArray *array, T const &item) -{ - T *result = Dqn_FArray_AddArray(array, &item, 1); - return result; -} - -template T *Dqn_FArray_MakeArray(Dqn_FArray *array, Dqn_usize count, Dqn_ZeroMem zero_mem) -{ - if (!Dqn_FArray_IsValid(array)) - return nullptr; - T *result = Dqn_CArray_MakeArray(array->data, &array->size, N, count, zero_mem); - return result; -} - -template T *Dqn_FArray_Make(Dqn_FArray *array, Dqn_ZeroMem zero_mem) -{ - T *result = Dqn_FArray_MakeArray(array, 1, zero_mem); - return result; -} - -template T *Dqn_FArray_InsertArray(Dqn_FArray *array, Dqn_usize index, T const *items, Dqn_usize count) -{ - T *result = nullptr; - if (!Dqn_FArray_IsValid(array)) - return result; - result = Dqn_CArray_InsertArray(array->data, &array->size, N, index, items, count); - return result; -} - -template T *Dqn_FArray_InsertCArray(Dqn_FArray *array, Dqn_usize index, T const (&items)[K]) -{ - T *result = Dqn_FArray_InsertArray(array, index, items, K); - return result; -} - -template T *Dqn_FArray_Insert(Dqn_FArray *array, Dqn_usize index, T const &item) -{ - T *result = Dqn_FArray_InsertArray(array, index, &item, 1); - return result; -} - -template T Dqn_FArray_PopFront(Dqn_FArray *array, Dqn_usize count) -{ - T result = Dqn_CArray_PopFront(array->data, &array->size, count); - return result; -} - -template T Dqn_FArray_PopBack(Dqn_FArray *array, Dqn_usize count) -{ - T result = Dqn_CArray_PopBack(array->data, &array->size, count); - return result; -} - -template Dqn_ArrayFindResult Dqn_FArray_Find(Dqn_FArray *array, T const &find) -{ - Dqn_ArrayFindResult result = Dqn_CArray_Find(array->data, array->size, find); - return result; -} - -template Dqn_ArrayEraseResult Dqn_FArray_EraseRange(Dqn_FArray *array, Dqn_usize begin_index, Dqn_isize count, Dqn_ArrayErase erase) -{ - Dqn_ArrayEraseResult result = {}; - if (!Dqn_FArray_IsValid(array) || array->size == 0 || count == 0) - return result; - result = Dqn_CArray_EraseRange(array->data, &array->size, begin_index, count, erase); - return result; -} - -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_InitCArray(Dqn_Arena *arena, T const (&array)[N]) -{ - Dqn_Slice result = Dqn_Slice_Alloc(arena, N, Dqn_ZeroMem_No); - if (result.data) - DQN_MEMCPY(result.data, array, sizeof(T) * N); - return result; -} - -template Dqn_Slice Dqn_Slice_CopyPtr(Dqn_Arena *arena, T *const data, Dqn_usize size) -{ - T *copy = Dqn_Arena_NewArrayCopy(arena, T, data, size); - Dqn_Slice result = Dqn_Slice_Init(copy, copy ? size : 0); - return result; -} - -template Dqn_Slice Dqn_Slice_Copy(Dqn_Arena *arena, Dqn_Slice slice) -{ - Dqn_Slice result = Dqn_Slice_CopyPtr(arena, slice.data, slice.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; -uint32_t const DQN_DS_MAP_SENTINEL_SLOT = 0; - -template Dqn_DSMap Dqn_DSMap_Init(Dqn_Arena *arena, uint32_t size, Dqn_DSMapFlags flags) -{ - Dqn_DSMap result = {}; - if (!DQN_CHECKF(Dqn_IsPowerOfTwo(size), "Power-of-two size required, given size was '%u'", size)) - return result; - if (!DQN_CHECKF(size > 0, "Non-zero size must be given")) - return result; - if (!DQN_CHECK(arena)) - return result; - result.arena = arena; - result.hash_to_slot = Dqn_Arena_NewArray(result.arena, uint32_t, size, Dqn_ZeroMem_Yes); - result.slots = Dqn_Arena_NewArray(result.arena, Dqn_DSMapSlot, size, Dqn_ZeroMem_Yes); - result.occupied = 1; // For sentinel - result.size = size; - result.initial_size = size; - result.flags = flags; - DQN_ASSERTF(result.hash_to_slot && result.slots, "We pre-allocated a block of memory sufficient in size for the 2 arrays. Maybe the pointers needed extra space because of natural alignment?"); - return result; -} - -template -void Dqn_DSMap_Deinit(Dqn_DSMap *map, Dqn_ZeroMem zero_mem) -{ - if (!map) - return; - // TODO(doyle): Use zero_mem - (void)zero_mem; - Dqn_Arena_Deinit(map->arena); - *map = {}; -} - -template -bool Dqn_DSMap_IsValid(Dqn_DSMap const *map) -{ - bool result = map && - map->arena && - map->hash_to_slot && // Hash to slot mapping array must be allocated - map->slots && // Slots array must be allocated - (map->size & (map->size - 1)) == 0 && // Must be power of two size - map->occupied >= 1; // DQN_DS_MAP_SENTINEL_SLOT takes up one slot - return result; -} - -template -uint32_t Dqn_DSMap_Hash(Dqn_DSMap const *map, Dqn_DSMapKey key) -{ - uint32_t result = 0; - if (!map) - return result; - - if (key.type == Dqn_DSMapKeyType_U64NoHash) { - result = DQN_CAST(uint32_t)key.u64; - return result; - } - - if (key.type == Dqn_DSMapKeyType_BufferAsU64NoHash) { - result = key.hash; - return result; - } - - uint32_t seed = map->hash_seed ? map->hash_seed : DQN_DS_MAP_DEFAULT_HASH_SEED; - if (map->hash_function) { - map->hash_function(key, seed); - } else { - // NOTE: Courtesy of Demetri Spanos (which this hash table was inspired - // from), the following is a hashing function snippet provided for - // reliable, quick and simple quality hashing functions for hash table - // use. - // Source: https://github.com/demetri/scribbles/blob/c475464756c104c91bab83ed4e14badefef12ab5/hashing/ub_aware_hash_functions.c - - char const *key_ptr = nullptr; - uint32_t len = 0; - uint32_t h = seed; - switch (key.type) { - case Dqn_DSMapKeyType_BufferAsU64NoHash: /*FALLTHRU*/ - case Dqn_DSMapKeyType_U64NoHash: DQN_INVALID_CODE_PATH; /*FALLTHRU*/ - case Dqn_DSMapKeyType_Invalid: break; - - case Dqn_DSMapKeyType_Buffer: - key_ptr = DQN_CAST(char const *)key.buffer_data; - len = key.buffer_size; - break; - - case Dqn_DSMapKeyType_U64: - key_ptr = DQN_CAST(char const *)&key.u64; - len = sizeof(key.u64); - break; - } - - // Murmur3 32-bit without UB unaligned accesses - // uint32_t mur3_32_no_UB(const void *key, int len, uint32_t h) - - // main body, work on 32-bit blocks at a time - for (uint32_t i = 0; i < len / 4; i++) { - uint32_t k; - memcpy(&k, &key_ptr[i * 4], sizeof(k)); - - k *= 0xcc9e2d51; - k = ((k << 15) | (k >> 17)) * 0x1b873593; - h = (((h ^ k) << 13) | ((h ^ k) >> 19)) * 5 + 0xe6546b64; - } - - // load/mix up to 3 remaining tail bytes into a tail block - uint32_t t = 0; - uint8_t *tail = ((uint8_t *)key_ptr) + 4 * (len / 4); - switch (len & 3) { - case 3: t ^= tail[2] << 16; - case 2: t ^= tail[1] << 8; - case 1: { - t ^= tail[0] << 0; - h ^= ((0xcc9e2d51 * t << 15) | (0xcc9e2d51 * t >> 17)) * 0x1b873593; - } - } - - // finalization mix, including key length - h = ((h ^ len) ^ ((h ^ len) >> 16)) * 0x85ebca6b; - h = (h ^ (h >> 13)) * 0xc2b2ae35; - result = h ^ (h >> 16); - } - return result; -} - -template -uint32_t Dqn_DSMap_HashToSlotIndex(Dqn_DSMap const *map, Dqn_DSMapKey key) -{ - DQN_ASSERT(key.type != Dqn_DSMapKeyType_Invalid); - uint32_t result = DQN_DS_MAP_SENTINEL_SLOT; - if (!Dqn_DSMap_IsValid(map)) - return result; - - result = key.hash & (map->size - 1); - for (;;) { - if (map->hash_to_slot[result] == DQN_DS_MAP_SENTINEL_SLOT) - return result; - - Dqn_DSMapSlot *slot = map->slots + map->hash_to_slot[result]; - if (slot->key.type == Dqn_DSMapKeyType_Invalid || (slot->key.hash == key.hash && slot->key == key)) - return result; - - result = (result + 1) & (map->size - 1); - } -} - -template -Dqn_DSMapResult Dqn_DSMap_Find(Dqn_DSMap const *map, Dqn_DSMapKey key) -{ - Dqn_DSMapResult result = {}; - if (Dqn_DSMap_IsValid(map)) { - uint32_t index = Dqn_DSMap_HashToSlotIndex(map, key); - if (map->hash_to_slot[index] != DQN_DS_MAP_SENTINEL_SLOT) { - result.slot = map->slots + map->hash_to_slot[index]; - result.value = &result.slot->value; - result.found = true; - } - } - return result; -} - -template -Dqn_DSMapResult Dqn_DSMap_Make(Dqn_DSMap *map, Dqn_DSMapKey key) -{ - Dqn_DSMapResult result = {}; - if (!Dqn_DSMap_IsValid(map)) - return result; - - uint32_t index = Dqn_DSMap_HashToSlotIndex(map, key); - if (map->hash_to_slot[index] == DQN_DS_MAP_SENTINEL_SLOT) { - // NOTE: Create the slot - map->hash_to_slot[index] = map->occupied++; - - // NOTE: Check if resize is required - bool map_is_75pct_full = (map->occupied * 4) > (map->size * 3); - if (map_is_75pct_full) { - if (!Dqn_DSMap_Resize(map, map->size * 2)) - return result; - result = Dqn_DSMap_Make(map, key); - } else { - result.slot = map->slots + map->hash_to_slot[index]; - result.slot->key = key; // NOTE: Assign key to new slot - if ((result.slot->key.type == Dqn_DSMapKeyType_Buffer || - result->slot.key.type == Dqn_DSMapKeyType_BufferAsU64NoHash) && - !key.no_copy_buffer) { - result.slot->key.buffer_data = Dqn_Arena_Copy(map->arena, key.buffer_data, key.buffer_size, 1); - } - } - } else { - result.slot = map->slots + map->hash_to_slot[index]; - result.found = true; - } - - result.value = &result.slot->value; - DQN_ASSERT(result.slot->key.type != Dqn_DSMapKeyType_Invalid); - return result; -} - -template -Dqn_DSMapResult Dqn_DSMap_Set(Dqn_DSMap *map, Dqn_DSMapKey key, T const &value) -{ - Dqn_DSMapResult result = {}; - if (!Dqn_DSMap_IsValid(map)) - return result; - - result = Dqn_DSMap_Make(map, key); - result.slot->value = value; - return result; -} - -template -Dqn_DSMapResult Dqn_DSMap_FindKeyU64(Dqn_DSMap const *map, uint64_t key) -{ - Dqn_DSMapKey map_key = Dqn_DSMap_KeyU64(map, key); - Dqn_DSMapResult result = Dqn_DSMap_Find(map, map_key); - return result; -} - -template -Dqn_DSMapResult Dqn_DSMap_MakeKeyU64(Dqn_DSMap *map, uint64_t key) -{ - Dqn_DSMapKey map_key = Dqn_DSMap_KeyU64(map, key); - Dqn_DSMapResult result = Dqn_DSMap_Make(map, map_key); - return result; -} - -template -Dqn_DSMapResult Dqn_DSMap_SetKeyU64(Dqn_DSMap *map, uint64_t key, T const &value) -{ - Dqn_DSMapKey map_key = Dqn_DSMap_KeyU64(map, key); - Dqn_DSMapResult result = Dqn_DSMap_Set(map, map_key, value); - return result; -} - -template -Dqn_DSMapResult Dqn_DSMap_FindKeyStr8(Dqn_DSMap const *map, Dqn_Str8 key) -{ - Dqn_DSMapKey map_key = Dqn_DSMap_KeyStr8(map, key); - Dqn_DSMapResult result = Dqn_DSMap_Find(map, map_key); - return result; -} - -template -Dqn_DSMapResult Dqn_DSMap_MakeKeyStr8(Dqn_DSMap *map, Dqn_Str8 key) -{ - Dqn_DSMapKey map_key = Dqn_DSMap_KeyStr8(map, key); - Dqn_DSMapResult result = Dqn_DSMap_Make(map, map_key); - return result; -} - -template -Dqn_DSMapResult Dqn_DSMap_SetKeyStr8(Dqn_DSMap *map, Dqn_Str8 key, T const &value) -{ - Dqn_DSMapKey map_key = Dqn_DSMap_KeyStr8(map, key); - Dqn_DSMapResult result = Dqn_DSMap_Set(map, map_key); - return result; -} - -template -bool Dqn_DSMap_Resize(Dqn_DSMap *map, uint32_t size) -{ - if (!Dqn_DSMap_IsValid(map) || size < map->occupied || size < map->initial_size) - return false; - - Dqn_Arena *prev_arena = map->arena; - Dqn_Arena new_arena = {}; - new_arena.flags = prev_arena->flags; - - Dqn_DSMap new_map = Dqn_DSMap_Init(&new_arena, size, map->flags); - if (!Dqn_DSMap_IsValid(&new_map)) - return false; - - new_map.initial_size = map->initial_size; - for (uint32_t old_index = 1 /*Sentinel*/; old_index < map->occupied; old_index++) { - Dqn_DSMapSlot *old_slot = map->slots + old_index; - Dqn_DSMapKey old_key = old_slot->key; - if (old_key.type == Dqn_DSMapKeyType_Invalid) - continue; - Dqn_DSMap_Set(&new_map, old_key, old_slot->value); - } - - if ((map->flags & Dqn_DSMapFlags_DontFreeArenaOnResize) == 0) - Dqn_DSMap_Deinit(map, Dqn_ZeroMem_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 - return true; -} - -template -bool Dqn_DSMap_Erase(Dqn_DSMap *map, Dqn_DSMapKey key) -{ - if (!Dqn_DSMap_IsValid(map)) - return false; - - uint32_t index = Dqn_DSMap_HashToSlotIndex(map, key); - uint32_t slot_index = map->hash_to_slot[index]; - if (slot_index == DQN_DS_MAP_SENTINEL_SLOT) - return false; - - // NOTE: Mark the slot as unoccupied - map->hash_to_slot[index] = DQN_DS_MAP_SENTINEL_SLOT; - map->slots[slot_index] = {}; // TODO: Optional? - - if (map->occupied > 1 /*Sentinel*/) { - // NOTE: Repair the hash chain, e.g. rehash all the items after the removed - // element and reposition them if necessary. - for (uint32_t probe_index = index;;) { - probe_index = (probe_index + 1) & (map->size - 1); - if (map->hash_to_slot[probe_index] == DQN_DS_MAP_SENTINEL_SLOT) - break; - - Dqn_DSMapSlot *probe = map->slots + map->hash_to_slot[probe_index]; - uint32_t new_index = probe->key.hash & (map->size - 1); - if (index <= probe_index) { - if (index < new_index && new_index <= probe_index) - continue; - } else { - if (index < new_index || new_index <= probe_index) - continue; - } - - map->hash_to_slot[index] = map->hash_to_slot[probe_index]; - map->hash_to_slot[probe_index] = DQN_DS_MAP_SENTINEL_SLOT; - index = probe_index; - } - - // NOTE: We have erased a slot from the hash table, this leaves a gap - // in our contiguous array. After repairing the chain, the hash mapping - // is correct. - // We will now fill in the vacant spot that we erased using the last - // element in the slot list. - if (map->occupied >= 3 /*Ignoring sentinel, at least 2 other elements to unstable erase*/) { - uint32_t last_index = map->occupied - 1; - if (last_index != slot_index) { - // NOTE: Copy in last slot to the erase slot - Dqn_DSMapSlot *last_slot = map->slots + last_index; - map->slots[slot_index] = *last_slot; - - // NOTE: Update the hash-to-slot mapping for the value that was copied in - uint32_t hash_to_slot_index = Dqn_DSMap_HashToSlotIndex(map, last_slot->key); - map->hash_to_slot[hash_to_slot_index] = slot_index; - *last_slot = {}; // TODO: Optional? - } - } - } - - 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) - Dqn_DSMap_Resize(map, map->size / 2); - - return true; -} - -template -Dqn_DSMapKey Dqn_DSMap_KeyBuffer(Dqn_DSMap const *map, void const *data, Dqn_usize size) -{ - DQN_ASSERT(size > 0 && size <= UINT32_MAX); - Dqn_DSMapKey result = {}; - result.type = Dqn_DSMapKeyType_Buffer; - result.buffer_data = data; - result.buffer_size = DQN_CAST(uint32_t) size; - result.hash = Dqn_DSMap_Hash(map, result); - return result; -} - -template -Dqn_DSMapKey Dqn_DSMap_KeyBufferAsU64NoHash(Dqn_DSMap const *map, void const *data, uint32_t size) -{ - Dqn_DSMapKey result = {}; - result.type = Dqn_DSMapKeyType_BufferAsU64NoHash; - result.buffer_data = data; - result.buffer_size = DQN_CAST(uint32_t) size; - DQN_ASSERT(size >= sizeof(result.hash)); - DQN_MEMCPY(&result.hash, data, sizeof(result.hash)); - return result; -} - -template -Dqn_DSMapKey Dqn_DSMap_KeyU64(Dqn_DSMap const *map, uint64_t u64) -{ - Dqn_DSMapKey result = {}; - result.type = Dqn_DSMapKeyType_U64; - result.u64 = u64; - result.hash = Dqn_DSMap_Hash(map, result); - return result; -} - -template -Dqn_DSMapKey Dqn_DSMap_KeyStr8(Dqn_DSMap const *map, Dqn_Str8 string) -{ - Dqn_DSMapKey result = Dqn_DSMap_KeyBuffer(map, string.data, string.size); - return result; -} -#endif // !defined(DQN_NO_DSMAP) - -#if !defined(DQN_NO_LIST) -// NOTE: [$LIST] Dqn_List ////////////////////////////////////////////////////////////////////////// -template Dqn_List Dqn_List_Init(Dqn_usize chunk_size) -{ - Dqn_List result = {}; - result.chunk_size = chunk_size; - return result; -} - -template Dqn_List Dqn_List_InitCArray(Dqn_Arena *arena, Dqn_usize chunk_size, T const (&array)[N]) -{ - Dqn_List result = Dqn_List_Init(arena, chunk_size); - DQN_FOR_UINDEX (index, N) - Dqn_List_Add(&result, array[index]); - return result; -} - -template Dqn_List Dqn_List_InitSliceCopy(Dqn_Arena *arena, Dqn_usize chunk_size, Dqn_Slice slice) -{ - Dqn_List result = Dqn_List_Init(arena, chunk_size); - DQN_FOR_UINDEX (index, slice.size) - Dqn_List_Add(&result, slice.data[index]); - return result; -} - -template DQN_API bool Dqn_List_AttachTail_(Dqn_List *list, Dqn_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 DQN_API Dqn_ListChunk *Dqn_List_AllocArena_(Dqn_List *list, Dqn_Arena *arena, Dqn_usize count) -{ - auto *result = Dqn_Arena_New(arena, Dqn_ListChunk, Dqn_ZeroMem_Yes); - Dqn_ArenaTempMem tmem = Dqn_Arena_TempMemBegin(arena); - if (!result) - return nullptr; - - Dqn_usize items = DQN_MAX(list->chunk_size, count); - result->data = Dqn_Arena_NewArray(arena, T, items, Dqn_ZeroMem_Yes); - result->size = items; - if (!result->data) { - Dqn_Arena_TempMemEnd(tmem); - result = nullptr; - } - - Dqn_List_AttachTail_(list, result); - return result; -} - -template DQN_API Dqn_ListChunk *Dqn_List_AllocPool_(Dqn_List *list, Dqn_ChunkPool *pool, Dqn_usize count) -{ - auto *result = Dqn_ChunkPool_New(pool, Dqn_ListChunk); - if (!result) - return nullptr; - - Dqn_usize items = DQN_MAX(list->chunk_size, count); - result->data = Dqn_ChunkPool_NewArray(pool, T, items); - result->size = items; - if (!result->data) { - Dqn_ChunkPool_Dealloc(result); - result = nullptr; - } - - Dqn_List_AttachTail_(list, result); - return result; -} - -template DQN_API T *Dqn_List_MakeArena(Dqn_List *list, Dqn_Arena *arena, Dqn_usize count) -{ - if (list->chunk_size == 0) - list->chunk_size = 128; - - if (!list->tail || (list->tail->count + count) > list->tail->size) { - if (!Dqn_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 DQN_API T *Dqn_List_MakePool(Dqn_List *list, Dqn_ChunkPool *pool, Dqn_usize count) -{ - if (list->chunk_size == 0) - list->chunk_size = 128; - - if (!list->tail || (list->tail->count + count) > list->tail->size) { - if (!Dqn_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 DQN_API T *Dqn_List_AddArena(Dqn_List *list, Dqn_Arena *arena, T const &value) -{ - T *result = Dqn_List_MakeArena(list, arena, 1); - *result = value; - return result; -} - -template DQN_API T *Dqn_List_AddPool(Dqn_List *list, Dqn_ChunkPool *pool, T const &value) -{ - T *result = Dqn_List_MakePool(list, pool, 1); - *result = value; - return result; -} - -template DQN_API bool Dqn_List_AddCArray(Dqn_List *list, T const (&array)[N]) -{ - if (!list || list->chunk_size <= 0) - return false; - for (T const &item : array) { - if (!Dqn_List_Add(list, item)) - return false; - } - return true; -} - -template DQN_API void Dqn_List_AddListArena(Dqn_List *list, Dqn_Arena *arena, Dqn_List other) -{ - if (!list || list->chunk_size <= 0) - return; - // TODO(doyle): Copy chunk by chunk - for (Dqn_ListIterator it = {}; Dqn_List_Iterate(&other, &it, 0 /*start_index*/); ) - Dqn_List_AddArena(list, arena, *it.data); -} - -template DQN_API void Dqn_List_AddListPool(Dqn_List *list, Dqn_ChunkPool *pool, Dqn_List other) -{ - if (!list || list->chunk_size <= 0) - return; - // TODO(doyle): Copy chunk by chunk - for (Dqn_ListIterator it = {}; Dqn_List_Iterate(&other, &it, 0 /*start_index*/); ) - Dqn_List_AddPool(list, pool, *it.data); -} - -template DQN_API bool Dqn_List_Iterate(Dqn_List *list, Dqn_ListIterator *it, Dqn_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 { - Dqn_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) - DQN_ASSERT(result == false); - return result; -} - -template DQN_API T *Dqn_List_At(Dqn_List *list, Dqn_usize index, Dqn_ListChunk **at_chunk) -{ - if (!list || !list->chunk_size || index >= list->count) - return nullptr; - - Dqn_usize total_chunks = (list->count / list->chunk_size) + ((list->chunk_size % list->count) ? 1 : 0); - Dqn_usize desired_chunk = index / list->chunk_size; - Dqn_usize forward_scan_dist = desired_chunk; - Dqn_usize backward_scan_dist = total_chunks - desired_chunk; - - // NOTE: Linearly scan forwards/backwards to the chunk we need. We don't - // have random access to chunks - Dqn_usize current_chunk = 0; - Dqn_ListChunk **chunk = nullptr; - if (forward_scan_dist <= backward_scan_dist) { - for (chunk = &list->head; *chunk && current_chunk != desired_chunk; chunk = &((*chunk)->next), current_chunk++) { - } - } else { - current_chunk = total_chunks; - for (chunk = &list->tail; *chunk && current_chunk != desired_chunk; chunk = &((*chunk)->prev), current_chunk--) { - } - } - - T *result = nullptr; - if (*chunk) { - Dqn_usize relative_index = index % list->chunk_size; - result = (*chunk)->data + relative_index; - DQN_ASSERT(relative_index < (*chunk)->count); - } - - if (result && at_chunk) - *at_chunk = *chunk; - - return result; -} - -template Dqn_Slice Dqn_List_ToSliceCopy(Dqn_List const *list, Dqn_Arena *arena) -{ - // TODO(doyle): Chunk memcopies is much faster - Dqn_Slice result = Dqn_Slice_Alloc(arena, list->count, Dqn_ZeroMem_No); - if (result.size) { - Dqn_usize slice_index = 0; - DQN_MSVC_WARNING_PUSH - DQN_MSVC_WARNING_DISABLE(6011) // Dereferencing NULL pointer 'x' - for (Dqn_ListIterator it = {}; Dqn_List_Iterate(DQN_CAST(Dqn_List *)list, &it, 0);) - result.data[slice_index++] = *it.data; - DQN_MSVC_WARNING_POP - DQN_ASSERT(slice_index == result.size); - } - return result; -} -#endif // !defined(DQN_NO_LIST) diff --git a/dqn_cppbuild.h b/dqn_cppbuild.h deleted file mode 100644 index 2070d51..0000000 --- a/dqn_cppbuild.h +++ /dev/null @@ -1,204 +0,0 @@ -#if !defined(DQN_CPP_BUILD_H) -#define DQN_CPP_BUILD_H - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// $$$$$$\ $$$$$$$\ $$$$$$$\ $$$$$$$\ $$\ $$\ $$$$$$\ $$\ $$$$$$$\ -// $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$ | $$ |\_$$ _|$$ | $$ __$$\ -// $$ / \__|$$ | $$ |$$ | $$ | $$ | $$ |$$ | $$ | $$ | $$ | $$ | $$ | -// $$ | $$$$$$$ |$$$$$$$ | $$$$$$$\ |$$ | $$ | $$ | $$ | $$ | $$ | -// $$ | $$ ____/ $$ ____/ $$ __$$\ $$ | $$ | $$ | $$ | $$ | $$ | -// $$ | $$\ $$ | $$ | $$ | $$ |$$ | $$ | $$ | $$ | $$ | $$ | -// \$$$$$$ |$$ | $$ | $$$$$$$ |\$$$$$$ |$$$$$$\ $$$$$$$$\ $$$$$$$ | -// \______/ \__| \__| \_______/ \______/ \______|\________|\_______/ -// -// dqn_cppbuild.h -- Helper functions to make build scripts in C++ -// -//////////////////////////////////////////////////////////////////////////////////////////////////// - -#if !defined(DQN_H) -#error 'dqn.h' must be included before 'dqn_cppbuild.h' -#endif - -struct Dqn_CPPBuildCompileFile -{ - Dqn_Slice prefix_flags; - Dqn_Slice suffix_flags; - Dqn_Str8 input_file_path; - Dqn_Str8 output_file_path; -}; - -Dqn_Str8 const DQN_CPP_BUILD_OBJ_SUFFIX_OBJ = DQN_STR8(".obj"); -Dqn_Str8 const DQN_CPP_BUILD_OBJ_SUFFIX_O = DQN_STR8(".o"); - -enum Dqn_CPPBuildFlagsStyle -{ - Dqn_CPPBuildFlagsStyle_MSVC, - Dqn_CPPBuildFlagsStyle_GCC, - Dqn_CPPBuildFlagsStyle_CLANG, -}; - -enum Dqn_CPPBuildAppendCompilerToCommand -{ - Dqn_CPPBuildAppendCompilerToCommand_No, - Dqn_CPPBuildAppendCompilerToCommand_Yes, -}; - -struct Dqn_CPPBuildContext -{ - // Dictates the type of compiler flags the functions may append to the - // build command line - Dqn_CPPBuildFlagsStyle flags_style; - - Dqn_Str8 compile_file_obj_suffix; - Dqn_Slice compile_files; - Dqn_Slice compile_flags; - Dqn_Slice include_dirs; - Dqn_Slice link_flags; - Dqn_Str8 build_dir; -}; - -enum Dqn_CPPBuildStatus -{ - Dqn_CPPBuildStatus_Ok, - Dqn_CPPBuildStatus_BuildDirectoryFailedToBeMade, -}; - -struct Dqn_CPPBuildAsyncResult -{ - Dqn_CPPBuildStatus status; - Dqn_OSExecAsyncHandle async_handle; -}; - -enum Dqn_CPPBuildMode -{ - Dqn_CPPBuildMode_AlwaysRebuild, - Dqn_CPPBuildMode_CacheBuild, -}; - -DQN_API Dqn_Slice Dqn_CPPBuild_ToCommandLine (Dqn_CPPBuildContext build_context, Dqn_CPPBuildMode mode, Dqn_Arena *arena); -DQN_API Dqn_Str8 Dqn_CPPBuild_ToCommandLineStr8(Dqn_CPPBuildContext build_context, Dqn_CPPBuildMode mode, Dqn_Arena *arena); -DQN_API Dqn_CPPBuildAsyncResult Dqn_CPPBuild_Async (Dqn_CPPBuildContext build_context, Dqn_CPPBuildMode mode); -DQN_API void Dqn_CPPBuild_ExecOrAbort (Dqn_CPPBuildContext build_context, Dqn_CPPBuildMode mode); -#endif // DQN_CPP_BUILD_H - -#if defined(DQN_CPP_BUILD_IMPLEMENTATION) -DQN_API Dqn_Slice Dqn_CPPBuild_ToCommandLine(Dqn_CPPBuildContext build_context, Dqn_CPPBuildMode mode, Dqn_Arena *arena) -{ - // NOTE: Check if object files are newer than the source files ///////////////////////////////// - Dqn_Scratch scratch = Dqn_Scratch_Get(arena); - Dqn_Slice result = {}; - - Dqn_Slice dirtied_compile_files = build_context.compile_files; - if (mode == Dqn_CPPBuildMode_CacheBuild) { - dirtied_compile_files = Dqn_Slice_Alloc(scratch.arena, build_context.compile_files.size, Dqn_ZeroMem_Yes); - dirtied_compile_files.size = 0; - - DQN_FOR_UINDEX (index, build_context.compile_files.size) { - Dqn_CPPBuildCompileFile file = build_context.compile_files.data[index]; - - Dqn_Str8 obj_file_name = {}; - if (file.output_file_path.size) { - obj_file_name = file.output_file_path; - } else { - // NOTE: Determine the object file suffix - Dqn_Str8 compile_file_obj_suffix = build_context.compile_file_obj_suffix; - if (compile_file_obj_suffix.size == 0) - compile_file_obj_suffix = DQN_CPP_BUILD_OBJ_SUFFIX_OBJ; - - // NOTE: Create the object file path - Dqn_Str8 file_stem = Dqn_Str8_FileNameNoExtension(file.input_file_path); - obj_file_name = Dqn_Str8_InitF(scratch.arena, "%.*s%.*s", DQN_STR_FMT(file_stem), DQN_STR_FMT(compile_file_obj_suffix)); - } - - Dqn_Str8 obj_file_path = obj_file_name; - if (build_context.build_dir.size) - obj_file_path = Dqn_OS_PathConvertF(scratch.arena, "%.*s/%.*s", DQN_STR_FMT(build_context.build_dir), DQN_STR_FMT(obj_file_name)); - - Dqn_OSPathInfo file_info = Dqn_OS_PathInfo(file.input_file_path); - Dqn_OSPathInfo obj_file_info = Dqn_OS_PathInfo(obj_file_path); - if (obj_file_info.last_write_time_in_s >= file_info.last_write_time_in_s) - continue; - - dirtied_compile_files.data[dirtied_compile_files.size++] = file; - } - - if (dirtied_compile_files.size <= 0) - return result; - } - - // NOTE: Build the command line invocation ///////////////////////////////////////////////////// - Dqn_Str8Builder builder = {}; - builder.arena = scratch.arena; - Dqn_Str8Builder_AppendRefArray(&builder, build_context.compile_flags); - - DQN_FOR_UINDEX(index, build_context.include_dirs.size) { - Dqn_Str8 include_dir = build_context.include_dirs.data[index]; - Dqn_Str8Builder_AppendRef(&builder, DQN_STR8("-I")); - Dqn_Str8Builder_AppendRef(&builder, include_dir); - } - - DQN_FOR_UINDEX(index, dirtied_compile_files.size) { - Dqn_CPPBuildCompileFile file = dirtied_compile_files.data[index]; - if (Dqn_Str8_HasData(file.output_file_path)) { - switch (build_context.flags_style) { - case Dqn_CPPBuildFlagsStyle_MSVC: { - Dqn_Str8Builder_AppendF(&builder, "-Fo%.*s", DQN_STR_FMT(file.output_file_path)); - } break; - - case Dqn_CPPBuildFlagsStyle_GCC: /*FALLTHRU*/ - case Dqn_CPPBuildFlagsStyle_CLANG: { - Dqn_Str8Builder_AppendF (&builder, "-o"); - Dqn_Str8Builder_AppendRef(&builder, file.output_file_path); - } break; - } - } - - // TODO(doyle): Check if the file exists, error if it doesn't - - Dqn_Str8Builder_AppendRefArray(&builder, file.prefix_flags); - Dqn_Str8Builder_AppendRef(&builder, file.input_file_path); - Dqn_Str8Builder_AppendRefArray(&builder, file.suffix_flags); - } - - Dqn_Str8Builder_AppendRefArray(&builder, build_context.link_flags); - result = Dqn_Str8Builder_BuildSlice(&builder, arena); - return result; -} - -DQN_API Dqn_Str8 Dqn_CPPBuild_ToCommandLineStr8(Dqn_CPPBuildContext build_context, Dqn_CPPBuildMode mode, Dqn_Arena *arena) -{ - Dqn_Slice cmd_line = Dqn_CPPBuild_ToCommandLine(build_context, mode, arena); - Dqn_Str8 result = Dqn_Slice_Str8Render(arena, cmd_line, DQN_STR8(" ") /*separator*/); - return result; -} - -DQN_API Dqn_CPPBuildAsyncResult Dqn_CPPBuild_Async(Dqn_CPPBuildContext build_context, Dqn_CPPBuildMode mode, Dqn_ErrorSink *error) -{ - Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr); - Dqn_Slice cmd_line = Dqn_CPPBuild_ToCommandLine(build_context, mode, scratch.arena); - Dqn_CPPBuildAsyncResult result = {}; - if (!cmd_line.size) - return result; - - if (!Dqn_OS_MakeDir(build_context.build_dir)) { - result.status = Dqn_CPPBuildStatus_BuildDirectoryFailedToBeMade; - Dqn_ErrorSink_MakeF(error, result.status, "Failed to make build directory '%.*s'", DQN_STR_FMT(build_context.build_dir)); - return result; - } - - result.async_handle = Dqn_OS_ExecAsync(cmd_line, build_context.build_dir, Dqn_OSExecFlag_Nil, error); - return result; -} - -void Dqn_CPPBuild_ExecOrAbort(Dqn_CPPBuildContext build_context, Dqn_CPPBuildMode mode) -{ - if (!Dqn_OS_MakeDir(build_context.build_dir)) { - Dqn_Log_ErrorF("Failed to make build dir '%.*s'", DQN_STR_FMT(build_context.build_dir)); - exit(-1); - } - Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr); - Dqn_Slice cmd_line = Dqn_CPPBuild_ToCommandLine(build_context, mode, scratch.arena); - Dqn_OS_ExecOrAbort(cmd_line, build_context.build_dir, Dqn_OSExecFlag_Nil, scratch.arena); -} -#endif // DQN_CPP_BUILD_IMPLEMENTATION diff --git a/dqn_debug.cpp b/dqn_debug.cpp index 39bb3dc..398eb49 100644 --- a/dqn_debug.cpp +++ b/dqn_debug.cpp @@ -18,58 +18,61 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$ASAN] Dqn_Asan ////////////////////////////////////////////////////////////////////////// /// -DQN_API void Dqn_ASAN_PoisonMemoryRegion(void const volatile *ptr, Dqn_usize size) +// NOTE: [$ASAN] DN_Asan ////////////////////////////////////////////////////////////////////////// /// +DN_API void DN_ASAN_PoisonMemoryRegion(void const volatile *ptr, DN_USize size) { if (!ptr || !size) return; - #if DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) + #if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) + DN_ASSERTF(DN_IsPowerOfTwoAligned(ptr, 8), + "Poisoning requires the pointer to be aligned on an 8 byte boundary"); + __asan_poison_memory_region(ptr, size); - if (DQN_ASAN_VET_POISON) { - DQN_HARD_ASSERT(__asan_address_is_poisoned(ptr)); - DQN_HARD_ASSERT(__asan_address_is_poisoned((char *)ptr + (size - 1))); + if (DN_ASAN_VET_POISON) { + DN_HARD_ASSERT(__asan_address_is_poisoned(ptr)); + DN_HARD_ASSERT(__asan_address_is_poisoned((char *)ptr + (size - 1))); } #else (void)ptr; (void)size; #endif } -DQN_API void Dqn_ASAN_UnpoisonMemoryRegion(void const volatile *ptr, Dqn_usize size) +DN_API void DN_ASAN_UnpoisonMemoryRegion(void const volatile *ptr, DN_USize size) { if (!ptr || !size) return; - #if DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) + #if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) __asan_unpoison_memory_region(ptr, size); - if (DQN_ASAN_VET_POISON) { - DQN_HARD_ASSERT(__asan_region_is_poisoned((void *)ptr, size) == 0); + if (DN_ASAN_VET_POISON) { + DN_HARD_ASSERT(__asan_region_is_poisoned((void *)ptr, size) == 0); } #else (void)ptr; (void)size; #endif } -DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk(Dqn_Arena *arena, uint16_t limit) +DN_API DN_StackTraceWalkResult DN_StackTrace_Walk(DN_Arena *arena, uint16_t limit) { - Dqn_StackTraceWalkResult result = {}; - #if defined(DQN_OS_WIN32) + DN_StackTraceWalkResult result = {}; + #if defined(DN_OS_WIN32) if (!arena) return result; - static Dqn_TicketMutex mutex = {}; - Dqn_TicketMutex_Begin(&mutex); + static DN_TicketMutex mutex = {}; + DN_TicketMutex_Begin(&mutex); HANDLE thread = GetCurrentThread(); result.process = GetCurrentProcess(); - if (!g_dqn_library->win32_sym_initialised) { - g_dqn_library->win32_sym_initialised = true; + if (!g_dn_core->win32_sym_initialised) { + g_dn_core->win32_sym_initialised = true; SymSetOptions(SYMOPT_LOAD_LINES); if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); - Dqn_WinError error = Dqn_Win_LastError(tmem.arena); - Dqn_Log_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DQN_STR_FMT(error.msg)); + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_WinError error = DN_Win_LastError(tmem.arena); + DN_Log_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_STR_FMT(error.msg)); } } @@ -84,7 +87,7 @@ DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk(Dqn_Arena *arena, uint16_t frame.AddrStack.Offset = context.Rsp; frame.AddrStack.Mode = AddrModeFlat; - Dqn_FArray raw_frames = {}; + DN_FArray raw_frames = {}; while (raw_frames.size < limit) { if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64, result.process, @@ -100,53 +103,155 @@ DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk(Dqn_Arena *arena, uint16_t // NOTE: It might be useful one day to use frame.AddrReturn.Offset. // If AddrPC.Offset == AddrReturn.Offset then we can detect recursion. - Dqn_FArray_Add(&raw_frames, frame.AddrPC.Offset); + DN_FArray_Add(&raw_frames, frame.AddrPC.Offset); } - Dqn_TicketMutex_End(&mutex); + DN_TicketMutex_End(&mutex); - result.base_addr = Dqn_Arena_NewArray(arena, uint64_t, raw_frames.size, Dqn_ZeroMem_No); - result.size = DQN_CAST(uint16_t)raw_frames.size; - DQN_MEMCPY(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0])); + result.base_addr = DN_Arena_NewArray(arena, uint64_t, raw_frames.size, DN_ZeroMem_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; } -DQN_API Dqn_Str8 Dqn_StackTrace_WalkStr8CRT(uint16_t limit, uint16_t skip) +DN_API DN_StackTraceWalkResult DN_StackTrace_WalkCRT(uint16_t limit) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_StackTraceWalkResult walk_result = Dqn_StackTrace_Walk(tmem.arena, limit); - Dqn_Str8 result = Dqn_StackTrace_WalkResultStr8CRT(&walk_result, skip); + DN_StackTraceWalkResult result = {}; + #if defined(DN_OS_WIN32) + static DN_TicketMutex mutex = {}; + DN_TicketMutex_Begin(&mutex); + + HANDLE thread = GetCurrentThread(); + result.process = GetCurrentProcess(); + + if (!g_dn_core->win32_sym_initialised) { + g_dn_core->win32_sym_initialised = true; + SymSetOptions(SYMOPT_LOAD_LINES); + if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) { + DN_WinError error = DN_Win_LastErrorAlloc(); + DN_Log_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_STR_FMT(error.msg)); + DN_OS_MemDealloc(error.msg.data); + } + } + + 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; + + struct FrameChunk + { + uint64_t frames[128]; + FrameChunk *next; + uint8_t size; + }; + + DN_USize total_frames = 0; + FrameChunk frame_chunk = {}; + FrameChunk *frame_chunk_it = &frame_chunk; + for (; total_frames < limit; total_frames++) { + 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. + if (frame_chunk_it->size == DN_ARRAY_UCOUNT(frame_chunk_it->frames)) { + FrameChunk *next = DN_CAST(FrameChunk *) DN_OS_MemAlloc(sizeof(*next), DN_ZeroMem_No); + frame_chunk_it = next; + } + + if (!frame_chunk_it) + break; + frame_chunk_it->frames[frame_chunk_it->size++] = frame.AddrPC.Offset; + } + DN_TicketMutex_End(&mutex); + + result.base_addr = DN_CAST(uint64_t *)DN_OS_MemAlloc(sizeof(*result.base_addr) * total_frames, DN_ZeroMem_No); + for (FrameChunk *it = &frame_chunk; it; ) { + FrameChunk *next = it->next; + + // NOTE: Copy + DN_MEMCPY(result.base_addr, it->frames, it->size * sizeof(it->frames[0])); + result.size += it->size; + + // NOTE: Free + if (it != &frame_chunk) + DN_OS_MemDealloc(it); + it = next; + } + #else + DN_INVALID_CODE_PATH; + (void)limit; + #endif return result; } -static void Dqn_StackTrace_AddWalkToStr8Builder_(Dqn_StackTraceWalkResult const *walk, Dqn_Str8Builder *builder, Dqn_usize skip) +DN_API DN_Str8 DN_StackTrace_WalkStr8CRT(uint16_t limit, uint16_t skip) { - Dqn_StackTraceRawFrame raw_frame = {}; + DN_StackTraceWalkResult walk_result = DN_StackTrace_WalkCRT(limit); + DN_Str8 result = DN_StackTrace_WalkResultStr8CRT(&walk_result, skip); + return result; +} + +static void DN_StackTrace_AddWalkToStr8Builder_(DN_StackTraceWalkResult const *walk, DN_Str8Builder *builder, DN_USize skip) +{ + DN_StackTraceRawFrame raw_frame = {}; raw_frame.process = walk->process; - for (Dqn_usize index = skip; index < walk->size; index++) { + for (DN_USize index = skip; index < walk->size; index++) { raw_frame.base_addr = walk->base_addr[index]; - Dqn_StackTraceFrame frame = Dqn_StackTrace_RawFrameToFrame(builder->arena, raw_frame); - Dqn_Str8Builder_AddF(builder, "%.*s(%zu): %.*s%s", DQN_STR_FMT(frame.file_name), frame.line_number, DQN_STR_FMT(frame.function_name), (DQN_CAST(int)index == walk->size - 1) ? "" : "\n"); + DN_StackTraceFrame frame = DN_StackTrace_RawFrameToFrame(builder->arena, raw_frame); + DN_Str8Builder_AppendF(builder, "%.*s(%zu): %.*s%s", DN_STR_FMT(frame.file_name), frame.line_number, DN_STR_FMT(frame.function_name), (DN_CAST(int)index == walk->size - 1) ? "" : "\n"); } } -DQN_API Dqn_Str8 Dqn_StackTrace_WalkStr8CRTNoScratch(uint16_t limit, uint16_t skip) +DN_API DN_Str8 DN_StackTrace_WalkStr8CRTNoScratch(uint16_t limit, uint16_t skip) { - Dqn_Arena arena = {}; - arena.flags |= Dqn_ArenaFlag_NoAllocTrack; - Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(&arena, limit); + DN_Arena arena = {}; + arena.flags |= DN_ArenaFlags_NoAllocTrack; + DN_DEFER { DN_Arena_Deinit(&arena); }; + + DN_Str8Builder builder = {}; + builder.arena = &arena; + + DN_StackTraceWalkResult walk = DN_StackTrace_Walk(&arena, limit); + 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_StackTrace_RawFrameToFrame(builder.arena, raw_frame); + DN_Str8Builder_AppendF(&builder, "%.*s(%zu): %.*s%s", DN_STR_FMT(frame.file_name), frame.line_number, DN_STR_FMT(frame.function_name), (DN_CAST(int)index == walk.size - 1) ? "" : "\n"); + } + + DN_Str8 result = {}; + result.data = DN_CAST(char *)DN_OS_MemReserve(builder.string_size + 1, DN_OSMemCommit_Yes, DN_OSMemPage_ReadWrite); + if (result.data) { + for (DN_Str8Link *it = builder.head; it; it = it->next) { + DN_MEMCPY(result.data + result.size, it->string.data, it->string.size); + result.size += it->string.size; + } + } - Dqn_Str8Builder builder = {}; - builder.arena = &arena; - Dqn_StackTrace_AddWalkToStr8Builder_(&walk, &builder, skip); - Dqn_Str8 result = Dqn_Str8Builder_BuildCRT(&builder); - Dqn_Arena_Deinit(&arena); return result; } -DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator *it, Dqn_StackTraceWalkResult const *walk) +DN_API bool DN_StackTrace_WalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk) { bool result = false; if (!it || !walk || !walk->base_addr || !walk->process) @@ -161,55 +266,55 @@ DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator * return result; } -DQN_API Dqn_Str8 Dqn_StackTrace_WalkResultStr8(Dqn_Arena *arena, Dqn_StackTraceWalkResult const *walk, uint16_t skip) +DN_API DN_Str8 DN_StackTrace_WalkResultStr8(DN_Arena *arena, DN_StackTraceWalkResult const *walk, uint16_t skip) { - Dqn_Str8 result {}; + DN_Str8 result {}; if (!walk || !arena) return result; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); - Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena); - Dqn_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip); - result = Dqn_Str8Builder_Build(&builder, arena); + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena); + DN_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip); + result = DN_Str8Builder_Build(&builder, arena); return result; } -DQN_API Dqn_Str8 Dqn_StackTrace_WalkResultStr8CRT(Dqn_StackTraceWalkResult const *walk, uint16_t skip) +DN_API DN_Str8 DN_StackTrace_WalkResultStr8CRT(DN_StackTraceWalkResult const *walk, uint16_t skip) { - Dqn_Str8 result {}; + DN_Str8 result {}; if (!walk) return result; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena); - Dqn_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip); - result = Dqn_Str8Builder_BuildCRT(&builder); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena); + DN_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip); + result = DN_Str8Builder_BuildCRT(&builder); return result; } -DQN_API Dqn_Slice Dqn_StackTrace_GetFrames(Dqn_Arena *arena, uint16_t limit) +DN_API DN_Slice DN_StackTrace_GetFrames(DN_Arena *arena, uint16_t limit) { - Dqn_Slice result = {}; + DN_Slice result = {}; if (!arena) return result; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); - Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(tmem.arena, limit); + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_StackTraceWalkResult walk = DN_StackTrace_Walk(tmem.arena, limit); if (!walk.size) return result; - 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[slice_index++] = Dqn_StackTrace_RawFrameToFrame(arena, it.raw_frame); + DN_USize slice_index = 0; + result = DN_Slice_Alloc(arena, walk.size, DN_ZeroMem_No); + for (DN_StackTraceWalkResultIterator it = {}; DN_StackTrace_WalkResultIterate(&it, &walk); ) { + result.data[slice_index++] = DN_StackTrace_RawFrameToFrame(arena, it.raw_frame); } return result; } -DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame(Dqn_Arena *arena, Dqn_StackTraceRawFrame raw_frame) +DN_API DN_StackTraceFrame DN_StackTrace_RawFrameToFrame(DN_Arena *arena, DN_StackTraceRawFrame raw_frame) { - #if defined(DQN_OS_WIN32) + #if defined(DN_OS_WIN32) // NOTE: Get line+filename ///////////////////////////////////////////////////////////////////// // TODO: Why does zero-initialising this with `line = {};` cause @@ -227,7 +332,7 @@ DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame(Dqn_Arena *arena, Dqn // NOTE: Get function name ///////////////////////////////////////////////////////////////////// alignas(SYMBOL_INFOW) char buffer[sizeof(SYMBOL_INFOW) + (MAX_SYM_NAME * sizeof(wchar_t))] = {}; - SYMBOL_INFOW *symbol = DQN_CAST(SYMBOL_INFOW *)buffer; + SYMBOL_INFOW *symbol = DN_CAST(SYMBOL_INFOW *)buffer; symbol->SizeOfStruct = sizeof(*symbol); symbol->MaxNameLen = sizeof(buffer) - sizeof(*symbol); @@ -236,71 +341,71 @@ DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame(Dqn_Arena *arena, Dqn // NOTE: Construct result ////////////////////////////////////////////////////////////////////// - Dqn_Str16 file_name16 = Dqn_Str16{line.FileName, Dqn_CStr16_Size(line.FileName)}; - Dqn_Str16 function_name16 = Dqn_Str16{symbol->Name, symbol->NameLen}; + DN_Str16 file_name16 = DN_Str16{line.FileName, DN_CStr16_Size(line.FileName)}; + DN_Str16 function_name16 = DN_Str16{symbol->Name, symbol->NameLen}; - Dqn_StackTraceFrame result = {}; + DN_StackTraceFrame result = {}; result.address = raw_frame.base_addr; result.line_number = line.LineNumber; - result.file_name = Dqn_Win_Str16ToStr8(arena, file_name16); - result.function_name = Dqn_Win_Str16ToStr8(arena, function_name16); + result.file_name = DN_Win_Str16ToStr8(arena, file_name16); + result.function_name = DN_Win_Str16ToStr8(arena, function_name16); - if (!Dqn_Str8_HasData(result.function_name)) - result.function_name = DQN_STR8(""); - if (!Dqn_Str8_HasData(result.file_name)) - result.file_name = DQN_STR8(""); + if (!DN_Str8_HasData(result.function_name)) + result.function_name = DN_STR8(""); + if (!DN_Str8_HasData(result.file_name)) + result.file_name = DN_STR8(""); #else - Dqn_StackTraceFrame result = {}; + DN_StackTraceFrame result = {}; #endif return result; } -DQN_API void Dqn_StackTrace_Print(uint16_t limit) +DN_API void DN_StackTrace_Print(uint16_t limit) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Slice stack_trace = Dqn_StackTrace_GetFrames(tmem.arena, limit); - for (Dqn_StackTraceFrame &frame : stack_trace) - Dqn_Print_ErrLnF("%.*s(%I64u): %.*s", DQN_STR_FMT(frame.file_name), frame.line_number, DQN_STR_FMT(frame.function_name)); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Slice stack_trace = DN_StackTrace_GetFrames(tmem.arena, limit); + for (DN_StackTraceFrame &frame : stack_trace) + DN_Print_ErrLnF("%.*s(%I64u): %.*s", DN_STR_FMT(frame.file_name), frame.line_number, DN_STR_FMT(frame.function_name)); } -DQN_API void Dqn_StackTrace_ReloadSymbols() +DN_API void DN_StackTrace_ReloadSymbols() { - #if defined(DQN_OS_WIN32) + #if defined(DN_OS_WIN32) HANDLE process = GetCurrentProcess(); SymRefreshModuleList(process); #endif } -// NOTE: [$DEBG] Dqn_Debug ///////////////////////////////////////////////////////////////////////// -#if defined(DQN_LEAK_TRACKING) -DQN_API void Dqn_Debug_TrackAlloc(void *ptr, Dqn_usize size, bool leak_permitted) +// NOTE: [$DEBG] DN_Debug ///////////////////////////////////////////////////////////////////////// +#if defined(DN_LEAK_TRACKING) +DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted) { if (!ptr) return; - Dqn_TicketMutex_Begin(&g_dqn_library->alloc_table_mutex); - DQN_DEFER { - Dqn_TicketMutex_End(&g_dqn_library->alloc_table_mutex); + DN_TicketMutex_Begin(&g_dn_core->alloc_table_mutex); + DN_DEFER { + DN_TicketMutex_End(&g_dn_core->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. - Dqn_Str8 stack_trace = Dqn_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/); - Dqn_DSMap *alloc_table = &g_dqn_library->alloc_table; - Dqn_DSMapResult alloc_entry = Dqn_DSMap_MakeKeyU64(alloc_table, DQN_CAST(uint64_t) ptr); - Dqn_DebugAlloc *alloc = alloc_entry.value; + DN_Str8 stack_trace = DN_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/); + DN_DSMap *alloc_table = &g_dn_core->alloc_table; + DN_DSMapResult alloc_entry = DN_DSMap_MakeKeyU64(alloc_table, DN_CAST(uint64_t) ptr); + DN_DebugAlloc *alloc = alloc_entry.value; if (alloc_entry.found) { - if ((alloc->flags & Dqn_DebugAllocFlag_Freed) == 0) { - Dqn_Str8 alloc_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, alloc->size, Dqn_U64ByteSizeType_Auto); - Dqn_Str8 new_alloc_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, size, Dqn_U64ByteSizeType_Auto); - DQN_HARD_ASSERTF( - alloc->flags & Dqn_DebugAllocFlag_Freed, + if ((alloc->flags & DN_DebugAllocFlag_Freed) == 0) { + DN_Str8 alloc_size = DN_U64ToByteSizeStr8(alloc_table->arena, alloc->size, DN_U64ByteSizeType_Auto); + DN_Str8 new_alloc_size = DN_U64ToByteSizeStr8(alloc_table->arena, size, DN_U64ByteSizeType_Auto); + DN_HARD_ASSERTF( + alloc->flags & DN_DebugAllocFlag_Freed, "This pointer is already in the leak tracker, however it has not " "been freed yet. This same pointer is being ask to be tracked " "twice in the allocation table, e.g. one if its previous free " "calls has not being marked freed with an equivalent call to " - "Dqn_Debug_TrackDealloc()\n" + "DN_Debug_TrackDealloc()\n" "\n" "The pointer (0x%p) originally allocated %.*s at:\n" "\n" @@ -310,45 +415,45 @@ DQN_API void Dqn_Debug_TrackAlloc(void *ptr, Dqn_usize size, bool leak_permitted "\n" "%.*s\n" , - ptr, DQN_STR_FMT(alloc_size), - DQN_STR_FMT(alloc->stack_trace), - DQN_STR_FMT(new_alloc_size), - DQN_STR_FMT(stack_trace)); + ptr, DN_STR_FMT(alloc_size), + DN_STR_FMT(alloc->stack_trace), + DN_STR_FMT(new_alloc_size), + DN_STR_FMT(stack_trace)); } // NOTE: Pointer was reused, clean up the prior entry - free(alloc->stack_trace.data); - free(alloc->freed_stack_trace.data); + DN_OS_MemRelease(alloc->stack_trace.data, alloc->stack_trace.size); + DN_OS_MemRelease(alloc->freed_stack_trace.data, alloc->freed_stack_trace.size); *alloc = {}; } alloc->ptr = ptr; alloc->size = size; alloc->stack_trace = stack_trace; - alloc->flags |= leak_permitted ? Dqn_DebugAllocFlag_LeakPermitted : 0; + alloc->flags |= leak_permitted ? DN_DebugAllocFlag_LeakPermitted : 0; } -DQN_API void Dqn_Debug_TrackDealloc(void *ptr) +DN_API void DN_Debug_TrackDealloc(void *ptr) { if (!ptr) return; - Dqn_TicketMutex_Begin(&g_dqn_library->alloc_table_mutex); - DQN_DEFER { Dqn_TicketMutex_End(&g_dqn_library->alloc_table_mutex); }; + DN_TicketMutex_Begin(&g_dn_core->alloc_table_mutex); + DN_DEFER { DN_TicketMutex_End(&g_dn_core->alloc_table_mutex); }; - Dqn_Str8 stack_trace = Dqn_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/); - Dqn_DSMap *alloc_table = &g_dqn_library->alloc_table; - Dqn_DSMapResult alloc_entry = Dqn_DSMap_FindKeyU64(alloc_table, DQN_CAST(uintptr_t) ptr); - DQN_HARD_ASSERTF(alloc_entry.found, + DN_Str8 stack_trace = DN_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/); + DN_DSMap *alloc_table = &g_dn_core->alloc_table; + DN_DSMapResult alloc_entry = DN_DSMap_FindKeyU64(alloc_table, DN_CAST(uintptr_t) ptr); + DN_HARD_ASSERTF(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 " "not added to the allocation table [ptr=%p]", ptr); - Dqn_DebugAlloc *alloc = alloc_entry.value; - if (alloc->flags & Dqn_DebugAllocFlag_Freed) { - Dqn_Str8 freed_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, alloc->freed_size, Dqn_U64ByteSizeType_Auto); - DQN_HARD_ASSERTF((alloc->flags & Dqn_DebugAllocFlag_Freed) == 0, + DN_DebugAlloc *alloc = alloc_entry.value; + if (alloc->flags & DN_DebugAllocFlag_Freed) { + DN_Str8 freed_size = DN_U64ToByteSizeStr8(alloc_table->arena, alloc->freed_size, DN_U64ByteSizeType_Auto); + DN_HARD_ASSERTF((alloc->flags & DN_DebugAllocFlag_Freed) == 0, "Double free detected, pointer to free was already marked " "as freed. Either the pointer was reallocated but not " "traced, or, the pointer was freed twice.\n" @@ -365,40 +470,40 @@ DQN_API void Dqn_Debug_TrackDealloc(void *ptr) "\n" "%.*s\n" , - ptr, DQN_STR_FMT(freed_size), - DQN_STR_FMT(alloc->stack_trace), - DQN_STR_FMT(alloc->freed_stack_trace), - DQN_STR_FMT(stack_trace)); + ptr, DN_STR_FMT(freed_size), + DN_STR_FMT(alloc->stack_trace), + DN_STR_FMT(alloc->freed_stack_trace), + DN_STR_FMT(stack_trace)); } - DQN_ASSERT(!Dqn_Str8_HasData(alloc->freed_stack_trace)); - alloc->flags |= Dqn_DebugAllocFlag_Freed; + DN_ASSERT(!DN_Str8_HasData(alloc->freed_stack_trace)); + alloc->flags |= DN_DebugAllocFlag_Freed; alloc->freed_stack_trace = stack_trace; } -DQN_API void Dqn_Debug_DumpLeaks() +DN_API void DN_Debug_DumpLeaks() { uint64_t leak_count = 0; uint64_t leaked_bytes = 0; - for (Dqn_usize index = 1; index < g_dqn_library->alloc_table.occupied; index++) { - Dqn_DSMapSlot *slot = g_dqn_library->alloc_table.slots + index; - Dqn_DebugAlloc *alloc = &slot->value; - bool alloc_leaked = (alloc->flags & Dqn_DebugAllocFlag_Freed) == 0; - bool leak_permitted = (alloc->flags & Dqn_DebugAllocFlag_LeakPermitted); + for (DN_USize index = 1; index < g_dn_core->alloc_table.occupied; index++) { + DN_DSMapSlot *slot = g_dn_core->alloc_table.slots + index; + DN_DebugAlloc *alloc = &slot->value; + bool alloc_leaked = (alloc->flags & DN_DebugAllocFlag_Freed) == 0; + bool leak_permitted = (alloc->flags & DN_DebugAllocFlag_LeakPermitted); if (alloc_leaked && !leak_permitted) { leaked_bytes += alloc->size; leak_count++; - Dqn_Str8 alloc_size = Dqn_U64ToByteSizeStr8(g_dqn_library->alloc_table.arena, alloc->size, Dqn_U64ByteSizeType_Auto); - Dqn_Log_WarningF("Pointer (0x%p) leaked %.*s at:\n" + DN_Str8 alloc_size = DN_U64ToByteSizeStr8(g_dn_core->alloc_table.arena, alloc->size, DN_U64ByteSizeType_Auto); + DN_Log_WarningF("Pointer (0x%p) leaked %.*s at:\n" "%.*s", - alloc->ptr, DQN_STR_FMT(alloc_size), - DQN_STR_FMT(alloc->stack_trace)); + alloc->ptr, DN_STR_FMT(alloc_size), + DN_STR_FMT(alloc->stack_trace)); } } if (leak_count) { - Dqn_Str8 leak_size = Dqn_U64ToByteSizeStr8(&g_dqn_library->arena, leaked_bytes, Dqn_U64ByteSizeType_Auto); - Dqn_Log_WarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DQN_STR_FMT(leak_size)); + DN_Str8 leak_size = DN_U64ToByteSizeStr8(&g_dn_core->arena, leaked_bytes, DN_U64ByteSizeType_Auto); + DN_Log_WarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_STR_FMT(leak_size)); } } -#endif // DQN_LEAK_TRACKING +#endif // DN_LEAK_TRACKING diff --git a/dqn_debug.h b/dqn_debug.h index ff6665e..2ab706e 100644 --- a/dqn_debug.h +++ b/dqn_debug.h @@ -17,109 +17,109 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // -// [$ASAN] Dqn_Asan -- Helpers to manually poison memory using ASAN -// [$STKT] Dqn_StackTrace -- Create stack traces -// [$DEBG] Dqn_Debug -- Allocation leak tracking API +// [$ASAN] DN_Asan -- Helpers to manually poison memory using ASAN +// [$STKT] DN_StackTrace -- Create stack traces +// [$DEBG] DN_Debug -- Allocation leak tracking API // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$ASAN] Dqn_Asan ////////////////////////////////////////////////////////////////////////// -#if !defined(DQN_ASAN_POISON) - #define DQN_ASAN_POISON 0 +// NOTE: [$ASAN] DN_Asan ////////////////////////////////////////////////////////////////////////// +#if !defined(DN_ASAN_POISON) + #define DN_ASAN_POISON 0 #endif -#if !defined(DQN_ASAN_VET_POISON) - #define DQN_ASAN_VET_POISON 0 +#if !defined(DN_ASAN_VET_POISON) + #define DN_ASAN_VET_POISON 0 #endif -#define DQN_ASAN_POISON_ALIGNMENT 8 +#define DN_ASAN_POISON_ALIGNMENT 8 -#if !defined(DQN_ASAN_POISON_GUARD_SIZE) - #define DQN_ASAN_POISON_GUARD_SIZE 128 +#if !defined(DN_ASAN_POISON_GUARD_SIZE) + #define DN_ASAN_POISON_GUARD_SIZE 128 #endif -static_assert(Dqn_IsPowerOfTwoAligned(DQN_ASAN_POISON_GUARD_SIZE, DQN_ASAN_POISON_ALIGNMENT), +static_assert(DN_IsPowerOfTwoAligned(DN_ASAN_POISON_GUARD_SIZE, DN_ASAN_POISON_ALIGNMENT), "ASAN poison guard size must be a power-of-two and aligned to ASAN's alignment" "requirement (8 bytes)"); -#if DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) #include #endif -// NOTE: [$STKT] Dqn_StackTrace //////////////////////////////////////////////////////////////////// -struct Dqn_StackTraceFrame +// NOTE: [$STKT] DN_StackTrace //////////////////////////////////////////////////////////////////// +struct DN_StackTraceFrame { uint64_t address; uint64_t line_number; - Dqn_Str8 file_name; - Dqn_Str8 function_name; + DN_Str8 file_name; + DN_Str8 function_name; }; -struct Dqn_StackTraceRawFrame +struct DN_StackTraceRawFrame { void *process; uint64_t base_addr; }; -struct Dqn_StackTraceWalkResult +struct DN_StackTraceWalkResult { void *process; // [Internal] Windows handle to the process uint64_t *base_addr; // The addresses of the functions in the stack trace uint16_t size; // The number of `base_addr`'s stored from the walk }; -struct Dqn_StackTraceWalkResultIterator +struct DN_StackTraceWalkResultIterator { - Dqn_StackTraceRawFrame raw_frame; + DN_StackTraceRawFrame raw_frame; uint16_t index; }; -// NOTE: [$DEBG] Dqn_Debug ///////////////////////////////////////////////////////////////////////// -enum Dqn_DebugAllocFlag +// NOTE: [$DEBG] DN_Debug ///////////////////////////////////////////////////////////////////////// +enum DN_DebugAllocFlag { - Dqn_DebugAllocFlag_Freed = 1 << 0, - Dqn_DebugAllocFlag_LeakPermitted = 1 << 1, + DN_DebugAllocFlag_Freed = 1 << 0, + DN_DebugAllocFlag_LeakPermitted = 1 << 1, }; -struct Dqn_DebugAlloc +struct DN_DebugAlloc { void *ptr; // 8 Pointer to the allocation being tracked - Dqn_usize size; // 16 Size of the allocation - Dqn_usize freed_size; // 24 Store the size of the allocation when it is freed - Dqn_Str8 stack_trace; // 40 Stack trace at the point of allocation - Dqn_Str8 freed_stack_trace; // 56 Stack trace of where the allocation was freed - uint16_t flags; // 72 Bit flags from `Dqn_DebugAllocFlag` + DN_USize size; // 16 Size of the allocation + DN_USize freed_size; // 24 Store the size of the allocation when it is freed + DN_Str8 stack_trace; // 40 Stack trace at the point of allocation + DN_Str8 freed_stack_trace; // 56 Stack trace of where the allocation was freed + uint16_t flags; // 72 Bit flags from `DN_DebugAllocFlag` }; -static_assert(sizeof(Dqn_DebugAlloc) == 64 || sizeof(Dqn_DebugAlloc) == 32, // NOTE: 64 bit vs 32 bit pointers respectively +static_assert(sizeof(DN_DebugAlloc) == 64 || sizeof(DN_DebugAlloc) == 32, // NOTE: 64 bit vs 32 bit pointers respectively "We aim to keep the allocation record as light as possible as " "memory tracking can get expensive. Enforce that there is no " "unexpected padding."); -// NOTE: [$ASAN] Dqn_Asan ////////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_ASAN_PoisonMemoryRegion (void const volatile *ptr, Dqn_usize size); -DQN_API void Dqn_ASAN_UnpoisonMemoryRegion (void const volatile *ptr, Dqn_usize size); +// NOTE: [$ASAN] DN_Asan ////////////////////////////////////////////////////////////////////////// +DN_API void DN_ASAN_PoisonMemoryRegion (void const volatile *ptr, DN_USize size); +DN_API void DN_ASAN_UnpoisonMemoryRegion (void const volatile *ptr, DN_USize size); -// NOTE: [$STKT] Dqn_StackTrace //////////////////////////////////////////////////////////////////// -DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk (Dqn_Arena *arena, uint16_t limit); -DQN_API Dqn_Str8 Dqn_StackTrace_WalkStr8CRT (uint16_t limit, uint16_t skip); -DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator *it, Dqn_StackTraceWalkResult const *walk); -DQN_API Dqn_Str8 Dqn_StackTrace_WalkResultStr8 (Dqn_Arena *arena, Dqn_StackTraceWalkResult const *walk, uint16_t skip); -DQN_API Dqn_Str8 Dqn_StackTrace_WalkResultStr8CRT(Dqn_StackTraceWalkResult const *walk, uint16_t skip); -DQN_API Dqn_Slice Dqn_StackTrace_GetFrames (Dqn_Arena *arena, uint16_t limit); -DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame (Dqn_Arena *arena, Dqn_StackTraceRawFrame raw_frame); -DQN_API void Dqn_StackTrace_Print (uint16_t limit); -DQN_API void Dqn_StackTrace_ReloadSymbols (); +// NOTE: [$STKT] DN_StackTrace //////////////////////////////////////////////////////////////////// +DN_API DN_StackTraceWalkResult DN_StackTrace_Walk (DN_Arena *arena, uint16_t limit); +DN_API DN_Str8 DN_StackTrace_WalkStr8CRT (uint16_t limit, uint16_t skip); +DN_API bool DN_StackTrace_WalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk); +DN_API DN_Str8 DN_StackTrace_WalkResultStr8 (DN_Arena *arena, DN_StackTraceWalkResult const *walk, uint16_t skip); +DN_API DN_Str8 DN_StackTrace_WalkResultStr8CRT(DN_StackTraceWalkResult const *walk, uint16_t skip); +DN_API DN_Slice DN_StackTrace_GetFrames (DN_Arena *arena, uint16_t limit); +DN_API DN_StackTraceFrame DN_StackTrace_RawFrameToFrame (DN_Arena *arena, DN_StackTraceRawFrame raw_frame); +DN_API void DN_StackTrace_Print (uint16_t limit); +DN_API void DN_StackTrace_ReloadSymbols (); -// NOTE: [$DEBG] Dqn_Debug ///////////////////////////////////////////////////////////////////////// -#if defined(DQN_LEAK_TRACKING) -DQN_API void Dqn_Debug_TrackAlloc (void *ptr, Dqn_usize size, bool alloc_can_leak); -DQN_API void Dqn_Debug_TrackDealloc (void *ptr); -DQN_API void Dqn_Debug_DumpLeaks (); +// NOTE: [$DEBG] DN_Debug ///////////////////////////////////////////////////////////////////////// +#if defined(DN_LEAK_TRACKING) +DN_API void DN_Debug_TrackAlloc (void *ptr, DN_USize size, bool alloc_can_leak); +DN_API void DN_Debug_TrackDealloc (void *ptr); +DN_API void DN_Debug_DumpLeaks (); #else -#define Dqn_Debug_TrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0) -#define Dqn_Debug_TrackDealloc(ptr) do { (void)ptr; } while (0) -#define Dqn_Debug_DumpLeaks() do { } while (0) +#define DN_Debug_TrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0) +#define DN_Debug_TrackDealloc(ptr) do { (void)ptr; } while (0) +#define DN_Debug_DumpLeaks() do { } while (0) #endif diff --git a/dqn_docs.cpp b/dqn_docs.cpp index f318e1a..0a6fabb 100644 --- a/dqn_docs.cpp +++ b/dqn_docs.cpp @@ -27,36 +27,41 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -DQN_MSVC_WARNING_PUSH -DQN_MSVC_WARNING_DISABLE(4702) // unreachable code -void Dqn_Docs_Demo() +DN_MSVC_WARNING_PUSH +DN_MSVC_WARNING_DISABLE(4702) // unreachable code +void DN_Docs_Demo() { - Dqn_Library_Init(Dqn_LibraryOnInit_Nil); + // NOTE: Before using anything in the library, DN_Core_Init() must be + // called, for example: + #if 0 + DN_Core core = {}; + DN_Core_Init(&core, DN_CoreOnInit_Nil); + #endif - // NOTE: Dqn_Atomic_SetValue64 ///////////////////////////////////////////////////////////////// - // NOTE: Dqn_Atomic_SetValue32 ///////////////////////////////////////////////////////////////// + // NOTE: DN_Atomic_SetValue64 ///////////////////////////////////////////////////////////////// + // NOTE: DN_Atomic_SetValue32 ///////////////////////////////////////////////////////////////// // Atomically set the value into the target using an atomic compare and swap // idiom. The return value of the function is the value that was last stored // in the target. { uint64_t target = 8; uint64_t value_to_set = 0xCAFE; - if (Dqn_Atomic_SetValue64(&target, value_to_set) == 8) { + if (DN_Atomic_SetValue64(&target, value_to_set) == 8) { // Atomic swap was successful, e.g. the last value that this thread // observed was '8' which is the value we initialised with e.g. no // other thread has modified the value. } } - // NOTE: Dqn_BytesToHex //////////////////////////////////////////////////////////////////////// + // NOTE: DN_BytesToHex //////////////////////////////////////////////////////////////////////// { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); unsigned char bytes[2] = {0xFA, 0xCE}; - Dqn_Str8 hex = Dqn_BytesToHex(tmem.arena, bytes, sizeof(bytes)); - DQN_ASSERT(hex == DQN_STR8("face")); // NOTE: Guaranteed to be null-terminated + DN_Str8 hex = DN_BytesToHex(tmem.arena, bytes, sizeof(bytes)); + DN_ASSERT(hex == DN_STR8("face")); // NOTE: Guaranteed to be null-terminated } - // NOTE: DQN_CHECK ///////////////////////////////////////////////////////////////////////////// + // NOTE: DN_CHECK ///////////////////////////////////////////////////////////////////////////// // // Check the expression trapping in debug, whilst in release- trapping is // removed and the expression is evaluated as if it were a normal 'if' branch. @@ -65,29 +70,29 @@ void Dqn_Docs_Demo() // traps to notify the developer in builds when it's compiled in. { bool flag = true; - if (DQN_CHECKF(flag, "Flag was false!")) { + if (DN_CHECKF(flag, "Flag was false!")) { /// This branch will execute! } } - // NOTE: Dqn_CPUID ///////////////////////////////////////////////////////////////////////////// + // NOTE: DN_CPUID ///////////////////////////////////////////////////////////////////////////// // Execute the 'CPUID' instruction which lets you query the capabilities of // the current CPU. - // NOTE: DQN_DEFER + // NOTE: DN_DEFER // // A macro that expands to a C++ lambda that executes arbitrary code on // scope exit. { int x = 0; - DQN_DEFER { + DN_DEFER { x = 3; }; x = 1; - // On scope exit, DQN_DEFER object executes and assigns x = 3 + // On scope exit, DN_DEFER object executes and assigns x = 3 } - // NOTE: Dqn_DSMap ///////////////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap ///////////////////////////////////////////////////////////////////////////// // // A hash table configured using the presets recommended by Demitri Spanos // from the Handmade Network (HMN), @@ -112,7 +117,7 @@ void Dqn_Docs_Demo() // of the map. On element erase, the last element is swapped into the // deleted element causing the non-sorted property of this table. // - // The 0th slot (DQN_DS_MAP_SENTINEL_SLOT) in the slots array is reserved + // The 0th slot (DN_DS_MAP_SENTINEL_SLOT) in the slots array is reserved // for a sentinel value, e.g. all zeros value. After map initialisation the // 'occupied' value of the array will be set to 1 to exclude the sentinel // from the capacity of the table. Skip the first value if you are iterating @@ -128,8 +133,8 @@ void Dqn_Docs_Demo() // buffer, this buffer must be valid throughout the lifetime of the hash // table! { - // NOTE: Dqn_DSMap_Init ////////////////////////////////////////////////////////////////// - // NOTE: Dqn_DSMap_Deinit ////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_Init ////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_Deinit ////////////////////////////////////////////////////////////////// // // Initialise a hash table where the table size *must* be a // power-of-two, otherwise an assert will be triggered. If @@ -147,16 +152,16 @@ void Dqn_Docs_Demo() // // A 'Deinit' of the map will similarly deallocate the passed in arena (as // the map takes ownership of the arena). - Dqn_Arena arena = {}; - Dqn_DSMap map = Dqn_DSMap_Init(&arena, /*size*/ 1024, Dqn_DSMapFlags_Nil); // Size must be PoT! - DQN_ASSERT(Dqn_DSMap_IsValid(&map)); // Valid if no initialisation failure (e.g. mem alloc failure) + DN_Arena arena = {}; + 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) - // NOTE: Dqn_DSMap_KeyCStringLit /////////////////////////////////////////////////////////// - // NOTE: Dqn_DSMap_KeyU64 /////////////////////////////////////////////////////////// - // NOTE: Dqn_DSMap_KeyU64NoHash /////////////////////////////////////////////////////////// - // NOTE: Dqn_DSMap_KeyBuffer /////////////////////////////////////////////////////////// - // NOTE: Dqn_DSMap_KeyStr8 /////////////////////////////////////////////////////////// - // NOTE: Dqn_DSMap_KeyStr8Copy /////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_KeyCStringLit /////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_KeyU64 /////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_KeyU64NoHash /////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_KeyBuffer /////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_KeyStr8 /////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_KeyStr8Copy /////////////////////////////////////////////////////////// // Create a hash-table key where: // // KeyCStringLit: Uses a Hash(cstring literal) @@ -177,11 +182,11 @@ void Dqn_Docs_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. - Dqn_DSMapKey key = Dqn_DSMap_KeyStr8(&map, DQN_STR8("Sample Key")); + DN_DSMapKey key = DN_DSMap_KeyStr8(&map, DN_STR8("Sample Key")); - // NOTE: Dqn_DSMap_Find //////////////////////////////////////////////////////////////////// - // NOTE: Dqn_DSMap_Make //////////////////////////////////////////////////////////////////// - // NOTE: Dqn_DSMap_Set //////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_Find //////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_Make //////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_Set //////////////////////////////////////////////////////////////////// // // Query or commit key-value pair to the table, where: // @@ -199,54 +204,54 @@ void Dqn_Docs_Demo() // the table will be grown to 2x the current the size before insertion // completes. { - Dqn_DSMapResult set_result = Dqn_DSMap_Set(&map, key, 0xCAFE); - DQN_ASSERT(!set_result.found); // First time we are setting the key-value pair, it wasn't previously in the table - DQN_ASSERT(map.occupied == 2); // Sentinel + new element == 2 + DN_DSMapResult set_result = DN_DSMap_Set(&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 } // Iterating elements in the array, note that index '0' is the sentinel // slot! You typically don't care about it! - for (Dqn_usize index = 1; index < map.occupied; index++) { - Dqn_DSMapSlot *it = map.slots + index; - Dqn_DSMapKey it_key = it->key; + for (DN_USize index = 1; index < map.occupied; index++) { + DN_DSMapSlot *it = map.slots + index; + DN_DSMapKey it_key = it->key; int *it_value = &it->value; - DQN_ASSERT(*it_value == 0xCAFE); + DN_ASSERT(*it_value == 0xCAFE); - DQN_ASSERT(Dqn_Str8_Init(it_key.buffer_data, it_key.buffer_size) == DQN_STR8("Sample Key")); + DN_ASSERT(DN_Str8_Init(it_key.buffer_data, it_key.buffer_size) == DN_STR8("Sample Key")); } - // NOTE: Dqn_DSMap_Erase /////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_Erase /////////////////////////////////////////////////////////////////// // // 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 = Dqn_DSMap_Erase(&map, key); - DQN_ASSERT(erased); - DQN_ASSERT(map.occupied == 1); // Sentinel element + bool erased = DN_DSMap_Erase(&map, key); + DN_ASSERT(erased); + DN_ASSERT(map.occupied == 1); // Sentinel element } - Dqn_DSMap_Deinit(&map, Dqn_ZeroMem_Yes); // Deallocates the 'arena' for us! + DN_DSMap_Deinit(&map, DN_ZeroMem_Yes); // Deallocates the 'arena' for us! } - // NOTE: Dqn_DSMap_Hash //////////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_Hash //////////////////////////////////////////////////////////////////////// // // 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: Dqn_DSMap_HashToSlotIndex ///////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_HashToSlotIndex ///////////////////////////////////////////////////////////// // // Calculate the index into the map's 'slots' array from the given hash. - // NOTE: Dqn_DSMap_Resize ////////////////////////////////////////////////////////////////////// + // NOTE: DN_DSMap_Resize ////////////////////////////////////////////////////////////////////// // // 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: Dqn_ErrorSink ///////////////////////////////////////////////////////////////////////// + // 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 @@ -268,9 +273,9 @@ void Dqn_Docs_Demo() // (A) Conventional error checking patterns using return/sentinel values #if 0 - Dqn_OSFile *file = Dqn_OS_FileOpen("/path/to/file", ...); + DN_OSFile *file = DN_OS_FileOpen("/path/to/file", ...); if (file) { - if (!Dqn_OS_FileWrite(file, "abc")) { + if (!DN_OS_FileWrite(file, "abc")) { // Error handling! } Dnq_OS_FileClose(file); @@ -282,11 +287,11 @@ void Dqn_Docs_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) { - Dqn_ErrorSink *error = Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode_Nil); - Dqn_OSFile file = Dqn_OS_FileOpen(DQN_STR8("/path/to/file"), Dqn_OSFileOpen_OpenIfExist, Dqn_OSFileAccess_ReadWrite, error); - Dqn_OS_FileWrite(&file, DQN_STR8("abc"), error); - Dqn_OS_FileClose(&file); - if (Dqn_ErrorSink_EndAndLogErrorF(error, "Failed to write to file")) { + DN_ErrSink *error = DN_ErrSink_Begin(DN_ErrSinkMode_Nil); + DN_OSFile file = DN_OS_FileOpen(DN_STR8("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error); + DN_OS_FileWrite(&file, DN_STR8("abc"), error); + DN_OS_FileClose(&file); + if (DN_ErrSink_EndAndLogErrorF(error, "Failed to write to file")) { // Do error handling! } } @@ -306,49 +311,49 @@ void Dqn_Docs_Demo() // be populated by the first error encountered in that scope. if (0) { - Dqn_ErrorSink *error = Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode_Nil); - Dqn_OSFile file = Dqn_OS_FileOpen(DQN_STR8("/path/to/file"), Dqn_OSFileOpen_OpenIfExist, Dqn_OSFileAccess_ReadWrite, error); - Dqn_OS_FileWrite(&file, DQN_STR8("abc"), error); - Dqn_OS_FileClose(&file); + DN_ErrSink *error = DN_ErrSink_Begin(DN_ErrSinkMode_Nil); + DN_OSFile file = DN_OS_FileOpen(DN_STR8("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error); + DN_OS_FileWrite(&file, DN_STR8("abc"), error); + DN_OS_FileClose(&file); { // NOTE: My error sinks are thread-local, so the returned 'error' is // the same as the 'error' value above. - Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode_Nil); - Dqn_OS_WriteAll(DQN_STR8("/path/to/another/file"), DQN_STR8("123"), error); - Dqn_ErrorSink_EndAndLogErrorF(error, "Failed to write to another file"); + DN_ErrSink_Begin(DN_ErrSinkMode_Nil); + DN_OS_WriteAll(DN_STR8("/path/to/another/file"), DN_STR8("123"), error); + DN_ErrSink_EndAndLogErrorF(error, "Failed to write to another file"); } - if (Dqn_ErrorSink_EndAndLogErrorF(error, "Failed to write to file")) { + if (DN_ErrSink_EndAndLogErrorF(error, "Failed to write to file")) { // Do error handling! } } - // NOTE: Dqn_FStr8_Max ///////////////////////////////////////////////////////////////////////// + // NOTE: DN_FStr8_Max ///////////////////////////////////////////////////////////////////////// // // Return the maximum capacity of the string, e.g. the 'N' template // parameter of FStr8 - // NOTE: Dqn_FStr8_ToStr8 ////////////////////////////////////////////////////////////////////// + // NOTE: DN_FStr8_ToStr8 ////////////////////////////////////////////////////////////////////// // - // Create a slice of the string into a pointer and length string (Dqn_Str8). + // Create a slice of the string into a pointer and length string (DN_Str8). // The lifetime of the slice is bound to the lifetime of the FStr8 and is // invalidated when the FStr8 is. - // NOTE: Dqn_HexToBytes //////////////////////////////////////////////////////////////////////// + // NOTE: DN_HexToBytes //////////////////////////////////////////////////////////////////////// { unsigned char bytes[2]; - Dqn_usize bytes_written = Dqn_HexToBytesPtr(DQN_STR8("0xFACE"), bytes, sizeof(bytes)); - DQN_ASSERT(bytes_written == 2); - DQN_ASSERT(bytes[0] == 0xFA); - DQN_ASSERT(bytes[1] == 0xCE); + DN_USize bytes_written = DN_HexToBytesPtr(DN_STR8("0xFACE"), bytes, sizeof(bytes)); + DN_ASSERT(bytes_written == 2); + DN_ASSERT(bytes[0] == 0xFA); + DN_ASSERT(bytes[1] == 0xCE); } - // NOTE: Dqn_JSONBuilder_Build ///////////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_Build ///////////////////////////////////////////////////////////////// // // Convert the internal JSON buffer in the builder into a string. - // NOTE: Dqn_JSONBuilder_KeyValue, Dqn_JSONBuilder_KeyValueF + // NOTE: DN_JSONBuilder_KeyValue, DN_JSONBuilder_KeyValueF // // Add a JSON key value pair untyped. The value is emitted directly without // checking the contents of value. @@ -356,28 +361,28 @@ void Dqn_Docs_Demo() // All other functions internally call into this function which is the main // workhorse of the builder. - // NOTE: Dqn_JSON_Builder_ObjectEnd + // NOTE: DN_JSON_Builder_ObjectEnd // // End a JSON object in the builder, generates internally a '}' string - // NOTE: Dqn_JSON_Builder_ArrayEnd + // NOTE: DN_JSON_Builder_ArrayEnd // // End a JSON array in the builder, generates internally a ']' string - // NOTE: Dqn_JSONBuilder_LiteralNamed + // NOTE: DN_JSONBuilder_LiteralNamed // // Add a named JSON key-value object whose value is directly written to // the following '"": ' (e.g. useful for emitting the 'null' // value) - // NOTE: Dqn_JSONBuilder_U64 ///////////////////////////////////////////////////////////// - // NOTE: Dqn_JSONBuilder_U64Named ///////////////////////////////////////////////////////////// - // NOTE: Dqn_JSONBuilder_I64 ///////////////////////////////////////////////////////////// - // NOTE: Dqn_JSONBuilder_I64Named ///////////////////////////////////////////////////////////// - // NOTE: Dqn_JSONBuilder_F64 ///////////////////////////////////////////////////////////// - // NOTE: Dqn_JSONBuilder_F64Named ///////////////////////////////////////////////////////////// - // NOTE: Dqn_JSONBuilder_Bool ///////////////////////////////////////////////////////////// - // NOTE: Dqn_JSONBuilder_BoolNamed ///////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_U64 ///////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_U64Named ///////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_I64 ///////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_I64Named ///////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_F64 ///////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_F64Named ///////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_Bool ///////////////////////////////////////////////////////////// + // NOTE: DN_JSONBuilder_BoolNamed ///////////////////////////////////////////////////////////// // // Add the named JSON data type as a key-value object. The named variants // generates internally the key-value pair, e.g. @@ -386,31 +391,31 @@ void Dqn_Docs_Demo() // // And the non-named version emit just the 'value' portion - // NOTE: Dqn_List_Iterate ////////////////////////////////////////////////////////////////////// + // NOTE: DN_List_Iterate ////////////////////////////////////////////////////////////////////// { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_List list = Dqn_List_Init(/*chunk_size*/ 128); - for (Dqn_ListIterator it = {}; Dqn_List_Iterate(&list, &it, 0);) { + DN_TLSTMem tmem = DN_TLS_TMem(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: Dqn_LogProc /////////////////////////////////////////////////////////////////////////// + // NOTE: DN_LogProc /////////////////////////////////////////////////////////////////////////// // // Function prototype of the logging interface exposed by this library. Logs - // emitted using the Dqn_Log_* family of functions are routed through this + // emitted using the DN_Log_* family of functions are routed through this // routine. - // NOTE: Dqn_FNV1A ///////////////////////////////////////////////////////////////////////////// + // NOTE: DN_FNV1A ///////////////////////////////////////////////////////////////////////////// { - // Using the default hash as defined by DQN_FNV1A32_SEED and - // DQN_FNV1A64_SEED for 32/64bit hashes respectively + // Using the default hash as defined by DN_FNV1A32_SEED and + // DN_FNV1A64_SEED for 32/64bit hashes respectively uint32_t buffer1 = 0xCAFE0000; uint32_t buffer2 = 0xDEAD0000; { - uint64_t hash = Dqn_FNV1A64_Hash(&buffer1, sizeof(buffer1)); - hash = Dqn_FNV1A64_Iterate(&buffer2, sizeof(buffer2), hash); // Chained hashing + uint64_t hash = DN_FNV1A64_Hash(&buffer1, sizeof(buffer1)); + hash = DN_FNV1A64_Iterate(&buffer2, sizeof(buffer2), hash); // Chained hashing (void)hash; } @@ -418,22 +423,22 @@ void Dqn_Docs_Demo() // calling 'Iterate' immediately. { uint64_t custom_seed = 0xABCDEF12; - uint64_t hash = Dqn_FNV1A64_Iterate(&buffer1, sizeof(buffer1), custom_seed); - hash = Dqn_FNV1A64_Iterate(&buffer2, sizeof(buffer2), hash); + uint64_t hash = DN_FNV1A64_Iterate(&buffer1, sizeof(buffer1), custom_seed); + hash = DN_FNV1A64_Iterate(&buffer2, sizeof(buffer2), hash); (void)hash; } } - // NOTE: Dqn_FmtBuffer3DotTruncate ////////////////////////////////////////////////////////////// + // NOTE: DN_FmtBuffer3DotTruncate ////////////////////////////////////////////////////////////// { char buffer[8] = {}; - int buffer_chars_written = Dqn_FmtBuffer3DotTruncate(buffer, sizeof(buffer), "This string is longer than %d characters", DQN_CAST(int)(sizeof(buffer) - 1)); + int buffer_chars_written = DN_FmtBuffer3DotTruncate(buffer, sizeof(buffer), "This string is longer than %d characters", DN_CAST(int)(sizeof(buffer) - 1)); if (0) { // Prints "This ..." which is exactly 8 characters long printf("%.*s", buffer_chars_written, buffer); } } - // NOTE: Dqn_MurmurHash3 /////////////////////////////////////////////////////////////////////// + // NOTE: DN_MurmurHash3 /////////////////////////////////////////////////////////////////////// // MurmurHash3 was written by Austin Appleby, and is placed in the public // domain. The author (Austin Appleby) hereby disclaims copyright to this source // code. @@ -443,20 +448,27 @@ void Dqn_Docs_Demo() // compile and run any of them on any platform, but your performance with the // non-native version will be less than optimal. - // NOTE: Dqn_OS_DateUnixTime + // NOTE: DN_OS_DateUnixTime // // Produce the time elapsed since the unix epoch { - uint64_t now = Dqn_OS_DateUnixTime(); + uint64_t now = DN_OS_DateUnixTimeS(); (void)now; } - // NOTE: Dqn_OS_FileDelete + // NOTE: DN_OS_DirIterate ///////////////////////////////////////////////////////////////////// + // + // Iterate the files within the passed in folder + for (DN_OSDirIterator it = {}; DN_OS_DirIterate(DN_STR8("."), &it); ) { + printf("%.*s\n", DN_STR_FMT(it.file_name)); + } + + // NOTE: DN_OS_FileDelete // // This function can only delete files and it can *only* delete directories // if it is empty otherwise this function fails. - // NOTE: Dqn_OS_WriteAllSafe + // NOTE: DN_OS_WriteAllSafe // Writes the file at the path first by appending '.tmp' to the 'path' to // write to. If the temporary file is written successfully then the file is // copied into 'path', for example: @@ -467,13 +479,13 @@ void Dqn_Docs_Demo() // If 'tmp_path' is written to successfuly, the file will be copied over into // 'path'. if (0) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_ErrorSink *error = Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode_Nil); - Dqn_OS_WriteAllSafe(/*path*/ DQN_STR8("C:/Home/my.txt"), /*buffer*/ DQN_STR8("Hello world"), error); - Dqn_ErrorSink_EndAndLogErrorF(error, ""); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_ErrSink *error = DN_ErrSink_Begin(DN_ErrSinkMode_Nil); + DN_OS_WriteAllSafe(/*path*/ DN_STR8("C:/Home/my.txt"), /*buffer*/ DN_STR8("Hello world"), error); + DN_ErrSink_EndAndLogErrorF(error, ""); } - // NOTE: Dqn_OS_EstimateTSCPerSecond /////////////////////////////////////////////////////////// + // NOTE: DN_OS_EstimateTSCPerSecond /////////////////////////////////////////////////////////// // // Estimate how many timestamp count's (TSC) there are per second. TSC // is evaluated by calling __rdtsc() or the equivalent on the platform. This @@ -487,18 +499,18 @@ void Dqn_Docs_Demo() // This may return 0 if querying the CPU timestamp counter is not supported // on the platform (e.g. __rdtsc() or __builtin_readcyclecounter() returns 0). - // NOTE: Dqn_OS_EXEDir ///////////////////////////////////////////////////////////////////////// + // NOTE: DN_OS_EXEDir ///////////////////////////////////////////////////////////////////////// // // Retrieve the executable directory without the trailing '/' or ('\' for // windows). If this fails an empty string is returned. - // NOTE: Dqn_OS_PerfCounterFrequency /////////////////////////////////////////////////////////// + // NOTE: DN_OS_PerfCounterFrequency /////////////////////////////////////////////////////////// // // Get the number of ticks in the performance counter per second for the // operating system you're running on. This value can be used to calculate // duration from OS performance counter ticks. - // NOTE: Dqn_OS_Path* ////////////////////////////////////////////////////////////////////////// + // NOTE: DN_OS_Path* ////////////////////////////////////////////////////////////////////////// // Construct paths ensuring the native OS path separators are used in the // string. In 99% of cases you can use 'PathConvertF' which converts the // given path in one shot ensuring native path separators in the string. @@ -527,39 +539,39 @@ void Dqn_Docs_Demo() // path: path/to/your/desired/folder // popped_path: path/to/your/desired - // NOTE: Dqn_OS_SecureRNGBytes ///////////////////////////////////////////////////////////////// + // NOTE: DN_OS_SecureRNGBytes ///////////////////////////////////////////////////////////////// // // Generate cryptographically secure bytes - // NOTE: Dqn_PCG32 ///////////////////////////////////////////////////////////////////////////// + // NOTE: DN_PCG32 ///////////////////////////////////////////////////////////////////////////// // // Random number generator of the PCG family. Implementation taken from // Martins Mmozeiko from Handmade Network. // https://gist.github.com/mmozeiko/1561361cd4105749f80bb0b9223e9db8 { - Dqn_PCG32 rng = Dqn_PCG32_Init(0xb917'a66c'1d9b'3bd8); + DN_PCG32 rng = DN_PCG32_Init(0xb917'a66c'1d9b'3bd8); - // NOTE: Dqn_PCG32_Range /////////////////////////////////////////////////////////////////// + // NOTE: DN_PCG32_Range /////////////////////////////////////////////////////////////////// // // Generate a value in the [low, high) interval - uint32_t u32_value = Dqn_PCG32_Range(&rng, 32, 64); - DQN_ASSERT(u32_value >= 32 && u32_value < 64); + uint32_t u32_value = DN_PCG32_Range(&rng, 32, 64); + DN_ASSERT(u32_value >= 32 && u32_value < 64); - // NOTE: Dqn_PCG32_NextF32 ///////////////////////////////////////////////////////////////// - // NOTE: Dqn_PCG32_NextF64 ///////////////////////////////////////////////////////////////// + // NOTE: DN_PCG32_NextF32 ///////////////////////////////////////////////////////////////// + // NOTE: DN_PCG32_NextF64 ///////////////////////////////////////////////////////////////// // // Generate a float/double in the [0, 1) interval - Dqn_f64 f64_value = Dqn_PCG32_NextF64(&rng); - DQN_ASSERT(f64_value >= 0.f && f64_value < 1.f); + DN_F64 f64_value = DN_PCG32_NextF64(&rng); + DN_ASSERT(f64_value >= 0.f && f64_value < 1.f); - // NOTE: Dqn_PCG32_Advance ///////////////////////////////////////////////////////////////// + // NOTE: DN_PCG32_Advance ///////////////////////////////////////////////////////////////// // // Step the random number generator by 'delta' steps - Dqn_PCG32_Advance(&rng, /*delta*/ 5); + DN_PCG32_Advance(&rng, /*delta*/ 5); } - #if !defined(DQN_NO_PROFILER) - // NOTE: [$PROF] Dqn_Profiler ////////////////////////////////////////////////////////////////// + #if !defined(DN_NO_PROFILER) + // NOTE: [$PROF] DN_Profiler ////////////////////////////////////////////////////////////////// // // A profiler based off Casey Muratori's Computer Enhance course, Performance // Aware Programming. This profiler measures function elapsed time using the @@ -573,9 +585,9 @@ void Dqn_Docs_Demo() // frame's profiling metrics. { enum Zone { Zone_MainLoop, Zone_Count }; - Dqn_ProfilerZone profiler_zone_main_update = Dqn_Profiler_BeginZone(Zone_MainLoop); + DN_ProfilerZone profiler_zone_main_update = DN_Profiler_BeginZone(Zone_MainLoop); - // NOTE: Dqn_Profiler_AnchorBuffer ///////////////////////////////////////////////////// + // NOTE: DN_Profiler_AnchorBuffer ///////////////////////////////////////////////////// // // Retrieve the requested buffer from the profiler for // writing/reading profiling metrics. Pass in the enum to specify @@ -589,39 +601,39 @@ void Dqn_Docs_Demo() // the front buffer which contain the metrics that you can visualise // regarding the most profiling metrics recorded. - // NOTE: Dqn_Profiler_ReadBuffer /////////////////////////////////////////////////////////// + // NOTE: DN_Profiler_ReadBuffer /////////////////////////////////////////////////////////// // // Retrieve the buffer of anchors of which there are - // `DQN_PROFILER_ANCHOR_BUFFER_SIZE` anchors from the most recent run + // `DN_PROFILER_ANCHOR_BUFFER_SIZE` anchors from the most recent run // of the profiler after you have called `SwapAnchorBuffer` to trigger // the double buffer - Dqn_ProfilerAnchor *read_anchors = Dqn_Profiler_ReadBuffer(); - for (Dqn_usize index = 0; index < DQN_PROFILER_ANCHOR_BUFFER_SIZE; index++) { - Dqn_ProfilerAnchor *anchor = read_anchors + index; - if (Dqn_Str8_HasData(anchor->name)) { + DN_ProfilerAnchor *read_anchors = DN_Profiler_ReadBuffer(); + for (DN_USize index = 0; index < DN_PROFILER_ANCHOR_BUFFER_SIZE; index++) { + DN_ProfilerAnchor *anchor = read_anchors + index; + if (DN_Str8_HasData(anchor->name)) { // ... } } - // NOTE: Dqn_Profiler_WriteBuffer ////////////////////////////////////////////////////////// + // NOTE: DN_Profiler_WriteBuffer ////////////////////////////////////////////////////////// // // Same as `ReadBuffer` however we return the buffer that the profiler // is currently writing anchors into. - Dqn_ProfilerAnchor *write_anchors = Dqn_Profiler_WriteBuffer(); - for (Dqn_usize index = 0; index < DQN_PROFILER_ANCHOR_BUFFER_SIZE; index++) { - Dqn_ProfilerAnchor *anchor = write_anchors + index; - if (Dqn_Str8_HasData(anchor->name)) { + DN_ProfilerAnchor *write_anchors = DN_Profiler_WriteBuffer(); + for (DN_USize index = 0; index < DN_PROFILER_ANCHOR_BUFFER_SIZE; index++) { + DN_ProfilerAnchor *anchor = write_anchors + index; + if (DN_Str8_HasData(anchor->name)) { // ... } } - Dqn_Profiler_EndZone(profiler_zone_main_update); - Dqn_Profiler_SwapAnchorBuffer(); // Should occur after all profiling zones are ended! - *g_dqn_library->profiler = {}; + DN_Profiler_EndZone(profiler_zone_main_update); + DN_Profiler_SwapAnchorBuffer(); // Should occur after all profiling zones are ended! + DN_MEMSET(&g_dn_core->profiler, 0, sizeof(g_dn_core->profiler)); } - #endif // !defined(DQN_NO_PROFILER) + #endif // !defined(DN_NO_PROFILER) - // NOTE: Dqn_Raycast_LineIntersectV2 /////////////////////////////////////////////////////////// + // NOTE: DN_Raycast_LineIntersectV2 /////////////////////////////////////////////////////////// // Calculate the intersection point of 2 rays returning a `t` value // which is how much along the direction of the 'ray' did the intersection // occur. @@ -629,17 +641,17 @@ void Dqn_Docs_Demo() // The arguments passed in do not need to be normalised for the function to // work. - // NOTE: Dqn_Safe_* //////////////////////////////////////////////////////////////////////////// + // NOTE: DN_Safe_* //////////////////////////////////////////////////////////////////////////// // - // Performs the arithmetic operation and uses DQN_CHECK on the operation to + // Performs the arithmetic operation and uses DN_CHECK on the operation to // check if it overflows. If it overflows the MAX value of the integer is // returned in add and multiply operations, and, the minimum is returned in // subtraction and division. - // NOTE: Dqn_Safe_SaturateCast* //////////////////////////////////////////////////////////////// + // NOTE: DN_Safe_SaturateCast* //////////////////////////////////////////////////////////////// // // Truncate the passed in value to the return type clamping the resulting - // value to the max value of the desired data type. It DQN_CHECK's the + // value to the max value of the desired data type. It DN_CHECK's the // truncation. // // The following sentinel values are returned when saturated, @@ -671,7 +683,7 @@ void Dqn_Docs_Demo() // ISize -> U32: 0 or UINT32_MAX // ISize -> U64: 0 or UINT64_MAX // - // I64 -> ISize: DQN_ISIZE_MIN or DQN_ISIZE_MAX + // I64 -> ISize: DN_ISIZE_MIN or DN_ISIZE_MAX // I64 -> I8: INT8_MIN or INT8_MAX // I64 -> I16: INT16_MIN or INT16_MAX // I64 -> I32: INT32_MIN or INT32_MAX @@ -683,7 +695,7 @@ void Dqn_Docs_Demo() // Int -> U32: 0 or UINT32_MAX // Int -> U64: 0 or UINT64_MAX - // NOTE: Dqn_StackTrace //////////////////////////////////////////////////////////////////////// + // NOTE: DN_StackTrace //////////////////////////////////////////////////////////////////////// // Emit stack traces at the calling site that these functions are invoked // from. // @@ -700,45 +712,45 @@ void Dqn_Docs_Demo() // the debug APIs are aware of how to resolve the new addresses imported // into the address space. { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); - // NOTE: Dqn_StackTrace_Walk /////////////////////////////////////////////////////////////// + // NOTE: DN_StackTrace_Walk /////////////////////////////////////////////////////////////// // // 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. - Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(tmem.arena, /*depth limit*/ 128); + DN_StackTraceWalkResult walk = DN_StackTrace_Walk(tmem.arena, /*depth limit*/ 128); // Loop over the addresses produced in the stack trace - for (Dqn_StackTraceWalkResultIterator it = {}; Dqn_StackTrace_WalkResultIterate(&it, &walk); ) { + for (DN_StackTraceWalkResultIterator it = {}; DN_StackTrace_WalkResultIterate(&it, &walk); ) { - // NOTE: Dqn_StackTrace_RawFrameToFrame //////////////////////////////////////////////// + // NOTE: DN_StackTrace_RawFrameToFrame //////////////////////////////////////////////// // // Converts the base address into a human readable stack trace // entry (e.g. address, line number, file and function name). - Dqn_StackTraceFrame frame = Dqn_StackTrace_RawFrameToFrame(tmem.arena, it.raw_frame); + DN_StackTraceFrame frame = DN_StackTrace_RawFrameToFrame(tmem.arena, it.raw_frame); // You may then print out the frame like so if (0) - printf("%.*s(%" PRIu64 "): %.*s\n", DQN_STR_FMT(frame.file_name), frame.line_number, DQN_STR_FMT(frame.function_name)); + printf("%.*s(%" PRIu64 "): %.*s\n", DN_STR_FMT(frame.file_name), frame.line_number, DN_STR_FMT(frame.function_name)); } // If you load new shared-libraries into the address space it maybe // necessary to call into 'ReloadSymbols' to ensure that the OS is able // to resolve the new addresses. - Dqn_StackTrace_ReloadSymbols(); + DN_StackTrace_ReloadSymbols(); - // NOTE: Dqn_StackTrace_GetFrames ////////////////////////////////////////////////////////// + // NOTE: DN_StackTrace_GetFrames ////////////////////////////////////////////////////////// // // 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'. - Dqn_Slice frames = Dqn_StackTrace_GetFrames(tmem.arena, /*depth limit*/ 128); + DN_Slice frames = DN_StackTrace_GetFrames(tmem.arena, /*depth limit*/ 128); (void)frames; } - // NOTE: Dqn_Str8_Alloc //////////////////////////////////////////////////////////////////////// + // NOTE: DN_Str8_Alloc //////////////////////////////////////////////////////////////////////// // // Allocates a string with the requested 'size'. An additional byte is // always requested from the allocator to null-terminate the buffer. This @@ -747,34 +759,34 @@ void Dqn_Docs_Demo() // The returned string's 'size' member variable does *not* include this // additional null-terminating byte. { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 string = Dqn_Str8_Alloc(tmem.arena, /*size*/ 1, Dqn_ZeroMem_Yes); - DQN_ASSERT(string.size == 1); - DQN_ASSERT(string.data[string.size] == 0); // It is null-terminated! + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 string = DN_Str8_Alloc(tmem.arena, /*size*/ 1, DN_ZeroMem_Yes); + DN_ASSERT(string.size == 1); + DN_ASSERT(string.data[string.size] == 0); // It is null-terminated! } - // NOTE: Dqn_Str8_BinarySplit ////////////////////////////////////////////////////////////////// + // NOTE: DN_Str8_BinarySplit ////////////////////////////////////////////////////////////////// // // Splits a string into 2 substrings occuring prior and after the first // occurence of the delimiter. Neither strings include the matched // delimiter. If no delimiter is found, the 'rhs' of the split will be // empty. { - Dqn_Str8BinarySplitResult dot_split = Dqn_Str8_BinarySplit(/*string*/ DQN_STR8("abc.def.ghi"), /*delimiter*/ DQN_STR8(".")); - Dqn_Str8BinarySplitResult slash_split = Dqn_Str8_BinarySplit(/*string*/ DQN_STR8("abc.def.ghi"), /*delimiter*/ DQN_STR8("/")); - DQN_ASSERT(dot_split.lhs == DQN_STR8("abc") && dot_split.rhs == DQN_STR8("def.ghi")); - DQN_ASSERT(slash_split.lhs == DQN_STR8("abc.def.ghi") && slash_split.rhs == DQN_STR8("")); + DN_Str8BinarySplitResult dot_split = DN_Str8_BinarySplit(/*string*/ DN_STR8("abc.def.ghi"), /*delimiter*/ DN_STR8(".")); + DN_Str8BinarySplitResult slash_split = DN_Str8_BinarySplit(/*string*/ DN_STR8("abc.def.ghi"), /*delimiter*/ DN_STR8("/")); + DN_ASSERT(dot_split.lhs == DN_STR8("abc") && dot_split.rhs == DN_STR8("def.ghi")); + DN_ASSERT(slash_split.lhs == DN_STR8("abc.def.ghi") && slash_split.rhs == DN_STR8("")); // Loop that walks the string and produces ("abc", "def", "ghi") - for (Dqn_Str8 it = DQN_STR8("abc.def.ghi"); it.size; ) { - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplit(it, DQN_STR8(".")); - Dqn_Str8 chunk = split.lhs; // "abc", "def", ... + for (DN_Str8 it = DN_STR8("abc.def.ghi"); it.size; ) { + DN_Str8BinarySplitResult split = DN_Str8_BinarySplit(it, DN_STR8(".")); + DN_Str8 chunk = split.lhs; // "abc", "def", ... it = split.rhs; (void)chunk; } } - // NOTE: Dqn_Str8_FileNameFromPath ///////////////////////////////////////////////////////////// + // NOTE: DN_Str8_FileNameFromPath ///////////////////////////////////////////////////////////// // // Takes a slice to the file name from a file path. The file name is // evaluated by searching from the end of the string backwards to the first @@ -783,41 +795,41 @@ void Dqn_Docs_Demo() // if there were any. { { - Dqn_Str8 string = Dqn_Str8_FileNameFromPath(DQN_STR8("C:/Folder/item.txt")); - DQN_ASSERT(string == DQN_STR8("item.txt")); + DN_Str8 string = DN_Str8_FileNameFromPath(DN_STR8("C:/Folder/item.txt")); + DN_ASSERT(string == DN_STR8("item.txt")); } { // TODO(doyle): Intuitively this seems incorrect. Empty string instead? - Dqn_Str8 string = Dqn_Str8_FileNameFromPath(DQN_STR8("C:/Folder/")); - DQN_ASSERT(string == DQN_STR8("C:/Folder")); + DN_Str8 string = DN_Str8_FileNameFromPath(DN_STR8("C:/Folder/")); + DN_ASSERT(string == DN_STR8("C:/Folder")); } { - Dqn_Str8 string = Dqn_Str8_FileNameFromPath(DQN_STR8("C:/Folder")); - DQN_ASSERT(string == DQN_STR8("Folder")); + DN_Str8 string = DN_Str8_FileNameFromPath(DN_STR8("C:/Folder")); + DN_ASSERT(string == DN_STR8("Folder")); } } - // NOTE: Dqn_Str8_FilePathNoExtension ////////////////////////////////////////////////////////// + // NOTE: DN_Str8_FilePathNoExtension ////////////////////////////////////////////////////////// // // This function preserves the original string if no extension was found. // An extension is defined as the substring after the last '.' encountered // in the string. { - Dqn_Str8 string = Dqn_Str8_FilePathNoExtension(DQN_STR8("C:/Folder/item.txt.bak")); - DQN_ASSERT(string == DQN_STR8("C:/Folder/item.txt")); + DN_Str8 string = DN_Str8_FilePathNoExtension(DN_STR8("C:/Folder/item.txt.bak")); + DN_ASSERT(string == DN_STR8("C:/Folder/item.txt")); } - // NOTE: Dqn_Str8_FileNameNoExtension ////////////////////////////////////////////////////////// + // NOTE: DN_Str8_FileNameNoExtension ////////////////////////////////////////////////////////// // // This function is the same as calling 'FileNameFromPath' followed by // 'FilePathNoExtension' { - Dqn_Str8 string = Dqn_Str8_FileNameNoExtension(DQN_STR8("C:/Folder/item.txt.bak")); - DQN_ASSERT(string == DQN_STR8("item.txt")); + DN_Str8 string = DN_Str8_FileNameNoExtension(DN_STR8("C:/Folder/item.txt.bak")); + DN_ASSERT(string == DN_STR8("item.txt")); } - // NOTE: Dqn_Str8_Replace /////////////////////////////////////////////////////////// - // NOTE: Dqn_Str8_ReplaceInsensitive /////////////////////////////////////////////////////////// + // NOTE: DN_Str8_Replace /////////////////////////////////////////////////////////// + // NOTE: DN_Str8_ReplaceInsensitive /////////////////////////////////////////////////////////// // // Replace any matching substring 'find' with 'replace' in the passed in // 'string'. The 'start_index' may be specified to offset which index the @@ -827,17 +839,17 @@ void Dqn_Docs_Demo() // always be a newly allocated copy, irrespective of if any replacements // were done or not. { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 string = Dqn_Str8_Replace(/*string*/ DQN_STR8("Foo Foo Bar"), - /*find*/ DQN_STR8("Foo"), - /*replace*/ DQN_STR8("Moo"), + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 string = DN_Str8_Replace(/*string*/ DN_STR8("Foo Foo Bar"), + /*find*/ DN_STR8("Foo"), + /*replace*/ DN_STR8("Moo"), /*start_index*/ 1, /*arena*/ tmem.arena, - /*eq_case*/ Dqn_Str8EqCase_Sensitive); - DQN_ASSERT(string == DQN_STR8("Foo Moo Bar")); + /*eq_case*/ DN_Str8EqCase_Sensitive); + DN_ASSERT(string == DN_STR8("Foo Moo Bar")); } - // NOTE: Dqn_Str8_Segment ////////////////////////////////////////////////////////////////////// + // NOTE: DN_Str8_Segment ////////////////////////////////////////////////////////////////////// // // Add a delimiting 'segment_char' every 'segment_size' number of characters // in the string. @@ -845,39 +857,39 @@ void Dqn_Docs_Demo() // Reverse segment delimits the string counting 'segment_size' from the back // of the string. { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 string = Dqn_Str8_Segment(tmem.arena, /*string*/ DQN_STR8("123456789"), /*segment_size*/ 3, /*segment_char*/ ','); - DQN_ASSERT(string == DQN_STR8("123,456,789")); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 string = DN_Str8_Segment(tmem.arena, /*string*/ DN_STR8("123456789"), /*segment_size*/ 3, /*segment_char*/ ','); + DN_ASSERT(string == DN_STR8("123,456,789")); } - // NOTE: Dqn_Str8_Split //////////////////////////////////////////////////////////////////////// + // NOTE: DN_Str8_Split //////////////////////////////////////////////////////////////////////// { // Splits the string at each delimiter into substrings occuring prior and // after until the next delimiter. - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); { - Dqn_Slice splits = Dqn_Str8_SplitAlloc(/*arena*/ tmem.arena, - /*string*/ DQN_STR8("192.168.8.1"), - /*delimiter*/ DQN_STR8("."), - /*mode*/ Dqn_Str8SplitIncludeEmptyStrings_No); - DQN_ASSERT(splits.size == 4); - DQN_ASSERT(splits.data[0] == DQN_STR8("192") && splits.data[1] == DQN_STR8("168") && splits.data[2] == DQN_STR8("8") && splits.data[3] == DQN_STR8("1")); + DN_Slice splits = DN_Str8_SplitAlloc(/*arena*/ tmem.arena, + /*string*/ DN_STR8("192.168.8.1"), + /*delimiter*/ DN_STR8("."), + /*mode*/ DN_Str8SplitIncludeEmptyStrings_No); + DN_ASSERT(splits.size == 4); + DN_ASSERT(splits.data[0] == DN_STR8("192") && splits.data[1] == DN_STR8("168") && splits.data[2] == DN_STR8("8") && splits.data[3] == DN_STR8("1")); } // You can include empty strings that occur when splitting by setting // the split mode to include empty strings. { - Dqn_Slice splits = Dqn_Str8_SplitAlloc(/*arena*/ tmem.arena, - /*string*/ DQN_STR8("a--b"), - /*delimiter*/ DQN_STR8("-"), - /*mode*/ Dqn_Str8SplitIncludeEmptyStrings_Yes); - DQN_ASSERT(splits.size == 3); - DQN_ASSERT(splits.data[0] == DQN_STR8("a") && splits.data[1] == DQN_STR8("") && splits.data[2] == DQN_STR8("b")); + DN_Slice splits = DN_Str8_SplitAlloc(/*arena*/ tmem.arena, + /*string*/ DN_STR8("a--b"), + /*delimiter*/ DN_STR8("-"), + /*mode*/ DN_Str8SplitIncludeEmptyStrings_Yes); + DN_ASSERT(splits.size == 3); + DN_ASSERT(splits.data[0] == DN_STR8("a") && splits.data[1] == DN_STR8("") && splits.data[2] == DN_STR8("b")); } } - // NOTE: Dqn_Str8_ToI64 //////////////////////////////////////////////////////////////////////// - // NOTE: Dqn_Str8_ToU64 //////////////////////////////////////////////////////////////////////// + // NOTE: DN_Str8_ToI64 //////////////////////////////////////////////////////////////////////// + // NOTE: DN_Str8_ToU64 //////////////////////////////////////////////////////////////////////// // // Convert a number represented as a string to a signed 64 bit number. // @@ -897,31 +909,31 @@ void Dqn_Docs_Demo() // 'ToI64' either '+' or '-' prefix is permitted { { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("-1,234"), /*separator*/ ','); - DQN_ASSERT(result.success && result.value == -1234); + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("-1,234"), /*separator*/ ','); + DN_ASSERT(result.success && result.value == -1234); } { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("-1,234"), /*separator*/ 0); - DQN_ASSERT(!result.success && result.value == 1); // 1 because it's a greedy conversion + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("-1,234"), /*separator*/ 0); + DN_ASSERT(!result.success && result.value == 1); // 1 because it's a greedy conversion } } - // NOTE: Dqn_Str8_TrimByteOrderMark //////////////////////////////////////////////////////////// + // NOTE: DN_Str8_TrimByteOrderMark //////////////////////////////////////////////////////////// // // Removes a leading UTF8, UTF16 BE/LE, UTF32 BE/LE byte order mark from the // string if it's present. - // NOTE: DQN_STR_FMT /////////////////////////////////////////////////////////////////////////// + // NOTE: DN_STR_FMT /////////////////////////////////////////////////////////////////////////// // // Unpacks a string struct that has the fields {.data, .size} for printing a // pointer and length style string using the printf format specifier "%.*s" // - // printf("%.*s\n", DQN_STR_FMT(DQN_STR8("Hello world"))); + // printf("%.*s\n", DN_STR_FMT(DN_STR8("Hello world"))); - // NOTE: Dqn_Str8Builder_AppendF //////////////////////////////////////////////////////////// - // NOTE: Dqn_Str8Builder_AppendFV //////////////////////////////////////////////////////////// - // NOTE: Dqn_Str8Builder_AppendRef //////////////////////////////////////////////////////////// - // NOTE: Dqn_Str8Builder_AppendCopy //////////////////////////////////////////////////////////// + // NOTE: DN_Str8Builder_AppendF //////////////////////////////////////////////////////////// + // NOTE: DN_Str8Builder_AppendFV //////////////////////////////////////////////////////////// + // NOTE: DN_Str8Builder_AppendRef //////////////////////////////////////////////////////////// + // NOTE: DN_Str8Builder_AppendCopy //////////////////////////////////////////////////////////// // // - Appends a string to the string builder as follows // @@ -929,8 +941,8 @@ void Dqn_Docs_Demo() // AppendCopy: Stores the string slice by copy (with builder's arena) // AppendF/V: Constructs a format string and calls 'AppendRef' - // NOTE: Dqn_Str8Builder_Build /////////////////////////////////////////////////////////// - // NOTE: Dqn_Str8Builder_BuildCRT /////////////////////////////////////////////////////////// + // NOTE: DN_Str8Builder_Build /////////////////////////////////////////////////////////// + // NOTE: DN_Str8Builder_BuildCRT /////////////////////////////////////////////////////////// // // Constructs the final string by merging all the appended strings into // one merged string. @@ -938,11 +950,11 @@ void Dqn_Docs_Demo() // The CRT variant calls into 'malloc' and the string *must* be released // using 'free'. - // NOTE: Dqn_Str8Builder_BuildSlice /////////////////////////////////////////////////////////// + // NOTE: DN_Str8Builder_BuildSlice /////////////////////////////////////////////////////////// // // Constructs the final string into an array of strings (e.g. a slice) - // NOTE: Dqn_TicketMutex /////////////////////////////////////////////////////////////////////// + // NOTE: DN_TicketMutex /////////////////////////////////////////////////////////////////////// // // A mutex implemented using an atomic compare and swap on tickets handed // out for each critical section. @@ -958,28 +970,28 @@ void Dqn_Docs_Demo() // ideal for long blocking operations. This mutex does not issue any syscalls // and relies entirely on atomic instructions. { - Dqn_TicketMutex mutex = {}; - Dqn_TicketMutex_Begin(&mutex); // Simple procedural mutual exclusion lock - Dqn_TicketMutex_End(&mutex); + DN_TicketMutex mutex = {}; + DN_TicketMutex_Begin(&mutex); // Simple procedural mutual exclusion lock + DN_TicketMutex_End(&mutex); - // NOTE: Dqn_TicketMutex_MakeTicket //////////////////////////////////////////////////////// + // NOTE: DN_TicketMutex_MakeTicket //////////////////////////////////////////////////////// // // Request the next available ticket for locking from the mutex. - Dqn_uint ticket = Dqn_TicketMutex_MakeTicket(&mutex); + DN_UInt ticket = DN_TicketMutex_MakeTicket(&mutex); - if (Dqn_TicketMutex_CanLock(&mutex, ticket)) { - // NOTE: Dqn_TicketMutex_BeginTicket /////////////////////////////////////////////////// + if (DN_TicketMutex_CanLock(&mutex, ticket)) { + // NOTE: DN_TicketMutex_BeginTicket /////////////////////////////////////////////////// // // Locks the mutex using the given ticket if possible. If it's not // the next ticket to be locked the executing thread will block // until the mutex can lock the ticket, i.e. All prior tickets are // returned, in sequence, to the mutex. - Dqn_TicketMutex_BeginTicket(&mutex, ticket); - Dqn_TicketMutex_End(&mutex); + DN_TicketMutex_BeginTicket(&mutex, ticket); + DN_TicketMutex_End(&mutex); } } - // NOTE: Dqn_ThreadContext ///////////////////////////////////////////////////////////////////// + // NOTE: DN_ThreadContext ///////////////////////////////////////////////////////////////////// // // Each thread is assigned in their thread-local storage (TLS) tmem and // permanent arena allocators. These can be used for allocations with a @@ -989,7 +1001,7 @@ void Dqn_Docs_Demo() // TLS in this implementation is implemented using the `thread_local` C/C++ // keyword. // - // 99% of the time you will want Dqn_TLS_TMem(...) which returns you a + // 99% of the time you will want DN_TLS_TMem(...) which returns you a // temporary arena for function lifetime allocations. On scope exit, the // arena is cleared out. // @@ -1002,21 +1014,21 @@ void Dqn_Docs_Demo() // as the tmem arena requested in the function, we risk the tmem arena // on scope exit deallocating memory belonging to the caller. // - // To avoid this we the 'Dqn_TLS_TMem(...)' API takes in a list of arenas + // To avoid this we the 'DN_TLS_TMem(...)' API takes in a list of arenas // to ensure that we provide a tmem 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. { - Dqn_TLSTMem tmem_a = Dqn_TLS_TMem(nullptr); + DN_TLSTMem tmem_a = DN_TLS_TMem(nullptr); // 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 // to prevent aliasing. - Dqn_TLSTMem tmem_b = Dqn_TLS_TMem(tmem_a.arena); - DQN_ASSERT(tmem_a.arena != tmem_b.arena); + DN_TLSTMem tmem_b = DN_TLS_TMem(tmem_a.arena); + DN_ASSERT(tmem_a.arena != tmem_b.arena); } - // @proc Dqn_Thread_GetTMem + // @proc DN_Thread_GetTMem // @desc Retrieve the per-thread temporary arena allocator that is reset on scope // exit. @@ -1029,22 +1041,22 @@ void Dqn_Docs_Demo() // @param[in] conflict_arena A pointer to the arena currently being used in the // function - // NOTE: Dqn_U64ToStr8 ///////////////////////////////////////////////////////////////////////// + // NOTE: DN_U64ToStr8 ///////////////////////////////////////////////////////////////////////// { - Dqn_U64Str8 string = Dqn_U64ToStr8(123123, ','); + DN_U64Str8 string = DN_U64ToStr8(123123, ','); if (0) // Prints "123,123" - printf("%.*s", DQN_STR_FMT(string)); + printf("%.*s", DN_STR_FMT(string)); } - // NOTE: Dqn_U64ToAge ////////////////////////////////////////////////////////////////////////// + // NOTE: DN_U64ToAge ////////////////////////////////////////////////////////////////////////// { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 string = Dqn_U64ToAge(tmem.arena, DQN_HOURS_TO_S(2) + DQN_MINS_TO_S(30), Dqn_U64AgeUnit_All); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 string = DN_U64ToAge(tmem.arena, DN_HOURS_TO_S(2) + DN_MINS_TO_S(30), DN_U64AgeUnit_All); if (0) // Prints "2hr 30m" - printf("%.*s", DQN_STR_FMT(string)); + printf("%.*s", DN_STR_FMT(string)); } - // NOTE: Dqn_VArray //////////////////////////////////////////////////////////////////////////// + // NOTE: DN_VArray //////////////////////////////////////////////////////////////////////////// // // An array that is backed by virtual memory by reserving addressing space // and comitting pages as items are allocated in the array. This array never @@ -1068,21 +1080,21 @@ void Dqn_Docs_Demo() // In addition to no realloc on expansion or shrinking. // { - // NOTE: Dqn_VArray_Init /////////////////////////////////////////////////////////// - // NOTE: Dqn_VArray_InitByteSize /////////////////////////////////////////////////////////// + // NOTE: DN_VArray_Init /////////////////////////////////////////////////////////// + // NOTE: DN_VArray_InitByteSize /////////////////////////////////////////////////////////// // // 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). - Dqn_VArray array = Dqn_VArray_Init(1024, Dqn_ArenaFlag_Nil); - DQN_ASSERT(array.size == 0 && array.max >= 1024); + DN_VArray array = DN_VArray_Init(1024); + DN_ASSERT(array.size == 0 && array.max >= 1024); - // NOTE: Dqn_VArray_Make ////////////////////////////////////////////////////////////// - // NOTE: Dqn_VArray_Add ////////////////////////////////////////////////////////////// - // NOTE: Dqn_VArray_MakeArray ////////////////////////////////////////////////////////////// - // NOTE: Dqn_VArray_AddArray ////////////////////////////////////////////////////////////// + // NOTE: DN_VArray_Make ////////////////////////////////////////////////////////////// + // NOTE: DN_VArray_Add ////////////////////////////////////////////////////////////// + // NOTE: DN_VArray_MakeArray ////////////////////////////////////////////////////////////// + // NOTE: DN_VArray_AddArray ////////////////////////////////////////////////////////////// // // Allocate items from the array where: // @@ -1091,21 +1103,21 @@ void Dqn_Docs_Demo() // // If the array has run out of capacity or was never initialised, a null // pointer is returned. - int *item = Dqn_VArray_Add(&array, 0xCAFE); - DQN_ASSERT(*item == 0xCAFE && array.size == 1); + int *item = DN_VArray_Add(&array, 0xCAFE); + DN_ASSERT(*item == 0xCAFE && array.size == 1); - // NOTE: Dqn_VArray_AddCArray ///////////////////////////////////////////////////////////// - Dqn_VArray_AddCArray(&array, {1, 2, 3}); - DQN_ASSERT(array.size == 4); + // NOTE: DN_VArray_AddCArray ///////////////////////////////////////////////////////////// + DN_VArray_AddCArray(&array, {1, 2, 3}); + DN_ASSERT(array.size == 4); // TODO(doyle): There's a bug here with the negative erase! // Loop over the array items and erase 1 item. #if 0 - for (Dqn_usize index = 0; index < array.size; index++) { + for (DN_USize index = 0; index < array.size; index++) { if (index != 1) continue; - // NOTE: Dqn_VArray_EraseRange ///////////////////////////////////////////////////////// + // NOTE: DN_VArray_EraseRange ///////////////////////////////////////////////////////// // // Erase the next 'count' items at 'begin_index' in the array. // 'count' can be positive or negative which dictates the if we @@ -1123,24 +1135,24 @@ void Dqn_Docs_Demo() // TODO(doyle): There's a bug here! This doesn't work. // Erase index 0 with the negative count! - Dqn_ArrayEraseResult erase_result = Dqn_VArray_EraseRange(&array, + DN_ArrayEraseResult erase_result = DN_VArray_EraseRange(&array, /*begin_index*/ index, /*count*/ -1, - /*erase*/ Dqn_ArrayErase_Stable); - DQN_ASSERT(erase_result.items_erased == 1); + /*erase*/ DN_ArrayErase_Stable); + DN_ASSERT(erase_result.items_erased == 1); // Use the index returned to continue linearly iterating the array index = erase_result.it_index; - DQN_ASSERT(array.data[index + 1] == 2); // Next loop iteration will process item '2' + DN_ASSERT(array.data[index + 1] == 2); // Next loop iteration will process item '2' } - DQN_ASSERT(array.size == 3 && + DN_ASSERT(array.size == 3 && array.data[0] == 1 && array.data[1] == 2 && array.data[2] == 3); #endif - // NOTE: Dqn_VArray_Reserve //////////////////////////////////////////////////////////////////// + // NOTE: DN_VArray_Reserve //////////////////////////////////////////////////////////////////// // // Ensure that the requested number of items are backed by physical pages // from the OS. Calling this pre-emptively will minimise syscalls into the @@ -1148,36 +1160,36 @@ void Dqn_Docs_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). - Dqn_VArray_Reserve(&array, /*count*/ 8); + DN_VArray_Reserve(&array, /*count*/ 8); - Dqn_VArray_Deinit(&array); + DN_VArray_Deinit(&array); } - // NOTE: Dqn_Win_LastError ///////////////////////////////////////////////////////////// - // NOTE: Dqn_Win_ErrorCodeToMsg ///////////////////////////////////////////////////////////// - #if defined(DQN_PLATFORM_WIN32) + // NOTE: DN_Win_LastError ///////////////////////////////////////////////////////////// + // NOTE: DN_Win_ErrorCodeToMsg ///////////////////////////////////////////////////////////// + #if defined(DN_PLATFORM_WIN32) if (0) { // Generate the error string for the last Win32 API called that return // an error value. - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_WinError get_last_error = Dqn_Win_LastError(tmem.arena); - printf("Error (%lu): %.*s", get_last_error.code, DQN_STR_FMT(get_last_error.msg)); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_WinError get_last_error = DN_Win_LastError(tmem.arena); + printf("Error (%lu): %.*s", get_last_error.code, DN_STR_FMT(get_last_error.msg)); // Alternatively, pass in the error code directly - Dqn_WinError error_msg_for_code = Dqn_Win_ErrorCodeToMsg(tmem.arena, /*error_code*/ 0); - printf("Error (%lu): %.*s", error_msg_for_code.code, DQN_STR_FMT(error_msg_for_code.msg)); + DN_WinError error_msg_for_code = DN_Win_ErrorCodeToMsg(tmem.arena, /*error_code*/ 0); + printf("Error (%lu): %.*s", error_msg_for_code.code, DN_STR_FMT(error_msg_for_code.msg)); } - // NOTE: Dqn_Win_MakeProcessDPIAware /////////////////////////////////////////////////////////// + // NOTE: DN_Win_MakeProcessDPIAware /////////////////////////////////////////////////////////// // // Call once at application start-up to ensure that the application is DPI // aware on Windows and ensure that application UI is scaled up // appropriately for the monitor. - // NOTE: Dqn_Win_Str8ToStr16 ///////////////////////////////////////////////////////////// - // NOTE: Dqn_Win_Str8ToStr16Buffer ///////////////////////////////////////////////////////////// - // NOTE: Dqn_Win_Str16ToStr8 ///////////////////////////////////////////////////////////// - // NOTE: Dqn_Win_Str16ToStr8Buffer ///////////////////////////////////////////////////////////// + // NOTE: DN_Win_Str8ToStr16 ///////////////////////////////////////////////////////////// + // NOTE: DN_Win_Str8ToStr16Buffer ///////////////////////////////////////////////////////////// + // NOTE: DN_Win_Str16ToStr8 ///////////////////////////////////////////////////////////// + // NOTE: DN_Win_Str16ToStr8Buffer ///////////////////////////////////////////////////////////// // // Convert a UTF8 <-> UTF16 string. // @@ -1189,16 +1201,7 @@ void Dqn_Docs_Demo() // // Returns the number of u8's (for UTF16->8) OR u16's (for UTF8->16) // written/required for conversion. 0 if there was a conversion error and can be - // queried using 'Dqn_Win_LastError' - - // NOTE: Dqn_Win_FolderIterate ///////////////////////////////////////////////////////////////// - // - // Iterate the files within the passed in folder - if (0) { - for (Dqn_Win_FolderIterator it = {}; Dqn_Win_FolderIterate(DQN_STR8("C:/your/path/"), &it); ) { - printf("%.*s\n", DQN_STR_FMT(it.file_name)); - } - } + // queried using 'DN_Win_LastError' #endif } -DQN_MSVC_WARNING_POP +DN_MSVC_WARNING_POP diff --git a/dqn_external.cpp b/dqn_external.cpp index 80f53af..a3d6528 100644 --- a/dqn_external.cpp +++ b/dqn_external.cpp @@ -15,7 +15,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -#if !defined(DQN_USE_STD_PRINTF) && !defined(DQN_STB_SPRINTF_HEADER_ONLY) +#if !defined(DN_USE_STD_PRINTF) && !defined(DN_STB_SPRINTF_HEADER_ONLY) // NOTE: [$STBS] stb_sprintf /////////////////////////////////////////////////////////////////////// #define STB_SPRINTF_IMPLEMENTATION #ifdef STB_SPRINTF_IMPLEMENTATION @@ -1710,4 +1710,4 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ -#endif // !defined(DQN_USE_STD_PRINTF) && !defined(DQN_STB_SPRINTF_HEADER_ONLY) +#endif // !defined(DN_USE_STD_PRINTF) && !defined(DN_STB_SPRINTF_HEADER_ONLY) diff --git a/dqn_external.h b/dqn_external.h index 6ba7861..d63f461 100644 --- a/dqn_external.h +++ b/dqn_external.h @@ -19,12 +19,12 @@ */ // NOTE: [$OS_H] OS Headers //////////////////////////////////////////////////////////////////////// -#if !defined(DQN_OS_WIN32) || defined(DQN_OS_WIN32_USE_PTHREADS) +#if !defined(DN_OS_WIN32) || defined(DN_OS_WIN32_USE_PTHREADS) #include #include #endif -#if defined(DQN_OS_UNIX) || defined(DQN_PLATFORM_EMSCRIPTEN) +#if defined(DN_OS_UNIX) || defined(DN_PLATFORM_EMSCRIPTEN) #include // errno #include // O_RDONLY ... etc #include // ioctl @@ -36,31 +36,31 @@ #include // clock_gettime, nanosleep #include // access, gettid, write - #if defined(DQN_PLATFORM_EMSCRIPTEN) + #if defined(DN_PLATFORM_EMSCRIPTEN) #else #include // sendfile #include // FICLONE #endif #endif -#if defined(DQN_PLATFORM_EMSCRIPTEN) - #include // emscripten_fetch (for Dqn_OSHttpResponse) +#if defined(DN_PLATFORM_EMSCRIPTEN) + #include // emscripten_fetch (for DN_OSHttpResponse) #endif // NOTE: [$STBS] stb_sprintf /////////////////////////////////////////////////////////////////////// -#if defined(DQN_USE_STD_PRINTF) +#if defined(DN_USE_STD_PRINTF) #include - #define DQN_SPRINTF(...) sprintf(__VA_ARGS__) - #define DQN_SNPRINTF(...) snprintf(__VA_ARGS__) - #define DQN_VSPRINTF(...) vsprintf(__VA_ARGS__) - #define DQN_VSNPRINTF(...) vsnprintf(__VA_ARGS__) + #define DN_SPRINTF(...) sprintf(__VA_ARGS__) + #define DN_SNPRINTF(...) snprintf(__VA_ARGS__) + #define DN_VSPRINTF(...) vsprintf(__VA_ARGS__) + #define DN_VSNPRINTF(...) vsnprintf(__VA_ARGS__) #else - #define DQN_SPRINTF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__) - #define DQN_SNPRINTF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__) - #define DQN_VSPRINTF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__) - #define DQN_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__) - #if (DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)) && defined(DQN_COMPILER_MSVC) + #if (DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)) && defined(DN_COMPILER_MSVC) #error The STB implementation of sprintf triggers MSVCs implementation of ASAN. Compiling ASAN with STB sprintf is not supported. // NOTE: stb_sprintf assumes c-string literals are 4 byte aligned which is @@ -70,7 +70,7 @@ // // ==12072==ERROR: AddressSanitizer: global-buffer-overflow on address // READ of size 4 at 0x7ff6f442a0d8 thread T0 - // #0 0x7ff6f42d3be8 in stbsp_vsprintfcb C:\Home\Code\dqn\dqn_external.cpp:199 + // #0 0x7ff6f42d3be8 in stbsp_vsprintfcb C:\Home\Code\dn\dn_external.cpp:199 #define STBSP__ASAN __declspec(no_sanitize_address) #endif @@ -290,4 +290,4 @@ STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char c STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); #endif // STB_SPRINTF_H_INCLUDE -#endif // !defined(DQN_USE_STD_PRINTF) +#endif // !defined(DN_USE_STD_PRINTF) diff --git a/dqn_hash.cpp b/dqn_hash.cpp index 6232a75..c8e6301 100644 --- a/dqn_hash.cpp +++ b/dqn_hash.cpp @@ -18,55 +18,55 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$FNV1] Dqn_FNV1A ///////////////////////////////////////////////////////////////////////// +// NOTE: [$FNV1] DN_FNV1A ///////////////////////////////////////////////////////////////////////// // Default values recommended by: http://isthe.com/chongo/tech/comp/fnv/ -DQN_API uint32_t Dqn_FNV1A32_Iterate(void const *bytes, Dqn_usize size, uint32_t hash) +DN_API uint32_t DN_FNV1A32_Iterate(void const *bytes, DN_USize size, uint32_t hash) { - auto buffer = DQN_CAST(uint8_t const *)bytes; - for (Dqn_usize i = 0; i < size; i++) + auto buffer = DN_CAST(uint8_t const *)bytes; + for (DN_USize i = 0; i < size; i++) hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/; return hash; } -DQN_API uint32_t Dqn_FNV1A32_Hash(void const *bytes, Dqn_usize size) +DN_API uint32_t DN_FNV1A32_Hash(void const *bytes, DN_USize size) { - uint32_t result = Dqn_FNV1A32_Iterate(bytes, size, DQN_FNV1A32_SEED); + uint32_t result = DN_FNV1A32_Iterate(bytes, size, DN_FNV1A32_SEED); return result; } -DQN_API uint64_t Dqn_FNV1A64_Iterate(void const *bytes, Dqn_usize size, uint64_t hash) +DN_API uint64_t DN_FNV1A64_Iterate(void const *bytes, DN_USize size, uint64_t hash) { - auto buffer = DQN_CAST(uint8_t const *)bytes; - for (Dqn_usize i = 0; i < size; i++) + auto buffer = DN_CAST(uint8_t const *)bytes; + for (DN_USize i = 0; i < size; i++) hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/; return hash; } -DQN_API uint64_t Dqn_FNV1A64_Hash(void const *bytes, Dqn_usize size) +DN_API uint64_t DN_FNV1A64_Hash(void const *bytes, DN_USize size) { - uint64_t result = Dqn_FNV1A64_Iterate(bytes, size, DQN_FNV1A64_SEED); + uint64_t result = DN_FNV1A64_Iterate(bytes, size, DN_FNV1A64_SEED); return result; } -// NOTE: [$MMUR] Dqn_MurmurHash3 /////////////////////////////////////////////////////////////////// -#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) - #define DQN_MMH3_ROTL32(x, y) _rotl(x, y) - #define DQN_MMH3_ROTL64(x, y) _rotl64(x, y) +// NOTE: [$MMUR] 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 DQN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y))) - #define DQN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y))) + #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 -DQN_FORCE_INLINE uint32_t Dqn_MurmurHash3_GetBlock32(uint32_t const *p, int i) +DN_FORCE_INLINE uint32_t DN_MurmurHash3_GetBlock32(uint32_t const *p, int i) { return p[i]; } -DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_GetBlock64(uint64_t const *p, int i) +DN_FORCE_INLINE uint64_t DN_MurmurHash3_GetBlock64(uint64_t const *p, int i) { return p[i]; } @@ -74,7 +74,7 @@ DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_GetBlock64(uint64_t const *p, int i) //----------------------------------------------------------------------------- // Finalization mix - force all bits of a hash block to avalanche -DQN_FORCE_INLINE uint32_t Dqn_MurmurHash3_FMix32(uint32_t h) +DN_FORCE_INLINE uint32_t DN_MurmurHash3_FMix32(uint32_t h) { h ^= h >> 16; h *= 0x85ebca6b; @@ -84,7 +84,7 @@ DQN_FORCE_INLINE uint32_t Dqn_MurmurHash3_FMix32(uint32_t h) return h; } -DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_FMix64(uint64_t k) +DN_FORCE_INLINE uint64_t DN_MurmurHash3_FMix64(uint64_t k) { k ^= k >> 33; k *= 0xff51afd7ed558ccd; @@ -94,7 +94,7 @@ DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_FMix64(uint64_t k) return k; } -DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed) +DN_API uint32_t DN_MurmurHash3_x86U32(void const *key, int len, uint32_t seed) { const uint8_t *data = (const uint8_t *)key; const int nblocks = len / 4; @@ -111,14 +111,14 @@ DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed) for (int i = -nblocks; i; i++) { - uint32_t k1 = Dqn_MurmurHash3_GetBlock32(blocks, i); + uint32_t k1 = DN_MurmurHash3_GetBlock32(blocks, i); k1 *= c1; - k1 = DQN_MMH3_ROTL32(k1, 15); + k1 = DN_MMH3_ROTL32(k1, 15); k1 *= c2; h1 ^= k1; - h1 = DQN_MMH3_ROTL32(h1, 13); + h1 = DN_MMH3_ROTL32(h1, 13); h1 = h1 * 5 + 0xe6546b64; } @@ -138,7 +138,7 @@ DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed) case 1: k1 ^= tail[0]; k1 *= c1; - k1 = DQN_MMH3_ROTL32(k1, 15); + k1 = DN_MMH3_ROTL32(k1, 15); k1 *= c2; h1 ^= k1; }; @@ -148,12 +148,12 @@ DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed) h1 ^= len; - h1 = Dqn_MurmurHash3_FMix32(h1); + h1 = DN_MurmurHash3_FMix32(h1); return h1; } -DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32_t seed) +DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128(void const *key, int len, uint32_t seed) { const uint8_t *data = (const uint8_t *)key; const int nblocks = len / 16; @@ -171,24 +171,24 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32 for (int i = 0; i < nblocks; i++) { - uint64_t k1 = Dqn_MurmurHash3_GetBlock64(blocks, i * 2 + 0); - uint64_t k2 = Dqn_MurmurHash3_GetBlock64(blocks, i * 2 + 1); + uint64_t k1 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 0); + uint64_t k2 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 1); k1 *= c1; - k1 = DQN_MMH3_ROTL64(k1, 31); + k1 = DN_MMH3_ROTL64(k1, 31); k1 *= c2; h1 ^= k1; - h1 = DQN_MMH3_ROTL64(h1, 27); + h1 = DN_MMH3_ROTL64(h1, 27); h1 += h2; h1 = h1 * 5 + 0x52dce729; k2 *= c2; - k2 = DQN_MMH3_ROTL64(k2, 33); + k2 = DN_MMH3_ROTL64(k2, 33); k2 *= c1; h2 ^= k2; - h2 = DQN_MMH3_ROTL64(h2, 31); + h2 = DN_MMH3_ROTL64(h2, 31); h2 += h1; h2 = h2 * 5 + 0x38495ab5; } @@ -218,7 +218,7 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32 case 9: k2 ^= ((uint64_t)tail[8]) << 0; k2 *= c2; - k2 = DQN_MMH3_ROTL64(k2, 33); + k2 = DN_MMH3_ROTL64(k2, 33); k2 *= c1; h2 ^= k2; @@ -239,7 +239,7 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32 case 1: k1 ^= ((uint64_t)tail[0]) << 0; k1 *= c1; - k1 = DQN_MMH3_ROTL64(k1, 31); + k1 = DN_MMH3_ROTL64(k1, 31); k1 *= c2; h1 ^= k1; }; @@ -253,13 +253,13 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32 h1 += h2; h2 += h1; - h1 = Dqn_MurmurHash3_FMix64(h1); - h2 = Dqn_MurmurHash3_FMix64(h2); + h1 = DN_MurmurHash3_FMix64(h1); + h2 = DN_MurmurHash3_FMix64(h2); h1 += h2; h2 += h1; - Dqn_MurmurHash3 result = {}; + DN_MurmurHash3 result = {}; result.e[0] = h1; result.e[1] = h2; return result; diff --git a/dqn_hash.h b/dqn_hash.h index d17806d..386c7fb 100644 --- a/dqn_hash.h +++ b/dqn_hash.h @@ -17,33 +17,33 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // -// [$FNV1] Dqn_FNV1A -- Hash(x) -> 32/64bit via FNV1a -// [$MMUR] Dqn_MurmurHash3 -- Hash(x) -> 32/128bit via MurmurHash3 +// [$FNV1] DN_FNV1A -- Hash(x) -> 32/64bit via FNV1a +// [$MMUR] DN_MurmurHash3 -- Hash(x) -> 32/128bit via MurmurHash3 // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$FNV1] Dqn_FNV1A ///////////////////////////////////////////////////////////////////////// -#if !defined(DQN_FNV1A32_SEED) - #define DQN_FNV1A32_SEED 2166136261U +// NOTE: [$FNV1] DN_FNV1A ///////////////////////////////////////////////////////////////////////// +#if !defined(DN_FNV1A32_SEED) + #define DN_FNV1A32_SEED 2166136261U #endif -#if !defined(DQN_FNV1A64_SEED) - #define DQN_FNV1A64_SEED 14695981039346656037ULL +#if !defined(DN_FNV1A64_SEED) + #define DN_FNV1A64_SEED 14695981039346656037ULL #endif -// NOTE: [$MMUR] Dqn_MurmurHash3 /////////////////////////////////////////////////////////////////// -struct Dqn_MurmurHash3 { uint64_t e[2]; }; +// NOTE: [$MMUR] DN_MurmurHash3 /////////////////////////////////////////////////////////////////// +struct DN_MurmurHash3 { uint64_t e[2]; }; -// NOTE: [$FNV1] Dqn_FNV1A ///////////////////////////////////////////////////////////////////////// -DQN_API uint32_t Dqn_FNV1A32_Hash (void const *bytes, Dqn_usize size); -DQN_API uint64_t Dqn_FNV1A64_Hash (void const *bytes, Dqn_usize size); -DQN_API uint32_t Dqn_FNV1A32_Iterate (void const *bytes, Dqn_usize size, uint32_t hash); -DQN_API uint64_t Dqn_FNV1A64_Iterate (void const *bytes, Dqn_usize size, uint64_t hash); +// NOTE: [$FNV1] 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: [$MMUR] Dqn_MurmurHash3 /////////////////////////////////////////////////////////////////// -DQN_API uint32_t Dqn_MurmurHash3_x86U32 (void const *key, int len, uint32_t seed); -DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128 (void const *key, int len, uint32_t seed); -#define Dqn_MurmurHash3_x64U128AsU64(key, len, seed) (Dqn_MurmurHash3_x64U128(key, len, seed).e[0]) -#define Dqn_MurmurHash3_x64U128AsU32(key, len, seed) (DQN_CAST(uint32_t)Dqn_MurmurHash3_x64U128(key, len, seed).e[0]) +// NOTE: [$MMUR] 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]) diff --git a/dqn_helpers.cpp b/dqn_helpers.cpp index 73214b2..f6ce45d 100644 --- a/dqn_helpers.cpp +++ b/dqn_helpers.cpp @@ -18,23 +18,23 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$PCGX] Dqn_PCG32 ///////////////////////////////////////////////////////////////////////// -#define DQN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL -#define DQN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL +// NOTE: [$PCGX] DN_PCG32 ///////////////////////////////////////////////////////////////////////// +#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL +#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL -DQN_API Dqn_PCG32 Dqn_PCG32_Init(uint64_t seed) +DN_API DN_PCG32 DN_PCG32_Init(uint64_t seed) { - Dqn_PCG32 result = {}; - Dqn_PCG32_Next(&result); + DN_PCG32 result = {}; + DN_PCG32_Next(&result); result.state += seed; - Dqn_PCG32_Next(&result); + DN_PCG32_Next(&result); return result; } -DQN_API uint32_t Dqn_PCG32_Next(Dqn_PCG32 *rng) +DN_API uint32_t DN_PCG32_Next(DN_PCG32 *rng) { uint64_t state = rng->state; - rng->state = state * DQN_PCG_DEFAULT_MULTIPLIER_64 + DQN_PCG_DEFAULT_INCREMENT_64; + rng->state = state * DN_PCG_DEFAULT_MULTIPLIER_64 + DN_PCG_DEFAULT_INCREMENT_64; // XSH-RR uint32_t value = (uint32_t)((state ^ (state >> 18)) >> 27); @@ -42,42 +42,42 @@ DQN_API uint32_t Dqn_PCG32_Next(Dqn_PCG32 *rng) return rot ? (value >> rot) | (value << (32 - rot)) : value; } -DQN_API uint64_t Dqn_PCG32_Next64(Dqn_PCG32 *rng) +DN_API uint64_t DN_PCG32_Next64(DN_PCG32 *rng) { - uint64_t value = Dqn_PCG32_Next(rng); + uint64_t value = DN_PCG32_Next(rng); value <<= 32; - value |= Dqn_PCG32_Next(rng); + value |= DN_PCG32_Next(rng); return value; } -DQN_API uint32_t Dqn_PCG32_Range(Dqn_PCG32 *rng, uint32_t low, uint32_t high) +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 = Dqn_PCG32_Next(rng); + uint32_t r = DN_PCG32_Next(rng); if (r >= threshold) return low + (r % bound); } } -DQN_API float Dqn_PCG32_NextF32(Dqn_PCG32 *rng) +DN_API float DN_PCG32_NextF32(DN_PCG32 *rng) { - uint32_t x = Dqn_PCG32_Next(rng); + uint32_t x = DN_PCG32_Next(rng); return (float)(int32_t)(x >> 8) * 0x1.0p-24f; } -DQN_API double Dqn_PCG32_NextF64(Dqn_PCG32 *rng) +DN_API double DN_PCG32_NextF64(DN_PCG32 *rng) { - uint64_t x = Dqn_PCG32_Next64(rng); + uint64_t x = DN_PCG32_Next64(rng); return (double)(int64_t)(x >> 11) * 0x1.0p-53; } -DQN_API void Dqn_PCG32_Advance(Dqn_PCG32 *rng, uint64_t delta) +DN_API void DN_PCG32_Advance(DN_PCG32 *rng, uint64_t delta) { - uint64_t cur_mult = DQN_PCG_DEFAULT_MULTIPLIER_64; - uint64_t cur_plus = DQN_PCG_DEFAULT_INCREMENT_64; + 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; @@ -95,128 +95,131 @@ DQN_API void Dqn_PCG32_Advance(Dqn_PCG32 *rng, uint64_t delta) rng->state = acc_mult * rng->state + acc_plus; } -#if !defined(DQN_NO_JSON_BUILDER) -// NOTE: [$JSON] Dqn_JSONBuilder /////////////////////////////////////////////////////////////////// -DQN_API Dqn_JSONBuilder Dqn_JSONBuilder_Init(Dqn_Arena *arena, int spaces_per_indent) +#if !defined(DN_NO_JSON_BUILDER) +// NOTE: [$JSON] DN_JSONBuilder /////////////////////////////////////////////////////////////////// +DN_API DN_JSONBuilder DN_JSONBuilder_Init(DN_Arena *arena, int spaces_per_indent) { - Dqn_JSONBuilder result = {}; + DN_JSONBuilder result = {}; result.spaces_per_indent = spaces_per_indent; result.string_builder.arena = arena; return result; } -DQN_API Dqn_Str8 Dqn_JSONBuilder_Build(Dqn_JSONBuilder const *builder, Dqn_Arena *arena) +DN_API DN_Str8 DN_JSONBuilder_Build(DN_JSONBuilder const *builder, DN_Arena *arena) { - Dqn_Str8 result = Dqn_Str8Builder_Build(&builder->string_builder, arena); + DN_Str8 result = DN_Str8Builder_Build(&builder->string_builder, arena); return result; } -DQN_API void Dqn_JSONBuilder_KeyValue(Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value) +DN_API void DN_JSONBuilder_KeyValue(DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value) { if (key.size == 0 && value.size == 0) return; - Dqn_JSONBuilderItem item = Dqn_JSONBuilderItem_KeyValue; - if (value.size == 1) { + DN_JSONBuilderItem item = DN_JSONBuilderItem_KeyValue; + if (value.size >= 1) { if (value.data[0] == '{' || value.data[0] == '[') - item = Dqn_JSONBuilderItem_OpenContainer; + item = DN_JSONBuilderItem_OpenContainer; else if (value.data[0] == '}' || value.data[0] == ']') - item = Dqn_JSONBuilderItem_CloseContainer; + item = DN_JSONBuilderItem_CloseContainer; } bool adding_to_container_with_items = - item != Dqn_JSONBuilderItem_CloseContainer && (builder->last_item == Dqn_JSONBuilderItem_KeyValue || - builder->last_item == Dqn_JSONBuilderItem_CloseContainer); + item != DN_JSONBuilderItem_CloseContainer && (builder->last_item == DN_JSONBuilderItem_KeyValue || + builder->last_item == DN_JSONBuilderItem_CloseContainer); uint8_t prefix_size = 0; char prefix[2] = {0}; if (adding_to_container_with_items) prefix[prefix_size++] = ','; - if (builder->last_item != Dqn_JSONBuilderItem_Empty) + if (builder->last_item != DN_JSONBuilderItem_Empty) prefix[prefix_size++] = '\n'; - if (item == Dqn_JSONBuilderItem_CloseContainer) + if (item == DN_JSONBuilderItem_CloseContainer) builder->indent_level--; int spaces_per_indent = builder->spaces_per_indent ? builder->spaces_per_indent : 2; int spaces = builder->indent_level * spaces_per_indent; if (key.size) { - Dqn_Str8Builder_AddF(&builder->string_builder, + DN_Str8Builder_AppendF(&builder->string_builder, "%.*s%*c\"%.*s\": %.*s", prefix_size, prefix, spaces, ' ', - DQN_STR_FMT(key), - DQN_STR_FMT(value)); + DN_STR_FMT(key), + DN_STR_FMT(value)); } else { - Dqn_Str8Builder_AddF(&builder->string_builder, "%.*s%*c%.*s", prefix_size, prefix, spaces, ' ', DQN_STR_FMT(value)); + if (spaces == 0) + DN_Str8Builder_AppendF(&builder->string_builder, "%.*s%.*s", prefix_size, prefix, DN_STR_FMT(value)); + else + DN_Str8Builder_AppendF(&builder->string_builder, "%.*s%*c%.*s", prefix_size, prefix, spaces, ' ', DN_STR_FMT(value)); } - if (item == Dqn_JSONBuilderItem_OpenContainer) + if (item == DN_JSONBuilderItem_OpenContainer) builder->indent_level++; builder->last_item = item; } -DQN_API void Dqn_JSONBuilder_KeyValueFV(Dqn_JSONBuilder *builder, Dqn_Str8 key, char const *value_fmt, va_list args) +DN_API void DN_JSONBuilder_KeyValueFV(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, va_list args) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(builder->string_builder.arena); - Dqn_Str8 value = Dqn_Str8_InitFV(tmem.arena, value_fmt, args); - Dqn_JSONBuilder_KeyValue(builder, key, value); + DN_TLSTMem tmem = DN_TLS_TMem(builder->string_builder.arena); + DN_Str8 value = DN_Str8_InitFV(tmem.arena, value_fmt, args); + DN_JSONBuilder_KeyValue(builder, key, value); } -DQN_API void Dqn_JSONBuilder_KeyValueF(Dqn_JSONBuilder *builder, Dqn_Str8 key, char const *value_fmt, ...) +DN_API void DN_JSONBuilder_KeyValueF(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...) { va_list args; va_start(args, value_fmt); - Dqn_JSONBuilder_KeyValueFV(builder, key, value_fmt, args); + DN_JSONBuilder_KeyValueFV(builder, key, value_fmt, args); va_end(args); } -DQN_API void Dqn_JSONBuilder_ObjectBeginNamed(Dqn_JSONBuilder *builder, Dqn_Str8 name) +DN_API void DN_JSONBuilder_ObjectBeginNamed(DN_JSONBuilder *builder, DN_Str8 name) { - Dqn_JSONBuilder_KeyValue(builder, name, DQN_STR8("{")); + DN_JSONBuilder_KeyValue(builder, name, DN_STR8("{")); } -DQN_API void Dqn_JSONBuilder_ObjectEnd(Dqn_JSONBuilder *builder) +DN_API void DN_JSONBuilder_ObjectEnd(DN_JSONBuilder *builder) { - Dqn_JSONBuilder_KeyValue(builder, DQN_STR8(""), DQN_STR8("}")); + DN_JSONBuilder_KeyValue(builder, DN_STR8(""), DN_STR8("}")); } -DQN_API void Dqn_JSONBuilder_ArrayBeginNamed(Dqn_JSONBuilder *builder, Dqn_Str8 name) +DN_API void DN_JSONBuilder_ArrayBeginNamed(DN_JSONBuilder *builder, DN_Str8 name) { - Dqn_JSONBuilder_KeyValue(builder, name, DQN_STR8("[")); + DN_JSONBuilder_KeyValue(builder, name, DN_STR8("[")); } -DQN_API void Dqn_JSONBuilder_ArrayEnd(Dqn_JSONBuilder *builder) +DN_API void DN_JSONBuilder_ArrayEnd(DN_JSONBuilder *builder) { - Dqn_JSONBuilder_KeyValue(builder, DQN_STR8(""), DQN_STR8("]")); + DN_JSONBuilder_KeyValue(builder, DN_STR8(""), DN_STR8("]")); } -DQN_API void Dqn_JSONBuilder_StrNamed(Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value) +DN_API void DN_JSONBuilder_Str8Named(DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value) { - Dqn_JSONBuilder_KeyValueF(builder, key, "\"%.*s\"", value.size, value.data); + DN_JSONBuilder_KeyValueF(builder, key, "\"%.*s\"", value.size, value.data); } -DQN_API void Dqn_JSONBuilder_LiteralNamed(Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value) +DN_API void DN_JSONBuilder_LiteralNamed(DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value) { - Dqn_JSONBuilder_KeyValueF(builder, key, "%.*s", value.size, value.data); + DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value.size, value.data); } -DQN_API void Dqn_JSONBuilder_U64Named(Dqn_JSONBuilder *builder, Dqn_Str8 key, uint64_t value) +DN_API void DN_JSONBuilder_U64Named(DN_JSONBuilder *builder, DN_Str8 key, uint64_t value) { - Dqn_JSONBuilder_KeyValueF(builder, key, "%I64u", value); + DN_JSONBuilder_KeyValueF(builder, key, "%I64u", value); } -DQN_API void Dqn_JSONBuilder_I64Named(Dqn_JSONBuilder *builder, Dqn_Str8 key, int64_t value) +DN_API void DN_JSONBuilder_I64Named(DN_JSONBuilder *builder, DN_Str8 key, int64_t value) { - Dqn_JSONBuilder_KeyValueF(builder, key, "%I64d", value); + DN_JSONBuilder_KeyValueF(builder, key, "%I64d", value); } -DQN_API void Dqn_JSONBuilder_F64Named(Dqn_JSONBuilder *builder, Dqn_Str8 key, double value, int decimal_places) +DN_API void DN_JSONBuilder_F64Named(DN_JSONBuilder *builder, DN_Str8 key, double value, int decimal_places) { if (!builder) return; @@ -229,456 +232,467 @@ DQN_API void Dqn_JSONBuilder_F64Named(Dqn_JSONBuilder *builder, Dqn_Str8 key, do char float_fmt[16]; if (decimal_places > 0) { // NOTE: Emit the format string "%.f" i.e. %.1f - DQN_SNPRINTF(float_fmt, sizeof(float_fmt), "%%.%df", decimal_places); + DN_SNPRINTF(float_fmt, sizeof(float_fmt), "%%.%df", decimal_places); } else { // NOTE: Emit the format string "%f" - DQN_SNPRINTF(float_fmt, sizeof(float_fmt), "%%f"); + DN_SNPRINTF(float_fmt, sizeof(float_fmt), "%%f"); } - - char fmt[32]; - if (key.size) - DQN_SNPRINTF(fmt, sizeof(fmt), "\"%%.*s\": %s", float_fmt); - else - DQN_SNPRINTF(fmt, sizeof(fmt), "%s", float_fmt); - - Dqn_JSONBuilder_KeyValueF(builder, key, fmt, value); + DN_JSONBuilder_KeyValueF(builder, key, float_fmt, value); } -DQN_API void Dqn_JSONBuilder_BoolNamed(Dqn_JSONBuilder *builder, Dqn_Str8 key, bool value) +DN_API void DN_JSONBuilder_BoolNamed(DN_JSONBuilder *builder, DN_Str8 key, bool value) { - Dqn_Str8 value_string = value ? DQN_STR8("true") : DQN_STR8("false"); - Dqn_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data); + DN_Str8 value_string = value ? DN_STR8("true") : DN_STR8("false"); + DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data); } -#endif // !defined(DQN_NO_JSON_BUILDER) +#endif // !defined(DN_NO_JSON_BUILDER) -// NOTE: [$BITS] Dqn_Bit /////////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_Bit_UnsetInplace(Dqn_usize *flags, Dqn_usize bitfield) +// NOTE: [$BITS] DN_Bit /////////////////////////////////////////////////////////////////////////// +DN_API void DN_Bit_UnsetInplace(DN_USize *flags, DN_USize bitfield) { *flags = (*flags & ~bitfield); } -DQN_API void Dqn_Bit_SetInplace(Dqn_usize *flags, Dqn_usize bitfield) +DN_API void DN_Bit_SetInplace(DN_USize *flags, DN_USize bitfield) { *flags = (*flags | bitfield); } -DQN_API bool Dqn_Bit_IsSet(Dqn_usize bits, Dqn_usize bits_to_set) +DN_API bool DN_Bit_IsSet(DN_USize bits, DN_USize bits_to_set) { - auto result = DQN_CAST(bool)((bits & bits_to_set) == bits_to_set); + auto result = DN_CAST(bool)((bits & bits_to_set) == bits_to_set); return result; } -DQN_API bool Dqn_Bit_IsNotSet(Dqn_usize bits, Dqn_usize bits_to_check) +DN_API bool DN_Bit_IsNotSet(DN_USize bits, DN_USize bits_to_check) { - auto result = !Dqn_Bit_IsSet(bits, bits_to_check); + auto result = !DN_Bit_IsSet(bits, bits_to_check); return result; } -// NOTE: [$SAFE] Dqn_Safe ////////////////////////////////////////////////////////////////////////// -DQN_API int64_t Dqn_Safe_AddI64(int64_t a, int64_t b) +// NOTE: [$SAFE] DN_Safe ////////////////////////////////////////////////////////////////////////// +DN_API int64_t DN_Safe_AddI64(int64_t a, int64_t b) { - int64_t result = DQN_CHECKF(a <= INT64_MAX - b, "a=%zd, b=%zd", a, b) ? (a + b) : INT64_MAX; + int64_t result = DN_CHECKF(a <= INT64_MAX - b, "a=%zd, b=%zd", a, b) ? (a + b) : INT64_MAX; return result; } -DQN_API int64_t Dqn_Safe_MulI64(int64_t a, int64_t b) +DN_API int64_t DN_Safe_MulI64(int64_t a, int64_t b) { - int64_t result = DQN_CHECKF(a <= INT64_MAX / b, "a=%zd, b=%zd", a, b) ? (a * b) : INT64_MAX; + int64_t result = DN_CHECKF(a <= INT64_MAX / b, "a=%zd, b=%zd", a, b) ? (a * b) : INT64_MAX; return result; } -DQN_API uint64_t Dqn_Safe_AddU64(uint64_t a, uint64_t b) +DN_API uint64_t DN_Safe_AddU64(uint64_t a, uint64_t b) { - uint64_t result = DQN_CHECKF(a <= UINT64_MAX - b, "a=%zu, b=%zu", a, b) ? (a + b) : UINT64_MAX; + uint64_t result = DN_CHECKF(a <= UINT64_MAX - b, "a=%zu, b=%zu", a, b) ? (a + b) : UINT64_MAX; return result; } -DQN_API uint64_t Dqn_Safe_SubU64(uint64_t a, uint64_t b) +DN_API uint64_t DN_Safe_SubU64(uint64_t a, uint64_t b) { - uint64_t result = DQN_CHECKF(a >= b, "a=%zu, b=%zu", a, b) ? (a - b) : 0; + uint64_t result = DN_CHECKF(a >= b, "a=%zu, b=%zu", a, b) ? (a - b) : 0; return result; } -DQN_API uint64_t Dqn_Safe_MulU64(uint64_t a, uint64_t b) +DN_API uint64_t DN_Safe_MulU64(uint64_t a, uint64_t b) { - uint64_t result = DQN_CHECKF(a <= UINT64_MAX / b, "a=%zu, b=%zu", a, b) ? (a * b) : UINT64_MAX; + uint64_t result = DN_CHECKF(a <= UINT64_MAX / b, "a=%zu, b=%zu", a, b) ? (a * b) : UINT64_MAX; return result; } -DQN_API uint32_t Dqn_Safe_SubU32(uint32_t a, uint32_t b) +DN_API uint32_t DN_Safe_SubU32(uint32_t a, uint32_t b) { - uint32_t result = DQN_CHECKF(a >= b, "a=%u, b=%u", a, b) ? (a - b) : 0; + uint32_t result = DN_CHECKF(a >= b, "a=%u, b=%u", a, b) ? (a - b) : 0; return result; } -// NOTE: Dqn_Safe_SaturateCastUSizeToI* //////////////////////////////////////////////////////////// +// NOTE: DN_Safe_SaturateCastUSizeToI* //////////////////////////////////////////////////////////// // INT*_MAX literals will be promoted to the type of uintmax_t as uintmax_t is // the highest possible rank (unsigned > signed). -DQN_API int Dqn_Safe_SaturateCastUSizeToInt(Dqn_usize val) +DN_API int DN_Safe_SaturateCastUSizeToInt(DN_USize val) { - int result = DQN_CHECK(DQN_CAST(uintmax_t) val <= INT_MAX) ? DQN_CAST(int) val : INT_MAX; + int result = DN_CHECK(DN_CAST(uintmax_t) val <= INT_MAX) ? DN_CAST(int) val : INT_MAX; return result; } -DQN_API int8_t Dqn_Safe_SaturateCastUSizeToI8(Dqn_usize val) +DN_API int8_t DN_Safe_SaturateCastUSizeToI8(DN_USize val) { - int8_t result = DQN_CHECK(DQN_CAST(uintmax_t) val <= INT8_MAX) ? DQN_CAST(int8_t) val : INT8_MAX; + int8_t result = DN_CHECK(DN_CAST(uintmax_t) val <= INT8_MAX) ? DN_CAST(int8_t) val : INT8_MAX; return result; } -DQN_API int16_t Dqn_Safe_SaturateCastUSizeToI16(Dqn_usize val) +DN_API int16_t DN_Safe_SaturateCastUSizeToI16(DN_USize val) { - int16_t result = DQN_CHECK(DQN_CAST(uintmax_t) val <= INT16_MAX) ? DQN_CAST(int16_t) val : INT16_MAX; + int16_t result = DN_CHECK(DN_CAST(uintmax_t) val <= INT16_MAX) ? DN_CAST(int16_t) val : INT16_MAX; return result; } -DQN_API int32_t Dqn_Safe_SaturateCastUSizeToI32(Dqn_usize val) +DN_API int32_t DN_Safe_SaturateCastUSizeToI32(DN_USize val) { - int32_t result = DQN_CHECK(DQN_CAST(uintmax_t) val <= INT32_MAX) ? DQN_CAST(int32_t) val : INT32_MAX; + int32_t result = DN_CHECK(DN_CAST(uintmax_t) val <= INT32_MAX) ? DN_CAST(int32_t) val : INT32_MAX; return result; } -DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64(Dqn_usize val) +DN_API int64_t DN_Safe_SaturateCastUSizeToI64(DN_USize val) { - int64_t result = DQN_CHECK(DQN_CAST(uintmax_t) val <= INT64_MAX) ? DQN_CAST(int64_t) val : INT64_MAX; + int64_t result = DN_CHECK(DN_CAST(uintmax_t) val <= INT64_MAX) ? DN_CAST(int64_t) val : INT64_MAX; return result; } -// NOTE: Dqn_Safe_SaturateCastUSizeToU* //////////////////////////////////////////////////////////// +// NOTE: DN_Safe_SaturateCastUSizeToU* //////////////////////////////////////////////////////////// // Both operands are unsigned and the lowest rank operand will be promoted to // match the highest rank operand. -DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8(Dqn_usize val) +DN_API uint8_t DN_Safe_SaturateCastUSizeToU8(DN_USize val) { - uint8_t result = DQN_CHECK(val <= UINT8_MAX) ? DQN_CAST(uint8_t) val : UINT8_MAX; + uint8_t result = DN_CHECK(val <= UINT8_MAX) ? DN_CAST(uint8_t) val : UINT8_MAX; return result; } -DQN_API uint16_t Dqn_Safe_SaturateCastUSizeToU16(Dqn_usize val) +DN_API uint16_t DN_Safe_SaturateCastUSizeToU16(DN_USize val) { - uint16_t result = DQN_CHECK(val <= UINT16_MAX) ? DQN_CAST(uint16_t) val : UINT16_MAX; + uint16_t result = DN_CHECK(val <= UINT16_MAX) ? DN_CAST(uint16_t) val : UINT16_MAX; return result; } -DQN_API uint32_t Dqn_Safe_SaturateCastUSizeToU32(Dqn_usize val) +DN_API uint32_t DN_Safe_SaturateCastUSizeToU32(DN_USize val) { - uint32_t result = DQN_CHECK(val <= UINT32_MAX) ? DQN_CAST(uint32_t) val : UINT32_MAX; + uint32_t result = DN_CHECK(val <= UINT32_MAX) ? DN_CAST(uint32_t) val : UINT32_MAX; return result; } -DQN_API uint64_t Dqn_Safe_SaturateCastUSizeToU64(Dqn_usize val) +DN_API uint64_t DN_Safe_SaturateCastUSizeToU64(DN_USize val) { - uint64_t result = DQN_CHECK(DQN_CAST(uint64_t) val <= UINT64_MAX) ? DQN_CAST(uint64_t) val : UINT64_MAX; + uint64_t result = DN_CHECK(DN_CAST(uint64_t) val <= UINT64_MAX) ? DN_CAST(uint64_t) val : UINT64_MAX; return result; } -// NOTE: Dqn_Safe_SaturateCastU64To* /////////////////////////////////////////////////////////////// -DQN_API int Dqn_Safe_SaturateCastU64ToInt(uint64_t val) +// NOTE: DN_Safe_SaturateCastU64To* /////////////////////////////////////////////////////////////// +DN_API int DN_Safe_SaturateCastU64ToInt(uint64_t val) { - int result = DQN_CHECK(val <= INT_MAX) ? DQN_CAST(int)val : INT_MAX; + int result = DN_CHECK(val <= INT_MAX) ? DN_CAST(int)val : INT_MAX; return result; } -DQN_API int64_t Dqn_Safe_SaturateCastU64ToI64(uint64_t val) +DN_API int8_t DN_Safe_SaturateCastU64ToI8(uint64_t val) { - int64_t result = DQN_CHECK(val <= INT64_MAX) ? DQN_CAST(int64_t)val : INT64_MAX; + int8_t result = DN_CHECK(val <= INT8_MAX) ? DN_CAST(int8_t)val : INT8_MAX; + return result; +} + +DN_API int16_t DN_Safe_SaturateCastU64ToI16(uint64_t val) +{ + int16_t result = DN_CHECK(val <= INT16_MAX) ? DN_CAST(int16_t)val : INT16_MAX; + return result; +} + +DN_API int32_t DN_Safe_SaturateCastU64ToI32(uint64_t val) +{ + int32_t result = DN_CHECK(val <= INT32_MAX) ? DN_CAST(int32_t)val : INT32_MAX; + return result; +} + +DN_API int64_t DN_Safe_SaturateCastU64ToI64(uint64_t val) +{ + int64_t result = DN_CHECK(val <= INT64_MAX) ? DN_CAST(int64_t)val : INT64_MAX; return result; } // Both operands are unsigned and the lowest rank operand will be promoted to // match the highest rank operand. -DQN_API unsigned int Dqn_Safe_SaturateCastU64ToUInt(uint64_t val) +DN_API unsigned int DN_Safe_SaturateCastU64ToUInt(uint64_t val) { - unsigned int result = DQN_CHECK(val <= UINT8_MAX) ? DQN_CAST(unsigned int) val : UINT_MAX; + unsigned int result = DN_CHECK(val <= UINT8_MAX) ? DN_CAST(unsigned int) val : UINT_MAX; return result; } -DQN_API uint8_t Dqn_Safe_SaturateCastU64ToU8(uint64_t val) +DN_API uint8_t DN_Safe_SaturateCastU64ToU8(uint64_t val) { - uint8_t result = DQN_CHECK(val <= UINT8_MAX) ? DQN_CAST(uint8_t) val : UINT8_MAX; + uint8_t result = DN_CHECK(val <= UINT8_MAX) ? DN_CAST(uint8_t) val : UINT8_MAX; return result; } -DQN_API uint16_t Dqn_Safe_SaturateCastU64ToU16(uint64_t val) +DN_API uint16_t DN_Safe_SaturateCastU64ToU16(uint64_t val) { - uint16_t result = DQN_CHECK(val <= UINT16_MAX) ? DQN_CAST(uint16_t) val : UINT16_MAX; + uint16_t result = DN_CHECK(val <= UINT16_MAX) ? DN_CAST(uint16_t) val : UINT16_MAX; return result; } -DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32(uint64_t val) +DN_API uint32_t DN_Safe_SaturateCastU64ToU32(uint64_t val) { - uint32_t result = DQN_CHECK(val <= UINT32_MAX) ? DQN_CAST(uint32_t) val : UINT32_MAX; + uint32_t result = DN_CHECK(val <= UINT32_MAX) ? DN_CAST(uint32_t) val : UINT32_MAX; return result; } -// NOTE: Dqn_Safe_SaturateCastISizeToI* //////////////////////////////////////////////////////////// +// NOTE: DN_Safe_SaturateCastISizeToI* //////////////////////////////////////////////////////////// // Both operands are signed so the lowest rank operand will be promoted to // match the highest rank operand. -DQN_API int Dqn_Safe_SaturateCastISizeToInt(Dqn_isize val) +DN_API int DN_Safe_SaturateCastISizeToInt(DN_ISize val) { - DQN_ASSERT(val >= INT_MIN && val <= INT_MAX); - int result = DQN_CAST(int) DQN_CLAMP(val, INT_MIN, INT_MAX); + DN_ASSERT(val >= INT_MIN && val <= INT_MAX); + int result = DN_CAST(int) DN_CLAMP(val, INT_MIN, INT_MAX); return result; } -DQN_API int8_t Dqn_Safe_SaturateCastISizeToI8(Dqn_isize val) +DN_API int8_t DN_Safe_SaturateCastISizeToI8(DN_ISize val) { - DQN_ASSERT(val >= INT8_MIN && val <= INT8_MAX); - int8_t result = DQN_CAST(int8_t) DQN_CLAMP(val, INT8_MIN, INT8_MAX); + DN_ASSERT(val >= INT8_MIN && val <= INT8_MAX); + int8_t result = DN_CAST(int8_t) DN_CLAMP(val, INT8_MIN, INT8_MAX); return result; } -DQN_API int16_t Dqn_Safe_SaturateCastISizeToI16(Dqn_isize val) +DN_API int16_t DN_Safe_SaturateCastISizeToI16(DN_ISize val) { - DQN_ASSERT(val >= INT16_MIN && val <= INT16_MAX); - int16_t result = DQN_CAST(int16_t) DQN_CLAMP(val, INT16_MIN, INT16_MAX); + DN_ASSERT(val >= INT16_MIN && val <= INT16_MAX); + int16_t result = DN_CAST(int16_t) DN_CLAMP(val, INT16_MIN, INT16_MAX); return result; } -DQN_API int32_t Dqn_Safe_SaturateCastISizeToI32(Dqn_isize val) +DN_API int32_t DN_Safe_SaturateCastISizeToI32(DN_ISize val) { - DQN_ASSERT(val >= INT32_MIN && val <= INT32_MAX); - int32_t result = DQN_CAST(int32_t) DQN_CLAMP(val, INT32_MIN, INT32_MAX); + DN_ASSERT(val >= INT32_MIN && val <= INT32_MAX); + int32_t result = DN_CAST(int32_t) DN_CLAMP(val, INT32_MIN, INT32_MAX); return result; } -DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64(Dqn_isize val) +DN_API int64_t DN_Safe_SaturateCastISizeToI64(DN_ISize val) { - DQN_ASSERT(DQN_CAST(int64_t) val >= INT64_MIN && DQN_CAST(int64_t) val <= INT64_MAX); - int64_t result = DQN_CAST(int64_t) DQN_CLAMP(DQN_CAST(int64_t) val, INT64_MIN, INT64_MAX); + DN_ASSERT(DN_CAST(int64_t) val >= INT64_MIN && DN_CAST(int64_t) val <= INT64_MAX); + int64_t result = DN_CAST(int64_t) DN_CLAMP(DN_CAST(int64_t) val, INT64_MIN, INT64_MAX); return result; } -// NOTE: Dqn_Safe_SaturateCastISizeToU* //////////////////////////////////////////////////////////// +// NOTE: DN_Safe_SaturateCastISizeToU* //////////////////////////////////////////////////////////// // If the value is a negative integer, we clamp to 0. Otherwise, we know that // the value is >=0, we can upcast safely to bounds check against the maximum // allowed value. -DQN_API unsigned int Dqn_Safe_SaturateCastISizeToUInt(Dqn_isize val) +DN_API unsigned int DN_Safe_SaturateCastISizeToUInt(DN_ISize val) { unsigned int result = 0; - if (DQN_CHECK(val >= DQN_CAST(Dqn_isize) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT_MAX)) - result = DQN_CAST(unsigned int) val; + if (DN_CHECK(val >= DN_CAST(DN_ISize) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT_MAX)) + result = DN_CAST(unsigned int) val; else result = UINT_MAX; } return result; } -DQN_API uint8_t Dqn_Safe_SaturateCastISizeToU8(Dqn_isize val) +DN_API uint8_t DN_Safe_SaturateCastISizeToU8(DN_ISize val) { uint8_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(Dqn_isize) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT8_MAX)) - result = DQN_CAST(uint8_t) val; + if (DN_CHECK(val >= DN_CAST(DN_ISize) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT8_MAX)) + result = DN_CAST(uint8_t) val; else result = UINT8_MAX; } return result; } -DQN_API uint16_t Dqn_Safe_SaturateCastISizeToU16(Dqn_isize val) +DN_API uint16_t DN_Safe_SaturateCastISizeToU16(DN_ISize val) { uint16_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(Dqn_isize) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT16_MAX)) - result = DQN_CAST(uint16_t) val; + if (DN_CHECK(val >= DN_CAST(DN_ISize) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT16_MAX)) + result = DN_CAST(uint16_t) val; else result = UINT16_MAX; } return result; } -DQN_API uint32_t Dqn_Safe_SaturateCastISizeToU32(Dqn_isize val) +DN_API uint32_t DN_Safe_SaturateCastISizeToU32(DN_ISize val) { uint32_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(Dqn_isize) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT32_MAX)) - result = DQN_CAST(uint32_t) val; + if (DN_CHECK(val >= DN_CAST(DN_ISize) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT32_MAX)) + result = DN_CAST(uint32_t) val; else result = UINT32_MAX; } return result; } -DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64(Dqn_isize val) +DN_API uint64_t DN_Safe_SaturateCastISizeToU64(DN_ISize val) { uint64_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(Dqn_isize) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT64_MAX)) - result = DQN_CAST(uint64_t) val; + if (DN_CHECK(val >= DN_CAST(DN_ISize) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT64_MAX)) + result = DN_CAST(uint64_t) val; else result = UINT64_MAX; } return result; } -// NOTE: Dqn_Safe_SaturateCastI64To* /////////////////////////////////////////////////////////////// +// NOTE: DN_Safe_SaturateCastI64To* /////////////////////////////////////////////////////////////// // Both operands are signed so the lowest rank operand will be promoted to // match the highest rank operand. -DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize(int64_t val) +DN_API DN_ISize DN_Safe_SaturateCastI64ToISize(int64_t val) { - DQN_CHECK(val >= DQN_ISIZE_MIN && val <= DQN_ISIZE_MAX); - Dqn_isize result = DQN_CAST(int64_t) DQN_CLAMP(val, DQN_ISIZE_MIN, DQN_ISIZE_MAX); + DN_CHECK(val >= DN_ISIZE_MIN && val <= DN_ISIZE_MAX); + DN_ISize result = DN_CAST(int64_t) DN_CLAMP(val, DN_ISIZE_MIN, DN_ISIZE_MAX); return result; } -DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8(int64_t val) +DN_API int8_t DN_Safe_SaturateCastI64ToI8(int64_t val) { - DQN_CHECK(val >= INT8_MIN && val <= INT8_MAX); - int8_t result = DQN_CAST(int8_t) DQN_CLAMP(val, INT8_MIN, INT8_MAX); + DN_CHECK(val >= INT8_MIN && val <= INT8_MAX); + int8_t result = DN_CAST(int8_t) DN_CLAMP(val, INT8_MIN, INT8_MAX); return result; } -DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16(int64_t val) +DN_API int16_t DN_Safe_SaturateCastI64ToI16(int64_t val) { - DQN_CHECK(val >= INT16_MIN && val <= INT16_MAX); - int16_t result = DQN_CAST(int16_t) DQN_CLAMP(val, INT16_MIN, INT16_MAX); + DN_CHECK(val >= INT16_MIN && val <= INT16_MAX); + int16_t result = DN_CAST(int16_t) DN_CLAMP(val, INT16_MIN, INT16_MAX); return result; } -DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32(int64_t val) +DN_API int32_t DN_Safe_SaturateCastI64ToI32(int64_t val) { - DQN_CHECK(val >= INT32_MIN && val <= INT32_MAX); - int32_t result = DQN_CAST(int32_t) DQN_CLAMP(val, INT32_MIN, INT32_MAX); + DN_CHECK(val >= INT32_MIN && val <= INT32_MAX); + int32_t result = DN_CAST(int32_t) DN_CLAMP(val, INT32_MIN, INT32_MAX); return result; } -DQN_API unsigned int Dqn_Safe_SaturateCastI64ToUInt(int64_t val) +DN_API unsigned int DN_Safe_SaturateCastI64ToUInt(int64_t val) { unsigned int result = 0; - if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT_MAX)) - result = DQN_CAST(unsigned int) val; + if (DN_CHECK(val >= DN_CAST(int64_t) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT_MAX)) + result = DN_CAST(unsigned int) val; else result = UINT_MAX; } return result; } -DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToUSize(int64_t val) +DN_API DN_ISize DN_Safe_SaturateCastI64ToUSize(int64_t val) { - Dqn_usize result = 0; - if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= DQN_USIZE_MAX)) - result = DQN_CAST(Dqn_usize) val; + DN_USize result = 0; + if (DN_CHECK(val >= DN_CAST(int64_t) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= DN_USIZE_MAX)) + result = DN_CAST(DN_USize) val; else - result = DQN_USIZE_MAX; + result = DN_USIZE_MAX; } return result; } -DQN_API uint8_t Dqn_Safe_SaturateCastI64ToU8(int64_t val) +DN_API uint8_t DN_Safe_SaturateCastI64ToU8(int64_t val) { uint8_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT8_MAX)) - result = DQN_CAST(uint8_t) val; + if (DN_CHECK(val >= DN_CAST(int64_t) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT8_MAX)) + result = DN_CAST(uint8_t) val; else result = UINT8_MAX; } return result; } -DQN_API uint16_t Dqn_Safe_SaturateCastI64ToU16(int64_t val) +DN_API uint16_t DN_Safe_SaturateCastI64ToU16(int64_t val) { uint16_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT16_MAX)) - result = DQN_CAST(uint16_t) val; + if (DN_CHECK(val >= DN_CAST(int64_t) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT16_MAX)) + result = DN_CAST(uint16_t) val; else result = UINT16_MAX; } return result; } -DQN_API uint32_t Dqn_Safe_SaturateCastI64ToU32(int64_t val) +DN_API uint32_t DN_Safe_SaturateCastI64ToU32(int64_t val) { uint32_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT32_MAX)) - result = DQN_CAST(uint32_t) val; + if (DN_CHECK(val >= DN_CAST(int64_t) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT32_MAX)) + result = DN_CAST(uint32_t) val; else result = UINT32_MAX; } return result; } -DQN_API uint64_t Dqn_Safe_SaturateCastI64ToU64(int64_t val) +DN_API uint64_t DN_Safe_SaturateCastI64ToU64(int64_t val) { uint64_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT64_MAX)) - result = DQN_CAST(uint64_t) val; + if (DN_CHECK(val >= DN_CAST(int64_t) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT64_MAX)) + result = DN_CAST(uint64_t) val; else result = UINT64_MAX; } return result; } -// NOTE: Dqn_Safe_SaturateCastIntTo* /////////////////////////////////////////////////////////////// -DQN_API int8_t Dqn_Safe_SaturateCastIntToI8(int val) +// NOTE: DN_Safe_SaturateCastIntTo* /////////////////////////////////////////////////////////////// +DN_API int8_t DN_Safe_SaturateCastIntToI8(int val) { - DQN_CHECK(val >= INT8_MIN && val <= INT8_MAX); - int8_t result = DQN_CAST(int8_t) DQN_CLAMP(val, INT8_MIN, INT8_MAX); + DN_CHECK(val >= INT8_MIN && val <= INT8_MAX); + int8_t result = DN_CAST(int8_t) DN_CLAMP(val, INT8_MIN, INT8_MAX); return result; } -DQN_API int16_t Dqn_Safe_SaturateCastIntToI16(int val) +DN_API int16_t DN_Safe_SaturateCastIntToI16(int val) { - DQN_CHECK(val >= INT16_MIN && val <= INT16_MAX); - int16_t result = DQN_CAST(int16_t) DQN_CLAMP(val, INT16_MIN, INT16_MAX); + DN_CHECK(val >= INT16_MIN && val <= INT16_MAX); + int16_t result = DN_CAST(int16_t) DN_CLAMP(val, INT16_MIN, INT16_MAX); return result; } -DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8(int val) +DN_API uint8_t DN_Safe_SaturateCastIntToU8(int val) { uint8_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(Dqn_isize) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT8_MAX)) - result = DQN_CAST(uint8_t) val; + if (DN_CHECK(val >= DN_CAST(DN_ISize) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT8_MAX)) + result = DN_CAST(uint8_t) val; else result = UINT8_MAX; } return result; } -DQN_API uint16_t Dqn_Safe_SaturateCastIntToU16(int val) +DN_API uint16_t DN_Safe_SaturateCastIntToU16(int val) { uint16_t result = 0; - if (DQN_CHECK(val >= DQN_CAST(Dqn_isize) 0)) { - if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT16_MAX)) - result = DQN_CAST(uint16_t) val; + if (DN_CHECK(val >= DN_CAST(DN_ISize) 0)) { + if (DN_CHECK(DN_CAST(uintmax_t) val <= UINT16_MAX)) + result = DN_CAST(uint16_t) val; else result = UINT16_MAX; } return result; } -DQN_API uint32_t Dqn_Safe_SaturateCastIntToU32(int val) +DN_API uint32_t DN_Safe_SaturateCastIntToU32(int val) { static_assert(sizeof(val) <= sizeof(uint32_t), "Sanity check to allow simplifying of casting"); uint32_t result = 0; - if (DQN_CHECK(val >= 0)) - result = DQN_CAST(uint32_t) val; + if (DN_CHECK(val >= 0)) + result = DN_CAST(uint32_t) val; return result; } -DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64(int val) +DN_API uint64_t DN_Safe_SaturateCastIntToU64(int val) { static_assert(sizeof(val) <= sizeof(uint64_t), "Sanity check to allow simplifying of casting"); uint64_t result = 0; - if (DQN_CHECK(val >= 0)) - result = DQN_CAST(uint64_t) val; + if (DN_CHECK(val >= 0)) + result = DN_CAST(uint64_t) val; return result; } // NOTE: [$MISC] Misc ////////////////////////////////////////////////////////////////////////////// -DQN_API int Dqn_FmtBuffer3DotTruncate(char *buffer, int size, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API int DN_FmtBuffer3DotTruncate(char *buffer, int size, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - int size_required = DQN_VSNPRINTF(buffer, size, fmt, args); - int result = DQN_MAX(DQN_MIN(size_required, size - 1), 0); + int size_required = DN_VSNPRINTF(buffer, size, fmt, args); + int result = DN_MAX(DN_MIN(size_required, size - 1), 0); if (result == size - 1) { buffer[size - 2] = '.'; buffer[size - 3] = '.'; @@ -687,149 +701,207 @@ DQN_API int Dqn_FmtBuffer3DotTruncate(char *buffer, int size, DQN_FMT_ATTRIB cha return result; } -DQN_API Dqn_U64Str8 Dqn_U64ToStr8(uint64_t val, char separator) +DN_API DN_U64Str8 DN_U64ToStr8(uint64_t val, char separator) { - Dqn_U64Str8 result = {}; + DN_U64Str8 result = {}; if (val == 0) { result.data[result.size++] = '0'; } else { // NOTE: The number is written in reverse because we form the string by // dividing by 10, so we write it in, then reverse it out after all is // done. - Dqn_U64Str8 temp = {}; - for (Dqn_usize digit_count = 0; val > 0; digit_count++) { + DN_U64Str8 temp = {}; + for (DN_USize digit_count = 0; val > 0; digit_count++) { if (separator && (digit_count != 0) && (digit_count % 3 == 0)) temp.data[temp.size++] = separator; - auto digit = DQN_CAST(char)(val % 10); + auto digit = DN_CAST(char)(val % 10); temp.data[temp.size++] = '0' + digit; val /= 10; } // NOTE: Reverse the string - DQN_MSVC_WARNING_PUSH - DQN_MSVC_WARNING_DISABLE(6293) // Ill-defined for-loop - DQN_MSVC_WARNING_DISABLE( + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(6293) // Ill-defined for-loop + DN_MSVC_WARNING_DISABLE( 6385) // Reading invalid data from 'temp.data' NOTE(doyle): Unsigned overflow is valid for loop termination - for (Dqn_usize temp_index = temp.size - 1; temp_index < temp.size; temp_index--) { + for (DN_USize temp_index = temp.size - 1; temp_index < temp.size; temp_index--) { char ch = temp.data[temp_index]; result.data[result.size++] = ch; } - DQN_MSVC_WARNING_POP + DN_MSVC_WARNING_POP } return result; } -DQN_API Dqn_U64ByteSize Dqn_U64ToByteSize(uint64_t bytes, Dqn_U64ByteSizeType desired_type) +DN_API DN_U64ByteSize DN_U64ToByteSize(uint64_t bytes, DN_U64ByteSizeType desired_type) { - Dqn_U64ByteSize result = {}; - result.bytes = DQN_CAST(Dqn_f64)bytes; - if (!DQN_CHECK(desired_type != Dqn_U64ByteSizeType_Count)) { - result.suffix = Dqn_U64ByteSizeTypeString(result.type); + DN_U64ByteSize result = {}; + result.bytes = DN_CAST(DN_F64)bytes; + if (!DN_CHECK(desired_type != DN_U64ByteSizeType_Count)) { + result.suffix = DN_U64ByteSizeTypeString(result.type); return result; } - if (desired_type == Dqn_U64ByteSizeType_Auto) { - for (; result.type < Dqn_U64ByteSizeType_Count && result.bytes >= 1024.0; result.type = DQN_CAST(Dqn_U64ByteSizeType)(DQN_CAST(Dqn_usize)result.type + 1)) + if (desired_type == DN_U64ByteSizeType_Auto) { + for (; result.type < DN_U64ByteSizeType_Count && result.bytes >= 1024.0; result.type = DN_CAST(DN_U64ByteSizeType)(DN_CAST(DN_USize)result.type + 1)) result.bytes /= 1024.0; } else { - for (; result.type < desired_type; result.type = DQN_CAST(Dqn_U64ByteSizeType)(DQN_CAST(Dqn_usize)result.type + 1)) + for (; result.type < desired_type; result.type = DN_CAST(DN_U64ByteSizeType)(DN_CAST(DN_USize)result.type + 1)) result.bytes /= 1024.0; } - result.suffix = Dqn_U64ByteSizeTypeString(result.type); + result.suffix = DN_U64ByteSizeTypeString(result.type); return result; } -DQN_API Dqn_Str8 Dqn_U64ToByteSizeStr8(Dqn_Arena *arena, uint64_t bytes, Dqn_U64ByteSizeType desired_type) +DN_API DN_Str8 DN_U64ToByteSizeStr8(DN_Arena *arena, uint64_t bytes, DN_U64ByteSizeType desired_type) { - Dqn_U64ByteSize byte_size = Dqn_U64ToByteSize(bytes, desired_type); - Dqn_Str8 result = Dqn_Str8_InitF(arena, "%.2f%.*s", byte_size.bytes, DQN_STR_FMT(byte_size.suffix)); + DN_U64ByteSize byte_size = DN_U64ToByteSize(bytes, desired_type); + DN_Str8 result = DN_Str8_InitF(arena, "%.2f%.*s", byte_size.bytes, DN_STR_FMT(byte_size.suffix)); return result; } -DQN_API Dqn_Str8 Dqn_U64ByteSizeTypeString(Dqn_U64ByteSizeType type) +DN_API DN_Str8 DN_U64ByteSizeTypeString(DN_U64ByteSizeType type) { - Dqn_Str8 result = DQN_STR8(""); + DN_Str8 result = DN_STR8(""); switch (type) { - case Dqn_U64ByteSizeType_B: result = DQN_STR8("B"); break; - case Dqn_U64ByteSizeType_KiB: result = DQN_STR8("KiB"); break; - case Dqn_U64ByteSizeType_MiB: result = DQN_STR8("MiB"); break; - case Dqn_U64ByteSizeType_GiB: result = DQN_STR8("GiB"); break; - case Dqn_U64ByteSizeType_TiB: result = DQN_STR8("TiB"); break; - case Dqn_U64ByteSizeType_Count: result = DQN_STR8(""); break; - case Dqn_U64ByteSizeType_Auto: result = DQN_STR8(""); break; + case DN_U64ByteSizeType_B: result = DN_STR8("B"); break; + case DN_U64ByteSizeType_KiB: result = DN_STR8("KiB"); break; + case DN_U64ByteSizeType_MiB: result = DN_STR8("MiB"); break; + case DN_U64ByteSizeType_GiB: result = DN_STR8("GiB"); break; + case DN_U64ByteSizeType_TiB: result = DN_STR8("TiB"); break; + case DN_U64ByteSizeType_Count: result = DN_STR8(""); break; + case DN_U64ByteSizeType_Auto: result = DN_STR8(""); break; } return result; } -DQN_API Dqn_Str8 Dqn_U64ToAge(Dqn_Arena *arena, uint64_t age_s, Dqn_U64AgeUnit unit) +DN_API DN_Str8 DN_U64ToAge(DN_Arena *arena, uint64_t age_s, DN_U64AgeUnit unit) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; if (!arena) return result; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); - Dqn_Str8Builder builder = {}; - builder.arena = arena; - uint64_t remainder = age_s; + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena); + uint64_t remainder = age_s; - if (unit & Dqn_U64AgeUnit_Year) { - Dqn_usize value = remainder / DQN_YEARS_TO_S(1); - remainder -= DQN_YEARS_TO_S(value); + if (unit & DN_U64AgeUnit_Year) { + DN_USize value = remainder / DN_YEARS_TO_S(1); + remainder -= DN_YEARS_TO_S(value); if (value) - Dqn_Str8Builder_AddF(&builder, "%s%I64uyr", builder.string_size ? " " : "", value); + DN_Str8Builder_AppendF(&builder, "%s%I64uyr", builder.string_size ? " " : "", value); } - if (unit & Dqn_U64AgeUnit_Week) { - Dqn_usize value = remainder / DQN_WEEKS_TO_S(1); - remainder -= DQN_WEEKS_TO_S(value); + if (unit & DN_U64AgeUnit_Week) { + DN_USize value = remainder / DN_WEEKS_TO_S(1); + remainder -= DN_WEEKS_TO_S(value); if (value) - Dqn_Str8Builder_AddF(&builder, "%s%I64uw", builder.string_size ? " " : "", value); + DN_Str8Builder_AppendF(&builder, "%s%I64uw", builder.string_size ? " " : "", value); } - if (unit & Dqn_U64AgeUnit_Day) { - Dqn_usize value = remainder / DQN_DAYS_TO_S(1); - remainder -= DQN_DAYS_TO_S(value); + if (unit & DN_U64AgeUnit_Day) { + DN_USize value = remainder / DN_DAYS_TO_S(1); + remainder -= DN_DAYS_TO_S(value); if (value) - Dqn_Str8Builder_AddF(&builder, "%s%I64ud", builder.string_size ? " " : "", value); + DN_Str8Builder_AppendF(&builder, "%s%I64ud", builder.string_size ? " " : "", value); } - if (unit & Dqn_U64AgeUnit_Hr) { - Dqn_usize value = remainder / DQN_HOURS_TO_S(1); - remainder -= DQN_HOURS_TO_S(value); + if (unit & DN_U64AgeUnit_Hr) { + DN_USize value = remainder / DN_HOURS_TO_S(1); + remainder -= DN_HOURS_TO_S(value); if (value) - Dqn_Str8Builder_AddF(&builder, "%s%I64uh", builder.string_size ? " " : "", value); + DN_Str8Builder_AppendF(&builder, "%s%I64uh", builder.string_size ? " " : "", value); } - if (unit & Dqn_U64AgeUnit_Min) { - Dqn_usize value = remainder / DQN_MINS_TO_S(1); - remainder -= DQN_MINS_TO_S(value); + if (unit & DN_U64AgeUnit_Min) { + DN_USize value = remainder / DN_MINS_TO_S(1); + remainder -= DN_MINS_TO_S(value); if (value) - Dqn_Str8Builder_AddF(&builder, "%s%I64um", builder.string_size ? " " : "", value); + DN_Str8Builder_AppendF(&builder, "%s%I64um", builder.string_size ? " " : "", value); } - if (unit & Dqn_U64AgeUnit_Sec) { - Dqn_usize value = remainder; - Dqn_Str8Builder_AddF(&builder, "%s%I64us", builder.string_size ? " " : "", value); + if (unit & DN_U64AgeUnit_Sec) { + DN_USize value = remainder; + DN_Str8Builder_AppendF(&builder, "%s%I64us", builder.string_size ? " " : "", value); } - result = Dqn_Str8Builder_Build(&builder, arena); + result = DN_Str8Builder_Build(&builder, arena); return result; } -DQN_API uint64_t Dqn_HexToU64(Dqn_Str8 hex) +DN_API DN_Str8 DN_F64ToAge(DN_Arena *arena, DN_F64 age_s, DN_U64AgeUnit unit) { - Dqn_Str8 real_hex = Dqn_Str8_TrimPrefix(Dqn_Str8_TrimPrefix(hex, DQN_STR8("0x")), DQN_STR8("0X")); - Dqn_usize max_hex_size = sizeof(uint64_t) * 2 /*hex chars per byte*/; - DQN_ASSERT(real_hex.size <= max_hex_size); + DN_Str8 result = {}; + if (!arena) + return result; - Dqn_usize size = DQN_MIN(max_hex_size, real_hex.size); + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena); + DN_F64 remainder = age_s; + + if (unit & DN_U64AgeUnit_Year) { + DN_F64 value = remainder / DN_CAST(DN_F64)DN_YEARS_TO_S(1); + if (value >= 1.0) { + remainder -= DN_YEARS_TO_S(value); + DN_Str8Builder_AppendF(&builder, "%s%.1fyr", builder.string_size ? " " : "", value); + } + } + + if (unit & DN_U64AgeUnit_Week) { + DN_F64 value = remainder / DN_CAST(DN_F64)DN_WEEKS_TO_S(1); + if (value >= 1.0) { + remainder -= DN_WEEKS_TO_S(value); + DN_Str8Builder_AppendF(&builder, "%s%.1fw", builder.string_size ? " " : "", value); + } + } + + if (unit & DN_U64AgeUnit_Day) { + DN_F64 value = remainder / DN_CAST(DN_F64)DN_DAYS_TO_S(1); + if (value >= 1.0) { + remainder -= DN_WEEKS_TO_S(value); + DN_Str8Builder_AppendF(&builder, "%s%.1fd", builder.string_size ? " " : "", value); + } + } + + if (unit & DN_U64AgeUnit_Hr) { + DN_F64 value = remainder / DN_CAST(DN_F64)DN_HOURS_TO_S(1); + if (value >= 1.0) { + remainder -= DN_HOURS_TO_S(value); + DN_Str8Builder_AppendF(&builder, "%s%.1fh", builder.string_size ? " " : "", value); + } + } + + if (unit & DN_U64AgeUnit_Min) { + DN_F64 value = remainder / DN_CAST(DN_F64)DN_MINS_TO_S(1); + if (value >= 1.0) { + remainder -= DN_MINS_TO_S(value); + DN_Str8Builder_AppendF(&builder, "%s%.1fm", builder.string_size ? " " : "", value); + } + } + + if (unit & DN_U64AgeUnit_Sec) { + DN_F64 value = remainder; + DN_Str8Builder_AppendF(&builder, "%s%.1fs", builder.string_size ? " " : "", value); + } + + result = DN_Str8Builder_Build(&builder, arena); + return result; +} + +DN_API uint64_t DN_HexToU64(DN_Str8 hex) +{ + DN_Str8 real_hex = DN_Str8_TrimPrefix(DN_Str8_TrimPrefix(hex, DN_STR8("0x")), DN_STR8("0X")); + DN_USize max_hex_size = sizeof(uint64_t) * 2 /*hex chars per byte*/; + DN_ASSERT(real_hex.size <= max_hex_size); + + DN_USize size = DN_MIN(max_hex_size, real_hex.size); uint64_t result = 0; - for (Dqn_usize index = 0; index < size; index++) { + for (DN_USize index = 0; index < size; index++) { char ch = real_hex.data[index]; - Dqn_CharHexToU8 val = Dqn_Char_HexToU8(ch); + DN_CharHexToU8 val = DN_Char_HexToU8(ch); if (!val.success) break; result = (result << 4) | val.value; @@ -837,57 +909,57 @@ DQN_API uint64_t Dqn_HexToU64(Dqn_Str8 hex) return result; } -DQN_API Dqn_Str8 Dqn_U64ToHex(Dqn_Arena *arena, uint64_t number, uint32_t flags) +DN_API DN_Str8 DN_U64ToHex(DN_Arena *arena, uint64_t number, uint32_t flags) { - Dqn_Str8 prefix = {}; - if ((flags & Dqn_HexU64Str8Flags_0xPrefix)) - prefix = DQN_STR8("0x"); + DN_Str8 prefix = {}; + if ((flags & DN_HexU64Str8Flags_0xPrefix)) + prefix = DN_STR8("0x"); - char const *fmt = (flags & Dqn_HexU64Str8Flags_UppercaseHex) ? "%I64X" : "%I64x"; - Dqn_usize required_size = Dqn_CStr8_FSize(fmt, number) + prefix.size; - Dqn_Str8 result = Dqn_Str8_Alloc(arena, required_size, Dqn_ZeroMem_No); + char const *fmt = (flags & DN_HexU64Str8Flags_UppercaseHex) ? "%I64X" : "%I64x"; + DN_USize required_size = DN_CStr8_FSize(fmt, number) + prefix.size; + DN_Str8 result = DN_Str8_Alloc(arena, required_size, DN_ZeroMem_No); - if (Dqn_Str8_HasData(result)) { - DQN_MEMCPY(result.data, prefix.data, prefix.size); - int space = DQN_CAST(int) DQN_MAX((result.size - prefix.size) + 1, 0); /*null-terminator*/ - DQN_SNPRINTF(result.data + prefix.size, space, fmt, number); + if (DN_Str8_HasData(result)) { + DN_MEMCPY(result.data, prefix.data, prefix.size); + int space = DN_CAST(int) DN_MAX((result.size - prefix.size) + 1, 0); /*null-terminator*/ + DN_SNPRINTF(result.data + prefix.size, space, fmt, number); } return result; } -DQN_API Dqn_U64HexStr8 Dqn_U64ToHexStr8(uint64_t number, uint32_t flags) +DN_API DN_U64HexStr8 DN_U64ToHexStr8(uint64_t number, DN_U64HexStr8Flags flags) { - Dqn_Str8 prefix = {}; - if (flags & Dqn_HexU64Str8Flags_0xPrefix) - prefix = DQN_STR8("0x"); + DN_Str8 prefix = {}; + if (flags & DN_HexU64Str8Flags_0xPrefix) + prefix = DN_STR8("0x"); - Dqn_U64HexStr8 result = {}; - DQN_MEMCPY(result.data, prefix.data, prefix.size); - result.size += DQN_CAST(int8_t) prefix.size; + DN_U64HexStr8 result = {}; + DN_MEMCPY(result.data, prefix.data, prefix.size); + result.size += DN_CAST(int8_t) prefix.size; - char const *fmt = (flags & Dqn_HexU64Str8Flags_UppercaseHex) ? "%I64X" : "%I64x"; - int size = DQN_SNPRINTF(result.data + result.size, DQN_ARRAY_UCOUNT(result.data) - result.size, fmt, number); - result.size += DQN_CAST(uint8_t) size; - DQN_ASSERT(result.size < DQN_ARRAY_UCOUNT(result.data)); + char const *fmt = (flags & DN_HexU64Str8Flags_UppercaseHex) ? "%I64X" : "%I64x"; + int size = DN_SNPRINTF(result.data + result.size, DN_ARRAY_UCOUNT(result.data) - result.size, fmt, number); + result.size += DN_CAST(uint8_t) size; + DN_ASSERT(result.size < DN_ARRAY_UCOUNT(result.data)); // NOTE: snprintf returns the required size of the format string // irrespective of if there's space or not, but, always null terminates so // the last byte is wasted. - result.size = DQN_MIN(result.size, DQN_ARRAY_UCOUNT(result.data) - 1); + result.size = DN_MIN(result.size, DN_ARRAY_UCOUNT(result.data) - 1); return result; } -DQN_API bool Dqn_BytesToHexPtr(void const *src, Dqn_usize src_size, char *dest, Dqn_usize dest_size) +DN_API bool DN_BytesToHexPtr(void const *src, DN_USize src_size, char *dest, DN_USize dest_size) { if (!src || !dest) return false; - if (!DQN_CHECK(dest_size >= src_size * 2)) + if (!DN_CHECK(dest_size >= src_size * 2)) return false; char const *HEX = "0123456789abcdef"; - unsigned char const *src_u8 = DQN_CAST(unsigned char const *) src; - for (Dqn_usize src_index = 0, dest_index = 0; src_index < src_size; src_index++) { + unsigned char const *src_u8 = DN_CAST(unsigned char const *) src; + for (DN_USize src_index = 0, dest_index = 0; src_index < src_size; src_index++) { char byte = src_u8[src_index]; char hex01 = (byte >> 4) & 0b1111; char hex02 = (byte >> 0) & 0b1111; @@ -898,146 +970,149 @@ DQN_API bool Dqn_BytesToHexPtr(void const *src, Dqn_usize src_size, char *dest, return true; } -DQN_API Dqn_Str8 Dqn_BytesToHex(Dqn_Arena *arena, void const *src, Dqn_usize size) +DN_API DN_Str8 DN_BytesToHex(DN_Arena *arena, void const *src, DN_USize size) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; if (!src || size <= 0) return result; - result = Dqn_Str8_Alloc(arena, size * 2, Dqn_ZeroMem_No); + result = DN_Str8_Alloc(arena, size * 2, DN_ZeroMem_No); result.data[result.size] = 0; - bool converted = Dqn_BytesToHexPtr(src, size, result.data, result.size); - DQN_ASSERT(converted); + bool converted = DN_BytesToHexPtr(src, size, result.data, result.size); + DN_ASSERT(converted); return result; } -DQN_API Dqn_usize Dqn_HexToBytesPtrUnchecked(Dqn_Str8 hex, void *dest, Dqn_usize dest_size) +DN_API DN_USize DN_HexToBytesPtrUnchecked(DN_Str8 hex, void *dest, DN_USize dest_size) { - Dqn_usize result = 0; - unsigned char *dest_u8 = DQN_CAST(unsigned char *) dest; + DN_USize result = 0; + unsigned char *dest_u8 = DN_CAST(unsigned char *) dest; - for (Dqn_usize hex_index = 0; hex_index < hex.size; hex_index += 2, result += 1) { + for (DN_USize hex_index = 0; hex_index < hex.size; hex_index += 2, result += 1) { char hex01 = hex.data[hex_index]; char hex02 = (hex_index + 1 < hex.size) ? hex.data[hex_index + 1] : 0; - char bit4_01 = Dqn_Char_HexToU8(hex01).value; - char bit4_02 = Dqn_Char_HexToU8(hex02).value; + char bit4_01 = DN_Char_HexToU8(hex01).value; + char bit4_02 = DN_Char_HexToU8(hex02).value; char byte = (bit4_01 << 4) | (bit4_02 << 0); dest_u8[result] = byte; } - DQN_ASSERT(result <= dest_size); + DN_ASSERT(result <= dest_size); return result; } -DQN_API Dqn_usize Dqn_HexToBytesPtr(Dqn_Str8 hex, void *dest, Dqn_usize dest_size) +DN_API DN_USize DN_HexToBytesPtr(DN_Str8 hex, void *dest, DN_USize dest_size) { - hex = Dqn_Str8_TrimPrefix(hex, DQN_STR8("0x")); - hex = Dqn_Str8_TrimPrefix(hex, DQN_STR8("0X")); + hex = DN_Str8_TrimPrefix(hex, DN_STR8("0x")); + hex = DN_Str8_TrimPrefix(hex, DN_STR8("0X")); - Dqn_usize result = 0; - if (!Dqn_Str8_HasData(hex)) + DN_USize result = 0; + if (!DN_Str8_HasData(hex)) return result; // NOTE: Trimmed hex can be "0xf" -> "f" or "0xAB" -> "AB" // Either way, the size can be odd or even, hence we round up to the nearest // multiple of two to ensure that we calculate the min buffer size orrectly. - Dqn_usize hex_size_rounded_up = hex.size + (hex.size % 2); - Dqn_usize min_buffer_size = hex_size_rounded_up / 2; - if (hex.size <= 0 || !DQN_CHECK(dest_size >= min_buffer_size)) { + DN_USize hex_size_rounded_up = hex.size + (hex.size % 2); + DN_USize min_buffer_size = hex_size_rounded_up / 2; + if (hex.size <= 0 || !DN_CHECK(dest_size >= min_buffer_size)) { return result; } - result = Dqn_HexToBytesPtrUnchecked(hex, dest, dest_size); + result = DN_HexToBytesPtrUnchecked(hex, dest, dest_size); return result; } -DQN_API Dqn_Str8 Dqn_HexToBytesUnchecked(Dqn_Arena *arena, Dqn_Str8 hex) +DN_API DN_Str8 DN_HexToBytesUnchecked(DN_Arena *arena, DN_Str8 hex) { - Dqn_Str8 result = Dqn_Str8_Alloc(arena, hex.size / 2, Dqn_ZeroMem_No); + DN_USize hex_size_rounded_up = hex.size + (hex.size % 2); + DN_Str8 result = DN_Str8_Alloc(arena, (hex_size_rounded_up / 2), DN_ZeroMem_No); if (result.data) { - Dqn_usize bytes_written = Dqn_HexToBytesPtr(hex, result.data, result.size); - DQN_ASSERT(bytes_written == result.size); + DN_USize bytes_written = DN_HexToBytesPtr(hex, result.data, result.size); + DN_ASSERT(bytes_written == result.size); } return result; } -DQN_API Dqn_Str8 Dqn_HexToBytes(Dqn_Arena *arena, Dqn_Str8 hex) +DN_API DN_Str8 DN_HexToBytes(DN_Arena *arena, DN_Str8 hex) { - hex = Dqn_Str8_TrimPrefix(hex, DQN_STR8("0x")); - hex = Dqn_Str8_TrimPrefix(hex, DQN_STR8("0X")); + hex = DN_Str8_TrimPrefix(hex, DN_STR8("0x")); + hex = DN_Str8_TrimPrefix(hex, DN_STR8("0X")); - Dqn_Str8 result = {}; - if (!DQN_CHECK(Dqn_Str8_IsAll(hex, Dqn_Str8IsAll_Hex))) + DN_Str8 result = {}; + if (!DN_Str8_HasData(hex)) return result; - result = Dqn_HexToBytesUnchecked(arena, hex); + if (!DN_CHECK(DN_Str8_IsAll(hex, DN_Str8IsAll_Hex))) + return result; + + result = DN_HexToBytesUnchecked(arena, hex); return result; } -// NOTE: [$DLIB] Dqn_Library /////////////////////////////////////////////////////////////////////// -Dqn_Library *g_dqn_library; +// NOTE: [$CORE] DN_Core ////////////////////////////////////////////////////////////////////////// +DN_Core *g_dn_core; -DQN_API Dqn_Library *Dqn_Library_Init(Dqn_LibraryOnInit on_init) +DN_API void DN_Core_Init(DN_Core *core, DN_CoreOnInit on_init) { - if (!g_dqn_library) { - static Dqn_Library default_instance = {}; - g_dqn_library = &default_instance; - } - // NOTE: Init check /////////////////////////////////////////////////////////////////////////// - Dqn_Library *result = g_dqn_library; - Dqn_TicketMutex_Begin(&result->lib_mutex); - DQN_DEFER { - Dqn_TicketMutex_End(&result->lib_mutex); - }; + if (core->init) + return; - if (result->lib_init) - return result; + #define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_STR8(#label)}; + DN_CPU_FEAT_XMACRO + #undef DN_CPU_FEAT_XENTRY - #define DQN_CPU_FEAT_XENTRY(label) g_dqn_cpu_feature_decl[Dqn_CPUFeature_##label] = {Dqn_CPUFeature_##label, DQN_STR8(#label)}; - DQN_CPU_FEAT_XMACRO - #undef DQN_CPU_FEAT_XENTRY - - result->lib_init = true; - result->cpu_report = Dqn_CPU_Report(); - - // NOTE: Query OS info ///////////////////////////////////////////////////////////////////////// + // NOTE: Setup OS ////////////////////////////////////////////////////////////////////////////// { - #if defined(DQN_OS_WIN32) + #if defined(DN_OS_WIN32) SYSTEM_INFO system_info = {}; GetSystemInfo(&system_info); - result->os_page_size = system_info.dwPageSize; - result->os_alloc_granularity = system_info.dwAllocationGranularity; + core->os_page_size = system_info.dwPageSize; + core->os_alloc_granularity = system_info.dwAllocationGranularity; + QueryPerformanceFrequency(&core->win32_qpc_frequency); - QueryPerformanceFrequency(&result->win32_qpc_frequency); + HMODULE module = LoadLibraryA("kernel32.dll"); + g_dn_win_set_thread_description = DN_CAST(DN_WinSetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription"); + FreeLibrary(module); #else // TODO(doyle): Get the proper page size from the OS. - result->os_page_size = DQN_KILOBYTES(4); - result->os_alloc_granularity = DQN_KILOBYTES(64); + core->os_page_size = DN_KILOBYTES(4); + core->os_alloc_granularity = DN_KILOBYTES(64); #endif } + core->init_mutex = DN_OS_MutexInit(); + DN_OS_MutexLock(&core->init_mutex); + DN_DEFER { + DN_OS_MutexUnlock(&core->init_mutex); + }; + + DN_Core_SetPointer(core); + core->init = true; + core->cpu_report = DN_CPU_Report(); + // NOTE Initialise fields ////////////////////////////////////////////////////////////////////// - #if !defined(DQN_NO_PROFILER) - result->profiler = &result->profiler_default_instance; + #if !defined(DN_NO_PROFILER) + core->profiler = &core->profiler_default_instance; #endif // NOTE: BEGIN IMPORTANT ORDER OF STATEMENTS /////////////////////////////////////////////////// - #if defined(DQN_LEAK_TRACKING) + #if defined(DN_LEAK_TRACKING) // NOTE: Setup the allocation table with allocation tracking turned off on // the arena we're using to initialise the table. - result->alloc_table_arena.flags |= Dqn_ArenaFlag_NoAllocTrack; - result->alloc_table = Dqn_DSMap_Init(&result->alloc_table_arena, 4096, Dqn_DSMapFlags_Nil); + core->alloc_table_arena = DN_Arena_InitSize(DN_MEGABYTES(1), DN_KILOBYTES(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak); + core->alloc_table = DN_DSMap_Init(&core->alloc_table_arena, 4096, DN_DSMapFlags_Nil); #endif - result->arena = Dqn_Arena_InitSize(DQN_MEGABYTES(2), DQN_KILOBYTES(64), Dqn_ArenaFlag_AllocCanLeak); - result->pool = Dqn_ChunkPool_Init(&result->arena, /*align*/ 0); - Dqn_ArenaCatalog_Init(&result->arena_catalog, &result->pool); - Dqn_ArenaCatalog_AddF(&result->arena_catalog, &result->arena, "Dqn Library"); + core->arena = DN_Arena_InitSize(DN_KILOBYTES(64), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); + core->pool = DN_Pool_Init(&core->arena, /*align*/ 0); + DN_ArenaCatalog_Init(&core->arena_catalog, &core->pool); + DN_ArenaCatalog_AddF(&core->arena_catalog, &core->arena, "DN Core"); - #if defined(DQN_LEAK_TRACING) - Dqn_ArenaCatalog_AddF(&result->arena_catalog, &result->alloc_table_arena, "Dqn Allocation Table"); + #if defined(DN_LEAK_TRACKING) + DN_ArenaCatalog_AddF(&core->arena_catalog, &core->alloc_table_arena, "DN Allocation Table"); #endif // NOTE: Initialise tmem arenas which allocate memory and will be @@ -1045,306 +1120,316 @@ DQN_API Dqn_Library *Dqn_Library_Init(Dqn_LibraryOnInit on_init) // 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. - Dqn_TLS_Init(&result->tls); - Dqn_OS_ThreadSetTLS(&result->tls); - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); + DN_TLS_Init(&core->tls); + DN_OS_ThreadSetTLS(&core->tls); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); // NOTE: END IMPORTANT ORDER OF STATEMENTS ///////////////////////////////////////////////////// - result->exe_dir = Dqn_OS_EXEDir(&result->arena); + core->exe_dir = DN_OS_EXEDir(&core->arena); // NOTE: Print out init features /////////////////////////////////////////////////////////////// - Dqn_Str8Builder builder = {}; - builder.arena = tmem.arena; - if (on_init & Dqn_LibraryOnInit_LogLibFeatures) { - Dqn_Str8Builder_AddRef(&builder, DQN_STR8("Dqn Library initialised:\n")); + DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena); + if (on_init & DN_CoreOnInit_LogLibFeatures) { + DN_Str8Builder_AppendRef(&builder, DN_STR8("DN Library initialised:\n")); - Dqn_f64 page_size_kib = result->os_page_size / 1024.0; - Dqn_f64 alloc_granularity_kib = result->os_alloc_granularity / 1024.0; - Dqn_Str8Builder_AddF( + DN_F64 page_size_kib = core->os_page_size / 1024.0; + DN_F64 alloc_granularity_kib = core->os_alloc_granularity / 1024.0; + DN_Str8Builder_AppendF( &builder, " OS Page Size/Alloc Granularity: %.1f/%.1fKiB\n", page_size_kib, alloc_granularity_kib); - #if DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) - if (DQN_ASAN_POISON) { - Dqn_Str8Builder_AddF( - &builder, " ASAN manual poisoning%s\n", DQN_ASAN_VET_POISON ? " (+vet sanity checks)" : ""); - Dqn_Str8Builder_AddF(&builder, " ASAN poison guard size: %u\n", DQN_ASAN_POISON_GUARD_SIZE); + #if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) + if (DN_ASAN_POISON) { + DN_Str8Builder_AppendF( + &builder, " ASAN manual poisoning%s\n", DN_ASAN_VET_POISON ? " (+vet sanity checks)" : ""); + DN_Str8Builder_AppendF(&builder, " ASAN poison guard size: %u\n", DN_ASAN_POISON_GUARD_SIZE); } #endif - #if defined(DQN_LEAK_TRACKING) - Dqn_Str8Builder_AddRef(&builder, DQN_STR8(" Allocation leak tracing\n")); + #if defined(DN_LEAK_TRACKING) + DN_Str8Builder_AppendRef(&builder, DN_STR8(" Allocation leak tracing\n")); #endif - #if !defined(DQN_NO_PROFILER) - Dqn_Str8Builder_AddRef(&builder, DQN_STR8(" TSC profiler available\n")); + #if !defined(DN_NO_PROFILER) + DN_Str8Builder_AppendRef(&builder, DN_STR8(" TSC profiler available\n")); #endif - #if defined(DQN_USE_STD_PRINTF) - Dqn_Str8Builder_AddRef(&builder, DQN_STR8(" Using stdio's printf functions\n")); + #if defined(DN_USE_STD_PRINTF) + DN_Str8Builder_AppendRef(&builder, DN_STR8(" Using stdio's printf functions\n")); #else - Dqn_Str8Builder_AddRef(&builder, DQN_STR8(" Using stb_sprintf functions\n")); + DN_Str8Builder_AppendRef(&builder, DN_STR8(" Using stb_sprintf functions\n")); #endif // TODO(doyle): Add stacktrace feature log } - if (on_init & Dqn_LibraryOnInit_LogCPUFeatures) { - Dqn_CPUReport const *report = &result->cpu_report; - Dqn_Str8 brand = Dqn_Str8_TrimWhitespaceAround(Dqn_Str8_Init(report->brand, sizeof(report->brand) - 1)); - Dqn_Str8Builder_AddF(&builder, - " CPU '%.*s' from '%s' detected:\n", - DQN_STR_FMT(brand), - report->vendor); + if (on_init & DN_CoreOnInit_LogCPUFeatures) { + DN_CPUReport const *report = &core->cpu_report; + DN_Str8 brand = DN_Str8_TrimWhitespaceAround(DN_Str8_Init(report->brand, sizeof(report->brand) - 1)); + DN_Str8Builder_AppendF(&builder, + " CPU '%.*s' from '%s' detected:\n", + DN_STR_FMT(brand), + report->vendor); - Dqn_usize longest_feature_name = 0; - DQN_FOR_UINDEX(feature_index, Dqn_CPUFeature_Count) { - Dqn_CPUFeatureDecl feature_decl = g_dqn_cpu_feature_decl[feature_index]; - longest_feature_name = DQN_MAX(longest_feature_name, feature_decl.label.size); + DN_USize longest_feature_name = 0; + DN_FOR_UINDEX(feature_index, DN_CPUFeature_Count) { + DN_CPUFeatureDecl feature_decl = g_dn_cpu_feature_decl[feature_index]; + longest_feature_name = DN_MAX(longest_feature_name, feature_decl.label.size); } - DQN_FOR_UINDEX(feature_index, Dqn_CPUFeature_Count) { - Dqn_CPUFeatureDecl feature_decl = g_dqn_cpu_feature_decl[feature_index]; - bool has_feature = Dqn_CPU_HasFeature(report, feature_decl.value); - Dqn_Str8Builder_AddF(&builder, - " %.*s:%*s%s\n", - DQN_STR_FMT(feature_decl.label), - DQN_CAST(int)(longest_feature_name - feature_decl.label.size), - "", - has_feature ? "available" : "not available"); + DN_FOR_UINDEX(feature_index, DN_CPUFeature_Count) { + DN_CPUFeatureDecl feature_decl = g_dn_cpu_feature_decl[feature_index]; + bool has_feature = DN_CPU_HasFeature(report, feature_decl.value); + DN_Str8Builder_AppendF(&builder, + " %.*s:%*s%s\n", + DN_STR_FMT(feature_decl.label), + DN_CAST(int)(longest_feature_name - feature_decl.label.size), + "", + has_feature ? "available" : "not available"); } } - Dqn_Str8 info_log = Dqn_Str8Builder_Build(&builder, tmem.arena); - if (Dqn_Str8_HasData(info_log)) - Dqn_Log_DebugF("%.*s", DQN_STR_FMT(info_log)); - return result; + DN_Str8 info_log = DN_Str8Builder_Build(&builder, tmem.arena); + if (DN_Str8_HasData(info_log)) + DN_Log_DebugF("%.*s", DN_STR_FMT(info_log)); } -DQN_API void Dqn_Library_SetPointer(Dqn_Library *library) +DN_API void DN_Core_BeginFrame() +{ + DN_Atomic_SetValue64(&g_dn_core->mem_allocs_frame, 0); +} + +DN_API void DN_Core_SetPointer(DN_Core *library) { if (library) { - g_dqn_library = library; - Dqn_OS_ThreadSetTLS(&library->tls); + g_dn_core = library; + DN_OS_ThreadSetTLS(&library->tls); } } -#if !defined(DQN_NO_PROFILER) -DQN_API void Dqn_Library_SetProfiler(Dqn_Profiler *profiler) +#if !defined(DN_NO_PROFILER) +DN_API void DN_Core_SetProfiler(DN_Profiler *profiler) { if (profiler) - g_dqn_library->profiler = profiler; + g_dn_core->profiler = profiler; } #endif -DQN_API void Dqn_Library_SetLogCallback(Dqn_LogProc *proc, void *user_data) +DN_API void DN_Core_SetLogCallback(DN_LogProc *proc, void *user_data) { - g_dqn_library->log_callback = proc; - g_dqn_library->log_user_data = user_data; + g_dn_core->log_callback = proc; + g_dn_core->log_user_data = user_data; } -DQN_API void Dqn_Library_DumpThreadContextArenaStat(Dqn_Str8 file_path) +DN_API void DN_Core_DumpThreadContextArenaStat(DN_Str8 file_path) { -#if defined(DQN_DEBUG_THREAD_CONTEXT) +#if defined(DN_DEBUG_THREAD_CONTEXT) // NOTE: Open a file to write the arena stats to FILE *file = nullptr; fopen_s(&file, file_path.data, "a+b"); if (file) { - Dqn_Log_ErrorF("Failed to dump thread context arenas [file=%.*s]", DQN_STR_FMT(file_path)); + DN_Log_ErrorF("Failed to dump thread context arenas [file=%.*s]", DN_STR_FMT(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. - Dqn_ArenaStat stats[Dqn_CArray_CountI(g_dqn_library->thread_context_arena_stats)]; + DN_ArenaStat stats[DN_CArray_CountI(g_dn_core->thread_context_arena_stats)]; int stats_size = 0; - Dqn_TicketMutex_Begin(&g_dqn_library->thread_context_mutex); - stats_size = g_dqn_library->thread_context_arena_stats_count; - DQN_MEMCPY(stats, g_dqn_library->thread_context_arena_stats, sizeof(stats[0]) * stats_size); - Dqn_TicketMutex_End(&g_dqn_library->thread_context_mutex); + DN_TicketMutex_Begin(&g_dn_core->thread_context_mutex); + stats_size = g_dn_core->thread_context_arena_stats_count; + DN_MEMCPY(stats, g_dn_core->thread_context_arena_stats, sizeof(stats[0]) * stats_size); + DN_TicketMutex_End(&g_dn_core->thread_context_mutex); // NOTE: Print the cumulative stat - Dqn_DateHMSTimeStr now = Dqn_Date_HMSLocalTimeStrNow(); + DN_DateHMSTimeStr now = DN_Date_HMSLocalTimeStrNow(); fprintf(file, "Time=%.*s %.*s | Thread Context Arenas | Count=%d\n", now.date_size, now.date, now.hms_size, now.hms, - g_dqn_library->thread_context_arena_stats_count); + g_dn_core->thread_context_arena_stats_count); // NOTE: Write the cumulative thread arena data { - Dqn_ArenaStat stat = {}; - for (Dqn_usize index = 0; index < stats_size; index++) { - Dqn_ArenaStat const *current = stats + index; + DN_ArenaStat stat = {}; + for (DN_USize index = 0; index < stats_size; index++) { + DN_ArenaStat const *current = stats + index; stat.capacity += current->capacity; stat.used += current->used; stat.wasted += current->wasted; stat.blocks += current->blocks; - stat.capacity_hwm = DQN_MAX(stat.capacity_hwm, current->capacity_hwm); - stat.used_hwm = DQN_MAX(stat.used_hwm, current->used_hwm); - stat.wasted_hwm = DQN_MAX(stat.wasted_hwm, current->wasted_hwm); - stat.blocks_hwm = DQN_MAX(stat.blocks_hwm, current->blocks_hwm); + stat.capacity_hwm = DN_MAX(stat.capacity_hwm, current->capacity_hwm); + stat.used_hwm = DN_MAX(stat.used_hwm, current->used_hwm); + stat.wasted_hwm = DN_MAX(stat.wasted_hwm, current->wasted_hwm); + stat.blocks_hwm = DN_MAX(stat.blocks_hwm, current->blocks_hwm); } - Dqn_ArenaStatStr stats_string = Dqn_Arena_StatStr(&stat); + DN_ArenaStatStr stats_string = DN_Arena_StatStr(&stat); fprintf(file, " [ALL] CURR %.*s\n", stats_string.size, stats_string.data); } // NOTE: Print individual thread arena data - for (Dqn_usize index = 0; index < stats_size; index++) { - Dqn_ArenaStat const *current = stats + index; - Dqn_ArenaStatStr current_string = Dqn_Arena_StatStr(current); - fprintf(file, " [%03d] CURR %.*s\n", DQN_CAST(int) index, current_string.size, current_string.data); + for (DN_USize index = 0; index < stats_size; index++) { + DN_ArenaStat const *current = stats + index; + DN_ArenaStatStr current_string = DN_Arena_StatStr(current); + fprintf(file, " [%03d] CURR %.*s\n", DN_CAST(int) index, current_string.size, current_string.data); } fclose(file); - Dqn_Log_InfoF("Dumped thread context arenas [file=%.*s]", DQN_STR_FMT(file_path)); + DN_Log_InfoF("Dumped thread context arenas [file=%.*s]", DN_STR_FMT(file_path)); #else (void)file_path; -#endif // #if defined(DQN_DEBUG_THREAD_CONTEXT) +#endif // #if defined(DN_DEBUG_THREAD_CONTEXT) } -DQN_API Dqn_Arena *Dqn_Library_AllocArenaF(Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, char const *fmt, ...) +DN_API DN_Arena *DN_Core_AllocArenaF(DN_USize reserve, DN_USize commit, uint8_t arena_flags, char const *fmt, ...) { - DQN_ASSERT(g_dqn_library->lib_init); + DN_ASSERT(g_dn_core->init); va_list args; va_start(args, fmt); - Dqn_ArenaCatalog *catalog = &g_dqn_library->arena_catalog; - Dqn_Arena *result = Dqn_ArenaCatalog_AllocFV(catalog, reserve, commit, arena_flags, fmt, args); + DN_ArenaCatalog *catalog = &g_dn_core->arena_catalog; + DN_Arena *result = DN_ArenaCatalog_AllocFV(catalog, reserve, commit, arena_flags, fmt, args); va_end(args); return result; } -DQN_API bool Dqn_Library_EraseArena(Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena) +DN_API bool DN_Core_EraseArena(DN_Arena *arena, DN_ArenaCatalogFreeArena free_arena) { - Dqn_ArenaCatalog *catalog = &g_dqn_library->arena_catalog; - bool result = Dqn_ArenaCatalog_Erase(catalog, arena, free_arena); + DN_ArenaCatalog *catalog = &g_dn_core->arena_catalog; + bool result = DN_ArenaCatalog_Erase(catalog, arena, free_arena); return result; } -#if !defined(DQN_NO_PROFILER) -// NOTE: [$PROF] Dqn_Profiler ////////////////////////////////////////////////////////////////////// -DQN_API Dqn_ProfilerZoneScope::Dqn_ProfilerZoneScope(Dqn_Str8 name, uint16_t anchor_index) +#if !defined(DN_NO_PROFILER) +// NOTE: [$PROF] DN_Profiler ////////////////////////////////////////////////////////////////////// +DN_API DN_ProfilerZoneScope::DN_ProfilerZoneScope(DN_Str8 name, uint16_t anchor_index) { - zone = Dqn_Profiler_BeginZoneAtIndex(name, anchor_index); + zone = DN_Profiler_BeginZoneAtIndex(name, anchor_index); } -DQN_API Dqn_ProfilerZoneScope::~Dqn_ProfilerZoneScope() +DN_API DN_ProfilerZoneScope::~DN_ProfilerZoneScope() { - Dqn_Profiler_EndZone(zone); + DN_Profiler_EndZone(zone); } -DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_ReadBuffer() +DN_API DN_ProfilerAnchor *DN_Profiler_ReadBuffer() { - Dqn_ProfilerAnchor *result = Dqn_Profiler_AnchorBuffer(Dqn_ProfilerAnchorBuffer_Front); + uint8_t mask = DN_ARRAY_UCOUNT(g_dn_core->profiler->anchors) - 1; + DN_ProfilerAnchor *result = g_dn_core->profiler->anchors[(g_dn_core->profiler->active_anchor_buffer - 1) & mask]; return result; } -DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_WriteBuffer() +DN_API DN_ProfilerAnchor *DN_Profiler_WriteBuffer() { - Dqn_ProfilerAnchor *result = Dqn_Profiler_AnchorBuffer(Dqn_ProfilerAnchorBuffer_Back); + uint8_t mask = DN_ARRAY_UCOUNT(g_dn_core->profiler->anchors) - 1; + DN_ProfilerAnchor *result = g_dn_core->profiler->anchors[(g_dn_core->profiler->active_anchor_buffer + 0) & mask]; return result; } -DQN_API Dqn_ProfilerZone Dqn_Profiler_BeginZoneAtIndex(Dqn_Str8 name, uint16_t anchor_index) +DN_API DN_ProfilerZone DN_Profiler_BeginZoneAtIndex(DN_Str8 name, uint16_t anchor_index) { - Dqn_ProfilerAnchor *anchor = Dqn_Profiler_WriteBuffer() + anchor_index; - if (Dqn_Str8_HasData(anchor->name)) - DQN_ASSERTF(name == anchor->name, "Potentially overwriting a zone by accident?"); - anchor->name = name; - Dqn_ProfilerZone result = {}; - result.begin_tsc = Dqn_CPU_TSC(); - result.anchor_index = anchor_index; - result.parent_zone = g_dqn_library->profiler->parent_zone; - result.elapsed_tsc_at_zone_start = anchor->tsc_inclusive; - g_dqn_library->profiler->parent_zone = anchor_index; + DN_ProfilerAnchor *anchor = DN_Profiler_WriteBuffer() + anchor_index; + // TODO: We need per-thread-local-storage profiler so that we can use these apis + // across threads. For now, we let them overwrite each other but this is not tenable. +#if 0 + if (DN_Str8_HasData(anchor->name) && anchor->name != name) + DN_ASSERTF(name == anchor->name, "Potentially overwriting a zone by accident? Anchor is '%.*s', name is '%.*s'", DN_STR_FMT(anchor->name), DN_STR_FMT(name)); +#endif + anchor->name = name; + DN_ProfilerZone result = {}; + result.begin_tsc = DN_CPU_TSC(); + result.anchor_index = anchor_index; + result.parent_zone = g_dn_core->profiler->parent_zone; + result.elapsed_tsc_at_zone_start = anchor->tsc_inclusive; + g_dn_core->profiler->parent_zone = anchor_index; return result; } -DQN_API void Dqn_Profiler_EndZone(Dqn_ProfilerZone zone) +DN_API void DN_Profiler_EndZone(DN_ProfilerZone zone) { - uint64_t elapsed_tsc = Dqn_CPU_TSC() - zone.begin_tsc; - Dqn_ProfilerAnchor *anchor_buffer = Dqn_Profiler_WriteBuffer(); - Dqn_ProfilerAnchor *anchor = anchor_buffer + zone.anchor_index; + uint64_t elapsed_tsc = DN_CPU_TSC() - zone.begin_tsc; + DN_ProfilerAnchor *anchor_buffer = DN_Profiler_WriteBuffer(); + DN_ProfilerAnchor *anchor = anchor_buffer + zone.anchor_index; anchor->hit_count++; anchor->tsc_inclusive = zone.elapsed_tsc_at_zone_start + elapsed_tsc; anchor->tsc_exclusive += elapsed_tsc; - Dqn_ProfilerAnchor *parent_anchor = anchor_buffer + zone.parent_zone; + DN_ProfilerAnchor *parent_anchor = anchor_buffer + zone.parent_zone; parent_anchor->tsc_exclusive -= elapsed_tsc; - g_dqn_library->profiler->parent_zone = zone.parent_zone; + g_dn_core->profiler->parent_zone = zone.parent_zone; } -DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_AnchorBuffer(Dqn_ProfilerAnchorBuffer buffer) +DN_API void DN_Profiler_SwapAnchorBuffer() { - uint8_t offset = buffer == Dqn_ProfilerAnchorBuffer_Back ? 0 : 1; - uint8_t anchor_buffer = - (g_dqn_library->profiler->active_anchor_buffer + offset) % DQN_ARRAY_UCOUNT(g_dqn_library->profiler->anchors); - Dqn_ProfilerAnchor *result = g_dqn_library->profiler->anchors[anchor_buffer]; - return result; -} - -DQN_API void Dqn_Profiler_SwapAnchorBuffer() -{ - g_dqn_library->profiler->active_anchor_buffer++; - Dqn_ProfilerAnchor *anchors = Dqn_Profiler_AnchorBuffer(Dqn_ProfilerAnchorBuffer_Back); - DQN_MEMSET(anchors, + g_dn_core->profiler->active_anchor_buffer++; + g_dn_core->profiler->parent_zone = 0; + DN_ProfilerAnchor *anchors = DN_Profiler_WriteBuffer(); + DN_MEMSET(anchors, 0, - DQN_ARRAY_UCOUNT(g_dqn_library->profiler->anchors[0]) * sizeof(g_dqn_library->profiler->anchors[0][0])); + DN_ARRAY_UCOUNT(g_dn_core->profiler->anchors[0]) * sizeof(g_dn_core->profiler->anchors[0][0])); } -DQN_API void Dqn_Profiler_Dump(uint64_t tsc_per_second) +DN_API void DN_Profiler_Dump(uint64_t tsc_per_second) { - Dqn_ProfilerAnchor *anchors = Dqn_Profiler_ReadBuffer(); - for (size_t anchor_index = 1; anchor_index < DQN_PROFILER_ANCHOR_BUFFER_SIZE; anchor_index++) { - Dqn_ProfilerAnchor const *anchor = anchors + anchor_index; + DN_ProfilerAnchor *anchors = DN_Profiler_ReadBuffer(); + for (size_t anchor_index = 1; anchor_index < DN_PROFILER_ANCHOR_BUFFER_SIZE; anchor_index++) { + DN_ProfilerAnchor const *anchor = anchors + anchor_index; if (!anchor->hit_count) continue; uint64_t tsc_exclusive = anchor->tsc_exclusive; uint64_t tsc_inclusive = anchor->tsc_inclusive; - Dqn_f64 tsc_exclusive_milliseconds = tsc_exclusive * 1000 / DQN_CAST(Dqn_f64) tsc_per_second; + DN_F64 tsc_exclusive_milliseconds = tsc_exclusive * 1000 / DN_CAST(DN_F64) tsc_per_second; if (tsc_exclusive == tsc_inclusive) { - Dqn_Print_LnF("%.*s[%u]: %.1fms", DQN_STR_FMT(anchor->name), anchor->hit_count, tsc_exclusive_milliseconds); + DN_Print_LnF("%.*s[%u]: %.1fms", DN_STR_FMT(anchor->name), anchor->hit_count, tsc_exclusive_milliseconds); } else { - Dqn_f64 tsc_inclusive_milliseconds = tsc_inclusive * 1000 / DQN_CAST(Dqn_f64) tsc_per_second; - Dqn_Print_LnF("%.*s[%u]: %.1f/%.1fms", - DQN_STR_FMT(anchor->name), + DN_F64 tsc_inclusive_milliseconds = tsc_inclusive * 1000 / DN_CAST(DN_F64) tsc_per_second; + DN_Print_LnF("%.*s[%u]: %.1f/%.1fms", + DN_STR_FMT(anchor->name), anchor->hit_count, tsc_exclusive_milliseconds, tsc_inclusive_milliseconds); } } } -#endif // !defined(DQN_NO_PROFILER) +#endif // !defined(DN_NO_PROFILER) -// NOTE: [$JOBQ] Dqn_JobQueue /////////////////////////////////////////////////////////////////////// -DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit() +// NOTE: [$JOBQ] DN_JobQueue /////////////////////////////////////////////////////////////////////// +DN_API DN_JobQueueSPMC DN_OS_JobQueueSPMCInit() { - Dqn_JobQueueSPMC result = {}; - result.thread_wait_for_job_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/); - result.wait_for_completion_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/); - result.complete_queue_write_semaphore = Dqn_OS_SemaphoreInit(DQN_ARRAY_UCOUNT(result.complete_queue)); - result.mutex = Dqn_OS_MutexInit(); + DN_JobQueueSPMC result = {}; + result.thread_wait_for_job_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/); + result.wait_for_completion_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/); + result.complete_queue_write_semaphore = DN_OS_SemaphoreInit(DN_ARRAY_UCOUNT(result.complete_queue)); + result.mutex = DN_OS_MutexInit(); return result; } -DQN_API bool Dqn_OS_JobQueueSPMCAddArray(Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, uint32_t count) +DN_API bool DN_OS_JobQueueSPMCCanAdd(DN_JobQueueSPMC const *queue, uint32_t count) +{ + uint32_t read_index = queue->read_index; + uint32_t write_index = queue->write_index; + uint32_t size = write_index - read_index; + bool result = (size + count) <= DN_ARRAY_UCOUNT(queue->jobs); + return result; +} + +DN_API bool DN_OS_JobQueueSPMCAddArray(DN_JobQueueSPMC *queue, DN_Job *jobs, uint32_t count) { if (!queue) return false; - uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1; + uint32_t const pot_mask = DN_ARRAY_UCOUNT(queue->jobs) - 1; uint32_t read_index = queue->read_index; uint32_t write_index = queue->write_index; uint32_t size = write_index - read_index; - if ((size + count) > DQN_ARRAY_UCOUNT(queue->jobs)) + if ((size + count) > DN_ARRAY_UCOUNT(queue->jobs)) return false; for (size_t offset = 0; offset < count; offset++) { @@ -1352,52 +1437,52 @@ DQN_API bool Dqn_OS_JobQueueSPMCAddArray(Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, queue->jobs[wrapped_write_index] = jobs[offset]; } - Dqn_OS_MutexLock(&queue->mutex); + DN_OS_MutexLock(&queue->mutex); queue->write_index += count; - Dqn_OS_SemaphoreIncrement(&queue->thread_wait_for_job_semaphore, count); - Dqn_OS_MutexUnlock(&queue->mutex); + DN_OS_SemaphoreIncrement(&queue->thread_wait_for_job_semaphore, count); + DN_OS_MutexUnlock(&queue->mutex); return true; } -DQN_API bool Dqn_OS_JobQueueSPMCAdd(Dqn_JobQueueSPMC *queue, Dqn_Job job) +DN_API bool DN_OS_JobQueueSPMCAdd(DN_JobQueueSPMC *queue, DN_Job job) { - bool result = Dqn_OS_JobQueueSPMCAddArray(queue, &job, 1); + bool result = DN_OS_JobQueueSPMCAddArray(queue, &job, 1); return result; } -DQN_API int32_t Dqn_OS_JobQueueSPMCThread(Dqn_OSThread *thread) +DN_API int32_t DN_OS_JobQueueSPMCThread(DN_OSThread *thread) { - Dqn_JobQueueSPMC *queue = DQN_CAST(Dqn_JobQueueSPMC *) thread->user_context; - uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1; - static_assert(DQN_ARRAY_UCOUNT(queue->jobs) == DQN_ARRAY_UCOUNT(queue->complete_queue), "PoT mask is used to mask access to both arrays"); + DN_JobQueueSPMC *queue = DN_CAST(DN_JobQueueSPMC *) thread->user_context; + uint32_t const pot_mask = DN_ARRAY_UCOUNT(queue->jobs) - 1; + static_assert(DN_ARRAY_UCOUNT(queue->jobs) == DN_ARRAY_UCOUNT(queue->complete_queue), "PoT mask is used to mask access to both arrays"); for (;;) { - Dqn_OS_SemaphoreWait(&queue->thread_wait_for_job_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); + DN_OS_SemaphoreWait(&queue->thread_wait_for_job_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); if (queue->quit) break; - DQN_ASSERT(queue->read_index != queue->write_index); + DN_ASSERT(queue->read_index != queue->write_index); - Dqn_OS_MutexLock(&queue->mutex); + DN_OS_MutexLock(&queue->mutex); uint32_t wrapped_read_index = queue->read_index & pot_mask; - Dqn_Job job = queue->jobs[wrapped_read_index]; + DN_Job job = queue->jobs[wrapped_read_index]; queue->read_index += 1; - Dqn_OS_MutexUnlock(&queue->mutex); + DN_OS_MutexUnlock(&queue->mutex); - job.elapsed_tsc -= Dqn_CPU_TSC(); + job.elapsed_tsc -= DN_CPU_TSC(); job.func(thread, job.user_context); - job.elapsed_tsc += Dqn_CPU_TSC(); + job.elapsed_tsc += DN_CPU_TSC(); if (job.add_to_completion_queue) { - Dqn_OS_SemaphoreWait(&queue->complete_queue_write_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); - Dqn_OS_MutexLock(&queue->mutex); + DN_OS_SemaphoreWait(&queue->complete_queue_write_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); + DN_OS_MutexLock(&queue->mutex); queue->complete_queue[(queue->complete_write_index++ & pot_mask)] = job; - Dqn_OS_MutexUnlock(&queue->mutex); - Dqn_OS_SemaphoreIncrement(&queue->complete_queue_write_semaphore, 1); + DN_OS_MutexUnlock(&queue->mutex); + DN_OS_SemaphoreIncrement(&queue->complete_queue_write_semaphore, 1); } // NOTE: Update finish counter - Dqn_OS_MutexLock(&queue->mutex); + DN_OS_MutexLock(&queue->mutex); queue->finish_index += 1; // NOTE: If all jobs are finished and we have another thread who is @@ -1405,41 +1490,41 @@ DQN_API int32_t Dqn_OS_JobQueueSPMCThread(Dqn_OSThread *thread) // release the semaphore to wake them all up. bool all_jobs_finished = queue->finish_index == queue->write_index; if (all_jobs_finished && queue->threads_waiting_for_completion) { - Dqn_OS_SemaphoreIncrement(&queue->wait_for_completion_semaphore, + DN_OS_SemaphoreIncrement(&queue->wait_for_completion_semaphore, queue->threads_waiting_for_completion); queue->threads_waiting_for_completion = 0; } - Dqn_OS_MutexUnlock(&queue->mutex); + DN_OS_MutexUnlock(&queue->mutex); } return queue->quit_exit_code; } -DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion(Dqn_JobQueueSPMC *queue) +DN_API void DN_OS_JobQueueSPMCWaitForCompletion(DN_JobQueueSPMC *queue) { - Dqn_OS_MutexLock(&queue->mutex); + DN_OS_MutexLock(&queue->mutex); if (queue->finish_index == queue->write_index) { - Dqn_OS_MutexUnlock(&queue->mutex); + DN_OS_MutexUnlock(&queue->mutex); return; } queue->threads_waiting_for_completion++; - Dqn_OS_MutexUnlock(&queue->mutex); + DN_OS_MutexUnlock(&queue->mutex); - Dqn_OS_SemaphoreWait(&queue->wait_for_completion_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); + DN_OS_SemaphoreWait(&queue->wait_for_completion_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); } -DQN_API Dqn_usize Dqn_OS_JobQueueSPMCGetFinishedJobs(Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, Dqn_usize jobs_size) +DN_API DN_USize DN_OS_JobQueueSPMCGetFinishedJobs(DN_JobQueueSPMC *queue, DN_Job *jobs, DN_USize jobs_size) { - Dqn_usize result = 0; + DN_USize result = 0; if (!queue || !jobs || jobs_size <= 0) return result; - uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1; - Dqn_OS_MutexLock(&queue->mutex); + uint32_t const pot_mask = DN_ARRAY_UCOUNT(queue->jobs) - 1; + DN_OS_MutexLock(&queue->mutex); while (queue->complete_read_index < queue->complete_write_index && result < jobs_size) { jobs[result++] = queue->complete_queue[(queue->complete_read_index++ & pot_mask)]; } - Dqn_OS_MutexUnlock(&queue->mutex); + DN_OS_MutexUnlock(&queue->mutex); return result; } diff --git a/dqn_helpers.h b/dqn_helpers.h index c9336ba..8be471a 100644 --- a/dqn_helpers.h +++ b/dqn_helpers.h @@ -17,55 +17,55 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // -// [$PCG3] Dqn_PCG32 -- -- RNG from the PCG family -// [$JSON] Dqn_JSONBuilder -- DQN_JSON_BUILDER -- Construct json output -// [$BHEX] Dqn_Bin -- DQN_BIN -- Binary <-> hex helpers -// [$BSEA] Dqn_BinarySearch -- -- Binary search -// [$BITS] Dqn_Bit -- -- Bitset manipulation -// [$SAFE] Dqn_Safe -- -- Safe arithmetic, casts, asserts -// [$MISC] Misc -- -- Uncategorised helper functions -// [$DLIB] Dqn_Library -- -- Globally shared runtime data for this library -// [$PROF] Dqn_Profiler -- DQN_PROFILER -- Profiler that measures using a timestamp counter +// [$PCG3] DN_PCG32 -- -- RNG from the PCG family +// [$JSON] DN_JSONBuilder -- DN_JSON_BUILDER -- Construct json output +// [$BHEX] DN_Bin -- DN_BIN -- Binary <-> hex helpers +// [$BSEA] DN_BinarySearch -- -- Binary search +// [$BITS] DN_Bit -- -- Bitset manipulation +// [$SAFE] DN_Safe -- -- Safe arithmetic, casts, asserts +// [$MISC] Misc -- -- Uncategorised helper functions +// [$DLIB] DN_Library -- -- Globally shared runtime data for this library +// [$PROF] DN_Profiler -- DN_PROFILER -- Profiler that measures using a timestamp counter // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$PCGX] Dqn_PCG32 ///////////////////////////////////////////////////////////////////////// -struct Dqn_PCG32 { uint64_t state; }; +// NOTE: [$PCGX] DN_PCG32 ///////////////////////////////////////////////////////////////////////// +struct DN_PCG32 { uint64_t state; }; -#if !defined(DQN_NO_JSON_BUILDER) -// NOTE: [$JSON] Dqn_JSONBuilder /////////////////////////////////////////////////////////////////// -enum Dqn_JSONBuilderItem +#if !defined(DN_NO_JSON_BUILDER) +// NOTE: [$JSON] DN_JSONBuilder /////////////////////////////////////////////////////////////////// +enum DN_JSONBuilderItem { - Dqn_JSONBuilderItem_Empty, - Dqn_JSONBuilderItem_OpenContainer, - Dqn_JSONBuilderItem_CloseContainer, - Dqn_JSONBuilderItem_KeyValue, + DN_JSONBuilderItem_Empty, + DN_JSONBuilderItem_OpenContainer, + DN_JSONBuilderItem_CloseContainer, + DN_JSONBuilderItem_KeyValue, }; -struct Dqn_JSONBuilder +struct DN_JSONBuilder { - bool use_stdout; // When set, ignore the string builder and dump immediately to stdout - Dqn_Str8Builder string_builder; // (Internal) - int indent_level; // (Internal) - int spaces_per_indent; // The number of spaces per indent level - Dqn_JSONBuilderItem last_item; + bool use_stdout; // When set, ignore the string builder and dump immediately to stdout + DN_Str8Builder string_builder; // (Internal) + int indent_level; // (Internal) + int spaces_per_indent; // The number of spaces per indent level + DN_JSONBuilderItem last_item; }; -#endif // !defined(DQN_NO_JSON_BUIDLER) +#endif // !defined(DN_NO_JSON_BUIDLER) -// NOTE: [$BSEA] Dqn_BinarySearch ////////////////////////////////////////////////////////////////// +// NOTE: [$BSEA] DN_BinarySearch ////////////////////////////////////////////////////////////////// template -using Dqn_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs); +using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs); template -bool Dqn_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs); +bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs); -enum Dqn_BinarySearchType +enum DN_BinarySearchType { // Index of the match. If no match is found, found is set to false and the // index is set to the index where the match should be inserted/exist, if // it were in the array - Dqn_BinarySearchType_Match, + DN_BinarySearchType_Match, // Index of the first element in the array that is `element >= find`. If no such // item is found or the array is empty, then, the index is set to the array @@ -73,10 +73,10 @@ enum Dqn_BinarySearchType // // For example: // int array[] = {0, 1, 2, 3, 4, 5}; - // Dqn_BinarySearchResult result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4, Dqn_BinarySearchType_LowerBound); + // DN_BinarySearchResult result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4, DN_BinarySearchType_LowerBound); // printf("%zu\n", result.index); // Prints index '4' - Dqn_BinarySearchType_LowerBound, + DN_BinarySearchType_LowerBound, // Index of the first element in the array that is `element > find`. If no such // item is found or the array is empty, then, the index is set to the array @@ -84,79 +84,80 @@ enum Dqn_BinarySearchType // // For example: // int array[] = {0, 1, 2, 3, 4, 5}; - // Dqn_BinarySearchResult result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4, Dqn_BinarySearchType_UpperBound); + // DN_BinarySearchResult result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4, DN_BinarySearchType_UpperBound); // printf("%zu\n", result.index); // Prints index '5' - Dqn_BinarySearchType_UpperBound, + DN_BinarySearchType_UpperBound, }; -struct Dqn_BinarySearchResult +struct DN_BinarySearchResult { bool found; - Dqn_usize index; + DN_USize index; }; template -using Dqn_QSortLessThanProc = bool(T const &a, T const &b, void *user_context); +using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context); // NOTE: [$MISC] Misc ////////////////////////////////////////////////////////////////////////////// -struct Dqn_U64Str8 +struct DN_U64Str8 { - char data[27+1]; // NOTE(dqn): 27 is the maximum size of uint64_t including a separator + char data[27+1]; // NOTE(dn): 27 is the maximum size of uint64_t including a separator uint8_t size; }; -enum Dqn_U64ByteSizeType +enum DN_U64ByteSizeType { - Dqn_U64ByteSizeType_B, - Dqn_U64ByteSizeType_KiB, - Dqn_U64ByteSizeType_MiB, - Dqn_U64ByteSizeType_GiB, - Dqn_U64ByteSizeType_TiB, - Dqn_U64ByteSizeType_Count, - Dqn_U64ByteSizeType_Auto, + DN_U64ByteSizeType_B, + DN_U64ByteSizeType_KiB, + DN_U64ByteSizeType_MiB, + DN_U64ByteSizeType_GiB, + DN_U64ByteSizeType_TiB, + DN_U64ByteSizeType_Count, + DN_U64ByteSizeType_Auto, }; -struct Dqn_U64ByteSize +struct DN_U64ByteSize { - Dqn_U64ByteSizeType type; - Dqn_Str8 suffix; // "KiB", "MiB", "GiB" .. e.t.c - Dqn_f64 bytes; + DN_U64ByteSizeType type; + DN_Str8 suffix; // "KiB", "MiB", "GiB" .. e.t.c + DN_F64 bytes; }; -typedef uint32_t Dqn_U64AgeUnit; -enum Dqn_U64AgeUnit_ +typedef uint32_t DN_U64AgeUnit; +enum DN_U64AgeUnit_ { - Dqn_U64AgeUnit_Sec = 1 << 0, - Dqn_U64AgeUnit_Min = 1 << 1, - Dqn_U64AgeUnit_Hr = 1 << 2, - Dqn_U64AgeUnit_Day = 1 << 3, - Dqn_U64AgeUnit_Week = 1 << 4, - Dqn_U64AgeUnit_Year = 1 << 5, - Dqn_U64AgeUnit_HMS = Dqn_U64AgeUnit_Sec | Dqn_U64AgeUnit_Min | Dqn_U64AgeUnit_Hr, - Dqn_U64AgeUnit_All = Dqn_U64AgeUnit_HMS | Dqn_U64AgeUnit_Day | Dqn_U64AgeUnit_Week | Dqn_U64AgeUnit_Year, + DN_U64AgeUnit_Sec = 1 << 0, + DN_U64AgeUnit_Min = 1 << 1, + DN_U64AgeUnit_Hr = 1 << 2, + DN_U64AgeUnit_Day = 1 << 3, + DN_U64AgeUnit_Week = 1 << 4, + DN_U64AgeUnit_Year = 1 << 5, + DN_U64AgeUnit_HMS = DN_U64AgeUnit_Sec | DN_U64AgeUnit_Min | DN_U64AgeUnit_Hr, + DN_U64AgeUnit_All = DN_U64AgeUnit_HMS | DN_U64AgeUnit_Day | DN_U64AgeUnit_Week | DN_U64AgeUnit_Year, }; -struct Dqn_U64HexStr8 +struct DN_U64HexStr8 { char data[2 /*0x*/ + 16 /*hex*/ + 1 /*null-terminator*/]; uint8_t size; }; -enum Dqn_U64HexStr8Flags +typedef uint32_t DN_U64HexStr8Flags; +enum DN_U64HexStr8Flags_ { - Dqn_HexU64Str8Flags_Nil = 0, - Dqn_HexU64Str8Flags_0xPrefix = 1 << 0, /// Add the '0x' prefix from the string - Dqn_HexU64Str8Flags_UppercaseHex = 1 << 1, /// Use uppercase ascii characters for hex + DN_HexU64Str8Flags_Nil = 0, + DN_HexU64Str8Flags_0xPrefix = 1 << 0, /// Add the '0x' prefix from the string + DN_HexU64Str8Flags_UppercaseHex = 1 << 1, /// Use uppercase ascii characters for hex }; -#if !defined(DQN_NO_PROFILER) -// NOTE: [$PROF] Dqn_Profiler ////////////////////////////////////////////////////////////////////// -#if !defined(DQN_PROFILER_ANCHOR_BUFFER_SIZE) - #define DQN_PROFILER_ANCHOR_BUFFER_SIZE 128 +#if !defined(DN_NO_PROFILER) +// NOTE: [$PROF] DN_Profiler ////////////////////////////////////////////////////////////////////// +#if !defined(DN_PROFILER_ANCHOR_BUFFER_SIZE) + #define DN_PROFILER_ANCHOR_BUFFER_SIZE 256 #endif -struct Dqn_ProfilerAnchor +struct DN_ProfilerAnchor { // Inclusive refers to the time spent to complete the function call // including all children functions. @@ -168,10 +169,10 @@ struct Dqn_ProfilerAnchor uint64_t tsc_inclusive; uint64_t tsc_exclusive; uint16_t hit_count; - Dqn_Str8 name; + DN_Str8 name; }; -struct Dqn_ProfilerZone +struct DN_ProfilerZone { uint16_t anchor_index; uint64_t begin_tsc; @@ -180,332 +181,344 @@ struct Dqn_ProfilerZone }; #if defined(__cplusplus) -struct Dqn_ProfilerZoneScope +struct DN_ProfilerZoneScope { - Dqn_ProfilerZoneScope(Dqn_Str8 name, uint16_t anchor_index); - ~Dqn_ProfilerZoneScope(); - Dqn_ProfilerZone zone; + DN_ProfilerZoneScope(DN_Str8 name, uint16_t anchor_index); + ~DN_ProfilerZoneScope(); + DN_ProfilerZone zone; }; -#define Dqn_Profiler_ZoneScopeAtIndex(name, anchor_index) auto DQN_UNIQUE_NAME(profile_zone_) = Dqn_ProfilerZoneScope(DQN_STR8(name), anchor_index) -#define Dqn_Profiler_ZoneScope(name) Dqn_Profiler_ZoneScopeAtIndex(name, __COUNTER__ + 1) +#define DN_Profiler_ZoneScopeAtIndex(name, anchor_index) auto DN_UNIQUE_NAME(profile_zone_) = DN_ProfilerZoneScope(DN_STR8(name), anchor_index) +#define DN_Profiler_ZoneScope(name) DN_Profiler_ZoneScopeAtIndex(name, __COUNTER__ + 1) #endif -#define Dqn_Profiler_ZoneBlockIndex(name, index) \ - for (Dqn_ProfilerZone DQN_UNIQUE_NAME(profile_zone__) = Dqn_Profiler_BeginZoneAtIndex(name, index), DQN_UNIQUE_NAME(dummy__) = {}; \ - DQN_UNIQUE_NAME(dummy__).begin_tsc == 0; \ - Dqn_Profiler_EndZone(DQN_UNIQUE_NAME(profile_zone__)), DQN_UNIQUE_NAME(dummy__).begin_tsc = 1) +#define DN_Profiler_ZoneBlockIndex(name, index) \ + for (DN_ProfilerZone DN_UNIQUE_NAME(profile_zone__) = DN_Profiler_BeginZoneAtIndex(name, index), DN_UNIQUE_NAME(dummy__) = {}; \ + DN_UNIQUE_NAME(dummy__).begin_tsc == 0; \ + DN_Profiler_EndZone(DN_UNIQUE_NAME(profile_zone__)), DN_UNIQUE_NAME(dummy__).begin_tsc = 1) -#define Dqn_Profiler_ZoneBlock(name) Dqn_Profiler_ZoneBlockIndex(DQN_STR8(name), __COUNTER__ + 1) +#define DN_Profiler_ZoneBlock(name) DN_Profiler_ZoneBlockIndex(DN_STR8(name), __COUNTER__ + 1) -enum Dqn_ProfilerAnchorBuffer +enum DN_ProfilerAnchorBuffer { - Dqn_ProfilerAnchorBuffer_Back, - Dqn_ProfilerAnchorBuffer_Front, + DN_ProfilerAnchorBuffer_Back, + DN_ProfilerAnchorBuffer_Front, }; -struct Dqn_Profiler +struct DN_Profiler { - Dqn_ProfilerAnchor anchors[2][DQN_PROFILER_ANCHOR_BUFFER_SIZE]; - uint8_t active_anchor_buffer; - uint16_t parent_zone; + DN_ProfilerAnchor anchors[2][DN_PROFILER_ANCHOR_BUFFER_SIZE]; + uint8_t active_anchor_buffer; + uint16_t parent_zone; }; -#endif // !defined(DQN_NO_PROFILER) +#endif // !defined(DN_NO_PROFILER) -// NOTE: [$JOBQ] Dqn_JobQueue /////////////////////////////////////////////////////////////////////// -typedef void (Dqn_JobQueueFunc)(Dqn_OSThread *thread, void *user_context); -struct Dqn_Job +// NOTE: [$JOBQ] DN_JobQueue /////////////////////////////////////////////////////////////////////// +typedef void (DN_JobQueueFunc)(DN_OSThread *thread, void *user_context); +struct DN_Job { - Dqn_JobQueueFunc *func; // The function to invoke for the job - void *user_context; // Pointer user can set to use in their `job_func` - uint64_t elapsed_tsc; - uint16_t user_tag; // Arbitrary value the user can set to identiy the type of `user_context` this job has - bool add_to_completion_queue; // When true, on job completion, job must be dequeued from the completion queue via `GetFinishedJobs` + DN_JobQueueFunc *func; // The function to invoke for the job + void *user_context; // Pointer user can set to use in their `job_func` + uint64_t elapsed_tsc; + uint16_t user_tag; // Arbitrary value the user can set to identiy the type of `user_context` this job has + bool add_to_completion_queue; // When true, on job completion, job must be dequeued from the completion queue via `GetFinishedJobs` }; -#if !defined(DQN_JOB_QUEUE_SPMC_SIZE) - #define DQN_JOB_QUEUE_SPMC_SIZE 128 +#if !defined(DN_JOB_QUEUE_SPMC_SIZE) + #define DN_JOB_QUEUE_SPMC_SIZE 128 #endif -struct Dqn_JobQueueSPMC +struct DN_JobQueueSPMC { - Dqn_OSMutex mutex; - Dqn_OSSemaphore thread_wait_for_job_semaphore; - Dqn_OSSemaphore wait_for_completion_semaphore; - uint32_t threads_waiting_for_completion; + DN_OSMutex mutex; + DN_OSSemaphore thread_wait_for_job_semaphore; + DN_OSSemaphore wait_for_completion_semaphore; + DN_U32 threads_waiting_for_completion; - Dqn_Job jobs[DQN_JOB_QUEUE_SPMC_SIZE]; - Dqn_b32 quit; - uint32_t quit_exit_code; - uint32_t volatile read_index; - uint32_t volatile finish_index; - uint32_t volatile write_index; + DN_Job jobs[DN_JOB_QUEUE_SPMC_SIZE]; + DN_B32 quit; + DN_U32 quit_exit_code; + DN_U32 volatile read_index; + DN_U32 volatile finish_index; + DN_U32 volatile write_index; - Dqn_OSSemaphore complete_queue_write_semaphore; - Dqn_Job complete_queue[DQN_JOB_QUEUE_SPMC_SIZE]; - uint32_t volatile complete_read_index; - uint32_t volatile complete_write_index; + DN_OSSemaphore complete_queue_write_semaphore; + DN_Job complete_queue[DN_JOB_QUEUE_SPMC_SIZE]; + DN_U32 volatile complete_read_index; + DN_U32 volatile complete_write_index; }; -// NOTE: [$DLIB] Dqn_Library /////////////////////////////////////////////////////////////////////// +// NOTE: [$CORE] DN_Core ////////////////////////////////////////////////////////////////////////// // Book-keeping data for the library and allow customisation of certain features // provided. -struct Dqn_Library +struct DN_Core { - bool lib_init; // True if the library has been initialised via `Dqn_Library_Init` - Dqn_TicketMutex lib_mutex; - Dqn_Str8 exe_dir; // The directory of the current executable - Dqn_Arena arena; - Dqn_ChunkPool pool; // Uses 'arena' for malloc-like allocations - Dqn_ArenaCatalog arena_catalog; - bool slow_verification_checks; // Enable expensive library verification checks - Dqn_CPUReport cpu_report; - Dqn_TLS tls; // Thread local storage state for the main thread. + bool init; // True if the library has been initialised via `DN_Library_Init` + DN_OSMutex init_mutex; + DN_Str8 exe_dir; // The directory of the current executable + DN_Arena arena; + DN_Pool pool; + DN_ArenaCatalog arena_catalog; + bool slow_verification_checks; // Enable expensive library verification checks + DN_CPUReport cpu_report; + DN_TLS tls; // Thread local storage state for the main thread. // NOTE: Logging /////////////////////////////////////////////////////////////////////////////// - Dqn_LogProc * log_callback; // Set this pointer to override the logging routine - void * log_user_data; - bool log_to_file; // Output logs to file as well as standard out - Dqn_OSFile log_file; // TODO(dqn): Hmmm, how should we do this... ? - Dqn_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time - bool log_no_colour; // Disable colours in the logging output + DN_LogProc * 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... ? + DN_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time + bool log_no_colour; // Disable colours in the logging output + + // NOTE: Memory //////////////////////////////////////////////////////////////////////////////// + // Total OS mem allocs in lifetime of program (e.g. malloc, VirtualAlloc, HeapAlloc ...). This + // only includes allocations routed through the library such as the growing nature of arenas or + // using the memory allocation routines in the library like DN_OS_MemCommit and so forth. + uint64_t mem_allocs_total; + uint64_t mem_allocs_frame; // Total OS mem allocs since the last 'DN_Core_FrameBegin' was invoked // NOTE: Leak Tracing ////////////////////////////////////////////////////////////////////////// - #if defined(DQN_LEAK_TRACKING) - Dqn_DSMap alloc_table; - Dqn_TicketMutex alloc_table_mutex; - Dqn_Arena alloc_table_arena; + #if defined(DN_LEAK_TRACKING) + DN_DSMap alloc_table; + DN_TicketMutex alloc_table_mutex; + DN_Arena alloc_table_arena; #endif // NOTE: Win32 ///////////////////////////////////////////////////////////////////////////////// - #if defined(DQN_OS_WIN32) - LARGE_INTEGER win32_qpc_frequency; - Dqn_TicketMutex win32_bcrypt_rng_mutex; - void * win32_bcrypt_rng_handle; + #if defined(DN_OS_WIN32) + LARGE_INTEGER win32_qpc_frequency; + DN_TicketMutex win32_bcrypt_rng_mutex; + void * win32_bcrypt_rng_handle; + bool win32_sym_initialised; #endif - bool win32_sym_initialised; - // NOTE: OS //////////////////////////////////////////////////////////////////////////////////// - uint32_t os_page_size; - uint32_t os_alloc_granularity; + uint32_t os_page_size; + uint32_t os_alloc_granularity; // NOTE: Profiler ////////////////////////////////////////////////////////////////////////////// - #if !defined(DQN_NO_PROFILER) - Dqn_Profiler *profiler; - Dqn_Profiler profiler_default_instance; + #if !defined(DN_NO_PROFILER) + DN_Profiler * profiler; + DN_Profiler profiler_default_instance; #endif -} extern *g_dqn_library; - -enum Dqn_LibraryOnInit -{ - Dqn_LibraryOnInit_Nil = 0, - Dqn_LibraryOnInit_LogLibFeatures = 1 << 0, - Dqn_LibraryOnInit_LogCPUFeatures = 1 << 1, - Dqn_LibraryOnInit_LogAllFeatures = Dqn_LibraryOnInit_LogLibFeatures | Dqn_LibraryOnInit_LogCPUFeatures, }; -// NOTE: [$PCGX] Dqn_PCG32 ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_PCG32 Dqn_PCG32_Init (uint64_t seed); -DQN_API uint32_t Dqn_PCG32_Next (Dqn_PCG32 *rng); -DQN_API uint64_t Dqn_PCG32_Next64 (Dqn_PCG32 *rng); -DQN_API uint32_t Dqn_PCG32_Range (Dqn_PCG32 *rng, uint32_t low, uint32_t high); -DQN_API Dqn_f32 Dqn_PCG32_NextF32 (Dqn_PCG32 *rng); -DQN_API Dqn_f64 Dqn_PCG32_NextF64 (Dqn_PCG32 *rng); -DQN_API void Dqn_PCG32_Advance (Dqn_PCG32 *rng, uint64_t delta); +enum DN_CoreOnInit +{ + DN_CoreOnInit_Nil = 0, + DN_CoreOnInit_LogLibFeatures = 1 << 0, + DN_CoreOnInit_LogCPUFeatures = 1 << 1, + DN_CoreOnInit_LogAllFeatures = DN_CoreOnInit_LogLibFeatures | DN_CoreOnInit_LogCPUFeatures, +}; -#if !defined(DQN_NO_JSON_BUILDER) -// NOTE: [$JSON] Dqn_JSONBuilder /////////////////////////////////////////////////////////////////// -#define Dqn_JSONBuilder_Object(builder) \ - DQN_DEFER_LOOP(Dqn_JSONBuilder_ObjectBegin(builder), \ - Dqn_JSONBuilder_ObjectEnd(builder)) +// NOTE: [$PCGX] 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); -#define Dqn_JSONBuilder_ObjectNamed(builder, name) \ - DQN_DEFER_LOOP(Dqn_JSONBuilder_ObjectBeginNamed(builder, name), \ - Dqn_JSONBuilder_ObjectEnd(builder)) +#if !defined(DN_NO_JSON_BUILDER) +// NOTE: [$JSON] DN_JSONBuilder /////////////////////////////////////////////////////////////////// +#define DN_JSONBuilder_Object(builder) \ + DN_DEFER_LOOP(DN_JSONBuilder_ObjectBegin(builder), \ + DN_JSONBuilder_ObjectEnd(builder)) -#define Dqn_JSONBuilder_Array(builder) \ - DQN_DEFER_LOOP(Dqn_JSONBuilder_ArrayBegin(builder), \ - Dqn_JSONBuilder_ArrayEnd(builder)) +#define DN_JSONBuilder_ObjectNamed(builder, name) \ + DN_DEFER_LOOP(DN_JSONBuilder_ObjectBeginNamed(builder, name), \ + DN_JSONBuilder_ObjectEnd(builder)) -#define Dqn_JSONBuilder_ArrayNamed(builder, name) \ - DQN_DEFER_LOOP(Dqn_JSONBuilder_ArrayBeginNamed(builder, name), \ - Dqn_JSONBuilder_ArrayEnd(builder)) +#define DN_JSONBuilder_Array(builder) \ + DN_DEFER_LOOP(DN_JSONBuilder_ArrayBegin(builder), \ + DN_JSONBuilder_ArrayEnd(builder)) + +#define DN_JSONBuilder_ArrayNamed(builder, name) \ + DN_DEFER_LOOP(DN_JSONBuilder_ArrayBeginNamed(builder, name), \ + DN_JSONBuilder_ArrayEnd(builder)) -DQN_API Dqn_JSONBuilder Dqn_JSONBuilder_Init (Dqn_Arena *arena, int spaces_per_indent); -DQN_API Dqn_Str8 Dqn_JSONBuilder_Build (Dqn_JSONBuilder const *builder, Dqn_Arena *arena); -DQN_API void Dqn_JSONBuilder_KeyValue (Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value); -DQN_API void Dqn_JSONBuilder_KeyValueF (Dqn_JSONBuilder *builder, Dqn_Str8 key, char const *value_fmt, ...); -DQN_API void Dqn_JSONBuilder_ObjectBeginNamed (Dqn_JSONBuilder *builder, Dqn_Str8 name); -DQN_API void Dqn_JSONBuilder_ObjectEnd (Dqn_JSONBuilder *builder); -DQN_API void Dqn_JSONBuilder_ArrayBeginNamed (Dqn_JSONBuilder *builder, Dqn_Str8 name); -DQN_API void Dqn_JSONBuilder_ArrayEnd (Dqn_JSONBuilder *builder); -DQN_API void Dqn_JSONBuilder_Str8Named (Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value); -DQN_API void Dqn_JSONBuilder_LiteralNamed (Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value); -DQN_API void Dqn_JSONBuilder_U64Named (Dqn_JSONBuilder *builder, Dqn_Str8 key, uint64_t value); -DQN_API void Dqn_JSONBuilder_I64Named (Dqn_JSONBuilder *builder, Dqn_Str8 key, int64_t value); -DQN_API void Dqn_JSONBuilder_F64Named (Dqn_JSONBuilder *builder, Dqn_Str8 key, double value, int decimal_places); -DQN_API void Dqn_JSONBuilder_BoolNamed (Dqn_JSONBuilder *builder, Dqn_Str8 key, bool value); +DN_API DN_JSONBuilder DN_JSONBuilder_Init (DN_Arena *arena, int spaces_per_indent); +DN_API DN_Str8 DN_JSONBuilder_Build (DN_JSONBuilder const *builder, DN_Arena *arena); +DN_API void DN_JSONBuilder_KeyValue (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value); +DN_API void DN_JSONBuilder_KeyValueF (DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...); +DN_API void DN_JSONBuilder_ObjectBeginNamed (DN_JSONBuilder *builder, DN_Str8 name); +DN_API void DN_JSONBuilder_ObjectEnd (DN_JSONBuilder *builder); +DN_API void DN_JSONBuilder_ArrayBeginNamed (DN_JSONBuilder *builder, DN_Str8 name); +DN_API void DN_JSONBuilder_ArrayEnd (DN_JSONBuilder *builder); +DN_API void DN_JSONBuilder_Str8Named (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value); +DN_API void DN_JSONBuilder_LiteralNamed (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value); +DN_API void DN_JSONBuilder_U64Named (DN_JSONBuilder *builder, DN_Str8 key, uint64_t value); +DN_API void DN_JSONBuilder_I64Named (DN_JSONBuilder *builder, DN_Str8 key, int64_t value); +DN_API void DN_JSONBuilder_F64Named (DN_JSONBuilder *builder, DN_Str8 key, double value, int decimal_places); +DN_API void DN_JSONBuilder_BoolNamed (DN_JSONBuilder *builder, DN_Str8 key, bool value); -#define Dqn_JSONBuilder_ObjectBegin(builder) Dqn_JSONBuilder_ObjectBeginNamed(builder, DQN_STR8("")) -#define Dqn_JSONBuilder_ArrayBegin(builder) Dqn_JSONBuilder_ArrayBeginNamed(builder, DQN_STR8("")) -#define Dqn_JSONBuilder_Str8(builder, value) Dqn_JSONBuilder_Str8Named(builder, DQN_STR8(""), value) -#define Dqn_JSONBuilder_Literal(builder, value) Dqn_JSONBuilder_LiteralNamed(builder, DQN_STR8(""), value) -#define Dqn_JSONBuilder_U64(builder, value) Dqn_JSONBuilder_U64Named(builder, DQN_STR8(""), value) -#define Dqn_JSONBuilder_I64(builder, value) Dqn_JSONBuilder_I64Named(builder, DQN_STR8(""), value) -#define Dqn_JSONBuilder_F64(builder, value) Dqn_JSONBuilder_F64Named(builder, DQN_STR8(""), value) -#define Dqn_JSONBuilder_Bool(builder, value) Dqn_JSONBuilder_BoolNamed(builder, DQN_STR8(""), value) -#endif // !defined(DQN_NO_JSON_BUILDER) +#define DN_JSONBuilder_ObjectBegin(builder) DN_JSONBuilder_ObjectBeginNamed(builder, DN_STR8("")) +#define DN_JSONBuilder_ArrayBegin(builder) DN_JSONBuilder_ArrayBeginNamed(builder, DN_STR8("")) +#define DN_JSONBuilder_Str8(builder, value) DN_JSONBuilder_Str8Named(builder, DN_STR8(""), value) +#define DN_JSONBuilder_Literal(builder, value) DN_JSONBuilder_LiteralNamed(builder, DN_STR8(""), value) +#define DN_JSONBuilder_U64(builder, value) DN_JSONBuilder_U64Named(builder, DN_STR8(""), value) +#define DN_JSONBuilder_I64(builder, value) DN_JSONBuilder_I64Named(builder, DN_STR8(""), value) +#define DN_JSONBuilder_F64(builder, value) DN_JSONBuilder_F64Named(builder, DN_STR8(""), value) +#define DN_JSONBuilder_Bool(builder, value) DN_JSONBuilder_BoolNamed(builder, DN_STR8(""), value) +#endif // !defined(DN_NO_JSON_BUILDER) -// NOTE: [$BSEA] Dqn_BinarySearch ////////////////////////////////////////////////////////////////// -template bool Dqn_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs); -template Dqn_BinarySearchResult Dqn_BinarySearch (T const *array, - Dqn_usize array_size, +// NOTE: [$BSEA] DN_BinarySearch ////////////////////////////////////////////////////////////////// +template bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs); +template DN_BinarySearchResult DN_BinarySearch (T const *array, + DN_USize array_size, T const &find, - Dqn_BinarySearchType type = Dqn_BinarySearchType_Match, - Dqn_BinarySearchLessThanProc less_than = Dqn_BinarySearch_DefaultLessThan); + DN_BinarySearchType type = DN_BinarySearchType_Match, + DN_BinarySearchLessThanProc less_than = DN_BinarySearch_DefaultLessThan); -// NOTE: [$QSOR] Dqn_QSort ///////////////////////////////////////////////////////////////////////// -template bool Dqn_QSort_DefaultLessThan(T const &lhs, T const &rhs); -template void Dqn_QSort (T *array, - Dqn_usize array_size, +// NOTE: [$QSOR] DN_QSort ///////////////////////////////////////////////////////////////////////// +template bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs); +template void DN_QSort (T *array, + DN_USize array_size, void *user_context, - Dqn_QSortLessThanProc less_than = Dqn_QSort_DefaultLessThan); + DN_QSortLessThanProc less_than = DN_QSort_DefaultLessThan); -// NOTE: [$BITS] Dqn_Bit /////////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_Bit_UnsetInplace (Dqn_usize *flags, Dqn_usize bitfield); -DQN_API void Dqn_Bit_SetInplace (Dqn_usize *flags, Dqn_usize bitfield); -DQN_API bool Dqn_Bit_IsSet (Dqn_usize bits, Dqn_usize bits_to_set); -DQN_API bool Dqn_Bit_IsNotSet (Dqn_usize bits, Dqn_usize bits_to_check); -#define Dqn_Bit_ClearNextLSB(value) (value) & ((value) - 1) +// NOTE: [$BITS] DN_Bit /////////////////////////////////////////////////////////////////////////// +DN_API void DN_Bit_UnsetInplace (DN_USize *flags, DN_USize bitfield); +DN_API void DN_Bit_SetInplace (DN_USize *flags, DN_USize bitfield); +DN_API bool DN_Bit_IsSet (DN_USize bits, DN_USize bits_to_set); +DN_API bool DN_Bit_IsNotSet (DN_USize bits, DN_USize bits_to_check); +#define DN_Bit_ClearNextLSB(value) (value) & ((value) - 1) -// NOTE: [$SAFE] Dqn_Safe ////////////////////////////////////////////////////////////////////////// -DQN_API int64_t Dqn_Safe_AddI64 (int64_t a, int64_t b); -DQN_API int64_t Dqn_Safe_MulI64 (int64_t a, int64_t b); +// NOTE: [$SAFE] DN_Safe ////////////////////////////////////////////////////////////////////////// +DN_API int64_t DN_Safe_AddI64 (int64_t a, int64_t b); +DN_API int64_t DN_Safe_MulI64 (int64_t a, int64_t b); -DQN_API uint64_t Dqn_Safe_AddU64 (uint64_t a, uint64_t b); -DQN_API uint64_t Dqn_Safe_MulU64 (uint64_t a, uint64_t b); +DN_API uint64_t DN_Safe_AddU64 (uint64_t a, uint64_t b); +DN_API uint64_t DN_Safe_MulU64 (uint64_t a, uint64_t b); -DQN_API uint64_t Dqn_Safe_SubU64 (uint64_t a, uint64_t b); -DQN_API uint32_t Dqn_Safe_SubU32 (uint32_t a, uint32_t b); +DN_API uint64_t DN_Safe_SubU64 (uint64_t a, uint64_t b); +DN_API uint32_t DN_Safe_SubU32 (uint32_t a, uint32_t b); -DQN_API int Dqn_Safe_SaturateCastUSizeToInt (Dqn_usize val); -DQN_API int8_t Dqn_Safe_SaturateCastUSizeToI8 (Dqn_usize val); -DQN_API int16_t Dqn_Safe_SaturateCastUSizeToI16 (Dqn_usize val); -DQN_API int32_t Dqn_Safe_SaturateCastUSizeToI32 (Dqn_usize val); -DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64 (Dqn_usize val); +DN_API int DN_Safe_SaturateCastUSizeToInt (DN_USize val); +DN_API int8_t DN_Safe_SaturateCastUSizeToI8 (DN_USize val); +DN_API int16_t DN_Safe_SaturateCastUSizeToI16 (DN_USize val); +DN_API int32_t DN_Safe_SaturateCastUSizeToI32 (DN_USize val); +DN_API int64_t DN_Safe_SaturateCastUSizeToI64 (DN_USize val); -DQN_API int Dqn_Safe_SaturateCastU64ToInt (uint64_t val); -DQN_API int64_t Dqn_Safe_SaturateCastU64ToI64 (uint64_t val); -DQN_API unsigned int Dqn_Safe_SaturateCastU64ToUInt (uint64_t val); -DQN_API uint8_t Dqn_Safe_SaturateCastU64ToU8 (uint64_t val); -DQN_API uint16_t Dqn_Safe_SaturateCastU64ToU16 (uint64_t val); -DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32 (uint64_t val); +DN_API int DN_Safe_SaturateCastU64ToInt (uint64_t val); +DN_API int8_t DN_Safe_SaturateCastU8ToI8 (uint64_t val); +DN_API int16_t DN_Safe_SaturateCastU16ToI16 (uint64_t val); +DN_API int32_t DN_Safe_SaturateCastU32ToI32 (uint64_t val); +DN_API int64_t DN_Safe_SaturateCastU64ToI64 (uint64_t val); +DN_API unsigned int DN_Safe_SaturateCastU64ToUInt (uint64_t val); +DN_API uint8_t DN_Safe_SaturateCastU64ToU8 (uint64_t val); +DN_API uint16_t DN_Safe_SaturateCastU64ToU16 (uint64_t val); +DN_API uint32_t DN_Safe_SaturateCastU64ToU32 (uint64_t val); -DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8 (Dqn_usize val); -DQN_API uint16_t Dqn_Safe_SaturateCastUSizeToU16 (Dqn_usize val); -DQN_API uint32_t Dqn_Safe_SaturateCastUSizeToU32 (Dqn_usize val); -DQN_API uint64_t Dqn_Safe_SaturateCastUSizeToU64 (Dqn_usize val); +DN_API uint8_t DN_Safe_SaturateCastUSizeToU8 (DN_USize val); +DN_API uint16_t DN_Safe_SaturateCastUSizeToU16 (DN_USize val); +DN_API uint32_t DN_Safe_SaturateCastUSizeToU32 (DN_USize val); +DN_API uint64_t DN_Safe_SaturateCastUSizeToU64 (DN_USize val); -DQN_API int Dqn_Safe_SaturateCastISizeToInt (Dqn_isize val); -DQN_API int8_t Dqn_Safe_SaturateCastISizeToI8 (Dqn_isize val); -DQN_API int16_t Dqn_Safe_SaturateCastISizeToI16 (Dqn_isize val); -DQN_API int32_t Dqn_Safe_SaturateCastISizeToI32 (Dqn_isize val); -DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64 (Dqn_isize val); +DN_API int DN_Safe_SaturateCastISizeToInt (DN_ISize val); +DN_API int8_t DN_Safe_SaturateCastISizeToI8 (DN_ISize val); +DN_API int16_t DN_Safe_SaturateCastISizeToI16 (DN_ISize val); +DN_API int32_t DN_Safe_SaturateCastISizeToI32 (DN_ISize val); +DN_API int64_t DN_Safe_SaturateCastISizeToI64 (DN_ISize val); -DQN_API unsigned int Dqn_Safe_SaturateCastISizeToUInt (Dqn_isize val); -DQN_API uint8_t Dqn_Safe_SaturateCastISizeToU8 (Dqn_isize val); -DQN_API uint16_t Dqn_Safe_SaturateCastISizeToU16 (Dqn_isize val); -DQN_API uint32_t Dqn_Safe_SaturateCastISizeToU32 (Dqn_isize val); -DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64 (Dqn_isize val); +DN_API unsigned int DN_Safe_SaturateCastISizeToUInt (DN_ISize val); +DN_API uint8_t DN_Safe_SaturateCastISizeToU8 (DN_ISize val); +DN_API uint16_t DN_Safe_SaturateCastISizeToU16 (DN_ISize val); +DN_API uint32_t DN_Safe_SaturateCastISizeToU32 (DN_ISize val); +DN_API uint64_t DN_Safe_SaturateCastISizeToU64 (DN_ISize val); -DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize (int64_t val); -DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8 (int64_t val); -DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16 (int64_t val); -DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32 (int64_t val); +DN_API DN_ISize DN_Safe_SaturateCastI64ToISize (int64_t val); +DN_API int8_t DN_Safe_SaturateCastI64ToI8 (int64_t val); +DN_API int16_t DN_Safe_SaturateCastI64ToI16 (int64_t val); +DN_API int32_t DN_Safe_SaturateCastI64ToI32 (int64_t val); -DQN_API unsigned int Dqn_Safe_SaturateCastI64ToUInt (int64_t val); -DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToUSize (int64_t val); -DQN_API uint8_t Dqn_Safe_SaturateCastI64ToU8 (int64_t val); -DQN_API uint16_t Dqn_Safe_SaturateCastI64ToU16 (int64_t val); -DQN_API uint32_t Dqn_Safe_SaturateCastI64ToU32 (int64_t val); -DQN_API uint64_t Dqn_Safe_SaturateCastI64ToU64 (int64_t val); +DN_API unsigned int DN_Safe_SaturateCastI64ToUInt (int64_t val); +DN_API DN_ISize DN_Safe_SaturateCastI64ToUSize (int64_t val); +DN_API uint8_t DN_Safe_SaturateCastI64ToU8 (int64_t val); +DN_API uint16_t DN_Safe_SaturateCastI64ToU16 (int64_t val); +DN_API uint32_t DN_Safe_SaturateCastI64ToU32 (int64_t val); +DN_API uint64_t DN_Safe_SaturateCastI64ToU64 (int64_t val); -DQN_API int8_t Dqn_Safe_SaturateCastIntToI8 (int val); -DQN_API int16_t Dqn_Safe_SaturateCastIntToI16 (int val); -DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8 (int val); -DQN_API uint16_t Dqn_Safe_SaturateCastIntToU16 (int val); -DQN_API uint32_t Dqn_Safe_SaturateCastIntToU32 (int val); -DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64 (int val); +DN_API int8_t DN_Safe_SaturateCastIntToI8 (int val); +DN_API int16_t DN_Safe_SaturateCastIntToI16 (int val); +DN_API uint8_t DN_Safe_SaturateCastIntToU8 (int val); +DN_API uint16_t DN_Safe_SaturateCastIntToU16 (int val); +DN_API uint32_t DN_Safe_SaturateCastIntToU32 (int val); +DN_API uint64_t DN_Safe_SaturateCastIntToU64 (int val); // NOTE: [$MISC] Misc ////////////////////////////////////////////////////////////////////////////// -DQN_API int Dqn_FmtBuffer3DotTruncate (char *buffer, int size, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API Dqn_U64Str8 Dqn_U64ToStr8 (uint64_t val, char separator); -DQN_API Dqn_U64ByteSize Dqn_U64ToByteSize (uint64_t bytes, Dqn_U64ByteSizeType type); -DQN_API Dqn_Str8 Dqn_U64ToByteSizeStr8 (Dqn_Arena *arena, uint64_t bytes, Dqn_U64ByteSizeType desired_type); -DQN_API Dqn_Str8 Dqn_U64ByteSizeTypeString (Dqn_U64ByteSizeType type); -DQN_API Dqn_Str8 Dqn_U64ToAge (Dqn_Arena *arena, uint64_t age_s, Dqn_U64AgeUnit unit); +DN_API int DN_FmtBuffer3DotTruncate (char *buffer, int size, DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_U64Str8 DN_U64ToStr8 (uint64_t val, char separator); +DN_API DN_U64ByteSize DN_U64ToByteSize (uint64_t bytes, DN_U64ByteSizeType type); +DN_API DN_Str8 DN_U64ToByteSizeStr8 (DN_Arena *arena, uint64_t bytes, DN_U64ByteSizeType desired_type); +DN_API DN_Str8 DN_U64ByteSizeTypeString (DN_U64ByteSizeType type); +DN_API DN_Str8 DN_U64ToAge (DN_Arena *arena, uint64_t age_s, DN_U64AgeUnit unit); +DN_API DN_Str8 DN_F64ToAge (DN_Arena *arena, DN_F64 age_s, DN_U64AgeUnit unit); -DQN_API uint64_t Dqn_HexToU64 (Dqn_Str8 hex); -DQN_API Dqn_Str8 Dqn_U64ToHex (Dqn_Arena *arena, uint64_t number, uint32_t flags); -DQN_API Dqn_U64HexStr8 Dqn_U64ToHexStr8 (uint64_t number, uint32_t flags); +DN_API uint64_t DN_HexToU64 (DN_Str8 hex); +DN_API DN_Str8 DN_U64ToHex (DN_Arena *arena, uint64_t number, DN_U64HexStr8Flags flags); +DN_API DN_U64HexStr8 DN_U64ToHexStr8 (uint64_t number, uint32_t flags); -DQN_API bool Dqn_BytesToHexPtr (void const *src, Dqn_usize src_size, char *dest); -DQN_API Dqn_Str8 Dqn_BytesToHex (Dqn_Arena *arena, void const *src, Dqn_usize size); -#define Dqn_BytesToHex_TLS(...) Dqn_BytesToHex(Dqn_TLS_TopArena(), __VA_ARGS__) +DN_API bool DN_BytesToHexPtr (void const *src, DN_USize src_size, char *dest); +DN_API DN_Str8 DN_BytesToHex (DN_Arena *arena, void const *src, DN_USize size); +#define DN_BytesToHex_TLS(...) DN_BytesToHex(DN_TLS_TopArena(), __VA_ARGS__) -DQN_API Dqn_usize Dqn_HexToBytesPtrUnchecked (Dqn_Str8 hex, void *dest, Dqn_usize dest_size); -DQN_API Dqn_usize Dqn_HexToBytesPtr (Dqn_Str8 hex, void *dest, Dqn_usize dest_size); -DQN_API Dqn_Str8 Dqn_HexToBytesUnchecked (Dqn_Arena *arena, Dqn_Str8 hex); -#define Dqn_HexToBytesUnchecked_TLS(...) Dqn_HexToBytesUnchecked(Dqn_TLS_TopArena(), __VA_ARGS__) -DQN_API Dqn_Str8 Dqn_HexToBytes (Dqn_Arena *arena, Dqn_Str8 hex); -#define Dqn_HexToBytes_TLS(...) Dqn_HexToBytes(Dqn_TLS_TopArena(), __VA_ARGS__) +DN_API DN_USize DN_HexToBytesPtrUnchecked (DN_Str8 hex, void *dest, DN_USize dest_size); +DN_API DN_USize DN_HexToBytesPtr (DN_Str8 hex, void *dest, DN_USize dest_size); +DN_API DN_Str8 DN_HexToBytesUnchecked (DN_Arena *arena, DN_Str8 hex); +#define DN_HexToBytesUnchecked_TLS(...) DN_HexToBytesUnchecked(DN_TLS_TopArena(), __VA_ARGS__) +DN_API DN_Str8 DN_HexToBytes (DN_Arena *arena, DN_Str8 hex); +#define DN_HexToBytes_TLS(...) DN_HexToBytes(DN_TLS_TopArena(), __VA_ARGS__) -// NOTE: [$PROF] Dqn_Profiler ////////////////////////////////////////////////////////////////////// -DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_ReadBuffer (); -DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_WriteBuffer (); -#define Dqn_Profiler_BeginZone(name) Dqn_Profiler_BeginZoneAtIndex(DQN_STR8(name), __COUNTER__ + 1) -DQN_API Dqn_ProfilerZone Dqn_Profiler_BeginZoneAtIndex (Dqn_Str8 name, uint16_t anchor_index); -DQN_API void Dqn_Profiler_EndZone (Dqn_ProfilerZone zone); -DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_AnchorBuffer (Dqn_ProfilerAnchorBuffer buffer); -DQN_API void Dqn_Profiler_SwapAnchorBuffer (); -DQN_API void Dqn_Profiler_Dump (uint64_t tsc_per_second); +// NOTE: [$PROF] DN_Profiler ////////////////////////////////////////////////////////////////////// +DN_API DN_ProfilerAnchor * DN_Profiler_ReadBuffer (); +DN_API DN_ProfilerAnchor * DN_Profiler_WriteBuffer (); +#define DN_Profiler_BeginZone(name) DN_Profiler_BeginZoneAtIndex(DN_STR8(name), __COUNTER__ + 1) +DN_API DN_ProfilerZone DN_Profiler_BeginZoneAtIndex (DN_Str8 name, uint16_t anchor_index); +DN_API void DN_Profiler_EndZone (DN_ProfilerZone zone); +DN_API DN_ProfilerAnchor * DN_Profiler_AnchorBuffer (DN_ProfilerAnchorBuffer buffer); +DN_API void DN_Profiler_SwapAnchorBuffer (); +DN_API void DN_Profiler_Dump (uint64_t tsc_per_second); -// NOTE: [$JOBQ] Dqn_JobQueue /////////////////////////////////////////////////////////////////////// -DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit (); -DQN_API bool Dqn_OS_JobQueueSPMCAddArray (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, uint32_t count); -DQN_API bool Dqn_OS_JobQueueSPMCAdd (Dqn_JobQueueSPMC *queue, Dqn_Job job); -DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion (Dqn_JobQueueSPMC *queue); -DQN_API int32_t Dqn_OS_JobQueueSPMCThread (Dqn_OSThread *thread); -DQN_API Dqn_usize Dqn_OS_JobQueueSPMCGetFinishedJobs (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, Dqn_usize jobs_size); +// NOTE: [$JOBQ] DN_JobQueue /////////////////////////////////////////////////////////////////////// +DN_API DN_JobQueueSPMC DN_OS_JobQueueSPMCInit (); +DN_API bool DN_OS_JobQueueSPMCCanAdd (DN_JobQueueSPMC const *queue, uint32_t count); +DN_API bool DN_OS_JobQueueSPMCAddArray (DN_JobQueueSPMC *queue, DN_Job *jobs, uint32_t count); +DN_API bool DN_OS_JobQueueSPMCAdd (DN_JobQueueSPMC *queue, DN_Job job); +DN_API void DN_OS_JobQueueSPMCWaitForCompletion (DN_JobQueueSPMC *queue); +DN_API int32_t DN_OS_JobQueueSPMCThread (DN_OSThread *thread); +DN_API DN_USize DN_OS_JobQueueSPMCGetFinishedJobs (DN_JobQueueSPMC *queue, DN_Job *jobs, DN_USize jobs_size); -// NOTE: Dqn_Library /////////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Library * Dqn_Library_Init (Dqn_LibraryOnInit on_init); -DQN_API void Dqn_Library_SetPointer (Dqn_Library *library); -#if !defined(DQN_NO_PROFILER) -DQN_API void Dqn_Library_SetProfiler (Dqn_Profiler *profiler); +// NOTE: DN_Core /////////////////////////////////////////////////////////////////////////////// +DN_API void DN_Core_Init (DN_Core *core, DN_CoreOnInit on_init); +DN_API void DN_Core_BeginFrame (); +DN_API void DN_Core_SetPointer (DN_Core *core); +#if !defined(DN_NO_PROFILER) +DN_API void DN_Core_SetProfiler (DN_Profiler *profiler); #endif -DQN_API void Dqn_Library_SetLogCallback (Dqn_LogProc *proc, void *user_data); -DQN_API void Dqn_Library_DumpThreadContextArenaStat (Dqn_Str8 file_path); -DQN_API Dqn_Arena * Dqn_Library_AllocArenaF (Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, char const *fmt, ...); -DQN_API bool Dqn_Library_EraseArena (Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena); +DN_API void DN_Core_SetLogCallback (DN_LogProc *proc, void *user_data); +DN_API void DN_Core_DumpThreadContextArenaStat (DN_Str8 file_path); +DN_API DN_Arena * DN_Core_AllocArenaF (DN_USize reserve, DN_USize commit, uint8_t arena_flags, char const *fmt, ...); +DN_API bool DN_Core_EraseArena (DN_Arena *arena, DN_ArenaCatalogFreeArena free_arena); -// NOTE: [$BSEA] Dqn_BinarySearch ////////////////////////////////////////////////////////////////// +// NOTE: [$BSEA] DN_BinarySearch ////////////////////////////////////////////////////////////////// template -bool Dqn_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs) +bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs) { bool result = lhs < rhs; return result; } template -Dqn_BinarySearchResult Dqn_BinarySearch(T const *array, - Dqn_usize array_size, +DN_BinarySearchResult DN_BinarySearch(T const *array, + DN_USize array_size, T const &find, - Dqn_BinarySearchType type, - Dqn_BinarySearchLessThanProc less_than) + DN_BinarySearchType type, + DN_BinarySearchLessThanProc less_than) { - Dqn_BinarySearchResult result = {}; + DN_BinarySearchResult result = {}; if (!array || array_size <= 0 || !less_than) return result; @@ -513,11 +526,11 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array, T const *first = array; T const *last = end; while (first != last) { - Dqn_usize count = last - first; + DN_USize count = last - first; T const *it = first + (count / 2); bool advance_first = false; - if (type == Dqn_BinarySearchType_UpperBound) + if (type == DN_BinarySearchType_UpperBound) advance_first = !less_than(find, it[0]); else advance_first = less_than(it[0], find); @@ -529,12 +542,12 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array, } switch (type) { - case Dqn_BinarySearchType_Match: { + case DN_BinarySearchType_Match: { result.found = first != end && !less_than(find, *first); } break; - case Dqn_BinarySearchType_LowerBound: /*FALLTHRU*/ - case Dqn_BinarySearchType_UpperBound: { + case DN_BinarySearchType_LowerBound: /*FALLTHRU*/ + case DN_BinarySearchType_UpperBound: { result.found = first != end; } break; } @@ -543,9 +556,9 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array, return result; } -// NOTE: [$QSOR] Dqn_QSort ///////////////////////////////////////////////////////////////////////// +// NOTE: [$QSOR] DN_QSort ///////////////////////////////////////////////////////////////////////// template -bool Dqn_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context) +bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context) { (void)user_context; bool result = lhs < rhs; @@ -553,19 +566,19 @@ bool Dqn_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context) } template -void Dqn_QSort(T *array, Dqn_usize array_size, void *user_context, Dqn_QSortLessThanProc less_than) +void DN_QSort(T *array, DN_USize array_size, void *user_context, DN_QSortLessThanProc less_than) { if (!array || array_size <= 1 || !less_than) return; // NOTE: Insertion Sort, under 24->32 is an optimal amount ///////////////////////////////////// - const Dqn_usize QSORT_THRESHOLD = 24; + const DN_USize QSORT_THRESHOLD = 24; if (array_size < QSORT_THRESHOLD) { - for (Dqn_usize item_to_insert_index = 1; item_to_insert_index < array_size; item_to_insert_index++) { - for (Dqn_usize index = 0; index < item_to_insert_index; index++) { + for (DN_USize item_to_insert_index = 1; item_to_insert_index < array_size; item_to_insert_index++) { + for (DN_USize index = 0; index < item_to_insert_index; index++) { if (!less_than(array[index], array[item_to_insert_index], user_context)) { T item_to_insert = array[item_to_insert_index]; - for (Dqn_usize i = item_to_insert_index; i > index; i--) + for (DN_USize i = item_to_insert_index; i > index; i--) array[i] = array[i - 1]; array[index] = item_to_insert; @@ -577,14 +590,14 @@ void Dqn_QSort(T *array, Dqn_usize array_size, void *user_context, Dqn_QSortLess } // NOTE: Quick sort, under 24->32 is an optimal amount ///////////////////////////////////////// - Dqn_usize last_index = array_size - 1; - Dqn_usize pivot_index = array_size / 2; - Dqn_usize partition_index = 0; - Dqn_usize start_index = 0; + DN_USize last_index = array_size - 1; + DN_USize pivot_index = array_size / 2; + DN_USize partition_index = 0; + DN_USize start_index = 0; // Swap pivot with last index, so pivot is always at the end of the array. // This makes logic much simpler. - DQN_SWAP(array[last_index], array[pivot_index]); + DN_SWAP(array[last_index], array[pivot_index]); pivot_index = last_index; // 4^, 8, 7, 5, 2, 3, 6 @@ -596,20 +609,20 @@ void Dqn_QSort(T *array, Dqn_usize array_size, void *user_context, Dqn_QSortLess // 4, 5, |7, 8, 2^, 3, 6* // 4, 5, 2, |8, 7, ^3, 6* // 4, 5, 2, 3, |7, 8, ^6* - for (Dqn_usize index = start_index; index < last_index; index++) { + for (DN_USize index = start_index; index < last_index; index++) { if (less_than(array[index], array[pivot_index], user_context)) { - DQN_SWAP(array[partition_index], array[index]); + DN_SWAP(array[partition_index], array[index]); partition_index++; } } // Move pivot to right of partition // 4, 5, 2, 3, |6, 8, ^7* - DQN_SWAP(array[partition_index], array[pivot_index]); - Dqn_QSort(array, partition_index, user_context, less_than); + DN_SWAP(array[partition_index], array[pivot_index]); + DN_QSort(array, partition_index, user_context, less_than); // Skip the value at partion index since that is guaranteed to be sorted. // 4, 5, 2, 3, (x), 8, 7 - Dqn_usize one_after_partition_index = partition_index + 1; - Dqn_QSort(array + one_after_partition_index, (array_size - one_after_partition_index), user_context, less_than); + DN_USize one_after_partition_index = partition_index + 1; + DN_QSort(array + one_after_partition_index, (array_size - one_after_partition_index), user_context, less_than); } diff --git a/dqn_json.cpp b/dqn_json.cpp index 154f5dc..e8b099f 100644 --- a/dqn_json.cpp +++ b/dqn_json.cpp @@ -1,19 +1,19 @@ #pragma once #include "dqn.h" -// NOTE: Dqn_JSON ////////////////////////////////////////////////////////////////////////////////// -void *Dqn_JSON_ArenaAllocFunc(void *user_data, size_t count) +// NOTE: DN_JSON ////////////////////////////////////////////////////////////////////////////////// +void *DN_JSON_ArenaAllocFunc(void *user_data, size_t count) { void *result = NULL; if (!user_data) return result; - Dqn_Arena *arena = DQN_CAST(Dqn_Arena*)user_data; - result = Dqn_Arena_Alloc(arena, count, alignof(json_value_s), Dqn_ZeroMem_No); + DN_Arena *arena = DN_CAST(DN_Arena*)user_data; + result = DN_Arena_Alloc(arena, count, alignof(json_value_s), DN_ZeroMem_No); return result; } -char const *Dqn_JSON_TypeEnumCString(json_type_e type, size_t *size) +char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size) { switch (type) { case json_type_string: { if (size) { *size = sizeof("string") - 1; } return "string"; } @@ -28,165 +28,165 @@ char const *Dqn_JSON_TypeEnumCString(json_type_e type, size_t *size) } } -bool Dqn_JSON_String8Cmp(json_string_s const *lhs, Dqn_Str8 key) +bool DN_JSON_String8Cmp(json_string_s const *lhs, DN_Str8 key) { bool result = false; - if (lhs && Dqn_Str8_HasData(key)) { - Dqn_Str8 lhs_string = Dqn_Str8_Init(lhs->string, lhs->string_size); - result = Dqn_Str8_Eq(lhs_string, key); + if (lhs && DN_Str8_HasData(key)) { + DN_Str8 lhs_string = DN_Str8_Init(lhs->string, lhs->string_size); + result = DN_Str8_Eq(lhs_string, key); } return result; } -// NOTE: Dqn_JSON_It /////////////////////////////////////////////////////////////////////////////// -Dqn_JSONIt Dqn_JSON_LoadFileToIt(Dqn_Arena *arena, Dqn_Str8 json) +// NOTE: DN_JSON_It /////////////////////////////////////////////////////////////////////////////// +DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json) { json_parse_result_s parse_result = {}; json_value_ex_s *ex_value = - DQN_CAST(json_value_ex_s *) json_parse_ex(json.data, + DN_CAST(json_value_ex_s *) json_parse_ex(json.data, json.size, json_parse_flags_allow_location_information, - Dqn_JSON_ArenaAllocFunc, + DN_JSON_ArenaAllocFunc, arena, &parse_result); - Dqn_JSONIt result = {}; - Dqn_JSON_ItPushValue(&result, &ex_value->value); + DN_JSONIt result = {}; + DN_JSON_ItPushValue(&result, &ex_value->value); return result; } -// NOTE: Dqn_JSON_ItPush/Pop /////////////////////////////////////////////////////////////////////// -bool Dqn_JSON_ItPushObjElement(Dqn_JSONIt *it, json_object_element_s *element) +// NOTE: DN_JSON_ItPush/Pop /////////////////////////////////////////////////////////////////////// +bool DN_JSON_ItPushObjElement(DN_JSONIt *it, json_object_element_s *element) { if (!it || !element) return false; - DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack)); - it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeObjElement, element}; + DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack)); + it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeObjElement, element}; return true; } -bool Dqn_JSON_ItPushObj(Dqn_JSONIt *it, json_object_s *obj) +bool DN_JSON_ItPushObj(DN_JSONIt *it, json_object_s *obj) { if (!it || !obj) return false; - DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack)); - it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeObj, obj}; + DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack)); + it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeObj, obj}; return true; } -bool Dqn_JSON_ItPushArrayElement(Dqn_JSONIt *it, json_array_element_s *element) +bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element) { if (!it || !element) return false; - DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack)); - it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeArrayElement, element}; + DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack)); + it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeArrayElement, element}; return true; } -bool Dqn_JSON_ItPushArray(Dqn_JSONIt *it, json_value_s *value) +bool DN_JSON_ItPushArray(DN_JSONIt *it, json_value_s *value) { if (!it || !value || json_value_as_array(value) == nullptr) return false; - DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack)); - it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeArray, value}; + DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack)); + it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeArray, value}; return true; } -bool Dqn_JSON_ItPushValue(Dqn_JSONIt *it, json_value_s *value) +bool DN_JSON_ItPushValue(DN_JSONIt *it, json_value_s *value) { bool result = false; if (!it || !value) return result; if (value->type == json_type_object) { - result = Dqn_JSON_ItPushObj(it, json_value_as_object(value)); + result = DN_JSON_ItPushObj(it, json_value_as_object(value)); } else if (value->type == json_type_array) { - result = Dqn_JSON_ItPushArray(it, value); + result = DN_JSON_ItPushArray(it, value); } return result; } -void Dqn_JSON_ItPop(Dqn_JSONIt *it) +void DN_JSON_ItPop(DN_JSONIt *it) { if (!it) return; - DQN_ASSERT(it->stack_count > 0); + DN_ASSERT(it->stack_count > 0); if (it->stack_count > 0) it->stack_count--; } -// NOTE: Dqn_JSON_It JSON tree navigation ////////////////////////////////////////////////////////// -json_value_s *Dqn_JSON_ItPushCurrValue(Dqn_JSONIt *it) +// NOTE: DN_JSON_It JSON tree navigation ////////////////////////////////////////////////////////// +json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it) { json_value_s *result = nullptr; - Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it); + DN_JSONItEntry *curr = DN_JSON_ItCurr(it); if (!curr) return result; - if (curr->type == Dqn_JSON_ItEntryTypeObjElement) { - json_object_element_s *element = DQN_CAST(json_object_element_s *) curr->value; + if (curr->type == DN_JSON_ItEntryTypeObjElement) { + json_object_element_s *element = DN_CAST(json_object_element_s *) curr->value; result = element->value; - } else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) { - json_array_element_s *element = DQN_CAST(json_array_element_s *) curr->value; + } else if (curr->type == DN_JSON_ItEntryTypeArrayElement) { + json_array_element_s *element = DN_CAST(json_array_element_s *) curr->value; result = element->value; } else { - result = DQN_CAST(json_value_s *) curr->value; + result = DN_CAST(json_value_s *) curr->value; } if (result->type == json_type_array) { json_array_s *array = json_value_as_array(result); - DQN_ASSERT(array); - Dqn_JSON_ItPushArray(it, result); + DN_ASSERT(array); + DN_JSON_ItPushArray(it, result); } else if (result->type == json_type_object) { json_object_s *obj = json_value_as_object(result); - DQN_ASSERT(obj); - Dqn_JSON_ItPushObj(it, obj); + DN_ASSERT(obj); + DN_JSON_ItPushObj(it, obj); } return result; } -bool Dqn_JSON_ItNext(Dqn_JSONIt *it) +bool DN_JSON_ItNext(DN_JSONIt *it) { - Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it); + DN_JSONItEntry *curr = DN_JSON_ItCurr(it); if (!curr) return false; json_object_element_s *obj_element = nullptr; json_array_element_s *array_element = nullptr; - if (curr->type == Dqn_JSON_ItEntryTypeObj) { - auto *obj = DQN_CAST(json_object_s *) curr->value; + if (curr->type == DN_JSON_ItEntryTypeObj) { + auto *obj = DN_CAST(json_object_s *) curr->value; obj_element = obj->start; - } else if (curr->type == Dqn_JSON_ItEntryTypeObjElement) { - auto *element = DQN_CAST(json_object_element_s *) curr->value; + } else if (curr->type == DN_JSON_ItEntryTypeObjElement) { + auto *element = DN_CAST(json_object_element_s *) curr->value; obj_element = element->next; - Dqn_JSON_ItPop(it); - } else if (curr->type == Dqn_JSON_ItEntryTypeArray) { - auto *value = DQN_CAST(json_value_s *) curr->value; + DN_JSON_ItPop(it); + } else if (curr->type == DN_JSON_ItEntryTypeArray) { + auto *value = DN_CAST(json_value_s *) curr->value; auto *array = json_value_as_array(value); array_element = array->start; - } else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) { - auto *element = DQN_CAST(json_array_element_s *) curr->value; + } else if (curr->type == DN_JSON_ItEntryTypeArrayElement) { + auto *element = DN_CAST(json_array_element_s *) curr->value; array_element = element->next; - Dqn_JSON_ItPop(it); + DN_JSON_ItPop(it); } else { - Dqn_JSON_ItPop(it); + DN_JSON_ItPop(it); } if (obj_element) - Dqn_JSON_ItPushObjElement(it, obj_element); + DN_JSON_ItPushObjElement(it, obj_element); else if (array_element) - Dqn_JSON_ItPushArrayElement(it, array_element); + DN_JSON_ItPushArrayElement(it, array_element); bool result = obj_element || array_element; return result; } -// NOTE: Dqn_JSON_ItCurr /////////////////////////////////////////////////////////////////////////// -Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it) +// NOTE: DN_JSON_ItCurr /////////////////////////////////////////////////////////////////////////// +DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it) { - Dqn_JSONItEntry *result = nullptr; + DN_JSONItEntry *result = nullptr; if (!it || it->stack_count <= 0) return result; @@ -194,236 +194,236 @@ Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it) return result; } -json_value_s *Dqn_JSON_ItCurrValue(Dqn_JSONIt *it) +json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it) { json_value_s *result = nullptr; - Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it); + DN_JSONItEntry *curr = DN_JSON_ItCurr(it); if (!curr) return result; - if (curr->type == Dqn_JSON_ItEntryTypeObjElement) { - auto *element = DQN_CAST(json_object_element_s *)curr->value; + if (curr->type == DN_JSON_ItEntryTypeObjElement) { + auto *element = DN_CAST(json_object_element_s *)curr->value; result = element->value; - } else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) { - auto *element = DQN_CAST(json_array_element_s *)curr->value; + } else if (curr->type == DN_JSON_ItEntryTypeArrayElement) { + auto *element = DN_CAST(json_array_element_s *)curr->value; result = element->value; - } else if (curr->type == Dqn_JSON_ItEntryTypeString || - curr->type == Dqn_JSON_ItEntryTypeNumber || - curr->type == Dqn_JSON_ItEntryTypeObj || - curr->type == Dqn_JSON_ItEntryTypeArray) + } else if (curr->type == DN_JSON_ItEntryTypeString || + curr->type == DN_JSON_ItEntryTypeNumber || + curr->type == DN_JSON_ItEntryTypeObj || + curr->type == DN_JSON_ItEntryTypeArray) { - result = DQN_CAST(json_value_s *)curr->value; + result = DN_CAST(json_value_s *)curr->value; } return result; } -json_object_element_s *Dqn_JSON_ItCurrObjElement(Dqn_JSONIt *it) +json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it) { - Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it); - auto *result = (curr && curr->type == Dqn_JSON_ItEntryTypeObjElement) - ? DQN_CAST(json_object_element_s *) curr->value + DN_JSONItEntry *curr = DN_JSON_ItCurr(it); + auto *result = (curr && curr->type == DN_JSON_ItEntryTypeObjElement) + ? DN_CAST(json_object_element_s *) curr->value : nullptr; return result; } -// NOTE: Dqn_JSON_ItValueIs //////////////////////////////////////////////////////////////////////// -json_value_s *Dqn_JSON_ItValueIs(Dqn_JSONIt *it, json_type_e type) +// NOTE: DN_JSON_ItValueIs //////////////////////////////////////////////////////////////////////// +json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type) { - json_value_s *curr = Dqn_JSON_ItCurrValue(it); + json_value_s *curr = DN_JSON_ItCurrValue(it); json_value_s *result = (curr && type == curr->type) ? curr : nullptr; return result; } -json_object_s *Dqn_JSON_ItValueIsObj(Dqn_JSONIt *it) +json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it) { - json_value_s *curr = Dqn_JSON_ItCurrValue(it); + json_value_s *curr = DN_JSON_ItCurrValue(it); json_object_s *result = curr ? json_value_as_object(curr) : nullptr; return result; } -json_array_s *Dqn_JSON_ItValueIsArray(Dqn_JSONIt *it) +json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it) { - json_value_s *curr = Dqn_JSON_ItCurrValue(it); + json_value_s *curr = DN_JSON_ItCurrValue(it); json_array_s *result = curr ? json_value_as_array(curr) : nullptr; return result; } -json_string_s *Dqn_JSON_ItValueIsString(Dqn_JSONIt *it) +json_string_s *DN_JSON_ItValueIsString(DN_JSONIt *it) { - json_value_s *curr = Dqn_JSON_ItCurrValue(it); + json_value_s *curr = DN_JSON_ItCurrValue(it); json_string_s *result = curr ? json_value_as_string(curr) : nullptr; return result; } -json_number_s *Dqn_JSON_ItValueIsNumber(Dqn_JSONIt *it) +json_number_s *DN_JSON_ItValueIsNumber(DN_JSONIt *it) { - json_value_s *curr = Dqn_JSON_ItCurrValue(it); + json_value_s *curr = DN_JSON_ItCurrValue(it); json_number_s *result = curr ? json_value_as_number(curr) : nullptr; return result; } -json_value_s *Dqn_JSON_ItValueIsBool(Dqn_JSONIt *it) +json_value_s *DN_JSON_ItValueIsBool(DN_JSONIt *it) { - json_value_s *curr = Dqn_JSON_ItCurrValue(it); + json_value_s *curr = DN_JSON_ItCurrValue(it); json_value_s *result = (curr && (curr->type == json_type_true || curr->type == json_type_false)) ? curr : nullptr; return result; } -json_value_s *Dqn_JSON_ItValueIsNull(Dqn_JSONIt *it) +json_value_s *DN_JSON_ItValueIsNull(DN_JSONIt *it) { - json_value_s *curr = Dqn_JSON_ItCurrValue(it); + json_value_s *curr = DN_JSON_ItCurrValue(it); json_value_s *result = (curr && (curr->type == json_type_null)) ? curr : nullptr; return result; } -size_t Dqn_JSON_ItValueArraySize(Dqn_JSONIt *it) +size_t DN_JSON_ItValueArraySize(DN_JSONIt *it) { size_t result = 0; - if (json_array_s *curr = Dqn_JSON_ItValueIsArray(it)) + if (json_array_s *curr = DN_JSON_ItValueIsArray(it)) result = curr->length; return result; } -// NOTE: Dqn_JSON_ItKeyValueIs ///////////////////////////////////////////////////////////////////// -Dqn_Str8 Dqn_JSON_ItKey(Dqn_JSONIt *it) +// NOTE: DN_JSON_ItKeyValueIs ///////////////////////////////////////////////////////////////////// +DN_Str8 DN_JSON_ItKey(DN_JSONIt *it) { - json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); - Dqn_Str8 result = {}; + json_object_element_s *curr = DN_JSON_ItCurrObjElement(it); + DN_Str8 result = {}; if (curr) { - result.data = DQN_CAST(char *)curr->name->string; + result.data = DN_CAST(char *)curr->name->string; result.size = curr->name->string_size; } return result; } -bool Dqn_JSON_ItKeyIs(Dqn_JSONIt *it, Dqn_Str8 key) +bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key) { - json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); - bool result = Dqn_JSON_String8Cmp(curr->name, key); + json_object_element_s *curr = DN_JSON_ItCurrObjElement(it); + bool result = DN_JSON_String8Cmp(curr->name, key); return result; } -json_object_s *Dqn_JSON_ItKeyValueIsObj(Dqn_JSONIt *it, Dqn_Str8 key) +json_object_s *DN_JSON_ItKeyValueIsObj(DN_JSONIt *it, DN_Str8 key) { json_object_s *result = nullptr; - json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); - if (curr && Dqn_JSON_String8Cmp(curr->name, key)) + json_object_element_s *curr = DN_JSON_ItCurrObjElement(it); + if (curr && DN_JSON_String8Cmp(curr->name, key)) result = json_value_as_object(curr->value); return result; } -json_array_s *Dqn_JSON_ItKeyValueIsArray(Dqn_JSONIt *it, Dqn_Str8 key) +json_array_s *DN_JSON_ItKeyValueIsArray(DN_JSONIt *it, DN_Str8 key) { json_array_s *result = nullptr; - json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); - if (curr && Dqn_JSON_String8Cmp(curr->name, key)) + json_object_element_s *curr = DN_JSON_ItCurrObjElement(it); + if (curr && DN_JSON_String8Cmp(curr->name, key)) result = json_value_as_array(curr->value); return result; } -json_string_s *Dqn_JSON_ItKeyValueIsString(Dqn_JSONIt *it, Dqn_Str8 key) +json_string_s *DN_JSON_ItKeyValueIsString(DN_JSONIt *it, DN_Str8 key) { - json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); + json_object_element_s *curr = DN_JSON_ItCurrObjElement(it); json_string_s *result = nullptr; - if (curr && Dqn_JSON_String8Cmp(curr->name, key)) + if (curr && DN_JSON_String8Cmp(curr->name, key)) result = json_value_as_string(curr->value); return result; } -json_number_s *Dqn_JSON_ItKeyValueIsNumber(Dqn_JSONIt *it, Dqn_Str8 key) +json_number_s *DN_JSON_ItKeyValueIsNumber(DN_JSONIt *it, DN_Str8 key) { - json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); + json_object_element_s *curr = DN_JSON_ItCurrObjElement(it); json_number_s *result = nullptr; - if (curr && Dqn_JSON_String8Cmp(curr->name, key)) + if (curr && DN_JSON_String8Cmp(curr->name, key)) result = json_value_as_number(curr->value); return result; } -json_value_s *Dqn_JSON_ItKeyValueIsBool(Dqn_JSONIt *it, Dqn_Str8 key) +json_value_s *DN_JSON_ItKeyValueIsBool(DN_JSONIt *it, DN_Str8 key) { - json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); + json_object_element_s *curr = DN_JSON_ItCurrObjElement(it); json_value_s *result = nullptr; - if (curr && Dqn_JSON_String8Cmp(curr->name, key)) + if (curr && DN_JSON_String8Cmp(curr->name, key)) result = curr->value->type == json_type_true || curr->value->type == json_type_false ? curr->value : nullptr; return result; } -json_value_s *Dqn_JSON_ItKeyValueIsNull(Dqn_JSONIt *it, Dqn_Str8 key) +json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key) { - json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); + json_object_element_s *curr = DN_JSON_ItCurrObjElement(it); json_value_s *result = nullptr; - if (curr && Dqn_JSON_String8Cmp(curr->name, key)) + if (curr && DN_JSON_String8Cmp(curr->name, key)) result = curr->value->type == json_type_null ? curr->value : nullptr; return result; } -// NOTE: Dqn_JSON_ItValueTo //////////////////////////////////////////////////////////////////////// -Dqn_Str8 Dqn_JSON_ItValueToString(Dqn_JSONIt *it) +// NOTE: DN_JSON_ItValueTo //////////////////////////////////////////////////////////////////////// +DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it) { - Dqn_Str8 result = {}; - if (json_string_s *curr = Dqn_JSON_ItValueIsString(it)) - result = Dqn_Str8_Init(curr->string, curr->string_size); + DN_Str8 result = {}; + if (json_string_s *curr = DN_JSON_ItValueIsString(it)) + result = DN_Str8_Init(curr->string, curr->string_size); return result; } -int64_t Dqn_JSON_ItValueToI64(Dqn_JSONIt *it) +int64_t DN_JSON_ItValueToI64(DN_JSONIt *it) { int64_t result = {}; - if (json_number_s *curr = Dqn_JSON_ItValueIsNumber(it)) - result = Dqn_Str8_ToI64(Dqn_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value; + if (json_number_s *curr = DN_JSON_ItValueIsNumber(it)) + result = DN_Str8_ToI64(DN_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value; return result; } -uint64_t Dqn_JSON_ItValueToU64(Dqn_JSONIt *it) +uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it) { uint64_t result = {}; - if (json_number_s *curr = Dqn_JSON_ItValueIsNumber(it)) - result = Dqn_Str8_ToU64(Dqn_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value; + if (json_number_s *curr = DN_JSON_ItValueIsNumber(it)) + result = DN_Str8_ToU64(DN_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value; return result; } -bool Dqn_JSON_ItValueToBool(Dqn_JSONIt *it) +bool DN_JSON_ItValueToBool(DN_JSONIt *it) { bool result = {}; - if (json_value_s *curr = Dqn_JSON_ItValueIsBool(it)) + if (json_value_s *curr = DN_JSON_ItValueIsBool(it)) result = curr->type == json_type_true; return result; } -void Dqn_JSON_ItErrorUnknownKeyValue_(Dqn_JSONIt *it, Dqn_CallSite call_site) +void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site) { if (!it) return; - json_object_element_s const *curr = Dqn_JSON_ItCurrObjElement(it); + json_object_element_s const *curr = DN_JSON_ItCurrObjElement(it); if (!curr) return; size_t value_type_size = 0; - char const *value_type = Dqn_JSON_TypeEnumCString(DQN_CAST(json_type_e)curr->value->type, &value_type_size); + char const *value_type = DN_JSON_TypeEnumCString(DN_CAST(json_type_e)curr->value->type, &value_type_size); json_string_s const *key = curr->name; if (it->flags & json_parse_flags_allow_location_information) { - json_string_ex_s const *info = DQN_CAST(json_string_ex_s const *)key; - Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, + json_string_ex_s const *info = DN_CAST(json_string_ex_s const *)key; + DN_Log_TypeFCallSite(DN_LogType_Warning, call_site, "Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]", info->line_no, info->row_no, - DQN_CAST(int)key->string_size, + DN_CAST(int)key->string_size, key->string, - DQN_CAST(int)value_type_size, + DN_CAST(int)value_type_size, value_type); } else { - Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, + DN_Log_TypeFCallSite(DN_LogType_Warning, call_site, "Unknown key-value pair in object [key=%.*s, value=%.*s]", - DQN_CAST(int)key->string_size, + DN_CAST(int)key->string_size, key->string, - DQN_CAST(int)value_type_size, + DN_CAST(int)value_type_size, value_type); } } diff --git a/dqn_json.h b/dqn_json.h index 4e460f2..a129842 100644 --- a/dqn_json.h +++ b/dqn_json.h @@ -5,85 +5,85 @@ #error Sheredom json.h (github.com/sheredom/json.h) must be included before this file #endif -// NOTE: Dqn_JSON ////////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_JSON ////////////////////////////////////////////////////////////////////////////////// -void *Dqn_JSON_ArenaAllocFunc (void *user_data, size_t count); -char const *Dqn_JSON_TypeEnumCString(json_type_e type, size_t *size); -bool Dqn_JSON_String8Cmp (json_string_s const *lhs, Dqn_Str8 rhs); +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: Dqn_JSON_It ///////////////////////////////////////////////////////////////////////// -enum Dqn_JSONItEntryType +// NOTE: DN_JSON_It ///////////////////////////////////////////////////////////////////////// +enum DN_JSONItEntryType { - Dqn_JSON_ItEntryTypeObjElement, - Dqn_JSON_ItEntryTypeObj, - Dqn_JSON_ItEntryTypeArrayElement, - Dqn_JSON_ItEntryTypeArray, - Dqn_JSON_ItEntryTypeString, - Dqn_JSON_ItEntryTypeNumber, + DN_JSON_ItEntryTypeObjElement, + DN_JSON_ItEntryTypeObj, + DN_JSON_ItEntryTypeArrayElement, + DN_JSON_ItEntryTypeArray, + DN_JSON_ItEntryTypeString, + DN_JSON_ItEntryTypeNumber, }; -struct Dqn_JSONItEntry +struct DN_JSONItEntry { - Dqn_JSONItEntryType type; + DN_JSONItEntryType type; void *value; }; -struct Dqn_JSONIt +struct DN_JSONIt { - Dqn_JSONItEntry stack[128]; + DN_JSONItEntry stack[128]; int stack_count; size_t flags; }; -Dqn_JSONIt Dqn_JSON_LoadFileToIt(Dqn_Arena *arena, Dqn_Str8 json); +DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json); -// NOTE: Dqn_JSON_ItPush/Pop ///////////////////////////////////////////////////////////////// -bool Dqn_JSON_ItPushObjElement (Dqn_JSONIt *it, json_object_element_s *element); -bool Dqn_JSON_ItPushObj (Dqn_JSONIt *it, json_object_s *obj); -bool Dqn_JSON_ItPushArrayElement(Dqn_JSONIt *it, json_array_element_s *element); -bool Dqn_JSON_ItPushArray (Dqn_JSONIt *it, json_value_s *value); -bool Dqn_JSON_ItPushValue (Dqn_JSONIt *it, json_value_s *value); -void Dqn_JSON_ItPop (Dqn_JSONIt *it); +// 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); +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: Dqn_JSON_It tree navigation ///////////////////////////////////////////////////////// -json_value_s *Dqn_JSON_ItPushCurrValue(Dqn_JSONIt *it); -bool Dqn_JSON_ItNext(Dqn_JSONIt *it); +// NOTE: DN_JSON_It tree navigation ///////////////////////////////////////////////////////// +json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it); +bool DN_JSON_ItNext(DN_JSONIt *it); -#define Dqn_JSON_ItPushCurrValueIterateThenPop(it) \ - for(void *DQN_UNIQUE_NAME(ptr) = Dqn_JSON_ItPushCurrValue(it); DQN_UNIQUE_NAME(ptr); Dqn_JSON_ItPop(it), DQN_UNIQUE_NAME(ptr) = nullptr) \ - while (Dqn_JSON_ItNext(it)) +#define DN_JSON_ItPushCurrValueIterateThenPop(it) \ + for(void *DN_UNIQUE_NAME(ptr) = DN_JSON_ItPushCurrValue(it); DN_UNIQUE_NAME(ptr); DN_JSON_ItPop(it), DN_UNIQUE_NAME(ptr) = nullptr) \ + while (DN_JSON_ItNext(it)) -// NOTE: Dqn_JSON_ItCurr ///////////////////////////////////////////////////////////////////// -Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it); -json_value_s *Dqn_JSON_ItCurrValue(Dqn_JSONIt *it); -json_object_element_s *Dqn_JSON_ItCurrObjElement(Dqn_JSONIt *it); +// 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: Dqn_JSON_ItValueIs ////////////////////////////////////////////////////////////////// -json_value_s *Dqn_JSON_ItValueIs(Dqn_JSONIt *it, json_type_e type); -json_object_s *Dqn_JSON_ItValueIsObj(Dqn_JSONIt *it); -json_array_s *Dqn_JSON_ItValueIsArray(Dqn_JSONIt *it); -json_string_s *Dqn_JSON_ItValueIsString(Dqn_JSONIt *it); -json_number_s *Dqn_JSON_ItValueIsNumber(Dqn_JSONIt *it); -json_value_s *Dqn_JSON_ItValueIsBool(Dqn_JSONIt *it); -json_value_s *Dqn_JSON_ItValueIsNull(Dqn_JSONIt *it); +// 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); +json_string_s *DN_JSON_ItValueIsString(DN_JSONIt *it); +json_number_s *DN_JSON_ItValueIsNumber(DN_JSONIt *it); +json_value_s *DN_JSON_ItValueIsBool(DN_JSONIt *it); +json_value_s *DN_JSON_ItValueIsNull(DN_JSONIt *it); -size_t Dqn_JSON_ItValueArraySize(Dqn_JSONIt *it); +size_t DN_JSON_ItValueArraySize(DN_JSONIt *it); -// NOTE: Dqn_JSON_ItKeyValueIs /////////////////////////////////////////////////////////////// -Dqn_Str8 Dqn_JSON_ItKey(Dqn_JSONIt *it); -bool Dqn_JSON_ItKeyIs(Dqn_JSONIt *it, Dqn_Str8 key); -json_object_s *Dqn_JSON_ItKeyValueIsObj(Dqn_JSONIt *it, Dqn_Str8 key); -json_array_s *Dqn_JSON_ItKeyValueIsArray(Dqn_JSONIt *it, Dqn_Str8 key); -json_string_s *Dqn_JSON_ItKeyValueIsString(Dqn_JSONIt *it, Dqn_Str8 key); -json_number_s *Dqn_JSON_ItKeyValueIsNumber(Dqn_JSONIt *it, Dqn_Str8 key); -json_value_s *Dqn_JSON_ItKeyValueIsBool(Dqn_JSONIt *it, Dqn_Str8 key); -json_value_s *Dqn_JSON_ItKeyValueIsNull(Dqn_JSONIt *it, Dqn_Str8 key); +// 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); +json_array_s *DN_JSON_ItKeyValueIsArray(DN_JSONIt *it, DN_Str8 key); +json_string_s *DN_JSON_ItKeyValueIsString(DN_JSONIt *it, DN_Str8 key); +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: Dqn_JSON_ItValueTo ////////////////////////////////////////////////////////////////// -Dqn_Str8 Dqn_JSON_ItValueToString(Dqn_JSONIt *it); -int64_t Dqn_JSON_ItValueToI64(Dqn_JSONIt *it); -uint64_t Dqn_JSON_ItValueToU64(Dqn_JSONIt *it); -bool Dqn_JSON_ItValueToBool(Dqn_JSONIt *it); +// 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); +bool DN_JSON_ItValueToBool(DN_JSONIt *it); -#define Dqn_JSON_ItErrorUnknownKeyValue(it) Dqn_JSON_ItErrorUnknownKeyValue_(it, DQN_CALL_SITE) -void Dqn_JSON_ItErrorUnknownKeyValue_(Dqn_JSONIt *it, Dqn_CallSite call_site); +#define DN_JSON_ItErrorUnknownKeyValue(it) DN_JSON_ItErrorUnknownKeyValue_(it, DN_CALL_SITE) +void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site); diff --git a/dqn_math.cpp b/dqn_math.cpp index 6bda798..bc02eb7 100644 --- a/dqn_math.cpp +++ b/dqn_math.cpp @@ -18,560 +18,560 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -#if !defined(DQN_NO_V2) +#if !defined(DN_NO_V2) // NOTE: [$VEC2] Vector2 /////////////////////////////////////////////////////////////////////////// -// NOTE: Dqn_V2I -DQN_API bool operator!=(Dqn_V2I lhs, Dqn_V2I rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DQN_API bool operator==(Dqn_V2I lhs, Dqn_V2I rhs) +// NOTE: DN_V2I32 +DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) { bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); return result; } -DQN_API bool operator>=(Dqn_V2I lhs, Dqn_V2I rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DQN_API bool operator<=(Dqn_V2I lhs, Dqn_V2I rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DQN_API bool operator<(Dqn_V2I lhs, Dqn_V2I rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DQN_API bool operator>(Dqn_V2I lhs, Dqn_V2I rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DQN_API Dqn_V2I operator-(Dqn_V2I lhs, Dqn_V2I rhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DQN_API Dqn_V2I operator-(Dqn_V2I lhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(-lhs.x, -lhs.y); - return result; -} - -DQN_API Dqn_V2I operator+(Dqn_V2I lhs, Dqn_V2I rhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DQN_API Dqn_V2I operator*(Dqn_V2I lhs, Dqn_V2I rhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DQN_API Dqn_V2I operator*(Dqn_V2I lhs, Dqn_f32 rhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DQN_API Dqn_V2I operator*(Dqn_V2I lhs, int32_t rhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DQN_API Dqn_V2I operator/(Dqn_V2I lhs, Dqn_V2I rhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DQN_API Dqn_V2I operator/(Dqn_V2I lhs, Dqn_f32 rhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DQN_API Dqn_V2I operator/(Dqn_V2I lhs, int32_t rhs) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DQN_API Dqn_V2I &operator*=(Dqn_V2I &lhs, Dqn_V2I rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DQN_API Dqn_V2I &operator*=(Dqn_V2I &lhs, Dqn_f32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DQN_API Dqn_V2I &operator*=(Dqn_V2I &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DQN_API Dqn_V2I &operator/=(Dqn_V2I &lhs, Dqn_V2I rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DQN_API Dqn_V2I &operator/=(Dqn_V2I &lhs, Dqn_f32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DQN_API Dqn_V2I &operator/=(Dqn_V2I &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DQN_API Dqn_V2I &operator-=(Dqn_V2I &lhs, Dqn_V2I rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DQN_API Dqn_V2I &operator+=(Dqn_V2I &lhs, Dqn_V2I rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DQN_API Dqn_V2I Dqn_V2I_Min(Dqn_V2I a, Dqn_V2I b) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(DQN_MIN(a.x, b.x), DQN_MIN(a.y, b.y)); - return result; -} - -DQN_API Dqn_V2I Dqn_V2I_Max(Dqn_V2I a, Dqn_V2I b) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(DQN_MAX(a.x, b.x), DQN_MAX(a.y, b.y)); - return result; -} - -DQN_API Dqn_V2I Dqn_V2I_Abs(Dqn_V2I a) -{ - Dqn_V2I result = Dqn_V2I_InitNx2(DQN_ABS(a.x), DQN_ABS(a.y)); - return result; -} - -// NOTE: Dqn_V2U16 -DQN_API bool operator!=(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API bool operator!=(DN_V2I32 lhs, DN_V2I32 rhs) { bool result = !(lhs == rhs); return result; } -DQN_API bool operator==(Dqn_V2U16 lhs, Dqn_V2U16 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DQN_API bool operator>=(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API bool operator>=(DN_V2I32 lhs, DN_V2I32 rhs) { bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); return result; } -DQN_API bool operator<=(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API bool operator<=(DN_V2I32 lhs, DN_V2I32 rhs) { bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); return result; } -DQN_API bool operator<(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API bool operator<(DN_V2I32 lhs, DN_V2I32 rhs) { bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); return result; } -DQN_API bool operator>(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API bool operator>(DN_V2I32 lhs, DN_V2I32 rhs) { bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); return result; } -DQN_API Dqn_V2U16 operator-(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API DN_V2I32 operator-(DN_V2I32 lhs, DN_V2I32 rhs) { - Dqn_V2U16 result = Dqn_V2U16_InitNx2(lhs.x - rhs.x, lhs.y - rhs.y); + DN_V2I32 result = DN_V2I32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); return result; } -DQN_API Dqn_V2U16 operator+(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API DN_V2I32 operator-(DN_V2I32 lhs) { - Dqn_V2U16 result = Dqn_V2U16_InitNx2(lhs.x + rhs.x, lhs.y + rhs.y); + DN_V2I32 result = DN_V2I32_Init2N(-lhs.x, -lhs.y); return result; } -DQN_API Dqn_V2U16 operator*(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API DN_V2I32 operator+(DN_V2I32 lhs, DN_V2I32 rhs) { - Dqn_V2U16 result = Dqn_V2U16_InitNx2(lhs.x * rhs.x, lhs.y * rhs.y); + DN_V2I32 result = DN_V2I32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); return result; } -DQN_API Dqn_V2U16 operator*(Dqn_V2U16 lhs, Dqn_f32 rhs) +DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_V2I32 rhs) { - Dqn_V2U16 result = Dqn_V2U16_InitNx2(lhs.x * rhs, lhs.y * rhs); + DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); return result; } -DQN_API Dqn_V2U16 operator*(Dqn_V2U16 lhs, int32_t rhs) +DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_F32 rhs) { - Dqn_V2U16 result = Dqn_V2U16_InitNx2(lhs.x * rhs, lhs.y * rhs); + DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); return result; } -DQN_API Dqn_V2U16 operator/(Dqn_V2U16 lhs, Dqn_V2U16 rhs) +DN_API DN_V2I32 operator*(DN_V2I32 lhs, int32_t rhs) { - Dqn_V2U16 result = Dqn_V2U16_InitNx2(lhs.x / rhs.x, lhs.y / rhs.y); + DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); return result; } -DQN_API Dqn_V2U16 operator/(Dqn_V2U16 lhs, Dqn_f32 rhs) +DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_V2I32 rhs) { - Dqn_V2U16 result = Dqn_V2U16_InitNx2(lhs.x / rhs, lhs.y / rhs); + DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); return result; } -DQN_API Dqn_V2U16 operator/(Dqn_V2U16 lhs, int32_t rhs) +DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_F32 rhs) { - Dqn_V2U16 result = Dqn_V2U16_InitNx2(lhs.x / rhs, lhs.y / rhs); + DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); return result; } -DQN_API Dqn_V2U16 &operator*=(Dqn_V2U16 &lhs, Dqn_V2U16 rhs) +DN_API DN_V2I32 operator/(DN_V2I32 lhs, int32_t rhs) +{ + DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); + return result; +} + +DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_V2I32 rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V2U16 &operator*=(Dqn_V2U16 &lhs, Dqn_f32 rhs) +DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_F32 rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V2U16 &operator*=(Dqn_V2U16 &lhs, int32_t rhs) +DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, int32_t rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V2U16 &operator/=(Dqn_V2U16 &lhs, Dqn_V2U16 rhs) +DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_V2I32 rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V2U16 &operator/=(Dqn_V2U16 &lhs, Dqn_f32 rhs) +DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_F32 rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V2U16 &operator/=(Dqn_V2U16 &lhs, int32_t rhs) +DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, int32_t rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V2U16 &operator-=(Dqn_V2U16 &lhs, Dqn_V2U16 rhs) +DN_API DN_V2I32 &operator-=(DN_V2I32 &lhs, DN_V2I32 rhs) { lhs = lhs - rhs; return lhs; } -DQN_API Dqn_V2U16 &operator+=(Dqn_V2U16 &lhs, Dqn_V2U16 rhs) +DN_API DN_V2I32 &operator+=(DN_V2I32 &lhs, DN_V2I32 rhs) { lhs = lhs + rhs; return lhs; } -// NOTE: Dqn_V2 -DQN_API bool operator!=(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API DN_V2I32 DN_V2I32_Min(DN_V2I32 a, DN_V2I32 b) +{ + DN_V2I32 result = DN_V2I32_Init2N(DN_MIN(a.x, b.x), DN_MIN(a.y, b.y)); + return result; +} + +DN_API DN_V2I32 DN_V2I32_Max(DN_V2I32 a, DN_V2I32 b) +{ + DN_V2I32 result = DN_V2I32_Init2N(DN_MAX(a.x, b.x), DN_MAX(a.y, b.y)); + return result; +} + +DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) +{ + DN_V2I32 result = DN_V2I32_Init2N(DN_ABS(a.x), DN_ABS(a.y)); + return result; +} + +// NOTE: DN_V2U16 +DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) { bool result = !(lhs == rhs); return result; } -DQN_API bool operator==(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API bool operator==(DN_V2U16 lhs, DN_V2U16 rhs) { bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); return result; } -DQN_API bool operator>=(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API bool operator>=(DN_V2U16 lhs, DN_V2U16 rhs) { bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); return result; } -DQN_API bool operator<=(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API bool operator<=(DN_V2U16 lhs, DN_V2U16 rhs) { bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); return result; } -DQN_API bool operator<(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API bool operator<(DN_V2U16 lhs, DN_V2U16 rhs) { bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); return result; } -DQN_API bool operator>(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API bool operator>(DN_V2U16 lhs, DN_V2U16 rhs) { bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); return result; } -// NOTE: Dqn_V2 operator- ////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 operator-(Dqn_V2 lhs) +DN_API DN_V2U16 operator-(DN_V2U16 lhs, DN_V2U16 rhs) { - Dqn_V2 result = Dqn_V2_InitNx2(-lhs.x, -lhs.y); + DN_V2U16 result = DN_V2U16_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); return result; } -DQN_API Dqn_V2 operator-(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API DN_V2U16 operator+(DN_V2U16 lhs, DN_V2U16 rhs) { - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x - rhs.x, lhs.y - rhs.y); + DN_V2U16 result = DN_V2U16_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); return result; } -DQN_API Dqn_V2 operator-(Dqn_V2 lhs, Dqn_V2I rhs) +DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_V2U16 rhs) { - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x - rhs.x, lhs.y - rhs.y); + DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); return result; } -DQN_API Dqn_V2 operator-(Dqn_V2 lhs, Dqn_f32 rhs) +DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_F32 rhs) { - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x - rhs, lhs.y - rhs); + DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); return result; } -DQN_API Dqn_V2 operator-(Dqn_V2 lhs, int32_t rhs) +DN_API DN_V2U16 operator*(DN_V2U16 lhs, int32_t rhs) { - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x - rhs, lhs.y - rhs); + DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); return result; } -// NOTE: Dqn_V2 operator+ ////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 operator+(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_V2U16 rhs) { - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x + rhs.x, lhs.y + rhs.y); + DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); return result; } -DQN_API Dqn_V2 operator+(Dqn_V2 lhs, Dqn_V2I rhs) +DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_F32 rhs) { - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x + rhs.x, lhs.y + rhs.y); + DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); return result; } -DQN_API Dqn_V2 operator+(Dqn_V2 lhs, Dqn_f32 rhs) +DN_API DN_V2U16 operator/(DN_V2U16 lhs, int32_t rhs) { - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x + rhs, lhs.y + rhs); + DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); return result; } -DQN_API Dqn_V2 operator+(Dqn_V2 lhs, int32_t rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x + rhs, lhs.y + rhs); - return result; -} - -// NOTE: Dqn_V2 operator* ////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 operator*(Dqn_V2 lhs, Dqn_V2 rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DQN_API Dqn_V2 operator*(Dqn_V2 lhs, Dqn_V2I rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DQN_API Dqn_V2 operator*(Dqn_V2 lhs, Dqn_f32 rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DQN_API Dqn_V2 operator*(Dqn_V2 lhs, int32_t rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x * rhs, lhs.y * rhs); - return result; -} - -// NOTE: Dqn_V2 operator/ ////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 operator/(Dqn_V2 lhs, Dqn_V2 rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DQN_API Dqn_V2 operator/(Dqn_V2 lhs, Dqn_V2I rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DQN_API Dqn_V2 operator/(Dqn_V2 lhs, Dqn_f32 rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DQN_API Dqn_V2 operator/(Dqn_V2 lhs, int32_t rhs) -{ - Dqn_V2 result = Dqn_V2_InitNx2(lhs.x / rhs, lhs.y / rhs); - return result; -} - -// NOTE: Dqn_V2 operator*/ ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 &operator*=(Dqn_V2 &lhs, Dqn_V2 rhs) +DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_V2U16 rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V2 &operator*=(Dqn_V2 &lhs, Dqn_V2I rhs) +DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_F32 rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V2 &operator*=(Dqn_V2 &lhs, Dqn_f32 rhs) +DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, int32_t rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V2 &operator*=(Dqn_V2 &lhs, int32_t rhs) +DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_V2U16 rhs) +{ + lhs = lhs / rhs; + return lhs; +} + +DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_F32 rhs) +{ + lhs = lhs / rhs; + return lhs; +} + +DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, int32_t rhs) +{ + lhs = lhs / rhs; + return lhs; +} + +DN_API DN_V2U16 &operator-=(DN_V2U16 &lhs, DN_V2U16 rhs) +{ + lhs = lhs - rhs; + return lhs; +} + +DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) +{ + lhs = lhs + rhs; + return lhs; +} + +// NOTE: DN_V2 +DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) +{ + bool result = !(lhs == rhs); + return result; +} + +DN_API bool operator==(DN_V2F32 lhs, DN_V2F32 rhs) +{ + bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); + return result; +} + +DN_API bool operator>=(DN_V2F32 lhs, DN_V2F32 rhs) +{ + bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); + return result; +} + +DN_API bool operator<=(DN_V2F32 lhs, DN_V2F32 rhs) +{ + bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); + return result; +} + +DN_API bool operator<(DN_V2F32 lhs, DN_V2F32 rhs) +{ + bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); + return result; +} + +DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) +{ + bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); + return result; +} + +// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// +DN_API DN_V2F32 operator-(DN_V2F32 lhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(-lhs.x, -lhs.y); + return result; +} + +DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2F32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); + return result; +} + +DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2I32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); + return result; +} + +DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_F32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); + return result; +} + +DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); + return result; +} + +// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// +DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); + return result; +} + +DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2I32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); + return result; +} + +DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_F32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); + return result; +} + +DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); + return result; +} + +// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// +DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); + return result; +} + +DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2I32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); + return result; +} + +DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_F32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); + return result; +} + +DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); + return result; +} + +// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// +DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); + return result; +} + +DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2I32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); + return result; +} + +DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_F32 rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); + return result; +} + +DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) +{ + DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); + return result; +} + +// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// +DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs * rhs; return lhs; } -// NOTE: Dqn_V2 operator// ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 &operator/=(Dqn_V2 &lhs, Dqn_V2 rhs) +DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2I32 rhs) +{ + lhs = lhs * rhs; + return lhs; +} + +DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_F32 rhs) +{ + lhs = lhs * rhs; + return lhs; +} + +DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) +{ + lhs = lhs * rhs; + return lhs; +} + +// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// +DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V2 &operator/=(Dqn_V2 &lhs, Dqn_V2I rhs) +DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2I32 rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V2 &operator/=(Dqn_V2 &lhs, Dqn_f32 rhs) +DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_F32 rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V2 &operator/=(Dqn_V2 &lhs, int32_t rhs) +DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) { lhs = lhs / rhs; return lhs; } -// NOTE: Dqn_V2 operator-/ ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 &operator-=(Dqn_V2 &lhs, Dqn_V2 rhs) +// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// +DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs - rhs; return lhs; } -DQN_API Dqn_V2 &operator-=(Dqn_V2 &lhs, Dqn_V2I rhs) +DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2I32 rhs) { lhs = lhs - rhs; return lhs; } -DQN_API Dqn_V2 &operator-=(Dqn_V2 &lhs, Dqn_f32 rhs) +DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_F32 rhs) { lhs = lhs - rhs; return lhs; } -DQN_API Dqn_V2 &operator-=(Dqn_V2 &lhs, int32_t rhs) +DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) { lhs = lhs - rhs; return lhs; } -// NOTE: Dqn_V2 operator+/ ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 &operator+=(Dqn_V2 &lhs, Dqn_V2 rhs) +// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// +DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs + rhs; return lhs; } -DQN_API Dqn_V2 &operator+=(Dqn_V2 &lhs, Dqn_V2I rhs) +DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2I32 rhs) { lhs = lhs + rhs; return lhs; } -DQN_API Dqn_V2 &operator+=(Dqn_V2 &lhs, Dqn_f32 rhs) +DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_F32 rhs) { lhs = lhs + rhs; return lhs; } -DQN_API Dqn_V2 &operator+=(Dqn_V2 &lhs, int32_t rhs) +DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, int32_t rhs) { lhs = lhs + rhs; return lhs; } -DQN_API Dqn_V2 Dqn_V2_Min(Dqn_V2 a, Dqn_V2 b) +DN_API DN_V2F32 DN_V2F32_Min(DN_V2F32 a, DN_V2F32 b) { - Dqn_V2 result = Dqn_V2_InitNx2(DQN_MIN(a.x, b.x), DQN_MIN(a.y, b.y)); + DN_V2F32 result = DN_V2F32_Init2N(DN_MIN(a.x, b.x), DN_MIN(a.y, b.y)); return result; } -DQN_API Dqn_V2 Dqn_V2_Max(Dqn_V2 a, Dqn_V2 b) +DN_API DN_V2F32 DN_V2F32_Max(DN_V2F32 a, DN_V2F32 b) { - Dqn_V2 result = Dqn_V2_InitNx2(DQN_MAX(a.x, b.x), DQN_MAX(a.y, b.y)); + DN_V2F32 result = DN_V2F32_Init2N(DN_MAX(a.x, b.x), DN_MAX(a.y, b.y)); return result; } -DQN_API Dqn_V2 Dqn_V2_Abs(Dqn_V2 a) +DN_API DN_V2F32 DN_V2F32_Abs(DN_V2F32 a) { - Dqn_V2 result = Dqn_V2_InitNx2(DQN_ABS(a.x), DQN_ABS(a.y)); + DN_V2F32 result = DN_V2F32_Init2N(DN_ABS(a.x), DN_ABS(a.y)); return result; } -DQN_API Dqn_f32 Dqn_V2_Dot(Dqn_V2 a, Dqn_V2 b) +DN_API DN_F32 DN_V2F32_Dot(DN_V2F32 a, DN_V2F32 b) { // NOTE: Scalar projection of B onto A ///////////////////////////////////////////////////////// // @@ -614,50 +614,50 @@ DQN_API Dqn_f32 Dqn_V2_Dot(Dqn_V2 a, Dqn_V2 b) // // vector_projection = a * signed_distance = a * dot_product(a, b) - Dqn_f32 result = (a.x * b.x) + (a.y * b.y); + DN_F32 result = (a.x * b.x) + (a.y * b.y); return result; } -DQN_API Dqn_f32 Dqn_V2_LengthSq_V2x2(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API DN_F32 DN_V2F32_LengthSq_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) { // NOTE: Pythagoras's theorem (a^2 + b^2 = c^2) without the square root - Dqn_f32 a = rhs.x - lhs.x; - Dqn_f32 b = rhs.y - lhs.y; - Dqn_f32 c_squared = DQN_SQUARED(a) + DQN_SQUARED(b); - Dqn_f32 result = c_squared; + DN_F32 a = rhs.x - lhs.x; + DN_F32 b = rhs.y - lhs.y; + DN_F32 c_squared = DN_SQUARED(a) + DN_SQUARED(b); + DN_F32 result = c_squared; return result; } -DQN_API Dqn_f32 Dqn_V2_Length_V2x2(Dqn_V2 lhs, Dqn_V2 rhs) +DN_API DN_F32 DN_V2F32_Length_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) { - Dqn_f32 result_squared = Dqn_V2_LengthSq_V2x2(lhs, rhs); - Dqn_f32 result = DQN_SQRTF(result_squared); + DN_F32 result_squared = DN_V2F32_LengthSq_V2x2(lhs, rhs); + DN_F32 result = DN_SQRTF(result_squared); return result; } -DQN_API Dqn_f32 Dqn_V2_LengthSq(Dqn_V2 lhs) +DN_API DN_F32 DN_V2F32_LengthSq(DN_V2F32 lhs) { // NOTE: Pythagoras's theorem without the square root - Dqn_f32 c_squared = DQN_SQUARED(lhs.x) + DQN_SQUARED(lhs.y); - Dqn_f32 result = c_squared; + DN_F32 c_squared = DN_SQUARED(lhs.x) + DN_SQUARED(lhs.y); + DN_F32 result = c_squared; return result; } -DQN_API Dqn_f32 Dqn_V2_Length(Dqn_V2 lhs) +DN_API DN_F32 DN_V2F32_Length(DN_V2F32 lhs) { - Dqn_f32 c_squared = Dqn_V2_LengthSq(lhs); - Dqn_f32 result = DQN_SQRTF(c_squared); + DN_F32 c_squared = DN_V2F32_LengthSq(lhs); + DN_F32 result = DN_SQRTF(c_squared); return result; } -DQN_API Dqn_V2 Dqn_V2_Normalise(Dqn_V2 a) +DN_API DN_V2F32 DN_V2F32_Normalise(DN_V2F32 a) { - Dqn_f32 length = Dqn_V2_Length(a); - Dqn_V2 result = a / length; + DN_F32 length = DN_V2F32_Length(a); + DN_V2F32 result = a / length; return result; } -DQN_API Dqn_V2 Dqn_V2_Perpendicular(Dqn_V2 a) +DN_API DN_V2F32 DN_V2F32_Perpendicular(DN_V2F32 a) { // NOTE: Matrix form of a 2D vector can be defined as // @@ -675,309 +675,309 @@ DQN_API Dqn_V2 Dqn_V2_Perpendicular(Dqn_V2 a) // x' = -y // y' = +x - Dqn_V2 result = Dqn_V2_InitNx2(-a.y, a.x); + DN_V2F32 result = DN_V2F32_Init2N(-a.y, a.x); return result; } -DQN_API Dqn_V2 Dqn_V2_Reflect(Dqn_V2 in, Dqn_V2 surface) +DN_API DN_V2F32 DN_V2F32_Reflect(DN_V2F32 in, DN_V2F32 surface) { - Dqn_V2 normal = Dqn_V2_Perpendicular(surface); - Dqn_V2 normal_norm = Dqn_V2_Normalise(normal); - Dqn_f32 signed_dist = Dqn_V2_Dot(in, normal_norm); - Dqn_V2 result = Dqn_V2_InitNx2(in.x, in.y + (-signed_dist * 2.f)); + DN_V2F32 normal = DN_V2F32_Perpendicular(surface); + DN_V2F32 normal_norm = DN_V2F32_Normalise(normal); + DN_F32 signed_dist = DN_V2F32_Dot(in, normal_norm); + DN_V2F32 result = DN_V2F32_Init2N(in.x, in.y + (-signed_dist * 2.f)); return result; } -DQN_API Dqn_f32 Dqn_V2_Area(Dqn_V2 a) +DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) { - Dqn_f32 result = a.w * a.h; + DN_F32 result = a.w * a.h; return result; } -#endif // !defined(DQN_NO_V2) +#endif // !defined(DN_NO_V2) -#if !defined(DQN_NO_V3) +#if !defined(DN_NO_V3) // NOTE: [$VEC3] Vector3 /////////////////////////////////////////////////////////////////////////// -DQN_API bool operator!=(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) { bool result = !(lhs == rhs); return result; } -DQN_API bool operator==(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API bool operator==(DN_V3F32 lhs, DN_V3F32 rhs) { bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z); return result; } -DQN_API bool operator>=(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API bool operator>=(DN_V3F32 lhs, DN_V3F32 rhs) { bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z); return result; } -DQN_API bool operator<=(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API bool operator<=(DN_V3F32 lhs, DN_V3F32 rhs) { bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z); return result; } -DQN_API bool operator< (Dqn_V3 lhs, Dqn_V3 rhs) +DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs) { bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z); return result; } -DQN_API bool operator>(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API bool operator>(DN_V3F32 lhs, DN_V3F32 rhs) { bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z); return result; } -DQN_API Dqn_V3 operator-(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API DN_V3F32 operator-(DN_V3F32 lhs, DN_V3F32 rhs) { - Dqn_V3 result = Dqn_V3_InitNx3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); + DN_V3F32 result = DN_V3F32_Init3F32(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); return result; } -DQN_API Dqn_V3 operator-(Dqn_V3 lhs) +DN_API DN_V3F32 operator-(DN_V3F32 lhs) { - Dqn_V3 result = Dqn_V3_InitNx3(-lhs.x, -lhs.y, -lhs.z); + DN_V3F32 result = DN_V3F32_Init3F32(-lhs.x, -lhs.y, -lhs.z); return result; } -DQN_API Dqn_V3 operator+(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API DN_V3F32 operator+(DN_V3F32 lhs, DN_V3F32 rhs) { - Dqn_V3 result = Dqn_V3_InitNx3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); + DN_V3F32 result = DN_V3F32_Init3F32(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); return result; } -DQN_API Dqn_V3 operator*(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_V3F32 rhs) { - Dqn_V3 result = Dqn_V3_InitNx3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); + DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); return result; } -DQN_API Dqn_V3 operator*(Dqn_V3 lhs, Dqn_f32 rhs) +DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_F32 rhs) { - Dqn_V3 result = Dqn_V3_InitNx3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); + DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); return result; } -DQN_API Dqn_V3 operator*(Dqn_V3 lhs, int32_t rhs) +DN_API DN_V3F32 operator*(DN_V3F32 lhs, int32_t rhs) { - Dqn_V3 result = Dqn_V3_InitNx3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); + DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); return result; } -DQN_API Dqn_V3 operator/(Dqn_V3 lhs, Dqn_V3 rhs) +DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_V3F32 rhs) { - Dqn_V3 result = Dqn_V3_InitNx3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); + DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); return result; } -DQN_API Dqn_V3 operator/(Dqn_V3 lhs, Dqn_f32 rhs) +DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_F32 rhs) { - Dqn_V3 result = Dqn_V3_InitNx3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); + DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); return result; } -DQN_API Dqn_V3 operator/(Dqn_V3 lhs, int32_t rhs) +DN_API DN_V3F32 operator/(DN_V3F32 lhs, int32_t rhs) { - Dqn_V3 result = Dqn_V3_InitNx3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); + DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); return result; } -DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, Dqn_V3 rhs) +DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_V3F32 rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, Dqn_f32 rhs) +DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_F32 rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, int32_t rhs) +DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, int32_t rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, Dqn_V3 rhs) +DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_V3F32 rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, Dqn_f32 rhs) +DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_F32 rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, int32_t rhs) +DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, int32_t rhs) { lhs = lhs / rhs; return lhs; } -DQN_API Dqn_V3 &operator-=(Dqn_V3 &lhs, Dqn_V3 rhs) +DN_API DN_V3F32 &operator-=(DN_V3F32 &lhs, DN_V3F32 rhs) { lhs = lhs - rhs; return lhs; } -DQN_API Dqn_V3 &operator+=(Dqn_V3 &lhs, Dqn_V3 rhs) +DN_API DN_V3F32 &operator+=(DN_V3F32 &lhs, DN_V3F32 rhs) { lhs = lhs + rhs; return lhs; } -DQN_API Dqn_f32 Dqn_V3_LengthSq(Dqn_V3 a) +DN_API DN_F32 DN_V3_LengthSq(DN_V3F32 a) { - Dqn_f32 result = DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z); + DN_F32 result = DN_SQUARED(a.x) + DN_SQUARED(a.y) + DN_SQUARED(a.z); return result; } -DQN_API Dqn_f32 Dqn_V3_Length(Dqn_V3 a) +DN_API DN_F32 DN_V3_Length(DN_V3F32 a) { - Dqn_f32 length_sq = DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z); - Dqn_f32 result = DQN_SQRTF(length_sq); + DN_F32 length_sq = DN_SQUARED(a.x) + DN_SQUARED(a.y) + DN_SQUARED(a.z); + DN_F32 result = DN_SQRTF(length_sq); return result; } -DQN_API Dqn_V3 Dqn_V3_Normalise(Dqn_V3 a) +DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) { - Dqn_f32 length = Dqn_V3_Length(a); - Dqn_V3 result = a / length; + DN_F32 length = DN_V3_Length(a); + DN_V3F32 result = a / length; return result; } -#endif // !defined(DQN_NO_V3) +#endif // !defined(DN_NO_V3) -#if !defined(DQN_NO_V4) +#if !defined(DN_NO_V4) // NOTE: [$VEC4] Vector4 /////////////////////////////////////////////////////////////////////////// -DQN_API bool operator!=(Dqn_V4 lhs, Dqn_V4 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DQN_API bool operator==(Dqn_V4 lhs, Dqn_V4 rhs) +DN_API bool operator==(DN_V4F32 lhs, DN_V4F32 rhs) { bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.w == rhs.w); return result; } -DQN_API bool operator>=(Dqn_V4 lhs, Dqn_V4 rhs) +DN_API bool operator!=(DN_V4F32 lhs, DN_V4F32 rhs) +{ + bool result = !(lhs == rhs); + return result; +} + +DN_API bool operator>=(DN_V4F32 lhs, DN_V4F32 rhs) { bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z) && (lhs.w >= rhs.w); return result; } -DQN_API bool operator<=(Dqn_V4 lhs, Dqn_V4 rhs) +DN_API bool operator<=(DN_V4F32 lhs, DN_V4F32 rhs) { bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z) && (lhs.w <= rhs.w); return result; } -DQN_API bool operator< (Dqn_V4 lhs, Dqn_V4 rhs) +DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs) { bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z) && (lhs.w < rhs.w); return result; } -DQN_API bool operator>(Dqn_V4 lhs, Dqn_V4 rhs) +DN_API bool operator>(DN_V4F32 lhs, DN_V4F32 rhs) { bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z) && (lhs.w > rhs.w); return result; } -DQN_API Dqn_V4 operator-(Dqn_V4 lhs, Dqn_V4 rhs) +DN_API DN_V4F32 operator-(DN_V4F32 lhs, DN_V4F32 rhs) { - Dqn_V4 result = Dqn_V4_InitNx4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); + DN_V4F32 result = DN_V4F32_Init4N(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); return result; } -DQN_API Dqn_V4 operator-(Dqn_V4 lhs) +DN_API DN_V4F32 operator-(DN_V4F32 lhs) { - Dqn_V4 result = Dqn_V4_InitNx4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); + DN_V4F32 result = DN_V4F32_Init4N(-lhs.x, -lhs.y, -lhs.z, -lhs.w); return result; } -DQN_API Dqn_V4 operator+(Dqn_V4 lhs, Dqn_V4 rhs) +DN_API DN_V4F32 operator+(DN_V4F32 lhs, DN_V4F32 rhs) { - Dqn_V4 result = Dqn_V4_InitNx4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); + DN_V4F32 result = DN_V4F32_Init4N(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); return result; } -DQN_API Dqn_V4 operator* (Dqn_V4 lhs, Dqn_V4 rhs) +DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs) { - Dqn_V4 result = Dqn_V4_InitNx4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); + DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); return result; } -DQN_API Dqn_V4 operator*(Dqn_V4 lhs, Dqn_f32 rhs) +DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_F32 rhs) { - Dqn_V4 result = Dqn_V4_InitNx4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); + DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); return result; } -DQN_API Dqn_V4 operator*(Dqn_V4 lhs, int32_t rhs) +DN_API DN_V4F32 operator*(DN_V4F32 lhs, int32_t rhs) { - Dqn_V4 result = Dqn_V4_InitNx4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); + DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); return result; } -DQN_API Dqn_V4 operator/(Dqn_V4 lhs, Dqn_f32 rhs) +DN_API DN_V4F32 operator/(DN_V4F32 lhs, DN_F32 rhs) { - Dqn_V4 result = Dqn_V4_InitNx4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); + DN_V4F32 result = DN_V4F32_Init4N(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); return result; } -DQN_API Dqn_V4 &operator*=(Dqn_V4 &lhs, Dqn_V4 rhs) +DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_V4F32 rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V4 &operator*=(Dqn_V4 &lhs, Dqn_f32 rhs) +DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_F32 rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V4 &operator*=(Dqn_V4 &lhs, int32_t rhs) +DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, int32_t rhs) { lhs = lhs * rhs; return lhs; } -DQN_API Dqn_V4 &operator-=(Dqn_V4 &lhs, Dqn_V4 rhs) +DN_API DN_V4F32 &operator-=(DN_V4F32 &lhs, DN_V4F32 rhs) { lhs = lhs - rhs; return lhs; } -DQN_API Dqn_V4 &operator+=(Dqn_V4 &lhs, Dqn_V4 rhs) +DN_API DN_V4F32 &operator+=(DN_V4F32 &lhs, DN_V4F32 rhs) { lhs = lhs + rhs; return lhs; } -DQN_API Dqn_f32 Dqn_V4Dot(Dqn_V4 a, Dqn_V4 b) +DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) { - Dqn_f32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); + DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); return result; } -#endif // !defined(DQN_NO_V4) +#endif // !defined(DN_NO_V4) -#if !defined(DQN_NO_M4) -// NOTE: [$MAT4] Dqn_M4 //////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_M4 Dqn_M4_Identity() +#if !defined(DN_NO_M4) +// NOTE: [$MAT4] DN_M4 //////////////////////////////////////////////////////////////////////////// +DN_API DN_M4 DN_M4_Identity() { - Dqn_M4 result = + DN_M4 result = {{ {1, 0, 0, 0}, {0, 1, 0, 0}, @@ -988,9 +988,9 @@ DQN_API Dqn_M4 Dqn_M4_Identity() return result; } -DQN_API Dqn_M4 Dqn_M4_ScaleF(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z) +DN_API DN_M4 DN_M4_ScaleF(DN_F32 x, DN_F32 y, DN_F32 z) { - Dqn_M4 result = + DN_M4 result = {{ {x, 0, 0, 0}, {0, y, 0, 0}, @@ -1001,9 +1001,9 @@ DQN_API Dqn_M4 Dqn_M4_ScaleF(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z) return result; } -DQN_API Dqn_M4 Dqn_M4_Scale(Dqn_V3 xyz) +DN_API DN_M4 DN_M4_Scale(DN_V3F32 xyz) { - Dqn_M4 result = + DN_M4 result = {{ {xyz.x, 0, 0, 0}, {0, xyz.y, 0, 0}, @@ -1014,9 +1014,9 @@ DQN_API Dqn_M4 Dqn_M4_Scale(Dqn_V3 xyz) return result; } -DQN_API Dqn_M4 Dqn_M4_TranslateF(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z) +DN_API DN_M4 DN_M4_TranslateF(DN_F32 x, DN_F32 y, DN_F32 z) { - Dqn_M4 result = + DN_M4 result = {{ {1, 0, 0, 0}, {0, 1, 0, 0}, @@ -1027,9 +1027,9 @@ DQN_API Dqn_M4 Dqn_M4_TranslateF(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z) return result; } -DQN_API Dqn_M4 Dqn_M4_Translate(Dqn_V3 xyz) +DN_API DN_M4 DN_M4_Translate(DN_V3F32 xyz) { - Dqn_M4 result = + DN_M4 result = {{ {1, 0, 0, 0}, {0, 1, 0, 0}, @@ -1040,33 +1040,33 @@ DQN_API Dqn_M4 Dqn_M4_Translate(Dqn_V3 xyz) return result; } -DQN_API Dqn_M4 Dqn_M4_Transpose(Dqn_M4 mat) +DN_API DN_M4 DN_M4_Transpose(DN_M4 mat) { - Dqn_M4 result = {}; + DN_M4 result = {}; for (int col = 0; col < 4; col++) for (int row = 0; row < 4; row++) result.columns[col][row] = mat.columns[row][col]; return result; } -DQN_API Dqn_M4 Dqn_M4_Rotate(Dqn_V3 axis01, Dqn_f32 radians) +DN_API DN_M4 DN_M4_Rotate(DN_V3F32 axis01, DN_F32 radians) { - DQN_ASSERTF(DQN_ABS(Dqn_V3_Length(axis01) - 1.f) <= 0.01f, + DN_ASSERTF(DN_ABS(DN_V3_Length(axis01) - 1.f) <= 0.01f, "Rotation axis must be normalised, length = %f", - Dqn_V3_Length(axis01)); + DN_V3_Length(axis01)); - Dqn_f32 sin = DQN_SINF(radians); - Dqn_f32 cos = DQN_COSF(radians); - Dqn_f32 one_minus_cos = 1.f - cos; + DN_F32 sin = DN_SINF(radians); + DN_F32 cos = DN_COSF(radians); + DN_F32 one_minus_cos = 1.f - cos; - Dqn_f32 x = axis01.x; - Dqn_f32 y = axis01.y; - Dqn_f32 z = axis01.z; - Dqn_f32 x2 = DQN_SQUARED(x); - Dqn_f32 y2 = DQN_SQUARED(y); - Dqn_f32 z2 = DQN_SQUARED(z); + DN_F32 x = axis01.x; + DN_F32 y = axis01.y; + DN_F32 z = axis01.z; + DN_F32 x2 = DN_SQUARED(x); + DN_F32 y2 = DN_SQUARED(y); + DN_F32 z2 = DN_SQUARED(z); - Dqn_M4 result = + DN_M4 result = {{ {cos + x2*one_minus_cos, y*x*one_minus_cos + z*sin, z*x*one_minus_cos - y*sin, 0}, // Col 1 {x*y*one_minus_cos - z*sin, cos + y2*one_minus_cos, z*y*one_minus_cos + x*sin, 0}, // Col 2 @@ -1077,7 +1077,7 @@ DQN_API Dqn_M4 Dqn_M4_Rotate(Dqn_V3 axis01, Dqn_f32 radians) return result; } -DQN_API Dqn_M4 Dqn_M4_Orthographic(Dqn_f32 left, Dqn_f32 right, Dqn_f32 bottom, Dqn_f32 top, Dqn_f32 z_near, Dqn_f32 z_far) +DN_API DN_M4 DN_M4_Orthographic(DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far) { // NOTE: Here is the matrix in column major for readability. Below it's // transposed due to how you have to declare column major matrices in C/C++. @@ -1087,7 +1087,7 @@ DQN_API Dqn_M4 Dqn_M4_Orthographic(Dqn_f32 left, Dqn_f32 right, Dqn_f32 bottom, // [0, 0, -2/f-n, -1*(f+n)/(f-n)] // [0, 0, 0, 1 ] - Dqn_M4 result = + DN_M4 result = {{ {2.f / (right - left), 0.f, 0.f, 0.f}, {0.f, 2.f / (top - bottom), 0.f, 0.f}, @@ -1098,10 +1098,10 @@ DQN_API Dqn_M4 Dqn_M4_Orthographic(Dqn_f32 left, Dqn_f32 right, Dqn_f32 bottom, return result; } -DQN_API Dqn_M4 Dqn_M4_Perspective(Dqn_f32 fov /*radians*/, Dqn_f32 aspect, Dqn_f32 z_near, Dqn_f32 z_far) +DN_API DN_M4 DN_M4_Perspective(DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far) { - Dqn_f32 tan_fov = DQN_TANF(fov / 2.f); - Dqn_M4 result = + DN_F32 tan_fov = DN_TANF(fov / 2.f); + DN_M4 result = {{ {1.f / (aspect * tan_fov), 0.f, 0.f, 0.f}, {0, 1.f / tan_fov, 0.f, 0.f}, @@ -1112,9 +1112,9 @@ DQN_API Dqn_M4 Dqn_M4_Perspective(Dqn_f32 fov /*radians*/, Dqn_f32 aspect, Dqn_f return result; } -DQN_API Dqn_M4 Dqn_M4_Add(Dqn_M4 lhs, Dqn_M4 rhs) +DN_API DN_M4 DN_M4_Add(DN_M4 lhs, DN_M4 rhs) { - Dqn_M4 result; + DN_M4 result; for (int col = 0; col < 4; col++) { for (int it = 0; it < 4; it++) @@ -1123,9 +1123,9 @@ DQN_API Dqn_M4 Dqn_M4_Add(Dqn_M4 lhs, Dqn_M4 rhs) return result; } -DQN_API Dqn_M4 Dqn_M4_Sub(Dqn_M4 lhs, Dqn_M4 rhs) +DN_API DN_M4 DN_M4_Sub(DN_M4 lhs, DN_M4 rhs) { - Dqn_M4 result; + DN_M4 result; for (int col = 0; col < 4; col++) { for (int it = 0; it < 4; it++) @@ -1134,14 +1134,14 @@ DQN_API Dqn_M4 Dqn_M4_Sub(Dqn_M4 lhs, Dqn_M4 rhs) return result; } -DQN_API Dqn_M4 Dqn_M4_Mul(Dqn_M4 lhs, Dqn_M4 rhs) +DN_API DN_M4 DN_M4_Mul(DN_M4 lhs, DN_M4 rhs) { - Dqn_M4 result; + DN_M4 result; for (int col = 0; col < 4; col++) { for (int row = 0; row < 4; row++) { - Dqn_f32 sum = 0; + DN_F32 sum = 0; for (int f32_it = 0; f32_it < 4; f32_it++) sum += lhs.columns[f32_it][row] * rhs.columns[col][f32_it]; @@ -1151,9 +1151,9 @@ DQN_API Dqn_M4 Dqn_M4_Mul(Dqn_M4 lhs, Dqn_M4 rhs) return result; } -DQN_API Dqn_M4 Dqn_M4_Div(Dqn_M4 lhs, Dqn_M4 rhs) +DN_API DN_M4 DN_M4_Div(DN_M4 lhs, DN_M4 rhs) { - Dqn_M4 result; + DN_M4 result; for (int col = 0; col < 4; col++) { for (int it = 0; it < 4; it++) @@ -1162,9 +1162,9 @@ DQN_API Dqn_M4 Dqn_M4_Div(Dqn_M4 lhs, Dqn_M4 rhs) return result; } -DQN_API Dqn_M4 Dqn_M4_AddF(Dqn_M4 lhs, Dqn_f32 rhs) +DN_API DN_M4 DN_M4_AddF(DN_M4 lhs, DN_F32 rhs) { - Dqn_M4 result; + DN_M4 result; for (int col = 0; col < 4; col++) { for (int it = 0; it < 4; it++) @@ -1173,9 +1173,9 @@ DQN_API Dqn_M4 Dqn_M4_AddF(Dqn_M4 lhs, Dqn_f32 rhs) return result; } -DQN_API Dqn_M4 Dqn_M4_SubF(Dqn_M4 lhs, Dqn_f32 rhs) +DN_API DN_M4 DN_M4_SubF(DN_M4 lhs, DN_F32 rhs) { - Dqn_M4 result; + DN_M4 result; for (int col = 0; col < 4; col++) { for (int it = 0; it < 4; it++) @@ -1184,9 +1184,9 @@ DQN_API Dqn_M4 Dqn_M4_SubF(Dqn_M4 lhs, Dqn_f32 rhs) return result; } -DQN_API Dqn_M4 Dqn_M4_MulF(Dqn_M4 lhs, Dqn_f32 rhs) +DN_API DN_M4 DN_M4_MulF(DN_M4 lhs, DN_F32 rhs) { - Dqn_M4 result; + DN_M4 result; for (int col = 0; col < 4; col++) { for (int it = 0; it < 4; it++) @@ -1195,9 +1195,9 @@ DQN_API Dqn_M4 Dqn_M4_MulF(Dqn_M4 lhs, Dqn_f32 rhs) return result; } -DQN_API Dqn_M4 Dqn_M4_DivF(Dqn_M4 lhs, Dqn_f32 rhs) +DN_API DN_M4 DN_M4_DivF(DN_M4 lhs, DN_F32 rhs) { - Dqn_M4 result; + DN_M4 result; for (int col = 0; col < 4; col++) { for (int it = 0; it < 4; it++) @@ -1206,74 +1206,74 @@ DQN_API Dqn_M4 Dqn_M4_DivF(Dqn_M4 lhs, Dqn_f32 rhs) return result; } -#if !defined(DQN_NO_FSTR8) -DQN_API Dqn_FStr8<256> Dqn_M4_ColumnMajorString(Dqn_M4 mat) +#if !defined(DN_NO_FSTR8) +DN_API DN_FStr8<256> DN_M4_ColumnMajorString(DN_M4 mat) { - Dqn_FStr8<256> result = {}; + DN_FStr8<256> result = {}; for (int row = 0; row < 4; row++) { for (int it = 0; it < 4; it++) { - if (it == 0) Dqn_FStr8_Add(&result, DQN_STR8("|")); - Dqn_FStr8_AddF(&result, "%.5f", mat.columns[it][row]); - if (it != 3) Dqn_FStr8_Add(&result, DQN_STR8(", ")); - else Dqn_FStr8_Add(&result, DQN_STR8("|\n")); + if (it == 0) DN_FStr8_Add(&result, DN_STR8("|")); + DN_FStr8_AddF(&result, "%.5f", mat.columns[it][row]); + if (it != 3) DN_FStr8_Add(&result, DN_STR8(", ")); + else DN_FStr8_Add(&result, DN_STR8("|\n")); } } return result; } #endif -#endif // !defined(DQN_M4) +#endif // !defined(DN_M4) -// NOTE: [$M2x3] Dqn_M2x3 ////////////////////////////////////////////////////////////////////////// -DQN_API bool operator==(Dqn_M2x3 const &lhs, Dqn_M2x3 const &rhs) +// NOTE: [$M2x3] DN_M2x3 ////////////////////////////////////////////////////////////////////////// +DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) { - bool result = DQN_MEMCMP(lhs.e, rhs.e, sizeof(lhs.e[0]) * DQN_ARRAY_UCOUNT(lhs.e)) == 0; + bool result = DN_MEMCMP(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ARRAY_UCOUNT(lhs.e)) == 0; return result; } -DQN_API bool operator!=(Dqn_M2x3 const &lhs, Dqn_M2x3 const &rhs) +DN_API bool operator!=(DN_M2x3 const &lhs, DN_M2x3 const &rhs) { bool result = !(lhs == rhs); return result; } -DQN_API Dqn_M2x3 Dqn_M2x3_Identity() +DN_API DN_M2x3 DN_M2x3_Identity() { - Dqn_M2x3 result = {{ + DN_M2x3 result = {{ 1, 0, 0, 0, 1, 0, }}; return result; } -DQN_API Dqn_M2x3 Dqn_M2x3_Translate(Dqn_V2 offset) +DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset) { - Dqn_M2x3 result = {{ + DN_M2x3 result = {{ 1, 0, offset.x, 0, 1, offset.y, }}; return result; } -DQN_API Dqn_M2x3 Dqn_M2x3_Scale(Dqn_V2 scale) +DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) { - Dqn_M2x3 result = {{ + DN_M2x3 result = {{ scale.x, 0, 0, 0, scale.y, 0, }}; return result; } -DQN_API Dqn_M2x3 Dqn_M2x3_Rotate(Dqn_f32 radians) +DN_API DN_M2x3 DN_M2x3_Rotate(DN_F32 radians) { - Dqn_M2x3 result = {{ - DQN_COSF(radians), DQN_SINF(radians), 0, - -DQN_SINF(radians), DQN_COSF(radians), 0, + DN_M2x3 result = {{ + DN_COSF(radians), DN_SINF(radians), 0, + -DN_SINF(radians), DN_COSF(radians), 0, }}; return result; } -DQN_API Dqn_M2x3 Dqn_M2x3_Mul(Dqn_M2x3 m1, Dqn_M2x3 m2) +DN_API DN_M2x3 DN_M2x3_Mul(DN_M2x3 m1, DN_M2x3 m2) { // NOTE: Ordinarily you can't multiply M2x3 with M2x3 because column count // (3) != row count (2). We pretend we have two 3x3 matrices with the last @@ -1283,7 +1283,7 @@ DQN_API Dqn_M2x3 Dqn_M2x3_Mul(Dqn_M2x3 m1, Dqn_M2x3 m2) // | (3)d (4)e (5)f | x | (3)j (4)k (5)l | // | (6)0 (7)0 (8)1 | | (6)0 (7)0 (8)1 | - Dqn_M2x3 result = {{ + DN_M2x3 result = {{ m1.e[0]*m2.e[0] + m1.e[1]*m2.e[3], // a*g + b*j + c*0[omitted], m1.e[0]*m2.e[1] + m1.e[1]*m2.e[4], // a*h + b*k + c*0[omitted], m1.e[0]*m2.e[2] + m1.e[1]*m2.e[5] + m1.e[2], // a*i + b*l + c*1, @@ -1296,7 +1296,7 @@ DQN_API Dqn_M2x3 Dqn_M2x3_Mul(Dqn_M2x3 m1, Dqn_M2x3 m2) return result; } -DQN_API Dqn_V2 Dqn_M2x3_Mul2F32(Dqn_M2x3 m1, Dqn_f32 x, Dqn_f32 y) +DN_API DN_V2F32 DN_M2x3_Mul2F32(DN_M2x3 m1, DN_F32 x, DN_F32 y) { // NOTE: Ordinarily you can't multiply M2x3 with V2 because column count (3) // != row count (2). We pretend we have a V3 with `z` set to `1`. @@ -1305,227 +1305,227 @@ DQN_API Dqn_V2 Dqn_M2x3_Mul2F32(Dqn_M2x3 m1, Dqn_f32 x, Dqn_f32 y) // | (3)d (4)e (5)f | x | y | // | 1 | - Dqn_V2 result = {{ + DN_V2F32 result = {{ m1.e[0]*x + m1.e[1]*y + m1.e[2], // a*x + b*y + c*1 m1.e[3]*x + m1.e[4]*y + m1.e[5], // d*x + e*y + f*1 }}; return result; } -DQN_API Dqn_V2 Dqn_M2x3_MulV2(Dqn_M2x3 m1, Dqn_V2 v2) +DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) { - Dqn_V2 result = Dqn_M2x3_Mul2F32(m1, v2.x, v2.y); + DN_V2F32 result = DN_M2x3_Mul2F32(m1, v2.x, v2.y); return result; } -#if !defined(DQN_NO_RECT) -// NOTE: [$RECT] Dqn_Rect ////////////////////////////////////////////////////////////////////////// -DQN_API bool operator==(const Dqn_Rect& lhs, const Dqn_Rect& rhs) +#if !defined(DN_NO_RECT) +// NOTE: [$RECT] DN_Rect ////////////////////////////////////////////////////////////////////////// +DN_API bool operator==(const DN_Rect& lhs, const DN_Rect& rhs) { bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); return result; } -DQN_API Dqn_V2 Dqn_Rect_Center(Dqn_Rect rect) +DN_API DN_V2F32 DN_Rect_Center(DN_Rect rect) { - Dqn_V2 result = rect.pos + (rect.size * .5f); + DN_V2F32 result = rect.pos + (rect.size * .5f); return result; } -DQN_API bool Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p) +DN_API bool DN_Rect_ContainsPoint(DN_Rect rect, DN_V2F32 p) { - Dqn_V2 min = rect.pos; - Dqn_V2 max = rect.pos + rect.size; + DN_V2F32 min = rect.pos; + DN_V2F32 max = rect.pos + rect.size; bool result = (p.x >= min.x && p.x <= max.x && p.y >= min.y && p.y <= max.y); return result; } -DQN_API bool Dqn_Rect_ContainsRect(Dqn_Rect a, Dqn_Rect b) +DN_API bool DN_Rect_ContainsRect(DN_Rect a, DN_Rect b) { - Dqn_V2 a_min = a.pos; - Dqn_V2 a_max = a.pos + a.size; - Dqn_V2 b_min = b.pos; - Dqn_V2 b_max = b.pos + b.size; + DN_V2F32 a_min = a.pos; + DN_V2F32 a_max = a.pos + a.size; + DN_V2F32 b_min = b.pos; + DN_V2F32 b_max = b.pos + b.size; bool result = (b_min >= a_min && b_max <= a_max); return result; } -DQN_API Dqn_Rect Dqn_Rect_Expand(Dqn_Rect a, Dqn_f32 amount) +DN_API DN_Rect DN_Rect_Expand(DN_Rect a, DN_F32 amount) { - Dqn_Rect result = a; + DN_Rect result = a; result.pos -= amount; result.size += (amount * 2.f); return result; } -DQN_API Dqn_Rect Dqn_Rect_ExpandV2(Dqn_Rect a, Dqn_V2 amount) +DN_API DN_Rect DN_Rect_ExpandV2(DN_Rect a, DN_V2F32 amount) { - Dqn_Rect result = a; + DN_Rect result = a; result.pos -= amount; result.size += (amount * 2.f); return result; } -DQN_API bool Dqn_Rect_Intersects(Dqn_Rect a, Dqn_Rect b) +DN_API bool DN_Rect_Intersects(DN_Rect a, DN_Rect b) { - Dqn_V2 a_min = a.pos; - Dqn_V2 a_max = a.pos + a.size; - Dqn_V2 b_min = b.pos; - Dqn_V2 b_max = b.pos + b.size; + DN_V2F32 a_min = a.pos; + DN_V2F32 a_max = a.pos + a.size; + DN_V2F32 b_min = b.pos; + DN_V2F32 b_max = b.pos + b.size; bool result = (a_min.x <= b_max.x && a_max.x >= b_min.x) && (a_min.y <= b_max.y && a_max.y >= b_min.y); return result; } -DQN_API Dqn_Rect Dqn_Rect_Intersection(Dqn_Rect a, Dqn_Rect b) +DN_API DN_Rect DN_Rect_Intersection(DN_Rect a, DN_Rect b) { - Dqn_Rect result = Dqn_Rect_InitV2x2(a.pos, Dqn_V2_InitNx1(0)); - if (Dqn_Rect_Intersects(a, b)) { - Dqn_V2 a_min = a.pos; - Dqn_V2 a_max = a.pos + a.size; - Dqn_V2 b_min = b.pos; - Dqn_V2 b_max = b.pos + b.size; + DN_Rect result = DN_Rect_Init2V2(a.pos, DN_V2F32_Init1N(0)); + if (DN_Rect_Intersects(a, b)) { + DN_V2F32 a_min = a.pos; + DN_V2F32 a_max = a.pos + a.size; + DN_V2F32 b_min = b.pos; + DN_V2F32 b_max = b.pos + b.size; - Dqn_V2 min = {}; - Dqn_V2 max = {}; - min.x = DQN_MAX(a_min.x, b_min.x); - min.y = DQN_MAX(a_min.y, b_min.y); - max.x = DQN_MIN(a_max.x, b_max.x); - max.y = DQN_MIN(a_max.y, b_max.y); - result = Dqn_Rect_InitV2x2(min, max - min); + DN_V2F32 min = {}; + DN_V2F32 max = {}; + min.x = DN_MAX(a_min.x, b_min.x); + min.y = DN_MAX(a_min.y, b_min.y); + max.x = DN_MIN(a_max.x, b_max.x); + max.y = DN_MIN(a_max.y, b_max.y); + result = DN_Rect_Init2V2(min, max - min); } return result; } -DQN_API Dqn_Rect Dqn_Rect_Union(Dqn_Rect a, Dqn_Rect b) +DN_API DN_Rect DN_Rect_Union(DN_Rect a, DN_Rect b) { - Dqn_V2 a_min = a.pos; - Dqn_V2 a_max = a.pos + a.size; - Dqn_V2 b_min = b.pos; - Dqn_V2 b_max = b.pos + b.size; + DN_V2F32 a_min = a.pos; + DN_V2F32 a_max = a.pos + a.size; + DN_V2F32 b_min = b.pos; + DN_V2F32 b_max = b.pos + b.size; - Dqn_V2 min, max; - min.x = DQN_MIN(a_min.x, b_min.x); - min.y = DQN_MIN(a_min.y, b_min.y); - max.x = DQN_MAX(a_max.x, b_max.x); - max.y = DQN_MAX(a_max.y, b_max.y); - Dqn_Rect result = Dqn_Rect_InitV2x2(min, max - min); + DN_V2F32 min, max; + min.x = DN_MIN(a_min.x, b_min.x); + min.y = DN_MIN(a_min.y, b_min.y); + max.x = DN_MAX(a_max.x, b_max.x); + max.y = DN_MAX(a_max.y, b_max.y); + DN_Rect result = DN_Rect_Init2V2(min, max - min); return result; } -DQN_API Dqn_RectMinMax Dqn_Rect_MinMax(Dqn_Rect a) +DN_API DN_RectMinMax DN_Rect_MinMax(DN_Rect a) { - Dqn_RectMinMax result = {}; + DN_RectMinMax result = {}; result.min = a.pos; result.max = a.pos + a.size; return result; } -DQN_API Dqn_f32 Dqn_Rect_Area(Dqn_Rect a) +DN_API DN_F32 DN_Rect_Area(DN_Rect a) { - Dqn_f32 result = a.size.w * a.size.h; + DN_F32 result = a.size.w * a.size.h; return result; } -DQN_API Dqn_Rect Dqn_Rect_CutLeftClip(Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip) +DN_API DN_Rect DN_Rect_CutLeftClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) { - Dqn_f32 min_x = rect->pos.x; - Dqn_f32 max_x = rect->pos.x + rect->size.w; - Dqn_f32 result_max_x = min_x + amount; + DN_F32 min_x = rect->pos.x; + DN_F32 max_x = rect->pos.x + rect->size.w; + DN_F32 result_max_x = min_x + amount; if (clip) - result_max_x = DQN_MIN(result_max_x, max_x); - Dqn_Rect result = Dqn_Rect_InitNx4(min_x, rect->pos.y, result_max_x - min_x, rect->size.h); + result_max_x = DN_MIN(result_max_x, max_x); + DN_Rect result = DN_Rect_Init4N(min_x, rect->pos.y, result_max_x - min_x, rect->size.h); rect->pos.x = result_max_x; rect->size.w = max_x - result_max_x; return result; } -DQN_API Dqn_Rect Dqn_Rect_CutRightClip(Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip) +DN_API DN_Rect DN_Rect_CutRightClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) { - Dqn_f32 min_x = rect->pos.x; - Dqn_f32 max_x = rect->pos.x + rect->size.w; - Dqn_f32 result_min_x = max_x - amount; + DN_F32 min_x = rect->pos.x; + DN_F32 max_x = rect->pos.x + rect->size.w; + DN_F32 result_min_x = max_x - amount; if (clip) - result_min_x = DQN_MAX(result_min_x, 0); - Dqn_Rect result = Dqn_Rect_InitNx4(result_min_x, rect->pos.y, max_x - result_min_x, rect->size.h); + result_min_x = DN_MAX(result_min_x, 0); + DN_Rect result = DN_Rect_Init4N(result_min_x, rect->pos.y, max_x - result_min_x, rect->size.h); rect->size.w = result_min_x - min_x; return result; } -DQN_API Dqn_Rect Dqn_Rect_CutTopClip(Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip) +DN_API DN_Rect DN_Rect_CutTopClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) { - Dqn_f32 min_y = rect->pos.y; - Dqn_f32 max_y = rect->pos.y + rect->size.h; - Dqn_f32 result_max_y = min_y + amount; + DN_F32 min_y = rect->pos.y; + DN_F32 max_y = rect->pos.y + rect->size.h; + DN_F32 result_max_y = min_y + amount; if (clip) - result_max_y = DQN_MIN(result_max_y, max_y); - Dqn_Rect result = Dqn_Rect_InitNx4(rect->pos.x, min_y, rect->size.w, result_max_y - min_y); + result_max_y = DN_MIN(result_max_y, max_y); + DN_Rect result = DN_Rect_Init4N(rect->pos.x, min_y, rect->size.w, result_max_y - min_y); rect->pos.y = result_max_y; rect->size.h = max_y - result_max_y; return result; } -DQN_API Dqn_Rect Dqn_Rect_CutBottomClip(Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip) +DN_API DN_Rect DN_Rect_CutBottomClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) { - Dqn_f32 min_y = rect->pos.y; - Dqn_f32 max_y = rect->pos.y + rect->size.h; - Dqn_f32 result_min_y = max_y - amount; + DN_F32 min_y = rect->pos.y; + DN_F32 max_y = rect->pos.y + rect->size.h; + DN_F32 result_min_y = max_y - amount; if (clip) - result_min_y = DQN_MAX(result_min_y, 0); - Dqn_Rect result = Dqn_Rect_InitNx4(rect->pos.x, result_min_y, rect->size.w, max_y - result_min_y); + result_min_y = DN_MAX(result_min_y, 0); + DN_Rect result = DN_Rect_Init4N(rect->pos.x, result_min_y, rect->size.w, max_y - result_min_y); rect->size.h = result_min_y - min_y; return result; } -DQN_API Dqn_Rect Dqn_RectCut_Cut(Dqn_RectCut rect_cut, Dqn_V2 size, Dqn_RectCutClip clip) +DN_API DN_Rect DN_RectCut_Cut(DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip) { - Dqn_Rect result = {}; + DN_Rect result = {}; if (rect_cut.rect) { switch (rect_cut.side) { - case Dqn_RectCutSide_Left: result = Dqn_Rect_CutLeftClip(rect_cut.rect, size.w, clip); break; - case Dqn_RectCutSide_Right: result = Dqn_Rect_CutRightClip(rect_cut.rect, size.w, clip); break; - case Dqn_RectCutSide_Top: result = Dqn_Rect_CutTopClip(rect_cut.rect, size.h, clip); break; - case Dqn_RectCutSide_Bottom: result = Dqn_Rect_CutBottomClip(rect_cut.rect, size.h, clip); break; + case DN_RectCutSide_Left: result = DN_Rect_CutLeftClip(rect_cut.rect, size.w, clip); break; + case DN_RectCutSide_Right: result = DN_Rect_CutRightClip(rect_cut.rect, size.w, clip); break; + case DN_RectCutSide_Top: result = DN_Rect_CutTopClip(rect_cut.rect, size.h, clip); break; + case DN_RectCutSide_Bottom: result = DN_Rect_CutBottomClip(rect_cut.rect, size.h, clip); break; } } return result; } -DQN_API Dqn_V2 Dqn_Rect_InterpolatedPoint(Dqn_Rect rect, Dqn_V2 t01) +DN_API DN_V2F32 DN_Rect_InterpolatedPoint(DN_Rect rect, DN_V2F32 t01) { - Dqn_V2 result = Dqn_V2_InitNx2(rect.pos.w + (rect.size.w * t01.x), + DN_V2F32 result = DN_V2F32_Init2N(rect.pos.w + (rect.size.w * t01.x), rect.pos.h + (rect.size.h * t01.y)); return result; } -DQN_API Dqn_V2 Dqn_Rect_TopLeft(Dqn_Rect rect) +DN_API DN_V2F32 DN_Rect_TopLeft(DN_Rect rect) { - Dqn_V2 result = Dqn_Rect_InterpolatedPoint(rect, Dqn_V2_InitNx2(0, 0)); + DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 0)); return result; } -DQN_API Dqn_V2 Dqn_Rect_TopRight(Dqn_Rect rect) +DN_API DN_V2F32 DN_Rect_TopRight(DN_Rect rect) { - Dqn_V2 result = Dqn_Rect_InterpolatedPoint(rect, Dqn_V2_InitNx2(1, 0)); + DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 0)); return result; } -DQN_API Dqn_V2 Dqn_Rect_BottomLeft(Dqn_Rect rect) +DN_API DN_V2F32 DN_Rect_BottomLeft(DN_Rect rect) { - Dqn_V2 result = Dqn_Rect_InterpolatedPoint(rect, Dqn_V2_InitNx2(0, 1)); + DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 1)); return result; } -DQN_API Dqn_V2 Dqn_Rect_BottomRight(Dqn_Rect rect) +DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) { - Dqn_V2 result = Dqn_Rect_InterpolatedPoint(rect, Dqn_V2_InitNx2(1, 1)); + DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 1)); return result; } -#endif // !defined(DQN_NO_RECT) +#endif // !defined(DN_NO_RECT) // NOTE: [$MATH] Raycast /////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_RaycastLineIntersectV2Result Dqn_Raycast_LineIntersectV2(Dqn_V2 origin_a, Dqn_V2 dir_a, Dqn_V2 origin_b, Dqn_V2 dir_b) +DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) { // NOTE: Parametric equation of a line // @@ -1546,8 +1546,8 @@ DQN_API Dqn_RaycastLineIntersectV2Result Dqn_Raycast_LineIntersectV2(Dqn_V2 orig // // Working that math out produces the formula below for 't'. - Dqn_RaycastLineIntersectV2Result result = {}; - Dqn_f32 denominator = ((dir_b.y * dir_a.x) - (dir_b.x * dir_a.y)); + DN_RaycastLineIntersectV2Result result = {}; + DN_F32 denominator = ((dir_b.y * dir_a.x) - (dir_b.x * dir_a.y)); if (denominator != 0.0f) { result.t_a = (((origin_a.y - origin_b.y) * dir_b.x) + ((origin_b.x - origin_a.x) * dir_b.y)) / denominator; result.t_b = (((origin_a.y - origin_b.y) * dir_a.x) + ((origin_b.x - origin_a.x) * dir_a.y)) / denominator; @@ -1557,16 +1557,16 @@ DQN_API Dqn_RaycastLineIntersectV2Result Dqn_Raycast_LineIntersectV2(Dqn_V2 orig } // NOTE: [$MATH] Other ///////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_V2 Dqn_Lerp_V2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b) +DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) { - Dqn_V2 result = {}; + DN_V2F32 result = {}; result.x = a.x + ((b.x - a.x) * t); result.y = a.y + ((b.y - a.y) * t); return result; } -DQN_API Dqn_f32 Dqn_Lerp_F32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b) +DN_API DN_F32 DN_Lerp_F32(DN_F32 a, DN_F32 t, DN_F32 b) { - Dqn_f32 result = a + ((b - a) * t); + DN_F32 result = a + ((b - a) * t); return result; } diff --git a/dqn_math.h b/dqn_math.h index db71d9f..949a0de 100644 --- a/dqn_math.h +++ b/dqn_math.h @@ -17,397 +17,395 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // -// [$VEC2] Dqn_V2, V2i -- DQN_V2 -// [$VEC3] Dqn_V3, V3i -- DQN_V3 -// [$VEC4] Dqn_V4, V4i -- DQN_V4 -// [$MAT4] Dqn_M4 -- DQN_M4 -// [$M2x3] Dqn_M2x3 -- -// [$RECT] Dqn_Rect -- DQN_RECT -// [$MATH] Other -- +// [$VEC2] DN_V2F32, V2I32 -- DN_V2 +// [$VEC3] DN_V3F32, V3I32 -- DN_V3 +// [$VEC4] DN_V4F32, V4I32 -- DN_V4 +// [$MAT4] DN_M4 -- DN_M4 +// [$M2x3] DN_M2x3 -- +// [$RECT] DN_Rect -- DN_RECT +// [$MATH] Other -- // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -DQN_MSVC_WARNING_PUSH -DQN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DQN_NO_V2) +DN_MSVC_WARNING_PUSH +DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union +#if !defined(DN_NO_V2) // NOTE: [$VEC2] Vector2 /////////////////////////////////////////////////////////////////////////// -union Dqn_V2I +union DN_V2I32 { struct { int32_t x, y; }; struct { int32_t w, h; }; int32_t data[2]; }; -union Dqn_V2U16 +union DN_V2U16 { struct { uint16_t x, y; }; struct { uint16_t w, h; }; uint16_t data[2]; }; -union Dqn_V2 +union DN_V2F32 { - struct { Dqn_f32 x, y; }; - struct { Dqn_f32 w, h; }; - Dqn_f32 data[2]; + struct { DN_F32 x, y; }; + struct { DN_F32 w, h; }; + DN_F32 data[2]; }; -#endif // !defined(DQN_NO_V2) +#endif // !defined(DN_NO_V2) -#if !defined(DQN_NO_V3) +#if !defined(DN_NO_V3) // NOTE: [$VEC3] Vector3 /////////////////////////////////////////////////////////////////////////// -union Dqn_V3 +union DN_V3F32 { - struct { Dqn_f32 x, y, z; }; - struct { Dqn_f32 r, g, b; }; - Dqn_f32 data[3]; + struct { DN_F32 x, y, z; }; + struct { DN_F32 r, g, b; }; + DN_F32 data[3]; }; -#endif // !defined(DQN_NO_V3) +#endif // !defined(DN_NO_V3) -#if !defined(DQN_NO_V4) +#if !defined(DN_NO_V4) // NOTE: [$VEC4] Vector4 /////////////////////////////////////////////////////////////////////////// -union Dqn_V4 +union DN_V4F32 { - struct { Dqn_f32 x, y, z, w; }; - struct { Dqn_f32 r, g, b, a; }; - #if !defined(DQN_NO_V3) - Dqn_V3 rgb; - Dqn_V3 xyz; + 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 - Dqn_f32 data[4]; + DN_F32 data[4]; }; -#endif // !defined(DQN_NO_V4) -DQN_MSVC_WARNING_POP +#endif // !defined(DN_NO_V4) +DN_MSVC_WARNING_POP -#if !defined(DQN_NO_M4) -// NOTE: [$MAT4] Dqn_M4 //////////////////////////////////////////////////////////////////////////// -struct Dqn_M4 +#if !defined(DN_NO_M4) +// NOTE: [$MAT4] DN_M4 //////////////////////////////////////////////////////////////////////////// +struct DN_M4 { - Dqn_f32 columns[4][4]; // Column major matrix + DN_F32 columns[4][4]; // Column major matrix }; -#endif // !defined(DQN_M4) +#endif // !defined(DN_M4) -// NOTE: [$M2x3] Dqn_M2x3 ////////////////////////////////////////////////////////////////////////// -union Dqn_M2x3 +// NOTE: [$M2x3] DN_M2x3 ////////////////////////////////////////////////////////////////////////// +union DN_M2x3 { - Dqn_f32 e[6]; - Dqn_f32 row[2][3]; + DN_F32 e[6]; + DN_F32 row[2][3]; }; -// NOTE: [$RECT] Dqn_Rect ////////////////////////////////////////////////////////////////////////// -#if !defined(DQN_NO_RECT) -#if defined(DQN_NO_V2) - #error "Rectangles requires V2, DQN_NO_V2 must not be defined" +// NOTE: [$RECT] DN_Rect ////////////////////////////////////////////////////////////////////////// +#if !defined(DN_NO_RECT) +#if defined(DN_NO_V2) + #error "Rectangles requires V2, DN_NO_V2 must not be defined" #endif -struct Dqn_Rect +struct DN_Rect { - Dqn_V2 pos, size; + DN_V2F32 pos, size; }; -struct Dqn_RectMinMax +struct DN_RectMinMax { - Dqn_V2 min, max; + DN_V2F32 min, max; }; -enum Dqn_RectCutClip +enum DN_RectCutClip { - Dqn_RectCutClip_No, - Dqn_RectCutClip_Yes, + DN_RectCutClip_No, + DN_RectCutClip_Yes, }; -enum Dqn_RectCutSide +enum DN_RectCutSide { - Dqn_RectCutSide_Left, - Dqn_RectCutSide_Right, - Dqn_RectCutSide_Top, - Dqn_RectCutSide_Bottom, + DN_RectCutSide_Left, + DN_RectCutSide_Right, + DN_RectCutSide_Top, + DN_RectCutSide_Bottom, }; -struct Dqn_RectCut +struct DN_RectCut { - Dqn_Rect* rect; - Dqn_RectCutSide side; + DN_Rect* rect; + DN_RectCutSide side; }; -#endif // !defined(DQN_NO_RECT) +#endif // !defined(DN_NO_RECT) // NOTE: [$MATH] Other ///////////////////////////////////////////////////////////////////////////// // NOTE: API -struct Dqn_RaycastLineIntersectV2Result +struct DN_RaycastLineIntersectV2Result { bool hit; // True if there was an intersection, false if the lines are parallel - Dqn_f32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` - Dqn_f32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` + DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` + DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` }; -#if !defined(DQN_NO_V2) +#if !defined(DN_NO_V2) // NOTE: [$VEC2] Vector2 /////////////////////////////////////////////////////////////////////////// -#define Dqn_V2I_Zero DQN_LITERAL(Dqn_V2I){{(int32_t)(0), (int32_t)(0)}} -#define Dqn_V2I_One DQN_LITERAL(Dqn_V2I){{(int32_t)(1), (int32_t)(1)}} -#define Dqn_V2I_InitNx1(x) DQN_LITERAL(Dqn_V2I){{(int32_t)(x), (int32_t)(x)}} -#define Dqn_V2I_InitNx2(x, y) DQN_LITERAL(Dqn_V2I){{(int32_t)(x), (int32_t)(y)}} -#define Dqn_V2I_InitV2(xy) DQN_LITERAL(Dqn_V2I){{(int32_t)(xy).x, (int32_t)(xy).y}} +#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} +#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} +#define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} +#define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} +#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} -DQN_API bool operator!= (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API bool operator== (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API bool operator>= (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API bool operator<= (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API bool operator< (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API bool operator> (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API Dqn_V2I operator- (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API Dqn_V2I operator- (Dqn_V2I lhs); -DQN_API Dqn_V2I operator+ (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API Dqn_V2I operator* (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API Dqn_V2I operator* (Dqn_V2I lhs, Dqn_f32 rhs); -DQN_API Dqn_V2I operator* (Dqn_V2I lhs, int32_t rhs); -DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, Dqn_V2I rhs); -DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, Dqn_f32 rhs); -DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, int32_t rhs); -DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, Dqn_V2I rhs); -DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, Dqn_f32 rhs); -DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, int32_t rhs); -DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, Dqn_V2I rhs); -DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, Dqn_f32 rhs); -DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, int32_t rhs); -DQN_API Dqn_V2I & operator-= (Dqn_V2I& lhs, Dqn_V2I rhs); -DQN_API Dqn_V2I & operator+= (Dqn_V2I& lhs, Dqn_V2I rhs); +DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator- (DN_V2I32 lhs); +DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs); +DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs); +DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs); +DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs); +DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs); +DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs); +DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs); +DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs); +DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs); +DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs); +DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs); +DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs); -DQN_API Dqn_V2I Dqn_V2I_Min (Dqn_V2I a, Dqn_V2I b); -DQN_API Dqn_V2I Dqn_V2I_Max (Dqn_V2I a, Dqn_V2I b); -DQN_API Dqn_V2I Dqn_V2I_Abs (Dqn_V2I a); +DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b); +DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); +DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); -#define Dqn_V2U16_Zero DQN_LITERAL(Dqn_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define Dqn_V2U16_One DQN_LITERAL(Dqn_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define Dqn_V2U16_InitNx1(x) DQN_LITERAL(Dqn_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define Dqn_V2U16_InitNx2(x, y) DQN_LITERAL(Dqn_V2U16){{(uint16_t)(x), (uint16_t)(y)}} +#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_Init1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} +#define DN_V2U16_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} -DQN_API bool operator!= (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API bool operator== (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API bool operator>= (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API bool operator<= (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API bool operator< (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API bool operator> (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API Dqn_V2U16 operator- (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API Dqn_V2U16 operator+ (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, Dqn_f32 rhs); -DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, int32_t rhs); -DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, Dqn_V2U16 rhs); -DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, Dqn_f32 rhs); -DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, int32_t rhs); -DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, Dqn_V2U16 rhs); -DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, Dqn_f32 rhs); -DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, int32_t rhs); -DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, Dqn_V2U16 rhs); -DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, Dqn_f32 rhs); -DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, int32_t rhs); -DQN_API Dqn_V2U16 & operator-= (Dqn_V2U16& lhs, Dqn_V2U16 rhs); -DQN_API Dqn_V2U16 & operator+= (Dqn_V2U16& lhs, Dqn_V2U16 rhs); +DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs); +DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs); +DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs); +DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs); +DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs); +DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs); +DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs); +DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs); +DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs); +DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs); +DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); +DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); -#define Dqn_V2_Zero DQN_LITERAL(Dqn_V2){{(Dqn_f32)(0), (Dqn_f32)(0)}} -#define Dqn_V2_One DQN_LITERAL(Dqn_V2){{(Dqn_f32)(1), (Dqn_f32)(1)}} -#define Dqn_V2_InitNx1(x) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(x), (Dqn_f32)(x)}} -#define Dqn_V2_InitNx2(x, y) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(x), (Dqn_f32)(y)}} -#define Dqn_V2_InitV2I(xy) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(xy).x, (Dqn_f32)(xy).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_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} +#define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} +#define DN_V2F32_InitV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} -DQN_API bool operator!= (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API bool operator== (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API bool operator>= (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API bool operator<= (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API bool operator< (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API bool operator> (Dqn_V2 lhs, Dqn_V2 rhs); +DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs); -DQN_API Dqn_V2 operator- (Dqn_V2 lhs); -DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_V2I rhs); -DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_f32 rhs); -DQN_API Dqn_V2 operator- (Dqn_V2 lhs, int32_t rhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs); -DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_V2I rhs); -DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_f32 rhs); -DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, int32_t rhs); +DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs); +DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs); +DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs); -DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_V2I rhs); -DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_f32 rhs); -DQN_API Dqn_V2 operator* (Dqn_V2 lhs, int32_t rhs); +DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs); +DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs); +DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs); -DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_V2I rhs); -DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_f32 rhs); -DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, int32_t rhs); +DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs); +DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs); +DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs); -DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_V2 rhs); -DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_V2I rhs); -DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_f32 rhs); -DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, int32_t rhs); +DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs); +DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs); +DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs); +DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs); -DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_V2 rhs); -DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_V2I rhs); -DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_f32 rhs); -DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, int32_t rhs); +DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs); +DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs); +DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs); +DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs); -DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_V2 rhs); -DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_V2I rhs); -DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_f32 rhs); -DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, int32_t rhs); +DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs); +DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs); +DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs); +DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs); -DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_V2 rhs); -DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_V2I rhs); -DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_f32 rhs); -DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, int32_t rhs); +DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs); +DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs); +DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs); +DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs); -DQN_API Dqn_V2 Dqn_V2_Min (Dqn_V2 a, Dqn_V2 b); -DQN_API Dqn_V2 Dqn_V2_Max (Dqn_V2 a, Dqn_V2 b); -DQN_API Dqn_V2 Dqn_V2_Abs (Dqn_V2 a); -DQN_API Dqn_f32 Dqn_V2_Dot (Dqn_V2 a, Dqn_V2 b); -DQN_API Dqn_f32 Dqn_V2_LengthSq_V2x2 (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API Dqn_f32 Dqn_V2_Length_V2x2 (Dqn_V2 lhs, Dqn_V2 rhs); -DQN_API Dqn_f32 Dqn_V2_LengthSq (Dqn_V2 lhs); -DQN_API Dqn_f32 Dqn_V2_Length (Dqn_V2 lhs); -DQN_API Dqn_V2 Dqn_V2_Normalise (Dqn_V2 a); -DQN_API Dqn_V2 Dqn_V2_Perpendicular (Dqn_V2 a); -DQN_API Dqn_V2 Dqn_V2_Reflect (Dqn_V2 in, Dqn_V2 surface); -DQN_API Dqn_f32 Dqn_V2_Area (Dqn_V2 a); -#endif // !defined(DQN_NO_V2) -#if !defined(DQN_NO_V3) +DN_API DN_V2F32 DN_V2_Min (DN_V2F32 a, DN_V2F32 b); +DN_API DN_V2F32 DN_V2_Max (DN_V2F32 a, DN_V2F32 b); +DN_API DN_V2F32 DN_V2_Abs (DN_V2F32 a); +DN_API DN_F32 DN_V2_Dot (DN_V2F32 a, DN_V2F32 b); +DN_API DN_F32 DN_V2_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_F32 DN_V2_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_F32 DN_V2_LengthSq (DN_V2F32 lhs); +DN_API DN_F32 DN_V2_Length (DN_V2F32 lhs); +DN_API DN_V2F32 DN_V2_Normalise (DN_V2F32 a); +DN_API DN_V2F32 DN_V2_Perpendicular (DN_V2F32 a); +DN_API DN_V2F32 DN_V2_Reflect (DN_V2F32 in, DN_V2F32 surface); +DN_API DN_F32 DN_V2_Area (DN_V2F32 a); +#endif // !defined(DN_NO_V2) +#if !defined(DN_NO_V3) // NOTE: [$VEC3] Vector3 /////////////////////////////////////////////////////////////////////////// -#define Dqn_V3_InitNx1(x) DQN_LITERAL(Dqn_V3){{(Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x)}} -#define Dqn_V3_InitNx3(x, y, z) DQN_LITERAL(Dqn_V3){{(Dqn_f32)(x), (Dqn_f32)(y), (Dqn_f32)(z)}} -#define Dqn_V3_InitV2x1_Nx1(xy, z) DQN_LITERAL(Dqn_V3){{(Dqn_f32)(xy.x), (Dqn_f32)(xy.y), (Dqn_f32)(z)}} +#define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} +#define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} +#define DN_V3F32_InitV2F32_1F32(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} -DQN_API bool operator!= (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API bool operator== (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API bool operator>= (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API bool operator<= (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API bool operator< (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API bool operator> (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API Dqn_V3 operator- (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API Dqn_V3 operator- (Dqn_V3 lhs); -DQN_API Dqn_V3 operator+ (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API Dqn_V3 operator* (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API Dqn_V3 operator* (Dqn_V3 lhs, Dqn_f32 rhs); -DQN_API Dqn_V3 operator* (Dqn_V3 lhs, int32_t rhs); -DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, Dqn_V3 rhs); -DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, Dqn_f32 rhs); -DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, int32_t rhs); -DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, Dqn_V3 rhs); -DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, Dqn_f32 rhs); -DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, int32_t rhs); -DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, Dqn_V3 rhs); -DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, Dqn_f32 rhs); -DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, int32_t rhs); -DQN_API Dqn_V3 & operator-= (Dqn_V3 &lhs, Dqn_V3 rhs); -DQN_API Dqn_V3 & operator+= (Dqn_V3 &lhs, Dqn_V3 rhs); -DQN_API Dqn_f32 Dqn_V3_LengthSq (Dqn_V3 a); -DQN_API Dqn_f32 Dqn_V3_Length (Dqn_V3 a); -DQN_API Dqn_V3 Dqn_V3_Normalise (Dqn_V3 a); -#endif // !defined(DQN_NO_V3) -#if !defined(DQN_NO_V4) +DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator- (DN_V3F32 lhs); +DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs); +DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs); +DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs); +DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs); +DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs); +DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs); +DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs); +DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs); +DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs); +DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs); +DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs); +DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs); +DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); +DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); +DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); +#endif // !defined(DN_NO_V3) +#if !defined(DN_NO_V4) // NOTE: [$VEC4] Vector4 /////////////////////////////////////////////////////////////////////////// -#define Dqn_V4_InitNx1(x) DQN_LITERAL(Dqn_V4){{(Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x)}} -#define Dqn_V4_InitNx4(x, y, z, w) DQN_LITERAL(Dqn_V4){{(Dqn_f32)(x), (Dqn_f32)(y), (Dqn_f32)(z), (Dqn_f32)(w)}} -#define Dqn_V4_Init_V3x1_Nx1(xyz, w) DQN_LITERAL(Dqn_V4){{xyz.x, xyz.y, xyz.z, w}} -DQN_API bool operator!= (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API bool operator== (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API bool operator>= (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API bool operator<= (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API bool operator< (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API bool operator> (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API Dqn_V4 operator- (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API Dqn_V4 operator- (Dqn_V4 lhs); -DQN_API Dqn_V4 operator+ (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API Dqn_V4 operator* (Dqn_V4 lhs, Dqn_V4 rhs); -DQN_API Dqn_V4 operator* (Dqn_V4 lhs, Dqn_f32 rhs); -DQN_API Dqn_V4 operator* (Dqn_V4 lhs, int32_t rhs); -DQN_API Dqn_V4 operator/ (Dqn_V4 lhs, Dqn_f32 rhs); -DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, Dqn_V4 rhs); -DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, Dqn_f32 rhs); -DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, int32_t rhs); -DQN_API Dqn_V4 & operator-= (Dqn_V4 &lhs, Dqn_V4 rhs); -DQN_API Dqn_V4 & operator+= (Dqn_V4 &lhs, Dqn_V4 rhs); -#endif // !defined(DQN_NO_V4) -#if !defined(DQN_NO_M4) -// NOTE: [$MAT4] Dqn_M4 //////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_f32 Dqn_V4Dot (Dqn_V4 a, Dqn_V4 b); -DQN_API Dqn_M4 Dqn_M4_Identity (); -DQN_API Dqn_M4 Dqn_M4_ScaleF (Dqn_f32 x, Dqn_f32 y, Dqn_f32 z); -DQN_API Dqn_M4 Dqn_M4_Scale (Dqn_V3 xyz); -DQN_API Dqn_M4 Dqn_M4_TranslateF (Dqn_f32 x, Dqn_f32 y, Dqn_f32 z); -DQN_API Dqn_M4 Dqn_M4_Translate (Dqn_V3 xyz); -DQN_API Dqn_M4 Dqn_M4_Transpose (Dqn_M4 mat); -DQN_API Dqn_M4 Dqn_M4_Rotate (Dqn_V3 axis, Dqn_f32 radians); -DQN_API Dqn_M4 Dqn_M4_Orthographic (Dqn_f32 left, Dqn_f32 right, Dqn_f32 bottom, Dqn_f32 top, Dqn_f32 z_near, Dqn_f32 z_far); -DQN_API Dqn_M4 Dqn_M4_Perspective (Dqn_f32 fov /*radians*/, Dqn_f32 aspect, Dqn_f32 z_near, Dqn_f32 z_far); -DQN_API Dqn_M4 Dqn_M4_Add (Dqn_M4 lhs, Dqn_M4 rhs); -DQN_API Dqn_M4 Dqn_M4_Sub (Dqn_M4 lhs, Dqn_M4 rhs); -DQN_API Dqn_M4 Dqn_M4_Mul (Dqn_M4 lhs, Dqn_M4 rhs); -DQN_API Dqn_M4 Dqn_M4_Div (Dqn_M4 lhs, Dqn_M4 rhs); -DQN_API Dqn_M4 Dqn_M4_AddF (Dqn_M4 lhs, Dqn_f32 rhs); -DQN_API Dqn_M4 Dqn_M4_SubF (Dqn_M4 lhs, Dqn_f32 rhs); -DQN_API Dqn_M4 Dqn_M4_MulF (Dqn_M4 lhs, Dqn_f32 rhs); -DQN_API Dqn_M4 Dqn_M4_DivF (Dqn_M4 lhs, Dqn_f32 rhs); -#if !defined(DQN_NO_FSTR8) -DQN_API Dqn_FStr8<256> Dqn_M4_ColumnMajorString (Dqn_M4 mat); +#define DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} +#define DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} +#define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} +DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API DN_V4F32 operator- (DN_V4F32 lhs); +DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs); +DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs); +DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs); +DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs); +DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs); +DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs); +DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); +DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); +#endif // !defined(DN_NO_V4) +#if !defined(DN_NO_M4) +// NOTE: [$MAT4] DN_M4 //////////////////////////////////////////////////////////////////////////// +DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b); +DN_API DN_M4 DN_M4_Identity (); +DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); +DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); +DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z); +DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz); +DN_API DN_M4 DN_M4_Transpose (DN_M4 mat); +DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians); +DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far); +DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far); +DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs); +DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs); +DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs); +DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs); +DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs); +DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs); +DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); +DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); +#if !defined(DN_NO_FSTR8) +DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat); #endif -#endif // !defined(DQN_NO_M4) -// NOTE: [$M2x3] Dqn_M2x3 ////////////////////////////////////////////////////////////////////////// -DQN_API bool operator== (Dqn_M2x3 const &lhs, Dqn_M2x3 const &rhs); -DQN_API bool operator!= (Dqn_M2x3 const &lhs, Dqn_M2x3 const &rhs); -DQN_API Dqn_M2x3 Dqn_M2x3_Identity (); -DQN_API Dqn_M2x3 Dqn_M2x3_Translate (Dqn_V2 offset); -DQN_API Dqn_M2x3 Dqn_M2x3_Scale (Dqn_V2 scale); -DQN_API Dqn_M2x3 Dqn_M2x3_Rotate (Dqn_f32 radians); -DQN_API Dqn_M2x3 Dqn_M2x3_Mul (Dqn_M2x3 m1, Dqn_M2x3 m2); -DQN_API Dqn_V2 Dqn_M2x3_Mul2F32 (Dqn_M2x3 m1, Dqn_f32 x, Dqn_f32 y); -DQN_API Dqn_V2 Dqn_M2x3_MulV2 (Dqn_M2x3 m1, Dqn_V2 v2); +#endif // !defined(DN_NO_M4) +// NOTE: [$M2x3] DN_M2x3 ////////////////////////////////////////////////////////////////////////// +DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); +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_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); +DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); +DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); +#if !defined(DN_NO_RECT) +// NOTE: [$RECT] DN_Rect ////////////////////////////////////////////////////////////////////////// +#define DN_Rect_Init2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} +#define DN_Rect_Init4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} -#if !defined(DQN_NO_RECT) -// NOTE: [$RECT] Dqn_Rect ////////////////////////////////////////////////////////////////////////// -#define Dqn_Rect_InitV2x2(pos, size) DQN_LITERAL(Dqn_Rect){(pos), (size)} -#define Dqn_Rect_InitNx4(x, y, w, h) DQN_LITERAL(Dqn_Rect){DQN_LITERAL(Dqn_V2){{x, y}}, DQN_LITERAL(Dqn_V2){{w, h}}} +DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); +DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); +DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p); +DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b); +DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount); +DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount); +DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b); +DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b); +DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b); +DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a); +DN_API DN_F32 DN_Rect_Area (DN_Rect a); +DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01); +DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect); +DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect); +DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect); +DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect); -DQN_API bool operator== (const Dqn_Rect& lhs, const Dqn_Rect& rhs); -DQN_API Dqn_V2 Dqn_Rect_Center (Dqn_Rect rect); -DQN_API bool Dqn_Rect_ContainsPoint (Dqn_Rect rect, Dqn_V2 p); -DQN_API bool Dqn_Rect_ContainsRect (Dqn_Rect a, Dqn_Rect b); -DQN_API Dqn_Rect Dqn_Rect_Expand (Dqn_Rect a, Dqn_f32 amount); -DQN_API Dqn_Rect Dqn_Rect_ExpandV2 (Dqn_Rect a, Dqn_V2 amount); -DQN_API bool Dqn_Rect_Intersects (Dqn_Rect a, Dqn_Rect b); -DQN_API Dqn_Rect Dqn_Rect_Intersection (Dqn_Rect a, Dqn_Rect b); -DQN_API Dqn_Rect Dqn_Rect_Union (Dqn_Rect a, Dqn_Rect b); -DQN_API Dqn_RectMinMax Dqn_Rect_MinMax (Dqn_Rect a); -DQN_API Dqn_f32 Dqn_Rect_Area (Dqn_Rect a); -DQN_API Dqn_V2 Dqn_Rect_InterpolatedPoint (Dqn_Rect rect, Dqn_V2 t01); -DQN_API Dqn_V2 Dqn_Rect_TopLeft (Dqn_Rect rect); -DQN_API Dqn_V2 Dqn_Rect_TopRight (Dqn_Rect rect); -DQN_API Dqn_V2 Dqn_Rect_BottomLeft (Dqn_Rect rect); -DQN_API Dqn_V2 Dqn_Rect_BottomRight (Dqn_Rect rect); +DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); +DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); +DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); +DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DQN_API Dqn_Rect Dqn_Rect_CutLeftClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip); -DQN_API Dqn_Rect Dqn_Rect_CutRightClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip); -DQN_API Dqn_Rect Dqn_Rect_CutTopClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip); -DQN_API Dqn_Rect Dqn_Rect_CutBottomClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip); +#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes) +#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes) +#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes) +#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes) -#define Dqn_Rect_CutLeft(rect, amount) Dqn_Rect_CutLeftClip(rect, amount, Dqn_RectCutClip_Yes) -#define Dqn_Rect_CutRight(rect, amount) Dqn_Rect_CutRightClip(rect, amount, Dqn_RectCutClip_Yes) -#define Dqn_Rect_CutTop(rect, amount) Dqn_Rect_CutTopClip(rect, amount, Dqn_RectCutClip_Yes) -#define Dqn_Rect_CutBottom(rect, amount) Dqn_Rect_CutBottomClip(rect, amount, Dqn_RectCutClip_Yes) +#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No) +#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No) +#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No) +#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) -#define Dqn_Rect_CutLeftNoClip(rect, amount) Dqn_Rect_CutLeftClip(rect, amount, Dqn_RectCutClip_No) -#define Dqn_Rect_CutRightNoClip(rect, amount) Dqn_Rect_CutRightClip(rect, amount, Dqn_RectCutClip_No) -#define Dqn_Rect_CutTopNoClip(rect, amount) Dqn_Rect_CutTopClip(rect, amount, Dqn_RectCutClip_No) -#define Dqn_Rect_CutBottomNoClip(rect, amount) Dqn_Rect_CutBottomClip(rect, amount, Dqn_RectCutClip_No) - -DQN_API Dqn_Rect Dqn_RectCut_Cut (Dqn_RectCut rect_cut, Dqn_V2 size, Dqn_RectCutClip clip); -#define Dqn_RectCut_Init(rect, side) DQN_LITERAL(Dqn_RectCut){rect, side} -#define Dqn_RectCut_Left(rect) DQN_LITERAL(Dqn_RectCut){rect, Dqn_RectCutSide_Left} -#define Dqn_RectCut_Right(rect) DQN_LITERAL(Dqn_RectCut){rect, Dqn_RectCutSide_Right} -#define Dqn_RectCut_Top(rect) DQN_LITERAL(Dqn_RectCut){rect, Dqn_RectCutSide_Top} -#define Dqn_RectCut_Bottom(rect) DQN_LITERAL(Dqn_RectCut){rect, Dqn_RectCutSide_Bottom} -#endif // !defined(DQN_NO_RECT) +DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); +#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} +#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} +#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} +#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} +#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} +#endif // !defined(DN_NO_RECT) // NOTE: [$MATH] Other ///////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_RaycastLineIntersectV2Result Dqn_Raycast_LineIntersectV2(Dqn_V2 origin_a, Dqn_V2 dir_a, Dqn_V2 origin_b, Dqn_V2 dir_b); -DQN_API Dqn_V2 Dqn_Lerp_V2 (Dqn_V2 a, Dqn_f32 t, Dqn_V2 b); -DQN_API Dqn_f32 Dqn_Lerp_F32 (Dqn_f32 a, Dqn_f32 t, Dqn_f32 b); +DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); +DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); +DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); diff --git a/dqn_os.cpp b/dqn_os.cpp index 8ea1639..4d48712 100644 --- a/dqn_os.cpp +++ b/dqn_os.cpp @@ -19,11 +19,11 @@ */ // NOTE: [$DATE] Date ////////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8(Dqn_OSDateTime time, char date_separator, char hms_separator) +DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8(DN_OSDateTime time, char date_separator, char hms_separator) { - Dqn_OSDateTimeStr8 result = {}; - result.hms_size = DQN_CAST(uint8_t) DQN_SNPRINTF(result.hms, - DQN_ARRAY_ICOUNT(result.hms), + DN_OSDateTimeStr8 result = {}; + result.hms_size = DN_CAST(uint8_t) DN_SNPRINTF(result.hms, + DN_ARRAY_ICOUNT(result.hms), "%02hhu%c%02hhu%c%02hhu", time.hour, hms_separator, @@ -31,8 +31,8 @@ DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8(Dqn_OSDateTime time, char da hms_separator, time.seconds); - result.date_size = DQN_CAST(uint8_t) DQN_SNPRINTF(result.date, - DQN_ARRAY_ICOUNT(result.date), + result.date_size = DN_CAST(uint8_t) DN_SNPRINTF(result.date, + DN_ARRAY_ICOUNT(result.date), "%hu%c%02hhu%c%02hhu", time.year, date_separator, @@ -40,19 +40,25 @@ DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8(Dqn_OSDateTime time, char da date_separator, time.day); - DQN_ASSERT(result.hms_size < DQN_ARRAY_UCOUNT(result.hms)); - DQN_ASSERT(result.date_size < DQN_ARRAY_UCOUNT(result.date)); + DN_ASSERT(result.hms_size < DN_ARRAY_UCOUNT(result.hms)); + DN_ASSERT(result.date_size < DN_ARRAY_UCOUNT(result.date)); return result; } -DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator) +DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator) { - Dqn_OSDateTime time = Dqn_OS_DateLocalTimeNow(); - Dqn_OSDateTimeStr8 result = Dqn_OS_DateLocalTimeStr8(time, date_separator, hms_separator); + DN_OSDateTime time = DN_OS_DateLocalTimeNow(); + DN_OSDateTimeStr8 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator); return result; } -DQN_API bool Dqn_OS_DateIsValid(Dqn_OSDateTime date) +DN_API uint64_t DN_OS_DateUnixTimeS() +{ + uint64_t result = DN_OS_DateUnixTimeNs() / (1'000 /*us*/ * 1'000 /*ms*/ * 1'000 /*s*/); + return result; +} + +DN_API bool DN_OS_DateIsValid(DN_OSDateTime date) { if (date.year < 1970) return false; @@ -70,245 +76,245 @@ DQN_API bool Dqn_OS_DateIsValid(Dqn_OSDateTime date) } // NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8 Dqn_OS_EXEDir(Dqn_Arena *arena) +DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; if (!arena) return result; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); - Dqn_Str8 exe_path = Dqn_OS_EXEPath(tmem.arena); - Dqn_Str8 separators[] = {DQN_STR8("/"), DQN_STR8("\\")}; - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplitLastArray(exe_path, separators, DQN_ARRAY_UCOUNT(separators)); - result = Dqn_Str8_Copy(arena, split.lhs); + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str8 exe_path = DN_OS_EXEPath(tmem.arena); + DN_Str8 separators[] = {DN_STR8("/"), DN_STR8("\\")}; + DN_Str8BinarySplitResult split = DN_Str8_BinarySplitLastArray(exe_path, separators, DN_ARRAY_UCOUNT(separators)); + result = DN_Str8_Copy(arena, split.lhs); return result; } // NOTE: Counters ////////////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_f64 Dqn_OS_PerfCounterS(uint64_t begin, uint64_t end) +DN_API DN_F64 DN_OS_PerfCounterS(uint64_t begin, uint64_t end) { - uint64_t frequency = Dqn_OS_PerfCounterFrequency(); + uint64_t frequency = DN_OS_PerfCounterFrequency(); uint64_t ticks = end - begin; - Dqn_f64 result = ticks / DQN_CAST(Dqn_f64)frequency; + DN_F64 result = ticks / DN_CAST(DN_F64)frequency; return result; } -DQN_API Dqn_f64 Dqn_OS_PerfCounterMs(uint64_t begin, uint64_t end) +DN_API DN_F64 DN_OS_PerfCounterMs(uint64_t begin, uint64_t end) { - uint64_t frequency = Dqn_OS_PerfCounterFrequency(); + uint64_t frequency = DN_OS_PerfCounterFrequency(); uint64_t ticks = end - begin; - Dqn_f64 result = (ticks * 1'000) / DQN_CAST(Dqn_f64)frequency; + DN_F64 result = (ticks * 1'000) / DN_CAST(DN_F64)frequency; return result; } -DQN_API Dqn_f64 Dqn_OS_PerfCounterUs(uint64_t begin, uint64_t end) +DN_API DN_F64 DN_OS_PerfCounterUs(uint64_t begin, uint64_t end) { - uint64_t frequency = Dqn_OS_PerfCounterFrequency(); + uint64_t frequency = DN_OS_PerfCounterFrequency(); uint64_t ticks = end - begin; - Dqn_f64 result = (ticks * 1'000'000) / DQN_CAST(Dqn_f64)frequency; + DN_F64 result = (ticks * 1'000'000) / DN_CAST(DN_F64)frequency; return result; } -DQN_API Dqn_f64 Dqn_OS_PerfCounterNs(uint64_t begin, uint64_t end) +DN_API DN_F64 DN_OS_PerfCounterNs(uint64_t begin, uint64_t end) { - uint64_t frequency = Dqn_OS_PerfCounterFrequency(); + uint64_t frequency = DN_OS_PerfCounterFrequency(); uint64_t ticks = end - begin; - Dqn_f64 result = (ticks * 1'000'000'000) / DQN_CAST(Dqn_f64)frequency; + DN_F64 result = (ticks * 1'000'000'000) / DN_CAST(DN_F64)frequency; return result; } -DQN_API Dqn_OSTimer Dqn_OS_TimerBegin() +DN_API DN_OSTimer DN_OS_TimerBegin() { - Dqn_OSTimer result = {}; - result.start = Dqn_OS_PerfCounterNow(); + DN_OSTimer result = {}; + result.start = DN_OS_PerfCounterNow(); return result; } -DQN_API void Dqn_OS_TimerEnd(Dqn_OSTimer *timer) +DN_API void DN_OS_TimerEnd(DN_OSTimer *timer) { - timer->end = Dqn_OS_PerfCounterNow(); + timer->end = DN_OS_PerfCounterNow(); } -DQN_API Dqn_f64 Dqn_OS_TimerS(Dqn_OSTimer timer) +DN_API DN_F64 DN_OS_TimerS(DN_OSTimer timer) { - Dqn_f64 result = Dqn_OS_PerfCounterS(timer.start, timer.end); + DN_F64 result = DN_OS_PerfCounterS(timer.start, timer.end); return result; } -DQN_API Dqn_f64 Dqn_OS_TimerMs(Dqn_OSTimer timer) +DN_API DN_F64 DN_OS_TimerMs(DN_OSTimer timer) { - Dqn_f64 result = Dqn_OS_PerfCounterMs(timer.start, timer.end); + DN_F64 result = DN_OS_PerfCounterMs(timer.start, timer.end); return result; } -DQN_API Dqn_f64 Dqn_OS_TimerUs(Dqn_OSTimer timer) +DN_API DN_F64 DN_OS_TimerUs(DN_OSTimer timer) { - Dqn_f64 result = Dqn_OS_PerfCounterUs(timer.start, timer.end); + DN_F64 result = DN_OS_PerfCounterUs(timer.start, timer.end); return result; } -DQN_API Dqn_f64 Dqn_OS_TimerNs(Dqn_OSTimer timer) +DN_API DN_F64 DN_OS_TimerNs(DN_OSTimer timer) { - Dqn_f64 result = Dqn_OS_PerfCounterNs(timer.start, timer.end); + DN_F64 result = DN_OS_PerfCounterNs(timer.start, timer.end); return result; } -DQN_API uint64_t Dqn_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency) +DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency) { - uint64_t os_frequency = Dqn_OS_PerfCounterFrequency(); + uint64_t os_frequency = DN_OS_PerfCounterFrequency(); uint64_t os_target_elapsed = duration_ms_to_gauge_tsc_frequency * os_frequency / 1000ULL; - uint64_t tsc_begin = Dqn_CPU_TSC(); + uint64_t tsc_begin = DN_CPU_TSC(); uint64_t result = 0; if (tsc_begin) { uint64_t os_elapsed = 0; - for (uint64_t os_begin = Dqn_OS_PerfCounterNow(); os_elapsed < os_target_elapsed; ) - os_elapsed = Dqn_OS_PerfCounterNow() - os_begin; - uint64_t tsc_end = Dqn_CPU_TSC(); + for (uint64_t os_begin = DN_OS_PerfCounterNow(); os_elapsed < os_target_elapsed; ) + os_elapsed = DN_OS_PerfCounterNow() - os_begin; + uint64_t tsc_end = DN_CPU_TSC(); uint64_t tsc_elapsed = tsc_end - tsc_begin; result = tsc_elapsed / os_elapsed * os_frequency; } return result; } -#if !defined(DQN_NO_OS_FILE_API) -// NOTE: [$FILE] Dqn_OSPathInfo/File /////////////////////////////////////////////////////////////// -DQN_API bool Dqn_OS_FileIsOlderThan(Dqn_Str8 file, Dqn_Str8 check_against) +#if !defined(DN_NO_OS_FILE_API) +// NOTE: [$FILE] DN_OSPathInfo/File /////////////////////////////////////////////////////////////// +DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against) { - Dqn_OSPathInfo file_info = Dqn_OS_PathInfo(file); - Dqn_OSPathInfo check_against_info = Dqn_OS_PathInfo(check_against); + DN_OSPathInfo file_info = DN_OS_PathInfo(file); + DN_OSPathInfo check_against_info = DN_OS_PathInfo(check_against); bool result = !file_info.exists || file_info.last_write_time_in_s < check_against_info.last_write_time_in_s; return result; } -DQN_API bool Dqn_OS_FileWrite(Dqn_OSFile *file, Dqn_Str8 buffer, Dqn_ErrorSink *error) +DN_API bool DN_OS_FileWrite(DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *error) { - bool result = Dqn_OS_FileWritePtr(file, buffer.data, buffer.size, error); + bool result = DN_OS_FileWritePtr(file, buffer.data, buffer.size, error); return result; } -DQN_API bool Dqn_OS_FileWriteFV(Dqn_OSFile *file, Dqn_ErrorSink *error, DQN_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) return result; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args); - result = Dqn_OS_FileWritePtr(file, buffer.data, buffer.size, error); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args); + result = DN_OS_FileWritePtr(file, buffer.data, buffer.size, error); return result; } -DQN_API bool Dqn_OS_FileWriteF(Dqn_OSFile *file, Dqn_ErrorSink *error, DQN_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); - bool result = Dqn_OS_FileWriteFV(file, error, fmt, args); + bool result = DN_OS_FileWriteFV(file, error, fmt, args); va_end(args); return result; } // NOTE: R/W Entire File /////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8 Dqn_OS_ReadAll(Dqn_Arena *arena, Dqn_Str8 path, Dqn_ErrorSink *error) +DN_API DN_Str8 DN_OS_ReadAll(DN_Arena *arena, DN_Str8 path, DN_ErrSink *error) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; if (!arena) return result; // NOTE: Query file size + allocate buffer ///////////////////////////////////////////////////// - Dqn_OSPathInfo path_info = Dqn_OS_PathInfo(path); + DN_OSPathInfo path_info = DN_OS_PathInfo(path); if (!path_info.exists) { - Dqn_ErrorSink_MakeF(error, 1, "File does not exist/could not be queried for reading '%.*s'", DQN_STR_FMT(path)); + DN_ErrSink_AppendF(error, 1, "File does not exist/could not be queried for reading '%.*s'", DN_STR_FMT(path)); return result; } - Dqn_ArenaTempMem temp_mem = Dqn_Arena_TempMemBegin(arena); - result = Dqn_Str8_Alloc(arena, path_info.size, Dqn_ZeroMem_No); - if (!Dqn_Str8_HasData(result)) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 buffer_size_str8 = Dqn_U64ToByteSizeStr8(tmem.arena, path_info.size, Dqn_U64ByteSizeType_Auto); - Dqn_ErrorSink_MakeF(error, 1 /*error_code*/, "Failed to allocate %.*s for reading file '%.*s'", DQN_STR_FMT(buffer_size_str8), DQN_STR_FMT(path)); - Dqn_Arena_TempMemEnd(temp_mem); + DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(arena); + result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No); + if (!DN_Str8_HasData(result)) { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 buffer_size_str8 = DN_U64ToByteSizeStr8(tmem.arena, path_info.size, DN_U64ByteSizeType_Auto); + DN_ErrSink_AppendF(error, 1 /*error_code*/, "Failed to allocate %.*s for reading file '%.*s'", DN_STR_FMT(buffer_size_str8), DN_STR_FMT(path)); + DN_Arena_TempMemEnd(temp_mem); result = {}; return result; } // NOTE: Read the file from disk /////////////////////////////////////////////////////////////// - Dqn_OSFile file = Dqn_OS_FileOpen(path, Dqn_OSFileOpen_OpenIfExist, Dqn_OSFileAccess_Read, error); - bool read_failed = !Dqn_OS_FileRead(&file, result.data, result.size, error); + DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, error); + bool read_failed = !DN_OS_FileRead(&file, result.data, result.size, error); if (file.error || read_failed) { - Dqn_Arena_TempMemEnd(temp_mem); + DN_Arena_TempMemEnd(temp_mem); result = {}; } - Dqn_OS_FileClose(&file); + DN_OS_FileClose(&file); return result; } -DQN_API bool Dqn_OS_WriteAll(Dqn_Str8 path, Dqn_Str8 buffer, Dqn_ErrorSink *error) +DN_API bool DN_OS_WriteAll(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error) { - Dqn_OSFile file = Dqn_OS_FileOpen(path, Dqn_OSFileOpen_CreateAlways, Dqn_OSFileAccess_Write, error); - bool result = Dqn_OS_FileWrite(&file, buffer, error); - Dqn_OS_FileClose(&file); + DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_Write, error); + bool result = DN_OS_FileWrite(&file, buffer, error); + DN_OS_FileClose(&file); return result; } -DQN_API bool Dqn_OS_WriteAllFV(Dqn_Str8 file_path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_WriteAllFV(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args); - bool result = Dqn_OS_WriteAll(file_path, buffer, error); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args); + bool result = DN_OS_WriteAll(file_path, buffer, error); return result; } -DQN_API bool Dqn_OS_WriteAllF(Dqn_Str8 file_path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_WriteAllF(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - bool result = Dqn_OS_WriteAllFV(file_path, error, fmt, args); + bool result = DN_OS_WriteAllFV(file_path, error, fmt, args); va_end(args); return result; } -DQN_API bool Dqn_OS_WriteAllSafe(Dqn_Str8 path, Dqn_Str8 buffer, Dqn_ErrorSink *error) +DN_API bool DN_OS_WriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 tmp_path = Dqn_Str8_InitF(tmem.arena, "%.*s.tmp", DQN_STR_FMT(path)); - if (!Dqn_OS_WriteAll(tmp_path, buffer, error)) + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 tmp_path = DN_Str8_InitF(tmem.arena, "%.*s.tmp", DN_STR_FMT(path)); + if (!DN_OS_WriteAll(tmp_path, buffer, error)) return false; - if (!Dqn_OS_CopyFile(tmp_path, path, true /*overwrite*/, error)) + if (!DN_OS_CopyFile(tmp_path, path, true /*overwrite*/, error)) return false; - if (!Dqn_OS_PathDelete(tmp_path)) + if (!DN_OS_PathDelete(tmp_path)) return false; return true; } -DQN_API bool Dqn_OS_WriteAllSafeFV(Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_WriteAllSafeFV(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args); - bool result = Dqn_OS_WriteAllSafe(path, buffer, error); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args); + bool result = DN_OS_WriteAllSafe(path, buffer, error); return result; } -DQN_API bool Dqn_OS_WriteAllSafeF(Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_WriteAllSafeF(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - bool result = Dqn_OS_WriteAllSafeFV(path, error, fmt, args); + bool result = DN_OS_WriteAllSafeFV(path, error, fmt, args); return result; } -#endif // !defined(DQN_NO_OS_FILE_API) +#endif // !defined(DN_NO_OS_FILE_API) -// NOTE: [$PATH] Dqn_OSPath //////////////////////////////////////////////////////////////////////// -DQN_API bool Dqn_OS_PathAddRef(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path) +// NOTE: [$PATH] DN_OSPath //////////////////////////////////////////////////////////////////////// +DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) { - if (!arena || !fs_path || !Dqn_Str8_HasData(path)) + if (!arena || !fs_path || !DN_Str8_HasData(path)) return false; if (path.size <= 0) return true; - Dqn_Str8 const delimiter_array[] = { - DQN_STR8("\\"), - DQN_STR8("/") + DN_Str8 const delimiter_array[] = { + DN_STR8("\\"), + DN_STR8("/") }; if (fs_path->links_size == 0) { @@ -316,12 +322,12 @@ DQN_API bool Dqn_OS_PathAddRef(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 p } for (;;) { - Dqn_Str8BinarySplitResult delimiter = Dqn_Str8_BinarySplitArray(path, delimiter_array, DQN_ARRAY_UCOUNT(delimiter_array)); - for (; delimiter.lhs.data; delimiter = Dqn_Str8_BinarySplitArray(delimiter.rhs, delimiter_array, DQN_ARRAY_UCOUNT(delimiter_array))) { + DN_Str8BinarySplitResult delimiter = DN_Str8_BinarySplitArray(path, delimiter_array, DN_ARRAY_UCOUNT(delimiter_array)); + for (; delimiter.lhs.data; delimiter = DN_Str8_BinarySplitArray(delimiter.rhs, delimiter_array, DN_ARRAY_UCOUNT(delimiter_array))) { if (delimiter.lhs.size <= 0) continue; - Dqn_OSPathLink *link = Dqn_Arena_New(arena, Dqn_OSPathLink, Dqn_ZeroMem_Yes); + DN_OSPathLink *link = DN_Arena_New(arena, DN_OSPathLink, DN_ZeroMem_Yes); if (!link) return false; @@ -344,30 +350,30 @@ DQN_API bool Dqn_OS_PathAddRef(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 p return true; } -DQN_API bool Dqn_OS_PathAdd(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path) +DN_API bool DN_OS_PathAdd(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) { - Dqn_Str8 copy = Dqn_Str8_Copy(arena, path); - bool result = Dqn_Str8_HasData(copy) ? true : Dqn_OS_PathAddRef(arena, fs_path, copy); + DN_Str8 copy = DN_Str8_Copy(arena, path); + bool result = DN_Str8_HasData(copy) ? true : DN_OS_PathAddRef(arena, fs_path, copy); return result; } -DQN_API bool Dqn_OS_PathAddF(Dqn_Arena *arena, Dqn_OSPath *fs_path, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_PathAddF(DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_Str8 path = Dqn_Str8_InitFV(arena, fmt, args); + DN_Str8 path = DN_Str8_InitFV(arena, fmt, args); va_end(args); - bool result = Dqn_OS_PathAddRef(arena, fs_path, path); + bool result = DN_OS_PathAddRef(arena, fs_path, path); return result; } -DQN_API bool Dqn_OS_PathPop(Dqn_OSPath *fs_path) +DN_API bool DN_OS_PathPop(DN_OSPath *fs_path) { if (!fs_path) return false; if (fs_path->tail) { - DQN_ASSERT(fs_path->head); + DN_ASSERT(fs_path->head); fs_path->links_size -= 1; fs_path->string_size -= fs_path->tail->string.size; fs_path->tail = fs_path->tail->prev; @@ -377,71 +383,71 @@ DQN_API bool Dqn_OS_PathPop(Dqn_OSPath *fs_path) fs_path->head = nullptr; } } else { - DQN_ASSERT(!fs_path->head); + DN_ASSERT(!fs_path->head); } return true; } -DQN_API Dqn_Str8 Dqn_OS_PathTo(Dqn_Arena *arena, Dqn_Str8 path, Dqn_Str8 path_separator) +DN_API DN_Str8 DN_OS_PathTo(DN_Arena *arena, DN_Str8 path, DN_Str8 path_separator) { - Dqn_OSPath fs_path = {}; - Dqn_OS_PathAddRef(arena, &fs_path, path); - Dqn_Str8 result = Dqn_OS_PathBuildWithSeparator(arena, &fs_path, path_separator); + DN_OSPath fs_path = {}; + DN_OS_PathAddRef(arena, &fs_path, path); + DN_Str8 result = DN_OS_PathBuildWithSeparator(arena, &fs_path, path_separator); return result; } -DQN_API Dqn_Str8 Dqn_OS_PathToF(Dqn_Arena *arena, Dqn_Str8 path_separator, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API DN_Str8 DN_OS_PathToF(DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); + DN_TLSTMem tmem = DN_TLS_TMem(arena); va_list args; va_start(args, fmt); - Dqn_Str8 path = Dqn_Str8_InitFV(tmem.arena, fmt, args); + DN_Str8 path = DN_Str8_InitFV(tmem.arena, fmt, args); va_end(args); - Dqn_Str8 result = Dqn_OS_PathTo(arena, path, path_separator); + DN_Str8 result = DN_OS_PathTo(arena, path, path_separator); return result; } -DQN_API Dqn_Str8 Dqn_OS_Path(Dqn_Arena *arena, Dqn_Str8 path) +DN_API DN_Str8 DN_OS_Path(DN_Arena *arena, DN_Str8 path) { - Dqn_Str8 result = Dqn_OS_PathTo(arena, path, Dqn_OSPathSeperatorString); + DN_Str8 result = DN_OS_PathTo(arena, path, DN_OSPathSeperatorString); return result; } -DQN_API Dqn_Str8 Dqn_OS_PathF(Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API DN_Str8 DN_OS_PathF(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); + DN_TLSTMem tmem = DN_TLS_TMem(arena); va_list args; va_start(args, fmt); - Dqn_Str8 path = Dqn_Str8_InitFV(tmem.arena, fmt, args); + DN_Str8 path = DN_Str8_InitFV(tmem.arena, fmt, args); va_end(args); - Dqn_Str8 result = Dqn_OS_Path(arena, path); + DN_Str8 result = DN_OS_Path(arena, path); return result; } -DQN_API Dqn_Str8 Dqn_OS_PathBuildWithSeparator(Dqn_Arena *arena, Dqn_OSPath const *fs_path, Dqn_Str8 path_separator) +DN_API DN_Str8 DN_OS_PathBuildWithSeparator(DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; if (!fs_path || fs_path->links_size <= 0) return result; // NOTE: Each link except the last one needs the path separator appended to it, '/' or '\\' - Dqn_usize string_size = (fs_path->has_prefix_path_separator ? path_separator.size : 0) + fs_path->string_size + ((fs_path->links_size - 1) * path_separator.size); - result = Dqn_Str8_Alloc(arena, string_size, Dqn_ZeroMem_No); + DN_USize string_size = (fs_path->has_prefix_path_separator ? path_separator.size : 0) + fs_path->string_size + ((fs_path->links_size - 1) * path_separator.size); + result = DN_Str8_Alloc(arena, string_size, DN_ZeroMem_No); if (result.data) { char *dest = result.data; if (fs_path->has_prefix_path_separator) { - DQN_MEMCPY(dest, path_separator.data, path_separator.size); + DN_MEMCPY(dest, path_separator.data, path_separator.size); dest += path_separator.size; } - for (Dqn_OSPathLink *link = fs_path->head; link; link = link->next) { - Dqn_Str8 string = link->string; - DQN_MEMCPY(dest, string.data, string.size); + for (DN_OSPathLink *link = fs_path->head; link; link = link->next) { + DN_Str8 string = link->string; + DN_MEMCPY(dest, string.data, string.size); dest += string.size; if (link != fs_path->tail) { - DQN_MEMCPY(dest, path_separator.data, path_separator.size); + DN_MEMCPY(dest, path_separator.data, path_separator.size); dest += path_separator.size; } } @@ -452,24 +458,23 @@ DQN_API Dqn_Str8 Dqn_OS_PathBuildWithSeparator(Dqn_Arena *arena, Dqn_OSPath cons } -// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSExecResult Dqn_OS_Exec(Dqn_Slice cmd_line, - Dqn_Str8 working_dir, - uint8_t exec_flags, - Dqn_Arena *arena, - Dqn_ErrorSink *error) +// NOTE: [$EXEC] DN_OSExec //////////////////////////////////////////////////////////////////////// +DN_API DN_OSExecResult DN_OS_Exec(DN_Slice cmd_line, + DN_OSExecArgs *args, + DN_Arena *arena, + DN_ErrSink *error) { - Dqn_OSExecAsyncHandle async_handle = Dqn_OS_ExecAsync(cmd_line, working_dir, exec_flags, error); - Dqn_OSExecResult result = Dqn_OS_ExecWait(async_handle, arena, error); + DN_OSExecAsyncHandle async_handle = DN_OS_ExecAsync(cmd_line, args, error); + DN_OSExecResult result = DN_OS_ExecWait(async_handle, arena, error); return result; } -DQN_API Dqn_OSExecResult Dqn_OS_ExecOrAbort(Dqn_Slice cmd_line, Dqn_Str8 working_dir, uint8_t exec_flags, Dqn_Arena *arena) +DN_API DN_OSExecResult DN_OS_ExecOrAbort(DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena) { - Dqn_ErrorSink *error = Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode_Nil); - Dqn_OSExecResult result = Dqn_OS_Exec(cmd_line, working_dir, exec_flags, arena, error); + DN_ErrSink *error = DN_ErrSink_Begin(DN_ErrSinkMode_Nil); + DN_OSExecResult result = DN_OS_Exec(cmd_line, args, arena, error); if (result.os_error_code) { - Dqn_ErrorSink_EndAndExitIfErrorF( + DN_ErrSink_EndAndExitIfErrorF( error, result.os_error_code, "OS failed to execute the requested command returning the error code %u", @@ -477,49 +482,63 @@ DQN_API Dqn_OSExecResult Dqn_OS_ExecOrAbort(Dqn_Slice cmd_line, Dqn_St } if (result.exit_code) { - Dqn_ErrorSink_EndAndExitIfErrorF( + DN_ErrSink_EndAndExitIfErrorF( error, result.exit_code, "OS executed command and returned non-zero exit code %u", result.exit_code); } - Dqn_ErrorSink_EndAndIgnore(error); + DN_ErrSink_EndAndIgnore(error); return result; } -// NOTE: [$THRD] Dqn_OSThread ////////////////////////////////////////////////////////////////////// -DQN_THREAD_LOCAL Dqn_TLS *g_dqn_os_thread_tls; +// NOTE: [$THRD] DN_OSThread ////////////////////////////////////////////////////////////////////// +DN_THREAD_LOCAL DN_TLS *g_dn_os_thread_tls; -static void Dqn_OS_ThreadExecute_(void *user_context) +static void DN_OS_ThreadExecute_(void *user_context) { - Dqn_OSThread *thread = DQN_CAST(Dqn_OSThread *)user_context; - Dqn_TLS_Init(&thread->tls); - Dqn_OS_ThreadSetTLS(&thread->tls); - Dqn_OS_SemaphoreWait(&thread->init_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); + DN_OSThread *thread = DN_CAST(DN_OSThread *)user_context; + DN_TLS_Init(&thread->tls); + DN_OS_ThreadSetTLS(&thread->tls); + DN_OS_SemaphoreWait(&thread->init_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); thread->func(thread); } -DQN_API void Dqn_OS_ThreadSetTLS(Dqn_TLS *tls) +DN_API void DN_OS_ThreadSetTLS(DN_TLS *tls) { - g_dqn_os_thread_tls = tls; + g_dn_os_thread_tls = tls; } -// NOTE: [$HTTP] Dqn_OSHttp //////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_OS_HttpRequestWait(Dqn_OSHttpResponse *response) +DN_API void DN_OS_ThreadSetName(DN_Str8 name) { - if (response && Dqn_OS_SemaphoreIsValid(&response->on_complete_semaphore)) - Dqn_OS_SemaphoreWait(&response->on_complete_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); + DN_TLS *tls = DN_TLS_Get(); + 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; + + #if defined(DN_OS_WIN32) + DN_Win_ThreadSetName(name); + #else + DN_Posix_ThreadSetName(name); + #endif } -DQN_API Dqn_OSHttpResponse Dqn_OS_HttpRequest(Dqn_Arena *arena, Dqn_Str8 host, Dqn_Str8 path, Dqn_OSHttpRequestSecure secure, Dqn_Str8 method, Dqn_Str8 body, Dqn_Str8 headers) +// NOTE: [$HTTP] DN_OSHttp //////////////////////////////////////////////////////////////////////// +DN_API void DN_OS_HttpRequestWait(DN_OSHttpResponse *response) +{ + if (response && DN_OS_SemaphoreIsValid(&response->on_complete_semaphore)) + DN_OS_SemaphoreWait(&response->on_complete_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); +} + +DN_API DN_OSHttpResponse DN_OS_HttpRequest(DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers) { // TODO(doyle): Revise the memory allocation and its lifetime - Dqn_OSHttpResponse result = {}; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); + DN_OSHttpResponse result = {}; + DN_TLSTMem tmem = DN_TLS_TMem(arena); result.tmem_arena = tmem.arena; - Dqn_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers); - Dqn_OS_HttpRequestWait(&result); + DN_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers); + DN_OS_HttpRequestWait(&result); return result; } diff --git a/dqn_os.h b/dqn_os.h index 0f9fbec..6ab5420 100644 --- a/dqn_os.h +++ b/dqn_os.h @@ -17,77 +17,77 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // -// [$OMEM] Dqn_OSMem -- -- Memory allocation (typically virtual memory if supported) -// [$DATE] Dqn_OSDate -- -- Date time APIs -// [$FILE] Dqn_OSPathInfo/File -- -- File path info/reading/writing -// [$PATH] Dqn_OSPath -- -- Construct native OS paths helpers -// [$EXEC] Dqn_OSExec -- -- Execute programs programatically -// [$SEMA] Dqn_OSSemaphore -- DQN_SEMAPHORE -- -// [$MUTX] Dqn_OSMutex -- -- -// [$THRD] Dqn_OSThread -- DQN_THREAD -- -// [$HTTP] Dqn_OSHttp -- -- +// [$OMEM] DN_OSMem -- -- Memory allocation (typically virtual memory if supported) +// [$DATE] DN_OSDate -- -- Date time APIs +// [$FILE] DN_OSPathInfo/File -- -- File path info/reading/writing +// [$PATH] DN_OSPath -- -- Construct native OS paths helpers +// [$EXEC] DN_OSExec -- -- Execute programs programatically +// [$SEMA] DN_OSSemaphore -- DN_SEMAPHORE -- +// [$MUTX] DN_OSMutex -- -- +// [$THRD] DN_OSThread -- DN_THREAD -- +// [$HTTP] DN_OSHttp -- -- // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$OMEM] Dqn_OSMem ////////////////////////////////////////////////////////////////////////// -enum Dqn_OSMemCommit +// NOTE: [$OMEM] DN_OSMem ////////////////////////////////////////////////////////////////////////// +enum DN_OSMemCommit { - Dqn_OSMemCommit_No, - Dqn_OSMemCommit_Yes, + DN_OSMemCommit_No, + DN_OSMemCommit_Yes, }; -enum Dqn_OSMemPage +enum DN_OSMemPage { // Exception on read/write with a page. This flag overrides the read/write // access. - Dqn_OSMemPage_NoAccess = 1 << 0, + DN_OSMemPage_NoAccess = 1 << 0, - Dqn_OSMemPage_Read = 1 << 1, // Only read permitted on the page. + DN_OSMemPage_Read = 1 << 1, // Only read permitted on the page. // Only write permitted on the page. On Windows this is not supported and // will be promoted to read+write permissions. - Dqn_OSMemPage_Write = 1 << 2, + DN_OSMemPage_Write = 1 << 2, - Dqn_OSMemPage_ReadWrite = Dqn_OSMemPage_Read | Dqn_OSMemPage_Write, + DN_OSMemPage_ReadWrite = DN_OSMemPage_Read | DN_OSMemPage_Write, // Modifier used in conjunction with previous flags. Raises exception on // first access to the page, then, the underlying protection flags are // active. This is supported on Windows, on other OS's using this flag will - // set the OS equivalent of Dqn_OSMemPage_NoAccess. - // This flag must only be used in Dqn_OSMem_Protect - Dqn_OSMemPage_Guard = 1 << 3, + // set the OS equivalent of DN_OSMemPage_NoAccess. + // This flag must only be used in DN_OSMem_Protect + DN_OSMemPage_Guard = 1 << 3, // If leak tracing is enabled, this flag will allow the allocation recorded // from the reserve call to be leaked, e.g. not printed when leaks are // dumped to the console. - Dqn_OSMemPage_AllocRecordLeakPermitted = 1 << 4, + DN_OSMemPage_AllocRecordLeakPermitted = 1 << 4, // If leak tracing is enabled this flag will prevent any allocation record // from being created in the allocation table at all. If this flag is // enabled, 'OSMemPage_AllocRecordLeakPermitted' has no effect since the // record will never be created. - Dqn_OSMemPage_NoAllocRecordEntry = 1 << 5, + DN_OSMemPage_NoAllocRecordEntry = 1 << 5, // [INTERNAL] Do not use. All flags together do not constitute a correct // configuration of pages. - Dqn_OSMemPage_All = Dqn_OSMemPage_NoAccess | - Dqn_OSMemPage_ReadWrite | - Dqn_OSMemPage_Guard | - Dqn_OSMemPage_AllocRecordLeakPermitted | - Dqn_OSMemPage_NoAllocRecordEntry, + DN_OSMemPage_All = DN_OSMemPage_NoAccess | + DN_OSMemPage_ReadWrite | + DN_OSMemPage_Guard | + DN_OSMemPage_AllocRecordLeakPermitted | + DN_OSMemPage_NoAllocRecordEntry, }; -// NOTE: [$DATE] Dqn_OSDate //////////////////////////////////////////////////////////////////////// -struct Dqn_OSDateTimeStr8 +// NOTE: [$DATE] DN_OSDate //////////////////////////////////////////////////////////////////////// +struct DN_OSDateTimeStr8 { - char date[DQN_ARRAY_UCOUNT("YYYY-MM-SS")]; + char date[DN_ARRAY_UCOUNT("YYYY-MM-SS")]; uint8_t date_size; - char hms[DQN_ARRAY_UCOUNT("HH:MM:SS")]; + char hms[DN_ARRAY_UCOUNT("HH:MM:SS")]; uint8_t hms_size; }; -struct Dqn_OSDateTime +struct DN_OSDateTime { uint8_t day; uint8_t month; @@ -97,126 +97,136 @@ struct Dqn_OSDateTime uint8_t seconds; }; -struct Dqn_OSTimer /// Record time between two time-points using the OS's performance counter. +struct DN_OSTimer /// Record time between two time-points using the OS's performance counter. { uint64_t start; uint64_t end; }; -#if !defined(DQN_NO_OS_FILE_API) -// NOTE: [$FSYS] Dqn_OSFile //////////////////////////////////////////////////////////////////////// -enum Dqn_OSPathInfoType +#if !defined(DN_NO_OS_FILE_API) +// NOTE: [$FSYS] DN_OSFile //////////////////////////////////////////////////////////////////////// +enum DN_OSPathInfoType { - Dqn_OSPathInfoType_Unknown, - Dqn_OSPathInfoType_Directory, - Dqn_OSPathInfoType_File, + DN_OSPathInfoType_Unknown, + DN_OSPathInfoType_Directory, + DN_OSPathInfoType_File, }; -struct Dqn_OSPathInfo +struct DN_OSPathInfo { bool exists; - Dqn_OSPathInfoType type; + DN_OSPathInfoType type; uint64_t create_time_in_s; uint64_t last_write_time_in_s; uint64_t last_access_time_in_s; uint64_t size; }; -struct Dqn_OS_DirIterator +struct DN_OSDirIterator { void *handle; - Dqn_Str8 file_name; + DN_Str8 file_name; char buffer[512]; }; // NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// -struct Dqn_OSFile +struct DN_OSFile { bool error; void *handle; }; -enum Dqn_OSFileOpen +enum DN_OSFileOpen { - Dqn_OSFileOpen_CreateAlways, // Create file if it does not exist, otherwise, zero out the file and open - Dqn_OSFileOpen_OpenIfExist, // Open file at path only if it exists - Dqn_OSFileOpen_OpenAlways, // Open file at path, create file if it does not exist + DN_OSFileOpen_CreateAlways, // Create file if it does not exist, otherwise, zero out the file and open + DN_OSFileOpen_OpenIfExist, // Open file at path only if it exists + DN_OSFileOpen_OpenAlways, // Open file at path, create file if it does not exist }; -enum Dqn_OSFileAccess +typedef uint32_t DN_OSFileAccess; +enum DN_OSFileAccess_ { - Dqn_OSFileAccess_Read = 1 << 0, - Dqn_OSFileAccess_Write = 1 << 1, - Dqn_OSFileAccess_Execute = 1 << 2, - Dqn_OSFileAccess_AppendOnly = 1 << 3, // This flag cannot be combined with any other access mode - Dqn_OSFileAccess_ReadWrite = Dqn_OSFileAccess_Read | Dqn_OSFileAccess_Write, - Dqn_OSFileAccess_All = Dqn_OSFileAccess_ReadWrite | Dqn_OSFileAccess_Execute, + DN_OSFileAccess_Read = 1 << 0, + DN_OSFileAccess_Write = 1 << 1, + DN_OSFileAccess_Execute = 1 << 2, + DN_OSFileAccess_AppendOnly = 1 << 3, // This flag cannot be combined with any other access mode + DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write, + DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly, }; -#endif // DQN_NO_OS_FILE_API +#endif // DN_NO_OS_FILE_API -// NOTE: Dqn_OSPath //////////////////////////////////////////////////////////////////////////////// -#if !defined(Dqn_OSPathSeperator) - #if defined(DQN_OS_WIN32) - #define Dqn_OSPathSeperator "\\" +// NOTE: DN_OSPath //////////////////////////////////////////////////////////////////////////////// +#if !defined(DN_OSPathSeperator) + #if defined(DN_OS_WIN32) + #define DN_OSPathSeperator "\\" #else - #define Dqn_OSPathSeperator "/" + #define DN_OSPathSeperator "/" #endif - #define Dqn_OSPathSeperatorString DQN_STR8(Dqn_OSPathSeperator) + #define DN_OSPathSeperatorString DN_STR8(DN_OSPathSeperator) #endif -struct Dqn_OSPathLink +struct DN_OSPathLink { - Dqn_Str8 string; - Dqn_OSPathLink *next; - Dqn_OSPathLink *prev; + DN_Str8 string; + DN_OSPathLink *next; + DN_OSPathLink *prev; }; -struct Dqn_OSPath +struct DN_OSPath { bool has_prefix_path_separator; - Dqn_OSPathLink *head; - Dqn_OSPathLink *tail; - Dqn_usize string_size; + DN_OSPathLink *head; + DN_OSPathLink *tail; + DN_USize string_size; uint16_t links_size; }; -// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// -enum Dqn_OSExecFlag +// NOTE: [$EXEC] DN_OSExec //////////////////////////////////////////////////////////////////////// +typedef uint32_t DN_OSExecFlags; +enum DN_OSExecFlags_ { - Dqn_OSExecFlag_Nil = 0, - Dqn_OSExecFlag_SaveStdout = 1 << 0, - Dqn_OSExecFlag_SaveStderr = 1 << 1, - Dqn_OSExecFlag_SaveOutput = Dqn_OSExecFlag_SaveStdout | Dqn_OSExecFlag_SaveStderr, - Dqn_OSExecFlag_MergeStderrToStdout = 1 << 2 | Dqn_OSExecFlag_SaveOutput, + DN_OSExecFlags_Nil = 0, + DN_OSExecFlags_SaveStdout = 1 << 0, + DN_OSExecFlags_SaveStderr = 1 << 1, + DN_OSExecFlags_SaveOutput = DN_OSExecFlags_SaveStdout | DN_OSExecFlags_SaveStderr, + DN_OSExecFlags_MergeStderrToStdout = 1 << 2 | DN_OSExecFlags_SaveOutput, }; -struct Dqn_OSExecAsyncHandle +struct DN_OSExecAsyncHandle { - uint8_t exec_flags; - uint32_t os_error_code; - uint32_t exit_code; - void *process; - void *stdout_read; - void *stdout_write; - void *stderr_read; - void *stderr_write; + DN_OSExecFlags exec_flags; + uint32_t os_error_code; + uint32_t exit_code; + void *process; + void *stdout_read; + void *stdout_write; + void *stderr_read; + void *stderr_write; }; -struct Dqn_OSExecResult +struct DN_OSExecResult { - Dqn_Str8 stdout_text; - Dqn_Str8 stderr_text; + bool finished; + DN_Str8 stdout_text; + DN_Str8 stderr_text; uint32_t os_error_code; uint32_t exit_code; }; -#if !defined(DQN_NO_SEMAPHORE) -// NOTE: [$SEMA] Dqn_OSSemaphore /////////////////////////////////////////////////////////////////// -uint32_t const DQN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; - -struct Dqn_OSSemaphore +struct DN_OSExecArgs { - #if defined(DQN_OS_WIN32) && !defined(DQN_OS_WIN32_USE_PTHREADS) + DN_OSExecFlags flags; + DN_Str8 working_dir; + DN_Slice environment; +}; + +#if !defined(DN_NO_SEMAPHORE) +// NOTE: [$SEMA] DN_OSSemaphore /////////////////////////////////////////////////////////////////// +uint32_t const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX; + +struct DN_OSSemaphore +{ + #if defined(DN_OS_WIN32) && !defined(DN_OS_WIN32_USE_PTHREADS) void *win32_handle; #else sem_t posix_handle; @@ -224,189 +234,212 @@ struct Dqn_OSSemaphore #endif }; -enum Dqn_OSSemaphoreWaitResult +enum DN_OSSemaphoreWaitResult { - Dqn_OSSemaphoreWaitResult_Failed, - Dqn_OSSemaphoreWaitResult_Success, - Dqn_OSSemaphoreWaitResult_Timeout, + DN_OSSemaphoreWaitResult_Failed, + DN_OSSemaphoreWaitResult_Success, + DN_OSSemaphoreWaitResult_Timeout, }; -#endif // !defined(DQN_NO_SEMAPHORE) +#endif // !defined(DN_NO_SEMAPHORE) -// NOTE: [$THRD] Dqn_OSThread ///////////////////////////////////////////////////////////////////// -#if !defined(DQN_NO_THREAD) && !defined(DQN_NO_SEMAPHORE) -typedef int32_t (Dqn_OSThreadFunc)(struct Dqn_OSThread*); +// NOTE: [$THRD] DN_OSThread ///////////////////////////////////////////////////////////////////// +#if !defined(DN_NO_THREAD) && !defined(DN_NO_SEMAPHORE) +typedef int32_t (DN_OSThreadFunc)(struct DN_OSThread*); -struct Dqn_OSThread +struct DN_OSThread { - Dqn_TLS tls; + DN_FStr8<64> name; + DN_TLS tls; void *handle; uint64_t thread_id; void *user_context; - Dqn_OSThreadFunc *func; - Dqn_OSSemaphore init_semaphore; + DN_OSThreadFunc *func; + DN_OSSemaphore init_semaphore; }; -#endif // !defined(DQN_NO_THREAD) +#endif // !defined(DN_NO_THREAD) -// NOTE: [$HTTP] Dqn_OSHttp //////////////////////////////////////////////////////////////////////// -enum Dqn_OSHttpRequestSecure +// NOTE: [$HTTP] DN_OSHttp //////////////////////////////////////////////////////////////////////// +enum DN_OSHttpRequestSecure { - Dqn_OSHttpRequestSecure_No, - Dqn_OSHttpRequestSecure_Yes, + DN_OSHttpRequestSecure_No, + DN_OSHttpRequestSecure_Yes, }; -struct Dqn_OSHttpResponse +struct DN_OSHttpResponse { // NOTE: Response data uint32_t error_code; - Dqn_Str8 error_msg; + DN_Str8 error_msg; uint16_t http_status; - Dqn_Str8 body; - Dqn_b32 done; + DN_Str8 body; + DN_B32 done; // NOTE: Book-keeping - Dqn_Arena *arena; // Allocates memory for the response + DN_Arena *arena; // Allocates memory for the response // NOTE: Async book-keeping // Synchronous HTTP response uses the TLS scratch arena whereas async // calls use their own dedicated arena. - Dqn_Arena tmp_arena; - Dqn_Arena *tmem_arena; - Dqn_Str8Builder builder; - Dqn_OSSemaphore on_complete_semaphore; + DN_Arena tmp_arena; + DN_Arena *tmem_arena; + DN_Str8Builder builder; + DN_OSSemaphore on_complete_semaphore; - #if defined(DQN_PLATFORM_EMSCRIPTEN) + #if defined(DN_PLATFORM_EMSCRIPTEN) emscripten_fetch_t *em_handle; - #elif defined(DQN_OS_WIN32) + #elif defined(DN_OS_WIN32) HINTERNET win32_request_session; HINTERNET win32_request_connection; HINTERNET win32_request_handle; #endif }; +DN_API void DN_OS_Init(); + // NOTE: [$OMEM] Memory ////////////////////////////////////////////////////////////////////////// -DQN_API void * Dqn_OS_MemReserve (Dqn_usize size, Dqn_OSMemCommit commit, uint32_t page_flags); -DQN_API bool Dqn_OS_MemCommit (void *ptr, Dqn_usize size, uint32_t page_flags); -DQN_API void Dqn_OS_MemDecommit(void *ptr, Dqn_usize size); -DQN_API void Dqn_OS_MemRelease (void *ptr, Dqn_usize size); -DQN_API int Dqn_OS_MemProtect (void *ptr, Dqn_usize size, uint32_t page_flags); +DN_API void * DN_OS_MemReserve (DN_USize size, DN_OSMemCommit commit, uint32_t page_flags); +DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, uint32_t page_flags); +DN_API void DN_OS_MemDecommit(void *ptr, DN_USize size); +DN_API void DN_OS_MemRelease (void *ptr, DN_USize size); +DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, uint32_t page_flags); + +// NOTE: Heap +DN_API void *DN_OS_MemAlloc (DN_USize size, DN_ZeroMem zero_mem); +DN_API void DN_OS_MemDealloc (void *ptr); // NOTE: [$DATE] Date ////////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSDateTime Dqn_OS_DateLocalTimeNow (); -DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8Now(char date_separator = '-', char hms_separator = ':'); -DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8 (Dqn_OSDateTime time, char date_separator = '-', char hms_separator = ':'); -DQN_API uint64_t Dqn_OS_DateUnixTime (); -DQN_API Dqn_OSDateTime Dqn_OS_DateUnixTimeToDate (uint64_t time); -DQN_API uint64_t Dqn_OS_DateToUnixTime (Dqn_OSDateTime date); -DQN_API bool Dqn_OS_DateIsValid (Dqn_OSDateTime date); +DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); +DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator = '-', char hms_separator = ':'); +DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); +DN_API uint64_t DN_OS_DateUnixTimeNs (); +DN_API uint64_t DN_OS_DateUnixTimeS (); +DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (uint64_t time); +DN_API uint64_t DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date); +DN_API uint64_t DN_OS_DateToUnixTimeS (DN_OSDateTime date); +DN_API bool DN_OS_DateIsValid (DN_OSDateTime date); // NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DQN_API bool Dqn_OS_SecureRNGBytes (void *buffer, uint32_t size); -DQN_API Dqn_Str8 Dqn_OS_EXEPath (Dqn_Arena *arena); -DQN_API Dqn_Str8 Dqn_OS_EXEDir (Dqn_Arena *arena); -#define Dqn_OS_EXEDir_TLS() Dqn_OS_EXEDir(Dqn_TLS_TopArena()) -DQN_API void Dqn_OS_SleepMs (Dqn_uint milliseconds); -// NOTE: Counters ////////////////////////////////////////////////////////////////////////////////// -DQN_API uint64_t Dqn_OS_PerfCounterNow (); -DQN_API uint64_t Dqn_OS_PerfCounterFrequency(); -DQN_API Dqn_f64 Dqn_OS_PerfCounterS (uint64_t begin, uint64_t end); -DQN_API Dqn_f64 Dqn_OS_PerfCounterMs (uint64_t begin, uint64_t end); -DQN_API Dqn_f64 Dqn_OS_PerfCounterUs (uint64_t begin, uint64_t end); -DQN_API Dqn_f64 Dqn_OS_PerfCounterNs (uint64_t begin, uint64_t end); -DQN_API Dqn_OSTimer Dqn_OS_TimerBegin (); -DQN_API void Dqn_OS_TimerEnd (Dqn_OSTimer *timer); -DQN_API Dqn_f64 Dqn_OS_TimerS (Dqn_OSTimer timer); -DQN_API Dqn_f64 Dqn_OS_TimerMs (Dqn_OSTimer timer); -DQN_API Dqn_f64 Dqn_OS_TimerUs (Dqn_OSTimer timer); -DQN_API Dqn_f64 Dqn_OS_TimerNs (Dqn_OSTimer timer); -DQN_API uint64_t Dqn_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency); +DN_API bool DN_OS_SecureRNGBytes (void *buffer, uint32_t size); +DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); +DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena); +DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena); +#define DN_OS_EXEDir_TLS() DN_OS_EXEDir(DN_TLS_TopArena()) +DN_API void DN_OS_SleepMs (DN_UInt milliseconds); -#if !defined(DQN_NO_OS_FILE_API) +// NOTE: Counters ////////////////////////////////////////////////////////////////////////////////// +DN_API uint64_t DN_OS_PerfCounterNow (); +DN_API uint64_t DN_OS_PerfCounterFrequency(); +DN_API DN_F64 DN_OS_PerfCounterS (uint64_t begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterMs (uint64_t begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterUs (uint64_t begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterNs (uint64_t begin, uint64_t end); +DN_API DN_OSTimer DN_OS_TimerBegin (); +DN_API void DN_OS_TimerEnd (DN_OSTimer *timer); +DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer); +DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency); +#if !defined(DN_NO_OS_FILE_API) // NOTE: File system paths ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSPathInfo Dqn_OS_PathInfo (Dqn_Str8 path); -DQN_API bool Dqn_OS_FileIsOlderThan(Dqn_Str8 file, Dqn_Str8 check_against); -DQN_API bool Dqn_OS_PathDelete (Dqn_Str8 path); -DQN_API bool Dqn_OS_FileExists (Dqn_Str8 path); -DQN_API bool Dqn_OS_CopyFile (Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_ErrorSink *error); -DQN_API bool Dqn_OS_MoveFile (Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_ErrorSink *error); -DQN_API bool Dqn_OS_MakeDir (Dqn_Str8 path); -DQN_API bool Dqn_OS_DirExists (Dqn_Str8 path); -DQN_API bool Dqn_OS_DirIterate (Dqn_Str8 path, Dqn_OS_DirIterator *it); +DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path); +DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against); +DN_API bool DN_OS_PathDelete (DN_Str8 path); +DN_API bool DN_OS_FileExists (DN_Str8 path); +DN_API bool DN_OS_CopyFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err); +DN_API bool DN_OS_MoveFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err); +DN_API bool DN_OS_MakeDir (DN_Str8 path); +DN_API bool DN_OS_DirExists (DN_Str8 path); +DN_API bool DN_OS_DirIterate (DN_Str8 path, DN_OSDirIterator *it); // NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSFile Dqn_OS_FileOpen (Dqn_Str8 path, Dqn_OSFileOpen open_mode, uint32_t access, Dqn_ErrorSink *error); -DQN_API bool Dqn_OS_FileRead (Dqn_OSFile *file, void *buffer, Dqn_usize size, Dqn_ErrorSink *error); -DQN_API bool Dqn_OS_FileWritePtr(Dqn_OSFile *file, void const *data, Dqn_usize size, Dqn_ErrorSink *error); -DQN_API bool Dqn_OS_FileWrite (Dqn_OSFile *file, Dqn_Str8 buffer, Dqn_ErrorSink *error); -DQN_API bool Dqn_OS_FileWriteFV (Dqn_OSFile *file, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API bool Dqn_OS_FileWriteF (Dqn_OSFile *file, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API void Dqn_OS_FileClose (Dqn_OSFile *file); +DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_ErrSink *err); +DN_API bool 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); // NOTE: R/W Entire File /////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8 Dqn_OS_ReadAll (Dqn_Arena *arena, Dqn_Str8 path, Dqn_ErrorSink *error); -#define Dqn_OS_ReadAll_TLS(...) Dqn_OS_ReadAll(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API bool Dqn_OS_WriteAll (Dqn_Str8 path, Dqn_Str8 buffer, Dqn_ErrorSink *error); -DQN_API bool Dqn_OS_WriteAllFV (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API bool Dqn_OS_WriteAllF (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API bool Dqn_OS_WriteAllSafe (Dqn_Str8 path, Dqn_Str8 buffer, Dqn_ErrorSink *error); -DQN_API bool Dqn_OS_WriteAllSafeFV (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API bool Dqn_OS_WriteAllSafeF (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...); -#endif // !defined(DQN_NO_OS_FILE_API) +DN_API DN_Str8 DN_OS_ReadAll (DN_Arena *arena, DN_Str8 path, DN_ErrSink *err); +#define DN_OS_ReadAll_TLS(...) DN_OS_ReadAll(DN_TLS_TopArena(), ##__VA_ARGS__) +DN_API bool DN_OS_WriteAll (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err); +DN_API bool DN_OS_WriteAllFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_WriteAllF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_OS_WriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err); +DN_API bool DN_OS_WriteAllSafeFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_WriteAllSafeF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +#endif // !defined(DN_NO_OS_FILE_API) // NOTE: File system paths ///////////////////////////////////////////////////////////////////////// -DQN_API bool Dqn_OS_PathAddRef (Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path); -#define Dqn_OS_PathAddRef_TLS(...) Dqn_OS_PathAddRef(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API bool Dqn_OS_PathAdd (Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path); -#define Dqn_OS_PathAdd_TLS(...) Dqn_OS_PathAdd(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API bool Dqn_OS_PathAddF (Dqn_Arena *arena, Dqn_OSPath *fs_path, DQN_FMT_ATTRIB char const *fmt, ...); -#define Dqn_OS_PathAddF_TLS(...) Dqn_OS_PathAddF(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API bool Dqn_OS_PathPop (Dqn_OSPath *fs_path); -DQN_API Dqn_Str8 Dqn_OS_PathBuildWithSeparator (Dqn_Arena *arena, Dqn_OSPath const *fs_path, Dqn_Str8 path_separator); -#define Dqn_OS_PathBuildWithSeperator_TLS(...) Dqn_OS_PathBuildWithSeperator(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_OS_PathTo (Dqn_Arena *arena, Dqn_Str8 path, Dqn_Str8 path_separtor); -#define Dqn_OS_PathTo_TLS(...) Dqn_OS_PathTo(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_OS_PathToF (Dqn_Arena *arena, Dqn_Str8 path_separator, DQN_FMT_ATTRIB char const *fmt, ...); -#define Dqn_OS_PathToF_TLS(...) Dqn_OS_PathToF(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_OS_Path (Dqn_Arena *arena, Dqn_Str8 path); -#define Dqn_OS_Path_TLS(...) Dqn_OS_Path(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_OS_PathF (Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...); -#define Dqn_OS_PathF_TLS(...) Dqn_OS_PathF(Dqn_TLS_TopArena(), ##__VA_ARGS__) -#define Dqn_OS_PathBuildFwdSlash(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, DQN_STR8("/")) -#define Dqn_OS_PathBuildBackSlash(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, DQN_STR8("\\")) -#define Dqn_OS_PathBuild(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, Dqn_OSPathSeparatorString) +DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); +#define DN_OS_PathAddRef_TLS(...) DN_OS_PathAddRef(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_OS_PathAddRef_Frame(...) DN_OS_PathAddRef(DN_TLS_FrameArena(), ##__VA_ARGS__) +DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); +#define DN_OS_PathAdd_TLS(...) DN_OS_PathAdd(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_OS_PathAdd_Frame(...) DN_OS_PathAdd(DN_TLS_FrameArena(), ##__VA_ARGS__) +DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...); +#define DN_OS_PathAddF_TLS(...) DN_OS_PathAddF(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_OS_PathAddF_Frame(...) DN_OS_PathAddF(DN_TLS_FrameArena(), ##__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_PathBuildWithSeperator_TLS(...) DN_OS_PathBuildWithSeperator(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_OS_PathBuildWithSeperator_Frame(...) DN_OS_PathBuildWithSeperator(DN_TLS_FrameArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor); +#define DN_OS_PathTo_TLS(...) DN_OS_PathTo(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_OS_PathTo_Frame(...) DN_OS_PathTo(DN_TLS_FrameArena(), ##__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_PathToF_TLS(...) DN_OS_PathToF(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_OS_PathToF_Frame(...) DN_OS_PathToF(DN_TLS_FrameArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path); +#define DN_OS_Path_TLS(...) DN_OS_Path(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_OS_Path_Frame(...) DN_OS_Path(DN_TLS_FrameArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); +#define DN_OS_PathF_TLS(...) DN_OS_PathF(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_OS_PathF_Frame(...) DN_OS_PathF(DN_TLS_FrameArena(), ##__VA_ARGS__) -// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_OS_Exit (int32_t exit_code); -DQN_API Dqn_OSExecResult Dqn_OS_ExecWait (Dqn_OSExecAsyncHandle handle, Dqn_Arena *arena, Dqn_ErrorSink *error); -DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync (Dqn_Slice cmd_line, Dqn_Str8 working_dir, uint8_t exec_flags, Dqn_ErrorSink *error); -DQN_API Dqn_OSExecResult Dqn_OS_Exec (Dqn_Slice cmd_line, Dqn_Str8 working_dir, uint8_t exec_flags, Dqn_Arena *arena, Dqn_ErrorSink *error); -DQN_API Dqn_OSExecResult Dqn_OS_ExecOrAbort (Dqn_Slice cmd_line, Dqn_Str8 working_dir, uint8_t exec_flags, Dqn_Arena *arena); -#define Dqn_OS_ExecOrAbort_TLS(...) Dqn_OS_ExecOrAbort(__VA_ARGS__, Dqn_TLS_TopArena()) +#define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("/")) +#define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("\\")) +#define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString) -// NOTE: [$SEMA] Dqn_OSSemaphore /////////////////////////////////////////////////////////////////// -#if !defined(DQN_NO_SEMAPHORE) -DQN_API Dqn_OSSemaphore Dqn_OS_SemaphoreInit (uint32_t initial_count); -DQN_API bool Dqn_OS_SemaphoreIsValid (Dqn_OSSemaphore *semaphore); -DQN_API void Dqn_OS_SemaphoreDeinit (Dqn_OSSemaphore *semaphore); -DQN_API void Dqn_OS_SemaphoreIncrement(Dqn_OSSemaphore *semaphore, uint32_t amount); -DQN_API Dqn_OSSemaphoreWaitResult Dqn_OS_SemaphoreWait (Dqn_OSSemaphore *semaphore, uint32_t timeout_ms); -#endif // !defined(DQN_NO_SEMAPHORE) +// NOTE: [$EXEC] DN_OSExec //////////////////////////////////////////////////////////////////////// +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, uint32_t 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_ExecOrAbort_TLS(...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_TLS_TopArena()) -// NOTE: [$MUTX] Dqn_OSMutex /////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSMutex Dqn_OS_MutexInit (); -DQN_API void Dqn_OS_MutexDeinit(Dqn_OSMutex *mutex); -DQN_API void Dqn_OS_MutexLock (Dqn_OSMutex *mutex); -DQN_API void Dqn_OS_MutexUnlock(Dqn_OSMutex *mutex); +// NOTE: [$SEMA] DN_OSSemaphore /////////////////////////////////////////////////////////////////// +#if !defined(DN_NO_SEMAPHORE) +DN_API DN_OSSemaphore DN_OS_SemaphoreInit (uint32_t initial_count); +DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore); +DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore); +DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, uint32_t amount); +DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, uint32_t timeout_ms); +#endif // !defined(DN_NO_SEMAPHORE) -// NOTE: [$THRD] Dqn_OSThread ///////////////////////////////////////////////////////////////////// -#if !defined(DQN_NO_THREAD) && !defined(DQN_NO_SEMAPHORE) -DQN_API bool Dqn_OS_ThreadInit (Dqn_OSThread *thread, Dqn_OSThreadFunc *func, void *user_context); -DQN_API void Dqn_OS_ThreadDeinit(Dqn_OSThread thread); -DQN_API uint32_t Dqn_OS_ThreadID (); -DQN_API void Dqn_OS_ThreadSetTLS(Dqn_TLS *tls); -#endif // !defined(DQN_NO_THREAD) +// NOTE: [$MUTX] DN_OSMutex /////////////////////////////////////////////////////////////////////// +DN_API DN_OSMutex DN_OS_MutexInit (); +DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex); +DN_API void DN_OS_MutexLock (DN_OSMutex *mutex); +DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex); +#define DN_OS_Mutex(mutex) DN_DEFER_LOOP(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex)) -// NOTE: [$HTTP] Dqn_OSHttp //////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_OS_HttpRequestAsync(Dqn_OSHttpResponse *response, Dqn_Arena *arena, Dqn_Str8 host, Dqn_Str8 path, Dqn_OSHttpRequestSecure secure, Dqn_Str8 method, Dqn_Str8 body, Dqn_Str8 headers); -DQN_API void Dqn_OS_HttpRequestWait (Dqn_OSHttpResponse *response); -DQN_API void Dqn_OS_HttpRequestFree (Dqn_OSHttpResponse *response); -DQN_API Dqn_OSHttpResponse Dqn_OS_HttpRequest (Dqn_Arena *arena, Dqn_Str8 host, Dqn_Str8 path, Dqn_OSHttpRequestSecure secure, Dqn_Str8 method, Dqn_Str8 body, Dqn_Str8 headers); +// NOTE: [$THRD] DN_OSThread ///////////////////////////////////////////////////////////////////// +#if !defined(DN_NO_THREAD) && !defined(DN_NO_SEMAPHORE) +DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context); +DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread); +DN_API uint32_t DN_OS_ThreadID (); +DN_API void DN_OS_ThreadSetTLS(DN_TLS *tls); +DN_API void DN_OS_ThreadSetName(DN_Str8 name); +#endif // !defined(DN_NO_THREAD) + +// NOTE: [$HTTP] DN_OSHttp //////////////////////////////////////////////////////////////////////// +DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); +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); diff --git a/dqn_os_posix.cpp b/dqn_os_posix.cpp index 5b22a88..e5ebdd9 100644 --- a/dqn_os_posix.cpp +++ b/dqn_os_posix.cpp @@ -20,84 +20,99 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$VMEM] Dqn_OSMem +// NOTE: [$VMEM] DN_OSMem // ////////////////////////////////////////////////////////////////////////// -static uint32_t Dqn_OS_MemConvertPageToOSFlags_(uint32_t protect) +static uint32_t DN_OS_MemConvertPageToOSFlags_(uint32_t protect) { - DQN_ASSERT((protect & ~Dqn_OSMemPage_All) == 0); - DQN_ASSERT(protect != 0); + DN_ASSERT((protect & ~DN_OSMemPage_All) == 0); + DN_ASSERT(protect != 0); uint32_t result = 0; - if (protect & (Dqn_OSMemPage_NoAccess | Dqn_OSMemPage_Guard)) { + if (protect & (DN_OSMemPage_NoAccess | DN_OSMemPage_Guard)) { result = PROT_NONE; } else { - if (protect & Dqn_OSMemPage_Read) + if (protect & DN_OSMemPage_Read) result = PROT_READ; - if (protect & Dqn_OSMemPage_Write) + if (protect & DN_OSMemPage_Write) result = PROT_WRITE; } return result; } -DQN_API void *Dqn_OS_MemReserve(Dqn_usize size, Dqn_OSMemCommit commit, uint32_t page_flags) +DN_API void *DN_OS_MemReserve(DN_usize size, DN_OSMemCommit commit, uint32_t page_flags) { - unsigned long os_page_flags = Dqn_OS_MemConvertPageToOSFlags_(page_flags); + unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags); - if (commit == Dqn_OSMemCommit_Yes) + if (commit == DN_OSMemCommit_Yes) os_page_flags |= (PROT_READ | PROT_WRITE); void *result = mmap(nullptr, size, os_page_flags, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + DN_Atomic_AddU64(&g_dn_core->mem_allocs_total, 1); + DN_Atomic_AddU64(&g_dn_core->mem_allocs_frame, 1); if (result == MAP_FAILED) result = nullptr; return result; } -DQN_API bool Dqn_OS_MemCommit(void *ptr, Dqn_usize size, uint32_t page_flags) +DN_API bool DN_OS_MemCommit(void *ptr, DN_usize size, uint32_t page_flags) { bool result = false; if (!ptr || size == 0) return false; - unsigned long os_page_flags = Dqn_OS_MemConvertPageToOSFlags_(page_flags); + unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags); result = mprotect(ptr, size, os_page_flags) == 0; + DN_Atomic_AddU64(&g_dn_core->mem_allocs_total, 1); + DN_Atomic_AddU64(&g_dn_core->mem_allocs_frame, 1); return result; } -DQN_API void Dqn_OS_MemDecommit(void *ptr, Dqn_usize size) +DN_API void DN_OS_MemDecommit(void *ptr, DN_usize size) { mprotect(ptr, size, PROT_NONE); madvise(ptr, size, MADV_FREE); } -DQN_API void Dqn_OS_MemRelease(void *ptr, Dqn_usize size) +DN_API void DN_OS_MemRelease(void *ptr, DN_usize size) { munmap(ptr, size); } -DQN_API int Dqn_OS_MemProtect(void *ptr, Dqn_usize size, uint32_t page_flags) +DN_API int DN_OS_MemProtect(void *ptr, DN_usize size, uint32_t page_flags) { if (!ptr || size == 0) return 0; - static Dqn_Str8 const ALIGNMENT_ERROR_MSG = DQN_STR8( + static DN_Str8 const ALIGNMENT_ERROR_MSG = DN_STR8( "Page protection requires pointers to be page aligned because we " "can only guard memory at a multiple of the page boundary."); - DQN_ASSERTF(Dqn_IsPowerOfTwoAligned(DQN_CAST(uintptr_t) ptr, g_dqn_library->os_page_size), + DN_ASSERTF(DN_IsPowerOfTwoAligned(DN_CAST(uintptr_t) ptr, g_dn_core->os_page_size), "%s", ALIGNMENT_ERROR_MSG.data); - DQN_ASSERTF( - Dqn_IsPowerOfTwoAligned(size, g_dqn_library->os_page_size), "%s", ALIGNMENT_ERROR_MSG.data); + DN_ASSERTF( + DN_IsPowerOfTwoAligned(size, g_dn_core->os_page_size), "%s", ALIGNMENT_ERROR_MSG.data); - unsigned long os_page_flags = Dqn_OS_MemConvertPageToOSFlags_(page_flags); + unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags); int result = mprotect(ptr, size, os_page_flags); - DQN_ASSERTF(result == 0, "mprotect failed (%d)", errno); + DN_ASSERTF(result == 0, "mprotect failed (%d)", errno); return result; } -// NOTE: [$DATE] Date ////////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSDateTime Dqn_OS_DateLocalTimeNow() +DN_API void *DN_OS_MemAlloc(DN_usize size, DN_ZeroMem zero_mem) { - Dqn_OSDateTime result = {}; + void *result = zero_mem == DN_ZeroMem_Yes ? calloc(1, size) : malloc(size); + return result; +} + +DN_API void DN_OS_MemDealloc(void *ptr) +{ + free(ptr); +} + +// NOTE: [$DATE] Date ////////////////////////////////////////////////////////////////////////////// +DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() +{ + DN_OSDateTime result = {}; struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); @@ -116,21 +131,30 @@ DQN_API Dqn_OSDateTime Dqn_OS_DateLocalTimeNow() result.minutes = time.tm_min; result.seconds = time.tm_sec; - result.day = DQN_CAST(uint8_t) time.tm_mday; - result.month = DQN_CAST(uint8_t) time.tm_mon + 1; - result.year = 1900 + DQN_CAST(int16_t) time.tm_year; + result.day = DN_CAST(uint8_t) time.tm_mday; + result.month = DN_CAST(uint8_t) time.tm_mon + 1; + result.year = 1900 + DN_CAST(int16_t) time.tm_year; return result; } -DQN_API uint64_t Dqn_OS_DateUnixTime() +DN_API uint64_t DN_OS_DateUnixTimeNs() { - uint64_t result = time(nullptr); + struct timespec ts = {}; + clock_gettime(CLOCK_REALTIME, &ts); + uint64_t result = (ts.tv_sec * 1000 /*ms*/ * 1000 /*us*/ * 1000 /*ns*/) + ts.tv_nsec; return result; } -DQN_API uint64_t Dqn_OS_DateToUnixTime(Dqn_OSDateTime date) +DN_API uint64_t DN_OS_DateLocalToUnixTimeS(DN_OSDateTime) { - DQN_ASSERT(Dqn_OS_DateIsValid(date)); + DN_ASSERT_ONCE(!"Unimplemented"); + uint64_t result = 0; + return result; +} + +DN_API uint64_t DN_OS_DateToUnixTimeS(DN_OSDateTime date) +{ + DN_ASSERT(DN_OS_DateIsValid(date)); struct tm timeinfo = {}; timeinfo.tm_year = date.year - 1900; timeinfo.tm_mon = date.month - 1; @@ -142,11 +166,11 @@ DQN_API uint64_t Dqn_OS_DateToUnixTime(Dqn_OSDateTime date) return result; } -DQN_API Dqn_OSDateTime Dqn_OS_DateUnixTimeToDate(uint64_t time) +DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(uint64_t time) { - time_t posix_time = DQN_CAST(time_t) time; + time_t posix_time = DN_CAST(time_t) time; struct tm posix_date = *gmtime(&posix_time); - Dqn_OSDateTime result = {}; + DN_OSDateTime result = {}; result.year = posix_date.tm_year + 1900; result.month = posix_date.tm_mon + 1; result.day = posix_date.tm_mday; @@ -156,9 +180,9 @@ DQN_API Dqn_OSDateTime Dqn_OS_DateUnixTimeToDate(uint64_t time) return result; } -DQN_API bool Dqn_OS_SecureRNGBytes(void *buffer, uint32_t size) +DN_API bool DN_OS_SecureRNGBytes(void *buffer, uint32_t size) { -#if defined(DQN_PLATFORM_EMSCRIPTEN) +#if defined(DN_PLATFORM_EMSCRIPTEN) (void)buffer; (void)size; return false; @@ -169,7 +193,7 @@ DQN_API bool Dqn_OS_SecureRNGBytes(void *buffer, uint32_t size) if (size == 0) return true; - DQN_ASSERTF(size <= 32, + DN_ASSERTF(size <= 32, "We can increase this by chunking the buffer and filling 32 bytes at a time. *Nix " "guarantees 32 " "bytes can always be fulfilled by this system at a time"); @@ -185,16 +209,26 @@ DQN_API bool Dqn_OS_SecureRNGBytes(void *buffer, uint32_t size) #endif } -DQN_API Dqn_Str8 Dqn_OS_EXEPath(Dqn_Arena *arena) +DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value) { - Dqn_Str8 result = {}; + DN_ASSERTF_ONCE(false, "Unimplemented"); + (void)name; + (void)value; + bool result = false; + return result; +} + + +DN_API DN_Str8 DN_OS_EXEPath(DN_Arena *arena) +{ + DN_Str8 result = {}; if (!arena) return result; int required_size_wo_null_terminator = 0; for (int try_size = 128;; try_size *= 2) { - auto scoped_arena = Dqn_ArenaTempMemScope(arena); - char *try_buf = Dqn_Arena_NewArray(arena, char, try_size, Dqn_ZeroMem_No); + auto scoped_arena = DN_ArenaTempMemScope(arena); + char *try_buf = DN_Arena_NewArray(arena, char, try_size, DN_ZeroMem_No); int bytes_written = readlink("/proc/self/exe", try_buf, try_size); if (bytes_written == -1) { // Failed, we're unable to determine the executable directory @@ -209,11 +243,11 @@ DQN_API Dqn_Str8 Dqn_OS_EXEPath(Dqn_Arena *arena) // path, we do some post-processing on said string and extract just // the directory. - // TODO(dqn): It'd be nice if there's some way of keeping this + // TODO(dn): It'd be nice if there's some way of keeping this // try_buf around, memcopy the byte and trash the try_buf from the // arena. Instead we just get the size and redo the call one last // time after this "calculate" step. - DQN_ASSERTF(bytes_written < try_size, + DN_ASSERTF(bytes_written < try_size, "bytes_written can never be greater than the try size, function writes at " "most try_size"); required_size_wo_null_terminator = bytes_written; @@ -222,9 +256,9 @@ DQN_API Dqn_Str8 Dqn_OS_EXEPath(Dqn_Arena *arena) } if (required_size_wo_null_terminator) { - Dqn_ArenaTempMem temp_mem = Dqn_Arena_TempMemBegin(arena); + DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(arena); char *exe_path = - Dqn_Arena_NewArray(arena, char, required_size_wo_null_terminator + 1, Dqn_ZeroMem_No); + DN_Arena_NewArray(arena, char, required_size_wo_null_terminator + 1, DN_ZeroMem_No); exe_path[required_size_wo_null_terminator] = 0; int bytes_written = readlink("/proc/self/exe", exe_path, required_size_wo_null_terminator); @@ -232,15 +266,24 @@ DQN_API Dqn_Str8 Dqn_OS_EXEPath(Dqn_Arena *arena) // Note that if read-link fails again can be because there's // a potential race condition here, our exe or directory could have // been deleted since the last call, so we need to be careful. - Dqn_Arena_TempMemEnd(temp_mem); + DN_Arena_TempMemEnd(temp_mem); } else { - result = Dqn_Str8_Init(exe_path, required_size_wo_null_terminator); + result = DN_Str8_Init(exe_path, required_size_wo_null_terminator); } } return result; } -DQN_API uint64_t Dqn_OS_PerfCounterFrequency() +DN_API void DN_OS_SleepMs(DN_uint milliseconds) +{ + struct timespec ts; + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = (milliseconds % 1000) * 1000000; // Convert remaining milliseconds to nanoseconds + // nanosleep can fail if interrupted by a signal, so we loop until the full sleep time has passed + while (nanosleep(&ts, &ts) == -1 && errno == EINTR); +} + +DN_API uint64_t DN_OS_PerfCounterFrequency() { // NOTE: On Linux we use clock_gettime(CLOCK_MONOTONIC_RAW) which // increments at nanosecond granularity. @@ -248,19 +291,19 @@ DQN_API uint64_t Dqn_OS_PerfCounterFrequency() return result; } -DQN_API uint64_t Dqn_OS_PerfCounterNow() +DN_API uint64_t DN_OS_PerfCounterNow() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC_RAW, &ts); - uint64_t result = DQN_CAST(uint64_t) ts.tv_sec * 1'000'000'000 + DQN_CAST(uint64_t) ts.tv_nsec; + uint64_t result = DN_CAST(uint64_t) ts.tv_sec * 1'000'000'000 + DN_CAST(uint64_t) ts.tv_nsec; return result; } -#if !defined(DQN_NO_OS_FILE_API) -DQN_API Dqn_OSPathInfo Dqn_OS_PathInfo(Dqn_Str8 path) +#if !defined(DN_NO_OS_FILE_API) +DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) { - Dqn_OSPathInfo result = {}; - if (!Dqn_Str8_HasData(path)) + DN_OSPathInfo result = {}; + if (!DN_Str8_HasData(path)) return result; struct stat file_stat; @@ -269,32 +312,32 @@ DQN_API Dqn_OSPathInfo Dqn_OS_PathInfo(Dqn_Str8 path) result.size = file_stat.st_size; result.last_access_time_in_s = file_stat.st_atime; result.last_write_time_in_s = file_stat.st_mtime; - // TODO(dqn): Seems linux does not support creation time via stat. We + // TODO(dn): Seems linux does not support creation time via stat. We // shoddily deal with this. result.create_time_in_s = - DQN_MIN(result.last_access_time_in_s, result.last_write_time_in_s); + DN_MIN(result.last_access_time_in_s, result.last_write_time_in_s); if (S_ISDIR(file_stat.st_mode)) { - result.type = Dqn_OSPathInfoType_Directory; + result.type = DN_OSPathInfoType_Directory; } else if (S_ISREG(file_stat.st_mode)) { - result.type = Dqn_OSPathInfoType_File; + result.type = DN_OSPathInfoType_File; } } return result; } -DQN_API bool Dqn_OS_PathDelete(Dqn_Str8 path) +DN_API bool DN_OS_PathDelete(DN_Str8 path) { bool result = false; - if (Dqn_Str8_HasData(path)) + if (DN_Str8_HasData(path)) result = remove(path.data) == 0; return result; } -DQN_API bool Dqn_OS_FileExists(Dqn_Str8 path) +DN_API bool DN_OS_FileExists(DN_Str8 path) { bool result = false; - if (!Dqn_Str8_HasData(path)) + if (!DN_Str8_HasData(path)) return result; struct stat stat_result; @@ -303,24 +346,24 @@ DQN_API bool Dqn_OS_FileExists(Dqn_Str8 path) return result; } -DQN_API bool Dqn_OS_CopyFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_ErrorSink *error) +DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error) { bool result = false; - #if defined(DQN_PLATFORM_EMSCRIPTEN) - Dqn_ErrorSink_MakeF(error, 1, "Unsupported on Emscripten because of their VFS model"); + #if defined(DN_PLATFORM_EMSCRIPTEN) + DN_ErrSink_AppendF(error, 1, "Unsupported on Emscripten because of their VFS model"); #else int src_fd = open(src.data, O_RDONLY); if (src_fd == -1) { int error_code = errno; - Dqn_ErrorSink_MakeF(error, - error_code, - "Failed to open file '%.*s' for copying: (%d) %s", - DQN_STR_FMT(src), - error_code, - strerror(error_code)); + DN_ErrSink_AppendF(error, + error_code, + "Failed to open file '%.*s' for copying: (%d) %s", + DN_STR_FMT(src), + error_code, + strerror(error_code)); return result; } - DQN_DEFER + DN_DEFER { close(src_fd); }; @@ -328,15 +371,15 @@ DQN_API bool Dqn_OS_CopyFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_Er int dest_fd = open(dest.data, O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : 0)); if (dest_fd == -1) { int error_code = errno; - Dqn_ErrorSink_MakeF(error, + DN_ErrSink_AppendF(error, error_code, "Failed to open file destination '%.*s' for copying to: (%d) %s", - DQN_STR_FMT(src), + DN_STR_FMT(src), error_code, strerror(error_code)); return result; } - DQN_DEFER + DN_DEFER { close(dest_fd); }; @@ -345,10 +388,10 @@ DQN_API bool Dqn_OS_CopyFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_Er int fstat_result = fstat(src_fd, &stat_existing); if (fstat_result == -1) { int error_code = errno; - Dqn_ErrorSink_MakeF(error, + DN_ErrSink_AppendF(error, error_code, "Failed to query file size of '%.*s' for copying: (%d) %s", - DQN_STR_FMT(src), + DN_STR_FMT(src), error_code, strerror(error_code)); return result; @@ -358,19 +401,19 @@ DQN_API bool Dqn_OS_CopyFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_Er result = (bytes_written == stat_existing.st_size); if (!result) { int error_code = errno; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 file_size_str8 = - Dqn_U64ToByteSizeStr8(tmem.arena, stat_existing.st_size, Dqn_U64ByteSizeType_Auto); - Dqn_Str8 bytes_written_str8 = - Dqn_U64ToByteSizeStr8(tmem.arena, bytes_written, Dqn_U64ByteSizeType_Auto); - Dqn_ErrorSink_MakeF(error, + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 file_size_str8 = + DN_U64ToByteSizeStr8(tmem.arena, stat_existing.st_size, DN_U64ByteSizeType_Auto); + DN_Str8 bytes_written_str8 = + DN_U64ToByteSizeStr8(tmem.arena, bytes_written, DN_U64ByteSizeType_Auto); + DN_ErrSink_AppendF(error, error_code, "Failed to copy file '%.*s' to '%.*s', we copied %.*s but the file " "size is %.*s: (%d) %s", - DQN_STR_FMT(src), - DQN_STR_FMT(dest), - DQN_STR_FMT(bytes_written_str8), - DQN_STR_FMT(file_size_str8), + DN_STR_FMT(src), + DN_STR_FMT(dest), + DN_STR_FMT(bytes_written_str8), + DN_STR_FMT(file_size_str8), error_code, strerror(error_code)); } @@ -379,7 +422,7 @@ DQN_API bool Dqn_OS_CopyFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_Er return result; } -DQN_API bool Dqn_OS_MoveFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_ErrorSink *error) +DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error) { // See: https://github.com/gingerBill/gb/blob/master/gb.h bool result = false; @@ -387,7 +430,7 @@ DQN_API bool Dqn_OS_MoveFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_Er if (link(src.data, dest.data) == -1) { // NOTE: Link can fail if we're trying to link across different volumes // so we fall back to a binary directory. - file_moved |= Dqn_OS_CopyFile(src, dest, overwrite, error); + file_moved |= DN_OS_CopyFile(src, dest, overwrite, error); } if (file_moved) { @@ -395,11 +438,11 @@ DQN_API bool Dqn_OS_MoveFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_Er int unlink_result = unlink(src.data); if (unlink_result == -1) { int error_code = errno; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, error_code, "File '%.*s' was moved but failed to be unlinked from old location: (%d) %s", - DQN_STR_FMT(src), + DN_STR_FMT(src), error_code, strerror(error_code)); } @@ -407,18 +450,18 @@ DQN_API bool Dqn_OS_MoveFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_Er return result; } -DQN_API bool Dqn_OS_MakeDir(Dqn_Str8 path) +DN_API bool DN_OS_MakeDir(DN_Str8 path) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); bool result = true; // TODO(doyle): Implement this without using the path indexes, it's not // necessary. See Windows implementation. - Dqn_usize path_indexes_size = 0; + DN_usize path_indexes_size = 0; uint16_t path_indexes[64] = {}; - Dqn_Str8 copy = Dqn_Str8_Copy(tmem.arena, path); - for (Dqn_usize index = copy.size - 1; index < copy.size; index--) { + DN_Str8 copy = DN_Str8_Copy(tmem.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]; if (ch == '/' || first_char) { @@ -427,7 +470,7 @@ DQN_API bool Dqn_OS_MakeDir(Dqn_Str8 path) if (!first_char) copy.data[index] = 0; // Temporarily null terminate it - bool is_file = Dqn_OS_FileExists(copy); + bool is_file = DN_OS_FileExists(copy); if (!first_char) copy.data[index] = temp; // Undo null termination @@ -437,7 +480,7 @@ DQN_API bool Dqn_OS_MakeDir(Dqn_Str8 path) // it's not a directory. This request to make a directory is // invalid. return false; - } else if (Dqn_OS_DirExists(copy)) { + } else if (DN_OS_DirExists(copy)) { // NOTE: We found a directory, we can stop here and start // building up all the directories that didn't exist up to // this point. @@ -445,12 +488,12 @@ DQN_API bool Dqn_OS_MakeDir(Dqn_Str8 path) } else { // NOTE: There's nothing that exists at this path, we can // create a directory here - path_indexes[path_indexes_size++] = DQN_CAST(uint16_t) index; + path_indexes[path_indexes_size++] = DN_CAST(uint16_t) index; } } } - for (Dqn_usize index = path_indexes_size - 1; result && index < path_indexes_size; index--) { + for (DN_usize index = path_indexes_size - 1; result && index < path_indexes_size; index--) { uint16_t path_index = path_indexes[index]; char temp = copy.data[path_index]; @@ -463,10 +506,10 @@ DQN_API bool Dqn_OS_MakeDir(Dqn_Str8 path) return result; } -DQN_API bool Dqn_OS_DirExists(Dqn_Str8 path) +DN_API bool DN_OS_DirExists(DN_Str8 path) { bool result = false; - if (!Dqn_Str8_HasData(path)) + if (!DN_Str8_HasData(path)) return result; struct stat stat_result; @@ -475,7 +518,7 @@ DQN_API bool Dqn_OS_DirExists(Dqn_Str8 path) return result; } -DQN_API bool Dqn_OS_DirIterate(Dqn_Str8 path, Dqn_OS_DirIterator *it) +DN_API bool DN_OS_DirIterate(DN_Str8 path, DN_OSDirIterator *it) { if (!it->handle) { it->handle = opendir(path.data); @@ -485,23 +528,23 @@ DQN_API bool Dqn_OS_DirIterate(Dqn_Str8 path, Dqn_OS_DirIterator *it) struct dirent *entry; for (;;) { - entry = readdir(DQN_CAST(DIR*)it->handle); + entry = readdir(DN_CAST(DIR*)it->handle); if (entry == NULL) break; if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; - Dqn_usize name_size = Dqn_CStr8_Size(entry->d_name); - Dqn_usize clamped_size = DQN_MIN(sizeof(it->buffer) - 1, name_size); - DQN_ASSERTF(name_size == clamped_size, "name: %s, name_size: %zu, clamped_size: %zu", entry->d_name, name_size, clamped_size); - DQN_MEMCPY(it->buffer, entry->d_name, clamped_size); + DN_usize name_size = DN_CStr8_Size(entry->d_name); + DN_usize clamped_size = DN_MIN(sizeof(it->buffer) - 1, name_size); + DN_ASSERTF(name_size == clamped_size, "name: %s, name_size: %zu, clamped_size: %zu", entry->d_name, name_size, clamped_size); + DN_MEMCPY(it->buffer, entry->d_name, clamped_size); it->buffer[clamped_size] = 0; - it->file_name = Dqn_Str8_Init(it->buffer, clamped_size); + it->file_name = DN_Str8_Init(it->buffer, clamped_size); return true; } - closedir(DQN_CAST(DIR*)it->handle); + closedir(DN_CAST(DIR*)it->handle); it->handle = NULL; it->file_name = {}; it->buffer[0] = 0; @@ -509,28 +552,28 @@ DQN_API bool Dqn_OS_DirIterate(Dqn_Str8 path, Dqn_OS_DirIterator *it) } // NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSFile Dqn_OS_FileOpen(Dqn_Str8 path, - Dqn_OSFileOpen open_mode, - uint32_t access, - Dqn_ErrorSink *error) +DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, + DN_OSFileOpen open_mode, + DN_OSFileAccess access, + DN_ErrSink *error) { - Dqn_OSFile result = {}; - if (!Dqn_Str8_HasData(path) || path.size <= 0) + DN_OSFile result = {}; + if (!DN_Str8_HasData(path) || path.size <= 0) return result; - if ((access & ~Dqn_OSFileAccess_All) || ((access & Dqn_OSFileAccess_All) == 0)) { - DQN_INVALID_CODE_PATH; + if ((access & ~(DN_OSFileAccess_All) || ((access & DN_OSFileAccess_All) == 0))) { + DN_INVALID_CODE_PATH; return result; } - if (access & Dqn_OSFileAccess_Execute) { + if (access & DN_OSFileAccess_Execute) { result.error = true; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, 1, "Failed to open file '%.*s': File access flag 'execute' is not supported", - DQN_STR_FMT(path)); - DQN_INVALID_CODE_PATH; // TODO: Not supported via fopen + DN_STR_FMT(path)); + DN_INVALID_CODE_PATH; // TODO: Not supported via fopen return result; } @@ -541,19 +584,19 @@ DQN_API Dqn_OSFile Dqn_OS_FileOpen(Dqn_Str8 path, { FILE *handle = nullptr; switch (open_mode) { - case Dqn_OSFileOpen_CreateAlways: handle = fopen(path.data, "w"); break; - case Dqn_OSFileOpen_OpenIfExist: handle = fopen(path.data, "r"); break; - case Dqn_OSFileOpen_OpenAlways: handle = fopen(path.data, "a"); break; - default: DQN_INVALID_CODE_PATH; break; + case DN_OSFileOpen_CreateAlways: handle = fopen(path.data, "w"); break; + case DN_OSFileOpen_OpenIfExist: handle = fopen(path.data, "r"); break; + case DN_OSFileOpen_OpenAlways: handle = fopen(path.data, "a"); break; + default: DN_INVALID_CODE_PATH; break; } if (!handle) { // TODO(doyle): FileOpen flag to string result.error = true; - Dqn_ErrorSink_MakeF(error, + DN_ErrSink_AppendF(error, 1, "Failed to open file '%.*s': File could not be opened in requested " - "mode 'Dqn_OSFileOpen' flag %d", - DQN_STR_FMT(path), + "mode 'DN_OSFileOpen' flag %d", + DN_STR_FMT(path), open_mode); return result; } @@ -561,21 +604,21 @@ DQN_API Dqn_OSFile Dqn_OS_FileOpen(Dqn_Str8 path, } char const *fopen_mode = nullptr; - if (access & Dqn_OSFileAccess_AppendOnly) + if (access & DN_OSFileAccess_AppendOnly) fopen_mode = "a+"; - else if (access & Dqn_OSFileAccess_Write) + else if (access & DN_OSFileAccess_Write) fopen_mode = "w+"; - else if (access & Dqn_OSFileAccess_Read) + else if (access & DN_OSFileAccess_Read) fopen_mode = "r+"; FILE *handle = fopen(path.data, fopen_mode); if (!handle) { result.error = true; - Dqn_ErrorSink_MakeF(error, + DN_ErrSink_AppendF(error, 1, "Failed to open file '%.*s': File could not be opened with requested " - "access mode 'Dqn_OSFileAccess' %d", - DQN_STR_FMT(path), + "access mode 'DN_OSFileAccess' %d", + DN_STR_FMT(path), fopen_mode); return result; } @@ -583,88 +626,104 @@ DQN_API Dqn_OSFile Dqn_OS_FileOpen(Dqn_Str8 path, return result; } -DQN_API bool Dqn_OS_FileRead(Dqn_OSFile *file, void *buffer, Dqn_usize size, Dqn_ErrorSink *error) +DN_API bool DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_usize size, DN_ErrSink *error) { if (!file || !file->handle || file->error || !buffer || size <= 0) return false; - if (fread(buffer, size, 1, DQN_CAST(FILE *) file->handle) != 1) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 buffer_size_str8 = - Dqn_U64ToByteSizeStr8(tmem.arena, size, Dqn_U64ByteSizeType_Auto); - Dqn_ErrorSink_MakeF( - error, 1, "Failed to read %.*s from file", DQN_STR_FMT(buffer_size_str8)); + if (fread(buffer, size, 1, DN_CAST(FILE *) file->handle) != 1) { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 buffer_size_str8 = + DN_U64ToByteSizeStr8(tmem.arena, size, DN_U64ByteSizeType_Auto); + DN_ErrSink_AppendF( + error, 1, "Failed to read %.*s from file", DN_STR_FMT(buffer_size_str8)); return false; } return true; } -DQN_API bool -Dqn_OS_FileWritePtr(Dqn_OSFile *file, void const *buffer, Dqn_usize size, Dqn_ErrorSink *error) +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; bool result = - fwrite(buffer, DQN_CAST(Dqn_usize) size, 1 /*count*/, DQN_CAST(FILE *) file->handle) == + fwrite(buffer, DN_CAST(DN_usize) size, 1 /*count*/, DN_CAST(FILE *) file->handle) == 1 /*count*/; if (!result) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 buffer_size_str8 = - Dqn_U64ToByteSizeStr8(tmem.arena, size, Dqn_U64ByteSizeType_Auto); - Dqn_ErrorSink_MakeF( - error, 1, "Failed to write buffer (%s) to file handle", DQN_STR_FMT(buffer_size_str8)); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 buffer_size_str8 = + DN_U64ToByteSizeStr8(tmem.arena, size, DN_U64ByteSizeType_Auto); + DN_ErrSink_AppendF( + err, 1, "Failed to write buffer (%s) to file handle", DN_STR_FMT(buffer_size_str8)); } return result; } -DQN_API void Dqn_OS_FileClose(Dqn_OSFile *file) +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); + if (fd == -1) { + DN_ErrSink_AppendF(err, errno, "Failed to flush file buffer to disk, file handle could not be converted to descriptor (%d): %s", fd, strerror(errno)); + return false; + } + + int fsync_result = fsync(fd); + if (fsync_result == -1) { + DN_ErrSink_AppendF(err, errno, "Failed to flush file buffer to disk (%d): %s", fsync_result, strerror(errno)); + return false; + } + return true; +} + +DN_API void DN_OS_FileClose(DN_OSFile *file) { if (!file || !file->handle || file->error) return; - fclose(DQN_CAST(FILE *) file->handle); + fclose(DN_CAST(FILE *) file->handle); *file = {}; } -#endif // !defined(DQN_NO_OS_FILE_API) +#endif // !defined(DN_NO_OS_FILE_API) -// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_OS_Exit(int32_t exit_code) +// NOTE: [$EXEC] DN_OSExec //////////////////////////////////////////////////////////////////////// +DN_API void DN_OS_Exit(int32_t exit_code) { - exit(DQN_CAST(int) exit_code); + exit(DN_CAST(int) exit_code); } -enum Dqn_OSPipeType_ { - Dqn_OSPipeType__Read, - Dqn_OSPipeType__Write, - Dqn_OSPipeType__Count, +enum DN_OSPipeType_ { + DN_OSPipeType__Read, + DN_OSPipeType__Write, + DN_OSPipeType__Count, }; -DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle, - Dqn_Arena *arena, - Dqn_ErrorSink *error) +DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, + DN_Arena *arena, + DN_ErrSink *error) { - Dqn_OSExecResult result = {}; + DN_OSExecResult result = {}; if (!handle.process || handle.os_error_code || handle.exit_code) { if (handle.os_error_code) result.os_error_code = handle.os_error_code; else result.exit_code = handle.exit_code; - DQN_ASSERT(!handle.stdout_read); - DQN_ASSERT(!handle.stdout_write); - DQN_ASSERT(!handle.stderr_read); - DQN_ASSERT(!handle.stderr_write); + DN_ASSERT(!handle.stdout_read); + DN_ASSERT(!handle.stdout_write); + DN_ASSERT(!handle.stderr_read); + DN_ASSERT(!handle.stderr_write); return result; } -#if defined(DQN_PLATFORM_EMSCRIPTEN) - DQN_INVALID_CODE_PATHF("Unsupported operation"); +#if defined(DN_PLATFORM_EMSCRIPTEN) + DN_INVALID_CODE_PATHF("Unsupported operation"); #endif static_assert(sizeof(pid_t) <= sizeof(handle.process), "We store the PID opaquely in a register sized pointer"); pid_t process = {}; - DQN_MEMCPY(&process, &handle.process, sizeof(process)); + DN_MEMCPY(&process, &handle.process, sizeof(process)); for (;;) { int status = 0; if (waitpid(process, &status, 0) < 0) { @@ -683,188 +742,188 @@ DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle, } } - int stdout_pipe[Dqn_OSPipeType__Count] = {}; - int stderr_pipe[Dqn_OSPipeType__Count] = {}; - DQN_MEMCPY(&stdout_pipe[Dqn_OSPipeType__Read], + int stdout_pipe[DN_OSPipeType__Count] = {}; + int stderr_pipe[DN_OSPipeType__Count] = {}; + DN_MEMCPY(&stdout_pipe[DN_OSPipeType__Read], &handle.stdout_read, - sizeof(stdout_pipe[Dqn_OSPipeType__Read])); - DQN_MEMCPY(&stdout_pipe[Dqn_OSPipeType__Write], + sizeof(stdout_pipe[DN_OSPipeType__Read])); + DN_MEMCPY(&stdout_pipe[DN_OSPipeType__Write], &handle.stdout_write, - sizeof(stdout_pipe[Dqn_OSPipeType__Write])); - DQN_MEMCPY(&stderr_pipe[Dqn_OSPipeType__Read], + sizeof(stdout_pipe[DN_OSPipeType__Write])); + DN_MEMCPY(&stderr_pipe[DN_OSPipeType__Read], &handle.stderr_read, - sizeof(stderr_pipe[Dqn_OSPipeType__Read])); - DQN_MEMCPY(&stderr_pipe[Dqn_OSPipeType__Write], + sizeof(stderr_pipe[DN_OSPipeType__Read])); + DN_MEMCPY(&stderr_pipe[DN_OSPipeType__Write], &handle.stderr_write, - sizeof(stderr_pipe[Dqn_OSPipeType__Write])); + sizeof(stderr_pipe[DN_OSPipeType__Write])); // NOTE: Process has finished, stop the write end of the pipe - close(stdout_pipe[Dqn_OSPipeType__Write]); - close(stderr_pipe[Dqn_OSPipeType__Write]); + close(stdout_pipe[DN_OSPipeType__Write]); + close(stderr_pipe[DN_OSPipeType__Write]); // NOTE: Read the data from the read end of the pipe if (result.os_error_code == 0) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); + DN_TLSTMem tmem = DN_TLS_TMem(arena); if (arena && handle.stdout_read) { char buffer[4096]; - Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena); + DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena); for (;;) { ssize_t bytes_read = - read(stdout_pipe[Dqn_OSPipeType__Read], buffer, sizeof(buffer)); + read(stdout_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer)); if (bytes_read <= 0) break; - Dqn_Str8Builder_AddF(&builder, "%.*s", bytes_read, buffer); + DN_Str8Builder_AppendF(&builder, "%.*s", bytes_read, buffer); } - result.stdout_text = Dqn_Str8Builder_Build(&builder, arena); + result.stdout_text = DN_Str8Builder_Build(&builder, arena); } if (arena && handle.stderr_read) { char buffer[4096]; - Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena); + DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena); for (;;) { ssize_t bytes_read = - read(stderr_pipe[Dqn_OSPipeType__Read], buffer, sizeof(buffer)); + read(stderr_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer)); if (bytes_read <= 0) break; - Dqn_Str8Builder_AddF(&builder, "%.*s", bytes_read, buffer); + DN_Str8Builder_AppendF(&builder, "%.*s", bytes_read, buffer); } - result.stderr_text = Dqn_Str8Builder_Build(&builder, arena); + result.stderr_text = DN_Str8Builder_Build(&builder, arena); } } - close(stdout_pipe[Dqn_OSPipeType__Read]); - close(stderr_pipe[Dqn_OSPipeType__Read]); + close(stdout_pipe[DN_OSPipeType__Read]); + close(stderr_pipe[DN_OSPipeType__Read]); return result; } -DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync(Dqn_Slice cmd_line, - Dqn_Str8 working_dir, - uint8_t exec_flags, - Dqn_ErrorSink *error) +DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, + DN_OSExecArgs *args, + DN_ErrSink *error) { -#if defined(DQN_PLATFORM_EMSCRIPTEN) - DQN_INVALID_CODE_PATHF("Unsupported operation"); +#if defined(DN_PLATFORM_EMSCRIPTEN) + DN_INVALID_CODE_PATHF("Unsupported operation"); #endif + DN_ASSERTF_ONCE(args->environment.size == 0, "Unimplemented in POSIX"); - Dqn_OSExecAsyncHandle result = {}; + DN_OSExecAsyncHandle result = {}; if (cmd_line.size == 0) return result; - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 cmd_rendered = Dqn_Slice_Str8Render(tmem.arena, cmd_line, DQN_STR8(" ")); - int stdout_pipe[Dqn_OSPipeType__Count] = {}; - int stderr_pipe[Dqn_OSPipeType__Count] = {}; + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 cmd_rendered = DN_Slice_Str8Render(tmem.arena, cmd_line, DN_STR8(" ")); + int stdout_pipe[DN_OSPipeType__Count] = {}; + int stderr_pipe[DN_OSPipeType__Count] = {}; // NOTE: Open stdout pipe ////////////////////////////////////////////////////////////////////// - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_SaveStdout)) { + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStdout)) { if (pipe(stdout_pipe) == -1) { result.os_error_code = errno; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, result.os_error_code, "Failed to create stdout pipe to redirect the output of the command '%.*s': %s", - DQN_STR_FMT(cmd_rendered), + DN_STR_FMT(cmd_rendered), strerror(result.os_error_code)); return result; } - DQN_ASSERT(stdout_pipe[Dqn_OSPipeType__Read] != 0); - DQN_ASSERT(stdout_pipe[Dqn_OSPipeType__Write] != 0); + DN_ASSERT(stdout_pipe[DN_OSPipeType__Read] != 0); + DN_ASSERT(stdout_pipe[DN_OSPipeType__Write] != 0); } - DQN_DEFER + DN_DEFER { if (result.os_error_code == 0 && result.exit_code == 0) return; - close(stdout_pipe[Dqn_OSPipeType__Read]); - close(stdout_pipe[Dqn_OSPipeType__Write]); + close(stdout_pipe[DN_OSPipeType__Read]); + close(stdout_pipe[DN_OSPipeType__Write]); }; // NOTE: Open stderr pipe ////////////////////////////////////////////////////////////////////// - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_SaveStderr)) { - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_MergeStderrToStdout)) { - stderr_pipe[Dqn_OSPipeType__Read] = stdout_pipe[Dqn_OSPipeType__Read]; - stderr_pipe[Dqn_OSPipeType__Write] = stdout_pipe[Dqn_OSPipeType__Write]; + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr)) { + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) { + stderr_pipe[DN_OSPipeType__Read] = stdout_pipe[DN_OSPipeType__Read]; + stderr_pipe[DN_OSPipeType__Write] = stdout_pipe[DN_OSPipeType__Write]; } else if (pipe(stderr_pipe) == -1) { result.os_error_code = errno; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, result.os_error_code, "Failed to create stderr pipe to redirect the output of the command '%.*s': %s", - DQN_STR_FMT(cmd_rendered), + DN_STR_FMT(cmd_rendered), strerror(result.os_error_code)); return result; } - DQN_ASSERT(stderr_pipe[Dqn_OSPipeType__Read] != 0); - DQN_ASSERT(stderr_pipe[Dqn_OSPipeType__Write] != 0); + DN_ASSERT(stderr_pipe[DN_OSPipeType__Read] != 0); + DN_ASSERT(stderr_pipe[DN_OSPipeType__Write] != 0); } - DQN_DEFER { + DN_DEFER { if (result.os_error_code == 0 && result.exit_code == 0) return; - close(stderr_pipe[Dqn_OSPipeType__Read]); - close(stderr_pipe[Dqn_OSPipeType__Write]); + close(stderr_pipe[DN_OSPipeType__Read]); + close(stderr_pipe[DN_OSPipeType__Write]); }; pid_t child_pid = fork(); if (child_pid < 0) { result.os_error_code = errno; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, result.os_error_code, "Failed to fork process to execute the command '%.*s': %s", - DQN_STR_FMT(cmd_rendered), + DN_STR_FMT(cmd_rendered), strerror(result.os_error_code)); return result; } if (child_pid == 0) { // Child process - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_SaveStdout) && - (dup2(stdout_pipe[Dqn_OSPipeType__Write], STDOUT_FILENO) == -1)) { + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStdout) && + (dup2(stdout_pipe[DN_OSPipeType__Write], STDOUT_FILENO) == -1)) { result.os_error_code = errno; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, result.os_error_code, "Failed to redirect stdout 'write' pipe for output of command '%.*s': %s", - DQN_STR_FMT(cmd_rendered), + DN_STR_FMT(cmd_rendered), strerror(result.os_error_code)); return result; } - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_SaveStderr) && - (dup2(stderr_pipe[Dqn_OSPipeType__Write], STDERR_FILENO) == -1)) { + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr) && + (dup2(stderr_pipe[DN_OSPipeType__Write], STDERR_FILENO) == -1)) { result.os_error_code = errno; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, result.os_error_code, "Failed to redirect stderr 'read' pipe for output of command '%.*s': %s", - DQN_STR_FMT(cmd_rendered), + DN_STR_FMT(cmd_rendered), strerror(result.os_error_code)); return result; } // NOTE: Convert the command into something suitable for execvp char **argv = - Dqn_Arena_NewArray(tmem.arena, char *, cmd_line.size + 1 /*null*/, Dqn_ZeroMem_Yes); + DN_Arena_NewArray(tmem.arena, char *, cmd_line.size + 1 /*null*/, DN_ZeroMem_Yes); if (!argv) { result.exit_code = -1; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, result.os_error_code, "Failed to create argument values from command line '%.*s': Out of memory", - DQN_STR_FMT(cmd_rendered)); + DN_STR_FMT(cmd_rendered)); return result; } - for (Dqn_usize arg_index = 0; arg_index < cmd_line.size; arg_index++) { - Dqn_Str8 arg = cmd_line.data[arg_index]; - argv[arg_index] = Dqn_Str8_Copy(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated + for (DN_usize arg_index = 0; arg_index < cmd_line.size; arg_index++) { + DN_Str8 arg = cmd_line.data[arg_index]; + argv[arg_index] = DN_Str8_Copy(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated } // NOTE: Change the working directory if there is one char *prev_working_dir = nullptr; - DQN_DEFER { + DN_DEFER { if (!prev_working_dir) return; if (result.os_error_code == 0) { @@ -874,15 +933,16 @@ DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync(Dqn_Slice cmd_line, free(prev_working_dir); }; - if (working_dir.size) { + if (args->working_dir.size) { prev_working_dir = get_current_dir_name(); + DN_Str8 working_dir = DN_Str8_Copy(tmem.arena, args->working_dir); if (chdir(working_dir.data) == -1) { result.os_error_code = errno; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, result.os_error_code, "Failed to create argument values from command line '%.*s': %s", - DQN_STR_FMT(cmd_rendered), + DN_STR_FMT(cmd_rendered), strerror(result.os_error_code)); return result; } @@ -892,49 +952,49 @@ DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync(Dqn_Slice cmd_line, // binary to execute is guaranteed to be null-terminated. if (execvp(argv[0], argv) < 0) { result.os_error_code = errno; - Dqn_ErrorSink_MakeF( + DN_ErrSink_AppendF( error, result.os_error_code, "Failed to execute command'%.*s': %s", - DQN_STR_FMT(cmd_rendered), + DN_STR_FMT(cmd_rendered), strerror(result.os_error_code)); return result; } } - DQN_ASSERT(result.os_error_code == 0); - DQN_MEMCPY(&result.stdout_read, - &stdout_pipe[Dqn_OSPipeType__Read], - sizeof(stdout_pipe[Dqn_OSPipeType__Read])); - DQN_MEMCPY(&result.stdout_write, - &stdout_pipe[Dqn_OSPipeType__Write], - sizeof(stdout_pipe[Dqn_OSPipeType__Write])); + DN_ASSERT(result.os_error_code == 0); + DN_MEMCPY(&result.stdout_read, + &stdout_pipe[DN_OSPipeType__Read], + sizeof(stdout_pipe[DN_OSPipeType__Read])); + DN_MEMCPY(&result.stdout_write, + &stdout_pipe[DN_OSPipeType__Write], + sizeof(stdout_pipe[DN_OSPipeType__Write])); - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_SaveStderr) && Dqn_Bit_IsNotSet(exec_flags, Dqn_OSExecFlag_MergeStderrToStdout)) { - DQN_MEMCPY(&result.stderr_read, - &stderr_pipe[Dqn_OSPipeType__Read], - sizeof(stderr_pipe[Dqn_OSPipeType__Read])); - DQN_MEMCPY(&result.stderr_write, - &stderr_pipe[Dqn_OSPipeType__Write], - sizeof(stderr_pipe[Dqn_OSPipeType__Write])); + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr) && DN_Bit_IsNotSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) { + DN_MEMCPY(&result.stderr_read, + &stderr_pipe[DN_OSPipeType__Read], + sizeof(stderr_pipe[DN_OSPipeType__Read])); + DN_MEMCPY(&result.stderr_write, + &stderr_pipe[DN_OSPipeType__Write], + sizeof(stderr_pipe[DN_OSPipeType__Write])); } - result.exec_flags = exec_flags; - DQN_MEMCPY(&result.process, &child_pid, sizeof(child_pid)); + result.exec_flags = args->flags; + DN_MEMCPY(&result.process, &child_pid, sizeof(child_pid)); return result; } -#if !defined(DQN_NO_SEMAPHORE) -// NOTE: [$SEMA] Dqn_OSSemaphore /////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSSemaphore Dqn_OS_SemaphoreInit(uint32_t initial_count) +#if !defined(DN_NO_SEMAPHORE) +// NOTE: [$SEMA] DN_OSSemaphore /////////////////////////////////////////////////////////////////// +DN_API DN_OSSemaphore DN_OS_SemaphoreInit(uint32_t initial_count) { - Dqn_OSSemaphore result = {}; + DN_OSSemaphore result = {}; int pshared = 0; // Share the semaphore across all threads in the process if (sem_init(&result.posix_handle, pshared, initial_count) == 0) result.posix_init = true; return result; } -DQN_API bool Dqn_OS_SemaphoreIsValid(Dqn_OSSemaphore *semaphore) +DN_API bool DN_OS_SemaphoreIsValid(DN_OSSemaphore *semaphore) { bool result = false; if (semaphore) @@ -942,9 +1002,9 @@ DQN_API bool Dqn_OS_SemaphoreIsValid(Dqn_OSSemaphore *semaphore) return result; } -DQN_API void Dqn_OS_SemaphoreDeinit(Dqn_OSSemaphore *semaphore) +DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) { - if (!Dqn_OS_SemaphoreIsValid(semaphore)) + if (!DN_OS_SemaphoreIsValid(semaphore)) return; // TODO(doyle): Error handling? if (semaphore->posix_init) @@ -969,52 +1029,52 @@ DQN_API void Dqn_OS_SemaphoreDeinit(Dqn_OSSemaphore *semaphore) // referring to a copy of the object when locking, unlocking, or destroying it // is undefined. -DQN_API void Dqn_OS_SemaphoreIncrement(Dqn_OSSemaphore *semaphore, uint32_t amount) +DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, uint32_t amount) { - if (!Dqn_OS_SemaphoreIsValid(semaphore)) + if (!DN_OS_SemaphoreIsValid(semaphore)) return; - #if defined(DQN_OS_WIN32) + #if defined(DN_OS_WIN32) sem_post_multiple(&semaphore->posix_handle, amount); // mingw extension #else - DQN_FOR_UINDEX(index, amount) + DN_FOR_UINDEX(index, amount) sem_post(&semaphore->posix_handle); - #endif // !defined(DQN_OS_WIN32) + #endif // !defined(DN_OS_WIN32) } -DQN_API Dqn_OSSemaphoreWaitResult Dqn_OS_SemaphoreWait(Dqn_OSSemaphore *semaphore, +DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, uint32_t timeout_ms) { - Dqn_OSSemaphoreWaitResult result = {}; - if (!Dqn_OS_SemaphoreIsValid(semaphore)) + DN_OSSemaphoreWaitResult result = {}; + if (!DN_OS_SemaphoreIsValid(semaphore)) return result; - if (timeout_ms == DQN_OS_SEMAPHORE_INFINITE_TIMEOUT) { + if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) { int wait_result = 0; do { wait_result = sem_wait(&semaphore->posix_handle); } while (wait_result == -1 && errno == EINTR); if (wait_result == 0) - result = Dqn_OSSemaphoreWaitResult_Success; + result = DN_OSSemaphoreWaitResult_Success; } else { struct timespec abs_timeout = {}; abs_timeout.tv_sec = timeout_ms / 1000; abs_timeout.tv_nsec = (timeout_ms % 1000) * 1'000'000; if (sem_timedwait(&semaphore->posix_handle, &abs_timeout) == 0) - result = Dqn_OSSemaphoreWaitResult_Success; + result = DN_OSSemaphoreWaitResult_Success; else if (errno == ETIMEDOUT) - result = Dqn_OSSemaphoreWaitResult_Timeout; + result = DN_OSSemaphoreWaitResult_Timeout; } return result; } -#endif // !defined(DQN_NO_SEMAPHORE) +#endif // !defined(DN_NO_SEMAPHORE) -#if !defined(DQN_NO_THREAD) -// NOTE: [$MUTX] Dqn_OSMutex /////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSMutex Dqn_OS_MutexInit() +#if !defined(DN_NO_THREAD) +// NOTE: [$MUTX] DN_OSMutex /////////////////////////////////////////////////////////////////////// +DN_API DN_OSMutex DN_OS_MutexInit() { - Dqn_OSMutex result = {}; + DN_OSMutex result = {}; if (pthread_mutexattr_init(&result.posix_attribs) != 0) return result; if (pthread_mutex_init(&result.posix_handle, &result.posix_attribs) != 0) @@ -1022,7 +1082,7 @@ DQN_API Dqn_OSMutex Dqn_OS_MutexInit() return result; } -DQN_API void Dqn_OS_MutexDeinit(Dqn_OSMutex *mutex) +DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) { if (!mutex) return; @@ -1030,28 +1090,28 @@ DQN_API void Dqn_OS_MutexDeinit(Dqn_OSMutex *mutex) pthread_mutex_destroy(&mutex->posix_handle); } -DQN_API void Dqn_OS_MutexLock(Dqn_OSMutex *mutex) +DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) { if (!mutex) return; pthread_mutex_lock(&mutex->posix_handle); } -DQN_API void Dqn_OS_MutexUnlock(Dqn_OSMutex *mutex) +DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex) { if (!mutex) return; pthread_mutex_unlock(&mutex->posix_handle); } -// NOTE: [$THRD] Dqn_OSThread ///////////////////////////////////////////////////////////////////// -static void *Dqn_OS_ThreadFunc_(void *user_context) +// NOTE: [$THRD] DN_OSThread ///////////////////////////////////////////////////////////////////// +static void *DN_OS_ThreadFunc_(void *user_context) { - Dqn_OS_ThreadExecute_(user_context); + DN_OS_ThreadExecute_(user_context); return nullptr; } -DQN_API bool Dqn_OS_ThreadInit(Dqn_OSThread *thread, Dqn_OSThreadFunc *func, void *user_context) +DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context) { bool result = false; if (!thread) @@ -1059,7 +1119,7 @@ DQN_API bool Dqn_OS_ThreadInit(Dqn_OSThread *thread, Dqn_OSThreadFunc *func, voi thread->func = func; thread->user_context = user_context; - thread->init_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/); + thread->init_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/); // TODO(doyle): Check if semaphore is valid // NOTE: pthread_t is essentially the thread ID. In Windows, the handle and @@ -1075,31 +1135,31 @@ DQN_API bool Dqn_OS_ThreadInit(Dqn_OSThread *thread, Dqn_OSThreadFunc *func, voi pthread_attr_t attribs = {}; pthread_attr_init(&attribs); - result = pthread_create(&p_thread, &attribs, Dqn_OS_ThreadFunc_, thread) == 0; + result = pthread_create(&p_thread, &attribs, DN_OS_ThreadFunc_, thread) == 0; pthread_attr_destroy(&attribs); if (result) { - DQN_MEMCPY(&thread->handle, &p_thread, sizeof(p_thread)); - DQN_MEMCPY(&thread->thread_id, &p_thread, sizeof(p_thread)); + DN_MEMCPY(&thread->handle, &p_thread, sizeof(p_thread)); + DN_MEMCPY(&thread->thread_id, &p_thread, sizeof(p_thread)); } if (result) { - Dqn_OS_SemaphoreIncrement(&thread->init_semaphore, 1); + DN_OS_SemaphoreIncrement(&thread->init_semaphore, 1); } else { - Dqn_OS_SemaphoreDeinit(&thread->init_semaphore); + DN_OS_SemaphoreDeinit(&thread->init_semaphore); *thread = {}; } return result; } -DQN_API void Dqn_OS_ThreadDeinit(Dqn_OSThread *thread) +DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread) { if (!thread || !thread->handle) return; pthread_t thread_id = {}; - DQN_MEMCPY(&thread_id, &thread->thread_id, sizeof(thread_id)); + DN_MEMCPY(&thread_id, &thread->thread_id, sizeof(thread_id)); void *return_val = nullptr; pthread_join(thread_id, &return_val); @@ -1107,15 +1167,23 @@ DQN_API void Dqn_OS_ThreadDeinit(Dqn_OSThread *thread) thread->thread_id = {}; } -DQN_API uint32_t Dqn_OS_ThreadID() +DN_API uint32_t DN_OS_ThreadID() { pid_t result = gettid(); - DQN_ASSERT(gettid() >= 0); - return DQN_CAST(uint32_t) result; + DN_ASSERT(gettid() >= 0); + return DN_CAST(uint32_t) result; } -#endif // !defined(DQN_NO_THREAD) -// NOTE: [$HTTP] Dqn_OSHttp //////////////////////////////////////////////////////////////////////// +DN_API void DN_Posix_ThreadSetName(DN_Str8 name) +{ + DN_TLSTMem tmem = DN_TLS_PushTMem(nullptr); + DN_Str8 copy = DN_Str8_Copy(tmem.arena, name); + pthread_t thread = pthread_self(); + pthread_setname_np(thread, (char *)copy.data); +} +#endif // !defined(DN_NO_THREAD) + +// NOTE: [$HTTP] DN_OSHttp //////////////////////////////////////////////////////////////////////// #if 0 // TODO(doyle): Implement websockets for Windows and Emscripten static EM_BOOL EMWebSocketOnOpenCallback(int type, const EmscriptenWebSocketOpenEvent *event, void *user_context) { @@ -1124,7 +1192,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) - // Dqn_Log_InfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result); + // DN_Log_InfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result); return EM_TRUE; } @@ -1134,9 +1202,9 @@ static EM_BOOL EMWebSocketOnMsgCallback(int type, const EmscriptenWebSocketMessa (void)user_context; (void)event; if (event->isText) { - Dqn_Log_InfoF("Received: %.*s", event->numBytes, event->data); + DN_Log_InfoF("Received: %.*s", event->numBytes, event->data); } else { - Dqn_Log_InfoF("Received: %d bytes", event->numBytes); + DN_Log_InfoF("Received: %d bytes", event->numBytes); } return EM_TRUE; } @@ -1158,46 +1226,46 @@ static EM_BOOL EMWebSocketOnCloseCallback(int type, const EmscriptenWebSocketClo } #endif -#if defined(DQN_PLATFORM_EMSCRIPTEN) -static void Dqn_OS_HttpRequestEMFetchOnSuccessCallback(emscripten_fetch_t *fetch) +#if defined(DN_PLATFORM_EMSCRIPTEN) +static void DN_OS_HttpRequestEMFetchOnSuccessCallback(emscripten_fetch_t *fetch) { - Dqn_OSHttpResponse *response = DQN_CAST(Dqn_OSHttpResponse *) fetch->userData; - if (!DQN_CHECK(response)) + DN_OSHttpResponse *response = DN_CAST(DN_OSHttpResponse *) fetch->userData; + if (!DN_CHECK(response)) return; - response->http_status = DQN_CAST(uint32_t) fetch->status; - response->body = Dqn_Str8_Alloc(response->arena, fetch->numBytes, Dqn_ZeroMem_No); + response->http_status = DN_CAST(uint32_t) fetch->status; + response->body = DN_Str8_Alloc(response->arena, fetch->numBytes, DN_ZeroMem_No); if (response->body.data) - DQN_MEMCPY(response->body.data, fetch->data, fetch->numBytes); + DN_MEMCPY(response->body.data, fetch->data, fetch->numBytes); - Dqn_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1); - Dqn_Atomic_AddU32(&response->done, 1); + DN_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1); + DN_Atomic_AddU32(&response->done, 1); } -static void Dqn_OS_HttpRequestEMFetchOnErrorCallback(emscripten_fetch_t *fetch) +static void DN_OS_HttpRequestEMFetchOnErrorCallback(emscripten_fetch_t *fetch) { - Dqn_OSHttpResponse *response = DQN_CAST(Dqn_OSHttpResponse *) fetch->userData; - if (!DQN_CHECK(response)) + DN_OSHttpResponse *response = DN_CAST(DN_OSHttpResponse *) fetch->userData; + if (!DN_CHECK(response)) return; - response->http_status = DQN_CAST(uint32_t) fetch->status; - response->body = Dqn_Str8_Alloc(response->arena, fetch->numBytes, Dqn_ZeroMem_No); + response->http_status = DN_CAST(uint32_t) fetch->status; + response->body = DN_Str8_Alloc(response->arena, fetch->numBytes, DN_ZeroMem_No); if (response->body.size) - DQN_MEMCPY(response->body.data, fetch->data, fetch->numBytes); + DN_MEMCPY(response->body.data, fetch->data, fetch->numBytes); - Dqn_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1); - Dqn_Atomic_AddU32(&response->done, 1); + DN_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1); + DN_Atomic_AddU32(&response->done, 1); } #endif -DQN_API void Dqn_OS_HttpRequestAsync(Dqn_OSHttpResponse *response, - Dqn_Arena *arena, - Dqn_Str8 host, - Dqn_Str8 path, - Dqn_OSHttpRequestSecure secure, - Dqn_Str8 method, - Dqn_Str8 body, - Dqn_Str8 headers) +DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, + DN_Arena *arena, + DN_Str8 host, + DN_Str8 path, + DN_OSHttpRequestSecure secure, + DN_Str8 method, + DN_Str8 body, + DN_Str8 headers) { if (!response || !arena) return; @@ -1206,63 +1274,63 @@ DQN_API void Dqn_OS_HttpRequestAsync(Dqn_OSHttpResponse *response, response->builder.arena = response->tmem_arena ? response->tmem_arena : &response->tmp_arena; - Dqn_Arena *tmem = response->tmem_arena; - Dqn_TLSTMem tmem_ = Dqn_TLS_TMem(arena); + DN_Arena *tmem = response->tmem_arena; + DN_TLSTMem tmem_ = DN_TLS_TMem(arena); if (!tmem) tmem = tmem_.arena; -#if defined(DQN_PLATFORM_EMSCRIPTEN) +#if defined(DN_PLATFORM_EMSCRIPTEN) emscripten_fetch_attr_t fetch_attribs = {}; emscripten_fetch_attr_init(&fetch_attribs); if (method.size >= sizeof(fetch_attribs.requestMethod)) { response->error_msg = - Dqn_Str8_InitF(arena, + DN_Str8_InitF(arena, "Request method in EM has a size limit of 31 characters, method was " "'%.*s' which is %zu characters long", - DQN_STR_FMT(method), + DN_STR_FMT(method), method.size); - DQN_CHECKF(method.size < sizeof(fetch_attribs.requestMethod), + DN_CHECKF(method.size < sizeof(fetch_attribs.requestMethod), "%.*s", - DQN_STR_FMT(response->error_msg)); - response->error_code = DQN_CAST(uint32_t) - 1; - Dqn_Atomic_AddU32(&response->done, 1); + DN_STR_FMT(response->error_msg)); + response->error_code = DN_CAST(uint32_t) - 1; + DN_Atomic_AddU32(&response->done, 1); return; } - DQN_MEMCPY(fetch_attribs.requestMethod, method.data, method.size); + DN_MEMCPY(fetch_attribs.requestMethod, method.data, method.size); fetch_attribs.requestData = body.data; fetch_attribs.requestDataSize = body.size; fetch_attribs.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; - fetch_attribs.onsuccess = Dqn_OS_HttpRequestEMFetchOnSuccessCallback; - fetch_attribs.onerror = Dqn_OS_HttpRequestEMFetchOnErrorCallback; + fetch_attribs.onsuccess = DN_OS_HttpRequestEMFetchOnSuccessCallback; + fetch_attribs.onerror = DN_OS_HttpRequestEMFetchOnErrorCallback; fetch_attribs.userData = response; - Dqn_Str8 url = Dqn_Str8_InitF(scratch_arena, "%.*s%.*s", DQN_STR_FMT(host), DQN_STR_FMT(path)); - Dqn_Log_InfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'", + DN_Str8 url = DN_Str8_InitF(scratch_arena, "%.*s%.*s", DN_STR_FMT(host), DN_STR_FMT(path)); + DN_Log_InfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'", fetch_attribs.requestMethod, - DQN_STR_FMT(url), - DQN_STR_FMT(body)); - response->on_complete_semaphore = Dqn_OS_SemaphoreInit(0); + DN_STR_FMT(url), + DN_STR_FMT(body)); + response->on_complete_semaphore = DN_OS_SemaphoreInit(0); response->em_handle = emscripten_fetch(&fetch_attribs, url.data); -#else // #elif defined(DQN_OS_WIN32) - DQN_INVALID_CODE_PATHF("Unimplemented function"); +#else // #elif defined(DN_OS_WIN32) + DN_INVALID_CODE_PATHF("Unimplemented function"); #endif } -DQN_API void Dqn_OS_HttpRequestFree(Dqn_OSHttpResponse *response) +DN_API void DN_OS_HttpRequestFree(DN_OSHttpResponse *response) { // NOTE: Cleanup -#if defined(DQN_PLATFORM_EMSCRIPTEN) +#if defined(DN_PLATFORM_EMSCRIPTEN) if (response->em_handle) { emscripten_fetch_close(response->em_handle); response->em_handle = nullptr; } -#endif // #elif defined(DQN_OS_WIN32) +#endif // #elif defined(DN_OS_WIN32) - Dqn_Arena_Deinit(&response->tmp_arena); - if (Dqn_OS_SemaphoreIsValid(&response->on_complete_semaphore)) - Dqn_OS_SemaphoreDeinit(&response->on_complete_semaphore); + DN_Arena_Deinit(&response->tmp_arena); + if (DN_OS_SemaphoreIsValid(&response->on_complete_semaphore)) + DN_OS_SemaphoreDeinit(&response->on_complete_semaphore); *response = {}; } diff --git a/dqn_os_posix.h b/dqn_os_posix.h new file mode 100644 index 0000000..823f2cb --- /dev/null +++ b/dqn_os_posix.h @@ -0,0 +1,21 @@ +#pragma once +#include "dqn.h" + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// $$$$$$\ $$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ +// $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ \_$$ _|$$ | $$ | +// $$ / $$ |$$ / \__| $$ | $$ |$$ / $$ |$$ / \__| $$ | \$$\ $$ | +// $$ | $$ |\$$$$$$\ $$$$$$$ |$$ | $$ |\$$$$$$\ $$ | \$$$$ / +// $$ | $$ | \____$$\ $$ ____/ $$ | $$ | \____$$\ $$ | $$ $$< +// $$ | $$ |$$\ $$ | $$ | $$ | $$ |$$\ $$ | $$ | $$ /\$$\ +// $$$$$$ |\$$$$$$ | $$ | $$$$$$ |\$$$$$$ |$$$$$$\ $$ / $$ | +// \______/ \______/ \__| \______/ \______/ \______|\__| \__| +// +// dqn_os_posix.h +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + +DN_API void DN_Posix_ThreadSetName(DN_Str8 name); diff --git a/dqn_os_win32.cpp b/dqn_os_win32.cpp index ba66fe5..58b6ba7 100644 --- a/dqn_os_win32.cpp +++ b/dqn_os_win32.cpp @@ -18,121 +18,182 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$VMEM] Dqn_OSMem ///////////////////////////////////////////////////////////////////////// -static uint32_t Dqn_OS_MemConvertPageToOSFlags_(uint32_t protect) +// NOTE: [$VMEM] DN_OSMem ///////////////////////////////////////////////////////////////////////// +static uint32_t DN_OS_MemConvertPageToOSFlags_(uint32_t protect) { - DQN_ASSERT((protect & ~Dqn_OSMemPage_All) == 0); - DQN_ASSERT(protect != 0); + DN_ASSERT((protect & ~DN_OSMemPage_All) == 0); + DN_ASSERT(protect != 0); uint32_t result = 0; - if (protect & Dqn_OSMemPage_NoAccess) { + if (protect & DN_OSMemPage_NoAccess) { result = PAGE_NOACCESS; } else { - if (protect & Dqn_OSMemPage_ReadWrite) { + if (protect & DN_OSMemPage_ReadWrite) { result = PAGE_READWRITE; - } else if (protect & Dqn_OSMemPage_Read) { + } else if (protect & DN_OSMemPage_Read) { result = PAGE_READONLY; - } else if (protect & Dqn_OSMemPage_Write) { - Dqn_Log_WarningF("Windows does not support write-only pages, granting read+write access"); + } else if (protect & DN_OSMemPage_Write) { + DN_Log_WarningF("Windows does not support write-only pages, granting read+write access"); result = PAGE_READWRITE; } } - if (protect & Dqn_OSMemPage_Guard) + if (protect & DN_OSMemPage_Guard) result |= PAGE_GUARD; - DQN_ASSERTF(result != PAGE_GUARD, "Page guard is a modifier, you must also specify a page permission like read or/and write"); + DN_ASSERTF(result != PAGE_GUARD, "Page guard is a modifier, you must also specify a page permission like read or/and write"); return result; } -DQN_API void *Dqn_OS_MemReserve(Dqn_usize size, Dqn_OSMemCommit commit, uint32_t page_flags) +DN_API void *DN_OS_MemReserve(DN_USize size, DN_OSMemCommit commit, uint32_t page_flags) { - unsigned long os_page_flags = Dqn_OS_MemConvertPageToOSFlags_(page_flags); - unsigned long flags = MEM_RESERVE | (commit == Dqn_OSMemCommit_Yes ? MEM_COMMIT : 0); + unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags); + unsigned long flags = MEM_RESERVE | (commit == DN_OSMemCommit_Yes ? MEM_COMMIT : 0); void *result = VirtualAlloc(nullptr, size, flags, os_page_flags); + DN_Atomic_AddU64(&g_dn_core->mem_allocs_total, DN_CAST(bool)(flags & MEM_COMMIT)); + DN_Atomic_AddU64(&g_dn_core->mem_allocs_frame, DN_CAST(bool)(flags & MEM_COMMIT)); return result; } -DQN_API bool Dqn_OS_MemCommit(void *ptr, Dqn_usize size, uint32_t page_flags) +DN_API bool DN_OS_MemCommit(void *ptr, DN_USize size, uint32_t page_flags) { bool result = false; if (!ptr || size == 0) return false; - unsigned long os_page_flags = Dqn_OS_MemConvertPageToOSFlags_(page_flags); + unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags); result = VirtualAlloc(ptr, size, MEM_COMMIT, os_page_flags) != nullptr; + DN_Atomic_AddU64(&g_dn_core->mem_allocs_total, 1); + DN_Atomic_AddU64(&g_dn_core->mem_allocs_frame, 1); return result; } -DQN_API void Dqn_OS_MemDecommit(void *ptr, Dqn_usize size) +DN_API void DN_OS_MemDecommit(void *ptr, DN_USize size) { // NOTE: This is a decommit call, which is explicitly saying to free the // pages but not the address space, you would use OS_MemRelease to release // everything. - DQN_MSVC_WARNING_PUSH - DQN_MSVC_WARNING_DISABLE(6250) // Calling 'VirtualFree' without the MEM_RELEASE flag might free memory but not address descriptors (VADs). This causes address space leaks. + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(6250) // Calling 'VirtualFree' without the MEM_RELEASE flag might free memory but not address descriptors (VADs). This causes address space leaks. VirtualFree(ptr, size, MEM_DECOMMIT); - DQN_MSVC_WARNING_POP + DN_MSVC_WARNING_POP } -DQN_API void Dqn_OS_MemRelease(void *ptr, Dqn_usize size) +DN_API void DN_OS_MemRelease(void *ptr, DN_USize size) { (void)size; VirtualFree(ptr, 0, MEM_RELEASE); } -DQN_API int Dqn_OS_MemProtect(void *ptr, Dqn_usize size, uint32_t page_flags) +DN_API int DN_OS_MemProtect(void *ptr, DN_USize size, uint32_t page_flags) { if (!ptr || size == 0) return 0; - static Dqn_Str8 const ALIGNMENT_ERROR_MSG = - DQN_STR8("Page protection requires pointers to be page aligned because we " + static DN_Str8 const ALIGNMENT_ERROR_MSG = + DN_STR8("Page protection requires pointers to be page aligned because we " "can only guard memory at a multiple of the page boundary."); - DQN_ASSERTF(Dqn_IsPowerOfTwoAligned(DQN_CAST(uintptr_t)ptr, g_dqn_library->os_page_size), "%s", ALIGNMENT_ERROR_MSG.data); - DQN_ASSERTF(Dqn_IsPowerOfTwoAligned(size, g_dqn_library->os_page_size), "%s", ALIGNMENT_ERROR_MSG.data); + DN_ASSERTF(DN_IsPowerOfTwoAligned(DN_CAST(uintptr_t)ptr, g_dn_core->os_page_size), "%s", ALIGNMENT_ERROR_MSG.data); + DN_ASSERTF(DN_IsPowerOfTwoAligned(size, g_dn_core->os_page_size), "%s", ALIGNMENT_ERROR_MSG.data); - unsigned long os_page_flags = Dqn_OS_MemConvertPageToOSFlags_(page_flags); + unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags); unsigned long prev_flags = 0; int result = VirtualProtect(ptr, size, os_page_flags, &prev_flags); (void)prev_flags; if (result == 0) - DQN_ASSERTF(result, "VirtualProtect failed"); + DN_ASSERTF(result, "VirtualProtect failed"); return result; } +DN_API void *DN_OS_MemAlloc(DN_USize size, DN_ZeroMem zero_mem) +{ + uint32_t flags = zero_mem == DN_ZeroMem_Yes ? HEAP_ZERO_MEMORY : 0; + DN_ASSERT(size <= DN_CAST(DWORD)(-1)); + void *result = HeapAlloc(GetProcessHeap(), flags, DN_CAST(DWORD) size); + return result; +} + +DN_API void DN_OS_MemDealloc(void *ptr) +{ + HeapFree(GetProcessHeap(), 0, ptr); +} + // NOTE: [$DATE] Date ////////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSDateTime Dqn_OS_DateLocalTimeNow() +DN_API DN_OSDateTime DN_OS_DateLocalTimeNow() { SYSTEMTIME sys_time; GetLocalTime(&sys_time); - Dqn_OSDateTime result = {}; - result.hour = DQN_CAST(uint8_t) sys_time.wHour; - result.minutes = DQN_CAST(uint8_t) sys_time.wMinute; - result.seconds = DQN_CAST(uint8_t) sys_time.wSecond; - result.day = DQN_CAST(uint8_t) sys_time.wDay; - result.month = DQN_CAST(uint8_t) sys_time.wMonth; - result.year = DQN_CAST(int16_t) sys_time.wYear; + DN_OSDateTime result = {}; + result.hour = DN_CAST(uint8_t) sys_time.wHour; + result.minutes = DN_CAST(uint8_t) sys_time.wMinute; + result.seconds = DN_CAST(uint8_t) sys_time.wSecond; + result.day = DN_CAST(uint8_t) sys_time.wDay; + result.month = DN_CAST(uint8_t) sys_time.wMonth; + result.year = DN_CAST(int16_t) sys_time.wYear; return result; } -const uint64_t DQN_OS_WIN32_UNIX_TIME_START = 0x019DB1DED53E8000; // January 1, 1970 (start of Unix epoch) in "ticks" -const uint64_t DQN_OS_WIN32_FILE_TIME_TICKS_PER_SECOND = 10'000'000; // Filetime returned is in intervals of 100 nanoseconds +const uint64_t DN_OS_WIN32_UNIX_TIME_START = 0x019DB1DED53E8000; // January 1, 1970 (start of Unix epoch) in "ticks" +const uint64_t DN_OS_WIN32_FILE_TIME_TICKS_PER_SECOND = 10'000'000; // Filetime returned is in intervals of 100 nanoseconds -DQN_API uint64_t Dqn_OS_DateUnixTime() +DN_API uint64_t DN_OS_DateUnixTimeNs() { FILETIME file_time; GetSystemTimeAsFileTime(&file_time); + // NOTE: Filetime returned is in intervals of 100 nanoeseconds so we + // multiply by 100 to get nanoseconds. LARGE_INTEGER date_time; date_time.u.LowPart = file_time.dwLowDateTime; date_time.u.HighPart = file_time.dwHighDateTime; - uint64_t result = (date_time.QuadPart - DQN_OS_WIN32_UNIX_TIME_START) / DQN_OS_WIN32_FILE_TIME_TICKS_PER_SECOND; + uint64_t result = (date_time.QuadPart - DN_OS_WIN32_UNIX_TIME_START) * 100; return result; } -DQN_API Dqn_OSDateTime Dqn_OS_DateUnixTimeToDate(uint64_t time) +static SYSTEMTIME DN_OS_DateToSystemTime_(DN_OSDateTime date) +{ + SYSTEMTIME result = {}; + result.wYear = date.year; + result.wMonth = date.month; + result.wDay = date.day; + result.wHour = date.hour; + result.wMinute = date.minutes; + result.wSecond = date.seconds; + return result; +} + +static uint64_t DN_OS_SystemTimeToUnixTimeS_(SYSTEMTIME *sys_time) +{ + FILETIME file_time = {}; + SystemTimeToFileTime(sys_time, &file_time); + + LARGE_INTEGER date_time; + date_time.u.LowPart = file_time.dwLowDateTime; + date_time.u.HighPart = file_time.dwHighDateTime; + uint64_t result = (date_time.QuadPart - DN_OS_WIN32_UNIX_TIME_START) / DN_OS_WIN32_FILE_TIME_TICKS_PER_SECOND; + return result; +} + +DN_API uint64_t DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date) +{ + SYSTEMTIME local_time = DN_OS_DateToSystemTime_(date); + SYSTEMTIME sys_time = {}; + TzSpecificLocalTimeToSystemTime(nullptr, &local_time, &sys_time); + uint64_t result = DN_OS_SystemTimeToUnixTimeS_(&sys_time); + return result; +} + +DN_API uint64_t DN_OS_DateToUnixTimeS(DN_OSDateTime date) +{ + DN_ASSERT(DN_OS_DateIsValid(date)); + + SYSTEMTIME sys_time = DN_OS_DateToSystemTime_(date); + uint64_t result = DN_OS_SystemTimeToUnixTimeS_(&sys_time); + return result; +} + +DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(uint64_t time) { // NOTE: Windows epoch time starts from Jan 1, 1601 and counts in // 100-nanoseconds intervals. @@ -146,40 +207,17 @@ DQN_API Dqn_OSDateTime Dqn_OS_DateUnixTimeToDate(uint64_t time) file_time.dwHighDateTime = win32_time >> 32; FileTimeToSystemTime(&file_time, &sys_time); - Dqn_OSDateTime result = {}; - result.year = DQN_CAST(uint16_t)sys_time.wYear; - result.month = DQN_CAST(uint8_t)sys_time.wMonth; - result.day = DQN_CAST(uint8_t)sys_time.wDay; - result.hour = DQN_CAST(uint8_t)sys_time.wHour; - result.minutes = DQN_CAST(uint8_t)sys_time.wMinute; - result.seconds = DQN_CAST(uint8_t)sys_time.wSecond; + DN_OSDateTime result = {}; + result.year = DN_CAST(uint16_t)sys_time.wYear; + result.month = DN_CAST(uint8_t)sys_time.wMonth; + result.day = DN_CAST(uint8_t)sys_time.wDay; + result.hour = DN_CAST(uint8_t)sys_time.wHour; + result.minutes = DN_CAST(uint8_t)sys_time.wMinute; + result.seconds = DN_CAST(uint8_t)sys_time.wSecond; return result; } -DQN_API uint64_t Dqn_OS_DateToUnixTime(Dqn_OSDateTime date) -{ - DQN_ASSERT(Dqn_OS_DateIsValid(date)); - - SYSTEMTIME sys_time = {}; - sys_time.wYear = date.year; - sys_time.wMonth = date.month; - sys_time.wDay = date.day; - sys_time.wHour = date.hour; - sys_time.wMinute = date.minutes; - sys_time.wSecond = date.seconds; - - FILETIME file_time = {}; - SystemTimeToFileTime(&sys_time, &file_time); - - LARGE_INTEGER date_time; - date_time.u.LowPart = file_time.dwLowDateTime; - date_time.u.HighPart = file_time.dwHighDateTime; - - uint64_t result = (date_time.QuadPart - DQN_OS_WIN32_UNIX_TIME_START) / DQN_OS_WIN32_FILE_TIME_TICKS_PER_SECOND; - return result; -} - -DQN_API bool Dqn_OS_SecureRNGBytes(void *buffer, uint32_t size) +DN_API bool DN_OS_SecureRNGBytes(void *buffer, uint32_t size) { if (!buffer || size < 0) return false; @@ -188,56 +226,65 @@ DQN_API bool Dqn_OS_SecureRNGBytes(void *buffer, uint32_t size) return true; bool init = true; - Dqn_TicketMutex_Begin(&g_dqn_library->win32_bcrypt_rng_mutex); - if (!g_dqn_library->win32_bcrypt_rng_handle) + DN_TicketMutex_Begin(&g_dn_core->win32_bcrypt_rng_mutex); + if (!g_dn_core->win32_bcrypt_rng_handle) { wchar_t const BCRYPT_ALGORITHM[] = L"RNG"; - long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&g_dqn_library->win32_bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/); - if (!g_dqn_library->win32_bcrypt_rng_handle || init_status != 0) + long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&g_dn_core->win32_bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/); + if (!g_dn_core->win32_bcrypt_rng_handle || init_status != 0) { - Dqn_Log_ErrorF("Failed to initialise random number generator, error: %d", init_status); + DN_Log_ErrorF("Failed to initialise random number generator, error: %d", init_status); init = false; } } - Dqn_TicketMutex_End(&g_dqn_library->win32_bcrypt_rng_mutex); + DN_TicketMutex_End(&g_dn_core->win32_bcrypt_rng_mutex); if (!init) return false; - long gen_status = BCryptGenRandom(g_dqn_library->win32_bcrypt_rng_handle, DQN_CAST(unsigned char *)buffer, size, 0 /*flags*/); + long gen_status = BCryptGenRandom(g_dn_core->win32_bcrypt_rng_handle, DN_CAST(unsigned char *)buffer, size, 0 /*flags*/); if (gen_status != 0) { - Dqn_Log_ErrorF("Failed to generate random bytes: %d", gen_status); + DN_Log_ErrorF("Failed to generate random bytes: %d", gen_status); return false; } return true; } -DQN_API Dqn_Str8 Dqn_OS_EXEPath(Dqn_Arena *arena) +DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value) { - Dqn_Str8 result = {}; - if (!arena) - return result; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(arena); - Dqn_Str16 exe_dir16 = Dqn_Win_EXEPathW(t_mem.arena); - result = Dqn_Win_Str16ToStr8(arena, exe_dir16); + DN_TLSTMem tmem = DN_TLS_PushTMem(nullptr); + DN_Str16 name16 = DN_Win_Str8ToStr16(tmem.arena, name); + DN_Str16 value16 = DN_Win_Str8ToStr16(tmem.arena, value); + bool result = SetEnvironmentVariableW(name16.data, value16.data) != 0; return result; } -DQN_API void Dqn_OS_SleepMs(Dqn_uint milliseconds) +DN_API DN_Str8 DN_OS_EXEPath(DN_Arena *arena) +{ + DN_Str8 result = {}; + if (!arena) + return result; + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str16 exe_dir16 = DN_Win_EXEPathW(tmem.arena); + result = DN_Win_Str16ToStr8(arena, exe_dir16); + return result; +} + +DN_API void DN_OS_SleepMs(DN_UInt milliseconds) { Sleep(milliseconds); } -DQN_API uint64_t Dqn_OS_PerfCounterFrequency() +DN_API uint64_t DN_OS_PerfCounterFrequency() { - uint64_t result = g_dqn_library->win32_qpc_frequency.QuadPart; - DQN_ASSERTF(result, "Initialise the library with Dqn_Library_Init() to get a valid QPC frequency value"); + uint64_t result = g_dn_core->win32_qpc_frequency.QuadPart; + DN_ASSERTF(result, "Initialise the library with DN_Library_Init() to get a valid QPC frequency value"); return result; } -DQN_API uint64_t Dqn_OS_PerfCounterNow() +DN_API uint64_t DN_OS_PerfCounterNow() { LARGE_INTEGER integer = {}; QueryPerformanceCounter(&integer); @@ -245,8 +292,8 @@ DQN_API uint64_t Dqn_OS_PerfCounterNow() return result; } -#if !defined(DQN_NO_OS_FILE_API) -static uint64_t Dqn_Win_FileTimeToSeconds_(FILETIME const *time) +#if !defined(DN_NO_OS_FILE_API) +static uint64_t DN_Win_FileTimeToSeconds_(FILETIME const *time) { ULARGE_INTEGER time_large_int = {}; time_large_int.u.LowPart = time->dwLowDateTime; @@ -255,47 +302,47 @@ static uint64_t Dqn_Win_FileTimeToSeconds_(FILETIME const *time) return result; } -DQN_API Dqn_OSPathInfo Dqn_OS_PathInfo(Dqn_Str8 path) +DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) { - Dqn_OSPathInfo result = {}; - if (!Dqn_Str8_HasData(path)) + DN_OSPathInfo result = {}; + if (!DN_Str8_HasData(path)) return result; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str16 path16 = Dqn_Win_Str8ToStr16(t_mem.arena, path); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str16 path16 = DN_Win_Str8ToStr16(tmem.arena, path); WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) return result; result.exists = true; - result.create_time_in_s = Dqn_Win_FileTimeToSeconds_(&attrib_data.ftCreationTime); - result.last_access_time_in_s = Dqn_Win_FileTimeToSeconds_(&attrib_data.ftLastAccessTime); - result.last_write_time_in_s = Dqn_Win_FileTimeToSeconds_(&attrib_data.ftLastWriteTime); + result.create_time_in_s = DN_Win_FileTimeToSeconds_(&attrib_data.ftCreationTime); + result.last_access_time_in_s = DN_Win_FileTimeToSeconds_(&attrib_data.ftLastAccessTime); + result.last_write_time_in_s = DN_Win_FileTimeToSeconds_(&attrib_data.ftLastWriteTime); LARGE_INTEGER large_int = {}; - large_int.u.HighPart = DQN_CAST(int32_t)attrib_data.nFileSizeHigh; + large_int.u.HighPart = DN_CAST(int32_t)attrib_data.nFileSizeHigh; large_int.u.LowPart = attrib_data.nFileSizeLow; result.size = (uint64_t)large_int.QuadPart; if (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - result.type = Dqn_OSPathInfoType_Directory; + result.type = DN_OSPathInfoType_Directory; else - result.type = Dqn_OSPathInfoType_File; + result.type = DN_OSPathInfoType_File; } return result; } -DQN_API bool Dqn_OS_PathDelete(Dqn_Str8 path) +DN_API bool DN_OS_PathDelete(DN_Str8 path) { bool result = false; - if (!Dqn_Str8_HasData(path)) + if (!DN_Str8_HasData(path)) return result; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str16 path16 = Dqn_Win_Str8ToStr16(t_mem.arena, path); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str16 path16 = DN_Win_Str8ToStr16(tmem.arena, path); if (path16.size) { result = DeleteFileW(path16.data); if (!result) @@ -304,14 +351,14 @@ DQN_API bool Dqn_OS_PathDelete(Dqn_Str8 path) return result; } -DQN_API bool Dqn_OS_FileExists(Dqn_Str8 path) +DN_API bool DN_OS_FileExists(DN_Str8 path) { bool result = false; - if (!Dqn_Str8_HasData(path)) + if (!DN_Str8_HasData(path)) return result; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str16 path16 = Dqn_Win_Str8ToStr16(t_mem.arena, path); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str16 path16 = DN_Win_Str8ToStr16(tmem.arena, path); if (path16.size) { WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) { @@ -322,35 +369,35 @@ DQN_API bool Dqn_OS_FileExists(Dqn_Str8 path) return result; } -DQN_API bool Dqn_OS_CopyFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_ErrorSink *error) +DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err) { bool result = false; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str16 src16 = Dqn_Win_Str8ToStr16(t_mem.arena, src); - Dqn_Str16 dest16 = Dqn_Win_Str8ToStr16(t_mem.arena, dest); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str16 src16 = DN_Win_Str8ToStr16(tmem.arena, src); + DN_Str16 dest16 = DN_Win_Str8ToStr16(tmem.arena, dest); int fail_if_exists = overwrite == false; result = CopyFileW(src16.data, dest16.data, fail_if_exists) != 0; if (!result) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); - Dqn_ErrorSink_MakeF(error, + DN_WinError win_error = DN_Win_LastError(tmem.arena); + DN_ErrSink_AppendF(err, win_error.code, "Failed to copy file '%.*s' to '%.*s': (%u) %.*s", - DQN_STR_FMT(src), - DQN_STR_FMT(dest), + DN_STR_FMT(src), + DN_STR_FMT(dest), win_error.code, - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(win_error.msg)); } return result; } -DQN_API bool Dqn_OS_MoveFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_ErrorSink *error) +DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err) { bool result = false; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str16 src16 = Dqn_Win_Str8ToStr16(t_mem.arena, src); - Dqn_Str16 dest16 = Dqn_Win_Str8ToStr16(t_mem.arena, dest); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str16 src16 = DN_Win_Str8ToStr16(tmem.arena, src); + DN_Str16 dest16 = DN_Win_Str8ToStr16(tmem.arena, dest); unsigned long flags = MOVEFILE_COPY_ALLOWED; if (overwrite) { @@ -359,23 +406,23 @@ DQN_API bool Dqn_OS_MoveFile(Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_Er result = MoveFileExW(src16.data, dest16.data, flags) != 0; if (!result) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); - Dqn_ErrorSink_MakeF(error, + DN_WinError win_error = DN_Win_LastError(tmem.arena); + DN_ErrSink_AppendF(err, win_error.code, "Failed to move file '%.*s' to '%.*s': (%u) %.*s", - DQN_STR_FMT(src), - DQN_STR_FMT(dest), + DN_STR_FMT(src), + DN_STR_FMT(dest), win_error.code, - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(win_error.msg)); } return result; } -DQN_API bool Dqn_OS_MakeDir(Dqn_Str8 path) +DN_API bool DN_OS_MakeDir(DN_Str8 path) { bool result = true; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str16 path16 = Dqn_Win_Str8ToStr16(t_mem.arena, path); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str16 path16 = DN_Win_Str8ToStr16(tmem.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 @@ -389,7 +436,7 @@ DQN_API bool Dqn_OS_MakeDir(Dqn_Str8 path) // If we find a file at some point in the path we fail out because the // series of directories can not be made if a file exists with the same // name. - for (Dqn_usize index = 0; index < path16.size; index++) { + for (DN_USize index = 0; index < path16.size; index++) { bool first_char = index == (path16.size - 1); wchar_t ch = path16.data[index]; if (ch == '/' || ch == '\\' || first_char) { @@ -423,14 +470,14 @@ DQN_API bool Dqn_OS_MakeDir(Dqn_Str8 path) } -DQN_API bool Dqn_OS_DirExists(Dqn_Str8 path) +DN_API bool DN_OS_DirExists(DN_Str8 path) { bool result = false; - if (!Dqn_Str8_HasData(path)) + if (!DN_Str8_HasData(path)) return result; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str16 path16 = Dqn_Win_Str8ToStr16(t_mem.arena, path); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str16 path16 = DN_Win_Str8ToStr16(tmem.arena, path); if (path16.size) { WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) { @@ -442,54 +489,96 @@ DQN_API bool Dqn_OS_DirExists(Dqn_Str8 path) return result; } -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSFile Dqn_OS_FileOpen(Dqn_Str8 path, Dqn_OSFileOpen open_mode, uint32_t access, Dqn_ErrorSink *error) +DN_API bool DN_OS_DirIterate(DN_Str8 path, DN_OSDirIterator *it) { - Dqn_OSFile result = {}; - if (!Dqn_Str8_HasData(path) || path.size <= 0) + if (!DN_Str8_HasData(path) || !it || path.size <= 0) + return false; + + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Win_FolderIteratorW wide_it = {}; + DN_Str16 path16 = {}; + if (it->handle) { + wide_it.handle = it->handle; + } else { + bool needs_asterisks = DN_Str8_EndsWith(path, DN_STR8("\\")) || + DN_Str8_EndsWith(path, DN_STR8("/")); + bool has_glob = DN_Str8_EndsWith(path, DN_STR8("\\*")) || + DN_Str8_EndsWith(path, DN_STR8("/*")); + + DN_Str8 adjusted_path = path; + if (!has_glob) { + // NOTE: We are missing the glob for enumerating the files, we will + // 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_STR_FMT(path)); + else + adjusted_path = DN_OS_PathF(tmem.arena, "%.*s/*", DN_STR_FMT(path)); + } + + path16 = DN_Win_Str8ToStr16(tmem.arena, adjusted_path); + if (path16.size <= 0) // Conversion error + return false; + } + + bool result = DN_Win_DirWIterate(path16, &wide_it); + it->handle = wide_it.handle; + if (result) { + int size = DN_Win_Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ARRAY_UCOUNT(it->buffer)); + it->file_name = DN_Str8_Init(it->buffer, size); + } + + return result; +} + +// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// +DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, uint32_t access, DN_ErrSink *err) +{ + DN_OSFile result = {}; + if (!DN_Str8_HasData(path) || path.size <= 0) return result; - if ((access & ~Dqn_OSFileAccess_All) || ((access & Dqn_OSFileAccess_All) == 0)) { - DQN_INVALID_CODE_PATH; + if ((access & ~DN_OSFileAccess_All) || ((access & DN_OSFileAccess_All) == 0)) { + DN_INVALID_CODE_PATH; return result; } unsigned long create_flag = 0; switch (open_mode) { - case Dqn_OSFileOpen_CreateAlways: create_flag = CREATE_ALWAYS; break; - case Dqn_OSFileOpen_OpenIfExist: create_flag = OPEN_EXISTING; break; - case Dqn_OSFileOpen_OpenAlways: create_flag = OPEN_ALWAYS; break; - default: DQN_INVALID_CODE_PATH; return result; + case DN_OSFileOpen_CreateAlways: create_flag = CREATE_ALWAYS; break; + case DN_OSFileOpen_OpenIfExist: create_flag = OPEN_EXISTING; break; + case DN_OSFileOpen_OpenAlways: create_flag = OPEN_ALWAYS; break; + default: DN_INVALID_CODE_PATH; return result; } unsigned long access_mode = 0; - if (access & Dqn_OSFileAccess_AppendOnly) { - DQN_ASSERTF((access & ~Dqn_OSFileAccess_AppendOnly) == 0, + if (access & DN_OSFileAccess_AppendOnly) { + DN_ASSERTF((access & ~DN_OSFileAccess_AppendOnly) == 0, "Append can only be applied exclusively to the file, other access modes not permitted"); access_mode = FILE_APPEND_DATA; } else { - if (access & Dqn_OSFileAccess_Read) + if (access & DN_OSFileAccess_Read) access_mode |= GENERIC_READ; - if (access & Dqn_OSFileAccess_Write) + if (access & DN_OSFileAccess_Write) access_mode |= GENERIC_WRITE; - if (access & Dqn_OSFileAccess_Execute) + if (access & DN_OSFileAccess_Execute) access_mode |= GENERIC_EXECUTE; } - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str16 path16 = Dqn_Win_Str8ToStr16(t_mem.arena, path); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str16 path16 = DN_Win_Str8ToStr16(tmem.arena, path); void *handle = CreateFileW(/*LPCWSTR lpFileName*/ path16.data, /*DWORD dwDesiredAccess*/ access_mode, - /*DWORD dwShareMode*/ 0, + /*DWORD dwShareMode*/ FILE_SHARE_READ | FILE_SHARE_WRITE, /*LPSECURITY_ATTRIBUTES lpSecurityAttributes*/ nullptr, /*DWORD dwCreationDisposition*/ create_flag, /*DWORD dwFlagsAndAttributes*/ FILE_ATTRIBUTE_NORMAL, /*HANDLE hTemplateFile*/ nullptr); if (handle == INVALID_HANDLE_VALUE) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); + DN_WinError win_error = DN_Win_LastError(tmem.arena); result.error = true; - Dqn_ErrorSink_MakeF(error, win_error.code, "Failed to open file at '%.*s': '%.*s'", DQN_STR_FMT(path), DQN_STR_FMT(win_error.msg)); + DN_ErrSink_AppendF(err, win_error.code, "Failed to open file at '%.*s': '%.*s'", DN_STR_FMT(path), DN_STR_FMT(win_error.msg)); return result; } @@ -497,219 +586,282 @@ DQN_API Dqn_OSFile Dqn_OS_FileOpen(Dqn_Str8 path, Dqn_OSFileOpen open_mode, uint return result; } -DQN_API bool Dqn_OS_FileRead(Dqn_OSFile *file, void *buffer, Dqn_usize size, Dqn_ErrorSink *error) +DN_API bool DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err) { if (!file || !file->handle || file->error || !buffer || size <= 0) return false; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - if (!DQN_CHECK(size <= (unsigned long)-1)) { - Dqn_Str8 buffer_size_str8 = Dqn_U64ToByteSizeStr8(t_mem.arena, size, Dqn_U64ByteSizeType_Auto); - Dqn_ErrorSink_MakeF( - error, + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + if (!DN_CHECK(size <= (unsigned long)-1)) { + DN_Str8 buffer_size_str8 = DN_U64ToByteSizeStr8(tmem.arena, size, DN_U64ByteSizeType_Auto); + DN_ErrSink_AppendF( + err, 1 /*error_code*/, "Current implementation doesn't support reading >4GiB file (requested %.*s), implement Win32 overlapped IO", - DQN_STR_FMT(buffer_size_str8)); + DN_STR_FMT(buffer_size_str8)); return false; } unsigned long bytes_read = 0; unsigned long read_result = ReadFile(/*HANDLE hFile*/ file->handle, /*LPVOID lpBuffer*/ buffer, - /*DWORD nNumberOfBytesToRead*/ DQN_CAST(unsigned long)size, + /*DWORD nNumberOfBytesToRead*/ DN_CAST(unsigned long)size, /*LPDWORD lpNumberOfByesRead*/ &bytes_read, /*LPOVERLAPPED lpOverlapped*/ nullptr); if (read_result == 0) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); - Dqn_ErrorSink_MakeF(error, win_error.code, "Failed to read data from file: (%u) %.*s", win_error.code, DQN_STR_FMT(win_error.msg)); + DN_WinError win_error = DN_Win_LastError(tmem.arena); + DN_ErrSink_AppendF(err, win_error.code, "Failed to read data from file: (%u) %.*s", win_error.code, DN_STR_FMT(win_error.msg)); return false; } if (bytes_read != size) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); - Dqn_ErrorSink_MakeF( - error, + DN_WinError win_error = DN_Win_LastError(tmem.arena); + DN_ErrSink_AppendF( + err, win_error.code, "Failed to read the desired number of bytes from file, we read %uB but we expected %uB: (%u) %.*s", bytes_read, - DQN_CAST(unsigned long)size, + DN_CAST(unsigned long)size, win_error.code, - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(win_error.msg)); return false; } return true; } -DQN_API bool Dqn_OS_FileWritePtr(Dqn_OSFile *file, void const *buffer, Dqn_usize size, Dqn_ErrorSink *error) +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; bool result = true; - char const *end = DQN_CAST(char *) buffer + size; - for (char const *ptr = DQN_CAST(char const *) buffer; result && ptr != end;) { - unsigned long write_size = DQN_CAST(unsigned long)DQN_MIN((unsigned long)-1, end - ptr); + char const *end = DN_CAST(char *) buffer + size; + for (char const *ptr = DN_CAST(char const *) buffer; result && ptr != end;) { + unsigned long write_size = DN_CAST(unsigned long)DN_MIN((unsigned long)-1, end - ptr); unsigned long bytes_written = 0; result = WriteFile(file->handle, ptr, write_size, &bytes_written, nullptr /*lpOverlapped*/) != 0; ptr += bytes_written; } if (!result) { - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); - Dqn_Str8 buffer_size_str8 = Dqn_U64ToByteSizeStr8(t_mem.arena, size, Dqn_U64ByteSizeType_Auto); - Dqn_ErrorSink_MakeF(error, win_error.code, "Failed to write buffer (%.*s) to file handle: %.*s", DQN_STR_FMT(buffer_size_str8), DQN_STR_FMT(win_error.msg)); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_WinError win_error = DN_Win_LastError(tmem.arena); + DN_Str8 buffer_size_str8 = DN_U64ToByteSizeStr8(tmem.arena, size, DN_U64ByteSizeType_Auto); + DN_ErrSink_AppendF(err, win_error.code, "Failed to write buffer (%.*s) to file handle: %.*s", DN_STR_FMT(buffer_size_str8), DN_STR_FMT(win_error.msg)); } return result; } -DQN_API void Dqn_OS_FileClose(Dqn_OSFile *file) +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_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_WinError win_error = DN_Win_LastError(tmem.arena); + DN_ErrSink_AppendF(err, win_error.code, "Failed to flush file buffer to disk: %.*s", DN_STR_FMT(win_error.msg)); + } + + return DN_CAST(bool)result; +} + +DN_API void DN_OS_FileClose(DN_OSFile *file) { if (!file || !file->handle || file->error) return; CloseHandle(file->handle); *file = {}; } -#endif // !defined(DQN_NO_OS_FILE_API) +#endif // !defined(DN_NO_OS_FILE_API) -// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// -DQN_API void Dqn_OS_Exit(int32_t exit_code) +// NOTE: [$EXEC] DN_OSExec //////////////////////////////////////////////////////////////////////// +DN_API void DN_OS_Exit(int32_t exit_code) { - ExitProcess(DQN_CAST(UINT)exit_code); + ExitProcess(DN_CAST(UINT)exit_code); } -DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle, Dqn_Arena *arena, Dqn_ErrorSink *error) +DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, + char *stdout_buffer, + size_t *stdout_size, + char *stderr_buffer, + size_t *stderr_size, + uint32_t timeout_ms, + DN_ErrSink *err) { - Dqn_OSExecResult result = {}; + DN_OSExecResult result = {}; + size_t stdout_buffer_size = 0; + size_t stderr_buffer_size = 0; + if (stdout_size) { + stdout_buffer_size = *stdout_size; + *stdout_size = 0; + } + + if (stderr_size) { + stderr_buffer_size = *stderr_size; + *stderr_size = 0; + } + if (!handle.process || handle.os_error_code || handle.exit_code) { if (handle.os_error_code) result.os_error_code = handle.os_error_code; else result.exit_code = handle.exit_code; - DQN_ASSERT(!handle.stdout_read); - DQN_ASSERT(!handle.stdout_write); - DQN_ASSERT(!handle.stderr_read); - DQN_ASSERT(!handle.stderr_write); - DQN_ASSERT(!handle.process); + DN_ASSERT(!handle.stdout_read); + DN_ASSERT(!handle.stdout_write); + DN_ASSERT(!handle.stderr_read); + DN_ASSERT(!handle.stderr_write); + DN_ASSERT(!handle.process); return result; } - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(arena); - Dqn_Str8Builder stdout_builder = {}; - Dqn_Str8Builder stderr_builder = {}; - if (arena) { - stdout_builder.arena = t_mem.arena; - stderr_builder.arena = t_mem.arena; - } + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DWORD stdout_bytes_available = 0; + DWORD stderr_bytes_available = 0; + PeekNamedPipe(handle.stdout_read, nullptr, 0, nullptr, &stdout_bytes_available, nullptr); + PeekNamedPipe(handle.stderr_read, nullptr, 0, nullptr, &stderr_bytes_available, nullptr); - DWORD const SLOW_WAIT_TIME_MS = 100; - DWORD const FAST_WAIT_TIME_MS = 20; - DWORD wait_ms = FAST_WAIT_TIME_MS; - DWORD exec_result = WAIT_TIMEOUT; - while (exec_result == WAIT_TIMEOUT) { - exec_result = WaitForSingleObject(handle.process, wait_ms); - if (exec_result == WAIT_FAILED) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); - result.os_error_code = win_error.code; - Dqn_ErrorSink_MakeF(error, result.os_error_code, "Executed command failed to terminate: %.*s", DQN_STR_FMT(win_error.msg)); - } else if (DQN_CHECK(exec_result == WAIT_TIMEOUT || exec_result == WAIT_OBJECT_0)) { - // NOTE: If the pipes are full, the process will block. We - // periodically flush the pipes to make sure this doesn't happen + DWORD exec_result = WAIT_TIMEOUT; + if (stdout_bytes_available == 0 && stderr_bytes_available == 0) + exec_result = WaitForSingleObject(handle.process, timeout_ms); + if (exec_result == WAIT_FAILED) { + DN_WinError win_error = DN_Win_LastError(tmem.arena); + result.os_error_code = win_error.code; + DN_ErrSink_AppendF(err, result.os_error_code, "Executed command failed to terminate: %.*s", DN_STR_FMT(win_error.msg)); + } else { + if (DN_CHECK(exec_result == WAIT_TIMEOUT || exec_result == WAIT_OBJECT_0)) { // NOTE: Read stdout from process ////////////////////////////////////////////////////// - // TODO: Allow the user to pump the execution of the command w/ a user passed in buffer. - char output_buffer[DQN_KILOBYTES(8)]; - DWORD stdout_bytes_available = 0; + // If the pipes are full, the process will block. We periodically + // flush the pipes to make sure this doesn't happen + char sink[DN_KILOBYTES(8)]; + stdout_bytes_available = 0; if (PeekNamedPipe(handle.stdout_read, nullptr, 0, nullptr, &stdout_bytes_available, nullptr)) { if (stdout_bytes_available) { - for (;;) { - DWORD bytes_read = 0; - BOOL success = ReadFile(handle.stdout_read, output_buffer, sizeof(output_buffer), &bytes_read, NULL); - if (!success || bytes_read == 0) - break; - - if (handle.stdout_write && arena) - Dqn_Str8Builder_AddF(&stdout_builder, "%.*s", bytes_read, output_buffer); - - if (bytes_read < sizeof(output_buffer)) - break; - } + DWORD bytes_read = 0; + char *dest_buffer = handle.stdout_write && stdout_buffer ? stdout_buffer : sink; + size_t dest_size = handle.stdout_write && stdout_buffer ? stdout_buffer_size : DN_ARRAY_UCOUNT(sink); + BOOL success = ReadFile(handle.stdout_read, dest_buffer, DN_CAST(DWORD)dest_size, &bytes_read, NULL); + (void)success; // TODO: + if (stdout_size) + *stdout_size = bytes_read; } } // NOTE: Read stderr from process ////////////////////////////////////////////////////// - DWORD stderr_bytes_available = 0; + stderr_bytes_available = 0; if (PeekNamedPipe(handle.stderr_read, nullptr, 0, nullptr, &stderr_bytes_available, nullptr)) { if (stderr_bytes_available) { - for (;;) { - DWORD bytes_read = 0; - BOOL success = ReadFile(handle.stderr_read, output_buffer, sizeof(output_buffer), &bytes_read, NULL); - if (!success || bytes_read == 0) - break; - - if (handle.stderr_read && arena) - Dqn_Str8Builder_AddF(&stderr_builder, "%.*s", bytes_read, output_buffer); - - if (bytes_read < sizeof(output_buffer)) - break; - } + char *dest_buffer = handle.stderr_write && stderr_buffer ? stderr_buffer : sink; + size_t dest_size = handle.stderr_write && stderr_buffer ? stderr_buffer_size : DN_ARRAY_UCOUNT(sink); + DWORD bytes_read = 0; + BOOL success = ReadFile(handle.stderr_read, dest_buffer, DN_CAST(DWORD)dest_size, &bytes_read, NULL); + (void)success; // TODO: + if (stderr_size) + *stderr_size = bytes_read; } } - - // NOTE: If we produced some data, we'll sleep for a short amount of - // time because if we have the presence of data it's typical we deal - // with N amount of. Otherwise if we timed-out and we didn't produce - // any data, its more likely this is a long running operation so we - // sleep longer to avoid slamming the CPU. - if (stdout_bytes_available || stderr_bytes_available) { - wait_ms = FAST_WAIT_TIME_MS; - } else { - wait_ms = SLOW_WAIT_TIME_MS; - } } } - // NOTE: Get stdout/stderr. If no arena is passed this is a no-op ////////////////////////////// - result.stdout_text = Dqn_Str8Builder_Build(&stdout_builder, arena); - result.stderr_text = Dqn_Str8Builder_Build(&stderr_builder, arena); - - // NOTE: Get exit code ///////////////////////////////////////////////////////////////////////// - if (exec_result != WAIT_FAILED) { + result.finished = exec_result == WAIT_OBJECT_0 || exec_result == WAIT_FAILED; + if (exec_result == WAIT_OBJECT_0) { DWORD exit_status; if (GetExitCodeProcess(handle.process, &exit_status)) { result.exit_code = exit_status; } else { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); + DN_WinError win_error = DN_Win_LastError(tmem.arena); result.os_error_code = win_error.code; - Dqn_ErrorSink_MakeF(error, + DN_ErrSink_AppendF(err, result.os_error_code, "Failed to retrieve command exit code: %.*s", - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(win_error.msg)); } + + // NOTE: Cleanup /////////////////////////////////////////////////////////////////////////////// + CloseHandle(handle.stdout_write); + CloseHandle(handle.stderr_write); + CloseHandle(handle.stdout_read); + CloseHandle(handle.stderr_read); + CloseHandle(handle.process); } - // NOTE: Cleanup /////////////////////////////////////////////////////////////////////////////// - CloseHandle(handle.stdout_write); - CloseHandle(handle.stderr_write); - CloseHandle(handle.stdout_read); - CloseHandle(handle.stderr_read); - CloseHandle(handle.process); + result.stdout_text = DN_Str8_Init(stdout_buffer, stdout_size ? *stdout_size : 0); + result.stderr_text = DN_Str8_Init(stderr_buffer, stderr_size ? *stderr_size : 0); return result; } -DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync(Dqn_Slice cmd_line, Dqn_Str8 working_dir, uint8_t exec_flags, Dqn_ErrorSink *error) + +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) { + result.finished = true; + if (handle.os_error_code) + result.os_error_code = handle.os_error_code; + else + result.exit_code = handle.exit_code; + + DN_ASSERT(!handle.stdout_read); + DN_ASSERT(!handle.stdout_write); + DN_ASSERT(!handle.stderr_read); + DN_ASSERT(!handle.stderr_write); + DN_ASSERT(!handle.process); + return result; + } + + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str8Builder stdout_builder = {}; + DN_Str8Builder stderr_builder = {}; + if (arena) { + stdout_builder.arena = tmem.arena; + stderr_builder.arena = tmem.arena; + } + + uint32_t const SLOW_WAIT_TIME_MS = 100; + uint32_t const FAST_WAIT_TIME_MS = 20; + uint32_t wait_ms = FAST_WAIT_TIME_MS; + while (!result.finished) { + size_t stdout_size = DN_KILOBYTES(8); + size_t stderr_size = DN_KILOBYTES(8); + char *stdout_buffer = DN_Arena_NewArray(tmem.arena, char, stdout_size, DN_ZeroMem_No); + char *stderr_buffer = DN_Arena_NewArray(tmem.arena, char, stderr_size, DN_ZeroMem_No); + result = DN_OS_ExecPump(handle, stdout_buffer, &stdout_size, stderr_buffer, &stderr_size, wait_ms, err); + DN_Str8Builder_AppendCopy(&stdout_builder, result.stdout_text); + DN_Str8Builder_AppendCopy(&stderr_builder, result.stderr_text); + wait_ms = (DN_Str8_HasData(result.stdout_text) || DN_Str8_HasData(result.stderr_text)) ? FAST_WAIT_TIME_MS : SLOW_WAIT_TIME_MS; + } + + // NOTE: Get stdout/stderr. If no arena is passed this is a no-op ////////////////////////////// + result.stdout_text = DN_Str8Builder_Build(&stdout_builder, arena); + result.stderr_text = DN_Str8Builder_Build(&stderr_builder, arena); + return result; +} + +DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, DN_OSExecArgs *args, DN_ErrSink *err) { // NOTE: Pre-amble ///////////////////////////////////////////////////////////////////////////// - Dqn_OSExecAsyncHandle result = {}; + DN_OSExecAsyncHandle result = {}; if (cmd_line.size == 0) return result; - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 cmd_rendered = Dqn_Slice_Str8Render(t_mem.arena, cmd_line, DQN_STR8(" ")); - Dqn_Str16 cmd16 = Dqn_Win_Str8ToStr16(t_mem.arena, cmd_rendered); - Dqn_Str16 working_dir16 = Dqn_Win_Str8ToStr16(t_mem.arena, working_dir); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 cmd_rendered = DN_Slice_Str8Render(tmem.arena, cmd_line, DN_STR8(" ")); + DN_Str16 cmd16 = DN_Win_Str8ToStr16(tmem.arena, cmd_rendered); + DN_Str16 working_dir16 = DN_Win_Str8ToStr16(tmem.arena, args->working_dir); + + DN_Str8Builder env_builder = DN_Str8Builder_Init_TLS(); + DN_Str8Builder_AppendArrayRef(&env_builder, args->environment.data, args->environment.size); + if (env_builder.string_size) + DN_Str8Builder_AppendRef(&env_builder, DN_STR8("\0")); + + DN_Str8 env_block8 = DN_Str8Builder_BuildDelimited_TLS(&env_builder, DN_STR8("\0")); + DN_Str16 env_block16 = {}; + if (env_block8.size) + env_block16 = DN_Win_Str8ToStr16(tmem.arena, env_block8); // NOTE: Stdout/err security attributes //////////////////////////////////////////////////////// SECURITY_ATTRIBUTES save_std_security_attribs = {}; @@ -719,35 +871,35 @@ DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync(Dqn_Slice cmd_line, Dqn // NOTE: Redirect stdout /////////////////////////////////////////////////////////////////////// HANDLE stdout_read = {}; HANDLE stdout_write = {}; - DQN_DEFER { + DN_DEFER { if (result.os_error_code || result.exit_code) { CloseHandle(stdout_read); CloseHandle(stdout_write); } }; - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_SaveStdout)) { + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStdout)) { if (!CreatePipe(&stdout_read, &stdout_write, &save_std_security_attribs, /*nSize*/ 0)) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); + DN_WinError win_error = DN_Win_LastError(tmem.arena); result.os_error_code = win_error.code; - Dqn_ErrorSink_MakeF( - error, + DN_ErrSink_AppendF( + err, result.os_error_code, "Failed to create stdout pipe to redirect the output of the command '%.*s': %.*s", - DQN_STR_FMT(cmd_rendered), - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(cmd_rendered), + DN_STR_FMT(win_error.msg)); return result; } if (!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0)) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); + DN_WinError win_error = DN_Win_LastError(tmem.arena); result.os_error_code = win_error.code; - Dqn_ErrorSink_MakeF(error, + DN_ErrSink_AppendF(err, result.os_error_code, "Failed to make stdout 'read' pipe non-inheritable when trying to " "execute command '%.*s': %.*s", - DQN_STR_FMT(cmd_rendered), - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(cmd_rendered), + DN_STR_FMT(win_error.msg)); return result; } } @@ -755,39 +907,39 @@ DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync(Dqn_Slice cmd_line, Dqn // NOTE: Redirect stderr /////////////////////////////////////////////////////////////////////// HANDLE stderr_read = {}; HANDLE stderr_write = {}; - DQN_DEFER { + DN_DEFER { if (result.os_error_code || result.exit_code) { CloseHandle(stderr_read); CloseHandle(stderr_write); } }; - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_SaveStderr)) { - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_MergeStderrToStdout)) { + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr)) { + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) { stderr_read = stdout_read; stderr_write = stdout_write; } else { if (!CreatePipe(&stderr_read, &stderr_write, &save_std_security_attribs, /*nSize*/ 0)) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); + DN_WinError win_error = DN_Win_LastError(tmem.arena); result.os_error_code = win_error.code; - Dqn_ErrorSink_MakeF( - error, + DN_ErrSink_AppendF( + err, result.os_error_code, "Failed to create stderr pipe to redirect the output of the command '%.*s': %.*s", - DQN_STR_FMT(cmd_rendered), - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(cmd_rendered), + DN_STR_FMT(win_error.msg)); return result; } if (!SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0)) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); + DN_WinError win_error = DN_Win_LastError(tmem.arena); result.os_error_code = win_error.code; - Dqn_ErrorSink_MakeF(error, + DN_ErrSink_AppendF(err, result.os_error_code, "Failed to make stderr 'read' pipe non-inheritable when trying to " "execute command '%.*s': %.*s", - DQN_STR_FMT(cmd_rendered), - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(cmd_rendered), + DN_STR_FMT(win_error.msg)); return result; } } @@ -801,15 +953,24 @@ DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync(Dqn_Slice cmd_line, Dqn startup_info.hStdOutput = stdout_write ? stdout_write : GetStdHandle(STD_OUTPUT_HANDLE); startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); startup_info.dwFlags |= STARTF_USESTDHANDLES; - BOOL create_result = CreateProcessW(nullptr, cmd16.data, nullptr, nullptr, true, 0, nullptr, working_dir16.data, &startup_info, &proc_info); + BOOL create_result = CreateProcessW(nullptr, + cmd16.data, + nullptr, + nullptr, + true, + CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, + env_block16.data, + working_dir16.data, + &startup_info, + &proc_info); if (!create_result) { - Dqn_WinError win_error = Dqn_Win_LastError(t_mem.arena); + DN_WinError win_error = DN_Win_LastError(tmem.arena); result.os_error_code = win_error.code; - Dqn_ErrorSink_MakeF(error, + DN_ErrSink_AppendF(err, result.os_error_code, "Failed to execute command '%.*s': %.*s", - DQN_STR_FMT(cmd_rendered), - DQN_STR_FMT(win_error.msg)); + DN_STR_FMT(cmd_rendered), + DN_STR_FMT(win_error.msg)); return result; } @@ -818,25 +979,25 @@ DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync(Dqn_Slice cmd_line, Dqn result.process = proc_info.hProcess; result.stdout_read = stdout_read; result.stdout_write = stdout_write; - if (Dqn_Bit_IsSet(exec_flags, Dqn_OSExecFlag_SaveStderr) && Dqn_Bit_IsNotSet(exec_flags, Dqn_OSExecFlag_MergeStderrToStdout)) { + if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr) && DN_Bit_IsNotSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) { result.stderr_read = stderr_read; result.stderr_write = stderr_write; } - result.exec_flags = exec_flags; + result.exec_flags = args->flags; return result; } -#if !defined(DQN_NO_SEMAPHORE) -// NOTE: [$SEMA] Dqn_OSSemaphore /////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSSemaphore Dqn_OS_SemaphoreInit(uint32_t initial_count) +#if !defined(DN_NO_SEMAPHORE) +// NOTE: [$SEMA] DN_OSSemaphore /////////////////////////////////////////////////////////////////// +DN_API DN_OSSemaphore DN_OS_SemaphoreInit(uint32_t initial_count) { - Dqn_OSSemaphore result = {}; + DN_OSSemaphore result = {}; SECURITY_ATTRIBUTES security_attribs = {}; result.win32_handle = CreateSemaphoreA(&security_attribs, initial_count, INT32_MAX, nullptr /*name*/); return result; } -DQN_API bool Dqn_OS_SemaphoreIsValid(Dqn_OSSemaphore *semaphore) +DN_API bool DN_OS_SemaphoreIsValid(DN_OSSemaphore *semaphore) { bool result = false; if (semaphore) { @@ -845,87 +1006,88 @@ DQN_API bool Dqn_OS_SemaphoreIsValid(Dqn_OSSemaphore *semaphore) return result; } -DQN_API void Dqn_OS_SemaphoreDeinit(Dqn_OSSemaphore *semaphore) +DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) { - if (!Dqn_OS_SemaphoreIsValid(semaphore)) + if (!DN_OS_SemaphoreIsValid(semaphore)) return; CloseHandle(semaphore->win32_handle); *semaphore = {}; } -DQN_API void Dqn_OS_SemaphoreIncrement(Dqn_OSSemaphore *semaphore, uint32_t amount) +DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, uint32_t amount) { - if (!Dqn_OS_SemaphoreIsValid(semaphore)) + if (!DN_OS_SemaphoreIsValid(semaphore)) return; LONG prev_count = 0; - ReleaseSemaphore(DQN_CAST(HANDLE *)semaphore->win32_handle, amount, &prev_count); + ReleaseSemaphore(DN_CAST(HANDLE *)semaphore->win32_handle, amount, &prev_count); } -DQN_API Dqn_OSSemaphoreWaitResult Dqn_OS_SemaphoreWait(Dqn_OSSemaphore *semaphore, uint32_t timeout_ms) +DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, uint32_t timeout_ms) { - Dqn_OSSemaphoreWaitResult result = {}; - if (!Dqn_OS_SemaphoreIsValid(semaphore)) + DN_OSSemaphoreWaitResult result = {}; + if (!DN_OS_SemaphoreIsValid(semaphore)) return result; if (!semaphore->win32_handle) return result; - DWORD wait_result = WaitForSingleObject(semaphore->win32_handle, timeout_ms == DQN_OS_SEMAPHORE_INFINITE_TIMEOUT ? INFINITE : timeout_ms); + DWORD wait_result = WaitForSingleObject(semaphore->win32_handle, timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT ? INFINITE : timeout_ms); if (wait_result == WAIT_TIMEOUT) - result = Dqn_OSSemaphoreWaitResult_Timeout; + result = DN_OSSemaphoreWaitResult_Timeout; else if (wait_result == WAIT_OBJECT_0) - result = Dqn_OSSemaphoreWaitResult_Success; + result = DN_OSSemaphoreWaitResult_Success; return result; } -#endif // !defined(DQN_NO_SEMAPHORE) +#endif // !defined(DN_NO_SEMAPHORE) -#if !defined(DQN_NO_THREAD) -// NOTE: [$MUTX] Dqn_OSMutex /////////////////////////////////////////////////////////////////////// -DQN_API Dqn_OSMutex Dqn_OS_MutexInit() +#if !defined(DN_NO_THREAD) +// NOTE: [$MUTX] DN_OSMutex /////////////////////////////////////////////////////////////////////// +DN_API DN_OSMutex DN_OS_MutexInit() { - Dqn_OSMutex result = {}; + DN_OSMutex result = {}; CRITICAL_SECTION crit_section = {}; InitializeCriticalSection(&crit_section); - static_assert(sizeof(CRITICAL_SECTION) <= sizeof(result.win32_handle), "Insufficient bytes to store Win32 mutex opaquely in our abstracted Dqn_OSMutex"); - DQN_MEMCPY(result.win32_handle, &crit_section, sizeof(crit_section)); + static_assert(sizeof(CRITICAL_SECTION) <= sizeof(result.win32_handle), "Insufficient bytes to store Win32 mutex opaquely in our abstracted DN_OSMutex"); + DN_MEMCPY(result.win32_handle, &crit_section, sizeof(crit_section)); return result; } -DQN_API void Dqn_OS_MutexDeinit(Dqn_OSMutex *mutex) +DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) { if (!mutex) return; - CRITICAL_SECTION *crit_section = DQN_CAST(CRITICAL_SECTION *)mutex->win32_handle; + CRITICAL_SECTION *crit_section = DN_CAST(CRITICAL_SECTION *)mutex->win32_handle; DeleteCriticalSection(crit_section); - DQN_MEMSET(mutex->win32_handle, 0, DQN_ARRAY_UCOUNT(mutex->win32_handle)); + DN_MEMSET(mutex->win32_handle, 0, DN_ARRAY_UCOUNT(mutex->win32_handle)); } -DQN_API void Dqn_OS_MutexLock(Dqn_OSMutex *mutex) +DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) { if (!mutex) return; - CRITICAL_SECTION *crit_section = DQN_CAST(CRITICAL_SECTION *)mutex->win32_handle; + CRITICAL_SECTION *crit_section = DN_CAST(CRITICAL_SECTION *)mutex->win32_handle; EnterCriticalSection(crit_section); } -DQN_API void Dqn_OS_MutexUnlock(Dqn_OSMutex *mutex) +DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex) { if (!mutex) return; - CRITICAL_SECTION *crit_section = DQN_CAST(CRITICAL_SECTION *)mutex->win32_handle; + CRITICAL_SECTION *crit_section = DN_CAST(CRITICAL_SECTION *)mutex->win32_handle; LeaveCriticalSection(crit_section); } -// NOTE: [$THRD] Dqn_OSThread ///////////////////////////////////////////////////////////////////// -static DWORD __stdcall Dqn_OS_ThreadFunc_(void *user_context) +// NOTE: [$THRD] DN_OSThread ///////////////////////////////////////////////////////////////////// + +static DWORD __stdcall DN_OS_ThreadFunc_(void *user_context) { - Dqn_OS_ThreadExecute_(user_context); + DN_OS_ThreadExecute_(user_context); return 0; } -DQN_API bool Dqn_OS_ThreadInit(Dqn_OSThread *thread, Dqn_OSThreadFunc *func, void *user_context) +DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context) { bool result = false; if (!thread) @@ -933,14 +1095,14 @@ DQN_API bool Dqn_OS_ThreadInit(Dqn_OSThread *thread, Dqn_OSThreadFunc *func, voi thread->func = func; thread->user_context = user_context; - thread->init_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/); + thread->init_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/); // TODO(doyle): Check if semaphore is valid DWORD thread_id = 0; SECURITY_ATTRIBUTES security_attribs = {}; thread->handle = CreateThread(&security_attribs, 0 /*stack_size*/, - Dqn_OS_ThreadFunc_, + DN_OS_ThreadFunc_, thread, 0 /*creation_flags*/, &thread_id); @@ -950,17 +1112,18 @@ DQN_API bool Dqn_OS_ThreadInit(Dqn_OSThread *thread, Dqn_OSThreadFunc *func, voi thread->thread_id = thread_id; } + // NOTE: Ensure that thread_id is set before 'thread->func' is called. if (result) { - Dqn_OS_SemaphoreIncrement(&thread->init_semaphore, 1); + DN_OS_SemaphoreIncrement(&thread->init_semaphore, 1); } else { - Dqn_OS_SemaphoreDeinit(&thread->init_semaphore); + DN_OS_SemaphoreDeinit(&thread->init_semaphore); *thread = {}; } return result; } -DQN_API void Dqn_OS_ThreadDeinit(Dqn_OSThread *thread) +DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread) { if (!thread || !thread->handle) return; @@ -969,25 +1132,68 @@ DQN_API void Dqn_OS_ThreadDeinit(Dqn_OSThread *thread) CloseHandle(thread->handle); thread->handle = INVALID_HANDLE_VALUE; thread->thread_id = {}; + DN_TLS_Deinit(&thread->tls); } -DQN_API uint32_t Dqn_OS_ThreadID() +DN_API uint32_t DN_OS_ThreadID() { unsigned long result = GetCurrentThreadId(); return result; } -#endif // !defined(DQN_NO_THREAD) -// NOTE: [$HTTP] Dqn_OSHttp //////////////////////////////////////////////////////////////////////// -void Dqn_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD dwInternetStatus, VOID *lpvStatusInformation, DWORD dwStatusInformationLength) +typedef HRESULT DN_WinSetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription); +static DN_WinSetThreadDescriptionFunc *g_dn_win_set_thread_description = nullptr; + +DN_API void DN_Win_ThreadSetName(DN_Str8 name) +{ + DN_TLS *tls = DN_TLS_Get(); + DN_ArenaTempMem tmem = DN_Arena_TempMemBegin(tls->arenas + DN_TLSArena_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/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription + if (g_dn_win_set_thread_description) { + DN_Str16 name16 = DN_Win_Str8ToStr16(tmem.arena, name); + g_dn_win_set_thread_description(GetCurrentThread(), (WCHAR *)name16.data); + DN_Arena_TempMemEnd(tmem); + return; + } + + // NOTE: Fallback to throw-exception method to set thread name + #pragma pack(push, 8) + struct DN_WinThreadNameInfo { + uint32_t dwType; + char *szName; + uint32_t dwThreadID; + uint32_t dwFlags; + }; + #pragma pack(pop) + + DN_Str8 copy = DN_Str8_Copy(tmem.arena, name); + DN_WinThreadNameInfo info = {}; + info.dwType = 0x1000; + info.szName = (char *)copy.data; + info.dwThreadID = DN_OS_ThreadID(); + __try { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { + } + + DN_Arena_TempMemEnd(tmem); +} +#endif // !defined(DN_NO_THREAD) + +// NOTE: [$HTTP] DN_OSHttp //////////////////////////////////////////////////////////////////////// +void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD dwInternetStatus, VOID *lpvStatusInformation, DWORD dwStatusInformationLength) { (void)session; (void)dwStatusInformationLength; - Dqn_OSHttpResponse *response = DQN_CAST(Dqn_OSHttpResponse *)dwContext; - HINTERNET request = DQN_CAST(HINTERNET)response->win32_request_handle; - Dqn_WinError error = {}; - DWORD const READ_BUFFER_SIZE = DQN_MEGABYTES(1); + DN_OSHttpResponse *response = DN_CAST(DN_OSHttpResponse *)dwContext; + HINTERNET request = DN_CAST(HINTERNET)response->win32_request_handle; + DN_WinError error = {}; + DWORD const READ_BUFFER_SIZE = DN_MEGABYTES(1); if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_RESOLVING_NAME) { } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_NAME_RESOLVED) { @@ -1015,7 +1221,7 @@ void Dqn_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD &status, &status_size, WINHTTP_NO_HEADER_INDEX)) { - response->http_status = DQN_CAST(uint16_t)status; + response->http_status = DN_CAST(uint16_t)status; // NOTE: You can normally call into WinHttpQueryDataAvailable which means the kernel // will buffer the response into a single buffer and return us the full size of the @@ -1027,44 +1233,44 @@ void Dqn_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD // This is advantageous to avoid a copy from the kernel buffer into our buffer. If the // end user application knows the typical payload size then they can optimise for this // to prevent unnecessary allocation on the user side. - void *buffer = Dqn_Arena_Alloc(response->builder.arena, READ_BUFFER_SIZE, 1 /*align*/, Dqn_ZeroMem_No); + void *buffer = DN_Arena_Alloc(response->builder.arena, READ_BUFFER_SIZE, 1 /*align*/, DN_ZeroMem_No); if (!WinHttpReadData(request, buffer, READ_BUFFER_SIZE, nullptr)) - error = Dqn_Win_LastError(&response->tmp_arena); + error = DN_Win_LastError(&response->tmp_arena); } else { - error = Dqn_Win_LastError(&response->tmp_arena); + error = DN_Win_LastError(&response->tmp_arena); } } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE) { } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_READ_COMPLETE) { DWORD bytes_read = dwStatusInformationLength; if (bytes_read) { - Dqn_Str8 prev_buffer = Dqn_Str8_Init(DQN_CAST(char *) lpvStatusInformation, bytes_read); - Dqn_Str8Builder_AddRef(&response->builder, prev_buffer); + DN_Str8 prev_buffer = DN_Str8_Init(DN_CAST(char *) lpvStatusInformation, bytes_read); + DN_Str8Builder_AppendRef(&response->builder, prev_buffer); - void *buffer = Dqn_Arena_Alloc(response->builder.arena, READ_BUFFER_SIZE, 1 /*align*/, Dqn_ZeroMem_No); + void *buffer = DN_Arena_Alloc(response->builder.arena, READ_BUFFER_SIZE, 1 /*align*/, DN_ZeroMem_No); if (!WinHttpReadData(request, buffer, READ_BUFFER_SIZE, nullptr)) - error = Dqn_Win_LastError(&response->tmp_arena); + error = DN_Win_LastError(&response->tmp_arena); } } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE) { } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) { - WINHTTP_ASYNC_RESULT *async_result = DQN_CAST(WINHTTP_ASYNC_RESULT *)lpvStatusInformation; - error = Dqn_Win_ErrorCodeToMsg(&response->tmp_arena, DQN_CAST(uint32_t)async_result->dwError); + WINHTTP_ASYNC_RESULT *async_result = DN_CAST(WINHTTP_ASYNC_RESULT *)lpvStatusInformation; + error = DN_Win_ErrorCodeToMsg(&response->tmp_arena, DN_CAST(uint32_t)async_result->dwError); } else if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE) { if (!WinHttpReceiveResponse(request, 0)) - error = Dqn_Win_LastError(&response->tmp_arena); + error = DN_Win_LastError(&response->tmp_arena); } // NOTE: If the request handle is missing, then, the response has been freed. // MSDN says that this callback can still be called after closing the handle // and trigger the WINHTTP_CALLBACK_STATUS_REQUEST_ERROR. - if (response->win32_request_handle) { + if (request) { bool read_complete = dwInternetStatus == WINHTTP_CALLBACK_STATUS_READ_COMPLETE && dwStatusInformationLength == 0; if (read_complete) { - response->body = Dqn_Str8Builder_Build(&response->builder, response->arena); + response->body = DN_Str8Builder_Build(&response->builder, response->arena); } if (read_complete || dwInternetStatus == WINHTTP_CALLBACK_STATUS_REQUEST_ERROR || error.code) { - Dqn_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1); - Dqn_Atomic_AddU32(&response->done, 1); + DN_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1); + DN_Atomic_AddU32(&response->done, 1); } if (error.code) { @@ -1074,14 +1280,14 @@ void Dqn_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD } } -DQN_API void Dqn_OS_HttpRequestAsync(Dqn_OSHttpResponse *response, - Dqn_Arena *arena, - Dqn_Str8 host, - Dqn_Str8 path, - Dqn_OSHttpRequestSecure secure, - Dqn_Str8 method, - Dqn_Str8 body, - Dqn_Str8 headers) +DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, + DN_Arena *arena, + DN_Str8 host, + DN_Str8 path, + DN_OSHttpRequestSecure secure, + DN_Str8 method, + DN_Str8 body, + DN_Str8 headers) { if (!response || !arena) return; @@ -1089,27 +1295,27 @@ DQN_API void Dqn_OS_HttpRequestAsync(Dqn_OSHttpResponse *response, response->arena = arena; response->builder.arena = response->tmem_arena ? response->tmem_arena : &response->tmp_arena; - Dqn_Arena *t_mem_arena = response->tmem_arena; - Dqn_TLSTMem t_mem_ = Dqn_TLS_TMem(arena); - if (!t_mem_arena) { - t_mem_arena = t_mem_.arena; + DN_Arena *tmem_arena = response->tmem_arena; + DN_TLSTMem tmem_ = DN_TLS_TMem(arena); + if (!tmem_arena) { + tmem_arena = tmem_.arena; } - Dqn_WinError error = {}; - DQN_DEFER { + DN_WinError error = {}; + DN_DEFER { response->error_msg = error.msg; response->error_code = error.code; if (error.code) { // NOTE: 'Wait' handles failures gracefully, skipping the wait and // cleans up the request - Dqn_OS_HttpRequestWait(response); - Dqn_Atomic_AddU32(&response->done, 1); + DN_OS_HttpRequestWait(response); + DN_Atomic_AddU32(&response->done, 1); } }; response->win32_request_session = WinHttpOpen(nullptr /*user agent*/, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC); if (!response->win32_request_session) { - error = Dqn_Win_LastError(&response->tmp_arena); + error = DN_Win_LastError(&response->tmp_arena); return; } @@ -1118,22 +1324,22 @@ DQN_API void Dqn_OS_HttpRequestAsync(Dqn_OSHttpResponse *response, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR | WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE; if (WinHttpSetStatusCallback(response->win32_request_session, - DQN_CAST(WINHTTP_STATUS_CALLBACK)Dqn_OS_HttpRequestWin32Callback, + DN_CAST(WINHTTP_STATUS_CALLBACK)DN_OS_HttpRequestWin32Callback, callback_flags, - DQN_CAST(DWORD_PTR)nullptr /*dwReserved*/) == WINHTTP_INVALID_STATUS_CALLBACK) { - error = Dqn_Win_LastError(&response->tmp_arena); + DN_CAST(DWORD_PTR)nullptr /*dwReserved*/) == WINHTTP_INVALID_STATUS_CALLBACK) { + error = DN_Win_LastError(&response->tmp_arena); return; } - Dqn_Str16 host16 = Dqn_Win_Str8ToStr16(t_mem_arena, host); + DN_Str16 host16 = DN_Win_Str8ToStr16(tmem_arena, host); response->win32_request_connection = WinHttpConnect(response->win32_request_session, host16.data, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0 /*reserved*/); if (!response->win32_request_connection) { - error = Dqn_Win_LastError(&response->tmp_arena); + error = DN_Win_LastError(&response->tmp_arena); return; } - Dqn_Str16 method16 = Dqn_Win_Str8ToStr16(t_mem_arena, method); - Dqn_Str16 path16 = Dqn_Win_Str8ToStr16(t_mem_arena, path); + DN_Str16 method16 = DN_Win_Str8ToStr16(tmem_arena, method); + DN_Str16 path16 = DN_Win_Str8ToStr16(tmem_arena, path); response->win32_request_handle = WinHttpOpenRequest(response->win32_request_connection, method16.data, path16.data, @@ -1142,25 +1348,25 @@ DQN_API void Dqn_OS_HttpRequestAsync(Dqn_OSHttpResponse *response, nullptr /*accept types*/, secure ? WINHTTP_FLAG_SECURE : 0); if (!response->win32_request_handle) { - error = Dqn_Win_LastError(&response->tmp_arena); + error = DN_Win_LastError(&response->tmp_arena); return; } - Dqn_Str16 headers16 = Dqn_Win_Str8ToStr16(t_mem_arena, headers); - response->on_complete_semaphore = Dqn_OS_SemaphoreInit(0); + DN_Str16 headers16 = DN_Win_Str8ToStr16(tmem_arena, headers); + response->on_complete_semaphore = DN_OS_SemaphoreInit(0); if (!WinHttpSendRequest(response->win32_request_handle, headers16.data, - DQN_CAST(DWORD)headers16.size, + DN_CAST(DWORD)headers16.size, body.data /*optional data*/, - DQN_CAST(DWORD) body.size /*optional length*/, - DQN_CAST(DWORD) body.size /*total content length*/, - DQN_CAST(DWORD_PTR)response)) { - error = Dqn_Win_LastError(&response->tmp_arena); + DN_CAST(DWORD) body.size /*optional length*/, + DN_CAST(DWORD) body.size /*total content length*/, + DN_CAST(DWORD_PTR)response)) { + error = DN_Win_LastError(&response->tmp_arena); return; } } -DQN_API void Dqn_OS_HttpRequestFree(Dqn_OSHttpResponse *response) +DN_API void DN_OS_HttpRequestFree(DN_OSHttpResponse *response) { // NOTE: Cleanup // NOTE: These calls are synchronous even when the HTTP request is async. @@ -1171,52 +1377,75 @@ DQN_API void Dqn_OS_HttpRequestFree(Dqn_OSHttpResponse *response) response->win32_request_session = nullptr; response->win32_request_connection = nullptr; response->win32_request_handle = nullptr; - Dqn_Arena_Deinit(&response->tmp_arena); - if (Dqn_OS_SemaphoreIsValid(&response->on_complete_semaphore)) - Dqn_OS_SemaphoreDeinit(&response->on_complete_semaphore); + DN_Arena_Deinit(&response->tmp_arena); + if (DN_OS_SemaphoreIsValid(&response->on_complete_semaphore)) + DN_OS_SemaphoreDeinit(&response->on_complete_semaphore); *response = {}; } -// NOTE: [$WIND] Dqn_Win /////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_WinError Dqn_Win_ErrorCodeToMsg(Dqn_Arena *arena, uint32_t error_code) +// NOTE: [$WIND] DN_Win /////////////////////////////////////////////////////////////////////////// +DN_API DN_Str16 DN_Win_ErrorCodeToMsg16Alloc(uint32_t error_code) { - Dqn_WinError result = {}; - result.code = error_code; - if (!arena) - return result; - DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; void *module_to_get_errors_from = nullptr; - - if (result.code >= 12000 && result.code <= 12175) { + if (error_code >= 12000 && error_code <= 12175) { flags |= FORMAT_MESSAGE_FROM_HMODULE; module_to_get_errors_from = GetModuleHandleA("winhttp.dll"); } - wchar_t *error16 = nullptr; + wchar_t *result16 = nullptr; DWORD size = FormatMessageW(/*DWORD dwFlags */ flags | FORMAT_MESSAGE_ALLOCATE_BUFFER, /*LPCVOID lpSource */ module_to_get_errors_from, - /*DWORD dwMessageId */ result.code, + /*DWORD dwMessageId */ error_code, /*DWORD dwLanguageId*/ 0, - /*LPWSTR lpBuffer */ (LPWSTR)&error16, + /*LPWSTR lpBuffer */ (LPWSTR)&result16, /*DWORD nSize */ 0, /*va_list *Arguments */ nullptr); - if (size) - result.msg = Dqn_Win_Str16ToStr8(arena, {error16, size}); - if (error16) - LocalFree(error16); + DN_Str16 result = {result16, size}; return result; } -DQN_API Dqn_WinError Dqn_Win_LastError(Dqn_Arena *arena) +DN_API DN_WinError DN_Win_ErrorCodeToMsgAlloc(uint32_t error_code) { - Dqn_WinError result = Dqn_Win_ErrorCodeToMsg(arena, GetLastError()); + DN_WinError result = {}; + result.code = error_code; + DN_Str16 error16 = DN_Win_ErrorCodeToMsg16Alloc(error_code); + if (error16.size) + result.msg = DN_Win_Str16ToStr8Alloc(error16); + if (error16.data) + LocalFree(error16.data); return result; } -DQN_API void Dqn_Win_MakeProcessDPIAware() +DN_API DN_WinError DN_Win_ErrorCodeToMsg(DN_Arena *arena, uint32_t error_code) +{ + DN_WinError result = {}; + result.code = error_code; + if (arena) { + DN_Str16 error16 = DN_Win_ErrorCodeToMsg16Alloc(error_code); + if (error16.size) + result.msg = DN_Win_Str16ToStr8(arena, error16); + if (error16.data) + LocalFree(error16.data); + } + return result; +} + +DN_API DN_WinError DN_Win_LastError(DN_Arena *arena) +{ + DN_WinError result = DN_Win_ErrorCodeToMsg(arena, GetLastError()); + return result; +} + +DN_API DN_WinError DN_Win_LastErrorAlloc() +{ + DN_WinError result = DN_Win_ErrorCodeToMsgAlloc(GetLastError()); + return result; +} + +DN_API void DN_Win_MakeProcessDPIAware() { typedef bool SetProcessDpiAwareProc(void); typedef bool SetProcessDpiAwarenessProc(DPI_AWARENESS); @@ -1230,32 +1459,32 @@ DQN_API void Dqn_Win_MakeProcessDPIAware() if (!lib_handle) return; - if (auto *set_process_dpi_awareness_context = DQN_CAST(SetProcessDpiAwarenessContextProc *)GetProcAddress(DQN_CAST(HMODULE)lib_handle, "SetProcessDpiAwarenessContext")) { + if (auto *set_process_dpi_awareness_context = DN_CAST(SetProcessDpiAwarenessContextProc *)GetProcAddress(DN_CAST(HMODULE)lib_handle, "SetProcessDpiAwarenessContext")) { set_process_dpi_awareness_context(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); - } else if (auto *set_process_dpi_awareness = DQN_CAST(SetProcessDpiAwarenessProc *)GetProcAddress(DQN_CAST(HMODULE)lib_handle, "SetProcessDpiAwareness")) { + } else if (auto *set_process_dpi_awareness = DN_CAST(SetProcessDpiAwarenessProc *)GetProcAddress(DN_CAST(HMODULE)lib_handle, "SetProcessDpiAwareness")) { set_process_dpi_awareness(DPI_AWARENESS_PER_MONITOR_AWARE); - } else if (auto *set_process_dpi_aware = DQN_CAST(SetProcessDpiAwareProc *)GetProcAddress(DQN_CAST(HMODULE)lib_handle, "SetProcessDpiAware")) { + } else if (auto *set_process_dpi_aware = DN_CAST(SetProcessDpiAwareProc *)GetProcAddress(DN_CAST(HMODULE)lib_handle, "SetProcessDpiAware")) { set_process_dpi_aware(); } } // NOTE: Windows UTF8 to Str16 ////////////////////////////////////////////// -DQN_API Dqn_Str16 Dqn_Win_Str8ToStr16(Dqn_Arena *arena, Dqn_Str8 src) +DN_API DN_Str16 DN_Win_Str8ToStr16(DN_Arena *arena, DN_Str8 src) { - Dqn_Str16 result = {}; - if (!arena || !Dqn_Str8_HasData(src)) + DN_Str16 result = {}; + if (!arena || !DN_Str8_HasData(src)) return result; - int required_size = MultiByteToWideChar(CP_UTF8, 0 /*dwFlags*/, src.data, DQN_CAST(int)src.size, nullptr /*dest*/, 0 /*dest size*/); + int required_size = MultiByteToWideChar(CP_UTF8, 0 /*dwFlags*/, src.data, DN_CAST(int)src.size, nullptr /*dest*/, 0 /*dest size*/); if (required_size <= 0) return result; - wchar_t *buffer = Dqn_Arena_NewArray(arena, wchar_t, required_size + 1, Dqn_ZeroMem_No); + wchar_t *buffer = DN_Arena_NewArray(arena, wchar_t, required_size + 1, DN_ZeroMem_No); if (!buffer) return result; - int chars_written = MultiByteToWideChar(CP_UTF8, 0 /*dwFlags*/, src.data, DQN_CAST(int)src.size, buffer, required_size); - if (DQN_CHECK(chars_written == required_size)) { + int chars_written = MultiByteToWideChar(CP_UTF8, 0 /*dwFlags*/, src.data, DN_CAST(int)src.size, buffer, required_size); + if (DN_CHECK(chars_written == required_size)) { result.data = buffer; result.size = chars_written; result.data[result.size] = 0; @@ -1263,29 +1492,29 @@ DQN_API Dqn_Str16 Dqn_Win_Str8ToStr16(Dqn_Arena *arena, Dqn_Str8 src) return result; } -DQN_API int Dqn_Win_Str8ToStr16Buffer(Dqn_Str8 src, wchar_t *dest, int dest_size) +DN_API int DN_Win_Str8ToStr16Buffer(DN_Str8 src, wchar_t *dest, int dest_size) { int result = 0; - if (!Dqn_Str8_HasData(src)) + if (!DN_Str8_HasData(src)) return result; - result = MultiByteToWideChar(CP_UTF8, 0 /*dwFlags*/, src.data, DQN_CAST(int)src.size, nullptr /*dest*/, 0 /*dest size*/); + result = MultiByteToWideChar(CP_UTF8, 0 /*dwFlags*/, src.data, DN_CAST(int)src.size, nullptr /*dest*/, 0 /*dest size*/); if (result <= 0 || result > dest_size || !dest) return result; - result = MultiByteToWideChar(CP_UTF8, 0 /*dwFlags*/, src.data, DQN_CAST(int)src.size, dest, DQN_CAST(int)dest_size); - dest[DQN_MIN(result, dest_size - 1)] = 0; + result = MultiByteToWideChar(CP_UTF8, 0 /*dwFlags*/, src.data, DN_CAST(int)src.size, dest, DN_CAST(int)dest_size); + dest[DN_MIN(result, dest_size - 1)] = 0; return result; } // NOTE: Windows Str16 To UTF8 ////////////////////////////////////////////////////////////////// -DQN_API int Dqn_Win_Str16ToStr8Buffer(Dqn_Str16 src, char *dest, int dest_size) +DN_API int DN_Win_Str16ToStr8Buffer(DN_Str16 src, char *dest, int dest_size) { int result = 0; - if (!Dqn_Str16_HasData(src)) + if (!DN_Str16_HasData(src)) return result; - int src_size = Dqn_Safe_SaturateCastISizeToInt(src.size); + int src_size = DN_Safe_SaturateCastISizeToInt(src.size); if (src_size <= 0) return result; @@ -1293,18 +1522,52 @@ DQN_API int Dqn_Win_Str16ToStr8Buffer(Dqn_Str16 src, char *dest, int dest_size) if (result <= 0 || result > dest_size || !dest) return result; - result = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, src.data, src_size, dest, DQN_CAST(int)dest_size, nullptr, nullptr); - dest[DQN_MIN(result, dest_size - 1)] = 0; + result = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, src.data, src_size, dest, DN_CAST(int)dest_size, nullptr, nullptr); + dest[DN_MIN(result, dest_size - 1)] = 0; return result; } -DQN_API Dqn_Str8 Dqn_Win_Str16ToStr8(Dqn_Arena *arena, Dqn_Str16 src) +DN_API DN_Str8 DN_Win_Str16ToStr8Alloc(DN_Str16 src) { - Dqn_Str8 result = {}; - if (!arena || !Dqn_Str16_HasData(src)) + DN_Str8 result = {}; + if (!DN_Str16_HasData(src)) return result; - int src_size = Dqn_Safe_SaturateCastISizeToInt(src.size); + int src_size = DN_Safe_SaturateCastISizeToInt(src.size); + if (src_size <= 0) + return result; + + int required_size = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, src.data, src_size, nullptr /*dest*/, 0 /*dest size*/, nullptr, nullptr); + if (required_size <= 0) + return result; + + DN_Str8 buffer = {}; + buffer.data = DN_CAST(char *)DN_OS_MemAlloc(required_size + 1, DN_ZeroMem_No); + if (buffer.data) { + buffer.size = required_size; + int chars_written = WideCharToMultiByte(CP_UTF8, + 0 /*dwFlags*/, + src.data, + src_size, + buffer.data, + DN_CAST(int) buffer.size, + nullptr, + nullptr); + if (DN_CHECK(chars_written == required_size)) { + result = buffer; + result.data[result.size] = 0; + } + } + return result; +} + +DN_API DN_Str8 DN_Win_Str16ToStr8(DN_Arena *arena, DN_Str16 src) +{ + DN_Str8 result = {}; + if (!arena || !DN_Str16_HasData(src)) + return result; + + int src_size = DN_Safe_SaturateCastISizeToInt(src.size); if (src_size <= 0) return result; @@ -1314,13 +1577,13 @@ DQN_API Dqn_Str8 Dqn_Win_Str16ToStr8(Dqn_Arena *arena, Dqn_Str16 src) // NOTE: Str8 allocate ensures there's one extra byte for // null-termination already so no-need to +1 the required size - Dqn_ArenaTempMemScope temp_mem = Dqn_ArenaTempMemScope(arena); - Dqn_Str8 buffer = Dqn_Str8_Alloc(arena, required_size, Dqn_ZeroMem_No); - if (!Dqn_Str8_HasData(buffer)) + DN_ArenaTempMemScope temp_mem = DN_ArenaTempMemScope(arena); + DN_Str8 buffer = DN_Str8_Alloc(arena, required_size, DN_ZeroMem_No); + if (!DN_Str8_HasData(buffer)) return result; - int chars_written = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, src.data, src_size, buffer.data, DQN_CAST(int)buffer.size, nullptr, nullptr); - if (DQN_CHECK(chars_written == required_size)) { + int chars_written = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, src.data, src_size, buffer.data, DN_CAST(int)buffer.size, nullptr, nullptr); + if (DN_CHECK(chars_written == required_size)) { result = buffer; result.data[result.size] = 0; temp_mem.mem = {}; @@ -1330,106 +1593,108 @@ DQN_API Dqn_Str8 Dqn_Win_Str16ToStr8(Dqn_Arena *arena, Dqn_Str16 src) } // NOTE: Windows Executable Directory ////////////////////////////////////////// -DQN_API Dqn_Str16 Dqn_Win_EXEPathW(Dqn_Arena *arena) +DN_API DN_Str16 DN_Win_EXEPathW(DN_Arena *arena) { - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(arena); - Dqn_Str16 result = {}; - Dqn_usize module_size = 0; + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str16 result = {}; + DN_USize module_size = 0; wchar_t *module_path = nullptr; do { module_size += 256; - module_path = Dqn_Arena_NewArray(t_mem.arena, wchar_t, module_size, Dqn_ZeroMem_No); + module_path = DN_Arena_NewArray(tmem.arena, wchar_t, module_size, DN_ZeroMem_No); if (!module_path) return result; - module_size = DQN_CAST(Dqn_usize)GetModuleFileNameW(nullptr /*module*/, module_path, DQN_CAST(int)module_size); + module_size = DN_CAST(DN_USize)GetModuleFileNameW(nullptr /*module*/, module_path, DN_CAST(int)module_size); } while (GetLastError() == ERROR_INSUFFICIENT_BUFFER); - Dqn_usize index_of_last_slash = 0; - for (Dqn_usize index = module_size - 1; !index_of_last_slash && index < module_size; index--) + DN_USize index_of_last_slash = 0; + for (DN_USize index = module_size - 1; !index_of_last_slash && index < module_size; index--) index_of_last_slash = module_path[index] == '\\' ? index : 0; - result.data = Dqn_Arena_NewArray(arena, wchar_t, module_size + 1, Dqn_ZeroMem_No); + result.data = DN_Arena_NewArray(arena, wchar_t, module_size + 1, DN_ZeroMem_No); result.size = module_size; - DQN_MEMCPY(result.data, module_path, sizeof(wchar_t) * result.size); + DN_MEMCPY(result.data, module_path, sizeof(wchar_t) * result.size); result.data[result.size] = 0; return result; } -DQN_API Dqn_Str16 Dqn_Win_EXEDirW(Dqn_Arena *arena) +DN_API DN_Str16 DN_Win_EXEDirW(DN_Arena *arena) { - // TODO(doyle): Implement a Dqn_Str16_BinarySearchReverse - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(arena); - Dqn_Str16 result = {}; - Dqn_usize module_size = 0; + // TODO(doyle): Implement a DN_Str16_BinarySearchReverse + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str16 result = {}; + DN_USize module_size = 0; wchar_t *module_path = nullptr; do { module_size += 256; - module_path = Dqn_Arena_NewArray(t_mem.arena, wchar_t, module_size, Dqn_ZeroMem_No); + module_path = DN_Arena_NewArray(tmem.arena, wchar_t, module_size, DN_ZeroMem_No); if (!module_path) return result; - module_size = DQN_CAST(Dqn_usize)GetModuleFileNameW(nullptr /*module*/, module_path, DQN_CAST(int)module_size); + module_size = DN_CAST(DN_USize)GetModuleFileNameW(nullptr /*module*/, module_path, DN_CAST(int)module_size); } while (GetLastError() == ERROR_INSUFFICIENT_BUFFER); - Dqn_usize index_of_last_slash = 0; - for (Dqn_usize index = module_size - 1; !index_of_last_slash && index < module_size; index--) + DN_USize index_of_last_slash = 0; + for (DN_USize index = module_size - 1; !index_of_last_slash && index < module_size; index--) index_of_last_slash = module_path[index] == '\\' ? index : 0; - result.data = Dqn_Arena_NewArray(arena, wchar_t, index_of_last_slash + 1, Dqn_ZeroMem_No); + result.data = DN_Arena_NewArray(arena, wchar_t, index_of_last_slash + 1, DN_ZeroMem_No); result.size = index_of_last_slash; - DQN_MEMCPY(result.data, module_path, sizeof(wchar_t) * result.size); + DN_MEMCPY(result.data, module_path, sizeof(wchar_t) * result.size); result.data[result.size] = 0; return result; } -DQN_API Dqn_Str8 Dqn_Win_WorkingDir(Dqn_Arena *arena, Dqn_Str8 suffix) +DN_API DN_Str8 DN_Win_WorkingDir(DN_Arena *arena, DN_Str8 suffix) { - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(arena); - Dqn_Str16 suffix16 = Dqn_Win_Str8ToStr16(t_mem.arena, suffix); - Dqn_Str16 dir16 = Dqn_Win_WorkingDirW(t_mem.arena, suffix16); - Dqn_Str8 result = Dqn_Win_Str16ToStr8(arena, dir16); + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str16 suffix16 = DN_Win_Str8ToStr16(tmem.arena, suffix); + DN_Str16 dir16 = DN_Win_WorkingDirW(tmem.arena, suffix16); + DN_Str8 result = DN_Win_Str16ToStr8(arena, dir16); return result; } -DQN_API Dqn_Str16 Dqn_Win_WorkingDirW(Dqn_Arena *arena, Dqn_Str16 suffix) +DN_API DN_Str16 DN_Win_WorkingDirW(DN_Arena *arena, DN_Str16 suffix) { - DQN_ASSERT(suffix.size >= 0); - Dqn_Str16 result = {}; + DN_ASSERT(suffix.size >= 0); + DN_Str16 result = {}; // NOTE: required_size is the size required *including* the null-terminator - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(arena); + DN_TLSTMem tmem = DN_TLS_TMem(arena); unsigned long required_size = GetCurrentDirectoryW(0, nullptr); - unsigned long desired_size = required_size + DQN_CAST(unsigned long) suffix.size; + unsigned long desired_size = required_size + DN_CAST(unsigned long) suffix.size; - wchar_t *t_mem_w_path = Dqn_Arena_NewArray(t_mem.arena, wchar_t, desired_size, Dqn_ZeroMem_No); - if (!t_mem_w_path) + wchar_t *tmem_w_path = DN_Arena_NewArray(tmem.arena, wchar_t, desired_size, DN_ZeroMem_No); + if (!tmem_w_path) return result; - unsigned long bytes_written_wo_null_terminator = GetCurrentDirectoryW(desired_size, t_mem_w_path); + unsigned long bytes_written_wo_null_terminator = GetCurrentDirectoryW(desired_size, tmem_w_path); if ((bytes_written_wo_null_terminator + 1) != required_size) { - // TODO(dqn): Error + // TODO(dn): Error return result; } - wchar_t *w_path = Dqn_Arena_NewArray(arena, wchar_t, desired_size, Dqn_ZeroMem_No); + wchar_t *w_path = DN_Arena_NewArray(arena, wchar_t, desired_size, DN_ZeroMem_No); if (!w_path) return result; if (suffix.size) { - DQN_MEMCPY(w_path, t_mem_w_path, sizeof(*t_mem_w_path) * bytes_written_wo_null_terminator); - DQN_MEMCPY(w_path + bytes_written_wo_null_terminator, suffix.data, sizeof(suffix.data[0]) * suffix.size); + DN_MEMCPY(w_path, tmem_w_path, sizeof(*tmem_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 = Dqn_Str16{w_path, DQN_CAST(Dqn_usize)(desired_size - 1)}; + result = DN_Str16{w_path, DN_CAST(DN_USize)(desired_size - 1)}; return result; } -DQN_API bool Dqn_Win_FolderWIterate(Dqn_Str16 path, Dqn_Win_FolderIteratorW *it) +DN_API bool DN_Win_DirWIterate(DN_Str16 path, DN_Win_FolderIteratorW *it) { WIN32_FIND_DATAW find_data = {}; if (it->handle) { - if (FindNextFileW(it->handle, &find_data) == 0) + if (FindNextFileW(it->handle, &find_data) == 0) { + FindClose(it->handle); return false; + } } else { it->handle = FindFirstFileExW(path.data, /*LPCWSTR lpFileName,*/ FindExInfoStandard, /*FINDEX_INFO_LEVELS fInfoLevelId,*/ @@ -1443,60 +1708,21 @@ DQN_API bool Dqn_Win_FolderWIterate(Dqn_Str16 path, Dqn_Win_FolderIteratorW *it) } it->file_name_buf[0] = 0; - it->file_name = Dqn_Str16{it->file_name_buf, 0}; + it->file_name = DN_Str16{it->file_name_buf, 0}; do { if (find_data.cFileName[0] == '.' || (find_data.cFileName[0] == '.' && find_data.cFileName[1] == '.')) continue; - it->file_name.size = Dqn_CStr16_Size(find_data.cFileName); - DQN_ASSERT(it->file_name.size < (DQN_ARRAY_UCOUNT(it->file_name_buf) - 1)); - DQN_MEMCPY(it->file_name.data, find_data.cFileName, it->file_name.size * sizeof(wchar_t)); + it->file_name.size = DN_CStr16_Size(find_data.cFileName); + DN_ASSERT(it->file_name.size < (DN_ARRAY_UCOUNT(it->file_name_buf) - 1)); + DN_MEMCPY(it->file_name.data, find_data.cFileName, it->file_name.size * sizeof(wchar_t)); it->file_name_buf[it->file_name.size] = 0; break; } while (FindNextFileW(it->handle, &find_data) != 0); - return it->file_name.size > 0; -} - -DQN_API bool Dqn_Win_FolderIterate(Dqn_Str8 path, Dqn_Win_FolderIterator *it) -{ - if (!Dqn_Str8_HasData(path) || !it || path.size <= 0) - return false; - - Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr); - Dqn_Win_FolderIteratorW wide_it = {}; - Dqn_Str16 path16 = {}; - if (it->handle) { - wide_it.handle = it->handle; - } else { - bool needs_asterisks = Dqn_Str8_EndsWith(path, DQN_STR8("\\")) || - Dqn_Str8_EndsWith(path, DQN_STR8("/")); - bool has_glob = Dqn_Str8_EndsWith(path, DQN_STR8("\\*")) || - Dqn_Str8_EndsWith(path, DQN_STR8("/*")); - - Dqn_Str8 adjusted_path = path; - if (!has_glob) { - // NOTE: We are missing the glob for enumerating the files, we will - // 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 = Dqn_OS_PathF(t_mem.arena, "%.*s*", DQN_STR_FMT(path)); - else - adjusted_path = Dqn_OS_PathF(t_mem.arena, "%.*s/*", DQN_STR_FMT(path)); - } - - path16 = Dqn_Win_Str8ToStr16(t_mem.arena, adjusted_path); - if (path16.size <= 0) // Conversion error - return false; - } - - bool result = Dqn_Win_FolderWIterate(path16, &wide_it); - it->handle = wide_it.handle; - if (result) { - int size = Dqn_Win_Str16ToStr8Buffer(wide_it.file_name, it->file_name_buf, DQN_ARRAY_UCOUNT(it->file_name_buf)); - it->file_name = Dqn_Str8_Init(it->file_name_buf, size); - } - + bool result = it->file_name.size > 0; + if (!result) + FindClose(it->handle); return result; } diff --git a/dqn_os_win32.h b/dqn_os_win32.h index 4684ca7..5e60e18 100644 --- a/dqn_os_win32.h +++ b/dqn_os_win32.h @@ -18,40 +18,40 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -struct Dqn_WinError +struct DN_WinError { unsigned long code; - Dqn_Str8 msg; + DN_Str8 msg; }; // NOTE: Windows Str8 <-> Str16 /////////////////////////////////////////// -struct Dqn_Win_FolderIteratorW +struct DN_Win_FolderIteratorW { void *handle; - Dqn_Str16 file_name; + DN_Str16 file_name; wchar_t file_name_buf[512]; }; -struct Dqn_Win_FolderIterator -{ - void *handle; - Dqn_Str8 file_name; - char file_name_buf[512]; -}; +DN_API void DN_Win_ThreadSetName (DN_Str8 name); + +// NOTE: [$WIND] DN_Win /////////////////////////////////////////////////////////////////////////// +DN_API DN_Str16 DN_Win_ErrorCodeToMsg16Alloc(uint32_t error_code); +DN_API DN_WinError DN_Win_ErrorCodeToMsg (DN_Arena *arena, uint32_t error_code); +DN_API DN_WinError DN_Win_ErrorCodeToMsgAlloc (uint32_t error_code); +DN_API DN_WinError DN_Win_LastError (DN_Arena *arena); +DN_API DN_WinError DN_Win_LastErrorAlloc (); +DN_API void DN_Win_MakeProcessDPIAware (); -// NOTE: [$WIND] Dqn_Win /////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_WinError Dqn_Win_ErrorCodeToMsg (Dqn_Arena *arena, uint32_t error_code); -DQN_API Dqn_WinError Dqn_Win_LastError (Dqn_Arena *arena); -DQN_API void Dqn_Win_MakeProcessDPIAware(); // NOTE: Windows Str8 <-> Str16 //////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str16 Dqn_Win_Str8ToStr16 (Dqn_Arena *arena, Dqn_Str8 src); -DQN_API int Dqn_Win_Str8ToStr16Buffer (Dqn_Str16 src, char *dest, int dest_size); -DQN_API Dqn_Str8 Dqn_Win_Str16ToStr8 (Dqn_Arena *arena, Dqn_Str16 src); -DQN_API int Dqn_Win_Str16ToStr8Buffer (Dqn_Str16 src, char *dest, int dest_size); +DN_API DN_Str16 DN_Win_Str8ToStr16 (DN_Arena *arena, DN_Str8 src); +DN_API int DN_Win_Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size); +DN_API DN_Str8 DN_Win_Str16ToStr8 (DN_Arena *arena, DN_Str16 src); +DN_API int DN_Win_Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size); +DN_API DN_Str8 DN_Win_Str16ToStr8Alloc (DN_Str16 src); + // NOTE: Path navigation /////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str16 Dqn_Win_EXEPathW (Dqn_Arena *arena); -DQN_API Dqn_Str16 Dqn_Win_EXEDirW (Dqn_Arena *arena); -DQN_API Dqn_Str8 Dqn_Win_WorkingDir (Dqn_Arena *arena, Dqn_Str8 suffix); -DQN_API Dqn_Str16 Dqn_Win_WorkingDirW (Dqn_Arena *arena, Dqn_Str16 suffix); -DQN_API bool Dqn_Win_FolderIterate (Dqn_Str8 path, Dqn_Win_FolderIterator *it); -DQN_API bool Dqn_Win_FolderWIterate (Dqn_Str16 path, Dqn_Win_FolderIteratorW *it); +DN_API DN_Str16 DN_Win_EXEPathW (DN_Arena *arena); +DN_API DN_Str16 DN_Win_EXEDirW (DN_Arena *arena); +DN_API DN_Str8 DN_Win_WorkingDir (DN_Arena *arena, DN_Str8 suffix); +DN_API DN_Str16 DN_Win_WorkingDirW (DN_Arena *arena, DN_Str16 suffix); +DN_API bool DN_Win_DirWIterate (DN_Str16 path, DN_Win_FolderIteratorW *it); diff --git a/dqn_string.cpp b/dqn_string.cpp index 9538af5..794f28c 100644 --- a/dqn_string.cpp +++ b/dqn_string.cpp @@ -18,28 +18,28 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$CSTR] Dqn_CStr8 ///////////////////////////////////////////////////////////////////////// -DQN_API Dqn_usize Dqn_CStr8_FSize(DQN_FMT_ATTRIB char const *fmt, ...) +// NOTE: [$CSTR] DN_CStr8 ///////////////////////////////////////////////////////////////////////// +DN_API DN_USize DN_CStr8_FSize(DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - Dqn_usize result = DQN_VSNPRINTF(nullptr, 0, fmt, args); + DN_USize result = DN_VSNPRINTF(nullptr, 0, fmt, args); va_end(args); return result; } -DQN_API Dqn_usize Dqn_CStr8_FVSize(DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API DN_USize DN_CStr8_FVSize(DN_FMT_ATTRIB char const *fmt, va_list args) { va_list args_copy; va_copy(args_copy, args); - Dqn_usize result = DQN_VSNPRINTF(nullptr, 0, fmt, args_copy); + DN_USize result = DN_VSNPRINTF(nullptr, 0, fmt, args_copy); va_end(args_copy); return result; } -DQN_API Dqn_usize Dqn_CStr8_Size(char const *src) +DN_API DN_USize DN_CStr8_Size(char const *src) { - Dqn_usize result = 0; + DN_USize result = 0; while (src && src[0] != 0) { src++; result++; @@ -47,9 +47,9 @@ DQN_API Dqn_usize Dqn_CStr8_Size(char const *src) return result; } -DQN_API Dqn_usize Dqn_CStr16_Size(wchar_t const *src) +DN_API DN_USize DN_CStr16_Size(wchar_t const *src) { - Dqn_usize result = 0; + DN_USize result = 0; while (src && src[0] != 0) { src++; result++; @@ -58,44 +58,44 @@ DQN_API Dqn_usize Dqn_CStr16_Size(wchar_t const *src) return result; } -// NOTE: [$STR6] Dqn_Str16 ///////////////////////////////////////////////////////////////////////// -DQN_API bool operator==(Dqn_Str16 const &lhs, Dqn_Str16 const &rhs) +// NOTE: [$STR6] DN_Str16 ///////////////////////////////////////////////////////////////////////// +DN_API bool operator==(DN_Str16 const &lhs, DN_Str16 const &rhs) { bool result = false; if (lhs.size == rhs.size) - result = DQN_MEMCMP(lhs.data, rhs.data, lhs.size * sizeof(*lhs.data)) == 0; + result = DN_MEMCMP(lhs.data, rhs.data, lhs.size * sizeof(*lhs.data)) == 0; return result; } -DQN_API bool operator!=(Dqn_Str16 const &lhs, Dqn_Str16 const &rhs) +DN_API bool operator!=(DN_Str16 const &lhs, DN_Str16 const &rhs) { bool result = !(lhs == rhs); return result; } -// NOTE: [$STR8] Dqn_Str8 ////////////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8 Dqn_Str8_InitCStr8(char const *src) +// NOTE: [$STR8] DN_Str8 ////////////////////////////////////////////////////////////////////////// +DN_API DN_Str8 DN_Str8_InitCStr8(char const *src) { - Dqn_usize size = Dqn_CStr8_Size(src); - Dqn_Str8 result = Dqn_Str8_Init(src, size); + DN_USize size = DN_CStr8_Size(src); + DN_Str8 result = DN_Str8_Init(src, size); return result; } -DQN_API bool Dqn_Str8_IsAll(Dqn_Str8 string, Dqn_Str8IsAll is_all) +DN_API bool DN_Str8_IsAll(DN_Str8 string, DN_Str8IsAll is_all) { - bool result = Dqn_Str8_HasData(string); + bool result = DN_Str8_HasData(string); if (!result) return result; switch (is_all) { - case Dqn_Str8IsAll_Digits: { - for (Dqn_usize index = 0; result && index < string.size; index++) + case DN_Str8IsAll_Digits: { + for (DN_USize index = 0; result && index < string.size; index++) result = string.data[index] >= '0' && string.data[index] <= '9'; } break; - case Dqn_Str8IsAll_Hex: { - Dqn_Str8 trimmed = Dqn_Str8_TrimPrefix(string, DQN_STR8("0x"), Dqn_Str8EqCase_Insensitive); - for (Dqn_usize index = 0; result && index < trimmed.size; index++) { + case DN_Str8IsAll_Hex: { + DN_Str8 trimmed = DN_Str8_TrimPrefix(string, DN_STR8("0x"), DN_Str8EqCase_Insensitive); + for (DN_USize index = 0; result && index < trimmed.size; index++) { char ch = trimmed.data[index]; result = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); } @@ -105,43 +105,49 @@ DQN_API bool Dqn_Str8_IsAll(Dqn_Str8 string, Dqn_Str8IsAll is_all) return result; } -DQN_API Dqn_Str8 Dqn_Str8_Slice(Dqn_Str8 string, Dqn_usize offset, Dqn_usize size) +DN_API char *DN_Str8_End(DN_Str8 string) { - Dqn_Str8 result = Dqn_Str8_Init(string.data, 0); - if (!Dqn_Str8_HasData(string)) + char *result = string.data + string.size; + return result; +} + +DN_API DN_Str8 DN_Str8_Slice(DN_Str8 string, DN_USize offset, DN_USize size) +{ + DN_Str8 result = DN_Str8_Init(string.data, 0); + if (!DN_Str8_HasData(string)) return result; - Dqn_usize capped_offset = DQN_MIN(offset, string.size); - Dqn_usize max_size = string.size - capped_offset; - Dqn_usize capped_size = DQN_MIN(size, max_size); - result = Dqn_Str8_Init(string.data + capped_offset, capped_size); + DN_USize capped_offset = DN_MIN(offset, string.size); + DN_USize max_size = string.size - capped_offset; + DN_USize capped_size = DN_MIN(size, max_size); + result = DN_Str8_Init(string.data + capped_offset, capped_size); return result; } -DQN_API Dqn_Str8 Dqn_Str8_Advance(Dqn_Str8 string, Dqn_usize amount) +DN_API DN_Str8 DN_Str8_Advance(DN_Str8 string, DN_USize amount) { - Dqn_Str8 result = Dqn_Str8_Slice(string, amount, DQN_USIZE_MAX); + DN_Str8 result = DN_Str8_Slice(string, amount, DN_USIZE_MAX); return result; } -DQN_API Dqn_Str8 Dqn_Str8_NextLine(Dqn_Str8 string) +DN_API DN_Str8 DN_Str8_NextLine(DN_Str8 string) { - Dqn_Str8 result = Dqn_Str8_BinarySplit(string, DQN_STR8("\n")).rhs; + DN_Str8 result = DN_Str8_BinarySplit(string, DN_STR8("\n")).rhs; return result; } -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size) +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitArray(DN_Str8 string, DN_Str8 const *find, DN_USize find_size) { - Dqn_Str8BinarySplitResult result = {}; - if (!Dqn_Str8_HasData(string) || !find || find_size == 0) + DN_Str8BinarySplitResult result = {}; + if (!DN_Str8_HasData(string) || !find || find_size == 0) return result; result.lhs = string; for (size_t index = 0; !result.rhs.data && index < string.size; index++) { - for (Dqn_usize find_index = 0; find_index < find_size; find_index++) { - Dqn_Str8 find_item = find[find_index]; - Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find_item.size); - if (Dqn_Str8_Eq(string_slice, find_item)) { + for (DN_USize find_index = 0; find_index < find_size; find_index++) { + DN_Str8 find_item = find[find_index]; + DN_Str8 string_slice = DN_Str8_Slice(string, index, find_item.size); + if (DN_Str8_Eq(string_slice, find_item)) { result.lhs.size = index; result.rhs.data = string_slice.data + find_item.size; result.rhs.size = string.size - (index + find_item.size); @@ -153,24 +159,24 @@ DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray(Dqn_Str8 string, Dqn return result; } -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplit(Dqn_Str8 string, Dqn_Str8 find) +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplit(DN_Str8 string, DN_Str8 find) { - Dqn_Str8BinarySplitResult result = Dqn_Str8_BinarySplitArray(string, &find, 1); + DN_Str8BinarySplitResult result = DN_Str8_BinarySplitArray(string, &find, 1); return result; } -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastArray(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size) +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLastArray(DN_Str8 string, DN_Str8 const *find, DN_USize find_size) { - Dqn_Str8BinarySplitResult result = {}; - if (!Dqn_Str8_HasData(string) || !find || find_size == 0) + DN_Str8BinarySplitResult result = {}; + if (!DN_Str8_HasData(string) || !find || find_size == 0) return result; result.lhs = string; for (size_t index = string.size - 1; !result.rhs.data && index < string.size; index--) { - for (Dqn_usize find_index = 0; find_index < find_size; find_index++) { - Dqn_Str8 find_item = find[find_index]; - Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find_item.size); - if (Dqn_Str8_Eq(string_slice, find_item)) { + for (DN_USize find_index = 0; find_index < find_size; find_index++) { + DN_Str8 find_item = find[find_index]; + DN_Str8 string_slice = DN_Str8_Slice(string, index, find_item.size); + if (DN_Str8_Eq(string_slice, find_item)) { result.lhs.size = index; result.rhs.data = string_slice.data + find_item.size; result.rhs.size = string.size - (index + find_item.size); @@ -182,23 +188,23 @@ DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastArray(Dqn_Str8 string, return result; } -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLast(Dqn_Str8 string, Dqn_Str8 find) +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLast(DN_Str8 string, DN_Str8 find) { - Dqn_Str8BinarySplitResult result = Dqn_Str8_BinarySplitLastArray(string, &find, 1); + DN_Str8BinarySplitResult result = DN_Str8_BinarySplitLastArray(string, &find, 1); return result; } -DQN_API Dqn_usize Dqn_Str8_Split(Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8 *splits, Dqn_usize splits_count, Dqn_Str8SplitIncludeEmptyStrings mode) +DN_API DN_USize DN_Str8_Split(DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode) { - Dqn_usize result = 0; // The number of splits in the actual string. - if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(delimiter) || delimiter.size <= 0) + DN_USize result = 0; // The number of splits in the actual string. + if (!DN_Str8_HasData(string) || !DN_Str8_HasData(delimiter) || delimiter.size <= 0) return result; - Dqn_Str8BinarySplitResult split = {}; - Dqn_Str8 first = string; + DN_Str8BinarySplitResult split = {}; + DN_Str8 first = string; do { - split = Dqn_Str8_BinarySplit(first, delimiter); - if (split.lhs.size || mode == Dqn_Str8SplitIncludeEmptyStrings_Yes) { + split = DN_Str8_BinarySplit(first, delimiter); + if (split.lhs.size || mode == DN_Str8SplitIncludeEmptyStrings_Yes) { if (splits && result < splits_count) splits[result] = split.lhs; result++; @@ -209,34 +215,35 @@ DQN_API Dqn_usize Dqn_Str8_Split(Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8 * return result; } -DQN_API Dqn_Slice Dqn_Str8_SplitAlloc(Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8SplitIncludeEmptyStrings mode) +DN_API DN_Slice DN_Str8_SplitAlloc(DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode) { - Dqn_Slice result = {}; - Dqn_usize splits_required = Dqn_Str8_Split(string, delimiter, /*splits*/ nullptr, /*count*/ 0, mode); - result.data = Dqn_Arena_NewArray(arena, Dqn_Str8, splits_required, Dqn_ZeroMem_No); + DN_Slice result = {}; + DN_USize splits_required = DN_Str8_Split(string, delimiter, /*splits*/ nullptr, /*count*/ 0, mode); + result.data = DN_Arena_NewArray(arena, DN_Str8, splits_required, DN_ZeroMem_No); if (result.data) { - result.size = Dqn_Str8_Split(string, delimiter, result.data, splits_required, mode); - DQN_ASSERT(splits_required == result.size); + result.size = DN_Str8_Split(string, delimiter, result.data, splits_required, mode); + DN_ASSERT(splits_required == result.size); } return result; } -DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8Array(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size, Dqn_Str8EqCase eq_case) +DN_API DN_Str8FindResult DN_Str8_FindStr8Array(DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case) { - Dqn_Str8FindResult result = {}; - if (!Dqn_Str8_HasData(string) || !find || find_size == 0) + DN_Str8FindResult result = {}; + if (!DN_Str8_HasData(string) || !find || find_size == 0) return result; - for (Dqn_usize index = 0; !result.found && index < string.size; index++) { - for (Dqn_usize find_index = 0; find_index < find_size; find_index++) { - Dqn_Str8 find_item = find[find_index]; - Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find_item.size); - if (Dqn_Str8_Eq(string_slice, find_item, eq_case)) { - result.found = true; - result.index = index; - result.start_to_before_match = Dqn_Str8_Init(string.data, index); - result.match = Dqn_Str8_Init(string.data + index, find_item.size); - result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - index); + 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_Str8_Slice(string, index, find_item.size); + if (DN_Str8_Eq(string_slice, find_item, eq_case)) { + result.found = true; + result.index = index; + result.start_to_before_match = DN_Str8_Init(string.data, index); + result.match = DN_Str8_Init(string.data + index, find_item.size); + result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - index); + result.after_match_to_end_of_buffer = DN_Str8_Advance(result.match_to_end_of_buffer, find_item.size); break; } } @@ -244,78 +251,79 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8Array(Dqn_Str8 string, Dqn_Str8 cons return result; } -DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8(Dqn_Str8 string, Dqn_Str8 find, Dqn_Str8EqCase eq_case) +DN_API DN_Str8FindResult DN_Str8_FindStr8(DN_Str8 string, DN_Str8 find, DN_Str8EqCase eq_case) { - Dqn_Str8FindResult result = Dqn_Str8_FindStr8Array(string, &find, 1, eq_case); + DN_Str8FindResult result = DN_Str8_FindStr8Array(string, &find, 1, eq_case); return result; } -DQN_API Dqn_Str8FindResult Dqn_Str8_Find(Dqn_Str8 string, uint32_t flags) +DN_API DN_Str8FindResult DN_Str8_Find(DN_Str8 string, uint32_t flags) { - Dqn_Str8FindResult result = {}; + DN_Str8FindResult result = {}; for (size_t index = 0; !result.found && index < string.size; index++) { - result.found |= ((flags & Dqn_Str8FindFlag_Digit) && Dqn_Char_IsDigit(string.data[index])); - result.found |= ((flags & Dqn_Str8FindFlag_Alphabet) && Dqn_Char_IsAlphabet(string.data[index])); - result.found |= ((flags & Dqn_Str8FindFlag_Whitespace) && Dqn_Char_IsWhitespace(string.data[index])); - result.found |= ((flags & Dqn_Str8FindFlag_Plus) && string.data[index] == '+'); - result.found |= ((flags & Dqn_Str8FindFlag_Minus) && string.data[index] == '-'); + result.found |= ((flags & DN_Str8FindFlag_Digit) && DN_Char_IsDigit(string.data[index])); + result.found |= ((flags & DN_Str8FindFlag_Alphabet) && DN_Char_IsAlphabet(string.data[index])); + result.found |= ((flags & DN_Str8FindFlag_Whitespace) && DN_Char_IsWhitespace(string.data[index])); + result.found |= ((flags & DN_Str8FindFlag_Plus) && string.data[index] == '+'); + result.found |= ((flags & DN_Str8FindFlag_Minus) && string.data[index] == '-'); if (result.found) { - result.index = index; - result.match = Dqn_Str8_Init(string.data + index, 1); - result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - index); + result.index = index; + result.match = DN_Str8_Init(string.data + index, 1); + result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - index); + result.after_match_to_end_of_buffer = DN_Str8_Advance(result.match_to_end_of_buffer, 1); } } return result; } -DQN_API Dqn_Str8 Dqn_Str8_Segment(Dqn_Arena *arena, Dqn_Str8 src, Dqn_usize segment_size, char segment_char) +DN_API DN_Str8 DN_Str8_Segment(DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char) { - if (!segment_size || !Dqn_Str8_HasData(src)) { - Dqn_Str8 result = Dqn_Str8_Copy(arena, src); + if (!segment_size || !DN_Str8_HasData(src)) { + DN_Str8 result = DN_Str8_Copy(arena, src); return result; } - Dqn_usize segments = src.size / segment_size; + DN_USize segments = src.size / segment_size; if (src.size % segment_size == 0) segments--; - Dqn_usize segment_counter = 0; - Dqn_Str8 result = Dqn_Str8_Alloc(arena, src.size + segments, Dqn_ZeroMem_Yes); - Dqn_usize write_index = 0; - DQN_FOR_UINDEX(src_index, src.size) { + DN_USize segment_counter = 0; + DN_Str8 result = DN_Str8_Alloc(arena, src.size + segments, DN_ZeroMem_Yes); + DN_USize write_index = 0; + DN_FOR_UINDEX(src_index, src.size) { result.data[write_index++] = src.data[src_index]; if ((src_index + 1) % segment_size == 0 && segment_counter < segments) { result.data[write_index++] = segment_char; segment_counter++; } - DQN_ASSERTF(write_index <= result.size, "result.size=%zu, write_index=%zu", result.size, write_index); + DN_ASSERTF(write_index <= result.size, "result.size=%zu, write_index=%zu", result.size, write_index); } - DQN_ASSERTF(write_index == result.size, "result.size=%zu, write_index=%zu", result.size, write_index); + DN_ASSERTF(write_index == result.size, "result.size=%zu, write_index=%zu", result.size, write_index); return result; } -DQN_API Dqn_Str8 Dqn_Str8_ReverseSegment(Dqn_Arena *arena, Dqn_Str8 src, Dqn_usize segment_size, char segment_char) +DN_API DN_Str8 DN_Str8_ReverseSegment(DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char) { - if (!segment_size || !Dqn_Str8_HasData(src)) { - Dqn_Str8 result = Dqn_Str8_Copy(arena, src); + if (!segment_size || !DN_Str8_HasData(src)) { + DN_Str8 result = DN_Str8_Copy(arena, src); return result; } - Dqn_usize segments = src.size / segment_size; + DN_USize segments = src.size / segment_size; if (src.size % segment_size == 0) segments--; - Dqn_usize write_counter = 0; - Dqn_usize segment_counter = 0; - Dqn_Str8 result = Dqn_Str8_Alloc(arena, src.size + segments, Dqn_ZeroMem_Yes); - Dqn_usize write_index = result.size - 1; + DN_USize write_counter = 0; + DN_USize segment_counter = 0; + DN_Str8 result = DN_Str8_Alloc(arena, src.size + segments, DN_ZeroMem_Yes); + DN_USize write_index = result.size - 1; - DQN_MSVC_WARNING_PUSH - DQN_MSVC_WARNING_DISABLE(6293) // NOTE: Ill-defined loop + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(6293) // NOTE: Ill-defined loop for (size_t src_index = src.size - 1; src_index < src.size; src_index--) { - DQN_MSVC_WARNING_POP + DN_MSVC_WARNING_POP result.data[write_index--] = src.data[src_index]; if (++write_counter % segment_size == 0 && segment_counter < segments) { result.data[write_index--] = segment_char; @@ -323,12 +331,12 @@ DQN_API Dqn_Str8 Dqn_Str8_ReverseSegment(Dqn_Arena *arena, Dqn_Str8 src, Dqn_usi } } - DQN_ASSERT(write_index == SIZE_MAX); + DN_ASSERT(write_index == SIZE_MAX); return result; } -DQN_API bool Dqn_Str8_Eq(Dqn_Str8 lhs, Dqn_Str8 rhs, Dqn_Str8EqCase eq_case) +DN_API bool DN_Str8_Eq(DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case) { if (lhs.size != rhs.size) return false; @@ -341,220 +349,220 @@ DQN_API bool Dqn_Str8_Eq(Dqn_Str8 lhs, Dqn_Str8 rhs, Dqn_Str8EqCase eq_case) bool result = true; switch (eq_case) { - case Dqn_Str8EqCase_Sensitive: { - result = (DQN_MEMCMP(lhs.data, rhs.data, lhs.size) == 0); + case DN_Str8EqCase_Sensitive: { + result = (DN_MEMCMP(lhs.data, rhs.data, lhs.size) == 0); } break; - case Dqn_Str8EqCase_Insensitive: { - for (Dqn_usize index = 0; index < lhs.size && result; index++) - result = (Dqn_Char_ToLower(lhs.data[index]) == Dqn_Char_ToLower(rhs.data[index])); + case DN_Str8EqCase_Insensitive: { + for (DN_USize index = 0; index < lhs.size && result; index++) + result = (DN_Char_ToLower(lhs.data[index]) == DN_Char_ToLower(rhs.data[index])); } break; } return result; } -DQN_API bool Dqn_Str8_EqInsensitive(Dqn_Str8 lhs, Dqn_Str8 rhs) +DN_API bool DN_Str8_EqInsensitive(DN_Str8 lhs, DN_Str8 rhs) { - bool result = Dqn_Str8_Eq(lhs, rhs, Dqn_Str8EqCase_Insensitive); + bool result = DN_Str8_Eq(lhs, rhs, DN_Str8EqCase_Insensitive); return result; } -DQN_API bool Dqn_Str8_StartsWith(Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case) +DN_API bool DN_Str8_StartsWith(DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case) { - Dqn_Str8 substring = {string.data, DQN_MIN(prefix.size, string.size)}; - bool result = Dqn_Str8_Eq(substring, prefix, eq_case); + DN_Str8 substring = {string.data, DN_MIN(prefix.size, string.size)}; + bool result = DN_Str8_Eq(substring, prefix, eq_case); return result; } -DQN_API bool Dqn_Str8_StartsWithInsensitive(Dqn_Str8 string, Dqn_Str8 prefix) +DN_API bool DN_Str8_StartsWithInsensitive(DN_Str8 string, DN_Str8 prefix) { - bool result = Dqn_Str8_StartsWith(string, prefix, Dqn_Str8EqCase_Insensitive); + bool result = DN_Str8_StartsWith(string, prefix, DN_Str8EqCase_Insensitive); return result; } -DQN_API bool Dqn_Str8_EndsWith(Dqn_Str8 string, Dqn_Str8 suffix, Dqn_Str8EqCase eq_case) +DN_API bool DN_Str8_EndsWith(DN_Str8 string, DN_Str8 suffix, DN_Str8EqCase eq_case) { - Dqn_Str8 substring = {string.data + string.size - suffix.size, DQN_MIN(string.size, suffix.size)}; - bool result = Dqn_Str8_Eq(substring, suffix, eq_case); + DN_Str8 substring = {string.data + string.size - suffix.size, DN_MIN(string.size, suffix.size)}; + bool result = DN_Str8_Eq(substring, suffix, eq_case); return result; } -DQN_API bool Dqn_Str8_EndsWithInsensitive(Dqn_Str8 string, Dqn_Str8 suffix) +DN_API bool DN_Str8_EndsWithInsensitive(DN_Str8 string, DN_Str8 suffix) { - bool result = Dqn_Str8_EndsWith(string, suffix, Dqn_Str8EqCase_Insensitive); + bool result = DN_Str8_EndsWith(string, suffix, DN_Str8EqCase_Insensitive); return result; } -DQN_API bool Dqn_Str8_HasChar(Dqn_Str8 string, char ch) +DN_API bool DN_Str8_HasChar(DN_Str8 string, char ch) { bool result = false; - for (Dqn_usize index = 0; !result && index < string.size; index++) + for (DN_USize index = 0; !result && index < string.size; index++) result = string.data[index] == ch; return result; } -DQN_API Dqn_Str8 Dqn_Str8_TrimPrefix(Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case) +DN_API DN_Str8 DN_Str8_TrimPrefix(DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case) { - Dqn_Str8 result = string; - if (Dqn_Str8_StartsWith(string, prefix, eq_case)) { + DN_Str8 result = string; + if (DN_Str8_StartsWith(string, prefix, eq_case)) { result.data += prefix.size; result.size -= prefix.size; } return result; } -DQN_API Dqn_Str8 Dqn_Str8_TrimHexPrefix(Dqn_Str8 string) +DN_API DN_Str8 DN_Str8_TrimHexPrefix(DN_Str8 string) { - Dqn_Str8 result = Dqn_Str8_TrimPrefix(string, DQN_STR8("0x"), Dqn_Str8EqCase_Insensitive); + DN_Str8 result = DN_Str8_TrimPrefix(string, DN_STR8("0x"), DN_Str8EqCase_Insensitive); return result; } -DQN_API Dqn_Str8 Dqn_Str8_TrimSuffix(Dqn_Str8 string, Dqn_Str8 suffix, Dqn_Str8EqCase eq_case) +DN_API DN_Str8 DN_Str8_TrimSuffix(DN_Str8 string, DN_Str8 suffix, DN_Str8EqCase eq_case) { - Dqn_Str8 result = string; - if (Dqn_Str8_EndsWith(string, suffix, eq_case)) + DN_Str8 result = string; + if (DN_Str8_EndsWith(string, suffix, eq_case)) result.size -= suffix.size; return result; } -DQN_API Dqn_Str8 Dqn_Str8_TrimAround(Dqn_Str8 string, Dqn_Str8 trim_string) +DN_API DN_Str8 DN_Str8_TrimAround(DN_Str8 string, DN_Str8 trim_string) { - Dqn_Str8 result = Dqn_Str8_TrimPrefix(string, trim_string); - result = Dqn_Str8_TrimSuffix(result, trim_string); + DN_Str8 result = DN_Str8_TrimPrefix(string, trim_string); + result = DN_Str8_TrimSuffix(result, trim_string); return result; } -DQN_API Dqn_Str8 Dqn_Str8_TrimWhitespaceAround(Dqn_Str8 string) +DN_API DN_Str8 DN_Str8_TrimWhitespaceAround(DN_Str8 string) { - Dqn_Str8 result = string; - if (!Dqn_Str8_HasData(string)) + DN_Str8 result = string; + if (!DN_Str8_HasData(string)) return result; char const *start = string.data; char const *end = string.data + string.size; - while (start < end && Dqn_Char_IsWhitespace(start[0])) + while (start < end && DN_Char_IsWhitespace(start[0])) start++; - while (end > start && Dqn_Char_IsWhitespace(end[-1])) + while (end > start && DN_Char_IsWhitespace(end[-1])) end--; - result = Dqn_Str8_Init(start, end - start); + result = DN_Str8_Init(start, end - start); return result; } -DQN_API Dqn_Str8 Dqn_Str8_TrimByteOrderMark(Dqn_Str8 string) +DN_API DN_Str8 DN_Str8_TrimByteOrderMark(DN_Str8 string) { - Dqn_Str8 result = string; - if (!Dqn_Str8_HasData(result)) + DN_Str8 result = string; + if (!DN_Str8_HasData(result)) return result; - // TODO(dqn): This is little endian - Dqn_Str8 UTF8_BOM = DQN_STR8("\xEF\xBB\xBF"); - Dqn_Str8 UTF16_BOM_BE = DQN_STR8("\xEF\xFF"); - Dqn_Str8 UTF16_BOM_LE = DQN_STR8("\xFF\xEF"); - Dqn_Str8 UTF32_BOM_BE = DQN_STR8("\x00\x00\xFE\xFF"); - Dqn_Str8 UTF32_BOM_LE = DQN_STR8("\xFF\xFE\x00\x00"); + // TODO(dn): This is little endian + DN_Str8 UTF8_BOM = DN_STR8("\xEF\xBB\xBF"); + DN_Str8 UTF16_BOM_BE = DN_STR8("\xEF\xFF"); + DN_Str8 UTF16_BOM_LE = DN_STR8("\xFF\xEF"); + DN_Str8 UTF32_BOM_BE = DN_STR8("\x00\x00\xFE\xFF"); + DN_Str8 UTF32_BOM_LE = DN_STR8("\xFF\xFE\x00\x00"); - result = Dqn_Str8_TrimPrefix(result, UTF8_BOM, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_TrimPrefix(result, UTF16_BOM_BE, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_TrimPrefix(result, UTF16_BOM_LE, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_TrimPrefix(result, UTF32_BOM_BE, Dqn_Str8EqCase_Sensitive); - result = Dqn_Str8_TrimPrefix(result, UTF32_BOM_LE, Dqn_Str8EqCase_Sensitive); + result = DN_Str8_TrimPrefix(result, UTF8_BOM, DN_Str8EqCase_Sensitive); + result = DN_Str8_TrimPrefix(result, UTF16_BOM_BE, DN_Str8EqCase_Sensitive); + result = DN_Str8_TrimPrefix(result, UTF16_BOM_LE, DN_Str8EqCase_Sensitive); + result = DN_Str8_TrimPrefix(result, UTF32_BOM_BE, DN_Str8EqCase_Sensitive); + result = DN_Str8_TrimPrefix(result, UTF32_BOM_LE, DN_Str8EqCase_Sensitive); return result; } -DQN_API Dqn_Str8 Dqn_Str8_FileNameFromPath(Dqn_Str8 path) +DN_API DN_Str8 DN_Str8_FileNameFromPath(DN_Str8 path) { - Dqn_Str8 separators[] = {DQN_STR8("/"), DQN_STR8("\\")}; - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplitLastArray(path, separators, DQN_ARRAY_UCOUNT(separators)); - Dqn_Str8 result = Dqn_Str8_HasData(split.rhs) ? split.rhs : split.lhs; + DN_Str8 separators[] = {DN_STR8("/"), DN_STR8("\\")}; + DN_Str8BinarySplitResult split = DN_Str8_BinarySplitLastArray(path, separators, DN_ARRAY_UCOUNT(separators)); + DN_Str8 result = DN_Str8_HasData(split.rhs) ? split.rhs : split.lhs; return result; } -DQN_API Dqn_Str8 Dqn_Str8_FileNameNoExtension(Dqn_Str8 path) +DN_API DN_Str8 DN_Str8_FileNameNoExtension(DN_Str8 path) { - Dqn_Str8 file_name = Dqn_Str8_FileNameFromPath(path); - Dqn_Str8 result = Dqn_Str8_FilePathNoExtension(file_name); + DN_Str8 file_name = DN_Str8_FileNameFromPath(path); + DN_Str8 result = DN_Str8_FilePathNoExtension(file_name); return result; } -DQN_API Dqn_Str8 Dqn_Str8_FilePathNoExtension(Dqn_Str8 path) +DN_API DN_Str8 DN_Str8_FilePathNoExtension(DN_Str8 path) { - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplitLast(path, DQN_STR8(".")); - Dqn_Str8 result = split.lhs; + DN_Str8BinarySplitResult split = DN_Str8_BinarySplitLast(path, DN_STR8(".")); + DN_Str8 result = split.lhs; return result; } -DQN_API Dqn_Str8 Dqn_Str8_FileExtension(Dqn_Str8 path) +DN_API DN_Str8 DN_Str8_FileExtension(DN_Str8 path) { - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplitLast(path, DQN_STR8(".")); - Dqn_Str8 result = split.rhs; + DN_Str8BinarySplitResult split = DN_Str8_BinarySplitLast(path, DN_STR8(".")); + DN_Str8 result = split.rhs; return result; } -DQN_API Dqn_Str8ToU64Result Dqn_Str8_ToU64(Dqn_Str8 string, char separator) +DN_API DN_Str8ToU64Result DN_Str8_ToU64(DN_Str8 string, char separator) { // NOTE: Argument check - Dqn_Str8ToU64Result result = {}; - if (!Dqn_Str8_HasData(string)) { + DN_Str8ToU64Result result = {}; + if (!DN_Str8_HasData(string)) { result.success = true; return result; } // NOTE: Sanitize input/output - Dqn_Str8 trim_string = Dqn_Str8_TrimWhitespaceAround(string); + DN_Str8 trim_string = DN_Str8_TrimWhitespaceAround(string); if (trim_string.size == 0) { result.success = true; return result; } // NOTE: Handle prefix '+' - Dqn_usize start_index = 0; - if (!Dqn_Char_IsDigit(trim_string.data[0])) { + DN_USize start_index = 0; + if (!DN_Char_IsDigit(trim_string.data[0])) { if (trim_string.data[0] != '+') return result; start_index++; } // NOTE: Convert the string number to the binary number - for (Dqn_usize index = start_index; index < trim_string.size; index++) { + for (DN_USize index = start_index; index < trim_string.size; index++) { char ch = trim_string.data[index]; if (index) { if (separator != 0 && ch == separator) continue; } - if (!Dqn_Char_IsDigit(ch)) + if (!DN_Char_IsDigit(ch)) return result; - result.value = Dqn_Safe_MulU64(result.value, 10); + result.value = DN_Safe_MulU64(result.value, 10); uint64_t digit = ch - '0'; - result.value = Dqn_Safe_AddU64(result.value, digit); + result.value = DN_Safe_AddU64(result.value, digit); } result.success = true; return result; } -DQN_API Dqn_Str8ToI64Result Dqn_Str8_ToI64(Dqn_Str8 string, char separator) +DN_API DN_Str8ToI64Result DN_Str8_ToI64(DN_Str8 string, char separator) { // NOTE: Argument check - Dqn_Str8ToI64Result result = {}; - if (!Dqn_Str8_HasData(string)) { + DN_Str8ToI64Result result = {}; + if (!DN_Str8_HasData(string)) { result.success = true; return result; } // NOTE: Sanitize input/output - Dqn_Str8 trim_string = Dqn_Str8_TrimWhitespaceAround(string); + DN_Str8 trim_string = DN_Str8_TrimWhitespaceAround(string); if (trim_string.size == 0) { result.success = true; return result; } bool negative = false; - Dqn_usize start_index = 0; - if (!Dqn_Char_IsDigit(trim_string.data[0])) { + DN_USize start_index = 0; + if (!DN_Char_IsDigit(trim_string.data[0])) { negative = (trim_string.data[start_index] == '-'); if (!negative && trim_string.data[0] != '+') return result; @@ -562,19 +570,19 @@ DQN_API Dqn_Str8ToI64Result Dqn_Str8_ToI64(Dqn_Str8 string, char separator) } // NOTE: Convert the string number to the binary number - for (Dqn_usize index = start_index; index < trim_string.size; index++) { + for (DN_USize index = start_index; index < trim_string.size; index++) { char ch = trim_string.data[index]; if (index) { if (separator != 0 && ch == separator) continue; } - if (!Dqn_Char_IsDigit(ch)) + if (!DN_Char_IsDigit(ch)) return result; - result.value = Dqn_Safe_MulU64(result.value, 10); + result.value = DN_Safe_MulU64(result.value, 10); uint64_t digit = ch - '0'; - result.value = Dqn_Safe_AddU64(result.value, digit); + result.value = DN_Safe_AddU64(result.value, digit); } if (negative) @@ -584,27 +592,54 @@ DQN_API Dqn_Str8ToI64Result Dqn_Str8_ToI64(Dqn_Str8 string, char separator) return result; } -DQN_API Dqn_Str8 Dqn_Str8_Replace(Dqn_Str8 string, - Dqn_Str8 find, - Dqn_Str8 replace, - Dqn_usize start_index, - Dqn_Arena *arena, - Dqn_Str8EqCase eq_case) +DN_API DN_Str8 DN_Str8_AppendF(DN_Arena *arena, DN_Str8 string, char const *fmt, ...) { - Dqn_Str8 result = {}; - if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(find) || find.size > string.size || find.size == 0 || string.size == 0) { - result = Dqn_Str8_Copy(arena, string); + va_list args; + va_start(args, fmt); + DN_Str8 append = DN_Str8_InitFV(arena, fmt, args); + va_end(args); + + DN_Str8 result = DN_Str8_Alloc(arena, string.size + append.size, DN_ZeroMem_No); + DN_MEMCPY(result.data, string.data, string.size); + DN_MEMCPY(result.data + string.size, append.data, append.size); + return result; +} + +DN_API DN_Str8 DN_Str8_FillF(DN_Arena *arena, DN_USize count, char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_Str8 fill = DN_Str8_InitFV(arena, fmt, args); + va_end(args); + DN_Str8 result = DN_Str8_Alloc(arena, count * fill.size, DN_ZeroMem_No); + for (DN_USize index = 0; index < count; index++) { + void *dest = result.data + (index * fill.size); + DN_MEMCPY(dest, fill.data, fill.size); + } + return result; +} + +DN_API DN_Str8 DN_Str8_Replace(DN_Str8 string, + DN_Str8 find, + DN_Str8 replace, + DN_USize start_index, + DN_Arena *arena, + DN_Str8EqCase eq_case) +{ + DN_Str8 result = {}; + if (!DN_Str8_HasData(string) || !DN_Str8_HasData(find) || find.size > string.size || find.size == 0 || string.size == 0) { + result = DN_Str8_Copy(arena, string); return result; } - Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); - Dqn_Str8Builder string_builder = Dqn_Str8Builder_Init(tmem.arena); - Dqn_usize max = string.size - find.size; - Dqn_usize head = start_index; + DN_TLSTMem tmem = DN_TLS_TMem(arena); + DN_Str8Builder string_builder = DN_Str8Builder_Init(tmem.arena); + DN_USize max = string.size - find.size; + DN_USize head = start_index; - for (Dqn_usize tail = head; tail <= max; tail++) { - Dqn_Str8 check = Dqn_Str8_Slice(string, tail, find.size); - if (!Dqn_Str8_Eq(check, find, eq_case)) + for (DN_USize tail = head; tail <= max; tail++) { + DN_Str8 check = DN_Str8_Slice(string, tail, find.size); + if (!DN_Str8_Eq(check, find, eq_case)) continue; if (start_index > 0 && string_builder.string_size == 0) { @@ -612,144 +647,192 @@ DQN_API Dqn_Str8 Dqn_Str8_Replace(Dqn_Str8 string, // 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. - Dqn_Str8 slice = Dqn_Str8_Init(string.data, head); - Dqn_Str8Builder_AddRef(&string_builder, slice); + DN_Str8 slice = DN_Str8_Init(string.data, head); + DN_Str8Builder_AppendRef(&string_builder, slice); } - Dqn_Str8 range = Dqn_Str8_Slice(string, head, (tail - head)); - Dqn_Str8Builder_AddRef(&string_builder, range); - Dqn_Str8Builder_AddRef(&string_builder, replace); + DN_Str8 range = DN_Str8_Slice(string, head, (tail - head)); + DN_Str8Builder_AppendRef(&string_builder, range); + DN_Str8Builder_AppendRef(&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 = Dqn_Str8_Copy(arena, string); + result = DN_Str8_Copy(arena, string); } else { - Dqn_Str8 remainder = Dqn_Str8_Init(string.data + head, string.size - head); - Dqn_Str8Builder_AddRef(&string_builder, remainder); - result = Dqn_Str8Builder_Build(&string_builder, arena); + DN_Str8 remainder = DN_Str8_Init(string.data + head, string.size - head); + DN_Str8Builder_AppendRef(&string_builder, remainder); + result = DN_Str8Builder_Build(&string_builder, arena); } return result; } -DQN_API Dqn_Str8 Dqn_Str8_ReplaceInsensitive(Dqn_Str8 string, Dqn_Str8 find, Dqn_Str8 replace, Dqn_usize start_index, Dqn_Arena *arena) +DN_API DN_Str8 DN_Str8_ReplaceInsensitive(DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena) { - Dqn_Str8 result = Dqn_Str8_Replace(string, find, replace, start_index, arena, Dqn_Str8EqCase_Insensitive); + DN_Str8 result = DN_Str8_Replace(string, find, replace, start_index, arena, DN_Str8EqCase_Insensitive); return result; } -DQN_API void Dqn_Str8_Remove(Dqn_Str8 *string, Dqn_usize offset, Dqn_usize size) +DN_API void DN_Str8_Remove(DN_Str8 *string, DN_USize offset, DN_USize size) { - if (!string || !Dqn_Str8_HasData(*string)) + if (!string || !DN_Str8_HasData(*string)) return; char *end = string->data + string->size; - char *dest = DQN_MIN(string->data + offset, end); - char *src = DQN_MIN(string->data + offset + size, end); - Dqn_usize bytes_to_move = end - src; - DQN_MEMMOVE(dest, src, bytes_to_move); + char *dest = DN_MIN(string->data + offset, end); + char *src = DN_MIN(string->data + offset + size, end); + DN_USize bytes_to_move = end - src; + DN_MEMMOVE(dest, src, bytes_to_move); string->size -= bytes_to_move; } -#if defined(__cplusplus) -DQN_API bool operator==(Dqn_Str8 const &lhs, Dqn_Str8 const &rhs) +DN_API DN_Str8DotTruncateResult DN_Str8_DotTruncateMiddle(DN_Arena *arena, DN_Str8 str8, uint32_t side_size, DN_Str8 truncator) { - bool result = Dqn_Str8_Eq(lhs, rhs, Dqn_Str8EqCase_Sensitive); + DN_Str8DotTruncateResult result = {}; + if (str8.size <= (side_size * 2)) { + result.str8 = DN_Str8_Copy(arena, str8); + return result; + } + + DN_Str8 head = DN_Str8_Slice(str8, 0, side_size); + DN_Str8 tail = DN_Str8_Slice(str8, str8.size - side_size, side_size); + result.str8 = DN_Str8_InitF(arena, "%.*s%.*s%.*s", DN_STR_FMT(head), DN_STR_FMT(truncator), DN_STR_FMT(tail)); + result.truncated = true; + return result; +} + +DN_API DN_Str8 DN_Str8_PadNewLines(DN_Arena *arena, DN_Str8 src, DN_Str8 pad) +{ + DN_TLSTMem tmem = DN_TLS_PushTMem(arena); + DN_Str8Builder builder = DN_Str8Builder_Init_TLS(); + + DN_Str8BinarySplitResult split = DN_Str8_BinarySplit(src, DN_STR8("\n")); + while (split.lhs.size) { + DN_Str8Builder_AppendRef(&builder, pad); + DN_Str8Builder_AppendRef(&builder, split.lhs); + split = DN_Str8_BinarySplit(split.rhs, DN_STR8("\n")); + if (split.lhs.size) + DN_Str8Builder_AppendRef(&builder, DN_STR8("\n")); + } + + DN_Str8 result = DN_Str8Builder_Build(&builder, arena); + return result; +} + +DN_API DN_Str8 DN_Str8_Lower(DN_Arena *arena, DN_Str8 string) +{ + DN_Str8 result = DN_Str8_Copy(arena, string); + DN_FOR_UINDEX (index, result.size) + result.data[index] = DN_Char_ToLower(result.data[index]); return result; } -DQN_API bool operator!=(Dqn_Str8 const &lhs, Dqn_Str8 const &rhs) +DN_API DN_Str8 DN_Str8_Upper(DN_Arena *arena, DN_Str8 string) +{ + DN_Str8 result = DN_Str8_Copy(arena, string); + DN_FOR_UINDEX (index, result.size) + result.data[index] = DN_Char_ToUpper(result.data[index]); + return result; +} + +#if defined(__cplusplus) +DN_API bool operator==(DN_Str8 const &lhs, DN_Str8 const &rhs) +{ + bool result = DN_Str8_Eq(lhs, rhs, DN_Str8EqCase_Sensitive); + return result; +} + +DN_API bool operator!=(DN_Str8 const &lhs, DN_Str8 const &rhs) { bool result = !(lhs == rhs); return result; } #endif -DQN_API Dqn_Str8 Dqn_Str8_InitF(Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API DN_Str8 DN_Str8_InitF(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...) { va_list va; va_start(va, fmt); - Dqn_Str8 result = Dqn_Str8_InitFV(arena, fmt, va); + DN_Str8 result = DN_Str8_InitFV(arena, fmt, va); va_end(va); return result; } -DQN_API Dqn_Str8 Dqn_Str8_InitFV(Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args) +DN_API DN_Str8 DN_Str8_InitFV(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; if (!fmt) return result; - Dqn_usize size = Dqn_CStr8_FVSize(fmt, args); + DN_USize size = DN_CStr8_FVSize(fmt, args); if (size) { - result = Dqn_Str8_Alloc(arena, size, Dqn_ZeroMem_No); - if (Dqn_Str8_HasData(result)) - DQN_VSNPRINTF(result.data, Dqn_Safe_SaturateCastISizeToInt(size + 1 /*null-terminator*/), fmt, args); + result = DN_Str8_Alloc(arena, size, DN_ZeroMem_No); + if (DN_Str8_HasData(result)) + DN_VSNPRINTF(result.data, DN_Safe_SaturateCastISizeToInt(size + 1 /*null-terminator*/), fmt, args); } return result; } -DQN_API Dqn_Str8 Dqn_Str8_Alloc(Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem) +DN_API DN_Str8 DN_Str8_Alloc(DN_Arena *arena, DN_USize size, DN_ZeroMem zero_mem) { - Dqn_Str8 result = {}; - result.data = Dqn_Arena_NewArray(arena, char, size + 1, zero_mem); + DN_Str8 result = {}; + result.data = DN_Arena_NewArray(arena, char, size + 1, zero_mem); if (result.data) result.size = size; - if (zero_mem == Dqn_ZeroMem_No) - result.data[result.size] = 0; + result.data[result.size] = 0; return result; } -DQN_API Dqn_Str8 Dqn_Str8_CopyCString(Dqn_Arena *arena, char const *string, Dqn_usize size) +DN_API DN_Str8 DN_Str8_CopyCString(DN_Arena *arena, char const *string, DN_USize size) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; if (!string) return result; - result = Dqn_Str8_Alloc(arena, size, Dqn_ZeroMem_No); - if (Dqn_Str8_HasData(result)) { - DQN_MEMCPY(result.data, string, size); + result = DN_Str8_Alloc(arena, size, DN_ZeroMem_No); + if (DN_Str8_HasData(result)) { + DN_MEMCPY(result.data, string, size); result.data[size] = 0; } return result; } -DQN_API Dqn_Str8 Dqn_Str8_Copy(Dqn_Arena *arena, Dqn_Str8 string) +DN_API DN_Str8 DN_Str8_Copy(DN_Arena *arena, DN_Str8 string) { - Dqn_Str8 result = Dqn_Str8_CopyCString(arena, string.data, string.size); + DN_Str8 result = DN_Str8_CopyCString(arena, string.data, string.size); return result; } -// NOTE: [$STRB] Dqn_Str8Builder //////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8Builder Dqn_Str8Builder_Init(Dqn_Arena *arena) +// NOTE: [$STRB] DN_Str8Builder //////////////////////////////////////////////////////////////// +DN_API DN_Str8Builder DN_Str8Builder_Init(DN_Arena *arena) { - Dqn_Str8Builder result = {}; + DN_Str8Builder result = {}; result.arena = arena; return result; } -DQN_API Dqn_Str8Builder Dqn_Str8Builder_InitArrayRef(Dqn_Arena *arena, - Dqn_Str8 const *strings, - Dqn_usize size) +DN_API DN_Str8Builder DN_Str8Builder_InitArrayRef(DN_Arena *arena, + DN_Str8 const *strings, + DN_USize size) { - Dqn_Str8Builder result = Dqn_Str8Builder_Init(arena); - Dqn_Str8Builder_AddArrayRef(&result, strings, size); + DN_Str8Builder result = DN_Str8Builder_Init(arena); + DN_Str8Builder_AppendArrayRef(&result, strings, size); return result; } -DQN_API Dqn_Str8Builder Dqn_Str8Builder_InitArrayCopy(Dqn_Arena *arena, - Dqn_Str8 const *strings, - Dqn_usize size) +DN_API DN_Str8Builder DN_Str8Builder_InitArrayCopy(DN_Arena *arena, + DN_Str8 const *strings, + DN_USize size) { - Dqn_Str8Builder result = Dqn_Str8Builder_Init(arena); - Dqn_Str8Builder_AddArrayCopy(&result, strings, size); + DN_Str8Builder result = DN_Str8Builder_Init(arena); + DN_Str8Builder_AppendArrayCopy(&result, strings, size); return result; } -DQN_API bool Dqn_Str8Builder_AddArrayRef(Dqn_Str8Builder *builder, Dqn_Str8 const *strings, Dqn_usize size) +DN_API bool DN_Str8Builder_AddArrayRef(DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add) { if (!builder) return false; @@ -757,31 +840,48 @@ DQN_API bool Dqn_Str8Builder_AddArrayRef(Dqn_Str8Builder *builder, Dqn_Str8 cons if (!strings || size <= 0) return true; - Dqn_Str8Link *links = Dqn_Arena_NewArray(builder->arena, Dqn_Str8Link, size, Dqn_ZeroMem_No); + DN_Str8Link *links = DN_Arena_NewArray(builder->arena, DN_Str8Link, size, DN_ZeroMem_No); if (!links) return false; - DQN_FOR_UINDEX(index, size) { - Dqn_Str8 string = strings[index]; - Dqn_Str8Link *link = links + index; + if (add == DN_Str8BuilderAdd_Append) { + DN_FOR_UINDEX(index, size) { + DN_Str8 string = strings[index]; + DN_Str8Link *link = links + index; - link->string = string; - link->next = NULL; + link->string = string; + link->next = NULL; - if (builder->head) - builder->tail->next = link; - else + if (builder->head) + builder->tail->next = link; + else + builder->head = link; + + builder->tail = link; + builder->count++; + builder->string_size += string.size; + } + } else { + DN_ASSERT(add == DN_Str8BuilderAdd_Prepend); + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(6293) // NOTE: Ill-defined loop + for (DN_USize index = size - 1; index < size; index--) { + DN_MSVC_WARNING_POP + DN_Str8 string = strings[index]; + DN_Str8Link *link = links + index; + link->string = string; + link->next = builder->head; builder->head = link; - - builder->tail = link; - builder->count++; - builder->string_size += string.size; + if (!builder->tail) + builder->tail = link; + builder->count++; + builder->string_size += string.size; + } } - return true; } -DQN_API bool Dqn_Str8Builder_AddArrayCopy(Dqn_Str8Builder *builder, Dqn_Str8 const *strings, Dqn_usize size) +DN_API bool DN_Str8Builder_AddArrayCopy(DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add) { if (!builder) return false; @@ -789,11 +889,11 @@ DQN_API bool Dqn_Str8Builder_AddArrayCopy(Dqn_Str8Builder *builder, Dqn_Str8 con if (!strings || size <= 0) return true; - Dqn_ArenaTempMem tmp_mem = Dqn_Arena_TempMemBegin(builder->arena); + DN_ArenaTempMem tmp_mem = DN_Arena_TempMemBegin(builder->arena); bool result = true; - Dqn_Str8 *strings_copy = Dqn_Arena_NewArray(builder->arena, Dqn_Str8, size, Dqn_ZeroMem_No); - DQN_FOR_UINDEX (index, size) { - strings_copy[index] = Dqn_Str8_Copy(builder->arena, strings[index]); + DN_Str8 *strings_copy = DN_Arena_NewArray(builder->arena, DN_Str8, size, DN_ZeroMem_No); + DN_FOR_UINDEX (index, size) { + strings_copy[index] = DN_Str8_Copy(builder->arena, strings[index]); if (strings_copy[index].size != strings[index].size) { result = false; break; @@ -801,94 +901,82 @@ DQN_API bool Dqn_Str8Builder_AddArrayCopy(Dqn_Str8Builder *builder, Dqn_Str8 con } if (result) - result = Dqn_Str8Builder_AddArrayRef(builder, strings_copy, size); + result = DN_Str8Builder_AddArrayRef(builder, strings_copy, size, add); if (!result) - Dqn_Arena_TempMemEnd(tmp_mem); + DN_Arena_TempMemEnd(tmp_mem); return result; } -DQN_API bool Dqn_Str8Builder_AddSliceRef(Dqn_Str8Builder *builder, Dqn_Slice array) +DN_API bool DN_Str8Builder_AddFV(DN_Str8Builder *builder, DN_Str8BuilderAdd add, DN_FMT_ATTRIB char const *fmt, va_list args) { - bool result = Dqn_Str8Builder_AddArrayRef(builder, array.data, array.size); - return result; -} - -DQN_API bool Dqn_Str8Builder_AddSliceCopy(Dqn_Str8Builder *builder, Dqn_Slice array) -{ - bool result = Dqn_Str8Builder_AddArrayCopy(builder, array.data, array.size); - return result; -} - -DQN_API bool Dqn_Str8Builder_AddRef(Dqn_Str8Builder *builder, Dqn_Str8 string) -{ - bool result = Dqn_Str8Builder_AddArrayRef(builder, &string, 1); - return result; -} - -DQN_API bool Dqn_Str8Builder_AddCopy(Dqn_Str8Builder *builder, Dqn_Str8 string) -{ - bool result = Dqn_Str8Builder_AddArrayCopy(builder, &string, 1); - return result; -} - -DQN_API bool Dqn_Str8Builder_AddFV(Dqn_Str8Builder *builder, DQN_FMT_ATTRIB char const *fmt, va_list args) -{ - Dqn_Str8 string = Dqn_Str8_InitFV(builder->arena, fmt, args); - Dqn_ArenaTempMem temp_mem = Dqn_Arena_TempMemBegin(builder->arena); - bool result = Dqn_Str8Builder_AddRef(builder, string); + DN_Str8 string = DN_Str8_InitFV(builder->arena, fmt, args); + DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(builder->arena); + bool result = DN_Str8Builder_AddArrayRef(builder, &string, 1, add); if (!result) - Dqn_Arena_TempMemEnd(temp_mem); + DN_Arena_TempMemEnd(temp_mem); return result; } -DQN_API bool Dqn_Str8Builder_AddF(Dqn_Str8Builder *builder, DQN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_Str8Builder_AppendRef(DN_Str8Builder *builder, DN_Str8 string) +{ + bool result = DN_Str8Builder_AddArrayRef(builder, &string, 1, DN_Str8BuilderAdd_Append); + return result; +} + +DN_API bool DN_Str8Builder_AppendCopy(DN_Str8Builder *builder, DN_Str8 string) +{ + bool result = DN_Str8Builder_AddArrayCopy(builder, &string, 1, DN_Str8BuilderAdd_Append); + return result; +} + +DN_API bool DN_Str8Builder_AppendF(DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - bool result = Dqn_Str8Builder_AddFV(builder, fmt, args); + bool result = DN_Str8Builder_AppendFV(builder, fmt, args); va_end(args); return result; } -DQN_API bool Dqn_Str8Builder_AddBytesRef(Dqn_Str8Builder *builder, void const *ptr, Dqn_usize size) +DN_API bool DN_Str8Builder_AppendBytesRef(DN_Str8Builder *builder, void const *ptr, DN_USize size) { - Dqn_Str8 input = Dqn_Str8_Init(ptr, size); - bool result = Dqn_Str8Builder_AddRef(builder, input); + DN_Str8 input = DN_Str8_Init(ptr, size); + bool result = DN_Str8Builder_AppendRef(builder, input); return result; } -DQN_API bool Dqn_Str8Builder_AddBytesCopy(Dqn_Str8Builder *builder, void const *ptr, Dqn_usize size) +DN_API bool DN_Str8Builder_AppendBytesCopy(DN_Str8Builder *builder, void const *ptr, DN_USize size) { - Dqn_Str8 input = Dqn_Str8_Init(ptr, size); - bool result = Dqn_Str8Builder_AddCopy(builder, input); + DN_Str8 input = DN_Str8_Init(ptr, size); + bool result = DN_Str8Builder_AppendCopy(builder, input); return result; } -static bool Dqn_Str8Builder_AddBuilder_(Dqn_Str8Builder *dest, Dqn_Str8Builder const *src, bool copy) +static bool DN_Str8Builder_AppendBuilder_(DN_Str8Builder *dest, DN_Str8Builder const *src, bool copy) { if (!dest) return false; if (!src) return true; - Dqn_Arena_TempMemBegin(dest->arena); - Dqn_Str8Link *links = Dqn_Arena_NewArray(dest->arena, Dqn_Str8Link, src->count, Dqn_ZeroMem_No); + DN_Arena_TempMemBegin(dest->arena); + DN_Str8Link *links = DN_Arena_NewArray(dest->arena, DN_Str8Link, src->count, DN_ZeroMem_No); if (!links) return false; - Dqn_Str8Link *first = nullptr; - Dqn_Str8Link *last = nullptr; - Dqn_usize link_index = 0; + DN_Str8Link *first = nullptr; + DN_Str8Link *last = nullptr; + DN_USize link_index = 0; bool result = true; - for (Dqn_Str8Link const *it = src->head; it; it = it->next) { - Dqn_Str8Link *link = links + link_index++; + for (DN_Str8Link const *it = src->head; it; it = it->next) { + DN_Str8Link *link = links + link_index++; link->next = nullptr; link->string = it->string; if (copy) { - link->string = Dqn_Str8_Copy(dest->arena, it->string); + link->string = DN_Str8_Copy(dest->arena, it->string); if (link->string.size != it->string.size) { result = false; break; @@ -915,21 +1003,42 @@ static bool Dqn_Str8Builder_AddBuilder_(Dqn_Str8Builder *dest, Dqn_Str8Builder c return true; } -DQN_API bool Dqn_Str8Builder_AddBuilderRef(Dqn_Str8Builder *dest, Dqn_Str8Builder const *src) +DN_API bool DN_Str8Builder_AppendBuilderRef(DN_Str8Builder *dest, DN_Str8Builder const *src) { - bool result = Dqn_Str8Builder_AddBuilder_(dest, src, false); + bool result = DN_Str8Builder_AppendBuilder_(dest, src, false); return result; } -DQN_API bool Dqn_Str8Builder_AddBuilderCopy(Dqn_Str8Builder *dest, Dqn_Str8Builder const *src) +DN_API bool DN_Str8Builder_AppendBuilderCopy(DN_Str8Builder *dest, DN_Str8Builder const *src) { - bool result = Dqn_Str8Builder_AddBuilder_(dest, src, true); + bool result = DN_Str8Builder_AppendBuilder_(dest, src, true); return result; } -DQN_API bool Dqn_Str8Builder_Erase(Dqn_Str8Builder *builder, Dqn_Str8 string) +DN_API bool DN_Str8Builder_PrependRef(DN_Str8Builder *builder, DN_Str8 string) { - for (Dqn_Str8Link **it = &builder->head; *it; it = &((*it)->next)) { + bool result = DN_Str8Builder_AddArrayRef(builder, &string, 1, DN_Str8BuilderAdd_Prepend); + return result; +} + +DN_API bool DN_Str8Builder_PrependCopy(DN_Str8Builder *builder, DN_Str8 string) +{ + bool result = DN_Str8Builder_AddArrayCopy(builder, &string, 1, DN_Str8BuilderAdd_Prepend); + return result; +} + +DN_API bool DN_Str8Builder_PrependF(DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + bool result = DN_Str8Builder_PrependFV(builder, fmt, args); + va_end(args); + return result; +} + +DN_API bool DN_Str8Builder_Erase(DN_Str8Builder *builder, DN_Str8 string) +{ + for (DN_Str8Link **it = &builder->head; *it; it = &((*it)->next)) { if ((*it)->string == string) { *it = (*it)->next; builder->string_size -= string.size; @@ -940,136 +1049,136 @@ DQN_API bool Dqn_Str8Builder_Erase(Dqn_Str8Builder *builder, Dqn_Str8 string) return false; } -DQN_API Dqn_Str8Builder Dqn_Str8Builder_Copy(Dqn_Arena *arena, Dqn_Str8Builder const *builder) +DN_API DN_Str8Builder DN_Str8Builder_Copy(DN_Arena *arena, DN_Str8Builder const *builder) { - Dqn_Str8Builder result = Dqn_Str8Builder_Init(arena); - Dqn_Str8Builder_AddBuilderCopy(&result, builder); + DN_Str8Builder result = DN_Str8Builder_Init(arena); + DN_Str8Builder_AppendBuilderCopy(&result, builder); return result; } -DQN_API Dqn_Str8 Dqn_Str8Builder_Build(Dqn_Str8Builder const *builder, Dqn_Arena *arena) +DN_API DN_Str8 DN_Str8Builder_Build(DN_Str8Builder const *builder, DN_Arena *arena) { - Dqn_Str8 result = Dqn_Str8Builder_BuildDelimited(builder, DQN_STR8(""), arena); + DN_Str8 result = DN_Str8Builder_BuildDelimited(builder, DN_STR8(""), arena); return result; } -DQN_API Dqn_Str8 Dqn_Str8Builder_BuildDelimited(Dqn_Str8Builder const *builder, Dqn_Str8 delimiter, Dqn_Arena *arena) +DN_API DN_Str8 DN_Str8Builder_BuildDelimited(DN_Str8Builder const *builder, DN_Str8 delimiter, DN_Arena *arena) { - Dqn_Str8 result = DQN_ZERO_INIT; + DN_Str8 result = DN_ZERO_INIT; if (!builder || builder->string_size <= 0 || builder->count <= 0) return result; - Dqn_usize size_for_delimiter = Dqn_Str8_HasData(delimiter) ? ((builder->count - 1) * delimiter.size) : 0; - result.data = Dqn_Arena_NewArray(arena, + DN_USize size_for_delimiter = DN_Str8_HasData(delimiter) ? ((builder->count - 1) * delimiter.size) : 0; + result.data = DN_Arena_NewArray(arena, char, builder->string_size + size_for_delimiter + 1 /*null terminator*/, - Dqn_ZeroMem_No); + DN_ZeroMem_No); if (!result.data) return result; - for (Dqn_Str8Link *link = builder->head; link; link = link->next) { - DQN_MEMCPY(result.data + result.size, link->string.data, link->string.size); + 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; - if (link->next && Dqn_Str8_HasData(delimiter)) { - DQN_MEMCPY(result.data + result.size, delimiter.data, delimiter.size); + if (link->next && DN_Str8_HasData(delimiter)) { + DN_MEMCPY(result.data + result.size, delimiter.data, delimiter.size); result.size += delimiter.size; } } result.data[result.size] = 0; - DQN_ASSERT(result.size == builder->string_size + size_for_delimiter); + DN_ASSERT(result.size == builder->string_size + size_for_delimiter); return result; } -DQN_API Dqn_Str8 Dqn_Str8Builder_BuildCRT(Dqn_Str8Builder const *builder) +DN_API DN_Str8 DN_Str8Builder_BuildCRT(DN_Str8Builder const *builder) { - Dqn_Str8 result = DQN_ZERO_INIT; + DN_Str8 result = DN_ZERO_INIT; if (!builder || builder->string_size <= 0 || builder->count <= 0) return result; - result.data = DQN_CAST(char *)malloc(builder->string_size + 1); + result.data = DN_CAST(char *)malloc(builder->string_size + 1); if (!result.data) return result; - for (Dqn_Str8Link *link = builder->head; link; link = link->next) { - DQN_MEMCPY(result.data + result.size, link->string.data, link->string.size); + 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; - DQN_ASSERT(result.size == builder->string_size); + DN_ASSERT(result.size == builder->string_size); return result; } -DQN_API Dqn_Slice Dqn_Str8Builder_BuildSlice(Dqn_Str8Builder const *builder, Dqn_Arena *arena) +DN_API DN_Slice DN_Str8Builder_BuildSlice(DN_Str8Builder const *builder, DN_Arena *arena) { - Dqn_Slice result = DQN_ZERO_INIT; + DN_Slice result = DN_ZERO_INIT; if (!builder || builder->string_size <= 0 || builder->count <= 0) return result; - result = Dqn_Slice_Alloc(arena, builder->count, Dqn_ZeroMem_No); + result = DN_Slice_Alloc(arena, builder->count, DN_ZeroMem_No); if (!result.data) return result; - Dqn_usize slice_index = 0; - for (Dqn_Str8Link *link = builder->head; link; link = link->next) - result.data[slice_index++] = Dqn_Str8_Copy(arena, link->string); + DN_USize slice_index = 0; + for (DN_Str8Link *link = builder->head; link; link = link->next) + result.data[slice_index++] = DN_Str8_Copy(arena, link->string); - DQN_ASSERT(slice_index == builder->count); + DN_ASSERT(slice_index == builder->count); return result; } -DQN_API void Dqn_Str8Builder_Print(Dqn_Str8Builder const *builder) +DN_API void DN_Str8Builder_Print(DN_Str8Builder const *builder) { - for (Dqn_Str8Link *link = builder ? builder->head : nullptr; link; link = link->next) - Dqn_Print(link->string); + for (DN_Str8Link *link = builder ? builder->head : nullptr; link; link = link->next) + DN_Print(link->string); } -DQN_API void Dqn_Str8Builder_PrintLn(Dqn_Str8Builder const *builder) +DN_API void DN_Str8Builder_PrintLn(DN_Str8Builder const *builder) { - for (Dqn_Str8Link *link = builder ? builder->head : nullptr; link; link = link->next) { + for (DN_Str8Link *link = builder ? builder->head : nullptr; link; link = link->next) { if (link->next) { - Dqn_Print(link->string); + DN_Print(link->string); } else { - Dqn_Print_Ln(link->string); + DN_Print_Ln(link->string); } } } -// NOTE: [$CHAR] Dqn_Char ////////////////////////////////////////////////////////////////////////// -DQN_API bool Dqn_Char_IsAlphabet(char ch) +// NOTE: [$CHAR] DN_Char ////////////////////////////////////////////////////////////////////////// +DN_API bool DN_Char_IsAlphabet(char ch) { bool result = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); return result; } -DQN_API bool Dqn_Char_IsDigit(char ch) +DN_API bool DN_Char_IsDigit(char ch) { bool result = (ch >= '0' && ch <= '9'); return result; } -DQN_API bool Dqn_Char_IsAlphaNum(char ch) +DN_API bool DN_Char_IsAlphaNum(char ch) { - bool result = Dqn_Char_IsAlphabet(ch) || Dqn_Char_IsDigit(ch); + bool result = DN_Char_IsAlphabet(ch) || DN_Char_IsDigit(ch); return result; } -DQN_API bool Dqn_Char_IsWhitespace(char ch) +DN_API bool DN_Char_IsWhitespace(char ch) { bool result = (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); return result; } -DQN_API bool Dqn_Char_IsHex(char ch) +DN_API bool DN_Char_IsHex(char ch) { bool result = ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') || (ch >= '0' && ch <= '9')); return result; } -DQN_API Dqn_CharHexToU8 Dqn_Char_HexToU8(char ch) +DN_API DN_CharHexToU8 DN_Char_HexToU8(char ch) { - Dqn_CharHexToU8 result = {}; + DN_CharHexToU8 result = {}; result.success = true; if (ch >= 'a' && ch <= 'f') result.value = ch - 'a' + 10; @@ -1082,22 +1191,22 @@ DQN_API Dqn_CharHexToU8 Dqn_Char_HexToU8(char ch) return result; } -static char constexpr DQN_HEX_LUT[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; -DQN_API char Dqn_Char_ToHex(char ch) +static char constexpr DN_HEX_LUT[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; +DN_API char DN_Char_ToHex(char ch) { - char result = DQN_CAST(char)-1; + char result = DN_CAST(char)-1; if (ch < 16) - result = DQN_HEX_LUT[DQN_CAST(uint8_t)ch]; + result = DN_HEX_LUT[DN_CAST(uint8_t)ch]; return result; } -DQN_API char Dqn_Char_ToHexUnchecked(char ch) +DN_API char DN_Char_ToHexUnchecked(char ch) { - char result = DQN_HEX_LUT[DQN_CAST(uint8_t)ch]; + char result = DN_HEX_LUT[DN_CAST(uint8_t)ch]; return result; } -DQN_API char Dqn_Char_ToLower(char ch) +DN_API char DN_Char_ToLower(char ch) { char result = ch; if (result >= 'A' && result <= 'Z') @@ -1105,8 +1214,17 @@ DQN_API char Dqn_Char_ToLower(char ch) return result; } -// NOTE: [$UTFX] Dqn_UTF /////////////////////////////////////////////////////////////////////////// -DQN_API int Dqn_UTF8_EncodeCodepoint(uint8_t utf8[4], uint32_t codepoint) +DN_API char DN_Char_ToUpper(char ch) +{ + char result = ch; + if (result >= 'a' && result <= 'z') + result -= 'a' - 'A'; + return result; +} + + +// NOTE: [$UTFX] DN_UTF /////////////////////////////////////////////////////////////////////////// +DN_API int DN_UTF8_EncodeCodepoint(uint8_t utf8[4], uint32_t codepoint) { // NOTE: Table from https://www.reedbeta.com/blog/programmers-intro-to-unicode/ // ----------------------------------------+----------------------------+--------------------+ @@ -1119,7 +1237,7 @@ DQN_API int Dqn_UTF8_EncodeCodepoint(uint8_t utf8[4], uint32_t codepoint) // ----------------------------------------+----------------------------+--------------------+ if (codepoint <= 0b0111'1111) { - utf8[0] = DQN_CAST(uint8_t) codepoint; + utf8[0] = DN_CAST(uint8_t) codepoint; return 1; } @@ -1147,18 +1265,18 @@ DQN_API int Dqn_UTF8_EncodeCodepoint(uint8_t utf8[4], uint32_t codepoint) return 0; } -DQN_API int Dqn_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint) +DN_API int DN_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint) { // NOTE: Table from https://www.reedbeta.com/blog/programmers-intro-to-unicode/ // ----------------------------------------+------------------------------------+------------------+ // UTF-16 (binary) | Code point (binary) | Range | // ----------------------------------------+------------------------------------+------------------+ - // xxxx'xxxx'xxxx'xxxx | xxxx'xxxx'xxxx'xxxx | U+0000–U+FFFF | - // 1101'10xx'xxxx'xxxx 1101'11yy'yyyy'yyyy | xxxx'xxxx'xxyy'yyyy'yyyy + 0x10000 | U+10000–U+10FFFF | + // xxxx'xxxx'xxxx'xxxx | xxxx'xxxx'xxxx'xxxx | U+0000???U+FFFF | + // 1101'10xx'xxxx'xxxx 1101'11yy'yyyy'yyyy | xxxx'xxxx'xxyy'yyyy'yyyy + 0x10000 | U+10000???U+10FFFF | // ----------------------------------------+------------------------------------+------------------+ if (codepoint <= 0b1111'1111'1111'1111) { - utf16[0] = DQN_CAST(uint16_t) codepoint; + utf16[0] = DN_CAST(uint16_t) codepoint; return 1; } diff --git a/dqn_string.h b/dqn_string.h index c27f026..2307e3c 100644 --- a/dqn_string.h +++ b/dqn_string.h @@ -17,27 +17,28 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // -// [$CSTR] Dqn_CStr8 -- C-string helpers -// [$STR8] Dqn_Str8 -- Pointer and length strings -// [$STRB] Dqn_Str8Builder -- Construct strings dynamically -// [$FSTR] Dqn_FStr8 -- Fixed-size strings -// [$CHAR] Dqn_Char -- Character ascii/digit.. helpers -// [$UTFX] Dqn_UTF -- Unicode helpers +// [$CSTR] DN_CStr8 -- C-string helpers +// [$STR8] DN_Str8 -- Pointer and length strings +// [$STRB] DN_Str8Builder -- Construct strings dynamically +// [$FSTR] DN_FStr8 -- Fixed-size strings +// [$CHAR] DN_Char -- Character ascii/digit.. helpers +// [$UTFX] DN_UTF -- Unicode helpers // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$STR8] Dqn_Str8 ////////////////////////////////////////////////////////////////////////// -struct Dqn_Str8Link +// NOTE: [$STR8] DN_Str8 ////////////////////////////////////////////////////////////////////////// +struct DN_Str8Link { - Dqn_Str8 string; // The string - Dqn_Str8Link *next; // The next string in the linked list + DN_Str8 string; // The string + DN_Str8Link *next; // The next string in the linked list + DN_Str8Link *prev; // The prev string in the linked list }; -struct Dqn_Str16 // A pointer and length style string that holds slices to UTF16 bytes. +struct DN_Str16 // A pointer and length style string that holds slices to UTF16 bytes. { wchar_t *data; // The UTF16 bytes of the string - Dqn_usize size; // The number of characters in the string + DN_USize size; // The number of characters in the string #if defined(__cplusplus) wchar_t const *begin() const { return data; } // Const begin iterator for range-for loops @@ -47,417 +48,490 @@ struct Dqn_Str16 // A pointer and length style string that holds slices to UTF16 #endif }; -struct Dqn_Str8BinarySplitResult +struct DN_Str8BinarySplitResult { - Dqn_Str8 lhs; - Dqn_Str8 rhs; + DN_Str8 lhs; + DN_Str8 rhs; }; -struct Dqn_Str8FindResult +struct DN_Str8FindResult { - bool found; // True if string was found. If false, the subsequent fields below are not set. - Dqn_usize index; // The index in the buffer where the found string starts - Dqn_Str8 match; // The matching string in the buffer that was searched - Dqn_Str8 match_to_end_of_buffer; // The substring containing the found string to the end of the buffer - Dqn_Str8 start_to_before_match; // The substring from the start of the buffer up until the found string, not including it + bool found; // True if string was found. If false, the subsequent fields below are not set. + DN_USize index; // Index in the buffer where the found string starts + DN_Str8 match; // Matching string in the buffer that was searched + DN_Str8 match_to_end_of_buffer; // Substring containing the found string to the end of the buffer + DN_Str8 after_match_to_end_of_buffer; // Substring starting after the found string to the end of the buffer + DN_Str8 start_to_before_match; // Substring from the start of the buffer up until the found string, not including it }; -enum Dqn_Str8IsAll +enum DN_Str8IsAll { - Dqn_Str8IsAll_Digits, - Dqn_Str8IsAll_Hex, + DN_Str8IsAll_Digits, + DN_Str8IsAll_Hex, }; -enum Dqn_Str8EqCase +enum DN_Str8EqCase { - Dqn_Str8EqCase_Sensitive, - Dqn_Str8EqCase_Insensitive, + DN_Str8EqCase_Sensitive, + DN_Str8EqCase_Insensitive, }; -enum Dqn_Str8FindFlag +enum DN_Str8FindFlag { - Dqn_Str8FindFlag_Digit = 1 << 0, // 0-9 - Dqn_Str8FindFlag_Whitespace = 1 << 1, // '\r', '\t', '\n', ' ' - Dqn_Str8FindFlag_Alphabet = 1 << 2, // A-Z, a-z - Dqn_Str8FindFlag_Plus = 1 << 3, // + - Dqn_Str8FindFlag_Minus = 1 << 4, // - - Dqn_Str8FindFlag_AlphaNum = Dqn_Str8FindFlag_Alphabet | Dqn_Str8FindFlag_Digit, + DN_Str8FindFlag_Digit = 1 << 0, // 0-9 + DN_Str8FindFlag_Whitespace = 1 << 1, // '\r', '\t', '\n', ' ' + DN_Str8FindFlag_Alphabet = 1 << 2, // A-Z, a-z + DN_Str8FindFlag_Plus = 1 << 3, // + + DN_Str8FindFlag_Minus = 1 << 4, // - + DN_Str8FindFlag_AlphaNum = DN_Str8FindFlag_Alphabet | DN_Str8FindFlag_Digit, }; -enum Dqn_Str8SplitIncludeEmptyStrings +enum DN_Str8SplitIncludeEmptyStrings { - Dqn_Str8SplitIncludeEmptyStrings_No, - Dqn_Str8SplitIncludeEmptyStrings_Yes, + DN_Str8SplitIncludeEmptyStrings_No, + DN_Str8SplitIncludeEmptyStrings_Yes, }; -struct Dqn_Str8ToU64Result +struct DN_Str8ToU64Result { bool success; uint64_t value; }; -struct Dqn_Str8ToI64Result +struct DN_Str8ToI64Result { bool success; int64_t value; }; -// NOTE: [$FSTR] Dqn_FStr8 ///////////////////////////////////////////////////////////////////////// -#if !defined(DQN_NO_FSTR8) -template struct Dqn_FStr8 +struct DN_Str8DotTruncateResult +{ + bool truncated; + DN_Str8 str8; +}; + +// NOTE: [$FSTR] DN_FStr8 ///////////////////////////////////////////////////////////////////////// +#if !defined(DN_NO_FSTR8) +template struct DN_FStr8 { char data[N+1]; - Dqn_usize size; + DN_USize size; char *begin() { return data; } char *end () { return data + size; } char const *begin() const { return data; } char const *end () const { return data + size; } }; -#endif // !defined(DQN_NO_FSTR8) +#endif // !defined(DN_NO_FSTR8) -struct Dqn_Str8Builder +struct DN_Str8Builder { - Dqn_Arena *arena; // Allocator to use to back the string list - Dqn_Str8Link *head; // First string in the linked list of strings - Dqn_Str8Link *tail; // Last string in the linked list of strings - Dqn_usize string_size; // The size in bytes necessary to construct the current string - Dqn_usize count; // The number of links in the linked list of strings + DN_Arena *arena; // Allocator to use to back the string list + DN_Str8Link *head; // First string in the linked list of strings + DN_Str8Link *tail; // Last string in the linked list of strings + DN_USize string_size; // The size in bytes necessary to construct the current string + DN_USize count; // The number of links in the linked list of strings }; -// NOTE: [$CSTR] Dqn_CStr8 ///////////////////////////////////////////////////////////////////////// -template constexpr Dqn_usize Dqn_CStr8_ArrayUCount (char const (&literal)[N]) { (void)literal; return N - 1; } -template constexpr Dqn_usize Dqn_CStr8_ArrayICount (char const (&literal)[N]) { (void)literal; return N - 1; } -DQN_API Dqn_usize Dqn_CStr8_FSize (DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API Dqn_usize Dqn_CStr8_FVSize (DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API Dqn_usize Dqn_CStr8_Size (char const *a); -DQN_API Dqn_usize Dqn_CStr16_Size (wchar_t const *a); +enum DN_Str8BuilderAdd +{ + DN_Str8BuilderAdd_Append, + DN_Str8BuilderAdd_Prepend, +}; -// NOTE: [$STR6] Dqn_Str16 ///////////////////////////////////////////////////////////////////////// -#define DQN_STR16(string) Dqn_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1} -#define Dqn_Str16_HasData(string) ((string).data && (string).size) +// NOTE: [$CSTR] DN_CStr8 ///////////////////////////////////////////////////////////////////////// +template constexpr DN_USize DN_CStr8_ArrayUCount (char const (&literal)[N]) { (void)literal; return N - 1; } +template constexpr DN_USize DN_CStr8_ArrayICount (char const (&literal)[N]) { (void)literal; return N - 1; } +DN_API DN_USize DN_CStr8_FSize (DN_FMT_ATTRIB char const *fmt, ...); +DN_API DN_USize DN_CStr8_FVSize (DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_USize DN_CStr8_Size (char const *a); +DN_API DN_USize DN_CStr16_Size (wchar_t const *a); + +// NOTE: [$STR6] DN_Str16 ///////////////////////////////////////////////////////////////////////// +#define DN_STR16(string) DN_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1} +#define DN_Str16_HasData(string) ((string).data && (string).size) #if defined(__cplusplus) -DQN_API bool operator== (Dqn_Str16 const &lhs, Dqn_Str16 const &rhs); -DQN_API bool operator!= (Dqn_Str16 const &lhs, Dqn_Str16 const &rhs); +DN_API bool operator== (DN_Str16 const &lhs, DN_Str16 const &rhs); +DN_API bool operator!= (DN_Str16 const &lhs, DN_Str16 const &rhs); #endif -// NOTE: [$STR8] Dqn_Str8 ////////////////////////////////////////////////////////////////////////// -#define DQN_STR8(string) Dqn_Str8{(char *)(string), (sizeof(string) - 1)} -#define DQN_STR_FMT(string) (int)((string).size), (string).data -#define Dqn_Str8_Init(data, size) Dqn_Str8{(char *)(data), (size_t)(size)} +// NOTE: [$STR8] DN_Str8 ////////////////////////////////////////////////////////////////////////// +#define DN_STR8(string) DN_Str8{(char *)(string), (sizeof(string) - 1)} +#define DN_STR_FMT(string) (int)((string).size), (string).data +#define DN_Str8_Init(data, size) DN_Str8{(char *)(data), (size_t)(size)} -DQN_API Dqn_Str8 Dqn_Str8_InitCStr8 (char const *src); -#define Dqn_Str8_HasData(string) ((string).data && (string).size) -DQN_API bool Dqn_Str8_IsAll (Dqn_Str8 string, Dqn_Str8IsAll is_all); +DN_API DN_Str8 DN_Str8_InitCStr8 (char const *src); +#define DN_Str8_HasData(string) ((string).data && (string).size) +DN_API bool DN_Str8_IsAll (DN_Str8 string, DN_Str8IsAll is_all); -DQN_API Dqn_Str8 Dqn_Str8_InitF (Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...); -#define Dqn_Str8_InitF_TLS(...) Dqn_Str8_InitF(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_Str8_InitFV (Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args); -#define Dqn_Str8_InitFV_TLS(...) Dqn_Str8_InitFV(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_Str8_Alloc (Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem); -#define Dqn_Str8_Alloc_TLS(...) Dqn_Str8_Alloc(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_Str8_CopyCString (Dqn_Arena *arena, char const *string, Dqn_usize size); -#define Dqn_Str8_CopyCString_TLS(...) Dqn_Str8_CopyCString(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_Str8_Copy (Dqn_Arena *arena, Dqn_Str8 string); -#define Dqn_Str8_Copy_TLS(...) Dqn_Str8_Copy(Dqn_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8_InitF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); +#define DN_Str8_InitF_TLS(...) DN_Str8_InitF(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_Str8_InitF_Frame(...) DN_Str8_InitF(DN_TLS_FrameArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8_InitFV (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args); +#define DN_Str8_InitFV_TLS(...) DN_Str8_InitFV(DN_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8_Alloc (DN_Arena *arena, DN_USize size, DN_ZeroMem zero_mem); +#define DN_Str8_Alloc_TLS(...) DN_Str8_Alloc(DN_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8_CopyCString (DN_Arena *arena, char const *string, DN_USize size); +#define DN_Str8_CopyCString_TLS(...) DN_Str8_CopyCString(DN_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8_Copy (DN_Arena *arena, DN_Str8 string); +#define DN_Str8_Copy_TLS(...) DN_Str8_Copy(DN_TLS_TopArena(), ##__VA_ARGS__) +#define DN_Str8_Copy_Frame(...) DN_Str8_Copy(DN_TLS_FrameArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_Str8_Slice (Dqn_Str8 string, Dqn_usize offset, Dqn_usize size); -DQN_API Dqn_Str8 Dqn_Str8_Advance (Dqn_Str8 string, Dqn_usize amount); -DQN_API Dqn_Str8 Dqn_Str8_NextLine (Dqn_Str8 string); -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size); -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplit (Dqn_Str8 string, Dqn_Str8 find); -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size); -DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLast (Dqn_Str8 string, Dqn_Str8 find); -DQN_API Dqn_usize Dqn_Str8_Split (Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8 *splits, Dqn_usize splits_count, Dqn_Str8SplitIncludeEmptyStrings mode); -DQN_API Dqn_Slice Dqn_Str8_SplitAlloc (Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8SplitIncludeEmptyStrings mode); -#define Dqn_Str8_SplitAlloc_TLS(...) Dqn_Str8_SplitAlloc(Dqn_TLS_TopArena(), ##__VA_ARGS__) +DN_API char * DN_Str8_End (DN_Str8 string); +DN_API DN_Str8 DN_Str8_Slice (DN_Str8 string, DN_USize offset, DN_USize size); +DN_API DN_Str8 DN_Str8_Advance (DN_Str8 string, DN_USize amount); +DN_API DN_Str8 DN_Str8_NextLine (DN_Str8 string); +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplit (DN_Str8 string, DN_Str8 find); +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); +DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLast (DN_Str8 string, DN_Str8 find); +DN_API DN_USize DN_Str8_Split (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode); +DN_API DN_Slice DN_Str8_SplitAlloc (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode); +#define DN_Str8_SplitAlloc_TLS(...) DN_Str8_SplitAlloc(DN_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8Array (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size, Dqn_Str8EqCase eq_case); -DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8 (Dqn_Str8 string, Dqn_Str8 find, Dqn_Str8EqCase eq_case); -DQN_API Dqn_Str8FindResult Dqn_Str8_Find (Dqn_Str8 string, uint32_t flags); -DQN_API Dqn_Str8 Dqn_Str8_Segment (Dqn_Arena *arena, Dqn_Str8 src, Dqn_usize segment_size, char segment_char); -#define Dqn_Str8_Segment_TLS(...) Dqn_Str8_Segment(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_Str8_ReverseSegment (Dqn_Arena *arena, Dqn_Str8 src, Dqn_usize segment_size, char segment_char); -#define Dqn_Str8_ReverseSegment_TLS(...) Dqn_Str8_ReverseSegment(Dqn_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8FindResult DN_Str8_FindStr8Array (DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case); +DN_API DN_Str8FindResult DN_Str8_FindStr8 (DN_Str8 string, DN_Str8 find, DN_Str8EqCase eq_case); +DN_API DN_Str8FindResult DN_Str8_Find (DN_Str8 string, uint32_t flags); +DN_API DN_Str8 DN_Str8_Segment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char); +#define DN_Str8_Segment_TLS(...) DN_Str8_Segment(DN_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8_ReverseSegment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char); +#define DN_Str8_ReverseSegment_TLS(...) DN_Str8_ReverseSegment(DN_TLS_TopArena(), ##__VA_ARGS__) -DQN_API bool Dqn_Str8_Eq (Dqn_Str8 lhs, Dqn_Str8 rhs, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); -DQN_API bool Dqn_Str8_EqInsensitive (Dqn_Str8 lhs, Dqn_Str8 rhs); -DQN_API bool Dqn_Str8_StartsWith (Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); -DQN_API bool Dqn_Str8_StartsWithInsensitive (Dqn_Str8 string, Dqn_Str8 prefix); -DQN_API bool Dqn_Str8_EndsWith (Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); -DQN_API bool Dqn_Str8_EndsWithInsensitive (Dqn_Str8 string, Dqn_Str8 prefix); -DQN_API bool Dqn_Str8_HasChar (Dqn_Str8 string, char ch); +DN_API bool DN_Str8_Eq (DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API bool DN_Str8_EqInsensitive (DN_Str8 lhs, DN_Str8 rhs); +DN_API bool DN_Str8_StartsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API bool DN_Str8_StartsWithInsensitive (DN_Str8 string, DN_Str8 prefix); +DN_API bool DN_Str8_EndsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API bool DN_Str8_EndsWithInsensitive (DN_Str8 string, DN_Str8 prefix); +DN_API bool DN_Str8_HasChar (DN_Str8 string, char ch); -DQN_API Dqn_Str8 Dqn_Str8_TrimPrefix (Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); -DQN_API Dqn_Str8 Dqn_Str8_TrimHexPrefix (Dqn_Str8 string); -DQN_API Dqn_Str8 Dqn_Str8_TrimSuffix (Dqn_Str8 string, Dqn_Str8 suffix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); -DQN_API Dqn_Str8 Dqn_Str8_TrimAround (Dqn_Str8 string, Dqn_Str8 trim_string); -DQN_API Dqn_Str8 Dqn_Str8_TrimWhitespaceAround (Dqn_Str8 string); -DQN_API Dqn_Str8 Dqn_Str8_TrimByteOrderMark (Dqn_Str8 string); +DN_API DN_Str8 DN_Str8_TrimPrefix (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API DN_Str8 DN_Str8_TrimHexPrefix (DN_Str8 string); +DN_API DN_Str8 DN_Str8_TrimSuffix (DN_Str8 string, DN_Str8 suffix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive); +DN_API DN_Str8 DN_Str8_TrimAround (DN_Str8 string, DN_Str8 trim_string); +DN_API DN_Str8 DN_Str8_TrimWhitespaceAround (DN_Str8 string); +DN_API DN_Str8 DN_Str8_TrimByteOrderMark (DN_Str8 string); -DQN_API Dqn_Str8 Dqn_Str8_FileNameFromPath (Dqn_Str8 path); -DQN_API Dqn_Str8 Dqn_Str8_FileNameNoExtension (Dqn_Str8 path); -DQN_API Dqn_Str8 Dqn_Str8_FilePathNoExtension (Dqn_Str8 path); -DQN_API Dqn_Str8 Dqn_Str8_FileExtension (Dqn_Str8 path); +DN_API DN_Str8 DN_Str8_FileNameFromPath (DN_Str8 path); +DN_API DN_Str8 DN_Str8_FileNameNoExtension (DN_Str8 path); +DN_API DN_Str8 DN_Str8_FilePathNoExtension (DN_Str8 path); +DN_API DN_Str8 DN_Str8_FileExtension (DN_Str8 path); -DQN_API Dqn_Str8ToU64Result Dqn_Str8_ToU64 (Dqn_Str8 string, char separator); -DQN_API Dqn_Str8ToI64Result Dqn_Str8_ToI64 (Dqn_Str8 string, char separator); +DN_API DN_Str8ToU64Result DN_Str8_ToU64 (DN_Str8 string, char separator); +DN_API DN_Str8ToI64Result DN_Str8_ToI64 (DN_Str8 string, char separator); -DQN_API Dqn_Str8 Dqn_Str8_Replace (Dqn_Str8 string, Dqn_Str8 find, Dqn_Str8 replace, Dqn_usize start_index, Dqn_Arena *arena, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); -DQN_API Dqn_Str8 Dqn_Str8_ReplaceInsensitive (Dqn_Str8 string, Dqn_Str8 find, Dqn_Str8 replace, Dqn_usize start_index, Dqn_Arena *arena); -DQN_API void Dqn_Str8_Remove (Dqn_Str8 *string, Dqn_usize offset, Dqn_usize size); +#define DN_Str8_AppendF_TLS(...) DN_Str8_AppendF(DN_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8_AppendF (DN_Arena *arena, DN_Str8 string, char const *fmt, ...); +DN_API DN_Str8 DN_Str8_FillF (DN_Arena *arena, DN_USize count, char const *fmt, ...); +#define DN_Str8_FillF_TLS(count, ...) DN_Str8_FillF(DN_TLS_TopArena(), count, ##__VA_ARGS__) +#define DN_Str8_FillF_Frame(count, ...) DN_Str8_FillF(DN_TLS_FrameArena(), count, ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8_Replace (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_Str8_ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena); +DN_API void DN_Str8_Remove (DN_Str8 *string, DN_USize offset, DN_USize size); +DN_API DN_Str8DotTruncateResult DN_Str8_DotTruncateMiddle (DN_Arena *arena, DN_Str8 str8, uint32_t side_size, DN_Str8 truncator); +#define DN_Str8_DotTruncateMiddle_Frame(...) DN_Str8_DotTruncateMiddle(DN_TLS_FrameArena(), ## __VA_ARGS__) +DN_API DN_Str8 DN_Str8_PadNewLines(DN_Arena *arena, DN_Str8 src, DN_Str8 pad); +#define DN_Str8_PadNewLines_TLS(src, pad) DN_Str8_PadNewLines(DN_TLS_TopArena(), src, pad) + + +#define DN_Str8_Lower_TLS(...) DN_Str8_Lower(DN_TLS_TopArena(), __VA_ARGS__) +DN_API DN_Str8 DN_Str8_Lower (DN_Arena *arena, DN_Str8 string); +#define DN_Str8_Upper_TLS(...) DN_Str8_Upper(DN_TLS_TopArena(), __VA_ARGS__) +DN_API DN_Str8 DN_Str8_Upper (DN_Arena *arena, DN_Str8 string); #if defined(__cplusplus) -DQN_API bool operator== (Dqn_Str8 const &lhs, Dqn_Str8 const &rhs); -DQN_API bool operator!= (Dqn_Str8 const &lhs, Dqn_Str8 const &rhs); +DN_API bool operator== (DN_Str8 const &lhs, DN_Str8 const &rhs); +DN_API bool operator!= (DN_Str8 const &lhs, DN_Str8 const &rhs); #endif -// NOTE: [$STRB] Dqn_Str8Builder /////////////////////////////////////////////////////////////////// -DQN_API Dqn_Str8Builder Dqn_Str8Builder_Init (Dqn_Arena *arena); -#define Dqn_Str8Builder_Init_TLS() Dqn_Str8Builder_Init(Dqn_TLS_TopArena()) -DQN_API Dqn_Str8Builder Dqn_Str8Builder_InitArrayRef (Dqn_Arena *arena, Dqn_Str8 const *strings, Dqn_usize size); -#define Dqn_Str8Builder_InitArrayRef_TLS(...) Dqn_Str8Builder_InitArrayRef(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8Builder Dqn_Str8Builder_InitArrayCopy (Dqn_Arena *arena, Dqn_Str8 const *strings, Dqn_usize size); -#define Dqn_Str8Builder_InitArrayCopy_TLS(...) Dqn_Str8Builder_InitArrayCopy(Dqn_TLS_TopArena(), ##__VA_ARGS__) -template Dqn_Str8Builder Dqn_Str8Builder_InitCArrayRef (Dqn_Arena *arena, Dqn_Str8 const (&array)[N]); -#define Dqn_Str8Builder_InitCArrayRef_TLS(...) Dqn_Str8Builder_InitCArrayRef(Dqn_TLS_TopArena(), ##__VA_ARGS__) -template Dqn_Str8Builder Dqn_Str8Builder_InitCArrayCopy (Dqn_Arena *arena, Dqn_Str8 const (&array)[N]); -#define Dqn_Str8Builder_InitCArrayCopy_TLS(...) Dqn_Str8Builder_InitCArrayCopy(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API bool Dqn_Str8Builder_AddArrayRef (Dqn_Str8Builder *builder, Dqn_Str8 const *strings, Dqn_usize size); -DQN_API bool Dqn_Str8Builder_AddArrayCopy (Dqn_Str8Builder *builder, Dqn_Str8 const *strings, Dqn_usize size); -template bool Dqn_Str8Builder_AddCArrayRef (Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]); -template bool Dqn_Str8Builder_AddCArrayCopy (Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]); -DQN_API bool Dqn_Str8Builder_AddSliceRef (Dqn_Str8Builder *builder, Dqn_Slice string); -DQN_API bool Dqn_Str8Builder_AddSliceCopy (Dqn_Str8Builder *builder, Dqn_Slice string); -DQN_API bool Dqn_Str8Builder_AddRef (Dqn_Str8Builder *builder, Dqn_Str8 string); -DQN_API bool Dqn_Str8Builder_AddCopy (Dqn_Str8Builder *builder, Dqn_Str8 string); -DQN_API bool Dqn_Str8Builder_AddFV (Dqn_Str8Builder *builder, DQN_FMT_ATTRIB char const *fmt, va_list args); -DQN_API bool Dqn_Str8Builder_AddF (Dqn_Str8Builder *builder, DQN_FMT_ATTRIB char const *fmt, ...); -DQN_API bool Dqn_Str8Builder_AddBytesRef (Dqn_Str8Builder *builder, void const *ptr, Dqn_usize size); -DQN_API bool Dqn_Str8Builder_AddBytesCopy (Dqn_Str8Builder *builder, void const *ptr, Dqn_usize size); -DQN_API bool Dqn_Str8Builder_AddBuilderRef (Dqn_Str8Builder *dest, Dqn_Str8Builder const *src); -DQN_API bool Dqn_Str8Builder_AddBuilderCopy (Dqn_Str8Builder *dest, Dqn_Str8Builder const *src); -DQN_API bool Dqn_Str8Builder_Erase (Dqn_Str8Builder *builder, Dqn_Str8 string); -DQN_API Dqn_Str8Builder Dqn_Str8Builder_Copy (Dqn_Arena *arena, Dqn_Str8Builder const *builder); -#define Dqn_Str8Builder_Copy_TLS(...) Dqn_Str8Builder_Copy(Dqn_TLS_TopArena(), ##__VA_ARGS__) -DQN_API Dqn_Str8 Dqn_Str8Builder_Build (Dqn_Str8Builder const *builder, Dqn_Arena *arena); -#define Dqn_Str8Builder_Build_TLS(...) Dqn_Str8Builder_Build(__VA_ARGS__, Dqn_TLS_TopArena()) -DQN_API Dqn_Str8 Dqn_Str8Builder_BuildDelimited (Dqn_Str8Builder const *builder, Dqn_Str8 delimiter, Dqn_Arena *arena); -#define Dqn_Str8Builder_BuildDelimited_TLS(...) Dqn_Str8Builder_BuildDelimited(__VA_ARGS__, Dqn_TLS_TopArena()) -DQN_API Dqn_Str8 Dqn_Str8Builder_BuildCRT (Dqn_Str8Builder const *builder); -DQN_API Dqn_Slice Dqn_Str8Builder_BuildSlice (Dqn_Str8Builder const *builder, Dqn_Arena *arena); -#define Dqn_Str8Builder_BuildSlice_TLS(...) Dqn_Str8Builder_BuildSlice(__VA_ARGS__, Dqn_TLS_TopArena()) -DQN_API void Dqn_Str8Builder_Print (Dqn_Str8Builder const *builder); -DQN_API void Dqn_Str8Builder_PrintLn (Dqn_Str8Builder const *builder); +// NOTE: [$STRB] DN_Str8Builder /////////////////////////////////////////////////////////////////// +DN_API DN_Str8Builder DN_Str8Builder_Init (DN_Arena *arena); +DN_API DN_Str8Builder DN_Str8Builder_Init_Frame () { return DN_Str8Builder_Init(DN_TLS_Get()->frame_arena); } +#define DN_Str8Builder_Init_TLS() DN_Str8Builder_Init(DN_TLS_TopArena()) +DN_API DN_Str8Builder DN_Str8Builder_InitArrayRef (DN_Arena *arena, DN_Str8 const *strings, DN_USize size); +DN_API DN_Str8Builder DN_Str8Builder_InitArrayRef_Frame (DN_Str8 const *strings, DN_USize size) { return DN_Str8Builder_InitArrayRef(DN_TLS_Get()->frame_arena, strings, size); } +#define DN_Str8Builder_InitArrayRef_TLS(...) DN_Str8Builder_InitArrayRef(DN_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8Builder DN_Str8Builder_InitArrayCopy (DN_Arena *arena, DN_Str8 const *strings, DN_USize size); +DN_API DN_Str8Builder DN_Str8Builder_InitArrayCopy_Frame (DN_Str8 const *strings, DN_USize size) { return DN_Str8Builder_InitArrayCopy(DN_TLS_Get()->frame_arena, strings, size); } +#define DN_Str8Builder_InitArrayCopy_TLS(...) DN_Str8Builder_InitArrayCopy(DN_TLS_TopArena(), ##__VA_ARGS__) +template DN_Str8Builder DN_Str8Builder_InitCArrayRef (DN_Arena *arena, DN_Str8 const (&array)[N]); +template DN_Str8Builder DN_Str8Builder_InitCArrayRef_Frame (DN_Str8 const (&array)[N]) { return DN_Str8Builder_InitCArrayRef(DN_TLS_Get()->frame_arena, array); } +#define DN_Str8Builder_InitCArrayRef_TLS(...) DN_Str8Builder_InitCArrayRef(DN_TLS_TopArena(), ##__VA_ARGS__) +template DN_Str8Builder DN_Str8Builder_InitCArrayCopy (DN_Arena *arena, DN_Str8 const (&array)[N]); +template DN_Str8Builder DN_Str8Builder_InitCArrayCopy_Frame (DN_Str8 const (&array)[N]) { return DN_Str8Builder_InitCArrayCopy(DN_TLS_Get()->frame_arena, array); } +#define DN_Str8Builder_InitCArrayCopy_TLS(...) DN_Str8Builder_InitCArrayCopy(DN_TLS_TopArena(), ##__VA_ARGS__) -// NOTE: [$FSTR] Dqn_FStr8 ////////////////////////////////////////////////////////////////////// -#if !defined(DQN_NO_FSTR8) -template Dqn_FStr8 Dqn_FStr8_InitF (DQN_FMT_ATTRIB char const *fmt, ...); -template Dqn_usize Dqn_FStr8_Max (Dqn_FStr8 const *string); -template void Dqn_FStr8_Clear (Dqn_FStr8 *string); -template bool Dqn_FStr8_AddFV (Dqn_FStr8 *string, DQN_FMT_ATTRIB char const *fmt, va_list va); -template bool Dqn_FStr8_AddF (Dqn_FStr8 *string, DQN_FMT_ATTRIB char const *fmt, ...); -template bool Dqn_FStr8_AddCStr8 (Dqn_FStr8 *string, char const *value, Dqn_usize size); -template bool Dqn_FStr8_Add (Dqn_FStr8 *string, Dqn_Str8 value); -template Dqn_Str8 Dqn_FStr8_ToStr8 (Dqn_FStr8 const *string); -template bool Dqn_FStr8_Eq (Dqn_FStr8 const *lhs, Dqn_FStr8 const *rhs, Dqn_Str8EqCase eq_case); -template bool Dqn_FStr8_EqStr8 (Dqn_FStr8 const *lhs, Dqn_Str8 rhs, Dqn_Str8EqCase eq_case); -template bool Dqn_FStr8_EqInsensitive (Dqn_FStr8 const *lhs, Dqn_FStr8 const *rhs); -template bool Dqn_FStr8_EqStr8Insensitive (Dqn_FStr8 const *lhs, Dqn_Str8 rhs); -template bool Dqn_FStr8_EqFStr8 (Dqn_FStr8 const *lhs, Dqn_FStr8 const *rhs, Dqn_Str8EqCase eq_case); -template bool Dqn_FStr8_EqFStr8Insensitive (Dqn_FStr8 const *lhs, Dqn_FStr8 const *rhs); -template bool operator== (Dqn_FStr8 const &lhs, Dqn_FStr8 const &rhs); -template bool operator!= (Dqn_FStr8 const &lhs, Dqn_FStr8 const &rhs); -#endif // !defined(DQN_NO_FSTR8) +DN_API bool DN_Str8Builder_AddArrayRef (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add); +DN_API bool DN_Str8Builder_AddArrayCopy (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add); +DN_API bool DN_Str8Builder_AddFV (DN_Str8Builder *builder, DN_Str8BuilderAdd add, DN_FMT_ATTRIB char const *fmt, va_list args); -// NOTE: [$CHAR] Dqn_Char ////////////////////////////////////////////////////////////////////////// -struct Dqn_CharHexToU8 +#define DN_Str8Builder_AppendArrayRef(builder, strings, size) DN_Str8Builder_AddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Append) +#define DN_Str8Builder_AppendArrayCopy(builder, strings, size) DN_Str8Builder_AddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Append) +#define DN_Str8Builder_AppendSliceRef(builder, slice) DN_Str8Builder_AddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append) +#define DN_Str8Builder_AppendSliceCopy(builder, slice) DN_Str8Builder_AddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append) +DN_API bool DN_Str8Builder_AppendRef (DN_Str8Builder *builder, DN_Str8 string); +DN_API bool DN_Str8Builder_AppendCopy (DN_Str8Builder *builder, DN_Str8 string); +#define DN_Str8Builder_AppendFV(builder, fmt, args) DN_Str8Builder_AddFV(builder, DN_Str8BuilderAdd_Append, fmt, args) +DN_API bool DN_Str8Builder_AppendF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_Str8Builder_AppendBytesRef (DN_Str8Builder *builder, void const *ptr, DN_USize size); +DN_API bool DN_Str8Builder_AppendBytesCopy (DN_Str8Builder *builder, void const *ptr, DN_USize size); +DN_API bool DN_Str8Builder_AppendBuilderRef (DN_Str8Builder *dest, DN_Str8Builder const *src); +DN_API bool DN_Str8Builder_AppendBuilderCopy (DN_Str8Builder *dest, DN_Str8Builder const *src); + +#define DN_Str8Builder_PrependArrayRef(builder, strings, size) DN_Str8Builder_AddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Prepend) +#define DN_Str8Builder_PrependArrayCopy(builder, strings, size) DN_Str8Builder_AddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Prepend) +#define DN_Str8Builder_PrependSliceRef(builder, slice) DN_Str8Builder_AddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Prepend) +#define DN_Str8Builder_PrependSliceCopy(builder, slice) DN_Str8Builder_AddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Prepend) +DN_API bool DN_Str8Builder_PrependRef (DN_Str8Builder *builder, DN_Str8 string); +DN_API bool DN_Str8Builder_PrependCopy (DN_Str8Builder *builder, DN_Str8 string); +#define DN_Str8Builder_PrependFV(builder, fmt, args) DN_Str8Builder_AddFV(builder, DN_Str8BuilderAdd_Prepend, fmt, args) +DN_API bool DN_Str8Builder_PrependF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...); + +DN_API bool DN_Str8Builder_Erase (DN_Str8Builder *builder, DN_Str8 string); +DN_API DN_Str8Builder DN_Str8Builder_Copy (DN_Arena *arena, DN_Str8Builder const *builder); +#define DN_Str8Builder_Copy_TLS(...) DN_Str8Builder_Copy(DN_TLS_TopArena(), ##__VA_ARGS__) +DN_API DN_Str8 DN_Str8Builder_Build (DN_Str8Builder const *builder, DN_Arena *arena); +#define DN_Str8Builder_Build_TLS(...) DN_Str8Builder_Build(__VA_ARGS__, DN_TLS_TopArena()) +#define DN_Str8Builder_Build_Frame(...) DN_Str8Builder_Build(__VA_ARGS__, DN_TLS_FrameArena()) +DN_API DN_Str8 DN_Str8Builder_BuildDelimited (DN_Str8Builder const *builder, DN_Str8 delimiter, DN_Arena *arena); +#define DN_Str8Builder_BuildDelimited_TLS(...) DN_Str8Builder_BuildDelimited(__VA_ARGS__, DN_TLS_TopArena()) +DN_API DN_Str8 DN_Str8Builder_BuildCRT (DN_Str8Builder const *builder); +DN_API DN_Slice DN_Str8Builder_BuildSlice (DN_Str8Builder const *builder, DN_Arena *arena); +#define DN_Str8Builder_BuildSlice_TLS(...) DN_Str8Builder_BuildSlice(__VA_ARGS__, DN_TLS_TopArena()) +DN_API void DN_Str8Builder_Print (DN_Str8Builder const *builder); +DN_API void DN_Str8Builder_PrintLn (DN_Str8Builder const *builder); + +// NOTE: [$FSTR] DN_FStr8 ////////////////////////////////////////////////////////////////////// +#if !defined(DN_NO_FSTR8) +template DN_FStr8 DN_FStr8_InitF (DN_FMT_ATTRIB char const *fmt, ...); +template DN_FStr8 DN_FStr8_InitFV (char const *fmt, va_list args); +template DN_USize DN_FStr8_Max (DN_FStr8 const *string); +template void DN_FStr8_Clear (DN_FStr8 *string); +template bool DN_FStr8_AddFV (DN_FStr8 *string, DN_FMT_ATTRIB char const *fmt, va_list va); +template bool DN_FStr8_AddF (DN_FStr8 *string, DN_FMT_ATTRIB char const *fmt, ...); +template bool DN_FStr8_AddCStr8 (DN_FStr8 *string, char const *value, DN_USize size); +template bool DN_FStr8_Add (DN_FStr8 *string, DN_Str8 value); +template DN_Str8 DN_FStr8_ToStr8 (DN_FStr8 const *string); +template bool DN_FStr8_Eq (DN_FStr8 const *lhs, DN_FStr8 const *rhs, DN_Str8EqCase eq_case); +template bool DN_FStr8_EqStr8 (DN_FStr8 const *lhs, DN_Str8 rhs, DN_Str8EqCase eq_case); +template bool DN_FStr8_EqInsensitive (DN_FStr8 const *lhs, DN_FStr8 const *rhs); +template bool DN_FStr8_EqStr8Insensitive (DN_FStr8 const *lhs, DN_Str8 rhs); +template bool DN_FStr8_EqFStr8 (DN_FStr8 const *lhs, DN_FStr8 const *rhs, DN_Str8EqCase eq_case); +template bool DN_FStr8_EqFStr8Insensitive (DN_FStr8 const *lhs, DN_FStr8 const *rhs); +template bool operator== (DN_FStr8 const &lhs, DN_FStr8 const &rhs); +template bool operator!= (DN_FStr8 const &lhs, DN_FStr8 const &rhs); +template bool operator== (DN_FStr8 const &lhs, DN_Str8 const &rhs); +template bool operator!= (DN_FStr8 const &lhs, DN_Str8 const &rhs); +#endif // !defined(DN_NO_FSTR8) + +// NOTE: [$CHAR] DN_Char ////////////////////////////////////////////////////////////////////////// +struct DN_CharHexToU8 { bool success; uint8_t value; }; -DQN_API bool Dqn_Char_IsAlphabet (char ch); -DQN_API bool Dqn_Char_IsDigit (char ch); -DQN_API bool Dqn_Char_IsAlphaNum (char ch); -DQN_API bool Dqn_Char_IsWhitespace (char ch); -DQN_API bool Dqn_Char_IsHex (char ch); -DQN_API Dqn_CharHexToU8 Dqn_Char_HexToU8 (char ch); -DQN_API char Dqn_Char_ToHex (char ch); -DQN_API char Dqn_Char_ToHexUnchecked (char ch); -DQN_API char Dqn_Char_ToLower (char ch); +DN_API bool DN_Char_IsAlphabet (char ch); +DN_API bool DN_Char_IsDigit (char ch); +DN_API bool DN_Char_IsAlphaNum (char ch); +DN_API bool DN_Char_IsWhitespace (char ch); +DN_API bool DN_Char_IsHex (char ch); +DN_API DN_CharHexToU8 DN_Char_HexToU8 (char ch); +DN_API char DN_Char_ToHex (char ch); +DN_API char DN_Char_ToHexUnchecked (char ch); +DN_API char DN_Char_ToLower (char ch); +DN_API char DN_Char_ToUpper (char ch); -// NOTE: [$UTFX] Dqn_UTF /////////////////////////////////////////////////////////////////////////// -DQN_API int Dqn_UTF8_EncodeCodepoint (uint8_t utf8[4], uint32_t codepoint); -DQN_API int Dqn_UTF16_EncodeCodepoint (uint16_t utf16[2], uint32_t codepoint); +// NOTE: [$UTFX] DN_UTF /////////////////////////////////////////////////////////////////////////// +DN_API int DN_UTF8_EncodeCodepoint (uint8_t utf8[4], uint32_t codepoint); +DN_API int DN_UTF16_EncodeCodepoint (uint16_t utf16[2], uint32_t codepoint); -// NOTE: [$STRB] Dqn_Str8Builder /////////////////////////////////////////////////////////////////// -template Dqn_Str8Builder Dqn_Str8Builder_InitCArrayRef(Dqn_Arena *arena, Dqn_Str8 const (&array)[N]) +// NOTE: [$STRB] DN_Str8Builder /////////////////////////////////////////////////////////////////// +template DN_Str8Builder DN_Str8Builder_InitCArrayRef(DN_Arena *arena, DN_Str8 const (&array)[N]) { - Dqn_Str8Builder result = Dqn_Str8Builder_InitArrayRef(arena, array, N); + DN_Str8Builder result = DN_Str8Builder_InitArrayRef(arena, array, N); return result; } -template Dqn_Str8Builder Dqn_Str8Builder_InitCArrayCopy(Dqn_Arena *arena, Dqn_Str8 const (&array)[N]) +template DN_Str8Builder DN_Str8Builder_InitCArrayCopy(DN_Arena *arena, DN_Str8 const (&array)[N]) { - Dqn_Str8Builder result = Dqn_Str8Builder_InitArrayCopy(arena, array, N); + DN_Str8Builder result = DN_Str8Builder_InitArrayCopy(arena, array, N); return result; } -template bool Dqn_Str8Builder_AddCArrayRef(Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]) +template bool DN_Str8Builder_AddCArrayRef(DN_Str8Builder *builder, DN_Str8 const (&array)[N], DN_Str8BuilderAdd add) { - bool result = Dqn_Str8Builder_AddArrayRef(builder, array, N); + bool result = DN_Str8Builder_AddArrayRef(builder, array, N, add); return result; } -template bool Dqn_Str8Builder_AddCArrayCopy(Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]) +template bool DN_Str8Builder_AddCArrayCopy(DN_Str8Builder *builder, DN_Str8 const (&array)[N], DN_Str8BuilderAdd add) { - bool result = Dqn_Str8Builder_AddArrayCopy(builder, array, N); + bool result = DN_Str8Builder_AddArrayCopy(builder, array, N, add); return result; } -#if !defined(DQN_NO_FSTR8) -// NOTE: [$FSTR] Dqn_FStr8 ///////////////////////////////////////////////////////////////////////// -template Dqn_FStr8 Dqn_FStr8_InitF(DQN_FMT_ATTRIB char const *fmt, ...) +#if !defined(DN_NO_FSTR8) +// NOTE: [$FSTR] DN_FStr8 ///////////////////////////////////////////////////////////////////////// +template DN_FStr8 DN_FStr8_InitF(DN_FMT_ATTRIB char const *fmt, ...) { - Dqn_FStr8 result = {}; + DN_FStr8 result = {}; if (fmt) { va_list args; va_start(args, fmt); - Dqn_FStr8_AddFV(&result, fmt, args); + DN_FStr8_AddFV(&result, fmt, args); va_end(args); } return result; } -template Dqn_usize Dqn_FStr8_Max(Dqn_FStr8 const *) +template DN_FStr8 DN_FStr8_InitFV(char const *fmt, va_list args) { - Dqn_usize result = N; + DN_FStr8 result = {}; + DN_FStr8_AddFV(&result, fmt, args); return result; } -template void Dqn_FStr8_Clear(Dqn_FStr8 *string) +template DN_USize DN_FStr8_Max(DN_FStr8 const *) +{ + DN_USize result = N; + return result; +} + +template void DN_FStr8_Clear(DN_FStr8 *string) { *string = {}; } -template bool Dqn_FStr8_AddFV(Dqn_FStr8 *string, DQN_FMT_ATTRIB char const *fmt, va_list args) +template bool DN_FStr8_AddFV(DN_FStr8 *string, DN_FMT_ATTRIB char const *fmt, va_list args) { bool result = false; if (!string || !fmt) return result; - Dqn_usize require = Dqn_CStr8_FVSize(fmt, args) + 1 /*null_terminate*/; - Dqn_usize space = (N + 1) - string->size; + DN_USize require = DN_CStr8_FVSize(fmt, args) + 1 /*null_terminate*/; + DN_USize space = (N + 1) - string->size; result = require <= space; - string->size += DQN_VSNPRINTF(string->data + string->size, DQN_CAST(int)space, fmt, args); + string->size += DN_VSNPRINTF(string->data + string->size, DN_CAST(int)space, fmt, args); // NOTE: snprintf returns the required size of the format string // irrespective of if there's space or not. - string->size = DQN_MIN(string->size, N); + string->size = DN_MIN(string->size, N); return result; } -template bool Dqn_FStr8_AddF(Dqn_FStr8 *string, DQN_FMT_ATTRIB char const *fmt, ...) +template bool DN_FStr8_AddF(DN_FStr8 *string, DN_FMT_ATTRIB char const *fmt, ...) { bool result = false; if (!string || !fmt) return result; va_list args; va_start(args, fmt); - result = Dqn_FStr8_AddFV(string, fmt, args); + result = DN_FStr8_AddFV(string, fmt, args); va_end(args); return result; } -template bool Dqn_FStr8_AddCStr8(Dqn_FStr8 *string, char const *src, Dqn_usize size) +template bool DN_FStr8_AddCStr8(DN_FStr8 *string, char const *src, DN_USize size) { - DQN_ASSERT(string->size <= N); + DN_ASSERT(string->size <= N); bool result = false; if (!string || !src || size == 0 || string->size >= N) return result; - Dqn_usize space = N - string->size; + DN_USize space = N - string->size; result = size <= space; - DQN_MEMCPY(string->data + string->size, src, DQN_MIN(space, size)); - string->size = DQN_MIN(string->size + size, N); + DN_MEMCPY(string->data + string->size, src, DN_MIN(space, size)); + string->size = DN_MIN(string->size + size, N); string->data[string->size] = 0; return result; } -template bool Dqn_FStr8_Add(Dqn_FStr8 *string, Dqn_Str8 src) +template bool DN_FStr8_Add(DN_FStr8 *string, DN_Str8 src) { - bool result = Dqn_FStr8_AddCStr8(string, src.data, src.size); + bool result = DN_FStr8_AddCStr8(string, src.data, src.size); return result; } -template Dqn_Str8 Dqn_FStr8_ToStr8(Dqn_FStr8 const *string) +template DN_Str8 DN_FStr8_ToStr8(DN_FStr8 const *string) { - Dqn_Str8 result = {}; + DN_Str8 result = {}; if (!string || string->size <= 0) return result; - result.data = DQN_CAST(char *)string->data; + result.data = DN_CAST(char *)string->data; result.size = string->size; return result; } -template bool Dqn_FStr8_Eq(Dqn_FStr8 const *lhs, Dqn_FStr8 const *rhs, Dqn_Str8EqCase eq_case) +template bool DN_FStr8_Eq(DN_FStr8 const *lhs, DN_FStr8 const *rhs, DN_Str8EqCase eq_case) { - Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); - Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs); - bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, eq_case); + DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs); + DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs); + bool result = DN_Str8_Eq(lhs_s8, rhs_s8, eq_case); return result; } -template bool Dqn_FStr8_EqStr8(Dqn_FStr8 const *lhs, Dqn_Str8 rhs, Dqn_Str8EqCase eq_case) +template bool DN_FStr8_EqStr8(DN_FStr8 const *lhs, DN_Str8 rhs, DN_Str8EqCase eq_case) { - Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); - bool result = Dqn_Str8_Eq(lhs_s8, rhs, eq_case); + DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs); + bool result = DN_Str8_Eq(lhs_s8, rhs, eq_case); return result; } -template bool Dqn_FStr8_EqInsensitive(Dqn_FStr8 const *lhs, Dqn_FStr8 const *rhs) +template bool DN_FStr8_EqInsensitive(DN_FStr8 const *lhs, DN_FStr8 const *rhs) { - Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); - Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs); - bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, Dqn_Str8EqCase_Insensitive); + DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs); + DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs); + bool result = DN_Str8_Eq(lhs_s8, rhs_s8, DN_Str8EqCase_Insensitive); return result; } -template bool Dqn_FStr8_EqStr8Insensitive(Dqn_FStr8 const *lhs, Dqn_Str8 rhs) +template bool DN_FStr8_EqStr8Insensitive(DN_FStr8 const *lhs, DN_Str8 rhs) { - Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); - bool result = Dqn_Str8_Eq(lhs_s8, rhs, Dqn_Str8EqCase_Insensitive); + DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs); + bool result = DN_Str8_Eq(lhs_s8, rhs, DN_Str8EqCase_Insensitive); return result; } -template bool Dqn_FStr8_EqFStr8(Dqn_FStr8 const *lhs, Dqn_FStr8 const *rhs, Dqn_Str8EqCase eq_case) +template bool DN_FStr8_EqFStr8(DN_FStr8 const *lhs, DN_FStr8 const *rhs, DN_Str8EqCase eq_case) { - Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); - Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs); - bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, eq_case); + DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs); + DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs); + bool result = DN_Str8_Eq(lhs_s8, rhs_s8, eq_case); return result; } -template bool Dqn_FStr8_EqFStr8Insensitive(Dqn_FStr8 const *lhs, Dqn_FStr8 const *rhs) +template bool DN_FStr8_EqFStr8Insensitive(DN_FStr8 const *lhs, DN_FStr8 const *rhs) { - Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); - Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs); - bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, Dqn_Str8EqCase_Insensitive); + DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs); + DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs); + bool result = DN_Str8_Eq(lhs_s8, rhs_s8, DN_Str8EqCase_Insensitive); return result; } -template bool operator==(Dqn_FStr8 const &lhs, Dqn_FStr8 const &rhs) +template bool operator==(DN_FStr8 const &lhs, DN_FStr8 const &rhs) { - bool result = Dqn_FStr8_Eq(&lhs, &rhs, Dqn_Str8EqCase_Sensitive); + bool result = DN_FStr8_Eq(&lhs, &rhs, DN_Str8EqCase_Sensitive); return result; } -template bool operator!=(Dqn_FStr8 const &lhs, Dqn_FStr8 const &rhs) +template bool operator!=(DN_FStr8 const &lhs, DN_FStr8 const &rhs) { bool result = !(lhs == rhs); return result; } -#endif // !defined(DQN_NO_FSTR8) + +template bool operator==(DN_FStr8 const &lhs, DN_Str8 const &rhs) +{ + bool result = DN_Str8_Eq(DN_FStr8_ToStr8(&lhs), rhs, DN_Str8EqCase_Insensitive); + return result; +} + +template bool operator!=(DN_FStr8 const &lhs, DN_Str8 const &rhs) +{ + bool result = !(lhs == rhs); + return result; +} +#endif // !defined(DN_NO_FSTR8) diff --git a/dqn_tls.cpp b/dqn_tls.cpp index fef4fac..e261488 100644 --- a/dqn_tls.cpp +++ b/dqn_tls.cpp @@ -18,109 +18,133 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -// NOTE: [$TCTX] Dqn_TLS ///////////////////////////////////////////////////////////////// -Dqn_TLSTMem::Dqn_TLSTMem(Dqn_TLS *tls, uint8_t arena_index, Dqn_TLSPushTMem push_tmem) +// NOTE: [$TCTX] DN_TLS ///////////////////////////////////////////////////////////////// +DN_TLSTMem::DN_TLSTMem(DN_TLS *tls, uint8_t arena_index, DN_TLSPushTMem push_tmem) { - DQN_ASSERT(arena_index == Dqn_TLSArena_TMem0 || arena_index == Dqn_TLSArena_TMem1); + DN_ASSERT(arena_index == DN_TLSArena_TMem0 || arena_index == DN_TLSArena_TMem1); arena = tls->arenas + arena_index; - temp_mem = Dqn_Arena_TempMemBegin(arena); + temp_mem = DN_Arena_TempMemBegin(arena); destructed = false; push_arena = push_tmem; if (push_arena) - Dqn_TLS_PushArena(arena); + DN_TLS_PushArena(arena); } -Dqn_TLSTMem::~Dqn_TLSTMem() +DN_TLSTMem::~DN_TLSTMem() { - DQN_ASSERT(destructed == false); - Dqn_Arena_TempMemEnd(temp_mem); + DN_ASSERT(destructed == false); + DN_Arena_TempMemEnd(temp_mem); destructed = true; if (push_arena) - Dqn_TLS_PopArena(); + DN_TLS_PopArena(); } -DQN_API void Dqn_TLS_Init(Dqn_TLS *tls) +DN_API void DN_TLS_Init(DN_TLS *tls) { - DQN_CHECK(tls); + DN_CHECK(tls); if (tls->init) return; - DQN_FOR_UINDEX (index, Dqn_TLSArena_Count) { - Dqn_Arena *arena = tls->arenas + index; - switch (DQN_CAST(Dqn_TLSArena)index) { - default: *arena = Dqn_Arena_InitSize(DQN_MEGABYTES(4), DQN_KILOBYTES(4), Dqn_ArenaFlag_AllocCanLeak); break; - case Dqn_TLSArena_ErrorSink: *arena = Dqn_Arena_InitSize(DQN_KILOBYTES(64), DQN_KILOBYTES(4), Dqn_ArenaFlag_AllocCanLeak); break; - case Dqn_TLSArena_Count: DQN_INVALID_CODE_PATH; break; + DN_FOR_UINDEX (index, DN_TLSArena_Count) { + DN_Arena *arena = tls->arenas + index; + switch (DN_CAST(DN_TLSArena)index) { + default: *arena = DN_Arena_InitSize(DN_MEGABYTES(4), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); break; + case DN_TLSArena_ErrorSink: *arena = DN_Arena_InitSize(DN_KILOBYTES(64), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); break; + case DN_TLSArena_Count: DN_INVALID_CODE_PATH; break; } } - tls->thread_id = Dqn_OS_ThreadID(); - tls->error_sink.arena = tls->arenas + Dqn_TLSArena_ErrorSink; - tls->init = true; + tls->thread_id = DN_OS_ThreadID(); + tls->err_sink.arena = tls->arenas + DN_TLSArena_ErrorSink; + tls->init = true; } -DQN_API Dqn_TLS *Dqn_TLS_Get() +DN_API void DN_TLS_Deinit(DN_TLS *tls) { - Dqn_TLS *result = g_dqn_os_thread_tls; - // TODO(doyle): Fix stack-trace infinite loop with requiring the TLS that is not initialised - // yet. - DQN_ASSERT( - g_dqn_library->lib_init && - "Library context must be be initialised first by calling Dqn_Library_Init. This " - "initialises the main thread's TLS for you (no need to call Dqn_OS_ThreadSetTLS on main)"); + tls->init = false; + tls->err_sink = {}; + tls->arena_stack_index = {}; + DN_FOR_UINDEX(index, DN_TLSArena_Count) + { + DN_Arena *arena = tls->arenas + index; + DN_Arena_Deinit(arena); + } +} - DQN_ASSERT(result && - "Thread must be assigned the TLS with Dqn_OS_ThreadSetTLS. If the library is " +DN_API DN_TLS *DN_TLS_Get() +{ + DN_TLS *result = g_dn_os_thread_tls; + DN_ASSERT( + g_dn_core->init && + "Library context must be be initialised first by calling DN_Library_Init. This " + "initialises the main thread's TLS for you (no need to call DN_OS_ThreadSetTLS on main)"); + + DN_ASSERT(result && + "Thread must be assigned the TLS with DN_OS_ThreadSetTLS. If the library is " "initialised, then, this thread was created without calling the set TLS function " "for the spawned thread."); return result; } -DQN_API Dqn_Arena *Dqn_TLS_Arena() +DN_API DN_Arena *DN_TLS_Arena() { - Dqn_TLS *tls = Dqn_TLS_Get(); - Dqn_Arena *result = tls->arenas + Dqn_TLSArena_Main; + DN_TLS *tls = DN_TLS_Get(); + DN_Arena *result = tls->arenas + DN_TLSArena_Main; return result; } // TODO: Is there a way to handle conflict arenas without the user needing to // manually pass it in? -DQN_API Dqn_TLSTMem Dqn_TLS_GetTMem(void const *conflict_arena, Dqn_TLSPushTMem push_tmem) +DN_API DN_TLSTMem DN_TLS_GetTMem(void const *conflict_arena, DN_TLSPushTMem push_tmem) { - Dqn_TLS *tls = Dqn_TLS_Get(); + DN_TLS *tls = DN_TLS_Get(); uint8_t tls_index = (uint8_t)-1; - for (uint8_t index = Dqn_TLSArena_TMem0; index <= Dqn_TLSArena_TMem1; index++) { - Dqn_Arena *arena = tls->arenas + index; + for (uint8_t index = DN_TLSArena_TMem0; index <= DN_TLSArena_TMem1; index++) { + DN_Arena *arena = tls->arenas + index; if (!conflict_arena || arena != conflict_arena) { tls_index = index; break; } } - DQN_ASSERT(tls_index != (uint8_t)-1); - return Dqn_TLSTMem(tls, tls_index, push_tmem); + DN_ASSERT(tls_index != (uint8_t)-1); + return DN_TLSTMem(tls, tls_index, push_tmem); } -DQN_API void Dqn_TLS_PushArena(Dqn_Arena *arena) +DN_API void DN_TLS_PushArena(DN_Arena *arena) { - DQN_ASSERT(arena); - Dqn_TLS *tls = Dqn_TLS_Get(); - DQN_ASSERT(tls->arena_stack_index < DQN_ARRAY_UCOUNT(tls->arena_stack)); + DN_ASSERT(arena); + DN_TLS *tls = DN_TLS_Get(); + DN_ASSERT(tls->arena_stack_index < DN_ARRAY_UCOUNT(tls->arena_stack)); tls->arena_stack[tls->arena_stack_index++] = arena; } -DQN_API void Dqn_TLS_PopArena() +DN_API void DN_TLS_PopArena() { - Dqn_TLS *tls = Dqn_TLS_Get(); - DQN_ASSERT(tls->arena_stack_index > 0); + DN_TLS *tls = DN_TLS_Get(); + DN_ASSERT(tls->arena_stack_index > 0); tls->arena_stack_index--; } -DQN_API Dqn_Arena *Dqn_TLS_TopArena() +DN_API DN_Arena *DN_TLS_TopArena() { - Dqn_TLS *tls = Dqn_TLS_Get(); - Dqn_Arena *result = nullptr; + DN_TLS *tls = DN_TLS_Get(); + DN_Arena *result = nullptr; if (tls->arena_stack_index) result = tls->arena_stack[tls->arena_stack_index - 1]; return result; } + +DN_API void DN_TLS_BeginFrame(DN_Arena *frame_arena) +{ + DN_TLS *tls = DN_TLS_Get(); + tls->frame_arena = frame_arena; +} + +DN_API DN_Arena *DN_TLS_FrameArena() +{ + DN_TLS *tls = DN_TLS_Get(); + DN_Arena *result = tls->frame_arena; + return result; +} + diff --git a/dqn_tls.h b/dqn_tls.h index 94aae6f..194cd9e 100644 --- a/dqn_tls.h +++ b/dqn_tls.h @@ -27,58 +27,67 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -enum Dqn_TLSArena +enum DN_TLSArena { - Dqn_TLSArena_Main, // NOTE: Arena for Permanent allocations - Dqn_TLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread + DN_TLSArena_Main, // NOTE: Arena for Permanent allocations + DN_TLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread // NOTE: Per-thread scratch arenas (2 to prevent aliasing) - Dqn_TLSArena_TMem0, - Dqn_TLSArena_TMem1, + DN_TLSArena_TMem0, + DN_TLSArena_TMem1, - Dqn_TLSArena_Count, + DN_TLSArena_Count, }; -struct Dqn_TLS +struct DN_TLS { - Dqn_b32 init; // Flag to track if Thread has been initialised - uint64_t thread_id; - Dqn_CallSite call_site; // Stores call-site information when requested by thread - Dqn_ErrorSink error_sink; // Error handling state - Dqn_Arena arenas[Dqn_TLSArena_Count]; + DN_B32 init; // Flag to track if Thread has been initialised + uint64_t thread_id; + DN_CallSite call_site; // Stores call-site information when requested by thread + DN_ErrSink err_sink; // Error handling state + DN_Arena arenas[DN_TLSArena_Count]; // Push and pop arenas onto the stack. Functions suffixed 'TLS' will use // these arenas for memory allocation. - Dqn_Arena *arena_stack[8]; - Dqn_usize arena_stack_index; + DN_Arena *arena_stack[8]; + DN_USize arena_stack_index; + + DN_Arena *frame_arena; + char name[64]; + uint8_t 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 Dqn_TLSPushTMem +enum DN_TLSPushTMem { - Dqn_TLSPushTMem_No, - Dqn_TLSPushTMem_Yes, + DN_TLSPushTMem_No, + DN_TLSPushTMem_Yes, }; -struct Dqn_TLSTMem +struct DN_TLSTMem { - Dqn_TLSTMem(Dqn_TLS *context, uint8_t context_index, Dqn_TLSPushTMem push_scratch); - ~Dqn_TLSTMem(); + DN_TLSTMem(DN_TLS *context, uint8_t context_index, DN_TLSPushTMem push_scratch); + ~DN_TLSTMem(); - Dqn_Arena *arena; - Dqn_b32 destructed; - Dqn_TLSPushTMem push_arena; - Dqn_ArenaTempMem temp_mem; + DN_Arena *arena; + DN_B32 destructed; + DN_TLSPushTMem push_arena; + DN_ArenaTempMem temp_mem; }; -DQN_API void Dqn_TLS_Init(Dqn_TLS *tls); -DQN_API Dqn_TLS * Dqn_TLS_Get(); -#define Dqn_TLS_SaveCallSite do { Dqn_TLS_Get()->call_site = DQN_CALL_SITE; } while (0) -DQN_API Dqn_TLSTMem Dqn_TLS_GetTMem(void const *conflict_arena, Dqn_TLSPushTMem push_tmp_mem); -#define Dqn_TLS_TMem(...) Dqn_TLS_GetTMem(__VA_ARGS__, Dqn_TLSPushTMem_No) -#define Dqn_TLS_PushTMem(...) Dqn_TLS_GetTMem(__VA_ARGS__, Dqn_TLSPushTMem_Yes) -DQN_API void Dqn_TLS_PushArena(Dqn_Arena *arena); -DQN_API void Dqn_TLS_PopArena(); -DQN_API Dqn_Arena * Dqn_TLS_TopArena(); +DN_API void DN_TLS_Init(DN_TLS *tls); +DN_API void DN_TLS_Deinit(DN_TLS *tls); +DN_API DN_TLS * DN_TLS_Get(); +DN_API DN_Arena * DN_TLS_Arena(); +#define DN_TLS_SaveCallSite do { DN_TLS_Get()->call_site = DN_CALL_SITE; } while (0) +DN_API DN_TLSTMem DN_TLS_GetTMem(void const *conflict_arena, DN_TLSPushTMem push_tmp_mem); +#define DN_TLS_TMem(...) DN_TLS_GetTMem(__VA_ARGS__, DN_TLSPushTMem_No) +#define DN_TLS_PushTMem(...) DN_TLS_GetTMem(__VA_ARGS__, DN_TLSPushTMem_Yes) +DN_API void DN_TLS_PushArena(DN_Arena *arena); +DN_API void DN_TLS_PopArena(); +DN_API DN_Arena * DN_TLS_TopArena(); + +DN_API void DN_TLS_BeginFrame(DN_Arena *frame_arena); +DN_API DN_Arena * DN_TLS_FrameArena(); diff --git a/dqn_type_info.cpp b/dqn_type_info.cpp index f5911c8..f261f7d 100644 --- a/dqn_type_info.cpp +++ b/dqn_type_info.cpp @@ -18,15 +18,15 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -Dqn_TypeGetField Dqn_Type_GetField(Dqn_TypeInfo const *type_info, Dqn_Str8 name) +DN_TypeGetField DN_Type_GetField(DN_TypeInfo const *type_info, DN_Str8 name) { - Dqn_TypeGetField result = {}; - for (Dqn_usize index = 0; index < type_info->fields_count; index++) { - Dqn_TypeField const *type_field = type_info->fields + index; + DN_TypeGetField result = {}; + for (DN_USize index = 0; index < type_info->fields_count; index++) { + DN_TypeField const *type_field = type_info->fields + index; if (type_field->name == name) { result.success = true; result.index = index; - result.field = DQN_CAST(Dqn_TypeField *)type_field; + result.field = DN_CAST(DN_TypeField *)type_field; break; } } diff --git a/dqn_type_info.h b/dqn_type_info.h index 48bef0e..7b0da44 100644 --- a/dqn_type_info.h +++ b/dqn_type_info.h @@ -18,44 +18,44 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// */ -enum Dqn_TypeKind +enum DN_TypeKind { - Dqn_TypeKind_Nil, - Dqn_TypeKind_Basic, - Dqn_TypeKind_Enum, - Dqn_TypeKind_Struct, + DN_TypeKind_Nil, + DN_TypeKind_Basic, + DN_TypeKind_Enum, + DN_TypeKind_Struct, }; -struct Dqn_TypeField +struct DN_TypeField { - uint16_t index; - Dqn_Str8 name; - Dqn_Str8 label; - Dqn_isize value; - Dqn_usize offset_of; - Dqn_usize size_of; - Dqn_usize align_of; - Dqn_Str8 type_decl; - uint32_t type_enum; - bool is_pointer; - uint16_t array_size; - Dqn_TypeField const * array_size_field; + uint16_t index; + DN_Str8 name; + DN_Str8 label; + DN_ISize value; + DN_USize offset_of; + DN_USize size_of; + DN_USize align_of; + DN_Str8 type_decl; + uint32_t type_enum; + bool is_pointer; + uint16_t array_size; + DN_TypeField const * array_size_field; }; -struct Dqn_TypeInfo +struct DN_TypeInfo { - Dqn_Str8 name; - Dqn_TypeKind kind; - Dqn_usize size_of; - Dqn_TypeField const *fields; - uint16_t fields_count; + DN_Str8 name; + DN_TypeKind kind; + DN_USize size_of; + DN_TypeField const *fields; + uint16_t fields_count; }; -struct Dqn_TypeGetField +struct DN_TypeGetField { - bool success; - Dqn_usize index; - Dqn_TypeField *field; + bool success; + DN_USize index; + DN_TypeField *field; }; -Dqn_TypeGetField Dqn_Type_GetField(Dqn_TypeInfo const *type_info, Dqn_Str8 name); +DN_TypeGetField DN_Type_GetField(DN_TypeInfo const *type_info, DN_Str8 name); diff --git a/dqn_unit_tests.cpp b/dqn_unit_tests.cpp index 496f939..76838f4 100644 --- a/dqn_unit_tests.cpp +++ b/dqn_unit_tests.cpp @@ -1,327 +1,283 @@ -#define DQN_UTEST_IMPLEMENTATION +#define DN_UTEST_IMPLEMENTATION #include "Standalone/dqn_utest.h" #include - // NOTE: Taken from MSDN __cpuid example implementation // https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=msvc-170 -#include -#include -#include -#include +struct DN_RefImplCPUReport { + unsigned int nIds_ = 0; + unsigned int nExIds_ = 0; + char vendor_[0x20] = {}; + int vendorSize_ = 0; + char brand_[0x40] = {}; + int brandSize_ = 0; + bool isIntel_ = false; + bool isAMD_ = false; + uint32_t f_1_ECX_ = 0; + uint32_t f_1_EDX_ = 0; + uint32_t f_7_EBX_ = 0; + uint32_t f_7_ECX_ = 0; + uint32_t f_81_ECX_ = 0; + uint32_t f_81_EDX_ = 0; + int data_[400][4] = {}; + size_t dataSize_ = 0; + int extdata_[400][4] = {}; + size_t extdataSize_ = 0; -class Dqn_RefImplCPUReport -{ - // forward declarations - class Dqn_RefImplCPUReport_Internal; + bool SSE3(void) const { return f_1_ECX_ & (1 << 0); } + bool PCLMULQDQ(void) const { return f_1_ECX_ & (1 << 1); } + bool MONITOR(void) const { return f_1_ECX_ & (1 << 3); } + bool SSSE3(void) const { return f_1_ECX_ & (1 << 9); } + bool FMA(void) const { return f_1_ECX_ & (1 << 12); } + bool CMPXCHG16B(void) const { return f_1_ECX_ & (1 << 13); } + bool SSE41(void) const { return f_1_ECX_ & (1 << 19); } + bool SSE42(void) const { return f_1_ECX_ & (1 << 20); } + bool MOVBE(void) const { return f_1_ECX_ & (1 << 22); } + bool POPCNT(void) const { return f_1_ECX_ & (1 << 23); } + bool AES(void) const { return f_1_ECX_ & (1 << 25); } + bool XSAVE(void) const { return f_1_ECX_ & (1 << 26); } + bool OSXSAVE(void) const { return f_1_ECX_ & (1 << 27); } + bool AVX(void) const { return f_1_ECX_ & (1 << 28); } + bool F16C(void) const { return f_1_ECX_ & (1 << 29); } + bool RDRAND(void) const { return f_1_ECX_ & (1 << 30); } -public: - // getters - static std::string Vendor(void) { return CPU_Rep.vendor_; } - static std::string Brand(void) { return CPU_Rep.brand_; } + bool MSR(void) const { return f_1_EDX_ & (1 << 5); } + bool CX8(void) const { return f_1_EDX_ & (1 << 8); } + bool SEP(void) const { return f_1_EDX_ & (1 << 11); } + bool CMOV(void) const { return f_1_EDX_ & (1 << 15); } + bool CLFSH(void) const { return f_1_EDX_ & (1 << 19); } + bool MMX(void) const { return f_1_EDX_ & (1 << 23); } + bool FXSR(void) const { return f_1_EDX_ & (1 << 24); } + bool SSE(void) const { return f_1_EDX_ & (1 << 25); } + bool SSE2(void) const { return f_1_EDX_ & (1 << 26); } - static bool SSE3(void) { return CPU_Rep.f_1_ECX_[0]; } - static bool PCLMULQDQ(void) { return CPU_Rep.f_1_ECX_[1]; } - static bool MONITOR(void) { return CPU_Rep.f_1_ECX_[3]; } - static bool SSSE3(void) { return CPU_Rep.f_1_ECX_[9]; } - static bool FMA(void) { return CPU_Rep.f_1_ECX_[12]; } - static bool CMPXCHG16B(void) { return CPU_Rep.f_1_ECX_[13]; } - static bool SSE41(void) { return CPU_Rep.f_1_ECX_[19]; } - static bool SSE42(void) { return CPU_Rep.f_1_ECX_[20]; } - static bool MOVBE(void) { return CPU_Rep.f_1_ECX_[22]; } - static bool POPCNT(void) { return CPU_Rep.f_1_ECX_[23]; } - static bool AES(void) { return CPU_Rep.f_1_ECX_[25]; } - static bool XSAVE(void) { return CPU_Rep.f_1_ECX_[26]; } - static bool OSXSAVE(void) { return CPU_Rep.f_1_ECX_[27]; } - static bool AVX(void) { return CPU_Rep.f_1_ECX_[28]; } - static bool F16C(void) { return CPU_Rep.f_1_ECX_[29]; } - static bool RDRAND(void) { return CPU_Rep.f_1_ECX_[30]; } + bool FSGSBASE(void) const { return f_7_EBX_ & (1 << 0); } + bool BMI1(void) const { return f_7_EBX_ & (1 << 3); } + bool HLE(void) const { return isIntel_ && f_7_EBX_ & (1 << 4); } + bool AVX2(void) const { return f_7_EBX_ & (1 << 5); } + bool BMI2(void) const { return f_7_EBX_ & (1 << 8); } + bool ERMS(void) const { return f_7_EBX_ & (1 << 9); } + bool INVPCID(void) const { return f_7_EBX_ & (1 << 10); } + bool RTM(void) const { return isIntel_ && f_7_EBX_ & (1 << 11); } + bool AVX512F(void) const { return f_7_EBX_ & (1 << 16); } + bool RDSEED(void) const { return f_7_EBX_ & (1 << 18); } + bool ADX(void) const { return f_7_EBX_ & (1 << 19); } + bool AVX512PF(void) const { return f_7_EBX_ & (1 << 26); } + bool AVX512ER(void) const { return f_7_EBX_ & (1 << 27); } + bool AVX512CD(void) const { return f_7_EBX_ & (1 << 28); } + bool SHA(void) const { return f_7_EBX_ & (1 << 29); } - static bool MSR(void) { return CPU_Rep.f_1_EDX_[5]; } - static bool CX8(void) { return CPU_Rep.f_1_EDX_[8]; } - static bool SEP(void) { return CPU_Rep.f_1_EDX_[11]; } - static bool CMOV(void) { return CPU_Rep.f_1_EDX_[15]; } - static bool CLFSH(void) { return CPU_Rep.f_1_EDX_[19]; } - static bool MMX(void) { return CPU_Rep.f_1_EDX_[23]; } - static bool FXSR(void) { return CPU_Rep.f_1_EDX_[24]; } - static bool SSE(void) { return CPU_Rep.f_1_EDX_[25]; } - static bool SSE2(void) { return CPU_Rep.f_1_EDX_[26]; } + bool PREFETCHWT1(void) const { return f_7_ECX_ & (1 << 0); } - static bool FSGSBASE(void) { return CPU_Rep.f_7_EBX_[0]; } - static bool BMI1(void) { return CPU_Rep.f_7_EBX_[3]; } - static bool HLE(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_7_EBX_[4]; } - static bool AVX2(void) { return CPU_Rep.f_7_EBX_[5]; } - static bool BMI2(void) { return CPU_Rep.f_7_EBX_[8]; } - static bool ERMS(void) { return CPU_Rep.f_7_EBX_[9]; } - static bool INVPCID(void) { return CPU_Rep.f_7_EBX_[10]; } - static bool RTM(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_7_EBX_[11]; } - static bool AVX512F(void) { return CPU_Rep.f_7_EBX_[16]; } - static bool RDSEED(void) { return CPU_Rep.f_7_EBX_[18]; } - static bool ADX(void) { return CPU_Rep.f_7_EBX_[19]; } - static bool AVX512PF(void) { return CPU_Rep.f_7_EBX_[26]; } - static bool AVX512ER(void) { return CPU_Rep.f_7_EBX_[27]; } - static bool AVX512CD(void) { return CPU_Rep.f_7_EBX_[28]; } - static bool SHA(void) { return CPU_Rep.f_7_EBX_[29]; } + bool LAHF(void) const { return f_81_ECX_ & (1 << 0); } + bool LZCNT(void) const { return isIntel_ && f_81_ECX_ & (1 << 5); } + bool ABM(void) const { return isAMD_ && f_81_ECX_ & (1 << 5); } + bool SSE4a(void) const { return isAMD_ && f_81_ECX_ & (1 << 6); } + bool XOP(void) const { return isAMD_ && f_81_ECX_ & (1 << 11); } + bool TBM(void) const { return isAMD_ && f_81_ECX_ & (1 << 21); } - static bool PREFETCHWT1(void) { return CPU_Rep.f_7_ECX_[0]; } - - static bool LAHF(void) { return CPU_Rep.f_81_ECX_[0]; } - static bool LZCNT(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_ECX_[5]; } - static bool ABM(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[5]; } - static bool SSE4a(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[6]; } - static bool XOP(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[11]; } - static bool TBM(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_ECX_[21]; } - - static bool SYSCALL(void) { return CPU_Rep.isIntel_ && CPU_Rep.f_81_EDX_[11]; } - static bool MMXEXT(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[22]; } - static bool RDTSCP(void) { return CPU_Rep.f_81_EDX_[27]; } - static bool _3DNOWEXT(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[30]; } - static bool _3DNOW(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[31]; } - -private: - static const Dqn_RefImplCPUReport_Internal CPU_Rep; - - class Dqn_RefImplCPUReport_Internal - { - public: - Dqn_RefImplCPUReport_Internal() - : nIds_{ 0 }, - nExIds_{ 0 }, - isIntel_{ false }, - isAMD_{ false }, - f_1_ECX_{ 0 }, - f_1_EDX_{ 0 }, - f_7_EBX_{ 0 }, - f_7_ECX_{ 0 }, - f_81_ECX_{ 0 }, - f_81_EDX_{ 0 }, - data_{}, - extdata_{} - { - //int cpuInfo[4] = {-1}; - std::array cpui; - - // Calling __cpuid with 0x0 as the function_id argument - // gets the number of the highest valid function ID. - __cpuid(cpui.data(), 0); - nIds_ = cpui[0]; - - for (int i = 0; i <= nIds_; ++i) - { - __cpuidex(cpui.data(), i, 0); - data_[dataSize_++] = cpui; - } - - // Capture vendor string - char vendor[0x20]; - memset(vendor, 0, sizeof(vendor)); - *reinterpret_cast(vendor) = data_[0][1]; - *reinterpret_cast(vendor + 4) = data_[0][3]; - *reinterpret_cast(vendor + 8) = data_[0][2]; - vendor_ = vendor; - if (vendor_ == "GenuineIntel") - { - isIntel_ = true; - } - else if (vendor_ == "AuthenticAMD") - { - isAMD_ = true; - } - - // load bitset with flags for function 0x00000001 - if (nIds_ >= 1) - { - f_1_ECX_ = data_[1][2]; - f_1_EDX_ = data_[1][3]; - } - - // load bitset with flags for function 0x00000007 - if (nIds_ >= 7) - { - f_7_EBX_ = data_[7][1]; - f_7_ECX_ = data_[7][2]; - } - - // Calling __cpuid with 0x80000000 as the function_id argument - // gets the number of the highest valid extended ID. - __cpuid(cpui.data(), 0x80000000); - nExIds_ = cpui[0]; - - char brand[0x40]; - memset(brand, 0, sizeof(brand)); - - for (int i = 0x80000000; i <= nExIds_; ++i) - { - __cpuidex(cpui.data(), i, 0); - extdata_[extdataSize_++] = cpui; - } - - // load bitset with flags for function 0x80000001 - if (nExIds_ >= 0x80000001) - { - f_81_ECX_ = extdata_[1][2]; - f_81_EDX_ = extdata_[1][3]; - } - - // Interpret CPU brand string if reported - if (nExIds_ >= 0x80000004) - { - memcpy(brand, extdata_[2].data(), sizeof(cpui)); - memcpy(brand + 16, extdata_[3].data(), sizeof(cpui)); - memcpy(brand + 32, extdata_[4].data(), sizeof(cpui)); - brand_ = brand; - } - }; - - int nIds_; - int nExIds_; - std::string vendor_; - std::string brand_; - bool isIntel_; - bool isAMD_; - std::bitset<32> f_1_ECX_; - std::bitset<32> f_1_EDX_; - std::bitset<32> f_7_EBX_; - std::bitset<32> f_7_ECX_; - std::bitset<32> f_81_ECX_; - std::bitset<32> f_81_EDX_; - std::array, 512> data_{}; - size_t dataSize_ = 0; - std::array, 512> extdata_{}; - size_t extdataSize_ = 0; - }; + bool SYSCALL(void) const { return isIntel_ && f_81_EDX_ & (1 << 11); } + bool MMXEXT(void) const { return isAMD_ && f_81_EDX_ & (1 << 22); } + bool RDTSCP(void) const { return f_81_EDX_ & (1 << 27); } + bool _3DNOWEXT(void) const { return isAMD_ && f_81_EDX_ & (1 << 30); } + bool _3DNOW(void) const { return isAMD_ && f_81_EDX_ & (1 << 31); } }; -// Initialize static member data -const Dqn_RefImplCPUReport::Dqn_RefImplCPUReport_Internal Dqn_RefImplCPUReport::CPU_Rep; +DN_RefImplCPUReport DN_RefImplCPUReport_Init() +{ + DN_RefImplCPUReport result = {}; + + // int cpuInfo[4] = {-1}; + int cpui[4]; + + // Calling __cpuid with 0x0 as the function_id argument + // gets the number of the highest valid function ID. + __cpuid(cpui, 0); + result.nIds_ = cpui[0]; + + for (unsigned int i = 0; i <= result.nIds_; ++i) { + __cpuidex(cpui, i, 0); + memcpy(result.data_[result.dataSize_++], cpui, sizeof(cpui)); + } + + // Capture vendor string + *reinterpret_cast(result.vendor_) = result.data_[0][1]; + *reinterpret_cast(result.vendor_ + 4) = result.data_[0][3]; + *reinterpret_cast(result.vendor_ + 8) = result.data_[0][2]; + result.vendorSize_ = (int)strlen(result.vendor_); + + if (strcmp(result.vendor_, "GenuineIntel") == 0) + result.isIntel_ = true; + else if (strcmp(result.vendor_, "AuthenticAMD") == 0) + result.isAMD_ = true; + + // load bitset with flags for function 0x00000001 + if (result.nIds_ >= 1) { + result.f_1_ECX_ = result.data_[1][2]; + result.f_1_EDX_ = result.data_[1][3]; + } + + // load bitset with flags for function 0x00000007 + if (result.nIds_ >= 7) { + result.f_7_EBX_ = result.data_[7][1]; + result.f_7_ECX_ = result.data_[7][2]; + } + + // Calling __cpuid with 0x80000000 as the function_id argument + // gets the number of the highest valid extended ID. + __cpuid(cpui, 0x80000000); + result.nExIds_ = cpui[0]; + + for (unsigned int i = 0x80000000; i <= result.nExIds_; ++i) { + __cpuidex(cpui, i, 0); + memcpy(result.extdata_[result.extdataSize_++], cpui, sizeof(cpui)); + } + + // load bitset with flags for function 0x80000001 + if (result.nExIds_ >= 0x80000001) { + result.f_81_ECX_ = result.extdata_[1][2]; + result.f_81_EDX_ = result.extdata_[1][3]; + } + + // Interpret CPU brand string if reported + if (result.nExIds_ >= 0x80000004) { + memcpy(result.brand_, result.extdata_[2], sizeof(cpui)); + memcpy(result.brand_ + 16, result.extdata_[3], sizeof(cpui)); + memcpy(result.brand_ + 32, result.extdata_[4], sizeof(cpui)); + result.brandSize_ = (int)strlen(result.brand_); + } + + return result; +} #if 0 -static void Dqn_RefImpl_CPUReportDump() // Print out supported instruction set features +static void DN_RefImpl_CPUReportDump() // Print out supported instruction set features { auto support_message = [](std::string isa_feature, bool is_supported) { printf("%s %s\n", isa_feature.c_str(), is_supported ? "supported" : "not supported"); }; - printf("%s\n", Dqn_RefImplCPUReport::Vendor().c_str()); - printf("%s\n", Dqn_RefImplCPUReport::Brand().c_str()); + printf("%s\n", DN_RefImplCPUReport::Vendor().c_str()); + printf("%s\n", DN_RefImplCPUReport::Brand().c_str()); - support_message("3DNOW", Dqn_RefImplCPUReport::_3DNOW()); - support_message("3DNOWEXT", Dqn_RefImplCPUReport::_3DNOWEXT()); - support_message("ABM", Dqn_RefImplCPUReport::ABM()); - support_message("ADX", Dqn_RefImplCPUReport::ADX()); - support_message("AES", Dqn_RefImplCPUReport::AES()); - support_message("AVX", Dqn_RefImplCPUReport::AVX()); - support_message("AVX2", Dqn_RefImplCPUReport::AVX2()); - support_message("AVX512CD", Dqn_RefImplCPUReport::AVX512CD()); - support_message("AVX512ER", Dqn_RefImplCPUReport::AVX512ER()); - support_message("AVX512F", Dqn_RefImplCPUReport::AVX512F()); - support_message("AVX512PF", Dqn_RefImplCPUReport::AVX512PF()); - support_message("BMI1", Dqn_RefImplCPUReport::BMI1()); - support_message("BMI2", Dqn_RefImplCPUReport::BMI2()); - support_message("CLFSH", Dqn_RefImplCPUReport::CLFSH()); - support_message("CMPXCHG16B", Dqn_RefImplCPUReport::CMPXCHG16B()); - support_message("CX8", Dqn_RefImplCPUReport::CX8()); - support_message("ERMS", Dqn_RefImplCPUReport::ERMS()); - support_message("F16C", Dqn_RefImplCPUReport::F16C()); - support_message("FMA", Dqn_RefImplCPUReport::FMA()); - support_message("FSGSBASE", Dqn_RefImplCPUReport::FSGSBASE()); - support_message("FXSR", Dqn_RefImplCPUReport::FXSR()); - support_message("HLE", Dqn_RefImplCPUReport::HLE()); - support_message("INVPCID", Dqn_RefImplCPUReport::INVPCID()); - support_message("LAHF", Dqn_RefImplCPUReport::LAHF()); - support_message("LZCNT", Dqn_RefImplCPUReport::LZCNT()); - support_message("MMX", Dqn_RefImplCPUReport::MMX()); - support_message("MMXEXT", Dqn_RefImplCPUReport::MMXEXT()); - support_message("MONITOR", Dqn_RefImplCPUReport::MONITOR()); - support_message("MOVBE", Dqn_RefImplCPUReport::MOVBE()); - support_message("MSR", Dqn_RefImplCPUReport::MSR()); - support_message("OSXSAVE", Dqn_RefImplCPUReport::OSXSAVE()); - support_message("PCLMULQDQ", Dqn_RefImplCPUReport::PCLMULQDQ()); - support_message("POPCNT", Dqn_RefImplCPUReport::POPCNT()); - support_message("PREFETCHWT1", Dqn_RefImplCPUReport::PREFETCHWT1()); - support_message("RDRAND", Dqn_RefImplCPUReport::RDRAND()); - support_message("RDSEED", Dqn_RefImplCPUReport::RDSEED()); - support_message("RDTSCP", Dqn_RefImplCPUReport::RDTSCP()); - support_message("RTM", Dqn_RefImplCPUReport::RTM()); - support_message("SEP", Dqn_RefImplCPUReport::SEP()); - support_message("SHA", Dqn_RefImplCPUReport::SHA()); - support_message("SSE", Dqn_RefImplCPUReport::SSE()); - support_message("SSE2", Dqn_RefImplCPUReport::SSE2()); - support_message("SSE3", Dqn_RefImplCPUReport::SSE3()); - support_message("SSE4.1", Dqn_RefImplCPUReport::SSE41()); - support_message("SSE4.2", Dqn_RefImplCPUReport::SSE42()); - support_message("SSE4a", Dqn_RefImplCPUReport::SSE4a()); - support_message("SSSE3", Dqn_RefImplCPUReport::SSSE3()); - support_message("SYSCALL", Dqn_RefImplCPUReport::SYSCALL()); - support_message("TBM", Dqn_RefImplCPUReport::TBM()); - support_message("XOP", Dqn_RefImplCPUReport::XOP()); - support_message("XSAVE", Dqn_RefImplCPUReport::XSAVE()); + support_message("3DNOW", DN_RefImplCPUReport::_3DNOW()); + support_message("3DNOWEXT", DN_RefImplCPUReport::_3DNOWEXT()); + support_message("ABM", DN_RefImplCPUReport::ABM()); + support_message("ADX", DN_RefImplCPUReport::ADX()); + support_message("AES", DN_RefImplCPUReport::AES()); + support_message("AVX", DN_RefImplCPUReport::AVX()); + support_message("AVX2", DN_RefImplCPUReport::AVX2()); + support_message("AVX512CD", DN_RefImplCPUReport::AVX512CD()); + support_message("AVX512ER", DN_RefImplCPUReport::AVX512ER()); + support_message("AVX512F", DN_RefImplCPUReport::AVX512F()); + support_message("AVX512PF", DN_RefImplCPUReport::AVX512PF()); + support_message("BMI1", DN_RefImplCPUReport::BMI1()); + support_message("BMI2", DN_RefImplCPUReport::BMI2()); + support_message("CLFSH", DN_RefImplCPUReport::CLFSH()); + support_message("CMPXCHG16B", DN_RefImplCPUReport::CMPXCHG16B()); + support_message("CX8", DN_RefImplCPUReport::CX8()); + support_message("ERMS", DN_RefImplCPUReport::ERMS()); + support_message("F16C", DN_RefImplCPUReport::F16C()); + support_message("FMA", DN_RefImplCPUReport::FMA()); + support_message("FSGSBASE", DN_RefImplCPUReport::FSGSBASE()); + support_message("FXSR", DN_RefImplCPUReport::FXSR()); + support_message("HLE", DN_RefImplCPUReport::HLE()); + support_message("INVPCID", DN_RefImplCPUReport::INVPCID()); + support_message("LAHF", DN_RefImplCPUReport::LAHF()); + support_message("LZCNT", DN_RefImplCPUReport::LZCNT()); + support_message("MMX", DN_RefImplCPUReport::MMX()); + support_message("MMXEXT", DN_RefImplCPUReport::MMXEXT()); + support_message("MONITOR", DN_RefImplCPUReport::MONITOR()); + support_message("MOVBE", DN_RefImplCPUReport::MOVBE()); + support_message("MSR", DN_RefImplCPUReport::MSR()); + support_message("OSXSAVE", DN_RefImplCPUReport::OSXSAVE()); + support_message("PCLMULQDQ", DN_RefImplCPUReport::PCLMULQDQ()); + support_message("POPCNT", DN_RefImplCPUReport::POPCNT()); + support_message("PREFETCHWT1", DN_RefImplCPUReport::PREFETCHWT1()); + support_message("RDRAND", DN_RefImplCPUReport::RDRAND()); + support_message("RDSEED", DN_RefImplCPUReport::RDSEED()); + support_message("RDTSCP", DN_RefImplCPUReport::RDTSCP()); + support_message("RTM", DN_RefImplCPUReport::RTM()); + support_message("SEP", DN_RefImplCPUReport::SEP()); + support_message("SHA", DN_RefImplCPUReport::SHA()); + support_message("SSE", DN_RefImplCPUReport::SSE()); + support_message("SSE2", DN_RefImplCPUReport::SSE2()); + support_message("SSE3", DN_RefImplCPUReport::SSE3()); + support_message("SSE4.1", DN_RefImplCPUReport::SSE41()); + support_message("SSE4.2", DN_RefImplCPUReport::SSE42()); + support_message("SSE4a", DN_RefImplCPUReport::SSE4a()); + support_message("SSSE3", DN_RefImplCPUReport::SSSE3()); + support_message("SYSCALL", DN_RefImplCPUReport::SYSCALL()); + support_message("TBM", DN_RefImplCPUReport::TBM()); + support_message("XOP", DN_RefImplCPUReport::XOP()); + support_message("XSAVE", DN_RefImplCPUReport::XSAVE()); }; #endif -static Dqn_UTest Dqn_Test_Base() +static DN_UTest DN_Test_Base() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_Base") { - DQN_UTEST_TEST("Query CPUID") { - Dqn_CPUReport cpu_report = Dqn_CPU_Report(); + DN_RefImplCPUReport ref_cpu_report = DN_RefImplCPUReport_Init(); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_Base") { + DN_UTEST_TEST("Query CPUID") { + DN_CPUReport cpu_report = DN_CPU_Report(); // NOTE: Sanity check our report against MSDN's example //////////////////////////////////////// - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_3DNow) == Dqn_RefImplCPUReport::_3DNOW()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_3DNowExt) == Dqn_RefImplCPUReport::_3DNOWEXT()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_ABM) == Dqn_RefImplCPUReport::ABM()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_AES) == Dqn_RefImplCPUReport::AES()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_AVX) == Dqn_RefImplCPUReport::AVX()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_AVX2) == Dqn_RefImplCPUReport::AVX2()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_AVX512CD) == Dqn_RefImplCPUReport::AVX512CD()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_AVX512ER) == Dqn_RefImplCPUReport::AVX512ER()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_AVX512F) == Dqn_RefImplCPUReport::AVX512F()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_AVX512PF) == Dqn_RefImplCPUReport::AVX512PF()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_CMPXCHG16B) == Dqn_RefImplCPUReport::CMPXCHG16B()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_F16C) == Dqn_RefImplCPUReport::F16C()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_FMA) == Dqn_RefImplCPUReport::FMA()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_MMX) == Dqn_RefImplCPUReport::MMX()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_MmxExt) == Dqn_RefImplCPUReport::MMXEXT()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_MONITOR) == Dqn_RefImplCPUReport::MONITOR()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_MOVBE) == Dqn_RefImplCPUReport::MOVBE()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_PCLMULQDQ) == Dqn_RefImplCPUReport::PCLMULQDQ()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_POPCNT) == Dqn_RefImplCPUReport::POPCNT()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_RDRAND) == Dqn_RefImplCPUReport::RDRAND()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_RDSEED) == Dqn_RefImplCPUReport::RDSEED()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_RDTSCP) == Dqn_RefImplCPUReport::RDTSCP()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SHA) == Dqn_RefImplCPUReport::SHA()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SSE) == Dqn_RefImplCPUReport::SSE()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SSE2) == Dqn_RefImplCPUReport::SSE2()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SSE3) == Dqn_RefImplCPUReport::SSE3()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SSE41) == Dqn_RefImplCPUReport::SSE41()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SSE42) == Dqn_RefImplCPUReport::SSE42()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SSE4A) == Dqn_RefImplCPUReport::SSE4a()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SSSE3) == Dqn_RefImplCPUReport::SSSE3()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_3DNow) == ref_cpu_report._3DNOW()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_3DNowExt) == ref_cpu_report._3DNOWEXT()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_ABM) == ref_cpu_report.ABM()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AES) == ref_cpu_report.AES()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX) == ref_cpu_report.AVX()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX2) == ref_cpu_report.AVX2()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX512CD) == ref_cpu_report.AVX512CD()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX512ER) == ref_cpu_report.AVX512ER()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX512F) == ref_cpu_report.AVX512F()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX512PF) == ref_cpu_report.AVX512PF()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_CMPXCHG16B) == ref_cpu_report.CMPXCHG16B()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_F16C) == ref_cpu_report.F16C()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_FMA) == ref_cpu_report.FMA()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MMX) == ref_cpu_report.MMX()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MmxExt) == ref_cpu_report.MMXEXT()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MONITOR) == ref_cpu_report.MONITOR()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MOVBE) == ref_cpu_report.MOVBE()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_PCLMULQDQ) == ref_cpu_report.PCLMULQDQ()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_POPCNT) == ref_cpu_report.POPCNT()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_RDRAND) == ref_cpu_report.RDRAND()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_RDSEED) == ref_cpu_report.RDSEED()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_RDTSCP) == ref_cpu_report.RDTSCP()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SHA) == ref_cpu_report.SHA()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE) == ref_cpu_report.SSE()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE2) == ref_cpu_report.SSE2()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE3) == ref_cpu_report.SSE3()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE41) == ref_cpu_report.SSE41()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE42) == ref_cpu_report.SSE42()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE4A) == ref_cpu_report.SSE4a()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSSE3) == ref_cpu_report.SSSE3()); // NOTE: Feature flags we haven't bothered detecting yet but are in MSDN's example ///////////// #if 0 - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_ADX) == Dqn_RefImplCPUReport::ADX()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_BMI1) == Dqn_RefImplCPUReport::BMI1()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_BMI2) == Dqn_RefImplCPUReport::BMI2()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_CLFSH) == Dqn_RefImplCPUReport::CLFSH()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_CX8) == Dqn_RefImplCPUReport::CX8()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_ERMS) == Dqn_RefImplCPUReport::ERMS()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_FSGSBASE) == Dqn_RefImplCPUReport::FSGSBASE()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_FXSR) == Dqn_RefImplCPUReport::FXSR()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_HLE) == Dqn_RefImplCPUReport::HLE()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_INVPCID) == Dqn_RefImplCPUReport::INVPCID()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_LAHF) == Dqn_RefImplCPUReport::LAHF()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_LZCNT) == Dqn_RefImplCPUReport::LZCNT()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_MSR) == Dqn_RefImplCPUReport::MSR()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_OSXSAVE) == Dqn_RefImplCPUReport::OSXSAVE()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_PREFETCHWT1) == Dqn_RefImplCPUReport::PREFETCHWT1()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_RTM) == Dqn_RefImplCPUReport::RTM()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SEP) == Dqn_RefImplCPUReport::SEP()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_SYSCALL) == Dqn_RefImplCPUReport::SYSCALL()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_TBM) == Dqn_RefImplCPUReport::TBM()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_XOP) == Dqn_RefImplCPUReport::XOP()); - DQN_UTEST_ASSERT(&test, Dqn_CPU_HasFeature(&cpu_report, Dqn_CPUFeature_XSAVE) == Dqn_RefImplCPUReport::XSAVE()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_ADX) == DN_RefImplCPUReport::ADX()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_BMI1) == DN_RefImplCPUReport::BMI1()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_BMI2) == DN_RefImplCPUReport::BMI2()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_CLFSH) == DN_RefImplCPUReport::CLFSH()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_CX8) == DN_RefImplCPUReport::CX8()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_ERMS) == DN_RefImplCPUReport::ERMS()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_FSGSBASE) == DN_RefImplCPUReport::FSGSBASE()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_FXSR) == DN_RefImplCPUReport::FXSR()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_HLE) == DN_RefImplCPUReport::HLE()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_INVPCID) == DN_RefImplCPUReport::INVPCID()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_LAHF) == DN_RefImplCPUReport::LAHF()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_LZCNT) == DN_RefImplCPUReport::LZCNT()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MSR) == DN_RefImplCPUReport::MSR()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_OSXSAVE) == DN_RefImplCPUReport::OSXSAVE()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_PREFETCHWT1) == DN_RefImplCPUReport::PREFETCHWT1()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_RTM) == DN_RefImplCPUReport::RTM()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SEP) == DN_RefImplCPUReport::SEP()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SYSCALL) == DN_RefImplCPUReport::SYSCALL()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_TBM) == DN_RefImplCPUReport::TBM()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_XOP) == DN_RefImplCPUReport::XOP()); + DN_UTEST_ASSERT(&test, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_XSAVE) == DN_RefImplCPUReport::XSAVE()); #endif } @@ -329,180 +285,180 @@ static Dqn_UTest Dqn_Test_Base() return test; } -static Dqn_UTest Dqn_Test_Arena() +static DN_UTest DN_Test_Arena() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_Arena") { - DQN_UTEST_TEST("Reused memory is zeroed out") { + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_Arena") { + DN_UTEST_TEST("Reused memory is zeroed out") { uint8_t alignment = 1; - Dqn_usize alloc_size = DQN_KILOBYTES(128); - Dqn_Arena arena = {}; - DQN_DEFER { - Dqn_Arena_Deinit(&arena); + DN_USize alloc_size = DN_KILOBYTES(128); + DN_Arena arena = {}; + DN_DEFER { + DN_Arena_Deinit(&arena); }; // NOTE: Allocate 128 kilobytes, fill it with garbage, then reset the arena uintptr_t first_ptr_address = 0; { - Dqn_ArenaTempMem temp_mem = Dqn_Arena_TempMemBegin(&arena); - void *ptr = Dqn_Arena_Alloc(&arena, alloc_size, alignment, Dqn_ZeroMem_Yes); - first_ptr_address = DQN_CAST(uintptr_t)ptr; - DQN_MEMSET(ptr, 'z', alloc_size); - Dqn_Arena_TempMemEnd(temp_mem); + DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(&arena); + void *ptr = DN_Arena_Alloc(&arena, alloc_size, alignment, DN_ZeroMem_Yes); + first_ptr_address = DN_CAST(uintptr_t)ptr; + DN_MEMSET(ptr, 'z', alloc_size); + DN_Arena_TempMemEnd(temp_mem); } // NOTE: Reallocate 128 kilobytes - char *ptr = DQN_CAST(char *)Dqn_Arena_Alloc(&arena, alloc_size, alignment, Dqn_ZeroMem_Yes); + char *ptr = DN_CAST(char *)DN_Arena_Alloc(&arena, alloc_size, alignment, DN_ZeroMem_Yes); // NOTE: Double check we got the same pointer - DQN_UTEST_ASSERT(&test, first_ptr_address == DQN_CAST(uintptr_t)ptr); + DN_UTEST_ASSERT(&test, first_ptr_address == DN_CAST(uintptr_t)ptr); // NOTE: Check that the bytes are set to 0 - for (Dqn_usize i = 0; i < alloc_size; i++) - DQN_UTEST_ASSERT(&test, ptr[i] == 0); + for (DN_USize i = 0; i < alloc_size; i++) + DN_UTEST_ASSERT(&test, ptr[i] == 0); } - DQN_UTEST_TEST("Test arena grows naturally, 1mb + 4mb") { + DN_UTEST_TEST("Test arena grows naturally, 1mb + 4mb") { // NOTE: Allocate 1mb, then 4mb, this should force the arena to grow - Dqn_Arena arena = Dqn_Arena_InitSize(DQN_MEGABYTES(2), DQN_MEGABYTES(2), Dqn_ArenaFlag_Nil); - DQN_DEFER { - Dqn_Arena_Deinit(&arena); + DN_Arena arena = DN_Arena_InitSize(DN_MEGABYTES(2), DN_MEGABYTES(2), DN_ArenaFlags_Nil); + DN_DEFER { + DN_Arena_Deinit(&arena); }; - char *ptr_1mb = Dqn_Arena_NewArray(&arena, char, DQN_MEGABYTES(1), Dqn_ZeroMem_Yes); - char *ptr_4mb = Dqn_Arena_NewArray(&arena, char, DQN_MEGABYTES(4), Dqn_ZeroMem_Yes); - DQN_UTEST_ASSERT(&test, ptr_1mb); - DQN_UTEST_ASSERT(&test, ptr_4mb); + char *ptr_1mb = DN_Arena_NewArray(&arena, char, DN_MEGABYTES(1), DN_ZeroMem_Yes); + char *ptr_4mb = DN_Arena_NewArray(&arena, char, DN_MEGABYTES(4), DN_ZeroMem_Yes); + DN_UTEST_ASSERT(&test, ptr_1mb); + DN_UTEST_ASSERT(&test, ptr_4mb); - Dqn_ArenaBlock const *block_4mb_begin = arena.curr; - char const *block_4mb_end = DQN_CAST(char *)block_4mb_begin + block_4mb_begin->reserve; + DN_ArenaBlock const *block_4mb_begin = arena.curr; + char const *block_4mb_end = DN_CAST(char *)block_4mb_begin + block_4mb_begin->reserve; - Dqn_ArenaBlock const *block_1mb_begin = block_4mb_begin->prev; - DQN_UTEST_ASSERTF(&test, block_1mb_begin, "New block should have been allocated"); - char const *block_1mb_end = DQN_CAST(char *)block_1mb_begin + block_1mb_begin->reserve; + DN_ArenaBlock const *block_1mb_begin = block_4mb_begin->prev; + DN_UTEST_ASSERTF(&test, block_1mb_begin, "New block should have been allocated"); + char const *block_1mb_end = DN_CAST(char *)block_1mb_begin + block_1mb_begin->reserve; - DQN_UTEST_ASSERTF(&test, block_1mb_begin != block_4mb_begin, "New block should have been allocated and linked"); - DQN_UTEST_ASSERTF(&test, ptr_1mb >= DQN_CAST(char *)block_1mb_begin && ptr_1mb <= block_1mb_end, "Pointer was not allocated from correct memory block"); - DQN_UTEST_ASSERTF(&test, ptr_4mb >= DQN_CAST(char *)block_4mb_begin && ptr_4mb <= block_4mb_end, "Pointer was not allocated from correct memory block"); + DN_UTEST_ASSERTF(&test, block_1mb_begin != block_4mb_begin, "New block should have been allocated and linked"); + DN_UTEST_ASSERTF(&test, ptr_1mb >= DN_CAST(char *)block_1mb_begin && ptr_1mb <= block_1mb_end, "Pointer was not allocated from correct memory block"); + DN_UTEST_ASSERTF(&test, ptr_4mb >= DN_CAST(char *)block_4mb_begin && ptr_4mb <= block_4mb_end, "Pointer was not allocated from correct memory block"); } - DQN_UTEST_TEST("Test arena grows naturally, 1mb, temp memory 4mb") { - Dqn_Arena arena = Dqn_Arena_InitSize(DQN_MEGABYTES(2), DQN_MEGABYTES(2), Dqn_ArenaFlag_Nil); - DQN_DEFER { - Dqn_Arena_Deinit(&arena); + DN_UTEST_TEST("Test arena grows naturally, 1mb, temp memory 4mb") { + DN_Arena arena = DN_Arena_InitSize(DN_MEGABYTES(2), DN_MEGABYTES(2), DN_ArenaFlags_Nil); + DN_DEFER { + DN_Arena_Deinit(&arena); }; // NOTE: Allocate 1mb, then 4mb, this should force the arena to grow - char *ptr_1mb = DQN_CAST(char *)Dqn_Arena_Alloc(&arena, DQN_MEGABYTES(1), 1 /*align*/, Dqn_ZeroMem_Yes); - DQN_UTEST_ASSERT(&test, ptr_1mb); + char *ptr_1mb = DN_CAST(char *)DN_Arena_Alloc(&arena, DN_MEGABYTES(1), 1 /*align*/, DN_ZeroMem_Yes); + DN_UTEST_ASSERT(&test, ptr_1mb); - Dqn_ArenaTempMem temp_memory = Dqn_Arena_TempMemBegin(&arena); + DN_ArenaTempMem temp_memory = DN_Arena_TempMemBegin(&arena); { - char *ptr_4mb = Dqn_Arena_NewArray(&arena, char, DQN_MEGABYTES(4), Dqn_ZeroMem_Yes); - DQN_UTEST_ASSERT(&test, ptr_4mb); + char *ptr_4mb = DN_Arena_NewArray(&arena, char, DN_MEGABYTES(4), DN_ZeroMem_Yes); + DN_UTEST_ASSERT(&test, ptr_4mb); - Dqn_ArenaBlock const *block_4mb_begin = arena.curr; - char const *block_4mb_end = DQN_CAST(char *) block_4mb_begin + block_4mb_begin->reserve; + DN_ArenaBlock const *block_4mb_begin = arena.curr; + char const *block_4mb_end = DN_CAST(char *) block_4mb_begin + block_4mb_begin->reserve; - Dqn_ArenaBlock const *block_1mb_begin = block_4mb_begin->prev; - char const *block_1mb_end = DQN_CAST(char *) block_1mb_begin + block_1mb_begin->reserve; + DN_ArenaBlock const *block_1mb_begin = block_4mb_begin->prev; + char const *block_1mb_end = DN_CAST(char *) block_1mb_begin + block_1mb_begin->reserve; - DQN_UTEST_ASSERTF(&test, block_1mb_begin != block_4mb_begin, "New block should have been allocated and linked"); - DQN_UTEST_ASSERTF(&test, ptr_1mb >= DQN_CAST(char *)block_1mb_begin && ptr_1mb <= block_1mb_end, "Pointer was not allocated from correct memory block"); - DQN_UTEST_ASSERTF(&test, ptr_4mb >= DQN_CAST(char *)block_4mb_begin && ptr_4mb <= block_4mb_end, "Pointer was not allocated from correct memory block"); + DN_UTEST_ASSERTF(&test, block_1mb_begin != block_4mb_begin, "New block should have been allocated and linked"); + DN_UTEST_ASSERTF(&test, ptr_1mb >= DN_CAST(char *)block_1mb_begin && ptr_1mb <= block_1mb_end, "Pointer was not allocated from correct memory block"); + DN_UTEST_ASSERTF(&test, ptr_4mb >= DN_CAST(char *)block_4mb_begin && ptr_4mb <= block_4mb_end, "Pointer was not allocated from correct memory block"); } - Dqn_Arena_TempMemEnd(temp_memory); - DQN_UTEST_ASSERT (&test, arena.curr->prev == nullptr); - DQN_UTEST_ASSERTF(&test, - arena.curr->reserve >= DQN_MEGABYTES(1), + DN_Arena_TempMemEnd(temp_memory); + DN_UTEST_ASSERT (&test, arena.curr->prev == nullptr); + DN_UTEST_ASSERTF(&test, + arena.curr->reserve >= DN_MEGABYTES(1), "size=%" PRIu64 "MiB (%" PRIu64 "B), expect=%" PRIu64 "B", (arena.curr->reserve / 1024 / 1024), arena.curr->reserve, - DQN_MEGABYTES(1)); + DN_MEGABYTES(1)); } } return test; } -static Dqn_UTest Dqn_Test_Bin() +static DN_UTest DN_Test_Bin() { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_Bin") { - DQN_UTEST_TEST("Convert 0x123") { - uint64_t result = Dqn_HexToU64(DQN_STR8("0x123")); - DQN_UTEST_ASSERTF(&test, result == 0x123, "result: %" PRIu64, result); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_Bin") { + DN_UTEST_TEST("Convert 0x123") { + uint64_t result = DN_HexToU64(DN_STR8("0x123")); + DN_UTEST_ASSERTF(&test, result == 0x123, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert 0xFFFF") { - uint64_t result = Dqn_HexToU64(DQN_STR8("0xFFFF")); - DQN_UTEST_ASSERTF(&test, result == 0xFFFF, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert 0xFFFF") { + uint64_t result = DN_HexToU64(DN_STR8("0xFFFF")); + DN_UTEST_ASSERTF(&test, result == 0xFFFF, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert FFFF") { - uint64_t result = Dqn_HexToU64(DQN_STR8("FFFF")); - DQN_UTEST_ASSERTF(&test, result == 0xFFFF, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert FFFF") { + uint64_t result = DN_HexToU64(DN_STR8("FFFF")); + DN_UTEST_ASSERTF(&test, result == 0xFFFF, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert abCD") { - uint64_t result = Dqn_HexToU64(DQN_STR8("abCD")); - DQN_UTEST_ASSERTF(&test, result == 0xabCD, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert abCD") { + uint64_t result = DN_HexToU64(DN_STR8("abCD")); + DN_UTEST_ASSERTF(&test, result == 0xabCD, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert 0xabCD") { - uint64_t result = Dqn_HexToU64(DQN_STR8("0xabCD")); - DQN_UTEST_ASSERTF(&test, result == 0xabCD, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert 0xabCD") { + uint64_t result = DN_HexToU64(DN_STR8("0xabCD")); + DN_UTEST_ASSERTF(&test, result == 0xabCD, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert 0x") { - uint64_t result = Dqn_HexToU64(DQN_STR8("0x")); - DQN_UTEST_ASSERTF(&test, result == 0x0, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert 0x") { + uint64_t result = DN_HexToU64(DN_STR8("0x")); + DN_UTEST_ASSERTF(&test, result == 0x0, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert 0X") { - uint64_t result = Dqn_HexToU64(DQN_STR8("0X")); - DQN_UTEST_ASSERTF(&test, result == 0x0, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert 0X") { + uint64_t result = DN_HexToU64(DN_STR8("0X")); + DN_UTEST_ASSERTF(&test, result == 0x0, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert 3") { - uint64_t result = Dqn_HexToU64(DQN_STR8("3")); - DQN_UTEST_ASSERTF(&test, result == 3, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert 3") { + uint64_t result = DN_HexToU64(DN_STR8("3")); + DN_UTEST_ASSERTF(&test, result == 3, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert f") { - uint64_t result = Dqn_HexToU64(DQN_STR8("f")); - DQN_UTEST_ASSERTF(&test, result == 0xf, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert f") { + uint64_t result = DN_HexToU64(DN_STR8("f")); + DN_UTEST_ASSERTF(&test, result == 0xf, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert g") { - uint64_t result = Dqn_HexToU64(DQN_STR8("g")); - DQN_UTEST_ASSERTF(&test, result == 0, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert g") { + uint64_t result = DN_HexToU64(DN_STR8("g")); + DN_UTEST_ASSERTF(&test, result == 0, "result: %" PRIu64, result); } - DQN_UTEST_TEST("Convert -0x3") { - uint64_t result = Dqn_HexToU64(DQN_STR8("-0x3")); - DQN_UTEST_ASSERTF(&test, result == 0, "result: %" PRIu64, result); + DN_UTEST_TEST("Convert -0x3") { + uint64_t result = DN_HexToU64(DN_STR8("-0x3")); + DN_UTEST_ASSERTF(&test, result == 0, "result: %" PRIu64, result); } uint32_t number = 0xd095f6; - DQN_UTEST_TEST("Convert %x to string", number) { - Dqn_Str8 number_hex = Dqn_BytesToHex(tmem.arena, &number, sizeof(number)); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(number_hex, DQN_STR8("f695d000")), "number_hex=%.*s", DQN_STR_FMT(number_hex)); + DN_UTEST_TEST("Convert %x to string", number) { + DN_Str8 number_hex = DN_BytesToHex(tmem.arena, &number, sizeof(number)); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(number_hex, DN_STR8("f695d000")), "number_hex=%.*s", DN_STR_FMT(number_hex)); } number = 0xf6ed00; - DQN_UTEST_TEST("Convert %x to string", number) { - Dqn_Str8 number_hex = Dqn_BytesToHex(tmem.arena, &number, sizeof(number)); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(number_hex, DQN_STR8("00edf600")), "number_hex=%.*s", DQN_STR_FMT(number_hex)); + DN_UTEST_TEST("Convert %x to string", number) { + DN_Str8 number_hex = DN_BytesToHex(tmem.arena, &number, sizeof(number)); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(number_hex, DN_STR8("00edf600")), "number_hex=%.*s", DN_STR_FMT(number_hex)); } - Dqn_Str8 hex = DQN_STR8("0xf6ed00"); - DQN_UTEST_TEST("Convert %.*s to bytes", DQN_STR_FMT(hex)) { - Dqn_Str8 bytes = Dqn_HexToBytes(tmem.arena, hex); - DQN_UTEST_ASSERTF(&test, - Dqn_Str8_Eq(bytes, DQN_STR8("\xf6\xed\x00")), + DN_Str8 hex = DN_STR8("0xf6ed00"); + DN_UTEST_TEST("Convert %.*s to bytes", DN_STR_FMT(hex)) { + DN_Str8 bytes = DN_HexToBytes(tmem.arena, hex); + DN_UTEST_ASSERTF(&test, + DN_Str8_Eq(bytes, DN_STR8("\xf6\xed\x00")), "number_hex=%.*s", - DQN_STR_FMT(Dqn_BytesToHex(tmem.arena, bytes.data, bytes.size))); + DN_STR_FMT(DN_BytesToHex(tmem.arena, bytes.data, bytes.size))); } } @@ -510,459 +466,459 @@ static Dqn_UTest Dqn_Test_Bin() } -static Dqn_UTest Dqn_Test_BinarySearch() +static DN_UTest DN_Test_BinarySearch() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_BinarySearch") { - DQN_UTEST_TEST("Search array of 1 item") { + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_BinarySearch") { + DN_UTEST_TEST("Search array of 1 item") { uint32_t array[] = {1}; - Dqn_BinarySearchResult result = {}; + DN_BinarySearchResult result = {}; // NOTE: Match ============================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 1); // NOTE: Lower bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 1); // NOTE: Upper bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 1); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 1); } - DQN_UTEST_TEST("Search array of 2 items") { + DN_UTEST_TEST("Search array of 2 items") { uint32_t array[] = {1}; - Dqn_BinarySearchResult result = {}; + DN_BinarySearchResult result = {}; // NOTE: Match ============================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 1); // NOTE: Lower bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 1); // NOTE: Upper bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 1); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 1); } - DQN_UTEST_TEST("Search array of 3 items") { + DN_UTEST_TEST("Search array of 3 items") { uint32_t array[] = {1, 2, 3}; - Dqn_BinarySearchResult result = {}; + DN_BinarySearchResult result = {}; // NOTE: Match ============================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 1); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 3); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 3); // NOTE: Lower bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 1); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 3); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 3); // NOTE: Upper bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 1); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 3); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 3); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 3); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 3); } - DQN_UTEST_TEST("Search array of 4 items") { + DN_UTEST_TEST("Search array of 4 items") { uint32_t array[] = {1, 2, 3, 4}; - Dqn_BinarySearchResult result = {}; + DN_BinarySearchResult result = {}; // NOTE: Match ============================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 1); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 3); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 3); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 5U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 4); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 5U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 4); // NOTE: Lower bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 1); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 3); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 3); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 5U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 4); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 5U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 4); // NOTE: Upper bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 1); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 1); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 3); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 3); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 4); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 4); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 5U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 4); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 5U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 4); } - DQN_UTEST_TEST("Search array with duplicate items") { + DN_UTEST_TEST("Search array with duplicate items") { uint32_t array[] = {1, 1, 2, 2, 3}; - Dqn_BinarySearchResult result = {}; + DN_BinarySearchResult result = {}; // NOTE: Match ============================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 4); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 4); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_Match); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 5); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4U /*find*/, DN_BinarySearchType_Match); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 5); // NOTE: Lower bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 4); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 4); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4U /*find*/, Dqn_BinarySearchType_LowerBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 5); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4U /*find*/, DN_BinarySearchType_LowerBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 5); // NOTE: Upper bound ======================================================================= - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 0U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 0U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 0); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 1U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 1U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 2U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 4); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 2U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 4); - result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 3U /*find*/, Dqn_BinarySearchType_UpperBound); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 5); + result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 3U /*find*/, DN_BinarySearchType_UpperBound); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 5); } } return test; } -static Dqn_UTest Dqn_Test_DSMap() +static DN_UTest DN_Test_DSMap() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_DSMap") { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_DSMap") { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); { - Dqn_Arena arena = {}; + DN_Arena arena = {}; uint32_t const MAP_SIZE = 64; - Dqn_DSMap map = Dqn_DSMap_Init(&arena, MAP_SIZE, Dqn_DSMapFlags_Nil); - DQN_DEFER { Dqn_DSMap_Deinit(&map, Dqn_ZeroMem_Yes); }; + DN_DSMap map = DN_DSMap_Init(&arena, MAP_SIZE, DN_DSMapFlags_Nil); + DN_DEFER { DN_DSMap_Deinit(&map, DN_ZeroMem_Yes); }; - DQN_UTEST_TEST("Find non-existent value") { - uint64_t *value = Dqn_DSMap_FindKeyStr8(&map, DQN_STR8("Foo")).value; - DQN_UTEST_ASSERT(&test, !value); - DQN_UTEST_ASSERT(&test, map.size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); + DN_UTEST_TEST("Find non-existent value") { + DN_DSMapResult find = DN_DSMap_FindKeyStr8(&map, DN_STR8("Foo")); + DN_UTEST_ASSERT(&test, !find.found); + DN_UTEST_ASSERT(&test, map.size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); } - Dqn_DSMapKey key = Dqn_DSMap_KeyCStr8(&map, "Bar"); - DQN_UTEST_TEST("Insert value and lookup") { + DN_DSMapKey key = DN_DSMap_KeyCStr8(&map, "Bar"); + DN_UTEST_TEST("Insert value and lookup") { uint64_t desired_value = 0xF00BAA; - uint64_t *slot_value = Dqn_DSMap_Set(&map, key, desired_value).value; - DQN_UTEST_ASSERT(&test, slot_value); - DQN_UTEST_ASSERT(&test, map.size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.occupied == 2); + uint64_t *slot_value = DN_DSMap_Set(&map, key, desired_value).value; + DN_UTEST_ASSERT(&test, slot_value); + DN_UTEST_ASSERT(&test, map.size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.occupied == 2); - uint64_t *value = Dqn_DSMap_Find(&map, key).value; - DQN_UTEST_ASSERT(&test, value); - DQN_UTEST_ASSERT(&test, *value == desired_value); + uint64_t *value = DN_DSMap_Find(&map, key).value; + DN_UTEST_ASSERT(&test, value); + DN_UTEST_ASSERT(&test, *value == desired_value); } - DQN_UTEST_TEST("Remove key") { - Dqn_DSMap_Erase(&map, key); - DQN_UTEST_ASSERT(&test, map.size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); + DN_UTEST_TEST("Remove key") { + DN_DSMap_Erase(&map, key); + DN_UTEST_ASSERT(&test, map.size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); } } enum DSMapTestType { DSMapTestType_Set, DSMapTestType_MakeSlot, DSMapTestType_Count }; for (int test_type = 0; test_type < DSMapTestType_Count; test_type++) { - Dqn_Str8 prefix = {}; + DN_Str8 prefix = {}; switch (test_type) { - case DSMapTestType_Set: prefix = DQN_STR8("Set"); break; - case DSMapTestType_MakeSlot: prefix = DQN_STR8("Make slot"); break; + case DSMapTestType_Set: prefix = DN_STR8("Set"); break; + case DSMapTestType_MakeSlot: prefix = DN_STR8("Make slot"); break; } - Dqn_ArenaTempMemScope temp_mem_scope = Dqn_ArenaTempMemScope(tmem.arena); - Dqn_Arena arena = {}; + DN_ArenaTempMemScope temp_mem_scope = DN_ArenaTempMemScope(tmem.arena); + DN_Arena arena = {}; uint32_t const MAP_SIZE = 64; - Dqn_DSMap map = Dqn_DSMap_Init(&arena, MAP_SIZE, Dqn_DSMapFlags_Nil); - DQN_DEFER { Dqn_DSMap_Deinit(&map, Dqn_ZeroMem_Yes); }; + DN_DSMap map = DN_DSMap_Init(&arena, MAP_SIZE, DN_DSMapFlags_Nil); + DN_DEFER { DN_DSMap_Deinit(&map, DN_ZeroMem_Yes); }; - DQN_UTEST_TEST("%.*s: Test growing", DQN_STR_FMT(prefix)) { + DN_UTEST_TEST("%.*s: Test growing", DN_STR_FMT(prefix)) { uint64_t map_start_size = map.size; uint64_t value = 0; uint64_t grow_threshold = map_start_size * 3 / 4; for (; map.occupied != grow_threshold; value++) { - Dqn_DSMapKey key = Dqn_DSMap_KeyU64(&map, value); - DQN_UTEST_ASSERT(&test, !Dqn_DSMap_Find(&map, key).value); - Dqn_DSMapResult make_result = {}; + DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); + DN_UTEST_ASSERT(&test, !DN_DSMap_Find(&map, key).found); + DN_DSMapResult make_result = {}; if (test_type == DSMapTestType_Set) { - make_result = Dqn_DSMap_Set(&map, key, value); + make_result = DN_DSMap_Set(&map, key, value); } else { - make_result = Dqn_DSMap_Make(&map, key); + make_result = DN_DSMap_Make(&map, key); } - DQN_UTEST_ASSERT(&test, !make_result.found); - DQN_UTEST_ASSERT(&test, Dqn_DSMap_Find(&map, key).value); + DN_UTEST_ASSERT(&test, !make_result.found); + DN_UTEST_ASSERT(&test, DN_DSMap_Find(&map, key).value); } - DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.size == map_start_size); - DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/ + value); + DN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.size == map_start_size); + DN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/ + value); { // NOTE: One more item should cause the table to grow by 2x - Dqn_DSMapKey key = Dqn_DSMap_KeyU64(&map, value); - Dqn_DSMapResult make_result = {}; + DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); + DN_DSMapResult make_result = {}; if (test_type == DSMapTestType_Set) { - make_result = Dqn_DSMap_Set(&map, key, value); + make_result = DN_DSMap_Set(&map, key, value); } else { - make_result = Dqn_DSMap_Make(&map, key); + make_result = DN_DSMap_Make(&map, key); } value++; - DQN_UTEST_ASSERT(&test, !make_result.found); - DQN_UTEST_ASSERT(&test, map.size == map_start_size * 2); - DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/ + value); + DN_UTEST_ASSERT(&test, !make_result.found); + DN_UTEST_ASSERT(&test, map.size == map_start_size * 2); + DN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/ + value); } } - DQN_UTEST_TEST("%.*s: Check the sentinel is present", DQN_STR_FMT(prefix)) { - Dqn_DSMapSlot NIL_SLOT = {}; - Dqn_DSMapSlot sentinel = map.slots[DQN_DS_MAP_SENTINEL_SLOT]; - DQN_UTEST_ASSERT(&test, DQN_MEMCMP(&sentinel, &NIL_SLOT, sizeof(NIL_SLOT)) == 0); + DN_UTEST_TEST("%.*s: Check the sentinel is present", DN_STR_FMT(prefix)) { + DN_DSMapSlot NIL_SLOT = {}; + DN_DSMapSlot sentinel = map.slots[DN_DS_MAP_SENTINEL_SLOT]; + DN_UTEST_ASSERT(&test, DN_MEMCMP(&sentinel, &NIL_SLOT, sizeof(NIL_SLOT)) == 0); } - DQN_UTEST_TEST("%.*s: Recheck all the hash tables values after growing", DQN_STR_FMT(prefix)) { + DN_UTEST_TEST("%.*s: Recheck all the hash tables values after growing", DN_STR_FMT(prefix)) { for (uint64_t index = 1 /*Sentinel*/; index < map.occupied; index++) { - Dqn_DSMapSlot const *slot = map.slots + index; + DN_DSMapSlot const *slot = map.slots + index; // NOTE: Validate each slot value uint64_t value_test = index - 1; - Dqn_DSMapKey key = Dqn_DSMap_KeyU64(&map, value_test); - DQN_UTEST_ASSERT(&test, Dqn_DSMap_KeyEquals(slot->key, key)); + DN_DSMapKey key = DN_DSMap_KeyU64(&map, value_test); + DN_UTEST_ASSERT(&test, DN_DSMap_KeyEquals(slot->key, key)); if (test_type == DSMapTestType_Set) { - DQN_UTEST_ASSERT(&test, slot->value == value_test); + DN_UTEST_ASSERT(&test, slot->value == value_test); } else { - DQN_UTEST_ASSERT(&test, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 + DN_UTEST_ASSERT(&test, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 } - DQN_UTEST_ASSERT(&test, slot->key.hash == Dqn_DSMap_Hash(&map, slot->key)); + DN_UTEST_ASSERT(&test, slot->key.hash == DN_DSMap_Hash(&map, slot->key)); // NOTE: Check the reverse lookup is correct - Dqn_DSMapResult check = Dqn_DSMap_Find(&map, slot->key); - DQN_UTEST_ASSERT(&test, slot->value == *check.value); + DN_DSMapResult check = DN_DSMap_Find(&map, slot->key); + DN_UTEST_ASSERT(&test, slot->value == *check.value); } } - DQN_UTEST_TEST("%.*s: Test shrinking", DQN_STR_FMT(prefix)) { + DN_UTEST_TEST("%.*s: Test shrinking", DN_STR_FMT(prefix)) { uint64_t start_map_size = map.size; uint64_t start_map_occupied = map.occupied; uint64_t value = 0; uint64_t shrink_threshold = map.size * 1 / 4; for (; map.occupied != shrink_threshold; value++) { - Dqn_DSMapKey key = Dqn_DSMap_KeyU64(&map, value); - DQN_UTEST_ASSERT(&test, Dqn_DSMap_Find(&map, key).value); - Dqn_DSMap_Erase(&map, key); - DQN_UTEST_ASSERT(&test, !Dqn_DSMap_Find(&map, key).value); + DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); + DN_UTEST_ASSERT(&test, DN_DSMap_Find(&map, key).found); + DN_DSMap_Erase(&map, key); + DN_UTEST_ASSERT(&test, !DN_DSMap_Find(&map, key).found); } - DQN_UTEST_ASSERT(&test, map.size == start_map_size); - DQN_UTEST_ASSERT(&test, map.occupied == start_map_occupied - value); + DN_UTEST_ASSERT(&test, map.size == start_map_size); + DN_UTEST_ASSERT(&test, map.occupied == start_map_occupied - value); { // NOTE: One more item should cause the table to shrink by 2x - Dqn_DSMapKey key = Dqn_DSMap_KeyU64(&map, value); - Dqn_DSMap_Erase(&map, key); + DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); + DN_DSMap_Erase(&map, key); value++; - DQN_UTEST_ASSERT(&test, map.size == start_map_size / 2); - DQN_UTEST_ASSERT(&test, map.occupied == start_map_occupied - value); + DN_UTEST_ASSERT(&test, map.size == start_map_size / 2); + DN_UTEST_ASSERT(&test, map.occupied == start_map_occupied - value); } { // NOTE: Check the sentinel is present - Dqn_DSMapSlot NIL_SLOT = {}; - Dqn_DSMapSlot sentinel = map.slots[DQN_DS_MAP_SENTINEL_SLOT]; - DQN_UTEST_ASSERT(&test, DQN_MEMCMP(&sentinel, &NIL_SLOT, sizeof(NIL_SLOT)) == 0); + DN_DSMapSlot NIL_SLOT = {}; + DN_DSMapSlot sentinel = map.slots[DN_DS_MAP_SENTINEL_SLOT]; + DN_UTEST_ASSERT(&test, DN_MEMCMP(&sentinel, &NIL_SLOT, sizeof(NIL_SLOT)) == 0); } // NOTE: Recheck all the hash table values after shrinking @@ -970,171 +926,171 @@ static Dqn_UTest Dqn_Test_DSMap() // NOTE: Generate the key uint64_t value_test = value + (index - 1); - Dqn_DSMapKey key = Dqn_DSMap_KeyU64(&map, value_test); + DN_DSMapKey key = DN_DSMap_KeyU64(&map, value_test); // NOTE: Validate each slot value - Dqn_DSMapResult find_result = Dqn_DSMap_Find(&map, key); - DQN_UTEST_ASSERT(&test, find_result.value); - DQN_UTEST_ASSERT(&test, find_result.slot->key == key); + DN_DSMapResult find_result = DN_DSMap_Find(&map, key); + DN_UTEST_ASSERT(&test, find_result.value); + DN_UTEST_ASSERT(&test, find_result.slot->key == key); if (test_type == DSMapTestType_Set) { - DQN_UTEST_ASSERT(&test, *find_result.value == value_test); + DN_UTEST_ASSERT(&test, *find_result.value == value_test); } else { - DQN_UTEST_ASSERT(&test, *find_result.value == 0); // NOTE: Make slot does not set the key so should be 0 + DN_UTEST_ASSERT(&test, *find_result.value == 0); // NOTE: Make slot does not set the key so should be 0 } - DQN_UTEST_ASSERT(&test, find_result.slot->key.hash == Dqn_DSMap_Hash(&map, find_result.slot->key)); + DN_UTEST_ASSERT(&test, find_result.slot->key.hash == DN_DSMap_Hash(&map, find_result.slot->key)); // NOTE: Check the reverse lookup is correct - Dqn_DSMapResult check = Dqn_DSMap_Find(&map, find_result.slot->key); - DQN_UTEST_ASSERT(&test, *find_result.value == *check.value); + DN_DSMapResult check = DN_DSMap_Find(&map, find_result.slot->key); + DN_UTEST_ASSERT(&test, *find_result.value == *check.value); } for (; map.occupied != 1; value++) { // NOTE: Remove all items from the table - Dqn_DSMapKey key = Dqn_DSMap_KeyU64(&map, value); - DQN_UTEST_ASSERT(&test, Dqn_DSMap_Find(&map, key).value); - Dqn_DSMap_Erase(&map, key); - DQN_UTEST_ASSERT(&test, !Dqn_DSMap_Find(&map, key).value); + DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); + DN_UTEST_ASSERT(&test, DN_DSMap_Find(&map, key).found); + DN_DSMap_Erase(&map, key); + DN_UTEST_ASSERT(&test, !DN_DSMap_Find(&map, key).found); } - DQN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); - DQN_UTEST_ASSERT(&test, map.size == map.initial_size); - DQN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); + DN_UTEST_ASSERT(&test, map.initial_size == MAP_SIZE); + DN_UTEST_ASSERT(&test, map.size == map.initial_size); + DN_UTEST_ASSERT(&test, map.occupied == 1 /*Sentinel*/); } } } return test; } -static Dqn_UTest Dqn_Test_FStr8() +static DN_UTest DN_Test_FStr8() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_FStr8") { - DQN_UTEST_TEST("Append too much fails") { - Dqn_FStr8<4> str = {}; - DQN_UTEST_ASSERT(&test, !Dqn_FStr8_Add(&str, DQN_STR8("abcde"))); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_FStr8") { + DN_UTEST_TEST("Append too much fails") { + DN_FStr8<4> str = {}; + DN_UTEST_ASSERT(&test, !DN_FStr8_Add(&str, DN_STR8("abcde"))); } - DQN_UTEST_TEST("Append format string too much fails") { - Dqn_FStr8<4> str = {}; - DQN_UTEST_ASSERT(&test, !Dqn_FStr8_AddF(&str, "abcde")); + DN_UTEST_TEST("Append format string too much fails") { + DN_FStr8<4> str = {}; + DN_UTEST_ASSERT(&test, !DN_FStr8_AddF(&str, "abcde")); } } return test; } -static Dqn_UTest Dqn_Test_Fs() +static DN_UTest DN_Test_Fs() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_OS_[Path|File]") { - DQN_UTEST_TEST("Make directory recursive \"abcd/efgh\"") { - DQN_UTEST_ASSERTF(&test, Dqn_OS_MakeDir(DQN_STR8("abcd/efgh")), "Failed to make directory"); - DQN_UTEST_ASSERTF(&test, Dqn_OS_DirExists(DQN_STR8("abcd")), "Directory was not made"); - DQN_UTEST_ASSERTF(&test, Dqn_OS_DirExists(DQN_STR8("abcd/efgh")), "Subdirectory was not made"); - DQN_UTEST_ASSERTF(&test, Dqn_OS_FileExists(DQN_STR8("abcd")) == false, "This function should only return true for files"); - DQN_UTEST_ASSERTF(&test, Dqn_OS_FileExists(DQN_STR8("abcd/efgh")) == false, "This function should only return true for files"); - DQN_UTEST_ASSERTF(&test, Dqn_OS_PathDelete(DQN_STR8("abcd/efgh")), "Failed to delete directory"); - DQN_UTEST_ASSERTF(&test, Dqn_OS_PathDelete(DQN_STR8("abcd")), "Failed to cleanup directory"); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_OS_[Path|File]") { + DN_UTEST_TEST("Make directory recursive \"abcd/efgh\"") { + DN_UTEST_ASSERTF(&test, DN_OS_MakeDir(DN_STR8("abcd/efgh")), "Failed to make directory"); + DN_UTEST_ASSERTF(&test, DN_OS_DirExists(DN_STR8("abcd")), "Directory was not made"); + DN_UTEST_ASSERTF(&test, DN_OS_DirExists(DN_STR8("abcd/efgh")), "Subdirectory was not made"); + DN_UTEST_ASSERTF(&test, DN_OS_FileExists(DN_STR8("abcd")) == false, "This function should only return true for files"); + DN_UTEST_ASSERTF(&test, DN_OS_FileExists(DN_STR8("abcd/efgh")) == false, "This function should only return true for files"); + DN_UTEST_ASSERTF(&test, DN_OS_PathDelete(DN_STR8("abcd/efgh")), "Failed to delete directory"); + DN_UTEST_ASSERTF(&test, DN_OS_PathDelete(DN_STR8("abcd")), "Failed to cleanup directory"); } - DQN_UTEST_TEST("File write, read, copy, move and delete") { + DN_UTEST_TEST("File write, read, copy, move and delete") { // NOTE: Write step - Dqn_Str8 const SRC_FILE = DQN_STR8("dqn_test_file"); - Dqn_b32 write_result = Dqn_OS_WriteAll(SRC_FILE, DQN_STR8("test"), nullptr); - DQN_UTEST_ASSERT(&test, write_result); - DQN_UTEST_ASSERT(&test, Dqn_OS_FileExists(SRC_FILE)); + DN_Str8 const SRC_FILE = DN_STR8("dqn_test_file"); + DN_B32 write_result = DN_OS_WriteAll(SRC_FILE, DN_STR8("test"), nullptr); + DN_UTEST_ASSERT(&test, write_result); + DN_UTEST_ASSERT(&test, DN_OS_FileExists(SRC_FILE)); // NOTE: Read step - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 read_file = Dqn_OS_ReadAll(tmem.arena, SRC_FILE, nullptr); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_HasData(read_file), "Failed to load file"); - DQN_UTEST_ASSERTF(&test, read_file.size == 4, "File read wrong amount of bytes"); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(read_file, DQN_STR8("test")), "read(%zu): %.*s", read_file.size, DQN_STR_FMT(read_file)); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 read_file = DN_OS_ReadAll(tmem.arena, SRC_FILE, nullptr); + DN_UTEST_ASSERTF(&test, DN_Str8_HasData(read_file), "Failed to load file"); + DN_UTEST_ASSERTF(&test, read_file.size == 4, "File read wrong amount of bytes"); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(read_file, DN_STR8("test")), "read(%zu): %.*s", read_file.size, DN_STR_FMT(read_file)); // NOTE: Copy step - Dqn_Str8 const COPY_FILE = DQN_STR8("dqn_test_file_copy"); - Dqn_b32 copy_result = Dqn_OS_CopyFile(SRC_FILE, COPY_FILE, true /*overwrite*/, nullptr); - DQN_UTEST_ASSERT(&test, copy_result); - DQN_UTEST_ASSERT(&test, Dqn_OS_FileExists(COPY_FILE)); + DN_Str8 const COPY_FILE = DN_STR8("dqn_test_file_copy"); + DN_B32 copy_result = DN_OS_CopyFile(SRC_FILE, COPY_FILE, true /*overwrite*/, nullptr); + DN_UTEST_ASSERT(&test, copy_result); + DN_UTEST_ASSERT(&test, DN_OS_FileExists(COPY_FILE)); // NOTE: Move step - Dqn_Str8 const MOVE_FILE = DQN_STR8("dqn_test_file_move"); - Dqn_b32 move_result = Dqn_OS_MoveFile(COPY_FILE, MOVE_FILE, true /*overwrite*/, nullptr); - DQN_UTEST_ASSERT(&test, move_result); - DQN_UTEST_ASSERT(&test, Dqn_OS_FileExists(MOVE_FILE)); - DQN_UTEST_ASSERTF(&test, Dqn_OS_FileExists(COPY_FILE) == false, "Moving a file should remove the original"); + DN_Str8 const MOVE_FILE = DN_STR8("dqn_test_file_move"); + DN_B32 move_result = DN_OS_MoveFile(COPY_FILE, MOVE_FILE, true /*overwrite*/, nullptr); + DN_UTEST_ASSERT(&test, move_result); + DN_UTEST_ASSERT(&test, DN_OS_FileExists(MOVE_FILE)); + DN_UTEST_ASSERTF(&test, DN_OS_FileExists(COPY_FILE) == false, "Moving a file should remove the original"); // NOTE: Delete step - Dqn_b32 delete_src_file = Dqn_OS_PathDelete(SRC_FILE); - Dqn_b32 delete_moved_file = Dqn_OS_PathDelete(MOVE_FILE); - DQN_UTEST_ASSERT(&test, delete_src_file); - DQN_UTEST_ASSERT(&test, delete_moved_file); + DN_B32 delete_src_file = DN_OS_PathDelete(SRC_FILE); + DN_B32 delete_moved_file = DN_OS_PathDelete(MOVE_FILE); + DN_UTEST_ASSERT(&test, delete_src_file); + DN_UTEST_ASSERT(&test, delete_moved_file); // NOTE: Deleting non-existent file fails - Dqn_b32 delete_non_existent_src_file = Dqn_OS_PathDelete(SRC_FILE); - Dqn_b32 delete_non_existent_moved_file = Dqn_OS_PathDelete(MOVE_FILE); - DQN_UTEST_ASSERT(&test, delete_non_existent_moved_file == false); - DQN_UTEST_ASSERT(&test, delete_non_existent_src_file == false); + DN_B32 delete_non_existent_src_file = DN_OS_PathDelete(SRC_FILE); + DN_B32 delete_non_existent_moved_file = DN_OS_PathDelete(MOVE_FILE); + DN_UTEST_ASSERT(&test, delete_non_existent_moved_file == false); + DN_UTEST_ASSERT(&test, delete_non_existent_src_file == false); } } return test; } -static Dqn_UTest Dqn_Test_FixedArray() +static DN_UTest DN_Test_FixedArray() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_FArray") { - DQN_UTEST_TEST("Initialise from raw array") { + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_FArray") { + DN_UTEST_TEST("Initialise from raw array") { int raw_array[] = {1, 2}; - auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); - DQN_UTEST_ASSERT(&test, array.size == 2); - DQN_UTEST_ASSERT(&test, array.data[0] == 1); - DQN_UTEST_ASSERT(&test, array.data[1] == 2); + auto array = DN_FArray_Init(raw_array, DN_ARRAY_UCOUNT(raw_array)); + DN_UTEST_ASSERT(&test, array.size == 2); + DN_UTEST_ASSERT(&test, array.data[0] == 1); + DN_UTEST_ASSERT(&test, array.data[1] == 2); } - DQN_UTEST_TEST("Erase stable 1 element from array") { + DN_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_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); + auto array = DN_FArray_Init(raw_array, DN_ARRAY_UCOUNT(raw_array)); + DN_FArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable); + DN_UTEST_ASSERT(&test, array.size == 2); + DN_UTEST_ASSERT(&test, array.data[0] == 1); + DN_UTEST_ASSERT(&test, array.data[1] == 3); } - DQN_UTEST_TEST("Erase unstable 1 element from array") { + DN_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_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); + auto array = DN_FArray_Init(raw_array, DN_ARRAY_UCOUNT(raw_array)); + DN_FArray_EraseRange(&array, 0 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable); + DN_UTEST_ASSERT(&test, array.size == 2); + DN_UTEST_ASSERT(&test, array.data[0] == 3); + DN_UTEST_ASSERT(&test, array.data[1] == 2); } - DQN_UTEST_TEST("Add 1 element to array") { + DN_UTEST_TEST("Add 1 element to array") { int const ITEM = 2; int raw_array[] = {1}; - auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); - Dqn_FArray_Add(&array, ITEM); - DQN_UTEST_ASSERT(&test, array.size == 2); - DQN_UTEST_ASSERT(&test, array.data[0] == 1); - DQN_UTEST_ASSERT(&test, array.data[1] == ITEM); + auto array = DN_FArray_Init(raw_array, DN_ARRAY_UCOUNT(raw_array)); + DN_FArray_Add(&array, ITEM); + DN_UTEST_ASSERT(&test, array.size == 2); + DN_UTEST_ASSERT(&test, array.data[0] == 1); + DN_UTEST_ASSERT(&test, array.data[1] == ITEM); } - DQN_UTEST_TEST("Clear array") { + DN_UTEST_TEST("Clear array") { int raw_array[] = {1}; - auto array = Dqn_FArray_Init(raw_array, DQN_ARRAY_UCOUNT(raw_array)); - Dqn_FArray_Clear(&array); - DQN_UTEST_ASSERT(&test, array.size == 0); + auto array = DN_FArray_Init(raw_array, DN_ARRAY_UCOUNT(raw_array)); + DN_FArray_Clear(&array); + DN_UTEST_ASSERT(&test, array.size == 0); } } return test; } -static Dqn_UTest Dqn_Test_Intrinsics() +static DN_UTest DN_Test_Intrinsics() { - Dqn_UTest test = {}; - // TODO(dqn): We don't have meaningful tests here, but since + DN_UTest test = {}; + // TODO(dn): We don't have meaningful tests here, but since // atomics/intrinsics are implemented using macros we ensure the macro was // written properly with these tests. - DQN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_PUSH // NOTE: MSVC SAL complains that we are using Interlocked functionality on // variables it has detected as *not* being shared across threads. This is @@ -1143,74 +1099,74 @@ static Dqn_UTest Dqn_Test_Intrinsics() // Warning 28112 is a knock-on effect of this that it doesn't like us // reading the value of the variable that has been used in an Interlocked // function locally. - DQN_MSVC_WARNING_DISABLE(28113) // Accessing a local variable val via an Interlocked function. - DQN_MSVC_WARNING_DISABLE(28112) // A variable (val) which is accessed via an Interlocked function must always be accessed via an Interlocked function. See line 759. + DN_MSVC_WARNING_DISABLE(28113) // Accessing a local variable val via an Interlocked function. + DN_MSVC_WARNING_DISABLE(28112) // A variable (val) which is accessed via an Interlocked function must always be accessed via an Interlocked function. See line 759. - DQN_UTEST_GROUP(test, "Dqn_Atomic") { - DQN_UTEST_TEST("Dqn_Atomic_AddU32") { + DN_UTEST_GROUP(test, "DN_Atomic") { + DN_UTEST_TEST("DN_Atomic_AddU32") { uint32_t val = 0; - Dqn_Atomic_AddU32(&val, 1); - DQN_UTEST_ASSERTF(&test, val == 1, "val: %u", val); + DN_Atomic_AddU32(&val, 1); + DN_UTEST_ASSERTF(&test, val == 1, "val: %u", val); } - DQN_UTEST_TEST("Dqn_Atomic_AddU64") { + DN_UTEST_TEST("DN_Atomic_AddU64") { uint64_t val = 0; - Dqn_Atomic_AddU64(&val, 1); - DQN_UTEST_ASSERTF(&test, val == 1, "val: %" PRIu64, val); + DN_Atomic_AddU64(&val, 1); + DN_UTEST_ASSERTF(&test, val == 1, "val: %" PRIu64, val); } - DQN_UTEST_TEST("Dqn_Atomic_SubU32") { + DN_UTEST_TEST("DN_Atomic_SubU32") { uint32_t val = 1; - Dqn_Atomic_SubU32(&val, 1); - DQN_UTEST_ASSERTF(&test, val == 0, "val: %u", val); + DN_Atomic_SubU32(&val, 1); + DN_UTEST_ASSERTF(&test, val == 0, "val: %u", val); } - DQN_UTEST_TEST("Dqn_Atomic_SubU64") { + DN_UTEST_TEST("DN_Atomic_SubU64") { uint64_t val = 1; - Dqn_Atomic_SubU64(&val, 1); - DQN_UTEST_ASSERTF(&test, val == 0, "val: %" PRIu64, val); + DN_Atomic_SubU64(&val, 1); + DN_UTEST_ASSERTF(&test, val == 0, "val: %" PRIu64, val); } - DQN_UTEST_TEST("Dqn_Atomic_SetValue32") { + DN_UTEST_TEST("DN_Atomic_SetValue32") { long a = 0; long b = 111; - Dqn_Atomic_SetValue32(&a, b); - DQN_UTEST_ASSERTF(&test, a == b, "a: %ld, b: %ld", a, b); + DN_Atomic_SetValue32(&a, b); + DN_UTEST_ASSERTF(&test, a == b, "a: %ld, b: %ld", a, b); } - DQN_UTEST_TEST("Dqn_Atomic_SetValue64") { + DN_UTEST_TEST("DN_Atomic_SetValue64") { int64_t a = 0; int64_t b = 111; - Dqn_Atomic_SetValue64(DQN_CAST(uint64_t *)&a, b); - DQN_UTEST_ASSERTF(&test, a == b, "a: %" PRId64 ", b: %" PRId64, a, b); + DN_Atomic_SetValue64(DN_CAST(uint64_t *)&a, b); + DN_UTEST_ASSERTF(&test, a == b, "a: %" PRId64 ", b: %" PRId64, a, b); } - Dqn_UTest_Begin(&test, "Dqn_CPU_TSC"); - Dqn_CPU_TSC(); - Dqn_UTest_End(&test); + DN_UTest_Begin(&test, "DN_CPU_TSC"); + DN_CPU_TSC(); + DN_UTest_End(&test); - Dqn_UTest_Begin(&test, "Dqn_CompilerReadBarrierAndCPUReadFence"); - Dqn_CompilerReadBarrierAndCPUReadFence; - Dqn_UTest_End(&test); + DN_UTest_Begin(&test, "DN_CompilerReadBarrierAndCPUReadFence"); + DN_CompilerReadBarrierAndCPUReadFence; + DN_UTest_End(&test); - Dqn_UTest_Begin(&test, "Dqn_CompilerWriteBarrierAndCPUWriteFence"); - Dqn_CompilerWriteBarrierAndCPUWriteFence; - Dqn_UTest_End(&test); + DN_UTest_Begin(&test, "DN_CompilerWriteBarrierAndCPUWriteFence"); + DN_CompilerWriteBarrierAndCPUWriteFence; + DN_UTest_End(&test); } - DQN_MSVC_WARNING_POP + DN_MSVC_WARNING_POP return test; } -#if defined(DQN_UNIT_TESTS_WITH_KECCAK) -DQN_GCC_WARNING_PUSH -DQN_GCC_WARNING_DISABLE(-Wunused-parameter) -DQN_GCC_WARNING_DISABLE(-Wsign-compare) +#if defined(DN_UNIT_TESTS_WITH_KECCAK) +DN_GCC_WARNING_PUSH +DN_GCC_WARNING_DISABLE(-Wunused-parameter) +DN_GCC_WARNING_DISABLE(-Wsign-compare) -DQN_MSVC_WARNING_PUSH -DQN_MSVC_WARNING_DISABLE(4244) -DQN_MSVC_WARNING_DISABLE(4100) -DQN_MSVC_WARNING_DISABLE(6385) +DN_MSVC_WARNING_PUSH +DN_MSVC_WARNING_DISABLE(4244) +DN_MSVC_WARNING_DISABLE(4100) +DN_MSVC_WARNING_DISABLE(6385) // NOTE: Keccak Reference Implementation /////////////////////////////////////////////////////////// // A very compact Keccak implementation taken from the reference implementation // repository @@ -1218,42 +1174,42 @@ DQN_MSVC_WARNING_DISABLE(6385) // https://github.com/XKCP/XKCP/blob/master/Standalone/CompactFIPS202/C/Keccak-more-compact.c #define FOR(i,n) for(i=0; i>1; } +int DN_RefImpl_LFSR86540_(uint8_t *R) { (*R)=((*R)<<1)^(((*R)&0x80)?0x71:0); return ((*R)&2)>>1; } #define ROL(a,o) ((((uint64_t)a)<>(64-o))) -static uint64_t Dqn_RefImpl_load64_ (const uint8_t *x) { int i; uint64_t u=0; FOR(i,8) { u<<=8; u|=x[7-i]; } return u; } -static void Dqn_RefImpl_store64_(uint8_t *x, uint64_t u) { int i; FOR(i,8) { x[i]=u; u>>=8; } } -static void Dqn_RefImpl_xor64_ (uint8_t *x, uint64_t u) { int i; FOR(i,8) { x[i]^=u; u>>=8; } } +static uint64_t DN_RefImpl_load64_ (const uint8_t *x) { int i; uint64_t u=0; FOR(i,8) { u<<=8; u|=x[7-i]; } return u; } +static void DN_RefImpl_store64_(uint8_t *x, uint64_t u) { int i; FOR(i,8) { x[i]=u; u>>=8; } } +static void DN_RefImpl_xor64_ (uint8_t *x, uint64_t u) { int i; FOR(i,8) { x[i]^=u; u>>=8; } } -#define rL(x,y) Dqn_RefImpl_load64_((uint8_t*)s+8*(x+5*y)) -#define wL(x,y,l) Dqn_RefImpl_store64_((uint8_t*)s+8*(x+5*y),l) -#define XL(x,y,l) Dqn_RefImpl_xor64_((uint8_t*)s+8*(x+5*y),l) +#define rL(x,y) DN_RefImpl_load64_((uint8_t*)s+8*(x+5*y)) +#define wL(x,y,l) DN_RefImpl_store64_((uint8_t*)s+8*(x+5*y),l) +#define XL(x,y,l) DN_RefImpl_xor64_((uint8_t*)s+8*(x+5*y),l) -void Dqn_RefImpl_Keccak_F1600(void *s) +void DN_RefImpl_Keccak_F1600(void *s) { int r,x,y,i,j,Y; uint8_t R=0x01; uint64_t C[5],D; for(i=0; i<24; i++) { - /*θ*/ FOR(x,5) C[x]=rL(x,0)^rL(x,1)^rL(x,2)^rL(x,3)^rL(x,4); FOR(x,5) { D=C[(x+4)%5]^ROL(C[(x+1)%5],1); FOR(y,5) XL(x,y,D); } - /*ρπ*/ x=1; y=r=0; D=rL(x,y); FOR(j,24) { r+=j+1; Y=(2*x+3*y)%5; x=y; y=Y; C[0]=rL(x,y); wL(x,y,ROL(D,r%64)); D=C[0]; } - /*χ*/ FOR(y,5) { FOR(x,5) C[x]=rL(x,y); FOR(x,5) wL(x,y,C[x]^((~C[(x+1)%5])&C[(x+2)%5])); } - /*ι*/ FOR(j,7) if (Dqn_RefImpl_LFSR86540_(&R)) XL(0,0,(uint64_t)1<<((1<0) { b=(inLen0) { b=(outLen0) Dqn_RefImpl_Keccak_F1600(s); } + /*absorb*/ while(inLen>0) { b=(inLen0) { b=(outLen0) DN_RefImpl_Keccak_F1600(s); } } #undef XL @@ -1261,318 +1217,318 @@ void Dqn_RefImpl_Keccak_(int r, int c, const uint8_t *in, uint64_t inLen, uint8_ #undef rL #undef ROL #undef FOR -DQN_MSVC_WARNING_POP -DQN_GCC_WARNING_POP +DN_MSVC_WARNING_POP +DN_GCC_WARNING_POP -#define DQN_KECCAK_IMPLEMENTATION +#define DN_KECCAK_IMPLEMENTATION #include "Standalone/dqn_keccak.h" -#define DQN_UTEST_HASH_X_MACRO \ - DQN_UTEST_HASH_X_ENTRY(SHA3_224, "SHA3-224") \ - DQN_UTEST_HASH_X_ENTRY(SHA3_256, "SHA3-256") \ - DQN_UTEST_HASH_X_ENTRY(SHA3_384, "SHA3-384") \ - DQN_UTEST_HASH_X_ENTRY(SHA3_512, "SHA3-512") \ - DQN_UTEST_HASH_X_ENTRY(Keccak_224, "Keccak-224") \ - DQN_UTEST_HASH_X_ENTRY(Keccak_256, "Keccak-256") \ - DQN_UTEST_HASH_X_ENTRY(Keccak_384, "Keccak-384") \ - DQN_UTEST_HASH_X_ENTRY(Keccak_512, "Keccak-512") \ - DQN_UTEST_HASH_X_ENTRY(Count, "Keccak-512") +#define DN_UTEST_HASH_X_MACRO \ + DN_UTEST_HASH_X_ENTRY(SHA3_224, "SHA3-224") \ + DN_UTEST_HASH_X_ENTRY(SHA3_256, "SHA3-256") \ + DN_UTEST_HASH_X_ENTRY(SHA3_384, "SHA3-384") \ + DN_UTEST_HASH_X_ENTRY(SHA3_512, "SHA3-512") \ + DN_UTEST_HASH_X_ENTRY(Keccak_224, "Keccak-224") \ + DN_UTEST_HASH_X_ENTRY(Keccak_256, "Keccak-256") \ + DN_UTEST_HASH_X_ENTRY(Keccak_384, "Keccak-384") \ + DN_UTEST_HASH_X_ENTRY(Keccak_512, "Keccak-512") \ + DN_UTEST_HASH_X_ENTRY(Count, "Keccak-512") -enum Dqn_Tests__HashType +enum DN_Tests__HashType { -#define DQN_UTEST_HASH_X_ENTRY(enum_val, string) Hash_##enum_val, - DQN_UTEST_HASH_X_MACRO -#undef DQN_UTEST_HASH_X_ENTRY +#define DN_UTEST_HASH_X_ENTRY(enum_val, string) Hash_##enum_val, + DN_UTEST_HASH_X_MACRO +#undef DN_UTEST_HASH_X_ENTRY }; -Dqn_Str8 const DQN_UTEST_HASH_STRING_[] = +DN_Str8 const DN_UTEST_HASH_STRING_[] = { -#define DQN_UTEST_HASH_X_ENTRY(enum_val, string) DQN_STR8(string), - DQN_UTEST_HASH_X_MACRO -#undef DQN_UTEST_HASH_X_ENTRY +#define DN_UTEST_HASH_X_ENTRY(enum_val, string) DN_STR8(string), + DN_UTEST_HASH_X_MACRO +#undef DN_UTEST_HASH_X_ENTRY }; -void Dqn_Test_KeccakDispatch_(Dqn_UTest *test, int hash_type, Dqn_Str8 input) +void DN_Test_KeccakDispatch_(DN_UTest *test, int hash_type, DN_Str8 input) { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 input_hex = Dqn_BytesToHex(tmem.arena, input.data, input.size); + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 input_hex = DN_BytesToHex(tmem.arena, input.data, input.size); switch(hash_type) { case Hash_SHA3_224: { - Dqn_KeccakBytes28 hash = Dqn_SHA3_224StringToBytes28(input); - Dqn_KeccakBytes28 expect; - Dqn_RefImpl_FIPS202_SHA3_224_(DQN_CAST(uint8_t *)input.data, input.size, (uint8_t *)expect.data); - DQN_UTEST_ASSERTF(test, - Dqn_KeccakBytes28Equals(&hash, &expect), + DN_KeccakBytes28 hash = DN_SHA3_224StringToBytes28(input); + DN_KeccakBytes28 expect; + DN_RefImpl_FIPS202_SHA3_224_(DN_CAST(uint8_t *)input.data, input.size, (uint8_t *)expect.data); + DN_UTEST_ASSERTF(test, + DN_KeccakBytes28Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" "\nexpect: %.*s" , - DQN_STR_FMT(input_hex), - DQN_KECCAK_STRING56_FMT(Dqn_KeccakBytes28ToHex(&hash).data), - DQN_KECCAK_STRING56_FMT(Dqn_KeccakBytes28ToHex(&expect).data)); + DN_STR_FMT(input_hex), + DN_KECCAK_STRING56_FMT(DN_KeccakBytes28ToHex(&hash).data), + DN_KECCAK_STRING56_FMT(DN_KeccakBytes28ToHex(&expect).data)); } break; case Hash_SHA3_256: { - Dqn_KeccakBytes32 hash = Dqn_SHA3_256StringToBytes32(input); - Dqn_KeccakBytes32 expect; - Dqn_RefImpl_FIPS202_SHA3_256_(DQN_CAST(uint8_t *)input.data, input.size, (uint8_t *)expect.data); - DQN_UTEST_ASSERTF(test, - Dqn_KeccakBytes32Equals(&hash, &expect), + DN_KeccakBytes32 hash = DN_SHA3_256StringToBytes32(input); + DN_KeccakBytes32 expect; + DN_RefImpl_FIPS202_SHA3_256_(DN_CAST(uint8_t *)input.data, input.size, (uint8_t *)expect.data); + DN_UTEST_ASSERTF(test, + DN_KeccakBytes32Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" "\nexpect: %.*s" , - DQN_STR_FMT(input_hex), - DQN_KECCAK_STRING64_FMT(Dqn_KeccakBytes32ToHex(&hash).data), - DQN_KECCAK_STRING64_FMT(Dqn_KeccakBytes32ToHex(&expect).data)); + DN_STR_FMT(input_hex), + DN_KECCAK_STRING64_FMT(DN_KeccakBytes32ToHex(&hash).data), + DN_KECCAK_STRING64_FMT(DN_KeccakBytes32ToHex(&expect).data)); } break; case Hash_SHA3_384: { - Dqn_KeccakBytes48 hash = Dqn_SHA3_384StringToBytes48(input); - Dqn_KeccakBytes48 expect; - Dqn_RefImpl_FIPS202_SHA3_384_(DQN_CAST(uint8_t *)input.data, input.size, (uint8_t *)expect.data); - DQN_UTEST_ASSERTF(test, - Dqn_KeccakBytes48Equals(&hash, &expect), + DN_KeccakBytes48 hash = DN_SHA3_384StringToBytes48(input); + DN_KeccakBytes48 expect; + DN_RefImpl_FIPS202_SHA3_384_(DN_CAST(uint8_t *)input.data, input.size, (uint8_t *)expect.data); + DN_UTEST_ASSERTF(test, + DN_KeccakBytes48Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" "\nexpect: %.*s" , - DQN_STR_FMT(input_hex), - DQN_KECCAK_STRING96_FMT(Dqn_KeccakBytes48ToHex(&hash).data), - DQN_KECCAK_STRING96_FMT(Dqn_KeccakBytes48ToHex(&expect).data)); + DN_STR_FMT(input_hex), + DN_KECCAK_STRING96_FMT(DN_KeccakBytes48ToHex(&hash).data), + DN_KECCAK_STRING96_FMT(DN_KeccakBytes48ToHex(&expect).data)); } break; case Hash_SHA3_512: { - Dqn_KeccakBytes64 hash = Dqn_SHA3_512StringToBytes64(input); - Dqn_KeccakBytes64 expect; - Dqn_RefImpl_FIPS202_SHA3_512_(DQN_CAST(uint8_t *)input.data, input.size, (uint8_t *)expect.data); - DQN_UTEST_ASSERTF(test, - Dqn_KeccakBytes64Equals(&hash, &expect), + DN_KeccakBytes64 hash = DN_SHA3_512StringToBytes64(input); + DN_KeccakBytes64 expect; + DN_RefImpl_FIPS202_SHA3_512_(DN_CAST(uint8_t *)input.data, input.size, (uint8_t *)expect.data); + DN_UTEST_ASSERTF(test, + DN_KeccakBytes64Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" "\nexpect: %.*s" , - DQN_STR_FMT(input_hex), - DQN_KECCAK_STRING128_FMT(Dqn_KeccakBytes64ToHex(&hash).data), - DQN_KECCAK_STRING128_FMT(Dqn_KeccakBytes64ToHex(&expect).data)); + DN_STR_FMT(input_hex), + DN_KECCAK_STRING128_FMT(DN_KeccakBytes64ToHex(&hash).data), + DN_KECCAK_STRING128_FMT(DN_KeccakBytes64ToHex(&expect).data)); } break; case Hash_Keccak_224: { - Dqn_KeccakBytes28 hash = Dqn_Keccak224StringToBytes28(input); - Dqn_KeccakBytes28 expect; - Dqn_RefImpl_Keccak_(1152, 448, DQN_CAST(uint8_t *)input.data, input.size, 0x01, (uint8_t *)expect.data, sizeof(expect)); - DQN_UTEST_ASSERTF(test, - Dqn_KeccakBytes28Equals(&hash, &expect), + DN_KeccakBytes28 hash = DN_Keccak224StringToBytes28(input); + DN_KeccakBytes28 expect; + DN_RefImpl_Keccak_(1152, 448, DN_CAST(uint8_t *)input.data, input.size, 0x01, (uint8_t *)expect.data, sizeof(expect)); + DN_UTEST_ASSERTF(test, + DN_KeccakBytes28Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" "\nexpect: %.*s" , - DQN_STR_FMT(input_hex), - DQN_KECCAK_STRING56_FMT(Dqn_KeccakBytes28ToHex(&hash).data), - DQN_KECCAK_STRING56_FMT(Dqn_KeccakBytes28ToHex(&expect).data)); + DN_STR_FMT(input_hex), + DN_KECCAK_STRING56_FMT(DN_KeccakBytes28ToHex(&hash).data), + DN_KECCAK_STRING56_FMT(DN_KeccakBytes28ToHex(&expect).data)); } break; case Hash_Keccak_256: { - Dqn_KeccakBytes32 hash = Dqn_Keccak256StringToBytes32(input); - Dqn_KeccakBytes32 expect; - Dqn_RefImpl_Keccak_(1088, 512, DQN_CAST(uint8_t *)input.data, input.size, 0x01, (uint8_t *)expect.data, sizeof(expect)); - DQN_UTEST_ASSERTF(test, - Dqn_KeccakBytes32Equals(&hash, &expect), + DN_KeccakBytes32 hash = DN_Keccak256StringToBytes32(input); + DN_KeccakBytes32 expect; + DN_RefImpl_Keccak_(1088, 512, DN_CAST(uint8_t *)input.data, input.size, 0x01, (uint8_t *)expect.data, sizeof(expect)); + DN_UTEST_ASSERTF(test, + DN_KeccakBytes32Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" "\nexpect: %.*s" , - DQN_STR_FMT(input_hex), - DQN_KECCAK_STRING64_FMT(Dqn_KeccakBytes32ToHex(&hash).data), - DQN_KECCAK_STRING64_FMT(Dqn_KeccakBytes32ToHex(&expect).data)); + DN_STR_FMT(input_hex), + DN_KECCAK_STRING64_FMT(DN_KeccakBytes32ToHex(&hash).data), + DN_KECCAK_STRING64_FMT(DN_KeccakBytes32ToHex(&expect).data)); } break; case Hash_Keccak_384: { - Dqn_KeccakBytes48 hash = Dqn_Keccak384StringToBytes48(input); - Dqn_KeccakBytes48 expect; - Dqn_RefImpl_Keccak_(832, 768, DQN_CAST(uint8_t *)input.data, input.size, 0x01, (uint8_t *)expect.data, sizeof(expect)); - DQN_UTEST_ASSERTF(test, - Dqn_KeccakBytes48Equals(&hash, &expect), + DN_KeccakBytes48 hash = DN_Keccak384StringToBytes48(input); + DN_KeccakBytes48 expect; + DN_RefImpl_Keccak_(832, 768, DN_CAST(uint8_t *)input.data, input.size, 0x01, (uint8_t *)expect.data, sizeof(expect)); + DN_UTEST_ASSERTF(test, + DN_KeccakBytes48Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" "\nexpect: %.*s" , - DQN_STR_FMT(input_hex), - DQN_KECCAK_STRING96_FMT(Dqn_KeccakBytes48ToHex(&hash).data), - DQN_KECCAK_STRING96_FMT(Dqn_KeccakBytes48ToHex(&expect).data)); + DN_STR_FMT(input_hex), + DN_KECCAK_STRING96_FMT(DN_KeccakBytes48ToHex(&hash).data), + DN_KECCAK_STRING96_FMT(DN_KeccakBytes48ToHex(&expect).data)); } break; case Hash_Keccak_512: { - Dqn_KeccakBytes64 hash = Dqn_Keccak512StringToBytes64(input); - Dqn_KeccakBytes64 expect; - Dqn_RefImpl_Keccak_(576, 1024, DQN_CAST(uint8_t *)input.data, input.size, 0x01, (uint8_t *)expect.data, sizeof(expect)); - DQN_UTEST_ASSERTF(test, - Dqn_KeccakBytes64Equals(&hash, &expect), + DN_KeccakBytes64 hash = DN_Keccak512StringToBytes64(input); + DN_KeccakBytes64 expect; + DN_RefImpl_Keccak_(576, 1024, DN_CAST(uint8_t *)input.data, input.size, 0x01, (uint8_t *)expect.data, sizeof(expect)); + DN_UTEST_ASSERTF(test, + DN_KeccakBytes64Equals(&hash, &expect), "\ninput: %.*s" "\nhash: %.*s" "\nexpect: %.*s" , - DQN_STR_FMT(input_hex), - DQN_KECCAK_STRING128_FMT(Dqn_KeccakBytes64ToHex(&hash).data), - DQN_KECCAK_STRING128_FMT(Dqn_KeccakBytes64ToHex(&expect).data)); + DN_STR_FMT(input_hex), + DN_KECCAK_STRING128_FMT(DN_KeccakBytes64ToHex(&hash).data), + DN_KECCAK_STRING128_FMT(DN_KeccakBytes64ToHex(&expect).data)); } break; } } -Dqn_UTest Dqn_Test_Keccak() +DN_UTest DN_Test_Keccak() { - Dqn_UTest test = {}; - Dqn_Str8 const INPUTS[] = { - DQN_STR8("abc"), - DQN_STR8(""), - DQN_STR8("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), - DQN_STR8("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmno" + DN_UTest test = {}; + DN_Str8 const INPUTS[] = { + DN_STR8("abc"), + DN_STR8(""), + DN_STR8("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), + DN_STR8("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmno" "pqrstnopqrstu"), }; - DQN_UTEST_GROUP(test, "Dqn_Keccak") + DN_UTEST_GROUP(test, "DN_Keccak") { for (int hash_type = 0; hash_type < Hash_Count; hash_type++) { - Dqn_PCG32 rng = Dqn_PCG32_Init(0xd48e'be21'2af8'733d); - for (Dqn_Str8 input : INPUTS) { - Dqn_UTest_Begin(&test, "%.*s - Input: %.*s", DQN_STR_FMT(DQN_UTEST_HASH_STRING_[hash_type]), DQN_CAST(int)DQN_MIN(input.size, 54), input.data); - Dqn_Test_KeccakDispatch_(&test, hash_type, input); - Dqn_UTest_End(&test); + DN_PCG32 rng = DN_PCG32_Init(0xd48e'be21'2af8'733d); + for (DN_Str8 input : INPUTS) { + DN_UTest_Begin(&test, "%.*s - Input: %.*s", DN_STR_FMT(DN_UTEST_HASH_STRING_[hash_type]), DN_CAST(int)DN_MIN(input.size, 54), input.data); + DN_Test_KeccakDispatch_(&test, hash_type, input); + DN_UTest_End(&test); } - Dqn_UTest_Begin(&test, "%.*s - Deterministic random inputs", DQN_STR_FMT(DQN_UTEST_HASH_STRING_[hash_type])); - for (Dqn_usize index = 0; index < 128; index++) { + DN_UTest_Begin(&test, "%.*s - Deterministic random inputs", DN_STR_FMT(DN_UTEST_HASH_STRING_[hash_type])); + for (DN_USize index = 0; index < 128; index++) { char src[4096] = {}; - uint32_t src_size = Dqn_PCG32_Range(&rng, 0, sizeof(src)); + uint32_t src_size = DN_PCG32_Range(&rng, 0, sizeof(src)); - for (Dqn_usize src_index = 0; src_index < src_size; src_index++) - src[src_index] = DQN_CAST(char)Dqn_PCG32_Range(&rng, 0, 255); + for (DN_USize src_index = 0; src_index < src_size; src_index++) + src[src_index] = DN_CAST(char)DN_PCG32_Range(&rng, 0, 255); - Dqn_Str8 input = Dqn_Str8_Init(src, src_size); - Dqn_Test_KeccakDispatch_(&test, hash_type, input); + DN_Str8 input = DN_Str8_Init(src, src_size); + DN_Test_KeccakDispatch_(&test, hash_type, input); } - Dqn_UTest_End(&test); + DN_UTest_End(&test); } } return test; } -#endif // defined(DQN_UNIT_TESTS_WITH_KECCAK) +#endif // defined(DN_UNIT_TESTS_WITH_KECCAK) -static Dqn_UTest Dqn_Test_M4() +static DN_UTest DN_Test_M4() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_M4") { - DQN_UTEST_TEST("Simple translate and scale matrix") { - Dqn_M4 translate = Dqn_M4_TranslateF(1, 2, 3); - Dqn_M4 scale = Dqn_M4_ScaleF(2, 2, 2); - Dqn_M4 result = Dqn_M4_Mul(translate, scale); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_M4") { + DN_UTEST_TEST("Simple translate and scale matrix") { + DN_M4 translate = DN_M4_TranslateF(1, 2, 3); + DN_M4 scale = DN_M4_ScaleF(2, 2, 2); + DN_M4 result = DN_M4_Mul(translate, scale); - const Dqn_M4 EXPECT = {{ + const DN_M4 EXPECT = {{ {2, 0, 0, 0}, {0, 2, 0, 0}, {0, 0, 2, 0}, {1, 2, 3, 1}, }}; - DQN_UTEST_ASSERTF(&test, + DN_UTEST_ASSERTF(&test, memcmp(result.columns, EXPECT.columns, sizeof(EXPECT)) == 0, "\nresult =\n%s\nexpected =\n%s", - Dqn_M4_ColumnMajorString(result).data, - Dqn_M4_ColumnMajorString(EXPECT).data); + DN_M4_ColumnMajorString(result).data, + DN_M4_ColumnMajorString(EXPECT).data); } } return test; } -static Dqn_UTest Dqn_Test_OS() +static DN_UTest DN_Test_OS() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_OS") { - DQN_UTEST_TEST("Generate secure RNG bytes with nullptr") { - Dqn_b32 result = Dqn_OS_SecureRNGBytes(nullptr, 1); - DQN_UTEST_ASSERT(&test, result == false); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_OS") { + DN_UTEST_TEST("Generate secure RNG bytes with nullptr") { + DN_B32 result = DN_OS_SecureRNGBytes(nullptr, 1); + DN_UTEST_ASSERT(&test, result == false); } - DQN_UTEST_TEST("Generate secure RNG 32 bytes") { + DN_UTEST_TEST("Generate secure RNG 32 bytes") { char const ZERO[32] = {}; char buf[32] = {}; - bool result = Dqn_OS_SecureRNGBytes(buf, DQN_ARRAY_UCOUNT(buf)); - DQN_UTEST_ASSERT(&test, result); - DQN_UTEST_ASSERT(&test, DQN_MEMCMP(buf, ZERO, DQN_ARRAY_UCOUNT(buf)) != 0); + bool result = DN_OS_SecureRNGBytes(buf, DN_ARRAY_UCOUNT(buf)); + DN_UTEST_ASSERT(&test, result); + DN_UTEST_ASSERT(&test, DN_MEMCMP(buf, ZERO, DN_ARRAY_UCOUNT(buf)) != 0); } - DQN_UTEST_TEST("Generate secure RNG 0 bytes") { + DN_UTEST_TEST("Generate secure RNG 0 bytes") { char buf[32] = {}; buf[0] = 'Z'; - Dqn_b32 result = Dqn_OS_SecureRNGBytes(buf, 0); - DQN_UTEST_ASSERT(&test, result); - DQN_UTEST_ASSERT(&test, buf[0] == 'Z'); + DN_B32 result = DN_OS_SecureRNGBytes(buf, 0); + DN_UTEST_ASSERT(&test, result); + DN_UTEST_ASSERT(&test, buf[0] == 'Z'); } - DQN_UTEST_TEST("Query executable directory") { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 result = Dqn_OS_EXEDir(tmem.arena); - DQN_UTEST_ASSERT(&test, Dqn_Str8_HasData(result)); - DQN_UTEST_ASSERTF(&test, Dqn_OS_DirExists(result), "result(%zu): %.*s", result.size, DQN_STR_FMT(result)); + DN_UTEST_TEST("Query executable directory") { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 result = DN_OS_EXEDir(tmem.arena); + DN_UTEST_ASSERT(&test, DN_Str8_HasData(result)); + DN_UTEST_ASSERTF(&test, DN_OS_DirExists(result), "result(%zu): %.*s", result.size, DN_STR_FMT(result)); } - DQN_UTEST_TEST("Dqn_OS_PerfCounterNow") { - uint64_t result = Dqn_OS_PerfCounterNow(); - DQN_UTEST_ASSERT(&test, result != 0); + DN_UTEST_TEST("DN_OS_PerfCounterNow") { + uint64_t result = DN_OS_PerfCounterNow(); + DN_UTEST_ASSERT(&test, result != 0); } - DQN_UTEST_TEST("Consecutive ticks are ordered") { - uint64_t a = Dqn_OS_PerfCounterNow(); - uint64_t b = Dqn_OS_PerfCounterNow(); - DQN_UTEST_ASSERTF(&test, b >= a, "a: %" PRIu64 ", b: %" PRIu64, a, b); + DN_UTEST_TEST("Consecutive ticks are ordered") { + uint64_t a = DN_OS_PerfCounterNow(); + uint64_t b = DN_OS_PerfCounterNow(); + DN_UTEST_ASSERTF(&test, b >= a, "a: %" PRIu64 ", b: %" PRIu64, a, b); } - DQN_UTEST_TEST("Ticks to time are a correct order of magnitude") { - uint64_t a = Dqn_OS_PerfCounterNow(); - uint64_t b = Dqn_OS_PerfCounterNow(); - Dqn_f64 s = Dqn_OS_PerfCounterS(a, b); - Dqn_f64 ms = Dqn_OS_PerfCounterMs(a, b); - Dqn_f64 us = Dqn_OS_PerfCounterUs(a, b); - Dqn_f64 ns = Dqn_OS_PerfCounterNs(a, b); - DQN_UTEST_ASSERTF(&test, s <= ms, "s: %f, ms: %f", s, ms); - DQN_UTEST_ASSERTF(&test, ms <= us, "ms: %f, us: %f", ms, us); - DQN_UTEST_ASSERTF(&test, us <= ns, "us: %f, ns: %f", us, ns); + DN_UTEST_TEST("Ticks to time are a correct order of magnitude") { + uint64_t a = DN_OS_PerfCounterNow(); + uint64_t b = DN_OS_PerfCounterNow(); + DN_F64 s = DN_OS_PerfCounterS(a, b); + DN_F64 ms = DN_OS_PerfCounterMs(a, b); + DN_F64 us = DN_OS_PerfCounterUs(a, b); + DN_F64 ns = DN_OS_PerfCounterNs(a, b); + DN_UTEST_ASSERTF(&test, s <= ms, "s: %f, ms: %f", s, ms); + DN_UTEST_ASSERTF(&test, ms <= us, "ms: %f, us: %f", ms, us); + DN_UTEST_ASSERTF(&test, us <= ns, "us: %f, ns: %f", us, ns); } } return test; } -static Dqn_UTest Dqn_Test_Rect() +static DN_UTest DN_Test_Rect() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_Rect") { - DQN_UTEST_TEST("No intersection") { - Dqn_Rect a = Dqn_Rect_InitV2x2(Dqn_V2_InitNx1(0), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect b = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2(200, 0), Dqn_V2_InitNx2(200, 200)); - Dqn_Rect ab = Dqn_Rect_Intersection(a, b); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_Rect") { + DN_UTEST_TEST("No intersection") { + DN_Rect a = DN_Rect_Init2V2(DN_V2F32_Init1N(0), DN_V2F32_Init2N(100, 100)); + DN_Rect b = DN_Rect_Init2V2(DN_V2F32_Init2N(200, 0), DN_V2F32_Init2N(200, 200)); + DN_Rect ab = DN_Rect_Intersection(a, b); - Dqn_V2 ab_max = ab.pos + ab.size; - DQN_UTEST_ASSERTF(&test, + DN_V2F32 ab_max = ab.pos + ab.size; + DN_UTEST_ASSERTF(&test, ab.pos.x == 0 && ab.pos.y == 0 && ab_max.x == 0 && ab_max.y == 0, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.pos.x, @@ -1581,13 +1537,13 @@ static Dqn_UTest Dqn_Test_Rect() ab_max.y); } - DQN_UTEST_TEST("A's min intersects B") { - Dqn_Rect a = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2(50, 50), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect b = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2( 0, 0), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect ab = Dqn_Rect_Intersection(a, b); + DN_UTEST_TEST("A's min intersects B") { + DN_Rect a = DN_Rect_Init2V2(DN_V2F32_Init2N(50, 50), DN_V2F32_Init2N(100, 100)); + DN_Rect b = DN_Rect_Init2V2(DN_V2F32_Init2N( 0, 0), DN_V2F32_Init2N(100, 100)); + DN_Rect ab = DN_Rect_Intersection(a, b); - Dqn_V2 ab_max = ab.pos + ab.size; - DQN_UTEST_ASSERTF(&test, + DN_V2F32 ab_max = ab.pos + ab.size; + DN_UTEST_ASSERTF(&test, ab.pos.x == 50 && ab.pos.y == 50 && ab_max.x == 100 && ab_max.y == 100, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.pos.x, @@ -1596,13 +1552,13 @@ static Dqn_UTest Dqn_Test_Rect() ab_max.y); } - DQN_UTEST_TEST("B's min intersects A") { - Dqn_Rect a = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2( 0, 0), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect b = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2(50, 50), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect ab = Dqn_Rect_Intersection(a, b); + DN_UTEST_TEST("B's min intersects A") { + DN_Rect a = DN_Rect_Init2V2(DN_V2F32_Init2N( 0, 0), DN_V2F32_Init2N(100, 100)); + DN_Rect b = DN_Rect_Init2V2(DN_V2F32_Init2N(50, 50), DN_V2F32_Init2N(100, 100)); + DN_Rect ab = DN_Rect_Intersection(a, b); - Dqn_V2 ab_max = ab.pos + ab.size; - DQN_UTEST_ASSERTF(&test, + DN_V2F32 ab_max = ab.pos + ab.size; + DN_UTEST_ASSERTF(&test, ab.pos.x == 50 && ab.pos.y == 50 && ab_max.x == 100 && ab_max.y == 100, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.pos.x, @@ -1611,13 +1567,13 @@ static Dqn_UTest Dqn_Test_Rect() ab_max.y); } - DQN_UTEST_TEST("A's max intersects B") { - Dqn_Rect a = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2(-50, -50), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect b = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2( 0, 0), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect ab = Dqn_Rect_Intersection(a, b); + DN_UTEST_TEST("A's max intersects B") { + DN_Rect a = DN_Rect_Init2V2(DN_V2F32_Init2N(-50, -50), DN_V2F32_Init2N(100, 100)); + DN_Rect b = DN_Rect_Init2V2(DN_V2F32_Init2N( 0, 0), DN_V2F32_Init2N(100, 100)); + DN_Rect ab = DN_Rect_Intersection(a, b); - Dqn_V2 ab_max = ab.pos + ab.size; - DQN_UTEST_ASSERTF(&test, + DN_V2F32 ab_max = ab.pos + ab.size; + DN_UTEST_ASSERTF(&test, ab.pos.x == 0 && ab.pos.y == 0 && ab_max.x == 50 && ab_max.y == 50, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.pos.x, @@ -1626,13 +1582,13 @@ static Dqn_UTest Dqn_Test_Rect() ab_max.y); } - DQN_UTEST_TEST("B's max intersects A") { - Dqn_Rect a = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2( 0, 0), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect b = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2(-50, -50), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect ab = Dqn_Rect_Intersection(a, b); + DN_UTEST_TEST("B's max intersects A") { + DN_Rect a = DN_Rect_Init2V2(DN_V2F32_Init2N( 0, 0), DN_V2F32_Init2N(100, 100)); + DN_Rect b = DN_Rect_Init2V2(DN_V2F32_Init2N(-50, -50), DN_V2F32_Init2N(100, 100)); + DN_Rect ab = DN_Rect_Intersection(a, b); - Dqn_V2 ab_max = ab.pos + ab.size; - DQN_UTEST_ASSERTF(&test, + DN_V2F32 ab_max = ab.pos + ab.size; + DN_UTEST_ASSERTF(&test, ab.pos.x == 0 && ab.pos.y == 0 && ab_max.x == 50 && ab_max.y == 50, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.pos.x, @@ -1642,13 +1598,13 @@ static Dqn_UTest Dqn_Test_Rect() } - DQN_UTEST_TEST("B contains A") { - Dqn_Rect a = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2(25, 25), Dqn_V2_InitNx2( 25, 25)); - Dqn_Rect b = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2( 0, 0), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect ab = Dqn_Rect_Intersection(a, b); + DN_UTEST_TEST("B contains A") { + DN_Rect a = DN_Rect_Init2V2(DN_V2F32_Init2N(25, 25), DN_V2F32_Init2N( 25, 25)); + DN_Rect b = DN_Rect_Init2V2(DN_V2F32_Init2N( 0, 0), DN_V2F32_Init2N(100, 100)); + DN_Rect ab = DN_Rect_Intersection(a, b); - Dqn_V2 ab_max = ab.pos + ab.size; - DQN_UTEST_ASSERTF(&test, + DN_V2F32 ab_max = ab.pos + ab.size; + DN_UTEST_ASSERTF(&test, ab.pos.x == 25 && ab.pos.y == 25 && ab_max.x == 50 && ab_max.y == 50, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.pos.x, @@ -1657,13 +1613,13 @@ static Dqn_UTest Dqn_Test_Rect() ab_max.y); } - DQN_UTEST_TEST("A contains B") { - Dqn_Rect a = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2( 0, 0), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect b = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2(25, 25), Dqn_V2_InitNx2( 25, 25)); - Dqn_Rect ab = Dqn_Rect_Intersection(a, b); + DN_UTEST_TEST("A contains B") { + DN_Rect a = DN_Rect_Init2V2(DN_V2F32_Init2N( 0, 0), DN_V2F32_Init2N(100, 100)); + DN_Rect b = DN_Rect_Init2V2(DN_V2F32_Init2N(25, 25), DN_V2F32_Init2N( 25, 25)); + DN_Rect ab = DN_Rect_Intersection(a, b); - Dqn_V2 ab_max = ab.pos + ab.size; - DQN_UTEST_ASSERTF(&test, + DN_V2F32 ab_max = ab.pos + ab.size; + DN_UTEST_ASSERTF(&test, ab.pos.x == 25 && ab.pos.y == 25 && ab_max.x == 50 && ab_max.y == 50, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.pos.x, @@ -1672,13 +1628,13 @@ static Dqn_UTest Dqn_Test_Rect() ab_max.y); } - DQN_UTEST_TEST("A equals B") { - Dqn_Rect a = Dqn_Rect_InitV2x2(Dqn_V2_InitNx2(0, 0), Dqn_V2_InitNx2(100, 100)); - Dqn_Rect b = a; - Dqn_Rect ab = Dqn_Rect_Intersection(a, b); + DN_UTEST_TEST("A equals B") { + DN_Rect a = DN_Rect_Init2V2(DN_V2F32_Init2N(0, 0), DN_V2F32_Init2N(100, 100)); + DN_Rect b = a; + DN_Rect ab = DN_Rect_Intersection(a, b); - Dqn_V2 ab_max = ab.pos + ab.size; - DQN_UTEST_ASSERTF(&test, + DN_V2F32 ab_max = ab.pos + ab.size; + DN_UTEST_ASSERTF(&test, ab.pos.x == 0 && ab.pos.y == 0 && ab_max.x == 100 && ab_max.y == 100, "ab = { min.x = %.2f, min.y = %.2f, max.x = %.2f. max.y = %.2f }", ab.pos.x, @@ -1690,427 +1646,427 @@ static Dqn_UTest Dqn_Test_Rect() return test; } -static Dqn_UTest Dqn_Test_Str8() +static DN_UTest DN_Test_Str8() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_Str8") { - DQN_UTEST_TEST("Initialise with string literal w/ macro") { - Dqn_Str8 string = DQN_STR8("AB"); - DQN_UTEST_ASSERTF(&test, string.size == 2, "size: %zu", string.size); - DQN_UTEST_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); - DQN_UTEST_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_Str8") { + DN_UTEST_TEST("Initialise with string literal w/ macro") { + DN_Str8 string = DN_STR8("AB"); + DN_UTEST_ASSERTF(&test, string.size == 2, "size: %zu", string.size); + DN_UTEST_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); + DN_UTEST_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); } - DQN_UTEST_TEST("Initialise with format string") { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 string = Dqn_Str8_InitF(tmem.arena, "%s", "AB"); - DQN_UTEST_ASSERTF(&test, string.size == 2, "size: %zu", string.size); - DQN_UTEST_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); - DQN_UTEST_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); - DQN_UTEST_ASSERTF(&test, string.data[2] == 0, "string[2]: %c", string.data[2]); + DN_UTEST_TEST("Initialise with format string") { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 string = DN_Str8_InitF(tmem.arena, "%s", "AB"); + DN_UTEST_ASSERTF(&test, string.size == 2, "size: %zu", string.size); + DN_UTEST_ASSERTF(&test, string.data[0] == 'A', "string[0]: %c", string.data[0]); + DN_UTEST_ASSERTF(&test, string.data[1] == 'B', "string[1]: %c", string.data[1]); + DN_UTEST_ASSERTF(&test, string.data[2] == 0, "string[2]: %c", string.data[2]); } - DQN_UTEST_TEST("Copy string") { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 string = DQN_STR8("AB"); - Dqn_Str8 copy = Dqn_Str8_Copy(tmem.arena, string); - DQN_UTEST_ASSERTF(&test, copy.size == 2, "size: %zu", copy.size); - DQN_UTEST_ASSERTF(&test, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]); - DQN_UTEST_ASSERTF(&test, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]); - DQN_UTEST_ASSERTF(&test, copy.data[2] == 0, "copy[2]: %c", copy.data[2]); + DN_UTEST_TEST("Copy string") { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 string = DN_STR8("AB"); + DN_Str8 copy = DN_Str8_Copy(tmem.arena, string); + DN_UTEST_ASSERTF(&test, copy.size == 2, "size: %zu", copy.size); + DN_UTEST_ASSERTF(&test, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]); + DN_UTEST_ASSERTF(&test, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]); + DN_UTEST_ASSERTF(&test, copy.data[2] == 0, "copy[2]: %c", copy.data[2]); } - DQN_UTEST_TEST("Trim whitespace around string") { - Dqn_Str8 string = Dqn_Str8_TrimWhitespaceAround(DQN_STR8(" AB ")); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(string, DQN_STR8("AB")), "[string=%.*s]", DQN_STR_FMT(string)); + DN_UTEST_TEST("Trim whitespace around string") { + DN_Str8 string = DN_Str8_TrimWhitespaceAround(DN_STR8(" AB ")); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(string, DN_STR8("AB")), "[string=%.*s]", DN_STR_FMT(string)); } - DQN_UTEST_TEST("Allocate string from arena") { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 string = Dqn_Str8_Alloc(tmem.arena, 2, Dqn_ZeroMem_No); - DQN_UTEST_ASSERTF(&test, string.size == 2, "size: %zu", string.size); + DN_UTEST_TEST("Allocate string from arena") { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 string = DN_Str8_Alloc(tmem.arena, 2, DN_ZeroMem_No); + DN_UTEST_ASSERTF(&test, string.size == 2, "size: %zu", string.size); } - // NOTE: Dqn_CStr8_Trim[Prefix/Suffix] + // NOTE: DN_CStr8_Trim[Prefix/Suffix] // --------------------------------------------------------------------------------------------- - DQN_UTEST_TEST("Trim prefix with matching prefix") { - Dqn_Str8 input = DQN_STR8("nft/abc"); - Dqn_Str8 result = Dqn_Str8_TrimPrefix(input, DQN_STR8("nft/")); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(result, DQN_STR8("abc")), "%.*s", DQN_STR_FMT(result)); + DN_UTEST_TEST("Trim prefix with matching prefix") { + DN_Str8 input = DN_STR8("nft/abc"); + DN_Str8 result = DN_Str8_TrimPrefix(input, DN_STR8("nft/")); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(result, DN_STR8("abc")), "%.*s", DN_STR_FMT(result)); } - DQN_UTEST_TEST("Trim prefix with non matching prefix") { - Dqn_Str8 input = DQN_STR8("nft/abc"); - Dqn_Str8 result = Dqn_Str8_TrimPrefix(input, DQN_STR8(" ft/")); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(result, input), "%.*s", DQN_STR_FMT(result)); + DN_UTEST_TEST("Trim prefix with non matching prefix") { + DN_Str8 input = DN_STR8("nft/abc"); + DN_Str8 result = DN_Str8_TrimPrefix(input, DN_STR8(" ft/")); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(result, input), "%.*s", DN_STR_FMT(result)); } - DQN_UTEST_TEST("Trim suffix with matching suffix") { - Dqn_Str8 input = DQN_STR8("nft/abc"); - Dqn_Str8 result = Dqn_Str8_TrimSuffix(input, DQN_STR8("abc")); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(result, DQN_STR8("nft/")), "%.*s", DQN_STR_FMT(result)); + DN_UTEST_TEST("Trim suffix with matching suffix") { + DN_Str8 input = DN_STR8("nft/abc"); + DN_Str8 result = DN_Str8_TrimSuffix(input, DN_STR8("abc")); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(result, DN_STR8("nft/")), "%.*s", DN_STR_FMT(result)); } - DQN_UTEST_TEST("Trim suffix with non matching suffix") { - Dqn_Str8 input = DQN_STR8("nft/abc"); - Dqn_Str8 result = Dqn_Str8_TrimSuffix(input, DQN_STR8("ab")); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(result, input), "%.*s", DQN_STR_FMT(result)); + DN_UTEST_TEST("Trim suffix with non matching suffix") { + DN_Str8 input = DN_STR8("nft/abc"); + DN_Str8 result = DN_Str8_TrimSuffix(input, DN_STR8("ab")); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(result, input), "%.*s", DN_STR_FMT(result)); } - // NOTE: Dqn_Str8_IsAllDigits ////////////////////////////////////////////////////////////// - DQN_UTEST_TEST("Is all digits fails on non-digit string") { - Dqn_b32 result = Dqn_Str8_IsAll(DQN_STR8("@123string"), Dqn_Str8IsAll_Digits); - DQN_UTEST_ASSERT(&test, result == false); + // NOTE: DN_Str8_IsAllDigits ////////////////////////////////////////////////////////////// + DN_UTEST_TEST("Is all digits fails on non-digit string") { + DN_B32 result = DN_Str8_IsAll(DN_STR8("@123string"), DN_Str8IsAll_Digits); + DN_UTEST_ASSERT(&test, result == false); } - DQN_UTEST_TEST("Is all digits fails on nullptr") { - Dqn_b32 result = Dqn_Str8_IsAll(Dqn_Str8_Init(nullptr, 0), Dqn_Str8IsAll_Digits); - DQN_UTEST_ASSERT(&test, result == false); + DN_UTEST_TEST("Is all digits fails on nullptr") { + DN_B32 result = DN_Str8_IsAll(DN_Str8_Init(nullptr, 0), DN_Str8IsAll_Digits); + DN_UTEST_ASSERT(&test, result == false); } - DQN_UTEST_TEST("Is all digits fails on nullptr w/ size") { - Dqn_b32 result = Dqn_Str8_IsAll(Dqn_Str8_Init(nullptr, 1), Dqn_Str8IsAll_Digits); - DQN_UTEST_ASSERT(&test, result == false); + DN_UTEST_TEST("Is all digits fails on nullptr w/ size") { + DN_B32 result = DN_Str8_IsAll(DN_Str8_Init(nullptr, 1), DN_Str8IsAll_Digits); + DN_UTEST_ASSERT(&test, result == false); } - DQN_UTEST_TEST("Is all digits fails on string w/ 0 size") { + DN_UTEST_TEST("Is all digits fails on string w/ 0 size") { char const buf[] = "@123string"; - Dqn_b32 result = Dqn_Str8_IsAll(Dqn_Str8_Init(buf, 0), Dqn_Str8IsAll_Digits); - DQN_UTEST_ASSERT(&test, !result); + DN_B32 result = DN_Str8_IsAll(DN_Str8_Init(buf, 0), DN_Str8IsAll_Digits); + DN_UTEST_ASSERT(&test, !result); } - DQN_UTEST_TEST("Is all digits success") { - Dqn_b32 result = Dqn_Str8_IsAll(DQN_STR8("23"), Dqn_Str8IsAll_Digits); - DQN_UTEST_ASSERT(&test, DQN_CAST(bool)result == true); + DN_UTEST_TEST("Is all digits success") { + DN_B32 result = DN_Str8_IsAll(DN_STR8("23"), DN_Str8IsAll_Digits); + DN_UTEST_ASSERT(&test, DN_CAST(bool)result == true); } - DQN_UTEST_TEST("Is all digits fails on whitespace") { - Dqn_b32 result = Dqn_Str8_IsAll(DQN_STR8("23 "), Dqn_Str8IsAll_Digits); - DQN_UTEST_ASSERT(&test, DQN_CAST(bool)result == false); + DN_UTEST_TEST("Is all digits fails on whitespace") { + DN_B32 result = DN_Str8_IsAll(DN_STR8("23 "), DN_Str8IsAll_Digits); + DN_UTEST_ASSERT(&test, DN_CAST(bool)result == false); } - // NOTE: Dqn_Str8_BinarySplit + // NOTE: DN_Str8_BinarySplit // --------------------------------------------------------------------------------------------- { { char const *TEST_FMT = "Binary split \"%.*s\" with \"%.*s\""; - Dqn_Str8 delimiter = DQN_STR8("/"); - Dqn_Str8 input = DQN_STR8("abcdef"); - DQN_UTEST_TEST(TEST_FMT, DQN_STR_FMT(input), DQN_STR_FMT(delimiter)) { - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplit(input, delimiter); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(split.lhs, DQN_STR8("abcdef")), "[lhs=%.*s]", DQN_STR_FMT(split.lhs)); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(split.rhs, DQN_STR8("")), "[rhs=%.*s]", DQN_STR_FMT(split.rhs)); + DN_Str8 delimiter = DN_STR8("/"); + DN_Str8 input = DN_STR8("abcdef"); + DN_UTEST_TEST(TEST_FMT, DN_STR_FMT(input), DN_STR_FMT(delimiter)) { + DN_Str8BinarySplitResult split = DN_Str8_BinarySplit(input, delimiter); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(split.lhs, DN_STR8("abcdef")), "[lhs=%.*s]", DN_STR_FMT(split.lhs)); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(split.rhs, DN_STR8("")), "[rhs=%.*s]", DN_STR_FMT(split.rhs)); } - input = DQN_STR8("abc/def"); - DQN_UTEST_TEST(TEST_FMT, DQN_STR_FMT(input), DQN_STR_FMT(delimiter)) { - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplit(input, delimiter); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(split.lhs, DQN_STR8("abc")), "[lhs=%.*s]", DQN_STR_FMT(split.lhs)); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(split.rhs, DQN_STR8("def")), "[rhs=%.*s]", DQN_STR_FMT(split.rhs)); + input = DN_STR8("abc/def"); + DN_UTEST_TEST(TEST_FMT, DN_STR_FMT(input), DN_STR_FMT(delimiter)) { + DN_Str8BinarySplitResult split = DN_Str8_BinarySplit(input, delimiter); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(split.lhs, DN_STR8("abc")), "[lhs=%.*s]", DN_STR_FMT(split.lhs)); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(split.rhs, DN_STR8("def")), "[rhs=%.*s]", DN_STR_FMT(split.rhs)); } - input = DQN_STR8("/abcdef"); - DQN_UTEST_TEST(TEST_FMT, DQN_STR_FMT(input), DQN_STR_FMT(delimiter)) { - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplit(input, delimiter); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(split.lhs, DQN_STR8("")), "[lhs=%.*s]", DQN_STR_FMT(split.lhs)); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(split.rhs, DQN_STR8("abcdef")), "[rhs=%.*s]", DQN_STR_FMT(split.rhs)); + input = DN_STR8("/abcdef"); + DN_UTEST_TEST(TEST_FMT, DN_STR_FMT(input), DN_STR_FMT(delimiter)) { + DN_Str8BinarySplitResult split = DN_Str8_BinarySplit(input, delimiter); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(split.lhs, DN_STR8("")), "[lhs=%.*s]", DN_STR_FMT(split.lhs)); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(split.rhs, DN_STR8("abcdef")), "[rhs=%.*s]", DN_STR_FMT(split.rhs)); } } { - Dqn_Str8 delimiter = DQN_STR8("-=-"); - Dqn_Str8 input = DQN_STR8("123-=-456"); - DQN_UTEST_TEST("Binary split \"%.*s\" with \"%.*s\"", DQN_STR_FMT(input), DQN_STR_FMT(delimiter)) { - Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplit(input, delimiter); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(split.lhs, DQN_STR8("123")), "[lhs=%.*s]", DQN_STR_FMT(split.lhs)); - DQN_UTEST_ASSERTF(&test, Dqn_Str8_Eq(split.rhs, DQN_STR8("456")), "[rhs=%.*s]", DQN_STR_FMT(split.rhs)); + DN_Str8 delimiter = DN_STR8("-=-"); + DN_Str8 input = DN_STR8("123-=-456"); + DN_UTEST_TEST("Binary split \"%.*s\" with \"%.*s\"", DN_STR_FMT(input), DN_STR_FMT(delimiter)) { + DN_Str8BinarySplitResult split = DN_Str8_BinarySplit(input, delimiter); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(split.lhs, DN_STR8("123")), "[lhs=%.*s]", DN_STR_FMT(split.lhs)); + DN_UTEST_ASSERTF(&test, DN_Str8_Eq(split.rhs, DN_STR8("456")), "[rhs=%.*s]", DN_STR_FMT(split.rhs)); } } } - // NOTE: Dqn_Str8_ToI64 //////////////////////////////////////////////////////////////////// - DQN_UTEST_TEST("To I64: Convert null string") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(Dqn_Str8_Init(nullptr, 5), 0); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERT(&test, result.value == 0); + // NOTE: DN_Str8_ToI64 //////////////////////////////////////////////////////////////////// + DN_UTEST_TEST("To I64: Convert null string") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_Str8_Init(nullptr, 5), 0); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERT(&test, result.value == 0); } - DQN_UTEST_TEST("To I64: Convert empty string") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8(""), 0); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERT(&test, result.value == 0); + DN_UTEST_TEST("To I64: Convert empty string") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8(""), 0); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERT(&test, result.value == 0); } - DQN_UTEST_TEST("To I64: Convert \"1\"") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("1"), 0); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERT(&test, result.value == 1); + DN_UTEST_TEST("To I64: Convert \"1\"") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("1"), 0); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERT(&test, result.value == 1); } - DQN_UTEST_TEST("To I64: Convert \"-0\"") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("-0"), 0); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERT(&test, result.value == 0); + DN_UTEST_TEST("To I64: Convert \"-0\"") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("-0"), 0); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERT(&test, result.value == 0); } - DQN_UTEST_TEST("To I64: Convert \"-1\"") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("-1"), 0); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERT(&test, result.value == -1); + DN_UTEST_TEST("To I64: Convert \"-1\"") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("-1"), 0); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERT(&test, result.value == -1); } - DQN_UTEST_TEST("To I64: Convert \"1.2\"") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("1.2"), 0); - DQN_UTEST_ASSERT(&test, !result.success); - DQN_UTEST_ASSERT(&test, result.value == 1); + DN_UTEST_TEST("To I64: Convert \"1.2\"") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("1.2"), 0); + DN_UTEST_ASSERT(&test, !result.success); + DN_UTEST_ASSERT(&test, result.value == 1); } - DQN_UTEST_TEST("To I64: Convert \"1,234\"") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("1,234"), ','); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERT(&test, result.value == 1234); + DN_UTEST_TEST("To I64: Convert \"1,234\"") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("1,234"), ','); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERT(&test, result.value == 1234); } - DQN_UTEST_TEST("To I64: Convert \"1,2\"") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("1,2"), ','); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERT(&test, result.value == 12); + DN_UTEST_TEST("To I64: Convert \"1,2\"") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("1,2"), ','); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERT(&test, result.value == 12); } - DQN_UTEST_TEST("To I64: Convert \"12a3\"") { - Dqn_Str8ToI64Result result = Dqn_Str8_ToI64(DQN_STR8("12a3"), 0); - DQN_UTEST_ASSERT(&test, !result.success); - DQN_UTEST_ASSERT(&test, result.value == 12); + DN_UTEST_TEST("To I64: Convert \"12a3\"") { + DN_Str8ToI64Result result = DN_Str8_ToI64(DN_STR8("12a3"), 0); + DN_UTEST_ASSERT(&test, !result.success); + DN_UTEST_ASSERT(&test, result.value == 12); } - // NOTE: Dqn_Str8_ToU64 + // NOTE: DN_Str8_ToU64 // --------------------------------------------------------------------------------------------- - DQN_UTEST_TEST("To U64: Convert nullptr") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(Dqn_Str8_Init(nullptr, 5), 0); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERTF(&test, result.value == 0, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert nullptr") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_Str8_Init(nullptr, 5), 0); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERTF(&test, result.value == 0, "result: %" PRIu64, result.value); } - DQN_UTEST_TEST("To U64: Convert empty string") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(DQN_STR8(""), 0); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERTF(&test, result.value == 0, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert empty string") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_STR8(""), 0); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERTF(&test, result.value == 0, "result: %" PRIu64, result.value); } - DQN_UTEST_TEST("To U64: Convert \"1\"") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(DQN_STR8("1"), 0); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERTF(&test, result.value == 1, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert \"1\"") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_STR8("1"), 0); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERTF(&test, result.value == 1, "result: %" PRIu64, result.value); } - DQN_UTEST_TEST("To U64: Convert \"-0\"") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(DQN_STR8("-0"), 0); - DQN_UTEST_ASSERT(&test, !result.success); - DQN_UTEST_ASSERTF(&test, result.value == 0, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert \"-0\"") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_STR8("-0"), 0); + DN_UTEST_ASSERT(&test, !result.success); + DN_UTEST_ASSERTF(&test, result.value == 0, "result: %" PRIu64, result.value); } - DQN_UTEST_TEST("To U64: Convert \"-1\"") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(DQN_STR8("-1"), 0); - DQN_UTEST_ASSERT(&test, !result.success); - DQN_UTEST_ASSERTF(&test, result.value == 0, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert \"-1\"") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_STR8("-1"), 0); + DN_UTEST_ASSERT(&test, !result.success); + DN_UTEST_ASSERTF(&test, result.value == 0, "result: %" PRIu64, result.value); } - DQN_UTEST_TEST("To U64: Convert \"1.2\"") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(DQN_STR8("1.2"), 0); - DQN_UTEST_ASSERT(&test, !result.success); - DQN_UTEST_ASSERTF(&test, result.value == 1, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert \"1.2\"") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_STR8("1.2"), 0); + DN_UTEST_ASSERT(&test, !result.success); + DN_UTEST_ASSERTF(&test, result.value == 1, "result: %" PRIu64, result.value); } - DQN_UTEST_TEST("To U64: Convert \"1,234\"") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(DQN_STR8("1,234"), ','); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERTF(&test, result.value == 1234, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert \"1,234\"") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_STR8("1,234"), ','); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERTF(&test, result.value == 1234, "result: %" PRIu64, result.value); } - DQN_UTEST_TEST("To U64: Convert \"1,2\"") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(DQN_STR8("1,2"), ','); - DQN_UTEST_ASSERT(&test, result.success); - DQN_UTEST_ASSERTF(&test, result.value == 12, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert \"1,2\"") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_STR8("1,2"), ','); + DN_UTEST_ASSERT(&test, result.success); + DN_UTEST_ASSERTF(&test, result.value == 12, "result: %" PRIu64, result.value); } - DQN_UTEST_TEST("To U64: Convert \"12a3\"") { - Dqn_Str8ToU64Result result = Dqn_Str8_ToU64(DQN_STR8("12a3"), 0); - DQN_UTEST_ASSERT(&test, !result.success); - DQN_UTEST_ASSERTF(&test, result.value == 12, "result: %" PRIu64, result.value); + DN_UTEST_TEST("To U64: Convert \"12a3\"") { + DN_Str8ToU64Result result = DN_Str8_ToU64(DN_STR8("12a3"), 0); + DN_UTEST_ASSERT(&test, !result.success); + DN_UTEST_ASSERTF(&test, result.value == 12, "result: %" PRIu64, result.value); } - // NOTE: Dqn_Str8_Find ///////////////////////////////////////////////////////////////////// - DQN_UTEST_TEST("Find: String (char) is not in buffer") { - Dqn_Str8 buf = DQN_STR8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"); - Dqn_Str8 find = DQN_STR8("2"); - Dqn_Str8FindResult result = Dqn_Str8_FindStr8(buf, find, Dqn_Str8EqCase_Sensitive); - DQN_UTEST_ASSERT(&test, !result.found); - DQN_UTEST_ASSERT(&test, result.index == 0); - DQN_UTEST_ASSERT(&test, result.match.data == nullptr); - DQN_UTEST_ASSERT(&test, result.match.size == 0); + // NOTE: DN_Str8_Find ///////////////////////////////////////////////////////////////////// + DN_UTEST_TEST("Find: String (char) is not in buffer") { + DN_Str8 buf = DN_STR8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"); + DN_Str8 find = DN_STR8("2"); + DN_Str8FindResult result = DN_Str8_FindStr8(buf, find, DN_Str8EqCase_Sensitive); + DN_UTEST_ASSERT(&test, !result.found); + DN_UTEST_ASSERT(&test, result.index == 0); + DN_UTEST_ASSERT(&test, result.match.data == nullptr); + DN_UTEST_ASSERT(&test, result.match.size == 0); } - DQN_UTEST_TEST("Find: String (char) is in buffer") { - Dqn_Str8 buf = DQN_STR8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"); - Dqn_Str8 find = DQN_STR8("6"); - Dqn_Str8FindResult result = Dqn_Str8_FindStr8(buf, find, Dqn_Str8EqCase_Sensitive); - DQN_UTEST_ASSERT(&test, result.found); - DQN_UTEST_ASSERT(&test, result.index == 2); - DQN_UTEST_ASSERT(&test, result.match.data[0] == '6'); + DN_UTEST_TEST("Find: String (char) is in buffer") { + DN_Str8 buf = DN_STR8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"); + DN_Str8 find = DN_STR8("6"); + DN_Str8FindResult result = DN_Str8_FindStr8(buf, find, DN_Str8EqCase_Sensitive); + DN_UTEST_ASSERT(&test, result.found); + DN_UTEST_ASSERT(&test, result.index == 2); + DN_UTEST_ASSERT(&test, result.match.data[0] == '6'); } - // NOTE: Dqn_Str8_FileNameFromPath ///////////////////////////////////////////////////////// - DQN_UTEST_TEST("File name from Windows path") { - Dqn_Str8 buf = DQN_STR8("C:\\ABC\\test.exe"); - Dqn_Str8 result = Dqn_Str8_FileNameFromPath(buf); - DQN_UTEST_ASSERTF(&test, result == DQN_STR8("test.exe"), "%.*s", DQN_STR_FMT(result)); + // NOTE: DN_Str8_FileNameFromPath ///////////////////////////////////////////////////////// + DN_UTEST_TEST("File name from Windows path") { + DN_Str8 buf = DN_STR8("C:\\ABC\\test.exe"); + DN_Str8 result = DN_Str8_FileNameFromPath(buf); + DN_UTEST_ASSERTF(&test, result == DN_STR8("test.exe"), "%.*s", DN_STR_FMT(result)); } - DQN_UTEST_TEST("File name from Linux path") { - Dqn_Str8 buf = DQN_STR8("/ABC/test.exe"); - Dqn_Str8 result = Dqn_Str8_FileNameFromPath(buf); - DQN_UTEST_ASSERTF(&test, result == DQN_STR8("test.exe"), "%.*s", DQN_STR_FMT(result)); + DN_UTEST_TEST("File name from Linux path") { + DN_Str8 buf = DN_STR8("/ABC/test.exe"); + DN_Str8 result = DN_Str8_FileNameFromPath(buf); + DN_UTEST_ASSERTF(&test, result == DN_STR8("test.exe"), "%.*s", DN_STR_FMT(result)); } - // NOTE: Dqn_Str8_TrimPrefix + // NOTE: DN_Str8_TrimPrefix // ========================================================================================= - DQN_UTEST_TEST("Trim prefix") { - Dqn_Str8 prefix = DQN_STR8("@123"); - Dqn_Str8 buf = DQN_STR8("@123string"); - Dqn_Str8 result = Dqn_Str8_TrimPrefix(buf, prefix, Dqn_Str8EqCase_Sensitive); - DQN_UTEST_ASSERT(&test, result == DQN_STR8("string")); + DN_UTEST_TEST("Trim prefix") { + DN_Str8 prefix = DN_STR8("@123"); + DN_Str8 buf = DN_STR8("@123string"); + DN_Str8 result = DN_Str8_TrimPrefix(buf, prefix, DN_Str8EqCase_Sensitive); + DN_UTEST_ASSERT(&test, result == DN_STR8("string")); } } return test; } -static Dqn_UTest Dqn_Test_TicketMutex() +static DN_UTest DN_Test_TicketMutex() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_TicketMutex") { - DQN_UTEST_TEST("Ticket mutex start and stop") { + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_TicketMutex") { + DN_UTEST_TEST("Ticket mutex start and stop") { // TODO: We don't have a meaningful test but since atomics are // implemented with a macro this ensures that we test that they are // written correctly. - Dqn_TicketMutex mutex = {}; - Dqn_TicketMutex_Begin(&mutex); - Dqn_TicketMutex_End(&mutex); - DQN_UTEST_ASSERT(&test, mutex.ticket == mutex.serving); + DN_TicketMutex mutex = {}; + DN_TicketMutex_Begin(&mutex); + DN_TicketMutex_End(&mutex); + DN_UTEST_ASSERT(&test, mutex.ticket == mutex.serving); } - DQN_UTEST_TEST("Ticket mutex start and stop w/ advanced API") { - Dqn_TicketMutex mutex = {}; - unsigned int ticket_a = Dqn_TicketMutex_MakeTicket(&mutex); - unsigned int ticket_b = Dqn_TicketMutex_MakeTicket(&mutex); - DQN_UTEST_ASSERT(&test, DQN_CAST(bool)Dqn_TicketMutex_CanLock(&mutex, ticket_b) == false); - DQN_UTEST_ASSERT(&test, DQN_CAST(bool)Dqn_TicketMutex_CanLock(&mutex, ticket_a) == true); + DN_UTEST_TEST("Ticket mutex start and stop w/ advanced API") { + DN_TicketMutex mutex = {}; + unsigned int ticket_a = DN_TicketMutex_MakeTicket(&mutex); + unsigned int ticket_b = DN_TicketMutex_MakeTicket(&mutex); + DN_UTEST_ASSERT(&test, DN_CAST(bool)DN_TicketMutex_CanLock(&mutex, ticket_b) == false); + DN_UTEST_ASSERT(&test, DN_CAST(bool)DN_TicketMutex_CanLock(&mutex, ticket_a) == true); - Dqn_TicketMutex_BeginTicket(&mutex, ticket_a); - Dqn_TicketMutex_End(&mutex); - Dqn_TicketMutex_BeginTicket(&mutex, ticket_b); - Dqn_TicketMutex_End(&mutex); + DN_TicketMutex_BeginTicket(&mutex, ticket_a); + DN_TicketMutex_End(&mutex); + DN_TicketMutex_BeginTicket(&mutex, ticket_b); + DN_TicketMutex_End(&mutex); - DQN_UTEST_ASSERT(&test, mutex.ticket == mutex.serving); - DQN_UTEST_ASSERT(&test, mutex.ticket == ticket_b + 1); + DN_UTEST_ASSERT(&test, mutex.ticket == mutex.serving); + DN_UTEST_ASSERT(&test, mutex.ticket == ticket_b + 1); } } return test; } -static Dqn_UTest Dqn_Test_VArray() +static DN_UTest DN_Test_VArray() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "Dqn_VArray") { + DN_UTest test = {}; + DN_UTEST_GROUP(test, "DN_VArray") { { - Dqn_VArray array = Dqn_VArray_InitByteSize(DQN_KILOBYTES(64), 0); - DQN_DEFER { - Dqn_VArray_Deinit(&array); + DN_VArray array = DN_VArray_InitByteSize(DN_KILOBYTES(64)); + DN_DEFER { + DN_VArray_Deinit(&array); }; - DQN_UTEST_TEST("Test adding an array of items to the array") { + DN_UTEST_TEST("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}; - Dqn_VArray_AddArray(&array, array_literal, DQN_ARRAY_UCOUNT(array_literal)); - 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); + DN_VArray_AddArray(&array, array_literal, DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_UTEST_TEST("Test stable erase, 1 item, the '2' value from the array") { - Dqn_VArray_EraseRange(&array, 2 /*begin_index*/, 1 /*count*/, Dqn_ArrayErase_Stable); + DN_UTEST_TEST("Test stable erase, 1 item, the '2' value from the array") { + DN_VArray_EraseRange(&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}; - 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); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_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_ArrayErase_Unstable); + DN_UTEST_TEST("Test unstable erase, 1 item, the '1' value from the array") { + DN_VArray_EraseRange(&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}; - 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); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - Dqn_ArrayErase erase_enums[] = {Dqn_ArrayErase_Stable, Dqn_ArrayErase_Unstable}; - DQN_UTEST_TEST("Test un/stable erase, OOB") { - for (Dqn_ArrayErase erase : erase_enums) { + DN_ArrayErase erase_enums[] = {DN_ArrayErase_Stable, DN_ArrayErase_Unstable}; + DN_UTEST_TEST("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}; - 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)); - DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, array_literal, DQN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); + DN_VArray_EraseRange(&array, DN_ARRAY_UCOUNT(array_literal) /*begin_index*/, DN_ARRAY_UCOUNT(array_literal) + 100 /*count*/, erase); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } } - 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_ArrayErase_Stable); + DN_UTEST_TEST("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); 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); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_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_ArrayErase_Unstable); + DN_UTEST_TEST("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); 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); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_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_ArrayErase_Stable); + DN_UTEST_TEST("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); 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); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_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_ArrayErase_Unstable); + DN_UTEST_TEST("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); 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); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_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_ArrayErase_Stable); + DN_UTEST_TEST("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); 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); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_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_ArrayErase_Unstable); + DN_UTEST_TEST("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); 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); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(array_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, array_literal, DN_ARRAY_UCOUNT(array_literal) * sizeof(array_literal[0])) == 0); } - DQN_UTEST_TEST("Test adding an array of items after erase") { + DN_UTEST_TEST("Test adding an array of items after erase") { uint32_t array_literal[] = {0, 1, 2, 3}; - Dqn_VArray_AddArray(&array, array_literal, DQN_ARRAY_UCOUNT(array_literal)); + DN_VArray_AddArray(&array, array_literal, DN_ARRAY_UCOUNT(array_literal)); uint32_t expected_literal[] = {14, 6, 0, 1, 2, 3}; - DQN_UTEST_ASSERT(&test, array.size == DQN_ARRAY_UCOUNT(expected_literal)); - DQN_UTEST_ASSERT(&test, DQN_MEMCMP(array.data, expected_literal, DQN_ARRAY_UCOUNT(expected_literal) * sizeof(expected_literal[0])) == 0); + DN_UTEST_ASSERT(&test, array.size == DN_ARRAY_UCOUNT(expected_literal)); + DN_UTEST_ASSERT(&test, DN_MEMCMP(array.data, expected_literal, DN_ARRAY_UCOUNT(expected_literal) * sizeof(expected_literal[0])) == 0); } } - DQN_UTEST_TEST("Array of unaligned objects are contiguously laid out in memory") { + DN_UTEST_TEST("Array of unaligned objects are contiguously laid out in memory") { // NOTE: Since we allocate from a virtual memory block, each time // we request memory from the block we can demand some alignment // on the returned pointer from the memory block. If there's @@ -2122,125 +2078,125 @@ static Dqn_UTest Dqn_Test_VArray() // from the memory block (and hence the array) contiguously // when the size of the object is not aligned with the required // alignment of the object. - DQN_MSVC_WARNING_PUSH - DQN_MSVC_WARNING_DISABLE(4324) // warning C4324: 'TestVArray::UnalignedObject': structure was padded due to alignment specifier + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(4324) // warning C4324: 'TestVArray::UnalignedObject': structure was padded due to alignment specifier struct alignas(8) UnalignedObject { char data[511]; }; - DQN_MSVC_WARNING_POP + DN_MSVC_WARNING_POP - Dqn_VArray array = Dqn_VArray_InitByteSize(DQN_KILOBYTES(64), 0); - DQN_DEFER { - Dqn_VArray_Deinit(&array); + DN_VArray array = DN_VArray_InitByteSize(DN_KILOBYTES(64)); + DN_DEFER { + DN_VArray_Deinit(&array); }; // NOTE: Verify that the items returned from the data array are // contiguous in memory. - UnalignedObject *make_item_a = Dqn_VArray_MakeArray(&array, 1, Dqn_ZeroMem_Yes); - UnalignedObject *make_item_b = Dqn_VArray_MakeArray(&array, 1, Dqn_ZeroMem_Yes); - DQN_MEMSET(make_item_a->data, 'a', sizeof(make_item_a->data)); - DQN_MEMSET(make_item_b->data, 'b', sizeof(make_item_b->data)); - DQN_UTEST_ASSERT(&test, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1)); + UnalignedObject *make_item_a = DN_VArray_MakeArray(&array, 1, DN_ZeroMem_Yes); + UnalignedObject *make_item_b = DN_VArray_MakeArray(&array, 1, DN_ZeroMem_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_UTEST_ASSERT(&test, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1)); // NOTE: Verify that accessing the items from the data array yield // the same object. - DQN_UTEST_ASSERT(&test, array.size == 2); + DN_UTEST_ASSERT(&test, array.size == 2); UnalignedObject *data_item_a = array.data + 0; UnalignedObject *data_item_b = array.data + 1; - DQN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)(data_item_a + 1)); - DQN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)(make_item_a + 1)); - DQN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)make_item_b); + DN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)(data_item_a + 1)); + DN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)(make_item_a + 1)); + DN_UTEST_ASSERT(&test, (uintptr_t)data_item_b == (uintptr_t)make_item_b); - for (Dqn_usize i = 0; i < sizeof(data_item_a->data); i++) { - DQN_UTEST_ASSERT(&test, data_item_a->data[i] == 'a'); + for (DN_USize i = 0; i < sizeof(data_item_a->data); i++) { + DN_UTEST_ASSERT(&test, data_item_a->data[i] == 'a'); } - for (Dqn_usize i = 0; i < sizeof(data_item_b->data); i++) { - DQN_UTEST_ASSERT(&test, data_item_b->data[i] == 'b'); + for (DN_USize i = 0; i < sizeof(data_item_b->data); i++) { + DN_UTEST_ASSERT(&test, data_item_b->data[i] == 'b'); } } } return test; } -#if defined(DQN_PLATFORM_WIN32) -static Dqn_UTest Dqn_Test_Win() +#if defined(DN_PLATFORM_WIN32) +static DN_UTest DN_Test_Win() { - Dqn_UTest test = {}; - DQN_UTEST_GROUP(test, "OS Win32") { - Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); - Dqn_Str8 input8 = DQN_STR8("String"); - Dqn_Str16 input16 = Dqn_Str16{(wchar_t *)(L"String"), sizeof(L"String") / sizeof(L"String"[0]) - 1}; + DN_UTest test = {}; + DN_UTEST_GROUP(test, "OS Win32") { + DN_TLSTMem tmem = DN_TLS_TMem(nullptr); + DN_Str8 input8 = DN_STR8("String"); + DN_Str16 input16 = DN_Str16{(wchar_t *)(L"String"), sizeof(L"String") / sizeof(L"String"[0]) - 1}; - DQN_UTEST_TEST("Str8 to Str16") { - Dqn_Str16 result = Dqn_Win_Str8ToStr16(tmem.arena, input8); - DQN_UTEST_ASSERT(&test, result == input16); + DN_UTEST_TEST("Str8 to Str16") { + DN_Str16 result = DN_Win_Str8ToStr16(tmem.arena, input8); + DN_UTEST_ASSERT(&test, result == input16); } - DQN_UTEST_TEST("Str16 to Str8") { - Dqn_Str8 result = Dqn_Win_Str16ToStr8(tmem.arena, input16); - DQN_UTEST_ASSERT(&test, result == input8); + DN_UTEST_TEST("Str16 to Str8") { + DN_Str8 result = DN_Win_Str16ToStr8(tmem.arena, input16); + DN_UTEST_ASSERT(&test, result == input8); } - DQN_UTEST_TEST("Str16 to Str8: Null terminates string") { - int size_required = Dqn_Win_Str16ToStr8Buffer(input16, nullptr, 0); - char *string = Dqn_Arena_NewArray(tmem.arena, char, size_required + 1, Dqn_ZeroMem_No); + DN_UTEST_TEST("Str16 to Str8: Null terminates string") { + int size_required = DN_Win_Str16ToStr8Buffer(input16, nullptr, 0); + char *string = DN_Arena_NewArray(tmem.arena, char, size_required + 1, DN_ZeroMem_No); // Fill the string with error sentinels - DQN_MEMSET(string, 'Z', size_required + 1); + DN_MEMSET(string, 'Z', size_required + 1); - int size_returned = Dqn_Win_Str16ToStr8Buffer(input16, string, size_required + 1); + int size_returned = DN_Win_Str16ToStr8Buffer(input16, string, size_required + 1); char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; - DQN_UTEST_ASSERTF(&test, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); - DQN_UTEST_ASSERTF(&test, size_returned == DQN_ARRAY_UCOUNT(EXPECTED) - 1, "string_size: %d, expected: %zu", size_returned, DQN_ARRAY_UCOUNT(EXPECTED) - 1); - DQN_UTEST_ASSERT(&test, DQN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); + DN_UTEST_ASSERTF(&test, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); + DN_UTEST_ASSERTF(&test, size_returned == DN_ARRAY_UCOUNT(EXPECTED) - 1, "string_size: %d, expected: %zu", size_returned, DN_ARRAY_UCOUNT(EXPECTED) - 1); + DN_UTEST_ASSERT(&test, DN_MEMCMP(EXPECTED, string, sizeof(EXPECTED)) == 0); } - DQN_UTEST_TEST("Str16 to Str8: Arena null terminates string") { - Dqn_Str8 string8 = Dqn_Win_Str16ToStr8(tmem.arena, input16); - int size_returned = Dqn_Win_Str16ToStr8Buffer(input16, nullptr, 0); + DN_UTEST_TEST("Str16 to Str8: Arena null terminates string") { + DN_Str8 string8 = DN_Win_Str16ToStr8(tmem.arena, input16); + int size_returned = DN_Win_Str16ToStr8Buffer(input16, nullptr, 0); char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; - DQN_UTEST_ASSERTF(&test, DQN_CAST(int)string8.size == size_returned, "string_size: %d, result: %d", DQN_CAST(int)string8.size, size_returned); - DQN_UTEST_ASSERTF(&test, DQN_CAST(int)string8.size == DQN_ARRAY_UCOUNT(EXPECTED) - 1, "string_size: %d, expected: %zu", DQN_CAST(int)string8.size, DQN_ARRAY_UCOUNT(EXPECTED) - 1); - DQN_UTEST_ASSERT (&test, DQN_MEMCMP(EXPECTED, string8.data, sizeof(EXPECTED)) == 0); + DN_UTEST_ASSERTF(&test, DN_CAST(int)string8.size == size_returned, "string_size: %d, result: %d", DN_CAST(int)string8.size, size_returned); + DN_UTEST_ASSERTF(&test, DN_CAST(int)string8.size == DN_ARRAY_UCOUNT(EXPECTED) - 1, "string_size: %d, expected: %zu", DN_CAST(int)string8.size, DN_ARRAY_UCOUNT(EXPECTED) - 1); + DN_UTEST_ASSERT (&test, DN_MEMCMP(EXPECTED, string8.data, sizeof(EXPECTED)) == 0); } } return test; } -#endif // DQN_PLATFORM_WIN#@ +#endif // DN_PLATFORM_WIN#@ -void Dqn_Test_RunSuite() +void DN_Test_RunSuite() { - Dqn_UTest tests[] = + DN_UTest tests[] = { - Dqn_Test_Base(), - Dqn_Test_Arena(), - Dqn_Test_Bin(), - Dqn_Test_BinarySearch(), - Dqn_Test_DSMap(), - Dqn_Test_FStr8(), - Dqn_Test_Fs(), - Dqn_Test_FixedArray(), - Dqn_Test_Intrinsics(), - #if defined(DQN_UNIT_TESTS_WITH_KECCAK) - Dqn_Test_Keccak(), + DN_Test_Base(), + DN_Test_Arena(), + DN_Test_Bin(), + DN_Test_BinarySearch(), + DN_Test_DSMap(), + DN_Test_FStr8(), + DN_Test_Fs(), + DN_Test_FixedArray(), + DN_Test_Intrinsics(), + #if defined(DN_UNIT_TESTS_WITH_KECCAK) + DN_Test_Keccak(), #endif - Dqn_Test_M4(), - Dqn_Test_OS(), - Dqn_Test_Rect(), - Dqn_Test_Str8(), - Dqn_Test_TicketMutex(), - Dqn_Test_VArray(), - #if defined(DQN_PLATFORM_WIN32) - Dqn_Test_Win(), + DN_Test_M4(), + DN_Test_OS(), + DN_Test_Rect(), + DN_Test_Str8(), + DN_Test_TicketMutex(), + DN_Test_VArray(), + #if defined(DN_PLATFORM_WIN32) + DN_Test_Win(), #endif }; int total_tests = 0; int total_good_tests = 0; - for (const Dqn_UTest &test : tests) { + for (const DN_UTest &test : tests) { total_tests += test.num_tests_in_group; total_good_tests += test.num_tests_ok_in_group; } @@ -2248,12 +2204,3 @@ void Dqn_Test_RunSuite() fprintf(stdout, "Summary: %d/%d tests succeeded\n", total_good_tests, total_tests); } -#if defined(DQN_UNIT_TESTS_WITH_MAIN) -int main(int argc, char *argv[]) -{ - (void)argv; (void)argc; - Dqn_Library_Init(Dqn_LibraryOnInit_LogFeatures); - Dqn_Test_RunSuite(); - return 0; -} -#endif diff --git a/dqn_unit_tests_main.cpp b/dqn_unit_tests_main.cpp new file mode 100644 index 0000000..d465753 --- /dev/null +++ b/dqn_unit_tests_main.cpp @@ -0,0 +1,12 @@ +#include "dqn.h" +#include "dqn.cpp" +#include "dqn_unit_tests.cpp" + +int main(int argc, char *argv[]) +{ + (void)argv; (void)argc; + DN_Core *core = (DN_Core *)DN_OS_MemAlloc(sizeof(DN_Core), DN_ZeroMem_Yes); + DN_Core_Init(core, DN_CoreOnInit_LogAllFeatures); + DN_Test_RunSuite(); + return 0; +} diff --git a/dqn_win32.h b/dqn_win32.h index 9a7f808..fee808e 100644 --- a/dqn_win32.h +++ b/dqn_win32.h @@ -13,12 +13,12 @@ // $$ / \$$ |$$$$$$\ $$ | \$$ |\$$$$$$ |$$$$$$$$\ // \__/ \__|\______|\__| \__| \______/ \________| // -// dqn_win32.h -- Windows replacement header +// dn_win32.h -- Windows replacement header // //////////////////////////////////////////////////////////////////////////////////////////////////// */ -#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) #pragma comment(lib, "bcrypt") #pragma comment(lib, "winhttp") #pragma comment(lib, "dbghelp") @@ -27,18 +27,19 @@ #pragma comment(lib, "shlwapi") #endif -#if defined(DQN_NO_WIN32_MIN_HEADER) || defined(_INC_WINDOWS) +#if defined(DN_NO_WIN32_MIN_HEADER) || defined(_INC_WINDOWS) #define WIN32_LEAN_AND_MEAN #include // LONG - #include // Dqn_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc - #include // Dqn_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc + #include // DN_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc + #include // DN_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc #include // PathRelativePathTO #include // PathCchCanonicalizeEx #include // WinHttp* + #include // OPENFILENAMEW #include #else - DQN_MSVC_WARNING_PUSH - DQN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union + DN_MSVC_WARNING_PUSH + DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union // NOTE: basetsd.h ///////////////////////////////////////////////////////////////////////////// typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; @@ -111,6 +112,25 @@ #define PAGE_READWRITE 0x04 #define PAGE_GUARD 0x100 + // NOTE: HeapAlloc + #define HEAP_ZERO_MEMORY 0x00000008 + #define HEAP_NO_SERIALIZE 0x00000001 + #define HEAP_GROWABLE 0x00000002 + #define HEAP_GENERATE_EXCEPTIONS 0x00000004 + #define HEAP_ZERO_MEMORY 0x00000008 + #define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010 + #define HEAP_TAIL_CHECKING_ENABLED 0x00000020 + #define HEAP_FREE_CHECKING_ENABLED 0x00000040 + #define HEAP_DISABLE_COALESCE_ON_FREE 0x00000080 + #define HEAP_CREATE_ALIGN_16 0x00010000 + #define HEAP_CREATE_ENABLE_TRACING 0x00020000 + #define HEAP_CREATE_ENABLE_EXECUTE 0x00040000 + #define HEAP_MAXIMUM_TAG 0x0FFF + #define HEAP_PSEUDO_TAG_FLAG 0x8000 + #define HEAP_TAG_SHIFT 18 + #define HEAP_CREATE_SEGMENT_HEAP 0x00000100 + #define HEAP_CREATE_HARDENED 0x00000200 + // NOTE: FormatMessageA #define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p)) #define LANG_NEUTRAL 0x00 @@ -331,6 +351,19 @@ __declspec(dllimport) BOOL __stdcall SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll); } + // NOTE: um/heapapi.h //////////////////////////////////////////////////////////////////// + extern "C" + { + __declspec(dllimport) HANDLE __stdcall HeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize); + __declspec(dllimport) BOOL __stdcall HeapDestroy(HANDLE hHeap); + __declspec(dllimport) VOID * __stdcall HeapAlloc(HANDLE hHeap, DWORD dwFlags,SIZE_T dwBytes); + __declspec(dllimport) VOID * __stdcall HeapReAlloc(HANDLE hHeap, DWORD dwFlags, VOID *lpMem, SIZE_T dwBytes); + __declspec(dllimport) BOOL __stdcall HeapFree(HANDLE hHeap, DWORD dwFlags, VOID *lpMem); + __declspec(dllimport) SIZE_T __stdcall HeapSize(HANDLE hHeap, DWORD dwFlags, VOID const *lpMem); + __declspec(dllimport) HANDLE __stdcall GetProcessHeap(VOID); + __declspec(dllimport) SIZE_T __stdcall HeapCompact(HANDLE hHeap, DWORD dwFlags); + } + // NOTE: shared/windef.h //////////////////////////////////////////////////////////////////// typedef struct tagPOINT { @@ -367,6 +400,10 @@ #define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 ) #define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 ) + // NOTE: CreateProcessW + #define CREATE_UNICODE_ENVIRONMENT 0x00000400 + #define CREATE_NO_WINDOW 0x08000000 + typedef enum _GET_FILEEX_INFO_LEVELS { GetFileExInfoStandard, GetFileExMaxInfoLevel @@ -499,9 +536,12 @@ extern "C" { + __declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile); __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); + __declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile); + __declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags); __declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation); __declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); @@ -509,14 +549,17 @@ __declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); __declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); - } // NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// extern "C" { - __declspec(dllimport) DWORD __stdcall GetCurrentDirectoryW(DWORD nBufferLength, WCHAR *lpBuffer); - __declspec(dllimport) HANDLE __stdcall GetStdHandle(DWORD nStdHandle); + __declspec(dllimport) DWORD __stdcall GetCurrentDirectoryW (DWORD nBufferLength, WCHAR *lpBuffer); + __declspec(dllimport) HANDLE __stdcall GetStdHandle (DWORD nStdHandle); + __declspec(dllimport) WCHAR* __stdcall GetEnvironmentStringsW (); + __declspec(dllimport) BOOL __stdcall FreeEnvironmentStringsW(WCHAR *penv); + __declspec(dllimport) DWORD __stdcall GetEnvironmentVariableW(WCHAR const *lpName, WCHAR *lpBuffer, DWORD nSize); + __declspec(dllimport) BOOL __stdcall SetEnvironmentVariableW(WCHAR const *lpName, WCHAR const *lpValue); } // NOTE: um/sysinfoapi.h /////////////////////////////////////////////////////////////////////// @@ -548,10 +591,21 @@ } // NOTE: um/timezoneapi.h ////////////////////////////////////////////////////////////////////// + typedef struct _TIME_ZONE_INFORMATION { + LONG Bias; + WCHAR StandardName[32]; + SYSTEMTIME StandardDate; + LONG StandardBias; + WCHAR DaylightName[32]; + SYSTEMTIME DaylightDate; + LONG DaylightBias; + } TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION; + extern "C" { - __declspec(dllimport) BOOL __stdcall FileTimeToSystemTime(const FILETIME* lpFileTime, SYSTEMTIME *lpSystemTime); - __declspec(dllimport) BOOL __stdcall SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, FILETIME *lpFileTime); + __declspec(dllimport) BOOL __stdcall FileTimeToSystemTime (const FILETIME* lpFileTime, SYSTEMTIME *lpSystemTime); + __declspec(dllimport) BOOL __stdcall SystemTimeToFileTime (const SYSTEMTIME* lpSystemTime, FILETIME *lpFileTime); + __declspec(dllimport) BOOL __stdcall TzSpecificLocalTimeToSystemTime(const TIME_ZONE_INFORMATION* lpTimeZoneInformation, const SYSTEMTIME* lpLocalTime, const LPSYSTEMTIME lpUniversalTime); } // NOTE: shared/windef.h /////////////////////////////////////////////////////////////////////// @@ -1249,5 +1303,16 @@ __declspec(dllimport) HRESULT __stdcall PathCchCanonicalizeEx(PWSTR pszPathOut, size_t cchPathOut, WCHAR const *pszPathIn, ULONG dwFlags); }; - DQN_MSVC_WARNING_POP + // NOTE: um/errhandlingapi.h /////////////////////////////////////////////////////////////////// + extern "C" + { + __declspec(dllimport) VOID __stdcall RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR* lpArguments); + }; + + // NOTE: include/excpt.h /////////////////////////////////////////////////////////////////// + #define EXCEPTION_EXECUTE_HANDLER 1 + #define EXCEPTION_CONTINUE_SEARCH 0 + #define EXCEPTION_CONTINUE_EXECUTION (-1) + + DN_MSVC_WARNING_POP #endif // !defined(_INC_WINDOWS)