Import latest changes from CSIGHT project
This commit is contained in:
parent
bf413d7e57
commit
022c309e3a
@ -2,7 +2,7 @@
|
||||
#define DQN_CPP_FILE_H
|
||||
|
||||
// NOTE: Dqn_CppFile: Helper functions to generate C++ files
|
||||
// =============================================================================
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
#include <stdio.h> /// printf, fputc
|
||||
#include <stdarg.h> /// va_list...
|
||||
#include <assert.h> /// assert
|
||||
@ -51,21 +51,21 @@ void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...);
|
||||
|
||||
#define Dqn_CppEnumBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__), true); \
|
||||
(Dqn_CppBeginEnumBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndEnumBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppForBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginBlock(cpp, false /*append*/, "for (" fmt ")", ##__VA_ARGS__), true); \
|
||||
(Dqn_CppBeginForBLock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndForBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppWhileBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginBlock(cpp, false /*append*/, "while (" fmt ")", ##__VA_ARGS__), true); \
|
||||
(Dqn_CppBeginWhileBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndForBlock(cpp), false))
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndWhileBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppIfOrElseIfBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
@ -81,22 +81,28 @@ void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...);
|
||||
|
||||
#define Dqn_CppFuncBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__), true); \
|
||||
(Dqn_CppBeginFuncBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndFuncBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppStructBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginBlock(cpp, false /*append*/, "struct " fmt, ##__VA_ARGS__), true); \
|
||||
(Dqn_CppBeginStructBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndStructBlock(cpp), false))
|
||||
|
||||
#define Dqn_CppSwitchBlock(cpp, fmt, ...) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
|
||||
(Dqn_CppBeginBlock(cpp, false /*append*/, "switch (" fmt ")", ##__VA_ARGS__), true); \
|
||||
(Dqn_CppBeginSwitchBlock(cpp, fmt, ##__VA_ARGS__), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_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 Dqn_CppIfChain(cpp) \
|
||||
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppBeginIfChain(cpp), true); \
|
||||
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
|
||||
@ -106,29 +112,32 @@ void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...);
|
||||
/// 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);
|
||||
void Dqn_CppEndBlock (Dqn_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*/, fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndEnumBlock(cpp) Dqn_CppEndBlock(cpp), Dqn_CppAppend(cpp, ";\n")
|
||||
#define Dqn_CppBeginEnumBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "enum " fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndEnumBlock(cpp) Dqn_CppEndBlock(cpp, ";\n")
|
||||
|
||||
#define Dqn_CppBeginForBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndForBlock(cpp) Dqn_CppEndBlock(cpp), Dqn_CppAppend(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 Dqn_CppBeginForBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "for (" fmt ")", ##__VA_ARGS__)
|
||||
#define Dqn_CppEndForBlock(cpp) Dqn_CppEndBlock(cpp, "\n")
|
||||
|
||||
#define Dqn_CppBeginFuncBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndFuncBlock(cpp) Dqn_CppEndBlock(cpp), Dqn_CppAppend(cpp, "\n")
|
||||
#define Dqn_CppEndFuncBlock(cpp) Dqn_CppEndBlock(cpp, "\n")
|
||||
|
||||
#define Dqn_CppBeginStructBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndStructBlock(cpp) Dqn_CppEndBlock(cpp), Dqn_CppAppend(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 Dqn_CppBeginSwitchBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, fmt, ##__VA_ARGS__)
|
||||
#define Dqn_CppEndSwitchBlock(cpp) Dqn_CppEndBlock(cpp), Dqn_CppAppend(cpp, "\n")
|
||||
#define Dqn_CppBeginSwitchBlock(cpp, fmt, ...) Dqn_CppBeginBlock(cpp, false /*append*/, "switch (" fmt ")", ##__VA_ARGS__)
|
||||
#define Dqn_CppEndSwitchBlock(cpp) Dqn_CppEndBlock(cpp, "\n")
|
||||
|
||||
void Dqn_CppBeginIfOrElseIfBlock (Dqn_CppFile *cpp, char const *fmt, ...);
|
||||
#define Dqn_CppEndIfOrElseIfBlock(cpp) Dqn_CppEndBlock(cpp)
|
||||
#define Dqn_CppEndIfOrElseIfBlock(cpp) Dqn_CppEndBlock(cpp, "")
|
||||
|
||||
void Dqn_CppBeginElseBlock (Dqn_CppFile *cpp);
|
||||
#define Dqn_CppEndElseBlock(cpp) Dqn_CppEndBlock(cpp)
|
||||
void Dqn_CppEndElseBlock (Dqn_CppFile *cpp);
|
||||
|
||||
#define DQN_CPP_TOKEN_PASTE2_(x, y) x ## y
|
||||
#define DQN_CPP_TOKEN_PASTE_(x, y) DQN_CPP_TOKEN_PASTE2_(x, y)
|
||||
@ -179,20 +188,23 @@ void Dqn_CppBeginBlockV(Dqn_CppFile *cpp, bool append, char const *fmt, va_list
|
||||
Dqn_CppAppendV(cpp, fmt, args);
|
||||
else
|
||||
Dqn_CppPrintV(cpp, fmt, args);
|
||||
Dqn_CppAppend(cpp, " {\n");
|
||||
|
||||
bool empty_fmt = fmt == nullptr || strlen(fmt) == 0;
|
||||
Dqn_CppAppend(cpp, "%s{\n", empty_fmt ? "" : " ");
|
||||
Dqn_CppIndent(cpp);
|
||||
}
|
||||
|
||||
void Dqn_CppEndBlock(Dqn_CppFile *cpp)
|
||||
void Dqn_CppEndBlock(Dqn_CppFile *cpp, char const *ending)
|
||||
{
|
||||
Dqn_CppUnindent(cpp);
|
||||
Dqn_CppPrint(cpp, "}");
|
||||
Dqn_CppPrint(cpp, "}%s", ending);
|
||||
}
|
||||
|
||||
void Dqn_CppBeginIfOrElseIfBlock(Dqn_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");
|
||||
else
|
||||
@ -208,10 +220,17 @@ void Dqn_CppBeginIfOrElseIfBlock(Dqn_CppFile *cpp, char const *fmt, ...)
|
||||
|
||||
void Dqn_CppBeginElseBlock(Dqn_CppFile *cpp)
|
||||
{
|
||||
assert(cpp->if_chain_size);
|
||||
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1)
|
||||
Dqn_CppBeginBlock(cpp, true /*append*/, " else");
|
||||
}
|
||||
|
||||
void Dqn_CppEndElseBlock(Dqn_CppFile *cpp)
|
||||
{
|
||||
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1)
|
||||
Dqn_CppEndBlock(cpp, "");
|
||||
}
|
||||
|
||||
void Dqn_CppBeginIfChain(Dqn_CppFile *cpp)
|
||||
{
|
||||
assert(cpp->if_chain_size < sizeof(cpp->if_chain)/sizeof(cpp->if_chain[0]));
|
||||
@ -220,8 +239,12 @@ void Dqn_CppBeginIfChain(Dqn_CppFile *cpp)
|
||||
|
||||
void Dqn_CppEndIfChain(Dqn_CppFile *cpp)
|
||||
{
|
||||
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1)
|
||||
assert(cpp->if_chain_size);
|
||||
if (cpp->if_chain[cpp->if_chain_size - 1] >= 1) {
|
||||
Dqn_CppNewLine(cpp);
|
||||
}
|
||||
cpp->if_chain[cpp->if_chain_size - 1] = 0;
|
||||
cpp->if_chain_size--;
|
||||
}
|
||||
|
||||
#endif // DQN_CPP_FILE_IMPLEMENTATION
|
||||
|
375
Misc/dqn_json.h
375
Misc/dqn_json.h
@ -4,103 +4,93 @@
|
||||
|
||||
#if !defined(DQN_JSON_H)
|
||||
#define DQN_JSON_H
|
||||
// NOTE: Dqn_JSON //////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// NOTE: Dqn_JSON
|
||||
// -----------------------------------------------------------------------------
|
||||
void *Dqn_JSON_ArenaAllocFunc(void *user_data, size_t count);
|
||||
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_String8 rhs);
|
||||
bool Dqn_JSON_String8Cmp (json_string_s const *lhs, Dqn_Str8 rhs);
|
||||
|
||||
// NOTE: Dqn_JSON_Iterator
|
||||
// -----------------------------------------------------------------------------
|
||||
enum Dqn_JSONIteratorEntryType
|
||||
// NOTE: Dqn_JSON_It /////////////////////////////////////////////////////////////////////////
|
||||
enum Dqn_JSONItEntryType
|
||||
{
|
||||
Dqn_JSON_IteratorEntryTypeObjElement,
|
||||
Dqn_JSON_IteratorEntryTypeObj,
|
||||
Dqn_JSON_IteratorEntryTypeArrayElement,
|
||||
Dqn_JSON_IteratorEntryTypeArray,
|
||||
Dqn_JSON_IteratorEntryTypeString,
|
||||
Dqn_JSON_IteratorEntryTypeNumber,
|
||||
Dqn_JSON_ItEntryTypeObjElement,
|
||||
Dqn_JSON_ItEntryTypeObj,
|
||||
Dqn_JSON_ItEntryTypeArrayElement,
|
||||
Dqn_JSON_ItEntryTypeArray,
|
||||
Dqn_JSON_ItEntryTypeString,
|
||||
Dqn_JSON_ItEntryTypeNumber,
|
||||
};
|
||||
|
||||
struct Dqn_JSONIteratorEntry
|
||||
struct Dqn_JSONItEntry
|
||||
{
|
||||
Dqn_JSONIteratorEntryType type;
|
||||
void *value;
|
||||
Dqn_JSONItEntryType type;
|
||||
void *value;
|
||||
};
|
||||
|
||||
struct Dqn_JSONIterator
|
||||
struct Dqn_JSONIt
|
||||
{
|
||||
Dqn_JSONIteratorEntry stack[128];
|
||||
int stack_count;
|
||||
size_t flags;
|
||||
Dqn_JSONItEntry stack[128];
|
||||
int stack_count;
|
||||
size_t flags;
|
||||
};
|
||||
|
||||
// NOTE: Dqn_JSON_IteratorPush/Pop
|
||||
// -----------------------------------------------------------------------------
|
||||
bool Dqn_JSON_IteratorPushObjElement (Dqn_JSONIterator *it, json_object_element_s *element);
|
||||
bool Dqn_JSON_IteratorPushObj (Dqn_JSONIterator *it, json_object_s *obj);
|
||||
bool Dqn_JSON_IteratorPushArrayElement(Dqn_JSONIterator *it, json_array_element_s *element);
|
||||
bool Dqn_JSON_IteratorPushArray (Dqn_JSONIterator *it, json_value_s *value);
|
||||
bool Dqn_JSON_IteratorPushValue (Dqn_JSONIterator *it, json_value_s *value);
|
||||
void Dqn_JSON_IteratorPop (Dqn_JSONIterator *it);
|
||||
Dqn_JSONIt Dqn_JSON_LoadFileToIt(Dqn_Arena *arena, Dqn_Str8 json);
|
||||
|
||||
// NOTE: Dqn_JSON_Iterator tree navigation
|
||||
// -----------------------------------------------------------------------------
|
||||
json_value_s *Dqn_JSON_IteratorPushCurrValue(Dqn_JSONIterator *it);
|
||||
bool Dqn_JSON_IteratorNext(Dqn_JSONIterator *it);
|
||||
// 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);
|
||||
|
||||
#define Dqn_JSON_IteratorErrorUnrecognisedKey(it) Dqn_JSON_IteratorErrorUnrecognisedKey_(it, DQN_STRING8(__FILE__), DQN_STRING8(__func__), __LINE__)
|
||||
void Dqn_JSON_IteratorErrorUnrecognisedKey_(Dqn_JSONIterator *it, Dqn_String8 file, Dqn_String8 func, Dqn_uint line);
|
||||
// NOTE: Dqn_JSON_It tree navigation /////////////////////////////////////////////////////////
|
||||
json_value_s *Dqn_JSON_ItPushCurrValue(Dqn_JSONIt *it);
|
||||
bool Dqn_JSON_ItNext(Dqn_JSONIt *it);
|
||||
|
||||
#define Dqn_JSON_IteratorPushCurrValueIterateThenPop(it) \
|
||||
for(void *DQN_UNIQUE_NAME(ptr) = Dqn_JSON_IteratorPushCurrValue(it); DQN_UNIQUE_NAME(ptr); Dqn_JSON_IteratorPop(it), DQN_UNIQUE_NAME(ptr) = nullptr) \
|
||||
while (Dqn_JSON_IteratorNext(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))
|
||||
|
||||
// NOTE: Dqn_JSON_IteratorCurr
|
||||
// -----------------------------------------------------------------------------
|
||||
Dqn_JSONIteratorEntry *Dqn_JSON_IteratorCurr(Dqn_JSONIterator *it);
|
||||
json_value_s *Dqn_JSON_IteratorCurrValue(Dqn_JSONIterator *it);
|
||||
json_object_element_s *Dqn_JSON_IteratorCurrObjElement(Dqn_JSONIterator *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: Dqn_JSON_IteratorValueIs
|
||||
// -----------------------------------------------------------------------------
|
||||
json_value_s *Dqn_JSON_IteratorValueIs(Dqn_JSONIterator *it, json_type_e type);
|
||||
json_object_s *Dqn_JSON_IteratorValueIsObj(Dqn_JSONIterator *it);
|
||||
json_array_s *Dqn_JSON_IteratorValueIsArray(Dqn_JSONIterator *it);
|
||||
json_string_s *Dqn_JSON_IteratorValueIsString(Dqn_JSONIterator *it);
|
||||
json_number_s *Dqn_JSON_IteratorValueIsNumber(Dqn_JSONIterator *it);
|
||||
json_value_s *Dqn_JSON_IteratorValueIsBool(Dqn_JSONIterator *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);
|
||||
|
||||
size_t Dqn_JSON_IteratorValueArraySize(Dqn_JSONIterator *it);
|
||||
size_t Dqn_JSON_ItValueArraySize(Dqn_JSONIt *it);
|
||||
|
||||
// NOTE: Dqn_JSON_IteratorKeyValueIs
|
||||
// -----------------------------------------------------------------------------
|
||||
Dqn_String8 Dqn_JSON_IteratorKey(Dqn_JSONIterator *it);
|
||||
bool Dqn_JSON_IteratorKeyIs(Dqn_JSONIterator *it, Dqn_String8 key);
|
||||
json_object_s *Dqn_JSON_IteratorKeyValueIsObj(Dqn_JSONIterator *it, Dqn_String8 key);
|
||||
json_array_s *Dqn_JSON_IteratorKeyValueIsArray(Dqn_JSONIterator *it, Dqn_String8 key);
|
||||
json_string_s *Dqn_JSON_IteratorKeyValueIsString(Dqn_JSONIterator *it, Dqn_String8 key);
|
||||
json_number_s *Dqn_JSON_IteratorKeyValueIsNumber(Dqn_JSONIterator *it, Dqn_String8 key);
|
||||
json_value_s *Dqn_JSON_IteratorKeyValueIsBool(Dqn_JSONIterator *it, Dqn_String8 key);
|
||||
// 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: Dqn_JSON_IteratorValueTo
|
||||
// -----------------------------------------------------------------------------
|
||||
Dqn_String8 Dqn_JSON_IteratorValueToString(Dqn_JSONIterator *it);
|
||||
int64_t Dqn_JSON_IteratorValueToI64(Dqn_JSONIterator *it);
|
||||
uint64_t Dqn_JSON_IteratorValueToU64(Dqn_JSONIterator *it);
|
||||
bool Dqn_JSON_IteratorValueToBool(Dqn_JSONIterator *it);
|
||||
// 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);
|
||||
|
||||
#define Dqn_JSON_IteratorErrorUnknownKeyValue(it) \
|
||||
Dqn_JSON_IteratorErrorUnknownKeyValue_(it, DQN_CALL_SITE)
|
||||
|
||||
void Dqn_JSON_IteratorErrorUnknownKeyValue_(Dqn_JSONIterator *it, Dqn_String8 file, Dqn_String8 func, int line);
|
||||
#define Dqn_JSON_ItErrorUnknownKeyValue(it) Dqn_JSON_ItErrorUnknownKeyValue_(it, DQN_CALL_SITE)
|
||||
void Dqn_JSON_ItErrorUnknownKeyValue_(Dqn_JSONIt *it, Dqn_CallSite call_site);
|
||||
|
||||
#endif // DQN_JSON_H
|
||||
|
||||
#if defined(DQN_JSON_IMPLEMENTATION)
|
||||
// NOTE: Dqn_JSON
|
||||
// -----------------------------------------------------------------------------
|
||||
// NOTE: Dqn_JSON //////////////////////////////////////////////////////////////////////////////////
|
||||
void *Dqn_JSON_ArenaAllocFunc(void *user_data, size_t count)
|
||||
{
|
||||
void *result = NULL;
|
||||
@ -108,7 +98,7 @@ void *Dqn_JSON_ArenaAllocFunc(void *user_data, size_t count)
|
||||
return result;
|
||||
|
||||
Dqn_Arena *arena = DQN_CAST(Dqn_Arena*)user_data;
|
||||
result = Dqn_Arena_Allocate(arena, count, alignof(json_value_s), Dqn_ZeroMem_No);
|
||||
result = Dqn_Arena_Alloc(arena, count, alignof(json_value_s), Dqn_ZeroMem_No);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -127,70 +117,86 @@ char const *Dqn_JSON_TypeEnumCString(json_type_e type, size_t *size)
|
||||
}
|
||||
}
|
||||
|
||||
bool Dqn_JSON_String8Cmp(json_string_s const *lhs, Dqn_String8 key)
|
||||
bool Dqn_JSON_String8Cmp(json_string_s const *lhs, Dqn_Str8 key)
|
||||
{
|
||||
bool result = false;
|
||||
if (lhs && Dqn_String8_IsValid(key)) {
|
||||
Dqn_String8 lhs_string = Dqn_String8_Init(lhs->string, lhs->string_size);
|
||||
result = Dqn_String8_Eq(lhs_string, key);
|
||||
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);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_Iterator_push/pop
|
||||
// -----------------------------------------------------------------------------
|
||||
bool Dqn_JSON_IteratorPushObjElement(Dqn_JSONIterator *it, json_object_element_s *element)
|
||||
// NOTE: Dqn_JSON_It ///////////////////////////////////////////////////////////////////////////////
|
||||
Dqn_JSONIt Dqn_JSON_LoadFileToIt(Dqn_Arena *arena, Dqn_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,
|
||||
json.size,
|
||||
json_parse_flags_allow_location_information,
|
||||
Dqn_JSON_ArenaAllocFunc,
|
||||
arena,
|
||||
&parse_result);
|
||||
|
||||
Dqn_JSONIt result = {};
|
||||
Dqn_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)
|
||||
{
|
||||
if (!it || !element)
|
||||
return false;
|
||||
DQN_ASSERT(it->stack_count < DQN_ARRAY_ICOUNT(it->stack));
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_IteratorEntryTypeObjElement, element};
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeObjElement, element};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_IteratorPushObj(Dqn_JSONIterator *it, json_object_s *obj)
|
||||
bool Dqn_JSON_ItPushObj(Dqn_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_IteratorEntryTypeObj, obj};
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeObj, obj};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_IteratorPushArrayElement(Dqn_JSONIterator *it, json_array_element_s *element)
|
||||
bool Dqn_JSON_ItPushArrayElement(Dqn_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_IteratorEntryTypeArrayElement, element};
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeArrayElement, element};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_IteratorPushArray(Dqn_JSONIterator *it, json_value_s *value)
|
||||
bool Dqn_JSON_ItPushArray(Dqn_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_IteratorEntryTypeArray, value};
|
||||
it->stack[it->stack_count++] = {Dqn_JSON_ItEntryTypeArray, value};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_IteratorPushValue(Dqn_JSONIterator *it, json_value_s *value)
|
||||
bool Dqn_JSON_ItPushValue(Dqn_JSONIt *it, json_value_s *value)
|
||||
{
|
||||
bool result = false;
|
||||
if (!it || !value)
|
||||
return result;
|
||||
|
||||
if (value->type == json_type_object) {
|
||||
result = Dqn_JSON_IteratorPushObj(it, json_value_as_object(value));
|
||||
result = Dqn_JSON_ItPushObj(it, json_value_as_object(value));
|
||||
} else if (value->type == json_type_array) {
|
||||
result = Dqn_JSON_IteratorPushArray(it, value);
|
||||
result = Dqn_JSON_ItPushArray(it, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Dqn_JSON_IteratorPop(Dqn_JSONIterator *it)
|
||||
void Dqn_JSON_ItPop(Dqn_JSONIt *it)
|
||||
{
|
||||
if (!it)
|
||||
return;
|
||||
@ -199,19 +205,18 @@ void Dqn_JSON_IteratorPop(Dqn_JSONIterator *it)
|
||||
it->stack_count--;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_Iterator json tree navigation
|
||||
// -----------------------------------------------------------------------------
|
||||
json_value_s *Dqn_JSON_IteratorPushCurrValue(Dqn_JSONIterator *it)
|
||||
// NOTE: Dqn_JSON_It JSON tree navigation //////////////////////////////////////////////////////////
|
||||
json_value_s *Dqn_JSON_ItPushCurrValue(Dqn_JSONIt *it)
|
||||
{
|
||||
json_value_s *result = nullptr;
|
||||
Dqn_JSONIteratorEntry *curr = Dqn_JSON_IteratorCurr(it);
|
||||
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it);
|
||||
if (!curr)
|
||||
return result;
|
||||
|
||||
if (curr->type == Dqn_JSON_IteratorEntryTypeObjElement) {
|
||||
if (curr->type == Dqn_JSON_ItEntryTypeObjElement) {
|
||||
json_object_element_s *element = DQN_CAST(json_object_element_s *) curr->value;
|
||||
result = element->value;
|
||||
} else if (curr->type == Dqn_JSON_IteratorEntryTypeArrayElement) {
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) {
|
||||
json_array_element_s *element = DQN_CAST(json_array_element_s *) curr->value;
|
||||
result = element->value;
|
||||
} else {
|
||||
@ -221,57 +226,56 @@ json_value_s *Dqn_JSON_IteratorPushCurrValue(Dqn_JSONIterator *it)
|
||||
if (result->type == json_type_array) {
|
||||
json_array_s *array = json_value_as_array(result);
|
||||
DQN_ASSERT(array);
|
||||
Dqn_JSON_IteratorPushArray(it, result);
|
||||
Dqn_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_IteratorPushObj(it, obj);
|
||||
Dqn_JSON_ItPushObj(it, obj);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_IteratorNext(Dqn_JSONIterator *it)
|
||||
bool Dqn_JSON_ItNext(Dqn_JSONIt *it)
|
||||
{
|
||||
Dqn_JSONIteratorEntry *curr = Dqn_JSON_IteratorCurr(it);
|
||||
Dqn_JSONItEntry *curr = Dqn_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_IteratorEntryTypeObj) {
|
||||
if (curr->type == Dqn_JSON_ItEntryTypeObj) {
|
||||
auto *obj = DQN_CAST(json_object_s *) curr->value;
|
||||
obj_element = obj->start;
|
||||
} else if (curr->type == Dqn_JSON_IteratorEntryTypeObjElement) {
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeObjElement) {
|
||||
auto *element = DQN_CAST(json_object_element_s *) curr->value;
|
||||
obj_element = element->next;
|
||||
Dqn_JSON_IteratorPop(it);
|
||||
} else if (curr->type == Dqn_JSON_IteratorEntryTypeArray) {
|
||||
Dqn_JSON_ItPop(it);
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeArray) {
|
||||
auto *value = DQN_CAST(json_value_s *) curr->value;
|
||||
auto *array = json_value_as_array(value);
|
||||
array_element = array->start;
|
||||
} else if (curr->type == Dqn_JSON_IteratorEntryTypeArrayElement) {
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) {
|
||||
auto *element = DQN_CAST(json_array_element_s *) curr->value;
|
||||
array_element = element->next;
|
||||
Dqn_JSON_IteratorPop(it);
|
||||
Dqn_JSON_ItPop(it);
|
||||
} else {
|
||||
Dqn_JSON_IteratorPop(it);
|
||||
Dqn_JSON_ItPop(it);
|
||||
}
|
||||
|
||||
if (obj_element)
|
||||
Dqn_JSON_IteratorPushObjElement(it, obj_element);
|
||||
Dqn_JSON_ItPushObjElement(it, obj_element);
|
||||
else if (array_element)
|
||||
Dqn_JSON_IteratorPushArrayElement(it, array_element);
|
||||
Dqn_JSON_ItPushArrayElement(it, array_element);
|
||||
|
||||
bool result = obj_element || array_element;
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_IteratorCurr
|
||||
// -----------------------------------------------------------------------------
|
||||
Dqn_JSONIteratorEntry *Dqn_JSON_IteratorCurr(Dqn_JSONIterator *it)
|
||||
// NOTE: Dqn_JSON_ItCurr ///////////////////////////////////////////////////////////////////////////
|
||||
Dqn_JSONItEntry *Dqn_JSON_ItCurr(Dqn_JSONIt *it)
|
||||
{
|
||||
Dqn_JSONIteratorEntry *result = nullptr;
|
||||
Dqn_JSONItEntry *result = nullptr;
|
||||
if (!it || it->stack_count <= 0)
|
||||
return result;
|
||||
|
||||
@ -279,23 +283,23 @@ Dqn_JSONIteratorEntry *Dqn_JSON_IteratorCurr(Dqn_JSONIterator *it)
|
||||
return result;
|
||||
}
|
||||
|
||||
json_value_s *Dqn_JSON_IteratorCurrValue(Dqn_JSONIterator *it)
|
||||
json_value_s *Dqn_JSON_ItCurrValue(Dqn_JSONIt *it)
|
||||
{
|
||||
json_value_s *result = nullptr;
|
||||
Dqn_JSONIteratorEntry *curr = Dqn_JSON_IteratorCurr(it);
|
||||
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it);
|
||||
if (!curr)
|
||||
return result;
|
||||
|
||||
if (curr->type == Dqn_JSON_IteratorEntryTypeObjElement) {
|
||||
if (curr->type == Dqn_JSON_ItEntryTypeObjElement) {
|
||||
auto *element = DQN_CAST(json_object_element_s *)curr->value;
|
||||
result = element->value;
|
||||
} else if (curr->type == Dqn_JSON_IteratorEntryTypeArrayElement) {
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeArrayElement) {
|
||||
auto *element = DQN_CAST(json_array_element_s *)curr->value;
|
||||
result = element->value;
|
||||
} else if (curr->type == Dqn_JSON_IteratorEntryTypeString ||
|
||||
curr->type == Dqn_JSON_IteratorEntryTypeNumber ||
|
||||
curr->type == Dqn_JSON_IteratorEntryTypeObj ||
|
||||
curr->type == Dqn_JSON_IteratorEntryTypeArray)
|
||||
} else if (curr->type == Dqn_JSON_ItEntryTypeString ||
|
||||
curr->type == Dqn_JSON_ItEntryTypeNumber ||
|
||||
curr->type == Dqn_JSON_ItEntryTypeObj ||
|
||||
curr->type == Dqn_JSON_ItEntryTypeArray)
|
||||
{
|
||||
result = DQN_CAST(json_value_s *)curr->value;
|
||||
}
|
||||
@ -303,74 +307,79 @@ json_value_s *Dqn_JSON_IteratorCurrValue(Dqn_JSONIterator *it)
|
||||
return result;
|
||||
}
|
||||
|
||||
json_object_element_s *Dqn_JSON_IteratorCurrObjElement(Dqn_JSONIterator *it)
|
||||
json_object_element_s *Dqn_JSON_ItCurrObjElement(Dqn_JSONIt *it)
|
||||
{
|
||||
Dqn_JSONIteratorEntry *curr = Dqn_JSON_IteratorCurr(it);
|
||||
auto *result = (curr && curr->type == Dqn_JSON_IteratorEntryTypeObjElement)
|
||||
Dqn_JSONItEntry *curr = Dqn_JSON_ItCurr(it);
|
||||
auto *result = (curr && curr->type == Dqn_JSON_ItEntryTypeObjElement)
|
||||
? DQN_CAST(json_object_element_s *) curr->value
|
||||
: nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_IteratorValueIs
|
||||
// -----------------------------------------------------------------------------
|
||||
json_value_s *Dqn_JSON_IteratorValueIs(Dqn_JSONIterator *it, json_type_e type)
|
||||
// NOTE: Dqn_JSON_ItValueIs ////////////////////////////////////////////////////////////////////////
|
||||
json_value_s *Dqn_JSON_ItValueIs(Dqn_JSONIt *it, json_type_e type)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_IteratorCurrValue(it);
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *result = (curr && type == curr->type) ? curr : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_object_s *Dqn_JSON_IteratorValueIsObj(Dqn_JSONIterator *it)
|
||||
json_object_s *Dqn_JSON_ItValueIsObj(Dqn_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_IteratorCurrValue(it);
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_object_s *result = curr ? json_value_as_object(curr) : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_array_s *Dqn_JSON_IteratorValueIsArray(Dqn_JSONIterator *it)
|
||||
json_array_s *Dqn_JSON_ItValueIsArray(Dqn_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_IteratorCurrValue(it);
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_array_s *result = curr ? json_value_as_array(curr) : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_string_s *Dqn_JSON_IteratorValueIsString(Dqn_JSONIterator *it)
|
||||
json_string_s *Dqn_JSON_ItValueIsString(Dqn_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_IteratorCurrValue(it);
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_string_s *result = curr ? json_value_as_string(curr) : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_number_s *Dqn_JSON_IteratorValueIsNumber(Dqn_JSONIterator *it)
|
||||
json_number_s *Dqn_JSON_ItValueIsNumber(Dqn_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_IteratorCurrValue(it);
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_number_s *result = curr ? json_value_as_number(curr) : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
json_value_s *Dqn_JSON_IteratorValueIsBool(Dqn_JSONIterator *it)
|
||||
json_value_s *Dqn_JSON_ItValueIsBool(Dqn_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_JSON_IteratorCurrValue(it);
|
||||
json_value_s *curr = Dqn_JSON_ItCurrValue(it);
|
||||
json_value_s *result = (curr && (curr->type == json_type_true || curr->type == json_type_false)) ? curr : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t Dqn_JSON_IteratorValueArraySize(Dqn_JSONIterator *it)
|
||||
json_value_s *Dqn_JSON_ItValueIsNull(Dqn_JSONIt *it)
|
||||
{
|
||||
json_value_s *curr = Dqn_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 result = 0;
|
||||
if (json_array_s *curr = Dqn_JSON_IteratorValueIsArray(it))
|
||||
if (json_array_s *curr = Dqn_JSON_ItValueIsArray(it))
|
||||
result = curr->length;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Dqn_JSON_IteratorKeyValueIs
|
||||
// -----------------------------------------------------------------------------
|
||||
Dqn_String8 Dqn_JSON_IteratorKey(Dqn_JSONIterator *it)
|
||||
// NOTE: Dqn_JSON_ItKeyValueIs /////////////////////////////////////////////////////////////////////
|
||||
Dqn_Str8 Dqn_JSON_ItKey(Dqn_JSONIt *it)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_IteratorCurrObjElement(it);
|
||||
Dqn_String8 result = {};
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
Dqn_Str8 result = {};
|
||||
if (curr) {
|
||||
result.data = DQN_CAST(char *)curr->name->string;
|
||||
result.size = curr->name->string_size;
|
||||
@ -378,98 +387,107 @@ Dqn_String8 Dqn_JSON_IteratorKey(Dqn_JSONIterator *it)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_IteratorKeyIs(Dqn_JSONIterator *it, Dqn_String8 key)
|
||||
bool Dqn_JSON_ItKeyIs(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_IteratorCurrObjElement(it);
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
bool result = Dqn_JSON_String8Cmp(curr->name, key);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_object_s *Dqn_JSON_IteratorKeyValueIsObj(Dqn_JSONIterator *it, Dqn_String8 key)
|
||||
json_object_s *Dqn_JSON_ItKeyValueIsObj(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
{
|
||||
json_object_s *result = nullptr;
|
||||
json_object_element_s *curr = Dqn_JSON_IteratorCurrObjElement(it);
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
result = json_value_as_object(curr->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_array_s *Dqn_JSON_IteratorKeyValueIsArray(Dqn_JSONIterator *it, Dqn_String8 key)
|
||||
json_array_s *Dqn_JSON_ItKeyValueIsArray(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
{
|
||||
json_array_s *result = nullptr;
|
||||
json_object_element_s *curr = Dqn_JSON_IteratorCurrObjElement(it);
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
result = json_value_as_array(curr->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_string_s *Dqn_JSON_IteratorKeyValueIsString(Dqn_JSONIterator *it, Dqn_String8 key)
|
||||
json_string_s *Dqn_JSON_ItKeyValueIsString(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_IteratorCurrObjElement(it);
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_string_s *result = nullptr;
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
result = json_value_as_string(curr->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_number_s *Dqn_JSON_IteratorKeyValueIsNumber(Dqn_JSONIterator *it, Dqn_String8 key)
|
||||
json_number_s *Dqn_JSON_ItKeyValueIsNumber(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_IteratorCurrObjElement(it);
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_number_s *result = nullptr;
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
result = json_value_as_number(curr->value);
|
||||
return result;
|
||||
}
|
||||
|
||||
json_value_s *Dqn_JSON_IteratorKeyValueIsBool(Dqn_JSONIterator *it, Dqn_String8 key)
|
||||
json_value_s *Dqn_JSON_ItKeyValueIsBool(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
{
|
||||
json_object_element_s *curr = Dqn_JSON_IteratorCurrObjElement(it);
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_value_s *result = nullptr;
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
result = curr->value->type == json_type_true || curr->value->type == json_type_false ? curr->value : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Dqn_JSON_IteratorValueTo
|
||||
// -----------------------------------------------------------------------------
|
||||
Dqn_String8 Dqn_JSON_IteratorValueToString(Dqn_JSONIterator *it)
|
||||
json_value_s *Dqn_JSON_ItKeyValueIsNull(Dqn_JSONIt *it, Dqn_Str8 key)
|
||||
{
|
||||
Dqn_String8 result = {};
|
||||
if (json_string_s *curr = Dqn_JSON_IteratorValueIsString(it))
|
||||
result = Dqn_String8_Init(curr->string, curr->string_size);
|
||||
json_object_element_s *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
json_value_s *result = nullptr;
|
||||
if (curr && Dqn_JSON_String8Cmp(curr->name, key))
|
||||
result = curr->value->type == json_type_null ? curr->value : nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t Dqn_JSON_IteratorValueToI64(Dqn_JSONIterator *it)
|
||||
|
||||
// NOTE: Dqn_JSON_ItValueTo ////////////////////////////////////////////////////////////////////////
|
||||
Dqn_Str8 Dqn_JSON_ItValueToString(Dqn_JSONIt *it)
|
||||
{
|
||||
Dqn_Str8 result = {};
|
||||
if (json_string_s *curr = Dqn_JSON_ItValueIsString(it))
|
||||
result = Dqn_Str8_Init(curr->string, curr->string_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t Dqn_JSON_ItValueToI64(Dqn_JSONIt *it)
|
||||
{
|
||||
int64_t result = {};
|
||||
if (json_number_s *curr = Dqn_JSON_IteratorValueIsNumber(it))
|
||||
result = Dqn_String8_ToI64(Dqn_String8_Init(curr->number, curr->number_size), 0 /*separator*/);
|
||||
if (json_number_s *curr = Dqn_JSON_ItValueIsNumber(it))
|
||||
result = Dqn_Str8_ToI64(Dqn_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t Dqn_JSON_IteratorValueToU64(Dqn_JSONIterator *it)
|
||||
uint64_t Dqn_JSON_ItValueToU64(Dqn_JSONIt *it)
|
||||
{
|
||||
uint64_t result = {};
|
||||
if (json_number_s *curr = Dqn_JSON_IteratorValueIsNumber(it))
|
||||
result = Dqn_String8_ToU64(Dqn_String8_Init(curr->number, curr->number_size), 0 /*separator*/);
|
||||
if (json_number_s *curr = Dqn_JSON_ItValueIsNumber(it))
|
||||
result = Dqn_Str8_ToU64(Dqn_Str8_Init(curr->number, curr->number_size), 0 /*separator*/).value;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Dqn_JSON_IteratorValueToBool(Dqn_JSONIterator *it)
|
||||
bool Dqn_JSON_ItValueToBool(Dqn_JSONIt *it)
|
||||
{
|
||||
bool result = {};
|
||||
if (json_value_s *curr = Dqn_JSON_IteratorValueIsBool(it))
|
||||
if (json_value_s *curr = Dqn_JSON_ItValueIsBool(it))
|
||||
result = curr->type == json_type_true;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Dqn_JSON_IteratorErrorUnknownKeyValue_(Dqn_JSONIterator *it, Dqn_CallSite call_site)
|
||||
void Dqn_JSON_ItErrorUnknownKeyValue_(Dqn_JSONIt *it, Dqn_CallSite call_site)
|
||||
{
|
||||
if (!it)
|
||||
return;
|
||||
|
||||
json_object_element_s const *curr = Dqn_JSON_IteratorCurrObjElement(it);
|
||||
json_object_element_s const *curr = Dqn_JSON_ItCurrObjElement(it);
|
||||
if (!curr)
|
||||
return;
|
||||
|
||||
@ -484,19 +502,18 @@ void Dqn_JSON_IteratorErrorUnknownKeyValue_(Dqn_JSONIterator *it, Dqn_CallSite c
|
||||
"Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]",
|
||||
info->line_no,
|
||||
info->row_no,
|
||||
key->string_size,
|
||||
DQN_CAST(int)key->string_size,
|
||||
key->string,
|
||||
value_type_size,
|
||||
DQN_CAST(int)value_type_size,
|
||||
value_type);
|
||||
} else {
|
||||
Dqn_Log_TypeFCallSite(Dqn_LogType_Warning,
|
||||
call_site,
|
||||
"Unknown key-value pair in object [key=%.*s, value=%.*s]",
|
||||
key->string_size,
|
||||
DQN_CAST(int)key->string_size,
|
||||
key->string,
|
||||
value_type_size,
|
||||
DQN_CAST(int)value_type_size,
|
||||
value_type);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(DQN_JSON_IMPLEMENTATION)
|
||||
|
@ -1,100 +0,0 @@
|
||||
#if defined(DQN_KECCAK_H)
|
||||
// -----------------------------------------------------------------------------
|
||||
// Dqn_Keccak Reference Implementation
|
||||
// -----------------------------------------------------------------------------
|
||||
// A very compact Keccak implementation taken from the reference implementation
|
||||
// repository
|
||||
//
|
||||
// https://github.com/XKCP/XKCP/blob/master/Standalone/CompactFIPS202/C/Keccak-more-compact.c
|
||||
//
|
||||
|
||||
#define FOR(i,n) for(i=0; i<n; ++i)
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned long long int u64;
|
||||
typedef unsigned int ui;
|
||||
|
||||
void Keccak(ui r, ui c, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen);
|
||||
void FIPS202_SHAKE128(const u8 *in, u64 inLen, u8 *out, u64 outLen) { Keccak(1344, 256, in, inLen, 0x1F, out, outLen); }
|
||||
void FIPS202_SHAKE256(const u8 *in, u64 inLen, u8 *out, u64 outLen) { Keccak(1088, 512, in, inLen, 0x1F, out, outLen); }
|
||||
void FIPS202_SHA3_224(const u8 *in, u64 inLen, u8 *out) { Keccak(1152, 448, in, inLen, 0x06, out, 28); }
|
||||
void FIPS202_SHA3_256(const u8 *in, u64 inLen, u8 *out) { Keccak(1088, 512, in, inLen, 0x06, out, 32); }
|
||||
void FIPS202_SHA3_384(const u8 *in, u64 inLen, u8 *out) { Keccak(832, 768, in, inLen, 0x06, out, 48); }
|
||||
void FIPS202_SHA3_512(const u8 *in, u64 inLen, u8 *out) { Keccak(576, 1024, in, inLen, 0x06, out, 64); }
|
||||
|
||||
int LFSR86540(u8 *R) { (*R)=((*R)<<1)^(((*R)&0x80)?0x71:0); return ((*R)&2)>>1; }
|
||||
#define ROL(a,o) ((((u64)a)<<o)^(((u64)a)>>(64-o)))
|
||||
static u64 load64(const u8 *x) { ui i; u64 u=0; FOR(i,8) { u<<=8; u|=x[7-i]; } return u; }
|
||||
static void store64(u8 *x, u64 u) { ui i; FOR(i,8) { x[i]=u; u>>=8; } }
|
||||
static void xor64(u8 *x, u64 u) { ui i; FOR(i,8) { x[i]^=u; u>>=8; } }
|
||||
#define rL(x,y) load64((u8*)s+8*(x+5*y))
|
||||
#define wL(x,y,l) store64((u8*)s+8*(x+5*y),l)
|
||||
#define XL(x,y,l) xor64((u8*)s+8*(x+5*y),l)
|
||||
void KeccakF1600(void *s)
|
||||
{
|
||||
ui r,x,y,i,j,Y; u8 R=0x01; u64 C[5],D;
|
||||
for(i=0; i<24; i++) {
|
||||
/*θ*/ FOR(x,5) C[x]=rL(x,0)^rL(x,1)^rL(x,2)^rL(x,3)^rL(x,4); FOR(x,5) { D=C[(x+4)%5]^ROL(C[(x+1)%5],1); FOR(y,5) XL(x,y,D); }
|
||||
/*ρπ*/ x=1; y=r=0; D=rL(x,y); FOR(j,24) { r+=j+1; Y=(2*x+3*y)%5; x=y; y=Y; C[0]=rL(x,y); wL(x,y,ROL(D,r%64)); D=C[0]; }
|
||||
/*χ*/ FOR(y,5) { FOR(x,5) C[x]=rL(x,y); FOR(x,5) wL(x,y,C[x]^((~C[(x+1)%5])&C[(x+2)%5])); }
|
||||
/*ι*/ FOR(j,7) if (LFSR86540(&R)) XL(0,0,(u64)1<<((1<<j)-1));
|
||||
}
|
||||
}
|
||||
void Keccak(ui r, ui c, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen)
|
||||
{
|
||||
/*initialize*/ u8 s[200]; ui R=r/8; ui i,b=0; FOR(i,200) s[i]=0;
|
||||
/*absorb*/ while(inLen>0) { b=(inLen<R)?inLen:R; FOR(i,b) s[i]^=in[i]; in+=b; inLen-=b; if (b==R) { KeccakF1600(s); b=0; } }
|
||||
/*pad*/ s[b]^=sfx; if((sfx&0x80)&&(b==(R-1))) KeccakF1600(s); s[R-1]^=0x80; KeccakF1600(s);
|
||||
/*squeeze*/ while(outLen>0) { b=(outLen<R)?outLen:R; FOR(i,b) out[i]=s[i]; out+=b; outLen-=b; if(outLen>0) KeccakF1600(s); }
|
||||
}
|
||||
|
||||
|
||||
// PCG32 Random Number Generator
|
||||
// -----------------------------------------------------------------------------
|
||||
// NOTE: https://github.com/imneme/pcg-c-basic
|
||||
|
||||
struct pcg_state_setseq_64
|
||||
{ // Internals are *Private*.
|
||||
uint64_t state; // RNG state. All values are possible.
|
||||
uint64_t inc; // Controls which RNG sequence (stream) is
|
||||
// selected. Must *always* be odd.
|
||||
};
|
||||
typedef struct pcg_state_setseq_64 pcg32_random_t;
|
||||
|
||||
// pcg32_random_r(rng)
|
||||
// Generate a uniformly distributed 32-bit random number
|
||||
|
||||
uint32_t pcg32_random_r(pcg32_random_t* rng)
|
||||
{
|
||||
uint64_t oldstate = rng->state;
|
||||
rng->state = oldstate * 6364136223846793005ULL + rng->inc;
|
||||
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
|
||||
uint32_t rot = oldstate >> 59u;
|
||||
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
|
||||
}
|
||||
|
||||
// pcg32_srandom_r(rng, initstate, initseq):
|
||||
// Seed the rng. Specified in two parts, state initializer and a
|
||||
// sequence selection constant (a.k.a. stream id)
|
||||
|
||||
void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq)
|
||||
{
|
||||
rng->state = 0U;
|
||||
rng->inc = (initseq << 1u) | 1u;
|
||||
pcg32_random_r(rng);
|
||||
rng->state += initstate;
|
||||
pcg32_random_r(rng);
|
||||
}
|
||||
|
||||
// pcg32_boundedrand_r(rng, bound):
|
||||
// Generate a uniformly distributed number, r, where 0 <= r < bound
|
||||
|
||||
uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound)
|
||||
{
|
||||
uint32_t threshold = -bound % bound;
|
||||
for (;;) {
|
||||
uint32_t r = pcg32_random_r(rng);
|
||||
if (r >= threshold)
|
||||
return r % bound;
|
||||
}
|
||||
}
|
||||
#endif // DQN_KECCAK_H
|
@ -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_TEST_WITH_MAIN -I %script_dir% %script_dir%\Misc\dqn_unit_tests.cpp
|
||||
set common_flags=-D DQN_TEST_WITH_MAIN -D DQN_IMPLEMENTATION -D DQN_USE_STD_PRINTF /Tp %script_dir%\dqn.h
|
||||
|
||||
set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo
|
||||
|
||||
|
389
dqn.h
389
dqn.h
@ -1,11 +1,28 @@
|
||||
// dqn.h "Personal standard library" | MIT licensed | git.doylet.dev/dqn
|
||||
#if !defined(DQN_H)
|
||||
#define DQN_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// $$$$$$$\ $$$$$$\ $$\ $$\
|
||||
// $$ __$$\ $$ __$$\ $$$\ $$ |
|
||||
// $$ | $$ |$$ / $$ |$$$$\ $$ |
|
||||
// $$ | $$ |$$ | $$ |$$ $$\$$ |
|
||||
// $$ | $$ |$$ | $$ |$$ \$$$$ |
|
||||
// $$ | $$ |$$ $$\$$ |$$ |\$$$ |
|
||||
// $$$$$$$ |\$$$$$$ / $$ | \$$ |
|
||||
// \_______/ \___$$$\ \__| \__|
|
||||
// \___|
|
||||
//
|
||||
// dqn.h -- Personal standard library -- MIT License -- git.doylet.dev/dqn
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This library is a single-header file-esque library with inspiration taken
|
||||
// from STB libraries for ease of integration and use. It defines a bunch of
|
||||
// primitives and standard library functions that are missing and or more
|
||||
// appropriate for development in modern day computing (e.g. cache friendly
|
||||
// memory management, 64bit MMU, non-pessimized APIs that aren't constrained by
|
||||
// the language specification and operate closer to the OS).
|
||||
// appropriate for development in modern day computing (e.g. allocator
|
||||
// first-class APIs, a 64bit MMU and in general non-pessimized APIs that aren't
|
||||
// constrained by the language specification and operate closer to the OS).
|
||||
//
|
||||
// Define DQN_IMPLEMENTATION macro in one and only one translation unit to
|
||||
// enable the implementation of this library, for example:
|
||||
@ -15,7 +32,7 @@
|
||||
//
|
||||
// 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
|
||||
// documented in the section table of contents at the #define column, for
|
||||
// example:
|
||||
//
|
||||
// #define DQN_ONLY_VARRAY
|
||||
@ -33,18 +50,128 @@
|
||||
// Below is a table of contents that describes what you can find in each header
|
||||
// of this library and additional macros that can be defined to customise the
|
||||
// behaviour of this library.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// $$$$$$\ $$$$$$$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$\
|
||||
// $$ __$$\ $$ __$$\\__$$ __|\_$$ _|$$ __$$\ $$$\ $$ |$$ __$$\
|
||||
// $$ / $$ |$$ | $$ | $$ | $$ | $$ / $$ |$$$$\ $$ |$$ / \__|
|
||||
// $$ | $$ |$$$$$$$ | $$ | $$ | $$ | $$ |$$ $$\$$ |\$$$$$$\
|
||||
// $$ | $$ |$$ ____/ $$ | $$ | $$ | $$ |$$ \$$$$ | \____$$\
|
||||
// $$ | $$ |$$ | $$ | $$ | $$ | $$ |$$ |\$$$ |$$\ $$ |
|
||||
// $$$$$$ |$$ | $$ | $$$$$$\ $$$$$$ |$$ | \$$ |\$$$$$$ |
|
||||
// \______/ \__| \__| \______| \______/ \__| \__| \______/
|
||||
//
|
||||
// Options -- Compile time build customisation
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// - 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)
|
||||
//
|
||||
// - Redefine 'DQN_API' to change the prefix of all declared functions in the library
|
||||
//
|
||||
// #define DQN_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
|
||||
// 'static'.
|
||||
//
|
||||
// #define DQN_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
|
||||
//
|
||||
// - Augment DQN_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 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_Library_DumpLeaks()
|
||||
//
|
||||
// #define DQN_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
|
||||
//
|
||||
// However, if you are compiling with ASAN on MSVC, MSVC's implementation of
|
||||
// __declspec(no_sanitize_address) is unable to suppress warnings in some
|
||||
// individual functions in stb's implementation causing ASAN to trigger. This
|
||||
// library will error on compilation if it detects this is the case and is
|
||||
// being compiled with STB sprintf.
|
||||
//
|
||||
// - Define this to stop this library from defining a minimal subset of Win32
|
||||
// prototypes and definitions in this file. You should use this macro if you
|
||||
// intend to #include <Windows.h> yourself to avoid symbol conflicts with
|
||||
// the redefined declarations in this library.
|
||||
//
|
||||
// #define DQN_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
|
||||
//
|
||||
// - 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 this macro to 1 to enable poisoning of memory from arenas when ASAN
|
||||
// `-fsanitize=address` is enabled. Enabling this will detect memory overwrite
|
||||
// by padding allocated before and after with poisoned memory which will raise
|
||||
// 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 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`.
|
||||
//
|
||||
// #define DQN_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
|
||||
//
|
||||
|
||||
#if !defined(DQN_H)
|
||||
#if defined(DQN_ONLY_VARRAY) || \
|
||||
defined(DQN_ONLY_SARRAY) || \
|
||||
defined(DQN_ONLY_FARRAY) || \
|
||||
defined(DQN_ONLY_SLICE) || \
|
||||
defined(DQN_ONLY_DSMAP) || \
|
||||
defined(DQN_ONLY_LIST) || \
|
||||
defined(DQN_ONLY_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) || \
|
||||
@ -63,9 +190,6 @@
|
||||
#if !defined(DQN_ONLY_SARRAY)
|
||||
#define DQN_NO_SARRAY
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_SLICE)
|
||||
#define DQN_NO_SLICE
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_DSMAP)
|
||||
#define DQN_NO_DSMAP
|
||||
#endif
|
||||
@ -84,6 +208,12 @@
|
||||
#if !defined(DQN_ONLY_WIN)
|
||||
#define DQN_NO_WIN
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_SEMAPHORE)
|
||||
#define DQN_NO_SEMAPHORE
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_THREAD)
|
||||
#define DQN_NO_THREAD
|
||||
#endif
|
||||
#if !defined(DQN_ONLY_V2)
|
||||
#define DQN_NO_V2
|
||||
#endif
|
||||
@ -110,222 +240,65 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// NOTE: Table of Contents =========================================================================
|
||||
// Index | #define Label | Description
|
||||
// NOTE: C Headers =================================================================================
|
||||
#include <stdarg.h> // | | va_list
|
||||
#include <stdio.h> // | | fprintf, FILE, stdout, stderr
|
||||
#include <stdint.h> // | | [u]int_*, ...
|
||||
#include <limits.h> // | | [U]INT_MAX, ...
|
||||
|
||||
// NOTE: Dqn_Base ==================================================================================
|
||||
// [$CMAC] Compiler macros | | Macros for the compiler
|
||||
// [$MACR] Macros | | Define macros used in the library
|
||||
// [$TYPE] Types | | Basic types and typedefs
|
||||
// [$INTR] Intrinsics | | Atomics, cpuid, ticket mutex
|
||||
// [$CALL] Dqn_CallSite | | Source code location/tracing
|
||||
// [$TMUT] Dqn_TicketMutex | | Userland mutex via spinlocking atomics
|
||||
// [$ALLO] Dqn_Allocator | | Generic allocator interface
|
||||
// [$PRIN] Dqn_Print | | Console printing
|
||||
// [$LLOG] Dqn_Log | | Console logging macros
|
||||
|
||||
// NOTE: Additional Configuration
|
||||
// - Override the default heap-allocation routine that is called when the
|
||||
// default Dqn_Allocator is used by #define-ing. By default we use the OS's
|
||||
// virtual memory allocators (e.g. VirtualAlloc on Windows and mmap on Linux).
|
||||
//
|
||||
// DQN_ALLOC(size)
|
||||
// DQN_DEALLOC(ptr, size)
|
||||
//
|
||||
// - Override the byte-manipulation routines by #define-ing. By default we use
|
||||
// <strings.h>
|
||||
//
|
||||
// DQN_MEMCPY(dest, src, count)
|
||||
// DQN_MEMSET(dest, value, count)
|
||||
// DQN_MEMCMP(lhs, rhs, count)
|
||||
// DQN_MEMMOVE(dest, src, count)
|
||||
//
|
||||
// - Override these math functions. By default we use <math.h>
|
||||
//
|
||||
// DQN_SQRTF(val)
|
||||
// DQN_SINF(val)
|
||||
// DQN_COSF(val)
|
||||
// DQN_TANF(val)
|
||||
//
|
||||
// - Change the prefix to all declared functions in the library by #define-ing.
|
||||
//
|
||||
// DQN_API
|
||||
//
|
||||
// - Apply static to all function definitions and disable external linkage to
|
||||
// other translation units by #define-ing. This macro is only used if DQN_API
|
||||
// is not overriden.
|
||||
//
|
||||
// DQN_STATIC_API
|
||||
//
|
||||
// - Turn all assertion macros to no-ops except for hard asserts (which are
|
||||
// always enabled and represent unrecoverable errors in the library).
|
||||
//
|
||||
// DQN_NO_ASSERT
|
||||
//
|
||||
// - Augment DQN_CHECK(expr) macro's behaviour. By default it will trigger a
|
||||
// debugger break when when the expression evalutes false otherwise by
|
||||
// #define-ing this macro it will evaluate to false and DQN_CHECK is usually
|
||||
// used in a if branch to recover gracefully from the failed condition.
|
||||
//
|
||||
// DQN_NO_CHECK_BREAK
|
||||
|
||||
#include "dqn_base.h"
|
||||
|
||||
// NOTE: Dqn_External ==============================================================================
|
||||
// [$OS_H] OS Headers | | Headers from the operating system
|
||||
// [$STBS] stb_sprintf | | Portable sprintf
|
||||
#include "dqn_external.h"
|
||||
#if defined(DQN_PLATFORM_WIN32)
|
||||
#include "dqn_win32.h"
|
||||
|
||||
// NOTE: Additional Configuration
|
||||
// - Define this to stop this library from defining a minimal subset of Win32
|
||||
// prototypes and definitions in this file. You should use this macro if you
|
||||
// intend to #include <Windows.h> yourself to avoid symbol conflicts with
|
||||
// the redefined declarations in this library.
|
||||
//
|
||||
// DQN_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"
|
||||
//
|
||||
// DQN_STB_SPRINTF_HEADER_ONLY
|
||||
|
||||
// NOTE: Dqn_Memory ================================================================================
|
||||
// [$VMEM] Dqn_VMem | | Virtual memory allocation
|
||||
// [$MEMB] Dqn_MemBlock | | Virtual memory blocks
|
||||
// [$AREN] Dqn_Arena | | Growing bump allocator
|
||||
// [$ACAT] Dqn_ArenaCatalog | | Collate, create & manage arenas in a catalog
|
||||
#include "dqn_memory.h"
|
||||
|
||||
// NOTE: Dqn_Debug =================================================================================
|
||||
// [$DEBM] Debug Macros | |
|
||||
// [$ASAN] Dqn_Asan | | Helpers to manually poison memory using ASAN
|
||||
// [$STKT] Dqn_StackTrace | | Create stack traces
|
||||
// [$DEBG] Dqn_Debug | | Debugging tools/helpers
|
||||
#endif
|
||||
#include "dqn_allocator.h"
|
||||
#include "dqn_thread_context.h"
|
||||
#include "dqn_debug.h"
|
||||
|
||||
// NOTE: Dqn_Strings ===============================================================================
|
||||
// [$CSTR] Dqn_CStr8 | | C-string helpers
|
||||
// [$STR8] Dqn_Str8 | | Pointer and length strings
|
||||
// [$FSTR] Dqn_FStr8 | DQN_FSTr8 | Fixed-size strings
|
||||
// [$STRB] Dqn_Str8Builder | |
|
||||
// [$CHAR] Dqn_Char | | Character ascii/digit.. helpers
|
||||
// [$UTFX] Dqn_UTF | | Unicode helpers
|
||||
#include "dqn_strings.h"
|
||||
|
||||
// NOTE: Dqn_Containers ============================================================================
|
||||
// [$CARR] Dqn_CArray | | Basic operations on C arrays for VArray/SArray/FArray to reuse
|
||||
// [$VARR] Dqn_VArray | DQN_VARRAY | Array backed by virtual memory arena
|
||||
// [$SARR] Dqn_SArray | DQN_SARRAY | Array that are allocated but cannot resize
|
||||
// [$FARR] Dqn_FArray | DQN_FARRAY | Fixed-size arrays
|
||||
// [$SLIC] Dqn_Slice | DQN_SLICE | Pointe and length container of data
|
||||
// [$DMAP] Dqn_DSMap | DQN_DSMAP | Hashtable, 70% max load, PoT size, linear probe, chain repair
|
||||
// [$LIST] Dqn_List | DQN_LIST | Chunked linked lists, append only
|
||||
#include "dqn_string.h"
|
||||
#include "dqn_containers.h"
|
||||
|
||||
// NOTE: Additional Configuration
|
||||
// - Override the default break into the active debugger function. By default
|
||||
// we use __debugbreak() on Windows and raise(SIGTRAP) on other platforms.
|
||||
//
|
||||
// DQN_DEBUG_BREAK
|
||||
//
|
||||
// - Change the byte that DQN_MEMSET will clear memory with. By default this
|
||||
// is set to 0. Some of the API's in this library accept a Dqn_ZeroMem enum
|
||||
// which scrubs memory with this #define-d value.
|
||||
//
|
||||
// DQN_MEMSET_BYTE
|
||||
//
|
||||
// - Define this macro to enable emory leak tracking when requesting memory
|
||||
// from the OS via this library. For example calls to Dqn_VMem_Reserve or
|
||||
// DQN_ALLOC are recorded to the leak table.
|
||||
//
|
||||
// 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_Library_DumpLeaks()
|
||||
//
|
||||
// You may mark sections of your program as allowed to leak memory by setting
|
||||
// the arena's or Dqn_Library's runtime struct `allocs_are_allowed_to_leak`
|
||||
// flag.
|
||||
//
|
||||
// DQN_LEAK_TRACING
|
||||
//
|
||||
// - Define this macro to 1 to enable poisoning of memory from arenas when ASAN
|
||||
// `-fsanitize=address` is enabled. Enabling this will detect memory overwrite
|
||||
// by padding allocated before and after with poisoned memory which will raise
|
||||
// a use-after-poison in ASAN on read/write. This is a no-op if the library is
|
||||
// not compiled with ASAN.
|
||||
//
|
||||
// DQN_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`.
|
||||
//
|
||||
// DQN_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.
|
||||
//
|
||||
// DQN_ASAN_POISON_GUARD_SIZE 128
|
||||
|
||||
// NOTE: Dqn_Platform ==============================================================================
|
||||
// [$FSYS] Dqn_Fs | DQN_FS | Filesystem helpers
|
||||
// [$DATE] Dqn_Date | | Date-time helpers
|
||||
// [$WIND] Dqn_Win | | Windows OS helpers
|
||||
// [$WINN] Dqn_WinNet | DQN_WINNET | Windows internet download/query helpers
|
||||
// [$OSYS] Dqn_OS | DQN_WIN | Operating-system APIs
|
||||
// [$TCTX] Dqn_ThreadContext | | Per-thread data structure e.g. temp arenas
|
||||
#include "dqn_platform.h"
|
||||
|
||||
// NOTE: Dqn_OS ====================================================================================
|
||||
// [$EXEC] Dqn_OSExec | | Execute programs programatically
|
||||
#if defined(DQN_PLATFORM_EMSCRIPTEN) || defined(DQN_PLATFORM_POSIX) || defined(DQN_PLATFORM_ARM64)
|
||||
#elif defined(DQN_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
|
||||
#endif
|
||||
#include "dqn_os.h"
|
||||
|
||||
// NOTE: Dqn_Math ==================================================================================
|
||||
// [$VEC2] Dqn_V2, V2i | DQN_V2 |
|
||||
// [$VEC3] Dqn_V3, V3i | DQN_V3 |
|
||||
// [$VEC4] Dqn_V4, V4i | DQN_V4 |
|
||||
// [$MAT4] Dqn_M4 | DQN_M4 |
|
||||
// [$RECT] Dqn_Rect | DQN_RECT |
|
||||
// [$MATH] Other | |
|
||||
#include "dqn_math.h"
|
||||
|
||||
// NOTE: Dqn_Hash ==================================================================================
|
||||
// [$FNV1] Dqn_FNV1A | | Hash(x) -> 32/64bit via FNV1a
|
||||
// [$MMUR] Dqn_MurmurHash3 | | Hash(x) -> 32/128bit via MurmurHash3
|
||||
#include "dqn_hash.h"
|
||||
|
||||
// NOTE: Dqn_Helpers ===============================================================================
|
||||
// [$PCG3] Dqn_PCG32 | | RNG from the PCG family
|
||||
// [$JSON] Dqn_JSONBuilder | DQN_JSON_BUILDER | Construct json output
|
||||
// [$BHEX] Dqn_Bin | DQN_BIN | Binary <-> hex helpers
|
||||
// [$BSEA] Dqn_BinarySearch | | Binary search
|
||||
// [$BITS] Dqn_Bit | | Bitset manipulation
|
||||
// [$SAFE] Dqn_Safe | | Safe arithmetic, casts, asserts
|
||||
// [$MISC] Misc | | Uncategorised helper functions
|
||||
// [$DLIB] Dqn_Library | | Globally shared runtime data for this library
|
||||
// [$PROF] Dqn_Profiler | DQN_PROFILER | Profiler that measures using a timestamp counter
|
||||
#include "dqn_helpers.h"
|
||||
#include "dqn_type_info.h"
|
||||
#endif // DQN_H
|
||||
|
||||
#if defined(DQN_IMPLEMENTATION)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// /$$$$$$\ $$\ $$\ $$$$$$$\ $$\
|
||||
// \_$$ _|$$$\ $$$ |$$ __$$\ $$ |
|
||||
// $$ | $$$$\ $$$$ |$$ | $$ |$$ |
|
||||
// $$ | $$\$$\$$ $$ |$$$$$$$ |$$ |
|
||||
// $$ | $$ \$$$ $$ |$$ ____/ $$ |
|
||||
// $$ | $$ |\$ /$$ |$$ | $$ |
|
||||
// $$$$$$\ $$ | \_/ $$ |$$ | $$$$$$$$\
|
||||
// \______|\__| \__|\__| \________|
|
||||
//
|
||||
// Implementation
|
||||