Import latest revision of dqn lib from CSIGHT

This commit is contained in:
doylet 2024-03-19 23:11:00 +11:00
parent 7f2a0152e0
commit 158d058d5d
16 changed files with 270 additions and 81 deletions

View File

@ -71,7 +71,7 @@ void Dqn_CppPrint(Dqn_CppFile *cpp, char const *fmt, ...);
#define Dqn_CppForBlock(cpp, fmt, ...) \ #define Dqn_CppForBlock(cpp, fmt, ...) \
for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \ for (bool DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = \
(Dqn_CppBeginForBLock(cpp, fmt, ##__VA_ARGS__), true); \ (Dqn_CppBeginForBlock(cpp, fmt, ##__VA_ARGS__), true); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \ DQN_CPP_TOKEN_PASTE_(once_, __LINE__); \
DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndForBlock(cpp), false)) DQN_CPP_TOKEN_PASTE_(once_, __LINE__) = (Dqn_CppEndForBlock(cpp), false))

View File

@ -220,7 +220,7 @@ DQN_API void Dqn_Arena_Pop(Dqn_Arena *arena, uint64_t amount)
Dqn_Arena_PopTo(arena, pop_to); Dqn_Arena_PopTo(arena, pop_to);
} }
DQN_API uint64_t Dqn_Arena_Pos(Dqn_Arena *arena) DQN_API uint64_t Dqn_Arena_Pos(Dqn_Arena const *arena)
{ {
uint64_t result = (arena && arena->curr) ? arena->curr->reserve_sum + arena->curr->used : 0; uint64_t result = (arena && arena->curr) ? arena->curr->reserve_sum + arena->curr->used : 0;
return result; return result;
@ -231,6 +231,18 @@ DQN_API void Dqn_Arena_Clear(Dqn_Arena *arena)
Dqn_Arena_PopTo(arena, 0); Dqn_Arena_PopTo(arena, 0);
} }
DQN_API bool Dqn_Arena_OwnsPtr(Dqn_Arena const *arena, void *ptr)
{
bool result = false;
uintptr_t uint_ptr = DQN_CAST(uintptr_t)ptr;
for (Dqn_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; ) {
uintptr_t begin = DQN_CAST(uintptr_t) block + DQN_ARENA_HEADER_SIZE;
uintptr_t end = begin + block->reserve;
result = uint_ptr >= begin && uint_ptr <= end;
}
return result;
}
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin(Dqn_Arena *arena) DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin(Dqn_Arena *arena)
{ {
Dqn_ArenaTempMem result = {}; Dqn_ArenaTempMem result = {};

View File

@ -145,8 +145,9 @@ DQN_API void * Dqn_Arena_AllocContiguous (Dqn_Arena *arena,
DQN_API void * Dqn_Arena_Copy (Dqn_Arena *arena, void const *data, uint64_t size, uint8_t align); DQN_API void * Dqn_Arena_Copy (Dqn_Arena *arena, void const *data, uint64_t size, uint8_t align);
DQN_API void Dqn_Arena_PopTo (Dqn_Arena *arena, uint64_t init_used); DQN_API void Dqn_Arena_PopTo (Dqn_Arena *arena, uint64_t init_used);
DQN_API void Dqn_Arena_Pop (Dqn_Arena *arena, uint64_t amount); DQN_API void Dqn_Arena_Pop (Dqn_Arena *arena, uint64_t amount);
DQN_API uint64_t Dqn_Arena_Pos (Dqn_Arena *arena); DQN_API uint64_t Dqn_Arena_Pos (Dqn_Arena const *arena);
DQN_API void Dqn_Arena_Clear (Dqn_Arena *arena); DQN_API void Dqn_Arena_Clear (Dqn_Arena *arena);
DQN_API bool Dqn_Arena_OwnsPtr (Dqn_Arena const *arena, void *ptr);
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin (Dqn_Arena *arena); DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin (Dqn_Arena *arena);
DQN_API void Dqn_Arena_TempMemEnd (Dqn_ArenaTempMem mem); DQN_API void Dqn_Arena_TempMemEnd (Dqn_ArenaTempMem mem);
#define Dqn_Arena_New(arena, T, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem) #define Dqn_Arena_New(arena, T, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)

View File

@ -419,6 +419,12 @@ DQN_API Dqn_ErrorSink *Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode mode)
return result; return result;
} }
DQN_API bool Dqn_ErrorSink_HasError(Dqn_ErrorSink *error)
{
bool result = error && error->stack->error;
return result;
}
DQN_API Dqn_ErrorSinkNode Dqn_ErrorSink_End(Dqn_Arena *arena, Dqn_ErrorSink *error) DQN_API Dqn_ErrorSinkNode Dqn_ErrorSink_End(Dqn_Arena *arena, Dqn_ErrorSink *error)
{ {
Dqn_ErrorSinkNode result = {}; Dqn_ErrorSinkNode result = {};
@ -445,7 +451,7 @@ DQN_API bool Dqn_ErrorSink_EndAndLogError(Dqn_ErrorSink *error, Dqn_Str8 error_m
Dqn_ErrorSinkNode node = Dqn_ErrorSink_End(scratch.arena, error); Dqn_ErrorSinkNode node = Dqn_ErrorSink_End(scratch.arena, error);
if (node.error) { if (node.error) {
if (Dqn_Str8_HasData(error_msg)) { if (Dqn_Str8_HasData(error_msg)) {
Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s. %.*s", DQN_STR_FMT(error_msg), DQN_STR_FMT(node.msg)); Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s: %.*s", DQN_STR_FMT(error_msg), DQN_STR_FMT(node.msg));
} else { } else {
Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s", DQN_STR_FMT(node.msg)); Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s", DQN_STR_FMT(node.msg));
} }
@ -475,9 +481,11 @@ DQN_API bool Dqn_ErrorSink_EndAndLogErrorF(Dqn_ErrorSink *error, DQN_FMT_ATTRIB
DQN_API void Dqn_ErrorSink_EndAndExitIfErrorFV(Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, va_list args) DQN_API void Dqn_ErrorSink_EndAndExitIfErrorFV(Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, va_list args)
{ {
if (Dqn_ErrorSink_EndAndLogErrorFV(error, fmt, args)) if (Dqn_ErrorSink_EndAndLogErrorFV(error, fmt, args)) {
DQN_DEBUG_BREAK;
Dqn_OS_Exit(exit_code); Dqn_OS_Exit(exit_code);
} }
}
DQN_API void Dqn_ErrorSink_EndAndExitIfErrorF(Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, ...) DQN_API void Dqn_ErrorSink_EndAndExitIfErrorF(Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, ...)
{ {
@ -500,7 +508,7 @@ DQN_API void Dqn_ErrorSink_MakeFV_(Dqn_ErrorSink *error, uint32_t error_code, DQ
node->error = true; node->error = true;
node->call_site = Dqn_ThreadContext_Get()->call_site; node->call_site = Dqn_ThreadContext_Get()->call_site;
if (node->mode == Dqn_ErrorSinkMode_ExitOnError) if (node->mode == Dqn_ErrorSinkMode_ExitOnError)
Dqn_ErrorSink_EndAndExitIfErrorF(error, error_code, "Fatal error encountered: (%u) %.*s", error_code, DQN_STR_FMT(node->msg)); Dqn_ErrorSink_EndAndExitIfErrorF(error, error_code, "Fatal error %u", error_code);
} }
} }

View File

@ -285,7 +285,7 @@
} while (0) } while (0)
#endif #endif
#define DQN_INVALID_CODE_PATHF(fmt, ...) DQN_ASSERTF(0, fmt, ##__VA_ARGS__) #define DQN_INVALID_CODE_PATHF(fmt, ...) DQN_HARD_ASSERTF(0, fmt, ##__VA_ARGS__)
#define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered") #define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered")
// NOTE: Check macro /////////////////////////////////////////////////////////////////////////////// // NOTE: Check macro ///////////////////////////////////////////////////////////////////////////////
@ -621,6 +621,7 @@ DQN_API void Dqn_Log_FCallSite
// NOTE: [$ERRS] Dqn_ErrorSink ///////////////////////////////////////////////////////////////////// // NOTE: [$ERRS] Dqn_ErrorSink /////////////////////////////////////////////////////////////////////
DQN_API Dqn_ErrorSink * Dqn_ErrorSink_Begin (Dqn_ErrorSinkMode mode); DQN_API Dqn_ErrorSink * Dqn_ErrorSink_Begin (Dqn_ErrorSinkMode mode);
DQN_API bool Dqn_ErrorSink_HasError (Dqn_ErrorSink *error);
DQN_API Dqn_ErrorSinkNode Dqn_ErrorSink_End (Dqn_Arena *arena, Dqn_ErrorSink *error); DQN_API Dqn_ErrorSinkNode Dqn_ErrorSink_End (Dqn_Arena *arena, Dqn_ErrorSink *error);
DQN_API bool Dqn_ErrorSink_EndAndLogError (Dqn_ErrorSink *error, Dqn_Str8 error_msg); DQN_API bool Dqn_ErrorSink_EndAndLogError (Dqn_ErrorSink *error, Dqn_Str8 error_msg);
DQN_API bool Dqn_ErrorSink_EndAndLogErrorFV (Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args); DQN_API bool Dqn_ErrorSink_EndAndLogErrorFV (Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args);

View File

@ -105,6 +105,9 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error)
DQN_ARRAY_UCOUNT(DQN_CGEN_TABLE_TYPE_LIST), DQN_ARRAY_UCOUNT(DQN_CGEN_TABLE_TYPE_LIST),
"Table 'type' specified invalid value"); "Table 'type' specified invalid value");
table->type = DQN_CAST(Dqn_CGenTableType) table_type_validator.enum_val; table->type = DQN_CAST(Dqn_CGenTableType) table_type_validator.enum_val;
DQN_ASSERT(table->type <= Dqn_CGenTableType_Count);
cgen->table_counts[table->type]++;
} break; } break;
} }
} }
@ -454,6 +457,7 @@ DQN_API bool Dqn_CGen_LookupNextTableInCodeGenTable(Dqn_CGen *cgen, Dqn_CGenTabl
// NOTE: Lookup the table in this row that we will code generate from. Not // NOTE: Lookup the table in this row that we will code generate from. Not
// applicable when we are doing builtin types as the types are just put // applicable when we are doing builtin types as the types are just put
// in-line into the code generation table itself. // in-line into the code generation table itself.
it->cgen_table = cgen_table;
it->cgen_table_row = cgen_table->rows + it->row_index++; it->cgen_table_row = cgen_table->rows + it->row_index++;
if (cgen_table->type != Dqn_CGenTableType_CodeGenBuiltinTypes) { if (cgen_table->type != Dqn_CGenTableType_CodeGenBuiltinTypes) {
Dqn_CGenTableColumn cgen_table_column = it->cgen_table_row->columns[cgen_table->column_indexes[Dqn_CGenTableHeaderType_Table]]; Dqn_CGenTableColumn cgen_table_column = it->cgen_table_row->columns[cgen_table->column_indexes[Dqn_CGenTableHeaderType_Table]];
@ -752,7 +756,7 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
} }
Dqn_CppBlock(cpp, ";\n\n", "Dqn_TypeInfo const g_%.*s_types[] =", DQN_STR_FMT(emit_prefix)) { Dqn_CppBlock(cpp, ";\n\n", "Dqn_TypeInfo const g_%.*s_types[] =", DQN_STR_FMT(emit_prefix)) {
Dqn_CppLine(cpp, "{DQN_STR8(\"\"),%*sDqn_TypeKind_Nil, /*fields*/ NULL, /*count*/ 0},", 1 + longest_name_across_all_tables, ""); Dqn_CppLine(cpp, "{DQN_STR8(\"\"),%*sDqn_TypeKind_Nil, 0, /*fields*/ NULL, /*count*/ 0},", 1 + longest_name_across_all_tables, "");
for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string; Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
@ -794,16 +798,45 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
} }
Dqn_CppLine(cpp, Dqn_CppLine(cpp,
"{DQN_STR8(\"%.*s\"),%*s%.*s, %s/*fields*/ %.*s,%*s/*count*/ %.*s},", "{DQN_STR8(\"%.*s\"),%*s%.*s, %ssizeof(%.*s),%*s/*fields*/ %.*s,%*s/*count*/ %.*s},",
DQN_STR_FMT(type_name), DQN_STR_FMT(type_name),
name_padding, "", name_padding, "",
DQN_STR_FMT(type_info_kind), DQN_STR_FMT(type_info_kind),
type_info_kind_padding, type_info_kind_padding,
DQN_STR_FMT(type_name),
name_padding, "",
DQN_STR_FMT(fields), DQN_STR_FMT(fields),
fields_padding, "", fields_padding, "",
DQN_STR_FMT(fields_count)); DQN_STR_FMT(fields_count));
} }
} }
} }
for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
if (table->type != Dqn_CGenTableType_CodeGenEnum)
continue;
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
Dqn_CppStructBlock(cpp, "%.*sStr8ToEnumResult", DQN_STR_FMT(type_name)) {
Dqn_CppLine(cpp, "bool success;");
Dqn_CppLine(cpp, "%.*s value;", DQN_STR_FMT(type_name));
}
Dqn_CppFuncBlock(cpp, "%.*sStr8ToEnumResult %.*s_Str8ToEnum(Dqn_Str8 string)", DQN_STR_FMT(type_name), DQN_STR_FMT(type_name)) {
Dqn_CppLine(cpp, "%.*sStr8ToEnumResult result = {};", DQN_STR_FMT(type_name));
Dqn_CppForBlock(cpp, "Dqn_usize index = 0; !result.success && index < DQN_ARRAY_UCOUNT(g_%.*s_type_fields); index++", DQN_STR_FMT(type_name)) {
Dqn_CppIfChain(cpp) {
Dqn_CppLine(cpp, "Dqn_TypeField field = g_%.*s_type_fields[index];", DQN_STR_FMT(type_name));
Dqn_CppIfOrElseIfBlock(cpp, "string == field.name") {
Dqn_CppLine(cpp, "result.success = true;");
Dqn_CppLine(cpp, "result.value = (%.*s)index;", DQN_STR_FMT(type_name));
}
}
}
Dqn_CppLine(cpp, "return result;");
}
}
}
} }
} }

View File

@ -43,6 +43,7 @@ enum Dqn_CGenTableType
Dqn_CGenTableType_CodeGenBuiltinTypes, Dqn_CGenTableType_CodeGenBuiltinTypes,
Dqn_CGenTableType_CodeGenStruct, Dqn_CGenTableType_CodeGenStruct,
Dqn_CGenTableType_CodeGenEnum, Dqn_CGenTableType_CodeGenEnum,
Dqn_CGenTableType_Count,
}; };
enum Dqn_CGenTableRowTagType enum Dqn_CGenTableRowTagType
@ -123,6 +124,7 @@ struct Dqn_CGen
MD_Map table_map; MD_Map table_map;
Dqn_CGenTable *first_table; Dqn_CGenTable *first_table;
Dqn_CGenTable *last_table; Dqn_CGenTable *last_table;
Dqn_usize table_counts[Dqn_CGenTableType_Count];
}; };
struct Dqn_CGenMapNodeToEnum struct Dqn_CGenMapNodeToEnum
@ -133,6 +135,7 @@ struct Dqn_CGenMapNodeToEnum
struct Dqn_CGenLookupTableIterator struct Dqn_CGenLookupTableIterator
{ {
Dqn_CGenTable *cgen_table;
Dqn_CGenTableRow *cgen_table_row; Dqn_CGenTableRow *cgen_table_row;
Dqn_CGenTableColumn cgen_table_column[Dqn_CGenTableHeaderType_Count]; Dqn_CGenTableColumn cgen_table_column[Dqn_CGenTableHeaderType_Count];
Dqn_CGenTable *table; Dqn_CGenTable *table;

View File

@ -561,7 +561,7 @@ template <typename T> T *Dqn_VArray_InsertArray(Dqn_VArray<T> *array, Dqn_usize
T *result = nullptr; T *result = nullptr;
if (!Dqn_VArray_IsValid(array)) if (!Dqn_VArray_IsValid(array))
return result; return result;
if (Dqn_VArray_Reserve(array, count)) if (Dqn_VArray_Reserve(array, array->size + count))
result = Dqn_CArray_InsertArray(array->data, &array->size, array->max, index, items, count); result = Dqn_CArray_InsertArray(array->data, &array->size, array->max, index, items, count);
return result; return result;
} }

View File

@ -523,8 +523,7 @@ DQN_API uint32_t Dqn_Safe_SubU32(uint32_t a, uint32_t b)
return result; return result;
} }
// NOTE: Dqn_Safe_SaturateCastUSizeToI* // NOTE: Dqn_Safe_SaturateCastUSizeToI* ////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// INT*_MAX literals will be promoted to the type of uintmax_t as uintmax_t is // INT*_MAX literals will be promoted to the type of uintmax_t as uintmax_t is
// the highest possible rank (unsigned > signed). // the highest possible rank (unsigned > signed).
DQN_API int Dqn_Safe_SaturateCastUSizeToInt(Dqn_usize val) DQN_API int Dqn_Safe_SaturateCastUSizeToInt(Dqn_usize val)
@ -557,8 +556,7 @@ DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64(Dqn_usize val)
return result; return result;
} }
// NOTE: Dqn_Safe_SaturateCastUSizeToU* // NOTE: Dqn_Safe_SaturateCastUSizeToU* ////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// Both operands are unsigned and the lowest rank operand will be promoted to // Both operands are unsigned and the lowest rank operand will be promoted to
// match the highest rank operand. // match the highest rank operand.
DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8(Dqn_usize val) DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8(Dqn_usize val)
@ -624,8 +622,7 @@ DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32(uint64_t val)
return result; return result;
} }
// NOTE: Dqn_Safe_SaturateCastISizeToI* // NOTE: Dqn_Safe_SaturateCastISizeToI* ////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// Both operands are signed so the lowest rank operand will be promoted to // Both operands are signed so the lowest rank operand will be promoted to
// match the highest rank operand. // match the highest rank operand.
DQN_API int Dqn_Safe_SaturateCastISizeToInt(Dqn_isize val) DQN_API int Dqn_Safe_SaturateCastISizeToInt(Dqn_isize val)
@ -663,8 +660,7 @@ DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64(Dqn_isize val)
return result; return result;
} }
// NOTE: Dqn_Safe_SaturateCastISizeToU* // NOTE: Dqn_Safe_SaturateCastISizeToU* ////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// If the value is a negative integer, we clamp to 0. Otherwise, we know that // If the value is a negative integer, we clamp to 0. Otherwise, we know that
// the value is >=0, we can upcast safely to bounds check against the maximum // the value is >=0, we can upcast safely to bounds check against the maximum
// allowed value. // allowed value.
@ -728,8 +724,7 @@ DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64(Dqn_isize val)
return result; return result;
} }
// NOTE: Dqn_Safe_SaturateCastI64To* // NOTE: Dqn_Safe_SaturateCastI64To* ///////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// Both operands are signed so the lowest rank operand will be promoted to // Both operands are signed so the lowest rank operand will be promoted to
// match the highest rank operand. // match the highest rank operand.
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize(int64_t val) DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize(int64_t val)
@ -760,8 +755,79 @@ DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32(int64_t val)
return result; return result;
} }
// NOTE: Dqn_Safe_SaturateCastIntTo* DQN_API unsigned int Dqn_Safe_SaturateCastI64ToUInt(int64_t val)
// ----------------------------------------------------------------------------- {
unsigned int result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT_MAX))
result = DQN_CAST(unsigned int) val;
else
result = UINT_MAX;
}
return result;
}
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToUSize(int64_t val)
{
Dqn_usize result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= DQN_USIZE_MAX))
result = DQN_CAST(Dqn_usize) val;
else
result = DQN_USIZE_MAX;
}
return result;
}
DQN_API uint8_t Dqn_Safe_SaturateCastI64ToU8(int64_t val)
{
uint8_t result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT8_MAX))
result = DQN_CAST(uint8_t) val;
else
result = UINT8_MAX;
}
return result;
}
DQN_API uint16_t Dqn_Safe_SaturateCastI64ToU16(int64_t val)
{
uint16_t result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT16_MAX))
result = DQN_CAST(uint16_t) val;
else
result = UINT16_MAX;
}
return result;
}
DQN_API uint32_t Dqn_Safe_SaturateCastI64ToU32(int64_t val)
{
uint32_t result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT32_MAX))
result = DQN_CAST(uint32_t) val;
else
result = UINT32_MAX;
}
return result;
}
DQN_API uint64_t Dqn_Safe_SaturateCastI64ToU64(int64_t val)
{
uint64_t result = 0;
if (DQN_CHECK(val >= DQN_CAST(int64_t) 0)) {
if (DQN_CHECK(DQN_CAST(uintmax_t) val <= UINT64_MAX))
result = DQN_CAST(uint64_t) val;
else
result = UINT64_MAX;
}
return result;
}
// NOTE: Dqn_Safe_SaturateCastIntTo* ///////////////////////////////////////////////////////////////
DQN_API int8_t Dqn_Safe_SaturateCastIntToI8(int val) DQN_API int8_t Dqn_Safe_SaturateCastIntToI8(int val)
{ {
DQN_CHECK(val >= INT8_MIN && val <= INT8_MAX); DQN_CHECK(val >= INT8_MIN && val <= INT8_MAX);
@ -1263,84 +1329,110 @@ DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit()
Dqn_JobQueueSPMC result = {}; Dqn_JobQueueSPMC result = {};
result.thread_wait_for_job_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/); result.thread_wait_for_job_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/);
result.wait_for_completion_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/); result.wait_for_completion_semaphore = Dqn_OS_SemaphoreInit(0 /*initial_count*/);
result.complete_queue_write_semaphore = Dqn_OS_SemaphoreInit(DQN_ARRAY_UCOUNT(result.complete_queue));
result.mutex = Dqn_OS_MutexInit(); result.mutex = Dqn_OS_MutexInit();
return result; return result;
} }
DQN_API bool Dqn_OS_JobQueueSPMCAddArray(Dqn_JobQueueSPMC *job_queue, Dqn_Job *jobs, uint32_t count) DQN_API bool Dqn_OS_JobQueueSPMCAddArray(Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, uint32_t count)
{ {
if (!job_queue) if (!queue)
return false; return false;
uint32_t const pot_mask = DQN_ARRAY_UCOUNT(job_queue->jobs) - 1; uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1;
uint32_t read_index = job_queue->read_index; uint32_t read_index = queue->read_index;
uint32_t write_index = job_queue->write_index; uint32_t write_index = queue->write_index;
uint32_t size = write_index - read_index; uint32_t size = write_index - read_index;
if ((size + count) > DQN_ARRAY_UCOUNT(job_queue->jobs)) if ((size + count) > DQN_ARRAY_UCOUNT(queue->jobs))
return false; return false;
for (size_t offset = 0; offset < count; offset++) { for (size_t offset = 0; offset < count; offset++) {
uint32_t wrapped_write_index = (write_index + offset) & pot_mask; uint32_t wrapped_write_index = (write_index + offset) & pot_mask;
job_queue->jobs[wrapped_write_index] = jobs[offset]; queue->jobs[wrapped_write_index] = jobs[offset];
} }
Dqn_OS_MutexLock(&job_queue->mutex); Dqn_OS_MutexLock(&queue->mutex);
job_queue->write_index += count; queue->write_index += count;
Dqn_OS_SemaphoreIncrement(&job_queue->thread_wait_for_job_semaphore, count); Dqn_OS_SemaphoreIncrement(&queue->thread_wait_for_job_semaphore, count);
Dqn_OS_MutexUnlock(&job_queue->mutex); Dqn_OS_MutexUnlock(&queue->mutex);
return true; return true;
} }
DQN_API bool Dqn_OS_JobQueueSPMCAdd(Dqn_JobQueueSPMC *job_queue, Dqn_Job job) DQN_API bool Dqn_OS_JobQueueSPMCAdd(Dqn_JobQueueSPMC *queue, Dqn_Job job)
{ {
bool result = Dqn_OS_JobQueueSPMCAddArray(job_queue, &job, 1); bool result = Dqn_OS_JobQueueSPMCAddArray(queue, &job, 1);
return result; return result;
} }
DQN_API int32_t Dqn_OS_JobQueueSPMCThread(Dqn_OSThread *thread) DQN_API int32_t Dqn_OS_JobQueueSPMCThread(Dqn_OSThread *thread)
{ {
Dqn_JobQueueSPMC *job_queue = DQN_CAST(Dqn_JobQueueSPMC *) thread->user_context; Dqn_JobQueueSPMC *queue = DQN_CAST(Dqn_JobQueueSPMC *) thread->user_context;
uint32_t const pot_mask = DQN_ARRAY_UCOUNT(job_queue->jobs) - 1; uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1;
static_assert(DQN_ARRAY_UCOUNT(queue->jobs) == DQN_ARRAY_UCOUNT(queue->complete_queue), "PoT mask is used to mask access to both arrays");
for (;;) { for (;;) {
Dqn_OS_SemaphoreWait(&job_queue->thread_wait_for_job_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); Dqn_OS_SemaphoreWait(&queue->thread_wait_for_job_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
if (job_queue->quit) if (queue->quit)
break; break;
DQN_ASSERT(job_queue->read_index != job_queue->write_index); DQN_ASSERT(queue->read_index != queue->write_index);
Dqn_OS_MutexLock(&job_queue->mutex); Dqn_OS_MutexLock(&queue->mutex);
uint32_t wrapped_read_index = job_queue->read_index & pot_mask; uint32_t wrapped_read_index = queue->read_index & pot_mask;
Dqn_Job job = job_queue->jobs[wrapped_read_index]; Dqn_Job job = queue->jobs[wrapped_read_index];
job_queue->read_index += 1; queue->read_index += 1;
Dqn_OS_MutexUnlock(&job_queue->mutex); Dqn_OS_MutexUnlock(&queue->mutex);
job.func(job.user_context); job.func(job.user_context);
Dqn_Arena_Deinit(job.arena); Dqn_Arena_Deinit(job.arena);
Dqn_OS_MutexLock(&job_queue->mutex); if (job.add_to_completion_queue) {
job_queue->complete_index += 1; Dqn_OS_SemaphoreWait(&queue->complete_queue_write_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
if (job_queue->complete_index == job_queue->write_index && job_queue->threads_waiting_for_completion) { Dqn_OS_MutexLock(&queue->mutex);
Dqn_OS_SemaphoreIncrement(&job_queue->wait_for_completion_semaphore, queue->complete_queue[(queue->complete_write_index++ & pot_mask)] = job;
job_queue->threads_waiting_for_completion); Dqn_OS_MutexUnlock(&queue->mutex);
job_queue->threads_waiting_for_completion = 0; Dqn_OS_SemaphoreIncrement(&queue->complete_queue_write_semaphore, 1);
}
Dqn_OS_MutexUnlock(&job_queue->mutex);
} }
return job_queue->quit_exit_code; Dqn_OS_MutexLock(&queue->mutex);
queue->finish_index += 1;
if (queue->finish_index == queue->write_index && queue->threads_waiting_for_completion) {
Dqn_OS_SemaphoreIncrement(&queue->wait_for_completion_semaphore,
queue->threads_waiting_for_completion);
queue->threads_waiting_for_completion = 0;
}
Dqn_OS_MutexUnlock(&queue->mutex);
} }
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion(Dqn_JobQueueSPMC *job_queue) return queue->quit_exit_code;
}
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion(Dqn_JobQueueSPMC *queue)
{ {
Dqn_OS_MutexLock(&job_queue->mutex); Dqn_OS_MutexLock(&queue->mutex);
if (job_queue->read_index == job_queue->write_index) { if (queue->read_index == queue->write_index) {
Dqn_OS_MutexUnlock(&job_queue->mutex); Dqn_OS_MutexUnlock(&queue->mutex);
return; return;
} }
job_queue->threads_waiting_for_completion++; queue->threads_waiting_for_completion++;
Dqn_OS_MutexUnlock(&job_queue->mutex); Dqn_OS_MutexUnlock(&queue->mutex);
Dqn_OS_SemaphoreWait(&job_queue->wait_for_completion_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT); Dqn_OS_SemaphoreWait(&queue->wait_for_completion_semaphore, DQN_OS_SEMAPHORE_INFINITE_TIMEOUT);
}
DQN_API Dqn_usize Dqn_OS_JobQueueSPMCGetFinishedJobs(Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, Dqn_usize jobs_size)
{
Dqn_usize result = 0;
if (!queue || !jobs || jobs_size <= 0)
return result;
uint32_t const pot_mask = DQN_ARRAY_UCOUNT(queue->jobs) - 1;
Dqn_OS_MutexLock(&queue->mutex);
while (queue->complete_read_index < queue->complete_write_index && result < jobs_size) {
jobs[result++] = queue->complete_queue[(queue->complete_read_index++ & pot_mask)];
}
Dqn_OS_MutexUnlock(&queue->mutex);
return result;
} }

View File

@ -202,8 +202,10 @@ struct Dqn_Profiler
typedef void (Dqn_JobQueueFunc)(void *user_context); typedef void (Dqn_JobQueueFunc)(void *user_context);
struct Dqn_Job struct Dqn_Job
{ {
bool add_to_completion_queue;
Dqn_Arena *arena; Dqn_Arena *arena;
Dqn_JobQueueFunc *func; Dqn_JobQueueFunc *func;
uint32_t user_tag;
void *user_context; void *user_context;
}; };
@ -214,12 +216,17 @@ struct Dqn_JobQueueSPMC
Dqn_OSSemaphore wait_for_completion_semaphore; Dqn_OSSemaphore wait_for_completion_semaphore;
uint32_t threads_waiting_for_completion; uint32_t threads_waiting_for_completion;
Dqn_Job jobs[32]; Dqn_Job jobs[64];
Dqn_b32 quit; Dqn_b32 quit;
uint32_t quit_exit_code; uint32_t quit_exit_code;
uint32_t volatile read_index; uint32_t volatile read_index;
uint32_t volatile complete_index; uint32_t volatile finish_index;
uint32_t volatile write_index; uint32_t volatile write_index;
Dqn_OSSemaphore complete_queue_write_semaphore;
Dqn_Job complete_queue[64];
uint32_t volatile complete_read_index;
uint32_t volatile complete_write_index;
}; };
// NOTE: [$DLIB] Dqn_Library /////////////////////////////////////////////////////////////////////// // NOTE: [$DLIB] Dqn_Library ///////////////////////////////////////////////////////////////////////
@ -408,6 +415,13 @@ DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8 (int64_t va
DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16 (int64_t val); DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16 (int64_t val);
DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32 (int64_t val); DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32 (int64_t val);
DQN_API unsigned int Dqn_Safe_SaturateCastI64ToUInt (int64_t val);
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToUSize (int64_t val);
DQN_API uint8_t Dqn_Safe_SaturateCastI64ToU8 (int64_t val);
DQN_API uint16_t Dqn_Safe_SaturateCastI64ToU16 (int64_t val);
DQN_API uint32_t Dqn_Safe_SaturateCastI64ToU32 (int64_t val);
DQN_API uint64_t Dqn_Safe_SaturateCastI64ToU64 (int64_t val);
DQN_API int8_t Dqn_Safe_SaturateCastIntToI8 (int val); DQN_API int8_t Dqn_Safe_SaturateCastIntToI8 (int val);
DQN_API int16_t Dqn_Safe_SaturateCastIntToI16 (int val); DQN_API int16_t Dqn_Safe_SaturateCastIntToI16 (int val);
DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8 (int val); DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8 (int val);
@ -433,10 +447,11 @@ DQN_API void Dqn_Profiler_Dump (uint64_t t
// NOTE: [$JOBQ] Dqn_JobQueue /////////////////////////////////////////////////////////////////////// // NOTE: [$JOBQ] Dqn_JobQueue ///////////////////////////////////////////////////////////////////////
DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit (); DQN_API Dqn_JobQueueSPMC Dqn_OS_JobQueueSPMCInit ();
DQN_API bool Dqn_OS_JobQueueSPMCAddArray (Dqn_JobQueueSPMC *job_queue, Dqn_Job *jobs, uint32_t count); DQN_API bool Dqn_OS_JobQueueSPMCAddArray (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, uint32_t count);
DQN_API bool Dqn_OS_JobQueueSPMCAdd (Dqn_JobQueueSPMC *job_queue, Dqn_Job job); DQN_API bool Dqn_OS_JobQueueSPMCAdd (Dqn_JobQueueSPMC *queue, Dqn_Job job);
DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion (Dqn_JobQueueSPMC *job_queue); DQN_API void Dqn_OS_JobQueueSPMCWaitForCompletion (Dqn_JobQueueSPMC *queue);
DQN_API int32_t Dqn_OS_JobQueueSPMCThread (Dqn_OSThread *thread); DQN_API int32_t Dqn_OS_JobQueueSPMCThread (Dqn_OSThread *thread);
DQN_API Dqn_usize Dqn_OS_JobQueueSPMCGetFinishedJobs (Dqn_JobQueueSPMC *queue, Dqn_Job *jobs, Dqn_usize jobs_size);
// NOTE: Dqn_Library /////////////////////////////////////////////////////////////////////////////// // NOTE: Dqn_Library ///////////////////////////////////////////////////////////////////////////////
DQN_API Dqn_Library * Dqn_Library_Init (Dqn_LibraryOnInit on_init); DQN_API Dqn_Library * Dqn_Library_Init (Dqn_LibraryOnInit on_init);

View File

@ -285,7 +285,6 @@ DQN_API bool Dqn_OS_SecureRNGBytes (void *buffer, uint
DQN_API Dqn_Str8 Dqn_OS_EXEPath (Dqn_Arena *arena); DQN_API Dqn_Str8 Dqn_OS_EXEPath (Dqn_Arena *arena);
DQN_API Dqn_Str8 Dqn_OS_EXEDir (Dqn_Arena *arena); DQN_API Dqn_Str8 Dqn_OS_EXEDir (Dqn_Arena *arena);
DQN_API void Dqn_OS_SleepMs (Dqn_uint milliseconds); DQN_API void Dqn_OS_SleepMs (Dqn_uint milliseconds);
// NOTE: Counters ////////////////////////////////////////////////////////////////////////////////// // NOTE: Counters //////////////////////////////////////////////////////////////////////////////////
DQN_API uint64_t Dqn_OS_PerfCounterNow (); DQN_API uint64_t Dqn_OS_PerfCounterNow ();
DQN_API uint64_t Dqn_OS_PerfCounterFrequency(); DQN_API uint64_t Dqn_OS_PerfCounterFrequency();
@ -345,7 +344,7 @@ DQN_API Dqn_Str8 Dqn_OS_PathConvertF (Dqn_Arena *arena
#define Dqn_OS_PathBuild(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, Dqn_OSPathSeparatorString) #define Dqn_OS_PathBuild(allocator, fs_path) Dqn_OS_PathBuildWithSeparator(allocator, fs_path, Dqn_OSPathSeparatorString)
// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// // NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
DQN_API void Dqn_OS_Exit (uint32_t exit_code); DQN_API void Dqn_OS_Exit (int32_t exit_code);
DQN_API Dqn_OSExecResult Dqn_OS_ExecWait (Dqn_OSExecAsyncHandle handle); DQN_API Dqn_OSExecResult Dqn_OS_ExecWait (Dqn_OSExecAsyncHandle handle);
DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync (Dqn_Slice<Dqn_Str8> cmd_line, Dqn_Str8 working_dir); DQN_API Dqn_OSExecAsyncHandle Dqn_OS_ExecAsync (Dqn_Slice<Dqn_Str8> cmd_line, Dqn_Str8 working_dir);
DQN_API Dqn_OSExecResult Dqn_OS_Exec (Dqn_Slice<Dqn_Str8> cmd_line, Dqn_Str8 working_dir); DQN_API Dqn_OSExecResult Dqn_OS_Exec (Dqn_Slice<Dqn_Str8> cmd_line, Dqn_Str8 working_dir);

View File

@ -526,9 +526,9 @@ DQN_API void Dqn_OS_FileClose(Dqn_OSFile *file)
#endif // !defined(DQN_NO_OS_FILE_API) #endif // !defined(DQN_NO_OS_FILE_API)
// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// // NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
DQN_API void Dqn_OS_Exit(uint32_t exit_code) DQN_API void Dqn_OS_Exit(int32_t exit_code)
{ {
exit(exit_code); exit(DQN_CAST(int)exit_code);
} }
DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle) DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle)

View File

@ -545,9 +545,9 @@ DQN_API void Dqn_OS_FileClose(Dqn_OSFile *file)
#endif // !defined(DQN_NO_OS_FILE_API) #endif // !defined(DQN_NO_OS_FILE_API)
// NOTE: [$EXEC] Dqn_OSExec //////////////////////////////////////////////////////////////////////// // NOTE: [$EXEC] Dqn_OSExec ////////////////////////////////////////////////////////////////////////
DQN_API void Dqn_OS_Exit(uint32_t exit_code) DQN_API void Dqn_OS_Exit(int32_t exit_code)
{ {
ExitProcess(exit_code); ExitProcess(DQN_CAST(UINT)exit_code);
} }
DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle) DQN_API Dqn_OSExecResult Dqn_OS_ExecWait(Dqn_OSExecAsyncHandle handle)

View File

@ -119,6 +119,12 @@ DQN_API Dqn_Str8 Dqn_Str8_Advance(Dqn_Str8 string, Dqn_usize amount)
return result; return result;
} }
DQN_API Dqn_Str8 Dqn_Str8_NextLine(Dqn_Str8 string)
{
Dqn_Str8 result = Dqn_Str8_BinarySplit(string, DQN_STR8("\n")).rhs;
return result;
}
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size) DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size)
{ {
Dqn_Str8BinarySplitResult result = {}; Dqn_Str8BinarySplitResult result = {};
@ -839,6 +845,22 @@ DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8Builder_BuildSlice(Dqn_Str8Builder const *bu
return result; return result;
} }
DQN_API void Dqn_Str8Builder_PrintF(Dqn_Str8Builder const *builder)
{
for (Dqn_Str8Link *link = builder ? builder->head : nullptr; link; link = link->next)
Dqn_Print(link->string);
}
DQN_API void Dqn_Str8Builder_PrintLnF(Dqn_Str8Builder const *builder)
{
for (Dqn_Str8Link *link = builder ? builder->head : nullptr; link; link = link->next) {
if (link->next) {
Dqn_Print(link->string);
} else {
Dqn_Print_Ln(link->string);
}
}
}
// NOTE: [$CHAR] Dqn_Char ////////////////////////////////////////////////////////////////////////// // NOTE: [$CHAR] Dqn_Char //////////////////////////////////////////////////////////////////////////
DQN_API bool Dqn_Char_IsAlphabet(char ch) DQN_API bool Dqn_Char_IsAlphabet(char ch)

View File

@ -152,6 +152,7 @@ DQN_API Dqn_Str8 Dqn_Str8_Copy
DQN_API Dqn_Str8 Dqn_Str8_Slice (Dqn_Str8 string, Dqn_usize offset, Dqn_usize size); DQN_API Dqn_Str8 Dqn_Str8_Slice (Dqn_Str8 string, Dqn_usize offset, Dqn_usize size);
DQN_API Dqn_Str8 Dqn_Str8_Advance (Dqn_Str8 string, Dqn_usize amount); DQN_API Dqn_Str8 Dqn_Str8_Advance (Dqn_Str8 string, Dqn_usize amount);
DQN_API Dqn_Str8 Dqn_Str8_NextLine (Dqn_Str8 string);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size); DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitArray (Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplit (Dqn_Str8 string, Dqn_Str8 find); DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplit (Dqn_Str8 string, Dqn_Str8 find);
DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitReverseArray(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size); DQN_API Dqn_Str8BinarySplitResult Dqn_Str8_BinarySplitReverseArray(Dqn_Str8 string, Dqn_Str8 const *find, Dqn_usize find_size);
@ -206,6 +207,7 @@ DQN_API bool Dqn_Str8Builder_Ap
DQN_API Dqn_Str8 Dqn_Str8Builder_Build (Dqn_Str8Builder const *builder, Dqn_Arena *arena); DQN_API Dqn_Str8 Dqn_Str8Builder_Build (Dqn_Str8Builder const *builder, Dqn_Arena *arena);
DQN_API Dqn_Str8 Dqn_Str8Builder_BuildCRT (Dqn_Str8Builder const *builder); DQN_API Dqn_Str8 Dqn_Str8Builder_BuildCRT (Dqn_Str8Builder const *builder);
DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8Builder_BuildSlice (Dqn_Str8Builder const *builder, Dqn_Arena *arena); DQN_API Dqn_Slice<Dqn_Str8> Dqn_Str8Builder_BuildSlice (Dqn_Str8Builder const *builder, Dqn_Arena *arena);
DQN_API void Dqn_Str8Builder_PrintF (Dqn_Str8Builder const *builder);
// NOTE: [$FSTR] Dqn_FStr8 ////////////////////////////////////////////////////////////////////// // NOTE: [$FSTR] Dqn_FStr8 //////////////////////////////////////////////////////////////////////
#if !defined(DQN_NO_FSTR8) #if !defined(DQN_NO_FSTR8)

View File

@ -39,6 +39,7 @@ struct Dqn_TypeInfo
{ {
Dqn_Str8 name; Dqn_Str8 name;
Dqn_TypeKind kind; Dqn_TypeKind kind;
Dqn_usize size_of;
Dqn_TypeField const *fields; Dqn_TypeField const *fields;
uint16_t fields_count; uint16_t fields_count;
}; };