Update naming convention of library

This commit is contained in:
doyle 2021-09-24 22:29:34 +10:00
parent 37ae9b0e40
commit f6ae4ad2a0
5 changed files with 1574 additions and 1595 deletions

2032
dqn.h

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,5 @@
#if !defined(DQN_CPP_FILE_H) #if !defined(DQN_CPP_FILE_H)
#define DQN_CPP_FILE_H #define DQN_CPP_FILE_H
// -----------------------------------------------------------------------------
// NOTE: Overview
// -----------------------------------------------------------------------------
// Utility functions for creating C++ files at run-time.
//
// -----------------------------------------------------------------------------
// NOTE: Macros
// -----------------------------------------------------------------------------
// #define DQN_CPP_FILE_IMPLEMENTATION
// Define this in one and only one C++ file to enable the implementation
// code of the header file.
//
// #define DQN_CPPF_ASSERT(expr)
// Define this macro to override the default assert used.
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
@ -21,32 +7,22 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// NOTE: Dqn_CppFile: Helper functions to generate formatted CPP files // NOTE: Dqn_CppFile: Helper functions to generate formatted CPP files
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#if !defined(DQN_CPPF_ASSERT) #define DQN_CPPF_ASSERT(expr) do { if (!(expr)) { *((int *)0) = 0; } } while (0)
#define DQN_CPPF_ASSERT(expr) do { if (!(expr)) { *((volatile int *)0) = 0; } } while (0)
#endif
struct Dqn_CppFile struct Dqn_CppFile
{ {
FILE *file; // The file to output to. FILE *file;
int indent; // The current indent level int indent;
int space_per_indent; // The number of spaces applied per indent. If zero- the functions give a default value. int space_per_indent;
bool append_extra_new_line; // If true, when code blocks are terminated, an additional new line will be appended for whitespacing. bool append_extra_new_line;
}; };
// return: The number of spaces per indent at this point of invocation. If int Dqn_CppFile_SpacePerIndent(Dqn_CppFile *cpp);
// spaces-per-indent in the CppFile is set to 0 the indent defaults to 4 spaces.
int Dqn_CppFile_SpacePerIndent(Dqn_CppFile const *cpp);
// Create a line in the C++ file. This is a piece-meal API where you can
// flexibly construct a line by calling {LineBegin, LineAdd, LineEnd}. Calling
// LineEnd terminates the line with a trailing new-line. Calling LineAdd is
// optional if the line can be constructed with just a LineAdd and LineEnd.
void Dqn_CppFile_LineBeginV (Dqn_CppFile *cpp, char const *fmt, va_list args); void Dqn_CppFile_LineBeginV (Dqn_CppFile *cpp, char const *fmt, va_list args);
void Dqn_CppFile_LineBegin (Dqn_CppFile *cpp, char const *fmt, ...); void Dqn_CppFile_LineBegin (Dqn_CppFile *cpp, char const *fmt, ...);
void Dqn_CppFile_LineAdd (Dqn_CppFile *cpp, char const *fmt, ...);
void Dqn_CppFile_LineEnd (Dqn_CppFile *cpp, char const *fmt, ...); void Dqn_CppFile_LineEnd (Dqn_CppFile *cpp, char const *fmt, ...);
void Dqn_CppFile_LineAdd (Dqn_CppFile *cpp, char const *fmt, ...);
// Create a line in the C++ file and terminate it with a new-line.
void Dqn_CppFile_LineV (Dqn_CppFile *cpp, char const *fmt, va_list args); void Dqn_CppFile_LineV (Dqn_CppFile *cpp, char const *fmt, va_list args);
void Dqn_CppFile_Line (Dqn_CppFile *cpp, char const *fmt, ...); void Dqn_CppFile_Line (Dqn_CppFile *cpp, char const *fmt, ...);
@ -54,27 +30,9 @@ void Dqn_CppFile_NewLine (Dqn_CppFile *cpp);
void Dqn_CppFile_Indent (Dqn_CppFile *cpp); void Dqn_CppFile_Indent (Dqn_CppFile *cpp);
void Dqn_CppFile_Unindent (Dqn_CppFile *cpp); void Dqn_CppFile_Unindent (Dqn_CppFile *cpp);
// Begin a C++ code block which is any block that utilises a opening and
// closing brace.
// fmt: (Optional) The format string to print at the beginning of the block. // fmt: (Optional) The format string to print at the beginning of the block.
// When the fmt string is given, it will place a new-line at the end of the fmt // When the fmt string is given, it will place a new-line at the end of the fmt
// string. When fmt is nullptr, no new line will be appended. // string. When fmt is nullptr, no new line will be appended.
/*
Dqn_CppFile_Line(&cpp, "void MyFunction(int x, int y)");
Dqn_CppFile_BeginBlock(&cpp, nullptr);
Dqn_CppFile_Line(&cpp, "int result = x + y;");
Dqn_CppFile_Line(&cpp, "return result;");
Dqn_CppFile_EndFuncBlock(&cpp);
// Generates
//
// void MyFunction(int x, int y)
// {
// int result = x + y;
// return result;
// }
//
*/
void Dqn_CppFile_BeginBlock (Dqn_CppFile *cpp, char const *fmt, ...); void Dqn_CppFile_BeginBlock (Dqn_CppFile *cpp, char const *fmt, ...);
void Dqn_CppFile_EndBlock (Dqn_CppFile *cpp, bool trailing_semicolon, bool new_line_on_next_block); void Dqn_CppFile_EndBlock (Dqn_CppFile *cpp, bool trailing_semicolon, bool new_line_on_next_block);
@ -89,7 +47,7 @@ void Dqn_CppFile_EndBlock (Dqn_CppFile *cpp, bool trailing_semicolon, bo
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// NOTE: Dqn_CppFile Implementation // NOTE: Dqn_CppFile Implementation
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
int Dqn_CppFile_SpacePerIndent(Dqn_CppFile const *cpp) int Dqn_CppFile_SpacePerIndent(Dqn_CppFile *cpp)
{ {
int result = cpp->space_per_indent == 0 ? 4 : cpp->space_per_indent; int result = cpp->space_per_indent == 0 ? 4 : cpp->space_per_indent;
return result; return result;
@ -110,14 +68,6 @@ void Dqn_CppFile_LineBegin(Dqn_CppFile *cpp, char const *fmt, ...)
va_end(args); va_end(args);
} }
void Dqn_CppFile_LineAdd(Dqn_CppFile *cpp, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(cpp->file, fmt, args);
va_end(args);
}
void Dqn_CppFile_LineEnd(Dqn_CppFile *cpp, char const *fmt, ...) void Dqn_CppFile_LineEnd(Dqn_CppFile *cpp, char const *fmt, ...)
{ {
if (fmt) if (fmt)
@ -131,6 +81,14 @@ void Dqn_CppFile_LineEnd(Dqn_CppFile *cpp, char const *fmt, ...)
fputc('\n', cpp->file); fputc('\n', cpp->file);
} }
void Dqn_CppFile_LineAdd(Dqn_CppFile *cpp, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(cpp->file, fmt, args);
va_end(args);
}
void Dqn_CppFile_LineV(Dqn_CppFile *cpp, char const *fmt, va_list args) void Dqn_CppFile_LineV(Dqn_CppFile *cpp, char const *fmt, va_list args)
{ {
Dqn_CppFile_LineBeginV(cpp, fmt, args); Dqn_CppFile_LineBeginV(cpp, fmt, args);

View File

@ -14,10 +14,7 @@
// code of the header file. This will also automatically enable the JSMN // code of the header file. This will also automatically enable the JSMN
// implementation. // implementation.
// //
#include <assert.h>
#if !defined(DQN_H)
#error You must include "dqn.h" before including "dqn_jsmn.h"
#endif // DQN_H
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// NOTE: JSMN Configuration // NOTE: JSMN Configuration
@ -245,6 +242,22 @@ int jsmn_iterator_next( jsmn_iterator_t *iterator, jsmntok_t **jsmn_identifier,
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Header File // Header File
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#define DQN_JSMN_STRING(string) Dqn_JsmnString{(string), sizeof(string) - 1}
struct Dqn_JsmnString
{
union {
char * str;
char const *const_str;
};
int size;
};
bool Dqn_Jsmn_StringEq(Dqn_JsmnString lhs, Dqn_JsmnString rhs);
bool Dqn_Jsmn_StringIsValid(Dqn_JsmnString string);
bool Dqn_Jsmn_IsDigit(char ch);
uint64_t Dqn_Jsmn_StringToU64(Dqn_JsmnString string);
bool operator==(Dqn_JsmnString lhs, Dqn_JsmnString rhs);
#define DQN_JSMN_X_MACRO \ #define DQN_JSMN_X_MACRO \
DQN_JSMN_X_ENTRY(Object) \ DQN_JSMN_X_ENTRY(Object) \
DQN_JSMN_X_ENTRY(Array) \ DQN_JSMN_X_ENTRY(Array) \
@ -252,53 +265,50 @@ int jsmn_iterator_next( jsmn_iterator_t *iterator, jsmntok_t **jsmn_identifier,
DQN_JSMN_X_ENTRY(Number) \ DQN_JSMN_X_ENTRY(Number) \
DQN_JSMN_X_ENTRY(Bool) DQN_JSMN_X_ENTRY(Bool)
enum struct Dqn_JsmnTokenIs enum Dqn_JsmnTokenIs
{ {
#define DQN_JSMN_X_ENTRY(enum_val) enum_val, #define DQN_JSMN_X_ENTRY(enum_val) Dqn_JsmnTokenIs_##enum_val,
DQN_JSMN_X_MACRO DQN_JSMN_X_MACRO
#undef DQN_JSMN_X_ENTRY #undef DQN_JSMN_X_ENTRY
}; };
inline Dqn_String const Dqn_JsmnTokenIsEnumString(Dqn_JsmnTokenIs token) Dqn_JsmnString const Dqn_Jsmn_TokenIsToString[]
{ {
switch (token) #define DQN_JSMN_X_ENTRY(enum_val) DQN_JSMN_STRING(#enum_val),
{
#define DQN_JSMN_X_ENTRY(enum_val) case Dqn_JsmnTokenIs::enum_val: return DQN_STRING(#enum_val);
DQN_JSMN_X_MACRO DQN_JSMN_X_MACRO
#undef DQN_JSMN_X_ENTRY #undef DQN_JSMN_X_ENTRY
}
return DQN_STRING("DQN_JSMN_UNHANDLED_ENUM");
}; };
struct Dqn_JsmnError struct Dqn_JsmnError
{ {
jsmntok_t token; jsmntok_t token;
Dqn_String json; Dqn_JsmnString json;
Dqn_JsmnTokenIs expected; Dqn_JsmnTokenIs expected;
char const *cpp_file; // The file of the .cpp/h source code that triggered the error char const *cpp_file; // The file of the .cpp/h source code that triggered the error
int cpp_line; // The line of the .cpp/h source code that triggered the error int cpp_line; // The line of the .cpp/h source code that triggered the error
}; };
#define DQN_JSMN_ERROR_HANDLE_SIZE 128
struct Dqn_JsmnErrorHandle struct Dqn_JsmnErrorHandle
{ {
Dqn_ArenaAllocator *arena; Dqn_JsmnError errors[DQN_JSMN_ERROR_HANDLE_SIZE];
Dqn_List<Dqn_JsmnError> list; int errors_size;
}; };
struct Dqn_Jsmn struct Dqn_Jsmn
{ {
bool valid;
jsmn_parser parser; jsmn_parser parser;
Dqn_String json; Dqn_JsmnString json;
int tokens_size; int tokens_size;
jsmntok_t *tokens; jsmntok_t *tokens;
}; };
struct Dqn_JsmnIterator struct Dqn_JsmnIterator
{ {
Dqn_b32 init; bool init;
jsmn_iterator_t jsmn_it; jsmn_iterator_t jsmn_it;
Dqn_String json; Dqn_JsmnString json;
jsmntok_t *key; jsmntok_t *key;
jsmntok_t *value; jsmntok_t *value;
@ -308,61 +318,81 @@ struct Dqn_JsmnIterator
int token_index_hint; int token_index_hint;
}; };
Dqn_Jsmn Dqn_Jsmn_InitWithJSON (Dqn_String json, Dqn_ArenaAllocator *arena); // Calculate the number of tokens required to parse the 'json' input.
Dqn_Jsmn Dqn_Jsmn_InitWithJSONFile (Dqn_String file, Dqn_ArenaAllocator *arena); int Dqn_Jsmn_TokensRequired(char const *json, int size);
// To initialise successfully, call this function with the 'jsmn' parameter
// set with the 'jsmn->tokens' and 'jsmn->tokens_size' fields set to a valid
// destination buffer with a sufficient size that will be written on completion
// of the function. The required amount of tokens can be calculated using
// Dqn_Jsmn_TokensRequired.
//
// The function *does* not validate that the 'jsmn->tokens_size' is sufficient
// to hold the tokens in release mode.
//
// return: False if any of the parameters are invalid or the 'jsmn' tokens or
// size are not set, otherwise true. Additionally, 'jsmn->valid' is set
// accordingly to match the result of initialisation.
bool Dqn_Jsmn_InitWithJSONCString(char const *json, int size, Dqn_Jsmn *jsmn);
#if defined(DQN_H)
Dqn_Jsmn Dqn_Jsmn_InitWithJSON(Dqn_JsmnString json, Dqn_ArenaAllocator *arena);
Dqn_Jsmn Dqn_Jsmn_InitWithJSONFile(Dqn_JsmnString file, Dqn_ArenaAllocator *arena);
#endif // DQN_H
// return: If the token is an array, return the size of the array otherwise -1. // return: If the token is an array, return the size of the array otherwise -1.
int Dqn_Jsmn_TokenArraySize(jsmntok_t token); int Dqn_Jsmn_TokenArraySize(jsmntok_t token);
Dqn_String Dqn_Jsmn_TokenString(jsmntok_t token, Dqn_String json); Dqn_JsmnString Dqn_Jsmn_TokenString(jsmntok_t token, Dqn_JsmnString json);
Dqn_b32 Dqn_Jsmn_TokenBool(jsmntok_t token, Dqn_String json); bool Dqn_Jsmn_TokenBool(jsmntok_t token, Dqn_JsmnString json);
Dqn_u64 Dqn_Jsmn_TokenU64(jsmntok_t token, Dqn_String json); uint64_t Dqn_Jsmn_TokenU64(jsmntok_t token, Dqn_JsmnString json);
// Iterator abstraction over jsmn_iterator_t, example on how to use this is // Iterator abstraction over jsmn_iterator_t, example on how to use this is
// shown below. The goal here is to minimise the amount of state the user has to // shown below. The goal here is to minimise the amount of state the user has to
// manage. // manage.
#if 0 #if 0
Dqn_ArenaAllocator arena = {}; Dqn_ArenaAllocator arena = {};
Dqn_String json = DQN_STRING(R"({ Dqn_JsmnString json = DQN_STRING(R"({
"test": { "test": {
"test2": 0 "test2": 0
} }
})"); })");
Dqn_Jsmn jsmn_state = Dqn_Jsmn_InitWithJSON(json, &arena); Dqn_Jsmn jsmn_state = Dqn_Jsmn_InitWithJSON(json, &arena);
for (Dqn_JsmnIterator it = {}; Dqn_JsmnIterator_Next(&it, &jsmn_state, nullptr /*prev_it*/); ) for (Dqn_JsmnIterator it = {}; Dqn_Jsmn_IteratorNext(&it, &jsmn_state, nullptr /*prev_it*/); )
{ {
Dqn_String key_str = Dqn_Jsmn_TokenString(*it.key, jsmn_state.json); Dqn_JsmnString key = Dqn_JsmnITerator_Key(&it);
if (Dqn_JsmnIterator_Key(&it) == DQN_STRING("test")) if (key == DQN_STRING("test"))
{ {
if (!Dqn_JsmnIterator_ExpectValue(&it, Dqn_JsmnTokenIs::Object, nullptr)) if (!Dqn_Jsmn_IteratorExpectValue(&it, Dqn_JsmnTokenIs_Object, nullptr))
continue; continue;
for (Dqn_JsmnIterator obj_it = {}; Dqn_JsmnIterator_Next(&obj_it, &jsmn_state, &it); ) for (Dqn_JsmnIterator obj_it = {}; Dqn_Jsmn_IteratorNext(&obj_it, &jsmn_state, &it); )
{ {
if (Dqn_JsmnIterator_Key(&it) == DQN_STRING("test2")) Dqn_JsmnString obj_key = Dqn_JsmnITerator_Key(&obj_it);
if (obj_key == DQN_STRING("test2"))
{ {
if (!Dqn_JsmnIterator_ExpectValue(&it, Dqn_JsmnTokenIs::Number, nullptr)) if (!Dqn_Jsmn_IteratorExpectValue(&obj_it, Dqn_JsmnTokenIs_Number, nullptr))
continue; continue;
Dqn_u64 test_2_value = Dqn_JsmnIterator_U64(&obj_it); uint64_t test_2_value = Dqn_Jsmn_IteratorU64(&obj_it);
} }
} }
} }
} }
#endif #endif
Dqn_b32 Dqn_JsmnIterator_Next(Dqn_JsmnIterator *it, Dqn_Jsmn *jsmn_state, Dqn_JsmnIterator *prev_it); bool Dqn_Jsmn_IteratorNext(Dqn_JsmnIterator *it, Dqn_Jsmn *jsmn_state, Dqn_JsmnIterator *prev_it);
Dqn_String Dqn_JsmnIterator_Key (Dqn_JsmnIterator *it); Dqn_JsmnString Dqn_Jsmn_IteratorKey(Dqn_JsmnIterator *it);
Dqn_JsmnIterator Dqn_JsmnIterator_FindKey(Dqn_Jsmn *jsmn_state, Dqn_String key, Dqn_JsmnIterator *parent_it); Dqn_JsmnIterator Dqn_Jsmn_IteratorFindKey(Dqn_Jsmn *jsmn_state, Dqn_JsmnString key, Dqn_JsmnIterator *parent_it);
#define Dqn_JsmnIterator_ExpectValue(it, expected, err_handle) Dqn_JsmnIterator__ExpectValue(it, expected, err_handle, __FILE__, __LINE__) #define Dqn_Jsmn_IteratorExpectValue(it, expected, err_handle) Dqn_Jsmn_Iterator_ExpectValue(it, expected, err_handle, __FILE__, __LINE__)
#define Dqn_JsmnIterator_ExpectKey(it, expected, err_handle) Dqn_JsmnIterator__ExpectKey(it, expected, err_handle, __FILE__, __LINE__) #define Dqn_Jsmn_IteratorExpectKey(it, expected, err_handle) Dqn_Jsmn_Iterator_ExpectKey(it, expected, err_handle, __FILE__, __LINE__)
// Convert the value part of the key-value JSON pair the iterator is currently // Convert the value part of the key-value JSON pair the iterator is currently
// pointing to, to a string/bool/u64. If the iterator's value does not point to // pointing to, to a string/bool/u64. If the iterator's value does not point to
// the type requested, a zero initialised value is returned. // the type requested, a zero initialised value is returned.
Dqn_String Dqn_JsmnIterator_String(Dqn_JsmnIterator const *it); Dqn_JsmnString Dqn_Jsmn_IteratorString(Dqn_JsmnIterator const *it);
Dqn_b32 Dqn_JsmnIterator_Bool (Dqn_JsmnIterator const *it); bool Dqn_Jsmn_IteratorBool(Dqn_JsmnIterator const *it);
Dqn_u64 Dqn_JsmnIterator_U64 (Dqn_JsmnIterator const *it); uint64_t Dqn_Jsmn_IteratorU64(Dqn_JsmnIterator const *it);
#define DQN_JSMN_ERROR_HANDLE_DUMP(handle) \ #define DQN_JSMN_ERROR_HANDLE_DUMP(handle) \
for (Dqn_ListChunk<Dqn_JsmnError> *chunk = handle.list.head; chunk; chunk = chunk->next) \ for (Dqn_ListChunk<Dqn_JsmnError> *chunk = handle.list.head; chunk; chunk = chunk->next) \
@ -372,7 +402,7 @@ Dqn_u64 Dqn_JsmnIterator_U64 (Dqn_JsmnIterator const *it);
DQN_LOG_E("Json parsing error in %s:%d, expected token type: %.*s, token was: %.*s", \ DQN_LOG_E("Json parsing error in %s:%d, expected token type: %.*s, token was: %.*s", \
Dqn_Str_FileNameFromPath(error->cpp_file), \ Dqn_Str_FileNameFromPath(error->cpp_file), \
error->cpp_line, \ error->cpp_line, \
DQN_STRING_FMT(Dqn_JsmnTokenIsEnumString(error->expected)), \ DQN_STRING_FMT(Dqn_Jsmn_TokenIsToString(error->expected)), \
DQN_STRING_FMT(Dqn_Jsmn_TokenString(error->token, error->json))); \ DQN_STRING_FMT(Dqn_Jsmn_TokenString(error->token, error->json))); \
} \ } \
} }
@ -383,27 +413,89 @@ Dqn_u64 Dqn_JsmnIterator_U64 (Dqn_JsmnIterator const *it);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation // Implementation
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
Dqn_Jsmn Dqn_Jsmn_InitWithJSON(Dqn_String json, Dqn_ArenaAllocator *arena) bool Dqn_Jsmn_StringEq(Dqn_JsmnString lhs, Dqn_JsmnString rhs)
{ {
Dqn_Jsmn result = {}; bool result = lhs.size == rhs.size;
result.json = json; for (int i = 0; i < lhs.size && result; i++) result &= lhs.str[i] == rhs.str[i];
return result;
}
jsmn_init(&result.parser); bool Dqn_Jsmn_StringIsValid(Dqn_JsmnString string)
result.tokens_size = jsmn_parse(&result.parser, result.json.str, result.json.size, nullptr, 0); {
result.tokens = Dqn_ArenaAllocator_NewArray(arena, jsmntok_t, result.tokens_size, Dqn_ZeroMem::No); bool result = string.str && string.size >= 0;
return result;
}
jsmn_init(&result.parser); bool Dqn_Jsmn_IsDigit(char ch)
result.tokens_size = jsmn_parse(&result.parser, result.json.str, result.json.size, result.tokens, result.tokens_size); {
bool result = (ch >= '0' && ch <= '9');
return result;
}
uint64_t Dqn_Jsmn_StringToU64(Dqn_JsmnString string)
{
uint64_t result = 0;
if (!Dqn_Jsmn_StringIsValid(string))
return result;
for (int i = 0; i < string.size; i++)
{
char ch = string.str[i];
if (!Dqn_Jsmn_IsDigit(ch))
return result;
uint64_t digit = ch - '0';
result = (result * 10) + digit;
}
return result; return result;
} }
Dqn_Jsmn Dqn_Jsmn_InitWithJSONFile(Dqn_String file, Dqn_ArenaAllocator *arena) bool operator==(Dqn_JsmnString lhs, Dqn_JsmnString rhs)
{ {
Dqn_String json = Dqn_File_ArenaReadFileToString(file.str, arena); bool result = Dqn_Jsmn_StringEq(lhs, rhs);
return result;
}
int Dqn_Jsmn_TokensRequired(char const *json, int size)
{
jsmn_parser parser;
jsmn_init(&parser);
int result = jsmn_parse(&parser, json, size, nullptr, 0);
return result;
}
bool Dqn_Jsmn_InitWithJSONCString(char const *json, int size, Dqn_Jsmn *jsmn)
{
if (!jsmn || !jsmn->tokens || jsmn->tokens_size == 0 || !json)
return false;
assert(jsmn->tokens_size == Dqn_Jsmn_TokensRequired(json, size));
*jsmn = {};
jsmn_init(&jsmn->parser);
jsmn->valid = jsmn_parse(&jsmn->parser, jsmn->json.str, jsmn->json.size, jsmn->tokens, jsmn->tokens_size) > 0;
return jsmn->valid;
}
#if defined(DQN_H)
Dqn_Jsmn Dqn_Jsmn_InitWithJSON(Dqn_JsmnString json, Dqn_ArenaAllocator *arena)
{
Dqn_Jsmn result = {};
result.tokens_size = Dqn_Jsmn_InitWithJSONCString(json.str, json.size, nullptr);
result.tokens = Dqn_ArenaAllocator_NewArray(arena, jsmntok_t, result.tokens_size, Dqn_ZeroMem::No);
Dqn_Jsmn_InitWithJSONCString(json.str, json.size, &result)
return result;
}
Dqn_Jsmn Dqn_Jsmn_InitWithJSONFile(Dqn_JsmnString file, Dqn_ArenaAllocator *arena)
{
Dqn_JsmnString json = Dqn_File_ArenaReadFileToString(file.str, arena);
Dqn_Jsmn result = Dqn_Jsmn_InitWithJSON(json, arena); Dqn_Jsmn result = Dqn_Jsmn_InitWithJSON(json, arena);
return result; return result;
} }
#endif // DQN_H
int Dqn_Jsmn_TokenArraySize(jsmntok_t token) int Dqn_Jsmn_TokenArraySize(jsmntok_t token)
{ {
@ -411,58 +503,58 @@ int Dqn_Jsmn_TokenArraySize(jsmntok_t token)
return result; return result;
} }
Dqn_String Dqn_Jsmn_TokenString(jsmntok_t token, Dqn_String json) Dqn_JsmnString Dqn_Jsmn_TokenString(jsmntok_t token, Dqn_JsmnString json)
{ {
Dqn_String result = Dqn_String_Init(json.str + token.start, token.end - token.start); Dqn_JsmnString result = {json.str + token.start, token.end - token.start};
return result; return result;
} }
Dqn_b32 Dqn_Jsmn_TokenBool(jsmntok_t token, Dqn_String json) bool Dqn_Jsmn_TokenBool(jsmntok_t token, Dqn_JsmnString json)
{ {
DQN_ASSERT_MSG(token.start < json.size, "%I64d < %I64u", token.start, json.size); assert(token.start < json.size);
char ch = json.str[token.start]; char ch = json.str[token.start];
Dqn_b32 result = ch == 't'; bool result = ch == 't';
if (!result) { DQN_ASSERT(ch == 'f'); } if (!result) { assert(ch == 'f'); }
return result; return result;
} }
Dqn_u64 Dqn_Jsmn_TokenU64(jsmntok_t token, Dqn_String json) uint64_t Dqn_Jsmn_TokenU64(jsmntok_t token, Dqn_JsmnString json)
{ {
DQN_ASSERT_MSG(token.start < json.size, "%I64d < %I64u", token.start, json.size); assert(token.start < json.size);
Dqn_String string = Dqn_String_Init(json.str + token.start, token.end - token.start); Dqn_JsmnString string = {json.str + token.start, token.end - token.start};
Dqn_u64 result = Dqn_String_ToU64(string); uint64_t result = Dqn_Jsmn_StringToU64(string);
return result; return result;
} }
void Dqn_JsmnErrorHandle__AddError(Dqn_JsmnErrorHandle *err_handle, jsmntok_t token, Dqn_String json, Dqn_JsmnTokenIs expected, char const *file, int line) void Dqn_JsmnErrorHandle__AddError(Dqn_JsmnErrorHandle *handle, jsmntok_t token, Dqn_JsmnString json, Dqn_JsmnTokenIs expected, char const *file, int line)
{ {
if (!err_handle) if (!handle)
return; return;
if (!err_handle->list.head) if (handle->errors_size >= DQN_JSMN_ERROR_HANDLE_SIZE)
err_handle->list = Dqn_List_InitWithArena<Dqn_JsmnError>(err_handle->arena, 16); return;
Dqn_JsmnError *error = Dqn_List_Make(&err_handle->list, 1); Dqn_JsmnError *error = handle->errors + handle->errors_size++;
if (error)
{
error->expected = expected; error->expected = expected;
error->json = json; error->json = json;
error->cpp_file = file; error->cpp_file = file;
error->cpp_line = line; error->cpp_line = line;
} }
}
Dqn_b32 Dqn_JsmnIterator_Next(Dqn_JsmnIterator *it, Dqn_Jsmn *jsmn_state, Dqn_JsmnIterator *prev_it) bool Dqn_Jsmn_IteratorNext(Dqn_JsmnIterator *it, Dqn_Jsmn *jsmn_state, Dqn_JsmnIterator *prev_it)
{ {
if (!it->init) if (!it->init)
{ {
it->init = true; it->init = true;
if (jsmn_state->valid)
{
it->json = jsmn_state->json; it->json = jsmn_state->json;
jsmn_iterator_init(&it->jsmn_it, jsmn_state->tokens, jsmn_state->tokens_size, prev_it ? jsmn_iterator_position(&prev_it->jsmn_it) : 0); jsmn_iterator_init(&it->jsmn_it, jsmn_state->tokens, jsmn_state->tokens_size, prev_it ? jsmn_iterator_position(&prev_it->jsmn_it) : 0);
} }
}
Dqn_b32 result = false; bool result = false;
if (!Dqn_String_IsValid(it->json) || it->json.size <= 0) { if (!Dqn_Jsmn_StringIsValid(it->json) || it->json.size <= 0) {
return result; return result;
} }
@ -478,20 +570,20 @@ Dqn_b32 Dqn_JsmnIterator_Next(Dqn_JsmnIterator *it, Dqn_Jsmn *jsmn_state, Dqn_Js
return result; return result;
} }
Dqn_String Dqn_JsmnIterator_Key(Dqn_JsmnIterator *it) Dqn_JsmnString Dqn_Jsmn_IteratorKey(Dqn_JsmnIterator *it)
{ {
Dqn_String result = {}; Dqn_JsmnString result = {};
if (it && it->key) if (it && it->key)
result = Dqn_String_Init(it->json.str + it->key->start, it->key->end - it->key->start); result = {it->json.str + it->key->start, it->key->end - it->key->start};
return result; return result;
} }
Dqn_JsmnIterator Dqn_JsmnIterator_FindKey(Dqn_Jsmn *jsmn_state, Dqn_String key, Dqn_JsmnIterator *parent_it) Dqn_JsmnIterator Dqn_Jsmn_IteratorFindKey(Dqn_Jsmn *jsmn_state, Dqn_JsmnString key, Dqn_JsmnIterator *parent_it)
{ {
Dqn_JsmnIterator result = {}; Dqn_JsmnIterator result = {};
for (Dqn_JsmnIterator it = {}; Dqn_JsmnIterator_Next(&it, jsmn_state, parent_it); ) for (Dqn_JsmnIterator it = {}; Dqn_Jsmn_IteratorNext(&it, jsmn_state, parent_it); )
{ {
Dqn_String it_key = Dqn_Jsmn_TokenString(*it.key, jsmn_state->json); Dqn_JsmnString it_key = Dqn_Jsmn_TokenString(*it.key, jsmn_state->json);
if (it_key == key) if (it_key == key)
{ {
result = it; result = it;
@ -502,26 +594,26 @@ Dqn_JsmnIterator Dqn_JsmnIterator_FindKey(Dqn_Jsmn *jsmn_state, Dqn_String key,
return result; return result;
} }
static Dqn_b32 Dqn_JsmnIterator__Expect(Dqn_JsmnIterator *it, Dqn_JsmnTokenIs expected, jsmntok_t token, Dqn_JsmnErrorHandle *err_handle, char const *file, unsigned int line) static bool Dqn_Jsmn_Iterator_Expect(Dqn_JsmnIterator *it, Dqn_JsmnTokenIs expected, jsmntok_t token, Dqn_JsmnErrorHandle *err_handle, char const *file, unsigned int line)
{ {
Dqn_b32 result = false; bool result = false;
switch (expected) switch (expected)
{ {
case Dqn_JsmnTokenIs::Object: result = token.type == JSMN_OBJECT; break; case Dqn_JsmnTokenIs_Object: result = token.type == JSMN_OBJECT; break;
case Dqn_JsmnTokenIs::Array: result = token.type == JSMN_ARRAY; break; case Dqn_JsmnTokenIs_Array: result = token.type == JSMN_ARRAY; break;
case Dqn_JsmnTokenIs::String: result = token.type == JSMN_STRING; break; case Dqn_JsmnTokenIs_String: result = token.type == JSMN_STRING; break;
case Dqn_JsmnTokenIs::Number: case Dqn_JsmnTokenIs_Number:
{ {
DQN_ASSERT_MSG(token.start < it->json.size, "%I64d < %I64u", token.start, it->json.size); assert(token.start < it->json.size);
char ch = it->json.str[token.start]; char ch = it->json.str[token.start];
result = token.type == JSMN_PRIMITIVE && (ch == '-' || Dqn_Char_IsDigit(ch)); result = token.type == JSMN_PRIMITIVE && (ch == '-' || Dqn_Jsmn_IsDigit(ch));
} }
break; break;
case Dqn_JsmnTokenIs::Bool: case Dqn_JsmnTokenIs_Bool:
{ {
DQN_ASSERT_MSG(token.start < it->json.size, "%I64d < %I64u", token.start, it->json.size); assert(token.start < it->json.size);
char ch = it->json.str[token.start]; char ch = it->json.str[token.start];
result = token.type == JSMN_PRIMITIVE && (ch == 't' || ch == 'f'); result = token.type == JSMN_PRIMITIVE && (ch == 't' || ch == 'f');
} }
@ -534,34 +626,35 @@ static Dqn_b32 Dqn_JsmnIterator__Expect(Dqn_JsmnIterator *it, Dqn_JsmnTokenIs ex
return result; return result;
} }
Dqn_b32 Dqn_JsmnIterator__ExpectValue(Dqn_JsmnIterator *it, Dqn_JsmnTokenIs expected, Dqn_JsmnErrorHandle *err_handle, char const *file, unsigned int line) bool Dqn_Jsmn_Iterator_ExpectValue(Dqn_JsmnIterator *it, Dqn_JsmnTokenIs expected, Dqn_JsmnErrorHandle *err_handle, char const *file, unsigned int line)
{ {
Dqn_b32 result = it->value && Dqn_JsmnIterator__Expect(it, expected, *it->value, err_handle, file, line); bool result = it->value && Dqn_Jsmn_Iterator_Expect(it, expected, *it->value, err_handle, file, line);
return result; return result;
} }
Dqn_b32 Dqn_JsmnIterator__ExpectKey(Dqn_JsmnIterator *it, Dqn_JsmnTokenIs expected, Dqn_JsmnErrorHandle *err_handle, char const *file, unsigned int line) bool Dqn_Jsmn_Iterator_ExpectKey(Dqn_JsmnIterator *it, Dqn_JsmnTokenIs expected, Dqn_JsmnErrorHandle *err_handle, char const *file, unsigned int line)
{ {
Dqn_b32 result = it->key && Dqn_JsmnIterator__Expect(it, expected, *it->key, err_handle, file, line); bool result = it->key && Dqn_Jsmn_Iterator_Expect(it, expected, *it->key, err_handle, file, line);
return result; return result;
} }
Dqn_String Dqn_JsmnIterator_String(Dqn_JsmnIterator const *it) Dqn_JsmnString Dqn_Jsmn_IteratorString(Dqn_JsmnIterator const *it)
{ {
Dqn_String result = {}; Dqn_JsmnString result = {};
if (it->value && it->json.str) result = Dqn_String_Init(it->json.str + it->value->start, it->value->end - it->value->start); if (it->value && it->json.str)
result = {it->json.str + it->value->start, it->value->end - it->value->start};
return result; return result;
} }
Dqn_b32 Dqn_JsmnIterator_Bool(Dqn_JsmnIterator const *it) bool Dqn_Jsmn_IteratorBool(Dqn_JsmnIterator const *it)
{ {
Dqn_b32 result = it->value && Dqn_Jsmn_TokenBool(*it->value, it->json); bool result = it->value && Dqn_Jsmn_TokenBool(*it->value, it->json);
return result; return result;
} }
Dqn_u64 Dqn_JsmnIterator_U64(Dqn_JsmnIterator const *it) uint64_t Dqn_Jsmn_IteratorU64(Dqn_JsmnIterator const *it)
{ {
Dqn_u64 result = it->value && Dqn_Jsmn_TokenU64(*it->value, it->json); uint64_t result = it->value && Dqn_Jsmn_TokenU64(*it->value, it->json);
return result; return result;
} }

View File

@ -38,26 +38,6 @@
// #define DQN_KECCAK_IMPLEMENTATION // #define DQN_KECCAK_IMPLEMENTATION
// Define this in one and only one C++ file to enable the implementation // Define this in one and only one C++ file to enable the implementation
// code of the header file. // code of the header file.
//
// #define DQN_KECCAK_MEMCOPY
// Define this macro to override the memcpy implementation and avoid pulling
// in string.h.
//
// #define DQN_KECCAK_MEMCMP
// Define this macro to override the memcmp implementation and avoid pulling
// in string.h.
//
// #define DQN_NO_MALLOC_FUNCTIONS
// Define this macro to disable the non-essential helper functions that use
// malloc.
//
// #define DQN_KECCAK_MALLOC
// Define this macro to override the malloc implementation. This library
// provides helper functions that use malloc if DQN_NO_MALLOC_FUNCTIONS is
// not defined.
//
// #define DQN_KECCAK_ASSERT
// Define this macro to override the assert implementation.
#if !defined(DQN_KECCAK_MEMCOPY) #if !defined(DQN_KECCAK_MEMCOPY)
#include <string.h> #include <string.h>
@ -69,13 +49,6 @@
#define DQN_KECCAK_MEMCMP(dest, src, count) memcmp(dest, src, count) #define DQN_KECCAK_MEMCMP(dest, src, count) memcmp(dest, src, count)
#endif #endif
#if !defined(DQN_NO_MALLOC_FUNCTIONS)
#if !defined(DQN_KECCAK_MALLOC)
#include <stdlib.h>
#define DQN_KECCAK_MALLOC(size) malloc(size)
#endif
#endif
#if !defined(DQN_KECCAK_ASSERT) #if !defined(DQN_KECCAK_ASSERT)
#if defined(NDEBUG) #if defined(NDEBUG)
#define DQN_KECCAK_ASSERT(expr) #define DQN_KECCAK_ASSERT(expr)
@ -135,23 +108,15 @@ typedef unsigned int Dqn_Keccak_uint;
// the returned hash is (bit-rate/8) bytes, i.e. the dest_size must be atleast // the returned hash is (bit-rate/8) bytes, i.e. the dest_size must be atleast
// 32 bytes for SHA-256 and so forth. // 32 bytes for SHA-256 and so forth.
// dest_size: The passed in destination buffer must be >= 28 (bytes), otherwise
// the function asserts or does no-op in release.
void Dqn_Keccak_SHA3_224(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size); void Dqn_Keccak_SHA3_224(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size);
Dqn_KeccakBytes28 Dqn_Keccak_SHA3_224_ToBytes28(void *bytes, Dqn_Keccak_u64 bytes_size); Dqn_KeccakBytes28 Dqn_Keccak_SHA3_224_ToBytes28(void *bytes, Dqn_Keccak_u64 bytes_size);
// dest_size: The passed in destination buffer must be >= 32 (bytes), otherwise
// the function asserts or does no-op in release.
void Dqn_Keccak_SHA3_256(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size); void Dqn_Keccak_SHA3_256(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size);
Dqn_KeccakBytes32 Dqn_Keccak_SHA3_256_ToBytes32(void *bytes, Dqn_Keccak_u64 bytes_size); Dqn_KeccakBytes32 Dqn_Keccak_SHA3_256_ToBytes32(void *bytes, Dqn_Keccak_u64 bytes_size);
// dest_size: The passed in destination buffer must be >= 48 (bytes), otherwise
// the function asserts or does no-op in release.
void Dqn_Keccak_SHA3_384(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size); void Dqn_Keccak_SHA3_384(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size);
Dqn_KeccakBytes48 Dqn_Keccak_SHA3_384_ToBytes48(void *bytes, Dqn_Keccak_u64 bytes_size); Dqn_KeccakBytes48 Dqn_Keccak_SHA3_384_ToBytes48(void *bytes, Dqn_Keccak_u64 bytes_size);
// dest_size: The passed in destination buffer must be >= 64 (bytes), otherwise
// the function asserts or does no-op in release.
void Dqn_Keccak_SHA3_512(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size); void Dqn_Keccak_SHA3_512(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size);
Dqn_KeccakBytes64 Dqn_Keccak_SHA3_512_ToBytes64(void *bytes, Dqn_Keccak_u64 bytes_size); Dqn_KeccakBytes64 Dqn_Keccak_SHA3_512_ToBytes64(void *bytes, Dqn_Keccak_u64 bytes_size);
@ -176,24 +141,15 @@ Dqn_KeccakBytes64 Dqn_Keccak_SHA3_512_U8ArrayToBytes64(Dqn_Array<Dqn_Keccak_u8>
// Applies the non-finalized SHA3 algorithm (i.e. a delimited suffix of 0x1 // Applies the non-finalized SHA3 algorithm (i.e. a delimited suffix of 0x1
// instead of 0x6 in SHA3). This is the version of the algorithm used by // instead of 0x6 in SHA3). This is the version of the algorithm used by
// Ethereum and Monero as they adopted SHA3 before it was finalized. // Ethereum and Monero as they adopted SHA3 before it was finalized.
// dest_size: The passed in destination buffer must be >= 28 (bytes), otherwise
// the function asserts or does no-op in release.
void Dqn_Keccak_224(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size); void Dqn_Keccak_224(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size);
Dqn_KeccakBytes28 Dqn_Keccak_224_ToBytes28(void *bytes, Dqn_Keccak_u64 bytes_size); Dqn_KeccakBytes28 Dqn_Keccak_224_ToBytes28(void *bytes, Dqn_Keccak_u64 bytes_size);
// dest_size: The passed in destination buffer must be >= 32 (bytes), otherwise
// the function asserts or does no-op in release.
void Dqn_Keccak_256(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size); void Dqn_Keccak_256(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size);
Dqn_KeccakBytes32 Dqn_Keccak_256_ToBytes32(void *bytes, Dqn_Keccak_u64 bytes_size); Dqn_KeccakBytes32 Dqn_Keccak_256_ToBytes32(void *bytes, Dqn_Keccak_u64 bytes_size);
// dest_size: The passed in destination buffer must be >= 48 (bytes), otherwise
// the function asserts or does no-op in release.
void Dqn_Keccak_384(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size); void Dqn_Keccak_384(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size);
Dqn_KeccakBytes48 Dqn_Keccak_384_ToBytes48(void *bytes, Dqn_Keccak_u64 bytes_size); Dqn_KeccakBytes48 Dqn_Keccak_384_ToBytes48(void *bytes, Dqn_Keccak_u64 bytes_size);
// dest_size: The passed in destination buffer must be >= 64 (bytes), otherwise
// the function asserts or does no-op in release.
void Dqn_Keccak_512(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size); void Dqn_Keccak_512(void const *src, Dqn_Keccak_u64 src_size, void *dest, int dest_size);
Dqn_KeccakBytes64 Dqn_Keccak_512_ToBytes64(void *bytes, Dqn_Keccak_u64 bytes_size); Dqn_KeccakBytes64 Dqn_Keccak_512_ToBytes64(void *bytes, Dqn_Keccak_u64 bytes_size);
@ -218,19 +174,8 @@ Dqn_KeccakBytes64 Dqn_Keccak_512_U8ArrayToBytes64(Dqn_Array<Dqn_Keccak_u8> array
// Convert a binary buffer into its hex representation into dest. The dest // Convert a binary buffer into its hex representation into dest. The dest
// buffer must be large enough to contain the hex representation, i.e. // buffer must be large enough to contain the hex representation, i.e.
// atleast src_size * 2). This function does *not* null-terminate the buffer. // atleast src_size * 2). This function does *not* null-terminate the buffer.
// The returned result does *not* include a leading 0x prefix.
void Dqn_Keccak_BytesToHex(void const *src, Dqn_Keccak_u64 src_size, char *dest, Dqn_Keccak_u64 dest_size); void Dqn_Keccak_BytesToHex(void const *src, Dqn_Keccak_u64 src_size, char *dest, Dqn_Keccak_u64 dest_size);
#if defined(DQN_NO_MALLOC_FUNCTIONS)
// Convert the src bytes into a null-terminated c-string using malloc. Calls
// into Dqn_Keccak_BytesToHex under the hood.
// src: If src is nullptr, the function returns an empty null-terminated
// string, otherwise, the bytes will be converted and returned as hex.
// return: A null-terminated c-string. This string must be freed by the user
// using the CRT free(..). If malloc fails the returned string is nullptr.
char *Dqn_Keccak_BytesToHexCString(void const *src, Dqn_Keccak_u64 src_size);
#endif // DQN_NO_MALLOC_FUNCTIONS
// Converts a fixed amount of bytes into a hexadecimal string. Helper functions // Converts a fixed amount of bytes into a hexadecimal string. Helper functions
// that call into Dqn_Keccak_BytesToHex. // that call into Dqn_Keccak_BytesToHex.
// return: The hexadecimal string of the bytes, null-terminated. // return: The hexadecimal string of the bytes, null-terminated.
@ -878,21 +823,6 @@ void Dqn_Keccak_BytesToHex(void const *src, Dqn_Keccak_u64 src_size, char *dest,
} }
} }
#if defined(DQN_NO_MALLOC_FUNCTIONS)
char *Dqn_Keccak_BytesToHexCString(void const *src, Dqn_Keccak_u64 src_size)
{
int result_size = (src_size * 2);
char *result = DQN_KECCAK_MALLOC(result_size + 1 /*null-terminator*/);
if (result)
{
Dqn_Keccak_BytesToHex(src, src_size, result, result_size);
result[result_size] = 0;
}
return result;
}
#endif // DQN_NO_MALLOC_FUNCTIONS
Dqn_KeccakString56 Dqn_Keccak_Bytes28ToHex(Dqn_KeccakBytes28 const *bytes) Dqn_KeccakString56 Dqn_Keccak_Bytes28ToHex(Dqn_KeccakBytes28 const *bytes)
{ {
Dqn_KeccakString56 result; Dqn_KeccakString56 result;
@ -957,7 +887,7 @@ Dqn_KeccakBytes32 Dqn_Keccak_Hex64StringToBytes(Dqn_String hex)
{ {
DQN_KECCAK_ASSERT(hex.size == 64); DQN_KECCAK_ASSERT(hex.size == 64);
Dqn_KeccakBytes32 result; Dqn_KeccakBytes32 result;
Dqn_Hex_HexToBytes(hex.str, hex.size, result.data, sizeof(result)); Dqn_HexToBytes(hex.str, hex.size, result.data, sizeof(result));
return result; return result;
} }
#endif // DQN_H #endif // DQN_H

File diff suppressed because it is too large Load Diff