Get latest DQN lib from side projects
This commit is contained in:
parent
6b403eae71
commit
a844d2b992
@ -10,257 +10,257 @@
|
||||
// \$$$$$$ |$$ | $$ | $$ | $$$$$$\ $$$$$$$$\ $$$$$$$$\
|
||||
// \______/ \__| \__| \__| \______|\________|\________|
|
||||
//
|
||||
// dqn_cpp_file.h -- Functions to emit C++ formatted code
|
||||
// dn_cpp_file.h -- Functions to emit C++ formatted code
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
#if !defined(DQN_CPP_FILE_H)
|
||||
#define DQN_CPP_FILE_H
|
||||
#if !defined(DN_CPP_FILE_H)
|
||||
#define DN_CPP_FILE_H
|
||||
|
||||
#include <stdio.h> /// printf, fputc
|
||||
#include <stdarg.h> /// va_list...
|
||||
#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
|
||||
int indent; ///< Current indent level of the printer
|
||||
int space_per_indent; ///< (Write) Number of spaces per indent
|
||||
unsigned char if_chain[256]; ///
|
||||
unsigned char if_chain_size; ///
|
||||
} Dqn_CppFile;
|
||||
} DN_CppFile;
|
||||
|
||||
#define Dqn_CppSpacePerIndent(cpp) ((cpp) && (cpp)->space_per_indent) ? ((cpp)->space_per_indent) : 4
|
||||
#define DN_CppSpacePerIndent(cpp) ((cpp) && (cpp)->space_per_indent) ? ((cpp)->space_per_indent) : 4
|
||||
|
||||
/// Print the format string indented and terminate the string with a new-line.
|
||||
void Dqn_CppLineV(Dqn_CppFile *cpp, char const *fmt, va_list args);
|
||||
void Dqn_CppLine(Dqn_CppFile *cpp, char const *fmt, ...);
|
||||
void DN_CppLineV(DN_CppFile *cpp, char const *fmt, va_list args);
|
||||
void DN_CppLine(DN_CppFile *cpp, char const *fmt, ...);
|
||||
|
||||
/// Print the format string indented
|
||||
void Dqn_CppPrintV(Dqn_CppFile *cpp, char const *fmt, va_list args);
|
||||
void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...);
|
||||
void DN_CppPrintV(DN_CppFile *cpp, char const *fmt, va_list args);
|
||||
void DN_CppPrint(DN_CppFile *cpp, char const *fmt, ...);
|
||||
|
||||
/// Print the format string
|
||||
#define Dqn_CppAppend(cpp, fmt, ...) fprintf((cpp)->file, fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppAppendV(cpp, fmt, args) vfprintf((cpp)->file, fmt, args)
|
||||
#define DN_CppAppend(cpp, fmt, ...) fprintf((cpp)->file, fmt, ##__VA_ARGS__)
|
||||
#define DN_CppAppendV(cpp, fmt, args) vfprintf((cpp)->file, fmt, args)
|
||||
|
||||
/// End the current line, useful after CppPrint and CppAppend
|
||||
#define Dqn_CppNewLine(cpp) fputc('\n', (cpp)->file)
|
||||
#define DN_CppNewLine(cpp) fputc('\n', (cpp)->file)
|
||||
|
||||
/// Manually modify the indent level
|
||||
#define Dqn_CppIndent(cpp) (cpp)->indent++
|
||||
#define Dqn_CppUnindent(cpp) (cpp)->indent--; assert((cpp)->indent >= 0)
|
||||
#define DN_CppIndent(cpp) (cpp)->indent++
|
||||
#define DN_CppUnindent(cpp) (cpp)->indent--; assert((cpp)->indent >= 0)
|
||||
|
||||
/// Block scope functions that execute a function on entry and exit of the
|
||||
/// scope by exploiting the comma operator and a for loop.
|
||||
///
|
||||
/// @code
|
||||
/// Dqn_CppEnumBlock(cpp, "abc") {
|
||||
/// DN_CppEnumBlock(cpp, "abc") {
|
||||
/// printf("Hello world!");
|
||||
/// }
|
||||
///
|
||||
/// // Is equivalent to
|
||||
///
|
||||
/// Dqn_CppBeginBlock(cpp, "abc");
|
||||
/// DN_CppBeginBlock(cpp, "abc");
|
||||
/// printf("Hello world!");
|
||||
/// Dqn_CppEndEnumBlock(cpp);
|
||||
/// DN_CppEndEnumBlock(cpp);
|
||||
/// @endcode
|
||||
|
||||
#define Dqn_CppEnumBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginEnumBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndEnumBlock(cpp), false))
|
||||
#define DN_CppEnumBlock(cpp, fmt, ...) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginEnumBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndEnumBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppForBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginForBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndForBlock(cpp), false))
|
||||
#define DN_CppForBlock(cpp, fmt, ...) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginForBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndForBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppWhileBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginWhileBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndWhileBlock(cpp), false))
|
||||
#define DN_CppWhileBlock(cpp, fmt, ...) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginWhileBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndWhileBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppIfOrElseIfBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginIfOrElseIfBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndIfOrElseIfBlock(cpp), false))
|
||||
#define DN_CppIfOrElseIfBlock(cpp, fmt, ...) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginIfOrElseIfBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndIfOrElseIfBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppElseBlock(cpp) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginElseBlock(cpp), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndElseBlock(cpp), false))
|
||||
#define DN_CppElseBlock(cpp) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginElseBlock(cpp), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndElseBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppFuncBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginFuncBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndFuncBlock(cpp), false))
|
||||
#define DN_CppFuncBlock(cpp, fmt, ...) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginFuncBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndFuncBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppStructBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginStructBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndStructBlock(cpp), false))
|
||||
#define DN_CppStructBlock(cpp, fmt, ...) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginStructBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndStructBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppSwitchBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginSwitchBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndSwitchBlock(cpp), false))
|
||||
#define DN_CppSwitchBlock(cpp, fmt, ...) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginSwitchBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndSwitchBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppBlock(cpp, ending, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndBlock(cpp, ending), false))
|
||||
#define DN_CppBlock(cpp, ending, fmt, ...) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(DN_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndBlock(cpp, ending), false))
|
||||
|
||||
#define Dqn_CppIfChain(cpp) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppBeginIfChain(cpp), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndIfChain(cpp), false))
|
||||
#define DN_CppIfChain(cpp) \
|
||||
for (bool DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppBeginIfChain(cpp), true); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DN_CPP_TOKEN_PASTE_(once_, __LINE__) = (DN_CppEndIfChain(cpp), false))
|
||||
|
||||
/// Print the format string followed by a "{" and enter a new line whilst
|
||||
/// increasing the indent level after the brace.
|
||||
void Dqn_CppBeginBlock (Dqn_CppFile *cpp, bool append, char const *fmt, ...);
|
||||
void Dqn_CppBeginBlockV(Dqn_CppFile *cpp, bool append, char const *fmt, va_list args);
|
||||
void Dqn_CppEndBlock (Dqn_CppFile *cpp, char const *ending);
|
||||
void DN_CppBeginBlock (DN_CppFile *cpp, bool append, char const *fmt, ...);
|
||||
void DN_CppBeginBlockV(DN_CppFile *cpp, bool append, char const *fmt, va_list args);
|
||||
void DN_CppEndBlock (DN_CppFile *cpp, char const *ending);
|
||||
|
||||
/// Begin/End a block, specifically for the following language constructs.
|
||||
#define Dqn_CppBeginEnumBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "enum " fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndEnumBlock(cpp) Dqn_CppEndBlock(cpp, ";\n")
|
||||
#define DN_CppBeginEnumBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "enum " fmt, ##__VA_ARGS__)
|
||||
#define DN_CppEndEnumBlock(cpp) DN_CppEndBlock(cpp, ";\n")
|
||||
|
||||
#define Dqn_CppBeginWhileBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "while (" fmt ")", ##__VA_ARGS__)
|
||||
#define Dqn_CppEndWhileBlock(cpp) Dqn_CppEndBlock(cpp, "\n")
|
||||
#define DN_CppBeginWhileBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "while (" fmt ")", ##__VA_ARGS__)
|
||||
#define DN_CppEndWhileBlock(cpp) DN_CppEndBlock(cpp, "\n")
|
||||
|
||||
#define Dqn_CppBeginForBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "for (" fmt ")", ##__VA_ARGS__)
|
||||
#define Dqn_CppEndForBlock(cpp) Dqn_CppEndBlock(cpp, "\n")
|
||||
#define DN_CppBeginForBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "for (" fmt ")", ##__VA_ARGS__)
|
||||
#define DN_CppEndForBlock(cpp) DN_CppEndBlock(cpp, "\n")
|
||||
|
||||
#define Dqn_CppBeginFuncBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndFuncBlock(cpp) Dqn_CppEndBlock(cpp, "\n")
|
||||
#define DN_CppBeginFuncBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__)
|
||||
#define DN_CppEndFuncBlock(cpp) DN_CppEndBlock(cpp, "\n")
|
||||
|
||||
#define Dqn_CppBeginStructBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "struct " fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndStructBlock(cpp) Dqn_CppEndBlock(cpp, ";\n")
|
||||
#define DN_CppBeginStructBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "struct " fmt, ##__VA_ARGS__)
|
||||
#define DN_CppEndStructBlock(cpp) DN_CppEndBlock(cpp, ";\n")
|
||||
|
||||
#define Dqn_CppBeginSwitchBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "switch (" fmt ")", ##__VA_ARGS__)
|
||||
#define Dqn_CppEndSwitchBlock(cpp) Dqn_CppEndBlock(cpp, "\n")
|
||||
#define DN_CppBeginSwitchBlock(cpp, fmt, ...) DN_CppBeginBlock(cpp, false /*append*/, "switch (" fmt ")", ##__VA_ARGS__)
|
||||
#define DN_CppEndSwitchBlock(cpp) DN_CppEndBlock(cpp, "\n")
|
||||
|
||||
void Dqn_CppBeginIfOrElseIfBlock (Dqn_CppFile *cpp, char const *fmt, ...);
|
||||
#define Dqn_CppEndIfOrElseIfBlock(cpp) Dqn_CppEndBlock(cpp, "")
|
||||
void DN_CppBeginIfOrElseIfBlock (DN_CppFile *cpp, char const *fmt, ...);
|
||||
#define DN_CppEndIfOrElseIfBlock(cpp) DN_CppEndBlock(cpp, "")
|
||||
|
||||
void Dqn_CppBeginElseBlock (Dqn_CppFile *cpp);
|
||||
void Dqn_CppEndElseBlock (Dqn_CppFile *cpp);
|
||||
void DN_CppBeginElseBlock (DN_CppFile *cpp);
|
||||
void DN_CppEndElseBlock (DN_CppFile *cpp);
|
||||
|
||||
#define DQN_CPP_TOKEN_PASTE2_(x, y) x ## y
|
||||
#define DQN_CPP_TOKEN_PASTE_(x, y) DQN_CPP_TOKEN_PASTE2_(x, y)
|
||||
#endif // DQN_CPP_FILE_H
|
||||
#define DN_CPP_TOKEN_PASTE2_(x, y) x ## y
|
||||
#define DN_CPP_TOKEN_PASTE_(x, y) DN_CPP_TOKEN_PASTE2_(x, y)
|
||||
#endif // DN_CPP_FILE_H
|
||||
|
||||
#if defined(DQN_CPP_FILE_IMPLEMENTATION)
|
||||
void Dqn_CppLineV(Dqn_CppFile *cpp, char const *fmt, va_list args)
|
||||
#if defined(DN_CPP_FILE_IMPLEMENTATION)
|
||||
void DN_CppLineV(DN_CppFile *cpp, char const *fmt, va_list args)
|
||||
{
|
||||
Dqn_CppPrintV(cpp, fmt, args);
|
||||
Dqn_CppNewLine(cpp);
|
||||
DN_CppPrintV(cpp, fmt, args);
|
||||
DN_CppNewLine(cpp);
|
||||
}
|
||||
|
||||
void Dqn_CppLine(Dqn_CppFile *cpp, char const *fmt, ...)
|
||||
void DN_CppLine(DN_CppFile *cpp, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_CppLineV(cpp, fmt, args);
|
||||
DN_CppLineV(cpp, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Dqn_CppPrintV(Dqn_CppFile *cpp, char const *fmt, va_list args)
|
||||
void DN_CppPrintV(DN_CppFile *cpp, char const *fmt, va_list args)
|
||||
{
|
||||
int space_per_indent = Dqn_CppSpacePerIndent(cpp);
|
||||
int space_per_indent = DN_CppSpacePerIndent(cpp);
|
||||
int spaces = fmt ? (cpp->indent * space_per_indent) : 0;
|
||||
fprintf(cpp->file, "%*s", spaces, "");
|
||||
vfprintf(cpp->file, fmt, args);
|
||||
}
|
||||
|
||||
void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...)
|
||||
void DN_CppPrint(DN_CppFile *cpp, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_CppPrintV(cpp, fmt, args);
|
||||
DN_CppPrintV(cpp, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Dqn_CppBeginBlock(Dqn_CppFile *cpp, bool append, char const *fmt, ...)
|
||||
void DN_CppBeginBlock(DN_CppFile *cpp, bool append, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_CppBeginBlockV(cpp, append, fmt, args);
|
||||
DN_CppBeginBlockV(cpp, append, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Dqn_CppBeginBlockV(Dqn_CppFile *cpp, bool append, char const *fmt, va_list args)
|
||||
void DN_CppBeginBlockV(DN_CppFile *cpp, bool append, char const *fmt, va_list args)
|
||||
{
|
||||
if (append)
|
||||
Dqn_CppAppendV(cpp, fmt, args);
|
||||
DN_CppAppendV(cpp, fmt, args);
|
||||
else
|
||||
Dqn_CppPrintV(cpp, fmt, args);
|
||||
DN_CppPrintV(cpp, fmt, args);
|
||||
|
||||
bool empty_fmt = fmt == nullptr || strlen(fmt) == 0;
|
||||
Dqn_CppAppend(cpp, "%s{\n", empty_fmt ? "" : " ");
|
||||
Dqn_CppIndent(cpp);
|
||||
DN_CppAppend(cpp, "%s{\n", empty_fmt ? "" : " ");
|
||||
DN_CppIndent(cpp);
|
||||
}
|
||||
|
||||
void Dqn_CppEndBlock(Dqn_CppFile *cpp, char const *ending)
|
||||
void DN_CppEndBlock(DN_CppFile *cpp, char const *ending)
|
||||
{
|
||||
Dqn_CppUnindent(cpp);
|
||||
Dqn_CppPrint(cpp, "}%s", ending);
|
||||
DN_CppUnindent(cpp);
|
||||
DN_CppPrint(cpp, "}%s", ending);
|
||||
}
|
||||
|
||||
void Dqn_CppBeginIfOrElseIfBlock(Dqn_CppFile *cpp, char const *fmt, ...)
|
||||
void DN_CppBeginIfOrElseIfBlock(DN_CppFile *cpp, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
assert(cpp->if_chain_size);
|
||||
if (cpp->if_chain[cpp->if_chain_size - 1] == 0)
|
||||
Dqn_CppPrint(cpp, "if");
|
||||
DN_CppPrint(cpp, "if");
|
||||
else
|
||||
Dqn_CppAppend(cpp, " else if");
|
||||
DN_CppAppend(cpp, " else if");
|
||||
|
||||
Dqn_CppAppend(cpp, " (");
|
||||
Dqn_CppAppendV(cpp, fmt, args);
|
||||
Dqn_CppAppend(cpp, ") {\n");
|
||||
Dqn_CppIndent(cpp);
|
||||
DN_CppAppend(cpp, " (");
|
||||
DN_CppAppendV(cpp, fmt, args);
|
||||
DN_CppAppend(cpp, ") {\n");
|
||||
DN_CppIndent(cpp);
|
||||
va_end(args);
|
||||
cpp->if_chain[cpp->if_chain_size - 1]++;
|
||||
}
|
||||
|
||||
void Dqn_CppBeginElseBlock(Dqn_CppFile *cpp)
|
||||
void DN_CppBeginElseBlock(DN_CppFile *cpp)
|
||||
{
|
||||
assert(cpp->if_chain_size);
|
||||
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1)
|
||||
Dqn_CppBeginBlock(cpp, true /*append*/, " else");
|
||||
DN_CppBeginBlock(cpp, true /*append*/, " else");
|
||||
}
|
||||
|
||||
void Dqn_CppEndElseBlock(Dqn_CppFile *cpp)
|
||||
void DN_CppEndElseBlock(DN_CppFile *cpp)
|
||||
{
|
||||
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1)
|
||||
Dqn_CppEndBlock(cpp, "");
|
||||
DN_CppEndBlock(cpp, "");
|
||||
}
|
||||
|
||||
void Dqn_CppBeginIfChain(Dqn_CppFile *cpp)
|
||||
void DN_CppBeginIfChain(DN_CppFile *cpp)
|
||||
{
|
||||
assert(cpp->if_chain_size < sizeof(cpp->if_chain)/sizeof(cpp->if_chain[0]));
|
||||
cpp->if_chain_size++;
|
||||
}
|
||||
|
||||
void Dqn_CppEndIfChain(Dqn_CppFile *cpp)
|
||||
void DN_CppEndIfChain(DN_CppFile *cpp)
|
||||
{
|
||||
assert(cpp->if_chain_size);
|
||||
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1) {
|
||||
Dqn_CppNewLine(cpp);
|
||||
DN_CppNewLine(cpp);
|
||||
}
|
||||
cpp->if_chain[cpp->if_chain_size - 1] = 0;
|
||||
cpp->if_chain_size--;
|
||||
}
|
||||
|
||||
#endif // DQN_CPP_FILE_IMPLEMENTATION
|
||||
#endif // DN_CPP_FILE_IMPLEMENTATION
|
||||
|
@ -1,5 +1,5 @@
|
||||
#if !defined(DQN_KECCAK_H)
|
||||
#define DQN_KECCAK_H
|
||||
#if !defined(DN_KECCAK_H)
|
||||
#define DN_KECCAK_H
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -13,7 +13,7 @@
|
||||
// $$ | \$$\ $$$$$$$$\ \$$$$$$ |\$$$$$$ |$$ | $$ |$$ | \$$\
|
||||
// \__| \__|\________| \______/ \______/ \__| \__|\__| \__|
|
||||
//
|
||||
// dqn_keccak.h -- FIPS202 SHA3 + non-finalized SHA3 (aka. Keccak) hashing algorithms
|
||||
// dn_keccak.h -- FIPS202 SHA3 + non-finalized SHA3 (aka. Keccak) hashing algorithms
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -65,31 +65,31 @@
|
||||
// - Define this in one and only one C++ file to enable the implementation
|
||||
// code of the header file.
|
||||
//
|
||||
// #define DQN_KECCAK_IMPLEMENTATION
|
||||
// #define DN_KECCAK_IMPLEMENTATION
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
#if !defined(DQN_KECCAK_MEMCPY)
|
||||
#if !defined(DN_KECCAK_MEMCPY)
|
||||
#include <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
|
||||
|
||||
#if !defined(DQN_KECCAK_MEMCMP)
|
||||
#if !defined(DN_KECCAK_MEMCMP)
|
||||
#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
|
||||
|
||||
#if !defined(DQN_KECCAK_MEMSET)
|
||||
#if !defined(DN_KECCAK_MEMSET)
|
||||
#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
|
||||
|
||||
#if !defined(DQN_KECCAK_ASSERT)
|
||||
#if !defined(DN_KECCAK_ASSERT)
|
||||
#if defined(NDEBUG)
|
||||
#define DQN_KECCAK_ASSERT(expr)
|
||||
#define DN_KECCAK_ASSERT(expr)
|
||||
#else
|
||||
#define DQN_KECCAK_ASSERT(expr) \
|
||||
#define DN_KECCAK_ASSERT(expr) \
|
||||
do \
|
||||
{ \
|
||||
if (!(expr)) \
|
||||
@ -102,43 +102,43 @@
|
||||
|
||||
// Use this macro in a printf-like function,
|
||||
/*
|
||||
Dqn_KeccakString64 string = {};
|
||||
printf("%.*s\n", DQN_KECCAK_STRING64_FMT(string));
|
||||
DN_KeccakString64 string = {};
|
||||
printf("%.*s\n", DN_KECCAK_STRING64_FMT(string));
|
||||
*/
|
||||
#define DQN_KECCAK_STRING56_FMT(string) 56, string
|
||||
#define DQN_KECCAK_STRING64_FMT(string) 64, string
|
||||
#define DQN_KECCAK_STRING96_FMT(string) 96, string
|
||||
#define DQN_KECCAK_STRING128_FMT(string) 128, string
|
||||
#define DN_KECCAK_STRING56_FMT(string) 56, string
|
||||
#define DN_KECCAK_STRING64_FMT(string) 64, string
|
||||
#define DN_KECCAK_STRING96_FMT(string) 96, string
|
||||
#define DN_KECCAK_STRING128_FMT(string) 128, string
|
||||
|
||||
typedef unsigned char Dqn_KeccakU8;
|
||||
typedef unsigned short Dqn_KeccakU16;
|
||||
typedef unsigned int Dqn_KeccakU32;
|
||||
typedef unsigned int Dqn_KeccakUint;
|
||||
typedef unsigned char DN_KeccakU8;
|
||||
typedef unsigned short DN_KeccakU16;
|
||||
typedef unsigned int DN_KeccakU32;
|
||||
typedef unsigned int DN_KeccakUint;
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 Dqn_KeccakU64;
|
||||
typedef unsigned __int64 DN_KeccakU64;
|
||||
#else
|
||||
typedef unsigned long long Dqn_KeccakU64;
|
||||
typedef unsigned long long DN_KeccakU64;
|
||||
#endif
|
||||
|
||||
typedef struct Dqn_KeccakBytes28 { char data[28]; } Dqn_KeccakBytes28; // 224 bit
|
||||
typedef struct Dqn_KeccakBytes32 { char data[32]; } Dqn_KeccakBytes32; // 256 bit
|
||||
typedef struct Dqn_KeccakBytes48 { char data[48]; } Dqn_KeccakBytes48; // 384 bit
|
||||
typedef struct Dqn_KeccakBytes64 { char data[64]; } Dqn_KeccakBytes64; // 512 bit
|
||||
typedef struct DN_KeccakBytes28 { char data[28]; } DN_KeccakBytes28; // 224 bit
|
||||
typedef struct DN_KeccakBytes32 { char data[32]; } DN_KeccakBytes32; // 256 bit
|
||||
typedef struct DN_KeccakBytes48 { char data[48]; } DN_KeccakBytes48; // 384 bit
|
||||
typedef struct DN_KeccakBytes64 { char data[64]; } DN_KeccakBytes64; // 512 bit
|
||||
|
||||
typedef struct Dqn_KeccakString56 { char data[(sizeof(Dqn_KeccakBytes28) * 2) + 1]; } Dqn_KeccakString56;
|
||||
typedef struct Dqn_KeccakString64 { char data[(sizeof(Dqn_KeccakBytes32) * 2) + 1]; } Dqn_KeccakString64;
|
||||
typedef struct Dqn_KeccakString96 { char data[(sizeof(Dqn_KeccakBytes48) * 2) + 1]; } Dqn_KeccakString96;
|
||||
typedef struct Dqn_KeccakString128 { char data[(sizeof(Dqn_KeccakBytes64) * 2) + 1]; } Dqn_KeccakString128;
|
||||
typedef struct DN_KeccakString56 { char data[(sizeof(DN_KeccakBytes28) * 2) + 1]; } DN_KeccakString56;
|
||||
typedef struct DN_KeccakString64 { char data[(sizeof(DN_KeccakBytes32) * 2) + 1]; } DN_KeccakString64;
|
||||
typedef struct DN_KeccakString96 { char data[(sizeof(DN_KeccakBytes48) * 2) + 1]; } DN_KeccakString96;
|
||||
typedef struct DN_KeccakString128 { char data[(sizeof(DN_KeccakBytes64) * 2) + 1]; } DN_KeccakString128;
|
||||
|
||||
#define DQN_KECCAK_LANE_SIZE_U64 5
|
||||
typedef struct Dqn_KeccakState
|
||||
#define DN_KECCAK_LANE_SIZE_U64 5
|
||||
typedef struct DN_KeccakState
|
||||
{
|
||||
Dqn_KeccakU8 state[DQN_KECCAK_LANE_SIZE_U64 * DQN_KECCAK_LANE_SIZE_U64 * sizeof(Dqn_KeccakU64)];
|
||||
DN_KeccakU8 state[DN_KECCAK_LANE_SIZE_U64 * DN_KECCAK_LANE_SIZE_U64 * sizeof(DN_KeccakU64)];
|
||||
int state_size; // The number of bytes written to the state
|
||||
int absorb_size; // The amount of bytes to absorb/sponge in/from the state
|
||||
int hash_size_bits; // The size of the hash the context was initialised for in bits
|
||||
char delimited_suffix; // The delimited suffix of the current hash
|
||||
} Dqn_KeccakState;
|
||||
} DN_KeccakState;
|
||||
|
||||
// NOTE: SHA3/Keccak Streaming API /////////////////////////////////////////////////////////////////
|
||||
// Setup a hashing state for either
|
||||
@ -152,92 +152,92 @@ typedef struct Dqn_KeccakState
|
||||
//
|
||||
// sha3: If true, setup the state for FIPS 202 SHA3, otherwise the non-finalized version
|
||||
// hash_size_bits: The number of bits to setup the context for, available sizes are 224, 256, 384 and 512.
|
||||
Dqn_KeccakState Dqn_KeccakSHA3Init(bool sha3, int hash_size_bits);
|
||||
DN_KeccakState DN_KeccakSHA3Init(bool sha3, int hash_size_bits);
|
||||
|
||||
// After initialising a 'Dqn_KeccakState' via 'Dqn_KeccakSHA3Init', iteratively
|
||||
// update the hash with new data by calling 'Dqn_KeccakUpdate'. On completion,
|
||||
// call 'Dqn_KeccakFinish' to generate the hash from the state. The 'dest_size'
|
||||
// must be at-least the (bit-size / 8), i.e. for 'Dqn_Keccak512Init' it must be
|
||||
// After initialising a 'DN_KeccakState' via 'DN_KeccakSHA3Init', iteratively
|
||||
// update the hash with new data by calling 'DN_KeccakUpdate'. On completion,
|
||||
// call 'DN_KeccakFinish' to generate the hash from the state. The 'dest_size'
|
||||
// must be at-least the (bit-size / 8), i.e. for 'DN_Keccak512Init' it must be
|
||||
// atleast (512 / 8) bytes, 64 bytes.
|
||||
void Dqn_KeccakUpdate(Dqn_KeccakState *keccak, void const *data, Dqn_KeccakU64 data_size);
|
||||
void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size);
|
||||
void DN_KeccakUpdate(DN_KeccakState *keccak, void const *data, DN_KeccakU64 data_size);
|
||||
void DN_KeccakFinish(DN_KeccakState *keccak, void *dest, int dest_size);
|
||||
|
||||
// NOTE: Simple API ////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper function that combines the Init, Update and Finish step in one shot,
|
||||
// i.e. hashing a singlular contiguous buffer. Use the streaming API if data
|
||||
// is split across different buffers.
|
||||
void Dqn_KeccakSHA3Hash(bool sha3, int hash_size_bits, void const *src, Dqn_KeccakU64 src_size, void *dest, int dest_size);
|
||||
void DN_KeccakSHA3Hash(bool sha3, int hash_size_bits, void const *src, DN_KeccakU64 src_size, void *dest, int dest_size);
|
||||
|
||||
#define Dqn_SHA3Hash(hash_size_bits, src, src_size, dest, dest_size) Dqn_KeccakSHA3Hash(true /*sha3*/, hash_size_bits, src, src_size, dest, dest_size)
|
||||
#define Dqn_SHA3_224(src, src_size, dest, dest_size) Dqn_SHA3Hash(224, src, src_size, dest, dest_size)
|
||||
#define Dqn_SHA3_256(src, src_size, dest, dest_size) Dqn_SHA3Hash(256, src, src_size, dest, dest_size)
|
||||
#define Dqn_SHA3_384(src, src_size, dest, dest_size) Dqn_SHA3Hash(384, src, src_size, dest, dest_size)
|
||||
#define Dqn_SHA3_512(src, src_size, dest, dest_size) Dqn_SHA3Hash(512, src, src_size, dest, dest_size)
|
||||
#define DN_SHA3Hash(hash_size_bits, src, src_size, dest, dest_size) DN_KeccakSHA3Hash(true /*sha3*/, hash_size_bits, src, src_size, dest, dest_size)
|
||||
#define DN_SHA3_224(src, src_size, dest, dest_size) DN_SHA3Hash(224, src, src_size, dest, dest_size)
|
||||
#define DN_SHA3_256(src, src_size, dest, dest_size) DN_SHA3Hash(256, src, src_size, dest, dest_size)
|
||||
#define DN_SHA3_384(src, src_size, dest, dest_size) DN_SHA3Hash(384, src, src_size, dest, dest_size)
|
||||
#define DN_SHA3_512(src, src_size, dest, dest_size) DN_SHA3Hash(512, src, src_size, dest, dest_size)
|
||||
|
||||
#define Dqn_KeccakHash(hash_size_bits, src, src_size, dest, dest_size) Dqn_KeccakSHA3Hash(false /*sha3*/, hash_size_bits, src, src_size, dest, dest_size)
|
||||
#define Dqn_Keccak224(src, src_size, dest, dest_size) Dqn_KeccakHash(224, src, src_size, dest, dest_size)
|
||||
#define Dqn_Keccak256(src, src_size, dest, dest_size) Dqn_KeccakHash(256, src, src_size, dest, dest_size)
|
||||
#define Dqn_Keccak384(src, src_size, dest, dest_size) Dqn_KeccakHash(384, src, src_size, dest, dest_size)
|
||||
#define Dqn_Keccak512(src, src_size, dest, dest_size) Dqn_KeccakHash(512, src, src_size, dest, dest_size)
|
||||
#define DN_KeccakHash(hash_size_bits, src, src_size, dest, dest_size) DN_KeccakSHA3Hash(false /*sha3*/, hash_size_bits, src, src_size, dest, dest_size)
|
||||
#define DN_Keccak224(src, src_size, dest, dest_size) DN_KeccakHash(224, src, src_size, dest, dest_size)
|
||||
#define DN_Keccak256(src, src_size, dest, dest_size) DN_KeccakHash(256, src, src_size, dest, dest_size)
|
||||
#define DN_Keccak384(src, src_size, dest, dest_size) DN_KeccakHash(384, src, src_size, dest, dest_size)
|
||||
#define DN_Keccak512(src, src_size, dest, dest_size) DN_KeccakHash(512, src, src_size, dest, dest_size)
|
||||
|
||||
// NOTE: SHA3 Helpers //////////////////////////////////////////////////////////////////////////////
|
||||
Dqn_KeccakBytes28 Dqn_SHA3_224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size);
|
||||
Dqn_KeccakBytes32 Dqn_SHA3_256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size);
|
||||
Dqn_KeccakBytes48 Dqn_SHA3_384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size);
|
||||
Dqn_KeccakBytes64 Dqn_SHA3_512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size);
|
||||
DN_KeccakBytes28 DN_SHA3_224ToBytes28(void *bytes, DN_KeccakU64 bytes_size);
|
||||
DN_KeccakBytes32 DN_SHA3_256ToBytes32(void *bytes, DN_KeccakU64 bytes_size);
|
||||
DN_KeccakBytes48 DN_SHA3_384ToBytes48(void *bytes, DN_KeccakU64 bytes_size);
|
||||
DN_KeccakBytes64 DN_SHA3_512ToBytes64(void *bytes, DN_KeccakU64 bytes_size);
|
||||
|
||||
// NOTE: Keccak Helpers ////////////////////////////////////////////////////////////////////////////
|
||||
Dqn_KeccakBytes28 Dqn_Keccak224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size);
|
||||
Dqn_KeccakBytes32 Dqn_Keccak256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size);
|
||||
Dqn_KeccakBytes48 Dqn_Keccak384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size);
|
||||
Dqn_KeccakBytes64 Dqn_Keccak512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size);
|
||||
DN_KeccakBytes28 DN_Keccak224ToBytes28(void *bytes, DN_KeccakU64 bytes_size);
|
||||
DN_KeccakBytes32 DN_Keccak256ToBytes32(void *bytes, DN_KeccakU64 bytes_size);
|
||||
DN_KeccakBytes48 DN_Keccak384ToBytes48(void *bytes, DN_KeccakU64 bytes_size);
|
||||
DN_KeccakBytes64 DN_Keccak512ToBytes64(void *bytes, DN_KeccakU64 bytes_size);
|
||||
|
||||
#if defined(DQN_H)
|
||||
// NOTE: SHA3 - Helpers for Dqn data structures ////////////////////////////////////////////////////
|
||||
Dqn_KeccakBytes28 Dqn_SHA3_224StringToBytes28(Dqn_Str8 string);
|
||||
Dqn_KeccakBytes32 Dqn_SHA3_256StringToBytes32(Dqn_Str8 string);
|
||||
Dqn_KeccakBytes48 Dqn_SHA3_384StringToBytes48(Dqn_Str8 string);
|
||||
Dqn_KeccakBytes64 Dqn_SHA3_512StringToBytes64(Dqn_Str8 string);
|
||||
#if defined(DN_H)
|
||||
// NOTE: SHA3 - Helpers for DN data structures ////////////////////////////////////////////////////
|
||||
DN_KeccakBytes28 DN_SHA3_224StringToBytes28(DN_Str8 string);
|
||||
DN_KeccakBytes32 DN_SHA3_256StringToBytes32(DN_Str8 string);
|
||||
DN_KeccakBytes48 DN_SHA3_384StringToBytes48(DN_Str8 string);
|
||||
DN_KeccakBytes64 DN_SHA3_512StringToBytes64(DN_Str8 string);
|
||||
|
||||
// NOTE: Keccak - Helpers for Dqn data structures //////////////////////////////////////////////////
|
||||
Dqn_KeccakBytes28 Dqn_Keccak224StringToBytes28(Dqn_Str8 string);
|
||||
Dqn_KeccakBytes32 Dqn_Keccak256StringToBytes32(Dqn_Str8 string);
|
||||
Dqn_KeccakBytes48 Dqn_Keccak384StringToBytes48(Dqn_Str8 string);
|
||||
Dqn_KeccakBytes64 Dqn_Keccak512StringToBytes64(Dqn_Str8 string);
|
||||
#endif // DQN_H
|
||||
// NOTE: Keccak - Helpers for DN data structures //////////////////////////////////////////////////
|
||||
DN_KeccakBytes28 DN_Keccak224StringToBytes28(DN_Str8 string);
|
||||
DN_KeccakBytes32 DN_Keccak256StringToBytes32(DN_Str8 string);
|
||||
DN_KeccakBytes48 DN_Keccak384StringToBytes48(DN_Str8 string);
|
||||
DN_KeccakBytes64 DN_Keccak512StringToBytes64(DN_Str8 string);
|
||||
#endif // DN_H
|
||||
|
||||
// NOTE: Helper functions //////////////////////////////////////////////////////////////////////////
|
||||
// Convert a binary buffer into its hex representation into dest. The dest
|
||||
// buffer must be large enough to contain the hex representation, i.e.
|
||||
// atleast src_size * 2). This function does *not* null-terminate the buffer.
|
||||
void Dqn_KeccakBytesToHex(void const *src, Dqn_KeccakU64 src_size, char *dest, Dqn_KeccakU64 dest_size);
|
||||
void DN_KeccakBytesToHex(void const *src, DN_KeccakU64 src_size, char *dest, DN_KeccakU64 dest_size);
|
||||
|
||||
// Converts a fixed amount of bytes into a hexadecimal string. Helper functions
|
||||
// that call into Dqn_KeccakBytesToHex.
|
||||
// that call into DN_KeccakBytesToHex.
|
||||
// return: The hexadecimal string of the bytes, null-terminated.
|
||||
Dqn_KeccakString56 Dqn_KeccakBytes28ToHex(Dqn_KeccakBytes28 const *bytes);
|
||||
Dqn_KeccakString64 Dqn_KeccakBytes32ToHex(Dqn_KeccakBytes32 const *bytes);
|
||||
Dqn_KeccakString96 Dqn_KeccakBytes48ToHex(Dqn_KeccakBytes48 const *bytes);
|
||||
Dqn_KeccakString128 Dqn_KeccakBytes64ToHex(Dqn_KeccakBytes64 const *bytes);
|
||||
DN_KeccakString56 DN_KeccakBytes28ToHex(DN_KeccakBytes28 const *bytes);
|
||||
DN_KeccakString64 DN_KeccakBytes32ToHex(DN_KeccakBytes32 const *bytes);
|
||||
DN_KeccakString96 DN_KeccakBytes48ToHex(DN_KeccakBytes48 const *bytes);
|
||||
DN_KeccakString128 DN_KeccakBytes64ToHex(DN_KeccakBytes64 const *bytes);
|
||||
|
||||
// Compares byte data structures for byte equality (via memcmp).
|
||||
// return: 1 if the contents are equal otherwise 0.
|
||||
int Dqn_KeccakBytes28Equals(Dqn_KeccakBytes28 const *a, Dqn_KeccakBytes28 const *b);
|
||||
int Dqn_KeccakBytes32Equals(Dqn_KeccakBytes32 const *a, Dqn_KeccakBytes32 const *b);
|
||||
int Dqn_KeccakBytes48Equals(Dqn_KeccakBytes48 const *a, Dqn_KeccakBytes48 const *b);
|
||||
int Dqn_KeccakBytes64Equals(Dqn_KeccakBytes64 const *a, Dqn_KeccakBytes64 const *b);
|
||||
int DN_KeccakBytes28Equals(DN_KeccakBytes28 const *a, DN_KeccakBytes28 const *b);
|
||||
int DN_KeccakBytes32Equals(DN_KeccakBytes32 const *a, DN_KeccakBytes32 const *b);
|
||||
int DN_KeccakBytes48Equals(DN_KeccakBytes48 const *a, DN_KeccakBytes48 const *b);
|
||||
int DN_KeccakBytes64Equals(DN_KeccakBytes64 const *a, DN_KeccakBytes64 const *b);
|
||||
|
||||
#if defined(DQN_H) && defined(DQN_WITH_HEX)
|
||||
// NOTE: Other helper functions for Dqn data structures ////////////////////////////////////////////
|
||||
#if defined(DN_H) && defined(DN_WITH_HEX)
|
||||
// NOTE: Other helper functions for DN data structures ////////////////////////////////////////////
|
||||
// Converts a 64 character hex string into the 32 byte binary representation.
|
||||
// Invalid hex characters in the string will be represented as 0.
|
||||
// hex: Must be exactly a 64 character hex string.
|
||||
Dqn_KeccakBytes32 Dqn_KeccakHex64StringToBytes(Dqn_Str8 hex);
|
||||
#endif // DQN_H && DQN_WITH_HEX
|
||||
#endif // DQN_KECCAK_H
|
||||
DN_KeccakBytes32 DN_KeccakHex64StringToBytes(DN_Str8 hex);
|
||||
#endif // DN_H && DN_WITH_HEX
|
||||
#endif // DN_KECCAK_H
|
||||
|
||||
#if defined(DQN_KECCAK_IMPLEMENTATION)
|
||||
Dqn_KeccakU64 const DQN_KECCAK_ROUNDS[] = {
|
||||
#if defined(DN_KECCAK_IMPLEMENTATION)
|
||||
DN_KeccakU64 const DN_KECCAK_ROUNDS[] = {
|
||||
0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B,
|
||||
0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088,
|
||||
0x0000000080008009, 0x000000008000000A, 0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
|
||||
@ -245,7 +245,7 @@ Dqn_KeccakU64 const DQN_KECCAK_ROUNDS[] = {
|
||||
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
|
||||
};
|
||||
|
||||
Dqn_KeccakU64 const DQN_KECCAK_ROTATIONS[][5] =
|
||||
DN_KeccakU64 const DN_KECCAK_ROTATIONS[][5] =
|
||||
{
|
||||
{0, 36, 3, 41, 18},
|
||||
{1, 44, 10, 45, 2},
|
||||
@ -254,21 +254,21 @@ Dqn_KeccakU64 const DQN_KECCAK_ROTATIONS[][5] =
|
||||
{27, 20, 39, 8, 14},
|
||||
};
|
||||
|
||||
#define DQN_KECCAK_ROL64(val, rotate) (((val) << (rotate)) | (((val) >> (64 - (rotate)))))
|
||||
#define DN_KECCAK_ROL64(val, rotate) (((val) << (rotate)) | (((val) >> (64 - (rotate)))))
|
||||
|
||||
static void Dqn_Keccak__Permute(void *state)
|
||||
static void DN_Keccak__Permute(void *state)
|
||||
{
|
||||
// TODO(dqn): Do some profiling on unrolling and can we SIMD some part of
|
||||
// TODO(dn): Do some profiling on unrolling and can we SIMD some part of
|
||||
// this? Unroll loop, look at data dependencies and investigate.
|
||||
|
||||
Dqn_KeccakU64 *lanes_u64 = (Dqn_KeccakU64 *)state;
|
||||
DN_KeccakU64 *lanes_u64 = (DN_KeccakU64 *)state;
|
||||
for (int round_index = 0; round_index < 24; round_index++)
|
||||
{
|
||||
#define LANE_INDEX(x, y) ((x) + ((y) * DQN_KECCAK_LANE_SIZE_U64))
|
||||
// θ step //////////////////////////////////////////////////////////////////////////////////
|
||||
#define LANE_INDEX(x, y) ((x) + ((y) * DN_KECCAK_LANE_SIZE_U64))
|
||||
// ?? step //////////////////////////////////////////////////////////////////////////////////
|
||||
#if 1
|
||||
Dqn_KeccakU64 c[DQN_KECCAK_LANE_SIZE_U64];
|
||||
for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++)
|
||||
DN_KeccakU64 c[DN_KECCAK_LANE_SIZE_U64];
|
||||
for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++)
|
||||
{
|
||||
c[x] = lanes_u64[LANE_INDEX(x, 0)] ^
|
||||
lanes_u64[LANE_INDEX(x, 1)] ^
|
||||
@ -277,87 +277,87 @@ static void Dqn_Keccak__Permute(void *state)
|
||||
lanes_u64[LANE_INDEX(x, 4)];
|
||||
}
|
||||
|
||||
Dqn_KeccakU64 d[DQN_KECCAK_LANE_SIZE_U64];
|
||||
for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++)
|
||||
d[x] = c[(x + 4) % DQN_KECCAK_LANE_SIZE_U64] ^ DQN_KECCAK_ROL64(c[(x + 1) % DQN_KECCAK_LANE_SIZE_U64], 1);
|
||||
DN_KeccakU64 d[DN_KECCAK_LANE_SIZE_U64];
|
||||
for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++)
|
||||
d[x] = c[(x + 4) % DN_KECCAK_LANE_SIZE_U64] ^ DN_KECCAK_ROL64(c[(x + 1) % DN_KECCAK_LANE_SIZE_U64], 1);
|
||||
|
||||
for (int y = 0; y < DQN_KECCAK_LANE_SIZE_U64; y++)
|
||||
for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++)
|
||||
for (int y = 0; y < DN_KECCAK_LANE_SIZE_U64; y++)
|
||||
for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++)
|
||||
lanes_u64[LANE_INDEX(x, y)] ^= d[x];
|
||||
#else
|
||||
Dqn_KeccakU64 c[5], d[5];
|
||||
DN_KeccakU64 c[5], d[5];
|
||||
c[0] = lanes_u64[0 * 5 + 0] ^ lanes_u64[1 * 5 + 0] ^ lanes_u64[2 * 5 + 0] ^ lanes_u64[3 * 5 + 0] ^ lanes_u64[4 * 5 + 0];
|
||||
c[1] = lanes_u64[0 * 5 + 1] ^ lanes_u64[1 * 5 + 1] ^ lanes_u64[2 * 5 + 1] ^ lanes_u64[3 * 5 + 1] ^ lanes_u64[4 * 5 + 1];
|
||||
c[2] = lanes_u64[0 * 5 + 2] ^ lanes_u64[1 * 5 + 2] ^ lanes_u64[2 * 5 + 2] ^ lanes_u64[3 * 5 + 2] ^ lanes_u64[4 * 5 + 2];
|
||||
c[3] = lanes_u64[0 * 5 + 3] ^ lanes_u64[1 * 5 + 3] ^ lanes_u64[2 * 5 + 3] ^ lanes_u64[3 * 5 + 3] ^ lanes_u64[4 * 5 + 3];
|
||||
c[4] = lanes_u64[0 * 5 + 4] ^ lanes_u64[1 * 5 + 4] ^ lanes_u64[2 * 5 + 4] ^ lanes_u64[3 * 5 + 4] ^ lanes_u64[4 * 5 + 4];
|
||||
|
||||
d[0] = c[4] ^ DQN_KECCAK_ROL64(c[1], 1);
|
||||
d[1] = c[0] ^ DQN_KECCAK_ROL64(c[2], 1);
|
||||
d[2] = c[1] ^ DQN_KECCAK_ROL64(c[3], 1);
|
||||
d[3] = c[2] ^ DQN_KECCAK_ROL64(c[4], 1);
|
||||
d[4] = c[3] ^ DQN_KECCAK_ROL64(c[0], 1);
|
||||
d[0] = c[4] ^ DN_KECCAK_ROL64(c[1], 1);
|
||||
d[1] = c[0] ^ DN_KECCAK_ROL64(c[2], 1);
|
||||
d[2] = c[1] ^ DN_KECCAK_ROL64(c[3], 1);
|
||||
d[3] = c[2] ^ DN_KECCAK_ROL64(c[4], 1);
|
||||
d[4] = c[3] ^ DN_KECCAK_ROL64(c[0], 1);
|
||||
#endif
|
||||
|
||||
// ρ and π steps ///////////////////////////////////////////////////////////////////////////
|
||||
Dqn_KeccakU64 b[DQN_KECCAK_LANE_SIZE_U64 * DQN_KECCAK_LANE_SIZE_U64];
|
||||
for (int y = 0; y < DQN_KECCAK_LANE_SIZE_U64; y++)
|
||||
// ?? and ?? steps ///////////////////////////////////////////////////////////////////////////
|
||||
DN_KeccakU64 b[DN_KECCAK_LANE_SIZE_U64 * DN_KECCAK_LANE_SIZE_U64];
|
||||
for (int y = 0; y < DN_KECCAK_LANE_SIZE_U64; y++)
|
||||
{
|
||||
for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++)
|
||||
for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++)
|
||||
{
|
||||
Dqn_KeccakU64 lane = lanes_u64[LANE_INDEX(x, y)];
|
||||
Dqn_KeccakU64 rotate_count = DQN_KECCAK_ROTATIONS[x][y];
|
||||
b[LANE_INDEX(y, (2 * x + 3 * y) % 5)] = DQN_KECCAK_ROL64(lane, rotate_count);
|
||||
DN_KeccakU64 lane = lanes_u64[LANE_INDEX(x, y)];
|
||||
DN_KeccakU64 rotate_count = DN_KECCAK_ROTATIONS[x][y];
|
||||
b[LANE_INDEX(y, (2 * x + 3 * y) % 5)] = DN_KECCAK_ROL64(lane, rotate_count);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// χ step //////////////////////////////////////////////////////////////////////////////////
|
||||
for (int y = 0; y < DQN_KECCAK_LANE_SIZE_U64; y++)
|
||||
// ?? step //////////////////////////////////////////////////////////////////////////////////
|
||||
for (int y = 0; y < DN_KECCAK_LANE_SIZE_U64; y++)
|
||||
{
|
||||
for (int x = 0; x < DQN_KECCAK_LANE_SIZE_U64; x++)
|
||||
for (int x = 0; x < DN_KECCAK_LANE_SIZE_U64; x++)
|
||||
{
|
||||
Dqn_KeccakU64 rhs = ~b[LANE_INDEX((x + 1) % 5, y)] &
|
||||
DN_KeccakU64 rhs = ~b[LANE_INDEX((x + 1) % 5, y)] &
|
||||
b[LANE_INDEX((x + 2) % 5, y)];
|
||||
|
||||
lanes_u64[LANE_INDEX(x, y)] = b[LANE_INDEX(x, y)] ^ rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// ι step //////////////////////////////////////////////////////////////////////////////////
|
||||
lanes_u64[LANE_INDEX(0, 0)] ^= DQN_KECCAK_ROUNDS[round_index];
|
||||
// ?? step //////////////////////////////////////////////////////////////////////////////////
|
||||
lanes_u64[LANE_INDEX(0, 0)] ^= DN_KECCAK_ROUNDS[round_index];
|
||||
#undef LANE_INDEX
|
||||
#undef DQN_KECCAK_ROL64
|
||||
#undef DN_KECCAK_ROL64
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Streaming API /////////////////////////////////////////////////////////////////////////////
|
||||
Dqn_KeccakState Dqn_KeccakSHA3Init(bool sha3, int hash_size_bits)
|
||||
DN_KeccakState DN_KeccakSHA3Init(bool sha3, int hash_size_bits)
|
||||
{
|
||||
char const SHA3_DELIMITED_SUFFIX = 0x06;
|
||||
char const KECCAK_DELIMITED_SUFFIX = 0x01;
|
||||
int const bitrate = 1600 - (hash_size_bits * 2);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
Dqn_KeccakState result = {};
|
||||
DN_KeccakState result = {};
|
||||
#else
|
||||
Dqn_KeccakState result = {0};
|
||||
DN_KeccakState result = {0};
|
||||
#endif
|
||||
result.hash_size_bits = hash_size_bits;
|
||||
result.absorb_size = bitrate / 8;
|
||||
result.delimited_suffix = sha3 ? SHA3_DELIMITED_SUFFIX : KECCAK_DELIMITED_SUFFIX;
|
||||
DQN_KECCAK_ASSERT(bitrate + (hash_size_bits * 2) /*capacity*/ == 1600);
|
||||
DN_KECCAK_ASSERT(bitrate + (hash_size_bits * 2) /*capacity*/ == 1600);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Dqn_KeccakUpdate(Dqn_KeccakState *keccak, void const *data, Dqn_KeccakU64 data_size)
|
||||
void DN_KeccakUpdate(DN_KeccakState *keccak, void const *data, DN_KeccakU64 data_size)
|
||||
{
|
||||
Dqn_KeccakU8 *state = keccak->state;
|
||||
Dqn_KeccakU8 const *ptr = (Dqn_KeccakU8 *)data;
|
||||
Dqn_KeccakU64 ptr_size = data_size;
|
||||
DN_KeccakU8 *state = keccak->state;
|
||||
DN_KeccakU8 const *ptr = (DN_KeccakU8 *)data;
|
||||
DN_KeccakU64 ptr_size = data_size;
|
||||
while (ptr_size > 0)
|
||||
{
|
||||
Dqn_KeccakU64 space = keccak->absorb_size - keccak->state_size;
|
||||
DN_KeccakU64 space = keccak->absorb_size - keccak->state_size;
|
||||
int bytes_to_absorb = (int)(space < ptr_size ? space : ptr_size);
|
||||
|
||||
for (int index = 0; index < bytes_to_absorb; index++)
|
||||
@ -369,23 +369,23 @@ void Dqn_KeccakUpdate(Dqn_KeccakState *keccak, void const *data, Dqn_KeccakU64 d
|
||||
|
||||
if (keccak->state_size >= keccak->absorb_size)
|
||||
{
|
||||
DQN_KECCAK_ASSERT(keccak->state_size == keccak->absorb_size);
|
||||
Dqn_Keccak__Permute(state);
|
||||
DN_KECCAK_ASSERT(keccak->state_size == keccak->absorb_size);
|
||||
DN_Keccak__Permute(state);
|
||||
keccak->state_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size)
|
||||
void DN_KeccakFinish(DN_KeccakState *keccak, void *dest, int dest_size)
|
||||
{
|
||||
DQN_KECCAK_ASSERT(dest_size >= keccak->hash_size_bits / 8);
|
||||
DN_KECCAK_ASSERT(dest_size >= keccak->hash_size_bits / 8);
|
||||
|
||||
// Sponge Finalization Step: Final padding bit /////////////////////////////////////////////////
|
||||
int const INDEX_OF_0X80_BYTE = keccak->absorb_size - 1;
|
||||
int const delimited_suffix_index = keccak->state_size;
|
||||
DQN_KECCAK_ASSERT(delimited_suffix_index < keccak->absorb_size);
|
||||
DN_KECCAK_ASSERT(delimited_suffix_index < keccak->absorb_size);
|
||||
|
||||
Dqn_KeccakU8 *state = keccak->state;
|
||||
DN_KeccakU8 *state = keccak->state;
|
||||
state[delimited_suffix_index] ^= keccak->delimited_suffix;
|
||||
|
||||
// NOTE: In the reference implementation, it checks that if the
|
||||
@ -398,16 +398,16 @@ void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size)
|
||||
// this from the implementation here.
|
||||
|
||||
state[INDEX_OF_0X80_BYTE] ^= 0x80;
|
||||
Dqn_Keccak__Permute(state);
|
||||
DN_Keccak__Permute(state);
|
||||
|
||||
// Squeeze Step: Squeeze bytes from the state into our hash ////////////////////////////////////
|
||||
Dqn_KeccakU8 *dest_u8 = (Dqn_KeccakU8 *)dest;
|
||||
DN_KeccakU8 *dest_u8 = (DN_KeccakU8 *)dest;
|
||||
int const squeeze_count = dest_size / keccak->absorb_size;
|
||||
int squeeze_index = 0;
|
||||
for (; squeeze_index < squeeze_count; squeeze_index++)
|
||||
{
|
||||
if (squeeze_index) Dqn_Keccak__Permute(state);
|
||||
DQN_KECCAK_MEMCPY(dest_u8, state, keccak->absorb_size);
|
||||
if (squeeze_index) DN_Keccak__Permute(state);
|
||||
DN_KECCAK_MEMCPY(dest_u8, state, keccak->absorb_size);
|
||||
dest_u8 += keccak->absorb_size;
|
||||
}
|
||||
|
||||
@ -415,147 +415,147 @@ void Dqn_KeccakFinish(Dqn_KeccakState *keccak, void *dest, int dest_size)
|
||||
int const remainder = dest_size % keccak->absorb_size;
|
||||
if (remainder)
|
||||
{
|
||||
if (squeeze_index) Dqn_Keccak__Permute(state);
|
||||
DQN_KECCAK_MEMCPY(dest_u8, state, remainder);
|
||||
if (squeeze_index) DN_Keccak__Permute(state);
|
||||
DN_KECCAK_MEMCPY(dest_u8, state, remainder);
|
||||
}
|
||||
}
|
||||
|
||||
void Dqn_KeccakSHA3Hash(bool sha3, int hash_size_bits, void const *src, Dqn_KeccakU64 src_size, void *dest, int dest_size)
|
||||
void DN_KeccakSHA3Hash(bool sha3, int hash_size_bits, void const *src, DN_KeccakU64 src_size, void *dest, int dest_size)
|
||||
{
|
||||
Dqn_KeccakState keccak = Dqn_KeccakSHA3Init(sha3, hash_size_bits);
|
||||
Dqn_KeccakUpdate(&keccak, src, src_size);
|
||||
Dqn_KeccakFinish(&keccak, dest, dest_size);
|
||||
DN_KeccakState keccak = DN_KeccakSHA3Init(sha3, hash_size_bits);
|
||||
DN_KeccakUpdate(&keccak, src, src_size);
|
||||
DN_KeccakFinish(&keccak, dest, dest_size);
|
||||
}
|
||||
|
||||
// NOTE: SHA3 Helpers //////////////////////////////////////////////////////////////////////////////
|
||||
Dqn_KeccakBytes28 Dqn_SHA3_224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size)
|
||||
DN_KeccakBytes28 DN_SHA3_224ToBytes28(void *bytes, DN_KeccakU64 bytes_size)
|
||||
{
|
||||
Dqn_KeccakBytes28 result;
|
||||
Dqn_SHA3_224(bytes, bytes_size, result.data, sizeof(result));
|
||||
DN_KeccakBytes28 result;
|
||||
DN_SHA3_224(bytes, bytes_size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes32 Dqn_SHA3_256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size)
|
||||
DN_KeccakBytes32 DN_SHA3_256ToBytes32(void *bytes, DN_KeccakU64 bytes_size)
|
||||
{
|
||||
Dqn_KeccakBytes32 result;
|
||||
Dqn_SHA3_256(bytes, bytes_size, result.data, sizeof(result));
|
||||
DN_KeccakBytes32 result;
|
||||
DN_SHA3_256(bytes, bytes_size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes48 Dqn_SHA3_384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size)
|
||||
DN_KeccakBytes48 DN_SHA3_384ToBytes48(void *bytes, DN_KeccakU64 bytes_size)
|
||||
{
|
||||
Dqn_KeccakBytes48 result;
|
||||
Dqn_SHA3_384(bytes, bytes_size, result.data, sizeof(result));
|
||||
DN_KeccakBytes48 result;
|
||||
DN_SHA3_384(bytes, bytes_size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes64 Dqn_SHA3_512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size)
|
||||
DN_KeccakBytes64 DN_SHA3_512ToBytes64(void *bytes, DN_KeccakU64 bytes_size)
|
||||
{
|
||||
Dqn_KeccakBytes64 result;
|
||||
Dqn_SHA3_512(bytes, bytes_size, result.data, sizeof(result));
|
||||
DN_KeccakBytes64 result;
|
||||
DN_SHA3_512(bytes, bytes_size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Keccak Helpers ////////////////////////////////////////////////////////////////////////////
|
||||
Dqn_KeccakBytes28 Dqn_Keccak224ToBytes28(void *bytes, Dqn_KeccakU64 bytes_size)
|
||||
DN_KeccakBytes28 DN_Keccak224ToBytes28(void *bytes, DN_KeccakU64 bytes_size)
|
||||
{
|
||||
Dqn_KeccakBytes28 result;
|
||||
Dqn_Keccak224(bytes, bytes_size, result.data, sizeof(result));
|
||||
DN_KeccakBytes28 result;
|
||||
DN_Keccak224(bytes, bytes_size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes32 Dqn_Keccak256ToBytes32(void *bytes, Dqn_KeccakU64 bytes_size)
|
||||
DN_KeccakBytes32 DN_Keccak256ToBytes32(void *bytes, DN_KeccakU64 bytes_size)
|
||||
{
|
||||
Dqn_KeccakBytes32 result;
|
||||
Dqn_Keccak256(bytes, bytes_size, result.data, sizeof(result));
|
||||
DN_KeccakBytes32 result;
|
||||
DN_Keccak256(bytes, bytes_size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes48 Dqn_Keccak384ToBytes48(void *bytes, Dqn_KeccakU64 bytes_size)
|
||||
DN_KeccakBytes48 DN_Keccak384ToBytes48(void *bytes, DN_KeccakU64 bytes_size)
|
||||
{
|
||||
Dqn_KeccakBytes48 result;
|
||||
Dqn_Keccak384(bytes, bytes_size, result.data, sizeof(result));
|
||||
DN_KeccakBytes48 result;
|
||||
DN_Keccak384(bytes, bytes_size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes64 Dqn_Keccak512ToBytes64(void *bytes, Dqn_KeccakU64 bytes_size)
|
||||
DN_KeccakBytes64 DN_Keccak512ToBytes64(void *bytes, DN_KeccakU64 bytes_size)
|
||||
{
|
||||
Dqn_KeccakBytes64 result;
|
||||
Dqn_Keccak512(bytes, bytes_size, result.data, sizeof(result));
|
||||
DN_KeccakBytes64 result;
|
||||
DN_Keccak512(bytes, bytes_size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DQN_H)
|
||||
// NOTE: SHA3 - Helpers for Dqn data structures ////////////////////////////////////////////////////
|
||||
Dqn_KeccakBytes28 Dqn_SHA3_224StringToBytes28(Dqn_Str8 string)
|
||||
#if defined(DN_H)
|
||||
// NOTE: SHA3 - Helpers for DN data structures ////////////////////////////////////////////////////
|
||||
DN_KeccakBytes28 DN_SHA3_224StringToBytes28(DN_Str8 string)
|
||||
{
|
||||
Dqn_KeccakBytes28 result;
|
||||
Dqn_SHA3_224(string.data, string.size, result.data, sizeof(result));
|
||||
DN_KeccakBytes28 result;
|
||||
DN_SHA3_224(string.data, string.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes32 Dqn_SHA3_256StringToBytes32(Dqn_Str8 string)
|
||||
DN_KeccakBytes32 DN_SHA3_256StringToBytes32(DN_Str8 string)
|
||||
{
|
||||
Dqn_KeccakBytes32 result;
|
||||
Dqn_SHA3_256(string.data, string.size, result.data, sizeof(result));
|
||||
DN_KeccakBytes32 result;
|
||||
DN_SHA3_256(string.data, string.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes48 Dqn_SHA3_384StringToBytes48(Dqn_Str8 string)
|
||||
DN_KeccakBytes48 DN_SHA3_384StringToBytes48(DN_Str8 string)
|
||||
{
|
||||
Dqn_KeccakBytes48 result;
|
||||
Dqn_SHA3_384(string.data, string.size, result.data, sizeof(result));
|
||||
DN_KeccakBytes48 result;
|
||||
DN_SHA3_384(string.data, string.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes64 Dqn_SHA3_512StringToBytes64(Dqn_Str8 string)
|
||||
DN_KeccakBytes64 DN_SHA3_512StringToBytes64(DN_Str8 string)
|
||||
{
|
||||
Dqn_KeccakBytes64 result;
|
||||
Dqn_SHA3_512(string.data, string.size, result.data, sizeof(result));
|
||||
DN_KeccakBytes64 result;
|
||||
DN_SHA3_512(string.data, string.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
#endif // DQN_H
|
||||
#endif // DN_H
|
||||
|
||||
#if defined(DQN_H)
|
||||
// NOTE: Keccak - Helpers for Dqn data structures //////////////////////////////////////////////////
|
||||
Dqn_KeccakBytes28 Dqn_Keccak224StringToBytes28(Dqn_Str8 string)
|
||||
#if defined(DN_H)
|
||||
// NOTE: Keccak - Helpers for DN data structures //////////////////////////////////////////////////
|
||||
DN_KeccakBytes28 DN_Keccak224StringToBytes28(DN_Str8 string)
|
||||
{
|
||||
Dqn_KeccakBytes28 result;
|
||||
Dqn_Keccak224(string.data, string.size, result.data, sizeof(result));
|
||||
DN_KeccakBytes28 result;
|
||||
DN_Keccak224(string.data, string.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes32 Dqn_Keccak256StringToBytes32(Dqn_Str8 string)
|
||||
DN_KeccakBytes32 DN_Keccak256StringToBytes32(DN_Str8 string)
|
||||
{
|
||||
Dqn_KeccakBytes32 result;
|
||||
Dqn_Keccak256(string.data, string.size, result.data, sizeof(result));
|
||||
DN_KeccakBytes32 result;
|
||||
DN_Keccak256(string.data, string.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes48 Dqn_Keccak384StringToBytes48(Dqn_Str8 string)
|
||||
DN_KeccakBytes48 DN_Keccak384StringToBytes48(DN_Str8 string)
|
||||
{
|
||||
Dqn_KeccakBytes48 result;
|
||||
Dqn_Keccak384(string.data, string.size, result.data, sizeof(result));
|
||||
DN_KeccakBytes48 result;
|
||||
DN_Keccak384(string.data, string.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakBytes64 Dqn_Keccak512StringToBytes64(Dqn_Str8 string)
|
||||
DN_KeccakBytes64 DN_Keccak512StringToBytes64(DN_Str8 string)
|
||||
{
|
||||
Dqn_KeccakBytes64 result;
|
||||
Dqn_Keccak512(string.data, string.size, result.data, sizeof(result));
|
||||
DN_KeccakBytes64 result;
|
||||
DN_Keccak512(string.data, string.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
#endif // DQN_H
|
||||
#endif // DN_H
|
||||
|
||||
// NOTE: Helper functions //////////////////////////////////////////////////////////////////////////
|
||||
void Dqn_KeccakBytesToHex(void const *src, Dqn_KeccakU64 src_size, char *dest, Dqn_KeccakU64 dest_size)
|
||||
void DN_KeccakBytesToHex(void const *src, DN_KeccakU64 src_size, char *dest, DN_KeccakU64 dest_size)
|
||||
{
|
||||
(void)src_size; (void)dest_size;
|
||||
DQN_KECCAK_ASSERT(dest_size >= src_size * 2);
|
||||
DN_KECCAK_ASSERT(dest_size >= src_size * 2);
|
||||
|
||||
unsigned char *src_u8 = (unsigned char *)src;
|
||||
for (Dqn_KeccakU64 src_index = 0, dest_index = 0;
|
||||
for (DN_KeccakU64 src_index = 0, dest_index = 0;
|
||||
src_index < src_size;
|
||||
src_index += 1, dest_index += 2)
|
||||
{
|
||||
@ -567,70 +567,70 @@ void Dqn_KeccakBytesToHex(void const *src, Dqn_KeccakU64 src_size, char *dest, D
|
||||
}
|
||||
}
|
||||
|
||||
Dqn_KeccakString56 Dqn_KeccakBytes28ToHex(Dqn_KeccakBytes28 const *bytes)
|
||||
DN_KeccakString56 DN_KeccakBytes28ToHex(DN_KeccakBytes28 const *bytes)
|
||||
{
|
||||
Dqn_KeccakString56 result;
|
||||
Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
|
||||
DN_KeccakString56 result;
|
||||
DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
|
||||
result.data[sizeof(result.data) - 1] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakString64 Dqn_KeccakBytes32ToHex(Dqn_KeccakBytes32 const *bytes)
|
||||
DN_KeccakString64 DN_KeccakBytes32ToHex(DN_KeccakBytes32 const *bytes)
|
||||
{
|
||||
Dqn_KeccakString64 result;
|
||||
Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
|
||||
DN_KeccakString64 result;
|
||||
DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
|
||||
result.data[sizeof(result.data) - 1] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakString96 Dqn_KeccakBytes48ToHex(Dqn_KeccakBytes48 const *bytes)
|
||||
DN_KeccakString96 DN_KeccakBytes48ToHex(DN_KeccakBytes48 const *bytes)
|
||||
{
|
||||
Dqn_KeccakString96 result;
|
||||
Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
|
||||
DN_KeccakString96 result;
|
||||
DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
|
||||
result.data[sizeof(result.data) - 1] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_KeccakString128 Dqn_KeccakBytes64ToHex(Dqn_KeccakBytes64 const *bytes)
|
||||
DN_KeccakString128 DN_KeccakBytes64ToHex(DN_KeccakBytes64 const *bytes)
|
||||
{
|
||||
Dqn_KeccakString128 result;
|
||||
Dqn_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
|
||||
DN_KeccakString128 result;
|
||||
DN_KeccakBytesToHex(bytes->data, sizeof(bytes->data), result.data, sizeof(result.data));
|
||||
result.data[sizeof(result.data) - 1] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int Dqn_KeccakBytes28Equals(Dqn_KeccakBytes28 const *a, Dqn_KeccakBytes28 const *b)
|
||||
int DN_KeccakBytes28Equals(DN_KeccakBytes28 const *a, DN_KeccakBytes28 const *b)
|
||||
{
|
||||
int result = DQN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0;
|
||||
int result = DN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int Dqn_KeccakBytes32Equals(Dqn_KeccakBytes32 const *a, Dqn_KeccakBytes32 const *b)
|
||||
int DN_KeccakBytes32Equals(DN_KeccakBytes32 const *a, DN_KeccakBytes32 const *b)
|
||||
{
|
||||
int result = DQN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0;
|
||||
int result = DN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int Dqn_KeccakBytes48Equals(Dqn_KeccakBytes48 const *a, Dqn_KeccakBytes48 const *b)
|
||||
int DN_KeccakBytes48Equals(DN_KeccakBytes48 const *a, DN_KeccakBytes48 const *b)
|
||||
{
|
||||
int result = DQN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0;
|
||||
int result = DN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int Dqn_KeccakBytes64Equals(Dqn_KeccakBytes64 const *a, Dqn_KeccakBytes64 const *b)
|
||||
int DN_KeccakBytes64Equals(DN_KeccakBytes64 const *a, DN_KeccakBytes64 const *b)
|
||||
{
|
||||
int result = DQN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0;
|
||||
int result = DN_KECCAK_MEMCMP(a->data, b->data, sizeof(*a)) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(DQN_H) && defined(DQN_WITH_HEX)
|
||||
// NOTE: Other helper functions for Dqn data structures ////////////////////////////////////////////
|
||||
Dqn_KeccakBytes32 Dqn_KeccakHex64StringToBytes(Dqn_Str8 hex)
|
||||
#if defined(DN_H) && defined(DN_WITH_HEX)
|
||||
// NOTE: Other helper functions for DN data structures ////////////////////////////////////////////
|
||||
DN_KeccakBytes32 DN_KeccakHex64StringToBytes(DN_Str8 hex)
|
||||
{
|
||||
DQN_KECCAK_ASSERT(hex.size == 64);
|
||||
Dqn_KeccakBytes32 result;
|
||||
Dqn_Hex_CString8ToByteBuffer(hex.data, hex.size, result.data, sizeof(result));
|
||||
DN_KECCAK_ASSERT(hex.size == 64);
|
||||
DN_KeccakBytes32 result;
|
||||
DN_Hex_CString8ToByteBuffer(hex.data, hex.size, result.data, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
#endif // DQN_H && DQN_WITH_HEX
|
||||
#endif // DQN_KECCAK_IMPLEMENTATION
|
||||
#endif // DN_H && DN_WITH_HEX
|
||||
#endif // DN_KECCAK_IMPLEMENTATION
|
||||
|
@ -1,5 +1,5 @@
|
||||
#if !defined(DQN_UTEST_H)
|
||||
#define DQN_UTEST_H
|
||||
#if !defined(DN_UTEST_H)
|
||||
#define DN_UTEST_H
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -13,7 +13,7 @@
|
||||
// \$$$$$$ | $$ | $$$$$$$$\ \$$$$$$ | $$ |
|
||||
// \______/ \__| \________| \______/ \__|
|
||||
//
|
||||
// dqn_utest.h -- Extremely minimal unit testing framework
|
||||
// dn_utest.h -- Extremely minimal unit testing framework
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -22,28 +22,28 @@
|
||||
//
|
||||
// NOTE: Configuration /////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// #define DQN_UTEST_IMPLEMENTATION
|
||||
// #define DN_UTEST_IMPLEMENTATION
|
||||
// Define this in one and only one C++ file to enable the implementation
|
||||
// code of the header file. This will also automatically enable the JSMN
|
||||
// implementation.
|
||||
//
|
||||
// #define DQN_UTEST_RESULT_LPAD
|
||||
// #define DN_UTEST_RESULT_LPAD
|
||||
// Define this to a number to specify how much to pad the output of the test
|
||||
// result line before the test result is printed.
|
||||
//
|
||||
// #define DQN_UTEST_RESULT_PAD_CHAR
|
||||
// #define DN_UTEST_RESULT_PAD_CHAR
|
||||
// Define this to a character to specify the default character to use for
|
||||
// padding. By default this is '.'
|
||||
//
|
||||
// #define DQN_UTEST_SPACING
|
||||
// #define DN_UTEST_SPACING
|
||||
// Define this to a number to specify the number of spaces between the group
|
||||
// declaration and the test output in the group.
|
||||
//
|
||||
// #define DQN_UTEST_BAD_COLOR
|
||||
// #define DN_UTEST_BAD_COLOR
|
||||
// Define this to a terminal color code to specify what color errors will be
|
||||
// presented as.
|
||||
//
|
||||
// #define DQN_UTEST_GOOD_COLOR
|
||||
// #define DN_UTEST_GOOD_COLOR
|
||||
// Define this to a terminal color code to specify what color sucess will be
|
||||
// presented as.
|
||||
//
|
||||
@ -56,114 +56,114 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(DQN_UTEST_RESULT_LPAD)
|
||||
#define DQN_UTEST_RESULT_LPAD 90
|
||||
#if !defined(DN_UTEST_RESULT_LPAD)
|
||||
#define DN_UTEST_RESULT_LPAD 90
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_UTEST_RESULT_PAD_CHAR)
|
||||
#define DQN_UTEST_RESULT_PAD_CHAR '.'
|
||||
#if !defined(DN_UTEST_RESULT_PAD_CHAR)
|
||||
#define DN_UTEST_RESULT_PAD_CHAR '.'
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_UTEST_SPACING)
|
||||
#define DQN_UTEST_SPACING 2
|
||||
#if !defined(DN_UTEST_SPACING)
|
||||
#define DN_UTEST_SPACING 2
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_UTEST_BAD_COLOR)
|
||||
#define DQN_UTEST_BAD_COLOR "\x1b[31m"
|
||||
#if !defined(DN_UTEST_BAD_COLOR)
|
||||
#define DN_UTEST_BAD_COLOR "\x1b[31m"
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_UTEST_GOOD_COLOR)
|
||||
#define DQN_UTEST_GOOD_COLOR "\x1b[32m"
|
||||
#if !defined(DN_UTEST_GOOD_COLOR)
|
||||
#define DN_UTEST_GOOD_COLOR "\x1b[32m"
|
||||
#endif
|
||||
|
||||
#define DQN_UTEST_COLOR_RESET "\x1b[0m"
|
||||
#define DN_UTEST_COLOR_RESET "\x1b[0m"
|
||||
|
||||
#define DQN_UTEST_GROUP(test, fmt, ...) \
|
||||
for (Dqn_UTest *test_var_ = (printf(fmt "\n", ## __VA_ARGS__), &test); \
|
||||
#define DN_UTEST_GROUP(test, fmt, ...) \
|
||||
for (DN_UTest *test_var_ = (printf(fmt "\n", ## __VA_ARGS__), &test); \
|
||||
test_var_ != nullptr; \
|
||||
Dqn_UTest_PrintStats(&test), test_var_ = nullptr)
|
||||
DN_UTest_PrintStats(&test), test_var_ = nullptr)
|
||||
|
||||
#define DQN_UTEST_TEST(fmt, ...) \
|
||||
for (int dummy_ = (Dqn_UTest_Begin(test_var_, fmt, ## __VA_ARGS__), 0); \
|
||||
(void)dummy_, test_var_->state == Dqn_UTestState_TestBegun; \
|
||||
Dqn_UTest_End(test_var_))
|
||||
#define DN_UTEST_TEST(fmt, ...) \
|
||||
for (int dummy_ = (DN_UTest_Begin(test_var_, fmt, ## __VA_ARGS__), 0); \
|
||||
(void)dummy_, test_var_->state == DN_UTestState_TestBegun; \
|
||||
DN_UTest_End(test_var_))
|
||||
|
||||
#define DQN_UTEST_ASSERTF(test, expr, fmt, ...) \
|
||||
DQN_UTEST_ASSERTF_AT((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__)
|
||||
#define DN_UTEST_ASSERTF(test, expr, fmt, ...) \
|
||||
DN_UTEST_ASSERTF_AT((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DQN_UTEST_ASSERT(test, expr) \
|
||||
DQN_UTEST_ASSERT_AT((test), __FILE__, __LINE__, (expr))
|
||||
#define DN_UTEST_ASSERT(test, expr) \
|
||||
DN_UTEST_ASSERT_AT((test), __FILE__, __LINE__, (expr))
|
||||
|
||||
// TODO: Fix the logs. They print before the tests, we should accumulate logs
|
||||
// per test, then, dump them on test on. But to do this nicely without crappy
|
||||
// mem management we need to implement an arena.
|
||||
#define DQN_UTEST_LOG(fmt, ...) \
|
||||
fprintf(stdout, "%*s" fmt "\n", DQN_UTEST_SPACING * 2, "", ##__VA_ARGS__)
|
||||
#define DN_UTEST_LOG(fmt, ...) \
|
||||
fprintf(stdout, "%*s" fmt "\n", DN_UTEST_SPACING * 2, "", ##__VA_ARGS__)
|
||||
|
||||
#define DQN_UTEST_ASSERTF_AT(test, file, line, expr, fmt, ...) \
|
||||
#define DN_UTEST_ASSERTF_AT(test, file, line, expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
(test)->state = Dqn_UTestState_TestFailed; \
|
||||
(test)->state = DN_UTestState_TestFailed; \
|
||||
fprintf(stderr, \
|
||||
"%*sAssertion Triggered\n" \
|
||||
"%*sFile: %s:%d\n" \
|
||||
"%*sExpression: [" #expr "]\n" \
|
||||
"%*sReason: " fmt "\n\n", \
|
||||
DQN_UTEST_SPACING * 2, \
|
||||
DN_UTEST_SPACING * 2, \
|
||||
"", \
|
||||
DQN_UTEST_SPACING * 3, \
|
||||
DN_UTEST_SPACING * 3, \
|
||||
"", \
|
||||
file, \
|
||||
line, \
|
||||
DQN_UTEST_SPACING * 3, \
|
||||
DN_UTEST_SPACING * 3, \
|
||||
"", \
|
||||
DQN_UTEST_SPACING * 3, \
|
||||
DN_UTEST_SPACING * 3, \
|
||||
"", \
|
||||
##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DQN_UTEST_ASSERT_AT(test, file, line, expr) \
|
||||
#define DN_UTEST_ASSERT_AT(test, file, line, expr) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
(test)->state = Dqn_UTestState_TestFailed; \
|
||||
(test)->state = DN_UTestState_TestFailed; \
|
||||
fprintf(stderr, \
|
||||
"%*sFile: %s:%d\n" \
|
||||
"%*sExpression: [" #expr "]\n\n", \
|
||||
DQN_UTEST_SPACING * 2, \
|
||||
DN_UTEST_SPACING * 2, \
|
||||
"", \
|
||||
file, \
|
||||
line, \
|
||||
DQN_UTEST_SPACING * 2, \
|
||||
DN_UTEST_SPACING * 2, \
|
||||
""); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// NOTE: Header ////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef enum Dqn_UTestState {
|
||||
Dqn_UTestState_Nil,
|
||||
Dqn_UTestState_TestBegun,
|
||||
Dqn_UTestState_TestFailed,
|
||||
} Dqn_UTestState;
|
||||
typedef enum DN_UTestState {
|
||||
DN_UTestState_Nil,
|
||||
DN_UTestState_TestBegun,
|
||||
DN_UTestState_TestFailed,
|
||||
} DN_UTestState;
|
||||
|
||||
typedef struct Dqn_UTest {
|
||||
typedef struct DN_UTest {
|
||||
int num_tests_in_group;
|
||||
int num_tests_ok_in_group;
|
||||
Dqn_UTestState state;
|
||||
DN_UTestState state;
|
||||
bool finished;
|
||||
char name[256];
|
||||
size_t name_size;
|
||||
} Dqn_UTest;
|
||||
} DN_UTest;
|
||||
|
||||
void Dqn_UTest_PrintStats(Dqn_UTest *test);
|
||||
void Dqn_UTest_BeginV(Dqn_UTest *test, char const *fmt, va_list args);
|
||||
void Dqn_UTest_Begin(Dqn_UTest *test, char const *fmt, ...);
|
||||
void Dqn_UTest_End(Dqn_UTest *test);
|
||||
#endif // DQN_UTEST_H
|
||||
void DN_UTest_PrintStats(DN_UTest *test);
|
||||
void DN_UTest_BeginV(DN_UTest *test, char const *fmt, va_list args);
|
||||
void DN_UTest_Begin(DN_UTest *test, char const *fmt, ...);
|
||||
void DN_UTest_End(DN_UTest *test);
|
||||
#endif // DN_UTEST_H
|
||||
|
||||
// NOTE: Implementation ////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DQN_UTEST_IMPLEMENTATION)
|
||||
void Dqn_UTest_PrintStats(Dqn_UTest *test)
|
||||
#if defined(DN_UTEST_IMPLEMENTATION)
|
||||
void DN_UTest_PrintStats(DN_UTest *test)
|
||||
{
|
||||
if (test->finished)
|
||||
return;
|
||||
@ -171,21 +171,21 @@ void Dqn_UTest_PrintStats(Dqn_UTest *test)
|
||||
test->finished = true;
|
||||
bool all_clear = test->num_tests_ok_in_group == test->num_tests_in_group;
|
||||
fprintf(stdout,
|
||||
"%s\n %02d/%02d tests passed -- %s\n\n" DQN_UTEST_COLOR_RESET,
|
||||
all_clear ? DQN_UTEST_GOOD_COLOR : DQN_UTEST_BAD_COLOR,
|
||||
"%s\n %02d/%02d tests passed -- %s\n\n" DN_UTEST_COLOR_RESET,
|
||||
all_clear ? DN_UTEST_GOOD_COLOR : DN_UTEST_BAD_COLOR,
|
||||
test->num_tests_ok_in_group,
|
||||
test->num_tests_in_group,
|
||||
all_clear ? "OK" : "FAILED");
|
||||
}
|
||||
|
||||
void Dqn_UTest_BeginV(Dqn_UTest *test, char const *fmt, va_list args)
|
||||
void DN_UTest_BeginV(DN_UTest *test, char const *fmt, va_list args)
|
||||
{
|
||||
assert(test->state == Dqn_UTestState_Nil &&
|
||||
assert(test->state == DN_UTestState_Nil &&
|
||||
"Nesting a unit test within another unit test is not allowed, ensure"
|
||||
"the first test has finished by calling Dqn_UTest_End");
|
||||
"the first test has finished by calling DN_UTest_End");
|
||||
|
||||
test->num_tests_in_group++;
|
||||
test->state = Dqn_UTestState_TestBegun;
|
||||
test->state = DN_UTestState_TestBegun;
|
||||
|
||||
test->name_size = 0;
|
||||
{
|
||||
@ -199,32 +199,32 @@ void Dqn_UTest_BeginV(Dqn_UTest *test, char const *fmt, va_list args)
|
||||
vsnprintf(test->name, sizeof(test->name), fmt, args);
|
||||
}
|
||||
|
||||
void Dqn_UTest_Begin(Dqn_UTest *test, char const *fmt, ...)
|
||||
void DN_UTest_Begin(DN_UTest *test, char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_UTest_BeginV(test, fmt, args);
|
||||
DN_UTest_BeginV(test, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Dqn_UTest_End(Dqn_UTest *test)
|
||||
void DN_UTest_End(DN_UTest *test)
|
||||
{
|
||||
assert(test->state != Dqn_UTestState_Nil && "Test was marked as ended but a test was never commenced using Dqn_UTest_Begin");
|
||||
size_t pad_size = DQN_UTEST_RESULT_LPAD - (DQN_UTEST_SPACING + test->name_size);
|
||||
assert(test->state != DN_UTestState_Nil && "Test was marked as ended but a test was never commenced using DN_UTest_Begin");
|
||||
size_t pad_size = DN_UTEST_RESULT_LPAD - (DN_UTEST_SPACING + test->name_size);
|
||||
if (pad_size < 0)
|
||||
pad_size = 0;
|
||||
|
||||
char pad_buffer[DQN_UTEST_RESULT_LPAD] = {};
|
||||
memset(pad_buffer, DQN_UTEST_RESULT_PAD_CHAR, pad_size);
|
||||
char pad_buffer[DN_UTEST_RESULT_LPAD] = {};
|
||||
memset(pad_buffer, DN_UTEST_RESULT_PAD_CHAR, pad_size);
|
||||
|
||||
printf("%*s%.*s%.*s", DQN_UTEST_SPACING, "", (int)test->name_size, test->name, (int)pad_size, pad_buffer);
|
||||
if (test->state == Dqn_UTestState_TestFailed) {
|
||||
printf(DQN_UTEST_BAD_COLOR " FAILED");
|
||||
printf("%*s%.*s%.*s", DN_UTEST_SPACING, "", (int)test->name_size, test->name, (int)pad_size, pad_buffer);
|
||||
if (test->state == DN_UTestState_TestFailed) {
|
||||
printf(DN_UTEST_BAD_COLOR " FAILED");
|
||||
} else {
|
||||
printf(DQN_UTEST_GOOD_COLOR " OK");
|
||||
printf(DN_UTEST_GOOD_COLOR " OK");
|
||||
test->num_tests_ok_in_group++;
|
||||
}
|
||||
printf(DQN_UTEST_COLOR_RESET "\n");
|
||||
test->state = Dqn_UTestState_Nil;
|
||||
printf(DN_UTEST_COLOR_RESET "\n");
|
||||
test->state = DN_UTestState_Nil;
|
||||
}
|
||||
#endif // DQN_UTEST_IMPLEMENTATION
|
||||
#endif // DN_UTEST_IMPLEMENTATION
|
||||
|
@ -13,7 +13,7 @@ pushd Build
|
||||
REM O2 Optimisation Level 2
|
||||
REM Oi Use CPU Intrinsics
|
||||
REM Z7 Combine multi-debug files to one debug file
|
||||
set common_flags=-D DQN_UNIT_TESTS_WITH_MAIN -D DQN_UNIT_TESTS_WITH_KECCAK -D DQN_USE_STD_PRINTF /Tp %script_dir%\dqn.cpp
|
||||
set common_flags=-D DN_UNIT_TESTS_WITH_KECCAK -D DN_USE_STD_PRINTF %script_dir%\dqn_unit_tests_main.cpp
|
||||
|
||||
set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo
|
||||
|
||||
|
38
dqn.cpp
38
dqn.cpp
@ -1,5 +1,7 @@
|
||||
#include "dqn.h"
|
||||
|
||||
#define DN_CPP
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -17,29 +19,29 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
#if defined(DQN_WITH_CGEN)
|
||||
#if !defined(DQN_NO_METADESK)
|
||||
DQN_MSVC_WARNING_PUSH
|
||||
DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: '<function>': unreferenced function with internal linkage has been removed
|
||||
#if defined(DN_WITH_CGEN)
|
||||
#if !defined(DN_NO_METADESK)
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(4505) // warning C4505: '<function>': unreferenced function with internal linkage has been removed
|
||||
|
||||
DQN_GCC_WARNING_PUSH
|
||||
DQN_GCC_WARNING_DISABLE(-Wwrite-strings)
|
||||
DQN_GCC_WARNING_DISABLE(-Wunused-but-set-variable)
|
||||
DQN_GCC_WARNING_DISABLE(-Wsign-compare)
|
||||
DQN_GCC_WARNING_DISABLE(-Wunused-function)
|
||||
DQN_GCC_WARNING_DISABLE(-Wunused-result)
|
||||
DN_GCC_WARNING_PUSH
|
||||
DN_GCC_WARNING_DISABLE(-Wwrite-strings)
|
||||
DN_GCC_WARNING_DISABLE(-Wunused-but-set-variable)
|
||||
DN_GCC_WARNING_DISABLE(-Wsign-compare)
|
||||
DN_GCC_WARNING_DISABLE(-Wunused-function)
|
||||
DN_GCC_WARNING_DISABLE(-Wunused-result)
|
||||
|
||||
#include "External/metadesk/md.c"
|
||||
|
||||
DQN_GCC_WARNING_POP
|
||||
DQN_MSVC_WARNING_POP
|
||||
DN_GCC_WARNING_POP
|
||||
DN_MSVC_WARNING_POP
|
||||
#endif
|
||||
#define DQN_CPP_FILE_IMPLEMENTATION
|
||||
#define DN_CPP_FILE_IMPLEMENTATION
|
||||
#include "Standalone/dqn_cpp_file.h"
|
||||
#include "dqn_cgen.cpp"
|
||||
#endif
|
||||
|
||||
#if defined(DQN_WITH_JSON)
|
||||
#if defined(DN_WITH_JSON)
|
||||
#include "dqn_json.cpp"
|
||||
#endif
|
||||
|
||||
@ -52,12 +54,12 @@
|
||||
#include "dqn_type_info.cpp"
|
||||
#include "dqn_os.cpp"
|
||||
|
||||
#if defined(DQN_PLATFORM_EMSCRIPTEN) || defined(DQN_PLATFORM_POSIX) || defined(DQN_PLATFORM_ARM64)
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_ARM64)
|
||||
#include "dqn_os_posix.cpp"
|
||||
#elif defined(DQN_PLATFORM_WIN32)
|
||||
#elif defined(DN_PLATFORM_WIN32)
|
||||
#include "dqn_os_win32.cpp"
|
||||
#else
|
||||
#error Please define a platform e.g. 'DQN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
|
||||
#error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
|
||||
#endif
|
||||
|
||||
#include "dqn_tls.cpp"
|
||||
@ -65,7 +67,7 @@
|
||||
#include "dqn_hash.cpp"
|
||||
#include "dqn_helpers.cpp"
|
||||
|
||||
#if defined(DQN_WITH_UNIT_TESTS)
|
||||
#if defined(DN_WITH_UNIT_TESTS)
|
||||
#include "dqn_unit_tests.cpp"
|
||||
#endif
|
||||
|
||||
|
237
dqn.h
237
dqn.h
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define DQN_H
|
||||
#define DN_H
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -14,7 +14,7 @@
|
||||
// \_______/ \___$$$\ \__| \__|
|
||||
// \___|
|
||||
//
|
||||
// dqn.h -- Personal standard library -- MIT License -- git.doylet.dev/dqn
|
||||
// dqn.h -- Personal standard library -- MIT License -- git.doylet.dev/dn
|
||||
// ASCII -- BigMoney-NW by Nathan Bloomfild
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -43,21 +43,21 @@
|
||||
//
|
||||
// -- Compiling --
|
||||
//
|
||||
// Compile dqn.cpp or include it into one of your translation units.
|
||||
// Compile dn.cpp or include it into one of your translation units.
|
||||
//
|
||||
// Additionally, this library supports including/excluding specific sections
|
||||
// of the library by using #define on the name of the section. These names are
|
||||
// documented in the section table of contents at the #define column, for
|
||||
// example:
|
||||
//
|
||||
// #define DQN_ONLY_VARRAY
|
||||
// #define DQN_ONLY_WIN
|
||||
// #define DN_ONLY_VARRAY
|
||||
// #define DN_ONLY_WIN
|
||||
//
|
||||
// Compiles the library with all optional APIs turned off except virtual arrays
|
||||
// and the Win32 helpers. Alternatively:
|
||||
//
|
||||
// #define DQN_NO_VARRAY
|
||||
// #define DQN_NO_WIN
|
||||
// #define DN_NO_VARRAY
|
||||
// #define DN_NO_WIN
|
||||
//
|
||||
// Compiles the library with all optional APIs turned on except the previously
|
||||
// mentioned APIs.
|
||||
@ -69,7 +69,7 @@
|
||||
// drowning out the library interface with code comments like many other
|
||||
// documentation systems.
|
||||
//
|
||||
// Instead, documentation is laid out in dqn_docs.cpp in alphabetical order
|
||||
// Instead, documentation is laid out in dn_docs.cpp in alphabetical order
|
||||
// which provides self-contained examples in one contiguous top-down block of
|
||||
// source code with comments.
|
||||
//
|
||||
@ -91,51 +91,51 @@
|
||||
// - Override these routines from the CRT by redefining them. By default we wrap
|
||||
// the CRT functions from <strings.h> and <math.h>, e.g:
|
||||
//
|
||||
// #define DQN_MEMCPY(dest, src, count) memcpy(dest, src, value)
|
||||
// #define DQN_MEMSET(dest, value, count) memset(dest, value, count)
|
||||
// #define DQN_MEMCMP(lhs, rhs, count) memcpy(lhs, rhs, count)
|
||||
// #define DQN_MEMMOVE(dest, src, count) memmove(dest, src, count)
|
||||
// #define DQN_SQRTF(val) sqrtf(val)
|
||||
// #define DQN_SINF(val) sinf(val)
|
||||
// #define DQN_COSF(val) cosf(val)
|
||||
// #define DQN_TANF(val) tanf(val)
|
||||
// #define DN_MEMCPY(dest, src, count) memcpy(dest, src, value)
|
||||
// #define DN_MEMSET(dest, value, count) memset(dest, value, count)
|
||||
// #define DN_MEMCMP(lhs, rhs, count) memcpy(lhs, rhs, count)
|
||||
// #define DN_MEMMOVE(dest, src, count) memmove(dest, src, count)
|
||||
// #define DN_SQRTF(val) sqrtf(val)
|
||||
// #define DN_SINF(val) sinf(val)
|
||||
// #define DN_COSF(val) cosf(val)
|
||||
// #define DN_TANF(val) tanf(val)
|
||||
//
|
||||
// - Redefine 'DQN_API' to change the prefix of all declared functions in the library
|
||||
// - Redefine 'DN_API' to change the prefix of all declared functions in the library
|
||||
//
|
||||
// #define DQN_API
|
||||
// #define DN_API
|
||||
//
|
||||
// - Define 'DQN_STATIC_API' to apply 'static' to all function definitions and
|
||||
// disable external linkage to other translation units by redefining 'DQN_API' to
|
||||
// - Define 'DN_STATIC_API' to apply 'static' to all function definitions and
|
||||
// disable external linkage to other translation units by redefining 'DN_API' to
|
||||
// 'static'.
|
||||
//
|
||||
// #define DQN_STATIC_API
|
||||
// #define DN_STATIC_API
|
||||
//
|
||||
// - Turn all assertion macros to no-ops except for hard asserts (which are
|
||||
// always enabled and represent unrecoverable errors in the library).
|
||||
//
|
||||
// #define DQN_NO_ASSERT
|
||||
// #define DN_NO_ASSERT
|
||||
//
|
||||
// - Augment DQN_CHECK(expr) macro's behaviour. By default when the check fails a
|
||||
// - Augment DN_CHECK(expr) macro's behaviour. By default when the check fails a
|
||||
// debug break is emitted. If this macro is defined, the check will not trigger
|
||||
// a debug break.
|
||||
//
|
||||
// #define DQN_NO_CHECK_BREAK
|
||||
// #define DN_NO_CHECK_BREAK
|
||||
//
|
||||
// - Define this macro to enable memory leak tracking on arena's that are
|
||||
// configured to track allocations.
|
||||
//
|
||||
// Allocations are stored in a global hash-table and their respective stack
|
||||
// traces for the allocation location. Memory leaks can be dumped at the end
|
||||
// of the program or some epoch by calling Dqn_Debug_DumpLeaks()
|
||||
// of the program or some epoch by calling DN_Debug_DumpLeaks()
|
||||
//
|
||||
// #define DQN_LEAK_TRACKING
|
||||
// #define DN_LEAK_TRACKING
|
||||
//
|
||||
// - Define this to revert to the family of printf functions from <stdio.h>
|
||||
// instead of using stb_sprintf in this library. stb_sprintf is 5-6x faster
|
||||
// than printf with a smaller binary footprint and has deterministic behaviour
|
||||
// across all supported platforms.
|
||||
//
|
||||
// #define DQN_USE_STD_PRINTF
|
||||
// #define DN_USE_STD_PRINTF
|
||||
//
|
||||
// However, if you are compiling with ASAN on MSVC, MSVC's implementation of
|
||||
// __declspec(no_sanitize_address) is unable to suppress warnings in some
|
||||
@ -148,17 +148,17 @@
|
||||
// intend to #include <Windows.h> yourself to avoid symbol conflicts with
|
||||
// the redefined declarations in this library.
|
||||
//
|
||||
// #define DQN_NO_WIN32_MIN_HEADER
|
||||
// #define DN_NO_WIN32_MIN_HEADER
|
||||
//
|
||||
// - Define this to stop this library from defining STB_SPRINTF_IMPLEMENTATION.
|
||||
// Useful if another library uses and includes "stb_sprintf.h"
|
||||
//
|
||||
// #define DQN_STB_SPRINTF_HEADER_ONLY
|
||||
// #define DN_STB_SPRINTF_HEADER_ONLY
|
||||
//
|
||||
// - Override the default break into the active debugger function. By default
|
||||
// we use __debugbreak() on Windows and raise(SIGTRAP) on other platforms.
|
||||
//
|
||||
// #define DQN_DEBUG_BREAK
|
||||
// #define DN_DEBUG_BREAK
|
||||
//
|
||||
// - Define this macro to 1 to enable poisoning of memory from arenas when ASAN
|
||||
// `-fsanitize=address` is enabled. Enabling this will detect memory overwrite
|
||||
@ -166,181 +166,188 @@
|
||||
// a use-after-poison in ASAN on read/write. This is a no-op if the library is
|
||||
// not compiled with ASAN.
|
||||
//
|
||||
// #define DQN_ASAN_POISON 1
|
||||
// #define DN_ASAN_POISON 1
|
||||
//
|
||||
// - Define this macro 1 to enable sanity checks for manually poisoned memory in
|
||||
// this library when ASAN `-fsanitize=address` is enabled. These sanity checks
|
||||
// ensure that memory from arenas are correctly un/poisoned when pointers are
|
||||
// allocated and returned to the memory arena's. This is a no-op if we are not
|
||||
// compiled with ASAN or `DQN_ASAN_POISON` is not set to `1`.
|
||||
// compiled with ASAN or `DN_ASAN_POISON` is not set to `1`.
|
||||
//
|
||||
// #define DQN_ASAN_VET_POISON 1
|
||||
// #define DN_ASAN_VET_POISON 1
|
||||
//
|
||||
// - Define this macro to the size of the guard memory reserved before and after
|
||||
// allocations made that are poisoned to protect against out-of-bounds memory
|
||||
// accesses. By default the library sets the guard to 128 bytes.
|
||||
//
|
||||
// #define DQN_ASAN_POISON_GUARD_SIZE 128
|
||||
// #define DN_ASAN_POISON_GUARD_SIZE 128
|
||||
//
|
||||
// - Enable 'Dqn_CGen' a parser that can emit run-time type information and
|
||||
// - Enable 'DN_CGen' a parser that can emit run-time type information and
|
||||
// allow arbitrary querying of data definitions expressed in Excel-like tables
|
||||
// using text files encoded in Dion-System's Metadesk grammar.
|
||||
//
|
||||
// This option automatically includes 'dqn_cpp_file.h' to assist with code
|
||||
// This option automatically includes 'dn_cpp_file.h' to assist with code
|
||||
// generation and Metadesk's 'md.h' and its implementation library.
|
||||
//
|
||||
// #define DQN_WITH_CGEN
|
||||
// #define DN_WITH_CGEN
|
||||
//
|
||||
// Optionally define 'DQN_NO_METADESK' to disable the inclusion of Metadesk
|
||||
// Optionally define 'DN_NO_METADESK' to disable the inclusion of Metadesk
|
||||
// in the library. This might be useful if you are including the librarin in
|
||||
// your project yourself. This library must still be defined and visible
|
||||
// before this header.
|
||||
//
|
||||
// - Enable 'Dqn_JSON' a json parser. This option requires Sheredom's 'json.h'
|
||||
// - Enable 'DN_JSON' a json parser. This option requires Sheredom's 'json.h'
|
||||
// to be included prior to this file.
|
||||
//
|
||||
// #define DQN_WITH_JSON
|
||||
// #define DN_WITH_JSON
|
||||
//
|
||||
// Optionally define 'DQN_NO_SHEREDOM_JSON' to prevent Sheredom's 'json.h'
|
||||
// Optionally define 'DN_NO_SHEREDOM_JSON' to prevent Sheredom's 'json.h'
|
||||
// library from being included. This might be useful if you are including the
|
||||
// library in your project yourself. The library must still be defined and
|
||||
// visible before this header.
|
||||
//
|
||||
// - Enable compilation of unit tests with the library.
|
||||
//
|
||||
// #define DQN_WITH_UNIT_TESTS
|
||||
// #define DN_WITH_UNIT_TESTS
|
||||
//
|
||||
// - Increase the capacity of the job queue, default is 128.
|
||||
//
|
||||
// #define DQN_JOB_QUEUE_SPMC_SIZE 128
|
||||
// #define DN_JOB_QUEUE_SPMC_SIZE 128
|
||||
*/
|
||||
|
||||
#if defined(DQN_ONLY_VARRAY) || \
|
||||
defined(DQN_ONLY_SARRAY) || \
|
||||
defined(DQN_ONLY_FARRAY) || \
|
||||
defined(DQN_ONLY_DSMAP) || \
|
||||
defined(DQN_ONLY_LIST) || \
|
||||
defined(DQN_ONLY_FSTR8) || \
|
||||
defined(DQN_ONLY_FS) || \
|
||||
defined(DQN_ONLY_WINNET) || \
|
||||
defined(DQN_ONLY_WIN) || \
|
||||
defined(DQN_ONLY_SEMAPHORE) || \
|
||||
defined(DQN_ONLY_THREAD) || \
|
||||
defined(DQN_ONLY_V2) || \
|
||||
defined(DQN_ONLY_V3) || \
|
||||
defined(DQN_ONLY_V4) || \
|
||||
defined(DQN_ONLY_M4) || \
|
||||
defined(DQN_ONLY_RECT) || \
|
||||
defined(DQN_ONLY_JSON_BUILDER) || \
|
||||
defined(DQN_ONLY_BIN) || \
|
||||
defined(DQN_ONLY_PROFILER)
|
||||
#if defined(DN_ONLY_VARRAY) || \
|
||||
defined(DN_ONLY_SARRAY) || \
|
||||
defined(DN_ONLY_FARRAY) || \
|
||||
defined(DN_ONLY_DSMAP) || \
|
||||
defined(DN_ONLY_LIST) || \
|
||||
defined(DN_ONLY_FSTR8) || \
|
||||
defined(DN_ONLY_FS) || \
|
||||
defined(DN_ONLY_WINNET) || \
|
||||
defined(DN_ONLY_WIN) || \
|
||||
defined(DN_ONLY_SEMAPHORE) || \
|
||||
defined(DN_ONLY_THREAD) || \
|
||||
defined(DN_ONLY_V2) || \
|
||||
defined(DN_ONLY_V3) || \
|
||||
defined(DN_ONLY_V4) || \
|
||||
defined(DN_ONLY_M4) || \
|
||||
defined(DN_ONLY_RECT) || \
|
||||
defined(DN_ONLY_JSON_BUILDER) || \
|
||||
defined(DN_ONLY_BIN) || \
|
||||
defined(DN_ONLY_PROFILER)
|
||||
|
||||
#if !defined(DQN_ONLY_VARRAY)
|
||||
#define DQN_NO_VARRAY
|
||||
#if !defined(DN_ONLY_VARRAY)
|
||||
#define DN_NO_VARRAY
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_FARRAY)
|
||||
#define DQN_NO_FARRAY
|
||||
#if !defined(DN_ONLY_FARRAY)
|
||||
#define DN_NO_FARRAY
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_SARRAY)
|
||||
#define DQN_NO_SARRAY
|
||||
#if !defined(DN_ONLY_SARRAY)
|
||||
#define DN_NO_SARRAY
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_DSMAP)
|
||||
#define DQN_NO_DSMAP
|
||||
#if !defined(DN_ONLY_DSMAP)
|
||||
#define DN_NO_DSMAP
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_LIST)
|
||||
#define DQN_NO_LIST
|
||||
#if !defined(DN_ONLY_LIST)
|
||||
#define DN_NO_LIST
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_FSTR8)
|
||||
#define DQN_NO_FSTR8
|
||||
#if !defined(DN_ONLY_FSTR8)
|
||||
#define DN_NO_FSTR8
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_FS)
|
||||
#define DQN_NO_FS
|
||||
#if !defined(DN_ONLY_FS)
|
||||
#define DN_NO_FS
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_WINNET)
|
||||
#define DQN_NO_WINNET
|
||||
#if !defined(DN_ONLY_WINNET)
|
||||
#define DN_NO_WINNET
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_WIN)
|
||||
#define DQN_NO_WIN
|
||||
#if !defined(DN_ONLY_WIN)
|
||||
#define DN_NO_WIN
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_SEMAPHORE)
|
||||
#define DQN_NO_SEMAPHORE
|
||||
#if !defined(DN_ONLY_SEMAPHORE)
|
||||
#define DN_NO_SEMAPHORE
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_THREAD)
|
||||
#define DQN_NO_THREAD
|
||||
#if !defined(DN_ONLY_THREAD)
|
||||
#define DN_NO_THREAD
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_V2)
|
||||
#define DQN_NO_V2
|
||||
#if !defined(DN_ONLY_V2)
|
||||
#define DN_NO_V2
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_V3)
|
||||
#define DQN_NO_V3
|
||||
#if !defined(DN_ONLY_V3)
|
||||
#define DN_NO_V3
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_V4)
|
||||
#define DQN_NO_V4
|
||||
#if !defined(DN_ONLY_V4)
|
||||
#define DN_NO_V4
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_M4)
|
||||
#define DQN_NO_M4
|
||||
#if !defined(DN_ONLY_M4)
|
||||
#define DN_NO_M4
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_RECT)
|
||||
#define DQN_NO_RECT
|
||||
#if !defined(DN_ONLY_RECT)
|
||||
#define DN_NO_RECT
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_JSON_BUILDER)
|
||||
#define DQN_NO_JSON_BUILDER
|
||||
#if !defined(DN_ONLY_JSON_BUILDER)
|
||||
#define DN_NO_JSON_BUILDER
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_BIN)
|
||||
#define DQN_NO_BIN
|
||||
#if !defined(DN_ONLY_BIN)
|
||||
#define DN_NO_BIN
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_PROFILER)
|
||||
#define DQN_NO_PROFILER
|
||||
#if !defined(DN_ONLY_PROFILER)
|
||||
#define DN_NO_PROFILER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(DQN_WITH_CGEN)
|
||||
#if !defined(DQN_NO_METADESK)
|
||||
#include "dqn_base.h"
|
||||
#if defined(DN_WITH_CGEN)
|
||||
#if !defined(DN_NO_METADESK)
|
||||
#if !defined(_CRT_SECURE_NO_WARNINGS)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define DQN_UNDO_CRT_SECURE_NO_WARNINGS
|
||||
#define DN_UNDO_CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
// NOTE: Metadesk does not have the header for 'size_t'
|
||||
#if defined(DN_COMPILER_GCC)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define MD_DEFAULT_SPRINTF 0
|
||||
#define MD_IMPL_Vsnprintf DQN_VSNPRINTF
|
||||
#define MD_IMPL_Vsnprintf DN_VSNPRINTF
|
||||
#include "External/metadesk/md.h"
|
||||
#if defined(DQN_UNDO_CRT_SECURE_NO_WARNINGS)
|
||||
#if defined(DN_UNDO_CRT_SECURE_NO_WARNINGS)
|
||||
#undef _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Metadesk includes Windows.h
|
||||
#define DQN_NO_WIN32_MIN_HEADER
|
||||
#define DN_NO_WIN32_MIN_HEADER
|
||||
#endif
|
||||
|
||||
#include "dqn_base.h"
|
||||
#include "dqn_external.h"
|
||||
#if defined(DQN_PLATFORM_WIN32)
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
#include "dqn_win32.h"
|
||||
#endif
|
||||
#include "dqn_allocator.h"
|
||||
#include "dqn_tls.h"
|
||||
#include "dqn_debug.h"
|
||||
#include "dqn_string.h"
|
||||
#include "dqn_containers.h"
|
||||
#if defined(DQN_PLATFORM_EMSCRIPTEN) || defined(DQN_PLATFORM_POSIX) || defined(DQN_PLATFORM_ARM64)
|
||||
#elif defined(DQN_PLATFORM_WIN32)
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_ARM64)
|
||||
#include "dqn_os_posix.h"
|
||||
#elif defined(DN_PLATFORM_WIN32)
|
||||
#include "dqn_os_win32.h"
|
||||
#else
|
||||
#error Please define a platform e.g. 'DQN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
|
||||
#error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
|
||||
#endif
|
||||
#include "dqn_os.h"
|
||||
#include "dqn_containers.h"
|
||||
#include "dqn_math.h"
|
||||
#include "dqn_hash.h"
|
||||
#include "dqn_helpers.h"
|
||||
#include "dqn_type_info.h"
|
||||
|
||||
#if defined(DQN_WITH_CGEN)
|
||||
#if defined(DN_WITH_CGEN)
|
||||
#include "Standalone/dqn_cpp_file.h"
|
||||
#include "dqn_cgen.h"
|
||||
#endif
|
||||
|
||||
#if defined(DQN_WITH_JSON)
|
||||
#if !defined(DQN_NO_SHEREDOM_JSON)
|
||||
#if defined(DN_WITH_JSON)
|
||||
#if !defined(DN_NO_SHEREDOM_JSON)
|
||||
#include "External/json.h"
|
||||
#endif
|
||||
#include "dqn_json.h"
|
||||
|
@ -15,265 +15,303 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$AREN] Dqn_Arena /////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_ArenaBlock *Dqn_Arena_BlockInit(uint64_t reserve, uint64_t commit, bool track_alloc, bool alloc_can_leak)
|
||||
// NOTE: [$AREN] DN_Arena /////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_ArenaBlock *DN_Arena_BlockInit(DN_U64 reserve, DN_U64 commit, bool track_alloc, bool alloc_can_leak)
|
||||
{
|
||||
Dqn_usize const page_size = g_dqn_library->os_page_size;
|
||||
uint64_t real_reserve = reserve ? reserve : DQN_ARENA_RESERVE_SIZE;
|
||||
uint64_t real_commit = commit ? commit : DQN_ARENA_COMMIT_SIZE;
|
||||
real_reserve = Dqn_AlignUpPowerOfTwo(real_reserve, page_size);
|
||||
real_commit = DQN_MIN(Dqn_AlignUpPowerOfTwo(real_commit, page_size), real_reserve);
|
||||
DN_USize const page_size = g_dn_core->os_page_size;
|
||||
DN_U64 real_reserve = reserve ? reserve : DN_ARENA_RESERVE_SIZE;
|
||||
DN_U64 real_commit = commit ? commit : DN_ARENA_COMMIT_SIZE;
|
||||
real_reserve = DN_AlignUpPowerOfTwo(real_reserve, page_size);
|
||||
real_commit = DN_MIN(DN_AlignUpPowerOfTwo(real_commit, page_size), real_reserve);
|
||||
|
||||
DQN_ASSERTF(DQN_ARENA_HEADER_SIZE < real_commit && real_commit <= real_reserve, "%I64u < %I64u <= %I64u", DQN_ARENA_HEADER_SIZE, real_commit, real_reserve);
|
||||
DQN_ASSERTF(page_size, "Call Dqn_Library_Init() to initialise the known page size");
|
||||
DN_ASSERTF(DN_ARENA_HEADER_SIZE < real_commit && real_commit <= real_reserve, "%I64u < %I64u <= %I64u", DN_ARENA_HEADER_SIZE, real_commit, real_reserve);
|
||||
DN_ASSERTF(page_size, "Call DN_Library_Init() to initialise the known page size");
|
||||
|
||||
Dqn_OSMemCommit mem_commit = real_reserve == real_commit ? Dqn_OSMemCommit_Yes : Dqn_OSMemCommit_No;
|
||||
Dqn_ArenaBlock *result = DQN_CAST(Dqn_ArenaBlock *)Dqn_OS_MemReserve(real_reserve, mem_commit, Dqn_OSMemPage_ReadWrite);
|
||||
DN_OSMemCommit mem_commit = real_reserve == real_commit ? DN_OSMemCommit_Yes : DN_OSMemCommit_No;
|
||||
DN_ArenaBlock *result = DN_CAST(DN_ArenaBlock *)DN_OS_MemReserve(real_reserve, mem_commit, DN_OSMemPage_ReadWrite);
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
if (mem_commit == Dqn_OSMemCommit_No && !Dqn_OS_MemCommit(result, real_commit, Dqn_OSMemPage_ReadWrite)) {
|
||||
Dqn_OS_MemRelease(result, real_reserve);
|
||||
if (mem_commit == DN_OSMemCommit_No && !DN_OS_MemCommit(result, real_commit, DN_OSMemPage_ReadWrite)) {
|
||||
DN_OS_MemRelease(result, real_reserve);
|
||||
return result;
|
||||
}
|
||||
|
||||
result->used = DQN_ARENA_HEADER_SIZE;
|
||||
result->used = DN_ARENA_HEADER_SIZE;
|
||||
result->commit = real_commit;
|
||||
result->reserve = real_reserve;
|
||||
|
||||
if (track_alloc)
|
||||
Dqn_Debug_TrackAlloc(result, result->reserve, alloc_can_leak);
|
||||
DN_Debug_TrackAlloc(result, result->reserve, alloc_can_leak);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_ArenaBlock *Dqn_Arena_BlockInitFlags(uint64_t reserve, uint64_t commit, uint8_t arena_flags)
|
||||
DN_API DN_ArenaBlock *DN_Arena_BlockInitFlags(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags)
|
||||
{
|
||||
bool track_alloc = (arena_flags & Dqn_ArenaFlag_NoAllocTrack) == 0;
|
||||
bool alloc_can_leak = arena_flags & Dqn_ArenaFlag_AllocCanLeak;
|
||||
Dqn_ArenaBlock *result = Dqn_Arena_BlockInit(reserve, commit, track_alloc, alloc_can_leak);
|
||||
if (result && ((arena_flags & Dqn_ArenaFlag_NoPoison) == 0))
|
||||
Dqn_ASAN_PoisonMemoryRegion(DQN_CAST(char *)result + DQN_ARENA_HEADER_SIZE, result->commit - DQN_ARENA_HEADER_SIZE);
|
||||
bool track_alloc = (flags & DN_ArenaFlags_NoAllocTrack) == 0;
|
||||
bool alloc_can_leak = flags & DN_ArenaFlags_AllocCanLeak;
|
||||
DN_ArenaBlock *result = DN_Arena_BlockInit(reserve, commit, track_alloc, alloc_can_leak);
|
||||
if (result && ((flags & DN_ArenaFlags_NoPoison) == 0))
|
||||
DN_ASAN_PoisonMemoryRegion(DN_CAST(char *)result + DN_ARENA_HEADER_SIZE, result->commit - DN_ARENA_HEADER_SIZE);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void Dqn_Arena_UpdateStatsOnNewBlock_(Dqn_Arena *arena, Dqn_ArenaBlock const *block)
|
||||
static void DN_Arena_UpdateStatsOnNewBlock_(DN_Arena *arena, DN_ArenaBlock const *block)
|
||||
{
|
||||
DQN_ASSERT(arena);
|
||||
DN_ASSERT(arena);
|
||||
if (block) {
|
||||
arena->stats.info.used += block->used;
|
||||
arena->stats.info.commit += block->commit;
|
||||
arena->stats.info.reserve += block->reserve;
|
||||
arena->stats.info.blocks += 1;
|
||||
|
||||
arena->stats.hwm.used = DQN_MAX(arena->stats.hwm.used, arena->stats.info.used);
|
||||
arena->stats.hwm.commit = DQN_MAX(arena->stats.hwm.commit, arena->stats.info.commit);
|
||||
arena->stats.hwm.reserve = DQN_MAX(arena->stats.hwm.reserve, arena->stats.info.reserve);
|
||||
arena->stats.hwm.blocks = DQN_MAX(arena->stats.hwm.blocks, arena->stats.info.blocks);
|
||||
arena->stats.hwm.used = DN_MAX(arena->stats.hwm.used, arena->stats.info.used);
|
||||
arena->stats.hwm.commit = DN_MAX(arena->stats.hwm.commit, arena->stats.info.commit);
|
||||
arena->stats.hwm.reserve = DN_MAX(arena->stats.hwm.reserve, arena->stats.info.reserve);
|
||||
arena->stats.hwm.blocks = DN_MAX(arena->stats.hwm.blocks, arena->stats.info.blocks);
|
||||
}
|
||||
}
|
||||
|
||||
DQN_API Dqn_Arena Dqn_Arena_InitSize(uint64_t reserve, uint64_t commit, uint8_t flags)
|
||||
DN_API DN_Arena DN_Arena_InitBuffer(void *buffer, DN_USize size, DN_ArenaFlags flags)
|
||||
{
|
||||
Dqn_Arena result = {};
|
||||
result.flags = flags;
|
||||
result.curr = Dqn_Arena_BlockInitFlags(reserve, commit, flags);
|
||||
Dqn_Arena_UpdateStatsOnNewBlock_(&result, result.curr);
|
||||
DN_ASSERT(buffer);
|
||||
DN_ASSERTF(DN_ARENA_HEADER_SIZE < size, "Buffer (%zu bytes) too small, need atleast %zu bytes to store arena metadata", size, DN_ARENA_HEADER_SIZE);
|
||||
DN_ASSERTF(DN_IsPowerOfTwo(size), "Buffer (%zu bytes) must be a power-of-two", size);
|
||||
|
||||
// NOTE: Init block
|
||||
DN_ArenaBlock *block = DN_CAST(DN_ArenaBlock *) buffer;
|
||||
block->commit = size;
|
||||
block->reserve = size;
|
||||
block->used = DN_ARENA_HEADER_SIZE;
|
||||
if (block && ((flags & DN_ArenaFlags_NoPoison) == 0)) {
|
||||
DN_ASAN_PoisonMemoryRegion(DN_CAST(char *)block + DN_ARENA_HEADER_SIZE, block->commit - DN_ARENA_HEADER_SIZE);
|
||||
}
|
||||
|
||||
DN_Arena result = {};
|
||||
result.flags = flags | DN_ArenaFlags_NoGrow | DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_UserBuffer;
|
||||
result.curr = block;
|
||||
DN_Arena_UpdateStatsOnNewBlock_(&result, result.curr);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void Dqn_Arena_BlockDeinit_(Dqn_Arena const *arena, Dqn_ArenaBlock *block)
|
||||
DN_API DN_Arena DN_Arena_InitSize(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags)
|
||||
{
|
||||
Dqn_usize release_size = block->reserve;
|
||||
if (Dqn_Bit_IsNotSet(arena->flags, Dqn_ArenaFlag_NoAllocTrack))
|
||||
Dqn_Debug_TrackDealloc(block);
|
||||
Dqn_ASAN_UnpoisonMemoryRegion(block, block->commit);
|
||||
Dqn_OS_MemRelease(block, release_size);
|
||||
DN_Arena result = {};
|
||||
result.flags = flags;
|
||||
result.curr = DN_Arena_BlockInitFlags(reserve, commit, flags);
|
||||
DN_Arena_UpdateStatsOnNewBlock_(&result, result.curr);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Arena_Deinit(Dqn_Arena *arena)
|
||||
static void DN_Arena_BlockDeinit_(DN_Arena const *arena, DN_ArenaBlock *block)
|
||||
{
|
||||
for (Dqn_ArenaBlock *block = arena ? arena->curr : nullptr; block; ) {
|
||||
Dqn_ArenaBlock *block_to_free = block;
|
||||
DN_USize release_size = block->reserve;
|
||||
if (DN_Bit_IsNotSet(arena->flags, DN_ArenaFlags_NoAllocTrack))
|
||||
DN_Debug_TrackDealloc(block);
|
||||
DN_ASAN_UnpoisonMemoryRegion(block, block->commit);
|
||||
DN_OS_MemRelease(block, release_size);
|
||||
}
|
||||
|
||||
DN_API void DN_Arena_Deinit(DN_Arena *arena)
|
||||
{
|
||||
for (DN_ArenaBlock *block = arena ? arena->curr : nullptr; block; ) {
|
||||
DN_ArenaBlock *block_to_free = block;
|
||||
block = block->prev;
|
||||
Dqn_Arena_BlockDeinit_(arena, block_to_free);
|
||||
DN_Arena_BlockDeinit_(arena, block_to_free);
|
||||
}
|
||||
if (arena)
|
||||
*arena = {};
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_Arena_CommitTo(Dqn_Arena *arena, uint64_t pos)
|
||||
DN_API bool DN_Arena_CommitTo(DN_Arena *arena, DN_U64 pos)
|
||||
{
|
||||
if (!arena || !arena->curr)
|
||||
return false;
|
||||
|
||||
Dqn_ArenaBlock *curr = arena->curr;
|
||||
DN_ArenaBlock *curr = arena->curr;
|
||||
if (pos <= curr->commit)
|
||||
return true;
|
||||
|
||||
uint64_t real_pos = pos;
|
||||
if (!DQN_CHECK(pos <= curr->reserve))
|
||||
DN_U64 real_pos = pos;
|
||||
if (!DN_CHECK(pos <= curr->reserve))
|
||||
real_pos = curr->reserve;
|
||||
|
||||
Dqn_usize end_commit = Dqn_AlignUpPowerOfTwo(real_pos, g_dqn_library->os_page_size);
|
||||
Dqn_usize commit_size = end_commit - curr->commit;
|
||||
char *commit_ptr = DQN_CAST(char *) curr + curr->commit;
|
||||
if (!Dqn_OS_MemCommit(commit_ptr, commit_size, Dqn_OSMemPage_ReadWrite))
|
||||
DN_USize end_commit = DN_AlignUpPowerOfTwo(real_pos, g_dn_core->os_page_size);
|
||||
DN_USize commit_size = end_commit - curr->commit;
|
||||
char *commit_ptr = DN_CAST(char *) curr + curr->commit;
|
||||
if (!DN_OS_MemCommit(commit_ptr, commit_size, DN_OSMemPage_ReadWrite))
|
||||
return false;
|
||||
|
||||
bool poison = DQN_ASAN_POISON && ((arena->flags & Dqn_ArenaFlag_NoPoison) == 0);
|
||||
bool poison = DN_ASAN_POISON && ((arena->flags & DN_ArenaFlags_NoPoison) == 0);
|
||||
if (poison)
|
||||
Dqn_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
|
||||
DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
|
||||
|
||||
curr->commit = end_commit;
|
||||
return true;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_Arena_Commit(Dqn_Arena *arena, uint64_t size)
|
||||
DN_API bool DN_Arena_Commit(DN_Arena *arena, DN_U64 size)
|
||||
{
|
||||
if (!arena || !arena->curr)
|
||||
return false;
|
||||
uint64_t pos = arena->curr->commit + size;
|
||||
bool result = Dqn_Arena_CommitTo(arena, pos);
|
||||
DN_U64 pos = arena->curr->commit + size;
|
||||
bool result = DN_Arena_CommitTo(arena, pos);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void *Dqn_Arena_Alloc(Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem)
|
||||
DN_API bool DN_Arena_Grow(DN_Arena *arena, DN_U64 reserve, DN_U64 commit)
|
||||
{
|
||||
if (arena->flags & (DN_ArenaFlags_NoGrow | DN_ArenaFlags_UserBuffer))
|
||||
return false;
|
||||
|
||||
DN_ArenaBlock *new_block = DN_Arena_BlockInitFlags(reserve, commit, arena->flags);
|
||||
if (new_block) {
|
||||
new_block->prev = arena->curr;
|
||||
arena->curr = new_block;
|
||||
new_block->reserve_sum = new_block->prev->reserve_sum + new_block->prev->reserve;
|
||||
DN_Arena_UpdateStatsOnNewBlock_(arena, arena->curr);
|
||||
}
|
||||
bool result = new_block;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void *DN_Arena_Alloc(DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem)
|
||||
{
|
||||
if (!arena)
|
||||
return nullptr;
|
||||
|
||||
if (!arena->curr) {
|
||||
arena->curr = Dqn_Arena_BlockInitFlags(DQN_ARENA_RESERVE_SIZE, DQN_ARENA_COMMIT_SIZE, arena->flags);
|
||||
Dqn_Arena_UpdateStatsOnNewBlock_(arena, arena->curr);
|
||||
arena->curr = DN_Arena_BlockInitFlags(DN_ARENA_RESERVE_SIZE, DN_ARENA_COMMIT_SIZE, arena->flags);
|
||||
DN_Arena_UpdateStatsOnNewBlock_(arena, arena->curr);
|
||||
}
|
||||
|
||||
if (!arena->curr)
|
||||
return nullptr;
|
||||
|
||||
try_alloc_again:
|
||||
Dqn_ArenaBlock *curr = arena->curr;
|
||||
bool poison = DQN_ASAN_POISON && ((arena->flags & Dqn_ArenaFlag_NoPoison) == 0);
|
||||
uint8_t real_align = poison ? DQN_MAX(align, DQN_ASAN_POISON_ALIGNMENT) : align;
|
||||
uint64_t offset_pos = Dqn_AlignUpPowerOfTwo(curr->used, real_align) + (poison ? DQN_ASAN_POISON_GUARD_SIZE : 0);
|
||||
uint64_t end_pos = offset_pos + size;
|
||||
DN_ArenaBlock *curr = arena->curr;
|
||||
bool poison = DN_ASAN_POISON && ((arena->flags & DN_ArenaFlags_NoPoison) == 0);
|
||||
uint8_t real_align = poison ? DN_MAX(align, DN_ASAN_POISON_ALIGNMENT) : align;
|
||||
DN_U64 offset_pos = DN_AlignUpPowerOfTwo(curr->used, real_align) + (poison ? DN_ASAN_POISON_GUARD_SIZE : 0);
|
||||
DN_U64 end_pos = offset_pos + size;
|
||||
DN_U64 alloc_size = end_pos - curr->used;
|
||||
|
||||
if (end_pos > curr->reserve) {
|
||||
if (arena->flags & Dqn_ArenaFlag_NoGrow)
|
||||
if (arena->flags & (DN_ArenaFlags_NoGrow | DN_ArenaFlags_UserBuffer))
|
||||
return nullptr;
|
||||
Dqn_usize new_reserve = DQN_MAX(DQN_ARENA_HEADER_SIZE + size, DQN_ARENA_RESERVE_SIZE);
|
||||
Dqn_usize new_commit = DQN_MAX(DQN_ARENA_HEADER_SIZE + size, DQN_ARENA_COMMIT_SIZE);
|
||||
Dqn_ArenaBlock *new_block = Dqn_Arena_BlockInitFlags(new_reserve, new_commit, arena->flags);
|
||||
if (!new_block)
|
||||
DN_USize new_reserve = DN_MAX(DN_ARENA_HEADER_SIZE + alloc_size, DN_ARENA_RESERVE_SIZE);
|
||||
DN_USize new_commit = DN_MAX(DN_ARENA_HEADER_SIZE + alloc_size, DN_ARENA_COMMIT_SIZE);
|
||||
if (!DN_Arena_Grow(arena, new_reserve, new_commit))
|
||||
return nullptr;
|
||||
new_block->prev = arena->curr;
|
||||
arena->curr = new_block;
|
||||
new_block->reserve_sum = new_block->prev->reserve_sum + new_block->prev->reserve;
|
||||
Dqn_Arena_UpdateStatsOnNewBlock_(arena, arena->curr);
|
||||
goto try_alloc_again;
|
||||
}
|
||||
|
||||
Dqn_usize prev_arena_commit = curr->commit;
|
||||
DN_USize prev_arena_commit = curr->commit;
|
||||
if (end_pos > curr->commit) {
|
||||
Dqn_usize end_commit = Dqn_AlignUpPowerOfTwo(end_pos, g_dqn_library->os_page_size);
|
||||
Dqn_usize commit_size = end_commit - curr->commit;
|
||||
char *commit_ptr = DQN_CAST(char *)curr + curr->commit;
|
||||
if (!Dqn_OS_MemCommit(commit_ptr, commit_size, Dqn_OSMemPage_ReadWrite))
|
||||
DN_ASSERT((arena->flags & DN_ArenaFlags_UserBuffer) == 0);
|
||||
DN_USize end_commit = DN_AlignUpPowerOfTwo(end_pos, g_dn_core->os_page_size);
|
||||
DN_USize commit_size = end_commit - curr->commit;
|
||||
char *commit_ptr = DN_CAST(char *) curr + curr->commit;
|
||||
if (!DN_OS_MemCommit(commit_ptr, commit_size, DN_OSMemPage_ReadWrite))
|
||||
return nullptr;
|
||||
if (poison)
|
||||
Dqn_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
|
||||
DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
|
||||
curr->commit = end_commit;
|
||||
arena->stats.info.commit += commit_size;
|
||||
arena->stats.hwm.commit = DQN_MAX(arena->stats.hwm.commit, arena->stats.info.commit);
|
||||
arena->stats.hwm.commit = DN_MAX(arena->stats.hwm.commit, arena->stats.info.commit);
|
||||
}
|
||||
|
||||
void *result = DQN_CAST(char *) curr + offset_pos;
|
||||
Dqn_usize alloc_size = end_pos - curr->used;
|
||||
void *result = DN_CAST(char *) curr + offset_pos;
|
||||
curr->used += alloc_size;
|
||||
arena->stats.info.used += alloc_size;
|
||||
arena->stats.hwm.used = DQN_MAX(arena->stats.hwm.used, arena->stats.info.used);
|
||||
Dqn_ASAN_UnpoisonMemoryRegion(result, size);
|
||||
arena->stats.hwm.used = DN_MAX(arena->stats.hwm.used, arena->stats.info.used);
|
||||
DN_ASAN_UnpoisonMemoryRegion(result, size);
|
||||
|
||||
if (zero_mem == Dqn_ZeroMem_Yes) {
|
||||
Dqn_usize reused_bytes = DQN_MIN(prev_arena_commit - offset_pos, size);
|
||||
DQN_MEMSET(result, 0, reused_bytes);
|
||||
if (zero_mem == DN_ZeroMem_Yes) {
|
||||
DN_USize reused_bytes = DN_MIN(prev_arena_commit - offset_pos, size);
|
||||
DN_MEMSET(result, 0, reused_bytes);
|
||||
}
|
||||
|
||||
DQN_ASSERT(arena->stats.hwm.used >= arena->stats.info.used);
|
||||
DQN_ASSERT(arena->stats.hwm.commit >= arena->stats.info.commit);
|
||||
DQN_ASSERT(arena->stats.hwm.reserve >= arena->stats.info.reserve);
|
||||
DQN_ASSERT(arena->stats.hwm.blocks >= arena->stats.info.blocks);
|
||||
DN_ASSERT(arena->stats.hwm.used >= arena->stats.info.used);
|
||||
DN_ASSERT(arena->stats.hwm.commit >= arena->stats.info.commit);
|
||||
DN_ASSERT(arena->stats.hwm.reserve >= arena->stats.info.reserve);
|
||||
DN_ASSERT(arena->stats.hwm.blocks >= arena->stats.info.blocks);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void *Dqn_Arena_AllocContiguous(Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem)
|
||||
DN_API void *DN_Arena_AllocContiguous(DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem)
|
||||
{
|
||||
uint8_t prev_flags = arena->flags;
|
||||
arena->flags |= (Dqn_ArenaFlag_NoGrow | Dqn_ArenaFlag_NoPoison);
|
||||
void *memory = Dqn_Arena_Alloc(arena, size, align, zero_mem);
|
||||
DN_ArenaFlags prev_flags = arena->flags;
|
||||
arena->flags |= (DN_ArenaFlags_NoGrow | DN_ArenaFlags_NoPoison);
|
||||
void *memory = DN_Arena_Alloc(arena, size, align, zero_mem);
|
||||
arena->flags = prev_flags;
|
||||
return memory;
|
||||
}
|
||||
|
||||
DQN_API void *Dqn_Arena_Copy(Dqn_Arena *arena, void const *data, uint64_t size, uint8_t align)
|
||||
DN_API void *DN_Arena_Copy(DN_Arena *arena, void const *data, DN_U64 size, uint8_t align)
|
||||
{
|
||||
if (!arena || !data || size == 0)
|
||||
return nullptr;
|
||||
void *result = Dqn_Arena_Alloc(arena, size, align, Dqn_ZeroMem_No);
|
||||
void *result = DN_Arena_Alloc(arena, size, align, DN_ZeroMem_No);
|
||||
if (result)
|
||||
DQN_MEMCPY(result, data, size);
|
||||
DN_MEMCPY(result, data, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Arena_PopTo(Dqn_Arena *arena, uint64_t init_used)
|
||||
DN_API void DN_Arena_PopTo(DN_Arena *arena, DN_U64 init_used)
|
||||
{
|
||||
if (!arena || !arena->curr)
|
||||
return;
|
||||
uint64_t used = DQN_MAX(DQN_ARENA_HEADER_SIZE, init_used);
|
||||
Dqn_ArenaBlock *curr = arena->curr;
|
||||
DN_U64 used = DN_MAX(DN_ARENA_HEADER_SIZE, init_used);
|
||||
DN_ArenaBlock *curr = arena->curr;
|
||||
while (curr->reserve_sum >= used) {
|
||||
Dqn_ArenaBlock *block_to_free = curr;
|
||||
DN_ArenaBlock *block_to_free = curr;
|
||||
arena->stats.info.used -= block_to_free->used;
|
||||
arena->stats.info.commit -= block_to_free->commit;
|
||||
arena->stats.info.reserve -= block_to_free->reserve;
|
||||
arena->stats.info.blocks -= 1;
|
||||
if (arena->flags & DN_ArenaFlags_UserBuffer)
|
||||
break;
|
||||
curr = curr->prev;
|
||||
Dqn_Arena_BlockDeinit_(arena, block_to_free);
|
||||
DN_Arena_BlockDeinit_(arena, block_to_free);
|
||||
}
|
||||
|
||||
arena->stats.info.used -= curr->used;
|
||||
arena->curr = curr;
|
||||
curr->used = used - curr->reserve_sum;
|
||||
char *poison_ptr = (char *)curr + Dqn_AlignUpPowerOfTwo(curr->used, DQN_ASAN_POISON_ALIGNMENT);
|
||||
Dqn_usize poison_size = ((char *)curr + curr->commit) - poison_ptr;
|
||||
Dqn_ASAN_PoisonMemoryRegion(poison_ptr, poison_size);
|
||||
char *poison_ptr = (char *)curr + DN_AlignUpPowerOfTwo(curr->used, DN_ASAN_POISON_ALIGNMENT);
|
||||
DN_USize poison_size = ((char *)curr + curr->commit) - poison_ptr;
|
||||
DN_ASAN_PoisonMemoryRegion(poison_ptr, poison_size);
|
||||
arena->stats.info.used += curr->used;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Arena_Pop(Dqn_Arena *arena, uint64_t amount)
|
||||
DN_API void DN_Arena_Pop(DN_Arena *arena, DN_U64 amount)
|
||||
{
|
||||
Dqn_ArenaBlock *curr = arena->curr;
|
||||
Dqn_usize used_sum = curr->reserve_sum + curr->used;
|
||||
if (!DQN_CHECK(amount <= used_sum))
|
||||
DN_ArenaBlock *curr = arena->curr;
|
||||
DN_USize used_sum = curr->reserve_sum + curr->used;
|
||||
if (!DN_CHECK(amount <= used_sum))
|
||||
amount = used_sum;
|
||||
Dqn_usize pop_to = used_sum - amount;
|
||||
Dqn_Arena_PopTo(arena, pop_to);
|
||||
DN_USize pop_to = used_sum - amount;
|
||||
DN_Arena_PopTo(arena, pop_to);
|
||||
}
|
||||
|
||||
DQN_API uint64_t Dqn_Arena_Pos(Dqn_Arena const *arena)
|
||||
DN_API DN_U64 DN_Arena_Pos(DN_Arena const *arena)
|
||||
{
|
||||
uint64_t result = (arena && arena->curr) ? arena->curr->reserve_sum + arena->curr->used : 0;
|
||||
DN_U64 result = (arena && arena->curr) ? arena->curr->reserve_sum + arena->curr->used : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Arena_Clear(Dqn_Arena *arena)
|
||||
DN_API void DN_Arena_Clear(DN_Arena *arena)
|
||||
{
|
||||
Dqn_Arena_PopTo(arena, 0);
|
||||
DN_Arena_PopTo(arena, 0);
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_Arena_OwnsPtr(Dqn_Arena const *arena, void *ptr)
|
||||
DN_API bool DN_Arena_OwnsPtr(DN_Arena const *arena, void *ptr)
|
||||
{
|
||||
bool result = false;
|
||||
uintptr_t uint_ptr = DQN_CAST(uintptr_t)ptr;
|
||||
for (Dqn_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; block = block->prev) {
|
||||
uintptr_t begin = DQN_CAST(uintptr_t) block + DQN_ARENA_HEADER_SIZE;
|
||||
uintptr_t uint_ptr = DN_CAST(uintptr_t)ptr;
|
||||
for (DN_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; block = block->prev) {
|
||||
uintptr_t begin = DN_CAST(uintptr_t) block + DN_ARENA_HEADER_SIZE;
|
||||
uintptr_t end = begin + block->reserve;
|
||||
result = uint_ptr >= begin && uint_ptr <= end;
|
||||
}
|
||||
@ -281,120 +319,118 @@ DQN_API bool Dqn_Arena_OwnsPtr(Dqn_Arena const *arena, void *ptr)
|
||||
}
|
||||
|
||||
|
||||
DQN_API Dqn_ArenaStats Dqn_Arena_SumStatsArray(Dqn_ArenaStats const *array, Dqn_usize size)
|
||||
DN_API DN_ArenaStats DN_Arena_SumStatsArray(DN_ArenaStats const *array, DN_USize size)
|
||||
{
|
||||
Dqn_ArenaStats result = {};
|
||||
DQN_FOR_UINDEX(index, size) {
|
||||
Dqn_ArenaStats stats = array[index];
|
||||
DN_ArenaStats result = {};
|
||||
DN_FOR_UINDEX(index, size) {
|
||||
DN_ArenaStats stats = array[index];
|
||||
result.info.used += stats.info.used;
|
||||
result.info.commit += stats.info.commit;
|
||||
result.info.reserve += stats.info.reserve;
|
||||
result.info.blocks += stats.info.blocks;
|
||||
|
||||
result.hwm.used = DQN_MAX(result.hwm.used, result.info.used);
|
||||
result.hwm.commit = DQN_MAX(result.hwm.commit, result.info.commit);
|
||||
result.hwm.reserve = DQN_MAX(result.hwm.reserve, result.info.reserve);
|
||||
result.hwm.blocks = DQN_MAX(result.hwm.blocks, result.info.blocks);
|
||||
result.hwm.used = DN_MAX(result.hwm.used, result.info.used);
|
||||
result.hwm.commit = DN_MAX(result.hwm.commit, result.info.commit);
|
||||
result.hwm.reserve = DN_MAX(result.hwm.reserve, result.info.reserve);
|
||||
result.hwm.blocks = DN_MAX(result.hwm.blocks, result.info.blocks);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_ArenaStats Dqn_Arena_SumStats(Dqn_ArenaStats lhs, Dqn_ArenaStats rhs)
|
||||
DN_API DN_ArenaStats DN_Arena_SumStats(DN_ArenaStats lhs, DN_ArenaStats rhs)
|
||||
{
|
||||
Dqn_ArenaStats array[] = {lhs, rhs};
|
||||
Dqn_ArenaStats result = Dqn_Arena_SumStatsArray(array, DQN_ARRAY_UCOUNT(array));
|
||||
DN_ArenaStats array[] = {lhs, rhs};
|
||||
DN_ArenaStats result = DN_Arena_SumStatsArray(array, DN_ARRAY_UCOUNT(array));
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_ArenaStats Dqn_Arena_SumArenaArrayToStats(Dqn_Arena const *array, Dqn_usize size)
|
||||
DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats(DN_Arena const *array, DN_USize size)
|
||||
{
|
||||
Dqn_ArenaStats result = {};
|
||||
for (Dqn_usize index = 0; index < size; index++) {
|
||||
Dqn_Arena const *arena = array + index;
|
||||
result = Dqn_Arena_SumStats(result, arena->stats);
|
||||
DN_ArenaStats result = {};
|
||||
for (DN_USize index = 0; index < size; index++) {
|
||||
DN_Arena const *arena = array + index;
|
||||
result = DN_Arena_SumStats(result, arena->stats);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin(Dqn_Arena *arena)
|
||||
DN_API DN_ArenaTempMem DN_Arena_TempMemBegin(DN_Arena *arena)
|
||||
{
|
||||
Dqn_ArenaTempMem result = {};
|
||||
DN_ArenaTempMem result = {};
|
||||
if (arena) {
|
||||
Dqn_ArenaBlock *curr = arena->curr;
|
||||
DN_ArenaBlock *curr = arena->curr;
|
||||
result = {arena, curr ? curr->reserve_sum + curr->used : 0};
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
DQN_API void Dqn_Arena_TempMemEnd(Dqn_ArenaTempMem mem)
|
||||
DN_API void DN_Arena_TempMemEnd(DN_ArenaTempMem mem)
|
||||
{
|
||||
Dqn_Arena_PopTo(mem.arena, mem.used_sum);
|
||||
DN_Arena_PopTo(mem.arena, mem.used_sum);
|
||||
};
|
||||
|
||||
Dqn_ArenaTempMemScope::Dqn_ArenaTempMemScope(Dqn_Arena *arena)
|
||||
DN_ArenaTempMemScope::DN_ArenaTempMemScope(DN_Arena *arena)
|
||||
{
|
||||
mem = Dqn_Arena_TempMemBegin(arena);
|
||||
mem = DN_Arena_TempMemBegin(arena);
|
||||
}
|
||||
|
||||
Dqn_ArenaTempMemScope::~Dqn_ArenaTempMemScope()
|
||||
DN_ArenaTempMemScope::~DN_ArenaTempMemScope()
|
||||
{
|
||||
Dqn_Arena_TempMemEnd(mem);
|
||||
DN_Arena_TempMemEnd(mem);
|
||||
}
|
||||
|
||||
// NOTE: [$CHUN] Dqn_ChunkPool /////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_ChunkPool Dqn_ChunkPool_Init(Dqn_Arena *arena, uint8_t align)
|
||||
// NOTE: [$POOL] DN_Pool //////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Pool DN_Pool_Init(DN_Arena *arena, uint8_t align)
|
||||
{
|
||||
Dqn_ChunkPool result = {};
|
||||
DN_Pool result = {};
|
||||
if (arena) {
|
||||
result.arena = arena;
|
||||
result.align = align;
|
||||
if (result.align == 0)
|
||||
result.align = DQN_CHUNK_POOL_DEFAULT_ALIGN;
|
||||
result.align = align ? align : DN_POOL_DEFAULT_ALIGN;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_ChunkPool_IsValid(Dqn_ChunkPool const *pool)
|
||||
DN_API bool DN_Pool_IsValid(DN_Pool const *pool)
|
||||
{
|
||||
bool result = pool && pool->arena && pool->align;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void *Dqn_ChunkPool_Alloc(Dqn_ChunkPool *pool, Dqn_usize size)
|
||||
DN_API void *DN_Pool_Alloc(DN_Pool *pool, DN_USize size)
|
||||
{
|
||||
void *result = nullptr;
|
||||
if (!Dqn_ChunkPool_IsValid(pool))
|
||||
if (!DN_Pool_IsValid(pool))
|
||||
return result;
|
||||
|
||||
Dqn_usize const required_size = sizeof(Dqn_ChunkPoolSlot) + pool->align + size;
|
||||
Dqn_usize const size_to_slot_offset = 5; // __lzcnt64(32) e.g. Dqn_ChunkPoolSlotSize_32B
|
||||
Dqn_usize slot_index = 0;
|
||||
DN_USize const required_size = sizeof(DN_PoolSlot) + pool->align + size;
|
||||
DN_USize const size_to_slot_offset = 5; // __lzcnt64(32) e.g. DN_PoolSlotSize_32B
|
||||
DN_USize slot_index = 0;
|
||||
if (required_size > 32) {
|
||||
// NOTE: Round up if not PoT as the low bits are set.
|
||||
Dqn_usize dist_to_next_msb = Dqn_CountLeadingZerosU64(required_size) + 1;
|
||||
dist_to_next_msb -= DQN_CAST(Dqn_usize)(!Dqn_IsPowerOfTwo(required_size));
|
||||
DN_USize dist_to_next_msb = DN_CountLeadingZerosU64(required_size) + 1;
|
||||
dist_to_next_msb -= DN_CAST(DN_USize)(!DN_IsPowerOfTwo(required_size));
|
||||
|
||||
Dqn_usize const register_size = sizeof(Dqn_usize) * 8;
|
||||
DQN_ASSERT(register_size >= dist_to_next_msb + size_to_slot_offset);
|
||||
DN_USize const register_size = sizeof(DN_USize) * 8;
|
||||
DN_ASSERT(register_size >= dist_to_next_msb + size_to_slot_offset);
|
||||
slot_index = register_size - dist_to_next_msb - size_to_slot_offset;
|
||||
}
|
||||
|
||||
if (!DQN_CHECKF(slot_index < Dqn_ChunkPoolSlotSize_Count, "Chunk pool does not support the requested allocation size"))
|
||||
if (!DN_CHECKF(slot_index < DN_PoolSlotSize_Count, "Chunk pool does not support the requested allocation size"))
|
||||
return result;
|
||||
|
||||
Dqn_usize slot_size_in_bytes = 1ULL << (slot_index + size_to_slot_offset);
|
||||
DQN_ASSERT(required_size <= (slot_size_in_bytes << 0));
|
||||
DQN_ASSERT(required_size >= (slot_size_in_bytes >> 1));
|
||||
DN_USize slot_size_in_bytes = 1ULL << (slot_index + size_to_slot_offset);
|
||||
DN_ASSERT(required_size <= (slot_size_in_bytes << 0));
|
||||
DN_ASSERT(required_size >= (slot_size_in_bytes >> 1));
|
||||
|
||||
Dqn_ChunkPoolSlot *slot = nullptr;
|
||||
DN_PoolSlot *slot = nullptr;
|
||||
if (pool->slots[slot_index]) {
|
||||
slot = pool->slots[slot_index];
|
||||
pool->slots[slot_index] = slot->next;
|
||||
DQN_MEMSET(slot->data, 0, size);
|
||||
DQN_ASSERT(Dqn_IsPowerOfTwoAligned(slot->data, pool->align));
|
||||
DN_MEMSET(slot->data, 0, size);
|
||||
DN_ASSERT(DN_IsPowerOfTwoAligned(slot->data, pool->align));
|
||||
} else {
|
||||
void *bytes = Dqn_Arena_Alloc(pool->arena, slot_size_in_bytes, alignof(Dqn_ChunkPoolSlot), Dqn_ZeroMem_Yes);
|
||||
slot = DQN_CAST(Dqn_ChunkPoolSlot *) bytes;
|
||||
void *bytes = DN_Arena_Alloc(pool->arena, slot_size_in_bytes, alignof(DN_PoolSlot), DN_ZeroMem_Yes);
|
||||
slot = DN_CAST(DN_PoolSlot *) bytes;
|
||||
|
||||
// NOTE: The raw pointer is round up to the next 'pool->align'-ed
|
||||
// address ensuring at least 1 byte of padding between the raw pointer
|
||||
@ -403,215 +439,215 @@ DQN_API void *Dqn_ChunkPool_Alloc(Dqn_ChunkPool *pool, Dqn_usize size)
|
||||
//
|
||||
// This allows us to smuggle 1 byte behind the user pointer that has
|
||||
// the offset to the original pointer.
|
||||
slot->data = DQN_CAST(void *)Dqn_AlignDownPowerOfTwo(DQN_CAST(uintptr_t)slot + sizeof(Dqn_ChunkPoolSlot) + pool->align, pool->align);
|
||||
slot->data = DN_CAST(void *)DN_AlignDownPowerOfTwo(DN_CAST(uintptr_t)slot + sizeof(DN_PoolSlot) + pool->align, pool->align);
|
||||
|
||||
uintptr_t offset_to_original_ptr = DQN_CAST(uintptr_t)slot->data - DQN_CAST(uintptr_t)bytes;
|
||||
DQN_ASSERT(slot->data > bytes);
|
||||
DQN_ASSERT(offset_to_original_ptr <= sizeof(Dqn_ChunkPoolSlot) + pool->align);
|
||||
uintptr_t offset_to_original_ptr = DN_CAST(uintptr_t)slot->data - DN_CAST(uintptr_t)bytes;
|
||||
DN_ASSERT(slot->data > bytes);
|
||||
DN_ASSERT(offset_to_original_ptr <= sizeof(DN_PoolSlot) + pool->align);
|
||||
|
||||
// NOTE: Store the offset to the original pointer behind the user's
|
||||
// pointer.
|
||||
char *offset_to_original_storage = DQN_CAST(char *)slot->data - 1;
|
||||
DQN_MEMCPY(offset_to_original_storage, &offset_to_original_ptr, 1);
|
||||
char *offset_to_original_storage = DN_CAST(char *)slot->data - 1;
|
||||
DN_MEMCPY(offset_to_original_storage, &offset_to_original_ptr, 1);
|
||||
}
|
||||
|
||||
// NOTE: Smuggle the slot type in the next pointer so that we know, when the
|
||||
// pointer gets returned which free list to return the pointer to.
|
||||
result = slot->data;
|
||||
slot->next = DQN_CAST(Dqn_ChunkPoolSlot *)slot_index;
|
||||
slot->next = DN_CAST(DN_PoolSlot *)slot_index;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8FV(Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8FV(DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
Dqn_Str8 result = {};
|
||||
if (!Dqn_ChunkPool_IsValid(pool))
|
||||
DN_Str8 result = {};
|
||||
if (!DN_Pool_IsValid(pool))
|
||||
return result;
|
||||
|
||||
Dqn_usize size_required = Dqn_CStr8_FVSize(fmt, args);
|
||||
result.data = DQN_CAST(char *) Dqn_ChunkPool_Alloc(pool, size_required + 1);
|
||||
DN_USize size_required = DN_CStr8_FVSize(fmt, args);
|
||||
result.data = DN_CAST(char *) DN_Pool_Alloc(pool, size_required + 1);
|
||||
if (result.data) {
|
||||
result.size = size_required;
|
||||
DQN_VSNPRINTF(result.data, DQN_CAST(int)(result.size + 1), fmt, args);
|
||||
DN_VSNPRINTF(result.data, DN_CAST(int)(result.size + 1), fmt, args);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8F(Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8F(DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_Str8 result = Dqn_ChunkPool_AllocStr8FV(pool, fmt, args);
|
||||
DN_Str8 result = DN_Pool_AllocStr8FV(pool, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8Copy(Dqn_ChunkPool *pool, Dqn_Str8 string)
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8Copy(DN_Pool *pool, DN_Str8 string)
|
||||
{
|
||||
Dqn_Str8 result = {};
|
||||
if (!Dqn_ChunkPool_IsValid(pool))
|
||||
DN_Str8 result = {};
|
||||
if (!DN_Pool_IsValid(pool))
|
||||
return result;
|
||||
|
||||
if (!Dqn_Str8_HasData(string))
|
||||
if (!DN_Str8_HasData(string))
|
||||
return result;
|
||||
|
||||
char *data = DQN_CAST(char *)Dqn_ChunkPool_Alloc(pool, string.size + 1);
|
||||
char *data = DN_CAST(char *)DN_Pool_Alloc(pool, string.size + 1);
|
||||
if (!data)
|
||||
return result;
|
||||
|
||||
DQN_MEMCPY(data, string.data, string.size);
|
||||
DN_MEMCPY(data, string.data, string.size);
|
||||
data[string.size] = 0;
|
||||
result = Dqn_Str8_Init(data, string.size);
|
||||
result = DN_Str8_Init(data, string.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_ChunkPool_Dealloc(Dqn_ChunkPool *pool, void *ptr)
|
||||
DN_API void DN_Pool_Dealloc(DN_Pool *pool, void *ptr)
|
||||
{
|
||||
if (!Dqn_ChunkPool_IsValid(pool) || !ptr)
|
||||
if (!DN_Pool_IsValid(pool) || !ptr)
|
||||
return;
|
||||
|
||||
DQN_ASSERT(Dqn_Arena_OwnsPtr(pool->arena, ptr));
|
||||
DN_ASSERT(DN_Arena_OwnsPtr(pool->arena, ptr));
|
||||
|
||||
char const *one_byte_behind_ptr = DQN_CAST(char *) ptr - 1;
|
||||
Dqn_usize offset_to_original_ptr = 0;
|
||||
DQN_MEMCPY(&offset_to_original_ptr, one_byte_behind_ptr, 1);
|
||||
DQN_ASSERT(offset_to_original_ptr <= sizeof(Dqn_ChunkPoolSlot) + pool->align);
|
||||
char const *one_byte_behind_ptr = DN_CAST(char *) ptr - 1;
|
||||
DN_USize offset_to_original_ptr = 0;
|
||||
DN_MEMCPY(&offset_to_original_ptr, one_byte_behind_ptr, 1);
|
||||
DN_ASSERT(offset_to_original_ptr <= sizeof(DN_PoolSlot) + pool->align);
|
||||
|
||||
char *original_ptr = DQN_CAST(char *)ptr - offset_to_original_ptr;
|
||||
Dqn_ChunkPoolSlot *slot = DQN_CAST(Dqn_ChunkPoolSlot *)original_ptr;
|
||||
Dqn_ChunkPoolSlotSize slot_index = DQN_CAST(Dqn_ChunkPoolSlotSize)(DQN_CAST(uintptr_t)slot->next);
|
||||
DQN_ASSERT(slot_index < Dqn_ChunkPoolSlotSize_Count);
|
||||
char *original_ptr = DN_CAST(char *) ptr - offset_to_original_ptr;
|
||||
DN_PoolSlot *slot = DN_CAST(DN_PoolSlot *) original_ptr;
|
||||
DN_PoolSlotSize slot_index = DN_CAST(DN_PoolSlotSize)(DN_CAST(uintptr_t) slot->next);
|
||||
DN_ASSERT(slot_index < DN_PoolSlotSize_Count);
|
||||
|
||||
slot->next = pool->slots[slot_index];
|
||||
pool->slots[slot_index] = slot;
|
||||
}
|
||||
|
||||
DQN_API void *Dqn_ChunkPool_Copy(Dqn_ChunkPool *pool, void const *data, uint64_t size, uint8_t align)
|
||||
DN_API void *DN_Pool_Copy(DN_Pool *pool, void const *data, DN_U64 size, uint8_t align)
|
||||
{
|
||||
if (!pool || !data || size == 0)
|
||||
return nullptr;
|
||||
|
||||
// TODO: Hmm should align be part of the alloc interface in general? I'm not going to worry
|
||||
// about this until we crash because of misalignment.
|
||||
DQN_ASSERT(pool->align >= align);
|
||||
DN_ASSERT(pool->align >= align);
|
||||
|
||||
void *result = Dqn_ChunkPool_Alloc(pool, size);
|
||||
void *result = DN_Pool_Alloc(pool, size);
|
||||
if (result)
|
||||
DQN_MEMCPY(result, data, size);
|
||||
DN_MEMCPY(result, data, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: [$ACAT] Dqn_ArenaCatalog //////////////////////////////////////////////////////////////////
|
||||
DQN_API void Dqn_ArenaCatalog_Init(Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool)
|
||||
// NOTE: [$ACAT] DN_ArenaCatalog //////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_ArenaCatalog_Init(DN_ArenaCatalog *catalog, DN_Pool *pool)
|
||||
{
|
||||
catalog->pool = pool;
|
||||
catalog->sentinel.next = &catalog->sentinel;
|
||||
catalog->sentinel.prev = &catalog->sentinel;
|
||||
}
|
||||
|
||||
DQN_API Dqn_ArenaCatalogItem *Dqn_ArenaCatalog_Find(Dqn_ArenaCatalog *catalog, Dqn_Str8 label)
|
||||
DN_API DN_ArenaCatalogItem *DN_ArenaCatalog_Find(DN_ArenaCatalog *catalog, DN_Str8 label)
|
||||
{
|
||||
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
Dqn_ArenaCatalogItem *result = &catalog->sentinel;
|
||||
for (Dqn_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) {
|
||||
DN_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
DN_ArenaCatalogItem *result = &catalog->sentinel;
|
||||
for (DN_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) {
|
||||
if (item->label == label) {
|
||||
result = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Dqn_TicketMutex_End(&catalog->ticket_mutex);
|
||||
DN_TicketMutex_End(&catalog->ticket_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void Dqn_ArenaCatalog_AddInternal_(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_Str8 label, bool arena_pool_allocated)
|
||||
static void DN_ArenaCatalog_AddInternal_(DN_ArenaCatalog *catalog, DN_Arena *arena, DN_Str8 label, bool arena_pool_allocated)
|
||||
{
|
||||
// NOTE: We could use an atomic for appending to the sentinel but it is such
|
||||
// a rare operation to append to the catalog that we don't bother.
|
||||
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
DN_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
|
||||
// NOTE: Create item in the catalog
|
||||
Dqn_ArenaCatalogItem *result = Dqn_ChunkPool_New(catalog->pool, Dqn_ArenaCatalogItem);
|
||||
DN_ArenaCatalogItem *result = DN_Pool_New(catalog->pool, DN_ArenaCatalogItem);
|
||||
if (result) {
|
||||
result->arena = arena;
|
||||
result->label = label;
|
||||
result->arena_pool_allocated = arena_pool_allocated;
|
||||
|
||||
// NOTE: Add to the catalog (linked list)
|
||||
Dqn_ArenaCatalogItem *sentinel = &catalog->sentinel;
|
||||
DN_ArenaCatalogItem *sentinel = &catalog->sentinel;
|
||||
result->next = sentinel;
|
||||
result->prev = sentinel->prev;
|
||||
result->next->prev = result;
|
||||
result->prev->next = result;
|
||||
Dqn_Atomic_AddU32(&catalog->arena_count, 1);
|
||||
DN_Atomic_AddU32(&catalog->arena_count, 1);
|
||||
}
|
||||
Dqn_TicketMutex_End(&catalog->ticket_mutex);
|
||||
DN_TicketMutex_End(&catalog->ticket_mutex);
|
||||
}
|
||||
|
||||
DQN_API void Dqn_ArenaCatalog_AddF(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API void DN_ArenaCatalog_AddF(DN_ArenaCatalog *catalog, DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args);
|
||||
Dqn_TicketMutex_End(&catalog->ticket_mutex);
|
||||
DN_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args);
|
||||
DN_TicketMutex_End(&catalog->ticket_mutex);
|
||||
va_end(args);
|
||||
Dqn_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/);
|
||||
DN_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/);
|
||||
}
|
||||
|
||||
DQN_API void Dqn_ArenaCatalog_AddFV(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
DN_API void DN_ArenaCatalog_AddFV(DN_ArenaCatalog *catalog, DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args);
|
||||
Dqn_TicketMutex_End(&catalog->ticket_mutex);
|
||||
Dqn_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/);
|
||||
DN_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args);
|
||||
DN_TicketMutex_End(&catalog->ticket_mutex);
|
||||
DN_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/);
|
||||
}
|
||||
|
||||
DQN_API Dqn_Arena *Dqn_ArenaCatalog_AllocFV(Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
DN_API DN_Arena *DN_ArenaCatalog_AllocFV(DN_ArenaCatalog *catalog, DN_USize reserve, DN_USize commit, uint8_t arena_flags, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args);
|
||||
Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena);
|
||||
Dqn_TicketMutex_End(&catalog->ticket_mutex);
|
||||
DN_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args);
|
||||
DN_Arena *result = DN_Pool_New(catalog->pool, DN_Arena);
|
||||
DN_TicketMutex_End(&catalog->ticket_mutex);
|
||||
|
||||
*result = Dqn_Arena_InitSize(reserve, commit, arena_flags);
|
||||
Dqn_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/);
|
||||
*result = DN_Arena_InitSize(reserve, commit, arena_flags);
|
||||
DN_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Arena *Dqn_ArenaCatalog_AllocF(Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API DN_Arena *DN_ArenaCatalog_AllocF(DN_ArenaCatalog *catalog, DN_USize reserve, DN_USize commit, uint8_t arena_flags, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args);
|
||||
Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena);
|
||||
Dqn_TicketMutex_End(&catalog->ticket_mutex);
|
||||
DN_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
DN_Str8 label = DN_Pool_AllocStr8FV(catalog->pool, fmt, args);
|
||||
DN_Arena *result = DN_Pool_New(catalog->pool, DN_Arena);
|
||||
DN_TicketMutex_End(&catalog->ticket_mutex);
|
||||
va_end(args);
|
||||
|
||||
*result = Dqn_Arena_InitSize(reserve, commit, arena_flags);
|
||||
Dqn_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/);
|
||||
*result = DN_Arena_InitSize(reserve, commit, arena_flags);
|
||||
DN_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_ArenaCatalog_Erase(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena)
|
||||
DN_API bool DN_ArenaCatalog_Erase(DN_ArenaCatalog *catalog, DN_Arena *arena, DN_ArenaCatalogFreeArena free_arena)
|
||||
{
|
||||
bool result = false;
|
||||
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
for (Dqn_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) {
|
||||
DN_TicketMutex_Begin(&catalog->ticket_mutex);
|
||||
for (DN_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) {
|
||||
if (item->arena == arena) {
|
||||
item->next->prev = item->prev;
|
||||
item->prev->next = item->next;
|
||||
if (item->arena_pool_allocated) {
|
||||
if (free_arena == Dqn_ArenaCatalogFreeArena_Yes)
|
||||
Dqn_Arena_Deinit(item->arena);
|
||||
Dqn_ChunkPool_Dealloc(catalog->pool, item->arena);
|
||||
if (free_arena == DN_ArenaCatalogFreeArena_Yes)
|
||||
DN_Arena_Deinit(item->arena);
|
||||
DN_Pool_Dealloc(catalog->pool, item->arena);
|
||||
}
|
||||
Dqn_ChunkPool_Dealloc(catalog->pool, item->label.data);
|
||||
Dqn_ChunkPool_Dealloc(catalog->pool, item);
|
||||
DN_Pool_Dealloc(catalog->pool, item->label.data);
|
||||
DN_Pool_Dealloc(catalog->pool, item);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Dqn_TicketMutex_End(&catalog->ticket_mutex);
|
||||
DN_TicketMutex_End(&catalog->ticket_mutex);
|
||||
return result;
|
||||
}
|
||||
|
283
dqn_allocator.h
283
dqn_allocator.h
@ -17,197 +17,204 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [$AREN] Dqn_Arena -- Growing bump allocator
|
||||
// [$CHUN] Dqn_ChunkPool -- Allocates reusable, free-able memory in PoT chunks
|
||||
// [$ACAT] Dqn_ArenaCatalog -- Collate, create & manage arenas in a catalog
|
||||
// [$AREN] DN_Arena -- Growing bump allocator
|
||||
// [$CHUN] DN_Pool -- Allocates reusable, free-able memory in PoT chunks
|
||||
// [$POOL] DN_Pool -- TODO
|
||||
// [$ACAT] DN_ArenaCatalog -- Collate, create & manage arenas in a catalog
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$AREN] Dqn_Arena /////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_ARENA_RESERVE_SIZE)
|
||||
#define DQN_ARENA_RESERVE_SIZE DQN_MEGABYTES(64)
|
||||
// NOTE: [$AREN] DN_Arena /////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_ARENA_RESERVE_SIZE)
|
||||
#define DN_ARENA_RESERVE_SIZE DN_MEGABYTES(64)
|
||||
#endif
|
||||
#if !defined(DQN_ARENA_COMMIT_SIZE)
|
||||
#define DQN_ARENA_COMMIT_SIZE DQN_KILOBYTES(64)
|
||||
#if !defined(DN_ARENA_COMMIT_SIZE)
|
||||
#define DN_ARENA_COMMIT_SIZE DN_KILOBYTES(64)
|
||||
#endif
|
||||
|
||||
struct Dqn_ArenaBlock
|
||||
struct DN_ArenaBlock
|
||||
{
|
||||
Dqn_ArenaBlock *prev;
|
||||
uint64_t used;
|
||||
uint64_t commit;
|
||||
uint64_t reserve;
|
||||
uint64_t reserve_sum;
|
||||
DN_ArenaBlock *prev;
|
||||
DN_U64 used;
|
||||
DN_U64 commit;
|
||||
DN_U64 reserve;
|
||||
DN_U64 reserve_sum;
|
||||
};
|
||||
|
||||
enum Dqn_ArenaFlag
|
||||
typedef uint32_t DN_ArenaFlags;
|
||||
enum DN_ArenaFlags_
|
||||
{
|
||||
Dqn_ArenaFlag_Nil = 0,
|
||||
Dqn_ArenaFlag_NoGrow = 1 << 0,
|
||||
Dqn_ArenaFlag_NoPoison = 1 << 1,
|
||||
Dqn_ArenaFlag_NoAllocTrack = 1 << 2,
|
||||
Dqn_ArenaFlag_AllocCanLeak = 1 << 3,
|
||||
DN_ArenaFlags_Nil = 0,
|
||||
DN_ArenaFlags_NoGrow = 1 << 0,
|
||||
DN_ArenaFlags_NoPoison = 1 << 1,
|
||||
DN_ArenaFlags_NoAllocTrack = 1 << 2,
|
||||
DN_ArenaFlags_AllocCanLeak = 1 << 3,
|
||||
DN_ArenaFlags_UserBuffer = 1 << 4,
|
||||
};
|
||||
|
||||
struct Dqn_ArenaInfo
|
||||
struct DN_ArenaInfo
|
||||
{
|
||||
uint64_t used;
|
||||
uint64_t commit;
|
||||
uint64_t reserve;
|
||||
uint64_t blocks;
|
||||
DN_U64 used;
|
||||
DN_U64 commit;
|
||||
DN_U64 reserve;
|
||||
DN_U64 blocks;
|
||||
};
|
||||
|
||||
struct Dqn_ArenaStats
|
||||
struct DN_ArenaStats
|
||||
{
|
||||
Dqn_ArenaInfo info;
|
||||
Dqn_ArenaInfo hwm;
|
||||
DN_ArenaInfo info;
|
||||
DN_ArenaInfo hwm;
|
||||
};
|
||||
|
||||
struct Dqn_Arena
|
||||
struct DN_Arena
|
||||
{
|
||||
Dqn_ArenaBlock *curr;
|
||||
Dqn_ArenaStats stats;
|
||||
Dqn_TicketMutex mutex; // For user code to lock the arena, the arena itself does not use.
|
||||
uint8_t flags;
|
||||
DN_ArenaBlock *curr;
|
||||
DN_ArenaStats stats;
|
||||
DN_ArenaFlags flags;
|
||||
DN_Str8 label;
|
||||
DN_Arena *prev, *next;
|
||||
};
|
||||
|
||||
struct Dqn_ArenaTempMem
|
||||
struct DN_ArenaTempMem
|
||||
{
|
||||
Dqn_Arena *arena;
|
||||
uint64_t used_sum;
|
||||
DN_Arena *arena;
|
||||
DN_U64 used_sum;
|
||||
};
|
||||
|
||||
struct Dqn_ArenaTempMemScope
|
||||
struct DN_ArenaTempMemScope
|
||||
{
|
||||
Dqn_ArenaTempMemScope(Dqn_Arena *arena);
|
||||
~Dqn_ArenaTempMemScope();
|
||||
Dqn_ArenaTempMem mem;
|
||||
DN_ArenaTempMemScope(DN_Arena *arena);
|
||||
~DN_ArenaTempMemScope();
|
||||
DN_ArenaTempMem mem;
|
||||
};
|
||||
|
||||
Dqn_usize const DQN_ARENA_HEADER_SIZE = Dqn_AlignUpPowerOfTwo(sizeof(Dqn_Arena), 64);
|
||||
DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64);
|
||||
|
||||
// NOTE: [$CHUN] Dqn_ChunkPool /////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_CHUNK_POOL_DEFAULT_ALIGN)
|
||||
#define DQN_CHUNK_POOL_DEFAULT_ALIGN 16
|
||||
// NOTE: [$CHUN] DN_Pool /////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_POOL_DEFAULT_ALIGN)
|
||||
#define DN_POOL_DEFAULT_ALIGN 16
|
||||
#endif
|
||||
|
||||
struct Dqn_ChunkPoolSlot
|
||||
struct DN_PoolSlot
|
||||
{
|
||||
void *data;
|
||||
Dqn_ChunkPoolSlot *next;
|
||||
DN_PoolSlot *next;
|
||||
};
|
||||
|
||||
enum Dqn_ChunkPoolSlotSize
|
||||
enum DN_PoolSlotSize
|
||||
{
|
||||
Dqn_ChunkPoolSlotSize_32B,
|
||||
Dqn_ChunkPoolSlotSize_64B,
|
||||
Dqn_ChunkPoolSlotSize_128B,
|
||||
Dqn_ChunkPoolSlotSize_256B,
|
||||
Dqn_ChunkPoolSlotSize_512B,
|
||||
Dqn_ChunkPoolSlotSize_1KiB,
|
||||
Dqn_ChunkPoolSlotSize_2KiB,
|
||||
Dqn_ChunkPoolSlotSize_4KiB,
|
||||
Dqn_ChunkPoolSlotSize_8KiB,
|
||||
Dqn_ChunkPoolSlotSize_16KiB,
|
||||
Dqn_ChunkPoolSlotSize_32KiB,
|
||||
Dqn_ChunkPoolSlotSize_64KiB,
|
||||
Dqn_ChunkPoolSlotSize_128KiB,
|
||||
Dqn_ChunkPoolSlotSize_256KiB,
|
||||
Dqn_ChunkPoolSlotSize_512KiB,
|
||||
Dqn_ChunkPoolSlotSize_1MiB,
|
||||
Dqn_ChunkPoolSlotSize_2MiB,
|
||||
Dqn_ChunkPoolSlotSize_4MiB,
|
||||
Dqn_ChunkPoolSlotSize_8MiB,
|
||||
Dqn_ChunkPoolSlotSize_16MiB,
|
||||
Dqn_ChunkPoolSlotSize_32MiB,
|
||||
Dqn_ChunkPoolSlotSize_64MiB,
|
||||
Dqn_ChunkPoolSlotSize_128MiB,
|
||||
Dqn_ChunkPoolSlotSize_256MiB,
|
||||
Dqn_ChunkPoolSlotSize_512MiB,
|
||||
Dqn_ChunkPoolSlotSize_1GiB,
|
||||
Dqn_ChunkPoolSlotSize_2GiB,
|
||||
Dqn_ChunkPoolSlotSize_4GiB,
|
||||
Dqn_ChunkPoolSlotSize_8GiB,
|
||||
Dqn_ChunkPoolSlotSize_16GiB,
|
||||
Dqn_ChunkPoolSlotSize_32GiB,
|
||||
Dqn_ChunkPoolSlotSize_Count,
|
||||
DN_PoolSlotSize_32B,
|
||||
DN_PoolSlotSize_64B,
|
||||
DN_PoolSlotSize_128B,
|
||||
DN_PoolSlotSize_256B,
|
||||
DN_PoolSlotSize_512B,
|
||||
DN_PoolSlotSize_1KiB,
|
||||
DN_PoolSlotSize_2KiB,
|
||||
DN_PoolSlotSize_4KiB,
|
||||
DN_PoolSlotSize_8KiB,
|
||||
DN_PoolSlotSize_16KiB,
|
||||
DN_PoolSlotSize_32KiB,
|
||||
DN_PoolSlotSize_64KiB,
|
||||
DN_PoolSlotSize_128KiB,
|
||||
DN_PoolSlotSize_256KiB,
|
||||
DN_PoolSlotSize_512KiB,
|
||||
DN_PoolSlotSize_1MiB,
|
||||
DN_PoolSlotSize_2MiB,
|
||||
DN_PoolSlotSize_4MiB,
|
||||
DN_PoolSlotSize_8MiB,
|
||||
DN_PoolSlotSize_16MiB,
|
||||
DN_PoolSlotSize_32MiB,
|
||||
DN_PoolSlotSize_64MiB,
|
||||
DN_PoolSlotSize_128MiB,
|
||||
DN_PoolSlotSize_256MiB,
|
||||
DN_PoolSlotSize_512MiB,
|
||||
DN_PoolSlotSize_1GiB,
|
||||
DN_PoolSlotSize_2GiB,
|
||||
DN_PoolSlotSize_4GiB,
|
||||
DN_PoolSlotSize_8GiB,
|
||||
DN_PoolSlotSize_16GiB,
|
||||
DN_PoolSlotSize_32GiB,
|
||||
DN_PoolSlotSize_Count,
|
||||
};
|
||||
|
||||
struct Dqn_ChunkPool
|
||||
struct DN_Pool
|
||||
{
|
||||
Dqn_Arena *arena;
|
||||
Dqn_ChunkPoolSlot *slots[Dqn_ChunkPoolSlotSize_Count];
|
||||
DN_Arena *arena;
|
||||
DN_PoolSlot *slots[DN_PoolSlotSize_Count];
|
||||
uint8_t align;
|
||||
};
|
||||
|
||||
// NOTE: [$ACAT] Dqn_ArenaCatalog //////////////////////////////////////////////////////////////////
|
||||
struct Dqn_ArenaCatalogItem
|
||||
// NOTE: [$ACAT] DN_ArenaCatalog //////////////////////////////////////////////////////////////////
|
||||
struct DN_ArenaCatalogItem
|
||||
{
|
||||
Dqn_Arena *arena;
|
||||
Dqn_Str8 label;
|
||||
DN_Arena *arena;
|
||||
DN_Str8 label;
|
||||
bool arena_pool_allocated;
|
||||
Dqn_ArenaCatalogItem *next;
|
||||
Dqn_ArenaCatalogItem *prev;
|
||||
DN_ArenaCatalogItem *next;
|
||||
DN_ArenaCatalogItem *prev;
|
||||
};
|
||||
|
||||
struct Dqn_ArenaCatalog
|
||||
struct DN_ArenaCatalog
|
||||
{
|
||||
Dqn_TicketMutex ticket_mutex; // Mutex for adding to the linked list of arenas
|
||||
struct Dqn_ChunkPool *pool;
|
||||
Dqn_ArenaCatalogItem sentinel;
|
||||
DN_TicketMutex ticket_mutex; // Mutex for adding to the linked list of arenas
|
||||
DN_Pool *pool;
|
||||
DN_ArenaCatalogItem sentinel;
|
||||
uint16_t arena_count;
|
||||
};
|
||||
|
||||
enum Dqn_ArenaCatalogFreeArena
|
||||
enum DN_ArenaCatalogFreeArena
|
||||
{
|
||||
Dqn_ArenaCatalogFreeArena_No,
|
||||
Dqn_ArenaCatalogFreeArena_Yes,
|
||||
DN_ArenaCatalogFreeArena_No,
|
||||
DN_ArenaCatalogFreeArena_Yes,
|
||||
};
|
||||
|
||||
// NOTE: [$AREN] Dqn_Arena /////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_Arena Dqn_Arena_InitSize (uint64_t reserve, uint64_t commit, uint8_t flags);
|
||||
DQN_API void Dqn_Arena_Deinit (Dqn_Arena *arena);
|
||||
DQN_API bool Dqn_Arena_Commit (Dqn_Arena *arena, uint64_t size);
|
||||
DQN_API bool Dqn_Arena_CommitTo (Dqn_Arena *arena, uint64_t pos);
|
||||
DQN_API void * Dqn_Arena_Alloc (Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem);
|
||||
DQN_API void * Dqn_Arena_AllocContiguous (Dqn_Arena *arena, uint64_t size, uint8_t align, Dqn_ZeroMem zero_mem);
|
||||
DQN_API void * Dqn_Arena_Copy (Dqn_Arena *arena, void const *data, uint64_t size, uint8_t align);
|
||||
DQN_API void Dqn_Arena_PopTo (Dqn_Arena *arena, uint64_t init_used);
|
||||
DQN_API void Dqn_Arena_Pop (Dqn_Arena *arena, uint64_t amount);
|
||||
DQN_API uint64_t Dqn_Arena_Pos (Dqn_Arena const *arena);
|
||||
DQN_API void Dqn_Arena_Clear (Dqn_Arena *arena);
|
||||
DQN_API bool Dqn_Arena_OwnsPtr (Dqn_Arena const *arena, void *ptr);
|
||||
DQN_API Dqn_ArenaStats Dqn_Arena_SumStatsArray (Dqn_ArenaStats const *array, Dqn_usize size);
|
||||
DQN_API Dqn_ArenaStats Dqn_Arena_SumStats (Dqn_ArenaStats lhs, Dqn_ArenaStats rhs);
|
||||
DQN_API Dqn_ArenaStats Dqn_Arena_SumArenaArrayToStats (Dqn_Arena const *array, Dqn_usize size);
|
||||
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin (Dqn_Arena *arena);
|
||||
DQN_API void Dqn_Arena_TempMemEnd (Dqn_ArenaTempMem mem);
|
||||
#define Dqn_Arena_New(arena, T, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define Dqn_Arena_NewArray(arena, T, count, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem)
|
||||
#define Dqn_Arena_NewCopy(arena, T, src) (T *)Dqn_Arena_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define Dqn_Arena_NewArrayCopy(arena, T, src, count) (T *)Dqn_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
// NOTE: [$AREN] DN_Arena /////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Arena DN_Arena_InitBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_Arena_InitSize (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
|
||||
DN_API void DN_Arena_Deinit (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_Commit (DN_Arena *arena, DN_U64 size);
|
||||
DN_API bool DN_Arena_CommitTo (DN_Arena *arena, DN_U64 pos);
|
||||
DN_API bool DN_Arena_Grow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit);
|
||||
DN_API void * DN_Arena_Alloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_AllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_Copy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
|
||||
DN_API void DN_Arena_PopTo (DN_Arena *arena, DN_U64 init_used);
|
||||
DN_API void DN_Arena_Pop (DN_Arena *arena, DN_U64 amount);
|
||||
DN_API DN_U64 DN_Arena_Pos (DN_Arena const *arena);
|
||||
DN_API void DN_Arena_Clear (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_OwnsPtr (DN_Arena const *arena, void *ptr);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStatsArray (DN_ArenaStats const *array, DN_USize size);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
|
||||
DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats (DN_Arena const *array, DN_USize size);
|
||||
DN_API DN_ArenaTempMem DN_Arena_TempMemBegin (DN_Arena *arena);
|
||||
DN_API void DN_Arena_TempMemEnd (DN_ArenaTempMem mem);
|
||||
#define DN_Arena_New_Frame(T, zero_mem) (T *)DN_Arena_Alloc(DN_TLS_Get()->frame_arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_New(arena, T, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewArray(arena, T, count, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewCopy(arena, T, src) (T *)DN_Arena_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Arena_NewArrayCopy(arena, T, src, count) (T *)DN_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
|
||||
// NOTE: [$CHUN] Dqn_ChunkPool /////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_ChunkPool Dqn_ChunkPool_Init (Dqn_Arena *arena, uint8_t align);
|
||||
DQN_API bool Dqn_ChunkPool_IsValid (Dqn_ChunkPool const *pool);
|
||||
DQN_API void * Dqn_ChunkPool_Alloc (Dqn_ChunkPool *pool, Dqn_usize size);
|
||||
DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8FV (Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8F (Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8Copy (Dqn_ChunkPool *pool, Dqn_Str8 string);
|
||||
DQN_API void Dqn_ChunkPool_Dealloc (Dqn_ChunkPool *pool, void *ptr);
|
||||
DQN_API void * Dqn_ChunkPool_Copy (Dqn_ChunkPool *pool, void const *data, uint64_t size, uint8_t align);
|
||||
// NOTE: [$CHUN] DN_Pool /////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Pool DN_Pool_Init (DN_Arena *arena, uint8_t align);
|
||||
DN_API bool DN_Pool_IsValid (DN_Pool const *pool);
|
||||
DN_API void * DN_Pool_Alloc (DN_Pool *pool, DN_USize size);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8FV (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8F (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8Copy (DN_Pool *pool, DN_Str8 string);
|
||||
DN_API void DN_Pool_Dealloc (DN_Pool *pool, void *ptr);
|
||||
DN_API void * DN_Pool_Copy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align);
|
||||
|
||||
#define Dqn_ChunkPool_New(pool, T) (T *)Dqn_ChunkPool_Alloc(pool, sizeof(T))
|
||||
#define Dqn_ChunkPool_NewArray(pool, T, count) (T *)Dqn_ChunkPool_Alloc(pool, count * sizeof(T))
|
||||
#define Dqn_ChunkPool_NewCopy(arena, T, src) (T *)Dqn_ChunkPool_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define Dqn_ChunkPool_NewArrayCopy(arena, T, src, count) (T *)Dqn_ChunkPool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
#define DN_Pool_New(pool, T) (T *)DN_Pool_Alloc(pool, sizeof(T))
|
||||
#define DN_Pool_NewArray(pool, T, count) (T *)DN_Pool_Alloc(pool, count * sizeof(T))
|
||||
#define DN_Pool_NewCopy(arena, T, src) (T *)DN_Pool_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Pool_NewArrayCopy(arena, T, src, count) (T *)DN_Pool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
|
||||
// NOTE: [$ACAT] Dqn_ArenaCatalog //////////////////////////////////////////////////////////////////
|
||||
DQN_API void Dqn_ArenaCatalog_Init (Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool);
|
||||
DQN_API Dqn_ArenaCatalogItem *Dqn_ArenaCatalog_Find (Dqn_ArenaCatalog *catalog, Dqn_Str8 label);
|
||||
DQN_API void Dqn_ArenaCatalog_AddF (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
DQN_API void Dqn_ArenaCatalog_AddFV (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocFV (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocF (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
DQN_API bool Dqn_ArenaCatalog_Erase (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena);
|
||||
// NOTE: [$ACAT] DN_ArenaCatalog //////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_ArenaCatalog_Init (DN_ArenaCatalog *catalog, DN_Pool *pool);
|
||||
DN_API DN_ArenaCatalogItem *DN_ArenaCatalog_Find (DN_ArenaCatalog *catalog, DN_Str8 label);
|
||||
DN_API void DN_ArenaCatalog_AddF (DN_ArenaCatalog *catalog, DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API void DN_ArenaCatalog_AddFV (DN_ArenaCatalog *catalog, DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Arena * DN_ArenaCatalog_AllocFV (DN_ArenaCatalog *catalog, DN_USize reserve, DN_USize commit, uint8_t arena_flags, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Arena * DN_ArenaCatalog_AllocF (DN_ArenaCatalog *catalog, DN_USize reserve, DN_USize commit, uint8_t arena_flags, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_ArenaCatalog_Erase (DN_ArenaCatalog *catalog, DN_Arena *arena, DN_ArenaCatalogFreeArena free_arena);
|
||||
|
120
dqn_avx512f.cpp
120
dqn_avx512f.cpp
@ -19,18 +19,18 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F(Dqn_Str8 string, Dqn_Str8 find)
|
||||
DN_API DN_Str8FindResult DN_Str8_FindStr8AVX512F(DN_Str8 string, DN_Str8 find)
|
||||
{
|
||||
// NOTE: Algorithm as described in http://0x80.pl/articles/simd-strfind.html
|
||||
Dqn_Str8FindResult result = {};
|
||||
if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(find) || find.size > string.size)
|
||||
DN_Str8FindResult result = {};
|
||||
if (!DN_Str8_HasData(string) || !DN_Str8_HasData(find) || find.size > string.size)
|
||||
return result;
|
||||
|
||||
__m512i const find_first_ch = _mm512_set1_epi8(find.data[0]);
|
||||
__m512i const find_last_ch = _mm512_set1_epi8(find.data[find.size - 1]);
|
||||
|
||||
Dqn_usize const search_size = string.size - find.size;
|
||||
Dqn_usize simd_iterations = search_size / sizeof(__m512i);
|
||||
DN_USize const search_size = string.size - find.size;
|
||||
DN_USize simd_iterations = search_size / sizeof(__m512i);
|
||||
char const *ptr = string.data;
|
||||
|
||||
while (simd_iterations--) {
|
||||
@ -79,41 +79,43 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F(Dqn_Str8 string, Dqn_Str8 fi
|
||||
uint64_t const lsb_zero_pos = _tzcnt_u64(zero_byte_mask);
|
||||
char const *base_ptr = ptr + (4 * lsb_zero_pos);
|
||||
|
||||
if (DQN_MEMCMP(base_ptr + 0, find.data, find.size) == 0) {
|
||||
if (DN_MEMCMP(base_ptr + 0, find.data, find.size) == 0) {
|
||||
result.found = true;
|
||||
result.index = base_ptr - string.data;
|
||||
} else if (DQN_MEMCMP(base_ptr + 1, find.data, find.size) == 0) {
|
||||
} else if (DN_MEMCMP(base_ptr + 1, find.data, find.size) == 0) {
|
||||
result.found = true;
|
||||
result.index = base_ptr - string.data + 1;
|
||||
} else if (DQN_MEMCMP(base_ptr + 2, find.data, find.size) == 0) {
|
||||
} else if (DN_MEMCMP(base_ptr + 2, find.data, find.size) == 0) {
|
||||
result.found = true;
|
||||
result.index = base_ptr - string.data + 2;
|
||||
} else if (DQN_MEMCMP(base_ptr + 3, find.data, find.size) == 0) {
|
||||
} else if (DN_MEMCMP(base_ptr + 3, find.data, find.size) == 0) {
|
||||
result.found = true;
|
||||
result.index = base_ptr - string.data + 3;
|
||||
}
|
||||
|
||||
if (result.found) {
|
||||
result.start_to_before_match = Dqn_Str8_Init(string.data, result.index);
|
||||
result.match = Dqn_Str8_Init(string.data + result.index, find.size);
|
||||
result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - result.index);
|
||||
result.start_to_before_match = DN_Str8_Init(string.data, result.index);
|
||||
result.match = DN_Str8_Init(string.data + result.index, find.size);
|
||||
result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - result.index);
|
||||
result.after_match_to_end_of_buffer = DN_Str8_Advance(result.match_to_end_of_buffer, find.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
zero_byte_mask = Dqn_Bit_ClearNextLSB(zero_byte_mask);
|
||||
zero_byte_mask = DN_Bit_ClearNextLSB(zero_byte_mask);
|
||||
}
|
||||
|
||||
ptr += sizeof(__m512i);
|
||||
}
|
||||
|
||||
for (Dqn_usize index = ptr - string.data; index < string.size; index++) {
|
||||
Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find.size);
|
||||
if (Dqn_Str8_Eq(string_slice, find)) {
|
||||
for (DN_USize index = ptr - string.data; index < string.size; index++) {
|
||||
DN_Str8 string_slice = DN_Str8_Slice(string, index, find.size);
|
||||
if (DN_Str8_Eq(string_slice, find)) {
|
||||
result.found = true;
|
||||
result.index = index;
|
||||
result.start_to_before_match = Dqn_Str8_Init(string.data, index);
|
||||
result.match = Dqn_Str8_Init(string.data + index, find.size);
|
||||
result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - index);
|
||||
result.start_to_before_match = DN_Str8_Init(string.data, index);
|
||||
result.match = DN_Str8_Init(string.data + index, find.size);
|
||||
result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - index);
|
||||
result.after_match_to_end_of_buffer = DN_Str8_Advance(result.match_to_end_of_buffer, find.size);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -121,18 +123,18 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F(Dqn_Str8 string, Dqn_Str8 fi
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F(Dqn_Str8 string, Dqn_Str8 find)
|
||||
DN_API DN_Str8FindResult DN_Str8_FindLastStr8AVX512F(DN_Str8 string, DN_Str8 find)
|
||||
{
|
||||
// NOTE: Algorithm as described in http://0x80.pl/articles/simd-strfind.html
|
||||
Dqn_Str8FindResult result = {};
|
||||
if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(find) || find.size > string.size)
|
||||
DN_Str8FindResult result = {};
|
||||
if (!DN_Str8_HasData(string) || !DN_Str8_HasData(find) || find.size > string.size)
|
||||
return result;
|
||||
|
||||
__m512i const find_first_ch = _mm512_set1_epi8(find.data[0]);
|
||||
__m512i const find_last_ch = _mm512_set1_epi8(find.data[find.size - 1]);
|
||||
|
||||
Dqn_usize const search_size = string.size - find.size;
|
||||
Dqn_usize simd_iterations = search_size / sizeof(__m512i);
|
||||
DN_USize const search_size = string.size - find.size;
|
||||
DN_USize simd_iterations = search_size / sizeof(__m512i);
|
||||
char const *ptr = string.data + search_size + 1;
|
||||
|
||||
while (simd_iterations--) {
|
||||
@ -182,39 +184,39 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F(Dqn_Str8 string, Dqn_Str
|
||||
uint64_t const lsb_zero_pos = _tzcnt_u64(zero_byte_mask);
|
||||
char const *base_ptr = ptr + (4 * lsb_zero_pos);
|
||||
|
||||
if (DQN_MEMCMP(base_ptr + 0, find.data, find.size) == 0) {
|
||||
if (DN_MEMCMP(base_ptr + 0, find.data, find.size) == 0) {
|
||||
result.found = true;
|
||||
result.index = base_ptr - string.data;
|
||||
} else if (DQN_MEMCMP(base_ptr + 1, find.data, find.size) == 0) {
|
||||
} else if (DN_MEMCMP(base_ptr + 1, find.data, find.size) == 0) {
|
||||
result.found = true;
|
||||
result.index = base_ptr - string.data + 1;
|
||||
} else if (DQN_MEMCMP(base_ptr + 2, find.data, find.size) == 0) {
|
||||
} else if (DN_MEMCMP(base_ptr + 2, find.data, find.size) == 0) {
|
||||
result.found = true;
|
||||
result.index = base_ptr - string.data + 2;
|
||||
} else if (DQN_MEMCMP(base_ptr + 3, find.data, find.size) == 0) {
|
||||
} else if (DN_MEMCMP(base_ptr + 3, find.data, find.size) == 0) {
|
||||
result.found = true;
|
||||
result.index = base_ptr - string.data + 3;
|
||||
}
|
||||
|
||||
if (result.found) {
|
||||
result.start_to_before_match = Dqn_Str8_Init(string.data, result.index);
|
||||
result.match = Dqn_Str8_Init(string.data + result.index, find.size);
|
||||
result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - result.index);
|
||||
result.start_to_before_match = DN_Str8_Init(string.data, result.index);
|
||||
result.match = DN_Str8_Init(string.data + result.index, find.size);
|
||||
result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - result.index);
|
||||
return result;
|
||||
}
|
||||
|
||||
zero_byte_mask = Dqn_Bit_ClearNextLSB(zero_byte_mask);
|
||||
zero_byte_mask = DN_Bit_ClearNextLSB(zero_byte_mask);
|
||||
}
|
||||
}
|
||||
|
||||
for (Dqn_usize index = ptr - string.data - 1; index < string.size; index--) {
|
||||
Dqn_Str8 string_slice = Dqn_Str8_Slice(string, index, find.size);
|
||||
if (Dqn_Str8_Eq(string_slice, find)) {
|
||||
for (DN_USize index = ptr - string.data - 1; index < string.size; index--) {
|
||||
DN_Str8 string_slice = DN_Str8_Slice(string, index, find.size);
|
||||
if (DN_Str8_Eq(string_slice, find)) {
|
||||
result.found = true;
|
||||
result.index = index;
|
||||
result.start_to_before_match = Dqn_Str8_Init(string.data, index);
|
||||
result.match = Dqn_Str8_Init(string.data + index, find.size);
|
||||
result.match_to_end_of_buffer = Dqn_Str8_Init(result.match.data, string.size - index);
|
||||
result.start_to_before_match = DN_Str8_Init(string.data, index);
|
||||
result.match = DN_Str8_Init(string.data + index, find.size);
|
||||
result.match_to_end_of_buffer = DN_Str8_Init(result.match.data, string.size - index);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -222,14 +224,14 @@ DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F(Dqn_Str8 string, Dqn_Str
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitAVX512F(Dqn_Str8 string, Dqn_Str8 find)
|
||||
DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitAVX512F(DN_Str8 string, DN_Str8 find)
|
||||
{
|
||||
Dqn_Str8BinarySplitResult result = {};
|
||||
Dqn_Str8FindResult find_result = Dqn_Str8_FindStr8AVX512F(string, find);
|
||||
DN_Str8BinarySplitResult result = {};
|
||||
DN_Str8FindResult find_result = DN_Str8_FindStr8AVX512F(string, find);
|
||||
if (find_result.found) {
|
||||
result.lhs.data = string.data;
|
||||
result.lhs.size = find_result.index;
|
||||
result.rhs = Dqn_Str8_Advance(find_result.match_to_end_of_buffer, find.size);
|
||||
result.rhs = DN_Str8_Advance(find_result.match_to_end_of_buffer, find.size);
|
||||
} else {
|
||||
result.lhs = string;
|
||||
}
|
||||
@ -237,14 +239,14 @@ DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitAVX512F(Dqn_Str8 string, D
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastAVX512F(Dqn_Str8 string, Dqn_Str8 find)
|
||||
DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLastAVX512F(DN_Str8 string, DN_Str8 find)
|
||||
{
|
||||
Dqn_Str8BinarySplitResult result = {};
|
||||
Dqn_Str8FindResult find_result = Dqn_Str8_FindLastStr8AVX512F(string, find);
|
||||
DN_Str8BinarySplitResult result = {};
|
||||
DN_Str8FindResult find_result = DN_Str8_FindLastStr8AVX512F(string, find);
|
||||
if (find_result.found) {
|
||||
result.lhs.data = string.data;
|
||||
result.lhs.size = find_result.index;
|
||||
result.rhs = Dqn_Str8_Advance(find_result.match_to_end_of_buffer, find.size);
|
||||
result.rhs = DN_Str8_Advance(find_result.match_to_end_of_buffer, find.size);
|
||||
} else {
|
||||
result.lhs = string;
|
||||
}
|
||||
@ -252,17 +254,17 @@ DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastAVX512F(Dqn_Str8 strin
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_usize Dqn_Str8_SplitAVX512F(Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8 *splits, Dqn_usize splits_count, Dqn_Str8SplitIncludeEmptyStrings mode)
|
||||
DN_API DN_USize DN_Str8_SplitAVX512F(DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode)
|
||||
{
|
||||
Dqn_usize result = 0; // The number of splits in the actual string.
|
||||
if (!Dqn_Str8_HasData(string) || !Dqn_Str8_HasData(delimiter) || delimiter.size <= 0)
|
||||
DN_USize result = 0; // The number of splits in the actual string.
|
||||
if (!DN_Str8_HasData(string) || !DN_Str8_HasData(delimiter) || delimiter.size <= 0)
|
||||
return result;
|
||||
|
||||
Dqn_Str8BinarySplitResult split = {};
|
||||
Dqn_Str8 first = string;
|
||||
DN_Str8BinarySplitResult split = {};
|
||||
DN_Str8 first = string;
|
||||
do {
|
||||
split = Dqn_Str8_BinarySplitAVX512F(first, delimiter);
|
||||
if (split.lhs.size || mode == Dqn_Str8SplitIncludeEmptyStrings_Yes) {
|
||||
split = DN_Str8_BinarySplitAVX512F(first, delimiter);
|
||||
if (split.lhs.size || mode == DN_Str8SplitIncludeEmptyStrings_Yes) {
|
||||
if (splits && result < splits_count)
|
||||
splits[result] = split.lhs;
|
||||
result++;
|
||||
@ -273,14 +275,14 @@ DQN_API Dqn_usize Dqn_Str8_SplitAVX512F(Dqn_Str8 string, Dqn_Str8 delimiter, Dqn
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Slice<Dqn_Str8> 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 = {};
|
||||
Dqn_usize splits_required = Dqn_Str8_SplitAVX512F(string, delimiter, /*splits*/ nullptr, /*count*/ 0, mode);
|
||||
result.data = Dqn_Arena_NewArray(arena, Dqn_Str8, splits_required, Dqn_ZeroMem_No);
|
||||
DN_Slice<DN_Str8> result = {};
|
||||
DN_USize splits_required = DN_Str8_SplitAVX512F(string, delimiter, /*splits*/ nullptr, /*count*/ 0, mode);
|
||||
result.data = DN_Arena_NewArray(arena, DN_Str8, splits_required, DN_ZeroMem_No);
|
||||
if (result.data) {
|
||||
result.size = Dqn_Str8_SplitAVX512F(string, delimiter, result.data, splits_required, mode);
|
||||
DQN_ASSERT(splits_required == result.size);
|
||||
result.size = DN_Str8_SplitAVX512F(string, delimiter, result.data, splits_required, mode);
|
||||
DN_ASSERT(splits_required == result.size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#if !defined(DQN_AVX512F_H)
|
||||
#define DQN_AVX512F_H
|
||||
#if !defined(DN_AVX512F_H)
|
||||
#define DN_AVX512F_H
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -20,11 +20,11 @@
|
||||
|
||||
#include "dqn.h"
|
||||
|
||||
DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8AVX512F (Dqn_Str8 string, Dqn_Str8 find);
|
||||
DQN_API Dqn_Str8FindResult Dqn_Str8_FindLastStr8AVX512F (Dqn_Str8 string, Dqn_Str8 find);
|
||||
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitAVX512F (Dqn_Str8 string, Dqn_Str8 find);
|
||||
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastAVX512F(Dqn_Str8 string, Dqn_Str8 find);
|
||||
DQN_API Dqn_usize Dqn_Str8_SplitAVX512F (Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8 *splits, Dqn_usize splits_count, Dqn_Str8SplitIncludeEmptyStrings mode);
|
||||
DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8_SplitAllocAVX512F (Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8SplitIncludeEmptyStrings mode);
|
||||
DN_API DN_Str8FindResult DN_Str8_FindStr8AVX512F (DN_Str8 string, DN_Str8 find);
|
||||
DN_API DN_Str8FindResult DN_Str8_FindLastStr8AVX512F (DN_Str8 string, DN_Str8 find);
|
||||
DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitAVX512F (DN_Str8 string, DN_Str8 find);
|
||||
DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLastAVX512F(DN_Str8 string, DN_Str8 find);
|
||||
DN_API DN_USize DN_Str8_SplitAVX512F (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode);
|
||||
DN_API DN_Slice<DN_Str8> DN_Str8_SplitAllocAVX512F (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
|
||||
|
||||
#endif // DQN_AVX512F_H
|
||||
#endif // DN_AVX512F_H
|
||||
|
843
dqn_base.cpp
843
dqn_base.cpp
File diff suppressed because it is too large
Load Diff
1011
dqn_base.h
1011
dqn_base.h
File diff suppressed because it is too large
Load Diff
1195
dqn_cgen.cpp
1195
dqn_cgen.cpp
File diff suppressed because it is too large
Load Diff
178
dqn_cgen.h
178
dqn_cgen.h
@ -1,5 +1,5 @@
|
||||
#if !defined(DQN_CGEN_H)
|
||||
#define DQN_CGEN_H
|
||||
#if !defined(DN_CGEN_H)
|
||||
#define DN_CGEN_H
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -18,157 +18,157 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$CGEN] Dqn_CGen //////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: [$CGEN] DN_CGen //////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(MD_H)
|
||||
#error Metadesk 'md.h' must be included before 'dqn_cgen.h'
|
||||
#error Metadesk 'md.h' must be included before 'dn_cgen.h'
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_H)
|
||||
#error 'dqn.h' must be included before 'dqn_cgen.h'
|
||||
#if !defined(DN_H)
|
||||
#error 'dqn.h' must be included before 'dn_cgen.h'
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_CPP_FILE_H)
|
||||
#error 'dqn_cpp_file.h' must be included before 'dqn_cgen.h'
|
||||
#if !defined(DN_CPP_FILE_H)
|
||||
#error 'dn_cpp_file.h' must be included before 'dn_cgen.h'
|
||||
#endif
|
||||
|
||||
enum Dqn_CGenTableKeyType
|
||||
enum DN_CGenTableKeyType
|
||||
{
|
||||
Dqn_CGenTableKeyType_Nil,
|
||||
Dqn_CGenTableKeyType_Name,
|
||||
Dqn_CGenTableKeyType_Type,
|
||||
DN_CGenTableKeyType_Nil,
|
||||
DN_CGenTableKeyType_Name,
|
||||
DN_CGenTableKeyType_Type,
|
||||
};
|
||||
|
||||
enum Dqn_CGenTableType
|
||||
enum DN_CGenTableType
|
||||
{
|
||||
Dqn_CGenTableType_Nil,
|
||||
Dqn_CGenTableType_Data,
|
||||
Dqn_CGenTableType_CodeGenBuiltinTypes,
|
||||
Dqn_CGenTableType_CodeGenStruct,
|
||||
Dqn_CGenTableType_CodeGenEnum,
|
||||
Dqn_CGenTableType_Count,
|
||||
DN_CGenTableType_Nil,
|
||||
DN_CGenTableType_Data,
|
||||
DN_CGenTableType_CodeGenBuiltinTypes,
|
||||
DN_CGenTableType_CodeGenStruct,
|
||||
DN_CGenTableType_CodeGenEnum,
|
||||
DN_CGenTableType_Count,
|
||||
};
|
||||
|
||||
enum Dqn_CGenTableRowTagType
|
||||
enum DN_CGenTableRowTagType
|
||||
{
|
||||
Dqn_CGenTableRowTagType_Nil,
|
||||
Dqn_CGenTableRowTagType_CommentDivider,
|
||||
Dqn_CGenTableRowTagType_EmptyLine,
|
||||
DN_CGenTableRowTagType_Nil,
|
||||
DN_CGenTableRowTagType_CommentDivider,
|
||||
DN_CGenTableRowTagType_EmptyLine,
|
||||
};
|
||||
|
||||
enum Dqn_CGenTableRowTagCommentDivider
|
||||
enum DN_CGenTableRowTagCommentDivider
|
||||
{
|
||||
Dqn_CGenTableRowTagCommentDivider_Nil,
|
||||
Dqn_CGenTableRowTagCommentDivider_Label,
|
||||
DN_CGenTableRowTagCommentDivider_Nil,
|
||||
DN_CGenTableRowTagCommentDivider_Label,
|
||||
};
|
||||
|
||||
enum Dqn_CGenTableHeaderType
|
||||
enum DN_CGenTableHeaderType
|
||||
{
|
||||
Dqn_CGenTableHeaderType_Name,
|
||||
Dqn_CGenTableHeaderType_Table,
|
||||
Dqn_CGenTableHeaderType_CppType,
|
||||
Dqn_CGenTableHeaderType_CppName,
|
||||
Dqn_CGenTableHeaderType_CppValue,
|
||||
Dqn_CGenTableHeaderType_CppIsPtr,
|
||||
Dqn_CGenTableHeaderType_CppOpEquals,
|
||||
Dqn_CGenTableHeaderType_CppArraySize,
|
||||
Dqn_CGenTableHeaderType_CppArraySizeField,
|
||||
Dqn_CGenTableHeaderType_CppLabel,
|
||||
Dqn_CGenTableHeaderType_GenTypeInfo,
|
||||
Dqn_CGenTableHeaderType_GenEnumCount,
|
||||
Dqn_CGenTableHeaderType_Count,
|
||||
DN_CGenTableHeaderType_Name,
|
||||
DN_CGenTableHeaderType_Table,
|
||||
DN_CGenTableHeaderType_CppType,
|
||||
DN_CGenTableHeaderType_CppName,
|
||||
DN_CGenTableHeaderType_CppValue,
|
||||
DN_CGenTableHeaderType_CppIsPtr,
|
||||
DN_CGenTableHeaderType_CppOpEquals,
|
||||
DN_CGenTableHeaderType_CppArraySize,
|
||||
DN_CGenTableHeaderType_CppArraySizeField,
|
||||
DN_CGenTableHeaderType_CppLabel,
|
||||
DN_CGenTableHeaderType_GenTypeInfo,
|
||||
DN_CGenTableHeaderType_GenEnumCount,
|
||||
DN_CGenTableHeaderType_Count,
|
||||
};
|
||||
|
||||
struct Dqn_CGenTableHeader
|
||||
struct DN_CGenTableHeader
|
||||
{
|
||||
MD_String8 name;
|
||||
int longest_string;
|
||||
};
|
||||
|
||||
struct Dqn_CGenTableRowTag
|
||||
struct DN_CGenTableRowTag
|
||||
{
|
||||
Dqn_CGenTableRowTagType type;
|
||||
DN_CGenTableRowTagType type;
|
||||
MD_String8 comment;
|
||||
Dqn_CGenTableRowTag *next;
|
||||
DN_CGenTableRowTag *next;
|
||||
};
|
||||
|
||||
|
||||
struct Dqn_CGenTableColumn
|
||||
struct DN_CGenTableColumn
|
||||
{
|
||||
MD_Node *node;
|
||||
Dqn_Str8 string;
|
||||
DN_Str8 string;
|
||||
};
|
||||
|
||||
struct Dqn_CGenTableRow
|
||||
struct DN_CGenTableRow
|
||||
{
|
||||
Dqn_CGenTableRowTag *first_tag;
|
||||
Dqn_CGenTableRowTag *last_tag;
|
||||
Dqn_CGenTableColumn *columns;
|
||||
DN_CGenTableRowTag *first_tag;
|
||||
DN_CGenTableRowTag *last_tag;
|
||||
DN_CGenTableColumn *columns;
|
||||
};
|
||||
|
||||
struct Dqn_CGenTable
|
||||
struct DN_CGenTable
|
||||
{
|
||||
Dqn_CGenTableType type;
|
||||
Dqn_Str8 name;
|
||||
DN_CGenTableType type;
|
||||
DN_Str8 name;
|
||||
MD_Map headers_map;
|
||||
Dqn_CGenTableHeader *headers;
|
||||
Dqn_CGenTableRow *rows;
|
||||
DN_CGenTableHeader *headers;
|
||||
DN_CGenTableRow *rows;
|
||||
size_t column_count;
|
||||
size_t row_count;
|
||||
|
||||
MD_Node *node;
|
||||
MD_Node *headers_node;
|
||||
Dqn_usize column_indexes[Dqn_CGenTableHeaderType_Count];
|
||||
Dqn_CGenTable *next;
|
||||
DN_USize column_indexes[DN_CGenTableHeaderType_Count];
|
||||
DN_CGenTable *next;
|
||||
};
|
||||
|
||||
struct Dqn_CGen
|
||||
struct DN_CGen
|
||||
{
|
||||
MD_Arena *arena;
|
||||
MD_Node *file_list;
|
||||
MD_Map table_map;
|
||||
Dqn_CGenTable *first_table;
|
||||
Dqn_CGenTable *last_table;
|
||||
Dqn_usize table_counts[Dqn_CGenTableType_Count];
|
||||
DN_CGenTable *first_table;
|
||||
DN_CGenTable *last_table;
|
||||
DN_USize table_counts[DN_CGenTableType_Count];
|
||||
};
|
||||
|
||||
struct Dqn_CGenMapNodeToEnum
|
||||
struct DN_CGenMapNodeToEnum
|
||||
{
|
||||
uint32_t enum_val;
|
||||
Dqn_Str8 node_string;
|
||||
DN_Str8 node_string;
|
||||
};
|
||||
|
||||
struct Dqn_CGenLookupTableIterator
|
||||
struct DN_CGenLookupTableIterator
|
||||
{
|
||||
Dqn_CGenTable *cgen_table;
|
||||
Dqn_CGenTableRow *cgen_table_row;
|
||||
Dqn_CGenTableColumn cgen_table_column[Dqn_CGenTableHeaderType_Count];
|
||||
Dqn_CGenTable *table;
|
||||
Dqn_usize row_index;
|
||||
DN_CGenTable *cgen_table;
|
||||
DN_CGenTableRow *cgen_table_row;
|
||||
DN_CGenTableColumn cgen_table_column[DN_CGenTableHeaderType_Count];
|
||||
DN_CGenTable *table;
|
||||
DN_USize row_index;
|
||||
};
|
||||
|
||||
struct Dqn_CGenLookupColumnAtHeader
|
||||
struct DN_CGenLookupColumnAtHeader
|
||||
{
|
||||
Dqn_usize index;
|
||||
Dqn_CGenTableHeader header;
|
||||
Dqn_CGenTableColumn column;
|
||||
DN_USize index;
|
||||
DN_CGenTableHeader header;
|
||||
DN_CGenTableColumn column;
|
||||
};
|
||||
|
||||
enum Dqn_CGenEmit
|
||||
enum DN_CGenEmit
|
||||
{
|
||||
Dqn_CGenEmit_Prototypes = 1 << 0,
|
||||
Dqn_CGenEmit_Implementation = 1 << 1,
|
||||
DN_CGenEmit_Prototypes = 1 << 0,
|
||||
DN_CGenEmit_Implementation = 1 << 1,
|
||||
};
|
||||
|
||||
// NOTE: [$CGEN] Dqn_CGen //////////////////////////////////////////////////////////////////////////
|
||||
#define Dqn_CGen_MDToDqnStr8(str8) Dqn_Str8_Init((str8).str, (str8).size)
|
||||
#define Dqn_CGen_DqnToMDStr8(str8) {DQN_CAST(MD_u8 *)(str8).data, (str8).size}
|
||||
DQN_API Dqn_CGen Dqn_CGen_InitFilesArgV (int argc, char const **argv, Dqn_ErrorSink *error);
|
||||
DQN_API Dqn_Str8 Dqn_CGen_TableHeaderTypeToDeclStr8 (Dqn_CGenTableHeaderType type);
|
||||
DQN_API Dqn_CGenMapNodeToEnum Dqn_CGen_MapNodeToEnumOrExit (MD_Node const *node, Dqn_CGenMapNodeToEnum const *valid_keys, Dqn_usize valid_keys_size, char const *fmt, ...);
|
||||
DQN_API Dqn_usize Dqn_CGen_NodeChildrenCount (MD_Node const *node);
|
||||
DQN_API void Dqn_CGen_LogF (MD_MessageKind kind, MD_Node *node, Dqn_ErrorSink *error, char const *fmt, ...);
|
||||
DQN_API bool Dqn_CGen_TableHasHeaders (Dqn_CGenTable const *table, Dqn_Str8 const *headers, Dqn_usize header_count, Dqn_ErrorSink *error);
|
||||
DQN_API Dqn_CGenLookupColumnAtHeader Dqn_CGen_LookupColumnAtHeader (Dqn_CGenTable *table, Dqn_Str8 header, Dqn_CGenTableRow const *row);
|
||||
DQN_API bool Dqn_CGen_LookupNextTableInCodeGenTable(Dqn_CGen *cgen, Dqn_CGenTable *cgen_table, Dqn_CGenLookupTableIterator *it);
|
||||
DQN_API void Dqn_CGen_EmitCodeForTables (Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_CppFile *cpp, Dqn_Str8 emit_prefix);
|
||||
#endif // DQN_CGEN_H
|
||||
// NOTE: [$CGEN] DN_CGen //////////////////////////////////////////////////////////////////////////
|
||||
#define DN_CGen_MDToDNStr8(str8) DN_Str8_Init((str8).str, (str8).size)
|
||||
#define DN_CGen_DNToMDStr8(str8) {DN_CAST(MD_u8 *)(str8).data, (str8).size}
|
||||
DN_API DN_CGen DN_CGen_InitFilesArgV (int argc, char const **argv, DN_ErrSink *err);
|
||||
DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8 (DN_CGenTableHeaderType type);
|
||||
DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit (MD_Node const *node, DN_CGenMapNodeToEnum const *valid_keys, DN_USize valid_keys_size, char const *fmt, ...);
|
||||
DN_API DN_USize DN_CGen_NodeChildrenCount (MD_Node const *node);
|
||||
DN_API void DN_CGen_LogF (MD_MessageKind kind, MD_Node *node, DN_ErrSink *err, char const *fmt, ...);
|
||||
DN_API bool DN_CGen_TableHasHeaders (DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_ErrSink *err);
|
||||
DN_API DN_CGenLookupColumnAtHeader DN_CGen_LookupColumnAtHeader (DN_CGenTable *table, DN_Str8 header, DN_CGenTableRow const *row);
|
||||
DN_API bool DN_CGen_LookupNextTableInCodeGenTable(DN_CGen *cgen, DN_CGenTable *cgen_table, DN_CGenLookupTableIterator *it);
|
||||
DN_API void DN_CGen_EmitCodeForTables (DN_CGen *cgen, DN_CGenEmit emit, DN_CppFile *cpp, DN_Str8 emit_prefix);
|
||||
#endif // DN_CGEN_H
|
||||
|
1360
dqn_containers.cpp
1360
dqn_containers.cpp
File diff suppressed because it is too large
Load Diff
1723
dqn_containers.h
1723
dqn_containers.h
File diff suppressed because it is too large
Load Diff
204
dqn_cppbuild.h
204
dqn_cppbuild.h
@ -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
|
379
dqn_debug.cpp
379
dqn_debug.cpp
@ -18,58 +18,61 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$ASAN] Dqn_Asan ////////////////////////////////////////////////////////////////////////// ///
|
||||
DQN_API void Dqn_ASAN_PoisonMemoryRegion(void const volatile *ptr, Dqn_usize size)
|
||||
// NOTE: [$ASAN] DN_Asan ////////////////////////////////////////////////////////////////////////// ///
|
||||
DN_API void DN_ASAN_PoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
{
|
||||
if (!ptr || !size)
|
||||
return;
|
||||
|
||||
#if DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
DN_ASSERTF(DN_IsPowerOfTwoAligned(ptr, 8),
|
||||
"Poisoning requires the pointer to be aligned on an 8 byte boundary");
|
||||
|
||||
__asan_poison_memory_region(ptr, size);
|
||||
if (DQN_ASAN_VET_POISON) {
|
||||
DQN_HARD_ASSERT(__asan_address_is_poisoned(ptr));
|
||||
DQN_HARD_ASSERT(__asan_address_is_poisoned((char *)ptr + (size - 1)));
|
||||
if (DN_ASAN_VET_POISON) {
|
||||
DN_HARD_ASSERT(__asan_address_is_poisoned(ptr));
|
||||
DN_HARD_ASSERT(__asan_address_is_poisoned((char *)ptr + (size - 1)));
|
||||
}
|
||||
#else
|
||||
(void)ptr; (void)size;
|
||||
#endif
|
||||
}
|
||||
|
||||
DQN_API void Dqn_ASAN_UnpoisonMemoryRegion(void const volatile *ptr, Dqn_usize size)
|
||||
DN_API void DN_ASAN_UnpoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
{
|
||||
if (!ptr || !size)
|
||||
return;
|
||||
|
||||
#if DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
__asan_unpoison_memory_region(ptr, size);
|
||||
if (DQN_ASAN_VET_POISON) {
|
||||
DQN_HARD_ASSERT(__asan_region_is_poisoned((void *)ptr, size) == 0);
|
||||
if (DN_ASAN_VET_POISON) {
|
||||
DN_HARD_ASSERT(__asan_region_is_poisoned((void *)ptr, size) == 0);
|
||||
}
|
||||
#else
|
||||
(void)ptr; (void)size;
|
||||
#endif
|
||||
}
|
||||
|
||||
DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk(Dqn_Arena *arena, uint16_t limit)
|
||||
DN_API DN_StackTraceWalkResult DN_StackTrace_Walk(DN_Arena *arena, uint16_t limit)
|
||||
{
|
||||
Dqn_StackTraceWalkResult result = {};
|
||||
#if defined(DQN_OS_WIN32)
|
||||
DN_StackTraceWalkResult result = {};
|
||||
#if defined(DN_OS_WIN32)
|
||||
if (!arena)
|
||||
return result;
|
||||
|
||||
static Dqn_TicketMutex mutex = {};
|
||||
Dqn_TicketMutex_Begin(&mutex);
|
||||
static DN_TicketMutex mutex = {};
|
||||
DN_TicketMutex_Begin(&mutex);
|
||||
|
||||
HANDLE thread = GetCurrentThread();
|
||||
result.process = GetCurrentProcess();
|
||||
|
||||
if (!g_dqn_library->win32_sym_initialised) {
|
||||
g_dqn_library->win32_sym_initialised = true;
|
||||
if (!g_dn_core->win32_sym_initialised) {
|
||||
g_dn_core->win32_sym_initialised = true;
|
||||
SymSetOptions(SYMOPT_LOAD_LINES);
|
||||
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena);
|
||||
Dqn_WinError error = Dqn_Win_LastError(tmem.arena);
|
||||
Dqn_Log_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DQN_STR_FMT(error.msg));
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(arena);
|
||||
DN_WinError error = DN_Win_LastError(tmem.arena);
|
||||
DN_Log_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_STR_FMT(error.msg));
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +87,7 @@ DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk(Dqn_Arena *arena, uint16_t
|
||||
frame.AddrStack.Offset = context.Rsp;
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
|
||||
Dqn_FArray<uint64_t, 256> raw_frames = {};
|
||||
DN_FArray<uint64_t, 256> raw_frames = {};
|
||||
while (raw_frames.size < limit) {
|
||||
if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64,
|
||||
result.process,
|
||||
@ -100,53 +103,155 @@ DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk(Dqn_Arena *arena, uint16_t
|
||||
|
||||
// NOTE: It might be useful one day to use frame.AddrReturn.Offset.
|
||||
// If AddrPC.Offset == AddrReturn.Offset then we can detect recursion.
|
||||
Dqn_FArray_Add(&raw_frames, frame.AddrPC.Offset);
|
||||
DN_FArray_Add(&raw_frames, frame.AddrPC.Offset);
|
||||
}
|
||||
Dqn_TicketMutex_End(&mutex);
|
||||
DN_TicketMutex_End(&mutex);
|
||||
|
||||
result.base_addr = Dqn_Arena_NewArray(arena, uint64_t, raw_frames.size, Dqn_ZeroMem_No);
|
||||
result.size = DQN_CAST(uint16_t)raw_frames.size;
|
||||
DQN_MEMCPY(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0]));
|
||||
result.base_addr = DN_Arena_NewArray(arena, uint64_t, raw_frames.size, DN_ZeroMem_No);
|
||||
result.size = DN_CAST(uint16_t)raw_frames.size;
|
||||
DN_MEMCPY(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0]));
|
||||
#else
|
||||
(void)limit; (void)arena;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_StackTrace_WalkStr8CRT(uint16_t limit, uint16_t skip)
|
||||
DN_API DN_StackTraceWalkResult DN_StackTrace_WalkCRT(uint16_t limit)
|
||||
{
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
|
||||
Dqn_StackTraceWalkResult walk_result = Dqn_StackTrace_Walk(tmem.arena, limit);
|
||||
Dqn_Str8 result = Dqn_StackTrace_WalkResultStr8CRT(&walk_result, skip);
|
||||
DN_StackTraceWalkResult result = {};
|
||||
#if defined(DN_OS_WIN32)
|
||||
static DN_TicketMutex mutex = {};
|
||||
DN_TicketMutex_Begin(&mutex);
|
||||
|
||||
HANDLE thread = GetCurrentThread();
|
||||
result.process = GetCurrentProcess();
|
||||
|
||||
if (!g_dn_core->win32_sym_initialised) {
|
||||
g_dn_core->win32_sym_initialised = true;
|
||||
SymSetOptions(SYMOPT_LOAD_LINES);
|
||||
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
|
||||
DN_WinError error = DN_Win_LastErrorAlloc();
|
||||
DN_Log_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_STR_FMT(error.msg));
|
||||
DN_OS_MemDealloc(error.msg.data);
|
||||
}
|
||||
}
|
||||
|
||||
CONTEXT context;
|
||||
RtlCaptureContext(&context);
|
||||
|
||||
STACKFRAME64 frame = {};
|
||||
frame.AddrPC.Offset = context.Rip;
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
frame.AddrFrame.Offset = context.Rbp;
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
frame.AddrStack.Offset = context.Rsp;
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
|
||||
struct FrameChunk
|
||||
{
|
||||
uint64_t frames[128];
|
||||
FrameChunk *next;
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
DN_USize total_frames = 0;
|
||||
FrameChunk frame_chunk = {};
|
||||
FrameChunk *frame_chunk_it = &frame_chunk;
|
||||
for (; total_frames < limit; total_frames++) {
|
||||
if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64,
|
||||
result.process,
|
||||
thread,
|
||||
&frame,
|
||||
&context,
|
||||
nullptr /*ReadMemoryRoutine*/,
|
||||
SymFunctionTableAccess64,
|
||||
SymGetModuleBase64,
|
||||
nullptr /*TranslateAddress*/)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: It might be useful one day to use frame.AddrReturn.Offset.
|
||||
// If AddrPC.Offset == AddrReturn.Offset then we can detect recursion.
|
||||
if (frame_chunk_it->size == DN_ARRAY_UCOUNT(frame_chunk_it->frames)) {
|
||||
FrameChunk *next = DN_CAST(FrameChunk *) DN_OS_MemAlloc(sizeof(*next), DN_ZeroMem_No);
|
||||
frame_chunk_it = next;
|
||||
}
|
||||
|
||||
if (!frame_chunk_it)
|
||||
break;
|
||||
frame_chunk_it->frames[frame_chunk_it->size++] = frame.AddrPC.Offset;
|
||||
}
|
||||
DN_TicketMutex_End(&mutex);
|
||||
|
||||
result.base_addr = DN_CAST(uint64_t *)DN_OS_MemAlloc(sizeof(*result.base_addr) * total_frames, DN_ZeroMem_No);
|
||||
for (FrameChunk *it = &frame_chunk; it; ) {
|
||||
FrameChunk *next = it->next;
|
||||
|
||||
// NOTE: Copy
|
||||
DN_MEMCPY(result.base_addr, it->frames, it->size * sizeof(it->frames[0]));
|
||||
result.size += it->size;
|
||||
|
||||
// NOTE: Free
|
||||
if (it != &frame_chunk)
|
||||
DN_OS_MemDealloc(it);
|
||||
it = next;
|
||||
}
|
||||
#else
|
||||
DN_INVALID_CODE_PATH;
|
||||
(void)limit;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static void Dqn_StackTrace_AddWalkToStr8Builder_(Dqn_StackTraceWalkResult const *walk, Dqn_Str8Builder *builder, Dqn_usize skip)
|
||||
DN_API DN_Str8 DN_StackTrace_WalkStr8CRT(uint16_t limit, uint16_t skip)
|
||||
{
|
||||
Dqn_StackTraceRawFrame raw_frame = {};
|
||||
DN_StackTraceWalkResult walk_result = DN_StackTrace_WalkCRT(limit);
|
||||
DN_Str8 result = DN_StackTrace_WalkResultStr8CRT(&walk_result, skip);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void DN_StackTrace_AddWalkToStr8Builder_(DN_StackTraceWalkResult const *walk, DN_Str8Builder *builder, DN_USize skip)
|
||||
{
|
||||
DN_StackTraceRawFrame raw_frame = {};
|
||||
raw_frame.process = walk->process;
|
||||
for (Dqn_usize index = skip; index < walk->size; index++) {
|
||||
for (DN_USize index = skip; index < walk->size; index++) {
|
||||
raw_frame.base_addr = walk->base_addr[index];
|
||||
Dqn_StackTraceFrame frame = Dqn_StackTrace_RawFrameToFrame(builder->arena, raw_frame);
|
||||
Dqn_Str8Builder_AddF(builder, "%.*s(%zu): %.*s%s", DQN_STR_FMT(frame.file_name), frame.line_number, DQN_STR_FMT(frame.function_name), (DQN_CAST(int)index == walk->size - 1) ? "" : "\n");
|
||||
DN_StackTraceFrame frame = DN_StackTrace_RawFrameToFrame(builder->arena, raw_frame);
|
||||
DN_Str8Builder_AppendF(builder, "%.*s(%zu): %.*s%s", DN_STR_FMT(frame.file_name), frame.line_number, DN_STR_FMT(frame.function_name), (DN_CAST(int)index == walk->size - 1) ? "" : "\n");
|
||||
}
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_StackTrace_WalkStr8CRTNoScratch(uint16_t limit, uint16_t skip)
|
||||
DN_API DN_Str8 DN_StackTrace_WalkStr8CRTNoScratch(uint16_t limit, uint16_t skip)
|
||||
{
|
||||
Dqn_Arena arena = {};
|
||||
arena.flags |= Dqn_ArenaFlag_NoAllocTrack;
|
||||
Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(&arena, limit);
|
||||
DN_Arena arena = {};
|
||||
arena.flags |= DN_ArenaFlags_NoAllocTrack;
|
||||
DN_DEFER { DN_Arena_Deinit(&arena); };
|
||||
|
||||
Dqn_Str8Builder builder = {};
|
||||
DN_Str8Builder builder = {};
|
||||
builder.arena = &arena;
|
||||
Dqn_StackTrace_AddWalkToStr8Builder_(&walk, &builder, skip);
|
||||
Dqn_Str8 result = Dqn_Str8Builder_BuildCRT(&builder);
|
||||
Dqn_Arena_Deinit(&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;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator *it, Dqn_StackTraceWalkResult const *walk)
|
||||
DN_API bool DN_StackTrace_WalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk)
|
||||
{
|
||||
bool result = false;
|
||||
if (!it || !walk || !walk->base_addr || !walk->process)
|
||||
@ -161,55 +266,55 @@ DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator *
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_StackTrace_WalkResultStr8(Dqn_Arena *arena, Dqn_StackTraceWalkResult const *walk, uint16_t skip)
|
||||
DN_API DN_Str8 DN_StackTrace_WalkResultStr8(DN_Arena *arena, DN_StackTraceWalkResult const *walk, uint16_t skip)
|
||||
{
|
||||
Dqn_Str8 result {};
|
||||
DN_Str8 result {};
|
||||
if (!walk || !arena)
|
||||
return result;
|
||||
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena);
|
||||
Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena);
|
||||
Dqn_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip);
|
||||
result = Dqn_Str8Builder_Build(&builder, arena);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(arena);
|
||||
DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena);
|
||||
DN_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip);
|
||||
result = DN_Str8Builder_Build(&builder, arena);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_StackTrace_WalkResultStr8CRT(Dqn_StackTraceWalkResult const *walk, uint16_t skip)
|
||||
DN_API DN_Str8 DN_StackTrace_WalkResultStr8CRT(DN_StackTraceWalkResult const *walk, uint16_t skip)
|
||||
{
|
||||
Dqn_Str8 result {};
|
||||
DN_Str8 result {};
|
||||
if (!walk)
|
||||
return result;
|
||||
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
|
||||
Dqn_Str8Builder builder = Dqn_Str8Builder_Init(tmem.arena);
|
||||
Dqn_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip);
|
||||
result = Dqn_Str8Builder_BuildCRT(&builder);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
|
||||
DN_Str8Builder builder = DN_Str8Builder_Init(tmem.arena);
|
||||
DN_StackTrace_AddWalkToStr8Builder_(walk, &builder, skip);
|
||||
result = DN_Str8Builder_BuildCRT(&builder);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DQN_API Dqn_Slice<Dqn_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)
|
||||
return result;
|
||||
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena);
|
||||
Dqn_StackTraceWalkResult walk = Dqn_StackTrace_Walk(tmem.arena, limit);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(arena);
|
||||
DN_StackTraceWalkResult walk = DN_StackTrace_Walk(tmem.arena, limit);
|
||||
if (!walk.size)
|
||||
return result;
|
||||
|
||||
Dqn_usize slice_index = 0;
|
||||
result = Dqn_Slice_Alloc<Dqn_StackTraceFrame>(arena, walk.size, Dqn_ZeroMem_No);
|
||||
for (Dqn_StackTraceWalkResultIterator it = {}; Dqn_StackTrace_WalkResultIterate(&it, &walk); ) {
|
||||
result.data[slice_index++] = Dqn_StackTrace_RawFrameToFrame(arena, it.raw_frame);
|
||||
DN_USize slice_index = 0;
|
||||
result = DN_Slice_Alloc<DN_StackTraceFrame>(arena, walk.size, DN_ZeroMem_No);
|
||||
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTrace_WalkResultIterate(&it, &walk); ) {
|
||||
result.data[slice_index++] = DN_StackTrace_RawFrameToFrame(arena, it.raw_frame);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame(Dqn_Arena *arena, Dqn_StackTraceRawFrame raw_frame)
|
||||
DN_API DN_StackTraceFrame DN_StackTrace_RawFrameToFrame(DN_Arena *arena, DN_StackTraceRawFrame raw_frame)
|
||||
{
|
||||
#if defined(DQN_OS_WIN32)
|
||||
#if defined(DN_OS_WIN32)
|
||||
// NOTE: Get line+filename /////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: Why does zero-initialising this with `line = {};` cause
|
||||
@ -227,7 +332,7 @@ DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame(Dqn_Arena *arena, Dqn
|
||||
// NOTE: Get function name /////////////////////////////////////////////////////////////////////
|
||||
|
||||
alignas(SYMBOL_INFOW) char buffer[sizeof(SYMBOL_INFOW) + (MAX_SYM_NAME * sizeof(wchar_t))] = {};
|
||||
SYMBOL_INFOW *symbol = DQN_CAST(SYMBOL_INFOW *)buffer;
|
||||
SYMBOL_INFOW *symbol = DN_CAST(SYMBOL_INFOW *)buffer;
|
||||
symbol->SizeOfStruct = sizeof(*symbol);
|
||||
symbol->MaxNameLen = sizeof(buffer) - sizeof(*symbol);
|
||||
|
||||
@ -236,71 +341,71 @@ DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame(Dqn_Arena *arena, Dqn
|
||||
|
||||
// NOTE: Construct result //////////////////////////////////////////////////////////////////////
|
||||
|
||||
Dqn_Str16 file_name16 = Dqn_Str16{line.FileName, Dqn_CStr16_Size(line.FileName)};
|
||||
Dqn_Str16 function_name16 = Dqn_Str16{symbol->Name, symbol->NameLen};
|
||||
DN_Str16 file_name16 = DN_Str16{line.FileName, DN_CStr16_Size(line.FileName)};
|
||||
DN_Str16 function_name16 = DN_Str16{symbol->Name, symbol->NameLen};
|
||||
|
||||
Dqn_StackTraceFrame result = {};
|
||||
DN_StackTraceFrame result = {};
|
||||
result.address = raw_frame.base_addr;
|
||||
result.line_number = line.LineNumber;
|
||||
result.file_name = Dqn_Win_Str16ToStr8(arena, file_name16);
|
||||
result.function_name = Dqn_Win_Str16ToStr8(arena, function_name16);
|
||||
result.file_name = DN_Win_Str16ToStr8(arena, file_name16);
|
||||
result.function_name = DN_Win_Str16ToStr8(arena, function_name16);
|
||||
|
||||
if (!Dqn_Str8_HasData(result.function_name))
|
||||
result.function_name = DQN_STR8("<unknown function>");
|
||||
if (!Dqn_Str8_HasData(result.file_name))
|
||||
result.file_name = DQN_STR8("<unknown file>");
|
||||
if (!DN_Str8_HasData(result.function_name))
|
||||
result.function_name = DN_STR8("<unknown function>");
|
||||
if (!DN_Str8_HasData(result.file_name))
|
||||
result.file_name = DN_STR8("<unknown file>");
|
||||
#else
|
||||
Dqn_StackTraceFrame result = {};
|
||||
DN_StackTraceFrame result = {};
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_StackTrace_Print(uint16_t limit)
|
||||
DN_API void DN_StackTrace_Print(uint16_t limit)
|
||||
{
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
|
||||
Dqn_Slice<Dqn_StackTraceFrame> stack_trace = Dqn_StackTrace_GetFrames(tmem.arena, limit);
|
||||
for (Dqn_StackTraceFrame &frame : stack_trace)
|
||||
Dqn_Print_ErrLnF("%.*s(%I64u): %.*s", DQN_STR_FMT(frame.file_name), frame.line_number, DQN_STR_FMT(frame.function_name));
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
|
||||
DN_Slice<DN_StackTraceFrame> stack_trace = DN_StackTrace_GetFrames(tmem.arena, limit);
|
||||
for (DN_StackTraceFrame &frame : stack_trace)
|
||||
DN_Print_ErrLnF("%.*s(%I64u): %.*s", DN_STR_FMT(frame.file_name), frame.line_number, DN_STR_FMT(frame.function_name));
|
||||
}
|
||||
|
||||
DQN_API void Dqn_StackTrace_ReloadSymbols()
|
||||
DN_API void DN_StackTrace_ReloadSymbols()
|
||||
{
|
||||
#if defined(DQN_OS_WIN32)
|
||||
#if defined(DN_OS_WIN32)
|
||||
HANDLE process = GetCurrentProcess();
|
||||
SymRefreshModuleList(process);
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: [$DEBG] Dqn_Debug /////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DQN_LEAK_TRACKING)
|
||||
DQN_API void Dqn_Debug_TrackAlloc(void *ptr, Dqn_usize size, bool leak_permitted)
|
||||
// NOTE: [$DEBG] DN_Debug /////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DN_LEAK_TRACKING)
|
||||
DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
Dqn_TicketMutex_Begin(&g_dqn_library->alloc_table_mutex);
|
||||
DQN_DEFER {
|
||||
Dqn_TicketMutex_End(&g_dqn_library->alloc_table_mutex);
|
||||
DN_TicketMutex_Begin(&g_dn_core->alloc_table_mutex);
|
||||
DN_DEFER {
|
||||
DN_TicketMutex_End(&g_dn_core->alloc_table_mutex);
|
||||
};
|
||||
|
||||
// NOTE: If the entry was not added, we are reusing a pointer that has been freed.
|
||||
// TODO: Add API for always making the item but exposing a var to indicate if the item was newly created or it
|
||||
// already existed.
|
||||
Dqn_Str8 stack_trace = Dqn_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/);
|
||||
Dqn_DSMap<Dqn_DebugAlloc> *alloc_table = &g_dqn_library->alloc_table;
|
||||
Dqn_DSMapResult<Dqn_DebugAlloc> alloc_entry = Dqn_DSMap_MakeKeyU64(alloc_table, DQN_CAST(uint64_t) ptr);
|
||||
Dqn_DebugAlloc *alloc = alloc_entry.value;
|
||||
DN_Str8 stack_trace = DN_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/);
|
||||
DN_DSMap<DN_DebugAlloc> *alloc_table = &g_dn_core->alloc_table;
|
||||
DN_DSMapResult<DN_DebugAlloc> alloc_entry = DN_DSMap_MakeKeyU64(alloc_table, DN_CAST(uint64_t) ptr);
|
||||
DN_DebugAlloc *alloc = alloc_entry.value;
|
||||
if (alloc_entry.found) {
|
||||
if ((alloc->flags & Dqn_DebugAllocFlag_Freed) == 0) {
|
||||
Dqn_Str8 alloc_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, alloc->size, Dqn_U64ByteSizeType_Auto);
|
||||
Dqn_Str8 new_alloc_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, size, Dqn_U64ByteSizeType_Auto);
|
||||
DQN_HARD_ASSERTF(
|
||||
alloc->flags & Dqn_DebugAllocFlag_Freed,
|
||||
if ((alloc->flags & DN_DebugAllocFlag_Freed) == 0) {
|
||||
DN_Str8 alloc_size = DN_U64ToByteSizeStr8(alloc_table->arena, alloc->size, DN_U64ByteSizeType_Auto);
|
||||
DN_Str8 new_alloc_size = DN_U64ToByteSizeStr8(alloc_table->arena, size, DN_U64ByteSizeType_Auto);
|
||||
DN_HARD_ASSERTF(
|
||||
alloc->flags & DN_DebugAllocFlag_Freed,
|
||||
"This pointer is already in the leak tracker, however it has not "
|
||||
"been freed yet. This same pointer is being ask to be tracked "
|
||||
"twice in the allocation table, e.g. one if its previous free "
|
||||
"calls has not being marked freed with an equivalent call to "
|
||||
"Dqn_Debug_TrackDealloc()\n"
|
||||
"DN_Debug_TrackDealloc()\n"
|
||||
"\n"
|
||||
"The pointer (0x%p) originally allocated %.*s at:\n"
|
||||
"\n"
|
||||
@ -310,45 +415,45 @@ DQN_API void Dqn_Debug_TrackAlloc(void *ptr, Dqn_usize size, bool leak_permitted
|
||||
"\n"
|
||||
"%.*s\n"
|
||||
,
|
||||
ptr, DQN_STR_FMT(alloc_size),
|
||||
DQN_STR_FMT(alloc->stack_trace),
|
||||
DQN_STR_FMT(new_alloc_size),
|
||||
DQN_STR_FMT(stack_trace));
|
||||
ptr, DN_STR_FMT(alloc_size),
|
||||
DN_STR_FMT(alloc->stack_trace),
|
||||
DN_STR_FMT(new_alloc_size),
|
||||
DN_STR_FMT(stack_trace));
|
||||
}
|
||||
|
||||
// NOTE: Pointer was reused, clean up the prior entry
|
||||
free(alloc->stack_trace.data);
|
||||
free(alloc->freed_stack_trace.data);
|
||||
DN_OS_MemRelease(alloc->stack_trace.data, alloc->stack_trace.size);
|
||||
DN_OS_MemRelease(alloc->freed_stack_trace.data, alloc->freed_stack_trace.size);
|
||||
*alloc = {};
|
||||
}
|
||||
|
||||
alloc->ptr = ptr;
|
||||
alloc->size = size;
|
||||
alloc->stack_trace = stack_trace;
|
||||
alloc->flags |= leak_permitted ? Dqn_DebugAllocFlag_LeakPermitted : 0;
|
||||
alloc->flags |= leak_permitted ? DN_DebugAllocFlag_LeakPermitted : 0;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Debug_TrackDealloc(void *ptr)
|
||||
DN_API void DN_Debug_TrackDealloc(void *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
Dqn_TicketMutex_Begin(&g_dqn_library->alloc_table_mutex);
|
||||
DQN_DEFER { Dqn_TicketMutex_End(&g_dqn_library->alloc_table_mutex); };
|
||||
DN_TicketMutex_Begin(&g_dn_core->alloc_table_mutex);
|
||||
DN_DEFER { DN_TicketMutex_End(&g_dn_core->alloc_table_mutex); };
|
||||
|
||||
Dqn_Str8 stack_trace = Dqn_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/);
|
||||
Dqn_DSMap<Dqn_DebugAlloc> *alloc_table = &g_dqn_library->alloc_table;
|
||||
Dqn_DSMapResult<Dqn_DebugAlloc> alloc_entry = Dqn_DSMap_FindKeyU64(alloc_table, DQN_CAST(uintptr_t) ptr);
|
||||
DQN_HARD_ASSERTF(alloc_entry.found,
|
||||
DN_Str8 stack_trace = DN_StackTrace_WalkStr8CRTNoScratch(128, 3 /*skip*/);
|
||||
DN_DSMap<DN_DebugAlloc> *alloc_table = &g_dn_core->alloc_table;
|
||||
DN_DSMapResult<DN_DebugAlloc> alloc_entry = DN_DSMap_FindKeyU64(alloc_table, DN_CAST(uintptr_t) ptr);
|
||||
DN_HARD_ASSERTF(alloc_entry.found,
|
||||
"Allocated pointer can not be removed as it does not exist in the "
|
||||
"allocation table. When this memory was allocated, the pointer was "
|
||||
"not added to the allocation table [ptr=%p]",
|
||||
ptr);
|
||||
|
||||
Dqn_DebugAlloc *alloc = alloc_entry.value;
|
||||
if (alloc->flags & Dqn_DebugAllocFlag_Freed) {
|
||||
Dqn_Str8 freed_size = Dqn_U64ToByteSizeStr8(alloc_table->arena, alloc->freed_size, Dqn_U64ByteSizeType_Auto);
|
||||
DQN_HARD_ASSERTF((alloc->flags & Dqn_DebugAllocFlag_Freed) == 0,
|
||||
DN_DebugAlloc *alloc = alloc_entry.value;
|
||||
if (alloc->flags & DN_DebugAllocFlag_Freed) {
|
||||
DN_Str8 freed_size = DN_U64ToByteSizeStr8(alloc_table->arena, alloc->freed_size, DN_U64ByteSizeType_Auto);
|
||||
DN_HARD_ASSERTF((alloc->flags & DN_DebugAllocFlag_Freed) == 0,
|
||||
"Double free detected, pointer to free was already marked "
|
||||
"as freed. Either the pointer was reallocated but not "
|
||||
"traced, or, the pointer was freed twice.\n"
|
||||
@ -365,40 +470,40 @@ DQN_API void Dqn_Debug_TrackDealloc(void *ptr)
|
||||
"\n"
|
||||
"%.*s\n"
|
||||
,
|
||||
ptr, DQN_STR_FMT(freed_size),
|
||||
DQN_STR_FMT(alloc->stack_trace),
|
||||
DQN_STR_FMT(alloc->freed_stack_trace),
|
||||
DQN_STR_FMT(stack_trace));
|
||||
ptr, DN_STR_FMT(freed_size),
|
||||
DN_STR_FMT(alloc->stack_trace),
|
||||
DN_STR_FMT(alloc->freed_stack_trace),
|
||||
DN_STR_FMT(stack_trace));
|
||||
}
|
||||
|
||||
DQN_ASSERT(!Dqn_Str8_HasData(alloc->freed_stack_trace));
|
||||
alloc->flags |= Dqn_DebugAllocFlag_Freed;
|
||||
DN_ASSERT(!DN_Str8_HasData(alloc->freed_stack_trace));
|
||||
alloc->flags |= DN_DebugAllocFlag_Freed;
|
||||
alloc->freed_stack_trace = stack_trace;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Debug_DumpLeaks()
|
||||
DN_API void DN_Debug_DumpLeaks()
|
||||
{
|
||||
uint64_t leak_count = 0;
|
||||
uint64_t leaked_bytes = 0;
|
||||
for (Dqn_usize index = 1; index < g_dqn_library->alloc_table.occupied; index++) {
|
||||
Dqn_DSMapSlot<Dqn_DebugAlloc> *slot = g_dqn_library->alloc_table.slots + index;
|
||||
Dqn_DebugAlloc *alloc = &slot->value;
|
||||
bool alloc_leaked = (alloc->flags & Dqn_DebugAllocFlag_Freed) == 0;
|
||||
bool leak_permitted = (alloc->flags & Dqn_DebugAllocFlag_LeakPermitted);
|
||||
for (DN_USize index = 1; index < g_dn_core->alloc_table.occupied; index++) {
|
||||
DN_DSMapSlot<DN_DebugAlloc> *slot = g_dn_core->alloc_table.slots + index;
|
||||
DN_DebugAlloc *alloc = &slot->value;
|
||||
bool alloc_leaked = (alloc->flags & DN_DebugAllocFlag_Freed) == 0;
|
||||
bool leak_permitted = (alloc->flags & DN_DebugAllocFlag_LeakPermitted);
|
||||
if (alloc_leaked && !leak_permitted) {
|
||||
leaked_bytes += alloc->size;
|
||||
leak_count++;
|
||||
Dqn_Str8 alloc_size = Dqn_U64ToByteSizeStr8(g_dqn_library->alloc_table.arena, alloc->size, Dqn_U64ByteSizeType_Auto);
|
||||
Dqn_Log_WarningF("Pointer (0x%p) leaked %.*s at:\n"
|
||||
DN_Str8 alloc_size = DN_U64ToByteSizeStr8(g_dn_core->alloc_table.arena, alloc->size, DN_U64ByteSizeType_Auto);
|
||||
DN_Log_WarningF("Pointer (0x%p) leaked %.*s at:\n"
|
||||
"%.*s",
|
||||
alloc->ptr, DQN_STR_FMT(alloc_size),
|
||||
DQN_STR_FMT(alloc->stack_trace));
|
||||
alloc->ptr, DN_STR_FMT(alloc_size),
|
||||
DN_STR_FMT(alloc->stack_trace));
|
||||
}
|
||||
}
|
||||
|
||||
if (leak_count) {
|
||||
Dqn_Str8 leak_size = Dqn_U64ToByteSizeStr8(&g_dqn_library->arena, leaked_bytes, Dqn_U64ByteSizeType_Auto);
|
||||
Dqn_Log_WarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DQN_STR_FMT(leak_size));
|
||||
DN_Str8 leak_size = DN_U64ToByteSizeStr8(&g_dn_core->arena, leaked_bytes, DN_U64ByteSizeType_Auto);
|
||||
DN_Log_WarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_STR_FMT(leak_size));
|
||||
}
|
||||
}
|
||||
#endif // DQN_LEAK_TRACKING
|
||||
#endif // DN_LEAK_TRACKING
|
||||
|
106
dqn_debug.h
106
dqn_debug.h
@ -17,109 +17,109 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [$ASAN] Dqn_Asan -- Helpers to manually poison memory using ASAN
|
||||
// [$STKT] Dqn_StackTrace -- Create stack traces
|
||||
// [$DEBG] Dqn_Debug -- Allocation leak tracking API
|
||||
// [$ASAN] DN_Asan -- Helpers to manually poison memory using ASAN
|
||||
// [$STKT] DN_StackTrace -- Create stack traces
|
||||
// [$DEBG] DN_Debug -- Allocation leak tracking API
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$ASAN] Dqn_Asan //////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_ASAN_POISON)
|
||||
#define DQN_ASAN_POISON 0
|
||||
// NOTE: [$ASAN] DN_Asan //////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_ASAN_POISON)
|
||||
#define DN_ASAN_POISON 0
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_ASAN_VET_POISON)
|
||||
#define DQN_ASAN_VET_POISON 0
|
||||
#if !defined(DN_ASAN_VET_POISON)
|
||||
#define DN_ASAN_VET_POISON 0
|
||||
#endif
|
||||
|
||||
#define DQN_ASAN_POISON_ALIGNMENT 8
|
||||
#define DN_ASAN_POISON_ALIGNMENT 8
|
||||
|
||||
#if !defined(DQN_ASAN_POISON_GUARD_SIZE)
|
||||
#define DQN_ASAN_POISON_GUARD_SIZE 128
|
||||
#if !defined(DN_ASAN_POISON_GUARD_SIZE)
|
||||
#define DN_ASAN_POISON_GUARD_SIZE 128
|
||||
#endif
|
||||
static_assert(Dqn_IsPowerOfTwoAligned(DQN_ASAN_POISON_GUARD_SIZE, DQN_ASAN_POISON_ALIGNMENT),
|
||||
static_assert(DN_IsPowerOfTwoAligned(DN_ASAN_POISON_GUARD_SIZE, DN_ASAN_POISON_ALIGNMENT),
|
||||
"ASAN poison guard size must be a power-of-two and aligned to ASAN's alignment"
|
||||
"requirement (8 bytes)");
|
||||
|
||||
#if DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif
|
||||
|
||||
// NOTE: [$STKT] Dqn_StackTrace ////////////////////////////////////////////////////////////////////
|
||||
struct Dqn_StackTraceFrame
|
||||
// NOTE: [$STKT] DN_StackTrace ////////////////////////////////////////////////////////////////////
|
||||
struct DN_StackTraceFrame
|
||||
{
|
||||
uint64_t address;
|
||||
uint64_t line_number;
|
||||
Dqn_Str8 file_name;
|
||||
Dqn_Str8 function_name;
|
||||
DN_Str8 file_name;
|
||||
DN_Str8 function_name;
|
||||
};
|
||||
|
||||
struct Dqn_StackTraceRawFrame
|
||||
struct DN_StackTraceRawFrame
|
||||
{
|
||||
void *process;
|
||||
uint64_t base_addr;
|
||||
};
|
||||
|
||||
struct Dqn_StackTraceWalkResult
|
||||
struct DN_StackTraceWalkResult
|
||||
{
|
||||
void *process; // [Internal] Windows handle to the process
|
||||
uint64_t *base_addr; // The addresses of the functions in the stack trace
|
||||
uint16_t size; // The number of `base_addr`'s stored from the walk
|
||||
};
|
||||
|
||||
struct Dqn_StackTraceWalkResultIterator
|
||||
struct DN_StackTraceWalkResultIterator
|
||||
{
|
||||
Dqn_StackTraceRawFrame raw_frame;
|
||||
DN_StackTraceRawFrame raw_frame;
|
||||
uint16_t index;
|
||||
};
|
||||
|
||||
// NOTE: [$DEBG] Dqn_Debug /////////////////////////////////////////////////////////////////////////
|
||||
enum Dqn_DebugAllocFlag
|
||||
// NOTE: [$DEBG] DN_Debug /////////////////////////////////////////////////////////////////////////
|
||||
enum DN_DebugAllocFlag
|
||||
{
|
||||
Dqn_DebugAllocFlag_Freed = 1 << 0,
|
||||
Dqn_DebugAllocFlag_LeakPermitted = 1 << 1,
|
||||
DN_DebugAllocFlag_Freed = 1 << 0,
|
||||
DN_DebugAllocFlag_LeakPermitted = 1 << 1,
|
||||
};
|
||||
|
||||
struct Dqn_DebugAlloc
|
||||
struct DN_DebugAlloc
|
||||
{
|
||||
void *ptr; // 8 Pointer to the allocation being tracked
|
||||
Dqn_usize size; // 16 Size of the allocation
|
||||
Dqn_usize freed_size; // 24 Store the size of the allocation when it is freed
|
||||
Dqn_Str8 stack_trace; // 40 Stack trace at the point of allocation
|
||||
Dqn_Str8 freed_stack_trace; // 56 Stack trace of where the allocation was freed
|
||||
uint16_t flags; // 72 Bit flags from `Dqn_DebugAllocFlag`
|
||||
DN_USize size; // 16 Size of the allocation
|
||||
DN_USize freed_size; // 24 Store the size of the allocation when it is freed
|
||||
DN_Str8 stack_trace; // 40 Stack trace at the point of allocation
|
||||
DN_Str8 freed_stack_trace; // 56 Stack trace of where the allocation was freed
|
||||
uint16_t flags; // 72 Bit flags from `DN_DebugAllocFlag`
|
||||
};
|
||||
|
||||
static_assert(sizeof(Dqn_DebugAlloc) == 64 || sizeof(Dqn_DebugAlloc) == 32, // NOTE: 64 bit vs 32 bit pointers respectively
|
||||
static_assert(sizeof(DN_DebugAlloc) == 64 || sizeof(DN_DebugAlloc) == 32, // NOTE: 64 bit vs 32 bit pointers respectively
|
||||
"We aim to keep the allocation record as light as possible as "
|
||||
"memory tracking can get expensive. Enforce that there is no "
|
||||
"unexpected padding.");
|
||||
|
||||
// NOTE: [$ASAN] Dqn_Asan //////////////////////////////////////////////////////////////////////////
|
||||
DQN_API void Dqn_ASAN_PoisonMemoryRegion (void const volatile *ptr, Dqn_usize size);
|
||||
DQN_API void Dqn_ASAN_UnpoisonMemoryRegion (void const volatile *ptr, Dqn_usize size);
|
||||
// NOTE: [$ASAN] DN_Asan //////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_ASAN_PoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
||||
DN_API void DN_ASAN_UnpoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
||||
|
||||
// NOTE: [$STKT] Dqn_StackTrace ////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_StackTraceWalkResult Dqn_StackTrace_Walk (Dqn_Arena *arena, uint16_t limit);
|
||||
DQN_API Dqn_Str8 Dqn_StackTrace_WalkStr8CRT (uint16_t limit, uint16_t skip);
|
||||
DQN_API bool Dqn_StackTrace_WalkResultIterate(Dqn_StackTraceWalkResultIterator *it, Dqn_StackTraceWalkResult const *walk);
|
||||
DQN_API Dqn_Str8 Dqn_StackTrace_WalkResultStr8 (Dqn_Arena *arena, Dqn_StackTraceWalkResult const *walk, uint16_t skip);
|
||||
DQN_API Dqn_Str8 Dqn_StackTrace_WalkResultStr8CRT(Dqn_StackTraceWalkResult const *walk, uint16_t skip);
|
||||
DQN_API Dqn_Slice<Dqn_StackTraceFrame> Dqn_StackTrace_GetFrames (Dqn_Arena *arena, uint16_t limit);
|
||||
DQN_API Dqn_StackTraceFrame Dqn_StackTrace_RawFrameToFrame (Dqn_Arena *arena, Dqn_StackTraceRawFrame raw_frame);
|
||||
DQN_API void Dqn_StackTrace_Print (uint16_t limit);
|
||||
DQN_API void Dqn_StackTrace_ReloadSymbols ();
|
||||
// NOTE: [$STKT] DN_StackTrace ////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_StackTraceWalkResult DN_StackTrace_Walk (DN_Arena *arena, uint16_t limit);
|
||||
DN_API DN_Str8 DN_StackTrace_WalkStr8CRT (uint16_t limit, uint16_t skip);
|
||||
DN_API bool DN_StackTrace_WalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk);
|
||||
DN_API DN_Str8 DN_StackTrace_WalkResultStr8 (DN_Arena *arena, DN_StackTraceWalkResult const *walk, uint16_t skip);
|
||||
DN_API DN_Str8 DN_StackTrace_WalkResultStr8CRT(DN_StackTraceWalkResult const *walk, uint16_t skip);
|
||||
DN_API DN_Slice<DN_StackTraceFrame> DN_StackTrace_GetFrames (DN_Arena *arena, uint16_t limit);
|
||||
DN_API DN_StackTraceFrame DN_StackTrace_RawFrameToFrame (DN_Arena *arena, DN_StackTraceRawFrame raw_frame);
|
||||
DN_API void DN_StackTrace_Print (uint16_t limit);
|
||||
DN_API void DN_StackTrace_ReloadSymbols ();
|
||||
|
||||
// NOTE: [$DEBG] Dqn_Debug /////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DQN_LEAK_TRACKING)
|
||||
DQN_API void Dqn_Debug_TrackAlloc (void *ptr, Dqn_usize size, bool alloc_can_leak);
|
||||
DQN_API void Dqn_Debug_TrackDealloc (void *ptr);
|
||||
DQN_API void Dqn_Debug_DumpLeaks ();
|
||||
// NOTE: [$DEBG] DN_Debug /////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DN_LEAK_TRACKING)
|
||||
DN_API void DN_Debug_TrackAlloc (void *ptr, DN_USize size, bool alloc_can_leak);
|
||||
DN_API void DN_Debug_TrackDealloc (void *ptr);
|
||||
DN_API void DN_Debug_DumpLeaks ();
|
||||
#else
|
||||
#define Dqn_Debug_TrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||
#define Dqn_Debug_TrackDealloc(ptr) do { (void)ptr; } while (0)
|
||||
#define Dqn_Debug_DumpLeaks() do { } while (0)
|
||||
#define DN_Debug_TrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||
#define DN_Debug_TrackDealloc(ptr) do { (void)ptr; } while (0)
|
||||
#define DN_Debug_DumpLeaks() do { } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
609
dqn_docs.cpp
609
dqn_docs.cpp
File diff suppressed because it is too large
Load Diff
@ -15,7 +15,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
#if !defined(DQN_USE_STD_PRINTF) && !defined(DQN_STB_SPRINTF_HEADER_ONLY)
|
||||
#if !defined(DN_USE_STD_PRINTF) && !defined(DN_STB_SPRINTF_HEADER_ONLY)
|
||||
// NOTE: [$STBS] stb_sprintf ///////////////////////////////////////////////////////////////////////
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#ifdef STB_SPRINTF_IMPLEMENTATION
|
||||
@ -1710,4 +1710,4 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
#endif // !defined(DQN_USE_STD_PRINTF) && !defined(DQN_STB_SPRINTF_HEADER_ONLY)
|
||||
#endif // !defined(DN_USE_STD_PRINTF) && !defined(DN_STB_SPRINTF_HEADER_ONLY)
|
||||
|
@ -19,12 +19,12 @@
|
||||
*/
|
||||
|
||||
// NOTE: [$OS_H] OS Headers ////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_OS_WIN32) || defined(DQN_OS_WIN32_USE_PTHREADS)
|
||||
#if !defined(DN_OS_WIN32) || defined(DN_OS_WIN32_USE_PTHREADS)
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#if defined(DQN_OS_UNIX) || defined(DQN_PLATFORM_EMSCRIPTEN)
|
||||
#if defined(DN_OS_UNIX) || defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#include <errno.h> // errno
|
||||
#include <fcntl.h> // O_RDONLY ... etc
|
||||
#include <sys/ioctl.h> // ioctl
|
||||
@ -36,31 +36,31 @@
|
||||
#include <time.h> // clock_gettime, nanosleep
|
||||
#include <unistd.h> // access, gettid, write
|
||||
|
||||
#if defined(DQN_PLATFORM_EMSCRIPTEN)
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#else
|
||||
#include <sys/sendfile.h> // sendfile
|
||||
#include <linux/fs.h> // FICLONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(DQN_PLATFORM_EMSCRIPTEN)
|
||||
#include <emscripten/fetch.h> // emscripten_fetch (for Dqn_OSHttpResponse)
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#include <emscripten/fetch.h> // emscripten_fetch (for DN_OSHttpResponse)
|
||||
#endif
|
||||
|
||||
// NOTE: [$STBS] stb_sprintf ///////////////////////////////////////////////////////////////////////
|
||||
#if defined(DQN_USE_STD_PRINTF)
|
||||
#if defined(DN_USE_STD_PRINTF)
|
||||
#include <stdio.h>
|
||||
#define DQN_SPRINTF(...) sprintf(__VA_ARGS__)
|
||||
#define DQN_SNPRINTF(...) snprintf(__VA_ARGS__)
|
||||
#define DQN_VSPRINTF(...) vsprintf(__VA_ARGS__)
|
||||
#define DQN_VSNPRINTF(...) vsnprintf(__VA_ARGS__)
|
||||
#define DN_SPRINTF(...) sprintf(__VA_ARGS__)
|
||||
#define DN_SNPRINTF(...) snprintf(__VA_ARGS__)
|
||||
#define DN_VSPRINTF(...) vsprintf(__VA_ARGS__)
|
||||
#define DN_VSNPRINTF(...) vsnprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define DQN_SPRINTF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__)
|
||||
#define DQN_SNPRINTF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__)
|
||||
#define DQN_VSPRINTF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
|
||||
#define DQN_VSNPRINTF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__)
|
||||
#define DN_SPRINTF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__)
|
||||
#define DN_SNPRINTF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__)
|
||||
#define DN_VSPRINTF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
|
||||
#define DN_VSNPRINTF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__)
|
||||
|
||||
#if (DQN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)) && defined(DQN_COMPILER_MSVC)
|
||||
#if (DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)) && defined(DN_COMPILER_MSVC)
|
||||
#error The STB implementation of sprintf triggers MSVCs implementation of ASAN. Compiling ASAN with STB sprintf is not supported.
|
||||
|
||||
// NOTE: stb_sprintf assumes c-string literals are 4 byte aligned which is
|
||||
@ -70,7 +70,7 @@
|
||||
//
|
||||
// ==12072==ERROR: AddressSanitizer: global-buffer-overflow on address
|
||||
// READ of size 4 at 0x7ff6f442a0d8 thread T0
|
||||
// #0 0x7ff6f42d3be8 in stbsp_vsprintfcb C:\Home\Code\dqn\dqn_external.cpp:199
|
||||
// #0 0x7ff6f42d3be8 in stbsp_vsprintfcb C:\Home\Code\dn\dn_external.cpp:199
|
||||
|
||||
#define STBSP__ASAN __declspec(no_sanitize_address)
|
||||
#endif
|
||||
@ -290,4 +290,4 @@ STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char c
|
||||
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va);
|
||||
STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period);
|
||||
#endif // STB_SPRINTF_H_INCLUDE
|
||||
#endif // !defined(DQN_USE_STD_PRINTF)
|
||||
#endif // !defined(DN_USE_STD_PRINTF)
|
||||
|
78
dqn_hash.cpp
78
dqn_hash.cpp
@ -18,55 +18,55 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$FNV1] Dqn_FNV1A /////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: [$FNV1] DN_FNV1A /////////////////////////////////////////////////////////////////////////
|
||||
// Default values recommended by: http://isthe.com/chongo/tech/comp/fnv/
|
||||
DQN_API uint32_t Dqn_FNV1A32_Iterate(void const *bytes, Dqn_usize size, uint32_t hash)
|
||||
DN_API uint32_t DN_FNV1A32_Iterate(void const *bytes, DN_USize size, uint32_t hash)
|
||||
{
|
||||
auto buffer = DQN_CAST(uint8_t const *)bytes;
|
||||
for (Dqn_usize i = 0; i < size; i++)
|
||||
auto buffer = DN_CAST(uint8_t const *)bytes;
|
||||
for (DN_USize i = 0; i < size; i++)
|
||||
hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/;
|
||||
return hash;
|
||||
}
|
||||
|
||||
DQN_API uint32_t Dqn_FNV1A32_Hash(void const *bytes, Dqn_usize size)
|
||||
DN_API uint32_t DN_FNV1A32_Hash(void const *bytes, DN_USize size)
|
||||
{
|
||||
uint32_t result = Dqn_FNV1A32_Iterate(bytes, size, DQN_FNV1A32_SEED);
|
||||
uint32_t result = DN_FNV1A32_Iterate(bytes, size, DN_FNV1A32_SEED);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API uint64_t Dqn_FNV1A64_Iterate(void const *bytes, Dqn_usize size, uint64_t hash)
|
||||
DN_API uint64_t DN_FNV1A64_Iterate(void const *bytes, DN_USize size, uint64_t hash)
|
||||
{
|
||||
auto buffer = DQN_CAST(uint8_t const *)bytes;
|
||||
for (Dqn_usize i = 0; i < size; i++)
|
||||
auto buffer = DN_CAST(uint8_t const *)bytes;
|
||||
for (DN_USize i = 0; i < size; i++)
|
||||
hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/;
|
||||
return hash;
|
||||
}
|
||||
|
||||
DQN_API uint64_t Dqn_FNV1A64_Hash(void const *bytes, Dqn_usize size)
|
||||
DN_API uint64_t DN_FNV1A64_Hash(void const *bytes, DN_USize size)
|
||||
{
|
||||
uint64_t result = Dqn_FNV1A64_Iterate(bytes, size, DQN_FNV1A64_SEED);
|
||||
uint64_t result = DN_FNV1A64_Iterate(bytes, size, DN_FNV1A64_SEED);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: [$MMUR] Dqn_MurmurHash3 ///////////////////////////////////////////////////////////////////
|
||||
#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL)
|
||||
#define DQN_MMH3_ROTL32(x, y) _rotl(x, y)
|
||||
#define DQN_MMH3_ROTL64(x, y) _rotl64(x, y)
|
||||
// NOTE: [$MMUR] DN_MurmurHash3 ///////////////////////////////////////////////////////////////////
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
#define DN_MMH3_ROTL32(x, y) _rotl(x, y)
|
||||
#define DN_MMH3_ROTL64(x, y) _rotl64(x, y)
|
||||
#else
|
||||
#define DQN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y)))
|
||||
#define DQN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y)))
|
||||
#define DN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y)))
|
||||
#define DN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y)))
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Block read - if your platform needs to do endian-swapping or can only
|
||||
// handle aligned reads, do the conversion here
|
||||
|
||||
DQN_FORCE_INLINE uint32_t Dqn_MurmurHash3_GetBlock32(uint32_t const *p, int i)
|
||||
DN_FORCE_INLINE uint32_t DN_MurmurHash3_GetBlock32(uint32_t const *p, int i)
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
|
||||
DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_GetBlock64(uint64_t const *p, int i)
|
||||
DN_FORCE_INLINE uint64_t DN_MurmurHash3_GetBlock64(uint64_t const *p, int i)
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
@ -74,7 +74,7 @@ DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_GetBlock64(uint64_t const *p, int i)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finalization mix - force all bits of a hash block to avalanche
|
||||
|
||||
DQN_FORCE_INLINE uint32_t Dqn_MurmurHash3_FMix32(uint32_t h)
|
||||
DN_FORCE_INLINE uint32_t DN_MurmurHash3_FMix32(uint32_t h)
|
||||
{
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
@ -84,7 +84,7 @@ DQN_FORCE_INLINE uint32_t Dqn_MurmurHash3_FMix32(uint32_t h)
|
||||
return h;
|
||||
}
|
||||
|
||||
DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_FMix64(uint64_t k)
|
||||
DN_FORCE_INLINE uint64_t DN_MurmurHash3_FMix64(uint64_t k)
|
||||
{
|
||||
k ^= k >> 33;
|
||||
k *= 0xff51afd7ed558ccd;
|
||||
@ -94,7 +94,7 @@ DQN_FORCE_INLINE uint64_t Dqn_MurmurHash3_FMix64(uint64_t k)
|
||||
return k;
|
||||
}
|
||||
|
||||
DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed)
|
||||
DN_API uint32_t DN_MurmurHash3_x86U32(void const *key, int len, uint32_t seed)
|
||||
{
|
||||
const uint8_t *data = (const uint8_t *)key;
|
||||
const int nblocks = len / 4;
|
||||
@ -111,14 +111,14 @@ DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed)
|
||||
|
||||
for (int i = -nblocks; i; i++)
|
||||
{
|
||||
uint32_t k1 = Dqn_MurmurHash3_GetBlock32(blocks, i);
|
||||
uint32_t k1 = DN_MurmurHash3_GetBlock32(blocks, i);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = DQN_MMH3_ROTL32(k1, 15);
|
||||
k1 = DN_MMH3_ROTL32(k1, 15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = DQN_MMH3_ROTL32(h1, 13);
|
||||
h1 = DN_MMH3_ROTL32(h1, 13);
|
||||
h1 = h1 * 5 + 0xe6546b64;
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed)
|
||||
case 1:
|
||||
k1 ^= tail[0];
|
||||
k1 *= c1;
|
||||
k1 = DQN_MMH3_ROTL32(k1, 15);
|
||||
k1 = DN_MMH3_ROTL32(k1, 15);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
};
|
||||
@ -148,12 +148,12 @@ DQN_API uint32_t Dqn_MurmurHash3_x86U32(void const *key, int len, uint32_t seed)
|
||||
|
||||
h1 ^= len;
|
||||
|
||||
h1 = Dqn_MurmurHash3_FMix32(h1);
|
||||
h1 = DN_MurmurHash3_FMix32(h1);
|
||||
|
||||
return h1;
|
||||
}
|
||||
|
||||
DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32_t seed)
|
||||
DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128(void const *key, int len, uint32_t seed)
|
||||
{
|
||||
const uint8_t *data = (const uint8_t *)key;
|
||||
const int nblocks = len / 16;
|
||||
@ -171,24 +171,24 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32
|
||||
|
||||
for (int i = 0; i < nblocks; i++)
|
||||
{
|
||||
uint64_t k1 = Dqn_MurmurHash3_GetBlock64(blocks, i * 2 + 0);
|
||||
uint64_t k2 = Dqn_MurmurHash3_GetBlock64(blocks, i * 2 + 1);
|
||||
uint64_t k1 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 0);
|
||||
uint64_t k2 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 1);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = DQN_MMH3_ROTL64(k1, 31);
|
||||
k1 = DN_MMH3_ROTL64(k1, 31);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
|
||||
h1 = DQN_MMH3_ROTL64(h1, 27);
|
||||
h1 = DN_MMH3_ROTL64(h1, 27);
|
||||
h1 += h2;
|
||||
h1 = h1 * 5 + 0x52dce729;
|
||||
|
||||
k2 *= c2;
|
||||
k2 = DQN_MMH3_ROTL64(k2, 33);
|
||||
k2 = DN_MMH3_ROTL64(k2, 33);
|
||||
k2 *= c1;
|
||||
h2 ^= k2;
|
||||
|
||||
h2 = DQN_MMH3_ROTL64(h2, 31);
|
||||
h2 = DN_MMH3_ROTL64(h2, 31);
|
||||
h2 += h1;
|
||||
h2 = h2 * 5 + 0x38495ab5;
|
||||
}
|
||||
@ -218,7 +218,7 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32
|
||||
case 9:
|
||||
k2 ^= ((uint64_t)tail[8]) << 0;
|
||||
k2 *= c2;
|
||||
k2 = DQN_MMH3_ROTL64(k2, 33);
|
||||
k2 = DN_MMH3_ROTL64(k2, 33);
|
||||
k2 *= c1;
|
||||
h2 ^= k2;
|
||||
|
||||
@ -239,7 +239,7 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32
|
||||
case 1:
|
||||
k1 ^= ((uint64_t)tail[0]) << 0;
|
||||
k1 *= c1;
|
||||
k1 = DQN_MMH3_ROTL64(k1, 31);
|
||||
k1 = DN_MMH3_ROTL64(k1, 31);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
};
|
||||
@ -253,13 +253,13 @@ DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128(void const *key, int len, uint32
|
||||
h1 += h2;
|
||||
h2 += h1;
|
||||
|
||||
h1 = Dqn_MurmurHash3_FMix64(h1);
|
||||
h2 = Dqn_MurmurHash3_FMix64(h2);
|
||||
h1 = DN_MurmurHash3_FMix64(h1);
|
||||
h2 = DN_MurmurHash3_FMix64(h2);
|
||||
|
||||
h1 += h2;
|
||||
h2 += h1;
|
||||
|
||||
Dqn_MurmurHash3 result = {};
|
||||
DN_MurmurHash3 result = {};
|
||||
result.e[0] = h1;
|
||||
result.e[1] = h2;
|
||||
return result;
|
||||
|
38
dqn_hash.h
38
dqn_hash.h
@ -17,33 +17,33 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [$FNV1] Dqn_FNV1A -- Hash(x) -> 32/64bit via FNV1a
|
||||
// [$MMUR] Dqn_MurmurHash3 -- Hash(x) -> 32/128bit via MurmurHash3
|
||||
// [$FNV1] DN_FNV1A -- Hash(x) -> 32/64bit via FNV1a
|
||||
// [$MMUR] DN_MurmurHash3 -- Hash(x) -> 32/128bit via MurmurHash3
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$FNV1] Dqn_FNV1A /////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_FNV1A32_SEED)
|
||||
#define DQN_FNV1A32_SEED 2166136261U
|
||||
// NOTE: [$FNV1] DN_FNV1A /////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_FNV1A32_SEED)
|
||||
#define DN_FNV1A32_SEED 2166136261U
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_FNV1A64_SEED)
|
||||
#define DQN_FNV1A64_SEED 14695981039346656037ULL
|
||||
#if !defined(DN_FNV1A64_SEED)
|
||||
#define DN_FNV1A64_SEED 14695981039346656037ULL
|
||||
#endif
|
||||
|
||||
// NOTE: [$MMUR] Dqn_MurmurHash3 ///////////////////////////////////////////////////////////////////
|
||||
struct Dqn_MurmurHash3 { uint64_t e[2]; };
|
||||
// NOTE: [$MMUR] DN_MurmurHash3 ///////////////////////////////////////////////////////////////////
|
||||
struct DN_MurmurHash3 { uint64_t e[2]; };
|
||||
|
||||
// NOTE: [$FNV1] Dqn_FNV1A /////////////////////////////////////////////////////////////////////////
|
||||
DQN_API uint32_t Dqn_FNV1A32_Hash (void const *bytes, Dqn_usize size);
|
||||
DQN_API uint64_t Dqn_FNV1A64_Hash (void const *bytes, Dqn_usize size);
|
||||
DQN_API uint32_t Dqn_FNV1A32_Iterate (void const *bytes, Dqn_usize size, uint32_t hash);
|
||||
DQN_API uint64_t Dqn_FNV1A64_Iterate (void const *bytes, Dqn_usize size, uint64_t hash);
|
||||
// NOTE: [$FNV1] DN_FNV1A /////////////////////////////////////////////////////////////////////////
|
||||
DN_API uint32_t DN_FNV1A32_Hash (void const *bytes, DN_USize size);
|
||||
DN_API uint64_t DN_FNV1A64_Hash (void const *bytes, DN_USize size);
|
||||
DN_API uint32_t DN_FNV1A32_Iterate (void const *bytes, DN_USize size, uint32_t hash);
|
||||
DN_API uint64_t DN_FNV1A64_Iterate (void const *bytes, DN_USize size, uint64_t hash);
|
||||
|
||||
// NOTE: [$MMUR] Dqn_MurmurHash3 ///////////////////////////////////////////////////////////////////
|
||||
DQN_API uint32_t Dqn_MurmurHash3_x86U32 (void const *key, int len, uint32_t seed);
|
||||
DQN_API Dqn_MurmurHash3 Dqn_MurmurHash3_x64U128 (void const *key, int len, uint32_t seed);
|
||||
#define Dqn_MurmurHash3_x64U128AsU64(key, len, seed) (Dqn_MurmurHash3_x64U128(key, len, seed).e[0])
|
||||
#define Dqn_MurmurHash3_x64U128AsU32(key, len, seed) (DQN_CAST(uint32_t)Dqn_MurmurHash3_x64U128(key, len, seed).e[0])
|
||||
// NOTE: [$MMUR] DN_MurmurHash3 ///////////////////////////////////////////////////////////////////
|
||||
DN_API uint32_t DN_MurmurHash3_x86U32 (void const *key, int len, uint32_t seed);
|
||||
DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128 (void const *key, int len, uint32_t seed);
|
||||
#define DN_MurmurHash3_x64U128AsU64(key, len, seed) (DN_MurmurHash3_x64U128(key, len, seed).e[0])
|
||||
#define DN_MurmurHash3_x64U128AsU32(key, len, seed) (DN_CAST(uint32_t)DN_MurmurHash3_x64U128(key, len, seed).e[0])
|
||||
|
||||
|
1223
dqn_helpers.cpp
1223
dqn_helpers.cpp
File diff suppressed because it is too large
Load Diff
659
dqn_helpers.h
659
dqn_helpers.h
@ -17,55 +17,55 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [$PCG3] Dqn_PCG32 -- -- RNG from the PCG family
|
||||
// [$JSON] Dqn_JSONBuilder -- DQN_JSON_BUILDER -- Construct json output
|
||||
// [$BHEX] Dqn_Bin -- DQN_BIN -- Binary <-> hex helpers
|
||||
// [$BSEA] Dqn_BinarySearch -- -- Binary search
|
||||
// [$BITS] Dqn_Bit -- -- Bitset manipulation
|
||||
// [$SAFE] Dqn_Safe -- -- Safe arithmetic, casts, asserts
|
||||
// [$PCG3] DN_PCG32 -- -- RNG from the PCG family
|
||||
// [$JSON] DN_JSONBuilder -- DN_JSON_BUILDER -- Construct json output
|
||||
// [$BHEX] DN_Bin -- DN_BIN -- Binary <-> hex helpers
|
||||
// [$BSEA] DN_BinarySearch -- -- Binary search
|
||||
// [$BITS] DN_Bit -- -- Bitset manipulation
|
||||
// [$SAFE] DN_Safe -- -- Safe arithmetic, casts, asserts
|
||||
// [$MISC] Misc -- -- Uncategorised helper functions
|
||||
// [$DLIB] Dqn_Library -- -- Globally shared runtime data for this library
|
||||
// [$PROF] Dqn_Profiler -- DQN_PROFILER -- Profiler that measures using a timestamp counter
|
||||
// [$DLIB] DN_Library -- -- Globally shared runtime data for this library
|
||||
// [$PROF] DN_Profiler -- DN_PROFILER -- Profiler that measures using a timestamp counter
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$PCGX] Dqn_PCG32 /////////////////////////////////////////////////////////////////////////
|
||||
struct Dqn_PCG32 { uint64_t state; };
|
||||
// NOTE: [$PCGX] DN_PCG32 /////////////////////////////////////////////////////////////////////////
|
||||
struct DN_PCG32 { uint64_t state; };
|
||||
|
||||
#if !defined(DQN_NO_JSON_BUILDER)
|
||||
// NOTE: [$JSON] Dqn_JSONBuilder ///////////////////////////////////////////////////////////////////
|
||||
enum Dqn_JSONBuilderItem
|
||||
#if !defined(DN_NO_JSON_BUILDER)
|
||||
// NOTE: [$JSON] DN_JSONBuilder ///////////////////////////////////////////////////////////////////
|
||||
enum DN_JSONBuilderItem
|
||||
{
|
||||
Dqn_JSONBuilderItem_Empty,
|
||||
Dqn_JSONBuilderItem_OpenContainer,
|
||||
Dqn_JSONBuilderItem_CloseContainer,
|
||||
Dqn_JSONBuilderItem_KeyValue,
|
||||
DN_JSONBuilderItem_Empty,
|
||||
DN_JSONBuilderItem_OpenContainer,
|
||||
DN_JSONBuilderItem_CloseContainer,
|
||||
DN_JSONBuilderItem_KeyValue,
|
||||
};
|
||||
|
||||
struct Dqn_JSONBuilder
|
||||
struct DN_JSONBuilder
|
||||
{
|
||||
bool use_stdout; // When set, ignore the string builder and dump immediately to stdout
|
||||
Dqn_Str8Builder string_builder; // (Internal)
|
||||
DN_Str8Builder string_builder; // (Internal)
|
||||
int indent_level; // (Internal)
|
||||
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>
|
||||
using Dqn_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
|
||||
using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
|
||||
|
||||
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 is set to the index where the match should be inserted/exist, if
|
||||
// it were in the array
|
||||
Dqn_BinarySearchType_Match,
|
||||
DN_BinarySearchType_Match,
|
||||
|
||||
// Index of the first element in the array that is `element >= find`. If no such
|
||||
// item is found or the array is empty, then, the index is set to the array
|
||||
@ -73,10 +73,10 @@ enum Dqn_BinarySearchType
|
||||
//
|
||||
// For example:
|
||||
// int array[] = {0, 1, 2, 3, 4, 5};
|
||||
// Dqn_BinarySearchResult result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4, Dqn_BinarySearchType_LowerBound);
|
||||
// DN_BinarySearchResult result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4, DN_BinarySearchType_LowerBound);
|
||||
// printf("%zu\n", result.index); // Prints index '4'
|
||||
|
||||
Dqn_BinarySearchType_LowerBound,
|
||||
DN_BinarySearchType_LowerBound,
|
||||
|
||||
// Index of the first element in the array that is `element > find`. If no such
|
||||
// item is found or the array is empty, then, the index is set to the array
|
||||
@ -84,79 +84,80 @@ enum Dqn_BinarySearchType
|
||||
//
|
||||
// For example:
|
||||
// int array[] = {0, 1, 2, 3, 4, 5};
|
||||
// Dqn_BinarySearchResult result = Dqn_BinarySearch(array, DQN_ARRAY_UCOUNT(array), 4, Dqn_BinarySearchType_UpperBound);
|
||||
// DN_BinarySearchResult result = DN_BinarySearch(array, DN_ARRAY_UCOUNT(array), 4, DN_BinarySearchType_UpperBound);
|
||||
// printf("%zu\n", result.index); // Prints index '5'
|
||||
|
||||
Dqn_BinarySearchType_UpperBound,
|
||||
DN_BinarySearchType_UpperBound,
|
||||
};
|
||||
|
||||
struct Dqn_BinarySearchResult
|
||||
struct DN_BinarySearchResult
|
||||
{
|
||||
bool found;
|
||||
Dqn_usize index;
|
||||
DN_USize index;
|
||||
};
|
||||
|
||||
template <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 //////////////////////////////////////////////////////////////////////////////
|
||||
struct Dqn_U64Str8
|
||||
struct DN_U64Str8
|
||||
{
|
||||
char data[27+1]; // NOTE(dqn): 27 is the maximum size of uint64_t including a separator
|
||||
char data[27+1]; // NOTE(dn): 27 is the maximum size of uint64_t including a separator
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
enum Dqn_U64ByteSizeType
|
||||
enum DN_U64ByteSizeType
|
||||
{
|
||||
Dqn_U64ByteSizeType_B,
|
||||
Dqn_U64ByteSizeType_KiB,
|
||||
Dqn_U64ByteSizeType_MiB,
|
||||
Dqn_U64ByteSizeType_GiB,
|
||||
Dqn_U64ByteSizeType_TiB,
|
||||
Dqn_U64ByteSizeType_Count,
|
||||
Dqn_U64ByteSizeType_Auto,
|
||||
DN_U64ByteSizeType_B,
|
||||
DN_U64ByteSizeType_KiB,
|
||||
DN_U64ByteSizeType_MiB,
|
||||
DN_U64ByteSizeType_GiB,
|
||||
DN_U64ByteSizeType_TiB,
|
||||
DN_U64ByteSizeType_Count,
|
||||
DN_U64ByteSizeType_Auto,
|
||||
};
|
||||
|
||||
struct Dqn_U64ByteSize
|
||||
struct DN_U64ByteSize
|
||||
{
|
||||
Dqn_U64ByteSizeType type;
|
||||
Dqn_Str8 suffix; // "KiB", "MiB", "GiB" .. e.t.c
|
||||
Dqn_f64 bytes;
|
||||
DN_U64ByteSizeType type;
|
||||
DN_Str8 suffix; // "KiB", "MiB", "GiB" .. e.t.c
|
||||
DN_F64 bytes;
|
||||
};
|
||||
|
||||
typedef uint32_t Dqn_U64AgeUnit;
|
||||
enum Dqn_U64AgeUnit_
|
||||
typedef uint32_t DN_U64AgeUnit;
|
||||
enum DN_U64AgeUnit_
|
||||
{
|
||||
Dqn_U64AgeUnit_Sec = 1 << 0,
|
||||
Dqn_U64AgeUnit_Min = 1 << 1,
|
||||
Dqn_U64AgeUnit_Hr = 1 << 2,
|
||||
Dqn_U64AgeUnit_Day = 1 << 3,
|
||||
Dqn_U64AgeUnit_Week = 1 << 4,
|
||||
Dqn_U64AgeUnit_Year = 1 << 5,
|
||||
Dqn_U64AgeUnit_HMS = Dqn_U64AgeUnit_Sec | Dqn_U64AgeUnit_Min | Dqn_U64AgeUnit_Hr,
|
||||
Dqn_U64AgeUnit_All = Dqn_U64AgeUnit_HMS | Dqn_U64AgeUnit_Day | Dqn_U64AgeUnit_Week | Dqn_U64AgeUnit_Year,
|
||||
DN_U64AgeUnit_Sec = 1 << 0,
|
||||
DN_U64AgeUnit_Min = 1 << 1,
|
||||
DN_U64AgeUnit_Hr = 1 << 2,
|
||||
DN_U64AgeUnit_Day = 1 << 3,
|
||||
DN_U64AgeUnit_Week = 1 << 4,
|
||||
DN_U64AgeUnit_Year = 1 << 5,
|
||||
DN_U64AgeUnit_HMS = DN_U64AgeUnit_Sec | DN_U64AgeUnit_Min | DN_U64AgeUnit_Hr,
|
||||
DN_U64AgeUnit_All = DN_U64AgeUnit_HMS | DN_U64AgeUnit_Day | DN_U64AgeUnit_Week | DN_U64AgeUnit_Year,
|
||||
};
|
||||
|
||||
struct Dqn_U64HexStr8
|
||||
struct DN_U64HexStr8
|
||||
{
|
||||
char data[2 /*0x*/ + 16 /*hex*/ + 1 /*null-terminator*/];
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
enum Dqn_U64HexStr8Flags
|
||||
typedef uint32_t DN_U64HexStr8Flags;
|
||||
enum DN_U64HexStr8Flags_
|
||||
{
|
||||
Dqn_HexU64Str8Flags_Nil = 0,
|
||||
Dqn_HexU64Str8Flags_0xPrefix = 1 << 0, /// Add the '0x' prefix from the string
|
||||
Dqn_HexU64Str8Flags_UppercaseHex = 1 << 1, /// Use uppercase ascii characters for hex
|
||||
DN_HexU64Str8Flags_Nil = 0,
|
||||
DN_HexU64Str8Flags_0xPrefix = 1 << 0, /// Add the '0x' prefix from the string
|
||||
DN_HexU64Str8Flags_UppercaseHex = 1 << 1, /// Use uppercase ascii characters for hex
|
||||
};
|
||||
|
||||
#if !defined(DQN_NO_PROFILER)
|
||||
// NOTE: [$PROF] Dqn_Profiler //////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_PROFILER_ANCHOR_BUFFER_SIZE)
|
||||
#define DQN_PROFILER_ANCHOR_BUFFER_SIZE 128
|
||||
#if !defined(DN_NO_PROFILER)
|
||||
// NOTE: [$PROF] DN_Profiler //////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_PROFILER_ANCHOR_BUFFER_SIZE)
|
||||
#define DN_PROFILER_ANCHOR_BUFFER_SIZE 256
|
||||
#endif
|
||||
|
||||
struct Dqn_ProfilerAnchor
|
||||
struct DN_ProfilerAnchor
|
||||
{
|
||||
// Inclusive refers to the time spent to complete the function call
|
||||
// including all children functions.
|
||||
@ -168,10 +169,10 @@ struct Dqn_ProfilerAnchor
|
||||
uint64_t tsc_inclusive;
|
||||
uint64_t tsc_exclusive;
|
||||
uint16_t hit_count;
|
||||
Dqn_Str8 name;
|
||||
DN_Str8 name;
|
||||
};
|
||||
|
||||
struct Dqn_ProfilerZone
|
||||
struct DN_ProfilerZone
|
||||
{
|
||||
uint16_t anchor_index;
|
||||
uint64_t begin_tsc;
|
||||
@ -180,332 +181,344 @@ struct Dqn_ProfilerZone
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
struct Dqn_ProfilerZoneScope
|
||||
struct DN_ProfilerZoneScope
|
||||
{
|
||||
Dqn_ProfilerZoneScope(Dqn_Str8 name, uint16_t anchor_index);
|
||||
~Dqn_ProfilerZoneScope();
|
||||
Dqn_ProfilerZone zone;
|
||||
DN_ProfilerZoneScope(DN_Str8 name, uint16_t anchor_index);
|
||||
~DN_ProfilerZoneScope();
|
||||
DN_ProfilerZone zone;
|
||||
};
|
||||
#define Dqn_Profiler_ZoneScopeAtIndex(name, anchor_index) auto DQN_UNIQUE_NAME(profile_zone_) = Dqn_ProfilerZoneScope(DQN_STR8(name), anchor_index)
|
||||
#define Dqn_Profiler_ZoneScope(name) Dqn_Profiler_ZoneScopeAtIndex(name, __COUNTER__ + 1)
|
||||
#define DN_Profiler_ZoneScopeAtIndex(name, anchor_index) auto DN_UNIQUE_NAME(profile_zone_) = DN_ProfilerZoneScope(DN_STR8(name), anchor_index)
|
||||
#define DN_Profiler_ZoneScope(name) DN_Profiler_ZoneScopeAtIndex(name, __COUNTER__ + 1)
|
||||
#endif
|
||||
|
||||
#define Dqn_Profiler_ZoneBlockIndex(name, index) \
|
||||
for (Dqn_ProfilerZone DQN_UNIQUE_NAME(profile_zone__) = Dqn_Profiler_BeginZoneAtIndex(name, index), DQN_UNIQUE_NAME(dummy__) = {}; \
|
||||
DQN_UNIQUE_NAME(dummy__).begin_tsc == 0; \
|
||||
Dqn_Profiler_EndZone(DQN_UNIQUE_NAME(profile_zone__)), DQN_UNIQUE_NAME(dummy__).begin_tsc = 1)
|
||||
#define DN_Profiler_ZoneBlockIndex(name, index) \
|
||||
for (DN_ProfilerZone DN_UNIQUE_NAME(profile_zone__) = DN_Profiler_BeginZoneAtIndex(name, index), DN_UNIQUE_NAME(dummy__) = {}; \
|
||||
DN_UNIQUE_NAME(dummy__).begin_tsc == 0; \
|
||||
DN_Profiler_EndZone(DN_UNIQUE_NAME(profile_zone__)), DN_UNIQUE_NAME(dummy__).begin_tsc = 1)
|
||||
|
||||
#define Dqn_Profiler_ZoneBlock(name) Dqn_Profiler_ZoneBlockIndex(DQN_STR8(name), __COUNTER__ + 1)
|
||||
#define DN_Profiler_ZoneBlock(name) DN_Profiler_ZoneBlockIndex(DN_STR8(name), __COUNTER__ + 1)
|
||||
|
||||
enum Dqn_ProfilerAnchorBuffer
|
||||
enum DN_ProfilerAnchorBuffer
|
||||
{
|
||||
Dqn_ProfilerAnchorBuffer_Back,
|
||||
Dqn_ProfilerAnchorBuffer_Front,
|
||||
DN_ProfilerAnchorBuffer_Back,
|
||||
DN_ProfilerAnchorBuffer_Front,
|
||||
};
|
||||
|
||||
struct Dqn_Profiler
|
||||
struct DN_Profiler
|
||||
{
|
||||
Dqn_ProfilerAnchor anchors[2][DQN_PROFILER_ANCHOR_BUFFER_SIZE];
|
||||
DN_ProfilerAnchor anchors[2][DN_PROFILER_ANCHOR_BUFFER_SIZE];
|
||||
uint8_t active_anchor_buffer;
|
||||
uint16_t parent_zone;
|
||||
};
|
||||
#endif // !defined(DQN_NO_PROFILER)
|
||||
#endif // !defined(DN_NO_PROFILER)
|
||||
|
||||
// NOTE: [$JOBQ] Dqn_JobQueue ///////////////////////////////////////////////////////////////////////
|
||||
typedef void (Dqn_JobQueueFunc)(Dqn_OSThread *thread, void *user_context);
|
||||
struct Dqn_Job
|
||||
// NOTE: [$JOBQ] DN_JobQueue ///////////////////////////////////////////////////////////////////////
|
||||
typedef void (DN_JobQueueFunc)(DN_OSThread *thread, void *user_context);
|
||||
struct DN_Job
|
||||
{
|
||||
Dqn_JobQueueFunc *func; // The function to invoke for the job
|
||||
DN_JobQueueFunc *func; // The function to invoke for the job
|
||||
void *user_context; // Pointer user can set to use in their `job_func`
|
||||
uint64_t elapsed_tsc;
|
||||
uint16_t user_tag; // Arbitrary value the user can set to identiy the type of `user_context` this job has
|
||||
bool add_to_completion_queue; // When true, on job completion, job must be dequeued from the completion queue via `GetFinishedJobs`
|
||||
};
|
||||
|
||||
#if !defined(DQN_JOB_QUEUE_SPMC_SIZE)
|
||||
#define DQN_JOB_QUEUE_SPMC_SIZE 128
|
||||
#if !defined(DN_JOB_QUEUE_SPMC_SIZE)
|
||||
#define DN_JOB_QUEUE_SPMC_SIZE 128
|
||||
#endif
|
||||
|
||||
struct Dqn_JobQueueSPMC
|
||||
struct DN_JobQueueSPMC
|
||||
{
|
||||
Dqn_OSMutex mutex;
|
||||
Dqn_OSSemaphore thread_wait_for_job_semaphore;
|
||||
Dqn_OSSemaphore wait_for_completion_semaphore;
|
||||
uint32_t threads_waiting_for_completion;
|
||||
DN_OSMutex mutex;
|
||||
DN_OSSemaphore thread_wait_for_job_semaphore;
|
||||
DN_OSSemaphore wait_for_completion_semaphore;
|
||||
DN_U32 threads_waiting_for_completion;
|
||||
|
||||
Dqn_Job jobs[DQN_JOB_QUEUE_SPMC_SIZE];
|
||||
Dqn_b32 quit;
|
||||
uint32_t quit_exit_code;
|
||||
uint32_t volatile read_index;
|
||||
uint32_t volatile finish_index;
|
||||
uint32_t volatile write_index;
|
||||
DN_Job jobs[DN_JOB_QUEUE_SPMC_SIZE];
|
||||
DN_B32 quit;
|
||||
DN_U32 quit_exit_code;
|
||||
DN_U32 volatile read_index;
|
||||
DN_U32 volatile finish_index;
|
||||
DN_U32 volatile write_index;
|
||||
|
||||
Dqn_OSSemaphore complete_queue_write_semaphore;
|
||||
Dqn_Job complete_queue[DQN_JOB_QUEUE_SPMC_SIZE];
|
||||
uint32_t volatile complete_read_index;
|
||||
uint32_t volatile complete_write_index;
|
||||
DN_OSSemaphore complete_queue_write_semaphore;
|
||||
DN_Job complete_queue[DN_JOB_QUEUE_SPMC_SIZE];
|
||||
DN_U32 volatile complete_read_index;
|
||||
DN_U32 volatile complete_write_index;
|
||||
};
|
||||
|
||||
// NOTE: [$DLIB] Dqn_Library ///////////////////////////////////////////////////////////////////////
|
||||
// NOTE: [$CORE] DN_Core //////////////////////////////////////////////////////////////////////////
|
||||
// Book-keeping data for the library and allow customisation of certain features
|
||||
// provided.
|
||||
struct Dqn_Library
|
||||
struct DN_Core
|
||||
{
|
||||
bool lib_init; // True if the library has been initialised via `Dqn_Library_Init`
|
||||
Dqn_TicketMutex lib_mutex;
|
||||
Dqn_Str8 exe_dir; // The directory of the current executable
|
||||
Dqn_Arena arena;
|
||||
Dqn_ChunkPool pool; // Uses 'arena' for malloc-like allocations
|
||||
Dqn_ArenaCatalog arena_catalog;
|
||||
bool init; // True if the library has been initialised via `DN_Library_Init`
|
||||
DN_OSMutex init_mutex;
|
||||
DN_Str8 exe_dir; // The directory of the current executable
|
||||
DN_Arena arena;
|
||||
DN_Pool pool;
|
||||
DN_ArenaCatalog arena_catalog;
|
||||
bool slow_verification_checks; // Enable expensive library verification checks
|
||||
Dqn_CPUReport cpu_report;
|
||||
Dqn_TLS tls; // Thread local storage state for the main thread.
|
||||
DN_CPUReport cpu_report;
|
||||
DN_TLS tls; // Thread local storage state for the main thread.
|
||||
|
||||
// NOTE: Logging ///////////////////////////////////////////////////////////////////////////////
|
||||
Dqn_LogProc * log_callback; // Set this pointer to override the logging routine
|
||||
void * log_user_data;
|
||||
DN_LogProc * log_callback; // Set this pointer to override the logging routine
|
||||
void * log_user_data; // User pointer passed into 'log_callback'
|
||||
bool log_to_file; // Output logs to file as well as standard out
|
||||
Dqn_OSFile log_file; // TODO(dqn): Hmmm, how should we do this... ?
|
||||
Dqn_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time
|
||||
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
|
||||
DN_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time
|
||||
bool log_no_colour; // Disable colours in the logging output
|
||||
|
||||
// NOTE: Memory ////////////////////////////////////////////////////////////////////////////////
|
||||
// Total OS mem allocs in lifetime of program (e.g. malloc, VirtualAlloc, HeapAlloc ...). This
|
||||
// only includes allocations routed through the library such as the growing nature of arenas or
|
||||
// using the memory allocation routines in the library like DN_OS_MemCommit and so forth.
|
||||
uint64_t mem_allocs_total;
|
||||
uint64_t mem_allocs_frame; // Total OS mem allocs since the last 'DN_Core_FrameBegin' was invoked
|
||||
|
||||
// NOTE: Leak Tracing //////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DQN_LEAK_TRACKING)
|
||||
Dqn_DSMap<Dqn_DebugAlloc> alloc_table;
|
||||
Dqn_TicketMutex alloc_table_mutex;
|
||||
Dqn_Arena alloc_table_arena;
|
||||
#if defined(DN_LEAK_TRACKING)
|
||||
DN_DSMap<DN_DebugAlloc> alloc_table;
|
||||
DN_TicketMutex alloc_table_mutex;
|
||||
DN_Arena alloc_table_arena;
|
||||
#endif
|
||||
|
||||
// NOTE: Win32 /////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DQN_OS_WIN32)
|
||||
#if defined(DN_OS_WIN32)
|
||||
LARGE_INTEGER win32_qpc_frequency;
|
||||
Dqn_TicketMutex win32_bcrypt_rng_mutex;
|
||||
DN_TicketMutex win32_bcrypt_rng_mutex;
|
||||
void * win32_bcrypt_rng_handle;
|
||||
#endif
|
||||
|
||||
bool win32_sym_initialised;
|
||||
#endif
|
||||
|
||||
// NOTE: OS ////////////////////////////////////////////////////////////////////////////////////
|
||||
uint32_t os_page_size;
|
||||
uint32_t os_alloc_granularity;
|
||||
|
||||
// NOTE: Profiler //////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_NO_PROFILER)
|
||||
Dqn_Profiler *profiler;
|
||||
Dqn_Profiler profiler_default_instance;
|
||||
#if !defined(DN_NO_PROFILER)
|
||||
DN_Profiler * profiler;
|
||||
DN_Profiler profiler_default_instance;
|
||||
#endif
|
||||
} extern *g_dqn_library;
|
||||
|
||||
enum Dqn_LibraryOnInit
|
||||
{
|
||||
Dqn_LibraryOnInit_Nil = 0,
|
||||
Dqn_LibraryOnInit_LogLibFeatures = 1 << 0,
|
||||
Dqn_LibraryOnInit_LogCPUFeatures = 1 << 1,
|
||||
Dqn_LibraryOnInit_LogAllFeatures = Dqn_LibraryOnInit_LogLibFeatures | Dqn_LibraryOnInit_LogCPUFeatures,
|
||||
};
|
||||
|
||||
// NOTE: [$PCGX] Dqn_PCG32 /////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_PCG32 Dqn_PCG32_Init (uint64_t seed);
|
||||
DQN_API uint32_t Dqn_PCG32_Next (Dqn_PCG32 *rng);
|
||||
DQN_API uint64_t Dqn_PCG32_Next64 (Dqn_PCG32 *rng);
|
||||
DQN_API uint32_t Dqn_PCG32_Range (Dqn_PCG32 *rng, uint32_t low, uint32_t high);
|
||||
DQN_API Dqn_f32 Dqn_PCG32_NextF32 (Dqn_PCG32 *rng);
|
||||
DQN_API Dqn_f64 Dqn_PCG32_NextF64 (Dqn_PCG32 *rng);
|
||||
DQN_API void Dqn_PCG32_Advance (Dqn_PCG32 *rng, uint64_t delta);
|
||||
enum DN_CoreOnInit
|
||||
{
|
||||
DN_CoreOnInit_Nil = 0,
|
||||
DN_CoreOnInit_LogLibFeatures = 1 << 0,
|
||||
DN_CoreOnInit_LogCPUFeatures = 1 << 1,
|
||||
DN_CoreOnInit_LogAllFeatures = DN_CoreOnInit_LogLibFeatures | DN_CoreOnInit_LogCPUFeatures,
|
||||
};
|
||||
|
||||
#if !defined(DQN_NO_JSON_BUILDER)
|
||||
// NOTE: [$JSON] Dqn_JSONBuilder ///////////////////////////////////////////////////////////////////
|
||||
#define Dqn_JSONBuilder_Object(builder) \
|
||||
DQN_DEFER_LOOP(Dqn_JSONBuilder_ObjectBegin(builder), \
|
||||
Dqn_JSONBuilder_ObjectEnd(builder))
|
||||
// NOTE: [$PCGX] DN_PCG32 /////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_PCG32 DN_PCG32_Init (uint64_t seed);
|
||||
DN_API uint32_t DN_PCG32_Next (DN_PCG32 *rng);
|
||||
DN_API uint64_t DN_PCG32_Next64 (DN_PCG32 *rng);
|
||||
DN_API uint32_t DN_PCG32_Range (DN_PCG32 *rng, uint32_t low, uint32_t high);
|
||||
DN_API DN_F32 DN_PCG32_NextF32 (DN_PCG32 *rng);
|
||||
DN_API DN_F64 DN_PCG32_NextF64 (DN_PCG32 *rng);
|
||||
DN_API void DN_PCG32_Advance (DN_PCG32 *rng, uint64_t delta);
|
||||
|
||||
#define Dqn_JSONBuilder_ObjectNamed(builder, name) \
|
||||
DQN_DEFER_LOOP(Dqn_JSONBuilder_ObjectBeginNamed(builder, name), \
|
||||
Dqn_JSONBuilder_ObjectEnd(builder))
|
||||
#if !defined(DN_NO_JSON_BUILDER)
|
||||
// NOTE: [$JSON] DN_JSONBuilder ///////////////////////////////////////////////////////////////////
|
||||
#define DN_JSONBuilder_Object(builder) \
|
||||
DN_DEFER_LOOP(DN_JSONBuilder_ObjectBegin(builder), \
|
||||
DN_JSONBuilder_ObjectEnd(builder))
|
||||
|
||||
#define Dqn_JSONBuilder_Array(builder) \
|
||||
DQN_DEFER_LOOP(Dqn_JSONBuilder_ArrayBegin(builder), \
|
||||
Dqn_JSONBuilder_ArrayEnd(builder))
|
||||
#define DN_JSONBuilder_ObjectNamed(builder, name) \
|
||||
DN_DEFER_LOOP(DN_JSONBuilder_ObjectBeginNamed(builder, name), \
|
||||
DN_JSONBuilder_ObjectEnd(builder))
|
||||
|
||||
#define Dqn_JSONBuilder_ArrayNamed(builder, name) \
|
||||
DQN_DEFER_LOOP(Dqn_JSONBuilder_ArrayBeginNamed(builder, name), \
|
||||
Dqn_JSONBuilder_ArrayEnd(builder))
|
||||
#define DN_JSONBuilder_Array(builder) \
|
||||
DN_DEFER_LOOP(DN_JSONBuilder_ArrayBegin(builder), \
|
||||
DN_JSONBuilder_ArrayEnd(builder))
|
||||
|
||||
#define DN_JSONBuilder_ArrayNamed(builder, name) \
|
||||
DN_DEFER_LOOP(DN_JSONBuilder_ArrayBeginNamed(builder, name), \
|
||||
DN_JSONBuilder_ArrayEnd(builder))
|
||||
|
||||
|
||||
DQN_API Dqn_JSONBuilder Dqn_JSONBuilder_Init (Dqn_Arena *arena, int spaces_per_indent);
|
||||
DQN_API Dqn_Str8 Dqn_JSONBuilder_Build (Dqn_JSONBuilder const *builder, Dqn_Arena *arena);
|
||||
DQN_API void Dqn_JSONBuilder_KeyValue (Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value);
|
||||
DQN_API void Dqn_JSONBuilder_KeyValueF (Dqn_JSONBuilder *builder, Dqn_Str8 key, char const *value_fmt, ...);
|
||||
DQN_API void Dqn_JSONBuilder_ObjectBeginNamed (Dqn_JSONBuilder *builder, Dqn_Str8 name);
|
||||
DQN_API void Dqn_JSONBuilder_ObjectEnd (Dqn_JSONBuilder *builder);
|
||||
DQN_API void Dqn_JSONBuilder_ArrayBeginNamed (Dqn_JSONBuilder *builder, Dqn_Str8 name);
|
||||
DQN_API void Dqn_JSONBuilder_ArrayEnd (Dqn_JSONBuilder *builder);
|
||||
DQN_API void Dqn_JSONBuilder_Str8Named (Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value);
|
||||
DQN_API void Dqn_JSONBuilder_LiteralNamed (Dqn_JSONBuilder *builder, Dqn_Str8 key, Dqn_Str8 value);
|
||||
DQN_API void Dqn_JSONBuilder_U64Named (Dqn_JSONBuilder *builder, Dqn_Str8 key, uint64_t value);
|
||||
DQN_API void Dqn_JSONBuilder_I64Named (Dqn_JSONBuilder *builder, Dqn_Str8 key, int64_t value);
|
||||
DQN_API void Dqn_JSONBuilder_F64Named (Dqn_JSONBuilder *builder, Dqn_Str8 key, double value, int decimal_places);
|
||||
DQN_API void Dqn_JSONBuilder_BoolNamed (Dqn_JSONBuilder *builder, Dqn_Str8 key, bool value);
|
||||
DN_API DN_JSONBuilder DN_JSONBuilder_Init (DN_Arena *arena, int spaces_per_indent);
|
||||
DN_API DN_Str8 DN_JSONBuilder_Build (DN_JSONBuilder const *builder, DN_Arena *arena);
|
||||
DN_API void DN_JSONBuilder_KeyValue (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value);
|
||||
DN_API void DN_JSONBuilder_KeyValueF (DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...);
|
||||
DN_API void DN_JSONBuilder_ObjectBeginNamed (DN_JSONBuilder *builder, DN_Str8 name);
|
||||
DN_API void DN_JSONBuilder_ObjectEnd (DN_JSONBuilder *builder);
|
||||
DN_API void DN_JSONBuilder_ArrayBeginNamed (DN_JSONBuilder *builder, DN_Str8 name);
|
||||
DN_API void DN_JSONBuilder_ArrayEnd (DN_JSONBuilder *builder);
|
||||
DN_API void DN_JSONBuilder_Str8Named (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value);
|
||||
DN_API void DN_JSONBuilder_LiteralNamed (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value);
|
||||
DN_API void DN_JSONBuilder_U64Named (DN_JSONBuilder *builder, DN_Str8 key, uint64_t value);
|
||||
DN_API void DN_JSONBuilder_I64Named (DN_JSONBuilder *builder, DN_Str8 key, int64_t value);
|
||||
DN_API void DN_JSONBuilder_F64Named (DN_JSONBuilder *builder, DN_Str8 key, double value, int decimal_places);
|
||||
DN_API void DN_JSONBuilder_BoolNamed (DN_JSONBuilder *builder, DN_Str8 key, bool value);
|
||||
|
||||
#define Dqn_JSONBuilder_ObjectBegin(builder) Dqn_JSONBuilder_ObjectBeginNamed(builder, DQN_STR8(""))
|
||||
#define Dqn_JSONBuilder_ArrayBegin(builder) Dqn_JSONBuilder_ArrayBeginNamed(builder, DQN_STR8(""))
|
||||
#define Dqn_JSONBuilder_Str8(builder, value) Dqn_JSONBuilder_Str8Named(builder, DQN_STR8(""), value)
|
||||
#define Dqn_JSONBuilder_Literal(builder, value) Dqn_JSONBuilder_LiteralNamed(builder, DQN_STR8(""), value)
|
||||
#define Dqn_JSONBuilder_U64(builder, value) Dqn_JSONBuilder_U64Named(builder, DQN_STR8(""), value)
|
||||
#define Dqn_JSONBuilder_I64(builder, value) Dqn_JSONBuilder_I64Named(builder, DQN_STR8(""), value)
|
||||
#define Dqn_JSONBuilder_F64(builder, value) Dqn_JSONBuilder_F64Named(builder, DQN_STR8(""), value)
|
||||
#define Dqn_JSONBuilder_Bool(builder, value) Dqn_JSONBuilder_BoolNamed(builder, DQN_STR8(""), value)
|
||||
#endif // !defined(DQN_NO_JSON_BUILDER)
|
||||
#define DN_JSONBuilder_ObjectBegin(builder) DN_JSONBuilder_ObjectBeginNamed(builder, DN_STR8(""))
|
||||
#define DN_JSONBuilder_ArrayBegin(builder) DN_JSONBuilder_ArrayBeginNamed(builder, DN_STR8(""))
|
||||
#define DN_JSONBuilder_Str8(builder, value) DN_JSONBuilder_Str8Named(builder, DN_STR8(""), value)
|
||||
#define DN_JSONBuilder_Literal(builder, value) DN_JSONBuilder_LiteralNamed(builder, DN_STR8(""), value)
|
||||
#define DN_JSONBuilder_U64(builder, value) DN_JSONBuilder_U64Named(builder, DN_STR8(""), value)
|
||||
#define DN_JSONBuilder_I64(builder, value) DN_JSONBuilder_I64Named(builder, DN_STR8(""), value)
|
||||
#define DN_JSONBuilder_F64(builder, value) DN_JSONBuilder_F64Named(builder, DN_STR8(""), value)
|
||||
#define DN_JSONBuilder_Bool(builder, value) DN_JSONBuilder_BoolNamed(builder, DN_STR8(""), value)
|
||||
#endif // !defined(DN_NO_JSON_BUILDER)
|
||||
|
||||
// NOTE: [$BSEA] Dqn_BinarySearch //////////////////////////////////////////////////////////////////
|
||||
template <typename T> bool Dqn_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
|
||||
template <typename T> Dqn_BinarySearchResult Dqn_BinarySearch (T const *array,
|
||||
Dqn_usize array_size,
|
||||
// NOTE: [$BSEA] DN_BinarySearch //////////////////////////////////////////////////////////////////
|
||||
template <typename T> bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
|
||||
template <typename T> DN_BinarySearchResult DN_BinarySearch (T const *array,
|
||||
DN_USize array_size,
|
||||
T const &find,
|
||||
Dqn_BinarySearchType type = Dqn_BinarySearchType_Match,
|
||||
Dqn_BinarySearchLessThanProc<T> less_than = Dqn_BinarySearch_DefaultLessThan);
|
||||
DN_BinarySearchType type = DN_BinarySearchType_Match,
|
||||
DN_BinarySearchLessThanProc<T> less_than = DN_BinarySearch_DefaultLessThan);
|
||||
|
||||
// NOTE: [$QSOR] Dqn_QSort /////////////////////////////////////////////////////////////////////////
|
||||
template <typename T> bool Dqn_QSort_DefaultLessThan(T const &lhs, T const &rhs);
|
||||
template <typename T> void Dqn_QSort (T *array,
|
||||
Dqn_usize array_size,
|
||||
// NOTE: [$QSOR] DN_QSort /////////////////////////////////////////////////////////////////////////
|
||||
template <typename T> bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs);
|
||||
template <typename T> void DN_QSort (T *array,
|
||||
DN_USize array_size,
|
||||
void *user_context,
|
||||
Dqn_QSortLessThanProc<T> less_than = Dqn_QSort_DefaultLessThan);
|
||||
DN_QSortLessThanProc<T> less_than = DN_QSort_DefaultLessThan);
|
||||
|
||||
// NOTE: [$BITS] Dqn_Bit ///////////////////////////////////////////////////////////////////////////
|
||||
DQN_API void Dqn_Bit_UnsetInplace (Dqn_usize *flags, Dqn_usize bitfield);
|
||||
DQN_API void Dqn_Bit_SetInplace (Dqn_usize *flags, Dqn_usize bitfield);
|
||||
DQN_API bool Dqn_Bit_IsSet (Dqn_usize bits, Dqn_usize bits_to_set);
|
||||
DQN_API bool Dqn_Bit_IsNotSet (Dqn_usize bits, Dqn_usize bits_to_check);
|
||||
#define Dqn_Bit_ClearNextLSB(value) (value) & ((value) - 1)
|
||||
// NOTE: [$BITS] DN_Bit ///////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_Bit_UnsetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API void DN_Bit_SetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API bool DN_Bit_IsSet (DN_USize bits, DN_USize bits_to_set);
|
||||
DN_API bool DN_Bit_IsNotSet (DN_USize bits, DN_USize bits_to_check);
|
||||
#define DN_Bit_ClearNextLSB(value) (value) & ((value) - 1)
|
||||
|
||||
// NOTE: [$SAFE] Dqn_Safe //////////////////////////////////////////////////////////////////////////
|
||||
DQN_API int64_t Dqn_Safe_AddI64 (int64_t a, int64_t b);
|
||||
DQN_API int64_t Dqn_Safe_MulI64 (int64_t a, int64_t b);
|
||||
// NOTE: [$SAFE] DN_Safe //////////////////////////////////////////////////////////////////////////
|
||||
DN_API int64_t DN_Safe_AddI64 (int64_t a, int64_t b);
|
||||
DN_API int64_t DN_Safe_MulI64 (int64_t a, int64_t b);
|
||||
|
||||
DQN_API uint64_t Dqn_Safe_AddU64 (uint64_t a, uint64_t b);
|
||||
DQN_API uint64_t Dqn_Safe_MulU64 (uint64_t a, uint64_t b);
|
||||
DN_API uint64_t DN_Safe_AddU64 (uint64_t a, uint64_t b);
|
||||
DN_API uint64_t DN_Safe_MulU64 (uint64_t a, uint64_t b);
|
||||
|
||||
DQN_API uint64_t Dqn_Safe_SubU64 (uint64_t a, uint64_t b);
|
||||
DQN_API uint32_t Dqn_Safe_SubU32 (uint32_t a, uint32_t b);
|
||||
DN_API uint64_t DN_Safe_SubU64 (uint64_t a, uint64_t b);
|
||||
DN_API uint32_t DN_Safe_SubU32 (uint32_t a, uint32_t b);
|
||||
|
||||
DQN_API int Dqn_Safe_SaturateCastUSizeToInt (Dqn_usize val);
|
||||
DQN_API int8_t Dqn_Safe_SaturateCastUSizeToI8 (Dqn_usize val);
|
||||
DQN_API int16_t Dqn_Safe_SaturateCastUSizeToI16 (Dqn_usize val);
|
||||
DQN_API int32_t Dqn_Safe_SaturateCastUSizeToI32 (Dqn_usize val);
|
||||
DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64 (Dqn_usize val);
|
||||
DN_API int DN_Safe_SaturateCastUSizeToInt (DN_USize val);
|
||||
DN_API int8_t DN_Safe_SaturateCastUSizeToI8 (DN_USize val);
|
||||
DN_API int16_t DN_Safe_SaturateCastUSizeToI16 (DN_USize val);
|
||||
DN_API int32_t DN_Safe_SaturateCastUSizeToI32 (DN_USize val);
|
||||
DN_API int64_t DN_Safe_SaturateCastUSizeToI64 (DN_USize val);
|
||||
|
||||
DQN_API int Dqn_Safe_SaturateCastU64ToInt (uint64_t val);
|
||||
DQN_API int64_t Dqn_Safe_SaturateCastU64ToI64 (uint64_t val);
|
||||
DQN_API unsigned int Dqn_Safe_SaturateCastU64ToUInt (uint64_t val);
|
||||
DQN_API uint8_t Dqn_Safe_SaturateCastU64ToU8 (uint64_t val);
|
||||
DQN_API uint16_t Dqn_Safe_SaturateCastU64ToU16 (uint64_t val);
|
||||
DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32 (uint64_t val);
|
||||
DN_API int DN_Safe_SaturateCastU64ToInt (uint64_t val);
|
||||
DN_API int8_t DN_Safe_SaturateCastU8ToI8 (uint64_t val);
|
||||
DN_API int16_t DN_Safe_SaturateCastU16ToI16 (uint64_t val);
|
||||
DN_API int32_t DN_Safe_SaturateCastU32ToI32 (uint64_t val);
|
||||
DN_API int64_t DN_Safe_SaturateCastU64ToI64 (uint64_t val);
|
||||
DN_API unsigned int DN_Safe_SaturateCastU64ToUInt (uint64_t val);
|
||||
DN_API uint8_t DN_Safe_SaturateCastU64ToU8 (uint64_t val);
|
||||
DN_API uint16_t DN_Safe_SaturateCastU64ToU16 (uint64_t val);
|
||||
DN_API uint32_t DN_Safe_SaturateCastU64ToU32 (uint64_t val);
|
||||
|
||||
DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8 (Dqn_usize val);
|
||||
DQN_API uint16_t Dqn_Safe_SaturateCastUSizeToU16 (Dqn_usize val);
|
||||
DQN_API uint32_t Dqn_Safe_SaturateCastUSizeToU32 (Dqn_usize val);
|
||||
DQN_API uint64_t Dqn_Safe_SaturateCastUSizeToU64 (Dqn_usize val);
|
||||
DN_API uint8_t DN_Safe_SaturateCastUSizeToU8 (DN_USize val);
|
||||
DN_API uint16_t DN_Safe_SaturateCastUSizeToU16 (DN_USize val);
|
||||
DN_API uint32_t DN_Safe_SaturateCastUSizeToU32 (DN_USize val);
|
||||
DN_API uint64_t DN_Safe_SaturateCastUSizeToU64 (DN_USize val);
|
||||
|
||||
DQN_API int Dqn_Safe_SaturateCastISizeToInt (Dqn_isize val);
|
||||
DQN_API int8_t Dqn_Safe_SaturateCastISizeToI8 (Dqn_isize val);
|
||||
DQN_API int16_t Dqn_Safe_SaturateCastISizeToI16 (Dqn_isize val);
|
||||
DQN_API int32_t Dqn_Safe_SaturateCastISizeToI32 (Dqn_isize val);
|
||||
DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64 (Dqn_isize val);
|
||||
DN_API int DN_Safe_SaturateCastISizeToInt (DN_ISize val);
|
||||
DN_API int8_t DN_Safe_SaturateCastISizeToI8 (DN_ISize val);
|
||||
DN_API int16_t DN_Safe_SaturateCastISizeToI16 (DN_ISize val);
|
||||
DN_API int32_t DN_Safe_SaturateCastISizeToI32 (DN_ISize val);
|
||||
DN_API int64_t DN_Safe_SaturateCastISizeToI64 (DN_ISize val);
|
||||
|
||||
DQN_API unsigned int Dqn_Safe_SaturateCastISizeToUInt (Dqn_isize val);
|
||||
DQN_API uint8_t Dqn_Safe_SaturateCastISizeToU8 (Dqn_isize val);
|
||||
DQN_API uint16_t Dqn_Safe_SaturateCastISizeToU16 (Dqn_isize val);
|
||||
DQN_API uint32_t Dqn_Safe_SaturateCastISizeToU32 (Dqn_isize val);
|
||||
DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64 (Dqn_isize val);
|
||||
DN_API unsigned int DN_Safe_SaturateCastISizeToUInt (DN_ISize val);
|
||||
DN_API uint8_t DN_Safe_SaturateCastISizeToU8 (DN_ISize val);
|
||||
DN_API uint16_t DN_Safe_SaturateCastISizeToU16 (DN_ISize val);
|
||||
DN_API uint32_t DN_Safe_SaturateCastISizeToU32 (DN_ISize val);
|
||||
DN_API uint64_t DN_Safe_SaturateCastISizeToU64 (DN_ISize val);
|
||||
|
||||
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize (int64_t val);
|
||||
DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8 (int64_t val);
|
||||
DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16 (int64_t val);
|
||||
DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32 (int64_t val);
|
||||
DN_API DN_ISize DN_Safe_SaturateCastI64ToISize (int64_t val);
|
||||
DN_API int8_t DN_Safe_SaturateCastI64ToI8 (int64_t val);
|
||||
DN_API int16_t DN_Safe_SaturateCastI64ToI16 (int64_t val);
|
||||
DN_API int32_t DN_Safe_SaturateCastI64ToI32 (int64_t val);
|
||||
|
||||
DQN_API unsigned int Dqn_Safe_SaturateCastI64ToUInt (int64_t val);
|
||||
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToUSize (int64_t val);
|
||||
DQN_API uint8_t Dqn_Safe_SaturateCastI64ToU8 (int64_t val);
|
||||
DQN_API uint16_t Dqn_Safe_SaturateCastI64ToU16 (int64_t val);
|
||||
DQN_API uint32_t Dqn_Safe_SaturateCastI64ToU32 (int64_t val);
|
||||
DQN_API uint64_t Dqn_Safe_SaturateCastI64ToU64 (int64_t val);
|
||||
DN_API unsigned int DN_Safe_SaturateCastI64ToUInt (int64_t val);
|
||||
DN_API DN_ISize DN_Safe_SaturateCastI64ToUSize (int64_t val);
|
||||
DN_API uint8_t DN_Safe_SaturateCastI64ToU8 (int64_t val);
|
||||
DN_API uint16_t DN_Safe_SaturateCastI64ToU16 (int64_t val);
|
||||
DN_API uint32_t DN_Safe_SaturateCastI64ToU32 (int64_t val);
|
||||
DN_API uint64_t DN_Safe_SaturateCastI64ToU64 (int64_t val);
|
||||
|
||||
DQN_API int8_t Dqn_Safe_SaturateCastIntToI8 (int val);
|
||||
DQN_API int16_t Dqn_Safe_SaturateCastIntToI16 (int val);
|
||||
DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8 (int val);
|
||||
DQN_API uint16_t Dqn_Safe_SaturateCastIntToU16 (int val);
|
||||
DQN_API uint32_t Dqn_Safe_SaturateCastIntToU32 (int val);
|
||||
DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64 (int val);
|
||||
DN_API int8_t DN_Safe_SaturateCastIntToI8 (int val);
|
||||
DN_API int16_t DN_Safe_SaturateCastIntToI16 (int val);
|
||||
DN_API uint8_t DN_Safe_SaturateCastIntToU8 (int val);
|
||||
DN_API uint16_t DN_Safe_SaturateCastIntToU16 (int val);
|
||||
DN_API uint32_t DN_Safe_SaturateCastIntToU32 (int val);
|
||||
DN_API uint64_t DN_Safe_SaturateCastIntToU64 (int val);
|
||||
|
||||
// NOTE: [$MISC] Misc //////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API int Dqn_FmtBuffer3DotTruncate (char *buffer, int size, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
DQN_API Dqn_U64Str8 Dqn_U64ToStr8 (uint64_t val, char separator);
|
||||
DQN_API Dqn_U64ByteSize Dqn_U64ToByteSize (uint64_t bytes, Dqn_U64ByteSizeType type);
|
||||
DQN_API Dqn_Str8 Dqn_U64ToByteSizeStr8 (Dqn_Arena *arena, uint64_t bytes, Dqn_U64ByteSizeType desired_type);
|
||||
DQN_API Dqn_Str8 Dqn_U64ByteSizeTypeString (Dqn_U64ByteSizeType type);
|
||||
DQN_API Dqn_Str8 Dqn_U64ToAge (Dqn_Arena *arena, uint64_t age_s, Dqn_U64AgeUnit unit);
|
||||
DN_API int DN_FmtBuffer3DotTruncate (char *buffer, int size, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_U64Str8 DN_U64ToStr8 (uint64_t val, char separator);
|
||||
DN_API DN_U64ByteSize DN_U64ToByteSize (uint64_t bytes, DN_U64ByteSizeType type);
|
||||
DN_API DN_Str8 DN_U64ToByteSizeStr8 (DN_Arena *arena, uint64_t bytes, DN_U64ByteSizeType desired_type);
|
||||
DN_API DN_Str8 DN_U64ByteSizeTypeString (DN_U64ByteSizeType type);
|
||||
DN_API DN_Str8 DN_U64ToAge (DN_Arena *arena, uint64_t age_s, DN_U64AgeUnit unit);
|
||||
DN_API DN_Str8 DN_F64ToAge (DN_Arena *arena, DN_F64 age_s, DN_U64AgeUnit unit);
|
||||
|
||||
DQN_API uint64_t Dqn_HexToU64 (Dqn_Str8 hex);
|
||||
DQN_API Dqn_Str8 Dqn_U64ToHex (Dqn_Arena *arena, uint64_t number, uint32_t flags);
|
||||
DQN_API Dqn_U64HexStr8 Dqn_U64ToHexStr8 (uint64_t number, uint32_t flags);
|
||||
DN_API uint64_t DN_HexToU64 (DN_Str8 hex);
|
||||
DN_API DN_Str8 DN_U64ToHex (DN_Arena *arena, uint64_t number, DN_U64HexStr8Flags flags);
|
||||
DN_API DN_U64HexStr8 DN_U64ToHexStr8 (uint64_t number, uint32_t flags);
|
||||
|
||||
DQN_API bool Dqn_BytesToHexPtr (void const *src, Dqn_usize src_size, char *dest);
|
||||
DQN_API Dqn_Str8 Dqn_BytesToHex (Dqn_Arena *arena, void const *src, Dqn_usize size);
|
||||
#define Dqn_BytesToHex_TLS(...) Dqn_BytesToHex(Dqn_TLS_TopArena(), __VA_ARGS__)
|
||||
DN_API bool DN_BytesToHexPtr (void const *src, DN_USize src_size, char *dest);
|
||||
DN_API DN_Str8 DN_BytesToHex (DN_Arena *arena, void const *src, DN_USize size);
|
||||
#define DN_BytesToHex_TLS(...) DN_BytesToHex(DN_TLS_TopArena(), __VA_ARGS__)
|
||||
|
||||
DQN_API Dqn_usize Dqn_HexToBytesPtrUnchecked (Dqn_Str8 hex, void *dest, Dqn_usize dest_size);
|
||||
DQN_API Dqn_usize Dqn_HexToBytesPtr (Dqn_Str8 hex, void *dest, Dqn_usize dest_size);
|
||||
DQN_API Dqn_Str8 Dqn_HexToBytesUnchecked (Dqn_Arena *arena, Dqn_Str8 hex);
|
||||
#define Dqn_HexToBytesUnchecked_TLS(...) Dqn_HexToBytesUnchecked(Dqn_TLS_TopArena(), __VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_HexToBytes (Dqn_Arena *arena, Dqn_Str8 hex);
|
||||
#define Dqn_HexToBytes_TLS(...) Dqn_HexToBytes(Dqn_TLS_TopArena(), __VA_ARGS__)
|
||||
DN_API DN_USize DN_HexToBytesPtrUnchecked (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_USize DN_HexToBytesPtr (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_Str8 DN_HexToBytesUnchecked (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_HexToBytesUnchecked_TLS(...) DN_HexToBytesUnchecked(DN_TLS_TopArena(), __VA_ARGS__)
|
||||
DN_API DN_Str8 DN_HexToBytes (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_HexToBytes_TLS(...) DN_HexToBytes(DN_TLS_TopArena(), __VA_ARGS__)
|
||||
|
||||
// NOTE: [$PROF] Dqn_Profiler //////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_ReadBuffer ();
|
||||
DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_WriteBuffer ();
|
||||
#define Dqn_Profiler_BeginZone(name) Dqn_Profiler_BeginZoneAtIndex(DQN_STR8(name), __COUNTER__ + 1)
|
||||
DQN_API Dqn_ProfilerZone Dqn_Profiler_BeginZoneAtIndex (Dqn_Str8 name, uint16_t anchor_index);
|
||||
DQN_API void Dqn_Profiler_EndZone (Dqn_ProfilerZone zone);
|
||||
DQN_API Dqn_ProfilerAnchor *Dqn_Profiler_AnchorBuffer (Dqn_ProfilerAnchorBuffer buffer);
|
||||
DQN_API void Dqn_Profiler_SwapAnchorBuffer ();
|
||||
DQN_API void Dqn_Profiler_Dump (uint64_t tsc_per_second);
|
||||
// NOTE: [$PROF] DN_Profiler //////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_ProfilerAnchor * DN_Profiler_ReadBuffer ();
|
||||
DN_API DN_ProfilerAnchor * DN_Profiler_WriteBuffer ();
|
||||
#define DN_Profiler_BeginZone(name) DN_Profiler_BeginZoneAtIndex(DN_STR8(name), __COUNTER__ + 1)
|
||||
DN_API DN_ProfilerZone DN_Profiler_BeginZoneAtIndex (DN_Str8 name, uint16_t anchor_index);
|
||||
DN_API void DN_Profiler_EndZone (DN_ProfilerZone zone);
|
||||
DN_API DN_ProfilerAnchor * DN_Profiler_AnchorBuffer (DN_ProfilerAnchorBuffer buffer);
|
||||
DN_API void DN_Profiler_SwapAnchorBuffer ();
|
||||
DN_API void DN_Profiler_Dump (uint64_t tsc_per_second);
|
||||
|
||||
// NOTE: [$JOBQ] Dqn_JobQueue ///////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit ();
|
||||
DQN_API bool Dqn_OS_JobQueueSPMCAddArray (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, uint32_t count);
|
||||
DQN_API bool Dqn_OS_JobQueueSPMCAdd (Dqn_JobQueueSPMC *queue, Dqn_Job job);
|
||||
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion (Dqn_JobQueueSPMC *queue);
|
||||
DQN_API int32_t Dqn_OS_JobQueueSPMCThread (Dqn_OSThread *thread);
|
||||
DQN_API Dqn_usize Dqn_OS_JobQueueSPMCGetFinishedJobs (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, Dqn_usize jobs_size);
|
||||
// NOTE: [$JOBQ] DN_JobQueue ///////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_JobQueueSPMC DN_OS_JobQueueSPMCInit ();
|
||||
DN_API bool DN_OS_JobQueueSPMCCanAdd (DN_JobQueueSPMC const *queue, uint32_t count);
|
||||
DN_API bool DN_OS_JobQueueSPMCAddArray (DN_JobQueueSPMC *queue, DN_Job *jobs, uint32_t count);
|
||||
DN_API bool DN_OS_JobQueueSPMCAdd (DN_JobQueueSPMC *queue, DN_Job job);
|
||||
DN_API void DN_OS_JobQueueSPMCWaitForCompletion (DN_JobQueueSPMC *queue);
|
||||
DN_API int32_t DN_OS_JobQueueSPMCThread (DN_OSThread *thread);
|
||||
DN_API DN_USize DN_OS_JobQueueSPMCGetFinishedJobs (DN_JobQueueSPMC *queue, DN_Job *jobs, DN_USize jobs_size);
|
||||
|
||||
// NOTE: Dqn_Library ///////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_Library * Dqn_Library_Init (Dqn_LibraryOnInit on_init);
|
||||
DQN_API void Dqn_Library_SetPointer (Dqn_Library *library);
|
||||
#if !defined(DQN_NO_PROFILER)
|
||||
DQN_API void Dqn_Library_SetProfiler (Dqn_Profiler *profiler);
|
||||
// NOTE: DN_Core ///////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_Core_Init (DN_Core *core, DN_CoreOnInit on_init);
|
||||
DN_API void DN_Core_BeginFrame ();
|
||||
DN_API void DN_Core_SetPointer (DN_Core *core);
|
||||
#if !defined(DN_NO_PROFILER)
|
||||
DN_API void DN_Core_SetProfiler (DN_Profiler *profiler);
|
||||
#endif
|
||||
DQN_API void Dqn_Library_SetLogCallback (Dqn_LogProc *proc, void *user_data);
|
||||
DQN_API void Dqn_Library_DumpThreadContextArenaStat (Dqn_Str8 file_path);
|
||||
DQN_API Dqn_Arena * Dqn_Library_AllocArenaF (Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, char const *fmt, ...);
|
||||
DQN_API bool Dqn_Library_EraseArena (Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena);
|
||||
DN_API void DN_Core_SetLogCallback (DN_LogProc *proc, void *user_data);
|
||||
DN_API void DN_Core_DumpThreadContextArenaStat (DN_Str8 file_path);
|
||||
DN_API DN_Arena * DN_Core_AllocArenaF (DN_USize reserve, DN_USize commit, uint8_t arena_flags, char const *fmt, ...);
|
||||
DN_API bool DN_Core_EraseArena (DN_Arena *arena, DN_ArenaCatalogFreeArena free_arena);
|
||||
|
||||
// NOTE: [$BSEA] Dqn_BinarySearch //////////////////////////////////////////////////////////////////
|
||||
// NOTE: [$BSEA] DN_BinarySearch //////////////////////////////////////////////////////////////////
|
||||
template <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;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Dqn_BinarySearchResult Dqn_BinarySearch(T const *array,
|
||||
Dqn_usize array_size,
|
||||
DN_BinarySearchResult DN_BinarySearch(T const *array,
|
||||
DN_USize array_size,
|
||||
T const &find,
|
||||
Dqn_BinarySearchType type,
|
||||
Dqn_BinarySearchLessThanProc<T> less_than)
|
||||
DN_BinarySearchType type,
|
||||
DN_BinarySearchLessThanProc<T> less_than)
|
||||
{
|
||||
Dqn_BinarySearchResult result = {};
|
||||
DN_BinarySearchResult result = {};
|
||||
if (!array || array_size <= 0 || !less_than)
|
||||
return result;
|
||||
|
||||
@ -513,11 +526,11 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array,
|
||||
T const *first = array;
|
||||
T const *last = end;
|
||||
while (first != last) {
|
||||
Dqn_usize count = last - first;
|
||||
DN_USize count = last - first;
|
||||
T const *it = first + (count / 2);
|
||||
|
||||
bool advance_first = false;
|
||||
if (type == Dqn_BinarySearchType_UpperBound)
|
||||
if (type == DN_BinarySearchType_UpperBound)
|
||||
advance_first = !less_than(find, it[0]);
|
||||
else
|
||||
advance_first = less_than(it[0], find);
|
||||
@ -529,12 +542,12 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array,
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case Dqn_BinarySearchType_Match: {
|
||||
case DN_BinarySearchType_Match: {
|
||||
result.found = first != end && !less_than(find, *first);
|
||||
} break;
|
||||
|
||||
case Dqn_BinarySearchType_LowerBound: /*FALLTHRU*/
|
||||
case Dqn_BinarySearchType_UpperBound: {
|
||||
case DN_BinarySearchType_LowerBound: /*FALLTHRU*/
|
||||
case DN_BinarySearchType_UpperBound: {
|
||||
result.found = first != end;
|
||||
} break;
|
||||
}
|
||||
@ -543,9 +556,9 @@ Dqn_BinarySearchResult Dqn_BinarySearch(T const *array,
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: [$QSOR] Dqn_QSort /////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: [$QSOR] DN_QSort /////////////////////////////////////////////////////////////////////////
|
||||
template <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;
|
||||
bool result = lhs < rhs;
|
||||
@ -553,19 +566,19 @@ bool Dqn_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context)
|
||||
}
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
// NOTE: Insertion Sort, under 24->32 is an optimal amount /////////////////////////////////////
|
||||
const Dqn_usize QSORT_THRESHOLD = 24;
|
||||
const DN_USize QSORT_THRESHOLD = 24;
|
||||
if (array_size < QSORT_THRESHOLD) {
|
||||
for (Dqn_usize item_to_insert_index = 1; item_to_insert_index < array_size; item_to_insert_index++) {
|
||||
for (Dqn_usize index = 0; index < item_to_insert_index; index++) {
|
||||
for (DN_USize item_to_insert_index = 1; item_to_insert_index < array_size; item_to_insert_index++) {
|
||||
for (DN_USize index = 0; index < item_to_insert_index; index++) {
|
||||
if (!less_than(array[index], array[item_to_insert_index], user_context)) {
|
||||
T item_to_insert = array[item_to_insert_index];
|
||||
for (Dqn_usize i = item_to_insert_index; i > index; i--)
|
||||
for (DN_USize i = item_to_insert_index; i > index; i--)
|
||||
array[i] = array[i - 1];
|
||||
|
||||
array[index] = item_to_insert;
|
||||
@ -577,14 +590,14 @@ void Dqn_QSort(T *array, Dqn_usize array_size, void *user_context, Dqn_QSortLess
|
||||
}
|
||||
|
||||
// NOTE: Quick sort, under 24->32 is an optimal amount /////////////////////////////////////////
|
||||
Dqn_usize last_index = array_size - 1;
|
||||
Dqn_usize pivot_index = array_size / 2;
|
||||
Dqn_usize partition_index = 0;
|
||||
Dqn_usize start_index = 0;
|
||||
DN_USize last_index = array_size - 1;
|
||||
DN_USize pivot_index = array_size / 2;
|
||||
DN_USize partition_index = 0;
|
||||
DN_USize start_index = 0;
|
||||
|
||||
// Swap pivot with last index, so pivot is always at the end of the array.
|
||||
// This makes logic much simpler.
|
||||
DQN_SWAP(array[last_index], array[pivot_index]);
|
||||
DN_SWAP(array[last_index], array[pivot_index]);
|
||||
pivot_index = last_index;
|
||||
|
||||
// 4^, 8, 7, 5, 2, 3, 6
|
||||
@ -596,20 +609,20 @@ void Dqn_QSort(T *array, Dqn_usize array_size, void *user_context, Dqn_QSortLess
|
||||
// 4, 5, |7, 8, 2^, 3, 6*
|
||||
// 4, 5, 2, |8, 7, ^3, 6*
|
||||
// 4, 5, 2, 3, |7, 8, ^6*
|
||||
for (Dqn_usize index = start_index; index < last_index; index++) {
|
||||
for (DN_USize index = start_index; index < last_index; index++) {
|
||||
if (less_than(array[index], array[pivot_index], user_context)) {
|
||||
DQN_SWAP(array[partition_index], array[index]);
|
||||
DN_SWAP(array[partition_index], array[index]);
|
||||
partition_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Move pivot to right of partition
|
||||
// 4, 5, 2, 3, |6, 8, ^7*
|
||||
DQN_SWAP(array[partition_index], array[pivot_index]);
|
||||
Dqn_QSort(array, partition_index, user_context, less_than);
|
||||
DN_SWAP(array[partition_index], array[pivot_index]);
|
||||
DN_QSort(array, partition_index, user_context, less_than);
|
||||
|
||||
// Skip the value at partion index since that is guaranteed to be sorted.
|
||||
// 4, 5, 2, 3, (x), 8, 7
|
||||
Dqn_usize one_after_partition_index = partition_index + 1;
|
||||
Dqn_QSort(array + one_after_partition_index, (array_size - one_after_partition_index), user_context, less_than);
|
||||
DN_USize one_after_partition_index = partition_index + 1;
|
||||
DN_QSort(array + one_after_partition_index, (array_size - one_after_partition_index), user_context, less_than);
|
||||
}
|
||||
|
288
dqn_json.cpp
288
dqn_json.cpp
@ -1,19 +1,19 @@
|
||||
#pragma once
|
||||
#include "dqn.h"
|
||||
|
||||
// NOTE: Dqn_JSON //////////////////////////////////////////////////////////////////////////////////
|
||||
void *Dqn_JSON_ArenaAllocFunc(void *user_data, size_t count)
|
||||
// NOTE: DN_JSON //////////////////////////////////////////////////////////////////////////////////
|
||||
void *DN_JSON_ArenaAllocFunc(void *user_data, size_t count)
|
||||
{
|
||||
void *result = NULL;
|
||||
if (!user_data)
|
||||
return result;
|
||||
|
||||
Dqn_Arena *arena = DQN_CAST(Dqn_Arena*)user_data;
|
||||
result = Dqn_Arena_Alloc(arena, count, alignof(json_value_s), Dqn_ZeroMem_No);
|
||||
DN_Arena *arena = DN_CAST(DN_Arena*)user_data;
|
||||
result = DN_Arena_Alloc(arena, count, alignof(json_value_s), DN_ZeroMem_No);
|
||||
return result;
|
||||
}
|
||||
|
||||
char const *Dqn_JSON_TypeEnumCString(json_type_e type, size_t *size)
|
||||
char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size)
|
||||
{
|
||||
switch (type) {
|
||||
case json_type_string: { if (size) { *size = sizeof("string") - 1; } return "string"; }
|
||||
@ -28,165 +28,165 @@ char const *Dqn_JSON_TypeEnumCString(json_type_e type, size_t *size)
|
||||
}
|
||||
}
|
||||
|
||||
bool Dqn_JSON_String8Cmp(json_string_s const *lhs, Dqn_Str8 key)
|
||||
bool DN_JSON_String8Cmp(json_string_s const *lhs, DN_Str8 key)
|
||||
{
|
||||
bool result = false;
|
||||
if (lhs && Dqn_Str8_HasData(key)) {
|
||||
Dqn_Str8 lhs_string = Dqn_Str8_Init(lhs->string, lhs->string_size);
|
||||
result = Dqn_Str8_Eq(lhs_string, key);
|
||||
if (lhs && DN_Str8_HasData(key)) {
|
||||
DN_Str8 lhs_string = DN_Str8_Init(lhs->string, lhs->string_size);
|
||||
result = DN_Str8_Eq(lhs_string, key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_It ///////////////////////////////////////////////////////////////////////////////
|
||||
Dqn_JSONIt Dqn_JSON_LoadFileToIt(Dqn_Arena *arena, Dqn_Str8 json)
|
||||
// NOTE: DN_JSON_It ///////////////////////////////////////////////////////////////////////////////
|
||||
DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json)
|
||||
{
|
||||
json_parse_result_s parse_result = {};
|
||||
json_value_ex_s *ex_value =
|
||||
DQN_CAST(json_value_ex_s *) json_parse_ex(json.data,
|
||||
DN_CAST(json_value_ex_s *) json_parse_ex(json.data,
|
||||
json.size,
|
||||
json_parse_flags_allow_location_information,
|
||||
Dqn_JSON_ArenaAllocFunc,
|
||||
DN_JSON_ArenaAllocFunc,
|
||||
arena,
|
||||
&parse_result);
|
||||
|
||||
Dqn_JSONIt result = {};
|
||||
Dqn_JSON_ItPushValue(&result, &ex_value->value);
|
||||
DN_JSONIt result = {};
|
||||
DN_JSON_ItPushValue(&result, &ex_value->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_ItPush/Pop ///////////////////////////////////////////////////////////////////////
|
||||
bool Dqn_JSON_ItPushObjElement(Dqn_JSONIt *it, json_object_element_s *element)
|
||||
// NOTE: DN_JSON_ItPush/Pop ///////////////////////////////////////////////////////////////////////
|
||||
bool DN_JSON_ItPushObjElement(DN_JSONIt *it, json_object_element_s *element)
|
||||
{
|
||||
if (!it || !element)
|
||||
return false;
|
||||
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeObjElement, element};
|
||||
DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeObjElement, element};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_ItPushObj(Dqn_JSONIt *it, json_object_s *obj)
|
||||
bool DN_JSON_ItPushObj(DN_JSONIt *it, json_object_s *obj)
|
||||
{
|
||||
if (!it || !obj)
|
||||
return false;
|
||||
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeObj, obj};
|
||||
DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeObj, obj};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_ItPushArrayElement(Dqn_JSONIt *it, json_array_element_s *element)
|
||||
bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element)
|
||||
{
|
||||
if (!it || !element)
|
||||
return false;
|
||||
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeArrayElement, element};
|
||||
DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeArrayElement, element};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_ItPushArray(Dqn_JSONIt *it, json_value_s *value)
|
||||
bool DN_JSON_ItPushArray(DN_JSONIt *it, json_value_s *value)
|
||||
{
|
||||
if (!it || !value || json_value_as_array(value) == nullptr)
|
||||
return false;
|
||||
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeArray, value};
|
||||
DN_ASSERT(it->stack_count < DN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {DN_JSON_ItEntryTypeArray, value};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_ItPushValue(Dqn_JSONIt *it, json_value_s *value)
|
||||
bool DN_JSON_ItPushValue(DN_JSONIt *it, json_value_s *value)
|
||||
{
|
||||
bool result = false;
|
||||
if (!it || !value)
|
||||
return result;
|
||||
|
||||
if (value->type == json_type_object) {
|
||||
result = Dqn_JSON_ItPushObj(it, json_value_as_object(value));
|
||||
result = DN_JSON_ItPushObj(it, json_value_as_object(value));
|
||||
} else if (value->type == json_type_array) {
|
||||
result = Dqn_JSON_ItPushArray(it, value);
|
||||
result = DN_JSON_ItPushArray(it, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Dqn_JSON_ItPop(Dqn_JSONIt *it)
|
||||
void DN_JSON_ItPop(DN_JSONIt *it)
|
||||
{
|
||||
if (!it)
|
||||
return;
|
||||
DQN_ASSERT(it->stack_count > 0);
|
||||
DN_ASSERT(it->stack_count > 0);
|
||||
if (it->stack_count > 0)
|
||||
it->stack_count--;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_It JSON tree navigation //////////////////////////////////////////////////////////
|
||||
json_value_s *Dqn_JSON_ItPushCurrValue(Dqn_JSONIt *it)
|
||||
// NOTE: DN_JSON_It JSON tree navigation //////////////////////////////////////////////////////////
|
||||
json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it)
|
||||
{
|
||||
json_value_s *result = nullptr;
|
||||
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it);
|
||||
DN_JSONItEntry *curr = DN_JSON_ItCurr(it);
|
||||
if (!curr)
|
||||
return result;
|
||||
|
||||
if (curr->type == Dqn_JSON_ItEntryTypeObjElement) {
|
||||
json_object_element_s *element = DQN_CAST(json_object_element_s *) curr->value;
|
||||
if (curr->type == DN_JSON_ItEntryTypeObjElement) {
|
||||
json_object_element_s *element = DN_CAST(json_object_element_s *) curr->value;
|
||||
result = element->value;
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) {
|
||||
json_array_element_s *element = DQN_CAST(json_array_element_s *) curr->value;
|
||||
} else if (curr->type == DN_JSON_ItEntryTypeArrayElement) {
|
||||
json_array_element_s *element = DN_CAST(json_array_element_s *) curr->value;
|
||||
result = element->value;
|
||||
} else {
|
||||
result = DQN_CAST(json_value_s *) curr->value;
|
||||
result = DN_CAST(json_value_s *) curr->value;
|
||||
}
|
||||
|
||||
if (result->type == json_type_array) {
|
||||
json_array_s *array = json_value_as_array(result);
|
||||
DQN_ASSERT(array);
|
||||
Dqn_JSON_ItPushArray(it, result);
|
||||
DN_ASSERT(array);
|
||||
DN_JSON_ItPushArray(it, result);
|
||||
} else if (result->type == json_type_object) {
|
||||
json_object_s *obj = json_value_as_object(result);
|
||||
DQN_ASSERT(obj);
|
||||
Dqn_JSON_ItPushObj(it, obj);
|
||||
DN_ASSERT(obj);
|
||||
DN_JSON_ItPushObj(it, obj);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_ItNext(Dqn_JSONIt *it)
|
||||
bool DN_JSON_ItNext(DN_JSONIt *it)
|
||||
{
|
||||
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it);
|
||||
DN_JSONItEntry *curr = DN_JSON_ItCurr(it);
|
||||
if (!curr)
|
||||
return false;
|
||||
|
||||
json_object_element_s *obj_element = nullptr;
|
||||
json_array_element_s *array_element = nullptr;
|
||||
if (curr->type == Dqn_JSON_ItEntryTypeObj) {
|
||||
auto *obj = DQN_CAST(json_object_s *) curr->value;
|
||||
if (curr->type == DN_JSON_ItEntryTypeObj) {
|
||||
auto *obj = DN_CAST(json_object_s *) curr->value;
|
||||
obj_element = obj->start;
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeObjElement) {
|
||||
auto *element = DQN_CAST(json_object_element_s *) curr->value;
|
||||
} else if (curr->type == DN_JSON_ItEntryTypeObjElement) {
|
||||
auto *element = DN_CAST(json_object_element_s *) curr->value;
|
||||
obj_element = element->next;
|
||||
Dqn_JSON_ItPop(it);
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeArray) {
|
||||
auto *value = DQN_CAST(json_value_s *) curr->value;
|
||||
DN_JSON_ItPop(it);
|
||||
} else if (curr->type == DN_JSON_ItEntryTypeArray) {
|
||||
auto *value = DN_CAST(json_value_s *) curr->value;
|
||||
auto *array = json_value_as_array(value);
|
||||
array_element = array->start;
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) {
|
||||
auto *element = DQN_CAST(json_array_element_s *) curr->value;
|
||||
} else if (curr->type == DN_JSON_ItEntryTypeArrayElement) {
|
||||
auto *element = DN_CAST(json_array_element_s *) curr->value;
|
||||
array_element = element->next;
|
||||
Dqn_JSON_ItPop(it);
|
||||
DN_JSON_ItPop(it);
|
||||
} else {
|
||||
Dqn_JSON_ItPop(it);
|
||||
DN_JSON_ItPop(it);
|
||||
}
|
||||
|
||||
if (obj_element)
|
||||
Dqn_JSON_ItPushObjElement(it, obj_element);
|
||||
DN_JSON_ItPushObjElement(it, obj_element);
|
||||
else if (array_element)
|
||||
Dqn_JSON_ItPushArrayElement(it, array_element);
|
||||
DN_JSON_ItPushArrayElement(it, array_element);
|
||||
|
||||
bool result = obj_element || array_element;
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_ItCurr ///////////////////////////////////////////////////////////////////////////
|
||||
Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it)
|
||||
// NOTE: DN_JSON_ItCurr ///////////////////////////////////////////////////////////////////////////
|
||||
DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it)
|
||||
{
|
||||
Dqn_JSONItEntry *result = nullptr;
|
||||
DN_JSONItEntry *result = nullptr;
|
||||
if (!it || it->stack_count <= 0)
|
||||
return result;
|
||||
|
||||
@ -194,236 +194,236 @@ Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it)
|
||||
return result;
|
||||
}
|
||||
|
||||
json_value_s *Dqn_JSON_ItCurrValue(Dqn_JSONIt *it)
|
||||
json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it)
|
||||
{
|
||||
json_value_s *result = nullptr;
|
||||
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it);
|
||||
DN_JSONItEntry *curr = DN_JSON_ItCurr(it);
|
||||
if (!curr)
|
||||
return result;
|
||||
|
||||
if (curr->type == Dqn_JSON_ItEntryTypeObjElement) {
|
||||
auto *element = DQN_CAST(json_object_element_s *)curr->value;
|
||||
if (curr->type == DN_JSON_ItEntryTypeObjElement) {
|
||||
auto *element = DN_CAST(json_object_element_s *)curr->value;
|
||||
result = element->value;
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) {
|
||||
auto *element = DQN_CAST(json_array_element_s *)curr->value;
|
||||
} else if (curr->type == DN_JSON_ItEntryTypeArrayElement) {
|
||||
auto *element = DN_CAST(json_array_element_s *)curr->value;
|
||||
result = element->value;
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeString ||
|
||||
curr->type == Dqn_JSON_ItEntryTypeNumber ||
|
||||
curr->type == Dqn_JSON_ItEntryTypeObj ||
|
||||
curr->type == Dqn_JSON_ItEntryTypeArray)
|
||||
} else if (curr->type == DN_JSON_ItEntryTypeString ||
|
||||
curr->type == DN_JSON_ItEntryTypeNumber ||
|
||||
curr->type == DN_JSON_ItEntryTypeObj ||
|
||||
curr->type == DN_JSON_ItEntryTypeArray)
|
||||
{
|
||||
result = DQN_CAST(json_value_s *)curr->value;
|
||||
result = DN_CAST(json_value_s *)curr->value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
json_object_element_s *Dqn_JSON_ItCurrObjElement(Dqn_JSONIt *it)
|
||||
json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it)
|
||||
{
|
||||
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it);
|
||||
auto *result = (curr && curr->type == Dqn_JSON_ItEntryTypeObjElement)
|
||||
? DQN_CAST(json_object_element_s *) curr->value
|
||||
DN_JSONItEntry *curr = DN_JSON_ItCurr(it);
|
||||
auto *result = (curr && curr->type == DN_JSON_ItEntryTypeObjElement)
|
||||
? DN_CAST(json_object_element_s *) curr->value
|
||||
: nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_ItValueIs ////////////////////////////////////////////////////////////////////////
|
||||
json_value_s *Dqn_JSON_ItValueIs(Dqn_JSONIt *it, json_type_e type)
|
||||
// NOTE: DN_JSON_ItValueIs ////////////////////////////////////////////////////////////////////////
|
||||
json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *curr = DN_JSON_ItCurrValue(it);
|
||||
json_value_s *result = (curr && type == curr->type) ? curr : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_object_s *Dqn_JSON_ItValueIsObj(Dqn_JSONIt *it)
|
||||
json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *curr = DN_JSON_ItCurrValue(it);
|
||||
json_object_s *result = curr ? json_value_as_object(curr) : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_array_s *Dqn_JSON_ItValueIsArray(Dqn_JSONIt *it)
|
||||
json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *curr = DN_JSON_ItCurrValue(it);
|
||||
json_array_s *result = curr ? json_value_as_array(curr) : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_string_s *Dqn_JSON_ItValueIsString(Dqn_JSONIt *it)
|
||||
json_string_s *DN_JSON_ItValueIsString(DN_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *curr = DN_JSON_ItCurrValue(it);
|
||||
json_string_s *result = curr ? json_value_as_string(curr) : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_number_s *Dqn_JSON_ItValueIsNumber(Dqn_JSONIt *it)
|
||||
json_number_s *DN_JSON_ItValueIsNumber(DN_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *curr = DN_JSON_ItCurrValue(it);
|
||||
json_number_s *result = curr ? json_value_as_number(curr) : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_value_s *Dqn_JSON_ItValueIsBool(Dqn_JSONIt *it)
|
||||
json_value_s *DN_JSON_ItValueIsBool(DN_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *curr = DN_JSON_ItCurrValue(it);
|
||||
json_value_s *result = (curr && (curr->type == json_type_true || curr->type == json_type_false)) ? curr : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_value_s *Dqn_JSON_ItValueIsNull(Dqn_JSONIt *it)
|
||||
json_value_s *DN_JSON_ItValueIsNull(DN_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *curr = DN_JSON_ItCurrValue(it);
|
||||
json_value_s *result = (curr && (curr->type == json_type_null)) ? curr : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t Dqn_JSON_ItValueArraySize(Dqn_JSONIt *it)
|
||||
size_t DN_JSON_ItValueArraySize(DN_JSONIt *it)
|
||||
{
|
||||
size_t result = 0;
|
||||
if (json_array_s *curr = Dqn_JSON_ItValueIsArray(it))
|
||||
if (json_array_s *curr = DN_JSON_ItValueIsArray(it))
|
||||
result = curr->length;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Dqn_JSON_ItKeyValueIs /////////////////////////////////////////////////////////////////////
|
||||
Dqn_Str8 Dqn_JSON_ItKey(Dqn_JSONIt *it)
|
||||
// NOTE: DN_JSON_ItKeyValueIs /////////////////////////////////////////////////////////////////////
|
||||
DN_Str8 DN_JSON_ItKey(DN_JSONIt *it)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
Dqn_Str8 result = {};
|
||||
json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
|
||||
DN_Str8 result = {};
|
||||
if (curr) {
|
||||
result.data = DQN_CAST(char *)curr->name->string;
|
||||
result.data = DN_CAST(char *)curr->name->string;
|
||||
result.size = curr->name->string_size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_ItKeyIs(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
bool result = Dqn_JSON_String8Cmp(curr->name, key);
|
||||
json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
|
||||
bool result = DN_JSON_String8Cmp(curr->name, key);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_object_s *Dqn_JSON_ItKeyValueIsObj(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
json_object_s *DN_JSON_ItKeyValueIsObj(DN_JSONIt *it, DN_Str8 key)
|
||||
{
|
||||
json_object_s *result = nullptr;
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
|
||||
if (curr && DN_JSON_String8Cmp(curr->name, key))
|
||||
result = json_value_as_object(curr->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_array_s *Dqn_JSON_ItKeyValueIsArray(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
json_array_s *DN_JSON_ItKeyValueIsArray(DN_JSONIt *it, DN_Str8 key)
|
||||
{
|
||||
json_array_s *result = nullptr;
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
|
||||
if (curr && DN_JSON_String8Cmp(curr->name, key))
|
||||
result = json_value_as_array(curr->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_string_s *Dqn_JSON_ItKeyValueIsString(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
json_string_s *DN_JSON_ItKeyValueIsString(DN_JSONIt *it, DN_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
|
||||
json_string_s *result = nullptr;
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
if (curr && DN_JSON_String8Cmp(curr->name, key))
|
||||
result = json_value_as_string(curr->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_number_s *Dqn_JSON_ItKeyValueIsNumber(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
json_number_s *DN_JSON_ItKeyValueIsNumber(DN_JSONIt *it, DN_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
|
||||
json_number_s *result = nullptr;
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
if (curr && DN_JSON_String8Cmp(curr->name, key))
|
||||
result = json_value_as_number(curr->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_value_s *Dqn_JSON_ItKeyValueIsBool(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
json_value_s *DN_JSON_ItKeyValueIsBool(DN_JSONIt *it, DN_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
|
||||
json_value_s *result = nullptr;
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
if (curr && DN_JSON_String8Cmp(curr->name, key))
|
||||
result = curr->value->type == json_type_true || curr->value->type == json_type_false ? curr->value : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_value_s *Dqn_JSON_ItKeyValueIsNull(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_object_element_s *curr = DN_JSON_ItCurrObjElement(it);
|
||||
json_value_s *result = nullptr;
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
if (curr && DN_JSON_String8Cmp(curr->name, key))
|
||||
result = curr->value->type == json_type_null ? curr->value : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Dqn_JSON_ItValueTo ////////////////////////////////////////////////////////////////////////
|
||||
Dqn_Str8 Dqn_JSON_ItValueToString(Dqn_JSONIt *it)
|
||||
// NOTE: DN_JSON_ItValueTo ////////////////////////////////////////////////////////////////////////
|
||||
DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it)
|
||||
{
|
||||
Dqn_Str8 result = {};
|
||||
if (json_string_s *curr = Dqn_JSON_ItValueIsString(it))
|
||||
result = Dqn_Str8_Init(curr->string, curr->string_size);
|
||||
DN_Str8 result = {};
|
||||
if (json_string_s *curr = DN_JSON_ItValueIsString(it))
|
||||
result = DN_Str8_Init(curr->string, curr->string_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t Dqn_JSON_ItValueToI64(Dqn_JSONIt *it)
|
||||
int64_t DN_JSON_ItValueToI64(DN_JSONIt *it)
|
||||
{
|
||||
int64_t result = {};
|
||||
if (json_number_s *curr = Dqn_JSON_ItValueIsNumber(it))
|
||||
result = Dqn_Str8_ToI64(Dqn_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value;
|
||||
if (json_number_s *curr = DN_JSON_ItValueIsNumber(it))
|
||||
result = DN_Str8_ToI64(DN_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t Dqn_JSON_ItValueToU64(Dqn_JSONIt *it)
|
||||
uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it)
|
||||
{
|
||||
uint64_t result = {};
|
||||
if (json_number_s *curr = Dqn_JSON_ItValueIsNumber(it))
|
||||
result = Dqn_Str8_ToU64(Dqn_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value;
|
||||
if (json_number_s *curr = DN_JSON_ItValueIsNumber(it))
|
||||
result = DN_Str8_ToU64(DN_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_ItValueToBool(Dqn_JSONIt *it)
|
||||
bool DN_JSON_ItValueToBool(DN_JSONIt *it)
|
||||
{
|
||||
bool result = {};
|
||||
if (json_value_s *curr = Dqn_JSON_ItValueIsBool(it))
|
||||
if (json_value_s *curr = DN_JSON_ItValueIsBool(it))
|
||||
result = curr->type == json_type_true;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Dqn_JSON_ItErrorUnknownKeyValue_(Dqn_JSONIt *it, Dqn_CallSite call_site)
|
||||
void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site)
|
||||
{
|
||||
if (!it)
|
||||
return;
|
||||
|
||||
json_object_element_s const *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_object_element_s const *curr = DN_JSON_ItCurrObjElement(it);
|
||||
if (!curr)
|
||||
return;
|
||||
|
||||
size_t value_type_size = 0;
|
||||
char const *value_type = Dqn_JSON_TypeEnumCString(DQN_CAST(json_type_e)curr->value->type, &value_type_size);
|
||||
char const *value_type = DN_JSON_TypeEnumCString(DN_CAST(json_type_e)curr->value->type, &value_type_size);
|
||||
|
||||
json_string_s const *key = curr->name;
|
||||
if (it->flags & json_parse_flags_allow_location_information) {
|
||||
json_string_ex_s const *info = DQN_CAST(json_string_ex_s const *)key;
|
||||
Dqn_Log_TypeFCallSite(Dqn_LogType_Warning,
|
||||
json_string_ex_s const *info = DN_CAST(json_string_ex_s const *)key;
|
||||
DN_Log_TypeFCallSite(DN_LogType_Warning,
|
||||
call_site,
|
||||
"Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]",
|
||||
info->line_no,
|
||||
info->row_no,
|
||||
DQN_CAST(int)key->string_size,
|
||||
DN_CAST(int)key->string_size,
|
||||
key->string,
|
||||
DQN_CAST(int)value_type_size,
|
||||
DN_CAST(int)value_type_size,
|
||||
value_type);
|
||||
} else {
|
||||
Dqn_Log_TypeFCallSite(Dqn_LogType_Warning,
|
||||
DN_Log_TypeFCallSite(DN_LogType_Warning,
|
||||
call_site,
|
||||
"Unknown key-value pair in object [key=%.*s, value=%.*s]",
|
||||
DQN_CAST(int)key->string_size,
|
||||
DN_CAST(int)key->string_size,
|
||||
key->string,
|
||||
DQN_CAST(int)value_type_size,
|
||||
DN_CAST(int)value_type_size,
|
||||
value_type);
|
||||
}
|
||||
}
|
||||
|
118
dqn_json.h
118
dqn_json.h
@ -5,85 +5,85 @@
|
||||
#error Sheredom json.h (github.com/sheredom/json.h) must be included before this file
|
||||
#endif
|
||||
|
||||
// NOTE: Dqn_JSON //////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_JSON //////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void *Dqn_JSON_ArenaAllocFunc (void *user_data, size_t count);
|
||||
char const *Dqn_JSON_TypeEnumCString(json_type_e type, size_t *size);
|
||||
bool Dqn_JSON_String8Cmp (json_string_s const *lhs, Dqn_Str8 rhs);
|
||||
void *DN_JSON_ArenaAllocFunc (void *user_data, size_t count);
|
||||
char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size);
|
||||
bool DN_JSON_String8Cmp (json_string_s const *lhs, DN_Str8 rhs);
|
||||
|
||||
// NOTE: Dqn_JSON_It /////////////////////////////////////////////////////////////////////////
|
||||
enum Dqn_JSONItEntryType
|
||||
// NOTE: DN_JSON_It /////////////////////////////////////////////////////////////////////////
|
||||
enum DN_JSONItEntryType
|
||||
{
|
||||
Dqn_JSON_ItEntryTypeObjElement,
|
||||
Dqn_JSON_ItEntryTypeObj,
|
||||
Dqn_JSON_ItEntryTypeArrayElement,
|
||||
Dqn_JSON_ItEntryTypeArray,
|
||||
Dqn_JSON_ItEntryTypeString,
|
||||
Dqn_JSON_ItEntryTypeNumber,
|
||||
DN_JSON_ItEntryTypeObjElement,
|
||||
DN_JSON_ItEntryTypeObj,
|
||||
DN_JSON_ItEntryTypeArrayElement,
|
||||
DN_JSON_ItEntryTypeArray,
|
||||
DN_JSON_ItEntryTypeString,
|
||||
DN_JSON_ItEntryTypeNumber,
|
||||
};
|
||||
|
||||
struct Dqn_JSONItEntry
|
||||
struct DN_JSONItEntry
|
||||
{
|
||||
Dqn_JSONItEntryType type;
|
||||
DN_JSONItEntryType type;
|
||||
void *value;
|
||||
};
|
||||
|
||||
struct Dqn_JSONIt
|
||||
struct DN_JSONIt
|
||||
{
|
||||
Dqn_JSONItEntry stack[128];
|
||||
DN_JSONItEntry stack[128];
|
||||
int stack_count;
|
||||
size_t flags;
|
||||
};
|
||||
|
||||
Dqn_JSONIt Dqn_JSON_LoadFileToIt(Dqn_Arena *arena, Dqn_Str8 json);
|
||||
DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json);
|
||||
|
||||
// NOTE: Dqn_JSON_ItPush/Pop /////////////////////////////////////////////////////////////////
|
||||
bool Dqn_JSON_ItPushObjElement (Dqn_JSONIt *it, json_object_element_s *element);
|
||||
bool Dqn_JSON_ItPushObj (Dqn_JSONIt *it, json_object_s *obj);
|
||||
bool Dqn_JSON_ItPushArrayElement(Dqn_JSONIt *it, json_array_element_s *element);
|
||||
bool Dqn_JSON_ItPushArray (Dqn_JSONIt *it, json_value_s *value);
|
||||
bool Dqn_JSON_ItPushValue (Dqn_JSONIt *it, json_value_s *value);
|
||||
void Dqn_JSON_ItPop (Dqn_JSONIt *it);
|
||||
// NOTE: DN_JSON_ItPush/Pop /////////////////////////////////////////////////////////////////
|
||||
bool DN_JSON_ItPushObjElement (DN_JSONIt *it, json_object_element_s *element);
|
||||
bool DN_JSON_ItPushObj (DN_JSONIt *it, json_object_s *obj);
|
||||
bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element);
|
||||
bool DN_JSON_ItPushArray (DN_JSONIt *it, json_value_s *value);
|
||||
bool DN_JSON_ItPushValue (DN_JSONIt *it, json_value_s *value);
|
||||
void DN_JSON_ItPop (DN_JSONIt *it);
|
||||
|
||||
// NOTE: Dqn_JSON_It tree navigation /////////////////////////////////////////////////////////
|
||||
json_value_s *Dqn_JSON_ItPushCurrValue(Dqn_JSONIt *it);
|
||||
bool Dqn_JSON_ItNext(Dqn_JSONIt *it);
|
||||
// NOTE: DN_JSON_It tree navigation /////////////////////////////////////////////////////////
|
||||
json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it);
|
||||
bool DN_JSON_ItNext(DN_JSONIt *it);
|
||||
|
||||
#define Dqn_JSON_ItPushCurrValueIterateThenPop(it) \
|
||||
for(void *DQN_UNIQUE_NAME(ptr) = Dqn_JSON_ItPushCurrValue(it); DQN_UNIQUE_NAME(ptr); Dqn_JSON_ItPop(it), DQN_UNIQUE_NAME(ptr) = nullptr) \
|
||||
while (Dqn_JSON_ItNext(it))
|
||||
#define DN_JSON_ItPushCurrValueIterateThenPop(it) \
|
||||
for(void *DN_UNIQUE_NAME(ptr) = DN_JSON_ItPushCurrValue(it); DN_UNIQUE_NAME(ptr); DN_JSON_ItPop(it), DN_UNIQUE_NAME(ptr) = nullptr) \
|
||||
while (DN_JSON_ItNext(it))
|
||||
|
||||
// NOTE: Dqn_JSON_ItCurr /////////////////////////////////////////////////////////////////////
|
||||
Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it);
|
||||
json_value_s *Dqn_JSON_ItCurrValue(Dqn_JSONIt *it);
|
||||
json_object_element_s *Dqn_JSON_ItCurrObjElement(Dqn_JSONIt *it);
|
||||
// NOTE: DN_JSON_ItCurr /////////////////////////////////////////////////////////////////////
|
||||
DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it);
|
||||
json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it);
|
||||
json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it);
|
||||
|
||||
// NOTE: Dqn_JSON_ItValueIs //////////////////////////////////////////////////////////////////
|
||||
json_value_s *Dqn_JSON_ItValueIs(Dqn_JSONIt *it, json_type_e type);
|
||||
json_object_s *Dqn_JSON_ItValueIsObj(Dqn_JSONIt *it);
|
||||
json_array_s *Dqn_JSON_ItValueIsArray(Dqn_JSONIt *it);
|
||||
json_string_s *Dqn_JSON_ItValueIsString(Dqn_JSONIt *it);
|
||||
json_number_s *Dqn_JSON_ItValueIsNumber(Dqn_JSONIt *it);
|
||||
json_value_s *Dqn_JSON_ItValueIsBool(Dqn_JSONIt *it);
|
||||
json_value_s *Dqn_JSON_ItValueIsNull(Dqn_JSONIt *it);
|
||||
// NOTE: DN_JSON_ItValueIs //////////////////////////////////////////////////////////////////
|
||||
json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type);
|
||||
json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it);
|
||||
json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it);
|
||||
json_string_s *DN_JSON_ItValueIsString(DN_JSONIt *it);
|
||||
json_number_s *DN_JSON_ItValueIsNumber(DN_JSONIt *it);
|
||||
json_value_s *DN_JSON_ItValueIsBool(DN_JSONIt *it);
|
||||
json_value_s *DN_JSON_ItValueIsNull(DN_JSONIt *it);
|
||||
|
||||
size_t Dqn_JSON_ItValueArraySize(Dqn_JSONIt *it);
|
||||
size_t DN_JSON_ItValueArraySize(DN_JSONIt *it);
|
||||
|
||||
// NOTE: Dqn_JSON_ItKeyValueIs ///////////////////////////////////////////////////////////////
|
||||
Dqn_Str8 Dqn_JSON_ItKey(Dqn_JSONIt *it);
|
||||
bool Dqn_JSON_ItKeyIs(Dqn_JSONIt *it, Dqn_Str8 key);
|
||||
json_object_s *Dqn_JSON_ItKeyValueIsObj(Dqn_JSONIt *it, Dqn_Str8 key);
|
||||
json_array_s *Dqn_JSON_ItKeyValueIsArray(Dqn_JSONIt *it, Dqn_Str8 key);
|
||||
json_string_s *Dqn_JSON_ItKeyValueIsString(Dqn_JSONIt *it, Dqn_Str8 key);
|
||||
json_number_s *Dqn_JSON_ItKeyValueIsNumber(Dqn_JSONIt *it, Dqn_Str8 key);
|
||||
json_value_s *Dqn_JSON_ItKeyValueIsBool(Dqn_JSONIt *it, Dqn_Str8 key);
|
||||
json_value_s *Dqn_JSON_ItKeyValueIsNull(Dqn_JSONIt *it, Dqn_Str8 key);
|
||||
// NOTE: DN_JSON_ItKeyValueIs ///////////////////////////////////////////////////////////////
|
||||
DN_Str8 DN_JSON_ItKey(DN_JSONIt *it);
|
||||
bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key);
|
||||
json_object_s *DN_JSON_ItKeyValueIsObj(DN_JSONIt *it, DN_Str8 key);
|
||||
json_array_s *DN_JSON_ItKeyValueIsArray(DN_JSONIt *it, DN_Str8 key);
|
||||
json_string_s *DN_JSON_ItKeyValueIsString(DN_JSONIt *it, DN_Str8 key);
|
||||
json_number_s *DN_JSON_ItKeyValueIsNumber(DN_JSONIt *it, DN_Str8 key);
|
||||
json_value_s *DN_JSON_ItKeyValueIsBool(DN_JSONIt *it, DN_Str8 key);
|
||||
json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key);
|
||||
|
||||
// NOTE: Dqn_JSON_ItValueTo //////////////////////////////////////////////////////////////////
|
||||
Dqn_Str8 Dqn_JSON_ItValueToString(Dqn_JSONIt *it);
|
||||
int64_t Dqn_JSON_ItValueToI64(Dqn_JSONIt *it);
|
||||
uint64_t Dqn_JSON_ItValueToU64(Dqn_JSONIt *it);
|
||||
bool Dqn_JSON_ItValueToBool(Dqn_JSONIt *it);
|
||||
// NOTE: DN_JSON_ItValueTo //////////////////////////////////////////////////////////////////
|
||||
DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it);
|
||||
int64_t DN_JSON_ItValueToI64(DN_JSONIt *it);
|
||||
uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it);
|
||||
bool DN_JSON_ItValueToBool(DN_JSONIt *it);
|
||||
|
||||
#define Dqn_JSON_ItErrorUnknownKeyValue(it) Dqn_JSON_ItErrorUnknownKeyValue_(it, DQN_CALL_SITE)
|
||||
void Dqn_JSON_ItErrorUnknownKeyValue_(Dqn_JSONIt *it, Dqn_CallSite call_site);
|
||||
#define DN_JSON_ItErrorUnknownKeyValue(it) DN_JSON_ItErrorUnknownKeyValue_(it, DN_CALL_SITE)
|
||||
void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site);
|
||||
|
1154
dqn_math.cpp
1154
dqn_math.cpp
File diff suppressed because it is too large
Load Diff
616
dqn_math.h
616
dqn_math.h
@ -17,397 +17,395 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [$VEC2] Dqn_V2, V2i -- DQN_V2
|
||||
// [$VEC3] Dqn_V3, V3i -- DQN_V3
|
||||
// [$VEC4] Dqn_V4, V4i -- DQN_V4
|
||||
// [$MAT4] Dqn_M4 -- DQN_M4
|
||||
// [$M2x3] Dqn_M2x3 --
|
||||
// [$RECT] Dqn_Rect -- DQN_RECT
|
||||
// [$VEC2] DN_V2F32, V2I32 -- DN_V2
|
||||
// [$VEC3] DN_V3F32, V3I32 -- DN_V3
|
||||
// [$VEC4] DN_V4F32, V4I32 -- DN_V4
|
||||
// [$MAT4] DN_M4 -- DN_M4
|
||||
// [$M2x3] DN_M2x3 --
|
||||
// [$RECT] DN_Rect -- DN_RECT
|
||||
// [$MATH] Other --
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
DQN_MSVC_WARNING_PUSH
|
||||
DQN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
||||
#if !defined(DQN_NO_V2)
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
||||
#if !defined(DN_NO_V2)
|
||||
// NOTE: [$VEC2] Vector2 ///////////////////////////////////////////////////////////////////////////
|
||||
union Dqn_V2I
|
||||
union DN_V2I32
|
||||
{
|
||||
struct { int32_t x, y; };
|
||||
struct { int32_t w, h; };
|
||||
int32_t data[2];
|
||||
};
|
||||
|
||||
union Dqn_V2U16
|
||||
union DN_V2U16
|
||||
{
|
||||
struct { uint16_t x, y; };
|
||||
struct { uint16_t w, h; };
|
||||
uint16_t data[2];
|
||||
};
|
||||
|
||||
union Dqn_V2
|
||||
union DN_V2F32
|
||||
{
|
||||
struct { Dqn_f32 x, y; };
|
||||
struct { Dqn_f32 w, h; };
|
||||
Dqn_f32 data[2];
|
||||
struct { DN_F32 x, y; };
|
||||
struct { DN_F32 w, h; };
|
||||
DN_F32 data[2];
|
||||
};
|
||||
#endif // !defined(DQN_NO_V2)
|
||||
#endif // !defined(DN_NO_V2)
|
||||
|
||||
#if !defined(DQN_NO_V3)
|
||||
#if !defined(DN_NO_V3)
|
||||
// NOTE: [$VEC3] Vector3 ///////////////////////////////////////////////////////////////////////////
|
||||
union Dqn_V3
|
||||
union DN_V3F32
|
||||
{
|
||||
struct { Dqn_f32 x, y, z; };
|
||||
struct { Dqn_f32 r, g, b; };
|
||||
Dqn_f32 data[3];
|
||||
struct { DN_F32 x, y, z; };
|
||||
struct { DN_F32 r, g, b; };
|
||||
DN_F32 data[3];
|
||||
};
|
||||
|
||||
#endif // !defined(DQN_NO_V3)
|
||||
#endif // !defined(DN_NO_V3)
|
||||
|
||||
#if !defined(DQN_NO_V4)
|
||||
#if !defined(DN_NO_V4)
|
||||
// NOTE: [$VEC4] Vector4 ///////////////////////////////////////////////////////////////////////////
|
||||
union Dqn_V4
|
||||
union DN_V4F32
|
||||
{
|
||||
struct { Dqn_f32 x, y, z, w; };
|
||||
struct { Dqn_f32 r, g, b, a; };
|
||||
#if !defined(DQN_NO_V3)
|
||||
Dqn_V3 rgb;
|
||||
Dqn_V3 xyz;
|
||||
struct { DN_F32 x, y, z, w; };
|
||||
struct { DN_F32 r, g, b, a; };
|
||||
#if !defined(DN_NO_V3)
|
||||
DN_V3F32 rgb;
|
||||
DN_V3F32 xyz;
|
||||
#endif
|
||||
Dqn_f32 data[4];
|
||||
DN_F32 data[4];
|
||||
};
|
||||
#endif // !defined(DQN_NO_V4)
|
||||
DQN_MSVC_WARNING_POP
|
||||
#endif // !defined(DN_NO_V4)
|
||||
DN_MSVC_WARNING_POP
|
||||
|
||||
#if !defined(DQN_NO_M4)
|
||||
// NOTE: [$MAT4] Dqn_M4 ////////////////////////////////////////////////////////////////////////////
|
||||
struct Dqn_M4
|
||||
#if !defined(DN_NO_M4)
|
||||
// NOTE: [$MAT4] DN_M4 ////////////////////////////////////////////////////////////////////////////
|
||||
struct DN_M4
|
||||
{
|
||||
Dqn_f32 columns[4][4]; // Column major matrix
|
||||
DN_F32 columns[4][4]; // Column major matrix
|
||||
};
|
||||
#endif // !defined(DQN_M4)
|
||||
#endif // !defined(DN_M4)
|
||||
|
||||
// NOTE: [$M2x3] Dqn_M2x3 //////////////////////////////////////////////////////////////////////////
|
||||
union Dqn_M2x3
|
||||
// NOTE: [$M2x3] DN_M2x3 //////////////////////////////////////////////////////////////////////////
|
||||
union DN_M2x3
|
||||
{
|
||||
Dqn_f32 e[6];
|
||||
Dqn_f32 row[2][3];
|
||||
DN_F32 e[6];
|
||||
DN_F32 row[2][3];
|
||||
};
|
||||
|
||||
// NOTE: [$RECT] Dqn_Rect //////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_NO_RECT)
|
||||
#if defined(DQN_NO_V2)
|
||||
#error "Rectangles requires V2, DQN_NO_V2 must not be defined"
|
||||
// NOTE: [$RECT] DN_Rect //////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_RECT)
|
||||
#if defined(DN_NO_V2)
|
||||
#error "Rectangles requires V2, DN_NO_V2 must not be defined"
|
||||
#endif
|
||||
struct Dqn_Rect
|
||||
struct DN_Rect
|
||||
{
|
||||
Dqn_V2 pos, size;
|
||||
DN_V2F32 pos, size;
|
||||
};
|
||||
|
||||
struct Dqn_RectMinMax
|
||||
struct DN_RectMinMax
|
||||
{
|
||||
Dqn_V2 min, max;
|
||||
DN_V2F32 min, max;
|
||||
};
|
||||
|
||||
enum Dqn_RectCutClip
|
||||
enum DN_RectCutClip
|
||||
{
|
||||
Dqn_RectCutClip_No,
|
||||
Dqn_RectCutClip_Yes,
|
||||
DN_RectCutClip_No,
|
||||
DN_RectCutClip_Yes,
|
||||
};
|
||||
|
||||
enum Dqn_RectCutSide
|
||||
enum DN_RectCutSide
|
||||
{
|
||||
Dqn_RectCutSide_Left,
|
||||
Dqn_RectCutSide_Right,
|
||||
Dqn_RectCutSide_Top,
|
||||
Dqn_RectCutSide_Bottom,
|
||||
DN_RectCutSide_Left,
|
||||
DN_RectCutSide_Right,
|
||||
DN_RectCutSide_Top,
|
||||
DN_RectCutSide_Bottom,
|
||||
};
|
||||
|
||||
struct Dqn_RectCut
|
||||
struct DN_RectCut
|
||||
{
|
||||
Dqn_Rect* rect;
|
||||
Dqn_RectCutSide side;
|
||||
DN_Rect* rect;
|
||||
DN_RectCutSide side;
|
||||
};
|
||||
#endif // !defined(DQN_NO_RECT)
|
||||
#endif // !defined(DN_NO_RECT)
|
||||
|
||||
// NOTE: [$MATH] Other /////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: API
|
||||
struct Dqn_RaycastLineIntersectV2Result
|
||||
struct DN_RaycastLineIntersectV2Result
|
||||
{
|
||||
bool hit; // True if there was an intersection, false if the lines are parallel
|
||||
Dqn_f32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)`
|
||||
Dqn_f32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)`
|
||||
DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)`
|
||||
DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)`
|
||||
};
|
||||
|
||||
#if !defined(DQN_NO_V2)
|
||||
#if !defined(DN_NO_V2)
|
||||
// NOTE: [$VEC2] Vector2 ///////////////////////////////////////////////////////////////////////////
|
||||
#define Dqn_V2I_Zero DQN_LITERAL(Dqn_V2I){{(int32_t)(0), (int32_t)(0)}}
|
||||
#define Dqn_V2I_One DQN_LITERAL(Dqn_V2I){{(int32_t)(1), (int32_t)(1)}}
|
||||
#define Dqn_V2I_InitNx1(x) DQN_LITERAL(Dqn_V2I){{(int32_t)(x), (int32_t)(x)}}
|
||||
#define Dqn_V2I_InitNx2(x, y) DQN_LITERAL(Dqn_V2I){{(int32_t)(x), (int32_t)(y)}}
|
||||
#define Dqn_V2I_InitV2(xy) DQN_LITERAL(Dqn_V2I){{(int32_t)(xy).x, (int32_t)(xy).y}}
|
||||
#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}}
|
||||
#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}}
|
||||
#define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}}
|
||||
#define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}}
|
||||
#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}}
|
||||
|
||||
DQN_API bool operator!= (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API bool operator== (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API bool operator>= (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API bool operator<= (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API bool operator< (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API bool operator> (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2I operator- (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2I operator- (Dqn_V2I lhs);
|
||||
DQN_API Dqn_V2I operator+ (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, int32_t rhs);
|
||||
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, int32_t rhs);
|
||||
DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2I & operator*= (Dqn_V2I& lhs, int32_t rhs);
|
||||
DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2I & operator/= (Dqn_V2I& lhs, int32_t rhs);
|
||||
DQN_API Dqn_V2I & operator-= (Dqn_V2I& lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2I & operator+= (Dqn_V2I& lhs, Dqn_V2I rhs);
|
||||
DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2I32 operator- (DN_V2I32 lhs);
|
||||
DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs);
|
||||
DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs);
|
||||
DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs);
|
||||
DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs);
|
||||
DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs);
|
||||
DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs);
|
||||
DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs);
|
||||
|
||||
DQN_API Dqn_V2I Dqn_V2I_Min (Dqn_V2I a, Dqn_V2I b);
|
||||
DQN_API Dqn_V2I Dqn_V2I_Max (Dqn_V2I a, Dqn_V2I b);
|
||||
DQN_API Dqn_V2I Dqn_V2I_Abs (Dqn_V2I a);
|
||||
DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b);
|
||||
DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b);
|
||||
DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a);
|
||||
|
||||
#define Dqn_V2U16_Zero DQN_LITERAL(Dqn_V2U16){{(uint16_t)(0), (uint16_t)(0)}}
|
||||
#define Dqn_V2U16_One DQN_LITERAL(Dqn_V2U16){{(uint16_t)(1), (uint16_t)(1)}}
|
||||
#define Dqn_V2U16_InitNx1(x) DQN_LITERAL(Dqn_V2U16){{(uint16_t)(x), (uint16_t)(x)}}
|
||||
#define Dqn_V2U16_InitNx2(x, y) DQN_LITERAL(Dqn_V2U16){{(uint16_t)(x), (uint16_t)(y)}}
|
||||
#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}}
|
||||
#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}}
|
||||
#define DN_V2U16_Init1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}}
|
||||
#define DN_V2U16_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}}
|
||||
|
||||
DQN_API bool operator!= (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API bool operator== (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API bool operator>= (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API bool operator<= (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API bool operator< (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API bool operator> (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API Dqn_V2U16 operator- (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API Dqn_V2U16 operator+ (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2U16 operator* (Dqn_V2U16 lhs, int32_t rhs);
|
||||
DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, Dqn_V2U16 rhs);
|
||||
DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2U16 operator/ (Dqn_V2U16 lhs, int32_t rhs);
|
||||
DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, Dqn_V2U16 rhs);
|
||||
DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2U16 & operator*= (Dqn_V2U16& lhs, int32_t rhs);
|
||||
DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, Dqn_V2U16 rhs);
|
||||
DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2U16 & operator/= (Dqn_V2U16& lhs, int32_t rhs);
|
||||
DQN_API Dqn_V2U16 & operator-= (Dqn_V2U16& lhs, Dqn_V2U16 rhs);
|
||||
DQN_API Dqn_V2U16 & operator+= (Dqn_V2U16& lhs, Dqn_V2U16 rhs);
|
||||
DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs);
|
||||
DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs);
|
||||
DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs);
|
||||
DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs);
|
||||
DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs);
|
||||
DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs);
|
||||
DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs);
|
||||
DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs);
|
||||
DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs);
|
||||
DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs);
|
||||
DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs);
|
||||
DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs);
|
||||
DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs);
|
||||
|
||||
#define Dqn_V2_Zero DQN_LITERAL(Dqn_V2){{(Dqn_f32)(0), (Dqn_f32)(0)}}
|
||||
#define Dqn_V2_One DQN_LITERAL(Dqn_V2){{(Dqn_f32)(1), (Dqn_f32)(1)}}
|
||||
#define Dqn_V2_InitNx1(x) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(x), (Dqn_f32)(x)}}
|
||||
#define Dqn_V2_InitNx2(x, y) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(x), (Dqn_f32)(y)}}
|
||||
#define Dqn_V2_InitV2I(xy) DQN_LITERAL(Dqn_V2){{(Dqn_f32)(xy).x, (Dqn_f32)(xy).y}}
|
||||
#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}}
|
||||
#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}}
|
||||
#define DN_V2F32_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}}
|
||||
#define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}}
|
||||
#define DN_V2F32_InitV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}}
|
||||
|
||||
DQN_API bool operator!= (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API bool operator== (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API bool operator>= (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API bool operator<= (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API bool operator< (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API bool operator> (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
|
||||
DQN_API Dqn_V2 operator- (Dqn_V2 lhs);
|
||||
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, int32_t rhs);
|
||||
DN_API DN_V2F32 operator- (DN_V2F32 lhs);
|
||||
DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs);
|
||||
|
||||
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, int32_t rhs);
|
||||
DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs);
|
||||
|
||||
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, int32_t rhs);
|
||||
DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs);
|
||||
|
||||
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, int32_t rhs);
|
||||
DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs);
|
||||
|
||||
DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2 & operator*= (Dqn_V2& lhs, int32_t rhs);
|
||||
DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs);
|
||||
DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs);
|
||||
DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs);
|
||||
|
||||
DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2 & operator/= (Dqn_V2& lhs, int32_t rhs);
|
||||
DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs);
|
||||
DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs);
|
||||
DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs);
|
||||
|
||||
DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2 & operator-= (Dqn_V2& lhs, int32_t rhs);
|
||||
DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs);
|
||||
DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs);
|
||||
DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs);
|
||||
|
||||
DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_V2I rhs);
|
||||
DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V2 & operator+= (Dqn_V2& lhs, int32_t rhs);
|
||||
DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs);
|
||||
DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs);
|
||||
DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs);
|
||||
DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs);
|
||||
|
||||
DQN_API Dqn_V2 Dqn_V2_Min (Dqn_V2 a, Dqn_V2 b);
|
||||
DQN_API Dqn_V2 Dqn_V2_Max (Dqn_V2 a, Dqn_V2 b);
|
||||
DQN_API Dqn_V2 Dqn_V2_Abs (Dqn_V2 a);
|
||||
DQN_API Dqn_f32 Dqn_V2_Dot (Dqn_V2 a, Dqn_V2 b);
|
||||
DQN_API Dqn_f32 Dqn_V2_LengthSq_V2x2 (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_f32 Dqn_V2_Length_V2x2 (Dqn_V2 lhs, Dqn_V2 rhs);
|
||||
DQN_API Dqn_f32 Dqn_V2_LengthSq (Dqn_V2 lhs);
|
||||
DQN_API Dqn_f32 Dqn_V2_Length (Dqn_V2 lhs);
|
||||
DQN_API Dqn_V2 Dqn_V2_Normalise (Dqn_V2 a);
|
||||
DQN_API Dqn_V2 Dqn_V2_Perpendicular (Dqn_V2 a);
|
||||
DQN_API Dqn_V2 Dqn_V2_Reflect (Dqn_V2 in, Dqn_V2 surface);
|
||||
DQN_API Dqn_f32 Dqn_V2_Area (Dqn_V2 a);
|
||||
#endif // !defined(DQN_NO_V2)
|
||||
#if !defined(DQN_NO_V3)
|
||||
DN_API DN_V2F32 DN_V2_Min (DN_V2F32 a, DN_V2F32 b);
|
||||
DN_API DN_V2F32 DN_V2_Max (DN_V2F32 a, DN_V2F32 b);
|
||||
DN_API DN_V2F32 DN_V2_Abs (DN_V2F32 a);
|
||||
DN_API DN_F32 DN_V2_Dot (DN_V2F32 a, DN_V2F32 b);
|
||||
DN_API DN_F32 DN_V2_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API DN_F32 DN_V2_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs);
|
||||
DN_API DN_F32 DN_V2_LengthSq (DN_V2F32 lhs);
|
||||
DN_API DN_F32 DN_V2_Length (DN_V2F32 lhs);
|
||||
DN_API DN_V2F32 DN_V2_Normalise (DN_V2F32 a);
|
||||
DN_API DN_V2F32 DN_V2_Perpendicular (DN_V2F32 a);
|
||||
DN_API DN_V2F32 DN_V2_Reflect (DN_V2F32 in, DN_V2F32 surface);
|
||||
DN_API DN_F32 DN_V2_Area (DN_V2F32 a);
|
||||
#endif // !defined(DN_NO_V2)
|
||||
#if !defined(DN_NO_V3)
|
||||
// NOTE: [$VEC3] Vector3 ///////////////////////////////////////////////////////////////////////////
|
||||
#define Dqn_V3_InitNx1(x) DQN_LITERAL(Dqn_V3){{(Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x)}}
|
||||
#define Dqn_V3_InitNx3(x, y, z) DQN_LITERAL(Dqn_V3){{(Dqn_f32)(x), (Dqn_f32)(y), (Dqn_f32)(z)}}
|
||||
#define Dqn_V3_InitV2x1_Nx1(xy, z) DQN_LITERAL(Dqn_V3){{(Dqn_f32)(xy.x), (Dqn_f32)(xy.y), (Dqn_f32)(z)}}
|
||||
#define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}}
|
||||
#define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}}
|
||||
#define DN_V3F32_InitV2F32_1F32(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}}
|
||||
|
||||
DQN_API bool operator!= (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API bool operator== (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API bool operator>= (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API bool operator<= (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API bool operator< (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API bool operator> (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_V3 operator- (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_V3 operator- (Dqn_V3 lhs);
|
||||
DQN_API Dqn_V3 operator+ (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, int32_t rhs);
|
||||
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, int32_t rhs);
|
||||
DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V3 & operator*= (Dqn_V3 &lhs, int32_t rhs);
|
||||
DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V3 & operator/= (Dqn_V3 &lhs, int32_t rhs);
|
||||
DQN_API Dqn_V3 & operator-= (Dqn_V3 &lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_V3 & operator+= (Dqn_V3 &lhs, Dqn_V3 rhs);
|
||||
DQN_API Dqn_f32 Dqn_V3_LengthSq (Dqn_V3 a);
|
||||
DQN_API Dqn_f32 Dqn_V3_Length (Dqn_V3 a);
|
||||
DQN_API Dqn_V3 Dqn_V3_Normalise (Dqn_V3 a);
|
||||
#endif // !defined(DQN_NO_V3)
|
||||
#if !defined(DQN_NO_V4)
|
||||
DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API DN_V3F32 operator- (DN_V3F32 lhs);
|
||||
DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs);
|
||||
DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs);
|
||||
DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs);
|
||||
DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs);
|
||||
DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs);
|
||||
DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs);
|
||||
DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs);
|
||||
DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs);
|
||||
DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs);
|
||||
DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs);
|
||||
DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs);
|
||||
DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a);
|
||||
DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a);
|
||||
DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a);
|
||||
#endif // !defined(DN_NO_V3)
|
||||
#if !defined(DN_NO_V4)
|
||||
// NOTE: [$VEC4] Vector4 ///////////////////////////////////////////////////////////////////////////
|
||||
#define Dqn_V4_InitNx1(x) DQN_LITERAL(Dqn_V4){{(Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x)}}
|
||||
#define Dqn_V4_InitNx4(x, y, z, w) DQN_LITERAL(Dqn_V4){{(Dqn_f32)(x), (Dqn_f32)(y), (Dqn_f32)(z), (Dqn_f32)(w)}}
|
||||
#define Dqn_V4_Init_V3x1_Nx1(xyz, w) DQN_LITERAL(Dqn_V4){{xyz.x, xyz.y, xyz.z, w}}
|
||||
DQN_API bool operator!= (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API bool operator== (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API bool operator>= (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API bool operator<= (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API bool operator< (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API bool operator> (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API Dqn_V4 operator- (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API Dqn_V4 operator- (Dqn_V4 lhs);
|
||||
DQN_API Dqn_V4 operator+ (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API Dqn_V4 operator* (Dqn_V4 lhs, Dqn_V4 rhs);
|
||||
DQN_API Dqn_V4 operator* (Dqn_V4 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V4 operator* (Dqn_V4 lhs, int32_t rhs);
|
||||
DQN_API Dqn_V4 operator/ (Dqn_V4 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, Dqn_V4 rhs);
|
||||
DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_V4 & operator*= (Dqn_V4 &lhs, int32_t rhs);
|
||||
DQN_API Dqn_V4 & operator-= (Dqn_V4 &lhs, Dqn_V4 rhs);
|
||||
DQN_API Dqn_V4 & operator+= (Dqn_V4 &lhs, Dqn_V4 rhs);
|
||||
#endif // !defined(DQN_NO_V4)
|
||||
#if !defined(DQN_NO_M4)
|
||||
// NOTE: [$MAT4] Dqn_M4 ////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_f32 Dqn_V4Dot (Dqn_V4 a, Dqn_V4 b);
|
||||
DQN_API Dqn_M4 Dqn_M4_Identity ();
|
||||
DQN_API Dqn_M4 Dqn_M4_ScaleF (Dqn_f32 x, Dqn_f32 y, Dqn_f32 z);
|
||||
DQN_API Dqn_M4 Dqn_M4_Scale (Dqn_V3 xyz);
|
||||
DQN_API Dqn_M4 Dqn_M4_TranslateF (Dqn_f32 x, Dqn_f32 y, Dqn_f32 z);
|
||||
DQN_API Dqn_M4 Dqn_M4_Translate (Dqn_V3 xyz);
|
||||
DQN_API Dqn_M4 Dqn_M4_Transpose (Dqn_M4 mat);
|
||||
DQN_API Dqn_M4 Dqn_M4_Rotate (Dqn_V3 axis, Dqn_f32 radians);
|
||||
DQN_API Dqn_M4 Dqn_M4_Orthographic (Dqn_f32 left, Dqn_f32 right, Dqn_f32 bottom, Dqn_f32 top, Dqn_f32 z_near, Dqn_f32 z_far);
|
||||
DQN_API Dqn_M4 Dqn_M4_Perspective (Dqn_f32 fov /*radians*/, Dqn_f32 aspect, Dqn_f32 z_near, Dqn_f32 z_far);
|
||||
DQN_API Dqn_M4 Dqn_M4_Add (Dqn_M4 lhs, Dqn_M4 rhs);
|
||||
DQN_API Dqn_M4 Dqn_M4_Sub (Dqn_M4 lhs, Dqn_M4 rhs);
|
||||
DQN_API Dqn_M4 Dqn_M4_Mul (Dqn_M4 lhs, Dqn_M4 rhs);
|
||||
DQN_API Dqn_M4 Dqn_M4_Div (Dqn_M4 lhs, Dqn_M4 rhs);
|
||||
DQN_API Dqn_M4 Dqn_M4_AddF (Dqn_M4 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_M4 Dqn_M4_SubF (Dqn_M4 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_M4 Dqn_M4_MulF (Dqn_M4 lhs, Dqn_f32 rhs);
|
||||
DQN_API Dqn_M4 Dqn_M4_DivF (Dqn_M4 lhs, Dqn_f32 rhs);
|
||||
#if !defined(DQN_NO_FSTR8)
|
||||
DQN_API Dqn_FStr8<256> Dqn_M4_ColumnMajorString (Dqn_M4 mat);
|
||||
#define DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}}
|
||||
#define DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}}
|
||||
#define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}}
|
||||
DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs);
|
||||
DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs);
|
||||
DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs);
|
||||
DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs);
|
||||
DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs);
|
||||
DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs);
|
||||
DN_API DN_V4F32 operator- (DN_V4F32 lhs);
|
||||
DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs);
|
||||
DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs);
|
||||
DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs);
|
||||
DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs);
|
||||
DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs);
|
||||
DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs);
|
||||
DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs);
|
||||
DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs);
|
||||
DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs);
|
||||
#endif // !defined(DN_NO_V4)
|
||||
#if !defined(DN_NO_M4)
|
||||
// NOTE: [$MAT4] DN_M4 ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b);
|
||||
DN_API DN_M4 DN_M4_Identity ();
|
||||
DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z);
|
||||
DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz);
|
||||
DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z);
|
||||
DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz);
|
||||
DN_API DN_M4 DN_M4_Transpose (DN_M4 mat);
|
||||
DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians);
|
||||
DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far);
|
||||
DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far);
|
||||
DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs);
|
||||
DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs);
|
||||
DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs);
|
||||
DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs);
|
||||
DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs);
|
||||
DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs);
|
||||
DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs);
|
||||
DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs);
|
||||
#if !defined(DN_NO_FSTR8)
|
||||
DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat);
|
||||
#endif
|
||||
#endif // !defined(DQN_NO_M4)
|
||||
// NOTE: [$M2x3] Dqn_M2x3 //////////////////////////////////////////////////////////////////////////
|
||||
DQN_API bool operator== (Dqn_M2x3 const &lhs, Dqn_M2x3 const &rhs);
|
||||
DQN_API bool operator!= (Dqn_M2x3 const &lhs, Dqn_M2x3 const &rhs);
|
||||
DQN_API Dqn_M2x3 Dqn_M2x3_Identity ();
|
||||
DQN_API Dqn_M2x3 Dqn_M2x3_Translate (Dqn_V2 offset);
|
||||
DQN_API Dqn_M2x3 Dqn_M2x3_Scale (Dqn_V2 scale);
|
||||
DQN_API Dqn_M2x3 Dqn_M2x3_Rotate (Dqn_f32 radians);
|
||||
DQN_API Dqn_M2x3 Dqn_M2x3_Mul (Dqn_M2x3 m1, Dqn_M2x3 m2);
|
||||
DQN_API Dqn_V2 Dqn_M2x3_Mul2F32 (Dqn_M2x3 m1, Dqn_f32 x, Dqn_f32 y);
|
||||
DQN_API Dqn_V2 Dqn_M2x3_MulV2 (Dqn_M2x3 m1, Dqn_V2 v2);
|
||||
#endif // !defined(DN_NO_M4)
|
||||
// NOTE: [$M2x3] DN_M2x3 //////////////////////////////////////////////////////////////////////////
|
||||
DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs);
|
||||
DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs);
|
||||
DN_API DN_M2x3 DN_M2x3_Identity ();
|
||||
DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset);
|
||||
DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale);
|
||||
DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians);
|
||||
DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2);
|
||||
DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y);
|
||||
DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2);
|
||||
#if !defined(DN_NO_RECT)
|
||||
// NOTE: [$RECT] DN_Rect //////////////////////////////////////////////////////////////////////////
|
||||
#define DN_Rect_Init2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)}
|
||||
#define DN_Rect_Init4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}}
|
||||
|
||||
#if !defined(DQN_NO_RECT)
|
||||
// NOTE: [$RECT] Dqn_Rect //////////////////////////////////////////////////////////////////////////
|
||||
#define Dqn_Rect_InitV2x2(pos, size) DQN_LITERAL(Dqn_Rect){(pos), (size)}
|
||||
#define Dqn_Rect_InitNx4(x, y, w, h) DQN_LITERAL(Dqn_Rect){DQN_LITERAL(Dqn_V2){{x, y}}, DQN_LITERAL(Dqn_V2){{w, h}}}
|
||||
DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs);
|
||||
DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect);
|
||||
DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p);
|
||||
DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b);
|
||||
DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount);
|
||||
DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount);
|
||||
DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b);
|
||||
DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b);
|
||||
DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b);
|
||||
DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a);
|
||||
DN_API DN_F32 DN_Rect_Area (DN_Rect a);
|
||||
DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01);
|
||||
DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect);
|
||||
DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect);
|
||||
DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect);
|
||||
DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect);
|
||||
|
||||
DQN_API bool operator== (const Dqn_Rect& lhs, const Dqn_Rect& rhs);
|
||||
DQN_API Dqn_V2 Dqn_Rect_Center (Dqn_Rect rect);
|
||||
DQN_API bool Dqn_Rect_ContainsPoint (Dqn_Rect rect, Dqn_V2 p);
|
||||
DQN_API bool Dqn_Rect_ContainsRect (Dqn_Rect a, Dqn_Rect b);
|
||||
DQN_API Dqn_Rect Dqn_Rect_Expand (Dqn_Rect a, Dqn_f32 amount);
|
||||
DQN_API Dqn_Rect Dqn_Rect_ExpandV2 (Dqn_Rect a, Dqn_V2 amount);
|
||||
DQN_API bool Dqn_Rect_Intersects (Dqn_Rect a, Dqn_Rect b);
|
||||
DQN_API Dqn_Rect Dqn_Rect_Intersection (Dqn_Rect a, Dqn_Rect b);
|
||||
DQN_API Dqn_Rect Dqn_Rect_Union (Dqn_Rect a, Dqn_Rect b);
|
||||
DQN_API Dqn_RectMinMax Dqn_Rect_MinMax (Dqn_Rect a);
|
||||
DQN_API Dqn_f32 Dqn_Rect_Area (Dqn_Rect a);
|
||||
DQN_API Dqn_V2 Dqn_Rect_InterpolatedPoint (Dqn_Rect rect, Dqn_V2 t01);
|
||||
DQN_API Dqn_V2 Dqn_Rect_TopLeft (Dqn_Rect rect);
|
||||
DQN_API Dqn_V2 Dqn_Rect_TopRight (Dqn_Rect rect);
|
||||
DQN_API Dqn_V2 Dqn_Rect_BottomLeft (Dqn_Rect rect);
|
||||
DQN_API Dqn_V2 Dqn_Rect_BottomRight (Dqn_Rect rect);
|
||||
DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
|
||||
DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
|
||||
DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
|
||||
DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
|
||||
|
||||
DQN_API Dqn_Rect Dqn_Rect_CutLeftClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip);
|
||||
DQN_API Dqn_Rect Dqn_Rect_CutRightClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip);
|
||||
DQN_API Dqn_Rect Dqn_Rect_CutTopClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip);
|
||||
DQN_API Dqn_Rect Dqn_Rect_CutBottomClip (Dqn_Rect *rect, Dqn_f32 amount, Dqn_RectCutClip clip);
|
||||
#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes)
|
||||
#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes)
|
||||
#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes)
|
||||
#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes)
|
||||
|
||||
#define Dqn_Rect_CutLeft(rect, amount) Dqn_Rect_CutLeftClip(rect, amount, Dqn_RectCutClip_Yes)
|
||||
#define Dqn_Rect_CutRight(rect, amount) Dqn_Rect_CutRightClip(rect, amount, Dqn_RectCutClip_Yes)
|
||||
#define Dqn_Rect_CutTop(rect, amount) Dqn_Rect_CutTopClip(rect, amount, Dqn_RectCutClip_Yes)
|
||||
#define Dqn_Rect_CutBottom(rect, amount) Dqn_Rect_CutBottomClip(rect, amount, Dqn_RectCutClip_Yes)
|
||||
#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No)
|
||||
#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No)
|
||||
#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No)
|
||||
#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No)
|
||||
|
||||
#define Dqn_Rect_CutLeftNoClip(rect, amount) Dqn_Rect_CutLeftClip(rect, amount, Dqn_RectCutClip_No)
|
||||
#define Dqn_Rect_CutRightNoClip(rect, amount) Dqn_Rect_CutRightClip(rect, amount, Dqn_RectCutClip_No)
|
||||
#define Dqn_Rect_CutTopNoClip(rect, amount) Dqn_Rect_CutTopClip(rect, amount, Dqn_RectCutClip_No)
|
||||
#define Dqn_Rect_CutBottomNoClip(rect, amount) Dqn_Rect_CutBottomClip(rect, amount, Dqn_RectCutClip_No)
|
||||
|
||||
DQN_API Dqn_Rect Dqn_RectCut_Cut (Dqn_RectCut rect_cut, Dqn_V2 size, Dqn_RectCutClip clip);
|
||||
#define Dqn_RectCut_Init(rect, side) DQN_LITERAL(Dqn_RectCut){rect, side}
|
||||
#define Dqn_RectCut_Left(rect) DQN_LITERAL(Dqn_RectCut){rect, Dqn_RectCutSide_Left}
|
||||
#define Dqn_RectCut_Right(rect) DQN_LITERAL(Dqn_RectCut){rect, Dqn_RectCutSide_Right}
|
||||
#define Dqn_RectCut_Top(rect) DQN_LITERAL(Dqn_RectCut){rect, Dqn_RectCutSide_Top}
|
||||
#define Dqn_RectCut_Bottom(rect) DQN_LITERAL(Dqn_RectCut){rect, Dqn_RectCutSide_Bottom}
|
||||
#endif // !defined(DQN_NO_RECT)
|
||||
DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip);
|
||||
#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side}
|
||||
#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left}
|
||||
#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right}
|
||||
#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top}
|
||||
#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom}
|
||||
#endif // !defined(DN_NO_RECT)
|
||||
// NOTE: [$MATH] Other /////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_RaycastLineIntersectV2Result Dqn_Raycast_LineIntersectV2(Dqn_V2 origin_a, Dqn_V2 dir_a, Dqn_V2 origin_b, Dqn_V2 dir_b);
|
||||
DQN_API Dqn_V2 Dqn_Lerp_V2 (Dqn_V2 a, Dqn_f32 t, Dqn_V2 b);
|
||||
DQN_API Dqn_f32 Dqn_Lerp_F32 (Dqn_f32 a, Dqn_f32 t, Dqn_f32 b);
|
||||
DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b);
|
||||
DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b);
|
||||
DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b);
|
||||
|
367
dqn_os.cpp
367
dqn_os.cpp
@ -19,11 +19,11 @@
|
||||
*/
|
||||
|
||||
// NOTE: [$DATE] Date //////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8(Dqn_OSDateTime time, char date_separator, char hms_separator)
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8(DN_OSDateTime time, char date_separator, char hms_separator)
|
||||
{
|
||||
Dqn_OSDateTimeStr8 result = {};
|
||||
result.hms_size = DQN_CAST(uint8_t) DQN_SNPRINTF(result.hms,
|
||||
DQN_ARRAY_ICOUNT(result.hms),
|
||||
DN_OSDateTimeStr8 result = {};
|
||||
result.hms_size = DN_CAST(uint8_t) DN_SNPRINTF(result.hms,
|
||||
DN_ARRAY_ICOUNT(result.hms),
|
||||
"%02hhu%c%02hhu%c%02hhu",
|
||||
time.hour,
|
||||
hms_separator,
|
||||
@ -31,8 +31,8 @@ DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8(Dqn_OSDateTime time, char da
|
||||
hms_separator,
|
||||
time.seconds);
|
||||
|
||||
result.date_size = DQN_CAST(uint8_t) DQN_SNPRINTF(result.date,
|
||||
DQN_ARRAY_ICOUNT(result.date),
|
||||
result.date_size = DN_CAST(uint8_t) DN_SNPRINTF(result.date,
|
||||
DN_ARRAY_ICOUNT(result.date),
|
||||
"%hu%c%02hhu%c%02hhu",
|
||||
time.year,
|
||||
date_separator,
|
||||
@ -40,19 +40,25 @@ DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8(Dqn_OSDateTime time, char da
|
||||
date_separator,
|
||||
time.day);
|
||||
|
||||
DQN_ASSERT(result.hms_size < DQN_ARRAY_UCOUNT(result.hms));
|
||||
DQN_ASSERT(result.date_size < DQN_ARRAY_UCOUNT(result.date));
|
||||
DN_ASSERT(result.hms_size < DN_ARRAY_UCOUNT(result.hms));
|
||||
DN_ASSERT(result.date_size < DN_ARRAY_UCOUNT(result.date));
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator)
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator, char hms_separator)
|
||||
{
|
||||
Dqn_OSDateTime time = Dqn_OS_DateLocalTimeNow();
|
||||
Dqn_OSDateTimeStr8 result = Dqn_OS_DateLocalTimeStr8(time, date_separator, hms_separator);
|
||||
DN_OSDateTime time = DN_OS_DateLocalTimeNow();
|
||||
DN_OSDateTimeStr8 result = DN_OS_DateLocalTimeStr8(time, date_separator, hms_separator);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_DateIsValid(Dqn_OSDateTime date)
|
||||
DN_API uint64_t DN_OS_DateUnixTimeS()
|
||||
{
|
||||
uint64_t result = DN_OS_DateUnixTimeNs() / (1'000 /*us*/ * 1'000 /*ms*/ * 1'000 /*s*/);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_DateIsValid(DN_OSDateTime date)
|
||||
{
|
||||
if (date.year < 1970)
|
||||
return false;
|
||||
@ -70,245 +76,245 @@ DQN_API bool Dqn_OS_DateIsValid(Dqn_OSDateTime date)
|
||||
}
|
||||
|
||||
// NOTE: Other /////////////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_Str8 Dqn_OS_EXEDir(Dqn_Arena *arena)
|
||||
DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena)
|
||||
{
|
||||
Dqn_Str8 result = {};
|
||||
DN_Str8 result = {};
|
||||
if (!arena)
|
||||
return result;
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena);
|
||||
Dqn_Str8 exe_path = Dqn_OS_EXEPath(tmem.arena);
|
||||
Dqn_Str8 separators[] = {DQN_STR8("/"), DQN_STR8("\\")};
|
||||
Dqn_Str8BinarySplitResult split = Dqn_Str8_BinarySplitLastArray(exe_path, separators, DQN_ARRAY_UCOUNT(separators));
|
||||
result = Dqn_Str8_Copy(arena, split.lhs);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(arena);
|
||||
DN_Str8 exe_path = DN_OS_EXEPath(tmem.arena);
|
||||
DN_Str8 separators[] = {DN_STR8("/"), DN_STR8("\\")};
|
||||
DN_Str8BinarySplitResult split = DN_Str8_BinarySplitLastArray(exe_path, separators, DN_ARRAY_UCOUNT(separators));
|
||||
result = DN_Str8_Copy(arena, split.lhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Counters //////////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_f64 Dqn_OS_PerfCounterS(uint64_t begin, uint64_t end)
|
||||
DN_API DN_F64 DN_OS_PerfCounterS(uint64_t begin, uint64_t end)
|
||||
{
|
||||
uint64_t frequency = Dqn_OS_PerfCounterFrequency();
|
||||
uint64_t frequency = DN_OS_PerfCounterFrequency();
|
||||
uint64_t ticks = end - begin;
|
||||
Dqn_f64 result = ticks / DQN_CAST(Dqn_f64)frequency;
|
||||
DN_F64 result = ticks / DN_CAST(DN_F64)frequency;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_f64 Dqn_OS_PerfCounterMs(uint64_t begin, uint64_t end)
|
||||
DN_API DN_F64 DN_OS_PerfCounterMs(uint64_t begin, uint64_t end)
|
||||
{
|
||||
uint64_t frequency = Dqn_OS_PerfCounterFrequency();
|
||||
uint64_t frequency = DN_OS_PerfCounterFrequency();
|
||||
uint64_t ticks = end - begin;
|
||||
Dqn_f64 result = (ticks * 1'000) / DQN_CAST(Dqn_f64)frequency;
|
||||
DN_F64 result = (ticks * 1'000) / DN_CAST(DN_F64)frequency;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_f64 Dqn_OS_PerfCounterUs(uint64_t begin, uint64_t end)
|
||||
DN_API DN_F64 DN_OS_PerfCounterUs(uint64_t begin, uint64_t end)
|
||||
{
|
||||
uint64_t frequency = Dqn_OS_PerfCounterFrequency();
|
||||
uint64_t frequency = DN_OS_PerfCounterFrequency();
|
||||
uint64_t ticks = end - begin;
|
||||
Dqn_f64 result = (ticks * 1'000'000) / DQN_CAST(Dqn_f64)frequency;
|
||||
DN_F64 result = (ticks * 1'000'000) / DN_CAST(DN_F64)frequency;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_f64 Dqn_OS_PerfCounterNs(uint64_t begin, uint64_t end)
|
||||
DN_API DN_F64 DN_OS_PerfCounterNs(uint64_t begin, uint64_t end)
|
||||
{
|
||||
uint64_t frequency = Dqn_OS_PerfCounterFrequency();
|
||||
uint64_t frequency = DN_OS_PerfCounterFrequency();
|
||||
uint64_t ticks = end - begin;
|
||||
Dqn_f64 result = (ticks * 1'000'000'000) / DQN_CAST(Dqn_f64)frequency;
|
||||
DN_F64 result = (ticks * 1'000'000'000) / DN_CAST(DN_F64)frequency;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DQN_API Dqn_OSTimer Dqn_OS_TimerBegin()
|
||||
DN_API DN_OSTimer DN_OS_TimerBegin()
|
||||
{
|
||||
Dqn_OSTimer result = {};
|
||||
result.start = Dqn_OS_PerfCounterNow();
|
||||
DN_OSTimer result = {};
|
||||
result.start = DN_OS_PerfCounterNow();
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_OS_TimerEnd(Dqn_OSTimer *timer)
|
||||
DN_API void DN_OS_TimerEnd(DN_OSTimer *timer)
|
||||
{
|
||||
timer->end = Dqn_OS_PerfCounterNow();
|
||||
timer->end = DN_OS_PerfCounterNow();
|
||||
}
|
||||
|
||||
DQN_API Dqn_f64 Dqn_OS_TimerS(Dqn_OSTimer timer)
|
||||
DN_API DN_F64 DN_OS_TimerS(DN_OSTimer timer)
|
||||
{
|
||||
Dqn_f64 result = Dqn_OS_PerfCounterS(timer.start, timer.end);
|
||||
DN_F64 result = DN_OS_PerfCounterS(timer.start, timer.end);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_f64 Dqn_OS_TimerMs(Dqn_OSTimer timer)
|
||||
DN_API DN_F64 DN_OS_TimerMs(DN_OSTimer timer)
|
||||
{
|
||||
Dqn_f64 result = Dqn_OS_PerfCounterMs(timer.start, timer.end);
|
||||
DN_F64 result = DN_OS_PerfCounterMs(timer.start, timer.end);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_f64 Dqn_OS_TimerUs(Dqn_OSTimer timer)
|
||||
DN_API DN_F64 DN_OS_TimerUs(DN_OSTimer timer)
|
||||
{
|
||||
Dqn_f64 result = Dqn_OS_PerfCounterUs(timer.start, timer.end);
|
||||
DN_F64 result = DN_OS_PerfCounterUs(timer.start, timer.end);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_f64 Dqn_OS_TimerNs(Dqn_OSTimer timer)
|
||||
DN_API DN_F64 DN_OS_TimerNs(DN_OSTimer timer)
|
||||
{
|
||||
Dqn_f64 result = Dqn_OS_PerfCounterNs(timer.start, timer.end);
|
||||
DN_F64 result = DN_OS_PerfCounterNs(timer.start, timer.end);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API uint64_t Dqn_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency)
|
||||
DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency)
|
||||
{
|
||||
uint64_t os_frequency = Dqn_OS_PerfCounterFrequency();
|
||||
uint64_t os_frequency = DN_OS_PerfCounterFrequency();
|
||||
uint64_t os_target_elapsed = duration_ms_to_gauge_tsc_frequency * os_frequency / 1000ULL;
|
||||
uint64_t tsc_begin = Dqn_CPU_TSC();
|
||||
uint64_t tsc_begin = DN_CPU_TSC();
|
||||
uint64_t result = 0;
|
||||
if (tsc_begin) {
|
||||
uint64_t os_elapsed = 0;
|
||||
for (uint64_t os_begin = Dqn_OS_PerfCounterNow(); os_elapsed < os_target_elapsed; )
|
||||
os_elapsed = Dqn_OS_PerfCounterNow() - os_begin;
|
||||
uint64_t tsc_end = Dqn_CPU_TSC();
|
||||
for (uint64_t os_begin = DN_OS_PerfCounterNow(); os_elapsed < os_target_elapsed; )
|
||||
os_elapsed = DN_OS_PerfCounterNow() - os_begin;
|
||||
uint64_t tsc_end = DN_CPU_TSC();
|
||||
uint64_t tsc_elapsed = tsc_end - tsc_begin;
|
||||
result = tsc_elapsed / os_elapsed * os_frequency;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !defined(DQN_NO_OS_FILE_API)
|
||||
// NOTE: [$FILE] Dqn_OSPathInfo/File ///////////////////////////////////////////////////////////////
|
||||
DQN_API bool Dqn_OS_FileIsOlderThan(Dqn_Str8 file, Dqn_Str8 check_against)
|
||||
#if !defined(DN_NO_OS_FILE_API)
|
||||
// NOTE: [$FILE] DN_OSPathInfo/File ///////////////////////////////////////////////////////////////
|
||||
DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against)
|
||||
{
|
||||
Dqn_OSPathInfo file_info = Dqn_OS_PathInfo(file);
|
||||
Dqn_OSPathInfo check_against_info = Dqn_OS_PathInfo(check_against);
|
||||
DN_OSPathInfo file_info = DN_OS_PathInfo(file);
|
||||
DN_OSPathInfo check_against_info = DN_OS_PathInfo(check_against);
|
||||
bool result = !file_info.exists || file_info.last_write_time_in_s < check_against_info.last_write_time_in_s;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_FileWrite(Dqn_OSFile *file, Dqn_Str8 buffer, Dqn_ErrorSink *error)
|
||||
DN_API bool DN_OS_FileWrite(DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *error)
|
||||
{
|
||||
bool result = Dqn_OS_FileWritePtr(file, buffer.data, buffer.size, error);
|
||||
bool result = DN_OS_FileWritePtr(file, buffer.data, buffer.size, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_FileWriteFV(Dqn_OSFile *file, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
DN_API bool DN_OS_FileWriteFV(DN_OSFile *file, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
bool result = false;
|
||||
if (!file || !fmt)
|
||||
return result;
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
|
||||
Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args);
|
||||
result = Dqn_OS_FileWritePtr(file, buffer.data, buffer.size, error);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
|
||||
DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args);
|
||||
result = DN_OS_FileWritePtr(file, buffer.data, buffer.size, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_FileWriteF(Dqn_OSFile *file, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool result = Dqn_OS_FileWriteFV(file, error, fmt, args);
|
||||
bool result = DN_OS_FileWriteFV(file, error, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: R/W Entire File ///////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_Str8 Dqn_OS_ReadAll(Dqn_Arena *arena, Dqn_Str8 path, Dqn_ErrorSink *error)
|
||||
DN_API DN_Str8 DN_OS_ReadAll(DN_Arena *arena, DN_Str8 path, DN_ErrSink *error)
|
||||
{
|
||||
Dqn_Str8 result = {};
|
||||
DN_Str8 result = {};
|
||||
if (!arena)
|
||||
return result;
|
||||
|
||||
// NOTE: Query file size + allocate buffer /////////////////////////////////////////////////////
|
||||
Dqn_OSPathInfo path_info = Dqn_OS_PathInfo(path);
|
||||
DN_OSPathInfo path_info = DN_OS_PathInfo(path);
|
||||
if (!path_info.exists) {
|
||||
Dqn_ErrorSink_MakeF(error, 1, "File does not exist/could not be queried for reading '%.*s'", DQN_STR_FMT(path));
|
||||
DN_ErrSink_AppendF(error, 1, "File does not exist/could not be queried for reading '%.*s'", DN_STR_FMT(path));
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_ArenaTempMem temp_mem = Dqn_Arena_TempMemBegin(arena);
|
||||
result = Dqn_Str8_Alloc(arena, path_info.size, Dqn_ZeroMem_No);
|
||||
if (!Dqn_Str8_HasData(result)) {
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
|
||||
Dqn_Str8 buffer_size_str8 = Dqn_U64ToByteSizeStr8(tmem.arena, path_info.size, Dqn_U64ByteSizeType_Auto);
|
||||
Dqn_ErrorSink_MakeF(error, 1 /*error_code*/, "Failed to allocate %.*s for reading file '%.*s'", DQN_STR_FMT(buffer_size_str8), DQN_STR_FMT(path));
|
||||
Dqn_Arena_TempMemEnd(temp_mem);
|
||||
DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(arena);
|
||||
result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No);
|
||||
if (!DN_Str8_HasData(result)) {
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
|
||||
DN_Str8 buffer_size_str8 = DN_U64ToByteSizeStr8(tmem.arena, path_info.size, DN_U64ByteSizeType_Auto);
|
||||
DN_ErrSink_AppendF(error, 1 /*error_code*/, "Failed to allocate %.*s for reading file '%.*s'", DN_STR_FMT(buffer_size_str8), DN_STR_FMT(path));
|
||||
DN_Arena_TempMemEnd(temp_mem);
|
||||
result = {};
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Read the file from disk ///////////////////////////////////////////////////////////////
|
||||
Dqn_OSFile file = Dqn_OS_FileOpen(path, Dqn_OSFileOpen_OpenIfExist, Dqn_OSFileAccess_Read, error);
|
||||
bool read_failed = !Dqn_OS_FileRead(&file, result.data, result.size, error);
|
||||
DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, error);
|
||||
bool read_failed = !DN_OS_FileRead(&file, result.data, result.size, error);
|
||||
if (file.error || read_failed) {
|
||||
Dqn_Arena_TempMemEnd(temp_mem);
|
||||
DN_Arena_TempMemEnd(temp_mem);
|
||||
result = {};
|
||||
}
|
||||
Dqn_OS_FileClose(&file);
|
||||
DN_OS_FileClose(&file);
|
||||
|
||||
return result;
|
||||
}
|
||||
DQN_API bool Dqn_OS_WriteAll(Dqn_Str8 path, Dqn_Str8 buffer, Dqn_ErrorSink *error)
|
||||
DN_API bool DN_OS_WriteAll(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error)
|
||||
{
|
||||
Dqn_OSFile file = Dqn_OS_FileOpen(path, Dqn_OSFileOpen_CreateAlways, Dqn_OSFileAccess_Write, error);
|
||||
bool result = Dqn_OS_FileWrite(&file, buffer, error);
|
||||
Dqn_OS_FileClose(&file);
|
||||
DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_Write, error);
|
||||
bool result = DN_OS_FileWrite(&file, buffer, error);
|
||||
DN_OS_FileClose(&file);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_WriteAllFV(Dqn_Str8 file_path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
DN_API bool DN_OS_WriteAllFV(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
|
||||
Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args);
|
||||
bool result = Dqn_OS_WriteAll(file_path, buffer, error);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
|
||||
DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args);
|
||||
bool result = DN_OS_WriteAll(file_path, buffer, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_WriteAllF(Dqn_Str8 file_path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API bool DN_OS_WriteAllF(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool result = Dqn_OS_WriteAllFV(file_path, error, fmt, args);
|
||||
bool result = DN_OS_WriteAllFV(file_path, error, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_WriteAllSafe(Dqn_Str8 path, Dqn_Str8 buffer, Dqn_ErrorSink *error)
|
||||
DN_API bool DN_OS_WriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error)
|
||||
{
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
|
||||
Dqn_Str8 tmp_path = Dqn_Str8_InitF(tmem.arena, "%.*s.tmp", DQN_STR_FMT(path));
|
||||
if (!Dqn_OS_WriteAll(tmp_path, buffer, error))
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
|
||||
DN_Str8 tmp_path = DN_Str8_InitF(tmem.arena, "%.*s.tmp", DN_STR_FMT(path));
|
||||
if (!DN_OS_WriteAll(tmp_path, buffer, error))
|
||||
return false;
|
||||
if (!Dqn_OS_CopyFile(tmp_path, path, true /*overwrite*/, error))
|
||||
if (!DN_OS_CopyFile(tmp_path, path, true /*overwrite*/, error))
|
||||
return false;
|
||||
if (!Dqn_OS_PathDelete(tmp_path))
|
||||
if (!DN_OS_PathDelete(tmp_path))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_WriteAllSafeFV(Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
DN_API bool DN_OS_WriteAllSafeFV(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
{
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
|
||||
Dqn_Str8 buffer = Dqn_Str8_InitFV(tmem.arena, fmt, args);
|
||||
bool result = Dqn_OS_WriteAllSafe(path, buffer, error);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(nullptr);
|
||||
DN_Str8 buffer = DN_Str8_InitFV(tmem.arena, fmt, args);
|
||||
bool result = DN_OS_WriteAllSafe(path, buffer, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_WriteAllSafeF(Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API bool DN_OS_WriteAllSafeF(DN_Str8 path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool result = Dqn_OS_WriteAllSafeFV(path, error, fmt, args);
|
||||
bool result = DN_OS_WriteAllSafeFV(path, error, fmt, args);
|
||||
return result;
|
||||
}
|
||||
#endif // !defined(DQN_NO_OS_FILE_API)
|
||||
#endif // !defined(DN_NO_OS_FILE_API)
|
||||
|
||||
// NOTE: [$PATH] Dqn_OSPath ////////////////////////////////////////////////////////////////////////
|
||||
DQN_API bool Dqn_OS_PathAddRef(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path)
|
||||
// NOTE: [$PATH] DN_OSPath ////////////////////////////////////////////////////////////////////////
|
||||
DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path)
|
||||
{
|
||||
if (!arena || !fs_path || !Dqn_Str8_HasData(path))
|
||||
if (!arena || !fs_path || !DN_Str8_HasData(path))
|
||||
return false;
|
||||
|
||||
if (path.size <= 0)
|
||||
return true;
|
||||
|
||||
Dqn_Str8 const delimiter_array[] = {
|
||||
DQN_STR8("\\"),
|
||||
DQN_STR8("/")
|
||||
DN_Str8 const delimiter_array[] = {
|
||||
DN_STR8("\\"),
|
||||
DN_STR8("/")
|
||||
};
|
||||
|
||||
if (fs_path->links_size == 0) {
|
||||
@ -316,12 +322,12 @@ DQN_API bool Dqn_OS_PathAddRef(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 p
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
Dqn_Str8BinarySplitResult delimiter = Dqn_Str8_BinarySplitArray(path, delimiter_array, DQN_ARRAY_UCOUNT(delimiter_array));
|
||||
for (; delimiter.lhs.data; delimiter = Dqn_Str8_BinarySplitArray(delimiter.rhs, delimiter_array, DQN_ARRAY_UCOUNT(delimiter_array))) {
|
||||
DN_Str8BinarySplitResult delimiter = DN_Str8_BinarySplitArray(path, delimiter_array, DN_ARRAY_UCOUNT(delimiter_array));
|
||||
for (; delimiter.lhs.data; delimiter = DN_Str8_BinarySplitArray(delimiter.rhs, delimiter_array, DN_ARRAY_UCOUNT(delimiter_array))) {
|
||||
if (delimiter.lhs.size <= 0)
|
||||
continue;
|
||||
|
||||
Dqn_OSPathLink *link = Dqn_Arena_New(arena, Dqn_OSPathLink, Dqn_ZeroMem_Yes);
|
||||
DN_OSPathLink *link = DN_Arena_New(arena, DN_OSPathLink, DN_ZeroMem_Yes);
|
||||
if (!link)
|
||||
return false;
|
||||
|
||||
@ -344,30 +350,30 @@ DQN_API bool Dqn_OS_PathAddRef(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 p
|
||||
return true;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_PathAdd(Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path)
|
||||
DN_API bool DN_OS_PathAdd(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path)
|
||||
{
|
||||
Dqn_Str8 copy = Dqn_Str8_Copy(arena, path);
|
||||
bool result = Dqn_Str8_HasData(copy) ? true : Dqn_OS_PathAddRef(arena, fs_path, copy);
|
||||
DN_Str8 copy = DN_Str8_Copy(arena, path);
|
||||
bool result = DN_Str8_HasData(copy) ? true : DN_OS_PathAddRef(arena, fs_path, copy);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_PathAddF(Dqn_Arena *arena, Dqn_OSPath *fs_path, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API bool DN_OS_PathAddF(DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_Str8 path = Dqn_Str8_InitFV(arena, fmt, args);
|
||||
DN_Str8 path = DN_Str8_InitFV(arena, fmt, args);
|
||||
va_end(args);
|
||||
bool result = Dqn_OS_PathAddRef(arena, fs_path, path);
|
||||
bool result = DN_OS_PathAddRef(arena, fs_path, path);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_OS_PathPop(Dqn_OSPath *fs_path)
|
||||
DN_API bool DN_OS_PathPop(DN_OSPath *fs_path)
|
||||
{
|
||||
if (!fs_path)
|
||||
return false;
|
||||
|
||||
if (fs_path->tail) {
|
||||
DQN_ASSERT(fs_path->head);
|
||||
DN_ASSERT(fs_path->head);
|
||||
fs_path->links_size -= 1;
|
||||
fs_path->string_size -= fs_path->tail->string.size;
|
||||
fs_path->tail = fs_path->tail->prev;
|
||||
@ -377,71 +383,71 @@ DQN_API bool Dqn_OS_PathPop(Dqn_OSPath *fs_path)
|
||||
fs_path->head = nullptr;
|
||||
}
|
||||
} else {
|
||||
DQN_ASSERT(!fs_path->head);
|
||||
DN_ASSERT(!fs_path->head);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_OS_PathTo(Dqn_Arena *arena, Dqn_Str8 path, Dqn_Str8 path_separator)
|
||||
DN_API DN_Str8 DN_OS_PathTo(DN_Arena *arena, DN_Str8 path, DN_Str8 path_separator)
|
||||
{
|
||||
Dqn_OSPath fs_path = {};
|
||||
Dqn_OS_PathAddRef(arena, &fs_path, path);
|
||||
Dqn_Str8 result = Dqn_OS_PathBuildWithSeparator(arena, &fs_path, path_separator);
|
||||
DN_OSPath fs_path = {};
|
||||
DN_OS_PathAddRef(arena, &fs_path, path);
|
||||
DN_Str8 result = DN_OS_PathBuildWithSeparator(arena, &fs_path, path_separator);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_OS_PathToF(Dqn_Arena *arena, Dqn_Str8 path_separator, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API DN_Str8 DN_OS_PathToF(DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(arena);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_Str8 path = Dqn_Str8_InitFV(tmem.arena, fmt, args);
|
||||
DN_Str8 path = DN_Str8_InitFV(tmem.arena, fmt, args);
|
||||
va_end(args);
|
||||
Dqn_Str8 result = Dqn_OS_PathTo(arena, path, path_separator);
|
||||
DN_Str8 result = DN_OS_PathTo(arena, path, path_separator);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_OS_Path(Dqn_Arena *arena, Dqn_Str8 path)
|
||||
DN_API DN_Str8 DN_OS_Path(DN_Arena *arena, DN_Str8 path)
|
||||
{
|
||||
Dqn_Str8 result = Dqn_OS_PathTo(arena, path, Dqn_OSPathSeperatorString);
|
||||
DN_Str8 result = DN_OS_PathTo(arena, path, DN_OSPathSeperatorString);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_OS_PathF(Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
DN_API DN_Str8 DN_OS_PathF(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...)
|
||||
{
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena);
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(arena);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_Str8 path = Dqn_Str8_InitFV(tmem.arena, fmt, args);
|
||||
DN_Str8 path = DN_Str8_InitFV(tmem.arena, fmt, args);
|
||||
va_end(args);
|
||||
Dqn_Str8 result = Dqn_OS_Path(arena, path);
|
||||
DN_Str8 result = DN_OS_Path(arena, path);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_OS_PathBuildWithSeparator(Dqn_Arena *arena, Dqn_OSPath const *fs_path, Dqn_Str8 path_separator)
|
||||
DN_API DN_Str8 DN_OS_PathBuildWithSeparator(DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator)
|
||||
{
|
||||
Dqn_Str8 result = {};
|
||||
DN_Str8 result = {};
|
||||
if (!fs_path || fs_path->links_size <= 0)
|
||||
return result;
|
||||
|
||||
// NOTE: Each link except the last one needs the path separator appended to it, '/' or '\\'
|
||||
Dqn_usize string_size = (fs_path->has_prefix_path_separator ? path_separator.size : 0) + fs_path->string_size + ((fs_path->links_size - 1) * path_separator.size);
|
||||
result = Dqn_Str8_Alloc(arena, string_size, Dqn_ZeroMem_No);
|
||||
DN_USize string_size = (fs_path->has_prefix_path_separator ? path_separator.size : 0) + fs_path->string_size + ((fs_path->links_size - 1) * path_separator.size);
|
||||
result = DN_Str8_Alloc(arena, string_size, DN_ZeroMem_No);
|
||||
if (result.data) {
|
||||
char *dest = result.data;
|
||||
if (fs_path->has_prefix_path_separator) {
|
||||
DQN_MEMCPY(dest, path_separator.data, path_separator.size);
|
||||
DN_MEMCPY(dest, path_separator.data, path_separator.size);
|
||||
dest += path_separator.size;
|
||||
}
|
||||
|
||||
for (Dqn_OSPathLink *link = fs_path->head; link; link = link->next) {
|
||||
Dqn_Str8 string = link->string;
|
||||
DQN_MEMCPY(dest, string.data, string.size);
|
||||
for (DN_OSPathLink *link = fs_path->head; link; link = link->next) {
|
||||
DN_Str8 string = link->string;
|
||||
DN_MEMCPY(dest, string.data, string.size);
|
||||
dest += string.size;
|
||||
|
||||
if (link != fs_path->tail) {
|
||||
DQN_MEMCPY(dest, path_separator.data, path_separator.size);
|
||||
DN_MEMCPY(dest, path_separator.data, path_separator.size);
|
||||
dest += path_separator.size;
|
||||
}
|
||||
}
|
||||
@ -452,24 +458,23 @@ DQN_API Dqn_Str8 Dqn_OS_PathBuildWithSeparator(Dqn_Arena *arena, Dqn_OSPath cons
|
||||
}
|
||||
|
||||
|
||||
// NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_OSExecResult Dqn_OS_Exec(Dqn_Slice<Dqn_Str8> cmd_line,
|
||||
Dqn_Str8 working_dir,
|
||||
uint8_t exec_flags,
|
||||
Dqn_Arena *arena,
|
||||
Dqn_ErrorSink *error)
|
||||
// NOTE: [$EXEC] DN_OSExec ////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSExecResult DN_OS_Exec(DN_Slice<DN_Str8> cmd_line,
|
||||
DN_OSExecArgs *args,
|
||||
DN_Arena *arena,
|
||||
DN_ErrSink *error)
|
||||
{
|
||||
Dqn_OSExecAsyncHandle async_handle = Dqn_OS_ExecAsync(cmd_line, working_dir, exec_flags, error);
|
||||
Dqn_OSExecResult result = Dqn_OS_ExecWait(async_handle, arena, error);
|
||||
DN_OSExecAsyncHandle async_handle = DN_OS_ExecAsync(cmd_line, args, error);
|
||||
DN_OSExecResult result = DN_OS_ExecWait(async_handle, arena, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_OSExecResult Dqn_OS_ExecOrAbort(Dqn_Slice<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);
|
||||
Dqn_OSExecResult result = Dqn_OS_Exec(cmd_line, working_dir, exec_flags, arena, error);
|
||||
DN_ErrSink *error = DN_ErrSink_Begin(DN_ErrSinkMode_Nil);
|
||||
DN_OSExecResult result = DN_OS_Exec(cmd_line, args, arena, error);
|
||||
if (result.os_error_code) {
|
||||
Dqn_ErrorSink_EndAndExitIfErrorF(
|
||||
DN_ErrSink_EndAndExitIfErrorF(
|
||||
error,
|
||||
result.os_error_code,
|
||||
"OS failed to execute the requested command returning the error code %u",
|
||||
@ -477,49 +482,63 @@ DQN_API Dqn_OSExecResult Dqn_OS_ExecOrAbort(Dqn_Slice<Dqn_Str8> cmd_line, Dqn_St
|
||||
}
|
||||
|
||||
if (result.exit_code) {
|
||||
Dqn_ErrorSink_EndAndExitIfErrorF(
|
||||
DN_ErrSink_EndAndExitIfErrorF(
|
||||
error,
|
||||
result.exit_code,
|
||||
"OS executed command and returned non-zero exit code %u",
|
||||
result.exit_code);
|
||||
}
|
||||
|
||||
Dqn_ErrorSink_EndAndIgnore(error);
|
||||
DN_ErrSink_EndAndIgnore(error);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: [$THRD] Dqn_OSThread //////////////////////////////////////////////////////////////////////
|
||||
DQN_THREAD_LOCAL Dqn_TLS *g_dqn_os_thread_tls;
|
||||
// NOTE: [$THRD] DN_OSThread //////////////////////////////////////////////////////////////////////
|
||||
DN_THREAD_LOCAL DN_TLS *g_dn_os_thread_tls;
|
||||
|
||||
static void Dqn_OS_ThreadExecute_(void *user_context)
|
||||
static void DN_OS_ThreadExecute_(void *user_context)
|
||||
{
|
||||
Dqn_OSThread *thread = DQN_CAST(Dqn_OSThread *)user_context;
|
||||
Dqn_TLS_Init(&thread->tls);
|
||||
Dqn_OS_ThreadSetTLS(&thread->tls);
|
||||
Dqn_OS_SemaphoreWait(&thread->init_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
|
||||
DN_OSThread *thread = DN_CAST(DN_OSThread *)user_context;
|
||||
DN_TLS_Init(&thread->tls);
|
||||
DN_OS_ThreadSetTLS(&thread->tls);
|
||||
DN_OS_SemaphoreWait(&thread->init_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT);
|
||||
thread->func(thread);
|
||||
}
|
||||
|
||||
DQN_API void Dqn_OS_ThreadSetTLS(Dqn_TLS *tls)
|
||||
DN_API void DN_OS_ThreadSetTLS(DN_TLS *tls)
|
||||
{
|
||||
g_dqn_os_thread_tls = tls;
|
||||
g_dn_os_thread_tls = tls;
|
||||
}
|
||||
|
||||
// NOTE: [$HTTP] Dqn_OSHttp ////////////////////////////////////////////////////////////////////////
|
||||
DQN_API void Dqn_OS_HttpRequestWait(Dqn_OSHttpResponse *response)
|
||||
DN_API void DN_OS_ThreadSetName(DN_Str8 name)
|
||||
{
|
||||
if (response && Dqn_OS_SemaphoreIsValid(&response->on_complete_semaphore))
|
||||
Dqn_OS_SemaphoreWait(&response->on_complete_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
|
||||
DN_TLS *tls = DN_TLS_Get();
|
||||
tls->name_size = DN_CAST(uint8_t)DN_MIN(name.size, sizeof(tls->name) - 1);
|
||||
DN_MEMCPY(tls->name, name.data, tls->name_size);
|
||||
tls->name[tls->name_size] = 0;
|
||||
|
||||
#if defined(DN_OS_WIN32)
|
||||
DN_Win_ThreadSetName(name);
|
||||
#else
|
||||
DN_Posix_ThreadSetName(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
DQN_API Dqn_OSHttpResponse Dqn_OS_HttpRequest(Dqn_Arena *arena, Dqn_Str8 host, Dqn_Str8 path, Dqn_OSHttpRequestSecure secure, Dqn_Str8 method, Dqn_Str8 body, Dqn_Str8 headers)
|
||||
// NOTE: [$HTTP] DN_OSHttp ////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_HttpRequestWait(DN_OSHttpResponse *response)
|
||||
{
|
||||
if (response && DN_OS_SemaphoreIsValid(&response->on_complete_semaphore))
|
||||
DN_OS_SemaphoreWait(&response->on_complete_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT);
|
||||
}
|
||||
|
||||
DN_API DN_OSHttpResponse DN_OS_HttpRequest(DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers)
|
||||
{
|
||||
// TODO(doyle): Revise the memory allocation and its lifetime
|
||||
Dqn_OSHttpResponse result = {};
|
||||
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena);
|
||||
DN_OSHttpResponse result = {};
|
||||
DN_TLSTMem tmem = DN_TLS_TMem(arena);
|
||||
result.tmem_arena = tmem.arena;
|
||||
|
||||
Dqn_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers);
|
||||
Dqn_OS_HttpRequestWait(&result);
|
||||
DN_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers);
|
||||
DN_OS_HttpRequestWait(&result);
|
||||
return result;
|
||||
}
|
||||
|
485
dqn_os.h
485
dqn_os.h
@ -17,77 +17,77 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [$OMEM] Dqn_OSMem -- -- Memory allocation (typically virtual memory if supported)
|
||||
// [$DATE] Dqn_OSDate -- -- Date time APIs
|
||||
// [$FILE] Dqn_OSPathInfo/File -- -- File path info/reading/writing
|
||||
// [$PATH] Dqn_OSPath -- -- Construct native OS paths helpers
|
||||
// [$EXEC] Dqn_OSExec -- -- Execute programs programatically
|
||||
// [$SEMA] Dqn_OSSemaphore -- DQN_SEMAPHORE --
|
||||
// [$MUTX] Dqn_OSMutex -- --
|
||||
// [$THRD] Dqn_OSThread -- DQN_THREAD --
|
||||
// [$HTTP] Dqn_OSHttp -- --
|
||||
// [$OMEM] DN_OSMem -- -- Memory allocation (typically virtual memory if supported)
|
||||
// [$DATE] DN_OSDate -- -- Date time APIs
|
||||
// [$FILE] DN_OSPathInfo/File -- -- File path info/reading/writing
|
||||
// [$PATH] DN_OSPath -- -- Construct native OS paths helpers
|
||||
// [$EXEC] DN_OSExec -- -- Execute programs programatically
|
||||
// [$SEMA] DN_OSSemaphore -- DN_SEMAPHORE --
|
||||
// [$MUTX] DN_OSMutex -- --
|
||||
// [$THRD] DN_OSThread -- DN_THREAD --
|
||||
// [$HTTP] DN_OSHttp -- --
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$OMEM] Dqn_OSMem //////////////////////////////////////////////////////////////////////////
|
||||
enum Dqn_OSMemCommit
|
||||
// NOTE: [$OMEM] DN_OSMem //////////////////////////////////////////////////////////////////////////
|
||||
enum DN_OSMemCommit
|
||||
{
|
||||
Dqn_OSMemCommit_No,
|
||||
Dqn_OSMemCommit_Yes,
|
||||
DN_OSMemCommit_No,
|
||||
DN_OSMemCommit_Yes,
|
||||
};
|
||||
|
||||
enum Dqn_OSMemPage
|
||||
enum DN_OSMemPage
|
||||
{
|
||||
// Exception on read/write with a page. This flag overrides the read/write
|
||||
// access.
|
||||
Dqn_OSMemPage_NoAccess = 1 << 0,
|
||||
DN_OSMemPage_NoAccess = 1 << 0,
|
||||
|
||||
Dqn_OSMemPage_Read = 1 << 1, // Only read permitted on the page.
|
||||
DN_OSMemPage_Read = 1 << 1, // Only read permitted on the page.
|
||||
|
||||
// Only write permitted on the page. On Windows this is not supported and
|
||||
// will be promoted to read+write permissions.
|
||||
Dqn_OSMemPage_Write = 1 << 2,
|
||||
DN_OSMemPage_Write = 1 << 2,
|
||||
|
||||
Dqn_OSMemPage_ReadWrite = Dqn_OSMemPage_Read | Dqn_OSMemPage_Write,
|
||||
DN_OSMemPage_ReadWrite = DN_OSMemPage_Read | DN_OSMemPage_Write,
|
||||
|
||||
// Modifier used in conjunction with previous flags. Raises exception on
|
||||
// first access to the page, then, the underlying protection flags are
|
||||
// active. This is supported on Windows, on other OS's using this flag will
|
||||
// set the OS equivalent of Dqn_OSMemPage_NoAccess.
|
||||
// This flag must only be used in Dqn_OSMem_Protect
|
||||
Dqn_OSMemPage_Guard = 1 << 3,
|
||||
// set the OS equivalent of DN_OSMemPage_NoAccess.
|
||||
// This flag must only be used in DN_OSMem_Protect
|
||||
DN_OSMemPage_Guard = 1 << 3,
|
||||
|
||||
// If leak tracing is enabled, this flag will allow the allocation recorded
|
||||
// from the reserve call to be leaked, e.g. not printed when leaks are
|
||||
// dumped to the console.
|
||||
Dqn_OSMemPage_AllocRecordLeakPermitted = 1 << 4,
|
||||
DN_OSMemPage_AllocRecordLeakPermitted = 1 << 4,
|
||||
|
||||
// If leak tracing is enabled this flag will prevent any allocation record
|
||||
// from being created in the allocation table at all. If this flag is
|
||||
// enabled, 'OSMemPage_AllocRecordLeakPermitted' has no effect since the
|
||||
// record will never be created.
|
||||
Dqn_OSMemPage_NoAllocRecordEntry = 1 << 5,
|
||||
DN_OSMemPage_NoAllocRecordEntry = 1 << 5,
|
||||
|
||||
// [INTERNAL] Do not use. All flags together do not constitute a correct
|
||||
// configuration of pages.
|
||||
Dqn_OSMemPage_All = Dqn_OSMemPage_NoAccess |
|
||||
Dqn_OSMemPage_ReadWrite |
|
||||
Dqn_OSMemPage_Guard |
|
||||
Dqn_OSMemPage_AllocRecordLeakPermitted |
|
||||
Dqn_OSMemPage_NoAllocRecordEntry,
|
||||
DN_OSMemPage_All = DN_OSMemPage_NoAccess |
|
||||
DN_OSMemPage_ReadWrite |
|
||||
DN_OSMemPage_Guard |
|
||||
DN_OSMemPage_AllocRecordLeakPermitted |
|
||||
DN_OSMemPage_NoAllocRecordEntry,
|
||||
};
|
||||
|
||||
// NOTE: [$DATE] Dqn_OSDate ////////////////////////////////////////////////////////////////////////
|
||||
struct Dqn_OSDateTimeStr8
|
||||
// NOTE: [$DATE] DN_OSDate ////////////////////////////////////////////////////////////////////////
|
||||
struct DN_OSDateTimeStr8
|
||||
{
|
||||
char date[DQN_ARRAY_UCOUNT("YYYY-MM-SS")];
|
||||
char date[DN_ARRAY_UCOUNT("YYYY-MM-SS")];
|
||||
uint8_t date_size;
|
||||
char hms[DQN_ARRAY_UCOUNT("HH:MM:SS")];
|
||||
char hms[DN_ARRAY_UCOUNT("HH:MM:SS")];
|
||||
uint8_t hms_size;
|
||||
};
|
||||
|
||||
struct Dqn_OSDateTime
|
||||
struct DN_OSDateTime
|
||||
{
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
@ -97,102 +97,104 @@ struct Dqn_OSDateTime
|
||||
uint8_t seconds;
|
||||
};
|
||||
|
||||
struct Dqn_OSTimer /// Record time between two time-points using the OS's performance counter.
|
||||
struct DN_OSTimer /// Record time between two time-points using the OS's performance counter.
|
||||
{
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
};
|
||||
|
||||
#if !defined(DQN_NO_OS_FILE_API)
|
||||
// NOTE: [$FSYS] Dqn_OSFile ////////////////////////////////////////////////////////////////////////
|
||||
enum Dqn_OSPathInfoType
|
||||
#if !defined(DN_NO_OS_FILE_API)
|
||||
// NOTE: [$FSYS] DN_OSFile ////////////////////////////////////////////////////////////////////////
|
||||
enum DN_OSPathInfoType
|
||||
{
|
||||
Dqn_OSPathInfoType_Unknown,
|
||||
Dqn_OSPathInfoType_Directory,
|
||||
Dqn_OSPathInfoType_File,
|
||||
DN_OSPathInfoType_Unknown,
|
||||
DN_OSPathInfoType_Directory,
|
||||
DN_OSPathInfoType_File,
|
||||
};
|
||||
|
||||
struct Dqn_OSPathInfo
|
||||
struct DN_OSPathInfo
|
||||
{
|
||||
bool exists;
|
||||
Dqn_OSPathInfoType type;
|
||||
DN_OSPathInfoType type;
|
||||
uint64_t create_time_in_s;
|
||||
uint64_t last_write_time_in_s;
|
||||
uint64_t last_access_time_in_s;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
struct Dqn_OS_DirIterator
|
||||
struct DN_OSDirIterator
|
||||
{
|
||||
void *handle;
|
||||
Dqn_Str8 file_name;
|
||||
DN_Str8 file_name;
|
||||
char buffer[512];
|
||||
};
|
||||
|
||||
// NOTE: R/W Stream API ////////////////////////////////////////////////////////////////////////////
|
||||
struct Dqn_OSFile
|
||||
struct DN_OSFile
|
||||
{
|
||||
bool error;
|
||||
void *handle;
|
||||
};
|
||||
|
||||
enum Dqn_OSFileOpen
|
||||
enum DN_OSFileOpen
|
||||
{
|
||||
Dqn_OSFileOpen_CreateAlways, // Create file if it does not exist, otherwise, zero out the file and open
|
||||
Dqn_OSFileOpen_OpenIfExist, // Open file at path only if it exists
|
||||
Dqn_OSFileOpen_OpenAlways, // Open file at path, create file if it does not exist
|
||||
DN_OSFileOpen_CreateAlways, // Create file if it does not exist, otherwise, zero out the file and open
|
||||
DN_OSFileOpen_OpenIfExist, // Open file at path only if it exists
|
||||
DN_OSFileOpen_OpenAlways, // Open file at path, create file if it does not exist
|
||||
};
|
||||
|
||||
enum Dqn_OSFileAccess
|
||||
typedef uint32_t DN_OSFileAccess;
|
||||
enum DN_OSFileAccess_
|
||||
{
|
||||
Dqn_OSFileAccess_Read = 1 << 0,
|
||||
Dqn_OSFileAccess_Write = 1 << 1,
|
||||
Dqn_OSFileAccess_Execute = 1 << 2,
|
||||
Dqn_OSFileAccess_AppendOnly = 1 << 3, // This flag cannot be combined with any other access mode
|
||||
Dqn_OSFileAccess_ReadWrite = Dqn_OSFileAccess_Read | Dqn_OSFileAccess_Write,
|
||||
Dqn_OSFileAccess_All = Dqn_OSFileAccess_ReadWrite | Dqn_OSFileAccess_Execute,
|
||||
DN_OSFileAccess_Read = 1 << 0,
|
||||
DN_OSFileAccess_Write = 1 << 1,
|
||||
DN_OSFileAccess_Execute = 1 << 2,
|
||||
DN_OSFileAccess_AppendOnly = 1 << 3, // This flag cannot be combined with any other access mode
|
||||
DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write,
|
||||
DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly,
|
||||
};
|
||||
#endif // DQN_NO_OS_FILE_API
|
||||
#endif // DN_NO_OS_FILE_API
|
||||
|
||||
// NOTE: Dqn_OSPath ////////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(Dqn_OSPathSeperator)
|
||||
#if defined(DQN_OS_WIN32)
|
||||
#define Dqn_OSPathSeperator "\\"
|
||||
// NOTE: DN_OSPath ////////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_OSPathSeperator)
|
||||
#if defined(DN_OS_WIN32)
|
||||
#define DN_OSPathSeperator "\\"
|
||||
#else
|
||||
#define Dqn_OSPathSeperator "/"
|
||||
#define DN_OSPathSeperator "/"
|
||||
#endif
|
||||
#define Dqn_OSPathSeperatorString DQN_STR8(Dqn_OSPathSeperator)
|
||||
#define DN_OSPathSeperatorString DN_STR8(DN_OSPathSeperator)
|
||||
#endif
|
||||
|
||||
struct Dqn_OSPathLink
|
||||
struct DN_OSPathLink
|
||||
{
|
||||
Dqn_Str8 string;
|
||||
Dqn_OSPathLink *next;
|
||||
Dqn_OSPathLink *prev;
|
||||
DN_Str8 string;
|
||||
DN_OSPathLink *next;
|
||||
DN_OSPathLink *prev;
|
||||
};
|
||||
|
||||
struct Dqn_OSPath
|
||||
struct DN_OSPath
|
||||
{
|
||||
bool has_prefix_path_separator;
|
||||
Dqn_OSPathLink *head;
|
||||
Dqn_OSPathLink *tail;
|
||||
Dqn_usize string_size;
|
||||
DN_OSPathLink *head;
|
||||
DN_OSPathLink *tail;
|
||||
DN_USize string_size;
|
||||
uint16_t links_size;
|
||||
};
|
||||
|
||||
// NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
|
||||
enum Dqn_OSExecFlag
|
||||
// NOTE: [$EXEC] DN_OSExec ////////////////////////////////////////////////////////////////////////
|
||||
typedef uint32_t DN_OSExecFlags;
|
||||
enum DN_OSExecFlags_
|
||||
{
|
||||
Dqn_OSExecFlag_Nil = 0,
|
||||
Dqn_OSExecFlag_SaveStdout = 1 << 0,
|
||||
Dqn_OSExecFlag_SaveStderr = 1 << 1,
|
||||
Dqn_OSExecFlag_SaveOutput = Dqn_OSExecFlag_SaveStdout | Dqn_OSExecFlag_SaveStderr,
|
||||
Dqn_OSExecFlag_MergeStderrToStdout = 1 << 2 | Dqn_OSExecFlag_SaveOutput,
|
||||
DN_OSExecFlags_Nil = 0,
|
||||
DN_OSExecFlags_SaveStdout = 1 << 0,
|
||||
DN_OSExecFlags_SaveStderr = 1 << 1,
|
||||
DN_OSExecFlags_SaveOutput = DN_OSExecFlags_SaveStdout | DN_OSExecFlags_SaveStderr,
|
||||
DN_OSExecFlags_MergeStderrToStdout = 1 << 2 | DN_OSExecFlags_SaveOutput,
|
||||
};
|
||||
|
||||
struct Dqn_OSExecAsyncHandle
|
||||
struct DN_OSExecAsyncHandle
|
||||
{
|
||||
uint8_t exec_flags;
|
||||
DN_OSExecFlags exec_flags;
|
||||
uint32_t os_error_code;
|
||||
uint32_t exit_code;
|
||||
void *process;
|
||||
@ -202,21 +204,29 @@ struct Dqn_OSExecAsyncHandle
|
||||
void *stderr_write;
|
||||
};
|
||||
|
||||
struct Dqn_OSExecResult
|
||||
struct DN_OSExecResult
|
||||
{
|
||||
Dqn_Str8 stdout_text;
|
||||
Dqn_Str8 stderr_text;
|
||||
bool finished;
|
||||
DN_Str8 stdout_text;
|
||||
DN_Str8 stderr_text;
|
||||
uint32_t os_error_code;
|
||||
uint32_t exit_code;
|
||||
};
|
||||
|
||||
#if !defined(DQN_NO_SEMAPHORE)
|
||||
// NOTE: [$SEMA] Dqn_OSSemaphore ///////////////////////////////////////////////////////////////////
|
||||
uint32_t const DQN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX;
|
||||
|
||||
struct Dqn_OSSemaphore
|
||||
struct DN_OSExecArgs
|
||||
{
|
||||
#if defined(DQN_OS_WIN32) && !defined(DQN_OS_WIN32_USE_PTHREADS)
|
||||
DN_OSExecFlags flags;
|
||||
DN_Str8 working_dir;
|
||||
DN_Slice<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;
|
||||
#else
|
||||
sem_t posix_handle;
|
||||
@ -224,189 +234,212 @@ struct Dqn_OSSemaphore
|
||||
#endif
|
||||
};
|
||||
|
||||
enum Dqn_OSSemaphoreWaitResult
|
||||
enum DN_OSSemaphoreWaitResult
|
||||
{
|
||||
Dqn_OSSemaphoreWaitResult_Failed,
|
||||
Dqn_OSSemaphoreWaitResult_Success,
|
||||
Dqn_OSSemaphoreWaitResult_Timeout,
|
||||
DN_OSSemaphoreWaitResult_Failed,
|
||||
DN_OSSemaphoreWaitResult_Success,
|
||||
DN_OSSemaphoreWaitResult_Timeout,
|
||||
};
|
||||
#endif // !defined(DQN_NO_SEMAPHORE)
|
||||
#endif // !defined(DN_NO_SEMAPHORE)
|
||||
|
||||
// NOTE: [$THRD] Dqn_OSThread /////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_NO_THREAD) && !defined(DQN_NO_SEMAPHORE)
|
||||
typedef int32_t (Dqn_OSThreadFunc)(struct Dqn_OSThread*);
|
||||
// NOTE: [$THRD] DN_OSThread /////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_THREAD) && !defined(DN_NO_SEMAPHORE)
|
||||
typedef int32_t (DN_OSThreadFunc)(struct DN_OSThread*);
|
||||
|
||||
struct Dqn_OSThread
|
||||
struct DN_OSThread
|
||||
{
|
||||
Dqn_TLS tls;
|
||||
DN_FStr8<64> name;
|
||||
DN_TLS tls;
|
||||
void *handle;
|
||||
uint64_t thread_id;
|
||||
void *user_context;
|
||||
Dqn_OSThreadFunc *func;
|
||||
Dqn_OSSemaphore init_semaphore;
|
||||
DN_OSThreadFunc *func;
|
||||
DN_OSSemaphore init_semaphore;
|
||||
};
|
||||
#endif // !defined(DQN_NO_THREAD)
|
||||
#endif // !defined(DN_NO_THREAD)
|
||||
|
||||
// NOTE: [$HTTP] Dqn_OSHttp ////////////////////////////////////////////////////////////////////////
|
||||
enum Dqn_OSHttpRequestSecure
|
||||
// NOTE: [$HTTP] DN_OSHttp ////////////////////////////////////////////////////////////////////////
|
||||
enum DN_OSHttpRequestSecure
|
||||
{
|
||||
Dqn_OSHttpRequestSecure_No,
|
||||
Dqn_OSHttpRequestSecure_Yes,
|
||||
DN_OSHttpRequestSecure_No,
|
||||
DN_OSHttpRequestSecure_Yes,
|
||||
};
|
||||
|
||||
struct Dqn_OSHttpResponse
|
||||
struct DN_OSHttpResponse
|
||||
{
|
||||
// NOTE: Response data
|
||||
uint32_t error_code;
|
||||
Dqn_Str8 error_msg;
|
||||
DN_Str8 error_msg;
|
||||
uint16_t http_status;
|
||||
Dqn_Str8 body;
|
||||
Dqn_b32 done;
|
||||
DN_Str8 body;
|
||||
DN_B32 done;
|
||||
|
||||
// NOTE: Book-keeping
|
||||
Dqn_Arena *arena; // Allocates memory for the response
|
||||
DN_Arena *arena; // Allocates memory for the response
|
||||
|
||||
// NOTE: Async book-keeping
|
||||
// Synchronous HTTP response uses the TLS scratch arena whereas async
|
||||
// calls use their own dedicated arena.
|
||||
Dqn_Arena tmp_arena;
|
||||
Dqn_Arena *tmem_arena;
|
||||
Dqn_Str8Builder builder;
|
||||
Dqn_OSSemaphore on_complete_semaphore;
|
||||
DN_Arena tmp_arena;
|
||||
DN_Arena *tmem_arena;
|
||||
DN_Str8Builder builder;
|
||||
DN_OSSemaphore on_complete_semaphore;
|
||||
|
||||
#if defined(DQN_PLATFORM_EMSCRIPTEN)
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
emscripten_fetch_t *em_handle;
|
||||
#elif defined(DQN_OS_WIN32)
|
||||
#elif defined(DN_OS_WIN32)
|
||||
HINTERNET win32_request_session;
|
||||
HINTERNET win32_request_connection;
|
||||
HINTERNET win32_request_handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
DN_API void DN_OS_Init();
|
||||
|
||||
// NOTE: [$OMEM] Memory //////////////////////////////////////////////////////////////////////////
|
||||
DQN_API void * Dqn_OS_MemReserve (Dqn_usize size, Dqn_OSMemCommit commit, uint32_t page_flags);
|
||||
DQN_API bool Dqn_OS_MemCommit (void *ptr, Dqn_usize size, uint32_t page_flags);
|
||||
DQN_API void Dqn_OS_MemDecommit(void *ptr, Dqn_usize size);
|
||||
DQN_API void Dqn_OS_MemRelease (void *ptr, Dqn_usize size);
|
||||
DQN_API int Dqn_OS_MemProtect (void *ptr, Dqn_usize size, uint32_t page_flags);
|
||||
DN_API void * DN_OS_MemReserve (DN_USize size, DN_OSMemCommit commit, uint32_t page_flags);
|
||||
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, uint32_t page_flags);
|
||||
DN_API void DN_OS_MemDecommit(void *ptr, DN_USize size);
|
||||
DN_API void DN_OS_MemRelease (void *ptr, DN_USize size);
|
||||
DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, uint32_t page_flags);
|
||||
|
||||
// NOTE: Heap
|
||||
DN_API void *DN_OS_MemAlloc (DN_USize size, DN_ZeroMem zero_mem);
|
||||
DN_API void DN_OS_MemDealloc (void *ptr);
|
||||
|
||||
// NOTE: [$DATE] Date //////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_OSDateTime Dqn_OS_DateLocalTimeNow ();
|
||||
DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8Now(char date_separator = '-', char hms_separator = ':');
|
||||
DQN_API Dqn_OSDateTimeStr8 Dqn_OS_DateLocalTimeStr8 (Dqn_OSDateTime time, char date_separator = '-', char hms_separator = ':');
|
||||
DQN_API uint64_t Dqn_OS_DateUnixTime ();
|
||||
DQN_API Dqn_OSDateTime Dqn_OS_DateUnixTimeToDate (uint64_t time);
|
||||
DQN_API uint64_t Dqn_OS_DateToUnixTime (Dqn_OSDateTime date);
|
||||
DQN_API bool Dqn_OS_DateIsValid (Dqn_OSDateTime date);
|
||||
DN_API DN_OSDateTime DN_OS_DateLocalTimeNow ();
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator = '-', char hms_separator = ':');
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':');
|
||||
DN_API uint64_t DN_OS_DateUnixTimeNs ();
|
||||
DN_API uint64_t DN_OS_DateUnixTimeS ();
|
||||
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (uint64_t time);
|
||||
DN_API uint64_t DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date);
|
||||
DN_API uint64_t DN_OS_DateToUnixTimeS (DN_OSDateTime date);
|
||||
DN_API bool DN_OS_DateIsValid (DN_OSDateTime date);
|
||||
|
||||
// NOTE: Other /////////////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API bool Dqn_OS_SecureRNGBytes (void *buffer, uint32_t size);
|
||||
DQN_API Dqn_Str8 Dqn_OS_EXEPath (Dqn_Arena *arena);
|
||||
DQN_API Dqn_Str8 Dqn_OS_EXEDir (Dqn_Arena *arena);
|
||||
#define Dqn_OS_EXEDir_TLS() Dqn_OS_EXEDir(Dqn_TLS_TopArena())
|
||||
DQN_API void Dqn_OS_SleepMs (Dqn_uint milliseconds);
|
||||
// NOTE: Counters //////////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API uint64_t Dqn_OS_PerfCounterNow ();
|
||||
DQN_API uint64_t Dqn_OS_PerfCounterFrequency();
|
||||
DQN_API Dqn_f64 Dqn_OS_PerfCounterS (uint64_t begin, uint64_t end);
|
||||
DQN_API Dqn_f64 Dqn_OS_PerfCounterMs (uint64_t begin, uint64_t end);
|
||||
DQN_API Dqn_f64 Dqn_OS_PerfCounterUs (uint64_t begin, uint64_t end);
|
||||
DQN_API Dqn_f64 Dqn_OS_PerfCounterNs (uint64_t begin, uint64_t end);
|
||||
DQN_API Dqn_OSTimer Dqn_OS_TimerBegin ();
|
||||
DQN_API void Dqn_OS_TimerEnd (Dqn_OSTimer *timer);
|
||||
DQN_API Dqn_f64 Dqn_OS_TimerS (Dqn_OSTimer timer);
|
||||
DQN_API Dqn_f64 Dqn_OS_TimerMs (Dqn_OSTimer timer);
|
||||
DQN_API Dqn_f64 Dqn_OS_TimerUs (Dqn_OSTimer timer);
|
||||
DQN_API Dqn_f64 Dqn_OS_TimerNs (Dqn_OSTimer timer);
|
||||
DQN_API uint64_t Dqn_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency);
|
||||
DN_API bool DN_OS_SecureRNGBytes (void *buffer, uint32_t size);
|
||||
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);
|
||||
DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena);
|
||||
#define DN_OS_EXEDir_TLS() DN_OS_EXEDir(DN_TLS_TopArena())
|
||||
DN_API void DN_OS_SleepMs (DN_UInt milliseconds);
|
||||
|
||||
#if !defined(DQN_NO_OS_FILE_API)
|
||||
// NOTE: Counters //////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API uint64_t DN_OS_PerfCounterNow ();
|
||||
DN_API uint64_t DN_OS_PerfCounterFrequency();
|
||||
DN_API DN_F64 DN_OS_PerfCounterS (uint64_t begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterMs (uint64_t begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterUs (uint64_t begin, uint64_t end);
|
||||
DN_API DN_F64 DN_OS_PerfCounterNs (uint64_t begin, uint64_t end);
|
||||
DN_API DN_OSTimer DN_OS_TimerBegin ();
|
||||
DN_API void DN_OS_TimerEnd (DN_OSTimer *timer);
|
||||
DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer);
|
||||
DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer);
|
||||
DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency);
|
||||
#if !defined(DN_NO_OS_FILE_API)
|
||||
// NOTE: File system paths /////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_OSPathInfo Dqn_OS_PathInfo (Dqn_Str8 path);
|
||||
DQN_API bool Dqn_OS_FileIsOlderThan(Dqn_Str8 file, Dqn_Str8 check_against);
|
||||
DQN_API bool Dqn_OS_PathDelete (Dqn_Str8 path);
|
||||
DQN_API bool Dqn_OS_FileExists (Dqn_Str8 path);
|
||||
DQN_API bool Dqn_OS_CopyFile (Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_ErrorSink *error);
|
||||
DQN_API bool Dqn_OS_MoveFile (Dqn_Str8 src, Dqn_Str8 dest, bool overwrite, Dqn_ErrorSink *error);
|
||||
DQN_API bool Dqn_OS_MakeDir (Dqn_Str8 path);
|
||||
DQN_API bool Dqn_OS_DirExists (Dqn_Str8 path);
|
||||
DQN_API bool Dqn_OS_DirIterate (Dqn_Str8 path, Dqn_OS_DirIterator *it);
|
||||
DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path);
|
||||
DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against);
|
||||
DN_API bool DN_OS_PathDelete (DN_Str8 path);
|
||||
DN_API bool DN_OS_FileExists (DN_Str8 path);
|
||||
DN_API bool DN_OS_CopyFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_MoveFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_MakeDir (DN_Str8 path);
|
||||
DN_API bool DN_OS_DirExists (DN_Str8 path);
|
||||
DN_API bool DN_OS_DirIterate (DN_Str8 path, DN_OSDirIterator *it);
|
||||
|
||||
// NOTE: R/W Stream API ////////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_OSFile Dqn_OS_FileOpen (Dqn_Str8 path, Dqn_OSFileOpen open_mode, uint32_t access, Dqn_ErrorSink *error);
|
||||
DQN_API bool Dqn_OS_FileRead (Dqn_OSFile *file, void *buffer, Dqn_usize size, Dqn_ErrorSink *error);
|
||||
DQN_API bool Dqn_OS_FileWritePtr(Dqn_OSFile *file, void const *data, Dqn_usize size, Dqn_ErrorSink *error);
|
||||
DQN_API bool Dqn_OS_FileWrite (Dqn_OSFile *file, Dqn_Str8 buffer, Dqn_ErrorSink *error);
|
||||
DQN_API bool Dqn_OS_FileWriteFV (Dqn_OSFile *file, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DQN_API bool Dqn_OS_FileWriteF (Dqn_OSFile *file, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
DQN_API void Dqn_OS_FileClose (Dqn_OSFile *file);
|
||||
DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *data, DN_USize size, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_ErrSink *err);
|
||||
DN_API void DN_OS_FileClose (DN_OSFile *file);
|
||||
|
||||
// NOTE: R/W Entire File ///////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_Str8 Dqn_OS_ReadAll (Dqn_Arena *arena, Dqn_Str8 path, Dqn_ErrorSink *error);
|
||||
#define Dqn_OS_ReadAll_TLS(...) Dqn_OS_ReadAll(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API bool Dqn_OS_WriteAll (Dqn_Str8 path, Dqn_Str8 buffer, Dqn_ErrorSink *error);
|
||||
DQN_API bool Dqn_OS_WriteAllFV (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DQN_API bool Dqn_OS_WriteAllF (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
DQN_API bool Dqn_OS_WriteAllSafe (Dqn_Str8 path, Dqn_Str8 buffer, Dqn_ErrorSink *error);
|
||||
DQN_API bool Dqn_OS_WriteAllSafeFV (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DQN_API bool Dqn_OS_WriteAllSafeF (Dqn_Str8 path, Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
#endif // !defined(DQN_NO_OS_FILE_API)
|
||||
DN_API DN_Str8 DN_OS_ReadAll (DN_Arena *arena, DN_Str8 path, DN_ErrSink *err);
|
||||
#define DN_OS_ReadAll_TLS(...) DN_OS_ReadAll(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API bool DN_OS_WriteAll (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_WriteAllFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_WriteAllF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_OS_WriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
|
||||
DN_API bool DN_OS_WriteAllSafeFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API bool DN_OS_WriteAllSafeF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#endif // !defined(DN_NO_OS_FILE_API)
|
||||
|
||||
// NOTE: File system paths /////////////////////////////////////////////////////////////////////////
|
||||
DQN_API bool Dqn_OS_PathAddRef (Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path);
|
||||
#define Dqn_OS_PathAddRef_TLS(...) Dqn_OS_PathAddRef(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API bool Dqn_OS_PathAdd (Dqn_Arena *arena, Dqn_OSPath *fs_path, Dqn_Str8 path);
|
||||
#define Dqn_OS_PathAdd_TLS(...) Dqn_OS_PathAdd(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API bool Dqn_OS_PathAddF (Dqn_Arena *arena, Dqn_OSPath *fs_path, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define Dqn_OS_PathAddF_TLS(...) Dqn_OS_PathAddF(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API bool Dqn_OS_PathPop (Dqn_OSPath *fs_path);
|
||||
DQN_API Dqn_Str8 Dqn_OS_PathBuildWithSeparator (Dqn_Arena *arena, Dqn_OSPath const *fs_path, Dqn_Str8 path_separator);
|
||||
#define Dqn_OS_PathBuildWithSeperator_TLS(...) Dqn_OS_PathBuildWithSeperator(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_OS_PathTo (Dqn_Arena *arena, Dqn_Str8 path, Dqn_Str8 path_separtor);
|
||||
#define Dqn_OS_PathTo_TLS(...) Dqn_OS_PathTo(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_OS_PathToF (Dqn_Arena *arena, Dqn_Str8 path_separator, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define Dqn_OS_PathToF_TLS(...) Dqn_OS_PathToF(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_OS_Path (Dqn_Arena *arena, Dqn_Str8 path);
|
||||
#define Dqn_OS_Path_TLS(...) Dqn_OS_Path(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_OS_PathF (Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define Dqn_OS_PathF_TLS(...) Dqn_OS_PathF(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define Dqn_OS_PathBuildFwdSlash(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, DQN_STR8("/"))
|
||||
#define Dqn_OS_PathBuildBackSlash(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, DQN_STR8("\\"))
|
||||
#define Dqn_OS_PathBuild(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, Dqn_OSPathSeparatorString)
|
||||
DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
|
||||
#define DN_OS_PathAddRef_TLS(...) DN_OS_PathAddRef(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathAddRef_Frame(...) DN_OS_PathAddRef(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
|
||||
#define DN_OS_PathAdd_TLS(...) DN_OS_PathAdd(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathAdd_Frame(...) DN_OS_PathAdd(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_PathAddF_TLS(...) DN_OS_PathAddF(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathAddF_Frame(...) DN_OS_PathAddF(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
DN_API bool DN_OS_PathPop (DN_OSPath *fs_path);
|
||||
DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator);
|
||||
#define DN_OS_PathBuildWithSeperator_TLS(...) DN_OS_PathBuildWithSeperator(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathBuildWithSeperator_Frame(...) DN_OS_PathBuildWithSeperator(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor);
|
||||
#define DN_OS_PathTo_TLS(...) DN_OS_PathTo(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathTo_Frame(...) DN_OS_PathTo(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_PathToF_TLS(...) DN_OS_PathToF(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathToF_Frame(...) DN_OS_PathToF(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path);
|
||||
#define DN_OS_Path_TLS(...) DN_OS_Path(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_Path_Frame(...) DN_OS_Path(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_OS_PathF_TLS(...) DN_OS_PathF(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_OS_PathF_Frame(...) DN_OS_PathF(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
|
||||
// NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
|
||||
DQN_API void Dqn_OS_Exit (int32_t exit_code);
|
||||
DQN_API Dqn_OSExecResult Dqn_OS_ExecWait (Dqn_OSExecAsyncHandle handle, Dqn_Arena *arena, Dqn_ErrorSink *error);
|
||||
DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync (Dqn_Slice<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())
|
||||
#define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("/"))
|
||||
#define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("\\"))
|
||||
#define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString)
|
||||
|
||||
// NOTE: [$SEMA] Dqn_OSSemaphore ///////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_NO_SEMAPHORE)
|
||||
DQN_API Dqn_OSSemaphore Dqn_OS_SemaphoreInit (uint32_t initial_count);
|
||||
DQN_API bool Dqn_OS_SemaphoreIsValid (Dqn_OSSemaphore *semaphore);
|
||||
DQN_API void Dqn_OS_SemaphoreDeinit (Dqn_OSSemaphore *semaphore);
|
||||
DQN_API void Dqn_OS_SemaphoreIncrement(Dqn_OSSemaphore *semaphore, uint32_t amount);
|
||||
DQN_API Dqn_OSSemaphoreWaitResult Dqn_OS_SemaphoreWait (Dqn_OSSemaphore *semaphore, uint32_t timeout_ms);
|
||||
#endif // !defined(DQN_NO_SEMAPHORE)
|
||||
// NOTE: [$EXEC] DN_OSExec ////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_Exit (int32_t exit_code);
|
||||
DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, uint32_t timeout_ms, DN_ErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_ErrSink *err);
|
||||
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_ErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_ErrSink *err);
|
||||
DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
|
||||
#define DN_OS_ExecOrAbort_TLS(...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_TLS_TopArena())
|
||||
|
||||
// NOTE: [$MUTX] Dqn_OSMutex ///////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_OSMutex Dqn_OS_MutexInit ();
|
||||
DQN_API void Dqn_OS_MutexDeinit(Dqn_OSMutex *mutex);
|
||||
DQN_API void Dqn_OS_MutexLock (Dqn_OSMutex *mutex);
|
||||
DQN_API void Dqn_OS_MutexUnlock(Dqn_OSMutex *mutex);
|
||||
// NOTE: [$SEMA] DN_OSSemaphore ///////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_SEMAPHORE)
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit (uint32_t initial_count);
|
||||
DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore);
|
||||
DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore);
|
||||
DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, uint32_t amount);
|
||||
DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, uint32_t timeout_ms);
|
||||
#endif // !defined(DN_NO_SEMAPHORE)
|
||||
|
||||
// NOTE: [$THRD] Dqn_OSThread /////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_NO_THREAD) && !defined(DQN_NO_SEMAPHORE)
|
||||
DQN_API bool Dqn_OS_ThreadInit (Dqn_OSThread *thread, Dqn_OSThreadFunc *func, void *user_context);
|
||||
DQN_API void Dqn_OS_ThreadDeinit(Dqn_OSThread thread);
|
||||
DQN_API uint32_t Dqn_OS_ThreadID ();
|
||||
DQN_API void Dqn_OS_ThreadSetTLS(Dqn_TLS *tls);
|
||||
#endif // !defined(DQN_NO_THREAD)
|
||||
// NOTE: [$MUTX] DN_OSMutex ///////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSMutex DN_OS_MutexInit ();
|
||||
DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex);
|
||||
DN_API void DN_OS_MutexLock (DN_OSMutex *mutex);
|
||||
DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex);
|
||||
#define DN_OS_Mutex(mutex) DN_DEFER_LOOP(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex))
|
||||
|
||||
// NOTE: [$HTTP] Dqn_OSHttp ////////////////////////////////////////////////////////////////////////
|
||||
DQN_API void Dqn_OS_HttpRequestAsync(Dqn_OSHttpResponse *response, Dqn_Arena *arena, Dqn_Str8 host, Dqn_Str8 path, Dqn_OSHttpRequestSecure secure, Dqn_Str8 method, Dqn_Str8 body, Dqn_Str8 headers);
|
||||
DQN_API void Dqn_OS_HttpRequestWait (Dqn_OSHttpResponse *response);
|
||||
DQN_API void Dqn_OS_HttpRequestFree (Dqn_OSHttpResponse *response);
|
||||
DQN_API Dqn_OSHttpResponse Dqn_OS_HttpRequest (Dqn_Arena *arena, Dqn_Str8 host, Dqn_Str8 path, Dqn_OSHttpRequestSecure secure, Dqn_Str8 method, Dqn_Str8 body, Dqn_Str8 headers);
|
||||
// NOTE: [$THRD] DN_OSThread /////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_THREAD) && !defined(DN_NO_SEMAPHORE)
|
||||
DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context);
|
||||
DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread);
|
||||
DN_API uint32_t DN_OS_ThreadID ();
|
||||
DN_API void DN_OS_ThreadSetTLS(DN_TLS *tls);
|
||||
DN_API void DN_OS_ThreadSetName(DN_Str8 name);
|
||||
#endif // !defined(DN_NO_THREAD)
|
||||
|
||||
// NOTE: [$HTTP] DN_OSHttp ////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
||||
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);
|
||||
DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response);
|
||||
DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
||||
|
778
dqn_os_posix.cpp
778
dqn_os_posix.cpp
File diff suppressed because it is too large
Load Diff
21
dqn_os_posix.h
Normal file
21
dqn_os_posix.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "dqn.h"
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// $$$$$$\ $$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\
|
||||
// $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ \_$$ _|$$ | $$ |
|
||||
// $$ / $$ |$$ / \__| $$ | $$ |$$ / $$ |$$ / \__| $$ | \$$\ $$ |
|
||||
// $$ | $$ |\$$$$$$\ $$$$$$$ |$$ | $$ |\$$$$$$\ $$ | \$$$$ /
|
||||
// $$ | $$ | \____$$\ $$ ____/ $$ | $$ | \____$$\ $$ | $$ $$<
|
||||
// $$ | $$ |$$\ $$ | $$ | $$ | $$ |$$\ $$ | $$ | $$ /\$$\
|
||||
// $$$$$$ |\$$$$$$ | $$ | $$$$$$ |\$$$$$$ |$$$$$$\ $$ / $$ |
|
||||
// \______/ \______/ \__| \______/ \______/ \______|\__| \__|
|
||||
//
|
||||
// dqn_os_posix.h
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
DN_API void DN_Posix_ThreadSetName(DN_Str8 name);
|
1292
dqn_os_win32.cpp
1292
dqn_os_win32.cpp
File diff suppressed because it is too large
Load Diff
@ -18,40 +18,40 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
struct Dqn_WinError
|
||||
struct DN_WinError
|
||||
{
|
||||
unsigned long code;
|
||||
Dqn_Str8 msg;
|
||||
DN_Str8 msg;
|
||||
};
|
||||
|
||||
// NOTE: Windows Str8 <-> Str16 ///////////////////////////////////////////
|
||||
struct Dqn_Win_FolderIteratorW
|
||||
struct DN_Win_FolderIteratorW
|
||||
{
|
||||
void *handle;
|
||||
Dqn_Str16 file_name;
|
||||
DN_Str16 file_name;
|
||||
wchar_t file_name_buf[512];
|
||||
};
|
||||
|
||||
struct Dqn_Win_FolderIterator
|
||||
{
|
||||
void *handle;
|
||||
Dqn_Str8 file_name;
|
||||
char file_name_buf[512];
|
||||
};
|
||||
DN_API void DN_Win_ThreadSetName (DN_Str8 name);
|
||||
|
||||
// NOTE: [$WIND] DN_Win ///////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str16 DN_Win_ErrorCodeToMsg16Alloc(uint32_t error_code);
|
||||
DN_API DN_WinError DN_Win_ErrorCodeToMsg (DN_Arena *arena, uint32_t error_code);
|
||||
DN_API DN_WinError DN_Win_ErrorCodeToMsgAlloc (uint32_t error_code);
|
||||
DN_API DN_WinError DN_Win_LastError (DN_Arena *arena);
|
||||
DN_API DN_WinError DN_Win_LastErrorAlloc ();
|
||||
DN_API void DN_Win_MakeProcessDPIAware ();
|
||||
|
||||
// NOTE: [$WIND] Dqn_Win ///////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_WinError Dqn_Win_ErrorCodeToMsg (Dqn_Arena *arena, uint32_t error_code);
|
||||
DQN_API Dqn_WinError Dqn_Win_LastError (Dqn_Arena *arena);
|
||||
DQN_API void Dqn_Win_MakeProcessDPIAware();
|
||||
// NOTE: Windows Str8 <-> Str16 ////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_Str16 Dqn_Win_Str8ToStr16 (Dqn_Arena *arena, Dqn_Str8 src);
|
||||
DQN_API int Dqn_Win_Str8ToStr16Buffer (Dqn_Str16 src, char *dest, int dest_size);
|
||||
DQN_API Dqn_Str8 Dqn_Win_Str16ToStr8 (Dqn_Arena *arena, Dqn_Str16 src);
|
||||
DQN_API int Dqn_Win_Str16ToStr8Buffer (Dqn_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str16 DN_Win_Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
|
||||
DN_API int DN_Win_Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_Win_Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
|
||||
DN_API int DN_Win_Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_Win_Str16ToStr8Alloc (DN_Str16 src);
|
||||
|
||||
// NOTE: Path navigation ///////////////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_Str16 Dqn_Win_EXEPathW (Dqn_Arena *arena);
|
||||
DQN_API Dqn_Str16 Dqn_Win_EXEDirW (Dqn_Arena *arena);
|
||||
DQN_API Dqn_Str8 Dqn_Win_WorkingDir (Dqn_Arena *arena, Dqn_Str8 suffix);
|
||||
DQN_API Dqn_Str16 Dqn_Win_WorkingDirW (Dqn_Arena *arena, Dqn_Str16 suffix);
|
||||
DQN_API bool Dqn_Win_FolderIterate (Dqn_Str8 path, Dqn_Win_FolderIterator *it);
|
||||
DQN_API bool Dqn_Win_FolderWIterate (Dqn_Str16 path, Dqn_Win_FolderIteratorW *it);
|
||||
DN_API DN_Str16 DN_Win_EXEPathW (DN_Arena *arena);
|
||||
DN_API DN_Str16 DN_Win_EXEDirW (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_Win_WorkingDir (DN_Arena *arena, DN_Str8 suffix);
|
||||
DN_API DN_Str16 DN_Win_WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
|
||||
DN_API bool DN_Win_DirWIterate (DN_Str16 path, DN_Win_FolderIteratorW *it);
|
||||
|
894
dqn_string.cpp
894
dqn_string.cpp
File diff suppressed because it is too large
Load Diff
572
dqn_string.h
572
dqn_string.h
@ -17,27 +17,28 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [$CSTR] Dqn_CStr8 -- C-string helpers
|
||||
// [$STR8] Dqn_Str8 -- Pointer and length strings
|
||||
// [$STRB] Dqn_Str8Builder -- Construct strings dynamically
|
||||
// [$FSTR] Dqn_FStr8 -- Fixed-size strings
|
||||
// [$CHAR] Dqn_Char -- Character ascii/digit.. helpers
|
||||
// [$UTFX] Dqn_UTF -- Unicode helpers
|
||||
// [$CSTR] DN_CStr8 -- C-string helpers
|
||||
// [$STR8] DN_Str8 -- Pointer and length strings
|
||||
// [$STRB] DN_Str8Builder -- Construct strings dynamically
|
||||
// [$FSTR] DN_FStr8 -- Fixed-size strings
|
||||
// [$CHAR] DN_Char -- Character ascii/digit.. helpers
|
||||
// [$UTFX] DN_UTF -- Unicode helpers
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$STR8] Dqn_Str8 //////////////////////////////////////////////////////////////////////////
|
||||
struct Dqn_Str8Link
|
||||
// NOTE: [$STR8] DN_Str8 //////////////////////////////////////////////////////////////////////////
|
||||
struct DN_Str8Link
|
||||
{
|
||||
Dqn_Str8 string; // The string
|
||||
Dqn_Str8Link *next; // The next string in the linked list
|
||||
DN_Str8 string; // The string
|
||||
DN_Str8Link *next; // The next string in the linked list
|
||||
DN_Str8Link *prev; // The prev string in the linked list
|
||||
};
|
||||
|
||||
struct Dqn_Str16 // A pointer and length style string that holds slices to UTF16 bytes.
|
||||
struct DN_Str16 // A pointer and length style string that holds slices to UTF16 bytes.
|
||||
{
|
||||
wchar_t *data; // The UTF16 bytes of the string
|
||||
Dqn_usize size; // The number of characters in the string
|
||||
DN_USize size; // The number of characters in the string
|
||||
|
||||
#if defined(__cplusplus)
|
||||
wchar_t const *begin() const { return data; } // Const begin iterator for range-for loops
|
||||
@ -47,417 +48,490 @@ struct Dqn_Str16 // A pointer and length style string that holds slices to UTF16
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Dqn_Str8BinarySplitResult
|
||||
struct DN_Str8BinarySplitResult
|
||||
{
|
||||
Dqn_Str8 lhs;
|
||||
Dqn_Str8 rhs;
|
||||
DN_Str8 lhs;
|
||||
DN_Str8 rhs;
|
||||
};
|
||||
|
||||
struct Dqn_Str8FindResult
|
||||
struct DN_Str8FindResult
|
||||
{
|
||||
bool found; // True if string was found. If false, the subsequent fields below are not set.
|
||||
Dqn_usize index; // The index in the buffer where the found string starts
|
||||
Dqn_Str8 match; // The matching string in the buffer that was searched
|
||||
Dqn_Str8 match_to_end_of_buffer; // The substring containing the found string to the end of the buffer
|
||||
Dqn_Str8 start_to_before_match; // The substring from the start of the buffer up until the found string, not including it
|
||||
DN_USize index; // Index in the buffer where the found string starts
|
||||
DN_Str8 match; // Matching string in the buffer that was searched
|
||||
DN_Str8 match_to_end_of_buffer; // Substring containing the found string to the end of the buffer
|
||||
DN_Str8 after_match_to_end_of_buffer; // Substring starting after the found string to the end of the buffer
|
||||
DN_Str8 start_to_before_match; // Substring from the start of the buffer up until the found string, not including it
|
||||
};
|
||||
|
||||
enum Dqn_Str8IsAll
|
||||
enum DN_Str8IsAll
|
||||
{
|
||||
Dqn_Str8IsAll_Digits,
|
||||
Dqn_Str8IsAll_Hex,
|
||||
DN_Str8IsAll_Digits,
|
||||
DN_Str8IsAll_Hex,
|
||||
};
|
||||
|
||||
enum Dqn_Str8EqCase
|
||||
enum DN_Str8EqCase
|
||||
{
|
||||
Dqn_Str8EqCase_Sensitive,
|
||||
Dqn_Str8EqCase_Insensitive,
|
||||
DN_Str8EqCase_Sensitive,
|
||||
DN_Str8EqCase_Insensitive,
|
||||
};
|
||||
|
||||
enum Dqn_Str8FindFlag
|
||||
enum DN_Str8FindFlag
|
||||
{
|
||||
Dqn_Str8FindFlag_Digit = 1 << 0, // 0-9
|
||||
Dqn_Str8FindFlag_Whitespace = 1 << 1, // '\r', '\t', '\n', ' '
|
||||
Dqn_Str8FindFlag_Alphabet = 1 << 2, // A-Z, a-z
|
||||
Dqn_Str8FindFlag_Plus = 1 << 3, // +
|
||||
Dqn_Str8FindFlag_Minus = 1 << 4, // -
|
||||
Dqn_Str8FindFlag_AlphaNum = Dqn_Str8FindFlag_Alphabet | Dqn_Str8FindFlag_Digit,
|
||||
DN_Str8FindFlag_Digit = 1 << 0, // 0-9
|
||||
DN_Str8FindFlag_Whitespace = 1 << 1, // '\r', '\t', '\n', ' '
|
||||
DN_Str8FindFlag_Alphabet = 1 << 2, // A-Z, a-z
|
||||
DN_Str8FindFlag_Plus = 1 << 3, // +
|
||||
DN_Str8FindFlag_Minus = 1 << 4, // -
|
||||
DN_Str8FindFlag_AlphaNum = DN_Str8FindFlag_Alphabet | DN_Str8FindFlag_Digit,
|
||||
};
|
||||
|
||||
enum Dqn_Str8SplitIncludeEmptyStrings
|
||||
enum DN_Str8SplitIncludeEmptyStrings
|
||||
{
|
||||
Dqn_Str8SplitIncludeEmptyStrings_No,
|
||||
Dqn_Str8SplitIncludeEmptyStrings_Yes,
|
||||
DN_Str8SplitIncludeEmptyStrings_No,
|
||||
DN_Str8SplitIncludeEmptyStrings_Yes,
|
||||
};
|
||||
|
||||
struct Dqn_Str8ToU64Result
|
||||
struct DN_Str8ToU64Result
|
||||
{
|
||||
bool success;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
struct Dqn_Str8ToI64Result
|
||||
struct DN_Str8ToI64Result
|
||||
{
|
||||
bool success;
|
||||
int64_t value;
|
||||
};
|
||||
|
||||
// NOTE: [$FSTR] Dqn_FStr8 /////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_NO_FSTR8)
|
||||
template <Dqn_usize N> struct Dqn_FStr8
|
||||
struct DN_Str8DotTruncateResult
|
||||
{
|
||||
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];
|
||||
Dqn_usize size;
|
||||
DN_USize size;
|
||||
|
||||
char *begin() { return data; }
|
||||
char *end () { return data + size; }
|
||||
char const *begin() const { return data; }
|
||||
char const *end () const { return data + size; }
|
||||
};
|
||||
#endif // !defined(DQN_NO_FSTR8)
|
||||
#endif // !defined(DN_NO_FSTR8)
|
||||
|
||||
struct Dqn_Str8Builder
|
||||
struct DN_Str8Builder
|
||||
{
|
||||
Dqn_Arena *arena; // Allocator to use to back the string list
|
||||
Dqn_Str8Link *head; // First string in the linked list of strings
|
||||
Dqn_Str8Link *tail; // Last string in the linked list of strings
|
||||
Dqn_usize string_size; // The size in bytes necessary to construct the current string
|
||||
Dqn_usize count; // The number of links in the linked list of strings
|
||||
DN_Arena *arena; // Allocator to use to back the string list
|
||||
DN_Str8Link *head; // First string in the linked list of strings
|
||||
DN_Str8Link *tail; // Last string in the linked list of strings
|
||||
DN_USize string_size; // The size in bytes necessary to construct the current string
|
||||
DN_USize count; // The number of links in the linked list of strings
|
||||
};
|
||||
|
||||
// NOTE: [$CSTR] Dqn_CStr8 /////////////////////////////////////////////////////////////////////////
|
||||
template <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; }
|
||||
DQN_API Dqn_usize Dqn_CStr8_FSize (DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
DQN_API Dqn_usize Dqn_CStr8_FVSize (DQN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DQN_API Dqn_usize Dqn_CStr8_Size (char const *a);
|
||||
DQN_API Dqn_usize Dqn_CStr16_Size (wchar_t const *a);
|
||||
enum DN_Str8BuilderAdd
|
||||
{
|
||||
DN_Str8BuilderAdd_Append,
|
||||
DN_Str8BuilderAdd_Prepend,
|
||||
};
|
||||
|
||||
// NOTE: [$STR6] Dqn_Str16 /////////////////////////////////////////////////////////////////////////
|
||||
#define DQN_STR16(string) Dqn_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1}
|
||||
#define Dqn_Str16_HasData(string) ((string).data && (string).size)
|
||||
// NOTE: [$CSTR] DN_CStr8 /////////////////////////////////////////////////////////////////////////
|
||||
template <DN_USize N> constexpr DN_USize DN_CStr8_ArrayUCount (char const (&literal)[N]) { (void)literal; return N - 1; }
|
||||
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)
|
||||
DQN_API bool operator== (Dqn_Str16 const &lhs, Dqn_Str16 const &rhs);
|
||||
DQN_API bool operator!= (Dqn_Str16 const &lhs, Dqn_Str16 const &rhs);
|
||||
DN_API bool operator== (DN_Str16 const &lhs, DN_Str16 const &rhs);
|
||||
DN_API bool operator!= (DN_Str16 const &lhs, DN_Str16 const &rhs);
|
||||
#endif
|
||||
|
||||
// NOTE: [$STR8] Dqn_Str8 //////////////////////////////////////////////////////////////////////////
|
||||
#define DQN_STR8(string) Dqn_Str8{(char *)(string), (sizeof(string) - 1)}
|
||||
#define DQN_STR_FMT(string) (int)((string).size), (string).data
|
||||
#define Dqn_Str8_Init(data, size) Dqn_Str8{(char *)(data), (size_t)(size)}
|
||||
// NOTE: [$STR8] DN_Str8 //////////////////////////////////////////////////////////////////////////
|
||||
#define DN_STR8(string) DN_Str8{(char *)(string), (sizeof(string) - 1)}
|
||||
#define DN_STR_FMT(string) (int)((string).size), (string).data
|
||||
#define DN_Str8_Init(data, size) DN_Str8{(char *)(data), (size_t)(size)}
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_Str8_InitCStr8 (char const *src);
|
||||
#define Dqn_Str8_HasData(string) ((string).data && (string).size)
|
||||
DQN_API bool Dqn_Str8_IsAll (Dqn_Str8 string, Dqn_Str8IsAll is_all);
|
||||
DN_API DN_Str8 DN_Str8_InitCStr8 (char const *src);
|
||||
#define DN_Str8_HasData(string) ((string).data && (string).size)
|
||||
DN_API bool DN_Str8_IsAll (DN_Str8 string, DN_Str8IsAll is_all);
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_Str8_InitF (Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define Dqn_Str8_InitF_TLS(...) Dqn_Str8_InitF(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_Str8_InitFV (Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
#define Dqn_Str8_InitFV_TLS(...) Dqn_Str8_InitFV(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_Str8_Alloc (Dqn_Arena *arena, Dqn_usize size, Dqn_ZeroMem zero_mem);
|
||||
#define Dqn_Str8_Alloc_TLS(...) Dqn_Str8_Alloc(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_Str8_CopyCString (Dqn_Arena *arena, char const *string, Dqn_usize size);
|
||||
#define Dqn_Str8_CopyCString_TLS(...) Dqn_Str8_CopyCString(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_Str8_Copy (Dqn_Arena *arena, Dqn_Str8 string);
|
||||
#define Dqn_Str8_Copy_TLS(...) Dqn_Str8_Copy(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_InitF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
#define DN_Str8_InitF_TLS(...) DN_Str8_InitF(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_Str8_InitF_Frame(...) DN_Str8_InitF(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_InitFV (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
#define DN_Str8_InitFV_TLS(...) DN_Str8_InitFV(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_Alloc (DN_Arena *arena, DN_USize size, DN_ZeroMem zero_mem);
|
||||
#define DN_Str8_Alloc_TLS(...) DN_Str8_Alloc(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_CopyCString (DN_Arena *arena, char const *string, DN_USize size);
|
||||
#define DN_Str8_CopyCString_TLS(...) DN_Str8_CopyCString(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_Copy (DN_Arena *arena, DN_Str8 string);
|
||||
#define DN_Str8_Copy_TLS(...) DN_Str8_Copy(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
#define DN_Str8_Copy_Frame(...) DN_Str8_Copy(DN_TLS_FrameArena(), ##__VA_ARGS__)
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_Str8_Slice (Dqn_Str8 string, Dqn_usize offset, Dqn_usize size);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_Advance (Dqn_Str8 string, Dqn_usize amount);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_NextLine (Dqn_Str8 string);
|
||||
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size);
|
||||
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplit (Dqn_Str8 string, Dqn_Str8 find);
|
||||
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLastArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size);
|
||||
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitLast (Dqn_Str8 string, Dqn_Str8 find);
|
||||
DQN_API Dqn_usize Dqn_Str8_Split (Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8 *splits, Dqn_usize splits_count, Dqn_Str8SplitIncludeEmptyStrings mode);
|
||||
DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8_SplitAlloc (Dqn_Arena *arena, Dqn_Str8 string, Dqn_Str8 delimiter, Dqn_Str8SplitIncludeEmptyStrings mode);
|
||||
#define Dqn_Str8_SplitAlloc_TLS(...) Dqn_Str8_SplitAlloc(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API char * DN_Str8_End (DN_Str8 string);
|
||||
DN_API DN_Str8 DN_Str8_Slice (DN_Str8 string, DN_USize offset, DN_USize size);
|
||||
DN_API DN_Str8 DN_Str8_Advance (DN_Str8 string, DN_USize amount);
|
||||
DN_API DN_Str8 DN_Str8_NextLine (DN_Str8 string);
|
||||
DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size);
|
||||
DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplit (DN_Str8 string, DN_Str8 find);
|
||||
DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size);
|
||||
DN_API DN_Str8BinarySplitResult DN_Str8_BinarySplitLast (DN_Str8 string, DN_Str8 find);
|
||||
DN_API DN_USize DN_Str8_Split (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode);
|
||||
DN_API DN_Slice<DN_Str8> DN_Str8_SplitAlloc (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
|
||||
#define DN_Str8_SplitAlloc_TLS(...) DN_Str8_SplitAlloc(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
|
||||
DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8Array (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size, Dqn_Str8EqCase eq_case);
|
||||
DQN_API Dqn_Str8FindResult Dqn_Str8_FindStr8 (Dqn_Str8 string, Dqn_Str8 find, Dqn_Str8EqCase eq_case);
|
||||
DQN_API Dqn_Str8FindResult Dqn_Str8_Find (Dqn_Str8 string, uint32_t flags);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_Segment (Dqn_Arena *arena, Dqn_Str8 src, Dqn_usize segment_size, char segment_char);
|
||||
#define Dqn_Str8_Segment_TLS(...) Dqn_Str8_Segment(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8 Dqn_Str8_ReverseSegment (Dqn_Arena *arena, Dqn_Str8 src, Dqn_usize segment_size, char segment_char);
|
||||
#define Dqn_Str8_ReverseSegment_TLS(...) Dqn_Str8_ReverseSegment(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8FindResult DN_Str8_FindStr8Array (DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case);
|
||||
DN_API DN_Str8FindResult DN_Str8_FindStr8 (DN_Str8 string, DN_Str8 find, DN_Str8EqCase eq_case);
|
||||
DN_API DN_Str8FindResult DN_Str8_Find (DN_Str8 string, uint32_t flags);
|
||||
DN_API DN_Str8 DN_Str8_Segment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char);
|
||||
#define DN_Str8_Segment_TLS(...) DN_Str8_Segment(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_ReverseSegment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char);
|
||||
#define DN_Str8_ReverseSegment_TLS(...) DN_Str8_ReverseSegment(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
|
||||
DQN_API bool Dqn_Str8_Eq (Dqn_Str8 lhs, Dqn_Str8 rhs, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive);
|
||||
DQN_API bool Dqn_Str8_EqInsensitive (Dqn_Str8 lhs, Dqn_Str8 rhs);
|
||||
DQN_API bool Dqn_Str8_StartsWith (Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive);
|
||||
DQN_API bool Dqn_Str8_StartsWithInsensitive (Dqn_Str8 string, Dqn_Str8 prefix);
|
||||
DQN_API bool Dqn_Str8_EndsWith (Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive);
|
||||
DQN_API bool Dqn_Str8_EndsWithInsensitive (Dqn_Str8 string, Dqn_Str8 prefix);
|
||||
DQN_API bool Dqn_Str8_HasChar (Dqn_Str8 string, char ch);
|
||||
DN_API bool DN_Str8_Eq (DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
||||
DN_API bool DN_Str8_EqInsensitive (DN_Str8 lhs, DN_Str8 rhs);
|
||||
DN_API bool DN_Str8_StartsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
||||
DN_API bool DN_Str8_StartsWithInsensitive (DN_Str8 string, DN_Str8 prefix);
|
||||
DN_API bool DN_Str8_EndsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
||||
DN_API bool DN_Str8_EndsWithInsensitive (DN_Str8 string, DN_Str8 prefix);
|
||||
DN_API bool DN_Str8_HasChar (DN_Str8 string, char ch);
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_Str8_TrimPrefix (Dqn_Str8 string, Dqn_Str8 prefix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_TrimHexPrefix (Dqn_Str8 string);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_TrimSuffix (Dqn_Str8 string, Dqn_Str8 suffix, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_TrimAround (Dqn_Str8 string, Dqn_Str8 trim_string);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_TrimWhitespaceAround (Dqn_Str8 string);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_TrimByteOrderMark (Dqn_Str8 string);
|
||||
DN_API DN_Str8 DN_Str8_TrimPrefix (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
||||
DN_API DN_Str8 DN_Str8_TrimHexPrefix (DN_Str8 string);
|
||||
DN_API DN_Str8 DN_Str8_TrimSuffix (DN_Str8 string, DN_Str8 suffix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
||||
DN_API DN_Str8 DN_Str8_TrimAround (DN_Str8 string, DN_Str8 trim_string);
|
||||
DN_API DN_Str8 DN_Str8_TrimWhitespaceAround (DN_Str8 string);
|
||||
DN_API DN_Str8 DN_Str8_TrimByteOrderMark (DN_Str8 string);
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_Str8_FileNameFromPath (Dqn_Str8 path);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_FileNameNoExtension (Dqn_Str8 path);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_FilePathNoExtension (Dqn_Str8 path);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_FileExtension (Dqn_Str8 path);
|
||||
DN_API DN_Str8 DN_Str8_FileNameFromPath (DN_Str8 path);
|
||||
DN_API DN_Str8 DN_Str8_FileNameNoExtension (DN_Str8 path);
|
||||
DN_API DN_Str8 DN_Str8_FilePathNoExtension (DN_Str8 path);
|
||||
DN_API DN_Str8 DN_Str8_FileExtension (DN_Str8 path);
|
||||
|
||||
DQN_API Dqn_Str8ToU64Result Dqn_Str8_ToU64 (Dqn_Str8 string, char separator);
|
||||
DQN_API Dqn_Str8ToI64Result Dqn_Str8_ToI64 (Dqn_Str8 string, char separator);
|
||||
DN_API DN_Str8ToU64Result DN_Str8_ToU64 (DN_Str8 string, char separator);
|
||||
DN_API DN_Str8ToI64Result DN_Str8_ToI64 (DN_Str8 string, char separator);
|
||||
|
||||
DQN_API Dqn_Str8 Dqn_Str8_Replace (Dqn_Str8 string, Dqn_Str8 find, Dqn_Str8 replace, Dqn_usize start_index, Dqn_Arena *arena, Dqn_Str8EqCase eq_case = Dqn_Str8EqCase_Sensitive);
|
||||
DQN_API Dqn_Str8 Dqn_Str8_ReplaceInsensitive (Dqn_Str8 string, Dqn_Str8 find, Dqn_Str8 replace, Dqn_usize start_index, Dqn_Arena *arena);
|
||||
DQN_API void Dqn_Str8_Remove (Dqn_Str8 *string, Dqn_usize offset, Dqn_usize size);
|
||||
#define DN_Str8_AppendF_TLS(...) DN_Str8_AppendF(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_AppendF (DN_Arena *arena, DN_Str8 string, char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Str8_FillF (DN_Arena *arena, DN_USize count, char const *fmt, ...);
|
||||
#define DN_Str8_FillF_TLS(count, ...) DN_Str8_FillF(DN_TLS_TopArena(), count, ##__VA_ARGS__)
|
||||
#define DN_Str8_FillF_Frame(count, ...) DN_Str8_FillF(DN_TLS_FrameArena(), count, ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_Replace (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
||||
DN_API DN_Str8 DN_Str8_ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
|
||||
DN_API void DN_Str8_Remove (DN_Str8 *string, DN_USize offset, DN_USize size);
|
||||
DN_API DN_Str8DotTruncateResult DN_Str8_DotTruncateMiddle (DN_Arena *arena, DN_Str8 str8, uint32_t side_size, DN_Str8 truncator);
|
||||
#define DN_Str8_DotTruncateMiddle_Frame(...) DN_Str8_DotTruncateMiddle(DN_TLS_FrameArena(), ## __VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_PadNewLines(DN_Arena *arena, DN_Str8 src, DN_Str8 pad);
|
||||
#define DN_Str8_PadNewLines_TLS(src, pad) DN_Str8_PadNewLines(DN_TLS_TopArena(), src, pad)
|
||||
|
||||
|
||||
#define DN_Str8_Lower_TLS(...) DN_Str8_Lower(DN_TLS_TopArena(), __VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_Lower (DN_Arena *arena, DN_Str8 string);
|
||||
#define DN_Str8_Upper_TLS(...) DN_Str8_Upper(DN_TLS_TopArena(), __VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8_Upper (DN_Arena *arena, DN_Str8 string);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
DQN_API bool operator== (Dqn_Str8 const &lhs, Dqn_Str8 const &rhs);
|
||||
DQN_API bool operator!= (Dqn_Str8 const &lhs, Dqn_Str8 const &rhs);
|
||||
DN_API bool operator== (DN_Str8 const &lhs, DN_Str8 const &rhs);
|
||||
DN_API bool operator!= (DN_Str8 const &lhs, DN_Str8 const &rhs);
|
||||
#endif
|
||||
|
||||
// NOTE: [$STRB] Dqn_Str8Builder ///////////////////////////////////////////////////////////////////
|
||||
DQN_API Dqn_Str8Builder Dqn_Str8Builder_Init (Dqn_Arena *arena);
|
||||
#define Dqn_Str8Builder_Init_TLS() Dqn_Str8Builder_Init(Dqn_TLS_TopArena())
|
||||
DQN_API Dqn_Str8Builder Dqn_Str8Builder_InitArrayRef (Dqn_Arena *arena, Dqn_Str8 const *strings, Dqn_usize size);
|
||||
#define Dqn_Str8Builder_InitArrayRef_TLS(...) Dqn_Str8Builder_InitArrayRef(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API Dqn_Str8Builder Dqn_Str8Builder_InitArrayCopy (Dqn_Arena *arena, Dqn_Str8 const *strings, Dqn_usize size);
|
||||
#define Dqn_Str8Builder_InitArrayCopy_TLS(...) Dqn_Str8Builder_InitArrayCopy(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
template <Dqn_usize N> Dqn_Str8Builder Dqn_Str8Builder_InitCArrayRef (Dqn_Arena *arena, Dqn_Str8 const (&array)[N]);
|
||||
#define Dqn_Str8Builder_InitCArrayRef_TLS(...) Dqn_Str8Builder_InitCArrayRef(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
template <Dqn_usize N> Dqn_Str8Builder Dqn_Str8Builder_InitCArrayCopy (Dqn_Arena *arena, Dqn_Str8 const (&array)[N]);
|
||||
#define Dqn_Str8Builder_InitCArrayCopy_TLS(...) Dqn_Str8Builder_InitCArrayCopy(Dqn_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DQN_API bool Dqn_Str8Builder_AddArrayRef (Dqn_Str8Builder *builder, Dqn_Str8 const *strings, Dqn_usize size);
|
||||
DQN_API bool Dqn_Str8Builder_AddArrayCopy (Dqn_Str8Builder *builder, Dqn_Str8 const *strings, Dqn_usize size);
|
||||
template <Dqn_usize N> bool Dqn_Str8Builder_AddCArrayRef (Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]);
|
||||
template <Dqn_usize N> bool Dqn_Str8Builder_AddCArrayCopy (Dqn_Str8Builder *builder, Dqn_Str8 const (&array)[N]);
|
||||
DQN_API bool Dqn_Str8Builder_AddSliceRef (Dqn_Str8Builder *builder, Dqn_Slice<Dqn_Str8> string);
|
||||
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: [$STRB] DN_Str8Builder ///////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str8Builder DN_Str8Builder_Init (DN_Arena *arena);
|
||||
DN_API DN_Str8Builder DN_Str8Builder_Init_Frame () { return DN_Str8Builder_Init(DN_TLS_Get()->frame_arena); }
|
||||
#define DN_Str8Builder_Init_TLS() DN_Str8Builder_Init(DN_TLS_TopArena())
|
||||
DN_API DN_Str8Builder DN_Str8Builder_InitArrayRef (DN_Arena *arena, DN_Str8 const *strings, DN_USize size);
|
||||
DN_API DN_Str8Builder DN_Str8Builder_InitArrayRef_Frame (DN_Str8 const *strings, DN_USize size) { return DN_Str8Builder_InitArrayRef(DN_TLS_Get()->frame_arena, strings, size); }
|
||||
#define DN_Str8Builder_InitArrayRef_TLS(...) DN_Str8Builder_InitArrayRef(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8Builder DN_Str8Builder_InitArrayCopy (DN_Arena *arena, DN_Str8 const *strings, DN_USize size);
|
||||
DN_API DN_Str8Builder DN_Str8Builder_InitArrayCopy_Frame (DN_Str8 const *strings, DN_USize size) { return DN_Str8Builder_InitArrayCopy(DN_TLS_Get()->frame_arena, strings, size); }
|
||||
#define DN_Str8Builder_InitArrayCopy_TLS(...) DN_Str8Builder_InitArrayCopy(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
template <DN_USize N> DN_Str8Builder DN_Str8Builder_InitCArrayRef (DN_Arena *arena, DN_Str8 const (&array)[N]);
|
||||
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); }
|
||||
#define DN_Str8Builder_InitCArrayRef_TLS(...) DN_Str8Builder_InitCArrayRef(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
template <DN_USize N> DN_Str8Builder DN_Str8Builder_InitCArrayCopy (DN_Arena *arena, DN_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); }
|
||||
#define DN_Str8Builder_InitCArrayCopy_TLS(...) DN_Str8Builder_InitCArrayCopy(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
|
||||
// NOTE: [$FSTR] Dqn_FStr8 //////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DQN_NO_FSTR8)
|
||||
template <Dqn_usize N> Dqn_FStr8<N> Dqn_FStr8_InitF (DQN_FMT_ATTRIB char const *fmt, ...);
|
||||
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)
|
||||
DN_API bool DN_Str8Builder_AddArrayRef (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add);
|
||||
DN_API bool DN_Str8Builder_AddArrayCopy (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add);
|
||||
DN_API bool DN_Str8Builder_AddFV (DN_Str8Builder *builder, DN_Str8BuilderAdd add, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
|
||||
// NOTE: [$CHAR] Dqn_Char //////////////////////////////////////////////////////////////////////////
|
||||
struct Dqn_CharHexToU8
|
||||
#define DN_Str8Builder_AppendArrayRef(builder, strings, size) DN_Str8Builder_AddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Append)
|
||||
#define DN_Str8Builder_AppendArrayCopy(builder, strings, size) DN_Str8Builder_AddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Append)
|
||||
#define DN_Str8Builder_AppendSliceRef(builder, slice) DN_Str8Builder_AddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append)
|
||||
#define DN_Str8Builder_AppendSliceCopy(builder, slice) DN_Str8Builder_AddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append)
|
||||
DN_API bool DN_Str8Builder_AppendRef (DN_Str8Builder *builder, DN_Str8 string);
|
||||
DN_API bool DN_Str8Builder_AppendCopy (DN_Str8Builder *builder, DN_Str8 string);
|
||||
#define DN_Str8Builder_AppendFV(builder, fmt, args) DN_Str8Builder_AddFV(builder, DN_Str8BuilderAdd_Append, fmt, args)
|
||||
DN_API bool DN_Str8Builder_AppendF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API bool DN_Str8Builder_AppendBytesRef (DN_Str8Builder *builder, void const *ptr, DN_USize size);
|
||||
DN_API bool DN_Str8Builder_AppendBytesCopy (DN_Str8Builder *builder, void const *ptr, DN_USize size);
|
||||
DN_API bool DN_Str8Builder_AppendBuilderRef (DN_Str8Builder *dest, DN_Str8Builder const *src);
|
||||
DN_API bool DN_Str8Builder_AppendBuilderCopy (DN_Str8Builder *dest, DN_Str8Builder const *src);
|
||||
|
||||
#define DN_Str8Builder_PrependArrayRef(builder, strings, size) DN_Str8Builder_AddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Prepend)
|
||||
#define DN_Str8Builder_PrependArrayCopy(builder, strings, size) DN_Str8Builder_AddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Prepend)
|
||||
#define DN_Str8Builder_PrependSliceRef(builder, slice) DN_Str8Builder_AddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Prepend)
|
||||
#define DN_Str8Builder_PrependSliceCopy(builder, slice) DN_Str8Builder_AddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Prepend)
|
||||
DN_API bool DN_Str8Builder_PrependRef (DN_Str8Builder *builder, DN_Str8 string);
|
||||
DN_API bool DN_Str8Builder_PrependCopy (DN_Str8Builder *builder, DN_Str8 string);
|
||||
#define DN_Str8Builder_PrependFV(builder, fmt, args) DN_Str8Builder_AddFV(builder, DN_Str8BuilderAdd_Prepend, fmt, args)
|
||||
DN_API bool DN_Str8Builder_PrependF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
|
||||
DN_API bool DN_Str8Builder_Erase (DN_Str8Builder *builder, DN_Str8 string);
|
||||
DN_API DN_Str8Builder DN_Str8Builder_Copy (DN_Arena *arena, DN_Str8Builder const *builder);
|
||||
#define DN_Str8Builder_Copy_TLS(...) DN_Str8Builder_Copy(DN_TLS_TopArena(), ##__VA_ARGS__)
|
||||
DN_API DN_Str8 DN_Str8Builder_Build (DN_Str8Builder const *builder, DN_Arena *arena);
|
||||
#define DN_Str8Builder_Build_TLS(...) DN_Str8Builder_Build(__VA_ARGS__, DN_TLS_TopArena())
|
||||
#define DN_Str8Builder_Build_Frame(...) DN_Str8Builder_Build(__VA_ARGS__, DN_TLS_FrameArena())
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildDelimited (DN_Str8Builder const *builder, DN_Str8 delimiter, DN_Arena *arena);
|
||||
#define DN_Str8Builder_BuildDelimited_TLS(...) DN_Str8Builder_BuildDelimited(__VA_ARGS__, DN_TLS_TopArena())
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildCRT (DN_Str8Builder const *builder);
|
||||
DN_API DN_Slice<DN_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;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
DQN_API bool Dqn_Char_IsAlphabet (char ch);
|
||||
DQN_API bool Dqn_Char_IsDigit (char ch);
|
||||
DQN_API bool Dqn_Char_IsAlphaNum (char ch);
|
||||
DQN_API bool Dqn_Char_IsWhitespace (char ch);
|
||||
DQN_API bool Dqn_Char_IsHex (char ch);
|
||||
DQN_API Dqn_CharHexToU8 Dqn_Char_HexToU8 (char ch);
|
||||
DQN_API char Dqn_Char_ToHex (char ch);
|
||||
DQN_API char Dqn_Char_ToHexUnchecked (char ch);
|
||||
DQN_API char Dqn_Char_ToLower (char ch);
|
||||
DN_API bool DN_Char_IsAlphabet (char ch);
|
||||
DN_API bool DN_Char_IsDigit (char ch);
|
||||
DN_API bool DN_Char_IsAlphaNum (char ch);
|
||||
DN_API bool DN_Char_IsWhitespace (char ch);
|
||||
DN_API bool DN_Char_IsHex (char ch);
|
||||
DN_API DN_CharHexToU8 DN_Char_HexToU8 (char ch);
|
||||
DN_API char DN_Char_ToHex (char ch);
|
||||
DN_API char DN_Char_ToHexUnchecked (char ch);
|
||||
DN_API char DN_Char_ToLower (char ch);
|
||||
DN_API char DN_Char_ToUpper (char ch);
|
||||
|
||||
// NOTE: [$UTFX] Dqn_UTF ///////////////////////////////////////////////////////////////////////////
|
||||
DQN_API int Dqn_UTF8_EncodeCodepoint (uint8_t utf8[4], uint32_t codepoint);
|
||||
DQN_API int Dqn_UTF16_EncodeCodepoint (uint16_t utf16[2], uint32_t codepoint);
|
||||
// NOTE: [$UTFX] DN_UTF ///////////////////////////////////////////////////////////////////////////
|
||||
DN_API int DN_UTF8_EncodeCodepoint (uint8_t utf8[4], uint32_t codepoint);
|
||||
DN_API int DN_UTF16_EncodeCodepoint (uint16_t utf16[2], uint32_t codepoint);
|
||||
|
||||
// NOTE: [$STRB] Dqn_Str8Builder ///////////////////////////////////////////////////////////////////
|
||||
template <Dqn_usize N> Dqn_Str8Builder Dqn_Str8Builder_InitCArrayRef(Dqn_Arena *arena, Dqn_Str8 const (&array)[N])
|
||||
// NOTE: [$STRB] DN_Str8Builder ///////////////////////////////////////////////////////////////////
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if !defined(DQN_NO_FSTR8)
|
||||
// NOTE: [$FSTR] Dqn_FStr8 /////////////////////////////////////////////////////////////////////////
|
||||
template <Dqn_usize N> Dqn_FStr8<N> Dqn_FStr8_InitF(DQN_FMT_ATTRIB char const *fmt, ...)
|
||||
#if !defined(DN_NO_FSTR8)
|
||||
// NOTE: [$FSTR] DN_FStr8 /////////////////////////////////////////////////////////////////////////
|
||||
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) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Dqn_FStr8_AddFV(&result, fmt, args);
|
||||
DN_FStr8_AddFV(&result, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <Dqn_usize 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;
|
||||
}
|
||||
|
||||
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 = {};
|
||||
}
|
||||
|
||||
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;
|
||||
if (!string || !fmt)
|
||||
return result;
|
||||
|
||||
Dqn_usize require = Dqn_CStr8_FVSize(fmt, args) + 1 /*null_terminate*/;
|
||||
Dqn_usize space = (N + 1) - string->size;
|
||||
DN_USize require = DN_CStr8_FVSize(fmt, args) + 1 /*null_terminate*/;
|
||||
DN_USize space = (N + 1) - string->size;
|
||||
result = require <= space;
|
||||
string->size += DQN_VSNPRINTF(string->data + string->size, DQN_CAST(int)space, fmt, args);
|
||||
string->size += DN_VSNPRINTF(string->data + string->size, DN_CAST(int)space, fmt, args);
|
||||
|
||||
// NOTE: snprintf returns the required size of the format string
|
||||
// irrespective of if there's space or not.
|
||||
string->size = DQN_MIN(string->size, N);
|
||||
string->size = DN_MIN(string->size, N);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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;
|
||||
if (!string || !fmt)
|
||||
return result;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
result = Dqn_FStr8_AddFV(string, fmt, args);
|
||||
result = DN_FStr8_AddFV(string, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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;
|
||||
if (!string || !src || size == 0 || string->size >= N)
|
||||
return result;
|
||||
|
||||
Dqn_usize space = N - string->size;
|
||||
DN_USize space = N - string->size;
|
||||
result = size <= space;
|
||||
DQN_MEMCPY(string->data + string->size, src, DQN_MIN(space, size));
|
||||
string->size = DQN_MIN(string->size + size, N);
|
||||
DN_MEMCPY(string->data + string->size, src, DN_MIN(space, size));
|
||||
string->size = DN_MIN(string->size + size, N);
|
||||
string->data[string->size] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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;
|
||||
}
|
||||
|
||||
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)
|
||||
return result;
|
||||
|
||||
result.data = DQN_CAST(char *)string->data;
|
||||
result.data = DN_CAST(char *)string->data;
|
||||
result.size = string->size;
|
||||
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);
|
||||
Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs);
|
||||
bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, eq_case);
|
||||
DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
|
||||
DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs);
|
||||
bool result = DN_Str8_Eq(lhs_s8, rhs_s8, eq_case);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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);
|
||||
bool result = Dqn_Str8_Eq(lhs_s8, rhs, eq_case);
|
||||
DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
|
||||
bool result = DN_Str8_Eq(lhs_s8, rhs, eq_case);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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);
|
||||
Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs);
|
||||
bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, Dqn_Str8EqCase_Insensitive);
|
||||
DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
|
||||
DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs);
|
||||
bool result = DN_Str8_Eq(lhs_s8, rhs_s8, DN_Str8EqCase_Insensitive);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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);
|
||||
bool result = Dqn_Str8_Eq(lhs_s8, rhs, Dqn_Str8EqCase_Insensitive);
|
||||
DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
|
||||
bool result = DN_Str8_Eq(lhs_s8, rhs, DN_Str8EqCase_Insensitive);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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);
|
||||
Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs);
|
||||
bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, eq_case);
|
||||
DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
|
||||
DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs);
|
||||
bool result = DN_Str8_Eq(lhs_s8, rhs_s8, eq_case);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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);
|
||||
Dqn_Str8 rhs_s8 = Dqn_FStr8_ToStr8(rhs);
|
||||
bool result = Dqn_Str8_Eq(lhs_s8, rhs_s8, Dqn_Str8EqCase_Insensitive);
|
||||
DN_Str8 lhs_s8 = DN_FStr8_ToStr8(lhs);
|
||||
DN_Str8 rhs_s8 = DN_FStr8_ToStr8(rhs);
|
||||
bool result = DN_Str8_Eq(lhs_s8, rhs_s8, DN_Str8EqCase_Insensitive);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <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;
|
||||
}
|
||||
|
||||
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);
|
||||
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)
|
||||
|
120
dqn_tls.cpp
120
dqn_tls.cpp
@ -18,109 +18,133 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: [$TCTX] Dqn_TLS /////////////////////////////////////////////////////////////////
|
||||
Dqn_TLSTMem::Dqn_TLSTMem(Dqn_TLS *tls, uint8_t arena_index, Dqn_TLSPushTMem push_tmem)
|
||||
// NOTE: [$TCTX] DN_TLS /////////////////////////////////////////////////////////////////
|
||||
DN_TLSTMem::DN_TLSTMem(DN_TLS *tls, uint8_t arena_index, DN_TLSPushTMem push_tmem)
|
||||
{
|
||||
DQN_ASSERT(arena_index == Dqn_TLSArena_TMem0 || arena_index == Dqn_TLSArena_TMem1);
|
||||
DN_ASSERT(arena_index == DN_TLSArena_TMem0 || arena_index == DN_TLSArena_TMem1);
|
||||
arena = tls->arenas + arena_index;
|
||||
temp_mem = Dqn_Arena_TempMemBegin(arena);
|
||||
temp_mem = DN_Arena_TempMemBegin(arena);
|
||||
destructed = false;
|
||||
push_arena = push_tmem;
|
||||
if (push_arena)
|
||||
Dqn_TLS_PushArena(arena);
|
||||
DN_TLS_PushArena(arena);
|
||||
}
|
||||
|
||||
Dqn_TLSTMem::~Dqn_TLSTMem()
|
||||
DN_TLSTMem::~DN_TLSTMem()
|
||||
{
|
||||
DQN_ASSERT(destructed == false);
|
||||
Dqn_Arena_TempMemEnd(temp_mem);
|
||||
DN_ASSERT(destructed == false);
|
||||
DN_Arena_TempMemEnd(temp_mem);
|
||||
destructed = true;
|
||||
if (push_arena)
|
||||
Dqn_TLS_PopArena();
|
||||
DN_TLS_PopArena();
|
||||
}
|
||||
|
||||
DQN_API void Dqn_TLS_Init(Dqn_TLS *tls)
|
||||
DN_API void DN_TLS_Init(DN_TLS *tls)
|
||||
{
|
||||
DQN_CHECK(tls);
|
||||
DN_CHECK(tls);
|
||||
if (tls->init)
|
||||
return;
|
||||
|
||||
DQN_FOR_UINDEX (index, Dqn_TLSArena_Count) {
|
||||
Dqn_Arena *arena = tls->arenas + index;
|
||||
switch (DQN_CAST(Dqn_TLSArena)index) {
|
||||
default: *arena = Dqn_Arena_InitSize(DQN_MEGABYTES(4), DQN_KILOBYTES(4), Dqn_ArenaFlag_AllocCanLeak); break;
|
||||
case Dqn_TLSArena_ErrorSink: *arena = Dqn_Arena_InitSize(DQN_KILOBYTES(64), DQN_KILOBYTES(4), Dqn_ArenaFlag_AllocCanLeak); break;
|
||||
case Dqn_TLSArena_Count: DQN_INVALID_CODE_PATH; break;
|
||||
DN_FOR_UINDEX (index, DN_TLSArena_Count) {
|
||||
DN_Arena *arena = tls->arenas + index;
|
||||
switch (DN_CAST(DN_TLSArena)index) {
|
||||
default: *arena = DN_Arena_InitSize(DN_MEGABYTES(4), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); break;
|
||||
case DN_TLSArena_ErrorSink: *arena = DN_Arena_InitSize(DN_KILOBYTES(64), DN_KILOBYTES(4), DN_ArenaFlags_AllocCanLeak); break;
|
||||
case DN_TLSArena_Count: DN_INVALID_CODE_PATH; break;
|
||||
}
|
||||
}
|
||||
|
||||
tls->thread_id = Dqn_OS_ThreadID();
|
||||
tls->error_sink.arena = tls->arenas + Dqn_TLSArena_ErrorSink;
|
||||
tls->thread_id = DN_OS_ThreadID();
|
||||
tls->err_sink.arena = tls->arenas + DN_TLSArena_ErrorSink;
|
||||
tls->init = true;
|
||||
}
|
||||
|
||||
DQN_API Dqn_TLS *Dqn_TLS_Get()
|
||||
DN_API void DN_TLS_Deinit(DN_TLS *tls)
|
||||
{
|
||||
Dqn_TLS *result = g_dqn_os_thread_tls;
|
||||
// TODO(doyle): Fix stack-trace infinite loop with requiring the TLS that is not initialised
|
||||
// yet.
|
||||
DQN_ASSERT(
|
||||
g_dqn_library->lib_init &&
|
||||
"Library context must be be initialised first by calling Dqn_Library_Init. This "
|
||||
"initialises the main thread's TLS for you (no need to call Dqn_OS_ThreadSetTLS on main)");
|
||||
tls->init = false;
|
||||
tls->err_sink = {};
|
||||
tls->arena_stack_index = {};
|
||||
DN_FOR_UINDEX(index, DN_TLSArena_Count)
|
||||
{
|
||||
DN_Arena *arena = tls->arenas + index;
|
||||
DN_Arena_Deinit(arena);
|
||||
}
|
||||
}
|
||||
|
||||
DQN_ASSERT(result &&
|
||||
"Thread must be assigned the TLS with Dqn_OS_ThreadSetTLS. If the library is "
|
||||
DN_API DN_TLS *DN_TLS_Get()
|
||||
{
|
||||
DN_TLS *result = g_dn_os_thread_tls;
|
||||
DN_ASSERT(
|
||||
g_dn_core->init &&
|
||||
"Library context must be be initialised first by calling DN_Library_Init. This "
|
||||
"initialises the main thread's TLS for you (no need to call DN_OS_ThreadSetTLS on main)");
|
||||
|
||||
DN_ASSERT(result &&
|
||||
"Thread must be assigned the TLS with DN_OS_ThreadSetTLS. If the library is "
|
||||
"initialised, then, this thread was created without calling the set TLS function "
|
||||
"for the spawned thread.");
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Arena *Dqn_TLS_Arena()
|
||||
DN_API DN_Arena *DN_TLS_Arena()
|
||||
{
|
||||
Dqn_TLS *tls = Dqn_TLS_Get();
|
||||
Dqn_Arena *result = tls->arenas + Dqn_TLSArena_Main;
|
||||
DN_TLS *tls = DN_TLS_Get();
|
||||
DN_Arena *result = tls->arenas + DN_TLSArena_Main;
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: Is there a way to handle conflict arenas without the user needing to
|
||||
// manually pass it in?
|
||||
DQN_API Dqn_TLSTMem Dqn_TLS_GetTMem(void const *conflict_arena, Dqn_TLSPushTMem push_tmem)
|
||||
DN_API DN_TLSTMem DN_TLS_GetTMem(void const *conflict_arena, DN_TLSPushTMem push_tmem)
|
||||
{
|
||||
Dqn_TLS *tls = Dqn_TLS_Get();
|
||||
DN_TLS *tls = DN_TLS_Get();
|
||||
uint8_t tls_index = (uint8_t)-1;
|
||||
for (uint8_t index = Dqn_TLSArena_TMem0; index <= Dqn_TLSArena_TMem1; index++) {
|
||||
Dqn_Arena *arena = tls->arenas + index;
|
||||
for (uint8_t index = DN_TLSArena_TMem0; index <= DN_TLSArena_TMem1; index++) {
|
||||
DN_Arena *arena = tls->arenas + index;
|
||||
if (!conflict_arena || arena != conflict_arena) {
|
||||
tls_index = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DQN_ASSERT(tls_index != (uint8_t)-1);
|
||||
return Dqn_TLSTMem(tls, tls_index, push_tmem);
|
||||
DN_ASSERT(tls_index != (uint8_t)-1);
|
||||
return DN_TLSTMem(tls, tls_index, push_tmem);
|
||||
}
|
||||
|
||||
DQN_API void Dqn_TLS_PushArena(Dqn_Arena *arena)
|
||||
DN_API void DN_TLS_PushArena(DN_Arena *arena)
|
||||
{
|
||||
DQN_ASSERT(arena);
|
||||
Dqn_TLS *tls = Dqn_TLS_Get();
|
||||
DQN_ASSERT(tls->arena_stack_index < DQN_ARRAY_UCOUNT(tls->arena_stack));
|
||||
DN_ASSERT(arena);
|
||||
DN_TLS *tls = DN_TLS_Get();
|
||||
DN_ASSERT(tls->arena_stack_index < DN_ARRAY_UCOUNT(tls->arena_stack));
|
||||
tls->arena_stack[tls->arena_stack_index++] = arena;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_TLS_PopArena()
|
||||
DN_API void DN_TLS_PopArena()
|
||||
{
|
||||
Dqn_TLS *tls = Dqn_TLS_Get();
|
||||
DQN_ASSERT(tls->arena_stack_index > 0);
|
||||
DN_TLS *tls = DN_TLS_Get();
|
||||
DN_ASSERT(tls->arena_stack_index > 0);
|
||||
tls->arena_stack_index--;
|
||||
}
|
||||
|
||||
DQN_API Dqn_Arena *Dqn_TLS_TopArena()
|
||||
DN_API DN_Arena *DN_TLS_TopArena()
|
||||
{
|
||||
Dqn_TLS *tls = Dqn_TLS_Get();
|
||||
Dqn_Arena *result = nullptr;
|
||||
DN_TLS *tls = DN_TLS_Get();
|
||||
DN_Arena *result = nullptr;
|
||||
if (tls->arena_stack_index)
|
||||
result = tls->arena_stack[tls->arena_stack_index - 1];
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_TLS_BeginFrame(DN_Arena *frame_arena)
|
||||
{
|
||||
DN_TLS *tls = DN_TLS_Get();
|
||||
tls->frame_arena = frame_arena;
|
||||
}
|
||||
|
||||
DN_API DN_Arena *DN_TLS_FrameArena()
|
||||
{
|
||||
DN_TLS *tls = DN_TLS_Get();
|
||||
DN_Arena *result = tls->frame_arena;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
73
dqn_tls.h
73
dqn_tls.h
@ -27,58 +27,67 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
enum Dqn_TLSArena
|
||||
enum DN_TLSArena
|
||||
{
|
||||
Dqn_TLSArena_Main, // NOTE: Arena for Permanent allocations
|
||||
Dqn_TLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread
|
||||
DN_TLSArena_Main, // NOTE: Arena for Permanent allocations
|
||||
DN_TLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread
|
||||
|
||||
// NOTE: Per-thread scratch arenas (2 to prevent aliasing)
|
||||
Dqn_TLSArena_TMem0,
|
||||
Dqn_TLSArena_TMem1,
|
||||
DN_TLSArena_TMem0,
|
||||
DN_TLSArena_TMem1,
|
||||
|
||||
Dqn_TLSArena_Count,
|
||||
DN_TLSArena_Count,
|
||||
};
|
||||
|
||||
struct Dqn_TLS
|
||||
struct DN_TLS
|
||||
{
|
||||
Dqn_b32 init; // Flag to track if Thread has been initialised
|
||||
DN_B32 init; // Flag to track if Thread has been initialised
|
||||
uint64_t thread_id;
|
||||
Dqn_CallSite call_site; // Stores call-site information when requested by thread
|
||||
Dqn_ErrorSink error_sink; // Error handling state
|
||||
Dqn_Arena arenas[Dqn_TLSArena_Count];
|
||||
DN_CallSite call_site; // Stores call-site information when requested by thread
|
||||
DN_ErrSink err_sink; // Error handling state
|
||||
DN_Arena arenas[DN_TLSArena_Count];
|
||||
|
||||
// Push and pop arenas onto the stack. Functions suffixed 'TLS' will use
|
||||
// these arenas for memory allocation.
|
||||
Dqn_Arena *arena_stack[8];
|
||||
Dqn_usize arena_stack_index;
|
||||
DN_Arena *arena_stack[8];
|
||||
DN_USize arena_stack_index;
|
||||
|
||||
DN_Arena *frame_arena;
|
||||
char name[64];
|
||||
uint8_t name_size;
|
||||
};
|
||||
|
||||
// Push the temporary memory arena when retrieved, popped when the arena goes
|
||||
// out of scope. Pushed arenas are used automatically as the allocator in TLS
|
||||
// suffixed function.
|
||||
enum Dqn_TLSPushTMem
|
||||
enum DN_TLSPushTMem
|
||||
{
|
||||
Dqn_TLSPushTMem_No,
|
||||
Dqn_TLSPushTMem_Yes,
|
||||
DN_TLSPushTMem_No,
|
||||
DN_TLSPushTMem_Yes,
|
||||
};
|
||||
|
||||
struct Dqn_TLSTMem
|
||||
struct DN_TLSTMem
|
||||
{
|
||||
Dqn_TLSTMem(Dqn_TLS *context, uint8_t context_index, Dqn_TLSPushTMem push_scratch);
|
||||
~Dqn_TLSTMem();
|
||||
DN_TLSTMem(DN_TLS *context, uint8_t context_index, DN_TLSPushTMem push_scratch);
|
||||
~DN_TLSTMem();
|
||||
|
||||
Dqn_Arena *arena;
|
||||
Dqn_b32 destructed;
|
||||
Dqn_TLSPushTMem push_arena;
|
||||
Dqn_ArenaTempMem temp_mem;
|
||||
DN_Arena *arena;
|
||||
DN_B32 destructed;
|
||||
DN_TLSPushTMem push_arena;
|
||||
DN_ArenaTempMem temp_mem;
|
||||
};
|
||||
|
||||
DQN_API void Dqn_TLS_Init(Dqn_TLS *tls);
|
||||
DQN_API Dqn_TLS * Dqn_TLS_Get();
|
||||
#define Dqn_TLS_SaveCallSite do { Dqn_TLS_Get()->call_site = DQN_CALL_SITE; } while (0)
|
||||
DQN_API Dqn_TLSTMem Dqn_TLS_GetTMem(void const *conflict_arena, Dqn_TLSPushTMem push_tmp_mem);
|
||||
#define Dqn_TLS_TMem(...) Dqn_TLS_GetTMem(__VA_ARGS__, Dqn_TLSPushTMem_No)
|
||||
#define Dqn_TLS_PushTMem(...) Dqn_TLS_GetTMem(__VA_ARGS__, Dqn_TLSPushTMem_Yes)
|
||||
DQN_API void Dqn_TLS_PushArena(Dqn_Arena *arena);
|
||||
DQN_API void Dqn_TLS_PopArena();
|
||||
DQN_API Dqn_Arena * Dqn_TLS_TopArena();
|
||||
DN_API void DN_TLS_Init(DN_TLS *tls);
|
||||
DN_API void DN_TLS_Deinit(DN_TLS *tls);
|
||||
DN_API DN_TLS * DN_TLS_Get();
|
||||
DN_API DN_Arena * DN_TLS_Arena();
|
||||
#define DN_TLS_SaveCallSite do { DN_TLS_Get()->call_site = DN_CALL_SITE; } while (0)
|
||||
DN_API DN_TLSTMem DN_TLS_GetTMem(void const *conflict_arena, DN_TLSPushTMem push_tmp_mem);
|
||||
#define DN_TLS_TMem(...) DN_TLS_GetTMem(__VA_ARGS__, DN_TLSPushTMem_No)
|
||||
#define DN_TLS_PushTMem(...) DN_TLS_GetTMem(__VA_ARGS__, DN_TLSPushTMem_Yes)
|
||||
DN_API void DN_TLS_PushArena(DN_Arena *arena);
|
||||
DN_API void DN_TLS_PopArena();
|
||||
DN_API DN_Arena * DN_TLS_TopArena();
|
||||
|
||||
DN_API void DN_TLS_BeginFrame(DN_Arena *frame_arena);
|
||||
DN_API DN_Arena * DN_TLS_FrameArena();
|
||||
|
@ -18,15 +18,15 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
Dqn_TypeGetField Dqn_Type_GetField(Dqn_TypeInfo const *type_info, Dqn_Str8 name)
|
||||
DN_TypeGetField DN_Type_GetField(DN_TypeInfo const *type_info, DN_Str8 name)
|
||||
{
|
||||
Dqn_TypeGetField result = {};
|
||||
for (Dqn_usize index = 0; index < type_info->fields_count; index++) {
|
||||
Dqn_TypeField const *type_field = type_info->fields + index;
|
||||
DN_TypeGetField result = {};
|
||||
for (DN_USize index = 0; index < type_info->fields_count; index++) {
|
||||
DN_TypeField const *type_field = type_info->fields + index;
|
||||
if (type_field->name == name) {
|
||||
result.success = true;
|
||||
result.index = index;
|
||||
result.field = DQN_CAST(Dqn_TypeField *)type_field;
|
||||
result.field = DN_CAST(DN_TypeField *)type_field;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -18,44 +18,44 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
enum Dqn_TypeKind
|
||||
enum DN_TypeKind
|
||||
{
|
||||
Dqn_TypeKind_Nil,
|
||||
Dqn_TypeKind_Basic,
|
||||
Dqn_TypeKind_Enum,
|
||||
Dqn_TypeKind_Struct,
|
||||
DN_TypeKind_Nil,
|
||||
DN_TypeKind_Basic,
|
||||
DN_TypeKind_Enum,
|
||||
DN_TypeKind_Struct,
|
||||
};
|
||||
|
||||
struct Dqn_TypeField
|
||||
struct DN_TypeField
|
||||
{
|
||||
uint16_t index;
|
||||
Dqn_Str8 name;
|
||||
Dqn_Str8 label;
|
||||
Dqn_isize value;
|
||||
Dqn_usize offset_of;
|
||||
Dqn_usize size_of;
|
||||
Dqn_usize align_of;
|
||||
Dqn_Str8 type_decl;
|
||||
DN_Str8 name;
|
||||
DN_Str8 label;
|
||||
DN_ISize value;
|
||||
DN_USize offset_of;
|
||||
DN_USize size_of;
|
||||
DN_USize align_of;
|
||||
DN_Str8 type_decl;
|
||||
uint32_t type_enum;
|
||||
bool is_pointer;
|
||||
uint16_t array_size;
|
||||
Dqn_TypeField const * array_size_field;
|
||||
DN_TypeField const * array_size_field;
|
||||
};
|
||||
|
||||
struct Dqn_TypeInfo
|
||||
struct DN_TypeInfo
|
||||
{
|
||||
Dqn_Str8 name;
|
||||
Dqn_TypeKind kind;
|
||||
Dqn_usize size_of;
|
||||
Dqn_TypeField const *fields;
|
||||
DN_Str8 name;
|
||||
DN_TypeKind kind;
|
||||
DN_USize size_of;
|
||||
DN_TypeField const *fields;
|
||||
uint16_t fields_count;
|
||||
};
|
||||
|
||||
struct Dqn_TypeGetField
|
||||
struct DN_TypeGetField
|
||||
{
|
||||
bool success;
|
||||
Dqn_usize index;
|
||||
Dqn_TypeField *field;
|
||||
DN_USize index;
|
||||
DN_TypeField *field;
|
||||
};
|
||||
|
||||
Dqn_TypeGetField Dqn_Type_GetField(Dqn_TypeInfo const *type_info, Dqn_Str8 name);
|
||||
DN_TypeGetField DN_Type_GetField(DN_TypeInfo const *type_info, DN_Str8 name);
|
||||
|
2701
dqn_unit_tests.cpp
2701
dqn_unit_tests.cpp
File diff suppressed because it is too large
Load Diff
12
dqn_unit_tests_main.cpp
Normal file
12
dqn_unit_tests_main.cpp
Normal 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;
|
||||
}
|
91
dqn_win32.h
91
dqn_win32.h
@ -13,12 +13,12 @@
|
||||
// $$ / \$$ |$$$$$$\ $$ | \$$ |\$$$$$$ |$$$$$$$$\
|
||||
// \__/ \__|\______|\__| \__| \______/ \________|
|
||||
//
|
||||
// dqn_win32.h -- Windows replacement header
|
||||
// dn_win32.h -- Windows replacement header
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL)
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
#pragma comment(lib, "bcrypt")
|
||||
#pragma comment(lib, "winhttp")
|
||||
#pragma comment(lib, "dbghelp")
|
||||
@ -27,18 +27,19 @@
|
||||
#pragma comment(lib, "shlwapi")
|
||||
#endif
|
||||
|
||||
#if defined(DQN_NO_WIN32_MIN_HEADER) || defined(_INC_WINDOWS)
|
||||
#if defined(DN_NO_WIN32_MIN_HEADER) || defined(_INC_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h> // LONG
|
||||
#include <bcrypt.h> // Dqn_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc
|
||||
#include <shellapi.h> // Dqn_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc
|
||||
#include <bcrypt.h> // DN_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc
|
||||
#include <shellapi.h> // DN_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc
|
||||
#include <shlwapi.h> // PathRelativePathTO
|
||||
#include <pathcch.h> // PathCchCanonicalizeEx
|
||||
#include <winhttp.h> // WinHttp*
|
||||
#include <commdlg.h> // OPENFILENAMEW
|
||||
#include <DbgHelp.h>
|
||||
#else
|
||||
DQN_MSVC_WARNING_PUSH
|
||||
DQN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
||||
|
||||
// NOTE: basetsd.h /////////////////////////////////////////////////////////////////////////////
|
||||
typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
|
||||
@ -111,6 +112,25 @@
|
||||
#define PAGE_READWRITE 0x04
|
||||
#define PAGE_GUARD 0x100
|
||||
|
||||
// NOTE: HeapAlloc
|
||||
#define HEAP_ZERO_MEMORY 0x00000008
|
||||
#define HEAP_NO_SERIALIZE 0x00000001
|
||||
#define HEAP_GROWABLE 0x00000002
|
||||
#define HEAP_GENERATE_EXCEPTIONS 0x00000004
|
||||
#define HEAP_ZERO_MEMORY 0x00000008
|
||||
#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010
|
||||
#define HEAP_TAIL_CHECKING_ENABLED 0x00000020
|
||||
#define HEAP_FREE_CHECKING_ENABLED 0x00000040
|
||||
#define HEAP_DISABLE_COALESCE_ON_FREE 0x00000080
|
||||
#define HEAP_CREATE_ALIGN_16 0x00010000
|
||||
#define HEAP_CREATE_ENABLE_TRACING 0x00020000
|
||||
#define HEAP_CREATE_ENABLE_EXECUTE 0x00040000
|
||||
#define HEAP_MAXIMUM_TAG 0x0FFF
|
||||
#define HEAP_PSEUDO_TAG_FLAG 0x8000
|
||||
#define HEAP_TAG_SHIFT 18
|
||||
#define HEAP_CREATE_SEGMENT_HEAP 0x00000100
|
||||
#define HEAP_CREATE_HARDENED 0x00000200
|
||||
|
||||
// NOTE: FormatMessageA
|
||||
#define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p))
|
||||
#define LANG_NEUTRAL 0x00
|
||||
@ -331,6 +351,19 @@
|
||||
__declspec(dllimport) BOOL __stdcall SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll);
|
||||
}
|
||||
|
||||
// NOTE: um/heapapi.h ////////////////////////////////////////////////////////////////////
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) HANDLE __stdcall HeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize);
|
||||
__declspec(dllimport) BOOL __stdcall HeapDestroy(HANDLE hHeap);
|
||||
__declspec(dllimport) VOID * __stdcall HeapAlloc(HANDLE hHeap, DWORD dwFlags,SIZE_T dwBytes);
|
||||
__declspec(dllimport) VOID * __stdcall HeapReAlloc(HANDLE hHeap, DWORD dwFlags, VOID *lpMem, SIZE_T dwBytes);
|
||||
__declspec(dllimport) BOOL __stdcall HeapFree(HANDLE hHeap, DWORD dwFlags, VOID *lpMem);
|
||||
__declspec(dllimport) SIZE_T __stdcall HeapSize(HANDLE hHeap, DWORD dwFlags, VOID const *lpMem);
|
||||
__declspec(dllimport) HANDLE __stdcall GetProcessHeap(VOID);
|
||||
__declspec(dllimport) SIZE_T __stdcall HeapCompact(HANDLE hHeap, DWORD dwFlags);
|
||||
}
|
||||
|
||||
// NOTE: shared/windef.h ////////////////////////////////////////////////////////////////////
|
||||
typedef struct tagPOINT
|
||||
{
|
||||
@ -367,6 +400,10 @@
|
||||
#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
|
||||
#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )
|
||||
|
||||
// NOTE: CreateProcessW
|
||||
#define CREATE_UNICODE_ENVIRONMENT 0x00000400
|
||||
#define CREATE_NO_WINDOW 0x08000000
|
||||
|
||||
typedef enum _GET_FILEEX_INFO_LEVELS {
|
||||
GetFileExInfoStandard,
|
||||
GetFileExMaxInfoLevel
|
||||
@ -499,9 +536,12 @@
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile);
|
||||
__declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes);
|
||||
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
|
||||
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
|
||||
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
|
||||
|
||||
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
|
||||
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW(const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
|
||||
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
|
||||
@ -509,14 +549,17 @@
|
||||
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
__declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped);
|
||||
__declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped);
|
||||
|
||||
}
|
||||
|
||||
// NOTE: um/processenv.h ///////////////////////////////////////////////////////////////////////
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) DWORD __stdcall GetCurrentDirectoryW(DWORD nBufferLength, WCHAR *lpBuffer);
|
||||
__declspec(dllimport) HANDLE __stdcall GetStdHandle(DWORD nStdHandle);
|
||||
__declspec(dllimport) DWORD __stdcall GetCurrentDirectoryW (DWORD nBufferLength, WCHAR *lpBuffer);
|
||||
__declspec(dllimport) HANDLE __stdcall GetStdHandle (DWORD nStdHandle);
|
||||
__declspec(dllimport) WCHAR* __stdcall GetEnvironmentStringsW ();
|
||||
__declspec(dllimport) BOOL __stdcall FreeEnvironmentStringsW(WCHAR *penv);
|
||||
__declspec(dllimport) DWORD __stdcall GetEnvironmentVariableW(WCHAR const *lpName, WCHAR *lpBuffer, DWORD nSize);
|
||||
__declspec(dllimport) BOOL __stdcall SetEnvironmentVariableW(WCHAR const *lpName, WCHAR const *lpValue);
|
||||
}
|
||||
|
||||
// NOTE: um/sysinfoapi.h ///////////////////////////////////////////////////////////////////////
|
||||
@ -548,10 +591,21 @@
|
||||
}
|
||||
|
||||
// NOTE: um/timezoneapi.h //////////////////////////////////////////////////////////////////////
|
||||
typedef struct _TIME_ZONE_INFORMATION {
|
||||
LONG Bias;
|
||||
WCHAR StandardName[32];
|
||||
SYSTEMTIME StandardDate;
|
||||
LONG StandardBias;
|
||||
WCHAR DaylightName[32];
|
||||
SYSTEMTIME DaylightDate;
|
||||
LONG DaylightBias;
|
||||
} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) BOOL __stdcall FileTimeToSystemTime(const FILETIME* lpFileTime, SYSTEMTIME *lpSystemTime);
|
||||
__declspec(dllimport) BOOL __stdcall SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, FILETIME *lpFileTime);
|
||||
__declspec(dllimport) BOOL __stdcall FileTimeToSystemTime (const FILETIME* lpFileTime, SYSTEMTIME *lpSystemTime);
|
||||
__declspec(dllimport) BOOL __stdcall SystemTimeToFileTime (const SYSTEMTIME* lpSystemTime, FILETIME *lpFileTime);
|
||||
__declspec(dllimport) BOOL __stdcall TzSpecificLocalTimeToSystemTime(const TIME_ZONE_INFORMATION* lpTimeZoneInformation, const SYSTEMTIME* lpLocalTime, const LPSYSTEMTIME lpUniversalTime);
|
||||
}
|
||||
|
||||
// NOTE: shared/windef.h ///////////////////////////////////////////////////////////////////////
|
||||
@ -1249,5 +1303,16 @@
|
||||
__declspec(dllimport) HRESULT __stdcall PathCchCanonicalizeEx(PWSTR pszPathOut, size_t cchPathOut, WCHAR const *pszPathIn, ULONG dwFlags);
|
||||
};
|
||||
|
||||
DQN_MSVC_WARNING_POP
|
||||
// NOTE: um/errhandlingapi.h ///////////////////////////////////////////////////////////////////
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) VOID __stdcall RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR* lpArguments);
|
||||
};
|
||||
|
||||
// NOTE: include/excpt.h ///////////////////////////////////////////////////////////////////
|
||||
#define EXCEPTION_EXECUTE_HANDLER 1
|
||||
#define EXCEPTION_CONTINUE_SEARCH 0
|
||||
#define EXCEPTION_CONTINUE_EXECUTION (-1)
|
||||
|
||||
DN_MSVC_WARNING_POP
|
||||
#endif // !defined(_INC_WINDOWS)
|
||||
|
Loading…
x
Reference in New Issue
Block a user