Get latest DQN lib from side projects

This commit is contained in:
doylet 2025-02-14 00:27:42 +11:00
parent 6b403eae71
commit a844d2b992
45 changed files with 11343 additions and 10359 deletions

View File

@ -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) #if !defined(DN_CPP_FILE_H)
#define DQN_CPP_FILE_H #define DN_CPP_FILE_H
#include <stdio.h> /// printf, fputc #include <stdio.h> /// printf, fputc
#include <stdarg.h> /// va_list... #include <stdarg.h> /// va_list...
#include <assert.h> /// assert #include <assert.h> /// 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 FILE *file; ///< (Write) File to print to
int indent; ///< Current indent level of the printer int indent; ///< Current indent level of the printer
int space_per_indent; ///< (Write) Number of spaces per indent int space_per_indent; ///< (Write) Number of spaces per indent
unsigned char if_chain[256]; /// unsigned char if_chain[256]; ///
unsigned char if_chain_size; /// 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. /// 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 DN_CppLineV(DN_CppFile *cpp, char const *fmt, va_list args);
void Dqn_CppLine(Dqn_CppFile *cpp, char const *fmt, ...); void DN_CppLine(DN_CppFile *cpp, char const *fmt, ...);
/// Print the format string indented /// Print the format string indented
void Dqn_CppPrintV(Dqn_CppFile *cpp, char const *fmt, va_list args); void DN_CppPrintV(DN_CppFile *cpp, char const *fmt, va_list args);
void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...); void DN_CppPrint(DN_CppFile *cpp, char const *fmt, ...);
/// Print the format string /// Print the format string
#define Dqn_CppAppend(cpp, fmt, ...) fprintf((cpp)->file, fmt, ##__VA_ARGS__) #define DN_CppAppend(cpp, fmt, ...) fprintf((cpp)->file, fmt, ##__VA_ARGS__)
#define Dqn_CppAppendV(cpp, fmt, args) vfprintf((cpp)->file, fmt, args) #define DN_CppAppendV(cpp, fmt, args) vfprintf((cpp)->file, fmt, args)
/// End the current line, useful after CppPrint and CppAppend /// 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 /// Manually modify the indent level
#define Dqn_CppIndent(cpp) (cpp)->indent++ #define DN_CppIndent(cpp) (cpp)->indent++
#define Dqn_CppUnindent(cpp) (cpp)->indent--; assert((cpp)->indent >= 0) #define DN_CppUnindent(cpp) (cpp)->indent--; assert((cpp)->indent >= 0)
/// Block scope functions that execute a function on entry and exit of the /// Block scope functions that execute a function on entry and exit of the
/// scope by exploiting the comma operator and a for loop. /// scope by exploiting the comma operator and a for loop.
/// ///
/// @code /// @code
/// Dqn_CppEnumBlock(cpp, "abc") { /// DN_CppEnumBlock(cpp, "abc") {
/// printf("Hello world!"); /// printf("Hello world!");
/// } /// }
/// ///
/// // Is equivalent to /// // Is equivalent to
/// ///
/// Dqn_CppBeginBlock(cpp, "abc"); /// DN_CppBeginBlock(cpp, "abc");
/// printf("Hello world!"); /// printf("Hello world!");
/// Dqn_CppEndEnumBlock(cpp); /// DN_CppEndEnumBlock(cpp);
/// @endcode /// @endcode
#define Dqn_CppEnumBlock(cpp, fmt, ...) \ #define DN_CppEnumBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginEnumBlock(cpp, fmt, ##__VA_ARGS__), true); \ (DN_CppBeginEnumBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndEnumBlock(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndEnumBlock(cpp), false))
#define Dqn_CppForBlock(cpp, fmt, ...) \ #define DN_CppForBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginForBlock(cpp, fmt, ##__VA_ARGS__), true); \ (DN_CppBeginForBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndForBlock(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndForBlock(cpp), false))
#define Dqn_CppWhileBlock(cpp, fmt, ...) \ #define DN_CppWhileBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginWhileBlock(cpp, fmt, ##__VA_ARGS__), true); \ (DN_CppBeginWhileBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndWhileBlock(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndWhileBlock(cpp), false))
#define Dqn_CppIfOrElseIfBlock(cpp, fmt, ...) \ #define DN_CppIfOrElseIfBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginIfOrElseIfBlock(cpp, fmt, ##__VA_ARGS__), true); \ (DN_CppBeginIfOrElseIfBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndIfOrElseIfBlock(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndIfOrElseIfBlock(cpp), false))
#define Dqn_CppElseBlock(cpp) \ #define DN_CppElseBlock(cpp) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginElseBlock(cpp), true); \ (DN_CppBeginElseBlock(cpp), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndElseBlock(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndElseBlock(cpp), false))
#define Dqn_CppFuncBlock(cpp, fmt, ...) \ #define DN_CppFuncBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginFuncBlock(cpp, fmt, ##__VA_ARGS__), true); \ (DN_CppBeginFuncBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndFuncBlock(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndFuncBlock(cpp), false))
#define Dqn_CppStructBlock(cpp, fmt, ...) \ #define DN_CppStructBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginStructBlock(cpp, fmt, ##__VA_ARGS__), true); \ (DN_CppBeginStructBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndStructBlock(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndStructBlock(cpp), false))
#define Dqn_CppSwitchBlock(cpp, fmt, ...) \ #define DN_CppSwitchBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginSwitchBlock(cpp, fmt, ##__VA_ARGS__), true); \ (DN_CppBeginSwitchBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndSwitchBlock(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndSwitchBlock(cpp), false))
#define Dqn_CppBlock(cpp, ending, fmt, ...) \ #define DN_CppBlock(cpp, ending, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__), true); \ (DN_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndBlock(cpp, ending), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndBlock(cpp, ending), false))
#define Dqn_CppIfChain(cpp) \ #define DN_CppIfChain(cpp) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppBeginIfChain(cpp), true); \ for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppBeginIfChain(cpp), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndIfChain(cpp), false)) DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndIfChain(cpp), false))
/// Print the format string followed by a "{" and enter a new line whilst /// Print the format string followed by a "{" and enter a new line whilst
/// increasing the indent level after the brace. /// increasing the indent level after the brace.
void Dqn_CppBeginBlock (Dqn_CppFile *cpp, bool append, char const *fmt, ...); void DN_CppBeginBlock (DN_CppFile *cpp, bool append, char const *fmt, ...);
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);
void Dqn_CppEndBlock (Dqn_CppFile *cpp, char const *ending); void DN_CppEndBlock (DN_CppFile *cpp, char const *ending);
/// Begin/End a block, specifically for the following language constructs. /// 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 DN_CppBeginEnumBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "enum " fmt, ##__VA_ARGS__)
#define Dqn_CppEndEnumBlock(cpp) Dqn_CppEndBlock(cpp, ";\n") #define DN_CppEndEnumBlock(cpp) DN_CppEndBlock(cpp, ";\n")
#define Dqn_CppBeginWhileBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "while (" fmt ")", ##__VA_ARGS__) #define DN_CppBeginWhileBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "while (" fmt ")", ##__VA_ARGS__)
#define Dqn_CppEndWhileBlock(cpp) Dqn_CppEndBlock(cpp, "\n") #define DN_CppEndWhileBlock(cpp) DN_CppEndBlock(cpp, "\n")
#define Dqn_CppBeginForBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "for (" fmt ")", ##__VA_ARGS__) #define DN_CppBeginForBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "for (" fmt ")", ##__VA_ARGS__)
#define Dqn_CppEndForBlock(cpp) Dqn_CppEndBlock(cpp, "\n") #define DN_CppEndForBlock(cpp) DN_CppEndBlock(cpp, "\n")
#define Dqn_CppBeginFuncBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__) #define DN_CppBeginFuncBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__)
#define Dqn_CppEndFuncBlock(cpp) Dqn_CppEndBlock(cpp, "\n") #define DN_CppEndFuncBlock(cpp) DN_CppEndBlock(cpp, "\n")
#define Dqn_CppBeginStructBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "struct " fmt, ##__VA_ARGS__) #define DN_CppBeginStructBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "struct " fmt, ##__VA_ARGS__)
#define Dqn_CppEndStructBlock(cpp) Dqn_CppEndBlock(cpp, ";\n") #define DN_CppEndStructBlock(cpp) DN_CppEndBlock(cpp, ";\n")
#define Dqn_CppBeginSwitchBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "switch (" fmt ")", ##__VA_ARGS__) #define DN_CppBeginSwitchBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "switch (" fmt ")", ##__VA_ARGS__)
#define Dqn_CppEndSwitchBlock(cpp) Dqn_CppEndBlock(cpp, "\n") #define DN_CppEndSwitchBlock(cpp) DN_CppEndBlock(cpp, "\n")
void Dqn_CppBeginIfOrElseIfBlock (Dqn_CppFile *cpp, char const *fmt, ...); void DN_CppBeginIfOrElseIfBlock (DN_CppFile *cpp, char const *fmt, ...);
#define Dqn_CppEndIfOrElseIfBlock(cpp) Dqn_CppEndBlock(cpp, "") #define DN_CppEndIfOrElseIfBlock(cpp) DN_CppEndBlock(cpp, "")
void Dqn_CppBeginElseBlock (Dqn_CppFile *cpp); void DN_CppBeginElseBlock (DN_CppFile *cpp);
void Dqn_CppEndElseBlock (Dqn_CppFile *cpp); void DN_CppEndElseBlock (DN_CppFile *cpp);
#define DQN_CPP_TOKEN_PASTE2_(x, y) x ## y #define DN_CPP_TOKEN_PASTE2_(x, y) x ## y
#define DQN_CPP_TOKEN_PASTE_(x, y) DQN_CPP_TOKEN_PASTE2_(x, y) #define DN_CPP_TOKEN_PASTE_(x, y) DN_CPP_TOKEN_PASTE2_(x, y)
#endif // DQN_CPP_FILE_H #endif // DN_CPP_FILE_H
#if defined(DQN_CPP_FILE_IMPLEMENTATION) #if defined(DN_CPP_FILE_IMPLEMENTATION)
void Dqn_CppLineV(Dqn_CppFile *cpp, char const *fmt, va_list args) void DN_CppLineV(DN_CppFile *cpp, char const *fmt, va_list args)
{ {
Dqn_CppPrintV(cpp, fmt, args); DN_CppPrintV(cpp, fmt, args);
Dqn_CppNewLine(cpp); 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_list args;
va_start(args, fmt); va_start(args, fmt);
Dqn_CppLineV(cpp, fmt, args); DN_CppLineV(cpp, fmt, args);
va_end(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; int spaces = fmt ? (cpp->indent * space_per_indent) : 0;
fprintf(cpp->file, "%*s", spaces, ""); fprintf(cpp->file, "%*s", spaces, "");
vfprintf(cpp->file, fmt, args); 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_list args;
va_start(args, fmt); va_start(args, fmt);
Dqn_CppPrintV(cpp, fmt, args); DN_CppPrintV(cpp, fmt, args);
va_end(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_list args;
va_start(args, fmt); va_start(args, fmt);
Dqn_CppBeginBlockV(cpp, append, fmt, args); DN_CppBeginBlockV(cpp, append, fmt, args);
va_end(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) if (append)
Dqn_CppAppendV(cpp, fmt, args); DN_CppAppendV(cpp, fmt, args);
else else
Dqn_CppPrintV(cpp, fmt, args); DN_CppPrintV(cpp, fmt, args);
bool empty_fmt = fmt == nullptr || strlen(fmt) == 0; bool empty_fmt = fmt == nullptr || strlen(fmt) == 0;
Dqn_CppAppend(cpp, "%s{\n", empty_fmt ? "" : " "); DN_CppAppend(cpp, "%s{\n", empty_fmt ? "" : " ");
Dqn_CppIndent(cpp); DN_CppIndent(cpp);
} }
void Dqn_CppEndBlock(Dqn_CppFile *cpp, char const *ending) void DN_CppEndBlock(DN_CppFile *cpp, char const *ending)
{ {
Dqn_CppUnindent(cpp); DN_CppUnindent(cpp);
Dqn_CppPrint(cpp, "}%s", ending); 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_list args;
va_start(args, fmt); va_start(args, fmt);
assert(cpp->if_chain_size); assert(cpp->if_chain_size);
if (cpp->if_chain[cpp->if_chain_size - 1] == 0) if (cpp->if_chain[cpp->if_chain_size - 1] == 0)
Dqn_CppPrint(cpp, "if"); DN_CppPrint(cpp, "if");
else else
Dqn_CppAppend(cpp, " else if"); DN_CppAppend(cpp, " else if");
Dqn_CppAppend(cpp, " ("); DN_CppAppend(cpp, " (");
Dqn_CppAppendV(cpp, fmt, args); DN_CppAppendV(cpp, fmt, args);
Dqn_CppAppend(cpp, ") {\n"); DN_CppAppend(cpp, ") {\n");
Dqn_CppIndent(cpp); DN_CppIndent(cpp);
va_end(args); va_end(args);
cpp->if_chain[cpp->if_chain_size - 1]++; 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); assert(cpp->if_chain_size);
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1) 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) 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])); assert(cpp->if_chain_size < sizeof(cpp->if_chain)/sizeof(cpp->if_chain[0]));
cpp->if_chain_size++; cpp->if_chain_size++;
} }
void Dqn_CppEndIfChain(Dqn_CppFile *cpp) void DN_CppEndIfChain(DN_CppFile *cpp)
{ {
assert(cpp->if_chain_size); assert(cpp->if_chain_size);
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1) { 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[cpp->if_chain_size - 1] = 0;
cpp->if_chain_size--; cpp->if_chain_size--;
} }
#endif // DQN_CPP_FILE_IMPLEMENTATION #endif // DN_CPP_FILE_IMPLEMENTATION

View File

@ -1,5 +1,5 @@
#if !defined(DQN_KECCAK_H) #if !defined(DN_KECCAK_H)
#define DQN_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 // - Define this in one and only one C++ file to enable the implementation
// code of the header file. // code of the header file.
// //
// #define DQN_KECCAK_IMPLEMENTATION // #define DN_KECCAK_IMPLEMENTATION
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
#if !defined(DQN_KECCAK_MEMCPY) #if !defined(DN_KECCAK_MEMCPY)
#include <string.h> #include <string.h>
#define DQN_KECCAK_MEMCPY(dest, src, count) memcpy(dest, src, count) #define DN_KECCAK_MEMCPY(dest, src, count) memcpy(dest, src, count)
#endif #endif
#if !defined(DQN_KECCAK_MEMCMP) #if !defined(DN_KECCAK_MEMCMP)
#include <string.h> #include <string.h>
#define DQN_KECCAK_MEMCMP(dest, src, count) memcmp(dest, src, count) #define DN_KECCAK_MEMCMP(dest, src, count) memcmp(dest, src, count)
#endif #endif
#if !defined(DQN_KECCAK_MEMSET) #if !defined(DN_KECCAK_MEMSET)
#include <string.h> #include <string.h>
#define DQN_KECCAK_MEMSET(dest, byte, count) memset(dest, byte, count) #define DN_KECCAK_MEMSET(dest, byte, count) memset(dest, byte, count)
#endif #endif
#if !defined(DQN_KECCAK_ASSERT) #if !defined(DN_KECCAK_ASSERT)
#if defined(NDEBUG) #if defined(NDEBUG)
#define DQN_KECCAK_ASSERT(expr) #define DN_KECCAK_ASSERT(expr)
#else #else
#define DQN_KECCAK_ASSERT(expr) \ #define DN_KECCAK_ASSERT(expr) \
do \ do \
{ \ { \
if (!(expr)) \ if (!(expr)) \
@ -102,43 +102,43 @@
// Use this macro in a printf-like function, // Use this macro in a printf-like function,
/* /*
Dqn_KeccakString64 string = {}; DN_KeccakString64 string = {};
printf("%.*s\n", DQN_KECCAK_STRING64_FMT(string)); printf("%.*s\n", DN_KECCAK_STRING64_FMT(string));
*/ */
#define DQN_KECCAK_STRING56_FMT(string) 56, string #define DN_KECCAK_STRING56_FMT(string) 56, string
#define DQN_KECCAK_STRING64_FMT(string) 64, string #define DN_KECCAK_STRING64_FMT(string) 64, string
#define DQN_KECCAK_STRING96_FMT(string) 96, string #define DN_KECCAK_STRING96_FMT(string) 96, string
#define DQN_KECCAK_STRING128_FMT(string) 128, string #define DN_KECCAK_STRING128_FMT(string) 128, string
typedef unsigned char Dqn_KeccakU8; typedef unsigned char DN_KeccakU8;
typedef unsigned short Dqn_KeccakU16; typedef unsigned short DN_KeccakU16;
typedef unsigned int Dqn_KeccakU32; typedef unsigned int DN_KeccakU32;
typedef unsigned int Dqn_KeccakUint; typedef unsigned int DN_KeccakUint;
#ifdef _MSC_VER #ifdef _MSC_VER
typedef unsigned __int64 Dqn_KeccakU64; typedef unsigned __int64 DN_KeccakU64;
#else #else
typedef unsigned long long Dqn_KeccakU64; typedef unsigned long long DN_KeccakU64;
#endif #endif
typedef struct Dqn_KeccakBytes28 { char data[28]; } Dqn_KeccakBytes28; // 224 bit typedef struct DN_KeccakBytes28 { char data[28]; } DN_KeccakBytes28; // 224 bit
typedef struct Dqn_KeccakBytes32 { char data[32]; } Dqn_KeccakBytes32; // 256 bit typedef struct DN_KeccakBytes32 { char data[32]; } DN_KeccakBytes32; // 256 bit
typedef struct Dqn_KeccakBytes48 { char data[48]; } Dqn_KeccakBytes48; // 384 bit typedef struct DN_KeccakBytes48 { char data[48]; } DN_KeccakBytes48; // 384 bit
typedef struct Dqn_KeccakBytes64 { char data[64]; } Dqn_KeccakBytes64; // 512 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 DN_KeccakString56 { char data[(sizeof(DN_KeccakBytes28) * 2) + 1]; } DN_KeccakString56;
typedef struct Dqn_KeccakString64 { char data[(sizeof(Dqn_KeccakBytes32) * 2) + 1]; } Dqn_KeccakString64; typedef struct DN_KeccakString64 { char data[(sizeof(DN_KeccakBytes32) * 2) + 1]; } DN_KeccakString64;
typedef struct Dqn_KeccakString96 { char data[(sizeof(Dqn_KeccakBytes48) * 2) + 1]; } Dqn_KeccakString96; typedef struct DN_KeccakString96 { char data[(sizeof(DN_KeccakBytes48) * 2) + 1]; } DN_KeccakString96;
typedef struct Dqn_KeccakString128 { char data[(sizeof(Dqn_KeccakBytes64) * 2) + 1]; } Dqn_KeccakString128; typedef struct DN_KeccakString128 { char data[(sizeof(DN_KeccakBytes64) * 2) + 1]; } DN_KeccakString128;
#define DQN_KECCAK_LANE_SIZE_U64 5 #define DN_KECCAK_LANE_SIZE_U64 5
typedef struct Dqn_KeccakState 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 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 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 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 char delimited_suffix; // The delimited suffix of the current hash
} Dqn_KeccakState; } DN_KeccakState;
// NOTE: SHA3/Keccak Streaming API ///////////////////////////////////////////////////////////////// // NOTE: SHA3/Keccak Streaming API /////////////////////////////////////////////////////////////////
// Setup a hashing state for either // 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 // 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. // 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 // After initialising a 'DN_KeccakState' via 'DN_KeccakSHA3Init', iteratively
// update the hash with new data by calling 'Dqn_KeccakUpdate'. On completion, // update the hash with new data by calling 'DN_KeccakUpdate'. On completion,
// call 'Dqn_KeccakFinish' to generate the hash from the state. The 'dest_size' // call 'DN_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 // must be at-least the (bit-size / 8), i.e. for 'DN_Keccak512Init' it must be
// atleast (512 / 8) bytes, 64 bytes. // atleast (512 / 8) bytes, 64 bytes.
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);
void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size); void DN_KeccakFinish(DN_KeccakState *keccak, void *dest, int dest_size);
// NOTE: Simple API //////////////////////////////////////////////////////////////////////////////// // NOTE: Simple API ////////////////////////////////////////////////////////////////////////////////
// Helper function that combines the Init, Update and Finish step in one shot, // 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 // i.e. hashing a singlular contiguous buffer. Use the streaming API if data
// is split across different buffers. // 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 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 Dqn_SHA3_224(src, src_size, dest, dest_size) Dqn_SHA3Hash(224, 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 Dqn_SHA3_256(src, src_size, dest, dest_size) Dqn_SHA3Hash(256, 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 Dqn_SHA3_384(src, src_size, dest, dest_size) Dqn_SHA3Hash(384, 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 Dqn_SHA3_512(src, src_size, dest, dest_size) Dqn_SHA3Hash(512, 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 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 Dqn_Keccak224(src, src_size, dest, dest_size) Dqn_KeccakHash(224, 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 Dqn_Keccak256(src, src_size, dest, dest_size) Dqn_KeccakHash(256, 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 Dqn_Keccak384(src, src_size, dest, dest_size) Dqn_KeccakHash(384, 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 Dqn_Keccak512(src, src_size, dest, dest_size) Dqn_KeccakHash(512, 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 ////////////////////////////////////////////////////////////////////////////// // 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_KeccakBytes32 Dqn_SHA3_256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size); DN_KeccakBytes32 DN_SHA3_256ToBytes32(void *bytes, DN_KeccakU64 bytes_size);
Dqn_KeccakBytes48 Dqn_SHA3_384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size); DN_KeccakBytes48 DN_SHA3_384ToBytes48(void *bytes, DN_KeccakU64 bytes_size);
Dqn_KeccakBytes64 Dqn_SHA3_512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size); DN_KeccakBytes64 DN_SHA3_512ToBytes64(void *bytes, DN_KeccakU64 bytes_size);
// NOTE: Keccak Helpers //////////////////////////////////////////////////////////////////////////// // NOTE: Keccak Helpers ////////////////////////////////////////////////////////////////////////////
Dqn_KeccakBytes28 Dqn_Keccak224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size); DN_KeccakBytes28 DN_Keccak224ToBytes28(void *bytes, DN_KeccakU64 bytes_size);
Dqn_KeccakBytes32 Dqn_Keccak256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size); DN_KeccakBytes32 DN_Keccak256ToBytes32(void *bytes, DN_KeccakU64 bytes_size);
Dqn_KeccakBytes48 Dqn_Keccak384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size); DN_KeccakBytes48 DN_Keccak384ToBytes48(void *bytes, DN_KeccakU64 bytes_size);
Dqn_KeccakBytes64 Dqn_Keccak512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size); DN_KeccakBytes64 DN_Keccak512ToBytes64(void *bytes, DN_KeccakU64 bytes_size);
#if defined(DQN_H) #if defined(DN_H)
// NOTE: SHA3 - Helpers for Dqn data structures //////////////////////////////////////////////////// // NOTE: SHA3 - Helpers for DN data structures ////////////////////////////////////////////////////
Dqn_KeccakBytes28 Dqn_SHA3_224StringToBytes28(Dqn_Str8 string); DN_KeccakBytes28 DN_SHA3_224StringToBytes28(DN_Str8 string);
Dqn_KeccakBytes32 Dqn_SHA3_256StringToBytes32(Dqn_Str8 string); DN_KeccakBytes32 DN_SHA3_256StringToBytes32(DN_Str8 string);
Dqn_KeccakBytes48 Dqn_SHA3_384StringToBytes48(Dqn_Str8 string); DN_KeccakBytes48 DN_SHA3_384StringToBytes48(DN_Str8 string);
Dqn_KeccakBytes64 Dqn_SHA3_512StringToBytes64(Dqn_Str8 string); DN_KeccakBytes64 DN_SHA3_512StringToBytes64(DN_Str8 string);
// NOTE: Keccak - Helpers for Dqn data structures ////////////////////////////////////////////////// // NOTE: Keccak - Helpers for DN data structures //////////////////////////////////////////////////
Dqn_KeccakBytes28 Dqn_Keccak224StringToBytes28(Dqn_Str8 string); DN_KeccakBytes28 DN_Keccak224StringToBytes28(DN_Str8 string);
Dqn_KeccakBytes32 Dqn_Keccak256StringToBytes32(Dqn_Str8 string); DN_KeccakBytes32 DN_Keccak256StringToBytes32(DN_Str8 string);
Dqn_KeccakBytes48 Dqn_Keccak384StringToBytes48(Dqn_Str8 string); DN_KeccakBytes48 DN_Keccak384StringToBytes48(DN_Str8 string);
Dqn_KeccakBytes64 Dqn_Keccak512StringToBytes64(Dqn_Str8 string); DN_KeccakBytes64 DN_Keccak512StringToBytes64(DN_Str8 string);
#endif // DQN_H #endif // DN_H
// NOTE: Helper functions ////////////////////////////////////////////////////////////////////////// // NOTE: Helper functions //////////////////////////////////////////////////////////////////////////
// Convert a binary buffer into its hex representation into dest. The dest // Convert a binary buffer into its hex representation into dest. The dest
// buffer must be large enough to contain the hex representation, i.e. // buffer must be large enough to contain the hex representation, i.e.
// atleast src_size * 2). This function does *not* null-terminate the buffer. // 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 // 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. // return: The hexadecimal string of the bytes, null-terminated.
Dqn_KeccakString56 Dqn_KeccakBytes28ToHex(Dqn_KeccakBytes28 const *bytes); DN_KeccakString56 DN_KeccakBytes28ToHex(DN_KeccakBytes28 const *bytes);
Dqn_KeccakString64 Dqn_KeccakBytes32ToHex(Dqn_KeccakBytes32 const *bytes); DN_KeccakString64 DN_KeccakBytes32ToHex(DN_KeccakBytes32 const *bytes);
Dqn_KeccakString96 Dqn_KeccakBytes48ToHex(Dqn_KeccakBytes48 const *bytes); DN_KeccakString96 DN_KeccakBytes48ToHex(DN_KeccakBytes48 const *bytes);
Dqn_KeccakString128 Dqn_KeccakBytes64ToHex(Dqn_KeccakBytes64 const *bytes); DN_KeccakString128 DN_KeccakBytes64ToHex(DN_KeccakBytes64 const *bytes);
// Compares byte data structures for byte equality (via memcmp). // Compares byte data structures for byte equality (via memcmp).
// return: 1 if the contents are equal otherwise 0. // return: 1 if the contents are equal otherwise 0.
int Dqn_KeccakBytes28Equals(Dqn_KeccakBytes28 const *a, Dqn_KeccakBytes28 const *b); int DN_KeccakBytes28Equals(DN_KeccakBytes28 const *a, DN_KeccakBytes28 const *b);
int Dqn_KeccakBytes32Equals(Dqn_KeccakBytes32 const *a, Dqn_KeccakBytes32 const *b); int DN_KeccakBytes32Equals(DN_KeccakBytes32 const *a, DN_KeccakBytes32 const *b);
int Dqn_KeccakBytes48Equals(Dqn_KeccakBytes48 const *a, Dqn_KeccakBytes48 const *b); int DN_KeccakBytes48Equals(DN_KeccakBytes48 const *a, DN_KeccakBytes48 const *b);
int Dqn_KeccakBytes64Equals(Dqn_KeccakBytes64 const *a, Dqn_KeccakBytes64 const *b); int DN_KeccakBytes64Equals(DN_KeccakBytes64 const *a, DN_KeccakBytes64 const *b);
#if defined(DQN_H) && defined(DQN_WITH_HEX) #if defined(DN_H) && defined(DN_WITH_HEX)
// NOTE: Other helper functions for Dqn data structures //////////////////////////////////////////// // NOTE: Other helper functions for DN data structures ////////////////////////////////////////////
// Converts a 64 character hex string into the 32 byte binary representation. // Converts a 64 character hex string into the 32 byte binary representation.
// Invalid hex characters in the string will be represented as 0. // Invalid hex characters in the string will be represented as 0.
// hex: Must be exactly a 64 character hex string. // hex: Must be exactly a 64 character hex string.
Dqn_KeccakBytes32 Dqn_KeccakHex64StringToBytes(Dqn_Str8 hex); DN_KeccakBytes32 DN_KeccakHex64StringToBytes(DN_Str8 hex);
#endif // DQN_H && DQN_WITH_HEX #endif // DN_H && DN_WITH_HEX
#endif // DQN_KECCAK_H #endif // DN_KECCAK_H
#if defined(DQN_KECCAK_IMPLEMENTATION) #if defined(DN_KECCAK_IMPLEMENTATION)
Dqn_KeccakU64 const DQN_KECCAK_ROUNDS[] = { DN_KeccakU64 const DN_KECCAK_ROUNDS[] = {
0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B, 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B,
0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088,
0x0000000080008009, 0x000000008000000A, 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x0000000080008009, 0x000000008000000A, 0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
@ -245,7 +245,7 @@ Dqn_KeccakU64 const DQN_KECCAK_ROUNDS[] = {
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
}; };
Dqn_KeccakU64 const DQN_KECCAK_ROTATIONS[][5] = DN_KeccakU64 const DN_KECCAK_ROTATIONS[][5] =
{ {
{0, 36, 3, 41, 18}, {0, 36, 3, 41, 18},
{1, 44, 10, 45, 2}, {1, 44, 10, 45, 2},
@ -254,21 +254,21 @@ Dqn_KeccakU64 const DQN_KECCAK_ROTATIONS[][5] =
{27, 20, 39, 8, 14}, {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. // 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++) for (int round_index = 0; round_index < 24; round_index++)
{ {
#define LANE_INDEX(x, y) ((x) + ((y) * DQN_KECCAK_LANE_SIZE_U64)) #define LANE_INDEX(x, y) ((x) + ((y) * DN_KECCAK_LANE_SIZE_U64))
// θ step ////////////////////////////////////////////////////////////////////////////////// // ?? step //////////////////////////////////////////////////////////////////////////////////
#if 1 #if 1
Dqn_KeccakU64 c[DQN_KECCAK_LANE_SIZE_U64]; DN_KeccakU64 c[DN_KECCAK_LANE_SIZE_U64];
for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++) for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++)
{ {
c[x] = lanes_u64[LANE_INDEX(x, 0)] ^ c[x] = lanes_u64[LANE_INDEX(x, 0)] ^
lanes_u64[LANE_INDEX(x, 1)] ^ lanes_u64[LANE_INDEX(x, 1)] ^
@ -277,87 +277,87 @@ static void Dqn_Keccak__Permute(void *state)
lanes_u64[LANE_INDEX(x, 4)]; lanes_u64[LANE_INDEX(x, 4)];
} }
Dqn_KeccakU64 d[DQN_KECCAK_LANE_SIZE_U64]; DN_KeccakU64 d[DN_KECCAK_LANE_SIZE_U64];
for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++) for (int x = 0; x < DN_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); 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 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++)
lanes_u64[LANE_INDEX(x, y)] ^= d[x]; lanes_u64[LANE_INDEX(x, y)] ^= d[x];
#else #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[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[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[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[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]; 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[0] = c[4] ^ DN_KECCAK_ROL64(c[1], 1);
d[1] = c[0] ^ DQN_KECCAK_ROL64(c[2], 1); d[1] = c[0] ^ DN_KECCAK_ROL64(c[2], 1);
d[2] = c[1] ^ DQN_KECCAK_ROL64(c[3], 1); d[2] = c[1] ^ DN_KECCAK_ROL64(c[3], 1);
d[3] = c[2] ^ DQN_KECCAK_ROL64(c[4], 1); d[3] = c[2] ^ DN_KECCAK_ROL64(c[4], 1);
d[4] = c[3] ^ DQN_KECCAK_ROL64(c[0], 1); d[4] = c[3] ^ DN_KECCAK_ROL64(c[0], 1);
#endif #endif
// ρ and π steps /////////////////////////////////////////////////////////////////////////// // ?? and ?? steps ///////////////////////////////////////////////////////////////////////////
Dqn_KeccakU64 b[DQN_KECCAK_LANE_SIZE_U64 * DQN_KECCAK_LANE_SIZE_U64]; DN_KeccakU64 b[DN_KECCAK_LANE_SIZE_U64 * DN_KECCAK_LANE_SIZE_U64];
for (int y = 0; y < DQN_KECCAK_LANE_SIZE_U64; y++) 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)]; DN_KeccakU64 lane = lanes_u64[LANE_INDEX(x, y)];
Dqn_KeccakU64 rotate_count = DQN_KECCAK_ROTATIONS[x][y]; DN_KeccakU64 rotate_count = DN_KECCAK_ROTATIONS[x][y];
b[LANE_INDEX(y, (2 * x + 3 * y) % 5)] = DQN_KECCAK_ROL64(lane, rotate_count); b[LANE_INDEX(y, (2 * x + 3 * y) % 5)] = DN_KECCAK_ROL64(lane, rotate_count);
} }
} }
// χ step ////////////////////////////////////////////////////////////////////////////////// // ?? step //////////////////////////////////////////////////////////////////////////////////
for (int y = 0; y < DQN_KECCAK_LANE_SIZE_U64; y++) 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)]; b[LANE_INDEX((x + 2) % 5, y)];
lanes_u64[LANE_INDEX(x, y)] = b[LANE_INDEX(x, y)] ^ rhs; lanes_u64[LANE_INDEX(x, y)] = b[LANE_INDEX(x, y)] ^ rhs;
} }
} }
// ι step ////////////////////////////////////////////////////////////////////////////////// // ?? step //////////////////////////////////////////////////////////////////////////////////
lanes_u64[LANE_INDEX(0, 0)] ^= DQN_KECCAK_ROUNDS[round_index]; lanes_u64[LANE_INDEX(0, 0)] ^= DN_KECCAK_ROUNDS[round_index];
#undef LANE_INDEX #undef LANE_INDEX
#undef DQN_KECCAK_ROL64 #undef DN_KECCAK_ROL64
} }
} }
// NOTE: Streaming API ///////////////////////////////////////////////////////////////////////////// // 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 SHA3_DELIMITED_SUFFIX = 0x06;
char const KECCAK_DELIMITED_SUFFIX = 0x01; char const KECCAK_DELIMITED_SUFFIX = 0x01;
int const bitrate = 1600 - (hash_size_bits * 2); int const bitrate = 1600 - (hash_size_bits * 2);
#if defined(__cplusplus) #if defined(__cplusplus)
Dqn_KeccakState result = {}; DN_KeccakState result = {};
#else #else
Dqn_KeccakState result = {0}; DN_KeccakState result = {0};
#endif #endif
result.hash_size_bits = hash_size_bits; result.hash_size_bits = hash_size_bits;
result.absorb_size = bitrate / 8; result.absorb_size = bitrate / 8;
result.delimited_suffix = sha3 ? SHA3_DELIMITED_SUFFIX : KECCAK_DELIMITED_SUFFIX; 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; 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; DN_KeccakU8 *state = keccak->state;
Dqn_KeccakU8 const *ptr = (Dqn_KeccakU8 *)data; DN_KeccakU8 const *ptr = (DN_KeccakU8 *)data;
Dqn_KeccakU64 ptr_size = data_size; DN_KeccakU64 ptr_size = data_size;
while (ptr_size > 0) 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); int bytes_to_absorb = (int)(space < ptr_size ? space : ptr_size);
for (int index = 0; index < bytes_to_absorb; index++) 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) if (keccak->state_size >= keccak->absorb_size)
{ {
DQN_KECCAK_ASSERT(keccak->state_size == keccak->absorb_size); DN_KECCAK_ASSERT(keccak->state_size == keccak->absorb_size);
Dqn_Keccak__Permute(state); DN_Keccak__Permute(state);
keccak->state_size = 0; 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 ///////////////////////////////////////////////// // Sponge Finalization Step: Final padding bit /////////////////////////////////////////////////
int const INDEX_OF_0X80_BYTE = keccak->absorb_size - 1; int const INDEX_OF_0X80_BYTE = keccak->absorb_size - 1;
int const delimited_suffix_index = keccak->state_size; 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; state[delimited_suffix_index] ^= keccak->delimited_suffix;
// NOTE: In the reference implementation, it checks that if the // 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. // this from the implementation here.
state[INDEX_OF_0X80_BYTE] ^= 0x80; state[INDEX_OF_0X80_BYTE] ^= 0x80;
Dqn_Keccak__Permute(state); DN_Keccak__Permute(state);
// Squeeze Step: Squeeze bytes from the state into our hash //////////////////////////////////// // 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 const squeeze_count = dest_size / keccak->absorb_size;
int squeeze_index = 0; int squeeze_index = 0;
for (; squeeze_index < squeeze_count; squeeze_index++) for (; squeeze_index < squeeze_count; squeeze_index++)
{ {
if (squeeze_index) Dqn_Keccak__Permute(state); if (squeeze_index) DN_Keccak__Permute(state);
DQN_KECCAK_MEMCPY(dest_u8, state, keccak->absorb_size); DN_KECCAK_MEMCPY(dest_u8, state, keccak->absorb_size);
dest_u8 += 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; int const remainder = dest_size % keccak->absorb_size;
if (remainder) if (remainder)
{ {
if (squeeze_index) Dqn_Keccak__Permute(state); if (squeeze_index) DN_Keccak__Permute(state);
DQN_KECCAK_MEMCPY(dest_u8, state, remainder); 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); DN_KeccakState keccak = DN_KeccakSHA3Init(sha3, hash_size_bits);
Dqn_KeccakUpdate(&keccak, src, src_size); DN_KeccakUpdate(&keccak, src, src_size);
Dqn_KeccakFinish(&keccak, dest, dest_size); DN_KeccakFinish(&keccak, dest, dest_size);
} }
// NOTE: SHA3 Helpers ////////////////////////////////////////////////////////////////////////////// // 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; DN_KeccakBytes28 result;
Dqn_SHA3_224(bytes, bytes_size, result.data, sizeof(result)); DN_SHA3_224(bytes, bytes_size, result.data, sizeof(result));
return 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; DN_KeccakBytes32 result;
Dqn_SHA3_256(bytes, bytes_size, result.data, sizeof(result)); DN_SHA3_256(bytes, bytes_size, result.data, sizeof(result));
return 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; DN_KeccakBytes48 result;
Dqn_SHA3_384(bytes, bytes_size, result.data, sizeof(result)); DN_SHA3_384(bytes, bytes_size, result.data, sizeof(result));
return 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; DN_KeccakBytes64 result;
Dqn_SHA3_512(bytes, bytes_size, result.data, sizeof(result)); DN_SHA3_512(bytes, bytes_size, result.data, sizeof(result));
return result; return result;
} }
// NOTE: Keccak Helpers //////////////////////////////////////////////////////////////////////////// // 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; DN_KeccakBytes28 result;
Dqn_Keccak224(bytes, bytes_size, result.data, sizeof(result)); DN_Keccak224(bytes, bytes_size, result.data, sizeof(result));
return 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; DN_KeccakBytes32 result;
Dqn_Keccak256(bytes, bytes_size, result.data, sizeof(result)); DN_Keccak256(bytes, bytes_size, result.data, sizeof(result));
return 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; DN_KeccakBytes48 result;
Dqn_Keccak384(bytes, bytes_size, result.data, sizeof(result)); DN_Keccak384(bytes, bytes_size, result.data, sizeof(result));
return 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; DN_KeccakBytes64 result;
Dqn_Keccak512(bytes, bytes_size, result.data, sizeof(result)); DN_Keccak512(bytes, bytes_size, result.data, sizeof(result));
return result; return result;
} }
#if defined(DQN_H) #if defined(DN_H)
// NOTE: SHA3 - Helpers for Dqn data structures //////////////////////////////////////////////////// // NOTE: SHA3 - Helpers for DN data structures ////////////////////////////////////////////////////
Dqn_KeccakBytes28 Dqn_SHA3_224StringToBytes28(Dqn_Str8 string) DN_KeccakBytes28 DN_SHA3_224StringToBytes28(DN_Str8 string)
{ {
Dqn_KeccakBytes28 result; DN_KeccakBytes28 result;
Dqn_SHA3_224(string.data, string.size, result.data, sizeof(result)); DN_SHA3_224(string.data, string.size, result.data, sizeof(result));
return result; return result;
} }
Dqn_KeccakBytes32 Dqn_SHA3_256StringToBytes32(Dqn_Str8 string) DN_KeccakBytes32 DN_SHA3_256StringToBytes32(DN_Str8 string)
{ {
Dqn_KeccakBytes32 result; DN_KeccakBytes32 result;
Dqn_SHA3_256(string.data, string.size, result.data, sizeof(result)); DN_SHA3_256(string.data, string.size, result.data, sizeof(result));
return result; return result;
} }
Dqn_KeccakBytes48 Dqn_SHA3_384StringToBytes48(Dqn_Str8 string) DN_KeccakBytes48 DN_SHA3_384StringToBytes48(DN_Str8 string)
{ {
Dqn_KeccakBytes48 result; DN_KeccakBytes48 result;
Dqn_SHA3_384(string.data, string.size, result.data, sizeof(result)); DN_SHA3_384(string.data, string.size, result.data, sizeof(result));
return result; return result;
} }
Dqn_KeccakBytes64 Dqn_SHA3_512StringToBytes64(Dqn_Str8 string) DN_KeccakBytes64 DN_SHA3_512StringToBytes64(DN_Str8 string)
{ {
Dqn_KeccakBytes64 result; DN_KeccakBytes64 result;
Dqn_SHA3_512(string.data, string.size, result.data, sizeof(result)); DN_SHA3_512(string.data, string.size, result.data, sizeof(result));
return result; return result;
} }
#endif // DQN_H #endif // DN_H
#if defined(DQN_H) #if defined(DN_H)
// NOTE: Keccak - Helpers for Dqn data structures ////////////////////////////////////////////////// // NOTE: Keccak - Helpers for DN data structures //////////////////////////////////////////////////
Dqn_KeccakBytes28 Dqn_Keccak224StringToBytes28(Dqn_Str8 string) DN_KeccakBytes28 DN_Keccak224StringToBytes28(DN_Str8 string)
{ {
Dqn_KeccakBytes28 result; DN_KeccakBytes28 result;
Dqn_Keccak224(string.data, string.size, result.data, sizeof(result)); DN_Keccak224(string.data, string.size, result.data, sizeof(result));
return result; return result;
} }
Dqn_KeccakBytes32 Dqn_Keccak256StringToBytes32(Dqn_Str8 string) DN_KeccakBytes32 DN_Keccak256StringToBytes32(DN_Str8 string)
{ {
Dqn_KeccakBytes32 result; DN_KeccakBytes32 result;
Dqn_Keccak256(string.data, string.size, result.data, sizeof(result)); DN_Keccak256(string.data, string.size, result.data, sizeof(result));
return result; return result;
} }
Dqn_KeccakBytes48 Dqn_Keccak384StringToBytes48(Dqn_Str8 string) DN_KeccakBytes48 DN_Keccak384StringToBytes48(DN_Str8 string)
{ {
Dqn_KeccakBytes48 result; DN_KeccakBytes48 result;
Dqn_Keccak384(string.data, string.size, result.data, sizeof(result)); DN_Keccak384(string.data, string.size, result.data, sizeof(result));
return result; return result;
} }
Dqn_KeccakBytes64 Dqn_Keccak512StringToBytes64(Dqn_Str8 string) DN_KeccakBytes64 DN_Keccak512StringToBytes64(DN_Str8 string)
{ {
Dqn_KeccakBytes64 result; DN_KeccakBytes64 result;
Dqn_Keccak512(string.data, string.size, result.data, sizeof(result)); DN_Keccak512(string.data, string.size, result.data, sizeof(result));
return result; return result;
} }
#endif // DQN_H #endif // DN_H
// NOTE: Helper functions ////////////////////////////////////////////////////////////////////////// // 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; (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; 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 < src_size;
src_index += 1, dest_index += 2) 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; DN_KeccakString56 result;
Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
result.data[sizeof(result.data) - 1] = 0; result.data[sizeof(result.data) - 1] = 0;
return result; return result;
} }
Dqn_KeccakString64 Dqn_KeccakBytes32ToHex(Dqn_KeccakBytes32 const *bytes) DN_KeccakString64 DN_KeccakBytes32ToHex(DN_KeccakBytes32 const *bytes)
{ {
Dqn_KeccakString64 result; DN_KeccakString64 result;
Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
result.data[sizeof(result.data) - 1] = 0; result.data[sizeof(result.data) - 1] = 0;
return result; return result;
} }
Dqn_KeccakString96 Dqn_KeccakBytes48ToHex(Dqn_KeccakBytes48 const *bytes) DN_KeccakString96 DN_KeccakBytes48ToHex(DN_KeccakBytes48 const *bytes)
{ {
Dqn_KeccakString96 result; DN_KeccakString96 result;
Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
result.data[sizeof(result.data) - 1] = 0; result.data[sizeof(result.data) - 1] = 0;
return result; return result;
} }
Dqn_KeccakString128 Dqn_KeccakBytes64ToHex(Dqn_KeccakBytes64 const *bytes) DN_KeccakString128 DN_KeccakBytes64ToHex(DN_KeccakBytes64 const *bytes)
{ {
Dqn_KeccakString128 result; DN_KeccakString128 result;
Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data)); DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
result.data[sizeof(result.data) - 1] = 0; result.data[sizeof(result.data) - 1] = 0;
return result; 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; 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; 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; 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; return result;
} }
#if defined(DQN_H) && defined(DQN_WITH_HEX) #if defined(DN_H) && defined(DN_WITH_HEX)
// NOTE: Other helper functions for Dqn data structures //////////////////////////////////////////// // NOTE: Other helper functions for DN data structures ////////////////////////////////////////////
Dqn_KeccakBytes32 Dqn_KeccakHex64StringToBytes(Dqn_Str8 hex) DN_KeccakBytes32 DN_KeccakHex64StringToBytes(DN_Str8 hex)
{ {
DQN_KECCAK_ASSERT(hex.size == 64); DN_KECCAK_ASSERT(hex.size == 64);
Dqn_KeccakBytes32 result; DN_KeccakBytes32 result;
Dqn_Hex_CString8ToByteBuffer(hex.data, hex.size, result.data, sizeof(result)); DN_Hex_CString8ToByteBuffer(hex.data, hex.size, result.data, sizeof(result));
return result; return result;
} }
#endif // DQN_H && DQN_WITH_HEX #endif // DN_H && DN_WITH_HEX
#endif // DQN_KECCAK_IMPLEMENTATION #endif // DN_KECCAK_IMPLEMENTATION

View File

@ -1,5 +1,5 @@
#if !defined(DQN_UTEST_H) #if !defined(DN_UTEST_H)
#define DQN_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 ///////////////////////////////////////////////////////////////////////////// // NOTE: Configuration /////////////////////////////////////////////////////////////////////////////
// //
// #define DQN_UTEST_IMPLEMENTATION // #define DN_UTEST_IMPLEMENTATION
// Define this in one and only one C++ file to enable the 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 // code of the header file. This will also automatically enable the JSMN
// implementation. // 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 // Define this to a number to specify how much to pad the output of the test
// result line before the test result is printed. // 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 // Define this to a character to specify the default character to use for
// padding. By default this is '.' // 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 // Define this to a number to specify the number of spaces between the group
// declaration and the test output in 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 // Define this to a terminal color code to specify what color errors will be
// presented as. // 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 // Define this to a terminal color code to specify what color sucess will be
// presented as. // presented as.
// //
@ -56,114 +56,114 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#if !defined(DQN_UTEST_RESULT_LPAD) #if !defined(DN_UTEST_RESULT_LPAD)
#define DQN_UTEST_RESULT_LPAD 90 #define DN_UTEST_RESULT_LPAD 90
#endif #endif
#if !defined(DQN_UTEST_RESULT_PAD_CHAR) #if !defined(DN_UTEST_RESULT_PAD_CHAR)
#define DQN_UTEST_RESULT_PAD_CHAR '.' #define DN_UTEST_RESULT_PAD_CHAR '.'
#endif #endif
#if !defined(DQN_UTEST_SPACING) #if !defined(DN_UTEST_SPACING)
#define DQN_UTEST_SPACING 2 #define DN_UTEST_SPACING 2
#endif #endif
#if !defined(DQN_UTEST_BAD_COLOR) #if !defined(DN_UTEST_BAD_COLOR)
#define DQN_UTEST_BAD_COLOR "\x1b[31m" #define DN_UTEST_BAD_COLOR "\x1b[31m"
#endif #endif
#if !defined(DQN_UTEST_GOOD_COLOR) #if !defined(DN_UTEST_GOOD_COLOR)
#define DQN_UTEST_GOOD_COLOR "\x1b[32m" #define DN_UTEST_GOOD_COLOR "\x1b[32m"
#endif #endif
#define DQN_UTEST_COLOR_RESET "\x1b[0m" #define DN_UTEST_COLOR_RESET "\x1b[0m"
#define DQN_UTEST_GROUP(test, fmt, ...) \ #define DN_UTEST_GROUP(test, fmt, ...) \
for (Dqn_UTest *test_var_ = (printf(fmt "\n", ## __VA_ARGS__), &test); \ for (DN_UTest *test_var_ = (printf(fmt "\n", ## __VA_ARGS__), &test); \
test_var_ != nullptr; \ test_var_ != nullptr; \
Dqn_UTest_PrintStats(&test), test_var_ = nullptr) DN_UTest_PrintStats(&test), test_var_ = nullptr)
#define DQN_UTEST_TEST(fmt, ...) \ #define DN_UTEST_TEST(fmt, ...) \
for (int dummy_ = (Dqn_UTest_Begin(test_var_, fmt, ## __VA_ARGS__), 0); \ for (int dummy_ = (DN_UTest_Begin(test_var_, fmt, ## __VA_ARGS__), 0); \
(void)dummy_, test_var_->state == Dqn_UTestState_TestBegun; \ (void)dummy_, test_var_->state == DN_UTestState_TestBegun; \
Dqn_UTest_End(test_var_)) DN_UTest_End(test_var_))
#define DQN_UTEST_ASSERTF(test, expr, fmt, ...) \ #define DN_UTEST_ASSERTF(test, expr, fmt, ...) \
DQN_UTEST_ASSERTF_AT((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__) DN_UTEST_ASSERTF_AT((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__)
#define DQN_UTEST_ASSERT(test, expr) \ #define DN_UTEST_ASSERT(test, expr) \
DQN_UTEST_ASSERT_AT((test), __FILE__, __LINE__, (expr)) DN_UTEST_ASSERT_AT((test), __FILE__, __LINE__, (expr))
// TODO: Fix the logs. They print before the tests, we should accumulate logs // 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 // per test, then, dump them on test on. But to do this nicely without crappy
// mem management we need to implement an arena. // mem management we need to implement an arena.
#define DQN_UTEST_LOG(fmt, ...) \ #define DN_UTEST_LOG(fmt, ...) \
fprintf(stdout, "%*s" fmt "\n", DQN_UTEST_SPACING * 2, "", ##__VA_ARGS__) 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 { \ do { \
if (!(expr)) { \ if (!(expr)) { \
(test)->state = Dqn_UTestState_TestFailed; \ (test)->state = DN_UTestState_TestFailed; \
fprintf(stderr, \ fprintf(stderr, \
"%*sAssertion Triggered\n" \ "%*sAssertion Triggered\n" \
"%*sFile: %s:%d\n" \ "%*sFile: %s:%d\n" \
"%*sExpression: [" #expr "]\n" \ "%*sExpression: [" #expr "]\n" \
"%*sReason: " fmt "\n\n", \ "%*sReason: " fmt "\n\n", \
DQN_UTEST_SPACING * 2, \ DN_UTEST_SPACING * 2, \
"", \ "", \
DQN_UTEST_SPACING * 3, \ DN_UTEST_SPACING * 3, \
"", \ "", \
file, \ file, \
line, \ line, \
DQN_UTEST_SPACING * 3, \ DN_UTEST_SPACING * 3, \
"", \ "", \
DQN_UTEST_SPACING * 3, \ DN_UTEST_SPACING * 3, \
"", \ "", \
##__VA_ARGS__); \ ##__VA_ARGS__); \
} \ } \
} while (0) } while (0)
#define DQN_UTEST_ASSERT_AT(test, file, line, expr) \ #define DN_UTEST_ASSERT_AT(test, file, line, expr) \
do { \ do { \
if (!(expr)) { \ if (!(expr)) { \
(test)->state = Dqn_UTestState_TestFailed; \ (test)->state = DN_UTestState_TestFailed; \
fprintf(stderr, \ fprintf(stderr, \
"%*sFile: %s:%d\n" \ "%*sFile: %s:%d\n" \
"%*sExpression: [" #expr "]\n\n", \ "%*sExpression: [" #expr "]\n\n", \
DQN_UTEST_SPACING * 2, \ DN_UTEST_SPACING * 2, \
"", \ "", \
file, \ file, \
line, \ line, \
DQN_UTEST_SPACING * 2, \ DN_UTEST_SPACING * 2, \
""); \ ""); \
} \ } \
} while (0) } while (0)
// NOTE: Header //////////////////////////////////////////////////////////////////////////////////// // NOTE: Header ////////////////////////////////////////////////////////////////////////////////////
typedef enum Dqn_UTestState { typedef enum DN_UTestState {
Dqn_UTestState_Nil, DN_UTestState_Nil,
Dqn_UTestState_TestBegun, DN_UTestState_TestBegun,
Dqn_UTestState_TestFailed, DN_UTestState_TestFailed,
} Dqn_UTestState; } DN_UTestState;
typedef struct Dqn_UTest { typedef struct DN_UTest {
int num_tests_in_group; int num_tests_in_group;
int num_tests_ok_in_group; int num_tests_ok_in_group;
Dqn_UTestState state; DN_UTestState state;
bool finished; bool finished;
char name[256]; char name[256];
size_t name_size; size_t name_size;
} Dqn_UTest; } DN_UTest;
void Dqn_UTest_PrintStats(Dqn_UTest *test); void DN_UTest_PrintStats(DN_UTest *test);
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);
void Dqn_UTest_Begin(Dqn_UTest *test, char const *fmt, ...); void DN_UTest_Begin(DN_UTest *test, char const *fmt, ...);
void Dqn_UTest_End(Dqn_UTest *test); void DN_UTest_End(DN_UTest *test);
#endif // DQN_UTEST_H #endif // DN_UTEST_H
// NOTE: Implementation //////////////////////////////////////////////////////////////////////////// // NOTE: Implementation ////////////////////////////////////////////////////////////////////////////
#if defined(DQN_UTEST_IMPLEMENTATION) #if defined(DN_UTEST_IMPLEMENTATION)
void Dqn_UTest_PrintStats(Dqn_UTest *test) void DN_UTest_PrintStats(DN_UTest *test)
{ {
if (test->finished) if (test->finished)
return; return;
@ -171,21 +171,21 @@ void Dqn_UTest_PrintStats(Dqn_UTest *test)
test->finished = true; test->finished = true;
bool all_clear = test->num_tests_ok_in_group == test->num_tests_in_group; bool all_clear = test->num_tests_ok_in_group == test->num_tests_in_group;
fprintf(stdout, fprintf(stdout,
"%s\n %02d/%02d tests passed -- %s\n\n" DQN_UTEST_COLOR_RESET, "%s\n %02d/%02d tests passed -- %s\n\n" DN_UTEST_COLOR_RESET,
all_clear ? DQN_UTEST_GOOD_COLOR : DQN_UTEST_BAD_COLOR, all_clear ? DN_UTEST_GOOD_COLOR : DN_UTEST_BAD_COLOR,
test->num_tests_ok_in_group, test->num_tests_ok_in_group,
test->num_tests_in_group, test->num_tests_in_group,
all_clear ? "OK" : "FAILED"); 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" "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->num_tests_in_group++;
test->state = Dqn_UTestState_TestBegun; test->state = DN_UTestState_TestBegun;
test->name_size = 0; 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); 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_list args;
va_start(args, fmt); va_start(args, fmt);
Dqn_UTest_BeginV(test, fmt, args); DN_UTest_BeginV(test, fmt, args);
va_end(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"); 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 = DQN_UTEST_RESULT_LPAD - (DQN_UTEST_SPACING + test->name_size); size_t pad_size = DN_UTEST_RESULT_LPAD - (DN_UTEST_SPACING + test->name_size);
if (pad_size < 0) if (pad_size < 0)
pad_size = 0; pad_size = 0;
char pad_buffer[DQN_UTEST_RESULT_LPAD] = {}; char pad_buffer[DN_UTEST_RESULT_LPAD] = {};
memset(pad_buffer, DQN_UTEST_RESULT_PAD_CHAR, pad_size); 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); printf("%*s%.*s%.*s", DN_UTEST_SPACING, "", (int)test->name_size, test->name, (int)pad_size, pad_buffer);
if (test->state == Dqn_UTestState_TestFailed) { if (test->state == DN_UTestState_TestFailed) {
printf(DQN_UTEST_BAD_COLOR " FAILED"); printf(DN_UTEST_BAD_COLOR " FAILED");
} else { } else {
printf(DQN_UTEST_GOOD_COLOR " OK"); printf(DN_UTEST_GOOD_COLOR " OK");
test->num_tests_ok_in_group++; test->num_tests_ok_in_group++;
} }
printf(DQN_UTEST_COLOR_RESET "\n"); printf(DN_UTEST_COLOR_RESET "\n");
test->state = Dqn_UTestState_Nil; test->state = DN_UTestState_Nil;
} }
#endif // DQN_UTEST_IMPLEMENTATION #endif // DN_UTEST_IMPLEMENTATION

View File

@ -13,7 +13,7 @@ pushd Build
REM O2 Optimisation Level 2 REM O2 Optimisation Level 2
REM Oi Use CPU Intrinsics REM Oi Use CPU Intrinsics
REM Z7 Combine multi-debug files to one debug file 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 set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo

38
dqn.cpp
View File

@ -1,5 +1,7 @@
#include "dqn.h" #include "dqn.h"
#define DN_CPP
/* /*
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
@ -17,29 +19,29 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
#if defined(DQN_WITH_CGEN) #if defined(DN_WITH_CGEN)
#if !defined(DQN_NO_METADESK) #if !defined(DN_NO_METADESK)
DQN_MSVC_WARNING_PUSH DN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: '<function>': unreferenced function with internal linkage has been removed DN_MSVC_WARNING_DISABLE(4505) // warning C4505: '<function>': unreferenced function with internal linkage has been removed
DQN_GCC_WARNING_PUSH DN_GCC_WARNING_PUSH
DQN_GCC_WARNING_DISABLE(-Wwrite-strings) DN_GCC_WARNING_DISABLE(-Wwrite-strings)
DQN_GCC_WARNING_DISABLE(-Wunused-but-set-variable) DN_GCC_WARNING_DISABLE(-Wunused-but-set-variable)
DQN_GCC_WARNING_DISABLE(-Wsign-compare) DN_GCC_WARNING_DISABLE(-Wsign-compare)
DQN_GCC_WARNING_DISABLE(-Wunused-function) DN_GCC_WARNING_DISABLE(-Wunused-function)
DQN_GCC_WARNING_DISABLE(-Wunused-result) DN_GCC_WARNING_DISABLE(-Wunused-result)
#include "External/metadesk/md.c" #include "External/metadesk/md.c"
DQN_GCC_WARNING_POP DN_GCC_WARNING_POP
DQN_MSVC_WARNING_POP DN_MSVC_WARNING_POP
#endif #endif
#define DQN_CPP_FILE_IMPLEMENTATION #define DN_CPP_FILE_IMPLEMENTATION
#include "Standalone/dqn_cpp_file.h" #include "Standalone/dqn_cpp_file.h"
#include "dqn_cgen.cpp" #include "dqn_cgen.cpp"
#endif #endif
#if defined(DQN_WITH_JSON) #if defined(DN_WITH_JSON)
#include "dqn_json.cpp" #include "dqn_json.cpp"
#endif #endif
@ -52,12 +54,12 @@
#include "dqn_type_info.cpp" #include "dqn_type_info.cpp"
#include "dqn_os.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" #include "dqn_os_posix.cpp"
#elif defined(DQN_PLATFORM_WIN32) #elif defined(DN_PLATFORM_WIN32)
#include "dqn_os_win32.cpp" #include "dqn_os_win32.cpp"
#else #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 #endif
#include "dqn_tls.cpp" #include "dqn_tls.cpp"
@ -65,7 +67,7 @@
#include "dqn_hash.cpp" #include "dqn_hash.cpp"
#include "dqn_helpers.cpp" #include "dqn_helpers.cpp"
#if defined(DQN_WITH_UNIT_TESTS) #if defined(DN_WITH_UNIT_TESTS)
#include "dqn_unit_tests.cpp" #include "dqn_unit_tests.cpp"
#endif #endif

237
dqn.h
View File

@ -1,5 +1,5 @@
#pragma once #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 // ASCII -- BigMoney-NW by Nathan Bloomfild
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -43,21 +43,21 @@
// //
// -- Compiling -- // -- 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 // Additionally, this library supports including/excluding specific sections
// of the library by using #define on the name of the section. These names are // 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 // documented in the section table of contents at the #define column, for
// example: // example:
// //
// #define DQN_ONLY_VARRAY // #define DN_ONLY_VARRAY
// #define DQN_ONLY_WIN // #define DN_ONLY_WIN
// //
// Compiles the library with all optional APIs turned off except virtual arrays // Compiles the library with all optional APIs turned off except virtual arrays
// and the Win32 helpers. Alternatively: // and the Win32 helpers. Alternatively:
// //
// #define DQN_NO_VARRAY // #define DN_NO_VARRAY
// #define DQN_NO_WIN // #define DN_NO_WIN
// //
// Compiles the library with all optional APIs turned on except the previously // Compiles the library with all optional APIs turned on except the previously
// mentioned APIs. // mentioned APIs.
@ -69,7 +69,7 @@
// drowning out the library interface with code comments like many other // drowning out the library interface with code comments like many other
// documentation systems. // 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 // which provides self-contained examples in one contiguous top-down block of
// source code with comments. // source code with comments.
// //
@ -91,51 +91,51 @@
// - Override these routines from the CRT by redefining them. By default we wrap // - Override these routines from the CRT by redefining them. By default we wrap
// the CRT functions from <strings.h> and <math.h>, e.g: // the CRT functions from <strings.h> and <math.h>, e.g:
// //
// #define DQN_MEMCPY(dest, src, count) memcpy(dest, src, value) // #define DN_MEMCPY(dest, src, count) memcpy(dest, src, value)
// #define DQN_MEMSET(dest, value, count) memset(dest, value, count) // #define DN_MEMSET(dest, value, count) memset(dest, value, count)
// #define DQN_MEMCMP(lhs, rhs, count) memcpy(lhs, rhs, count) // #define DN_MEMCMP(lhs, rhs, count) memcpy(lhs, rhs, count)
// #define DQN_MEMMOVE(dest, src, count) memmove(dest, src, count) // #define DN_MEMMOVE(dest, src, count) memmove(dest, src, count)
// #define DQN_SQRTF(val) sqrtf(val) // #define DN_SQRTF(val) sqrtf(val)
// #define DQN_SINF(val) sinf(val) // #define DN_SINF(val) sinf(val)
// #define DQN_COSF(val) cosf(val) // #define DN_COSF(val) cosf(val)
// #define DQN_TANF(val) tanf(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 // - Define 'DN_STATIC_API' to apply 'static' to all function definitions and
// disable external linkage to other translation units by redefining 'DQN_API' to // disable external linkage to other translation units by redefining 'DN_API' to
// 'static'. // 'static'.
// //
// #define DQN_STATIC_API // #define DN_STATIC_API
// //
// - Turn all assertion macros to no-ops except for hard asserts (which are // - Turn all assertion macros to no-ops except for hard asserts (which are
// always enabled and represent unrecoverable errors in the library). // 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 // debug break is emitted. If this macro is defined, the check will not trigger
// a debug break. // 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 // - Define this macro to enable memory leak tracking on arena's that are
// configured to track allocations. // configured to track allocations.
// //
// Allocations are stored in a global hash-table and their respective stack // 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 // 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 <stdio.h> // - Define this to revert to the family of printf functions from <stdio.h>
// instead of using stb_sprintf in this library. stb_sprintf is 5-6x faster // 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 // than printf with a smaller binary footprint and has deterministic behaviour
// across all supported platforms. // 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 // However, if you are compiling with ASAN on MSVC, MSVC's implementation of
// __declspec(no_sanitize_address) is unable to suppress warnings in some // __declspec(no_sanitize_address) is unable to suppress warnings in some
@ -148,17 +148,17 @@
// intend to #include <Windows.h> yourself to avoid symbol conflicts with // intend to #include <Windows.h> yourself to avoid symbol conflicts with
// the redefined declarations in this library. // 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. // - Define this to stop this library from defining STB_SPRINTF_IMPLEMENTATION.
// Useful if another library uses and includes "stb_sprintf.h" // 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 // - Override the default break into the active debugger function. By default
// we use __debugbreak() on Windows and raise(SIGTRAP) on other platforms. // 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 // - Define this macro to 1 to enable poisoning of memory from arenas when ASAN
// `-fsanitize=address` is enabled. Enabling this will detect memory overwrite // `-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 // a use-after-poison in ASAN on read/write. This is a no-op if the library is
// not compiled with ASAN. // 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 // - Define this macro 1 to enable sanity checks for manually poisoned memory in
// this library when ASAN `-fsanitize=address` is enabled. These sanity checks // this library when ASAN `-fsanitize=address` is enabled. These sanity checks
// ensure that memory from arenas are correctly un/poisoned when pointers are // 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 // 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 // - 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 // allocations made that are poisoned to protect against out-of-bounds memory
// accesses. By default the library sets the guard to 128 bytes. // 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 // allow arbitrary querying of data definitions expressed in Excel-like tables
// using text files encoded in Dion-System's Metadesk grammar. // 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. // 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 // 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 // your project yourself. This library must still be defined and visible
// before this header. // 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. // 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 from being included. This might be useful if you are including the
// library in your project yourself. The library must still be defined and // library in your project yourself. The library must still be defined and
// visible before this header. // visible before this header.
// //
// - Enable compilation of unit tests with the library. // - 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. // - 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) || \ #if defined(DN_ONLY_VARRAY) || \
defined(DQN_ONLY_SARRAY) || \ defined(DN_ONLY_SARRAY) || \
defined(DQN_ONLY_FARRAY) || \ defined(DN_ONLY_FARRAY) || \
defined(DQN_ONLY_DSMAP) || \ defined(DN_ONLY_DSMAP) || \
defined(DQN_ONLY_LIST) || \ defined(DN_ONLY_LIST) || \
defined(DQN_ONLY_FSTR8) || \ defined(DN_ONLY_FSTR8) || \
defined(DQN_ONLY_FS) || \ defined(DN_ONLY_FS) || \
defined(DQN_ONLY_WINNET) || \ defined(DN_ONLY_WINNET) || \
defined(DQN_ONLY_WIN) || \ defined(DN_ONLY_WIN) || \
defined(DQN_ONLY_SEMAPHORE) || \ defined(DN_ONLY_SEMAPHORE) || \
defined(DQN_ONLY_THREAD) || \ defined(DN_ONLY_THREAD) || \
defined(DQN_ONLY_V2) || \ defined(DN_ONLY_V2) || \
defined(DQN_ONLY_V3) || \ defined(DN_ONLY_V3) || \
defined(DQN_ONLY_V4) || \ defined(DN_ONLY_V4) || \
defined(DQN_ONLY_M4) || \ defined(DN_ONLY_M4) || \
defined(DQN_ONLY_RECT) || \ defined(DN_ONLY_RECT) || \
defined(DQN_ONLY_JSON_BUILDER) || \ defined(DN_ONLY_JSON_BUILDER) || \
defined(DQN_ONLY_BIN) || \ defined(DN_ONLY_BIN) || \
defined(DQN_ONLY_PROFILER) defined(DN_ONLY_PROFILER)
#if !defined(DQN_ONLY_VARRAY) #if !defined(DN_ONLY_VARRAY)
#define DQN_NO_VARRAY #define DN_NO_VARRAY
#endif #endif
#if !defined(DQN_ONLY_FARRAY) #if !defined(DN_ONLY_FARRAY)
#define DQN_NO_FARRAY #define DN_NO_FARRAY
#endif #endif
#if !defined(DQN_ONLY_SARRAY) #if !defined(DN_ONLY_SARRAY)
#define DQN_NO_SARRAY #define DN_NO_SARRAY
#endif #endif
#if !defined(DQN_ONLY_DSMAP) #if !defined(DN_ONLY_DSMAP)
#define DQN_NO_DSMAP #define DN_NO_DSMAP
#endif #endif
#if !defined(DQN_ONLY_LIST) #if !defined(DN_ONLY_LIST)
#define DQN_NO_LIST #define DN_NO_LIST
#endif #endif
#if !defined(DQN_ONLY_FSTR8) #if !defined(DN_ONLY_FSTR8)
#define DQN_NO_FSTR8 #define DN_NO_FSTR8
#endif #endif
#if !defined(DQN_ONLY_FS) #if !defined(DN_ONLY_FS)
#define DQN_NO_FS #define DN_NO_FS
#endif #endif
#if !defined(DQN_ONLY_WINNET) #if !defined(DN_ONLY_WINNET)
#define DQN_NO_WINNET #define DN_NO_WINNET
#endif #endif
#if !defined(DQN_ONLY_WIN) #if !defined(DN_ONLY_WIN)
#define DQN_NO_WIN #define DN_NO_WIN
#endif #endif
#if !defined(DQN_ONLY_SEMAPHORE) #if !defined(DN_ONLY_SEMAPHORE)
#define DQN_NO_SEMAPHORE #define DN_NO_SEMAPHORE
#endif #endif
#if !defined(DQN_ONLY_THREAD) #if !defined(DN_ONLY_THREAD)
#define DQN_NO_THREAD #define DN_NO_THREAD
#endif #endif
#if !defined(DQN_ONLY_V2) #if !defined(DN_ONLY_V2)
#define DQN_NO_V2 #define DN_NO_V2
#endif #endif
#if !defined(DQN_ONLY_V3) #if !defined(DN_ONLY_V3)
#define DQN_NO_V3 #define DN_NO_V3
#endif #endif
#if !defined(DQN_ONLY_V4) #if !defined(DN_ONLY_V4)
#define DQN_NO_V4 #define DN_NO_V4
#endif #endif
#if !defined(DQN_ONLY_M4) #if !defined(DN_ONLY_M4)
#define DQN_NO_M4 #define DN_NO_M4
#endif #endif
#if !defined(DQN_ONLY_RECT) #if !defined(DN_ONLY_RECT)
#define DQN_NO_RECT #define DN_NO_RECT
#endif #endif
#if !defined(DQN_ONLY_JSON_BUILDER) #if !defined(DN_ONLY_JSON_BUILDER)
#define DQN_NO_JSON_BUILDER #define DN_NO_JSON_BUILDER
#endif #endif
#if !defined(DQN_ONLY_BIN) #if !defined(DN_ONLY_BIN)
#define DQN_NO_BIN #define DN_NO_BIN
#endif #endif
#if !defined(DQN_ONLY_PROFILER) #if !defined(DN_ONLY_PROFILER)
#define DQN_NO_PROFILER #define DN_NO_PROFILER
#endif #endif
#endif #endif
#if defined(DQN_WITH_CGEN) #include "dqn_base.h"
#if !defined(DQN_NO_METADESK) #if defined(DN_WITH_CGEN)
#if !defined(DN_NO_METADESK)
#if !defined(_CRT_SECURE_NO_WARNINGS) #if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define DQN_UNDO_CRT_SECURE_NO_WARNINGS #define DN_UNDO_CRT_SECURE_NO_WARNINGS
#endif #endif
// NOTE: Metadesk does not have the header for 'size_t'
#if defined(DN_COMPILER_GCC)
#include <stdint.h>
#endif
#define MD_DEFAULT_SPRINTF 0 #define MD_DEFAULT_SPRINTF 0
#define MD_IMPL_Vsnprintf DQN_VSNPRINTF #define MD_IMPL_Vsnprintf DN_VSNPRINTF
#include "External/metadesk/md.h" #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 #undef _CRT_SECURE_NO_WARNINGS
#endif #endif
#endif #endif
// Metadesk includes Windows.h // Metadesk includes Windows.h
#define DQN_NO_WIN32_MIN_HEADER #define DN_NO_WIN32_MIN_HEADER
#endif #endif
#include "dqn_base.h"
#include "dqn_external.h" #include "dqn_external.h"
#if defined(DQN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
#include "dqn_win32.h" #include "dqn_win32.h"
#endif #endif
#include "dqn_allocator.h" #include "dqn_allocator.h"
#include "dqn_tls.h" #include "dqn_tls.h"
#include "dqn_debug.h" #include "dqn_debug.h"
#include "dqn_string.h" #include "dqn_string.h"
#include "dqn_containers.h" #if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_ARM64)
#if defined(DQN_PLATFORM_EMSCRIPTEN) || defined(DQN_PLATFORM_POSIX) || defined(DQN_PLATFORM_ARM64) #include "dqn_os_posix.h"
#elif defined(DQN_PLATFORM_WIN32) #elif defined(DN_PLATFORM_WIN32)
#include "dqn_os_win32.h" #include "dqn_os_win32.h"
#else #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 #endif
#include "dqn_os.h" #include "dqn_os.h"
#include "dqn_containers.h"
#include "dqn_math.h" #include "dqn_math.h"
#include "dqn_hash.h" #include "dqn_hash.h"
#include "dqn_helpers.h" #include "dqn_helpers.h"
#include "dqn_type_info.h" #include "dqn_type_info.h"
#if defined(DQN_WITH_CGEN) #if defined(DN_WITH_CGEN)
#include "Standalone/dqn_cpp_file.h" #include "Standalone/dqn_cpp_file.h"
#include "dqn_cgen.h" #include "dqn_cgen.h"
#endif #endif
#if defined(DQN_WITH_JSON) #if defined(DN_WITH_JSON)
#if !defined(DQN_NO_SHEREDOM_JSON) #if !defined(DN_NO_SHEREDOM_JSON)
#include "External/json.h" #include "External/json.h"
#endif #endif
#include "dqn_json.h" #include "dqn_json.h"

View File

@ -15,265 +15,303 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$AREN] Dqn_Arena ///////////////////////////////////////////////////////////////////////// // NOTE: [$AREN] DN_Arena /////////////////////////////////////////////////////////////////////////
DQN_API Dqn_ArenaBlock *Dqn_Arena_BlockInit(uint64_t reserve, uint64_t commit, bool track_alloc, bool alloc_can_leak) 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; DN_USize const page_size = g_dn_core->os_page_size;
uint64_t real_reserve = reserve ? reserve : DQN_ARENA_RESERVE_SIZE; DN_U64 real_reserve = reserve ? reserve : DN_ARENA_RESERVE_SIZE;
uint64_t real_commit = commit ? commit : DQN_ARENA_COMMIT_SIZE; DN_U64 real_commit = commit ? commit : DN_ARENA_COMMIT_SIZE;
real_reserve = Dqn_AlignUpPowerOfTwo(real_reserve, page_size); real_reserve = DN_AlignUpPowerOfTwo(real_reserve, page_size);
real_commit = DQN_MIN(Dqn_AlignUpPowerOfTwo(real_commit, page_size), real_reserve); 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); DN_ASSERTF(DN_ARENA_HEADER_SIZE < real_commit && real_commit <= real_reserve, "%I64u < %I64u <= %I64u", DN_ARENA_HEADER_SIZE, real_commit, real_reserve);
DQN_ASSERTF(page_size, "Call Dqn_Library_Init() to initialise the known page size"); 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; DN_OSMemCommit mem_commit = real_reserve == real_commit ? DN_OSMemCommit_Yes : DN_OSMemCommit_No;
Dqn_ArenaBlock *result = DQN_CAST(Dqn_ArenaBlock *)Dqn_OS_MemReserve(real_reserve, mem_commit, Dqn_OSMemPage_ReadWrite); DN_ArenaBlock *result = DN_CAST(DN_ArenaBlock *)DN_OS_MemReserve(real_reserve, mem_commit, DN_OSMemPage_ReadWrite);
if (!result) if (!result)
return result; return result;
if (mem_commit == Dqn_OSMemCommit_No && !Dqn_OS_MemCommit(result, real_commit, Dqn_OSMemPage_ReadWrite)) { if (mem_commit == DN_OSMemCommit_No && !DN_OS_MemCommit(result, real_commit, DN_OSMemPage_ReadWrite)) {
Dqn_OS_MemRelease(result, real_reserve); DN_OS_MemRelease(result, real_reserve);
return result; return result;
} }
result->used = DQN_ARENA_HEADER_SIZE; result->used = DN_ARENA_HEADER_SIZE;
result->commit = real_commit; result->commit = real_commit;
result->reserve = real_reserve; result->reserve = real_reserve;
if (track_alloc) if (track_alloc)
Dqn_Debug_TrackAlloc(result, result->reserve, alloc_can_leak); DN_Debug_TrackAlloc(result, result->reserve, alloc_can_leak);
return result; 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 track_alloc = (flags & DN_ArenaFlags_NoAllocTrack) == 0;
bool alloc_can_leak = arena_flags & Dqn_ArenaFlag_AllocCanLeak; bool alloc_can_leak = flags & DN_ArenaFlags_AllocCanLeak;
Dqn_ArenaBlock *result = Dqn_Arena_BlockInit(reserve, commit, track_alloc, alloc_can_leak); DN_ArenaBlock *result = DN_Arena_BlockInit(reserve, commit, track_alloc, alloc_can_leak);
if (result && ((arena_flags & Dqn_ArenaFlag_NoPoison) == 0)) if (result && ((flags & DN_ArenaFlags_NoPoison) == 0))
Dqn_ASAN_PoisonMemoryRegion(DQN_CAST(char *)result + DQN_ARENA_HEADER_SIZE, result->commit - DQN_ARENA_HEADER_SIZE); DN_ASAN_PoisonMemoryRegion(DN_CAST(char *)result + DN_ARENA_HEADER_SIZE, result->commit - DN_ARENA_HEADER_SIZE);
return result; 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) { if (block) {
arena->stats.info.used += block->used; arena->stats.info.used += block->used;
arena->stats.info.commit += block->commit; arena->stats.info.commit += block->commit;
arena->stats.info.reserve += block->reserve; arena->stats.info.reserve += block->reserve;
arena->stats.info.blocks += 1; arena->stats.info.blocks += 1;
arena->stats.hwm.used = DQN_MAX(arena->stats.hwm.used, arena->stats.info.used); arena->stats.hwm.used = DN_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.commit = DN_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.reserve = DN_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.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 = {}; DN_ASSERT(buffer);
result.flags = flags; 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);
result.curr = Dqn_Arena_BlockInitFlags(reserve, commit, flags); DN_ASSERTF(DN_IsPowerOfTwo(size), "Buffer (%zu bytes) must be a power-of-two", size);
Dqn_Arena_UpdateStatsOnNewBlock_(&result, result.curr);
// 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; 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; DN_Arena result = {};
if (Dqn_Bit_IsNotSet(arena->flags, Dqn_ArenaFlag_NoAllocTrack)) result.flags = flags;
Dqn_Debug_TrackDealloc(block); result.curr = DN_Arena_BlockInitFlags(reserve, commit, flags);
Dqn_ASAN_UnpoisonMemoryRegion(block, block->commit); DN_Arena_UpdateStatsOnNewBlock_(&result, result.curr);
Dqn_OS_MemRelease(block, release_size); 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; ) { DN_USize release_size = block->reserve;
Dqn_ArenaBlock *block_to_free = block; 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; 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) if (!arena || !arena->curr)
return false; return false;
Dqn_ArenaBlock *curr = arena->curr; DN_ArenaBlock *curr = arena->curr;
if (pos <= curr->commit) if (pos <= curr->commit)
return true; return true;
uint64_t real_pos = pos; DN_U64 real_pos = pos;
if (!DQN_CHECK(pos <= curr->reserve)) if (!DN_CHECK(pos <= curr->reserve))
real_pos = curr->reserve; real_pos = curr->reserve;
Dqn_usize end_commit = Dqn_AlignUpPowerOfTwo(real_pos, g_dqn_library->os_page_size); DN_USize end_commit = DN_AlignUpPowerOfTwo(real_pos, g_dn_core->os_page_size);
Dqn_usize commit_size = end_commit - curr->commit; DN_USize commit_size = end_commit - curr->commit;
char *commit_ptr = DQN_CAST(char *) curr + curr->commit; char *commit_ptr = DN_CAST(char *) curr + curr->commit;
if (!Dqn_OS_MemCommit(commit_ptr, commit_size, Dqn_OSMemPage_ReadWrite)) if (!DN_OS_MemCommit(commit_ptr, commit_size, DN_OSMemPage_ReadWrite))
return false; 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) if (poison)
Dqn_ASAN_PoisonMemoryRegion(commit_ptr, commit_size); DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
curr->commit = end_commit; curr->commit = end_commit;
return true; 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) if (!arena || !arena->curr)
return false; return false;
uint64_t pos = arena->curr->commit + size; DN_U64 pos = arena->curr->commit + size;
bool result = Dqn_Arena_CommitTo(arena, pos); bool result = DN_Arena_CommitTo(arena, pos);
return result; 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) if (!arena)
return nullptr; return nullptr;
if (!arena->curr) { if (!arena->curr) {
arena->curr = Dqn_Arena_BlockInitFlags(DQN_ARENA_RESERVE_SIZE, DQN_ARENA_COMMIT_SIZE, arena->flags); arena->curr = DN_Arena_BlockInitFlags(DN_ARENA_RESERVE_SIZE, DN_ARENA_COMMIT_SIZE, arena->flags);
Dqn_Arena_UpdateStatsOnNewBlock_(arena, arena->curr); DN_Arena_UpdateStatsOnNewBlock_(arena, arena->curr);
} }
if (!arena->curr) if (!arena->curr)
return nullptr; return nullptr;
try_alloc_again: try_alloc_again:
Dqn_ArenaBlock *curr = arena->curr; DN_ArenaBlock *curr = arena->curr;
bool poison = DQN_ASAN_POISON && ((arena->flags & Dqn_ArenaFlag_NoPoison) == 0); bool poison = DN_ASAN_POISON && ((arena->flags & DN_ArenaFlags_NoPoison) == 0);
uint8_t real_align = poison ? DQN_MAX(align, DQN_ASAN_POISON_ALIGNMENT) : align; uint8_t real_align = poison ? DN_MAX(align, DN_ASAN_POISON_ALIGNMENT) : align;
uint64_t offset_pos = Dqn_AlignUpPowerOfTwo(curr->used, real_align) + (poison ? DQN_ASAN_POISON_GUARD_SIZE : 0); DN_U64 offset_pos = DN_AlignUpPowerOfTwo(curr->used, real_align) + (poison ? DN_ASAN_POISON_GUARD_SIZE : 0);
uint64_t end_pos = offset_pos + size; DN_U64 end_pos = offset_pos + size;
DN_U64 alloc_size = end_pos - curr->used;
if (end_pos > curr->reserve) { if (end_pos > curr->reserve) {
if (arena->flags & Dqn_ArenaFlag_NoGrow) if (arena->flags & (DN_ArenaFlags_NoGrow | DN_ArenaFlags_UserBuffer))
return nullptr; return nullptr;
Dqn_usize new_reserve = DQN_MAX(DQN_ARENA_HEADER_SIZE + size, DQN_ARENA_RESERVE_SIZE); DN_USize new_reserve = DN_MAX(DN_ARENA_HEADER_SIZE + alloc_size, DN_ARENA_RESERVE_SIZE);
Dqn_usize new_commit = DQN_MAX(DQN_ARENA_HEADER_SIZE + size, DQN_ARENA_COMMIT_SIZE); DN_USize new_commit = DN_MAX(DN_ARENA_HEADER_SIZE + alloc_size, DN_ARENA_COMMIT_SIZE);
Dqn_ArenaBlock *new_block = Dqn_Arena_BlockInitFlags(new_reserve, new_commit, arena->flags); if (!DN_Arena_Grow(arena, new_reserve, new_commit))
if (!new_block)
return nullptr; 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; goto try_alloc_again;
} }
Dqn_usize prev_arena_commit = curr->commit; DN_USize prev_arena_commit = curr->commit;
if (end_pos > curr->commit) { if (end_pos > curr->commit) {
Dqn_usize end_commit = Dqn_AlignUpPowerOfTwo(end_pos, g_dqn_library->os_page_size); DN_ASSERT((arena->flags & DN_ArenaFlags_UserBuffer) == 0);
Dqn_usize commit_size = end_commit - curr->commit; DN_USize end_commit = DN_AlignUpPowerOfTwo(end_pos, g_dn_core->os_page_size);
char *commit_ptr = DQN_CAST(char *)curr + curr->commit; DN_USize commit_size = end_commit - curr->commit;
if (!Dqn_OS_MemCommit(commit_ptr, commit_size, Dqn_OSMemPage_ReadWrite)) char *commit_ptr = DN_CAST(char *) curr + curr->commit;
if (!DN_OS_MemCommit(commit_ptr, commit_size, DN_OSMemPage_ReadWrite))
return nullptr; return nullptr;
if (poison) if (poison)
Dqn_ASAN_PoisonMemoryRegion(commit_ptr, commit_size); DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
curr->commit = end_commit; curr->commit = end_commit;
arena->stats.info.commit += commit_size; 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; void *result = DN_CAST(char *) curr + offset_pos;
Dqn_usize alloc_size = end_pos - curr->used;
curr->used += alloc_size; curr->used += alloc_size;
arena->stats.info.used += alloc_size; arena->stats.info.used += alloc_size;
arena->stats.hwm.used = DQN_MAX(arena->stats.hwm.used, arena->stats.info.used); arena->stats.hwm.used = DN_MAX(arena->stats.hwm.used, arena->stats.info.used);
Dqn_ASAN_UnpoisonMemoryRegion(result, size); DN_ASAN_UnpoisonMemoryRegion(result, size);
if (zero_mem == Dqn_ZeroMem_Yes) { if (zero_mem == DN_ZeroMem_Yes) {
Dqn_usize reused_bytes = DQN_MIN(prev_arena_commit - offset_pos, size); DN_USize reused_bytes = DN_MIN(prev_arena_commit - offset_pos, size);
DQN_MEMSET(result, 0, reused_bytes); DN_MEMSET(result, 0, reused_bytes);
} }
DQN_ASSERT(arena->stats.hwm.used >= arena->stats.info.used); DN_ASSERT(arena->stats.hwm.used >= arena->stats.info.used);
DQN_ASSERT(arena->stats.hwm.commit >= arena->stats.info.commit); DN_ASSERT(arena->stats.hwm.commit >= arena->stats.info.commit);
DQN_ASSERT(arena->stats.hwm.reserve >= arena->stats.info.reserve); DN_ASSERT(arena->stats.hwm.reserve >= arena->stats.info.reserve);
DQN_ASSERT(arena->stats.hwm.blocks >= arena->stats.info.blocks); DN_ASSERT(arena->stats.hwm.blocks >= arena->stats.info.blocks);
return result; 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; DN_ArenaFlags prev_flags = arena->flags;
arena->flags |= (Dqn_ArenaFlag_NoGrow | Dqn_ArenaFlag_NoPoison); arena->flags |= (DN_ArenaFlags_NoGrow | DN_ArenaFlags_NoPoison);
void *memory = Dqn_Arena_Alloc(arena, size, align, zero_mem); void *memory = DN_Arena_Alloc(arena, size, align, zero_mem);
arena->flags = prev_flags; arena->flags = prev_flags;
return memory; 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) if (!arena || !data || size == 0)
return nullptr; 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) if (result)
DQN_MEMCPY(result, data, size); DN_MEMCPY(result, data, size);
return result; 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) if (!arena || !arena->curr)
return; return;
uint64_t used = DQN_MAX(DQN_ARENA_HEADER_SIZE, init_used); DN_U64 used = DN_MAX(DN_ARENA_HEADER_SIZE, init_used);
Dqn_ArenaBlock *curr = arena->curr; DN_ArenaBlock *curr = arena->curr;
while (curr->reserve_sum >= used) { 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.used -= block_to_free->used;
arena->stats.info.commit -= block_to_free->commit; arena->stats.info.commit -= block_to_free->commit;
arena->stats.info.reserve -= block_to_free->reserve; arena->stats.info.reserve -= block_to_free->reserve;
arena->stats.info.blocks -= 1; arena->stats.info.blocks -= 1;
if (arena->flags & DN_ArenaFlags_UserBuffer)
break;
curr = curr->prev; curr = curr->prev;
Dqn_Arena_BlockDeinit_(arena, block_to_free); DN_Arena_BlockDeinit_(arena, block_to_free);
} }
arena->stats.info.used -= curr->used; arena->stats.info.used -= curr->used;
arena->curr = curr; arena->curr = curr;
curr->used = used - curr->reserve_sum; curr->used = used - curr->reserve_sum;
char *poison_ptr = (char *)curr + Dqn_AlignUpPowerOfTwo(curr->used, DQN_ASAN_POISON_ALIGNMENT); char *poison_ptr = (char *)curr + DN_AlignUpPowerOfTwo(curr->used, DN_ASAN_POISON_ALIGNMENT);
Dqn_usize poison_size = ((char *)curr + curr->commit) - poison_ptr; DN_USize poison_size = ((char *)curr + curr->commit) - poison_ptr;
Dqn_ASAN_PoisonMemoryRegion(poison_ptr, poison_size); DN_ASAN_PoisonMemoryRegion(poison_ptr, poison_size);
arena->stats.info.used += curr->used; 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; DN_ArenaBlock *curr = arena->curr;
Dqn_usize used_sum = curr->reserve_sum + curr->used; DN_USize used_sum = curr->reserve_sum + curr->used;
if (!DQN_CHECK(amount <= used_sum)) if (!DN_CHECK(amount <= used_sum))
amount = used_sum; amount = used_sum;
Dqn_usize pop_to = used_sum - amount; DN_USize pop_to = used_sum - amount;
Dqn_Arena_PopTo(arena, pop_to); 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; 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; bool result = false;
uintptr_t uint_ptr = DQN_CAST(uintptr_t)ptr; uintptr_t uint_ptr = DN_CAST(uintptr_t)ptr;
for (Dqn_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; block = block->prev) { for (DN_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 begin = DN_CAST(uintptr_t) block + DN_ARENA_HEADER_SIZE;
uintptr_t end = begin + block->reserve; uintptr_t end = begin + block->reserve;
result = uint_ptr >= begin && uint_ptr <= end; 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 = {}; DN_ArenaStats result = {};
DQN_FOR_UINDEX(index, size) { DN_FOR_UINDEX(index, size) {
Dqn_ArenaStats stats = array[index]; DN_ArenaStats stats = array[index];
result.info.used += stats.info.used; result.info.used += stats.info.used;
result.info.commit += stats.info.commit; result.info.commit += stats.info.commit;
result.info.reserve += stats.info.reserve; result.info.reserve += stats.info.reserve;
result.info.blocks += stats.info.blocks; result.info.blocks += stats.info.blocks;
result.hwm.used = DQN_MAX(result.hwm.used, result.info.used); result.hwm.used = DN_MAX(result.hwm.used, result.info.used);
result.hwm.commit = DQN_MAX(result.hwm.commit, result.info.commit); result.hwm.commit = DN_MAX(result.hwm.commit, result.info.commit);
result.hwm.reserve = DQN_MAX(result.hwm.reserve, result.info.reserve); result.hwm.reserve = DN_MAX(result.hwm.reserve, result.info.reserve);
result.hwm.blocks = DQN_MAX(result.hwm.blocks, result.info.blocks); result.hwm.blocks = DN_MAX(result.hwm.blocks, result.info.blocks);
} }
return result; 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}; DN_ArenaStats array[] = {lhs, rhs};
Dqn_ArenaStats result = Dqn_Arena_SumStatsArray(array, DQN_ARRAY_UCOUNT(array)); DN_ArenaStats result = DN_Arena_SumStatsArray(array, DN_ARRAY_UCOUNT(array));
return result; 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 = {}; DN_ArenaStats result = {};
for (Dqn_usize index = 0; index < size; index++) { for (DN_USize index = 0; index < size; index++) {
Dqn_Arena const *arena = array + index; DN_Arena const *arena = array + index;
result = Dqn_Arena_SumStats(result, arena->stats); result = DN_Arena_SumStats(result, arena->stats);
} }
return result; 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) { if (arena) {
Dqn_ArenaBlock *curr = arena->curr; DN_ArenaBlock *curr = arena->curr;
result = {arena, curr ? curr->reserve_sum + curr->used : 0}; result = {arena, curr ? curr->reserve_sum + curr->used : 0};
} }
return result; 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 ///////////////////////////////////////////////////////////////////// // NOTE: [$POOL] DN_Pool //////////////////////////////////////////////////////////////////////////
DQN_API Dqn_ChunkPool Dqn_ChunkPool_Init(Dqn_Arena *arena, uint8_t align) DN_API DN_Pool DN_Pool_Init(DN_Arena *arena, uint8_t align)
{ {
Dqn_ChunkPool result = {}; DN_Pool result = {};
if (arena) { if (arena) {
result.arena = arena; result.arena = arena;
result.align = align; result.align = align ? align : DN_POOL_DEFAULT_ALIGN;
if (result.align == 0)
result.align = DQN_CHUNK_POOL_DEFAULT_ALIGN;
} }
return result; 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; bool result = pool && pool->arena && pool->align;
return result; 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; void *result = nullptr;
if (!Dqn_ChunkPool_IsValid(pool)) if (!DN_Pool_IsValid(pool))
return result; return result;
Dqn_usize const required_size = sizeof(Dqn_ChunkPoolSlot) + pool->align + size; DN_USize const required_size = sizeof(DN_PoolSlot) + pool->align + size;
Dqn_usize const size_to_slot_offset = 5; // __lzcnt64(32) e.g. Dqn_ChunkPoolSlotSize_32B DN_USize const size_to_slot_offset = 5; // __lzcnt64(32) e.g. DN_PoolSlotSize_32B
Dqn_usize slot_index = 0; DN_USize slot_index = 0;
if (required_size > 32) { if (required_size > 32) {
// NOTE: Round up if not PoT as the low bits are set. // NOTE: Round up if not PoT as the low bits are set.
Dqn_usize dist_to_next_msb = Dqn_CountLeadingZerosU64(required_size) + 1; DN_USize dist_to_next_msb = DN_CountLeadingZerosU64(required_size) + 1;
dist_to_next_msb -= DQN_CAST(Dqn_usize)(!Dqn_IsPowerOfTwo(required_size)); dist_to_next_msb -= DN_CAST(DN_USize)(!DN_IsPowerOfTwo(required_size));
Dqn_usize const register_size = sizeof(Dqn_usize) * 8; DN_USize const register_size = sizeof(DN_USize) * 8;
DQN_ASSERT(register_size >= dist_to_next_msb + size_to_slot_offset); DN_ASSERT(register_size >= dist_to_next_msb + size_to_slot_offset);
slot_index = 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; return result;
Dqn_usize slot_size_in_bytes = 1ULL << (slot_index + size_to_slot_offset); DN_USize slot_size_in_bytes = 1ULL << (slot_index + size_to_slot_offset);
DQN_ASSERT(required_size <= (slot_size_in_bytes << 0)); DN_ASSERT(required_size <= (slot_size_in_bytes << 0));
DQN_ASSERT(required_size >= (slot_size_in_bytes >> 1)); DN_ASSERT(required_size >= (slot_size_in_bytes >> 1));
Dqn_ChunkPoolSlot *slot = nullptr; DN_PoolSlot *slot = nullptr;
if (pool->slots[slot_index]) { if (pool->slots[slot_index]) {
slot = pool->slots[slot_index]; slot = pool->slots[slot_index];
pool->slots[slot_index] = slot->next; pool->slots[slot_index] = slot->next;
DQN_MEMSET(slot->data, 0, size); DN_MEMSET(slot->data, 0, size);
DQN_ASSERT(Dqn_IsPowerOfTwoAligned(slot->data, pool->align)); DN_ASSERT(DN_IsPowerOfTwoAligned(slot->data, pool->align));
} else { } else {
void *bytes = Dqn_Arena_Alloc(pool->arena, slot_size_in_bytes, alignof(Dqn_ChunkPoolSlot), Dqn_ZeroMem_Yes); void *bytes = DN_Arena_Alloc(pool->arena, slot_size_in_bytes, alignof(DN_PoolSlot), DN_ZeroMem_Yes);
slot = DQN_CAST(Dqn_ChunkPoolSlot *) bytes; slot = DN_CAST(DN_PoolSlot *) bytes;
// NOTE: The raw pointer is round up to the next 'pool->align'-ed // 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 // 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 // This allows us to smuggle 1 byte behind the user pointer that has
// the offset to the original pointer. // 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; uintptr_t offset_to_original_ptr = DN_CAST(uintptr_t)slot->data - DN_CAST(uintptr_t)bytes;
DQN_ASSERT(slot->data > bytes); DN_ASSERT(slot->data > bytes);
DQN_ASSERT(offset_to_original_ptr <= sizeof(Dqn_ChunkPoolSlot) + pool->align); DN_ASSERT(offset_to_original_ptr <= sizeof(DN_PoolSlot) + pool->align);
// NOTE: Store the offset to the original pointer behind the user's // NOTE: Store the offset to the original pointer behind the user's
// pointer. // pointer.
char *offset_to_original_storage = DQN_CAST(char *)slot->data - 1; char *offset_to_original_storage = DN_CAST(char *)slot->data - 1;
DQN_MEMCPY(offset_to_original_storage, &offset_to_original_ptr, 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 // 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. // pointer gets returned which free list to return the pointer to.
result = slot->data; result = slot->data;
slot->next = DQN_CAST(Dqn_ChunkPoolSlot *)slot_index; slot->next = DN_CAST(DN_PoolSlot *)slot_index;
return result; 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 = {}; DN_Str8 result = {};
if (!Dqn_ChunkPool_IsValid(pool)) if (!DN_Pool_IsValid(pool))
return result; return result;
Dqn_usize size_required = Dqn_CStr8_FVSize(fmt, args); DN_USize size_required = DN_CStr8_FVSize(fmt, args);
result.data = DQN_CAST(char *) Dqn_ChunkPool_Alloc(pool, size_required + 1); result.data = DN_CAST(char *) DN_Pool_Alloc(pool, size_required + 1);
if (result.data) { if (result.data) {
result.size = size_required; 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; 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_list args;
va_start(args, fmt); 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); va_end(args);
return result; 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 = {}; DN_Str8 result = {};
if (!Dqn_ChunkPool_IsValid(pool)) if (!DN_Pool_IsValid(pool))
return result; return result;
if (!Dqn_Str8_HasData(string)) if (!DN_Str8_HasData(string))
return result; 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) if (!data)
return result; return result;
DQN_MEMCPY(data, string.data, string.size); DN_MEMCPY(data, string.data, string.size);
data[string.size] = 0; data[string.size] = 0;
result = Dqn_Str8_Init(data, string.size); result = DN_Str8_Init(data, string.size);
return result; 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; 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; char const *one_byte_behind_ptr = DN_CAST(char *) ptr - 1;
Dqn_usize offset_to_original_ptr = 0; DN_USize offset_to_original_ptr = 0;
DQN_MEMCPY(&offset_to_original_ptr, one_byte_behind_ptr, 1); DN_MEMCPY(&offset_to_original_ptr, one_byte_behind_ptr, 1);
DQN_ASSERT(offset_to_original_ptr <= sizeof(Dqn_ChunkPoolSlot) + pool->align); DN_ASSERT(offset_to_original_ptr <= sizeof(DN_PoolSlot) + pool->align);
char *original_ptr = DQN_CAST(char *)ptr - offset_to_original_ptr; char *original_ptr = DN_CAST(char *) ptr - offset_to_original_ptr;
Dqn_ChunkPoolSlot *slot = DQN_CAST(Dqn_ChunkPoolSlot *)original_ptr; DN_PoolSlot *slot = DN_CAST(DN_PoolSlot *) original_ptr;
Dqn_ChunkPoolSlotSize slot_index = DQN_CAST(Dqn_ChunkPoolSlotSize)(DQN_CAST(uintptr_t)slot->next); DN_PoolSlotSize slot_index = DN_CAST(DN_PoolSlotSize)(DN_CAST(uintptr_t) slot->next);
DQN_ASSERT(slot_index < Dqn_ChunkPoolSlotSize_Count); DN_ASSERT(slot_index < DN_PoolSlotSize_Count);
slot->next = pool->slots[slot_index]; slot->next = pool->slots[slot_index];
pool->slots[slot_index] = slot; 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) if (!pool || !data || size == 0)
return nullptr; return nullptr;
// TODO: Hmm should align be part of the alloc interface in general? I'm not going to worry // 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. // 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) if (result)
DQN_MEMCPY(result, data, size); DN_MEMCPY(result, data, size);
return result; return result;
} }
// NOTE: [$ACAT] Dqn_ArenaCatalog ////////////////////////////////////////////////////////////////// // NOTE: [$ACAT] DN_ArenaCatalog //////////////////////////////////////////////////////////////////
DQN_API void Dqn_ArenaCatalog_Init(Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool) DN_API void DN_ArenaCatalog_Init(DN_ArenaCatalog *catalog, DN_Pool *pool)
{ {
catalog->pool = pool; catalog->pool = pool;
catalog->sentinel.next = &catalog->sentinel; catalog->sentinel.next = &catalog->sentinel;
catalog->sentinel.prev = &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); DN_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_ArenaCatalogItem *result = &catalog->sentinel; DN_ArenaCatalogItem *result = &catalog->sentinel;
for (Dqn_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) { for (DN_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) {
if (item->label == label) { if (item->label == label) {
result = item; result = item;
break; break;
} }
} }
Dqn_TicketMutex_End(&catalog->ticket_mutex); DN_TicketMutex_End(&catalog->ticket_mutex);
return result; 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 // 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. // 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 // 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) { if (result) {
result->arena = arena; result->arena = arena;
result->label = label; result->label = label;
result->arena_pool_allocated = arena_pool_allocated; result->arena_pool_allocated = arena_pool_allocated;
// NOTE: Add to the catalog (linked list) // NOTE: Add to the catalog (linked list)
Dqn_ArenaCatalogItem *sentinel = &catalog->sentinel; DN_ArenaCatalogItem *sentinel = &catalog->sentinel;
result->next = sentinel; result->next = sentinel;
result->prev = sentinel->prev; result->prev = sentinel->prev;
result->next->prev = result; result->next->prev = result;
result->prev->next = 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_list args;
va_start(args, fmt); va_start(args, fmt);
Dqn_TicketMutex_Begin(&catalog->ticket_mutex); DN_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args); DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args);
Dqn_TicketMutex_End(&catalog->ticket_mutex); DN_TicketMutex_End(&catalog->ticket_mutex);
va_end(args); 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); DN_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args); DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args);
Dqn_TicketMutex_End(&catalog->ticket_mutex); DN_TicketMutex_End(&catalog->ticket_mutex);
Dqn_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/); 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); DN_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args); DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args);
Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena); DN_Arena *result = DN_Pool_New(catalog->pool, DN_Arena);
Dqn_TicketMutex_End(&catalog->ticket_mutex); DN_TicketMutex_End(&catalog->ticket_mutex);
*result = Dqn_Arena_InitSize(reserve, commit, arena_flags); *result = DN_Arena_InitSize(reserve, commit, arena_flags);
Dqn_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/); DN_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/);
return result; 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_list args;
va_start(args, fmt); va_start(args, fmt);
Dqn_TicketMutex_Begin(&catalog->ticket_mutex); DN_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args); DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args);
Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena); DN_Arena *result = DN_Pool_New(catalog->pool, DN_Arena);
Dqn_TicketMutex_End(&catalog->ticket_mutex); DN_TicketMutex_End(&catalog->ticket_mutex);
va_end(args); va_end(args);
*result = Dqn_Arena_InitSize(reserve, commit, arena_flags); *result = DN_Arena_InitSize(reserve, commit, arena_flags);
Dqn_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/); DN_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/);
return result; 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; bool result = false;
Dqn_TicketMutex_Begin(&catalog->ticket_mutex); DN_TicketMutex_Begin(&catalog->ticket_mutex);
for (Dqn_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) { for (DN_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) {
if (item->arena == arena) { if (item->arena == arena) {
item->next->prev = item->prev; item->next->prev = item->prev;
item->prev->next = item->next; item->prev->next = item->next;
if (item->arena_pool_allocated) { if (item->arena_pool_allocated) {
if (free_arena == Dqn_ArenaCatalogFreeArena_Yes) if (free_arena == DN_ArenaCatalogFreeArena_Yes)
Dqn_Arena_Deinit(item->arena); DN_Arena_Deinit(item->arena);
Dqn_ChunkPool_Dealloc(catalog->pool, item->arena); DN_Pool_Dealloc(catalog->pool, item->arena);
} }
Dqn_ChunkPool_Dealloc(catalog->pool, item->label.data); DN_Pool_Dealloc(catalog->pool, item->label.data);
Dqn_ChunkPool_Dealloc(catalog->pool, item); DN_Pool_Dealloc(catalog->pool, item);
result = true; result = true;
break; break;
} }
} }
Dqn_TicketMutex_End(&catalog->ticket_mutex); DN_TicketMutex_End(&catalog->ticket_mutex);
return result; return result;
} }

View File

@ -17,197 +17,204 @@
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// [$AREN] Dqn_Arena -- Growing bump allocator // [$AREN] DN_Arena -- Growing bump allocator
// [$CHUN] Dqn_ChunkPool -- Allocates reusable, free-able memory in PoT chunks // [$CHUN] DN_Pool -- Allocates reusable, free-able memory in PoT chunks
// [$ACAT] Dqn_ArenaCatalog -- Collate, create & manage arenas in a catalog // [$POOL] DN_Pool -- TODO
// [$ACAT] DN_ArenaCatalog -- Collate, create & manage arenas in a catalog
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$AREN] Dqn_Arena ///////////////////////////////////////////////////////////////////////// // NOTE: [$AREN] DN_Arena /////////////////////////////////////////////////////////////////////////
#if !defined(DQN_ARENA_RESERVE_SIZE) #if !defined(DN_ARENA_RESERVE_SIZE)
#define DQN_ARENA_RESERVE_SIZE DQN_MEGABYTES(64) #define DN_ARENA_RESERVE_SIZE DN_MEGABYTES(64)
#endif #endif
#if !defined(DQN_ARENA_COMMIT_SIZE) #if !defined(DN_ARENA_COMMIT_SIZE)
#define DQN_ARENA_COMMIT_SIZE DQN_KILOBYTES(64) #define DN_ARENA_COMMIT_SIZE DN_KILOBYTES(64)
#endif #endif
struct Dqn_ArenaBlock struct DN_ArenaBlock
{ {
Dqn_ArenaBlock *prev; DN_ArenaBlock *prev;
uint64_t used; DN_U64 used;
uint64_t commit; DN_U64 commit;
uint64_t reserve; DN_U64 reserve;
uint64_t reserve_sum; DN_U64 reserve_sum;
}; };
enum Dqn_ArenaFlag typedef uint32_t DN_ArenaFlags;
enum DN_ArenaFlags_
{ {
Dqn_ArenaFlag_Nil = 0, DN_ArenaFlags_Nil = 0,
Dqn_ArenaFlag_NoGrow = 1 << 0, DN_ArenaFlags_NoGrow = 1 << 0,
Dqn_ArenaFlag_NoPoison = 1 << 1, DN_ArenaFlags_NoPoison = 1 << 1,
Dqn_ArenaFlag_NoAllocTrack = 1 << 2, DN_ArenaFlags_NoAllocTrack = 1 << 2,
Dqn_ArenaFlag_AllocCanLeak = 1 << 3, DN_ArenaFlags_AllocCanLeak = 1 << 3,
DN_ArenaFlags_UserBuffer = 1 << 4,
}; };
struct Dqn_ArenaInfo struct DN_ArenaInfo
{ {
uint64_t used; DN_U64 used;
uint64_t commit; DN_U64 commit;
uint64_t reserve; DN_U64 reserve;
uint64_t blocks; DN_U64 blocks;
}; };
struct Dqn_ArenaStats struct DN_ArenaStats
{ {
Dqn_ArenaInfo info; DN_ArenaInfo info;
Dqn_ArenaInfo hwm; DN_ArenaInfo hwm;
}; };
struct Dqn_Arena struct DN_Arena
{ {
Dqn_ArenaBlock *curr; DN_ArenaBlock *curr;
Dqn_ArenaStats stats; DN_ArenaStats stats;
Dqn_TicketMutex mutex; // For user code to lock the arena, the arena itself does not use. DN_ArenaFlags flags;
uint8_t flags; DN_Str8 label;
DN_Arena *prev, *next;
}; };
struct Dqn_ArenaTempMem struct DN_ArenaTempMem
{ {
Dqn_Arena *arena; DN_Arena *arena;
uint64_t used_sum; DN_U64 used_sum;
}; };
struct Dqn_ArenaTempMemScope struct DN_ArenaTempMemScope
{ {
Dqn_ArenaTempMemScope(Dqn_Arena *arena); DN_ArenaTempMemScope(DN_Arena *arena);
~Dqn_ArenaTempMemScope(); ~DN_ArenaTempMemScope();
Dqn_ArenaTempMem mem; 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 ///////////////////////////////////////////////////////////////////// // NOTE: [$CHUN] DN_Pool /////////////////////////////////////////////////////////////////////
#if !defined(DQN_CHUNK_POOL_DEFAULT_ALIGN) #if !defined(DN_POOL_DEFAULT_ALIGN)
#define DQN_CHUNK_POOL_DEFAULT_ALIGN 16 #define DN_POOL_DEFAULT_ALIGN 16
#endif #endif
struct Dqn_ChunkPoolSlot struct DN_PoolSlot
{ {
void *data; void *data;
Dqn_ChunkPoolSlot *next; DN_PoolSlot *next;
}; };
enum Dqn_ChunkPoolSlotSize enum DN_PoolSlotSize
{ {
Dqn_ChunkPoolSlotSize_32B, DN_PoolSlotSize_32B,
Dqn_ChunkPoolSlotSize_64B, DN_PoolSlotSize_64B,
Dqn_ChunkPoolSlotSize_128B, DN_PoolSlotSize_128B,
Dqn_ChunkPoolSlotSize_256B, DN_PoolSlotSize_256B,
Dqn_ChunkPoolSlotSize_512B, DN_PoolSlotSize_512B,
Dqn_ChunkPoolSlotSize_1KiB, DN_PoolSlotSize_1KiB,
Dqn_ChunkPoolSlotSize_2KiB, DN_PoolSlotSize_2KiB,
Dqn_ChunkPoolSlotSize_4KiB, DN_PoolSlotSize_4KiB,
Dqn_ChunkPoolSlotSize_8KiB, DN_PoolSlotSize_8KiB,
Dqn_ChunkPoolSlotSize_16KiB, DN_PoolSlotSize_16KiB,
Dqn_ChunkPoolSlotSize_32KiB, DN_PoolSlotSize_32KiB,
Dqn_ChunkPoolSlotSize_64KiB, DN_PoolSlotSize_64KiB,
Dqn_ChunkPoolSlotSize_128KiB, DN_PoolSlotSize_128KiB,
Dqn_ChunkPoolSlotSize_256KiB, DN_PoolSlotSize_256KiB,
Dqn_ChunkPoolSlotSize_512KiB, DN_PoolSlotSize_512KiB,
Dqn_ChunkPoolSlotSize_1MiB, DN_PoolSlotSize_1MiB,
Dqn_ChunkPoolSlotSize_2MiB, DN_PoolSlotSize_2MiB,
Dqn_ChunkPoolSlotSize_4MiB, DN_PoolSlotSize_4MiB,
Dqn_ChunkPoolSlotSize_8MiB, DN_PoolSlotSize_8MiB,
Dqn_ChunkPoolSlotSize_16MiB, DN_PoolSlotSize_16MiB,
Dqn_ChunkPoolSlotSize_32MiB, DN_PoolSlotSize_32MiB,
Dqn_ChunkPoolSlotSize_64MiB, DN_PoolSlotSize_64MiB,
Dqn_ChunkPoolSlotSize_128MiB, DN_PoolSlotSize_128MiB,
Dqn_ChunkPoolSlotSize_256MiB, DN_PoolSlotSize_256MiB,
Dqn_ChunkPoolSlotSize_512MiB, DN_PoolSlotSize_512MiB,
Dqn_ChunkPoolSlotSize_1GiB, DN_PoolSlotSize_1GiB,
Dqn_ChunkPoolSlotSize_2GiB, DN_PoolSlotSize_2GiB,
Dqn_ChunkPoolSlotSize_4GiB, DN_PoolSlotSize_4GiB,
Dqn_ChunkPoolSlotSize_8GiB, DN_PoolSlotSize_8GiB,
Dqn_ChunkPoolSlotSize_16GiB, DN_PoolSlotSize_16GiB,
Dqn_ChunkPoolSlotSize_32GiB, DN_PoolSlotSize_32GiB,
Dqn_ChunkPoolSlotSize_Count, DN_PoolSlotSize_Count,
}; };
struct Dqn_ChunkPool struct DN_Pool
{ {
Dqn_Arena *arena; DN_Arena *arena;
Dqn_ChunkPoolSlot *slots[Dqn_ChunkPoolSlotSize_Count]; DN_PoolSlot *slots[DN_PoolSlotSize_Count];
uint8_t align; uint8_t align;
}; };
// NOTE: [$ACAT] Dqn_ArenaCatalog ////////////////////////////////////////////////////////////////// // NOTE: [$ACAT] DN_ArenaCatalog //////////////////////////////////////////////////////////////////
struct Dqn_ArenaCatalogItem struct DN_ArenaCatalogItem
{ {
Dqn_Arena *arena; DN_Arena *arena;
Dqn_Str8 label; DN_Str8 label;
bool arena_pool_allocated; bool arena_pool_allocated;
Dqn_ArenaCatalogItem *next; DN_ArenaCatalogItem *next;
Dqn_ArenaCatalogItem *prev; DN_ArenaCatalogItem *prev;
}; };
struct Dqn_ArenaCatalog struct DN_ArenaCatalog
{ {
Dqn_TicketMutex ticket_mutex; // Mutex for adding to the linked list of arenas DN_TicketMutex ticket_mutex; // Mutex for adding to the linked list of arenas
struct Dqn_ChunkPool *pool; DN_Pool *pool;
Dqn_ArenaCatalogItem sentinel; DN_ArenaCatalogItem sentinel;
uint16_t arena_count; uint16_t arena_count;
}; };
enum Dqn_ArenaCatalogFreeArena enum DN_ArenaCatalogFreeArena
{ {
Dqn_ArenaCatalogFreeArena_No, DN_ArenaCatalogFreeArena_No,
Dqn_ArenaCatalogFreeArena_Yes, DN_ArenaCatalogFreeArena_Yes,
}; };
// NOTE: [$AREN] Dqn_Arena ///////////////////////////////////////////////////////////////////////// // NOTE: [$AREN] DN_Arena /////////////////////////////////////////////////////////////////////////
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_API void Dqn_Arena_Deinit (Dqn_Arena *arena); DN_API DN_Arena DN_Arena_InitSize (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
DQN_API bool Dqn_Arena_Commit (Dqn_Arena *arena, uint64_t size); DN_API void DN_Arena_Deinit (DN_Arena *arena);
DQN_API bool Dqn_Arena_CommitTo (Dqn_Arena *arena, uint64_t pos); DN_API bool DN_Arena_Commit (DN_Arena *arena, DN_U64 size);
DQN_API void * Dqn_Arena_Alloc (Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem); DN_API bool DN_Arena_CommitTo (DN_Arena *arena, DN_U64 pos);
DQN_API void * Dqn_Arena_AllocContiguous (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);
DQN_API void * Dqn_Arena_Copy (Dqn_Arena *arena, void const *data, uint64_t size, uint8_t align); DN_API void * DN_Arena_Alloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
DQN_API void Dqn_Arena_PopTo (Dqn_Arena *arena, uint64_t init_used); DN_API void * DN_Arena_AllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
DQN_API void Dqn_Arena_Pop (Dqn_Arena *arena, uint64_t amount); DN_API void * DN_Arena_Copy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
DQN_API uint64_t Dqn_Arena_Pos (Dqn_Arena const *arena); DN_API void DN_Arena_PopTo (DN_Arena *arena, DN_U64 init_used);
DQN_API void Dqn_Arena_Clear (Dqn_Arena *arena); DN_API void DN_Arena_Pop (DN_Arena *arena, DN_U64 amount);
DQN_API bool Dqn_Arena_OwnsPtr (Dqn_Arena const *arena, void *ptr); DN_API DN_U64 DN_Arena_Pos (DN_Arena const *arena);
DQN_API Dqn_ArenaStats Dqn_Arena_SumStatsArray (Dqn_ArenaStats const *array, Dqn_usize size); DN_API void DN_Arena_Clear (DN_Arena *arena);
DQN_API Dqn_ArenaStats Dqn_Arena_SumStats (Dqn_ArenaStats lhs, Dqn_ArenaStats rhs); DN_API bool DN_Arena_OwnsPtr (DN_Arena const *arena, void *ptr);
DQN_API Dqn_ArenaStats Dqn_Arena_SumArenaArrayToStats (Dqn_Arena const *array, Dqn_usize size); DN_API DN_ArenaStats DN_Arena_SumStatsArray (DN_ArenaStats const *array, DN_USize size);
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin (Dqn_Arena *arena); DN_API DN_ArenaStats DN_Arena_SumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
DQN_API void Dqn_Arena_TempMemEnd (Dqn_ArenaTempMem mem); DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats (DN_Arena const *array, DN_USize size);
#define Dqn_Arena_New(arena, T, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem) DN_API DN_ArenaTempMem DN_Arena_TempMemBegin (DN_Arena *arena);
#define Dqn_Arena_NewArray(arena, T, count, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem) DN_API void DN_Arena_TempMemEnd (DN_ArenaTempMem mem);
#define Dqn_Arena_NewCopy(arena, T, src) (T *)Dqn_Arena_Copy (arena, (src), sizeof(T), alignof(T)) #define DN_Arena_New_Frame(T, zero_mem) (T *)DN_Arena_Alloc(DN_TLS_Get()->frame_arena, sizeof(T), alignof(T), zero_mem)
#define Dqn_Arena_NewArrayCopy(arena, T, src, count) (T *)Dqn_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T)) #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 ///////////////////////////////////////////////////////////////////// // NOTE: [$CHUN] DN_Pool /////////////////////////////////////////////////////////////////////
DQN_API Dqn_ChunkPool Dqn_ChunkPool_Init (Dqn_Arena *arena, uint8_t align); DN_API DN_Pool DN_Pool_Init (DN_Arena *arena, uint8_t align);
DQN_API bool Dqn_ChunkPool_IsValid (Dqn_ChunkPool const *pool); DN_API bool DN_Pool_IsValid (DN_Pool const *pool);
DQN_API void * Dqn_ChunkPool_Alloc (Dqn_ChunkPool *pool, Dqn_usize size); DN_API void * DN_Pool_Alloc (DN_Pool *pool, DN_USize size);
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_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, ...);
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_API void Dqn_ChunkPool_Dealloc (Dqn_ChunkPool *pool, void *ptr); DN_API void DN_Pool_Dealloc (DN_Pool *pool, void *ptr);
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);
#define Dqn_ChunkPool_New(pool, T) (T *)Dqn_ChunkPool_Alloc(pool, sizeof(T)) #define DN_Pool_New(pool, T) (T *)DN_Pool_Alloc(pool, sizeof(T))
#define Dqn_ChunkPool_NewArray(pool, T, count) (T *)Dqn_ChunkPool_Alloc(pool, count * sizeof(T)) #define DN_Pool_NewArray(pool, T, count) (T *)DN_Pool_Alloc(pool, count * sizeof(T))
#define Dqn_ChunkPool_NewCopy(arena, T, src) (T *)Dqn_ChunkPool_Copy (arena, (src), sizeof(T), alignof(T)) #define DN_Pool_NewCopy(arena, T, src) (T *)DN_Pool_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_NewArrayCopy(arena, T, src, count) (T *)DN_Pool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
// NOTE: [$ACAT] Dqn_ArenaCatalog ////////////////////////////////////////////////////////////////// // NOTE: [$ACAT] DN_ArenaCatalog //////////////////////////////////////////////////////////////////
DQN_API void Dqn_ArenaCatalog_Init (Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool); DN_API void DN_ArenaCatalog_Init (DN_ArenaCatalog *catalog, DN_Pool *pool);
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_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, ...);
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_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_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, ...);
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);

View File

@ -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 // NOTE: Algorithm as described in http://0x80.pl/articles/simd-strfind.html
Dqn_Str8FindResult result = {}; DN_Str8FindResult result = {};
if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(find) || find.size > string.size) if (!DN_Str8_HasData(string) || !DN_Str8_HasData(find) || find.size > string.size)
return result; return result;
__m512i const find_first_ch = _mm512_set1_epi8(find.data[0]); __m512i const find_first_ch = _mm512_set1_epi8(find.data[0]);
__m512i const find_last_ch = _mm512_set1_epi8(find.data[find.size - 1]); __m512i const find_last_ch = _mm512_set1_epi8(find.data[find.size - 1]);
Dqn_usize const search_size = string.size - find.size; DN_USize const search_size = string.size - find.size;
Dqn_usize simd_iterations = search_size / sizeof(__m512i); DN_USize simd_iterations = search_size / sizeof(__m512i);
char const *ptr = string.data; char const *ptr = string.data;
while (simd_iterations--) { while (simd_iterations--) {
__m512i find_first_ch_block = _mm512_loadu_si512(ptr); __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); uint64_t const lsb_zero_pos = _tzcnt_u64(zero_byte_mask);
char const *base_ptr = ptr + (4 * lsb_zero_pos); 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.found = true;
result.index = base_ptr - string.data; 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.found = true;
result.index = base_ptr - string.data + 1; 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.found = true;
result.index = base_ptr - string.data + 2; 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.found = true;
result.index = base_ptr - string.data + 3; result.index = base_ptr - string.data + 3;
} }
if (result.found) { if (result.found) {
result.start_to_before_match = Dqn_Str8_Init(string.data, result.index); result.start_to_before_match = DN_Str8_Init(string.data, result.index);
result.match = Dqn_Str8_Init(string.data + result.index, find.size); result.match = DN_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.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; return result;
} }
zero_byte_mask = Dqn_Bit_ClearNextLSB(zero_byte_mask); zero_byte_mask = DN_Bit_ClearNextLSB(zero_byte_mask);
} }
ptr += sizeof(__m512i); ptr += sizeof(__m512i);
} }
for (Dqn_usize index = ptr - string.data; index < string.size; index++) { for (DN_USize index = ptr - string.data; index < string.size; index++) {
Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find.size); DN_Str8 string_slice = DN_Str8_Slice(string, index, find.size);
if (Dqn_Str8_Eq(string_slice, find)) { if (DN_Str8_Eq(string_slice, find)) {
result.found = true; result.found = true;
result.index = index; result.index = index;
result.start_to_before_match = Dqn_Str8_Init(string.data, index); result.start_to_before_match = DN_Str8_Init(string.data, index);
result.match = Dqn_Str8_Init(string.data + index, find.size); result.match = DN_Str8_Init(string.data + index, find.size);
result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - index); 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; return result;
} }
} }
@ -121,18 +123,18 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F(Dqn_Str8 string, Dqn_Str8 fi
return result; 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 // NOTE: Algorithm as described in http://0x80.pl/articles/simd-strfind.html
Dqn_Str8FindResult result = {}; DN_Str8FindResult result = {};
if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(find) || find.size > string.size) if (!DN_Str8_HasData(string) || !DN_Str8_HasData(find) || find.size > string.size)
return result; return result;
__m512i const find_first_ch = _mm512_set1_epi8(find.data[0]); __m512i const find_first_ch = _mm512_set1_epi8(find.data[0]);
__m512i const find_last_ch = _mm512_set1_epi8(find.data[find.size - 1]); __m512i const find_last_ch = _mm512_set1_epi8(find.data[find.size - 1]);
Dqn_usize const search_size = string.size - find.size; DN_USize const search_size = string.size - find.size;
Dqn_usize simd_iterations = search_size / sizeof(__m512i); DN_USize simd_iterations = search_size / sizeof(__m512i);
char const *ptr = string.data + search_size + 1; char const *ptr = string.data + search_size + 1;
while (simd_iterations--) { 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); uint64_t const lsb_zero_pos = _tzcnt_u64(zero_byte_mask);
char const *base_ptr = ptr + (4 * lsb_zero_pos); 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.found = true;
result.index = base_ptr - string.data; 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.found = true;
result.index = base_ptr - string.data + 1; 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.found = true;
result.index = base_ptr - string.data + 2; 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.found = true;
result.index = base_ptr - string.data + 3; result.index = base_ptr - string.data + 3;
} }
if (result.found) { if (result.found) {
result.start_to_before_match = Dqn_Str8_Init(string.data, result.index); result.start_to_before_match = DN_Str8_Init(string.data, result.index);
result.match = Dqn_Str8_Init(string.data + result.index, find.size); result.match = DN_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.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - result.index);
return result; 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--) { for (DN_USize index = ptr - string.data - 1; index < string.size; index--) {
Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find.size); DN_Str8 string_slice = DN_Str8_Slice(string, index, find.size);
if (Dqn_Str8_Eq(string_slice, find)) { if (DN_Str8_Eq(string_slice, find)) {
result.found = true; result.found = true;
result.index = index; result.index = index;
result.start_to_before_match = Dqn_Str8_Init(string.data, index); result.start_to_before_match = DN_Str8_Init(string.data, index);
result.match = Dqn_Str8_Init(string.data + index, find.size); result.match = DN_Str8_Init(string.data + index, find.size);
result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - index); result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - index);
return result; return result;
} }
} }
@ -222,14 +224,14 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F(Dqn_Str8 string, Dqn_Str
return result; 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 = {}; DN_Str8BinarySplitResult result = {};
Dqn_Str8FindResult find_result = Dqn_Str8_FindStr8AVX512F(string, find); DN_Str8FindResult find_result = DN_Str8_FindStr8AVX512F(string, find);
if (find_result.found) { if (find_result.found) {
result.lhs.data = string.data; result.lhs.data = string.data;
result.lhs.size = find_result.index; 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 { } else {
result.lhs = string; result.lhs = string;
} }
@ -237,14 +239,14 @@ DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitAVX512F(Dqn_Str8 string, D
return result; 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 = {}; DN_Str8BinarySplitResult result = {};
Dqn_Str8FindResult find_result = Dqn_Str8_FindLastStr8AVX512F(string, find); DN_Str8FindResult find_result = DN_Str8_FindLastStr8AVX512F(string, find);
if (find_result.found) { if (find_result.found) {
result.lhs.data = string.data; result.lhs.data = string.data;
result.lhs.size = find_result.index; 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 { } else {
result.lhs = string; result.lhs = string;
} }
@ -252,17 +254,17 @@ DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastAVX512F(Dqn_Str8 strin
return result; 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. DN_USize result = 0; // The number of splits in the actual string.
if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(delimiter) || delimiter.size <= 0) if (!DN_Str8_HasData(string) || !DN_Str8_HasData(delimiter) || delimiter.size <= 0)
return result; return result;
Dqn_Str8BinarySplitResult split = {}; DN_Str8BinarySplitResult split = {};
Dqn_Str8 first = string; DN_Str8 first = string;
do { do {
split = Dqn_Str8_BinarySplitAVX512F(first, delimiter); split = DN_Str8_BinarySplitAVX512F(first, delimiter);
if (split.lhs.size || mode == Dqn_Str8SplitIncludeEmptyStrings_Yes) { if (split.lhs.size || mode == DN_Str8SplitIncludeEmptyStrings_Yes) {
if (splits && result < splits_count) if (splits && result < splits_count)
splits[result] = split.lhs; splits[result] = split.lhs;
result++; result++;
@ -273,14 +275,14 @@ DQN_API Dqn_usize Dqn_Str8_SplitAVX512F(Dqn_Str8 string, Dqn_Str8 delimiter, Dqn
return result; return result;
} }
DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8_SplitAllocAVX512F(Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8SplitIncludeEmptyStrings mode) DN_API DN_Slice<DN_Str8> DN_Str8_SplitAllocAVX512F(DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode)
{ {
Dqn_Slice<Dqn_Str8> result = {}; DN_Slice<DN_Str8> result = {};
Dqn_usize splits_required = Dqn_Str8_SplitAVX512F(string, delimiter, /*splits*/ nullptr, /*count*/ 0, mode); DN_USize splits_required = DN_Str8_SplitAVX512F(string, delimiter, /*splits*/ nullptr, /*count*/ 0, mode);
result.data = Dqn_Arena_NewArray(arena, Dqn_Str8, splits_required, Dqn_ZeroMem_No); result.data = DN_Arena_NewArray(arena, DN_Str8, splits_required, DN_ZeroMem_No);
if (result.data) { if (result.data) {
result.size = Dqn_Str8_SplitAVX512F(string, delimiter, result.data, splits_required, mode); result.size = DN_Str8_SplitAVX512F(string, delimiter, result.data, splits_required, mode);
DQN_ASSERT(splits_required == result.size); DN_ASSERT(splits_required == result.size);
} }
return result; return result;
} }

View File

@ -1,5 +1,5 @@
#if !defined(DQN_AVX512F_H) #if !defined(DN_AVX512F_H)
#define DQN_AVX512F_H #define DN_AVX512F_H
/* /*
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -20,11 +20,11 @@
#include "dqn.h" #include "dqn.h"
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);
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);
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_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_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_API Dqn_Slice<Dqn_Str8> Dqn_Str8_SplitAllocAVX512F (Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8SplitIncludeEmptyStrings mode); DN_API DN_Slice<DN_Str8> DN_Str8_SplitAllocAVX512F (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
#endif // DQN_AVX512F_H #endif // DN_AVX512F_H

File diff suppressed because it is too large Load Diff

1013
dqn_base.h

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#if !defined(DQN_CGEN_H) #if !defined(DN_CGEN_H)
#define DQN_CGEN_H #define DN_CGEN_H
/* /*
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -18,157 +18,157 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$CGEN] Dqn_CGen ////////////////////////////////////////////////////////////////////////// // NOTE: [$CGEN] DN_CGen //////////////////////////////////////////////////////////////////////////
#if !defined(MD_H) #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 #endif
#if !defined(DQN_H) #if !defined(DN_H)
#error 'dqn.h' must be included before 'dqn_cgen.h' #error 'dqn.h' must be included before 'dn_cgen.h'
#endif #endif
#if !defined(DQN_CPP_FILE_H) #if !defined(DN_CPP_FILE_H)
#error 'dqn_cpp_file.h' must be included before 'dqn_cgen.h' #error 'dn_cpp_file.h' must be included before 'dn_cgen.h'
#endif #endif
enum Dqn_CGenTableKeyType enum DN_CGenTableKeyType
{ {
Dqn_CGenTableKeyType_Nil, DN_CGenTableKeyType_Nil,
Dqn_CGenTableKeyType_Name, DN_CGenTableKeyType_Name,
Dqn_CGenTableKeyType_Type, DN_CGenTableKeyType_Type,
}; };
enum Dqn_CGenTableType enum DN_CGenTableType
{ {
Dqn_CGenTableType_Nil, DN_CGenTableType_Nil,
Dqn_CGenTableType_Data, DN_CGenTableType_Data,
Dqn_CGenTableType_CodeGenBuiltinTypes, DN_CGenTableType_CodeGenBuiltinTypes,
Dqn_CGenTableType_CodeGenStruct, DN_CGenTableType_CodeGenStruct,
Dqn_CGenTableType_CodeGenEnum, DN_CGenTableType_CodeGenEnum,
Dqn_CGenTableType_Count, DN_CGenTableType_Count,
}; };
enum Dqn_CGenTableRowTagType enum DN_CGenTableRowTagType
{ {
Dqn_CGenTableRowTagType_Nil, DN_CGenTableRowTagType_Nil,
Dqn_CGenTableRowTagType_CommentDivider, DN_CGenTableRowTagType_CommentDivider,
Dqn_CGenTableRowTagType_EmptyLine, DN_CGenTableRowTagType_EmptyLine,
}; };
enum Dqn_CGenTableRowTagCommentDivider enum DN_CGenTableRowTagCommentDivider
{ {
Dqn_CGenTableRowTagCommentDivider_Nil, DN_CGenTableRowTagCommentDivider_Nil,
Dqn_CGenTableRowTagCommentDivider_Label, DN_CGenTableRowTagCommentDivider_Label,
}; };
enum Dqn_CGenTableHeaderType enum DN_CGenTableHeaderType
{ {
Dqn_CGenTableHeaderType_Name, DN_CGenTableHeaderType_Name,
Dqn_CGenTableHeaderType_Table, DN_CGenTableHeaderType_Table,
Dqn_CGenTableHeaderType_CppType, DN_CGenTableHeaderType_CppType,
Dqn_CGenTableHeaderType_CppName, DN_CGenTableHeaderType_CppName,
Dqn_CGenTableHeaderType_CppValue, DN_CGenTableHeaderType_CppValue,
Dqn_CGenTableHeaderType_CppIsPtr, DN_CGenTableHeaderType_CppIsPtr,
Dqn_CGenTableHeaderType_CppOpEquals, DN_CGenTableHeaderType_CppOpEquals,
Dqn_CGenTableHeaderType_CppArraySize, DN_CGenTableHeaderType_CppArraySize,
Dqn_CGenTableHeaderType_CppArraySizeField, DN_CGenTableHeaderType_CppArraySizeField,
Dqn_CGenTableHeaderType_CppLabel, DN_CGenTableHeaderType_CppLabel,
Dqn_CGenTableHeaderType_GenTypeInfo, DN_CGenTableHeaderType_GenTypeInfo,
Dqn_CGenTableHeaderType_GenEnumCount, DN_CGenTableHeaderType_GenEnumCount,
Dqn_CGenTableHeaderType_Count, DN_CGenTableHeaderType_Count,
}; };
struct Dqn_CGenTableHeader struct DN_CGenTableHeader
{ {
MD_String8 name; MD_String8 name;
int longest_string; int longest_string;
}; };
struct Dqn_CGenTableRowTag struct DN_CGenTableRowTag
{ {
Dqn_CGenTableRowTagType type; DN_CGenTableRowTagType type;
MD_String8 comment; MD_String8 comment;
Dqn_CGenTableRowTag *next; DN_CGenTableRowTag *next;
}; };
struct Dqn_CGenTableColumn struct DN_CGenTableColumn
{ {
MD_Node *node; MD_Node *node;
Dqn_Str8 string; DN_Str8 string;
}; };
struct Dqn_CGenTableRow struct DN_CGenTableRow
{ {
Dqn_CGenTableRowTag *first_tag; DN_CGenTableRowTag *first_tag;
Dqn_CGenTableRowTag *last_tag; DN_CGenTableRowTag *last_tag;
Dqn_CGenTableColumn *columns; DN_CGenTableColumn *columns;
}; };
struct Dqn_CGenTable struct DN_CGenTable
{ {
Dqn_CGenTableType type; DN_CGenTableType type;
Dqn_Str8 name; DN_Str8 name;
MD_Map headers_map; MD_Map headers_map;
Dqn_CGenTableHeader *headers; DN_CGenTableHeader *headers;
Dqn_CGenTableRow *rows; DN_CGenTableRow *rows;
size_t column_count; size_t column_count;
size_t row_count; size_t row_count;
MD_Node *node; MD_Node *node;
MD_Node *headers_node; MD_Node *headers_node;
Dqn_usize column_indexes[Dqn_CGenTableHeaderType_Count]; DN_USize column_indexes[DN_CGenTableHeaderType_Count];
Dqn_CGenTable *next; DN_CGenTable *next;
}; };
struct Dqn_CGen struct DN_CGen
{ {
MD_Arena *arena; MD_Arena *arena;
MD_Node *file_list; MD_Node *file_list;
MD_Map table_map; MD_Map table_map;
Dqn_CGenTable *first_table; DN_CGenTable *first_table;
Dqn_CGenTable *last_table; DN_CGenTable *last_table;
Dqn_usize table_counts[Dqn_CGenTableType_Count]; DN_USize table_counts[DN_CGenTableType_Count];
}; };
struct Dqn_CGenMapNodeToEnum struct DN_CGenMapNodeToEnum
{ {
uint32_t enum_val; uint32_t enum_val;
Dqn_Str8 node_string; DN_Str8 node_string;
}; };
struct Dqn_CGenLookupTableIterator struct DN_CGenLookupTableIterator
{ {
Dqn_CGenTable *cgen_table; DN_CGenTable *cgen_table;
Dqn_CGenTableRow *cgen_table_row; DN_CGenTableRow *cgen_table_row;
Dqn_CGenTableColumn cgen_table_column[Dqn_CGenTableHeaderType_Count]; DN_CGenTableColumn cgen_table_column[DN_CGenTableHeaderType_Count];
Dqn_CGenTable *table; DN_CGenTable *table;
Dqn_usize row_index; DN_USize row_index;
}; };
struct Dqn_CGenLookupColumnAtHeader struct DN_CGenLookupColumnAtHeader
{ {
Dqn_usize index; DN_USize index;
Dqn_CGenTableHeader header; DN_CGenTableHeader header;
Dqn_CGenTableColumn column; DN_CGenTableColumn column;
}; };
enum Dqn_CGenEmit enum DN_CGenEmit
{ {
Dqn_CGenEmit_Prototypes = 1 << 0, DN_CGenEmit_Prototypes = 1 << 0,
Dqn_CGenEmit_Implementation = 1 << 1, DN_CGenEmit_Implementation = 1 << 1,
}; };
// NOTE: [$CGEN] Dqn_CGen ////////////////////////////////////////////////////////////////////////// // NOTE: [$CGEN] DN_CGen //////////////////////////////////////////////////////////////////////////
#define Dqn_CGen_MDToDqnStr8(str8) Dqn_Str8_Init((str8).str, (str8).size) #define DN_CGen_MDToDNStr8(str8) DN_Str8_Init((str8).str, (str8).size)
#define Dqn_CGen_DqnToMDStr8(str8) {DQN_CAST(MD_u8 *)(str8).data, (str8).size} #define DN_CGen_DNToMDStr8(str8) {DN_CAST(MD_u8 *)(str8).data, (str8).size}
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_API Dqn_Str8 Dqn_CGen_TableHeaderTypeToDeclStr8 (Dqn_CGenTableHeaderType type); DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8 (DN_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, ...); 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_API Dqn_usize Dqn_CGen_NodeChildrenCount (MD_Node const *node); DN_API DN_USize DN_CGen_NodeChildrenCount (MD_Node const *node);
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, ...);
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);
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_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);
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);
#endif // DQN_CGEN_H #endif // DN_CGEN_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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<Dqn_Str8> prefix_flags;
Dqn_Slice<Dqn_Str8> 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<Dqn_CPPBuildCompileFile> compile_files;
Dqn_Slice<Dqn_Str8> compile_flags;
Dqn_Slice<Dqn_Str8> include_dirs;
Dqn_Slice<Dqn_Str8> 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_Str8> 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_Str8> 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<Dqn_Str8> result = {};
Dqn_Slice<Dqn_CPPBuildCompileFile> dirtied_compile_files = build_context.compile_files;
if (mode == Dqn_CPPBuildMode_CacheBuild) {
dirtied_compile_files = Dqn_Slice_Alloc<Dqn_CPPBuildCompileFile>(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<Dqn_Str8> 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<Dqn_Str8> 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<Dqn_Str8> 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

View File

@ -18,58 +18,61 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$ASAN] Dqn_Asan ////////////////////////////////////////////////////////////////////////// /// // NOTE: [$ASAN] DN_Asan ////////////////////////////////////////////////////////////////////////// ///
DQN_API void Dqn_ASAN_PoisonMemoryRegion(void const volatile *ptr, Dqn_usize size) DN_API void DN_ASAN_PoisonMemoryRegion(void const volatile *ptr, DN_USize size)
{ {
if (!ptr || !size) if (!ptr || !size)
return; 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); __asan_poison_memory_region(ptr, size);
if (DQN_ASAN_VET_POISON) { if (DN_ASAN_VET_POISON) {
DQN_HARD_ASSERT(__asan_address_is_poisoned(ptr)); DN_HARD_ASSERT(__asan_address_is_poisoned(ptr));
DQN_HARD_ASSERT(__asan_address_is_poisoned((char *)ptr + (size - 1))); DN_HARD_ASSERT(__asan_address_is_poisoned((char *)ptr + (size - 1)));
} }
#else #else
(void)ptr; (void)size; (void)ptr; (void)size;
#endif #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) if (!ptr || !size)
return; 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); __asan_unpoison_memory_region(ptr, size);
if (DQN_ASAN_VET_POISON) { if (DN_ASAN_VET_POISON) {
DQN_HARD_ASSERT(__asan_region_is_poisoned((void *)ptr, size) == 0); DN_HARD_ASSERT(__asan_region_is_poisoned((void *)ptr, size) == 0);
} }
#else #else
(void)ptr; (void)size; (void)ptr; (void)size;
#endif #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 = {}; DN_StackTraceWalkResult result = {};
#if defined(DQN_OS_WIN32) #if defined(DN_OS_WIN32)
if (!arena) if (!arena)
return result; return result;
static Dqn_TicketMutex mutex = {}; static DN_TicketMutex mutex = {};
Dqn_TicketMutex_Begin(&mutex); DN_TicketMutex_Begin(&mutex);
HANDLE thread = GetCurrentThread(); HANDLE thread = GetCurrentThread();
result.process = GetCurrentProcess(); result.process = GetCurrentProcess();
if (!g_dqn_library->win32_sym_initialised) { if (!g_dn_core->win32_sym_initialised) {
g_dqn_library->win32_sym_initialised = true; g_dn_core->win32_sym_initialised = true;
SymSetOptions(SYMOPT_LOAD_LINES); SymSetOptions(SYMOPT_LOAD_LINES);
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) { if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); DN_TLSTMem tmem = DN_TLS_TMem(arena);
Dqn_WinError error = Dqn_Win_LastError(tmem.arena); DN_WinError error = DN_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_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.Offset = context.Rsp;
frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Mode = AddrModeFlat;
Dqn_FArray<uint64_t, 256> raw_frames = {}; DN_FArray<uint64_t, 256> raw_frames = {};
while (raw_frames.size < limit) { while (raw_frames.size < limit) {
if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64, if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64,
result.process, 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. // NOTE: It might be useful one day to use frame.AddrReturn.Offset.
// If AddrPC.Offset == AddrReturn.Offset then we can detect recursion. // 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.base_addr = DN_Arena_NewArray(arena, uint64_t, raw_frames.size, DN_ZeroMem_No);
result.size = DQN_CAST(uint16_t)raw_frames.size; result.size = DN_CAST(uint16_t)raw_frames.size;
DQN_MEMCPY(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0])); DN_MEMCPY(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0]));
#else #else
(void)limit; (void)arena; (void)limit; (void)arena;
#endif #endif
return result; 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); DN_StackTraceWalkResult result = {};
Dqn_StackTraceWalkResult walk_result = Dqn_StackTrace_Walk(tmem.arena, limit); #if defined(DN_OS_WIN32)
Dqn_Str8 result = Dqn_StackTrace_WalkResultStr8CRT(&walk_result, skip); 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; 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; 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]; raw_frame.base_addr = walk->base_addr[index];
Dqn_StackTraceFrame frame = Dqn_StackTrace_RawFrameToFrame(builder->arena, raw_frame); DN_StackTraceFrame frame = DN_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_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 = {}; DN_Arena arena = {};
arena.flags |= Dqn_ArenaFlag_NoAllocTrack; arena.flags |= DN_ArenaFlags_NoAllocTrack;
Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(&arena, limit); 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; 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; bool result = false;
if (!it || !walk || !walk->base_addr || !walk->process) if (!it || !walk || !walk->base_addr || !walk->process)
@ -161,55 +266,55 @@ DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator *
return result; 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) if (!walk || !arena)
return result; return result;
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); DN_TLSTMem tmem = DN_TLS_TMem(arena);
Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena); DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena);
Dqn_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip); DN_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip);
result = Dqn_Str8Builder_Build(&builder, arena); result = DN_Str8Builder_Build(&builder, arena);
return result; 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) if (!walk)
return result; return result;
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena); DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena);
Dqn_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip); DN_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip);
result = Dqn_Str8Builder_BuildCRT(&builder); result = DN_Str8Builder_BuildCRT(&builder);
return result; return result;
} }
DQN_API Dqn_Slice<Dqn_StackTraceFrame> Dqn_StackTrace_GetFrames(Dqn_Arena *arena, uint16_t limit) DN_API DN_Slice<DN_StackTraceFrame> DN_StackTrace_GetFrames(DN_Arena *arena, uint16_t limit)
{ {
Dqn_Slice<Dqn_StackTraceFrame> result = {}; DN_Slice<DN_StackTraceFrame> result = {};
if (!arena) if (!arena)
return result; return result;
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); DN_TLSTMem tmem = DN_TLS_TMem(arena);
Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(tmem.arena, limit); DN_StackTraceWalkResult walk = DN_StackTrace_Walk(tmem.arena, limit);
if (!walk.size) if (!walk.size)
return result; return result;
Dqn_usize slice_index = 0; DN_USize slice_index = 0;
result = Dqn_Slice_Alloc<Dqn_StackTraceFrame>(arena, walk.size, Dqn_ZeroMem_No); result = DN_Slice_Alloc<DN_StackTraceFrame>(arena, walk.size, DN_ZeroMem_No);
for (Dqn_StackTraceWalkResultIterator it = {}; Dqn_StackTrace_WalkResultIterate(&it, &walk); ) { for (DN_StackTraceWalkResultIterator it = {}; DN_StackTrace_WalkResultIterate(&it, &walk); ) {
result.data[slice_index++] = Dqn_StackTrace_RawFrameToFrame(arena, it.raw_frame); result.data[slice_index++] = DN_StackTrace_RawFrameToFrame(arena, it.raw_frame);
} }
return result; 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 ///////////////////////////////////////////////////////////////////// // NOTE: Get line+filename /////////////////////////////////////////////////////////////////////
// TODO: Why does zero-initialising this with `line = {};` cause // 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 ///////////////////////////////////////////////////////////////////// // NOTE: Get function name /////////////////////////////////////////////////////////////////////
alignas(SYMBOL_INFOW) char buffer[sizeof(SYMBOL_INFOW) + (MAX_SYM_NAME * sizeof(wchar_t))] = {}; 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->SizeOfStruct = sizeof(*symbol);
symbol->MaxNameLen = sizeof(buffer) - 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 ////////////////////////////////////////////////////////////////////// // NOTE: Construct result //////////////////////////////////////////////////////////////////////
Dqn_Str16 file_name16 = Dqn_Str16{line.FileName, Dqn_CStr16_Size(line.FileName)}; DN_Str16 file_name16 = DN_Str16{line.FileName, DN_CStr16_Size(line.FileName)};
Dqn_Str16 function_name16 = Dqn_Str16{symbol->Name, symbol->NameLen}; DN_Str16 function_name16 = DN_Str16{symbol->Name, symbol->NameLen};
Dqn_StackTraceFrame result = {}; DN_StackTraceFrame result = {};
result.address = raw_frame.base_addr; result.address = raw_frame.base_addr;
result.line_number = line.LineNumber; result.line_number = line.LineNumber;
result.file_name = Dqn_Win_Str16ToStr8(arena, file_name16); result.file_name = DN_Win_Str16ToStr8(arena, file_name16);
result.function_name = Dqn_Win_Str16ToStr8(arena, function_name16); result.function_name = DN_Win_Str16ToStr8(arena, function_name16);
if (!Dqn_Str8_HasData(result.function_name)) if (!DN_Str8_HasData(result.function_name))
result.function_name = DQN_STR8("<unknown function>"); result.function_name = DN_STR8("<unknown function>");
if (!Dqn_Str8_HasData(result.file_name)) if (!DN_Str8_HasData(result.file_name))
result.file_name = DQN_STR8("<unknown file>"); result.file_name = DN_STR8("<unknown file>");
#else #else
Dqn_StackTraceFrame result = {}; DN_StackTraceFrame result = {};
#endif #endif
return result; 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); DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
Dqn_Slice<Dqn_StackTraceFrame> stack_trace = Dqn_StackTrace_GetFrames(tmem.arena, limit); DN_Slice<DN_StackTraceFrame> stack_trace = DN_StackTrace_GetFrames(tmem.arena, limit);
for (Dqn_StackTraceFrame &frame : stack_trace) for (DN_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_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(); HANDLE process = GetCurrentProcess();
SymRefreshModuleList(process); SymRefreshModuleList(process);
#endif #endif
} }
// NOTE: [$DEBG] Dqn_Debug ///////////////////////////////////////////////////////////////////////// // NOTE: [$DEBG] DN_Debug /////////////////////////////////////////////////////////////////////////
#if defined(DQN_LEAK_TRACKING) #if defined(DN_LEAK_TRACKING)
DQN_API void Dqn_Debug_TrackAlloc(void *ptr, Dqn_usize size, bool leak_permitted) DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
{ {
if (!ptr) if (!ptr)
return; return;
Dqn_TicketMutex_Begin(&g_dqn_library->alloc_table_mutex); DN_TicketMutex_Begin(&g_dn_core->alloc_table_mutex);
DQN_DEFER { DN_DEFER {
Dqn_TicketMutex_End(&g_dqn_library->alloc_table_mutex); 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. // 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 // TODO: Add API for always making the item but exposing a var to indicate if the item was newly created or it
// already existed. // already existed.
Dqn_Str8 stack_trace = Dqn_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/); DN_Str8 stack_trace = DN_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/);
Dqn_DSMap<Dqn_DebugAlloc> *alloc_table = &g_dqn_library->alloc_table; DN_DSMap<DN_DebugAlloc> *alloc_table = &g_dn_core->alloc_table;
Dqn_DSMapResult<Dqn_DebugAlloc> alloc_entry = Dqn_DSMap_MakeKeyU64(alloc_table, DQN_CAST(uint64_t) ptr); DN_DSMapResult<DN_DebugAlloc> alloc_entry = DN_DSMap_MakeKeyU64(alloc_table, DN_CAST(uint64_t) ptr);
Dqn_DebugAlloc *alloc = alloc_entry.value; DN_DebugAlloc *alloc = alloc_entry.value;
if (alloc_entry.found) { if (alloc_entry.found) {
if ((alloc->flags & Dqn_DebugAllocFlag_Freed) == 0) { if ((alloc->flags & DN_DebugAllocFlag_Freed) == 0) {
Dqn_Str8 alloc_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, alloc->size, Dqn_U64ByteSizeType_Auto); DN_Str8 alloc_size = DN_U64ToByteSizeStr8(alloc_table->arena, alloc->size, DN_U64ByteSizeType_Auto);
Dqn_Str8 new_alloc_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, size, Dqn_U64ByteSizeType_Auto); DN_Str8 new_alloc_size = DN_U64ToByteSizeStr8(alloc_table->arena, size, DN_U64ByteSizeType_Auto);
DQN_HARD_ASSERTF( DN_HARD_ASSERTF(
alloc->flags & Dqn_DebugAllocFlag_Freed, alloc->flags & DN_DebugAllocFlag_Freed,
"This pointer is already in the leak tracker, however it has not " "This pointer is already in the leak tracker, however it has not "
"been freed yet. This same pointer is being ask to be tracked " "been freed yet. This same pointer is being ask to be tracked "
"twice in the allocation table, e.g. one if its previous free " "twice in the allocation table, e.g. one if its previous free "
"calls has not being marked freed with an equivalent call to " "calls has not being marked freed with an equivalent call to "
"Dqn_Debug_TrackDealloc()\n" "DN_Debug_TrackDealloc()\n"
"\n" "\n"
"The pointer (0x%p) originally allocated %.*s at:\n" "The pointer (0x%p) originally allocated %.*s at:\n"
"\n" "\n"
@ -310,45 +415,45 @@ DQN_API void Dqn_Debug_TrackAlloc(void *ptr, Dqn_usize size, bool leak_permitted
"\n" "\n"
"%.*s\n" "%.*s\n"
, ,
ptr, DQN_STR_FMT(alloc_size), ptr, DN_STR_FMT(alloc_size),
DQN_STR_FMT(alloc->stack_trace), DN_STR_FMT(alloc->stack_trace),
DQN_STR_FMT(new_alloc_size), DN_STR_FMT(new_alloc_size),
DQN_STR_FMT(stack_trace)); DN_STR_FMT(stack_trace));
} }
// NOTE: Pointer was reused, clean up the prior entry // NOTE: Pointer was reused, clean up the prior entry
free(alloc->stack_trace.data); DN_OS_MemRelease(alloc->stack_trace.data, alloc->stack_trace.size);
free(alloc->freed_stack_trace.data); DN_OS_MemRelease(alloc->freed_stack_trace.data, alloc->freed_stack_trace.size);
*alloc = {}; *alloc = {};
} }
alloc->ptr = ptr; alloc->ptr = ptr;
alloc->size = size; alloc->size = size;
alloc->stack_trace = stack_trace; 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) if (!ptr)
return; return;
Dqn_TicketMutex_Begin(&g_dqn_library->alloc_table_mutex); DN_TicketMutex_Begin(&g_dn_core->alloc_table_mutex);
DQN_DEFER { Dqn_TicketMutex_End(&g_dqn_library->alloc_table_mutex); }; DN_DEFER { DN_TicketMutex_End(&g_dn_core->alloc_table_mutex); };
Dqn_Str8 stack_trace = Dqn_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/); DN_Str8 stack_trace = DN_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/);
Dqn_DSMap<Dqn_DebugAlloc> *alloc_table = &g_dqn_library->alloc_table; DN_DSMap<DN_DebugAlloc> *alloc_table = &g_dn_core->alloc_table;
Dqn_DSMapResult<Dqn_DebugAlloc> alloc_entry = Dqn_DSMap_FindKeyU64(alloc_table, DQN_CAST(uintptr_t) ptr); DN_DSMapResult<DN_DebugAlloc> alloc_entry = DN_DSMap_FindKeyU64(alloc_table, DN_CAST(uintptr_t) ptr);
DQN_HARD_ASSERTF(alloc_entry.found, DN_HARD_ASSERTF(alloc_entry.found,
"Allocated pointer can not be removed as it does not exist in the " "Allocated pointer can not be removed as it does not exist in the "
"allocation table. When this memory was allocated, the pointer was " "allocation table. When this memory was allocated, the pointer was "
"not added to the allocation table [ptr=%p]", "not added to the allocation table [ptr=%p]",
ptr); ptr);
Dqn_DebugAlloc *alloc = alloc_entry.value; DN_DebugAlloc *alloc = alloc_entry.value;
if (alloc->flags & Dqn_DebugAllocFlag_Freed) { if (alloc->flags & DN_DebugAllocFlag_Freed) {
Dqn_Str8 freed_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, alloc->freed_size, Dqn_U64ByteSizeType_Auto); DN_Str8 freed_size = DN_U64ToByteSizeStr8(alloc_table->arena, alloc->freed_size, DN_U64ByteSizeType_Auto);
DQN_HARD_ASSERTF((alloc->flags & Dqn_DebugAllocFlag_Freed) == 0, DN_HARD_ASSERTF((alloc->flags & DN_DebugAllocFlag_Freed) == 0,
"Double free detected, pointer to free was already marked " "Double free detected, pointer to free was already marked "
"as freed. Either the pointer was reallocated but not " "as freed. Either the pointer was reallocated but not "
"traced, or, the pointer was freed twice.\n" "traced, or, the pointer was freed twice.\n"
@ -365,40 +470,40 @@ DQN_API void Dqn_Debug_TrackDealloc(void *ptr)
"\n" "\n"
"%.*s\n" "%.*s\n"
, ,
ptr, DQN_STR_FMT(freed_size), ptr, DN_STR_FMT(freed_size),
DQN_STR_FMT(alloc->stack_trace), DN_STR_FMT(alloc->stack_trace),
DQN_STR_FMT(alloc->freed_stack_trace), DN_STR_FMT(alloc->freed_stack_trace),
DQN_STR_FMT(stack_trace)); DN_STR_FMT(stack_trace));
} }
DQN_ASSERT(!Dqn_Str8_HasData(alloc->freed_stack_trace)); DN_ASSERT(!DN_Str8_HasData(alloc->freed_stack_trace));
alloc->flags |= Dqn_DebugAllocFlag_Freed; alloc->flags |= DN_DebugAllocFlag_Freed;
alloc->freed_stack_trace = stack_trace; 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 leak_count = 0;
uint64_t leaked_bytes = 0; uint64_t leaked_bytes = 0;
for (Dqn_usize index = 1; index < g_dqn_library->alloc_table.occupied; index++) { for (DN_USize index = 1; index < g_dn_core->alloc_table.occupied; index++) {
Dqn_DSMapSlot<Dqn_DebugAlloc> *slot = g_dqn_library->alloc_table.slots + index; DN_DSMapSlot<DN_DebugAlloc> *slot = g_dn_core->alloc_table.slots + index;
Dqn_DebugAlloc *alloc = &slot->value; DN_DebugAlloc *alloc = &slot->value;
bool alloc_leaked = (alloc->flags & Dqn_DebugAllocFlag_Freed) == 0; bool alloc_leaked = (alloc->flags & DN_DebugAllocFlag_Freed) == 0;
bool leak_permitted = (alloc->flags & Dqn_DebugAllocFlag_LeakPermitted); bool leak_permitted = (alloc->flags & DN_DebugAllocFlag_LeakPermitted);
if (alloc_leaked && !leak_permitted) { if (alloc_leaked && !leak_permitted) {
leaked_bytes += alloc->size; leaked_bytes += alloc->size;
leak_count++; leak_count++;
Dqn_Str8 alloc_size = Dqn_U64ToByteSizeStr8(g_dqn_library->alloc_table.arena, alloc->size, Dqn_U64ByteSizeType_Auto); DN_Str8 alloc_size = DN_U64ToByteSizeStr8(g_dn_core->alloc_table.arena, alloc->size, DN_U64ByteSizeType_Auto);
Dqn_Log_WarningF("Pointer (0x%p) leaked %.*s at:\n" DN_Log_WarningF("Pointer (0x%p) leaked %.*s at:\n"
"%.*s", "%.*s",
alloc->ptr, DQN_STR_FMT(alloc_size), alloc->ptr, DN_STR_FMT(alloc_size),
DQN_STR_FMT(alloc->stack_trace)); DN_STR_FMT(alloc->stack_trace));
} }
} }
if (leak_count) { if (leak_count) {
Dqn_Str8 leak_size = Dqn_U64ToByteSizeStr8(&g_dqn_library->arena, leaked_bytes, Dqn_U64ByteSizeType_Auto); DN_Str8 leak_size = DN_U64ToByteSizeStr8(&g_dn_core->arena, leaked_bytes, DN_U64ByteSizeType_Auto);
Dqn_Log_WarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DQN_STR_FMT(leak_size)); 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

View File

@ -17,109 +17,109 @@
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// [$ASAN] Dqn_Asan -- Helpers to manually poison memory using ASAN // [$ASAN] DN_Asan -- Helpers to manually poison memory using ASAN
// [$STKT] Dqn_StackTrace -- Create stack traces // [$STKT] DN_StackTrace -- Create stack traces
// [$DEBG] Dqn_Debug -- Allocation leak tracking API // [$DEBG] DN_Debug -- Allocation leak tracking API
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$ASAN] Dqn_Asan ////////////////////////////////////////////////////////////////////////// // NOTE: [$ASAN] DN_Asan //////////////////////////////////////////////////////////////////////////
#if !defined(DQN_ASAN_POISON) #if !defined(DN_ASAN_POISON)
#define DQN_ASAN_POISON 0 #define DN_ASAN_POISON 0
#endif #endif
#if !defined(DQN_ASAN_VET_POISON) #if !defined(DN_ASAN_VET_POISON)
#define DQN_ASAN_VET_POISON 0 #define DN_ASAN_VET_POISON 0
#endif #endif
#define DQN_ASAN_POISON_ALIGNMENT 8 #define DN_ASAN_POISON_ALIGNMENT 8
#if !defined(DQN_ASAN_POISON_GUARD_SIZE) #if !defined(DN_ASAN_POISON_GUARD_SIZE)
#define DQN_ASAN_POISON_GUARD_SIZE 128 #define DN_ASAN_POISON_GUARD_SIZE 128
#endif #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" "ASAN poison guard size must be a power-of-two and aligned to ASAN's alignment"
"requirement (8 bytes)"); "requirement (8 bytes)");
#if DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) #if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#include <sanitizer/asan_interface.h> #include <sanitizer/asan_interface.h>
#endif #endif
// NOTE: [$STKT] Dqn_StackTrace //////////////////////////////////////////////////////////////////// // NOTE: [$STKT] DN_StackTrace ////////////////////////////////////////////////////////////////////
struct Dqn_StackTraceFrame struct DN_StackTraceFrame
{ {
uint64_t address; uint64_t address;
uint64_t line_number; uint64_t line_number;
Dqn_Str8 file_name; DN_Str8 file_name;
Dqn_Str8 function_name; DN_Str8 function_name;
}; };
struct Dqn_StackTraceRawFrame struct DN_StackTraceRawFrame
{ {
void *process; void *process;
uint64_t base_addr; uint64_t base_addr;
}; };
struct Dqn_StackTraceWalkResult struct DN_StackTraceWalkResult
{ {
void *process; // [Internal] Windows handle to the process void *process; // [Internal] Windows handle to the process
uint64_t *base_addr; // The addresses of the functions in the stack trace 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 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; uint16_t index;
}; };
// NOTE: [$DEBG] Dqn_Debug ///////////////////////////////////////////////////////////////////////// // NOTE: [$DEBG] DN_Debug /////////////////////////////////////////////////////////////////////////
enum Dqn_DebugAllocFlag enum DN_DebugAllocFlag
{ {
Dqn_DebugAllocFlag_Freed = 1 << 0, DN_DebugAllocFlag_Freed = 1 << 0,
Dqn_DebugAllocFlag_LeakPermitted = 1 << 1, DN_DebugAllocFlag_LeakPermitted = 1 << 1,
}; };
struct Dqn_DebugAlloc struct DN_DebugAlloc
{ {
void *ptr; // 8 Pointer to the allocation being tracked void *ptr; // 8 Pointer to the allocation being tracked
Dqn_usize size; // 16 Size of the allocation DN_USize size; // 16 Size of the allocation
Dqn_usize freed_size; // 24 Store the size of the allocation when it is freed DN_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 DN_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 DN_Str8 freed_stack_trace; // 56 Stack trace of where the allocation was freed
uint16_t flags; // 72 Bit flags from `Dqn_DebugAllocFlag` 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 " "We aim to keep the allocation record as light as possible as "
"memory tracking can get expensive. Enforce that there is no " "memory tracking can get expensive. Enforce that there is no "
"unexpected padding."); "unexpected padding.");
// NOTE: [$ASAN] Dqn_Asan ////////////////////////////////////////////////////////////////////////// // NOTE: [$ASAN] DN_Asan //////////////////////////////////////////////////////////////////////////
DQN_API void Dqn_ASAN_PoisonMemoryRegion (void const volatile *ptr, Dqn_usize size); DN_API void DN_ASAN_PoisonMemoryRegion (void const volatile *ptr, DN_USize size);
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);
// NOTE: [$STKT] Dqn_StackTrace //////////////////////////////////////////////////////////////////// // NOTE: [$STKT] DN_StackTrace ////////////////////////////////////////////////////////////////////
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_API Dqn_Str8 Dqn_StackTrace_WalkStr8CRT (uint16_t limit, uint16_t skip); DN_API DN_Str8 DN_StackTrace_WalkStr8CRT (uint16_t limit, uint16_t skip);
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);
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_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_API Dqn_Slice<Dqn_StackTraceFrame> Dqn_StackTrace_GetFrames (Dqn_Arena *arena, uint16_t limit); DN_API DN_Slice<DN_StackTraceFrame> DN_StackTrace_GetFrames (DN_Arena *arena, uint16_t limit);
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);
DQN_API void Dqn_StackTrace_Print (uint16_t limit); DN_API void DN_StackTrace_Print (uint16_t limit);
DQN_API void Dqn_StackTrace_ReloadSymbols (); DN_API void DN_StackTrace_ReloadSymbols ();
// NOTE: [$DEBG] Dqn_Debug ///////////////////////////////////////////////////////////////////////// // NOTE: [$DEBG] DN_Debug /////////////////////////////////////////////////////////////////////////
#if defined(DQN_LEAK_TRACKING) #if defined(DN_LEAK_TRACKING)
DQN_API void Dqn_Debug_TrackAlloc (void *ptr, Dqn_usize size, bool alloc_can_leak); DN_API void DN_Debug_TrackAlloc (void *ptr, DN_USize size, bool alloc_can_leak);
DQN_API void Dqn_Debug_TrackDealloc (void *ptr); DN_API void DN_Debug_TrackDealloc (void *ptr);
DQN_API void Dqn_Debug_DumpLeaks (); DN_API void DN_Debug_DumpLeaks ();
#else #else
#define Dqn_Debug_TrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0) #define DN_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 DN_Debug_TrackDealloc(ptr) do { (void)ptr; } while (0)
#define Dqn_Debug_DumpLeaks() do { } while (0) #define DN_Debug_DumpLeaks() do { } while (0)
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -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 /////////////////////////////////////////////////////////////////////// // NOTE: [$STBS] stb_sprintf ///////////////////////////////////////////////////////////////////////
#define STB_SPRINTF_IMPLEMENTATION #define STB_SPRINTF_IMPLEMENTATION
#ifdef 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. 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)

View File

@ -19,12 +19,12 @@
*/ */
// NOTE: [$OS_H] OS Headers //////////////////////////////////////////////////////////////////////// // 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 <pthread.h> #include <pthread.h>
#include <semaphore.h> #include <semaphore.h>
#endif #endif
#if defined(DQN_OS_UNIX) || defined(DQN_PLATFORM_EMSCRIPTEN) #if defined(DN_OS_UNIX) || defined(DN_PLATFORM_EMSCRIPTEN)
#include <errno.h> // errno #include <errno.h> // errno
#include <fcntl.h> // O_RDONLY ... etc #include <fcntl.h> // O_RDONLY ... etc
#include <sys/ioctl.h> // ioctl #include <sys/ioctl.h> // ioctl
@ -36,31 +36,31 @@
#include <time.h> // clock_gettime, nanosleep #include <time.h> // clock_gettime, nanosleep
#include <unistd.h> // access, gettid, write #include <unistd.h> // access, gettid, write
#if defined(DQN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
#else #else
#include <sys/sendfile.h> // sendfile #include <sys/sendfile.h> // sendfile
#include <linux/fs.h> // FICLONE #include <linux/fs.h> // FICLONE
#endif #endif
#endif #endif
#if defined(DQN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
#include <emscripten/fetch.h> // emscripten_fetch (for Dqn_OSHttpResponse) #include <emscripten/fetch.h> // emscripten_fetch (for DN_OSHttpResponse)
#endif #endif
// NOTE: [$STBS] stb_sprintf /////////////////////////////////////////////////////////////////////// // NOTE: [$STBS] stb_sprintf ///////////////////////////////////////////////////////////////////////
#if defined(DQN_USE_STD_PRINTF) #if defined(DN_USE_STD_PRINTF)
#include <stdio.h> #include <stdio.h>
#define DQN_SPRINTF(...) sprintf(__VA_ARGS__) #define DN_SPRINTF(...) sprintf(__VA_ARGS__)
#define DQN_SNPRINTF(...) snprintf(__VA_ARGS__) #define DN_SNPRINTF(...) snprintf(__VA_ARGS__)
#define DQN_VSPRINTF(...) vsprintf(__VA_ARGS__) #define DN_VSPRINTF(...) vsprintf(__VA_ARGS__)
#define DQN_VSNPRINTF(...) vsnprintf(__VA_ARGS__) #define DN_VSNPRINTF(...) vsnprintf(__VA_ARGS__)
#else #else
#define DQN_SPRINTF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__) #define DN_SPRINTF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__)
#define DQN_SNPRINTF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__) #define DN_SNPRINTF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__)
#define DQN_VSPRINTF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__) #define DN_VSPRINTF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
#define DQN_VSNPRINTF(...) STB_SPRINTF_DECORATE(vsnprintf)(__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. #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 // 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 // ==12072==ERROR: AddressSanitizer: global-buffer-overflow on address
// READ of size 4 at 0x7ff6f442a0d8 thread T0 // 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) #define STBSP__ASAN __declspec(no_sanitize_address)
#endif #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 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); STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period);
#endif // STB_SPRINTF_H_INCLUDE #endif // STB_SPRINTF_H_INCLUDE
#endif // !defined(DQN_USE_STD_PRINTF) #endif // !defined(DN_USE_STD_PRINTF)

View File

@ -18,55 +18,55 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$FNV1] Dqn_FNV1A ///////////////////////////////////////////////////////////////////////// // NOTE: [$FNV1] DN_FNV1A /////////////////////////////////////////////////////////////////////////
// Default values recommended by: http://isthe.com/chongo/tech/comp/fnv/ // 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; auto buffer = DN_CAST(uint8_t const *)bytes;
for (Dqn_usize i = 0; i < size; i++) for (DN_USize i = 0; i < size; i++)
hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/; hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/;
return hash; 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; 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; auto buffer = DN_CAST(uint8_t const *)bytes;
for (Dqn_usize i = 0; i < size; i++) for (DN_USize i = 0; i < size; i++)
hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/; hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/;
return hash; 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; return result;
} }
// NOTE: [$MMUR] Dqn_MurmurHash3 /////////////////////////////////////////////////////////////////// // NOTE: [$MMUR] DN_MurmurHash3 ///////////////////////////////////////////////////////////////////
#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) #if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#define DQN_MMH3_ROTL32(x, y) _rotl(x, y) #define DN_MMH3_ROTL32(x, y) _rotl(x, y)
#define DQN_MMH3_ROTL64(x, y) _rotl64(x, y) #define DN_MMH3_ROTL64(x, y) _rotl64(x, y)
#else #else
#define DQN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y))) #define DN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y)))
#define DQN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y))) #define DN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y)))
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only // Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here // 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]; 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]; 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 // 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 ^= h >> 16;
h *= 0x85ebca6b; h *= 0x85ebca6b;
@ -84,7 +84,7 @@ DQN_FORCE_INLINE uint32_t Dqn_MurmurHash3_FMix32(uint32_t h)
return 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 ^= k >> 33;
k *= 0xff51afd7ed558ccd; k *= 0xff51afd7ed558ccd;
@ -94,7 +94,7 @@ DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_FMix64(uint64_t k)
return 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 uint8_t *data = (const uint8_t *)key;
const int nblocks = len / 4; 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++) 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 *= c1;
k1 = DQN_MMH3_ROTL32(k1, 15); k1 = DN_MMH3_ROTL32(k1, 15);
k1 *= c2; k1 *= c2;
h1 ^= k1; h1 ^= k1;
h1 = DQN_MMH3_ROTL32(h1, 13); h1 = DN_MMH3_ROTL32(h1, 13);
h1 = h1 * 5 + 0xe6546b64; 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: case 1:
k1 ^= tail[0]; k1 ^= tail[0];
k1 *= c1; k1 *= c1;
k1 = DQN_MMH3_ROTL32(k1, 15); k1 = DN_MMH3_ROTL32(k1, 15);
k1 *= c2; k1 *= c2;
h1 ^= k1; h1 ^= k1;
}; };
@ -148,12 +148,12 @@ DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed)
h1 ^= len; h1 ^= len;
h1 = Dqn_MurmurHash3_FMix32(h1); h1 = DN_MurmurHash3_FMix32(h1);
return 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 uint8_t *data = (const uint8_t *)key;
const int nblocks = len / 16; 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++) for (int i = 0; i < nblocks; i++)
{ {
uint64_t k1 = Dqn_MurmurHash3_GetBlock64(blocks, i * 2 + 0); uint64_t k1 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 0);
uint64_t k2 = Dqn_MurmurHash3_GetBlock64(blocks, i * 2 + 1); uint64_t k2 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 1);
k1 *= c1; k1 *= c1;
k1 = DQN_MMH3_ROTL64(k1, 31); k1 = DN_MMH3_ROTL64(k1, 31);
k1 *= c2; k1 *= c2;
h1 ^= k1; h1 ^= k1;
h1 = DQN_MMH3_ROTL64(h1, 27); h1 = DN_MMH3_ROTL64(h1, 27);
h1 += h2; h1 += h2;
h1 = h1 * 5 + 0x52dce729; h1 = h1 * 5 + 0x52dce729;
k2 *= c2; k2 *= c2;
k2 = DQN_MMH3_ROTL64(k2, 33); k2 = DN_MMH3_ROTL64(k2, 33);
k2 *= c1; k2 *= c1;
h2 ^= k2; h2 ^= k2;
h2 = DQN_MMH3_ROTL64(h2, 31); h2 = DN_MMH3_ROTL64(h2, 31);
h2 += h1; h2 += h1;
h2 = h2 * 5 + 0x38495ab5; h2 = h2 * 5 + 0x38495ab5;
} }
@ -218,7 +218,7 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32
case 9: case 9:
k2 ^= ((uint64_t)tail[8]) << 0; k2 ^= ((uint64_t)tail[8]) << 0;
k2 *= c2; k2 *= c2;
k2 = DQN_MMH3_ROTL64(k2, 33); k2 = DN_MMH3_ROTL64(k2, 33);
k2 *= c1; k2 *= c1;
h2 ^= k2; h2 ^= k2;
@ -239,7 +239,7 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32
case 1: case 1:
k1 ^= ((uint64_t)tail[0]) << 0; k1 ^= ((uint64_t)tail[0]) << 0;
k1 *= c1; k1 *= c1;
k1 = DQN_MMH3_ROTL64(k1, 31); k1 = DN_MMH3_ROTL64(k1, 31);
k1 *= c2; k1 *= c2;
h1 ^= k1; h1 ^= k1;
}; };
@ -253,13 +253,13 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32
h1 += h2; h1 += h2;
h2 += h1; h2 += h1;
h1 = Dqn_MurmurHash3_FMix64(h1); h1 = DN_MurmurHash3_FMix64(h1);
h2 = Dqn_MurmurHash3_FMix64(h2); h2 = DN_MurmurHash3_FMix64(h2);
h1 += h2; h1 += h2;
h2 += h1; h2 += h1;
Dqn_MurmurHash3 result = {}; DN_MurmurHash3 result = {};
result.e[0] = h1; result.e[0] = h1;
result.e[1] = h2; result.e[1] = h2;
return result; return result;

View File

@ -17,33 +17,33 @@
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// [$FNV1] Dqn_FNV1A -- Hash(x) -> 32/64bit via FNV1a // [$FNV1] DN_FNV1A -- Hash(x) -> 32/64bit via FNV1a
// [$MMUR] Dqn_MurmurHash3 -- Hash(x) -> 32/128bit via MurmurHash3 // [$MMUR] DN_MurmurHash3 -- Hash(x) -> 32/128bit via MurmurHash3
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$FNV1] Dqn_FNV1A ///////////////////////////////////////////////////////////////////////// // NOTE: [$FNV1] DN_FNV1A /////////////////////////////////////////////////////////////////////////
#if !defined(DQN_FNV1A32_SEED) #if !defined(DN_FNV1A32_SEED)
#define DQN_FNV1A32_SEED 2166136261U #define DN_FNV1A32_SEED 2166136261U
#endif #endif
#if !defined(DQN_FNV1A64_SEED) #if !defined(DN_FNV1A64_SEED)
#define DQN_FNV1A64_SEED 14695981039346656037ULL #define DN_FNV1A64_SEED 14695981039346656037ULL
#endif #endif
// NOTE: [$MMUR] Dqn_MurmurHash3 /////////////////////////////////////////////////////////////////// // NOTE: [$MMUR] DN_MurmurHash3 ///////////////////////////////////////////////////////////////////
struct Dqn_MurmurHash3 { uint64_t e[2]; }; struct DN_MurmurHash3 { uint64_t e[2]; };
// NOTE: [$FNV1] Dqn_FNV1A ///////////////////////////////////////////////////////////////////////// // NOTE: [$FNV1] DN_FNV1A /////////////////////////////////////////////////////////////////////////
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);
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);
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);
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);
// NOTE: [$MMUR] Dqn_MurmurHash3 /////////////////////////////////////////////////////////////////// // NOTE: [$MMUR] DN_MurmurHash3 ///////////////////////////////////////////////////////////////////
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);
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);
#define Dqn_MurmurHash3_x64U128AsU64(key, len, seed) (Dqn_MurmurHash3_x64U128(key, len, seed).e[0]) #define DN_MurmurHash3_x64U128AsU64(key, len, seed) (DN_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]) #define DN_MurmurHash3_x64U128AsU32(key, len, seed) (DN_CAST(uint32_t)DN_MurmurHash3_x64U128(key, len, seed).e[0])

File diff suppressed because it is too large Load Diff

View File

@ -17,55 +17,55 @@
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// [$PCG3] Dqn_PCG32 -- -- RNG from the PCG family // [$PCG3] DN_PCG32 -- -- RNG from the PCG family
// [$JSON] Dqn_JSONBuilder -- DQN_JSON_BUILDER -- Construct json output // [$JSON] DN_JSONBuilder -- DN_JSON_BUILDER -- Construct json output
// [$BHEX] Dqn_Bin -- DQN_BIN -- Binary <-> hex helpers // [$BHEX] DN_Bin -- DN_BIN -- Binary <-> hex helpers
// [$BSEA] Dqn_BinarySearch -- -- Binary search // [$BSEA] DN_BinarySearch -- -- Binary search
// [$BITS] Dqn_Bit -- -- Bitset manipulation // [$BITS] DN_Bit -- -- Bitset manipulation
// [$SAFE] Dqn_Safe -- -- Safe arithmetic, casts, asserts // [$SAFE] DN_Safe -- -- Safe arithmetic, casts, asserts
// [$MISC] Misc -- -- Uncategorised helper functions // [$MISC] Misc -- -- Uncategorised helper functions
// [$DLIB] Dqn_Library -- -- Globally shared runtime data for this library // [$DLIB] DN_Library -- -- Globally shared runtime data for this library
// [$PROF] Dqn_Profiler -- DQN_PROFILER -- Profiler that measures using a timestamp counter // [$PROF] DN_Profiler -- DN_PROFILER -- Profiler that measures using a timestamp counter
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$PCGX] Dqn_PCG32 ///////////////////////////////////////////////////////////////////////// // NOTE: [$PCGX] DN_PCG32 /////////////////////////////////////////////////////////////////////////
struct Dqn_PCG32 { uint64_t state; }; struct DN_PCG32 { uint64_t state; };
#if !defined(DQN_NO_JSON_BUILDER) #if !defined(DN_NO_JSON_BUILDER)
// NOTE: [$JSON] Dqn_JSONBuilder /////////////////////////////////////////////////////////////////// // NOTE: [$JSON] DN_JSONBuilder ///////////////////////////////////////////////////////////////////
enum Dqn_JSONBuilderItem enum DN_JSONBuilderItem
{ {
Dqn_JSONBuilderItem_Empty, DN_JSONBuilderItem_Empty,
Dqn_JSONBuilderItem_OpenContainer, DN_JSONBuilderItem_OpenContainer,
Dqn_JSONBuilderItem_CloseContainer, DN_JSONBuilderItem_CloseContainer,
Dqn_JSONBuilderItem_KeyValue, DN_JSONBuilderItem_KeyValue,
}; };
struct Dqn_JSONBuilder struct DN_JSONBuilder
{ {
bool use_stdout; // When set, ignore the string builder and dump immediately to stdout bool use_stdout; // When set, ignore the string builder and dump immediately to stdout
Dqn_Str8Builder string_builder; // (Internal) DN_Str8Builder string_builder; // (Internal)
int indent_level; // (Internal) int indent_level; // (Internal)
int spaces_per_indent; // The number of spaces per indent level int spaces_per_indent; // The number of spaces per indent level
Dqn_JSONBuilderItem last_item; 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 <typename T> template <typename T>
using Dqn_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs); using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
template <typename T> template <typename T>
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 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 // index is set to the index where the match should be inserted/exist, if
// it were in the array // 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 // 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 // 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: // For example:
// int array[] = {0, 1, 2, 3, 4, 5}; // 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' // 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 // 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 // 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: // For example:
// int array[] = {0, 1, 2, 3, 4, 5}; // 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' // printf("%zu\n", result.index); // Prints index '5'
Dqn_BinarySearchType_UpperBound, DN_BinarySearchType_UpperBound,
}; };
struct Dqn_BinarySearchResult struct DN_BinarySearchResult
{ {
bool found; bool found;
Dqn_usize index; DN_USize index;
}; };
template <typename T> template <typename T>
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 ////////////////////////////////////////////////////////////////////////////// // 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; uint8_t size;
}; };
enum Dqn_U64ByteSizeType enum DN_U64ByteSizeType
{ {
Dqn_U64ByteSizeType_B, DN_U64ByteSizeType_B,
Dqn_U64ByteSizeType_KiB, DN_U64ByteSizeType_KiB,
Dqn_U64ByteSizeType_MiB, DN_U64ByteSizeType_MiB,
Dqn_U64ByteSizeType_GiB, DN_U64ByteSizeType_GiB,
Dqn_U64ByteSizeType_TiB, DN_U64ByteSizeType_TiB,
Dqn_U64ByteSizeType_Count, DN_U64ByteSizeType_Count,
Dqn_U64ByteSizeType_Auto, DN_U64ByteSizeType_Auto,
}; };
struct Dqn_U64ByteSize struct DN_U64ByteSize
{ {
Dqn_U64ByteSizeType type; DN_U64ByteSizeType type;
Dqn_Str8 suffix; // "KiB", "MiB", "GiB" .. e.t.c DN_Str8 suffix; // "KiB", "MiB", "GiB" .. e.t.c
Dqn_f64 bytes; DN_F64 bytes;
}; };
typedef uint32_t Dqn_U64AgeUnit; typedef uint32_t DN_U64AgeUnit;
enum Dqn_U64AgeUnit_ enum DN_U64AgeUnit_
{ {
Dqn_U64AgeUnit_Sec = 1 << 0, DN_U64AgeUnit_Sec = 1 << 0,
Dqn_U64AgeUnit_Min = 1 << 1, DN_U64AgeUnit_Min = 1 << 1,
Dqn_U64AgeUnit_Hr = 1 << 2, DN_U64AgeUnit_Hr = 1 << 2,
Dqn_U64AgeUnit_Day = 1 << 3, DN_U64AgeUnit_Day = 1 << 3,
Dqn_U64AgeUnit_Week = 1 << 4, DN_U64AgeUnit_Week = 1 << 4,
Dqn_U64AgeUnit_Year = 1 << 5, DN_U64AgeUnit_Year = 1 << 5,
Dqn_U64AgeUnit_HMS = Dqn_U64AgeUnit_Sec | Dqn_U64AgeUnit_Min | Dqn_U64AgeUnit_Hr, DN_U64AgeUnit_HMS = DN_U64AgeUnit_Sec | DN_U64AgeUnit_Min | DN_U64AgeUnit_Hr,
Dqn_U64AgeUnit_All = Dqn_U64AgeUnit_HMS | Dqn_U64AgeUnit_Day | Dqn_U64AgeUnit_Week | Dqn_U64AgeUnit_Year, 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*/]; char data[2 /*0x*/ + 16 /*hex*/ + 1 /*null-terminator*/];
uint8_t size; uint8_t size;
}; };
enum Dqn_U64HexStr8Flags typedef uint32_t DN_U64HexStr8Flags;
enum DN_U64HexStr8Flags_
{ {
Dqn_HexU64Str8Flags_Nil = 0, DN_HexU64Str8Flags_Nil = 0,
Dqn_HexU64Str8Flags_0xPrefix = 1 << 0, /// Add the '0x' prefix from the string DN_HexU64Str8Flags_0xPrefix = 1 << 0, /// Add the '0x' prefix from the string
Dqn_HexU64Str8Flags_UppercaseHex = 1 << 1, /// Use uppercase ascii characters for hex DN_HexU64Str8Flags_UppercaseHex = 1 << 1, /// Use uppercase ascii characters for hex
}; };
#if !defined(DQN_NO_PROFILER) #if !defined(DN_NO_PROFILER)
// NOTE: [$PROF] Dqn_Profiler ////////////////////////////////////////////////////////////////////// // NOTE: [$PROF] DN_Profiler //////////////////////////////////////////////////////////////////////
#if !defined(DQN_PROFILER_ANCHOR_BUFFER_SIZE) #if !defined(DN_PROFILER_ANCHOR_BUFFER_SIZE)
#define DQN_PROFILER_ANCHOR_BUFFER_SIZE 128 #define DN_PROFILER_ANCHOR_BUFFER_SIZE 256
#endif #endif
struct Dqn_ProfilerAnchor struct DN_ProfilerAnchor
{ {
// Inclusive refers to the time spent to complete the function call // Inclusive refers to the time spent to complete the function call
// including all children functions. // including all children functions.
@ -168,10 +169,10 @@ struct Dqn_ProfilerAnchor
uint64_t tsc_inclusive; uint64_t tsc_inclusive;
uint64_t tsc_exclusive; uint64_t tsc_exclusive;
uint16_t hit_count; uint16_t hit_count;
Dqn_Str8 name; DN_Str8 name;
}; };
struct Dqn_ProfilerZone struct DN_ProfilerZone
{ {
uint16_t anchor_index; uint16_t anchor_index;
uint64_t begin_tsc; uint64_t begin_tsc;
@ -180,332 +181,344 @@ struct Dqn_ProfilerZone
}; };
#if defined(__cplusplus) #if defined(__cplusplus)
struct Dqn_ProfilerZoneScope struct DN_ProfilerZoneScope
{ {
Dqn_ProfilerZoneScope(Dqn_Str8 name, uint16_t anchor_index); DN_ProfilerZoneScope(DN_Str8 name, uint16_t anchor_index);
~Dqn_ProfilerZoneScope(); ~DN_ProfilerZoneScope();
Dqn_ProfilerZone zone; DN_ProfilerZone zone;
}; };
#define Dqn_Profiler_ZoneScopeAtIndex(name, anchor_index) auto DQN_UNIQUE_NAME(profile_zone_) = Dqn_ProfilerZoneScope(DQN_STR8(name), anchor_index) #define DN_Profiler_ZoneScopeAtIndex(name, anchor_index) auto DN_UNIQUE_NAME(profile_zone_) = DN_ProfilerZoneScope(DN_STR8(name), anchor_index)
#define Dqn_Profiler_ZoneScope(name) Dqn_Profiler_ZoneScopeAtIndex(name, __COUNTER__ + 1) #define DN_Profiler_ZoneScope(name) DN_Profiler_ZoneScopeAtIndex(name, __COUNTER__ + 1)
#endif #endif
#define Dqn_Profiler_ZoneBlockIndex(name, index) \ #define DN_Profiler_ZoneBlockIndex(name, index) \
for (Dqn_ProfilerZone DQN_UNIQUE_NAME(profile_zone__) = Dqn_Profiler_BeginZoneAtIndex(name, index), DQN_UNIQUE_NAME(dummy__) = {}; \ for (DN_ProfilerZone DN_UNIQUE_NAME(profile_zone__) = DN_Profiler_BeginZoneAtIndex(name, index), DN_UNIQUE_NAME(dummy__) = {}; \
DQN_UNIQUE_NAME(dummy__).begin_tsc == 0; \ DN_UNIQUE_NAME(dummy__).begin_tsc == 0; \
Dqn_Profiler_EndZone(DQN_UNIQUE_NAME(profile_zone__)), DQN_UNIQUE_NAME(dummy__).begin_tsc = 1) 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, DN_ProfilerAnchorBuffer_Back,
Dqn_ProfilerAnchorBuffer_Front, DN_ProfilerAnchorBuffer_Front,
}; };
struct Dqn_Profiler struct DN_Profiler
{ {
Dqn_ProfilerAnchor anchors[2][DQN_PROFILER_ANCHOR_BUFFER_SIZE]; DN_ProfilerAnchor anchors[2][DN_PROFILER_ANCHOR_BUFFER_SIZE];
uint8_t active_anchor_buffer; uint8_t active_anchor_buffer;
uint16_t parent_zone; uint16_t parent_zone;
}; };
#endif // !defined(DQN_NO_PROFILER) #endif // !defined(DN_NO_PROFILER)
// NOTE: [$JOBQ] Dqn_JobQueue /////////////////////////////////////////////////////////////////////// // NOTE: [$JOBQ] DN_JobQueue ///////////////////////////////////////////////////////////////////////
typedef void (Dqn_JobQueueFunc)(Dqn_OSThread *thread, void *user_context); typedef void (DN_JobQueueFunc)(DN_OSThread *thread, void *user_context);
struct Dqn_Job struct DN_Job
{ {
Dqn_JobQueueFunc *func; // The function to invoke for the job DN_JobQueueFunc *func; // The function to invoke for the job
void *user_context; // Pointer user can set to use in their `job_func` void *user_context; // Pointer user can set to use in their `job_func`
uint64_t elapsed_tsc; uint64_t elapsed_tsc;
uint16_t user_tag; // Arbitrary value the user can set to identiy the type of `user_context` this job has 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` 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) #if !defined(DN_JOB_QUEUE_SPMC_SIZE)
#define DQN_JOB_QUEUE_SPMC_SIZE 128 #define DN_JOB_QUEUE_SPMC_SIZE 128
#endif #endif
struct Dqn_JobQueueSPMC struct DN_JobQueueSPMC
{ {
Dqn_OSMutex mutex; DN_OSMutex mutex;
Dqn_OSSemaphore thread_wait_for_job_semaphore; DN_OSSemaphore thread_wait_for_job_semaphore;
Dqn_OSSemaphore wait_for_completion_semaphore; DN_OSSemaphore wait_for_completion_semaphore;
uint32_t threads_waiting_for_completion; DN_U32 threads_waiting_for_completion;
Dqn_Job jobs[DQN_JOB_QUEUE_SPMC_SIZE]; DN_Job jobs[DN_JOB_QUEUE_SPMC_SIZE];
Dqn_b32 quit; DN_B32 quit;
uint32_t quit_exit_code; DN_U32 quit_exit_code;
uint32_t volatile read_index; DN_U32 volatile read_index;
uint32_t volatile finish_index; DN_U32 volatile finish_index;
uint32_t volatile write_index; DN_U32 volatile write_index;
Dqn_OSSemaphore complete_queue_write_semaphore; DN_OSSemaphore complete_queue_write_semaphore;
Dqn_Job complete_queue[DQN_JOB_QUEUE_SPMC_SIZE]; DN_Job complete_queue[DN_JOB_QUEUE_SPMC_SIZE];
uint32_t volatile complete_read_index; DN_U32 volatile complete_read_index;
uint32_t volatile complete_write_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 // Book-keeping data for the library and allow customisation of certain features
// provided. // provided.
struct Dqn_Library struct DN_Core
{ {
bool lib_init; // True if the library has been initialised via `Dqn_Library_Init` bool init; // True if the library has been initialised via `DN_Library_Init`
Dqn_TicketMutex lib_mutex; DN_OSMutex init_mutex;
Dqn_Str8 exe_dir; // The directory of the current executable DN_Str8 exe_dir; // The directory of the current executable
Dqn_Arena arena; DN_Arena arena;
Dqn_ChunkPool pool; // Uses 'arena' for malloc-like allocations DN_Pool pool;
Dqn_ArenaCatalog arena_catalog; DN_ArenaCatalog arena_catalog;
bool slow_verification_checks; // Enable expensive library verification checks bool slow_verification_checks; // Enable expensive library verification checks
Dqn_CPUReport cpu_report; DN_CPUReport cpu_report;
Dqn_TLS tls; // Thread local storage state for the main thread. DN_TLS tls; // Thread local storage state for the main thread.
// NOTE: Logging /////////////////////////////////////////////////////////////////////////////// // NOTE: Logging ///////////////////////////////////////////////////////////////////////////////
Dqn_LogProc * log_callback; // Set this pointer to override the logging routine DN_LogProc * log_callback; // Set this pointer to override the logging routine
void * log_user_data; void * log_user_data; // User pointer passed into 'log_callback'
bool log_to_file; // Output logs to file as well as standard out 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... ? DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
Dqn_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time 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 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 ////////////////////////////////////////////////////////////////////////// // NOTE: Leak Tracing //////////////////////////////////////////////////////////////////////////
#if defined(DQN_LEAK_TRACKING) #if defined(DN_LEAK_TRACKING)
Dqn_DSMap<Dqn_DebugAlloc> alloc_table; DN_DSMap<DN_DebugAlloc> alloc_table;
Dqn_TicketMutex alloc_table_mutex; DN_TicketMutex alloc_table_mutex;
Dqn_Arena alloc_table_arena; DN_Arena alloc_table_arena;
#endif #endif
// NOTE: Win32 ///////////////////////////////////////////////////////////////////////////////// // NOTE: Win32 /////////////////////////////////////////////////////////////////////////////////
#if defined(DQN_OS_WIN32) #if defined(DN_OS_WIN32)
LARGE_INTEGER win32_qpc_frequency; LARGE_INTEGER win32_qpc_frequency;
Dqn_TicketMutex win32_bcrypt_rng_mutex; DN_TicketMutex win32_bcrypt_rng_mutex;
void * win32_bcrypt_rng_handle; void * win32_bcrypt_rng_handle;
bool win32_sym_initialised;
#endif #endif
bool win32_sym_initialised;
// NOTE: OS //////////////////////////////////////////////////////////////////////////////////// // NOTE: OS ////////////////////////////////////////////////////////////////////////////////////
uint32_t os_page_size; uint32_t os_page_size;
uint32_t os_alloc_granularity; uint32_t os_alloc_granularity;
// NOTE: Profiler ////////////////////////////////////////////////////////////////////////////// // NOTE: Profiler //////////////////////////////////////////////////////////////////////////////
#if !defined(DQN_NO_PROFILER) #if !defined(DN_NO_PROFILER)
Dqn_Profiler *profiler; DN_Profiler * profiler;
Dqn_Profiler profiler_default_instance; DN_Profiler profiler_default_instance;
#endif #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 ///////////////////////////////////////////////////////////////////////// enum DN_CoreOnInit
DQN_API Dqn_PCG32 Dqn_PCG32_Init (uint64_t seed); {
DQN_API uint32_t Dqn_PCG32_Next (Dqn_PCG32 *rng); DN_CoreOnInit_Nil = 0,
DQN_API uint64_t Dqn_PCG32_Next64 (Dqn_PCG32 *rng); DN_CoreOnInit_LogLibFeatures = 1 << 0,
DQN_API uint32_t Dqn_PCG32_Range (Dqn_PCG32 *rng, uint32_t low, uint32_t high); DN_CoreOnInit_LogCPUFeatures = 1 << 1,
DQN_API Dqn_f32 Dqn_PCG32_NextF32 (Dqn_PCG32 *rng); DN_CoreOnInit_LogAllFeatures = DN_CoreOnInit_LogLibFeatures | DN_CoreOnInit_LogCPUFeatures,
DQN_API Dqn_f64 Dqn_PCG32_NextF64 (Dqn_PCG32 *rng); };
DQN_API void Dqn_PCG32_Advance (Dqn_PCG32 *rng, uint64_t delta);
#if !defined(DQN_NO_JSON_BUILDER) // NOTE: [$PCGX] DN_PCG32 /////////////////////////////////////////////////////////////////////////
// NOTE: [$JSON] Dqn_JSONBuilder /////////////////////////////////////////////////////////////////// DN_API DN_PCG32 DN_PCG32_Init (uint64_t seed);
#define Dqn_JSONBuilder_Object(builder) \ DN_API uint32_t DN_PCG32_Next (DN_PCG32 *rng);
DQN_DEFER_LOOP(Dqn_JSONBuilder_ObjectBegin(builder), \ DN_API uint64_t DN_PCG32_Next64 (DN_PCG32 *rng);
Dqn_JSONBuilder_ObjectEnd(builder)) 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) \ #if !defined(DN_NO_JSON_BUILDER)
DQN_DEFER_LOOP(Dqn_JSONBuilder_ObjectBeginNamed(builder, name), \ // NOTE: [$JSON] DN_JSONBuilder ///////////////////////////////////////////////////////////////////
Dqn_JSONBuilder_ObjectEnd(builder)) #define DN_JSONBuilder_Object(builder) \
DN_DEFER_LOOP(DN_JSONBuilder_ObjectBegin(builder), \
DN_JSONBuilder_ObjectEnd(builder))
#define Dqn_JSONBuilder_Array(builder) \ #define DN_JSONBuilder_ObjectNamed(builder, name) \
DQN_DEFER_LOOP(Dqn_JSONBuilder_ArrayBegin(builder), \ DN_DEFER_LOOP(DN_JSONBuilder_ObjectBeginNamed(builder, name), \
Dqn_JSONBuilder_ArrayEnd(builder)) DN_JSONBuilder_ObjectEnd(builder))
#define Dqn_JSONBuilder_ArrayNamed(builder, name) \ #define DN_JSONBuilder_Array(builder) \
DQN_DEFER_LOOP(Dqn_JSONBuilder_ArrayBeginNamed(builder, name), \ DN_DEFER_LOOP(DN_JSONBuilder_ArrayBegin(builder), \
Dqn_JSONBuilder_ArrayEnd(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); DN_API DN_JSONBuilder DN_JSONBuilder_Init (DN_Arena *arena, int spaces_per_indent);
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_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);
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, ...);
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_API void Dqn_JSONBuilder_ObjectEnd (Dqn_JSONBuilder *builder); DN_API void DN_JSONBuilder_ObjectEnd (DN_JSONBuilder *builder);
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_API void Dqn_JSONBuilder_ArrayEnd (Dqn_JSONBuilder *builder); DN_API void DN_JSONBuilder_ArrayEnd (DN_JSONBuilder *builder);
DQN_API void Dqn_JSONBuilder_Str8Named (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_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_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_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_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);
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);
#define Dqn_JSONBuilder_ObjectBegin(builder) Dqn_JSONBuilder_ObjectBeginNamed(builder, DQN_STR8("")) #define DN_JSONBuilder_ObjectBegin(builder) DN_JSONBuilder_ObjectBeginNamed(builder, DN_STR8(""))
#define Dqn_JSONBuilder_ArrayBegin(builder) Dqn_JSONBuilder_ArrayBeginNamed(builder, DQN_STR8("")) #define DN_JSONBuilder_ArrayBegin(builder) DN_JSONBuilder_ArrayBeginNamed(builder, DN_STR8(""))
#define Dqn_JSONBuilder_Str8(builder, value) Dqn_JSONBuilder_Str8Named(builder, DQN_STR8(""), value) #define DN_JSONBuilder_Str8(builder, value) DN_JSONBuilder_Str8Named(builder, DN_STR8(""), value)
#define Dqn_JSONBuilder_Literal(builder, value) Dqn_JSONBuilder_LiteralNamed(builder, DQN_STR8(""), value) #define DN_JSONBuilder_Literal(builder, value) DN_JSONBuilder_LiteralNamed(builder, DN_STR8(""), value)
#define Dqn_JSONBuilder_U64(builder, value) Dqn_JSONBuilder_U64Named(builder, DQN_STR8(""), value) #define DN_JSONBuilder_U64(builder, value) DN_JSONBuilder_U64Named(builder, DN_STR8(""), value)
#define Dqn_JSONBuilder_I64(builder, value) Dqn_JSONBuilder_I64Named(builder, DQN_STR8(""), value) #define DN_JSONBuilder_I64(builder, value) DN_JSONBuilder_I64Named(builder, DN_STR8(""), value)
#define Dqn_JSONBuilder_F64(builder, value) Dqn_JSONBuilder_F64Named(builder, DQN_STR8(""), value) #define DN_JSONBuilder_F64(builder, value) DN_JSONBuilder_F64Named(builder, DN_STR8(""), value)
#define Dqn_JSONBuilder_Bool(builder, value) Dqn_JSONBuilder_BoolNamed(builder, DQN_STR8(""), value) #define DN_JSONBuilder_Bool(builder, value) DN_JSONBuilder_BoolNamed(builder, DN_STR8(""), value)
#endif // !defined(DQN_NO_JSON_BUILDER) #endif // !defined(DN_NO_JSON_BUILDER)
// NOTE: [$BSEA] Dqn_BinarySearch ////////////////////////////////////////////////////////////////// // NOTE: [$BSEA] DN_BinarySearch //////////////////////////////////////////////////////////////////
template <typename T> bool Dqn_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs); template <typename T> bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
template <typename T> Dqn_BinarySearchResult Dqn_BinarySearch (T const *array, template <typename T> DN_BinarySearchResult DN_BinarySearch (T const *array,
Dqn_usize array_size, DN_USize array_size,
T const &find, T const &find,
Dqn_BinarySearchType type = Dqn_BinarySearchType_Match, DN_BinarySearchType type = DN_BinarySearchType_Match,
Dqn_BinarySearchLessThanProc<T> less_than = Dqn_BinarySearch_DefaultLessThan); DN_BinarySearchLessThanProc<T> less_than = DN_BinarySearch_DefaultLessThan);
// NOTE: [$QSOR] Dqn_QSort ///////////////////////////////////////////////////////////////////////// // NOTE: [$QSOR] DN_QSort /////////////////////////////////////////////////////////////////////////
template <typename T> bool Dqn_QSort_DefaultLessThan(T const &lhs, T const &rhs); template <typename T> bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs);
template <typename T> void Dqn_QSort (T *array, template <typename T> void DN_QSort (T *array,
Dqn_usize array_size, DN_USize array_size,
void *user_context, void *user_context,
Dqn_QSortLessThanProc<T> less_than = Dqn_QSort_DefaultLessThan); DN_QSortLessThanProc<T> less_than = DN_QSort_DefaultLessThan);
// NOTE: [$BITS] Dqn_Bit /////////////////////////////////////////////////////////////////////////// // NOTE: [$BITS] DN_Bit ///////////////////////////////////////////////////////////////////////////
DQN_API void Dqn_Bit_UnsetInplace (Dqn_usize *flags, Dqn_usize bitfield); DN_API void DN_Bit_UnsetInplace (DN_USize *flags, DN_USize 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);
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);
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);
#define Dqn_Bit_ClearNextLSB(value) (value) & ((value) - 1) #define DN_Bit_ClearNextLSB(value) (value) & ((value) - 1)
// NOTE: [$SAFE] Dqn_Safe ////////////////////////////////////////////////////////////////////////// // NOTE: [$SAFE] DN_Safe //////////////////////////////////////////////////////////////////////////
DQN_API int64_t Dqn_Safe_AddI64 (int64_t a, int64_t b); DN_API int64_t DN_Safe_AddI64 (int64_t a, int64_t b);
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);
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);
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);
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);
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);
DQN_API int Dqn_Safe_SaturateCastUSizeToInt (Dqn_usize val); DN_API int DN_Safe_SaturateCastUSizeToInt (DN_USize val);
DQN_API int8_t Dqn_Safe_SaturateCastUSizeToI8 (Dqn_usize val); DN_API int8_t DN_Safe_SaturateCastUSizeToI8 (DN_USize val);
DQN_API int16_t Dqn_Safe_SaturateCastUSizeToI16 (Dqn_usize val); DN_API int16_t DN_Safe_SaturateCastUSizeToI16 (DN_USize val);
DQN_API int32_t Dqn_Safe_SaturateCastUSizeToI32 (Dqn_usize val); DN_API int32_t DN_Safe_SaturateCastUSizeToI32 (DN_USize val);
DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64 (Dqn_usize val); DN_API int64_t DN_Safe_SaturateCastUSizeToI64 (DN_USize val);
DQN_API int Dqn_Safe_SaturateCastU64ToInt (uint64_t val); DN_API int DN_Safe_SaturateCastU64ToInt (uint64_t val);
DQN_API int64_t Dqn_Safe_SaturateCastU64ToI64 (uint64_t val); DN_API int8_t DN_Safe_SaturateCastU8ToI8 (uint64_t val);
DQN_API unsigned int Dqn_Safe_SaturateCastU64ToUInt (uint64_t val); DN_API int16_t DN_Safe_SaturateCastU16ToI16 (uint64_t val);
DQN_API uint8_t Dqn_Safe_SaturateCastU64ToU8 (uint64_t val); DN_API int32_t DN_Safe_SaturateCastU32ToI32 (uint64_t val);
DQN_API uint16_t Dqn_Safe_SaturateCastU64ToU16 (uint64_t val); DN_API int64_t DN_Safe_SaturateCastU64ToI64 (uint64_t val);
DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32 (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); DN_API uint8_t DN_Safe_SaturateCastUSizeToU8 (DN_USize val);
DQN_API uint16_t Dqn_Safe_SaturateCastUSizeToU16 (Dqn_usize val); DN_API uint16_t DN_Safe_SaturateCastUSizeToU16 (DN_USize val);
DQN_API uint32_t Dqn_Safe_SaturateCastUSizeToU32 (Dqn_usize val); DN_API uint32_t DN_Safe_SaturateCastUSizeToU32 (DN_USize val);
DQN_API uint64_t Dqn_Safe_SaturateCastUSizeToU64 (Dqn_usize val); DN_API uint64_t DN_Safe_SaturateCastUSizeToU64 (DN_USize val);
DQN_API int Dqn_Safe_SaturateCastISizeToInt (Dqn_isize val); DN_API int DN_Safe_SaturateCastISizeToInt (DN_ISize val);
DQN_API int8_t Dqn_Safe_SaturateCastISizeToI8 (Dqn_isize val); DN_API int8_t DN_Safe_SaturateCastISizeToI8 (DN_ISize val);
DQN_API int16_t Dqn_Safe_SaturateCastISizeToI16 (Dqn_isize val); DN_API int16_t DN_Safe_SaturateCastISizeToI16 (DN_ISize val);
DQN_API int32_t Dqn_Safe_SaturateCastISizeToI32 (Dqn_isize val); DN_API int32_t DN_Safe_SaturateCastISizeToI32 (DN_ISize val);
DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64 (Dqn_isize val); DN_API int64_t DN_Safe_SaturateCastISizeToI64 (DN_ISize val);
DQN_API unsigned int Dqn_Safe_SaturateCastISizeToUInt (Dqn_isize val); DN_API unsigned int DN_Safe_SaturateCastISizeToUInt (DN_ISize val);
DQN_API uint8_t Dqn_Safe_SaturateCastISizeToU8 (Dqn_isize val); DN_API uint8_t DN_Safe_SaturateCastISizeToU8 (DN_ISize val);
DQN_API uint16_t Dqn_Safe_SaturateCastISizeToU16 (Dqn_isize val); DN_API uint16_t DN_Safe_SaturateCastISizeToU16 (DN_ISize val);
DQN_API uint32_t Dqn_Safe_SaturateCastISizeToU32 (Dqn_isize val); DN_API uint32_t DN_Safe_SaturateCastISizeToU32 (DN_ISize val);
DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64 (Dqn_isize val); DN_API uint64_t DN_Safe_SaturateCastISizeToU64 (DN_ISize val);
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize (int64_t val); DN_API DN_ISize DN_Safe_SaturateCastI64ToISize (int64_t val);
DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8 (int64_t val); DN_API int8_t DN_Safe_SaturateCastI64ToI8 (int64_t val);
DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16 (int64_t val); DN_API int16_t DN_Safe_SaturateCastI64ToI16 (int64_t val);
DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32 (int64_t val); DN_API int32_t DN_Safe_SaturateCastI64ToI32 (int64_t val);
DQN_API unsigned int Dqn_Safe_SaturateCastI64ToUInt (int64_t val); DN_API unsigned int DN_Safe_SaturateCastI64ToUInt (int64_t val);
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToUSize (int64_t val); DN_API DN_ISize DN_Safe_SaturateCastI64ToUSize (int64_t val);
DQN_API uint8_t Dqn_Safe_SaturateCastI64ToU8 (int64_t val); DN_API uint8_t DN_Safe_SaturateCastI64ToU8 (int64_t val);
DQN_API uint16_t Dqn_Safe_SaturateCastI64ToU16 (int64_t val); DN_API uint16_t DN_Safe_SaturateCastI64ToU16 (int64_t val);
DQN_API uint32_t Dqn_Safe_SaturateCastI64ToU32 (int64_t val); DN_API uint32_t DN_Safe_SaturateCastI64ToU32 (int64_t val);
DQN_API uint64_t Dqn_Safe_SaturateCastI64ToU64 (int64_t val); DN_API uint64_t DN_Safe_SaturateCastI64ToU64 (int64_t val);
DQN_API int8_t Dqn_Safe_SaturateCastIntToI8 (int val); DN_API int8_t DN_Safe_SaturateCastIntToI8 (int val);
DQN_API int16_t Dqn_Safe_SaturateCastIntToI16 (int val); DN_API int16_t DN_Safe_SaturateCastIntToI16 (int val);
DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8 (int val); DN_API uint8_t DN_Safe_SaturateCastIntToU8 (int val);
DQN_API uint16_t Dqn_Safe_SaturateCastIntToU16 (int val); DN_API uint16_t DN_Safe_SaturateCastIntToU16 (int val);
DQN_API uint32_t Dqn_Safe_SaturateCastIntToU32 (int val); DN_API uint32_t DN_Safe_SaturateCastIntToU32 (int val);
DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64 (int val); DN_API uint64_t DN_Safe_SaturateCastIntToU64 (int val);
// NOTE: [$MISC] Misc ////////////////////////////////////////////////////////////////////////////// // 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, ...);
DQN_API Dqn_U64Str8 Dqn_U64ToStr8 (uint64_t val, char separator); DN_API DN_U64Str8 DN_U64ToStr8 (uint64_t val, char separator);
DQN_API Dqn_U64ByteSize Dqn_U64ToByteSize (uint64_t bytes, Dqn_U64ByteSizeType type); DN_API DN_U64ByteSize DN_U64ToByteSize (uint64_t bytes, DN_U64ByteSizeType type);
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_API Dqn_Str8 Dqn_U64ByteSizeTypeString (Dqn_U64ByteSizeType type); DN_API DN_Str8 DN_U64ByteSizeTypeString (DN_U64ByteSizeType type);
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);
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); DN_API uint64_t DN_HexToU64 (DN_Str8 hex);
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, DN_U64HexStr8Flags flags);
DQN_API Dqn_U64HexStr8 Dqn_U64ToHexStr8 (uint64_t number, uint32_t 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); DN_API bool DN_BytesToHexPtr (void const *src, DN_USize src_size, char *dest);
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);
#define Dqn_BytesToHex_TLS(...) Dqn_BytesToHex(Dqn_TLS_TopArena(), __VA_ARGS__) #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); DN_API DN_USize DN_HexToBytesPtrUnchecked (DN_Str8 hex, void *dest, DN_USize dest_size);
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);
DQN_API Dqn_Str8 Dqn_HexToBytesUnchecked (Dqn_Arena *arena, Dqn_Str8 hex); DN_API DN_Str8 DN_HexToBytesUnchecked (DN_Arena *arena, DN_Str8 hex);
#define Dqn_HexToBytesUnchecked_TLS(...) Dqn_HexToBytesUnchecked(Dqn_TLS_TopArena(), __VA_ARGS__) #define DN_HexToBytesUnchecked_TLS(...) DN_HexToBytesUnchecked(DN_TLS_TopArena(), __VA_ARGS__)
DQN_API Dqn_Str8 Dqn_HexToBytes (Dqn_Arena *arena, Dqn_Str8 hex); DN_API DN_Str8 DN_HexToBytes (DN_Arena *arena, DN_Str8 hex);
#define Dqn_HexToBytes_TLS(...) Dqn_HexToBytes(Dqn_TLS_TopArena(), __VA_ARGS__) #define DN_HexToBytes_TLS(...) DN_HexToBytes(DN_TLS_TopArena(), __VA_ARGS__)
// NOTE: [$PROF] Dqn_Profiler ////////////////////////////////////////////////////////////////////// // NOTE: [$PROF] DN_Profiler //////////////////////////////////////////////////////////////////////
DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_ReadBuffer (); DN_API DN_ProfilerAnchor * DN_Profiler_ReadBuffer ();
DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_WriteBuffer (); DN_API DN_ProfilerAnchor * DN_Profiler_WriteBuffer ();
#define Dqn_Profiler_BeginZone(name) Dqn_Profiler_BeginZoneAtIndex(DQN_STR8(name), __COUNTER__ + 1) #define DN_Profiler_BeginZone(name) DN_Profiler_BeginZoneAtIndex(DN_STR8(name), __COUNTER__ + 1)
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_API void Dqn_Profiler_EndZone (Dqn_ProfilerZone zone); DN_API void DN_Profiler_EndZone (DN_ProfilerZone zone);
DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_AnchorBuffer (Dqn_ProfilerAnchorBuffer buffer); DN_API DN_ProfilerAnchor * DN_Profiler_AnchorBuffer (DN_ProfilerAnchorBuffer buffer);
DQN_API void Dqn_Profiler_SwapAnchorBuffer (); DN_API void DN_Profiler_SwapAnchorBuffer ();
DQN_API void Dqn_Profiler_Dump (uint64_t tsc_per_second); DN_API void DN_Profiler_Dump (uint64_t tsc_per_second);
// NOTE: [$JOBQ] Dqn_JobQueue /////////////////////////////////////////////////////////////////////// // NOTE: [$JOBQ] DN_JobQueue ///////////////////////////////////////////////////////////////////////
DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit (); DN_API DN_JobQueueSPMC DN_OS_JobQueueSPMCInit ();
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);
DQN_API bool Dqn_OS_JobQueueSPMCAdd (Dqn_JobQueueSPMC *queue, Dqn_Job job); DN_API bool DN_OS_JobQueueSPMCAddArray (DN_JobQueueSPMC *queue, DN_Job *jobs, uint32_t count);
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion (Dqn_JobQueueSPMC *queue); DN_API bool DN_OS_JobQueueSPMCAdd (DN_JobQueueSPMC *queue, DN_Job job);
DQN_API int32_t Dqn_OS_JobQueueSPMCThread (Dqn_OSThread *thread); DN_API void DN_OS_JobQueueSPMCWaitForCompletion (DN_JobQueueSPMC *queue);
DQN_API Dqn_usize Dqn_OS_JobQueueSPMCGetFinishedJobs (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, Dqn_usize jobs_size); 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 /////////////////////////////////////////////////////////////////////////////// // NOTE: 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);
DQN_API void Dqn_Library_SetPointer (Dqn_Library *library); DN_API void DN_Core_BeginFrame ();
#if !defined(DQN_NO_PROFILER) DN_API void DN_Core_SetPointer (DN_Core *core);
DQN_API void Dqn_Library_SetProfiler (Dqn_Profiler *profiler); #if !defined(DN_NO_PROFILER)
DN_API void DN_Core_SetProfiler (DN_Profiler *profiler);
#endif #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);
DQN_API void Dqn_Library_DumpThreadContextArenaStat (Dqn_Str8 file_path); DN_API void DN_Core_DumpThreadContextArenaStat (DN_Str8 file_path);
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_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);
// NOTE: [$BSEA] Dqn_BinarySearch ////////////////////////////////////////////////////////////////// // NOTE: [$BSEA] DN_BinarySearch //////////////////////////////////////////////////////////////////
template <typename T> template <typename T>
bool Dqn_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs) bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs)
{ {
bool result = lhs < rhs; bool result = lhs < rhs;
return result; return result;
} }
template <typename T> template <typename T>
Dqn_BinarySearchResult Dqn_BinarySearch(T const *array, DN_BinarySearchResult DN_BinarySearch(T const *array,
Dqn_usize array_size, DN_USize array_size,
T const &find, T const &find,
Dqn_BinarySearchType type, DN_BinarySearchType type,
Dqn_BinarySearchLessThanProc<T> less_than) DN_BinarySearchLessThanProc<T> less_than)
{ {
Dqn_BinarySearchResult result = {}; DN_BinarySearchResult result = {};
if (!array || array_size <= 0 || !less_than) if (!array || array_size <= 0 || !less_than)
return result; return result;
@ -513,11 +526,11 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array,
T const *first = array; T const *first = array;
T const *last = end; T const *last = end;
while (first != last) { while (first != last) {
Dqn_usize count = last - first; DN_USize count = last - first;
T const *it = first + (count / 2); T const *it = first + (count / 2);
bool advance_first = false; bool advance_first = false;
if (type == Dqn_BinarySearchType_UpperBound) if (type == DN_BinarySearchType_UpperBound)
advance_first = !less_than(find, it[0]); advance_first = !less_than(find, it[0]);
else else
advance_first = less_than(it[0], find); advance_first = less_than(it[0], find);
@ -529,12 +542,12 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array,
} }
switch (type) { switch (type) {
case Dqn_BinarySearchType_Match: { case DN_BinarySearchType_Match: {
result.found = first != end && !less_than(find, *first); result.found = first != end && !less_than(find, *first);
} break; } break;
case Dqn_BinarySearchType_LowerBound: /*FALLTHRU*/ case DN_BinarySearchType_LowerBound: /*FALLTHRU*/
case Dqn_BinarySearchType_UpperBound: { case DN_BinarySearchType_UpperBound: {
result.found = first != end; result.found = first != end;
} break; } break;
} }
@ -543,9 +556,9 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array,
return result; return result;
} }
// NOTE: [$QSOR] Dqn_QSort ///////////////////////////////////////////////////////////////////////// // NOTE: [$QSOR] DN_QSort /////////////////////////////////////////////////////////////////////////
template <typename T> template <typename T>
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; (void)user_context;
bool result = lhs < rhs; bool result = lhs < rhs;
@ -553,19 +566,19 @@ bool Dqn_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context)
} }
template <typename T> template <typename T>
void Dqn_QSort(T *array, Dqn_usize array_size, void *user_context, Dqn_QSortLessThanProc<T> less_than) void DN_QSort(T *array, DN_USize array_size, void *user_context, DN_QSortLessThanProc<T> less_than)
{ {
if (!array || array_size <= 1 || !less_than) if (!array || array_size <= 1 || !less_than)
return; return;
// NOTE: Insertion Sort, under 24->32 is an optimal amount ///////////////////////////////////// // 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) { if (array_size < QSORT_THRESHOLD) {
for (Dqn_usize item_to_insert_index = 1; item_to_insert_index < array_size; item_to_insert_index++) { for (DN_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 index = 0; index < item_to_insert_index; index++) {
if (!less_than(array[index], array[item_to_insert_index], user_context)) { if (!less_than(array[index], array[item_to_insert_index], user_context)) {
T item_to_insert = array[item_to_insert_index]; 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[i] = array[i - 1];
array[index] = item_to_insert; 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 ///////////////////////////////////////// // NOTE: Quick sort, under 24->32 is an optimal amount /////////////////////////////////////////
Dqn_usize last_index = array_size - 1; DN_USize last_index = array_size - 1;
Dqn_usize pivot_index = array_size / 2; DN_USize pivot_index = array_size / 2;
Dqn_usize partition_index = 0; DN_USize partition_index = 0;
Dqn_usize start_index = 0; DN_USize start_index = 0;
// Swap pivot with last index, so pivot is always at the end of the array. // Swap pivot with last index, so pivot is always at the end of the array.
// This makes logic much simpler. // 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; pivot_index = last_index;
// 4^, 8, 7, 5, 2, 3, 6 // 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, |7, 8, 2^, 3, 6*
// 4, 5, 2, |8, 7, ^3, 6* // 4, 5, 2, |8, 7, ^3, 6*
// 4, 5, 2, 3, |7, 8, ^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)) { 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++; partition_index++;
} }
} }
// Move pivot to right of partition // Move pivot to right of partition
// 4, 5, 2, 3, |6, 8, ^7* // 4, 5, 2, 3, |6, 8, ^7*
DQN_SWAP(array[partition_index], array[pivot_index]); DN_SWAP(array[partition_index], array[pivot_index]);
Dqn_QSort(array, partition_index, user_context, less_than); DN_QSort(array, partition_index, user_context, less_than);
// Skip the value at partion index since that is guaranteed to be sorted. // Skip the value at partion index since that is guaranteed to be sorted.
// 4, 5, 2, 3, (x), 8, 7 // 4, 5, 2, 3, (x), 8, 7
Dqn_usize one_after_partition_index = partition_index + 1; DN_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_QSort(array + one_after_partition_index, (array_size - one_after_partition_index), user_context, less_than);
} }

View File

@ -1,19 +1,19 @@
#pragma once #pragma once
#include "dqn.h" #include "dqn.h"
// NOTE: Dqn_JSON ////////////////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON //////////////////////////////////////////////////////////////////////////////////
void *Dqn_JSON_ArenaAllocFunc(void *user_data, size_t count) void *DN_JSON_ArenaAllocFunc(void *user_data, size_t count)
{ {
void *result = NULL; void *result = NULL;
if (!user_data) if (!user_data)
return result; return result;
Dqn_Arena *arena = DQN_CAST(Dqn_Arena*)user_data; DN_Arena *arena = DN_CAST(DN_Arena*)user_data;
result = Dqn_Arena_Alloc(arena, count, alignof(json_value_s), Dqn_ZeroMem_No); result = DN_Arena_Alloc(arena, count, alignof(json_value_s), DN_ZeroMem_No);
return result; 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) { switch (type) {
case json_type_string: { if (size) { *size = sizeof("string") - 1; } return "string"; } 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; bool result = false;
if (lhs && Dqn_Str8_HasData(key)) { if (lhs && DN_Str8_HasData(key)) {
Dqn_Str8 lhs_string = Dqn_Str8_Init(lhs->string, lhs->string_size); DN_Str8 lhs_string = DN_Str8_Init(lhs->string, lhs->string_size);
result = Dqn_Str8_Eq(lhs_string, key); result = DN_Str8_Eq(lhs_string, key);
} }
return result; return result;
} }
// NOTE: Dqn_JSON_It /////////////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_It ///////////////////////////////////////////////////////////////////////////////
Dqn_JSONIt Dqn_JSON_LoadFileToIt(Dqn_Arena *arena, Dqn_Str8 json) DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json)
{ {
json_parse_result_s parse_result = {}; json_parse_result_s parse_result = {};
json_value_ex_s *ex_value = 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.size,
json_parse_flags_allow_location_information, json_parse_flags_allow_location_information,
Dqn_JSON_ArenaAllocFunc, DN_JSON_ArenaAllocFunc,
arena, arena,
&parse_result); &parse_result);
Dqn_JSONIt result = {}; DN_JSONIt result = {};
Dqn_JSON_ItPushValue(&result, &ex_value->value); DN_JSON_ItPushValue(&result, &ex_value->value);
return result; return result;
} }
// NOTE: Dqn_JSON_ItPush/Pop /////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItPush/Pop ///////////////////////////////////////////////////////////////////////
bool Dqn_JSON_ItPushObjElement(Dqn_JSONIt *it, json_object_element_s *element) bool DN_JSON_ItPushObjElement(DN_JSONIt *it, json_object_element_s *element)
{ {
if (!it || !element) if (!it || !element)
return false; return false;
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack)); DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack));
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeObjElement, element}; it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeObjElement, element};
return true; 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) if (!it || !obj)
return false; return false;
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack)); DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack));
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeObj, obj}; it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeObj, obj};
return true; 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) if (!it || !element)
return false; return false;
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack)); DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack));
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeArrayElement, element}; it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeArrayElement, element};
return true; 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) if (!it || !value || json_value_as_array(value) == nullptr)
return false; return false;
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack)); DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack));
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeArray, value}; it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeArray, value};
return true; 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; bool result = false;
if (!it || !value) if (!it || !value)
return result; return result;
if (value->type == json_type_object) { 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) { } else if (value->type == json_type_array) {
result = Dqn_JSON_ItPushArray(it, value); result = DN_JSON_ItPushArray(it, value);
} }
return result; return result;
} }
void Dqn_JSON_ItPop(Dqn_JSONIt *it) void DN_JSON_ItPop(DN_JSONIt *it)
{ {
if (!it) if (!it)
return; return;
DQN_ASSERT(it->stack_count > 0); DN_ASSERT(it->stack_count > 0);
if (it->stack_count > 0) if (it->stack_count > 0)
it->stack_count--; it->stack_count--;
} }
// NOTE: Dqn_JSON_It JSON tree navigation ////////////////////////////////////////////////////////// // NOTE: DN_JSON_It JSON tree navigation //////////////////////////////////////////////////////////
json_value_s *Dqn_JSON_ItPushCurrValue(Dqn_JSONIt *it) json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it)
{ {
json_value_s *result = nullptr; json_value_s *result = nullptr;
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it); DN_JSONItEntry *curr = DN_JSON_ItCurr(it);
if (!curr) if (!curr)
return result; return result;
if (curr->type == Dqn_JSON_ItEntryTypeObjElement) { if (curr->type == DN_JSON_ItEntryTypeObjElement) {
json_object_element_s *element = DQN_CAST(json_object_element_s *) curr->value; json_object_element_s *element = DN_CAST(json_object_element_s *) curr->value;
result = element->value; result = element->value;
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) { } else if (curr->type == DN_JSON_ItEntryTypeArrayElement) {
json_array_element_s *element = DQN_CAST(json_array_element_s *) curr->value; json_array_element_s *element = DN_CAST(json_array_element_s *) curr->value;
result = element->value; result = element->value;
} else { } else {
result = DQN_CAST(json_value_s *) curr->value; result = DN_CAST(json_value_s *) curr->value;
} }
if (result->type == json_type_array) { if (result->type == json_type_array) {
json_array_s *array = json_value_as_array(result); json_array_s *array = json_value_as_array(result);
DQN_ASSERT(array); DN_ASSERT(array);
Dqn_JSON_ItPushArray(it, result); DN_JSON_ItPushArray(it, result);
} else if (result->type == json_type_object) { } else if (result->type == json_type_object) {
json_object_s *obj = json_value_as_object(result); json_object_s *obj = json_value_as_object(result);
DQN_ASSERT(obj); DN_ASSERT(obj);
Dqn_JSON_ItPushObj(it, obj); DN_JSON_ItPushObj(it, obj);
} }
return result; 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) if (!curr)
return false; return false;
json_object_element_s *obj_element = nullptr; json_object_element_s *obj_element = nullptr;
json_array_element_s *array_element = nullptr; json_array_element_s *array_element = nullptr;
if (curr->type == Dqn_JSON_ItEntryTypeObj) { if (curr->type == DN_JSON_ItEntryTypeObj) {
auto *obj = DQN_CAST(json_object_s *) curr->value; auto *obj = DN_CAST(json_object_s *) curr->value;
obj_element = obj->start; obj_element = obj->start;
} else if (curr->type == Dqn_JSON_ItEntryTypeObjElement) { } else if (curr->type == DN_JSON_ItEntryTypeObjElement) {
auto *element = DQN_CAST(json_object_element_s *) curr->value; auto *element = DN_CAST(json_object_element_s *) curr->value;
obj_element = element->next; obj_element = element->next;
Dqn_JSON_ItPop(it); DN_JSON_ItPop(it);
} else if (curr->type == Dqn_JSON_ItEntryTypeArray) { } else if (curr->type == DN_JSON_ItEntryTypeArray) {
auto *value = DQN_CAST(json_value_s *) curr->value; auto *value = DN_CAST(json_value_s *) curr->value;
auto *array = json_value_as_array(value); auto *array = json_value_as_array(value);
array_element = array->start; array_element = array->start;
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) { } else if (curr->type == DN_JSON_ItEntryTypeArrayElement) {
auto *element = DQN_CAST(json_array_element_s *) curr->value; auto *element = DN_CAST(json_array_element_s *) curr->value;
array_element = element->next; array_element = element->next;
Dqn_JSON_ItPop(it); DN_JSON_ItPop(it);
} else { } else {
Dqn_JSON_ItPop(it); DN_JSON_ItPop(it);
} }
if (obj_element) if (obj_element)
Dqn_JSON_ItPushObjElement(it, obj_element); DN_JSON_ItPushObjElement(it, obj_element);
else if (array_element) else if (array_element)
Dqn_JSON_ItPushArrayElement(it, array_element); DN_JSON_ItPushArrayElement(it, array_element);
bool result = obj_element || array_element; bool result = obj_element || array_element;
return result; return result;
} }
// NOTE: Dqn_JSON_ItCurr /////////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItCurr ///////////////////////////////////////////////////////////////////////////
Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it) DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it)
{ {
Dqn_JSONItEntry *result = nullptr; DN_JSONItEntry *result = nullptr;
if (!it || it->stack_count <= 0) if (!it || it->stack_count <= 0)
return result; return result;
@ -194,236 +194,236 @@ Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it)
return result; 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; json_value_s *result = nullptr;
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it); DN_JSONItEntry *curr = DN_JSON_ItCurr(it);
if (!curr) if (!curr)
return result; return result;
if (curr->type == Dqn_JSON_ItEntryTypeObjElement) { if (curr->type == DN_JSON_ItEntryTypeObjElement) {
auto *element = DQN_CAST(json_object_element_s *)curr->value; auto *element = DN_CAST(json_object_element_s *)curr->value;
result = element->value; result = element->value;
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) { } else if (curr->type == DN_JSON_ItEntryTypeArrayElement) {
auto *element = DQN_CAST(json_array_element_s *)curr->value; auto *element = DN_CAST(json_array_element_s *)curr->value;
result = element->value; result = element->value;
} else if (curr->type == Dqn_JSON_ItEntryTypeString || } else if (curr->type == DN_JSON_ItEntryTypeString ||
curr->type == Dqn_JSON_ItEntryTypeNumber || curr->type == DN_JSON_ItEntryTypeNumber ||
curr->type == Dqn_JSON_ItEntryTypeObj || curr->type == DN_JSON_ItEntryTypeObj ||
curr->type == Dqn_JSON_ItEntryTypeArray) curr->type == DN_JSON_ItEntryTypeArray)
{ {
result = DQN_CAST(json_value_s *)curr->value; result = DN_CAST(json_value_s *)curr->value;
} }
return result; 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); DN_JSONItEntry *curr = DN_JSON_ItCurr(it);
auto *result = (curr && curr->type == Dqn_JSON_ItEntryTypeObjElement) auto *result = (curr && curr->type == DN_JSON_ItEntryTypeObjElement)
? DQN_CAST(json_object_element_s *) curr->value ? DN_CAST(json_object_element_s *) curr->value
: nullptr; : nullptr;
return result; return result;
} }
// NOTE: Dqn_JSON_ItValueIs //////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItValueIs ////////////////////////////////////////////////////////////////////////
json_value_s *Dqn_JSON_ItValueIs(Dqn_JSONIt *it, json_type_e type) 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; json_value_s *result = (curr && type == curr->type) ? curr : nullptr;
return result; 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; json_object_s *result = curr ? json_value_as_object(curr) : nullptr;
return result; 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; json_array_s *result = curr ? json_value_as_array(curr) : nullptr;
return result; 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; json_string_s *result = curr ? json_value_as_string(curr) : nullptr;
return result; 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; json_number_s *result = curr ? json_value_as_number(curr) : nullptr;
return result; 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; json_value_s *result = (curr && (curr->type == json_type_true || curr->type == json_type_false)) ? curr : nullptr;
return result; 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; json_value_s *result = (curr && (curr->type == json_type_null)) ? curr : nullptr;
return result; return result;
} }
size_t Dqn_JSON_ItValueArraySize(Dqn_JSONIt *it) size_t DN_JSON_ItValueArraySize(DN_JSONIt *it)
{ {
size_t result = 0; 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; result = curr->length;
return result; return result;
} }
// NOTE: Dqn_JSON_ItKeyValueIs ///////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItKeyValueIs /////////////////////////////////////////////////////////////////////
Dqn_Str8 Dqn_JSON_ItKey(Dqn_JSONIt *it) DN_Str8 DN_JSON_ItKey(DN_JSONIt *it)
{ {
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
Dqn_Str8 result = {}; DN_Str8 result = {};
if (curr) { if (curr) {
result.data = DQN_CAST(char *)curr->name->string; result.data = DN_CAST(char *)curr->name->string;
result.size = curr->name->string_size; result.size = curr->name->string_size;
} }
return result; 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); json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
bool result = Dqn_JSON_String8Cmp(curr->name, key); bool result = DN_JSON_String8Cmp(curr->name, key);
return result; 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_s *result = nullptr;
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
if (curr && Dqn_JSON_String8Cmp(curr->name, key)) if (curr && DN_JSON_String8Cmp(curr->name, key))
result = json_value_as_object(curr->value); result = json_value_as_object(curr->value);
return result; 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_array_s *result = nullptr;
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it); json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
if (curr && Dqn_JSON_String8Cmp(curr->name, key)) if (curr && DN_JSON_String8Cmp(curr->name, key))
result = json_value_as_array(curr->value); result = json_value_as_array(curr->value);
return result; 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; 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); result = json_value_as_string(curr->value);
return result; 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; 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); result = json_value_as_number(curr->value);
return result; 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; 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; result = curr->value->type == json_type_true || curr->value->type == json_type_false ? curr->value : nullptr;
return result; 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; 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; result = curr->value->type == json_type_null ? curr->value : nullptr;
return result; return result;
} }
// NOTE: Dqn_JSON_ItValueTo //////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItValueTo ////////////////////////////////////////////////////////////////////////
Dqn_Str8 Dqn_JSON_ItValueToString(Dqn_JSONIt *it) DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it)
{ {
Dqn_Str8 result = {}; DN_Str8 result = {};
if (json_string_s *curr = Dqn_JSON_ItValueIsString(it)) if (json_string_s *curr = DN_JSON_ItValueIsString(it))
result = Dqn_Str8_Init(curr->string, curr->string_size); result = DN_Str8_Init(curr->string, curr->string_size);
return result; return result;
} }
int64_t Dqn_JSON_ItValueToI64(Dqn_JSONIt *it) int64_t DN_JSON_ItValueToI64(DN_JSONIt *it)
{ {
int64_t result = {}; int64_t result = {};
if (json_number_s *curr = Dqn_JSON_ItValueIsNumber(it)) if (json_number_s *curr = DN_JSON_ItValueIsNumber(it))
result = Dqn_Str8_ToI64(Dqn_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value; result = DN_Str8_ToI64(DN_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value;
return result; return result;
} }
uint64_t Dqn_JSON_ItValueToU64(Dqn_JSONIt *it) uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it)
{ {
uint64_t result = {}; uint64_t result = {};
if (json_number_s *curr = Dqn_JSON_ItValueIsNumber(it)) if (json_number_s *curr = DN_JSON_ItValueIsNumber(it))
result = Dqn_Str8_ToU64(Dqn_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value; result = DN_Str8_ToU64(DN_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value;
return result; return result;
} }
bool Dqn_JSON_ItValueToBool(Dqn_JSONIt *it) bool DN_JSON_ItValueToBool(DN_JSONIt *it)
{ {
bool result = {}; 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; result = curr->type == json_type_true;
return result; 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) if (!it)
return; return;
json_object_element_s const *curr = Dqn_JSON_ItCurrObjElement(it); json_object_element_s const *curr = DN_JSON_ItCurrObjElement(it);
if (!curr) if (!curr)
return; return;
size_t value_type_size = 0; 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; json_string_s const *key = curr->name;
if (it->flags & json_parse_flags_allow_location_information) { if (it->flags & json_parse_flags_allow_location_information) {
json_string_ex_s const *info = DQN_CAST(json_string_ex_s const *)key; json_string_ex_s const *info = DN_CAST(json_string_ex_s const *)key;
Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, DN_Log_TypeFCallSite(DN_LogType_Warning,
call_site, call_site,
"Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]", "Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]",
info->line_no, info->line_no,
info->row_no, info->row_no,
DQN_CAST(int)key->string_size, DN_CAST(int)key->string_size,
key->string, key->string,
DQN_CAST(int)value_type_size, DN_CAST(int)value_type_size,
value_type); value_type);
} else { } else {
Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, DN_Log_TypeFCallSite(DN_LogType_Warning,
call_site, call_site,
"Unknown key-value pair in object [key=%.*s, value=%.*s]", "Unknown key-value pair in object [key=%.*s, value=%.*s]",
DQN_CAST(int)key->string_size, DN_CAST(int)key->string_size,
key->string, key->string,
DQN_CAST(int)value_type_size, DN_CAST(int)value_type_size,
value_type); value_type);
} }
} }

View File

@ -5,85 +5,85 @@
#error Sheredom json.h (github.com/sheredom/json.h) must be included before this file #error Sheredom json.h (github.com/sheredom/json.h) must be included before this file
#endif #endif
// NOTE: Dqn_JSON ////////////////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON //////////////////////////////////////////////////////////////////////////////////
void *Dqn_JSON_ArenaAllocFunc (void *user_data, size_t count); void *DN_JSON_ArenaAllocFunc (void *user_data, size_t count);
char const *Dqn_JSON_TypeEnumCString(json_type_e type, size_t *size); char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size);
bool Dqn_JSON_String8Cmp (json_string_s const *lhs, Dqn_Str8 rhs); bool DN_JSON_String8Cmp (json_string_s const *lhs, DN_Str8 rhs);
// NOTE: Dqn_JSON_It ///////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_It /////////////////////////////////////////////////////////////////////////
enum Dqn_JSONItEntryType enum DN_JSONItEntryType
{ {
Dqn_JSON_ItEntryTypeObjElement, DN_JSON_ItEntryTypeObjElement,
Dqn_JSON_ItEntryTypeObj, DN_JSON_ItEntryTypeObj,
Dqn_JSON_ItEntryTypeArrayElement, DN_JSON_ItEntryTypeArrayElement,
Dqn_JSON_ItEntryTypeArray, DN_JSON_ItEntryTypeArray,
Dqn_JSON_ItEntryTypeString, DN_JSON_ItEntryTypeString,
Dqn_JSON_ItEntryTypeNumber, DN_JSON_ItEntryTypeNumber,
}; };
struct Dqn_JSONItEntry struct DN_JSONItEntry
{ {
Dqn_JSONItEntryType type; DN_JSONItEntryType type;
void *value; void *value;
}; };
struct Dqn_JSONIt struct DN_JSONIt
{ {
Dqn_JSONItEntry stack[128]; DN_JSONItEntry stack[128];
int stack_count; int stack_count;
size_t flags; 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 ///////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItPush/Pop /////////////////////////////////////////////////////////////////
bool Dqn_JSON_ItPushObjElement (Dqn_JSONIt *it, json_object_element_s *element); bool DN_JSON_ItPushObjElement (DN_JSONIt *it, json_object_element_s *element);
bool Dqn_JSON_ItPushObj (Dqn_JSONIt *it, json_object_s *obj); bool DN_JSON_ItPushObj (DN_JSONIt *it, json_object_s *obj);
bool Dqn_JSON_ItPushArrayElement(Dqn_JSONIt *it, json_array_element_s *element); bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element);
bool Dqn_JSON_ItPushArray (Dqn_JSONIt *it, json_value_s *value); bool DN_JSON_ItPushArray (DN_JSONIt *it, json_value_s *value);
bool Dqn_JSON_ItPushValue (Dqn_JSONIt *it, json_value_s *value); bool DN_JSON_ItPushValue (DN_JSONIt *it, json_value_s *value);
void Dqn_JSON_ItPop (Dqn_JSONIt *it); void DN_JSON_ItPop (DN_JSONIt *it);
// NOTE: Dqn_JSON_It tree navigation ///////////////////////////////////////////////////////// // NOTE: DN_JSON_It tree navigation /////////////////////////////////////////////////////////
json_value_s *Dqn_JSON_ItPushCurrValue(Dqn_JSONIt *it); json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it);
bool Dqn_JSON_ItNext(Dqn_JSONIt *it); bool DN_JSON_ItNext(DN_JSONIt *it);
#define Dqn_JSON_ItPushCurrValueIterateThenPop(it) \ #define DN_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) \ for(void *DN_UNIQUE_NAME(ptr) = DN_JSON_ItPushCurrValue(it); DN_UNIQUE_NAME(ptr); DN_JSON_ItPop(it), DN_UNIQUE_NAME(ptr) = nullptr) \
while (Dqn_JSON_ItNext(it)) while (DN_JSON_ItNext(it))
// NOTE: Dqn_JSON_ItCurr ///////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItCurr /////////////////////////////////////////////////////////////////////
Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it); DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it);
json_value_s *Dqn_JSON_ItCurrValue(Dqn_JSONIt *it); json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it);
json_object_element_s *Dqn_JSON_ItCurrObjElement(Dqn_JSONIt *it); json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it);
// NOTE: Dqn_JSON_ItValueIs ////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItValueIs //////////////////////////////////////////////////////////////////
json_value_s *Dqn_JSON_ItValueIs(Dqn_JSONIt *it, json_type_e type); json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type);
json_object_s *Dqn_JSON_ItValueIsObj(Dqn_JSONIt *it); json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it);
json_array_s *Dqn_JSON_ItValueIsArray(Dqn_JSONIt *it); json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it);
json_string_s *Dqn_JSON_ItValueIsString(Dqn_JSONIt *it); json_string_s *DN_JSON_ItValueIsString(DN_JSONIt *it);
json_number_s *Dqn_JSON_ItValueIsNumber(Dqn_JSONIt *it); json_number_s *DN_JSON_ItValueIsNumber(DN_JSONIt *it);
json_value_s *Dqn_JSON_ItValueIsBool(Dqn_JSONIt *it); json_value_s *DN_JSON_ItValueIsBool(DN_JSONIt *it);
json_value_s *Dqn_JSON_ItValueIsNull(Dqn_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 /////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItKeyValueIs ///////////////////////////////////////////////////////////////
Dqn_Str8 Dqn_JSON_ItKey(Dqn_JSONIt *it); DN_Str8 DN_JSON_ItKey(DN_JSONIt *it);
bool Dqn_JSON_ItKeyIs(Dqn_JSONIt *it, Dqn_Str8 key); bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key);
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_array_s *Dqn_JSON_ItKeyValueIsArray(Dqn_JSONIt *it, Dqn_Str8 key); json_array_s *DN_JSON_ItKeyValueIsArray(DN_JSONIt *it, DN_Str8 key);
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_number_s *Dqn_JSON_ItKeyValueIsNumber(Dqn_JSONIt *it, Dqn_Str8 key); json_number_s *DN_JSON_ItKeyValueIsNumber(DN_JSONIt *it, DN_Str8 key);
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_value_s *Dqn_JSON_ItKeyValueIsNull(Dqn_JSONIt *it, Dqn_Str8 key); json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key);
// NOTE: Dqn_JSON_ItValueTo ////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItValueTo //////////////////////////////////////////////////////////////////
Dqn_Str8 Dqn_JSON_ItValueToString(Dqn_JSONIt *it); DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it);
int64_t Dqn_JSON_ItValueToI64(Dqn_JSONIt *it); int64_t DN_JSON_ItValueToI64(DN_JSONIt *it);
uint64_t Dqn_JSON_ItValueToU64(Dqn_JSONIt *it); uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it);
bool Dqn_JSON_ItValueToBool(Dqn_JSONIt *it); bool DN_JSON_ItValueToBool(DN_JSONIt *it);
#define Dqn_JSON_ItErrorUnknownKeyValue(it) Dqn_JSON_ItErrorUnknownKeyValue_(it, DQN_CALL_SITE) #define DN_JSON_ItErrorUnknownKeyValue(it) DN_JSON_ItErrorUnknownKeyValue_(it, DN_CALL_SITE)
void Dqn_JSON_ItErrorUnknownKeyValue_(Dqn_JSONIt *it, Dqn_CallSite call_site); void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site);

File diff suppressed because it is too large Load Diff

View File

@ -17,397 +17,395 @@
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// [$VEC2] Dqn_V2, V2i -- DQN_V2 // [$VEC2] DN_V2F32, V2I32 -- DN_V2
// [$VEC3] Dqn_V3, V3i -- DQN_V3 // [$VEC3] DN_V3F32, V3I32 -- DN_V3
// [$VEC4] Dqn_V4, V4i -- DQN_V4 // [$VEC4] DN_V4F32, V4I32 -- DN_V4
// [$MAT4] Dqn_M4 -- DQN_M4 // [$MAT4] DN_M4 -- DN_M4
// [$M2x3] Dqn_M2x3 -- // [$M2x3] DN_M2x3 --
// [$RECT] Dqn_Rect -- DQN_RECT // [$RECT] DN_Rect -- DN_RECT
// [$MATH] Other -- // [$MATH] Other --
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
DQN_MSVC_WARNING_PUSH DN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
#if !defined(DQN_NO_V2) #if !defined(DN_NO_V2)
// NOTE: [$VEC2] Vector2 /////////////////////////////////////////////////////////////////////////// // NOTE: [$VEC2] Vector2 ///////////////////////////////////////////////////////////////////////////
union Dqn_V2I union DN_V2I32
{ {
struct { int32_t x, y; }; struct { int32_t x, y; };
struct { int32_t w, h; }; struct { int32_t w, h; };
int32_t data[2]; int32_t data[2];
}; };
union Dqn_V2U16 union DN_V2U16
{ {
struct { uint16_t x, y; }; struct { uint16_t x, y; };
struct { uint16_t w, h; }; struct { uint16_t w, h; };
uint16_t data[2]; uint16_t data[2];
}; };
union Dqn_V2 union DN_V2F32
{ {
struct { Dqn_f32 x, y; }; struct { DN_F32 x, y; };
struct { Dqn_f32 w, h; }; struct { DN_F32 w, h; };
Dqn_f32 data[2]; 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 /////////////////////////////////////////////////////////////////////////// // NOTE: [$VEC3] Vector3 ///////////////////////////////////////////////////////////////////////////
union Dqn_V3 union DN_V3F32
{ {
struct { Dqn_f32 x, y, z; }; struct { DN_F32 x, y, z; };
struct { Dqn_f32 r, g, b; }; struct { DN_F32 r, g, b; };
Dqn_f32 data[3]; 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 /////////////////////////////////////////////////////////////////////////// // NOTE: [$VEC4] Vector4 ///////////////////////////////////////////////////////////////////////////
union Dqn_V4 union DN_V4F32
{ {
struct { Dqn_f32 x, y, z, w; }; struct { DN_F32 x, y, z, w; };
struct { Dqn_f32 r, g, b, a; }; struct { DN_F32 r, g, b, a; };
#if !defined(DQN_NO_V3) #if !defined(DN_NO_V3)
Dqn_V3 rgb; DN_V3F32 rgb;
Dqn_V3 xyz; DN_V3F32 xyz;
#endif #endif
Dqn_f32 data[4]; DN_F32 data[4];
}; };
#endif // !defined(DQN_NO_V4) #endif // !defined(DN_NO_V4)
DQN_MSVC_WARNING_POP DN_MSVC_WARNING_POP
#if !defined(DQN_NO_M4) #if !defined(DN_NO_M4)
// NOTE: [$MAT4] Dqn_M4 //////////////////////////////////////////////////////////////////////////// // NOTE: [$MAT4] DN_M4 ////////////////////////////////////////////////////////////////////////////
struct Dqn_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 ////////////////////////////////////////////////////////////////////////// // NOTE: [$M2x3] DN_M2x3 //////////////////////////////////////////////////////////////////////////
union Dqn_M2x3 union DN_M2x3
{ {
Dqn_f32 e[6]; DN_F32 e[6];
Dqn_f32 row[2][3]; DN_F32 row[2][3];
}; };
// NOTE: [$RECT] Dqn_Rect ////////////////////////////////////////////////////////////////////////// // NOTE: [$RECT] DN_Rect //////////////////////////////////////////////////////////////////////////
#if !defined(DQN_NO_RECT) #if !defined(DN_NO_RECT)
#if defined(DQN_NO_V2) #if defined(DN_NO_V2)
#error "Rectangles requires V2, DQN_NO_V2 must not be defined" #error "Rectangles requires V2, DN_NO_V2 must not be defined"
#endif #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, DN_RectCutClip_No,
Dqn_RectCutClip_Yes, DN_RectCutClip_Yes,
}; };
enum Dqn_RectCutSide enum DN_RectCutSide
{ {
Dqn_RectCutSide_Left, DN_RectCutSide_Left,
Dqn_RectCutSide_Right, DN_RectCutSide_Right,
Dqn_RectCutSide_Top, DN_RectCutSide_Top,
Dqn_RectCutSide_Bottom, DN_RectCutSide_Bottom,
}; };
struct Dqn_RectCut struct DN_RectCut
{ {
Dqn_Rect* rect; DN_Rect* rect;
Dqn_RectCutSide side; DN_RectCutSide side;
}; };
#endif // !defined(DQN_NO_RECT) #endif // !defined(DN_NO_RECT)
// NOTE: [$MATH] Other ///////////////////////////////////////////////////////////////////////////// // NOTE: [$MATH] Other /////////////////////////////////////////////////////////////////////////////
// NOTE: API // NOTE: API
struct Dqn_RaycastLineIntersectV2Result struct DN_RaycastLineIntersectV2Result
{ {
bool hit; // True if there was an intersection, false if the lines are parallel 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)` DN_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_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 /////////////////////////////////////////////////////////////////////////// // NOTE: [$VEC2] Vector2 ///////////////////////////////////////////////////////////////////////////
#define Dqn_V2I_Zero DQN_LITERAL(Dqn_V2I){{(int32_t)(0), (int32_t)(0)}} #define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}}
#define Dqn_V2I_One DQN_LITERAL(Dqn_V2I){{(int32_t)(1), (int32_t)(1)}} #define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}}
#define Dqn_V2I_InitNx1(x) DQN_LITERAL(Dqn_V2I){{(int32_t)(x), (int32_t)(x)}} #define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}}
#define Dqn_V2I_InitNx2(x, y) DQN_LITERAL(Dqn_V2I){{(int32_t)(x), (int32_t)(y)}} #define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(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_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}}
DQN_API bool operator!= (Dqn_V2I lhs, Dqn_V2I rhs); DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API bool operator== (Dqn_V2I lhs, Dqn_V2I rhs); DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API bool operator>= (Dqn_V2I lhs, Dqn_V2I rhs); DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API bool operator<= (Dqn_V2I lhs, Dqn_V2I rhs); DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API bool operator< (Dqn_V2I lhs, Dqn_V2I rhs); DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API bool operator> (Dqn_V2I lhs, Dqn_V2I rhs); DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2I operator- (Dqn_V2I lhs, Dqn_V2I rhs); DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2I operator- (Dqn_V2I lhs); DN_API DN_V2I32 operator- (DN_V2I32 lhs);
DQN_API Dqn_V2I operator+ (Dqn_V2I lhs, Dqn_V2I rhs); DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, Dqn_V2I rhs); DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, Dqn_f32 rhs); DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs);
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, int32_t rhs); DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs);
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, Dqn_V2I rhs); DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, Dqn_f32 rhs); DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs);
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, int32_t rhs); DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs);
DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, Dqn_V2I rhs); DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs);
DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, Dqn_f32 rhs); DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs);
DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, int32_t rhs); DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs);
DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, Dqn_V2I rhs); DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs);
DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, Dqn_f32 rhs); DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs);
DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, int32_t rhs); DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs);
DQN_API Dqn_V2I & operator-= (Dqn_V2I& lhs, Dqn_V2I rhs); DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs);
DQN_API Dqn_V2I & operator+= (Dqn_V2I& lhs, Dqn_V2I 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); DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b);
DQN_API Dqn_V2I Dqn_V2I_Max (Dqn_V2I a, Dqn_V2I b); DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b);
DQN_API Dqn_V2I Dqn_V2I_Abs (Dqn_V2I a); 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 DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}}
#define Dqn_V2U16_One DQN_LITERAL(Dqn_V2U16){{(uint16_t)(1), (uint16_t)(1)}} #define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}}
#define Dqn_V2U16_InitNx1(x) DQN_LITERAL(Dqn_V2U16){{(uint16_t)(x), (uint16_t)(x)}} #define DN_V2U16_Init1N(x) DN_LITERAL(DN_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_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}}
DQN_API bool operator!= (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API bool operator== (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API bool operator>= (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API bool operator<= (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API bool operator< (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API bool operator> (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API Dqn_V2U16 operator- (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API Dqn_V2U16 operator+ (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, Dqn_f32 rhs); DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs);
DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, int32_t rhs); DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs);
DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, Dqn_V2U16 rhs); DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs);
DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, Dqn_f32 rhs); DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs);
DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, int32_t rhs); DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs);
DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, Dqn_V2U16 rhs); DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs);
DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, Dqn_f32 rhs); DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs);
DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, int32_t rhs); DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs);
DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, Dqn_V2U16 rhs); DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs);
DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, Dqn_f32 rhs); DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs);
DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, int32_t rhs); DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs);
DQN_API Dqn_V2U16 & operator-= (Dqn_V2U16& lhs, Dqn_V2U16 rhs); DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs);
DQN_API Dqn_V2U16 & operator+= (Dqn_V2U16& lhs, Dqn_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 DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}}
#define Dqn_V2_One DQN_LITERAL(Dqn_V2){{(Dqn_f32)(1), (Dqn_f32)(1)}} #define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}}
#define Dqn_V2_InitNx1(x) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(x), (Dqn_f32)(x)}} #define DN_V2F32_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}}
#define Dqn_V2_InitNx2(x, y) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(x), (Dqn_f32)(y)}} #define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}}
#define Dqn_V2_InitV2I(xy) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(xy).x, (Dqn_f32)(xy).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); DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API bool operator== (Dqn_V2 lhs, Dqn_V2 rhs); DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API bool operator>= (Dqn_V2 lhs, Dqn_V2 rhs); DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API bool operator<= (Dqn_V2 lhs, Dqn_V2 rhs); DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API bool operator< (Dqn_V2 lhs, Dqn_V2 rhs); DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API bool operator> (Dqn_V2 lhs, Dqn_V2 rhs); DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 operator- (Dqn_V2 lhs); DN_API DN_V2F32 operator- (DN_V2F32 lhs);
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_V2 rhs); DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_V2I rhs); DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_f32 rhs); DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs);
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, int32_t rhs); DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs);
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_V2 rhs); DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_V2I rhs); DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_f32 rhs); DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs);
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, int32_t rhs); DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs);
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_V2 rhs); DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_V2I rhs); DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_f32 rhs); DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs);
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, int32_t rhs); DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs);
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_V2 rhs); DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_V2I rhs); DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs);
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_f32 rhs); DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs);
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, int32_t rhs); DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs);
DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_V2 rhs); DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_V2I rhs); DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs);
DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_f32 rhs); DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs);
DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, int32_t rhs); DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs);
DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_V2 rhs); DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_V2I rhs); DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs);
DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_f32 rhs); DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs);
DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, int32_t rhs); DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs);
DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_V2 rhs); DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_V2I rhs); DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs);
DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_f32 rhs); DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs);
DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, int32_t rhs); DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs);
DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_V2 rhs); DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs);
DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_V2I rhs); DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs);
DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_f32 rhs); DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs);
DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, int32_t 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); DN_API DN_V2F32 DN_V2_Min (DN_V2F32 a, DN_V2F32 b);
DQN_API Dqn_V2 Dqn_V2_Max (Dqn_V2 a, Dqn_V2 b); DN_API DN_V2F32 DN_V2_Max (DN_V2F32 a, DN_V2F32 b);
DQN_API Dqn_V2 Dqn_V2_Abs (Dqn_V2 a); DN_API DN_V2F32 DN_V2_Abs (DN_V2F32 a);
DQN_API Dqn_f32 Dqn_V2_Dot (Dqn_V2 a, Dqn_V2 b); DN_API DN_F32 DN_V2_Dot (DN_V2F32 a, DN_V2F32 b);
DQN_API Dqn_f32 Dqn_V2_LengthSq_V2x2 (Dqn_V2 lhs, Dqn_V2 rhs); DN_API DN_F32 DN_V2_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API Dqn_f32 Dqn_V2_Length_V2x2 (Dqn_V2 lhs, Dqn_V2 rhs); DN_API DN_F32 DN_V2_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs);
DQN_API Dqn_f32 Dqn_V2_LengthSq (Dqn_V2 lhs); DN_API DN_F32 DN_V2_LengthSq (DN_V2F32 lhs);
DQN_API Dqn_f32 Dqn_V2_Length (Dqn_V2 lhs); DN_API DN_F32 DN_V2_Length (DN_V2F32 lhs);
DQN_API Dqn_V2 Dqn_V2_Normalise (Dqn_V2 a); DN_API DN_V2F32 DN_V2_Normalise (DN_V2F32 a);
DQN_API Dqn_V2 Dqn_V2_Perpendicular (Dqn_V2 a); DN_API DN_V2F32 DN_V2_Perpendicular (DN_V2F32 a);
DQN_API Dqn_V2 Dqn_V2_Reflect (Dqn_V2 in, Dqn_V2 surface); DN_API DN_V2F32 DN_V2_Reflect (DN_V2F32 in, DN_V2F32 surface);
DQN_API Dqn_f32 Dqn_V2_Area (Dqn_V2 a); DN_API DN_F32 DN_V2_Area (DN_V2F32 a);
#endif // !defined(DQN_NO_V2) #endif // !defined(DN_NO_V2)
#if !defined(DQN_NO_V3) #if !defined(DN_NO_V3)
// NOTE: [$VEC3] Vector3 /////////////////////////////////////////////////////////////////////////// // NOTE: [$VEC3] Vector3 ///////////////////////////////////////////////////////////////////////////
#define Dqn_V3_InitNx1(x) DQN_LITERAL(Dqn_V3){{(Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x)}} #define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}}
#define Dqn_V3_InitNx3(x, y, z) DQN_LITERAL(Dqn_V3){{(Dqn_f32)(x), (Dqn_f32)(y), (Dqn_f32)(z)}} #define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_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_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); DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API bool operator== (Dqn_V3 lhs, Dqn_V3 rhs); DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API bool operator>= (Dqn_V3 lhs, Dqn_V3 rhs); DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API bool operator<= (Dqn_V3 lhs, Dqn_V3 rhs); DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API bool operator< (Dqn_V3 lhs, Dqn_V3 rhs); DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API bool operator> (Dqn_V3 lhs, Dqn_V3 rhs); DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API Dqn_V3 operator- (Dqn_V3 lhs, Dqn_V3 rhs); DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API Dqn_V3 operator- (Dqn_V3 lhs); DN_API DN_V3F32 operator- (DN_V3F32 lhs);
DQN_API Dqn_V3 operator+ (Dqn_V3 lhs, Dqn_V3 rhs); DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, Dqn_V3 rhs); DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, Dqn_f32 rhs); DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs);
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, int32_t rhs); DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs);
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, Dqn_V3 rhs); DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs);
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, Dqn_f32 rhs); DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs);
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, int32_t rhs); DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs);
DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, Dqn_V3 rhs); DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs);
DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, Dqn_f32 rhs); DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs);
DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, int32_t rhs); DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs);
DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, Dqn_V3 rhs); DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs);
DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, Dqn_f32 rhs); DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs);
DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, int32_t rhs); DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs);
DQN_API Dqn_V3 & operator-= (Dqn_V3 &lhs, Dqn_V3 rhs); DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs);
DQN_API Dqn_V3 & operator+= (Dqn_V3 &lhs, Dqn_V3 rhs); DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs);
DQN_API Dqn_f32 Dqn_V3_LengthSq (Dqn_V3 a); DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a);
DQN_API Dqn_f32 Dqn_V3_Length (Dqn_V3 a); DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a);
DQN_API Dqn_V3 Dqn_V3_Normalise (Dqn_V3 a); DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a);
#endif // !defined(DQN_NO_V3) #endif // !defined(DN_NO_V3)
#if !defined(DQN_NO_V4) #if !defined(DN_NO_V4)
// NOTE: [$VEC4] Vector4 /////////////////////////////////////////////////////////////////////////// // 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 DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_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 DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}}
#define Dqn_V4_Init_V3x1_Nx1(xyz, w) DQN_LITERAL(Dqn_V4){{xyz.x, xyz.y, xyz.z, w}} #define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}}
DQN_API bool operator!= (Dqn_V4 lhs, Dqn_V4 rhs); DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs);
DQN_API bool operator== (Dqn_V4 lhs, Dqn_V4 rhs); DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs);
DQN_API bool operator>= (Dqn_V4 lhs, Dqn_V4 rhs); DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs);
DQN_API bool operator<= (Dqn_V4 lhs, Dqn_V4 rhs); DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs);
DQN_API bool operator< (Dqn_V4 lhs, Dqn_V4 rhs); DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs);
DQN_API bool operator> (Dqn_V4 lhs, Dqn_V4 rhs); DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs);
DQN_API Dqn_V4 operator- (Dqn_V4 lhs, Dqn_V4 rhs); DN_API DN_V4F32 operator- (DN_V4F32 lhs);
DQN_API Dqn_V4 operator- (Dqn_V4 lhs); DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs);
DQN_API Dqn_V4 operator+ (Dqn_V4 lhs, Dqn_V4 rhs); DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs);
DQN_API Dqn_V4 operator* (Dqn_V4 lhs, Dqn_V4 rhs); DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs);
DQN_API Dqn_V4 operator* (Dqn_V4 lhs, Dqn_f32 rhs); DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs);
DQN_API Dqn_V4 operator* (Dqn_V4 lhs, int32_t rhs); DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs);
DQN_API Dqn_V4 operator/ (Dqn_V4 lhs, Dqn_f32 rhs); DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs);
DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, Dqn_V4 rhs); DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs);
DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, Dqn_f32 rhs); DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs);
DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, int32_t rhs); DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs);
DQN_API Dqn_V4 & operator-= (Dqn_V4 &lhs, Dqn_V4 rhs); DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs);
DQN_API Dqn_V4 & operator+= (Dqn_V4 &lhs, Dqn_V4 rhs); #endif // !defined(DN_NO_V4)
#endif // !defined(DQN_NO_V4) #if !defined(DN_NO_M4)
#if !defined(DQN_NO_M4) // NOTE: [$MAT4] DN_M4 ////////////////////////////////////////////////////////////////////////////
// NOTE: [$MAT4] Dqn_M4 //////////////////////////////////////////////////////////////////////////// DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b);
DQN_API Dqn_f32 Dqn_V4Dot (Dqn_V4 a, Dqn_V4 b); DN_API DN_M4 DN_M4_Identity ();
DQN_API Dqn_M4 Dqn_M4_Identity (); DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z);
DQN_API Dqn_M4 Dqn_M4_ScaleF (Dqn_f32 x, Dqn_f32 y, Dqn_f32 z); DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz);
DQN_API Dqn_M4 Dqn_M4_Scale (Dqn_V3 xyz); DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z);
DQN_API Dqn_M4 Dqn_M4_TranslateF (Dqn_f32 x, Dqn_f32 y, Dqn_f32 z); DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz);
DQN_API Dqn_M4 Dqn_M4_Translate (Dqn_V3 xyz); DN_API DN_M4 DN_M4_Transpose (DN_M4 mat);
DQN_API Dqn_M4 Dqn_M4_Transpose (Dqn_M4 mat); DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians);
DQN_API Dqn_M4 Dqn_M4_Rotate (Dqn_V3 axis, Dqn_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);
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_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_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); DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs);
DQN_API Dqn_M4 Dqn_M4_Add (Dqn_M4 lhs, Dqn_M4 rhs); DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs);
DQN_API Dqn_M4 Dqn_M4_Sub (Dqn_M4 lhs, Dqn_M4 rhs); DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs);
DQN_API Dqn_M4 Dqn_M4_Mul (Dqn_M4 lhs, Dqn_M4 rhs); DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs);
DQN_API Dqn_M4 Dqn_M4_Div (Dqn_M4 lhs, Dqn_M4 rhs); DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs);
DQN_API Dqn_M4 Dqn_M4_AddF (Dqn_M4 lhs, Dqn_f32 rhs); DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs);
DQN_API Dqn_M4 Dqn_M4_SubF (Dqn_M4 lhs, Dqn_f32 rhs); DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs);
DQN_API Dqn_M4 Dqn_M4_MulF (Dqn_M4 lhs, Dqn_f32 rhs); DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs);
DQN_API Dqn_M4 Dqn_M4_DivF (Dqn_M4 lhs, Dqn_f32 rhs); #if !defined(DN_NO_FSTR8)
#if !defined(DQN_NO_FSTR8) DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat);
DQN_API Dqn_FStr8<256> Dqn_M4_ColumnMajorString (Dqn_M4 mat);
#endif #endif
#endif // !defined(DQN_NO_M4) #endif // !defined(DN_NO_M4)
// NOTE: [$M2x3] Dqn_M2x3 ////////////////////////////////////////////////////////////////////////// // NOTE: [$M2x3] DN_M2x3 //////////////////////////////////////////////////////////////////////////
DQN_API bool operator== (Dqn_M2x3 const &lhs, Dqn_M2x3 const &rhs); DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs);
DQN_API bool operator!= (Dqn_M2x3 const &lhs, Dqn_M2x3 const &rhs); DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs);
DQN_API Dqn_M2x3 Dqn_M2x3_Identity (); DN_API DN_M2x3 DN_M2x3_Identity ();
DQN_API Dqn_M2x3 Dqn_M2x3_Translate (Dqn_V2 offset); DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset);
DQN_API Dqn_M2x3 Dqn_M2x3_Scale (Dqn_V2 scale); DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale);
DQN_API Dqn_M2x3 Dqn_M2x3_Rotate (Dqn_f32 radians); DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians);
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);
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);
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);
#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) DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs);
// NOTE: [$RECT] Dqn_Rect ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect);
#define Dqn_Rect_InitV2x2(pos, size) DQN_LITERAL(Dqn_Rect){(pos), (size)} DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p);
#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 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); DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
DQN_API Dqn_V2 Dqn_Rect_Center (Dqn_Rect rect); DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
DQN_API bool Dqn_Rect_ContainsPoint (Dqn_Rect rect, Dqn_V2 p); DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
DQN_API bool Dqn_Rect_ContainsRect (Dqn_Rect a, Dqn_Rect b); DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
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);
DQN_API Dqn_Rect Dqn_Rect_CutLeftClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip); #define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes)
DQN_API Dqn_Rect Dqn_Rect_CutRightClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip); #define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes)
DQN_API Dqn_Rect Dqn_Rect_CutTopClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip); #define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes)
DQN_API Dqn_Rect Dqn_Rect_CutBottomClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip); #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 DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No)
#define Dqn_Rect_CutRight(rect, amount) Dqn_Rect_CutRightClip(rect, amount, Dqn_RectCutClip_Yes) #define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No)
#define Dqn_Rect_CutTop(rect, amount) Dqn_Rect_CutTopClip(rect, amount, Dqn_RectCutClip_Yes) #define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No)
#define Dqn_Rect_CutBottom(rect, amount) Dqn_Rect_CutBottomClip(rect, amount, Dqn_RectCutClip_Yes) #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) DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip);
#define Dqn_Rect_CutRightNoClip(rect, amount) Dqn_Rect_CutRightClip(rect, amount, Dqn_RectCutClip_No) #define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side}
#define Dqn_Rect_CutTopNoClip(rect, amount) Dqn_Rect_CutTopClip(rect, amount, Dqn_RectCutClip_No) #define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left}
#define Dqn_Rect_CutBottomNoClip(rect, amount) Dqn_Rect_CutBottomClip(rect, amount, Dqn_RectCutClip_No) #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}
DQN_API Dqn_Rect Dqn_RectCut_Cut (Dqn_RectCut rect_cut, Dqn_V2 size, Dqn_RectCutClip clip); #define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom}
#define Dqn_RectCut_Init(rect, side) DQN_LITERAL(Dqn_RectCut){rect, side} #endif // !defined(DN_NO_RECT)
#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)
// NOTE: [$MATH] Other ///////////////////////////////////////////////////////////////////////////// // 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); DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b);
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_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);

View File

@ -19,11 +19,11 @@
*/ */
// NOTE: [$DATE] Date ////////////////////////////////////////////////////////////////////////////// // 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 = {}; DN_OSDateTimeStr8 result = {};
result.hms_size = DQN_CAST(uint8_t) DQN_SNPRINTF(result.hms, result.hms_size = DN_CAST(uint8_t) DN_SNPRINTF(result.hms,
DQN_ARRAY_ICOUNT(result.hms), DN_ARRAY_ICOUNT(result.hms),
"%02hhu%c%02hhu%c%02hhu", "%02hhu%c%02hhu%c%02hhu",
time.hour, time.hour,
hms_separator, hms_separator,
@ -31,8 +31,8 @@ DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8(Dqn_OSDateTime time, char da
hms_separator, hms_separator,
time.seconds); time.seconds);
result.date_size = DQN_CAST(uint8_t) DQN_SNPRINTF(result.date, result.date_size = DN_CAST(uint8_t) DN_SNPRINTF(result.date,
DQN_ARRAY_ICOUNT(result.date), DN_ARRAY_ICOUNT(result.date),
"%hu%c%02hhu%c%02hhu", "%hu%c%02hhu%c%02hhu",
time.year, time.year,
date_separator, date_separator,
@ -40,19 +40,25 @@ DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8(Dqn_OSDateTime time, char da
date_separator, date_separator,
time.day); time.day);
DQN_ASSERT(result.hms_size < DQN_ARRAY_UCOUNT(result.hms)); DN_ASSERT(result.hms_size < DN_ARRAY_UCOUNT(result.hms));
DQN_ASSERT(result.date_size < DQN_ARRAY_UCOUNT(result.date)); DN_ASSERT(result.date_size < DN_ARRAY_UCOUNT(result.date));
return result; 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(); DN_OSDateTime time = DN_OS_DateLocalTimeNow();
Dqn_OSDateTimeStr8 result = Dqn_OS_DateLocalTimeStr8(time, date_separator, hms_separator); DN_OSDateTimeStr8 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator);
return result; 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) if (date.year < 1970)
return false; return false;
@ -70,245 +76,245 @@ DQN_API bool Dqn_OS_DateIsValid(Dqn_OSDateTime date)
} }
// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// // 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) if (!arena)
return result; return result;
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); DN_TLSTMem tmem = DN_TLS_TMem(arena);
Dqn_Str8 exe_path = Dqn_OS_EXEPath(tmem.arena); DN_Str8 exe_path = DN_OS_EXEPath(tmem.arena);
Dqn_Str8 separators[] = {DQN_STR8("/"), DQN_STR8("\\")}; DN_Str8 separators[] = {DN_STR8("/"), DN_STR8("\\")};
Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplitLastArray(exe_path, separators, DQN_ARRAY_UCOUNT(separators)); DN_Str8BinarySplitResult split = DN_Str8_BinarySplitLastArray(exe_path, separators, DN_ARRAY_UCOUNT(separators));
result = Dqn_Str8_Copy(arena, split.lhs); result = DN_Str8_Copy(arena, split.lhs);
return result; return result;
} }
// NOTE: Counters ////////////////////////////////////////////////////////////////////////////////// // 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; 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; 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; 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; 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; 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; 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; 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; return result;
} }
DQN_API Dqn_OSTimer Dqn_OS_TimerBegin() DN_API DN_OSTimer DN_OS_TimerBegin()
{ {
Dqn_OSTimer result = {}; DN_OSTimer result = {};
result.start = Dqn_OS_PerfCounterNow(); result.start = DN_OS_PerfCounterNow();
return result; 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; 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; 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; 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; 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 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; uint64_t result = 0;
if (tsc_begin) { if (tsc_begin) {
uint64_t os_elapsed = 0; uint64_t os_elapsed = 0;
for (uint64_t os_begin = Dqn_OS_PerfCounterNow(); os_elapsed < os_target_elapsed; ) for (uint64_t os_begin = DN_OS_PerfCounterNow(); os_elapsed < os_target_elapsed; )
os_elapsed = Dqn_OS_PerfCounterNow() - os_begin; os_elapsed = DN_OS_PerfCounterNow() - os_begin;
uint64_t tsc_end = Dqn_CPU_TSC(); uint64_t tsc_end = DN_CPU_TSC();
uint64_t tsc_elapsed = tsc_end - tsc_begin; uint64_t tsc_elapsed = tsc_end - tsc_begin;
result = tsc_elapsed / os_elapsed * os_frequency; result = tsc_elapsed / os_elapsed * os_frequency;
} }
return result; return result;
} }
#if !defined(DQN_NO_OS_FILE_API) #if !defined(DN_NO_OS_FILE_API)
// NOTE: [$FILE] Dqn_OSPathInfo/File /////////////////////////////////////////////////////////////// // NOTE: [$FILE] DN_OSPathInfo/File ///////////////////////////////////////////////////////////////
DQN_API bool Dqn_OS_FileIsOlderThan(Dqn_Str8 file, Dqn_Str8 check_against) DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against)
{ {
Dqn_OSPathInfo file_info = Dqn_OS_PathInfo(file); DN_OSPathInfo file_info = DN_OS_PathInfo(file);
Dqn_OSPathInfo check_against_info = Dqn_OS_PathInfo(check_against); 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; bool result = !file_info.exists || file_info.last_write_time_in_s < check_against_info.last_write_time_in_s;
return result; 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; 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; bool result = false;
if (!file || !fmt) if (!file || !fmt)
return result; return result;
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args); DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args);
result = Dqn_OS_FileWritePtr(file, buffer.data, buffer.size, error); result = DN_OS_FileWritePtr(file, buffer.data, buffer.size, error);
return result; 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_list args;
va_start(args, fmt); 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); va_end(args);
return result; return result;
} }
// NOTE: R/W Entire File /////////////////////////////////////////////////////////////////////////// // 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) if (!arena)
return result; return result;
// NOTE: Query file size + allocate buffer ///////////////////////////////////////////////////// // 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) { 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; return result;
} }
Dqn_ArenaTempMem temp_mem = Dqn_Arena_TempMemBegin(arena); DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(arena);
result = Dqn_Str8_Alloc(arena, path_info.size, Dqn_ZeroMem_No); result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No);
if (!Dqn_Str8_HasData(result)) { if (!DN_Str8_HasData(result)) {
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr); DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
Dqn_Str8 buffer_size_str8 = Dqn_U64ToByteSizeStr8(tmem.arena, path_info.size, Dqn_U64ByteSizeType_Auto); DN_Str8 buffer_size_str8 = DN_U64ToByteSizeStr8(tmem.arena, path_info.size, DN_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)); 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));
Dqn_Arena_TempMemEnd(temp_mem); DN_Arena_TempMemEnd(temp_mem);
result = {}; result = {};
return result; return result;
} }
// NOTE: Read the file from disk /////////////////////////////////////////////////////////////// // NOTE: Read the file from disk ///////////////////////////////////////////////////////////////
Dqn_OSFile file = Dqn_OS_FileOpen(path, Dqn_OSFileOpen_OpenIfExist, Dqn_OSFileAccess_Read, error); DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, error);
bool read_failed = !Dqn_OS_FileRead(&file, result.data, result.size, error); bool read_failed = !DN_OS_FileRead(&file, result.data, result.size, error);
if (file.error || read_failed) { if (file.error || read_failed) {
Dqn_Arena_TempMemEnd(temp_mem); DN_Arena_TempMemEnd(temp_mem);
result = {}; result = {};
} }
Dqn_OS_FileClose(&file); DN_OS_FileClose(&file);
return result; 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); DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_Write, error);
bool result = Dqn_OS_FileWrite(&file, buffer, error); bool result = DN_OS_FileWrite(&file, buffer, error);
Dqn_OS_FileClose(&file); DN_OS_FileClose(&file);
return result; 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); DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args); DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args);
bool result = Dqn_OS_WriteAll(file_path, buffer, error); bool result = DN_OS_WriteAll(file_path, buffer, error);
return result; 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_list args;
va_start(args, fmt); 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); va_end(args);
return result; 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); DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
Dqn_Str8 tmp_path = Dqn_Str8_InitF(tmem.arena, "%.*s.tmp", DQN_STR_FMT(path)); DN_Str8 tmp_path = DN_Str8_InitF(tmem.arena, "%.*s.tmp", DN_STR_FMT(path));
if (!Dqn_OS_WriteAll(tmp_path, buffer, error)) if (!DN_OS_WriteAll(tmp_path, buffer, error))
return false; return false;
if (!Dqn_OS_CopyFile(tmp_path, path, true /*overwrite*/, error)) if (!DN_OS_CopyFile(tmp_path, path, true /*overwrite*/, error))
return false; return false;
if (!Dqn_OS_PathDelete(tmp_path)) if (!DN_OS_PathDelete(tmp_path))
return false; return false;
return true; 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); DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args); DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args);
bool result = Dqn_OS_WriteAllSafe(path, buffer, error); bool result = DN_OS_WriteAllSafe(path, buffer, error);
return result; 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_list args;
va_start(args, fmt); va_start(args, fmt);
bool result = Dqn_OS_WriteAllSafeFV(path, error, fmt, args); bool result = DN_OS_WriteAllSafeFV(path, error, fmt, args);
return result; return result;
} }
#endif // !defined(DQN_NO_OS_FILE_API) #endif // !defined(DN_NO_OS_FILE_API)
// NOTE: [$PATH] Dqn_OSPath //////////////////////////////////////////////////////////////////////// // NOTE: [$PATH] DN_OSPath ////////////////////////////////////////////////////////////////////////
DQN_API bool Dqn_OS_PathAddRef(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path) 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; return false;
if (path.size <= 0) if (path.size <= 0)
return true; return true;
Dqn_Str8 const delimiter_array[] = { DN_Str8 const delimiter_array[] = {
DQN_STR8("\\"), DN_STR8("\\"),
DQN_STR8("/") DN_STR8("/")
}; };
if (fs_path->links_size == 0) { 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 (;;) { for (;;) {
Dqn_Str8BinarySplitResult delimiter = Dqn_Str8_BinarySplitArray(path, 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 = Dqn_Str8_BinarySplitArray(delimiter.rhs, delimiter_array, DQN_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) if (delimiter.lhs.size <= 0)
continue; 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) if (!link)
return false; return false;
@ -344,30 +350,30 @@ DQN_API bool Dqn_OS_PathAddRef(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 p
return true; 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); DN_Str8 copy = DN_Str8_Copy(arena, path);
bool result = Dqn_Str8_HasData(copy) ? true : Dqn_OS_PathAddRef(arena, fs_path, copy); bool result = DN_Str8_HasData(copy) ? true : DN_OS_PathAddRef(arena, fs_path, copy);
return result; 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_list args;
va_start(args, fmt); 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); va_end(args);
bool result = Dqn_OS_PathAddRef(arena, fs_path, path); bool result = DN_OS_PathAddRef(arena, fs_path, path);
return result; 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) if (!fs_path)
return false; return false;
if (fs_path->tail) { if (fs_path->tail) {
DQN_ASSERT(fs_path->head); DN_ASSERT(fs_path->head);
fs_path->links_size -= 1; fs_path->links_size -= 1;
fs_path->string_size -= fs_path->tail->string.size; fs_path->string_size -= fs_path->tail->string.size;
fs_path->tail = fs_path->tail->prev; 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; fs_path->head = nullptr;
} }
} else { } else {
DQN_ASSERT(!fs_path->head); DN_ASSERT(!fs_path->head);
} }
return true; 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 = {}; DN_OSPath fs_path = {};
Dqn_OS_PathAddRef(arena, &fs_path, path); DN_OS_PathAddRef(arena, &fs_path, path);
Dqn_Str8 result = Dqn_OS_PathBuildWithSeparator(arena, &fs_path, path_separator); DN_Str8 result = DN_OS_PathBuildWithSeparator(arena, &fs_path, path_separator);
return result; 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_list args;
va_start(args, fmt); 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); 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; 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; 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_list args;
va_start(args, fmt); 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); va_end(args);
Dqn_Str8 result = Dqn_OS_Path(arena, path); DN_Str8 result = DN_OS_Path(arena, path);
return result; 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) if (!fs_path || fs_path->links_size <= 0)
return result; return result;
// NOTE: Each link except the last one needs the path separator appended to it, '/' or '\\' // 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); 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 = Dqn_Str8_Alloc(arena, string_size, Dqn_ZeroMem_No); result = DN_Str8_Alloc(arena, string_size, DN_ZeroMem_No);
if (result.data) { if (result.data) {
char *dest = result.data; char *dest = result.data;
if (fs_path->has_prefix_path_separator) { 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; dest += path_separator.size;
} }
for (Dqn_OSPathLink *link = fs_path->head; link; link = link->next) { for (DN_OSPathLink *link = fs_path->head; link; link = link->next) {
Dqn_Str8 string = link->string; DN_Str8 string = link->string;
DQN_MEMCPY(dest, string.data, string.size); DN_MEMCPY(dest, string.data, string.size);
dest += string.size; dest += string.size;
if (link != fs_path->tail) { 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; 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 //////////////////////////////////////////////////////////////////////// // NOTE: [$EXEC] DN_OSExec ////////////////////////////////////////////////////////////////////////
DQN_API Dqn_OSExecResult Dqn_OS_Exec(Dqn_Slice<Dqn_Str8> cmd_line, DN_API DN_OSExecResult DN_OS_Exec(DN_Slice<DN_Str8> cmd_line,
Dqn_Str8 working_dir, DN_OSExecArgs *args,
uint8_t exec_flags, DN_Arena *arena,
Dqn_Arena *arena, DN_ErrSink *error)
Dqn_ErrorSink *error)
{ {
Dqn_OSExecAsyncHandle async_handle = Dqn_OS_ExecAsync(cmd_line, working_dir, exec_flags, error); DN_OSExecAsyncHandle async_handle = DN_OS_ExecAsync(cmd_line, args, error);
Dqn_OSExecResult result = Dqn_OS_ExecWait(async_handle, arena, error); DN_OSExecResult result = DN_OS_ExecWait(async_handle, arena, error);
return result; return result;
} }
DQN_API Dqn_OSExecResult Dqn_OS_ExecOrAbort(Dqn_Slice<Dqn_Str8> cmd_line, Dqn_Str8 working_dir, uint8_t exec_flags, Dqn_Arena *arena) DN_API DN_OSExecResult DN_OS_ExecOrAbort(DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena)
{ {
Dqn_ErrorSink *error = Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode_Nil); DN_ErrSink *error = DN_ErrSink_Begin(DN_ErrSinkMode_Nil);
Dqn_OSExecResult result = Dqn_OS_Exec(cmd_line, working_dir, exec_flags, arena, error); DN_OSExecResult result = DN_OS_Exec(cmd_line, args, arena, error);
if (result.os_error_code) { if (result.os_error_code) {
Dqn_ErrorSink_EndAndExitIfErrorF( DN_ErrSink_EndAndExitIfErrorF(
error, error,
result.os_error_code, result.os_error_code,
"OS failed to execute the requested command returning the error code %u", "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<Dqn_Str8> cmd_line, Dqn_St
} }
if (result.exit_code) { if (result.exit_code) {
Dqn_ErrorSink_EndAndExitIfErrorF( DN_ErrSink_EndAndExitIfErrorF(
error, error,
result.exit_code, result.exit_code,
"OS executed command and returned non-zero exit code %u", "OS executed command and returned non-zero exit code %u",
result.exit_code); result.exit_code);
} }
Dqn_ErrorSink_EndAndIgnore(error); DN_ErrSink_EndAndIgnore(error);
return result; return result;
} }
// NOTE: [$THRD] Dqn_OSThread ////////////////////////////////////////////////////////////////////// // NOTE: [$THRD] DN_OSThread //////////////////////////////////////////////////////////////////////
DQN_THREAD_LOCAL Dqn_TLS *g_dqn_os_thread_tls; 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; DN_OSThread *thread = DN_CAST(DN_OSThread *)user_context;
Dqn_TLS_Init(&thread->tls); DN_TLS_Init(&thread->tls);
Dqn_OS_ThreadSetTLS(&thread->tls); DN_OS_ThreadSetTLS(&thread->tls);
Dqn_OS_SemaphoreWait(&thread->init_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); DN_OS_SemaphoreWait(&thread->init_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT);
thread->func(thread); 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 //////////////////////////////////////////////////////////////////////// DN_API void DN_OS_ThreadSetName(DN_Str8 name)
DQN_API void Dqn_OS_HttpRequestWait(Dqn_OSHttpResponse *response)
{ {
if (response && Dqn_OS_SemaphoreIsValid(&response->on_complete_semaphore)) DN_TLS *tls = DN_TLS_Get();
Dqn_OS_SemaphoreWait(&response->on_complete_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); 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 // TODO(doyle): Revise the memory allocation and its lifetime
Dqn_OSHttpResponse result = {}; DN_OSHttpResponse result = {};
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena); DN_TLSTMem tmem = DN_TLS_TMem(arena);
result.tmem_arena = tmem.arena; result.tmem_arena = tmem.arena;
Dqn_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers); DN_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers);
Dqn_OS_HttpRequestWait(&result); DN_OS_HttpRequestWait(&result);
return result; return result;
} }

499
dqn_os.h
View File

@ -17,77 +17,77 @@
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// [$OMEM] Dqn_OSMem -- -- Memory allocation (typically virtual memory if supported) // [$OMEM] DN_OSMem -- -- Memory allocation (typically virtual memory if supported)
// [$DATE] Dqn_OSDate -- -- Date time APIs // [$DATE] DN_OSDate -- -- Date time APIs
// [$FILE] Dqn_OSPathInfo/File -- -- File path info/reading/writing // [$FILE] DN_OSPathInfo/File -- -- File path info/reading/writing
// [$PATH] Dqn_OSPath -- -- Construct native OS paths helpers // [$PATH] DN_OSPath -- -- Construct native OS paths helpers
// [$EXEC] Dqn_OSExec -- -- Execute programs programatically // [$EXEC] DN_OSExec -- -- Execute programs programatically
// [$SEMA] Dqn_OSSemaphore -- DQN_SEMAPHORE -- // [$SEMA] DN_OSSemaphore -- DN_SEMAPHORE --
// [$MUTX] Dqn_OSMutex -- -- // [$MUTX] DN_OSMutex -- --
// [$THRD] Dqn_OSThread -- DQN_THREAD -- // [$THRD] DN_OSThread -- DN_THREAD --
// [$HTTP] Dqn_OSHttp -- -- // [$HTTP] DN_OSHttp -- --
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$OMEM] Dqn_OSMem ////////////////////////////////////////////////////////////////////////// // NOTE: [$OMEM] DN_OSMem //////////////////////////////////////////////////////////////////////////
enum Dqn_OSMemCommit enum DN_OSMemCommit
{ {
Dqn_OSMemCommit_No, DN_OSMemCommit_No,
Dqn_OSMemCommit_Yes, DN_OSMemCommit_Yes,
}; };
enum Dqn_OSMemPage enum DN_OSMemPage
{ {
// Exception on read/write with a page. This flag overrides the read/write // Exception on read/write with a page. This flag overrides the read/write
// access. // 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 // Only write permitted on the page. On Windows this is not supported and
// will be promoted to read+write permissions. // 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 // Modifier used in conjunction with previous flags. Raises exception on
// first access to the page, then, the underlying protection flags are // 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 // active. This is supported on Windows, on other OS's using this flag will
// set the OS equivalent of Dqn_OSMemPage_NoAccess. // set the OS equivalent of DN_OSMemPage_NoAccess.
// This flag must only be used in Dqn_OSMem_Protect // This flag must only be used in DN_OSMem_Protect
Dqn_OSMemPage_Guard = 1 << 3, DN_OSMemPage_Guard = 1 << 3,
// If leak tracing is enabled, this flag will allow the allocation recorded // 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 // from the reserve call to be leaked, e.g. not printed when leaks are
// dumped to the console. // 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 // 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 // from being created in the allocation table at all. If this flag is
// enabled, 'OSMemPage_AllocRecordLeakPermitted' has no effect since the // enabled, 'OSMemPage_AllocRecordLeakPermitted' has no effect since the
// record will never be created. // 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 // [INTERNAL] Do not use. All flags together do not constitute a correct
// configuration of pages. // configuration of pages.
Dqn_OSMemPage_All = Dqn_OSMemPage_NoAccess | DN_OSMemPage_All = DN_OSMemPage_NoAccess |
Dqn_OSMemPage_ReadWrite | DN_OSMemPage_ReadWrite |
Dqn_OSMemPage_Guard | DN_OSMemPage_Guard |
Dqn_OSMemPage_AllocRecordLeakPermitted | DN_OSMemPage_AllocRecordLeakPermitted |
Dqn_OSMemPage_NoAllocRecordEntry, DN_OSMemPage_NoAllocRecordEntry,
}; };
// NOTE: [$DATE] Dqn_OSDate //////////////////////////////////////////////////////////////////////// // NOTE: [$DATE] DN_OSDate ////////////////////////////////////////////////////////////////////////
struct Dqn_OSDateTimeStr8 struct DN_OSDateTimeStr8
{ {
char date[DQN_ARRAY_UCOUNT("YYYY-MM-SS")]; char date[DN_ARRAY_UCOUNT("YYYY-MM-SS")];
uint8_t date_size; uint8_t date_size;
char hms[DQN_ARRAY_UCOUNT("HH:MM:SS")]; char hms[DN_ARRAY_UCOUNT("HH:MM:SS")];
uint8_t hms_size; uint8_t hms_size;
}; };
struct Dqn_OSDateTime struct DN_OSDateTime
{ {
uint8_t day; uint8_t day;
uint8_t month; uint8_t month;
@ -97,126 +97,136 @@ struct Dqn_OSDateTime
uint8_t seconds; 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 start;
uint64_t end; uint64_t end;
}; };
#if !defined(DQN_NO_OS_FILE_API) #if !defined(DN_NO_OS_FILE_API)
// NOTE: [$FSYS] Dqn_OSFile //////////////////////////////////////////////////////////////////////// // NOTE: [$FSYS] DN_OSFile ////////////////////////////////////////////////////////////////////////
enum Dqn_OSPathInfoType enum DN_OSPathInfoType
{ {
Dqn_OSPathInfoType_Unknown, DN_OSPathInfoType_Unknown,
Dqn_OSPathInfoType_Directory, DN_OSPathInfoType_Directory,
Dqn_OSPathInfoType_File, DN_OSPathInfoType_File,
}; };
struct Dqn_OSPathInfo struct DN_OSPathInfo
{ {
bool exists; bool exists;
Dqn_OSPathInfoType type; DN_OSPathInfoType type;
uint64_t create_time_in_s; uint64_t create_time_in_s;
uint64_t last_write_time_in_s; uint64_t last_write_time_in_s;
uint64_t last_access_time_in_s; uint64_t last_access_time_in_s;
uint64_t size; uint64_t size;
}; };
struct Dqn_OS_DirIterator struct DN_OSDirIterator
{ {
void *handle; void *handle;
Dqn_Str8 file_name; DN_Str8 file_name;
char buffer[512]; char buffer[512];
}; };
// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// // NOTE: R/W Stream API ////////////////////////////////////////////////////////////////////////////
struct Dqn_OSFile struct DN_OSFile
{ {
bool error; bool error;
void *handle; 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 DN_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 DN_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_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, DN_OSFileAccess_Read = 1 << 0,
Dqn_OSFileAccess_Write = 1 << 1, DN_OSFileAccess_Write = 1 << 1,
Dqn_OSFileAccess_Execute = 1 << 2, DN_OSFileAccess_Execute = 1 << 2,
Dqn_OSFileAccess_AppendOnly = 1 << 3, // This flag cannot be combined with any other access mode DN_OSFileAccess_AppendOnly = 1 << 3, // This flag cannot be combined with any other access mode
Dqn_OSFileAccess_ReadWrite = Dqn_OSFileAccess_Read | Dqn_OSFileAccess_Write, DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write,
Dqn_OSFileAccess_All = Dqn_OSFileAccess_ReadWrite | Dqn_OSFileAccess_Execute, 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 //////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSPath ////////////////////////////////////////////////////////////////////////////////
#if !defined(Dqn_OSPathSeperator) #if !defined(DN_OSPathSeperator)
#if defined(DQN_OS_WIN32) #if defined(DN_OS_WIN32)
#define Dqn_OSPathSeperator "\\" #define DN_OSPathSeperator "\\"
#else #else
#define Dqn_OSPathSeperator "/" #define DN_OSPathSeperator "/"
#endif #endif
#define Dqn_OSPathSeperatorString DQN_STR8(Dqn_OSPathSeperator) #define DN_OSPathSeperatorString DN_STR8(DN_OSPathSeperator)
#endif #endif
struct Dqn_OSPathLink struct DN_OSPathLink
{ {
Dqn_Str8 string; DN_Str8 string;
Dqn_OSPathLink *next; DN_OSPathLink *next;
Dqn_OSPathLink *prev; DN_OSPathLink *prev;
}; };
struct Dqn_OSPath struct DN_OSPath
{ {
bool has_prefix_path_separator; bool has_prefix_path_separator;
Dqn_OSPathLink *head; DN_OSPathLink *head;
Dqn_OSPathLink *tail; DN_OSPathLink *tail;
Dqn_usize string_size; DN_USize string_size;
uint16_t links_size; uint16_t links_size;
}; };
// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// // NOTE: [$EXEC] DN_OSExec ////////////////////////////////////////////////////////////////////////
enum Dqn_OSExecFlag typedef uint32_t DN_OSExecFlags;
enum DN_OSExecFlags_
{ {
Dqn_OSExecFlag_Nil = 0, DN_OSExecFlags_Nil = 0,
Dqn_OSExecFlag_SaveStdout = 1 << 0, DN_OSExecFlags_SaveStdout = 1 << 0,
Dqn_OSExecFlag_SaveStderr = 1 << 1, DN_OSExecFlags_SaveStderr = 1 << 1,
Dqn_OSExecFlag_SaveOutput = Dqn_OSExecFlag_SaveStdout | Dqn_OSExecFlag_SaveStderr, DN_OSExecFlags_SaveOutput = DN_OSExecFlags_SaveStdout | DN_OSExecFlags_SaveStderr,
Dqn_OSExecFlag_MergeStderrToStdout = 1 << 2 | Dqn_OSExecFlag_SaveOutput, DN_OSExecFlags_MergeStderrToStdout = 1 << 2 | DN_OSExecFlags_SaveOutput,
}; };
struct Dqn_OSExecAsyncHandle struct DN_OSExecAsyncHandle
{ {
uint8_t exec_flags; DN_OSExecFlags exec_flags;
uint32_t os_error_code; uint32_t os_error_code;
uint32_t exit_code; uint32_t exit_code;
void *process; void *process;
void *stdout_read; void *stdout_read;
void *stdout_write; void *stdout_write;
void *stderr_read; void *stderr_read;
void *stderr_write; void *stderr_write;
}; };
struct Dqn_OSExecResult struct DN_OSExecResult
{ {
Dqn_Str8 stdout_text; bool finished;
Dqn_Str8 stderr_text; DN_Str8 stdout_text;
DN_Str8 stderr_text;
uint32_t os_error_code; uint32_t os_error_code;
uint32_t exit_code; uint32_t exit_code;
}; };
#if !defined(DQN_NO_SEMAPHORE) struct DN_OSExecArgs
// NOTE: [$SEMA] Dqn_OSSemaphore ///////////////////////////////////////////////////////////////////
uint32_t const DQN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX;
struct Dqn_OSSemaphore
{ {
#if defined(DQN_OS_WIN32) && !defined(DQN_OS_WIN32_USE_PTHREADS) DN_OSExecFlags flags;
DN_Str8 working_dir;
DN_Slice<DN_Str8> 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; void *win32_handle;
#else #else
sem_t posix_handle; sem_t posix_handle;
@ -224,189 +234,212 @@ struct Dqn_OSSemaphore
#endif #endif
}; };
enum Dqn_OSSemaphoreWaitResult enum DN_OSSemaphoreWaitResult
{ {
Dqn_OSSemaphoreWaitResult_Failed, DN_OSSemaphoreWaitResult_Failed,
Dqn_OSSemaphoreWaitResult_Success, DN_OSSemaphoreWaitResult_Success,
Dqn_OSSemaphoreWaitResult_Timeout, DN_OSSemaphoreWaitResult_Timeout,
}; };
#endif // !defined(DQN_NO_SEMAPHORE) #endif // !defined(DN_NO_SEMAPHORE)
// NOTE: [$THRD] Dqn_OSThread ///////////////////////////////////////////////////////////////////// // NOTE: [$THRD] DN_OSThread /////////////////////////////////////////////////////////////////////
#if !defined(DQN_NO_THREAD) && !defined(DQN_NO_SEMAPHORE) #if !defined(DN_NO_THREAD) && !defined(DN_NO_SEMAPHORE)
typedef int32_t (Dqn_OSThreadFunc)(struct Dqn_OSThread*); 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; void *handle;
uint64_t thread_id; uint64_t thread_id;
void *user_context; void *user_context;
Dqn_OSThreadFunc *func; DN_OSThreadFunc *func;
Dqn_OSSemaphore init_semaphore; DN_OSSemaphore init_semaphore;
}; };
#endif // !defined(DQN_NO_THREAD) #endif // !defined(DN_NO_THREAD)
// NOTE: [$HTTP] Dqn_OSHttp //////////////////////////////////////////////////////////////////////// // NOTE: [$HTTP] DN_OSHttp ////////////////////////////////////////////////////////////////////////
enum Dqn_OSHttpRequestSecure enum DN_OSHttpRequestSecure
{ {
Dqn_OSHttpRequestSecure_No, DN_OSHttpRequestSecure_No,
Dqn_OSHttpRequestSecure_Yes, DN_OSHttpRequestSecure_Yes,
}; };
struct Dqn_OSHttpResponse struct DN_OSHttpResponse
{ {
// NOTE: Response data // NOTE: Response data
uint32_t error_code; uint32_t error_code;
Dqn_Str8 error_msg; DN_Str8 error_msg;
uint16_t http_status; uint16_t http_status;
Dqn_Str8 body; DN_Str8 body;
Dqn_b32 done; DN_B32 done;
// NOTE: Book-keeping // NOTE: Book-keeping
Dqn_Arena *arena; // Allocates memory for the response DN_Arena *arena; // Allocates memory for the response
// NOTE: Async book-keeping // NOTE: Async book-keeping
// Synchronous HTTP response uses the TLS scratch arena whereas async // Synchronous HTTP response uses the TLS scratch arena whereas async
// calls use their own dedicated arena. // calls use their own dedicated arena.
Dqn_Arena tmp_arena; DN_Arena tmp_arena;
Dqn_Arena *tmem_arena; DN_Arena *tmem_arena;
Dqn_Str8Builder builder; DN_Str8Builder builder;
Dqn_OSSemaphore on_complete_semaphore; DN_OSSemaphore on_complete_semaphore;
#if defined(DQN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
emscripten_fetch_t *em_handle; emscripten_fetch_t *em_handle;
#elif defined(DQN_OS_WIN32) #elif defined(DN_OS_WIN32)
HINTERNET win32_request_session; HINTERNET win32_request_session;
HINTERNET win32_request_connection; HINTERNET win32_request_connection;
HINTERNET win32_request_handle; HINTERNET win32_request_handle;
#endif #endif
}; };
DN_API void DN_OS_Init();
// NOTE: [$OMEM] Memory ////////////////////////////////////////////////////////////////////////// // NOTE: [$OMEM] Memory //////////////////////////////////////////////////////////////////////////
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);
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);
DQN_API void Dqn_OS_MemDecommit(void *ptr, Dqn_usize size); DN_API void DN_OS_MemDecommit(void *ptr, DN_USize size);
DQN_API void Dqn_OS_MemRelease (void *ptr, Dqn_usize size); DN_API void DN_OS_MemRelease (void *ptr, DN_USize 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);
// 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 ////////////////////////////////////////////////////////////////////////////// // NOTE: [$DATE] Date //////////////////////////////////////////////////////////////////////////////
DQN_API Dqn_OSDateTime Dqn_OS_DateLocalTimeNow (); DN_API DN_OSDateTime DN_OS_DateLocalTimeNow ();
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_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_API uint64_t Dqn_OS_DateUnixTime (); DN_API uint64_t DN_OS_DateUnixTimeNs ();
DQN_API Dqn_OSDateTime Dqn_OS_DateUnixTimeToDate (uint64_t time); DN_API uint64_t DN_OS_DateUnixTimeS ();
DQN_API uint64_t Dqn_OS_DateToUnixTime (Dqn_OSDateTime date); DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (uint64_t time);
DQN_API bool Dqn_OS_DateIsValid (Dqn_OSDateTime date); 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 ///////////////////////////////////////////////////////////////////////////////////// // NOTE: Other /////////////////////////////////////////////////////////////////////////////////////
DQN_API bool Dqn_OS_SecureRNGBytes (void *buffer, uint32_t size); DN_API bool DN_OS_SecureRNGBytes (void *buffer, uint32_t size);
DQN_API Dqn_Str8 Dqn_OS_EXEPath (Dqn_Arena *arena); DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);
DQN_API Dqn_Str8 Dqn_OS_EXEDir (Dqn_Arena *arena); DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
#define Dqn_OS_EXEDir_TLS() Dqn_OS_EXEDir(Dqn_TLS_TopArena()) DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena);
DQN_API void Dqn_OS_SleepMs (Dqn_uint milliseconds); #define DN_OS_EXEDir_TLS() DN_OS_EXEDir(DN_TLS_TopArena())
// NOTE: Counters ////////////////////////////////////////////////////////////////////////////////// DN_API void DN_OS_SleepMs (DN_UInt milliseconds);
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);
#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 ///////////////////////////////////////////////////////////////////////// // NOTE: File system paths /////////////////////////////////////////////////////////////////////////
DQN_API Dqn_OSPathInfo Dqn_OS_PathInfo (Dqn_Str8 path); DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path);
DQN_API bool Dqn_OS_FileIsOlderThan(Dqn_Str8 file, Dqn_Str8 check_against); DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against);
DQN_API bool Dqn_OS_PathDelete (Dqn_Str8 path); DN_API bool DN_OS_PathDelete (DN_Str8 path);
DQN_API bool Dqn_OS_FileExists (Dqn_Str8 path); DN_API bool DN_OS_FileExists (DN_Str8 path);
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);
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);
DQN_API bool Dqn_OS_MakeDir (Dqn_Str8 path); DN_API bool DN_OS_MakeDir (DN_Str8 path);
DQN_API bool Dqn_OS_DirExists (Dqn_Str8 path); DN_API bool DN_OS_DirExists (DN_Str8 path);
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);
// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// // 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 *err);
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);
DQN_API bool Dqn_OS_FileWritePtr(Dqn_OSFile *file, void const *data, Dqn_usize size, Dqn_ErrorSink *error); DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *data, DN_USize size, DN_ErrSink *err);
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 *err);
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 *err, DN_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, ...); DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
DQN_API void Dqn_OS_FileClose (Dqn_OSFile *file); 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 /////////////////////////////////////////////////////////////////////////// // 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 *err);
#define Dqn_OS_ReadAll_TLS(...) Dqn_OS_ReadAll(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_OS_ReadAll_TLS(...) DN_OS_ReadAll(DN_TLS_TopArena(), ##__VA_ARGS__)
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 *err);
DQN_API bool Dqn_OS_WriteAllFV (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args); DN_API bool DN_OS_WriteAllFV (DN_Str8 path, DN_ErrSink *err, DN_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, ...); DN_API bool DN_OS_WriteAllF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
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 *err);
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 *err, DN_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, ...); DN_API bool DN_OS_WriteAllSafeF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
#endif // !defined(DQN_NO_OS_FILE_API) #endif // !defined(DN_NO_OS_FILE_API)
// NOTE: File system paths ///////////////////////////////////////////////////////////////////////// // NOTE: File system paths /////////////////////////////////////////////////////////////////////////
DQN_API bool Dqn_OS_PathAddRef (Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path); DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
#define Dqn_OS_PathAddRef_TLS(...) Dqn_OS_PathAddRef(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_OS_PathAddRef_TLS(...) DN_OS_PathAddRef(DN_TLS_TopArena(), ##__VA_ARGS__)
DQN_API bool Dqn_OS_PathAdd (Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path); #define DN_OS_PathAddRef_Frame(...) DN_OS_PathAddRef(DN_TLS_FrameArena(), ##__VA_ARGS__)
#define Dqn_OS_PathAdd_TLS(...) Dqn_OS_PathAdd(Dqn_TLS_TopArena(), ##__VA_ARGS__) DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
DQN_API bool Dqn_OS_PathAddF (Dqn_Arena *arena, Dqn_OSPath *fs_path, DQN_FMT_ATTRIB char const *fmt, ...); #define DN_OS_PathAdd_TLS(...) DN_OS_PathAdd(DN_TLS_TopArena(), ##__VA_ARGS__)
#define Dqn_OS_PathAddF_TLS(...) Dqn_OS_PathAddF(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_OS_PathAdd_Frame(...) DN_OS_PathAdd(DN_TLS_FrameArena(), ##__VA_ARGS__)
DQN_API bool Dqn_OS_PathPop (Dqn_OSPath *fs_path); DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...);
DQN_API Dqn_Str8 Dqn_OS_PathBuildWithSeparator (Dqn_Arena *arena, Dqn_OSPath const *fs_path, Dqn_Str8 path_separator); #define DN_OS_PathAddF_TLS(...) DN_OS_PathAddF(DN_TLS_TopArena(), ##__VA_ARGS__)
#define Dqn_OS_PathBuildWithSeperator_TLS(...) Dqn_OS_PathBuildWithSeperator(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_OS_PathAddF_Frame(...) DN_OS_PathAddF(DN_TLS_FrameArena(), ##__VA_ARGS__)
DQN_API Dqn_Str8 Dqn_OS_PathTo (Dqn_Arena *arena, Dqn_Str8 path, Dqn_Str8 path_separtor); DN_API bool DN_OS_PathPop (DN_OSPath *fs_path);
#define Dqn_OS_PathTo_TLS(...) Dqn_OS_PathTo(Dqn_TLS_TopArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator);
DQN_API Dqn_Str8 Dqn_OS_PathToF (Dqn_Arena *arena, Dqn_Str8 path_separator, DQN_FMT_ATTRIB char const *fmt, ...); #define DN_OS_PathBuildWithSeperator_TLS(...) DN_OS_PathBuildWithSeperator(DN_TLS_TopArena(), ##__VA_ARGS__)
#define Dqn_OS_PathToF_TLS(...) Dqn_OS_PathToF(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_OS_PathBuildWithSeperator_Frame(...) DN_OS_PathBuildWithSeperator(DN_TLS_FrameArena(), ##__VA_ARGS__)
DQN_API Dqn_Str8 Dqn_OS_Path (Dqn_Arena *arena, Dqn_Str8 path); DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor);
#define Dqn_OS_Path_TLS(...) Dqn_OS_Path(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_OS_PathTo_TLS(...) DN_OS_PathTo(DN_TLS_TopArena(), ##__VA_ARGS__)
DQN_API Dqn_Str8 Dqn_OS_PathF (Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...); #define DN_OS_PathTo_Frame(...) DN_OS_PathTo(DN_TLS_FrameArena(), ##__VA_ARGS__)
#define Dqn_OS_PathF_TLS(...) Dqn_OS_PathF(Dqn_TLS_TopArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...);
#define Dqn_OS_PathBuildFwdSlash(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, DQN_STR8("/")) #define DN_OS_PathToF_TLS(...) DN_OS_PathToF(DN_TLS_TopArena(), ##__VA_ARGS__)
#define Dqn_OS_PathBuildBackSlash(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, DQN_STR8("\\")) #define DN_OS_PathToF_Frame(...) DN_OS_PathToF(DN_TLS_FrameArena(), ##__VA_ARGS__)
#define Dqn_OS_PathBuild(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, Dqn_OSPathSeparatorString) 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 //////////////////////////////////////////////////////////////////////// #define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("/"))
DQN_API void Dqn_OS_Exit (int32_t exit_code); #define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("\\"))
DQN_API Dqn_OSExecResult Dqn_OS_ExecWait (Dqn_OSExecAsyncHandle handle, Dqn_Arena *arena, Dqn_ErrorSink *error); #define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString)
DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync (Dqn_Slice<Dqn_Str8> cmd_line, Dqn_Str8 working_dir, uint8_t exec_flags, Dqn_ErrorSink *error);
DQN_API Dqn_OSExecResult Dqn_OS_Exec (Dqn_Slice<Dqn_Str8> 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<Dqn_Str8> 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())
// NOTE: [$SEMA] Dqn_OSSemaphore /////////////////////////////////////////////////////////////////// // NOTE: [$EXEC] DN_OSExec ////////////////////////////////////////////////////////////////////////
#if !defined(DQN_NO_SEMAPHORE) DN_API void DN_OS_Exit (int32_t exit_code);
DQN_API Dqn_OSSemaphore Dqn_OS_SemaphoreInit (uint32_t initial_count); 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_API bool Dqn_OS_SemaphoreIsValid (Dqn_OSSemaphore *semaphore); DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_ErrSink *err);
DQN_API void Dqn_OS_SemaphoreDeinit (Dqn_OSSemaphore *semaphore); DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_ErrSink *err);
DQN_API void Dqn_OS_SemaphoreIncrement(Dqn_OSSemaphore *semaphore, uint32_t amount); DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_ErrSink *err);
DQN_API Dqn_OSSemaphoreWaitResult Dqn_OS_SemaphoreWait (Dqn_OSSemaphore *semaphore, uint32_t timeout_ms); DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
#endif // !defined(DQN_NO_SEMAPHORE) #define DN_OS_ExecOrAbort_TLS(...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_TLS_TopArena())
// NOTE: [$MUTX] Dqn_OSMutex /////////////////////////////////////////////////////////////////////// // NOTE: [$SEMA] DN_OSSemaphore ///////////////////////////////////////////////////////////////////
DQN_API Dqn_OSMutex Dqn_OS_MutexInit (); #if !defined(DN_NO_SEMAPHORE)
DQN_API void Dqn_OS_MutexDeinit(Dqn_OSMutex *mutex); DN_API DN_OSSemaphore DN_OS_SemaphoreInit (uint32_t initial_count);
DQN_API void Dqn_OS_MutexLock (Dqn_OSMutex *mutex); DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore);
DQN_API void Dqn_OS_MutexUnlock(Dqn_OSMutex *mutex); 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 ///////////////////////////////////////////////////////////////////// // NOTE: [$MUTX] DN_OSMutex ///////////////////////////////////////////////////////////////////////
#if !defined(DQN_NO_THREAD) && !defined(DQN_NO_SEMAPHORE) DN_API DN_OSMutex DN_OS_MutexInit ();
DQN_API bool Dqn_OS_ThreadInit (Dqn_OSThread *thread, Dqn_OSThreadFunc *func, void *user_context); DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex);
DQN_API void Dqn_OS_ThreadDeinit(Dqn_OSThread thread); DN_API void DN_OS_MutexLock (DN_OSMutex *mutex);
DQN_API uint32_t Dqn_OS_ThreadID (); DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex);
DQN_API void Dqn_OS_ThreadSetTLS(Dqn_TLS *tls); #define DN_OS_Mutex(mutex) DN_DEFER_LOOP(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex))
#endif // !defined(DQN_NO_THREAD)
// NOTE: [$HTTP] Dqn_OSHttp //////////////////////////////////////////////////////////////////////// // NOTE: [$THRD] DN_OSThread /////////////////////////////////////////////////////////////////////
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); #if !defined(DN_NO_THREAD) && !defined(DN_NO_SEMAPHORE)
DQN_API void Dqn_OS_HttpRequestWait (Dqn_OSHttpResponse *response); DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context);
DQN_API void Dqn_OS_HttpRequestFree (Dqn_OSHttpResponse *response); DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread);
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); 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);

File diff suppressed because it is too large Load Diff

21
dqn_os_posix.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include "dqn.h"
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\
// $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ \_$$ _|$$ | $$ |
// $$ / $$ |$$ / \__| $$ | $$ |$$ / $$ |$$ / \__| $$ | \$$\ $$ |
// $$ | $$ |\$$$$$$\ $$$$$$$ |$$ | $$ |\$$$$$$\ $$ | \$$$$ /
// $$ | $$ | \____$$\ $$ ____/ $$ | $$ | \____$$\ $$ | $$ $$<
// $$ | $$ |$$\ $$ | $$ | $$ | $$ |$$\ $$ | $$ | $$ /\$$\
// $$$$$$ |\$$$$$$ | $$ | $$$$$$ |\$$$$$$ |$$$$$$\ $$ / $$ |
// \______/ \______/ \__| \______/ \______/ \______|\__| \__|
//
// dqn_os_posix.h
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
DN_API void DN_Posix_ThreadSetName(DN_Str8 name);

File diff suppressed because it is too large Load Diff

View File

@ -18,40 +18,40 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
struct Dqn_WinError struct DN_WinError
{ {
unsigned long code; unsigned long code;
Dqn_Str8 msg; DN_Str8 msg;
}; };
// NOTE: Windows Str8 <-> Str16 /////////////////////////////////////////// // NOTE: Windows Str8 <-> Str16 ///////////////////////////////////////////
struct Dqn_Win_FolderIteratorW struct DN_Win_FolderIteratorW
{ {
void *handle; void *handle;
Dqn_Str16 file_name; DN_Str16 file_name;
wchar_t file_name_buf[512]; wchar_t file_name_buf[512];
}; };
struct Dqn_Win_FolderIterator DN_API void DN_Win_ThreadSetName (DN_Str8 name);
{
void *handle; // NOTE: [$WIND] DN_Win ///////////////////////////////////////////////////////////////////////////
Dqn_Str8 file_name; DN_API DN_Str16 DN_Win_ErrorCodeToMsg16Alloc(uint32_t error_code);
char file_name_buf[512]; 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 //////////////////////////////////////////////////////////////////// // NOTE: Windows Str8 <-> 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_API int Dqn_Win_Str8ToStr16Buffer (Dqn_Str16 src, char *dest, int dest_size); DN_API int DN_Win_Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
DQN_API Dqn_Str8 Dqn_Win_Str16ToStr8 (Dqn_Arena *arena, Dqn_Str16 src); DN_API DN_Str8 DN_Win_Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
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);
DN_API DN_Str8 DN_Win_Str16ToStr8Alloc (DN_Str16 src);
// NOTE: Path navigation /////////////////////////////////////////////////////////////////////////// // NOTE: Path navigation ///////////////////////////////////////////////////////////////////////////
DQN_API Dqn_Str16 Dqn_Win_EXEPathW (Dqn_Arena *arena); DN_API DN_Str16 DN_Win_EXEPathW (DN_Arena *arena);
DQN_API Dqn_Str16 Dqn_Win_EXEDirW (Dqn_Arena *arena); DN_API DN_Str16 DN_Win_EXEDirW (DN_Arena *arena);
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_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_API bool Dqn_Win_FolderIterate (Dqn_Str8 path, Dqn_Win_FolderIterator *it); DN_API bool DN_Win_DirWIterate (DN_Str16 path, DN_Win_FolderIteratorW *it);
DQN_API bool Dqn_Win_FolderWIterate (Dqn_Str16 path, Dqn_Win_FolderIteratorW *it);

File diff suppressed because it is too large Load Diff

View File

@ -17,27 +17,28 @@
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// [$CSTR] Dqn_CStr8 -- C-string helpers // [$CSTR] DN_CStr8 -- C-string helpers
// [$STR8] Dqn_Str8 -- Pointer and length strings // [$STR8] DN_Str8 -- Pointer and length strings
// [$STRB] Dqn_Str8Builder -- Construct strings dynamically // [$STRB] DN_Str8Builder -- Construct strings dynamically
// [$FSTR] Dqn_FStr8 -- Fixed-size strings // [$FSTR] DN_FStr8 -- Fixed-size strings
// [$CHAR] Dqn_Char -- Character ascii/digit.. helpers // [$CHAR] DN_Char -- Character ascii/digit.. helpers
// [$UTFX] Dqn_UTF -- Unicode helpers // [$UTFX] DN_UTF -- Unicode helpers
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$STR8] Dqn_Str8 ////////////////////////////////////////////////////////////////////////// // NOTE: [$STR8] DN_Str8 //////////////////////////////////////////////////////////////////////////
struct Dqn_Str8Link struct DN_Str8Link
{ {
Dqn_Str8 string; // The string DN_Str8 string; // The string
Dqn_Str8Link *next; // The next string in the linked list 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 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) #if defined(__cplusplus)
wchar_t const *begin() const { return data; } // Const begin iterator for range-for loops 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 #endif
}; };
struct Dqn_Str8BinarySplitResult struct DN_Str8BinarySplitResult
{ {
Dqn_Str8 lhs; DN_Str8 lhs;
Dqn_Str8 rhs; 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. 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 DN_USize index; // Index in the buffer where the found string starts
Dqn_Str8 match; // The matching string in the buffer that was searched DN_Str8 match; // 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 DN_Str8 match_to_end_of_buffer; // 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 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, DN_Str8IsAll_Digits,
Dqn_Str8IsAll_Hex, DN_Str8IsAll_Hex,
}; };
enum Dqn_Str8EqCase enum DN_Str8EqCase
{ {
Dqn_Str8EqCase_Sensitive, DN_Str8EqCase_Sensitive,
Dqn_Str8EqCase_Insensitive, DN_Str8EqCase_Insensitive,
}; };
enum Dqn_Str8FindFlag enum DN_Str8FindFlag
{ {
Dqn_Str8FindFlag_Digit = 1 << 0, // 0-9 DN_Str8FindFlag_Digit = 1 << 0, // 0-9
Dqn_Str8FindFlag_Whitespace = 1 << 1, // '\r', '\t', '\n', ' ' DN_Str8FindFlag_Whitespace = 1 << 1, // '\r', '\t', '\n', ' '
Dqn_Str8FindFlag_Alphabet = 1 << 2, // A-Z, a-z DN_Str8FindFlag_Alphabet = 1 << 2, // A-Z, a-z
Dqn_Str8FindFlag_Plus = 1 << 3, // + DN_Str8FindFlag_Plus = 1 << 3, // +
Dqn_Str8FindFlag_Minus = 1 << 4, // - DN_Str8FindFlag_Minus = 1 << 4, // -
Dqn_Str8FindFlag_AlphaNum = Dqn_Str8FindFlag_Alphabet | Dqn_Str8FindFlag_Digit, DN_Str8FindFlag_AlphaNum = DN_Str8FindFlag_Alphabet | DN_Str8FindFlag_Digit,
}; };
enum Dqn_Str8SplitIncludeEmptyStrings enum DN_Str8SplitIncludeEmptyStrings
{ {
Dqn_Str8SplitIncludeEmptyStrings_No, DN_Str8SplitIncludeEmptyStrings_No,
Dqn_Str8SplitIncludeEmptyStrings_Yes, DN_Str8SplitIncludeEmptyStrings_Yes,
}; };
struct Dqn_Str8ToU64Result struct DN_Str8ToU64Result
{ {
bool success; bool success;
uint64_t value; uint64_t value;
}; };
struct Dqn_Str8ToI64Result struct DN_Str8ToI64Result
{ {
bool success; bool success;
int64_t value; int64_t value;
}; };
// NOTE: [$FSTR] Dqn_FStr8 ///////////////////////////////////////////////////////////////////////// struct DN_Str8DotTruncateResult
#if !defined(DQN_NO_FSTR8) {
template <Dqn_usize N> struct Dqn_FStr8 bool truncated;
DN_Str8 str8;
};
// NOTE: [$FSTR] DN_FStr8 /////////////////////////////////////////////////////////////////////////
#if !defined(DN_NO_FSTR8)
template <DN_USize N> struct DN_FStr8
{ {
char data[N+1]; char data[N+1];
Dqn_usize size; DN_USize size;
char *begin() { return data; } char *begin() { return data; }
char *end () { return data + size; } char *end () { return data + size; }
char const *begin() const { return data; } char const *begin() const { return data; }
char const *end () const { return data + size; } 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 DN_Arena *arena; // Allocator to use to back the string list
Dqn_Str8Link *head; // First string in the linked list of strings DN_Str8Link *head; // First string in the linked list of strings
Dqn_Str8Link *tail; // Last string in the linked list of strings DN_Str8Link *tail; // Last string in the linked list of strings
Dqn_usize string_size; // The size in bytes necessary to construct the current string DN_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_USize count; // The number of links in the linked list of strings
}; };
// NOTE: [$CSTR] Dqn_CStr8 ///////////////////////////////////////////////////////////////////////// enum DN_Str8BuilderAdd
template <Dqn_usize N> constexpr Dqn_usize Dqn_CStr8_ArrayUCount (char const (&literal)[N]) { (void)literal; return N - 1; } {
template <Dqn_usize N> constexpr Dqn_usize Dqn_CStr8_ArrayICount (char const (&literal)[N]) { (void)literal; return N - 1; } DN_Str8BuilderAdd_Append,
DQN_API Dqn_usize Dqn_CStr8_FSize (DQN_FMT_ATTRIB char const *fmt, ...); DN_Str8BuilderAdd_Prepend,
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);
// NOTE: [$STR6] Dqn_Str16 ///////////////////////////////////////////////////////////////////////// // NOTE: [$CSTR] DN_CStr8 /////////////////////////////////////////////////////////////////////////
#define DQN_STR16(string) Dqn_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1} template <DN_USize N> constexpr DN_USize DN_CStr8_ArrayUCount (char const (&literal)[N]) { (void)literal; return N - 1; }
#define Dqn_Str16_HasData(string) ((string).data && (string).size) template <DN_USize N> 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) #if defined(__cplusplus)
DQN_API bool operator== (Dqn_Str16 const &lhs, Dqn_Str16 const &rhs); DN_API bool operator== (DN_Str16 const &lhs, DN_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);
#endif #endif
// NOTE: [$STR8] Dqn_Str8 ////////////////////////////////////////////////////////////////////////// // NOTE: [$STR8] DN_Str8 //////////////////////////////////////////////////////////////////////////
#define DQN_STR8(string) Dqn_Str8{(char *)(string), (sizeof(string) - 1)} #define DN_STR8(string) DN_Str8{(char *)(string), (sizeof(string) - 1)}
#define DQN_STR_FMT(string) (int)((string).size), (string).data #define DN_STR_FMT(string) (int)((string).size), (string).data
#define Dqn_Str8_Init(data, size) Dqn_Str8{(char *)(data), (size_t)(size)} #define DN_Str8_Init(data, size) DN_Str8{(char *)(data), (size_t)(size)}
DQN_API Dqn_Str8 Dqn_Str8_InitCStr8 (char const *src); DN_API DN_Str8 DN_Str8_InitCStr8 (char const *src);
#define Dqn_Str8_HasData(string) ((string).data && (string).size) #define DN_Str8_HasData(string) ((string).data && (string).size)
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);
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, ...);
#define Dqn_Str8_InitF_TLS(...) Dqn_Str8_InitF(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_Str8_InitF_TLS(...) DN_Str8_InitF(DN_TLS_TopArena(), ##__VA_ARGS__)
DQN_API Dqn_Str8 Dqn_Str8_InitFV (Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args); #define DN_Str8_InitF_Frame(...) DN_Str8_InitF(DN_TLS_FrameArena(), ##__VA_ARGS__)
#define Dqn_Str8_InitFV_TLS(...) Dqn_Str8_InitFV(Dqn_TLS_TopArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_Str8_InitFV (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args);
DQN_API Dqn_Str8 Dqn_Str8_Alloc (Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem); #define DN_Str8_InitFV_TLS(...) DN_Str8_InitFV(DN_TLS_TopArena(), ##__VA_ARGS__)
#define Dqn_Str8_Alloc_TLS(...) Dqn_Str8_Alloc(Dqn_TLS_TopArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_Str8_Alloc (DN_Arena *arena, DN_USize size, DN_ZeroMem zero_mem);
DQN_API Dqn_Str8 Dqn_Str8_CopyCString (Dqn_Arena *arena, char const *string, Dqn_usize size); #define DN_Str8_Alloc_TLS(...) DN_Str8_Alloc(DN_TLS_TopArena(), ##__VA_ARGS__)
#define Dqn_Str8_CopyCString_TLS(...) Dqn_Str8_CopyCString(Dqn_TLS_TopArena(), ##__VA_ARGS__) DN_API DN_Str8 DN_Str8_CopyCString (DN_Arena *arena, char const *string, DN_USize size);
DQN_API Dqn_Str8 Dqn_Str8_Copy (Dqn_Arena *arena, Dqn_Str8 string); #define DN_Str8_CopyCString_TLS(...) DN_Str8_CopyCString(DN_TLS_TopArena(), ##__VA_ARGS__)
#define Dqn_Str8_Copy_TLS(...) Dqn_Str8_Copy(Dqn_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); DN_API char * DN_Str8_End (DN_Str8 string);
DQN_API Dqn_Str8 Dqn_Str8_Advance (Dqn_Str8 string, Dqn_usize amount); DN_API DN_Str8 DN_Str8_Slice (DN_Str8 string, DN_USize offset, DN_USize size);
DQN_API Dqn_Str8 Dqn_Str8_NextLine (Dqn_Str8 string); DN_API DN_Str8 DN_Str8_Advance (DN_Str8 string, DN_USize amount);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size); DN_API DN_Str8 DN_Str8_NextLine (DN_Str8 string);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplit (Dqn_Str8 string, Dqn_Str8 find); DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size); DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplit (DN_Str8 string, DN_Str8 find);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLast (Dqn_Str8 string, Dqn_Str8 find); DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size);
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_Str8BinarySplitResult DN_Str8_BinarySplitLast (DN_Str8 string, DN_Str8 find);
DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8_SplitAlloc (Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, 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);
#define Dqn_Str8_SplitAlloc_TLS(...) Dqn_Str8_SplitAlloc(Dqn_TLS_TopArena(), ##__VA_ARGS__) DN_API DN_Slice<DN_Str8> 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); DN_API DN_Str8FindResult DN_Str8_FindStr8Array (DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case);
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_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_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);
#define Dqn_Str8_Segment_TLS(...) Dqn_Str8_Segment(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_Str8_Segment_TLS(...) DN_Str8_Segment(DN_TLS_TopArena(), ##__VA_ARGS__)
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);
#define Dqn_Str8_ReverseSegment_TLS(...) Dqn_Str8_ReverseSegment(Dqn_TLS_TopArena(), ##__VA_ARGS__) #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); DN_API bool DN_Str8_Eq (DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DQN_API bool Dqn_Str8_EqInsensitive (Dqn_Str8 lhs, Dqn_Str8 rhs); DN_API bool DN_Str8_EqInsensitive (DN_Str8 lhs, DN_Str8 rhs);
DQN_API bool Dqn_Str8_StartsWith (Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); DN_API bool DN_Str8_StartsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DQN_API bool Dqn_Str8_StartsWithInsensitive (Dqn_Str8 string, Dqn_Str8 prefix); DN_API bool DN_Str8_StartsWithInsensitive (DN_Str8 string, DN_Str8 prefix);
DQN_API bool Dqn_Str8_EndsWith (Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); DN_API bool DN_Str8_EndsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DQN_API bool Dqn_Str8_EndsWithInsensitive (Dqn_Str8 string, Dqn_Str8 prefix); DN_API bool DN_Str8_EndsWithInsensitive (DN_Str8 string, DN_Str8 prefix);
DQN_API bool Dqn_Str8_HasChar (Dqn_Str8 string, char ch); 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); DN_API DN_Str8 DN_Str8_TrimPrefix (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DQN_API Dqn_Str8 Dqn_Str8_TrimHexPrefix (Dqn_Str8 string); DN_API DN_Str8 DN_Str8_TrimHexPrefix (DN_Str8 string);
DQN_API Dqn_Str8 Dqn_Str8_TrimSuffix (Dqn_Str8 string, Dqn_Str8 suffix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive); DN_API DN_Str8 DN_Str8_TrimSuffix (DN_Str8 string, DN_Str8 suffix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
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_API Dqn_Str8 Dqn_Str8_TrimWhitespaceAround (Dqn_Str8 string); DN_API DN_Str8 DN_Str8_TrimWhitespaceAround (DN_Str8 string);
DQN_API Dqn_Str8 Dqn_Str8_TrimByteOrderMark (Dqn_Str8 string); DN_API DN_Str8 DN_Str8_TrimByteOrderMark (DN_Str8 string);
DQN_API Dqn_Str8 Dqn_Str8_FileNameFromPath (Dqn_Str8 path); DN_API DN_Str8 DN_Str8_FileNameFromPath (DN_Str8 path);
DQN_API Dqn_Str8 Dqn_Str8_FileNameNoExtension (Dqn_Str8 path); DN_API DN_Str8 DN_Str8_FileNameNoExtension (DN_Str8 path);
DQN_API Dqn_Str8 Dqn_Str8_FilePathNoExtension (Dqn_Str8 path); DN_API DN_Str8 DN_Str8_FilePathNoExtension (DN_Str8 path);
DQN_API Dqn_Str8 Dqn_Str8_FileExtension (Dqn_Str8 path); DN_API DN_Str8 DN_Str8_FileExtension (DN_Str8 path);
DQN_API Dqn_Str8ToU64Result Dqn_Str8_ToU64 (Dqn_Str8 string, char separator); DN_API DN_Str8ToU64Result DN_Str8_ToU64 (DN_Str8 string, char separator);
DQN_API Dqn_Str8ToI64Result Dqn_Str8_ToI64 (Dqn_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); #define DN_Str8_AppendF_TLS(...) DN_Str8_AppendF(DN_TLS_TopArena(), ##__VA_ARGS__)
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_AppendF (DN_Arena *arena, DN_Str8 string, char const *fmt, ...);
DQN_API void Dqn_Str8_Remove (Dqn_Str8 *string, Dqn_usize offset, Dqn_usize size); 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) #if defined(__cplusplus)
DQN_API bool operator== (Dqn_Str8 const &lhs, Dqn_Str8 const &rhs); DN_API bool operator== (DN_Str8 const &lhs, DN_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);
#endif #endif
// NOTE: [$STRB] Dqn_Str8Builder /////////////////////////////////////////////////////////////////// // NOTE: [$STRB] DN_Str8Builder ///////////////////////////////////////////////////////////////////
DQN_API Dqn_Str8Builder Dqn_Str8Builder_Init (Dqn_Arena *arena); DN_API DN_Str8Builder DN_Str8Builder_Init (DN_Arena *arena);
#define Dqn_Str8Builder_Init_TLS() Dqn_Str8Builder_Init(Dqn_TLS_TopArena()) DN_API DN_Str8Builder DN_Str8Builder_Init_Frame () { return DN_Str8Builder_Init(DN_TLS_Get()->frame_arena); }
DQN_API Dqn_Str8Builder Dqn_Str8Builder_InitArrayRef (Dqn_Arena *arena, Dqn_Str8 const *strings, Dqn_usize size); #define DN_Str8Builder_Init_TLS() DN_Str8Builder_Init(DN_TLS_TopArena())
#define Dqn_Str8Builder_InitArrayRef_TLS(...) Dqn_Str8Builder_InitArrayRef(Dqn_TLS_TopArena(), ##__VA_ARGS__) DN_API DN_Str8Builder DN_Str8Builder_InitArrayRef (DN_Arena *arena, DN_Str8 const *strings, DN_USize size);
DQN_API Dqn_Str8Builder Dqn_Str8Builder_InitArrayCopy (Dqn_Arena *arena, Dqn_Str8 const *strings, Dqn_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 Dqn_Str8Builder_InitArrayCopy_TLS(...) Dqn_Str8Builder_InitArrayCopy(Dqn_TLS_TopArena(), ##__VA_ARGS__) #define DN_Str8Builder_InitArrayRef_TLS(...) DN_Str8Builder_InitArrayRef(DN_TLS_TopArena(), ##__VA_ARGS__)
template <Dqn_usize N> Dqn_Str8Builder Dqn_Str8Builder_InitCArrayRef (Dqn_Arena *arena, Dqn_Str8 const (&array)[N]); DN_API DN_Str8Builder DN_Str8Builder_InitArrayCopy (DN_Arena *arena, DN_Str8 const *strings, DN_USize size);
#define Dqn_Str8Builder_InitCArrayRef_TLS(...) Dqn_Str8Builder_InitCArrayRef(Dqn_TLS_TopArena(), ##__VA_ARGS__) 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); }
template <Dqn_usize N> Dqn_Str8Builder Dqn_Str8Builder_InitCArrayCopy (Dqn_Arena *arena, Dqn_Str8 const (&array)[N]); #define DN_Str8Builder_InitArrayCopy_TLS(...) DN_Str8Builder_InitArrayCopy(DN_TLS_TopArena(), ##__VA_ARGS__)
#define Dqn_Str8Builder_InitCArrayCopy_TLS(...) Dqn_Str8Builder_InitCArrayCopy(Dqn_TLS_TopArena(), ##__VA_ARGS__) template <DN_USize N> DN_Str8Builder DN_Str8Builder_InitCArrayRef (DN_Arena *arena, DN_Str8 const (&array)[N]);
DQN_API bool Dqn_Str8Builder_AddArrayRef (Dqn_Str8Builder *builder, Dqn_Str8 const *strings, Dqn_usize size); template <DN_USize N> DN_Str8Builder DN_Str8Builder_InitCArrayRef_Frame (DN_Str8 const (&array)[N]) { return DN_Str8Builder_InitCArrayRef(DN_TLS_Get()->frame_arena, array); }
DQN_API bool Dqn_Str8Builder_AddArrayCopy (Dqn_Str8Builder *builder, Dqn_Str8 const *strings, Dqn_usize size); #define DN_Str8Builder_InitCArrayRef_TLS(...) DN_Str8Builder_InitCArrayRef(DN_TLS_TopArena(), ##__VA_ARGS__)
template <Dqn_usize N> bool Dqn_Str8Builder_AddCArrayRef (Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]); template <DN_USize N> DN_Str8Builder DN_Str8Builder_InitCArrayCopy (DN_Arena *arena, DN_Str8 const (&array)[N]);
template <Dqn_usize N> bool Dqn_Str8Builder_AddCArrayCopy (Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]); template <DN_USize N> DN_Str8Builder DN_Str8Builder_InitCArrayCopy_Frame (DN_Str8 const (&array)[N]) { return DN_Str8Builder_InitCArrayCopy(DN_TLS_Get()->frame_arena, array); }
DQN_API bool Dqn_Str8Builder_AddSliceRef (Dqn_Str8Builder *builder, Dqn_Slice<Dqn_Str8> string); #define DN_Str8Builder_InitCArrayCopy_TLS(...) DN_Str8Builder_InitCArrayCopy(DN_TLS_TopArena(), ##__VA_ARGS__)
DQN_API bool Dqn_Str8Builder_AddSliceCopy (Dqn_Str8Builder *builder, Dqn_Slice<Dqn_Str8> 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_Str8> 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: [$FSTR] Dqn_FStr8 ////////////////////////////////////////////////////////////////////// DN_API bool DN_Str8Builder_AddArrayRef (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add);
#if !defined(DQN_NO_FSTR8) DN_API bool DN_Str8Builder_AddArrayCopy (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add);
template <Dqn_usize N> Dqn_FStr8<N> Dqn_FStr8_InitF (DQN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_Str8Builder_AddFV (DN_Str8Builder *builder, DN_Str8BuilderAdd add, DN_FMT_ATTRIB char const *fmt, va_list args);
template <Dqn_usize N> Dqn_usize Dqn_FStr8_Max (Dqn_FStr8<N> const *string);
template <Dqn_usize N> void Dqn_FStr8_Clear (Dqn_FStr8<N> *string);
template <Dqn_usize N> bool Dqn_FStr8_AddFV (Dqn_FStr8<N> *string, DQN_FMT_ATTRIB char const *fmt, va_list va);
template <Dqn_usize N> bool Dqn_FStr8_AddF (Dqn_FStr8<N> *string, DQN_FMT_ATTRIB char const *fmt, ...);
template <Dqn_usize N> bool Dqn_FStr8_AddCStr8 (Dqn_FStr8<N> *string, char const *value, Dqn_usize size);
template <Dqn_usize N> bool Dqn_FStr8_Add (Dqn_FStr8<N> *string, Dqn_Str8 value);
template <Dqn_usize N> Dqn_Str8 Dqn_FStr8_ToStr8 (Dqn_FStr8<N> const *string);
template <Dqn_usize N> bool Dqn_FStr8_Eq (Dqn_FStr8<N> const *lhs, Dqn_FStr8<N> const *rhs, Dqn_Str8EqCase eq_case);
template <Dqn_usize N> bool Dqn_FStr8_EqStr8 (Dqn_FStr8<N> const *lhs, Dqn_Str8 rhs, Dqn_Str8EqCase eq_case);
template <Dqn_usize N> bool Dqn_FStr8_EqInsensitive (Dqn_FStr8<N> const *lhs, Dqn_FStr8<N> const *rhs);
template <Dqn_usize N> bool Dqn_FStr8_EqStr8Insensitive (Dqn_FStr8<N> const *lhs, Dqn_Str8 rhs);
template <Dqn_usize A, Dqn_usize B> bool Dqn_FStr8_EqFStr8 (Dqn_FStr8<A> const *lhs, Dqn_FStr8<B> const *rhs, Dqn_Str8EqCase eq_case);
template <Dqn_usize A, Dqn_usize B> bool Dqn_FStr8_EqFStr8Insensitive (Dqn_FStr8<A> const *lhs, Dqn_FStr8<B> const *rhs);
template <Dqn_usize N> bool operator== (Dqn_FStr8<N> const &lhs, Dqn_FStr8<N> const &rhs);
template <Dqn_usize N> bool operator!= (Dqn_FStr8<N> const &lhs, Dqn_FStr8<N> const &rhs);
#endif // !defined(DQN_NO_FSTR8)
// NOTE: [$CHAR] Dqn_Char ////////////////////////////////////////////////////////////////////////// #define DN_Str8Builder_AppendArrayRef(builder, strings, size) DN_Str8Builder_AddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Append)
struct Dqn_CharHexToU8 #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_Str8> 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_USize N> DN_FStr8<N> DN_FStr8_InitF (DN_FMT_ATTRIB char const *fmt, ...);
template <DN_USize N> DN_FStr8<N> DN_FStr8_InitFV (char const *fmt, va_list args);
template <DN_USize N> DN_USize DN_FStr8_Max (DN_FStr8<N> const *string);
template <DN_USize N> void DN_FStr8_Clear (DN_FStr8<N> *string);
template <DN_USize N> bool DN_FStr8_AddFV (DN_FStr8<N> *string, DN_FMT_ATTRIB char const *fmt, va_list va);
template <DN_USize N> bool DN_FStr8_AddF (DN_FStr8<N> *string, DN_FMT_ATTRIB char const *fmt, ...);
template <DN_USize N> bool DN_FStr8_AddCStr8 (DN_FStr8<N> *string, char const *value, DN_USize size);
template <DN_USize N> bool DN_FStr8_Add (DN_FStr8<N> *string, DN_Str8 value);
template <DN_USize N> DN_Str8 DN_FStr8_ToStr8 (DN_FStr8<N> const *string);
template <DN_USize N> bool DN_FStr8_Eq (DN_FStr8<N> const *lhs, DN_FStr8<N> const *rhs, DN_Str8EqCase eq_case);
template <DN_USize N> bool DN_FStr8_EqStr8 (DN_FStr8<N> const *lhs, DN_Str8 rhs, DN_Str8EqCase eq_case);
template <DN_USize N> bool DN_FStr8_EqInsensitive (DN_FStr8<N> const *lhs, DN_FStr8<N> const *rhs);
template <DN_USize N> bool DN_FStr8_EqStr8Insensitive (DN_FStr8<N> const *lhs, DN_Str8 rhs);
template <DN_USize A, DN_USize B> bool DN_FStr8_EqFStr8 (DN_FStr8<A> const *lhs, DN_FStr8<B> const *rhs, DN_Str8EqCase eq_case);
template <DN_USize A, DN_USize B> bool DN_FStr8_EqFStr8Insensitive (DN_FStr8<A> const *lhs, DN_FStr8<B> const *rhs);
template <DN_USize N> bool operator== (DN_FStr8<N> const &lhs, DN_FStr8<N> const &rhs);
template <DN_USize N> bool operator!= (DN_FStr8<N> const &lhs, DN_FStr8<N> const &rhs);
template <DN_USize N> bool operator== (DN_FStr8<N> const &lhs, DN_Str8 const &rhs);
template <DN_USize N> bool operator!= (DN_FStr8<N> const &lhs, DN_Str8 const &rhs);
#endif // !defined(DN_NO_FSTR8)
// NOTE: [$CHAR] DN_Char //////////////////////////////////////////////////////////////////////////
struct DN_CharHexToU8
{ {
bool success; bool success;
uint8_t value; uint8_t value;
}; };
DQN_API bool Dqn_Char_IsAlphabet (char ch); DN_API bool DN_Char_IsAlphabet (char ch);
DQN_API bool Dqn_Char_IsDigit (char ch); DN_API bool DN_Char_IsDigit (char ch);
DQN_API bool Dqn_Char_IsAlphaNum (char ch); DN_API bool DN_Char_IsAlphaNum (char ch);
DQN_API bool Dqn_Char_IsWhitespace (char ch); DN_API bool DN_Char_IsWhitespace (char ch);
DQN_API bool Dqn_Char_IsHex (char ch); DN_API bool DN_Char_IsHex (char ch);
DQN_API Dqn_CharHexToU8 Dqn_Char_HexToU8 (char ch); DN_API DN_CharHexToU8 DN_Char_HexToU8 (char ch);
DQN_API char Dqn_Char_ToHex (char ch); DN_API char DN_Char_ToHex (char ch);
DQN_API char Dqn_Char_ToHexUnchecked (char ch); DN_API char DN_Char_ToHexUnchecked (char ch);
DQN_API char Dqn_Char_ToLower (char ch); DN_API char DN_Char_ToLower (char ch);
DN_API char DN_Char_ToUpper (char ch);
// NOTE: [$UTFX] Dqn_UTF /////////////////////////////////////////////////////////////////////////// // NOTE: [$UTFX] DN_UTF ///////////////////////////////////////////////////////////////////////////
DQN_API int Dqn_UTF8_EncodeCodepoint (uint8_t utf8[4], uint32_t codepoint); DN_API int DN_UTF8_EncodeCodepoint (uint8_t utf8[4], uint32_t codepoint);
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: [$STRB] Dqn_Str8Builder /////////////////////////////////////////////////////////////////// // NOTE: [$STRB] DN_Str8Builder ///////////////////////////////////////////////////////////////////
template <Dqn_usize N> Dqn_Str8Builder Dqn_Str8Builder_InitCArrayRef(Dqn_Arena *arena, Dqn_Str8 const (&array)[N]) template <DN_USize N> 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; return result;
} }
template <Dqn_usize N> Dqn_Str8Builder Dqn_Str8Builder_InitCArrayCopy(Dqn_Arena *arena, Dqn_Str8 const (&array)[N]) template <DN_USize N> 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; return result;
} }
template <Dqn_usize N> bool Dqn_Str8Builder_AddCArrayRef(Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]) template <DN_USize N> 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; return result;
} }
template <Dqn_usize N> bool Dqn_Str8Builder_AddCArrayCopy(Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]) template <DN_USize N> 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; return result;
} }
#if !defined(DQN_NO_FSTR8) #if !defined(DN_NO_FSTR8)
// NOTE: [$FSTR] Dqn_FStr8 ///////////////////////////////////////////////////////////////////////// // NOTE: [$FSTR] DN_FStr8 /////////////////////////////////////////////////////////////////////////
template <Dqn_usize N> Dqn_FStr8<N> Dqn_FStr8_InitF(DQN_FMT_ATTRIB char const *fmt, ...) template <DN_USize N> DN_FStr8<N> DN_FStr8_InitF(DN_FMT_ATTRIB char const *fmt, ...)
{ {
Dqn_FStr8<N> result = {}; DN_FStr8<N> result = {};
if (fmt) { if (fmt) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
Dqn_FStr8_AddFV(&result, fmt, args); DN_FStr8_AddFV(&result, fmt, args);
va_end(args); va_end(args);
} }
return result; return result;
} }
template <Dqn_usize N> Dqn_usize Dqn_FStr8_Max(Dqn_FStr8<N> const *) template <DN_USize N> DN_FStr8<N> DN_FStr8_InitFV(char const *fmt, va_list args)
{ {
Dqn_usize result = N; DN_FStr8<N> result = {};
DN_FStr8_AddFV(&result, fmt, args);
return result; return result;
} }
template <Dqn_usize N> void Dqn_FStr8_Clear(Dqn_FStr8<N> *string) template <DN_USize N> DN_USize DN_FStr8_Max(DN_FStr8<N> const *)
{
DN_USize result = N;
return result;
}
template <DN_USize N> void DN_FStr8_Clear(DN_FStr8<N> *string)
{ {
*string = {}; *string = {};
} }
template <Dqn_usize N> bool Dqn_FStr8_AddFV(Dqn_FStr8<N> *string, DQN_FMT_ATTRIB char const *fmt, va_list args) template <DN_USize N> bool DN_FStr8_AddFV(DN_FStr8<N> *string, DN_FMT_ATTRIB char const *fmt, va_list args)
{ {
bool result = false; bool result = false;
if (!string || !fmt) if (!string || !fmt)
return result; return result;
Dqn_usize require = Dqn_CStr8_FVSize(fmt, args) + 1 /*null_terminate*/; DN_USize require = DN_CStr8_FVSize(fmt, args) + 1 /*null_terminate*/;
Dqn_usize space = (N + 1) - string->size; DN_USize space = (N + 1) - string->size;
result = require <= space; 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 // NOTE: snprintf returns the required size of the format string
// irrespective of if there's space or not. // irrespective of if there's space or not.
string->size = DQN_MIN(string->size, N); string->size = DN_MIN(string->size, N);
return result; return result;
} }
template <Dqn_usize N> bool Dqn_FStr8_AddF(Dqn_FStr8<N> *string, DQN_FMT_ATTRIB char const *fmt, ...) template <DN_USize N> bool DN_FStr8_AddF(DN_FStr8<N> *string, DN_FMT_ATTRIB char const *fmt, ...)
{ {
bool result = false; bool result = false;
if (!string || !fmt) if (!string || !fmt)
return result; return result;
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
result = Dqn_FStr8_AddFV(string, fmt, args); result = DN_FStr8_AddFV(string, fmt, args);
va_end(args); va_end(args);
return result; return result;
} }
template <Dqn_usize N> bool Dqn_FStr8_AddCStr8(Dqn_FStr8<N> *string, char const *src, Dqn_usize size) template <DN_USize N> bool DN_FStr8_AddCStr8(DN_FStr8<N> *string, char const *src, DN_USize size)
{ {
DQN_ASSERT(string->size <= N); DN_ASSERT(string->size <= N);
bool result = false; bool result = false;
if (!string || !src || size == 0 || string->size >= N) if (!string || !src || size == 0 || string->size >= N)
return result; return result;
Dqn_usize space = N - string->size; DN_USize space = N - string->size;
result = size <= space; result = size <= space;
DQN_MEMCPY(string->data + string->size, src, DQN_MIN(space, size)); DN_MEMCPY(string->data + string->size, src, DN_MIN(space, size));
string->size = DQN_MIN(string->size + size, N); string->size = DN_MIN(string->size + size, N);
string->data[string->size] = 0; string->data[string->size] = 0;
return result; return result;
} }
template <Dqn_usize N> bool Dqn_FStr8_Add(Dqn_FStr8<N> *string, Dqn_Str8 src) template <DN_USize N> bool DN_FStr8_Add(DN_FStr8<N> *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; return result;
} }
template <Dqn_usize N> Dqn_Str8 Dqn_FStr8_ToStr8(Dqn_FStr8<N> const *string) template <DN_USize N> DN_Str8 DN_FStr8_ToStr8(DN_FStr8<N> const *string)
{ {
Dqn_Str8 result = {}; DN_Str8 result = {};
if (!string || string->size <= 0) if (!string || string->size <= 0)
return result; return result;
result.data = DQN_CAST(char *)string->data; result.data = DN_CAST(char *)string->data;
result.size = string->size; result.size = string->size;
return result; return result;
} }
template <Dqn_usize N> bool Dqn_FStr8_Eq(Dqn_FStr8<N> const *lhs, Dqn_FStr8<N> const *rhs, Dqn_Str8EqCase eq_case) template <DN_USize N> bool DN_FStr8_Eq(DN_FStr8<N> const *lhs, DN_FStr8<N> const *rhs, DN_Str8EqCase eq_case)
{ {
Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs); DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs);
bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, eq_case); bool result = DN_Str8_Eq(lhs_s8, rhs_s8, eq_case);
return result; return result;
} }
template <Dqn_usize N> bool Dqn_FStr8_EqStr8(Dqn_FStr8<N> const *lhs, Dqn_Str8 rhs, Dqn_Str8EqCase eq_case) template <DN_USize N> bool DN_FStr8_EqStr8(DN_FStr8<N> const *lhs, DN_Str8 rhs, DN_Str8EqCase eq_case)
{ {
Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
bool result = Dqn_Str8_Eq(lhs_s8, rhs, eq_case); bool result = DN_Str8_Eq(lhs_s8, rhs, eq_case);
return result; return result;
} }
template <Dqn_usize N> bool Dqn_FStr8_EqInsensitive(Dqn_FStr8<N> const *lhs, Dqn_FStr8<N> const *rhs) template <DN_USize N> bool DN_FStr8_EqInsensitive(DN_FStr8<N> const *lhs, DN_FStr8<N> const *rhs)
{ {
Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs); DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs);
bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, Dqn_Str8EqCase_Insensitive); bool result = DN_Str8_Eq(lhs_s8, rhs_s8, DN_Str8EqCase_Insensitive);
return result; return result;
} }
template <Dqn_usize N> bool Dqn_FStr8_EqStr8Insensitive(Dqn_FStr8<N> const *lhs, Dqn_Str8 rhs) template <DN_USize N> bool DN_FStr8_EqStr8Insensitive(DN_FStr8<N> const *lhs, DN_Str8 rhs)
{ {
Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
bool result = Dqn_Str8_Eq(lhs_s8, rhs, Dqn_Str8EqCase_Insensitive); bool result = DN_Str8_Eq(lhs_s8, rhs, DN_Str8EqCase_Insensitive);
return result; return result;
} }
template <Dqn_usize A, Dqn_usize B> bool Dqn_FStr8_EqFStr8(Dqn_FStr8<A> const *lhs, Dqn_FStr8<B> const *rhs, Dqn_Str8EqCase eq_case) template <DN_USize A, DN_USize B> bool DN_FStr8_EqFStr8(DN_FStr8<A> const *lhs, DN_FStr8<B> const *rhs, DN_Str8EqCase eq_case)
{ {
Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs); DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs);
bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, eq_case); bool result = DN_Str8_Eq(lhs_s8, rhs_s8, eq_case);
return result; return result;
} }
template <Dqn_usize A, Dqn_usize B> bool Dqn_FStr8_EqFStr8Insensitive(Dqn_FStr8<A> const *lhs, Dqn_FStr8<B> const *rhs) template <DN_USize A, DN_USize B> bool DN_FStr8_EqFStr8Insensitive(DN_FStr8<A> const *lhs, DN_FStr8<B> const *rhs)
{ {
Dqn_Str8 lhs_s8 = Dqn_FStr8_ToStr8(lhs); DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs); DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs);
bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, Dqn_Str8EqCase_Insensitive); bool result = DN_Str8_Eq(lhs_s8, rhs_s8, DN_Str8EqCase_Insensitive);
return result; return result;
} }
template <Dqn_usize N> bool operator==(Dqn_FStr8<N> const &lhs, Dqn_FStr8<N> const &rhs) template <DN_USize N> bool operator==(DN_FStr8<N> const &lhs, DN_FStr8<N> const &rhs)
{ {
bool result = Dqn_FStr8_Eq(&lhs, &rhs, Dqn_Str8EqCase_Sensitive); bool result = DN_FStr8_Eq(&lhs, &rhs, DN_Str8EqCase_Sensitive);
return result; return result;
} }
template <Dqn_usize N> bool operator!=(Dqn_FStr8<N> const &lhs, Dqn_FStr8<N> const &rhs) template <DN_USize N> bool operator!=(DN_FStr8<N> const &lhs, DN_FStr8<N> const &rhs)
{ {
bool result = !(lhs == rhs); bool result = !(lhs == rhs);
return result; return result;
} }
#endif // !defined(DQN_NO_FSTR8)
template <DN_USize N> bool operator==(DN_FStr8<N> const &lhs, DN_Str8 const &rhs)
{
bool result = DN_Str8_Eq(DN_FStr8_ToStr8(&lhs), rhs, DN_Str8EqCase_Insensitive);
return result;
}
template <DN_USize N> bool operator!=(DN_FStr8<N> const &lhs, DN_Str8 const &rhs)
{
bool result = !(lhs == rhs);
return result;
}
#endif // !defined(DN_NO_FSTR8)

View File

@ -18,109 +18,133 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: [$TCTX] Dqn_TLS ///////////////////////////////////////////////////////////////// // NOTE: [$TCTX] DN_TLS /////////////////////////////////////////////////////////////////
Dqn_TLSTMem::Dqn_TLSTMem(Dqn_TLS *tls, uint8_t arena_index, Dqn_TLSPushTMem push_tmem) 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; arena = tls->arenas + arena_index;
temp_mem = Dqn_Arena_TempMemBegin(arena); temp_mem = DN_Arena_TempMemBegin(arena);
destructed = false; destructed = false;
push_arena = push_tmem; push_arena = push_tmem;
if (push_arena) if (push_arena)
Dqn_TLS_PushArena(arena); DN_TLS_PushArena(arena);
} }
Dqn_TLSTMem::~Dqn_TLSTMem() DN_TLSTMem::~DN_TLSTMem()
{ {
DQN_ASSERT(destructed == false); DN_ASSERT(destructed == false);
Dqn_Arena_TempMemEnd(temp_mem); DN_Arena_TempMemEnd(temp_mem);
destructed = true; destructed = true;
if (push_arena) 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) if (tls->init)
return; return;
DQN_FOR_UINDEX (index, Dqn_TLSArena_Count) { DN_FOR_UINDEX (index, DN_TLSArena_Count) {
Dqn_Arena *arena = tls->arenas + index; DN_Arena *arena = tls->arenas + index;
switch (DQN_CAST(Dqn_TLSArena)index) { switch (DN_CAST(DN_TLSArena)index) {
default: *arena = Dqn_Arena_InitSize(DQN_MEGABYTES(4), DQN_KILOBYTES(4), Dqn_ArenaFlag_AllocCanLeak); break; default: *arena = DN_Arena_InitSize(DN_MEGABYTES(4), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); break;
case Dqn_TLSArena_ErrorSink: *arena = Dqn_Arena_InitSize(DQN_KILOBYTES(64), DQN_KILOBYTES(4), Dqn_ArenaFlag_AllocCanLeak); break; case DN_TLSArena_ErrorSink: *arena = DN_Arena_InitSize(DN_KILOBYTES(64), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); break;
case Dqn_TLSArena_Count: DQN_INVALID_CODE_PATH; break; case DN_TLSArena_Count: DN_INVALID_CODE_PATH; break;
} }
} }
tls->thread_id = Dqn_OS_ThreadID(); tls->thread_id = DN_OS_ThreadID();
tls->error_sink.arena = tls->arenas + Dqn_TLSArena_ErrorSink; tls->err_sink.arena = tls->arenas + DN_TLSArena_ErrorSink;
tls->init = true; 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; tls->init = false;
// TODO(doyle): Fix stack-trace infinite loop with requiring the TLS that is not initialised tls->err_sink = {};
// yet. tls->arena_stack_index = {};
DQN_ASSERT( DN_FOR_UINDEX(index, DN_TLSArena_Count)
g_dqn_library->lib_init && {
"Library context must be be initialised first by calling Dqn_Library_Init. This " DN_Arena *arena = tls->arenas + index;
"initialises the main thread's TLS for you (no need to call Dqn_OS_ThreadSetTLS on main)"); DN_Arena_Deinit(arena);
}
}
DQN_ASSERT(result && DN_API DN_TLS *DN_TLS_Get()
"Thread must be assigned the TLS with Dqn_OS_ThreadSetTLS. If the library is " {
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 " "initialised, then, this thread was created without calling the set TLS function "
"for the spawned thread."); "for the spawned thread.");
return result; return result;
} }
DQN_API Dqn_Arena *Dqn_TLS_Arena() DN_API DN_Arena *DN_TLS_Arena()
{ {
Dqn_TLS *tls = Dqn_TLS_Get(); DN_TLS *tls = DN_TLS_Get();
Dqn_Arena *result = tls->arenas + Dqn_TLSArena_Main; DN_Arena *result = tls->arenas + DN_TLSArena_Main;
return result; return result;
} }
// TODO: Is there a way to handle conflict arenas without the user needing to // TODO: Is there a way to handle conflict arenas without the user needing to
// manually pass it in? // 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; uint8_t tls_index = (uint8_t)-1;
for (uint8_t index = Dqn_TLSArena_TMem0; index <= Dqn_TLSArena_TMem1; index++) { for (uint8_t index = DN_TLSArena_TMem0; index <= DN_TLSArena_TMem1; index++) {
Dqn_Arena *arena = tls->arenas + index; DN_Arena *arena = tls->arenas + index;
if (!conflict_arena || arena != conflict_arena) { if (!conflict_arena || arena != conflict_arena) {
tls_index = index; tls_index = index;
break; break;
} }
} }
DQN_ASSERT(tls_index != (uint8_t)-1); DN_ASSERT(tls_index != (uint8_t)-1);
return Dqn_TLSTMem(tls, tls_index, push_tmem); 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); DN_ASSERT(arena);
Dqn_TLS *tls = Dqn_TLS_Get(); DN_TLS *tls = DN_TLS_Get();
DQN_ASSERT(tls->arena_stack_index < DQN_ARRAY_UCOUNT(tls->arena_stack)); DN_ASSERT(tls->arena_stack_index < DN_ARRAY_UCOUNT(tls->arena_stack));
tls->arena_stack[tls->arena_stack_index++] = arena; 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(); DN_TLS *tls = DN_TLS_Get();
DQN_ASSERT(tls->arena_stack_index > 0); DN_ASSERT(tls->arena_stack_index > 0);
tls->arena_stack_index--; tls->arena_stack_index--;
} }
DQN_API Dqn_Arena *Dqn_TLS_TopArena() DN_API DN_Arena *DN_TLS_TopArena()
{ {
Dqn_TLS *tls = Dqn_TLS_Get(); DN_TLS *tls = DN_TLS_Get();
Dqn_Arena *result = nullptr; DN_Arena *result = nullptr;
if (tls->arena_stack_index) if (tls->arena_stack_index)
result = tls->arena_stack[tls->arena_stack_index - 1]; result = tls->arena_stack[tls->arena_stack_index - 1];
return result; 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;
}

View File

@ -27,58 +27,67 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
enum Dqn_TLSArena enum DN_TLSArena
{ {
Dqn_TLSArena_Main, // NOTE: Arena for Permanent allocations DN_TLSArena_Main, // NOTE: Arena for Permanent allocations
Dqn_TLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread DN_TLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread
// NOTE: Per-thread scratch arenas (2 to prevent aliasing) // NOTE: Per-thread scratch arenas (2 to prevent aliasing)
Dqn_TLSArena_TMem0, DN_TLSArena_TMem0,
Dqn_TLSArena_TMem1, 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 DN_B32 init; // Flag to track if Thread has been initialised
uint64_t thread_id; uint64_t thread_id;
Dqn_CallSite call_site; // Stores call-site information when requested by thread DN_CallSite call_site; // Stores call-site information when requested by thread
Dqn_ErrorSink error_sink; // Error handling state DN_ErrSink err_sink; // Error handling state
Dqn_Arena arenas[Dqn_TLSArena_Count]; DN_Arena arenas[DN_TLSArena_Count];
// Push and pop arenas onto the stack. Functions suffixed 'TLS' will use // Push and pop arenas onto the stack. Functions suffixed 'TLS' will use
// these arenas for memory allocation. // these arenas for memory allocation.
Dqn_Arena *arena_stack[8]; DN_Arena *arena_stack[8];
Dqn_usize arena_stack_index; 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 // 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 // out of scope. Pushed arenas are used automatically as the allocator in TLS
// suffixed function. // suffixed function.
enum Dqn_TLSPushTMem enum DN_TLSPushTMem
{ {
Dqn_TLSPushTMem_No, DN_TLSPushTMem_No,
Dqn_TLSPushTMem_Yes, DN_TLSPushTMem_Yes,
}; };
struct Dqn_TLSTMem struct DN_TLSTMem
{ {
Dqn_TLSTMem(Dqn_TLS *context, uint8_t context_index, Dqn_TLSPushTMem push_scratch); DN_TLSTMem(DN_TLS *context, uint8_t context_index, DN_TLSPushTMem push_scratch);
~Dqn_TLSTMem(); ~DN_TLSTMem();
Dqn_Arena *arena; DN_Arena *arena;
Dqn_b32 destructed; DN_B32 destructed;
Dqn_TLSPushTMem push_arena; DN_TLSPushTMem push_arena;
Dqn_ArenaTempMem temp_mem; DN_ArenaTempMem temp_mem;
}; };
DQN_API void Dqn_TLS_Init(Dqn_TLS *tls); DN_API void DN_TLS_Init(DN_TLS *tls);
DQN_API Dqn_TLS * Dqn_TLS_Get(); DN_API void DN_TLS_Deinit(DN_TLS *tls);
#define Dqn_TLS_SaveCallSite do { Dqn_TLS_Get()->call_site = DQN_CALL_SITE; } while (0) DN_API DN_TLS * DN_TLS_Get();
DQN_API Dqn_TLSTMem Dqn_TLS_GetTMem(void const *conflict_arena, Dqn_TLSPushTMem push_tmp_mem); DN_API DN_Arena * DN_TLS_Arena();
#define Dqn_TLS_TMem(...) Dqn_TLS_GetTMem(__VA_ARGS__, Dqn_TLSPushTMem_No) #define DN_TLS_SaveCallSite do { DN_TLS_Get()->call_site = DN_CALL_SITE; } while (0)
#define Dqn_TLS_PushTMem(...) Dqn_TLS_GetTMem(__VA_ARGS__, Dqn_TLSPushTMem_Yes) DN_API DN_TLSTMem DN_TLS_GetTMem(void const *conflict_arena, DN_TLSPushTMem push_tmp_mem);
DQN_API void Dqn_TLS_PushArena(Dqn_Arena *arena); #define DN_TLS_TMem(...) DN_TLS_GetTMem(__VA_ARGS__, DN_TLSPushTMem_No)
DQN_API void Dqn_TLS_PopArena(); #define DN_TLS_PushTMem(...) DN_TLS_GetTMem(__VA_ARGS__, DN_TLSPushTMem_Yes)
DQN_API Dqn_Arena * Dqn_TLS_TopArena(); 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();

View File

@ -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 = {}; DN_TypeGetField result = {};
for (Dqn_usize index = 0; index < type_info->fields_count; index++) { for (DN_USize index = 0; index < type_info->fields_count; index++) {
Dqn_TypeField const *type_field = type_info->fields + index; DN_TypeField const *type_field = type_info->fields + index;
if (type_field->name == name) { if (type_field->name == name) {
result.success = true; result.success = true;
result.index = index; result.index = index;
result.field = DQN_CAST(Dqn_TypeField *)type_field; result.field = DN_CAST(DN_TypeField *)type_field;
break; break;
} }
} }

View File

@ -18,44 +18,44 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
enum Dqn_TypeKind enum DN_TypeKind
{ {
Dqn_TypeKind_Nil, DN_TypeKind_Nil,
Dqn_TypeKind_Basic, DN_TypeKind_Basic,
Dqn_TypeKind_Enum, DN_TypeKind_Enum,
Dqn_TypeKind_Struct, DN_TypeKind_Struct,
}; };
struct Dqn_TypeField struct DN_TypeField
{ {
uint16_t index; uint16_t index;
Dqn_Str8 name; DN_Str8 name;
Dqn_Str8 label; DN_Str8 label;
Dqn_isize value; DN_ISize value;
Dqn_usize offset_of; DN_USize offset_of;
Dqn_usize size_of; DN_USize size_of;
Dqn_usize align_of; DN_USize align_of;
Dqn_Str8 type_decl; DN_Str8 type_decl;
uint32_t type_enum; uint32_t type_enum;
bool is_pointer; bool is_pointer;
uint16_t array_size; uint16_t array_size;
Dqn_TypeField const * array_size_field; DN_TypeField const * array_size_field;
}; };
struct Dqn_TypeInfo struct DN_TypeInfo
{ {
Dqn_Str8 name; DN_Str8 name;
Dqn_TypeKind kind; DN_TypeKind kind;
Dqn_usize size_of; DN_USize size_of;
Dqn_TypeField const *fields; DN_TypeField const *fields;
uint16_t fields_count; uint16_t fields_count;
}; };
struct Dqn_TypeGetField struct DN_TypeGetField
{ {
bool success; bool success;
Dqn_usize index; DN_USize index;
Dqn_TypeField *field; 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);

File diff suppressed because it is too large Load Diff

12
dqn_unit_tests_main.cpp Normal file
View File

@ -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;
}

View File

@ -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, "bcrypt")
#pragma comment(lib, "winhttp") #pragma comment(lib, "winhttp")
#pragma comment(lib, "dbghelp") #pragma comment(lib, "dbghelp")
@ -27,18 +27,19 @@
#pragma comment(lib, "shlwapi") #pragma comment(lib, "shlwapi")
#endif #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 #define WIN32_LEAN_AND_MEAN
#include <Windows.h> // LONG #include <Windows.h> // LONG
#include <bcrypt.h> // Dqn_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc #include <bcrypt.h> // DN_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc
#include <shellapi.h> // Dqn_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc #include <shellapi.h> // DN_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc
#include <shlwapi.h> // PathRelativePathTO #include <shlwapi.h> // PathRelativePathTO
#include <pathcch.h> // PathCchCanonicalizeEx #include <pathcch.h> // PathCchCanonicalizeEx
#include <winhttp.h> // WinHttp* #include <winhttp.h> // WinHttp*
#include <commdlg.h> // OPENFILENAMEW
#include <DbgHelp.h> #include <DbgHelp.h>
#else #else
DQN_MSVC_WARNING_PUSH DN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
// NOTE: basetsd.h ///////////////////////////////////////////////////////////////////////////// // NOTE: basetsd.h /////////////////////////////////////////////////////////////////////////////
typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
@ -111,6 +112,25 @@
#define PAGE_READWRITE 0x04 #define PAGE_READWRITE 0x04
#define PAGE_GUARD 0x100 #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 // NOTE: FormatMessageA
#define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p)) #define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p))
#define LANG_NEUTRAL 0x00 #define LANG_NEUTRAL 0x00
@ -331,6 +351,19 @@
__declspec(dllimport) BOOL __stdcall SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll); __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 //////////////////////////////////////////////////////////////////// // NOTE: shared/windef.h ////////////////////////////////////////////////////////////////////
typedef struct tagPOINT typedef struct tagPOINT
{ {
@ -367,6 +400,10 @@
#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 ) #define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
#define WAIT_ABANDONED_0 ((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 { typedef enum _GET_FILEEX_INFO_LEVELS {
GetFileExInfoStandard, GetFileExInfoStandard,
GetFileExMaxInfoLevel GetFileExMaxInfoLevel
@ -499,9 +536,12 @@
extern "C" extern "C"
{ {
__declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile);
__declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes); __declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes);
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName); __declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData); __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) 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 GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize); __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) 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 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); __declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped);
} }
// NOTE: um/processenv.h /////////////////////////////////////////////////////////////////////// // NOTE: um/processenv.h ///////////////////////////////////////////////////////////////////////
extern "C" extern "C"
{ {
__declspec(dllimport) DWORD __stdcall GetCurrentDirectoryW(DWORD nBufferLength, WCHAR *lpBuffer); __declspec(dllimport) DWORD __stdcall GetCurrentDirectoryW (DWORD nBufferLength, WCHAR *lpBuffer);
__declspec(dllimport) HANDLE __stdcall GetStdHandle(DWORD nStdHandle); __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 /////////////////////////////////////////////////////////////////////// // NOTE: um/sysinfoapi.h ///////////////////////////////////////////////////////////////////////
@ -548,10 +591,21 @@
} }
// NOTE: um/timezoneapi.h ////////////////////////////////////////////////////////////////////// // 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" extern "C"
{ {
__declspec(dllimport) BOOL __stdcall FileTimeToSystemTime(const FILETIME* lpFileTime, SYSTEMTIME *lpSystemTime); __declspec(dllimport) BOOL __stdcall FileTimeToSystemTime (const FILETIME* lpFileTime, SYSTEMTIME *lpSystemTime);
__declspec(dllimport) BOOL __stdcall SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, FILETIME *lpFileTime); __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 /////////////////////////////////////////////////////////////////////// // NOTE: shared/windef.h ///////////////////////////////////////////////////////////////////////
@ -1249,5 +1303,16 @@
__declspec(dllimport) HRESULT __stdcall PathCchCanonicalizeEx(PWSTR pszPathOut, size_t cchPathOut, WCHAR const *pszPathIn, ULONG dwFlags); __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) #endif // !defined(_INC_WINDOWS)