Do massive overhaul and simplification of DN

This commit is contained in:
doylet 2026-03-07 20:40:16 +11:00
parent ad019541a4
commit 19df3b75ce
53 changed files with 3880 additions and 5101 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,15 @@
#if !defined(DN_BASE_ASSERT_H) #if !defined(DN_BASE_ASSERT_H)
#define DN_BASE_ASSERT_H #define DN_BASE_ASSERT_H
#define DN_HardAssertF(expr, fmt, ...) \ #define DN_HardAssertF(expr, fmt, ...) \
do { \ do { \
if (!(expr)) { \ if (!(expr)) { \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LOG_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ DN_LogErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \ DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \ ##__VA_ARGS__); \
DN_DebugBreak; \ DN_DebugBreak; \
} \ } \
} while (0) } while (0)
#define DN_HardAssert(expr) DN_HardAssertF(expr, "") #define DN_HardAssert(expr) DN_HardAssertF(expr, "")
@ -33,7 +33,7 @@
do { \ do { \
if (!(expr)) { \ if (!(expr)) { \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \ DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \ ##__VA_ARGS__); \
DN_DebugBreak; \ DN_DebugBreak; \
@ -46,7 +46,7 @@
if (!(expr) && once) { \ if (!(expr) && once) { \
once = false; \ once = false; \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \ DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \ DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \ DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \ ##__VA_ARGS__); \
DN_DebugBreak; \ DN_DebugBreak; \
@ -68,10 +68,10 @@
#define DN_Check(expr) DN_CheckF(expr, "") #define DN_Check(expr) DN_CheckF(expr, "")
#if defined(DN_NO_CHECK_BREAK) #if defined(DN_NO_CHECK_BREAK)
#define DN_CheckF(expr, fmt, ...) \ #define DN_CheckF(expr, fmt, ...) \
((expr) ? true : (DN_LOG_WarningF(fmt, ##__VA_ARGS__), false)) ((expr) ? true : (DN_LogWarningF(fmt, ##__VA_ARGS__), false))
#else #else
#define DN_CheckF(expr, fmt, ...) \ #define DN_CheckF(expr, fmt, ...) \
((expr) ? true : (DN_LOG_ErrorF(fmt, ##__VA_ARGS__), DN_StackTracePrint(128 /*limit*/), DN_DebugBreak, false)) ((expr) ? true : (DN_LogErrorF(fmt, ##__VA_ARGS__), DN_StackTracePrint(128 /*limit*/), DN_DebugBreak, false))
#endif #endif
#endif #endif

View File

@ -1,160 +0,0 @@
#if !defined(DN_BASE_COMPILER_H)
#define DN_BASE_COMPILER_H
// NOTE: Compiler identification
// Warning! Order is important here, clang-cl on Windows defines _MSC_VER
#if defined(_MSC_VER)
#if defined(__clang__)
#define DN_COMPILER_CLANG_CL
#define DN_COMPILER_CLANG
#else
#define DN_COMPILER_MSVC
#endif
#elif defined(__clang__)
#define DN_COMPILER_CLANG
#elif defined(__GNUC__)
#define DN_COMPILER_GCC
#endif
// NOTE: __has_feature
// MSVC for example does not support the feature detection macro for instance so we compile it out
#if defined(__has_feature)
#define DN_HAS_FEATURE(expr) __has_feature(expr)
#else
#define DN_HAS_FEATURE(expr) 0
#endif
// NOTE: __has_builtin
// MSVC for example does not support the feature detection macro for instance so we compile it out
#if defined(__has_builtin)
#define DN_HAS_BUILTIN(expr) __has_builtin(expr)
#else
#define DN_HAS_BUILTIN(expr) 0
#endif
// NOTE: Warning suppression macros
#if defined(DN_COMPILER_MSVC)
#define DN_MSVC_WARNING_PUSH __pragma(warning(push))
#define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__))
#define DN_MSVC_WARNING_POP __pragma(warning(pop))
#else
#define DN_MSVC_WARNING_PUSH
#define DN_MSVC_WARNING_DISABLE(...)
#define DN_MSVC_WARNING_POP
#endif
#if defined(DN_COMPILER_CLANG) || defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG_CL)
#define DN_GCC_WARNING_PUSH _Pragma("GCC diagnostic push")
#define DN_GCC_WARNING_DISABLE_HELPER_0(x) #x
#define DN_GCC_WARNING_DISABLE_HELPER_1(y) DN_GCC_WARNING_DISABLE_HELPER_0(GCC diagnostic ignored #y)
#define DN_GCC_WARNING_DISABLE(warning) _Pragma(DN_GCC_WARNING_DISABLE_HELPER_1(warning))
#define DN_GCC_WARNING_POP _Pragma("GCC diagnostic pop")
#else
#define DN_GCC_WARNING_PUSH
#define DN_GCC_WARNING_DISABLE(...)
#define DN_GCC_WARNING_POP
#endif
// NOTE: Host OS identification
#if defined(_WIN32)
#define DN_OS_WIN32
#elif defined(__gnu_linux__) || defined(__linux__)
#define DN_OS_UNIX
#endif
// NOTE: Platform identification
#if !defined(DN_PLATFORM_EMSCRIPTEN) && \
!defined(DN_PLATFORM_POSIX) && \
!defined(DN_PLATFORM_WIN32)
#if defined(__aarch64__) || defined(_M_ARM64)
#define DN_PLATFORM_ARM64
#elif defined(__EMSCRIPTEN__)
#define DN_PLATFORM_EMSCRIPTEN
#elif defined(DN_OS_WIN32)
#define DN_PLATFORM_WIN32
#else
#define DN_PLATFORM_POSIX
#endif
#endif
// NOTE: Windows crap
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#if defined(_CRT_SECURE_NO_WARNINGS)
#define DN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED
#else
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
// NOTE: Force Inline
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#define DN_FORCE_INLINE __forceinline
#else
#define DN_FORCE_INLINE inline __attribute__((always_inline))
#endif
// NOTE: Function/Variable Annotations
#if defined(DN_STATIC_API)
#define DN_API static
#else
#define DN_API
#endif
// NOTE: C/CPP Literals
// Declare struct literals that work in both C and C++ because the syntax is different between
// languages.
#if 0
struct Foo { int a; }
struct Foo foo = DN_LITERAL(Foo){32}; // Works on both C and C++
#endif
#if defined(__cplusplus)
#define DN_Literal(T) T
#else
#define DN_Literal(T) (T)
#endif
// NOTE: Thread Locals
#if defined(__cplusplus)
#define DN_THREAD_LOCAL thread_local
#else
#define DN_THREAD_LOCAL _Thread_local
#endif
// NOTE: C variadic argument annotations
// TODO: Other compilers
#if defined(DN_COMPILER_MSVC)
#define DN_FMT_ATTRIB _Printf_format_string_
#else
#define DN_FMT_ATTRIB
#endif
// NOTE: Type Cast
#define DN_Cast(val) (val)
// NOTE: Zero initialisation macro
#if defined(__cplusplus)
#define DN_ZeroInit {}
#else
#define DN_ZeroInit {0}
#endif
// NOTE: Address sanitizer
#if !defined(DN_ASAN_POISON)
#define DN_ASAN_POISON 0
#endif
#if !defined(DN_ASAN_VET_POISON)
#define DN_ASAN_VET_POISON 0
#endif
#define DN_ASAN_POISON_ALIGNMENT 8
#if !defined(DN_ASAN_POISON_GUARD_SIZE)
#define DN_ASAN_POISON_GUARD_SIZE 128
#endif
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#include <sanitizer/asan_interface.h>
#endif
#endif // !defined(DN_BASE_COMPILER_H)

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,70 @@
#if !defined(DN_CONTAINERS_H) #if !defined(DN_CONTAINERS_H)
#define DN_CONTAINERS_H #define DN_CONTAINERS_H
// Containers that are imlpemented using primarily macros for operating on data structures that are
// embedded into a C style struct or from a set of defined variables from the available scope. Keep
// it stupid simple, structs and functions. Minimal amount of container types with flexible
// construction leads to less duplicated container code and less template meta-programming.
//
// PArray => Pointer (to) Array
// LArray => Literal Array
// Define a C array and size. (P) array macros take a pointer to the aray, its size and its max
// capacity. The (L) array macros take the literal array and derives the max capacity
// automatically using DN_ArrayCountU(l_array).
//
// MyStruct buffer[TB_ASType_Count] = {};
// DN_USize size = 0;
// MyStruct *item_0 = DN_PArrayMake(buffer, &size, DN_ArrayCountU(buffer), DN_ZMem_No);
// MyStruct *item_1 = DN_LArrayMake(buffer, &size, DN_ZMem_No);
//
// IArray => Intrusive Array
// Define a struct with the members `data`, `size` and `max`:
//
// struct MyArray {
// MyStruct *data;
// DN_USize size;
// DN_USize max;
// } my_array = {};
// MyStruct *item = DN_IArrayMake(&my_array, DN_ZMem_No);
//
// ISinglyLL => Intrusive Singly Linked List
// Define a struct with the members `next`:
//
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// } my_link = {};
//
// MyLinkItem *first_item = DN_ISinglyLLDetach(&my_link, MyLinkItem);
//
// DoublyLL => Doubly Linked List
// Define a struct with the members `next` and `prev`. This list has null pointers for head->prev
// and tail->next.
//
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// MyLinkItem *prev;
// } my_link = {};
//
// MyLinkItem first_item = {}, second_item = {};
// DN_DoublyLLAppend(&first_item, &second_item); // first_item -> second_item
//
// SentinelDoublyLL => Sentinel Doubly Linked List
// Uses a sentinel/dummy node as the list head. The sentinel points to itself when empty.
// Define a struct with the members `next` and `prev`:
//
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// MyLinkItem *prev;
// } my_list = {};
//
// DN_SentinelDoublyLLInit(&my_list);
// DN_SentinelDoublyLLAppend(&my_list, &new_item);
// DN_SentinelDoublyLLForEach(it, &my_list) { /* ... */ }
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn.h" #include "../dn.h"
#endif #endif
struct DN_Ring struct DN_Ring
@ -13,7 +75,6 @@ struct DN_Ring
DN_U64 read_pos; DN_U64 read_pos;
}; };
// NOTE: DN_CArray /////////////////////////////////////////////////////////////////////////////////
enum DN_ArrayErase enum DN_ArrayErase
{ {
DN_ArrayErase_Unstable, DN_ArrayErase_Unstable,
@ -45,42 +106,6 @@ template <typename T> struct DN_ArrayFindResult
DN_USize index; // Index to the value if a match is found, 0 otherwise DN_USize index; // Index to the value if a match is found, 0 otherwise
}; };
#if !defined(DN_NO_SARRAY)
// NOTE: DN_SArray /////////////////////////////////////////////////////////////////////////////////
template <typename T> struct DN_SArray
{
T *data; // Pointer to the start of the array items in the block of memory
DN_USize size; // Number of items currently in the array
DN_USize max; // Maximum number of items this array can store
T *begin() { return data; }
T *end () { return data + size; }
T const *begin() const { return data; }
T const *end () const { return data + size; }
};
#endif // !defined(DN_NO_SARRAY)
#if !defined(DN_NO_FARRAY)
// NOTE: DN_FArray /////////////////////////////////////////////////////////////////////////////////
template <typename T, DN_USize N> struct DN_FArray
{
T data[N]; // Pointer to the start of the array items in the block of memory
DN_USize size; // Number of items currently in the array
T *begin() { return data; }
T *end () { return data + size; }
T const *begin() const { return data; }
T const *end () const { return data + size; }
};
template <typename T> using DN_FArray8 = DN_FArray<T, 8>;
template <typename T> using DN_FArray16 = DN_FArray<T, 16>;
template <typename T> using DN_FArray32 = DN_FArray<T, 32>;
template <typename T> using DN_FArray64 = DN_FArray<T, 64>;
#endif // !defined(DN_NO_FARRAY)
#if !defined(DN_NO_DSMAP)
// NOTE: DN_DSMap //////////////////////////////////////////////////////////////////////////////////
enum DN_DSMapKeyType enum DN_DSMapKeyType
{ {
// Key | Key Hash | Map Index // Key | Key Hash | Map Index
@ -136,93 +161,29 @@ template <typename T> struct DN_DSMapResult
DN_DSMapSlot<T> *slot; DN_DSMapSlot<T> *slot;
T *value; T *value;
}; };
#endif // !defined(DN_NO_DSMAP)
#if !defined(DN_NO_LIST) #define DN_ISinglyLLDetach(list) (decltype(list))DN_SinglyLLDetach((void **)&(list), (void **)&(list)->next)
// NOTE: DN_List ///////////////////////////////////////////////////////////////////////////////////
template <typename T> struct DN_ListChunk
{
T *data;
DN_USize size;
DN_USize count;
DN_ListChunk<T> *next;
DN_ListChunk<T> *prev;
};
template <typename T> struct DN_ListIterator #define DN_SentinelDoublyLLInit(list) (list)->next = (list)->prev = (list)
{ #define DN_SentinelDoublyLLIsSentinel(list, item) ((list) == (item))
DN_B32 init; // True if DN_List_Iterate has been called at-least once on this iterator #define DN_SentinelDoublyLLIsEmpty(list) (!(list) || ((list) == (list)->next))
DN_ListChunk<T> *chunk; // The chunk that the iterator is reading from #define DN_SentinelDoublyLLIsInit(list) ((list)->next && (list)->prev)
DN_USize chunk_data_index; // The index in the chunk the iterator is referencing #define DN_SentinelDoublyLLHasItems(list) ((list) && ((list) != (list)->next))
DN_USize index; // The index of the item in the list as if it was flat array #define DN_SentinelDoublyLLForEach(it, list) auto *it = (list)->next; (it) != (list); (it) = (it)->next
T *data; // Pointer to the data the iterator is referencing. Nullptr if invalid.
};
template <typename T> struct DN_List #define DN_SentinelDoublyLLInitArena(list, T, arena) \
{
DN_USize count; // Cumulative count of all items made across all list chunks
DN_USize chunk_size; // When new ListChunk's are required, the minimum 'data' entries to allocate for that node.
DN_ListChunk<T> *head;
DN_ListChunk<T> *tail;
};
#endif // !defined(DN_NO_LIST)
// NOTE: Macros for operating on data structures that are embedded into a C style struct or from a
// set of defined variables from the available scope. Keep it stupid simple, structs and functions.
// Minimal amount of container types with flexible construction leads to less duplicated container
// code and less template meta-programming.
//
// LArray => Literal Array
// Define a C array and size:
//
// ```
// MyStruct buffer[TB_ASType_Count] = {};
// DN_USize size = 0;
// MyStruct *item = DN_LArray_Make(buffer, size, DN_ArrayCountU(buffer), DN_ZMem_No);
// ```
//
// IArray => Intrusive Array
// Define a struct with the members 'data', 'size' and 'max':
//
// ```
// struct MyArray {
// MyStruct *data;
// DN_USize size;
// DN_USize max;
// } my_array = {};
//
// MyStruct *item = DN_IArray_Make(&my_array, MyArray, DN_ZMem_No);
// ```
// ISLList => Intrusive Singly Linked List
// Define a struct with the members 'next':
//
// ```
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// } my_link = {};
//
// MyLinkItem *first_item = DN_ISLList_Detach(&my_link, MyLinkItem);
// ```
#define DN_DLList_Init(list) \
(list)->next = (list)->prev = (list)
#define DN_DLList_IsSentinel(list, item) ((list) == (item))
#define DN_DLList_InitArena(list, T, arena) \
do { \ do { \
(list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \ (list) = DN_ArenaNew(arena, T, DN_ZMem_Yes); \
DN_DLList_Init(list); \ DN_SentinelDoublyLLInit(list); \
} while (0) } while (0)
#define DN_DLList_InitPool(list, T, pool) \ #define DN_SentinelDoublyLLInitPool(list, T, pool) \
do { \ do { \
(list) = DN_PoolNew(pool, T); \ (list) = DN_PoolNew(pool, T); \
DN_DLList_Init(list); \ DN_SentinelDoublyLLInit(list); \
} while (0) } while (0)
#define DN_DLList_Detach(item) \ #define DN_SentinelDoublyLLDetach(item) \
do { \ do { \
if (item) { \ if (item) { \
(item)->prev->next = (item)->next; \ (item)->prev->next = (item)->next; \
@ -232,47 +193,47 @@ template <typename T> struct DN_List
} \ } \
} while (0) } while (0)
#define DN_DLList_Dequeue(list, dest_ptr) \ #define DN_SentinelDoublyLLDequeue(list, dest_ptr) \
if (DN_DLList_HasItems(list)) { \ if (DN_SentinelDoublyLLHasItems(list)) { \
dest_ptr = (list)->next; \ dest_ptr = (list)->next; \
DN_DLList_Detach(dest_ptr); \ DN_SentinelDoublyLLDetach(dest_ptr); \
} }
#define DN_DLList_Append(list, item) \ #define DN_SentinelDoublyLLAppend(list, item) \
do { \ do { \
if (item) { \ if (item) { \
if ((item)->next) \ if ((item)->next) \
DN_DLList_Detach(item); \ DN_SentinelDoublyLLDetach(item); \
(item)->next = (list)->next; \ (item)->next = (list)->next; \
(item)->prev = (list); \ (item)->prev = (list); \
(item)->next->prev = (item); \ (item)->next->prev = (item); \
(item)->prev->next = (item); \ (item)->prev->next = (item); \
} \ } \
} while (0) } while (0)
#define DN_DLList_Prepend(list, item) \ #define DN_SentinelDoublyLLPrepend(list, item) \
do { \ do { \
if (item) { \ if (item) { \
if ((item)->next) \ if ((item)->next) \
DN_DLList_Detach(item); \ DN_SentinelDoublyLLDetach(item); \
(item)->next = (list); \ (item)->next = (list); \
(item)->prev = (list)->prev; \ (item)->prev = (list)->prev; \
(item)->next->prev = (item); \ (item)->next->prev = (item); \
(item)->prev->next = (item); \ (item)->prev->next = (item); \
} \ } \
} while (0) } while (0)
#define DN_DLList_IsEmpty(list) \ // DoublyLL => Non-intrusive Doubly Linked List
(!(list) || ((list) == (list)->next)) // A simple doubly linked list where each node has `next` and `prev` pointers.
// The head is passed as a pointer-to-pointer to allow head updates.
#define DN_DLList_IsInit(list) \ //
((list)->next && (list)->prev) // struct MyLinkItem {
// int data;
#define DN_DLList_HasItems(list) \ // MyLinkItem *next;
((list) && ((list) != (list)->next)) // MyLinkItem *prev;
// } *head = nullptr;
#define DN_DLList_ForEach(it, list) \ // DN_DoublyLLAppend(&head, new_item);
auto *it = (list)->next; (it) != (list); (it) = (it)->next // for (MyLinkItem *it = head; it; it = it->next) { /* ... */ }
#define DN_DoublyLLDetach(head, ptr) \ #define DN_DoublyLLDetach(head, ptr) \
do { \ do { \
@ -317,182 +278,121 @@ template <typename T> struct DN_List
} \ } \
} while (0) } while (0)
#define DN_ISLList_Detach(list) (decltype(list))DN_CSLList_Detach((void **)&(list), (void **)&(list)->next) // NOTE: For C++ we need to cast the void* returned in these functions to the concrete type. In C,
// no cast is needed.
#if defined(__cplusplus)
#define DN_CppDeclType(x) decltype(x)
#else
#define DN_CppDeclType
#endif
#define DN_LArray_ResizeFromPool(c_array, size, max, pool, new_max) DN_CArray2_ResizeFromPool((void **)&(c_array), size, max, sizeof((c_array)[0]), pool, new_max) #define DN_PArrayResizeFromPool(ptr, size, max, pool, new_max) DN_CArrayResizeFromPool((void **)&(ptr), size, max, sizeof((ptr)[0]), pool, new_max)
#define DN_LArray_GrowFromPool(c_array, size, max, pool, new_max) DN_CArray2_GrowFromPool((void **)&(c_array), size, max, sizeof((c_array)[0]), pool, new_max) #define DN_PArrayGrowFromPool(ptr, size, max, pool, new_max) DN_CArrayGrowFromPool((void **)&(ptr), size, max, sizeof((ptr)[0]), pool, new_max)
#define DN_LArray_GrowIfNeededFromPool(c_array, size, max, pool, add_count) DN_CArray2_GrowIfNeededFromPool((void **)(c_array), size, max, sizeof((c_array)[0]), pool, add_count) #define DN_PArrayGrowIfNeededFromPool(ptr, size, max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, max, sizeof((ptr)[0]), pool, add_count)
#define DN_LArray_MakeArray(c_array, size, max, count, z_mem) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), count, z_mem) #define DN_PArrayMakeArray(ptr, size, max, count, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), count, z_mem)
#define DN_LArray_MakeArrayZ(c_array, size, max, count) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), count, DN_ZMem_Yes) #define DN_PArrayMakeArrayZ(ptr, size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), count, DN_ZMem_Yes)
#define DN_LArray_Make(c_array, size, max, z_mem) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), 1, z_mem) #define DN_PArrayMake(ptr, size, max, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), 1, z_mem)
#define DN_LArray_MakeZ(c_array, size, max) (decltype(&(c_array)[0]))DN_CArray2_MakeArray(c_array, size, max, sizeof((c_array)[0]), 1, DN_ZMem_Yes) #define DN_PArrayMakeZ(ptr, size, max) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, size, max, sizeof((ptr)[0]), 1, DN_ZMem_Yes)
#define DN_LArray_AddArray(c_array, size, max, items, count, add) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, add) #define DN_PArrayAddArray(ptr, size, max, items, count, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), items, count, add)
#define DN_LArray_Add(c_array, size, max, item, add) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, add) #define DN_PArrayAdd(ptr, size, max, item, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), &item, 1, add)
#define DN_LArray_AppendArray(c_array, size, max, items, count) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, DN_ArrayAdd_Append) #define DN_PArrayAppendArray(ptr, size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), items, count, DN_ArrayAdd_Append)
#define DN_LArray_Append(c_array, size, max, item) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, DN_ArrayAdd_Append) #define DN_PArrayAppend(ptr, size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Append)
#define DN_LArray_PrependArray(c_array, size, max, items, count) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), items, count, DN_ArrayAdd_Prepend) #define DN_PArrayPrependArray(ptr, size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), items, count, DN_ArrayAdd_Prepend)
#define DN_LArray_Prepend(c_array, size, max, item) (decltype(&(c_array)[0]))DN_CArray2_AddArray(c_array, size, max, sizeof((c_array)[0]), &item, 1, DN_ArrayAdd_Prepend) #define DN_PArrayPrepend(ptr, size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Prepend)
#define DN_LArray_EraseRange(c_array, size, begin_index, count, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), begin_index, count, erase) #define DN_PArrayEraseRange(ptr, size, begin_index, count, erase) DN_CArrayEraseRange(ptr, size, sizeof((ptr)[0]), begin_index, count, erase)
#define DN_LArray_Erase(c_array, size, index, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), index, 1, erase) #define DN_PArrayErase(ptr, size, index, erase) DN_CArrayEraseRange(ptr, size, sizeof((ptr)[0]), index, 1, erase)
#define DN_LArray_InsertArray(c_array, size, max, index, items, count) (decltype(&(c_array)[0]))DN_CArray2_InsertArray(c_array, size, max, sizeof((c_array)[0]), index, items, count) #define DN_PArrayInsertArray(ptr, size, max, index, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, size, max, sizeof((ptr)[0]), index, items, count)
#define DN_LArray_Insert(c_array, size, max, index, item) (decltype(&(c_array)[0]))DN_CArray2_InsertArray(c_array, size, max, sizeof((c_array)[0]), index, &item, 1) #define DN_PArrayInsert(ptr, size, max, index, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, size, max, sizeof((ptr)[0]), index, &item, 1)
#define DN_PArrayPopFront(ptr, size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopFront(ptr, size, sizeof((ptr)[0]), count)
#define DN_PArrayPopBack(ptr, size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopBack(ptr, size, sizeof((ptr)[0]), count)
#define DN_IArray_ResizeFromPool(array, pool, new_max) DN_CArray2_ResizeFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max) #define DN_LArrayResizeFromPool(c_array, size, pool, new_max) DN_PArrayResizeFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max)
#define DN_IArray_GrowFromPool(array, pool, new_max) DN_CArray2_GrowFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max) #define DN_LArrayGrowFromPool(c_array, size, pool, new_max) DN_PArrayGrowFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max)
#define DN_IArray_GrowIfNeededFromPool(array, pool, add_count) DN_CArray2_GrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, add_count) #define DN_LArrayGrowIfNeededFromPool(c_array, size, pool, add_count) DN_PArrayGrowIfNeededFromPool(c_array, size, DN_ArrayCountU(c_array), pool, add_count)
#define DN_IArray_MakeArray(array, count, z_mem) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, z_mem) #define DN_LArrayMakeArray(c_array, size, count, z_mem) DN_PArrayMakeArray(c_array, size, DN_ArrayCountU(c_array), count, z_mem)
#define DN_IArray_MakeArrayZ(array, count) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, DN_ZMem_Yes) #define DN_LArrayMakeArrayZ(c_array, size, count) DN_PArrayMakeArrayZ(c_array, size, DN_ArrayCountU(c_array), count)
#define DN_IArray_Make(array, z_mem) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, z_mem) #define DN_LArrayMake(c_array, size, z_mem) DN_PArrayMake(c_array, size, DN_ArrayCountU(c_array), z_mem)
#define DN_IArray_MakeZ(array) (decltype(&((array)->data)[0]))DN_CArray2_MakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, DN_ZMem_Yes) #define DN_LArrayMakeZ(c_array, size, max) DN_PArrayMakeZ(c_array, size, DN_ArrayCountU(c_array), max)
#define DN_IArray_AddArray(array, items, count, add) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, add) #define DN_LArrayAddArray(c_array, size, items, count, add) DN_PArrayAddArray(c_array, size, DN_ArrayCountU(c_array), items, count, add)
#define DN_IArray_Add(array, item, add) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, add) #define DN_LArrayAdd(c_array, size, item, add) DN_PArrayAdd(c_array, size, DN_ArrayCountU(c_array), item, add)
#define DN_IArray_AppendArray(array, items, count) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Append) #define DN_LArrayAppendArray(c_array, size, items, count) DN_PArrayAppendArray(c_array, size, DN_ArrayCountU(c_array), items, count)
#define DN_IArray_Append(array, item) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Append) #define DN_LArrayAppend(c_array, size, item) DN_PArrayAppend(c_array, size, DN_ArrayCountU(c_array), item)
#define DN_IArray_PrependArray(array, items, count) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Prepend) #define DN_LArrayPrependArray(c_array, size, items, count) DN_PArrayPrependArray(c_array, size, DN_ArrayCountU(c_array), items, count)
#define DN_IArray_Prepend(array, item) (decltype(&((array)->data)[0]))DN_CArray2_AddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend) #define DN_LArrayPrepend(c_array, size, item) DN_PArrayPrepend(c_array, size, DN_ArrayCountU(c_array), item)
#define DN_IArray_EraseRange(array, begin_index, count, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), begin_index, count, erase) #define DN_LArrayEraseRange(c_array, size, begin_index, count, erase) DN_PArrayEraseRange(c_array, size, DN_ArrayCountU(c_array), begin_index, count, erase)
#define DN_IArray_Erase(array, index, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), index, 1, erase) #define DN_LArrayErase(c_array, size, index, erase) DN_PArrayErase(c_array, size, DN_ArrayCountU(c_array), index, erase)
#define DN_IArray_InsertArray(array, index, items, count) (decltype(&((array)->data)[0]))DN_CArray2_InsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, items, count) #define DN_LArrayInsertArray(c_array, size, index, items, count) DN_PArrayInsertArray(c_array, size, DN_ArrayCountU(c_array), index, items, count)
#define DN_IArray_Insert(array, index, item, count) (decltype(&((array)->data)[0]))DN_CArray2_InsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, &item, 1) #define DN_LArrayInsert(c_array, size, index, item) DN_PArrayInsert(c_array, size, DN_ArrayCountU(c_array), index, item)
#define DN_LArrayPopFront(c_array, size, count) DN_PArrayPopFront(c_array, size, DN_ArrayCountU(c_array), count)
#define DN_LArrayPopBack(c_array, size, count) DN_PArrayPopBack(c_array, size, DN_ArrayCountU(c_array), count)
DN_API DN_ArrayEraseResult DN_CArray2_EraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); #define DN_IArrayResizeFromPool(array, pool, new_max) DN_CArrayResizeFromPool((void **)(&(array)->data), &(array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max)
DN_API void *DN_CArray2_MakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem); #define DN_IArrayGrowFromPool(array, pool, new_max) DN_CArrayGrowFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, new_max)
DN_API void *DN_CArray2_AddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add); #define DN_IArrayGrowIfNeededFromPool(array, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool, add_count)
DN_API bool DN_CArray2_Resize (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max); #define DN_IArrayMakeArray(array, count, z_mem) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, z_mem)
DN_API bool DN_CArray2_Grow (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max); #define DN_IArrayMakeArrayZ(array, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), count, DN_ZMem_Yes)
DN_API bool DN_CArray2_GrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool); #define DN_IArrayMake(array, z_mem) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, z_mem)
DN_API void *DN_CSLList_Detach (void **link, void **next); #define DN_IArrayMakeZ(array) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayMakeArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), 1, DN_ZMem_Yes)
#define DN_IArrayAddArray(array, items, count, add) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, add)
#define DN_IArrayAdd(array, item, add) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, add)
#define DN_IArrayAppendArray(array, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Append)
#define DN_IArrayAppend(array, item) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Append)
#define DN_IArrayPrependArray(array, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Prepend)
#define DN_IArrayPrepend(array, item) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayAddArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend)
#define DN_IArrayEraseRange(array, begin_index, count, erase) DN_CArrayEraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), begin_index, count, erase)
#define DN_IArrayErase(array, index, erase) DN_CArrayEraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), index, 1, erase)
#define DN_IArrayInsertArray(array, index, items, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayInsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, items, count)
#define DN_IArrayInsert(array, index, item, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayInsertArray((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), index, &item, 1)
#define DN_IArrayPopFront(array, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayPopFront((array)->data, &(array)->size, sizeof(((array)->data)[0]), count)
#define DN_IArrayPopBack(array, count) (DN_CppDeclType(&((array)->data)[0]))DN_CArrayPopBack((array)->data, &(array)->size, sizeof(((array)->data)[0]), count)
DN_API bool DN_Ring_HasSpace (DN_Ring const *ring, DN_U64 size); #define DN_ISliceAllocArena(T, slice_ptr, count_, zmem, arena) (T *)DN_SliceAllocArena((void **)&((slice_ptr)->data), &((slice_ptr)->count), count_, sizeof(T), alignof(T), zmem, arena)
DN_API bool DN_Ring_HasData (DN_Ring const *ring, DN_U64 size);
DN_API void DN_Ring_Write (DN_Ring *ring, void const *src, DN_U64 src_size);
#define DN_Ring_WriteStruct(ring, item) DN_Ring_Write((ring), (item), sizeof(*(item)))
DN_API void DN_Ring_Read (DN_Ring *ring, void *dest, DN_U64 dest_size);
#define DN_Ring_ReadStruct(ring, dest) DN_Ring_Read((ring), (dest), sizeof(*(dest)))
template <typename T> DN_ArrayEraseResult DN_CArray_EraseRange (T *data, DN_USize *size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); DN_API void* DN_SliceAllocArena (void **data, DN_USize *slice_size_field, DN_USize size, DN_USize elem_size, DN_U8 align, DN_ZMem zmem, DN_Arena *arena);
template <typename T> T * DN_CArray_MakeArray (T *data, DN_USize *size, DN_USize max, DN_USize count, DN_ZMem z_mem);
template <typename T> T * DN_CArray_InsertArray (T *data, DN_USize *size, DN_USize max, DN_USize index, T const *items, DN_USize count);
template <typename T> T DN_CArray_PopFront (T *data, DN_USize *size, DN_USize count);
template <typename T> T DN_CArray_PopBack (T *data, DN_USize *size, DN_USize count);
template <typename T> DN_ArrayFindResult<T> DN_CArray_Find (T *data, DN_USize size, T const &value);
// NOTE: DN_SArray ///////////////////////////////////////////////////////////////////////////////// DN_API void* DN_CArrayInsertArray (void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count);
#if !defined(DN_NO_SARRAY) DN_API void* DN_CArrayPopFront (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
template <typename T> DN_SArray<T> DN_SArray_Init (DN_Arena *arena, DN_USize size, DN_ZMem z_mem); DN_API void* DN_CArrayPopBack (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
template <typename T> DN_SArray<T> DN_SArray_InitSlice (DN_Arena *arena, DN_Slice<T> slice, DN_USize size, DN_ZMem z_mem); DN_API DN_ArrayEraseResult DN_CArrayEraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T, size_t N> DN_SArray<T> DN_SArray_InitCArray (DN_Arena *arena, T const (&array)[N], DN_USize size, DN_ZMem); DN_API void* DN_CArrayMakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem);
template <typename T> DN_SArray<T> DN_SArray_InitBuffer (T* buffer, DN_USize size); DN_API void* DN_CArrayAddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add);
template <typename T> bool DN_SArray_IsValid (DN_SArray<T> const *array); DN_API bool DN_CArrayResizeFromPool (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
template <typename T> DN_Slice<T> DN_SArray_Slice (DN_SArray<T> const *array); DN_API bool DN_CArrayGrowFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
template <typename T> T * DN_SArray_AddArray (DN_SArray<T> *array, T const *items, DN_USize count); DN_API bool DN_CArrayGrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool);
template <typename T, DN_USize N> T * DN_SArray_AddCArray (DN_SArray<T> *array, T const (&items)[N]);
template <typename T> T * DN_SArray_Add (DN_SArray<T> *array, T const &item);
#define DN_SArray_AddArrayAssert(...) DN_HardAssert(DN_SArray_AddArray(__VA_ARGS__))
#define DN_SArray_AddCArrayAssert(...) DN_HardAssert(DN_SArray_AddCArray(__VA_ARGS__))
#define DN_SArray_AddAssert(...) DN_HardAssert(DN_SArray_Add(__VA_ARGS__))
template <typename T> T * DN_SArray_MakeArray (DN_SArray<T> *array, DN_USize count, DN_ZMem z_mem);
template <typename T> T * DN_SArray_Make (DN_SArray<T> *array, DN_ZMem z_mem);
#define DN_SArray_MakeArrayAssert(...) DN_HardAssert(DN_SArray_MakeArray(__VA_ARGS__))
#define DN_SArray_MakeAssert(...) DN_HardAssert(DN_SArray_Make(__VA_ARGS__))
template <typename T> T * DN_SArray_InsertArray (DN_SArray<T> *array, DN_USize index, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_SArray_InsertCArray (DN_SArray<T> *array, DN_USize index, T const (&items)[N]);
template <typename T> T * DN_SArray_Insert (DN_SArray<T> *array, DN_USize index, T const &item);
#define DN_SArray_InsertArrayAssert(...) DN_HardAssert(DN_SArray_InsertArray(__VA_ARGS__))
#define DN_SArray_InsertCArrayAssert(...) DN_HardAssert(DN_SArray_InsertCArray(__VA_ARGS__))
#define DN_SArray_InsertAssert(...) DN_HardAssert(DN_SArray_Insert(__VA_ARGS__))
template <typename T> T DN_SArray_PopFront (DN_SArray<T> *array, DN_USize count);
template <typename T> T DN_SArray_PopBack (DN_SArray<T> *array, DN_USize count);
template <typename T> DN_ArrayEraseResult DN_SArray_EraseRange (DN_SArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T> void DN_SArray_Clear (DN_SArray<T> *array);
#endif // !defined(DN_NO_SARRAY)
#if !defined(DN_NO_FARRAY) DN_API void* DN_SinglyLLDetach (void **link, void **next);
#define DN_FArray_ToSArray(array) DN_SArray_InitBuffer((array)->data, DN_ArrayCountU((array)->data))
template <typename T, DN_USize N> DN_FArray<T, N> DN_FArray_Init (T const *array, DN_USize count);
#define DN_FArray_HasData(array) ((array).data && (array).size)
template <typename T, DN_USize N> DN_FArray<T, N> DN_FArray_InitSlice (DN_Slice<T> slice);
template <typename T, DN_USize N, DN_USize K> DN_FArray<T, N> DN_FArray_InitCArray (T const (&items)[K]);
template <typename T, DN_USize N> bool DN_FArray_IsValid (DN_FArray<T, N> const *array);
template <typename T, DN_USize N> DN_USize DN_FArray_Max (DN_FArray<T, N> const *) { return N; }
template <typename T, DN_USize N> DN_Slice<T> DN_FArray_Slice (DN_FArray<T, N> const *array);
template <typename T, DN_USize N> T * DN_FArray_AddArray (DN_FArray<T, N> *array, T const *items, DN_USize count);
template <typename T, DN_USize N, DN_USize K> T * DN_FArray_AddCArray (DN_FArray<T, N> *array, T const (&items)[K]);
template <typename T, DN_USize N> T * DN_FArray_Add (DN_FArray<T, N> *array, T const &item);
#define DN_FArray_AddArrayAssert(...) DN_HardAssert(DN_FArray_AddArray(__VA_ARGS__))
#define DN_FArray_AddCArrayAssert(...) DN_HardAssert(DN_FArray_AddCArray(__VA_ARGS__))
#define DN_FArray_AddAssert(...) DN_HardAssert(DN_FArray_Add(__VA_ARGS__))
template <typename T, DN_USize N> T * DN_FArray_MakeArray (DN_FArray<T, N> *array, DN_USize count, DN_ZMem z_mem);
template <typename T, DN_USize N> T * DN_FArray_Make (DN_FArray<T, N> *array, DN_ZMem z_mem);
#define DN_FArray_MakeArrayAssert(...) DN_HardAssert(DN_FArray_MakeArray(__VA_ARGS__))
#define DN_FArray_MakeAssert(...) DN_HardAssert(DN_FArray_Make(__VA_ARGS__))
template <typename T, DN_USize N> T * DN_FArray_InsertArray (DN_FArray<T, N> *array, T const &item, DN_USize index);
template <typename T, DN_USize N, DN_USize K> T * DN_FArray_InsertCArray (DN_FArray<T, N> *array, DN_USize index, T const (&items)[K]);
template <typename T, DN_USize N> T * DN_FArray_Insert (DN_FArray<T, N> *array, DN_USize index, T const &item);
#define DN_FArray_InsertArrayAssert(...) DN_HardAssert(DN_FArray_InsertArray(__VA_ARGS__))
#define DN_FArray_InsertAssert(...) DN_HardAssert(DN_FArray_Insert(__VA_ARGS__))
template <typename T, DN_USize N> T DN_FArray_PopFront (DN_FArray<T, N> *array, DN_USize count);
template <typename T, DN_USize N> T DN_FArray_PopBack (DN_FArray<T, N> *array, DN_USize count);
template <typename T, DN_USize N> DN_ArrayFindResult<T> DN_FArray_Find (DN_FArray<T, N> *array, T const &find);
template <typename T, DN_USize N> DN_ArrayEraseResult DN_FArray_EraseRange (DN_FArray<T, N> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T, DN_USize N> void DN_FArray_Clear (DN_FArray<T, N> *array);
#endif // !defined(DN_NO_FARRAY)
#if !defined(DN_NO_SLICE) DN_API bool DN_RingHasSpace (DN_Ring const *ring, DN_U64 size);
#define DN_TO_SLICE(val) DN_Slice_Init((val)->data, (val)->size) DN_API bool DN_RingHasData (DN_Ring const *ring, DN_U64 size);
#define DN_Slice_InitCArray(array) DN_Slice_Init(array, DN_ArrayCountU(array)) DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size);
template <typename T> DN_Slice<T> DN_Slice_Init (T* const data, DN_USize size); #define DN_RingWriteStruct(ring, item) DN_RingWrite((ring), (item), sizeof(*(item)))
template <typename T, DN_USize N> DN_Slice<T> DN_Slice_InitCArrayCopy (DN_Arena *arena, T const (&array)[N]); DN_API void DN_RingRead (DN_Ring *ring, void *dest, DN_U64 dest_size);
template <typename T> DN_Slice<T> DN_Slice_Copy (DN_Arena *arena, DN_Slice<T> slice); #define DN_RingReadStruct(ring, dest) DN_RingRead((ring), (dest), sizeof(*(dest)))
template <typename T> DN_Slice<T> DN_Slice_CopyPtr (DN_Arena *arena, T* const data, DN_USize size);
template <typename T> DN_Slice<T> DN_Slice_Alloc (DN_Arena *arena, DN_USize size, DN_ZMem z_mem);
DN_Str8 DN_Slice_Str8Render (DN_Arena *arena, DN_Slice<DN_Str8> array, DN_Str8 separator);
DN_Str8 DN_Slice_Str8RenderSpaceSeparated (DN_Arena *arena, DN_Slice<DN_Str8> array);
DN_Str16 DN_Slice_Str16Render (DN_Arena *arena, DN_Slice<DN_Str16> array, DN_Str16 separator);
DN_Str16 DN_Slice_Str16RenderSpaceSeparated(DN_Arena *arena, DN_Slice<DN_Str16> array);
#endif // !defined(DN_NO_SLICE)
#if !defined(DN_NO_DSMAP) template <typename T> DN_DSMap<T> DN_DSMapInit (DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags);
template <typename T> DN_DSMap<T> DN_DSMap_Init (DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags); template <typename T> void DN_DSMapDeinit (DN_DSMap<T> *map, DN_ZMem z_mem);
template <typename T> void DN_DSMap_Deinit (DN_DSMap<T> *map, DN_ZMem z_mem); template <typename T> bool DN_DSMapIsValid (DN_DSMap<T> const *map);
template <typename T> bool DN_DSMap_IsValid (DN_DSMap<T> const *map); template <typename T> DN_U32 DN_DSMapHash (DN_DSMap<T> const *map, DN_DSMapKey key);
template <typename T> DN_U32 DN_DSMap_Hash (DN_DSMap<T> const *map, DN_DSMapKey key); template <typename T> DN_U32 DN_DSMapHashToSlotIndex (DN_DSMap<T> const *map, DN_DSMapKey key);
template <typename T> DN_U32 DN_DSMap_HashToSlotIndex (DN_DSMap<T> const *map, DN_DSMapKey key); template <typename T> DN_DSMapResult<T> DN_DSMapFind (DN_DSMap<T> const *map, DN_DSMapKey key);
template <typename T> DN_DSMapResult<T> DN_DSMap_Find (DN_DSMap<T> const *map, DN_DSMapKey key); template <typename T> DN_DSMapResult<T> DN_DSMapMake (DN_DSMap<T> *map, DN_DSMapKey key);
template <typename T> DN_DSMapResult<T> DN_DSMap_Make (DN_DSMap<T> *map, DN_DSMapKey key); template <typename T> DN_DSMapResult<T> DN_DSMapSet (DN_DSMap<T> *map, DN_DSMapKey key, T const &value);
template <typename T> DN_DSMapResult<T> DN_DSMap_Set (DN_DSMap<T> *map, DN_DSMapKey key, T const &value); template <typename T> DN_DSMapResult<T> DN_DSMapFindKeyU64 (DN_DSMap<T> const *map, DN_U64 key);
template <typename T> DN_DSMapResult<T> DN_DSMap_FindKeyU64 (DN_DSMap<T> const *map, DN_U64 key); template <typename T> DN_DSMapResult<T> DN_DSMapMakeKeyU64 (DN_DSMap<T> *map, DN_U64 key);
template <typename T> DN_DSMapResult<T> DN_DSMap_MakeKeyU64 (DN_DSMap<T> *map, DN_U64 key); template <typename T> DN_DSMapResult<T> DN_DSMapSetKeyU64 (DN_DSMap<T> *map, DN_U64 key, T const &value);
template <typename T> DN_DSMapResult<T> DN_DSMap_SetKeyU64 (DN_DSMap<T> *map, DN_U64 key, T const &value); template <typename T> DN_DSMapResult<T> DN_DSMapFindKeyStr8 (DN_DSMap<T> const *map, DN_Str8 key);
template <typename T> DN_DSMapResult<T> DN_DSMap_FindKeyStr8 (DN_DSMap<T> const *map, DN_Str8 key); template <typename T> DN_DSMapResult<T> DN_DSMapMakeKeyStr8 (DN_DSMap<T> *map, DN_Str8 key);
template <typename T> DN_DSMapResult<T> DN_DSMap_MakeKeyStr8 (DN_DSMap<T> *map, DN_Str8 key); template <typename T> DN_DSMapResult<T> DN_DSMapSetKeyStr8 (DN_DSMap<T> *map, DN_Str8 key, T const &value);
template <typename T> DN_DSMapResult<T> DN_DSMap_SetKeyStr8 (DN_DSMap<T> *map, DN_Str8 key, T const &value); template <typename T> bool DN_DSMapResize (DN_DSMap<T> *map, DN_U32 size);
template <typename T> bool DN_DSMap_Resize (DN_DSMap<T> *map, DN_U32 size); template <typename T> bool DN_DSMapErase (DN_DSMap<T> *map, DN_DSMapKey key);
template <typename T> bool DN_DSMap_Erase (DN_DSMap<T> *map, DN_DSMapKey key); template <typename T> bool DN_DSMapEraseKeyU64 (DN_DSMap<T> *map, DN_U64 key);
template <typename T> bool DN_DSMap_EraseKeyU64 (DN_DSMap<T> *map, DN_U64 key); template <typename T> bool DN_DSMapEraseKeyStr8 (DN_DSMap<T> *map, DN_Str8 key);
template <typename T> bool DN_DSMap_EraseKeyStr8 (DN_DSMap<T> *map, DN_Str8 key); template <typename T> DN_DSMapKey DN_DSMapKeyBuffer (DN_DSMap<T> const *map, void const *data, DN_U32 size);
template <typename T> DN_DSMapKey DN_DSMap_KeyBuffer (DN_DSMap<T> const *map, void const *data, DN_U32 size); template <typename T> DN_DSMapKey DN_DSMapKeyBufferAsU64NoHash (DN_DSMap<T> const *map, void const *data, DN_U32 size);
template <typename T> DN_DSMapKey DN_DSMap_KeyBufferAsU64NoHash (DN_DSMap<T> const *map, void const *data, DN_U32 size); template <typename T> DN_DSMapKey DN_DSMapKeyU64 (DN_DSMap<T> const *map, DN_U64 u64);
template <typename T> DN_DSMapKey DN_DSMap_KeyU64 (DN_DSMap<T> const *map, DN_U64 u64); template <typename T> DN_DSMapKey DN_DSMapKeyStr8 (DN_DSMap<T> const *map, DN_Str8 string);
template <typename T> DN_DSMapKey DN_DSMap_KeyStr8 (DN_DSMap<T> const *map, DN_Str8 string); #define DN_DSMapKeyCStr8(map, string) DN_DSMapKeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1)
#define DN_DSMap_KeyCStr8(map, string) DN_DSMap_KeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1) DN_API DN_DSMapKey DN_DSMapKeyU64NoHash (DN_U64 u64);
DN_API DN_DSMapKey DN_DSMap_KeyU64NoHash (DN_U64 u64); DN_API bool DN_DSMapKeyEquals (DN_DSMapKey lhs, DN_DSMapKey rhs);
DN_API bool DN_DSMap_KeyEquals (DN_DSMapKey lhs, DN_DSMapKey rhs); DN_API bool operator== (DN_DSMapKey lhs, DN_DSMapKey rhs);
DN_API bool operator== (DN_DSMapKey lhs, DN_DSMapKey rhs);
#endif // !defined(DN_NO_DSMAP)
#if !defined(DN_NO_LIST)
template <typename T> DN_List<T> DN_List_Init (DN_USize chunk_size);
template <typename T, size_t N> DN_List<T> DN_List_InitCArray (DN_Arena *arena, DN_USize chunk_size, T const (&array)[N]);
template <typename T> T * DN_List_At (DN_List<T> *list, DN_USize index, DN_ListChunk<T> **at_chunk);
template <typename T> void DN_List_Clear (DN_List<T> *list);
template <typename T> bool DN_List_Iterate (DN_List<T> *list, DN_ListIterator<T> *it, DN_USize start_index);
template <typename T> T * DN_List_MakeArena (DN_List<T> *list, DN_Arena *arena, DN_USize count);
template <typename T> T * DN_List_MakePool (DN_List<T> *list, DN_Pool *pool, DN_USize count);
template <typename T> T * DN_List_AddArena (DN_List<T> *list, DN_Arena *arena, T const &value);
template <typename T> T * DN_List_AddPool (DN_List<T> *list, DN_Pool *pool, T const &value);
template <typename T> void DN_List_AddListArena (DN_List<T> *list, DN_Arena *arena, DN_List<T> other);
template <typename T> void DN_List_AddListArena (DN_List<T> *list, DN_Pool *pool, DN_List<T> other);
template <typename T> DN_Slice<T> DN_List_ToSliceCopy (DN_List<T> const *list, DN_Arena* arena);
#endif // !defined(DN_NO_LIST)
#endif // !defined(DN_CONTAINER_H) #endif // !defined(DN_CONTAINER_H)

View File

@ -15,12 +15,9 @@ DN_API void DN_LeakTrackAlloc_(DN_LeakTracker *leak, void *ptr, DN_USize size, b
DN_TicketMutex_End(&leak->alloc_table_mutex); DN_TicketMutex_End(&leak->alloc_table_mutex);
}; };
// NOTE: If the entry was not added, we are reusing a pointer that has been freed.
// TODO: Add API for always making the item but exposing a var to indicate if the item was newly created or it
// already existed.
DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/); DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/);
DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table; DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table;
DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMap_MakeKeyU64(alloc_table, DN_Cast(DN_U64) ptr); DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMapMakeKeyU64(alloc_table, DN_Cast(DN_U64) ptr);
DN_LeakAlloc *alloc = alloc_entry.value; DN_LeakAlloc *alloc = alloc_entry.value;
if (alloc_entry.found) { if (alloc_entry.found) {
if ((alloc->flags & DN_LeakAllocFlag_Freed) == 0) { if ((alloc->flags & DN_LeakAllocFlag_Freed) == 0) {
@ -76,7 +73,7 @@ DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr)
DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/); DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/);
DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table; DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table;
DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMap_FindKeyU64(alloc_table, DN_Cast(uintptr_t) ptr); DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMapFindKeyU64(alloc_table, DN_Cast(uintptr_t) ptr);
DN_HardAssertF(alloc_entry.found, DN_HardAssertF(alloc_entry.found,
"Allocated pointer can not be removed as it does not exist in the " "Allocated pointer can not be removed as it does not exist in the "
"allocation table. When this memory was allocated, the pointer was " "allocation table. When this memory was allocated, the pointer was "
@ -128,7 +125,7 @@ DN_API void DN_LeakDump_(DN_LeakTracker *leak)
leaked_bytes += alloc->size; leaked_bytes += alloc->size;
leak_count++; leak_count++;
DN_Str8x32 alloc_size = DN_ByteCountStr8x32(alloc->size); DN_Str8x32 alloc_size = DN_ByteCountStr8x32(alloc->size);
DN_LOG_WarningF( DN_LogWarningF(
"Pointer (0x%p) leaked %.*s at:\n" "Pointer (0x%p) leaked %.*s at:\n"
"%.*s", "%.*s",
alloc->ptr, alloc->ptr,
@ -139,6 +136,6 @@ DN_API void DN_LeakDump_(DN_LeakTracker *leak)
if (leak_count) { if (leak_count) {
DN_Str8x32 leak_size = DN_ByteCountStr8x32(leaked_bytes); DN_Str8x32 leak_size = DN_ByteCountStr8x32(leaked_bytes);
DN_LOG_WarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_Str8PrintFmt(leak_size)); DN_LogWarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_Str8PrintFmt(leak_size));
} }
} }

View File

@ -2,7 +2,7 @@
#define DN_BASE_LEAK_H #define DN_BASE_LEAK_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
enum DN_LeakAllocFlag enum DN_LeakAllocFlag

View File

@ -1,130 +0,0 @@
#define DN_BASE_LOG_CPP
#if defined(_CLANDG)
#include "../dn.h"
#endif
static DN_LOGEmitFromTypeFVFunc *g_dn_base_log_emit_from_type_fv_func_;
static void *g_dn_base_log_emit_from_type_fv_user_context_;
DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType colour, DN_U8 r, DN_U8 g, DN_U8 b)
{
DN_THREAD_LOCAL char buffer[32];
buffer[0] = 0;
DN_Str8 result = {};
result.size = DN_SNPrintF(buffer,
DN_ArrayCountU(buffer),
"\x1b[%d;2;%u;%u;%um",
colour == DN_LOGColourType_Fg ? 38 : 48,
r,
g,
b);
result.data = buffer;
return result;
}
DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromU32(DN_LOGColourType colour, DN_U32 value)
{
DN_U8 r = DN_Cast(DN_U8)(value >> 24);
DN_U8 g = DN_Cast(DN_U8)(value >> 16);
DN_U8 b = DN_Cast(DN_U8)(value >> 8);
DN_Str8 result = DN_LOG_ColourEscapeCodeStr8FromRGB(colour, r, g, b);
return result;
}
DN_API DN_LOGPrefixSize DN_LOG_MakePrefix(DN_LOGStyle style, DN_LOGTypeParam type, DN_CallSite call_site, DN_LOGDate date, char *dest, DN_USize dest_size)
{
DN_Str8 type_str8 = type.str8;
if (type.is_u32_enum) {
switch (type.u32) {
case DN_LOGType_Debug: type_str8 = DN_Str8Lit("DEBUG"); break;
case DN_LOGType_Info: type_str8 = DN_Str8Lit("INFO "); break;
case DN_LOGType_Warning: type_str8 = DN_Str8Lit("WARN"); break;
case DN_LOGType_Error: type_str8 = DN_Str8Lit("ERROR"); break;
case DN_LOGType_Count: type_str8 = DN_Str8Lit("BADXX"); break;
}
}
static DN_USize max_type_length = 0;
max_type_length = DN_Max(max_type_length, type_str8.size);
int type_padding = DN_Cast(int)(max_type_length - type_str8.size);
DN_Str8 colour_esc = {};
DN_Str8 bold_esc = {};
DN_Str8 reset_esc = {};
if (style.colour) {
bold_esc = DN_Str8Lit(DN_LOG_BoldEscapeCode);
reset_esc = DN_Str8Lit(DN_LOG_ResetEscapeCode);
colour_esc = DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b);
}
DN_Str8 file_name = DN_Str8FileNameFromPath(call_site.file);
DN_GCC_WARNING_PUSH
DN_GCC_WARNING_DISABLE(-Wformat)
DN_GCC_WARNING_DISABLE(-Wformat-extra-args)
DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(4477)
int size = DN_SNPrintF(dest,
DN_Cast(int)dest_size,
"%04u-%02u-%02uT%02u:%02u:%02u" // date
"%S" // colour
"%S" // bold
" %S" // type
"%.*s" // type padding
"%S" // reset
" %S" // file name
":%05I32u " // line number
,
date.year,
date.month,
date.day,
date.hour,
date.minute,
date.second,
colour_esc, // colour
bold_esc, // bold
type_str8, // type
DN_Cast(int) type_padding,
"", // type padding
reset_esc, // reset
file_name, // file name
call_site.line); // line number
DN_MSVC_WARNING_POP // '%S' requires an argument of type 'wchar_t *', but variadic argument 7 has type 'DN_Str8'
DN_GCC_WARNING_POP
static DN_USize max_header_length = 0;
DN_USize size_no_ansi_codes = size - colour_esc.size - reset_esc.size - bold_esc.size;
max_header_length = DN_Max(max_header_length, size_no_ansi_codes);
DN_USize header_padding = max_header_length - size_no_ansi_codes;
DN_LOGPrefixSize result = {};
result.size = size;
result.padding = header_padding;
return result;
}
DN_API void DN_LOG_SetEmitFromTypeFVFunc(DN_LOGEmitFromTypeFVFunc *print_func, void *user_data)
{
g_dn_base_log_emit_from_type_fv_func_ = print_func;
g_dn_base_log_emit_from_type_fv_user_context_ = user_data;
}
DN_API void DN_LOG_EmitFromType(DN_LOGTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...)
{
DN_LOGEmitFromTypeFVFunc *func = g_dn_base_log_emit_from_type_fv_func_;
void *user_context = g_dn_base_log_emit_from_type_fv_user_context_;
if (func) {
va_list args;
va_start(args, fmt);
func(type, user_context, call_site, fmt, args);
va_end(args);
}
}
DN_API DN_LOGTypeParam DN_LOG_MakeU32LogTypeParam(DN_LOGType type)
{
DN_LOGTypeParam result = {};
result.is_u32_enum = true;
result.u32 = type;
return result;
}

View File

@ -1,74 +0,0 @@
#if !defined(DN_BASE_LOG_H)
#define DN_BASE_LOG_H
#if defined(_CLANGD)
#include "../dn.h"
#endif
enum DN_LOGType
{
DN_LOGType_Debug,
DN_LOGType_Info,
DN_LOGType_Warning,
DN_LOGType_Error,
DN_LOGType_Count,
};
enum DN_LOGBold
{
DN_LOGBold_No,
DN_LOGBold_Yes,
};
struct DN_LOGStyle
{
DN_LOGBold bold;
bool colour;
DN_U8 r, g, b;
};
struct DN_LOGTypeParam
{
bool is_u32_enum;
DN_U32 u32;
DN_Str8 str8;
};
enum DN_LOGColourType
{
DN_LOGColourType_Fg,
DN_LOGColourType_Bg,
};
struct DN_LOGDate
{
DN_U16 year;
DN_U8 month;
DN_U8 day;
DN_U8 hour;
DN_U8 minute;
DN_U8 second;
};
struct DN_LOGPrefixSize
{
DN_USize size;
DN_USize padding;
};
typedef void DN_LOGEmitFromTypeFVFunc(DN_LOGTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
#define DN_LOG_ResetEscapeCode "\x1b[0m"
#define DN_LOG_BoldEscapeCode "\x1b[1m"
DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType colour, DN_U8 r, DN_U8 g, DN_U8 b);
DN_API DN_Str8 DN_LOG_ColourEscapeCodeStr8FromU32(DN_LOGColourType colour, DN_U32 value);
DN_API DN_LOGPrefixSize DN_LOG_MakePrefix (DN_LOGStyle style, DN_LOGTypeParam type, DN_CallSite call_site, DN_LOGDate date, char *dest, DN_USize dest_size);
DN_API void DN_LOG_SetEmitFromTypeFVFunc (DN_LOGEmitFromTypeFVFunc *print_func, void *user_data);
DN_API void DN_LOG_EmitFromType (DN_LOGTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_LOGTypeParam DN_LOG_MakeU32LogTypeParam (DN_LOGType type);
#define DN_LOG_DebugF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Debug), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LOG_InfoF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LOG_WarningF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LOG_ErrorF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#endif // !defined(DN_BASE_LOG_H)

View File

@ -1,60 +0,0 @@
#if !defined(DN_BASE_OS_H)
#define DN_BASE_OS_H
#if defined(_CLANGD)
#include "../dn.h"
#endif
// NOTE: OS primitives that the OS layer can provide for the base layer but is optional.
struct DN_StackTraceFrame
{
DN_U64 address;
DN_U64 line_number;
DN_Str8 file_name;
DN_Str8 function_name;
};
struct DN_StackTraceRawFrame
{
void *process;
DN_U64 base_addr;
};
struct DN_StackTraceWalkResult
{
void *process; // [Internal] Windows handle to the process
DN_U64 *base_addr; // The addresses of the functions in the stack trace
DN_U16 size; // The number of `base_addr`'s stored from the walk
};
struct DN_StackTraceWalkResultIterator
{
DN_StackTraceRawFrame raw_frame;
DN_U16 index;
};
#if defined(DN_FREESTANDING)
#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalk(...)
#define DN_StackTraceWalkResultIterate(...)
#define DN_StackTraceWalkResultToStr8(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalkStr8(...) DN_Str8Lit("N/A")
#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A")
#define DN_StackTraceGetFrames(...)
#define DN_StackTraceRawFrameToFrame(...)
#define DN_StackTracePrint(...)
#define DN_StackTraceReloadSymbols(...)
#else
DN_API DN_StackTraceWalkResult DN_StackTraceWalk (struct DN_Arena *arena, DN_U16 limit);
DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk);
DN_API DN_Str8 DN_StackTraceWalkResultToStr8 (struct DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip);
DN_API DN_Str8 DN_StackTraceWalkStr8 (struct DN_Arena *arena, DN_U16 limit, DN_U16 skip);
DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap (DN_U16 limit, DN_U16 skip);
DN_API DN_Slice<DN_StackTraceFrame> DN_StackTraceGetFrames (struct DN_Arena *arena, DN_U16 limit);
DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame (struct DN_Arena *arena, DN_StackTraceRawFrame raw_frame);
DN_API void DN_StackTracePrint (DN_U16 limit);
DN_API void DN_StackTraceReloadSymbols ();
#endif
#endif // !defined(DN_BASE_OS_H)

View File

@ -1,8 +1,8 @@
#define DN_ASYNC_CPP #define DN_ASYNC_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#include "dn_async.h" #include "dn_async.h"
#endif #endif
@ -18,8 +18,8 @@ static DN_I32 DN_ASYNC_ThreadEntryPoint_(DN_OSThread *thread)
DN_ASYNCTask task = {}; DN_ASYNCTask task = {};
for (DN_OS_MutexScope(&async->ring_mutex)) { for (DN_OS_MutexScope(&async->ring_mutex)) {
if (DN_Ring_HasData(ring, sizeof(task))) if (DN_RingHasData(ring, sizeof(task)))
DN_Ring_Read(ring, &task, sizeof(task)); DN_RingRead(ring, &task, sizeof(task));
} }
if (task.work.func) { if (task.work.func) {
@ -72,8 +72,8 @@ static bool DN_ASYNC_QueueTask_(DN_ASYNCCore *async, DN_ASYNCTask const *task, D
bool result = false; bool result = false;
for (DN_OS_MutexScope(&async->ring_mutex)) { for (DN_OS_MutexScope(&async->ring_mutex)) {
for (;;) { for (;;) {
if (DN_Ring_HasSpace(&async->ring, sizeof(*task))) { if (DN_RingHasSpace(&async->ring, sizeof(*task))) {
DN_Ring_WriteStruct(&async->ring, task); DN_RingWriteStruct(&async->ring, task);
result = true; result = true;
break; break;
} }

View File

@ -2,8 +2,8 @@
#define DN_ASYNC_H #define DN_ASYNC_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#endif #endif
enum DN_ASYNCPriority enum DN_ASYNCPriority

View File

@ -2,11 +2,7 @@
#define DN_BIN_PACK_H #define DN_BIN_PACK_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif
#if !defined(DN_BASE_INC_H)
#error dn_base_inc.h must be included before this
#endif #endif
enum DN_BinPackMode enum DN_BinPackMode

View File

@ -63,7 +63,7 @@ DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST[]
DN_CGenTableHeaderType_Name, DN_CGenTableHeaderType_Name,
}; };
static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_OSErrSink *err) static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_ErrSink *err)
{ {
bool result = false; bool result = false;
if (!cgen || !cgen->file_list || !cgen->arena) if (!cgen || !cgen->file_list || !cgen->arena)
@ -283,7 +283,7 @@ static bool DN_CGen_GatherTables_(DN_CGen *cgen, DN_OSErrSink *err)
return result; return result;
} }
DN_API DN_CGen DN_CGen_FromFilesArgV(int argc, char const **argv, DN_OSErrSink *err) DN_API DN_CGen DN_CGen_FromFilesArgV(int argc, char const **argv, DN_ErrSink *err)
{ {
DN_CGen result = {}; DN_CGen result = {};
result.arena = MD_ArenaAlloc(); result.arena = MD_ArenaAlloc();
@ -341,7 +341,7 @@ DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_
if (result.enum_val == 0) { if (result.enum_val == 0) {
MD_CodeLoc loc = MD_CodeLocFromNode(DN_Cast(MD_Node *) node); MD_CodeLoc loc = MD_CodeLocFromNode(DN_Cast(MD_Node *) node);
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
DN_Str8 user_msg = DN_Str8FromFmtVArena(tmem.arena, fmt, args); DN_Str8 user_msg = DN_Str8FromFmtVArena(tmem.arena, fmt, args);
@ -357,6 +357,7 @@ DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_
} }
DN_Str8 error_msg = DN_Str8BuilderBuild(&builder, tmem.arena); DN_Str8 error_msg = DN_Str8BuilderBuild(&builder, tmem.arena);
DN_TCScratchEnd(&tmem);
MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Error, DN_Cast(char *) "%.*s", DN_Str8PrintFmt(error_msg)); MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Error, DN_Cast(char *) "%.*s", DN_Str8PrintFmt(error_msg));
DN_OS_Exit(DN_Cast(uint32_t) - 1); DN_OS_Exit(DN_Cast(uint32_t) - 1);
} }
@ -371,13 +372,14 @@ DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node)
return result; return result;
} }
DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err, char const *fmt, ...) DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_ErrSink *err, char const *fmt, ...)
{ {
if (!err) if (!err)
return; return;
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8Builder builder = DN_Str8BuilderFromTLS(); DN_Str8Builder builder = {};
builder.arena = tmem.arena;
MD_String8 kind_string = MD_StringFromMessageKind(kind); MD_String8 kind_string = MD_StringFromMessageKind(kind);
MD_CodeLoc loc = MD_CodeLocFromNode(node); MD_CodeLoc loc = MD_CodeLocFromNode(node);
@ -388,14 +390,15 @@ DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err,
DN_Str8BuilderAppendFV(&builder, fmt, args); DN_Str8BuilderAppendFV(&builder, fmt, args);
va_end(args); va_end(args);
DN_Str8 msg = DN_Str8BuilderBuild(&builder, tmem.arena); DN_Str8 msg = DN_Str8BuilderBuild(&builder, err->arena);
DN_TCScratchEnd(&tmem);
DN_OS_ErrSinkAppendF(err, DN_Cast(uint32_t) - 1, "%.*s", DN_Str8PrintFmt(msg)); DN_OS_ErrSinkAppendF(err, DN_Cast(uint32_t) - 1, "%.*s", DN_Str8PrintFmt(msg));
} }
DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_OSErrSink *err) DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_ErrSink *err)
{ {
bool result = true; bool result = true;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8Builder builder = {}; DN_Str8Builder builder = {};
builder.arena = tmem.arena; builder.arena = tmem.arena;
@ -419,6 +422,7 @@ DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *he
DN_Str8PrintFmt(missing_headers)); DN_Str8PrintFmt(missing_headers));
} }
DN_TCScratchEnd(&tmem);
return result; return result;
} }
@ -515,13 +519,14 @@ static void DN_CGen_EmitRowWhitespace_(DN_CGenTableRow const *row, DN_CppFile *c
if (tag->comment.size <= 0) if (tag->comment.size <= 0)
break; break;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 prefix = DN_Str8FromFmtArena(tmem.arena, "// NOTE: %.*s ", MD_S8VArg(tag->comment)); DN_Str8 prefix = DN_Str8FromFmtArena(tmem.arena, "// NOTE: %.*s ", MD_S8VArg(tag->comment));
int line_padding = DN_Max(100 - (DN_Cast(int) prefix.size + (DN_CppSpacePerIndent(cpp) * cpp->indent)), 0); int line_padding = DN_Max(100 - (DN_Cast(int) prefix.size + (DN_CppSpacePerIndent(cpp) * cpp->indent)), 0);
DN_CppPrint(cpp, "%.*s", DN_Str8PrintFmt(prefix)); DN_CppPrint(cpp, "%.*s", DN_Str8PrintFmt(prefix));
for (int index = 0; index < line_padding; index++) for (int index = 0; index < line_padding; index++)
DN_CppAppend(cpp, "/"); DN_CppAppend(cpp, "/");
DN_CppAppend(cpp, "\n"); DN_CppAppend(cpp, "\n");
DN_TCScratchEnd(&tmem);
} break; } break;
case DN_CGenTableRowTagType_EmptyLine: { case DN_CGenTableRowTagType_EmptyLine: {
@ -533,17 +538,18 @@ static void DN_CGen_EmitRowWhitespace_(DN_CGenTableRow const *row, DN_CppFile *c
DN_Str8 DN_CGen_ConvertTemplatesToEmittableLiterals_(DN_Arena *arena, DN_Str8 type) DN_Str8 DN_CGen_ConvertTemplatesToEmittableLiterals_(DN_Arena *arena, DN_Str8 type)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); DN_TCScratch tmem = DN_TCScratchBegin(&arena, 1);
DN_Str8 result = DN_Str8TrimWhitespaceAround(type); DN_Str8 result = DN_Str8TrimWhitespaceAround(type);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("<"), /*replace*/ DN_Str8Lit("_"), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("<"), /*replace*/ DN_Str8Lit("_"), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(">"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(">"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive);
result = DN_Str8TrimWhitespaceAround(result); result = DN_Str8TrimWhitespaceAround(result);
DN_TCScratchEnd(&tmem);
return result; return result;
} }
DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type) DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); DN_TCScratch tmem = DN_TCScratchBegin(&arena, 1);
DN_Str8 result = DN_Str8TrimWhitespaceAround(type); DN_Str8 result = DN_Str8TrimWhitespaceAround(type);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("*"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("*"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("constexpr"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("constexpr"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive);
@ -551,6 +557,7 @@ DN_Str8 DN_CGen_StripQualifiersOnCppType_(DN_Arena *arena, DN_Str8 type)
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("static"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit("static"), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, tmem.arena, DN_Str8EqCase_Sensitive);
result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(" "), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive); result = DN_Str8Replace(result, /*find*/ DN_Str8Lit(" "), /*replace*/ DN_Str8Lit(""), /*start_index*/ 0, arena, DN_Str8EqCase_Sensitive);
result = DN_Str8TrimWhitespaceAround(result); result = DN_Str8TrimWhitespaceAround(result);
DN_TCScratchEnd(&tmem);
return result; return result;
} }
@ -563,9 +570,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_CppLine(cpp, "%.*sType_Nil,", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "%.*sType_Nil,", DN_Str8PrintFmt(emit_prefix));
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next)
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string); DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string);
DN_CppLine(cpp, "%.*sType_%.*s,", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(enum_name)); DN_CppLine(cpp, "%.*sType_%.*s,", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(enum_name));
DN_TCScratchEnd(&tmem);
} }
DN_CppLine(cpp, "%.*sType_Count,", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "%.*sType_Count,", DN_Str8PrintFmt(emit_prefix));
} }
@ -582,9 +590,9 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
case DN_CGenTableType_CodeGenStruct: { case DN_CGenTableType_CodeGenStruct: {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
// TODO(doyle): Verify the codegen table has the headers from the table it references // TODO(doyle): Verify the codegen table has the headers from the table it references
int longest_type_name = 0; int longest_type_name = 0;
for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) { for (DN_USize row_index = 0; row_index < it.table->row_count; row_index++) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_CGenTableRow const *row = it.table->rows + row_index; DN_CGenTableRow const *row = it.table->rows + row_index;
DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppType].string, row); DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[DN_CGenTableHeaderType_CppType].string, row);
@ -594,6 +602,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
length += emit_prefix.size; length += emit_prefix.size;
longest_type_name = DN_Max(longest_type_name, DN_Cast(int) length); longest_type_name = DN_Max(longest_type_name, DN_Cast(int) length);
DN_TCScratchEnd(&tmem);
} }
DN_CppStructBlock(cpp, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(it.cgen_table_column[DN_CGenTableHeaderType_Name].string)) DN_CppStructBlock(cpp, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(it.cgen_table_column[DN_CGenTableHeaderType_Name].string))
@ -606,8 +615,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
if (cpp_name.column.string.size <= 0 || cpp_type.column.string.size <= 0) if (cpp_name.column.string.size <= 0 || cpp_type.column.string.size <= 0)
continue; continue;
// NOTE: Generate cpp array size /////////////////////////////////// // NOTE: Generate cpp array size
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 array_size = {}; DN_Str8 array_size = {};
if (cpp_array_size.column.string.size) if (cpp_array_size.column.string.size)
array_size = DN_Str8FromFmtArena(tmem.arena, "[%.*s]", DN_Str8PrintFmt(cpp_array_size.column.string)); array_size = DN_Str8FromFmtArena(tmem.arena, "[%.*s]", DN_Str8PrintFmt(cpp_array_size.column.string));
@ -620,6 +629,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
if (DN_CGen_WillCodeGenTypeName(cgen, find_name)) if (DN_CGen_WillCodeGenTypeName(cgen, find_name))
emit_cpp_type = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type.column.string)); emit_cpp_type = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type.column.string));
} }
DN_TCScratchEnd(&tmem);
int name_to_type_padding = 1 + longest_type_name - DN_Cast(int) emit_cpp_type.size; int name_to_type_padding = 1 + longest_type_name - DN_Cast(int) emit_cpp_type.size;
@ -803,7 +813,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
// for types that are declared in the same mdesk file. We will also // for types that are declared in the same mdesk file. We will also
// calculate the longest type name that we will generate for whitespace // calculate the longest type name that we will generate for whitespace
// padding purposes. // padding purposes.
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_USize longest_cpp_type_name = 0; DN_USize longest_cpp_type_name = 0;
auto cpp_type_list = DN_SArray_Init<DN_Str8>(tmem.arena, it.table->row_count, DN_ZMem_Yes); auto cpp_type_list = DN_SArray_Init<DN_Str8>(tmem.arena, it.table->row_count, DN_ZMem_Yes);
@ -814,7 +824,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
// NOTE: CHeck the length of the string after turning it into emittable code // NOTE: CHeck the length of the string after turning it into emittable code
DN_Str8 cpp_type_name = DN_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string); DN_Str8 cpp_type_name = DN_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string);
if (DN_CGen_WillCodeGenTypeName(cgen, cpp_type_name)) if (DN_CGen_WillCodeGenTypeName(cgen, cpp_type_name))
cpp_type_name = DN_Str8FromTLSF("%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type_name)); cpp_type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(cpp_type_name));
DN_Str8 cpp_type_name_no_templates = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, cpp_type_name); DN_Str8 cpp_type_name_no_templates = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, cpp_type_name);
longest_cpp_type_name = DN_Max(longest_cpp_type_name, cpp_type_name_no_templates.size); longest_cpp_type_name = DN_Max(longest_cpp_type_name, cpp_type_name_no_templates.size);
@ -849,7 +859,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
index_the_field_references = sub_row_index; index_the_field_references = sub_row_index;
} }
cpp_array_size_field_str8 = cpp_array_size_field_str8 =
DN_Str8FromTLSF("&g_%.*s%.*s_type_fields[%zu]", DN_Str8FromFmtArena(tmem.arena, "&g_%.*s%.*s_type_fields[%zu]",
DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(emit_prefix),
DN_Str8PrintFmt(struct_name.string), DN_Str8PrintFmt(struct_name.string),
index_the_field_references); index_the_field_references);
@ -862,7 +872,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size;
DN_USize cpp_type_padding = 1 + longest_cpp_type_name - cpp_type_name.size; DN_USize cpp_type_padding = 1 + longest_cpp_type_name - cpp_type_name.size;
DN_Str8 cpp_type_enum = DN_Str8FromTLSF("%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(orig_cpp_type_no_templates)); DN_Str8 cpp_type_enum = DN_Str8FromFmtArena(tmem.arena, "%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(orig_cpp_type_no_templates));
DN_USize cpp_type_enum_padding = cpp_type_padding + (orig_cpp_type.size - cpp_type_name.size); DN_USize cpp_type_enum_padding = cpp_type_padding + (orig_cpp_type.size - cpp_type_name.size);
DN_Str8 cpp_label_str8 = cpp_name.column.string; DN_Str8 cpp_label_str8 = cpp_name.column.string;
@ -960,10 +970,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
if (cpp_name.column.string.size <= 0) if (cpp_name.column.string.size <= 0)
continue; continue;
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size; DN_USize cpp_name_padding = 1 + it.table->headers[cpp_name.index].longest_string - cpp_name.column.string.size;
DN_Str8 cpp_value_str8 = cpp_value.column.string.size ? cpp_value.column.string : DN_Str8FromTLSF("%zu", row_index); DN_Str8 cpp_value_str8 = cpp_value.column.string.size ? cpp_value.column.string : DN_Str8FromFmtArena(tmem.arena, "%zu", row_index);
DN_Str8 cpp_type_enum = DN_Str8FromTLSF("%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(struct_or_enum_name)); DN_Str8 cpp_type_enum = DN_Str8FromFmtArena(tmem.arena, "%.*sType_%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(struct_or_enum_name));
DN_Str8 cpp_label_str8 = cpp_name.column.string; DN_Str8 cpp_label_str8 = cpp_name.column.string;
DN_USize cpp_label_str8_padding = cpp_name_padding; DN_USize cpp_label_str8_padding = cpp_name_padding;
@ -972,7 +982,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
cpp_label_str8_padding = 1 + it.table->headers[cpp_label.index].longest_string - cpp_label.column.string.size; cpp_label_str8_padding = 1 + it.table->headers[cpp_label.index].longest_string - cpp_label.column.string.size;
} }
DN_Str8Builder builder = DN_Str8BuilderFromTLS(); DN_Str8Builder builder = {};
builder.arena = tmem.arena;
// NOTE: row // NOTE: row
DN_Str8BuilderAppendF(&builder, "{%2d, ", row_index); DN_Str8BuilderAppendF(&builder, "{%2d, ", row_index);
@ -1015,23 +1026,26 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_Str8BuilderAppendF(&builder, "/*array_size*/ 0, "); DN_Str8BuilderAppendF(&builder, "/*array_size*/ 0, ");
DN_Str8BuilderAppendF(&builder, "/*array_size_field*/ NULL},"); DN_Str8BuilderAppendF(&builder, "/*array_size_field*/ NULL},");
DN_Str8 line = DN_Str8BuilderBuildFromTLS(&builder); DN_Str8 line = DN_Str8BuilderBuild(&builder, tmem.arena);
DN_TCScratchEnd(&tmem);
DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line)); DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line));
} }
} }
DN_TCScratchEnd(&tmem);
} }
} }
} }
int longest_name_across_all_tables = 0; int longest_name_across_all_tables = 0;
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string;
if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) if (DN_CGen_WillCodeGenTypeName(cgen, type_name))
type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name));
longest_name_across_all_tables = DN_Max(longest_name_across_all_tables, DN_Cast(int) type_name.size); longest_name_across_all_tables = DN_Max(longest_name_across_all_tables, DN_Cast(int) type_name.size);
DN_TCScratchEnd(&tmem);
} }
} }
@ -1042,20 +1056,21 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_USize longest_type_name = 0; DN_USize longest_type_name = 0;
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string;
if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) if (DN_CGen_WillCodeGenTypeName(cgen, type_name))
type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name));
longest_type_name = DN_Max(longest_type_name, type_name.size); longest_type_name = DN_Max(longest_type_name, type_name.size);
DN_TCScratchEnd(&tmem);
} }
} }
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string; DN_Str8 type_name = it.cgen_table_column[DN_CGenTableHeaderType_Name].string;
if (DN_CGen_WillCodeGenTypeName(cgen, type_name)) if (DN_CGen_WillCodeGenTypeName(cgen, type_name))
type_name = DN_Str8FromTLSF("%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name)); type_name = DN_Str8FromFmtArena(tmem.arena, "%.*s%.*s", DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(type_name));
int name_padding = 1 + longest_name_across_all_tables - DN_Cast(int) type_name.size; int name_padding = 1 + longest_name_across_all_tables - DN_Cast(int) type_name.size;
DN_Str8 type_info_kind = {}; DN_Str8 type_info_kind = {};
@ -1080,9 +1095,10 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_Str8 fields_count = DN_Str8Lit("0"); DN_Str8 fields_count = DN_Str8Lit("0");
if (!DN_Str8Eq(fields, DN_Str8Lit("NULL"))) if (!DN_Str8Eq(fields, DN_Str8Lit("NULL")))
fields_count = DN_Str8FromTLSF("sizeof(%.*s)/sizeof(%.*s[0])", DN_Str8PrintFmt(fields), DN_Str8PrintFmt(fields)); fields_count = DN_Str8FromFmtArena(tmem.arena, "sizeof(%.*s)/sizeof(%.*s[0])", DN_Str8PrintFmt(fields), DN_Str8PrintFmt(fields));
DN_Str8Builder builder = DN_Str8BuilderFromTLS(); DN_Str8Builder builder = {};
builder.arena = tmem.arena;
// NOTE: name // NOTE: name
DN_Str8BuilderAppendF(&builder, "{DN_Str8Lit(\"%.*s\"),%*s", DN_Str8PrintFmt(type_name), name_padding, ""); DN_Str8BuilderAppendF(&builder, "{DN_Str8Lit(\"%.*s\"),%*s", DN_Str8PrintFmt(type_name), name_padding, "");
@ -1101,7 +1117,8 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
// NOTE: DN_TypeField length // NOTE: DN_TypeField length
DN_Str8BuilderAppendF(&builder, "/*count*/ %.*s},", DN_Str8PrintFmt(fields_count)); DN_Str8BuilderAppendF(&builder, "/*count*/ %.*s},", DN_Str8PrintFmt(fields_count));
DN_Str8 line = DN_Str8BuilderBuildFromTLS(&builder); DN_Str8 line = DN_Str8BuilderBuild(&builder, tmem.arena);
DN_TCScratchEnd(&tmem);
DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line)); DN_CppLine(cpp, "%.*s", DN_Str8PrintFmt(line));
} }
} }
@ -1115,7 +1132,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
{ {
DN_CppLine(cpp, "case %.*sType_Nil: break;", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "case %.*sType_Nil: break;", DN_Str8PrintFmt(emit_prefix));
DN_CppLine(cpp, "case %.*sType_Count: break;", DN_Str8PrintFmt(emit_prefix)); DN_CppLine(cpp, "case %.*sType_Count: break;", DN_Str8PrintFmt(emit_prefix));
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) { for (DN_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) { for (DN_CGenLookupTableIterator it = {}; DN_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string); DN_Str8 enum_name = DN_CGen_ConvertTemplatesToEmittableLiterals_(tmem.arena, it.cgen_table_column[DN_CGenTableHeaderType_Name].string);
@ -1129,6 +1146,7 @@ DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFil
DN_CppLine(cpp, "case %.*s: result = g_%.*stypes + %.*s; break;", DN_Str8PrintFmt(full_enum_name), DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(full_enum_name)); DN_CppLine(cpp, "case %.*s: result = g_%.*stypes + %.*s; break;", DN_Str8PrintFmt(full_enum_name), DN_Str8PrintFmt(emit_prefix), DN_Str8PrintFmt(full_enum_name));
} }
} }
DN_TCScratchEnd(&tmem);
} }
DN_CppLine(cpp, "return result;"); DN_CppLine(cpp, "return result;");
} }

View File

@ -2,8 +2,8 @@
#define DN_CGEN_H #define DN_CGEN_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#include "../Standalone/dn_cpp_file.h" #include "../Standalone/dn_cpp_file.h"
#endif #endif
@ -38,27 +38,6 @@
#error Metadesk 'md.h' must be included before 'dn_cgen.h' #error Metadesk 'md.h' must be included before 'dn_cgen.h'
#endif #endif
#if !defined(DN_BASE_INC_H)
#error dn_base_inc.h must be included before this
#endif
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$\ $$$$$$$$\ $$\ $$\
// $$ __$$\ $$ __$$\ $$ _____|$$$\ $$ |
// $$ / \__|$$ / \__|$$ | $$$$\ $$ |
// $$ | $$ |$$$$\ $$$$$\ $$ $$\$$ |
// $$ | $$ |\_$$ |$$ __| $$ \$$$$ |
// $$ | $$\ $$ | $$ |$$ | $$ |\$$$ |
// \$$$$$$ |\$$$$$$ |$$$$$$$$\ $$ | \$$ |
// \______/ \______/ \________|\__| \__|
//
// dn_cgen.h -- C/C++ code generation from table data in Metadesk files
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
enum DN_CGenTableKeyType enum DN_CGenTableKeyType
{ {
DN_CGenTableKeyType_Nil, DN_CGenTableKeyType_Nil,
@ -194,12 +173,12 @@ enum DN_CGenEmit
(str8).size \ (str8).size \
} }
DN_API DN_CGen DN_CGen_InitFilesArgV(int argc, char const **argv, DN_OSErrSink *err); DN_API DN_CGen DN_CGen_InitFilesArgV(int argc, char const **argv, DN_ErrSink *err);
DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8(DN_CGenTableHeaderType type); DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8(DN_CGenTableHeaderType type);
DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_CGenMapNodeToEnum const *valid_keys, DN_USize valid_keys_size, char const *fmt, ...); DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit(MD_Node const *node, DN_CGenMapNodeToEnum const *valid_keys, DN_USize valid_keys_size, char const *fmt, ...);
DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node); DN_API DN_USize DN_CGen_NodeChildrenCount(MD_Node const *node);
DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_OSErrSink *err, char const *fmt, ...); DN_API void DN_CGen_LogF(MD_MessageKind kind, MD_Node *node, DN_ErrSink *err, char const *fmt, ...);
DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_OSErrSink *err); DN_API bool DN_CGen_TableHasHeaders(DN_CGenTable const *table, DN_Str8 const *headers, DN_USize header_count, DN_ErrSink *err);
DN_API DN_CGenLookupColumnAtHeader DN_CGen_LookupColumnAtHeader(DN_CGenTable *table, DN_Str8 header, DN_CGenTableRow const *row); DN_API DN_CGenLookupColumnAtHeader DN_CGen_LookupColumnAtHeader(DN_CGenTable *table, DN_Str8 header, DN_CGenTableRow const *row);
DN_API bool DN_CGen_LookupNextTableInCodeGenTable(DN_CGen *cgen, DN_CGenTable *cgen_table, DN_CGenLookupTableIterator *it); DN_API bool DN_CGen_LookupNextTableInCodeGenTable(DN_CGen *cgen, DN_CGenTable *cgen_table, DN_CGenLookupTableIterator *it);
DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFile *cpp, DN_Str8 emit_prefix); DN_API void DN_CGen_EmitCodeForTables(DN_CGen *cgen, DN_CGenEmit emit, DN_CppFile *cpp, DN_Str8 emit_prefix);

View File

@ -2,7 +2,7 @@
#define DN_CSV_H #define DN_CSV_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
enum DN_CSVSerialise enum DN_CSVSerialise

View File

@ -1,6 +1,5 @@
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#include "../dn_os_inc.h"
#endif #endif
DN_MSVC_WARNING_PUSH DN_MSVC_WARNING_PUSH
@ -31,10 +30,11 @@ void DN_Demo()
// NOTE: DN_HexFromBytes // NOTE: DN_HexFromBytes
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
unsigned char bytes[2] = {0xFA, 0xCE}; unsigned char bytes[2] = {0xFA, 0xCE};
DN_Str8 hex = DN_HexFromBytesPtrArena(bytes, sizeof(bytes), tmem.arena); DN_Str8 hex = DN_HexFromBytesPtrArena(bytes, sizeof(bytes), scratch.arena);
DN_Assert(DN_Str8Eq(hex, DN_Str8Lit("face"))); // NOTE: Guaranteed to be null-terminated DN_Assert(DN_Str8Eq(hex, DN_Str8Lit("face"))); // NOTE: Guaranteed to be null-terminated
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_BytesFromHex // NOTE: DN_BytesFromHex
@ -119,8 +119,8 @@ void DN_Demo()
// buffer, this buffer must be valid throughout the lifetime of the hash // buffer, this buffer must be valid throughout the lifetime of the hash
// table! // table!
{ {
// NOTE: DN_DSMap_Init // NOTE: DN_DSMapInit
// NOTE: DN_DSMap_Deinit // NOTE: DN_DSMapDeinit
// //
// Initialise a hash table where the table size *must* be a // Initialise a hash table where the table size *must* be a
// power-of-two, otherwise an assert will be triggered. If // power-of-two, otherwise an assert will be triggered. If
@ -139,15 +139,15 @@ void DN_Demo()
// A 'Deinit' of the map will similarly deallocate the passed in arena (as // A 'Deinit' of the map will similarly deallocate the passed in arena (as
// the map takes ownership of the arena). // the map takes ownership of the arena).
DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil);
DN_DSMap<int> map = DN_DSMap_Init<int>(&arena, /*size*/ 1024, DN_DSMapFlags_Nil); // Size must be PoT! DN_DSMap<int> map = DN_DSMapInit<int>(&arena, /*size*/ 1024, DN_DSMapFlags_Nil); // Size must be PoT!
DN_Assert(DN_DSMap_IsValid(&map)); // Valid if no initialisation failure (e.g. mem alloc failure) DN_Assert(DN_DSMapIsValid(&map)); // Valid if no initialisation failure (e.g. mem alloc failure)
// NOTE: DN_DSMap_KeyCStringLit // NOTE: DN_DSMapKeyCStringLit
// NOTE: DN_DSMap_KeyU64 // NOTE: DN_DSMapKeyU64
// NOTE: DN_DSMap_KeyU64NoHash // NOTE: DN_DSMapKeyU64NoHash
// NOTE: DN_DSMap_KeyBuffer // NOTE: DN_DSMapKeyBuffer
// NOTE: DN_DSMap_KeyStr8 // NOTE: DN_DSMapKeyStr8
// NOTE: DN_DSMap_KeyStr8Copy // NOTE: DN_DSMapKeyStr8Copy
// Create a hash-table key where: // Create a hash-table key where:
// //
// KeyCStringLit: Uses a Hash(cstring literal) // KeyCStringLit: Uses a Hash(cstring literal)
@ -168,11 +168,11 @@ void DN_Demo()
// already sufficiently uniformly distributed already (e.g. using 8 // already sufficiently uniformly distributed already (e.g. using 8
// bytes taken from a SHA256 hash as the key) and the first 4 bytes // bytes taken from a SHA256 hash as the key) and the first 4 bytes
// will be used verbatim. // will be used verbatim.
DN_DSMapKey key = DN_DSMap_KeyStr8(&map, DN_Str8Lit("Sample Key")); DN_DSMapKey key = DN_DSMapKeyStr8(&map, DN_Str8Lit("Sample Key"));
// NOTE: DN_DSMap_Find // NOTE: DN_DSMapFind
// NOTE: DN_DSMap_Make // NOTE: DN_DSMapMake
// NOTE: DN_DSMap_Set // NOTE: DN_DSMapSet
// //
// Query or commit key-value pair to the table, where: // Query or commit key-value pair to the table, where:
// //
@ -190,7 +190,7 @@ void DN_Demo()
// the table will be grown to 2x the current the size before insertion // the table will be grown to 2x the current the size before insertion
// completes. // completes.
{ {
DN_DSMapResult<int> set_result = DN_DSMap_Set(&map, key, 0xCAFE); DN_DSMapResult<int> set_result = DN_DSMapSet(&map, key, 0xCAFE);
DN_Assert(!set_result.found); // First time we are setting the key-value pair, it wasn't previously in the table DN_Assert(!set_result.found); // First time we are setting the key-value pair, it wasn't previously in the table
DN_Assert(map.occupied == 2); // Sentinel + new element == 2 DN_Assert(map.occupied == 2); // Sentinel + new element == 2
} }
@ -206,38 +206,38 @@ void DN_Demo()
DN_Assert(DN_Str8Eq(DN_Str8FromPtr(it_key.buffer_data, it_key.buffer_size), DN_Str8Lit("Sample Key"))); DN_Assert(DN_Str8Eq(DN_Str8FromPtr(it_key.buffer_data, it_key.buffer_size), DN_Str8Lit("Sample Key")));
} }
// NOTE: DN_DSMap_Erase // NOTE: DN_DSMapErase
// //
// Remove the key-value pair from the table. If by erasing the key-value // Remove the key-value pair from the table. If by erasing the key-value
// pair from the table puts the table under 25% load, the table will be // pair from the table puts the table under 25% load, the table will be
// shrunk by 1/2 the current size after erasing. The table will not shrink // shrunk by 1/2 the current size after erasing. The table will not shrink
// below the initial size that the table was initialised as. // below the initial size that the table was initialised as.
{ {
bool erased = DN_DSMap_Erase(&map, key); bool erased = DN_DSMapErase(&map, key);
DN_Assert(erased); DN_Assert(erased);
DN_Assert(map.occupied == 1); // Sentinel element DN_Assert(map.occupied == 1); // Sentinel element
} }
DN_DSMap_Deinit(&map, DN_ZMem_Yes); // Deallocates the 'arena' for us! DN_DSMapDeinit(&map, DN_ZMem_Yes); // Deallocates the 'arena' for us!
} }
// NOTE: DN_DSMap_Hash // NOTE: DN_DSMapHash
// //
// Hash the input key using the custom hash function if it's set on the map, // Hash the input key using the custom hash function if it's set on the map,
// otherwise uses the default hashing function (32bit Murmur3). // otherwise uses the default hashing function (32bit Murmur3).
// NOTE: DN_DSMap_HashToSlotIndex // NOTE: DN_DSMapHashToSlotIndex
// //
// Calculate the index into the map's 'slots' array from the given hash. // Calculate the index into the map's 'slots' array from the given hash.
// NOTE: DN_DSMap_Resize // NOTE: DN_DSMapResize
// //
// Resize the table and move all elements to the new map, note that the new // Resize the table and move all elements to the new map, note that the new
// size must be a power of two. This function wil fail on memory allocation // size must be a power of two. This function wil fail on memory allocation
// failure, or the requested size is smaller than the current number of // failure, or the requested size is smaller than the current number of
// elements in the map to resize. // elements in the map to resize.
// NOTE: DN_OSErrSink // NOTE: DN_ErrSink
// //
// Error sinks are a way of accumulating errors from API calls related or // Error sinks are a way of accumulating errors from API calls related or
// unrelated into 1 unified error handling pattern. The implemenation of a // unrelated into 1 unified error handling pattern. The implemenation of a
@ -273,11 +273,11 @@ void DN_Demo()
// (B) Error handling using pipelining and and error proof APIs. APIs that // (B) Error handling using pipelining and and error proof APIs. APIs that
// produce errors take in the error sink as a parameter. // produce errors take in the error sink as a parameter.
if (0) { if (0) {
DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil);
DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error); DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error);
DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error); DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error);
DN_OS_FileClose(&file); DN_OS_FileClose(&file);
if (DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to file")) { if (DN_ErrSinkEndLogErrorF(error, "Failed to write to file")) {
// Do error handling! // Do error handling!
} }
} }
@ -297,7 +297,7 @@ void DN_Demo()
// be populated by the first error encountered in that scope. // be populated by the first error encountered in that scope.
if (0) { if (0) {
DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil);
DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error); DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/path/to/file"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_ReadWrite, error);
DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error); DN_OS_FileWrite(&file, DN_Str8Lit("abc"), error);
DN_OS_FileClose(&file); DN_OS_FileClose(&file);
@ -305,12 +305,12 @@ void DN_Demo()
{ {
// NOTE: My error sinks are thread-local, so the returned 'error' is // NOTE: My error sinks are thread-local, so the returned 'error' is
// the same as the 'error' value above. // the same as the 'error' value above.
DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); DN_TCErrSinkBegin(DN_ErrSinkMode_Nil);
DN_OS_FileWriteAll(DN_Str8Lit("/path/to/another/file"), DN_Str8Lit("123"), error); DN_OS_FileWriteAll(DN_Str8Lit("/path/to/another/file"), DN_Str8Lit("123"), error);
DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to another file"); DN_ErrSinkEndLogErrorF(error, "Failed to write to another file");
} }
if (DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to file")) { if (DN_ErrSinkEndLogErrorF(error, "Failed to write to file")) {
// Do error handling! // Do error handling!
} }
} }
@ -357,16 +357,6 @@ void DN_Demo()
// //
// And the non-named version emit just the 'value' portion // And the non-named version emit just the 'value' portion
// NOTE: DN_List_Iterate
{
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
DN_List<int> list = DN_List_Init<int>(/*chunk_size*/ 128);
for (DN_ListIterator<int> it = {}; DN_List_Iterate(&list, &it, 0);) {
int *item = it.data;
(void)item;
}
}
// NOTE: DN_LOGProc // NOTE: DN_LOGProc
// //
// Function prototype of the logging interface exposed by this library. Logs // Function prototype of the logging interface exposed by this library. Logs
@ -438,10 +428,11 @@ void DN_Demo()
// If 'tmp_path' is written to successfuly, the file will be copied over into // If 'tmp_path' is written to successfuly, the file will be copied over into
// 'path'. // 'path'.
if (0) { if (0) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); DN_ErrSink *error = DN_TCErrSinkBegin(DN_ErrSinkMode_Nil);
DN_OS_FileWriteAllSafe(/*path*/ DN_Str8Lit("C:/Home/my.txt"), /*buffer*/ DN_Str8Lit("Hello world"), error); DN_OS_FileWriteAllSafe(/*path*/ DN_Str8Lit("C:/Home/my.txt"), /*buffer*/ DN_Str8Lit("Hello world"), error);
DN_OS_ErrSinkEndAndLogErrorF(error, ""); DN_ErrSinkEndLogErrorF(error, "");
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_OS_EstimateTSCPerSecond // NOTE: DN_OS_EstimateTSCPerSecond
@ -630,7 +621,7 @@ void DN_Demo()
// Int -> U32: 0 or UINT32_MAX // Int -> U32: 0 or UINT32_MAX
// Int -> U64: 0 or UINT64_MAX // Int -> U64: 0 or UINT64_MAX
// NOTE: DN_StackTrace // NOTE: DN_OS_StackTrace
// Emit stack traces at the calling site that these functions are invoked // Emit stack traces at the calling site that these functions are invoked
// from. // from.
// //
@ -647,15 +638,15 @@ void DN_Demo()
// the debug APIs are aware of how to resolve the new addresses imported // the debug APIs are aware of how to resolve the new addresses imported
// into the address space. // into the address space.
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
// NOTE: DN_StackTraceWalk // NOTE: DN_OS_StackTraceWalk
// //
// Generate a stack trace as a series of addresses to the base of the // Generate a stack trace as a series of addresses to the base of the
// functions on the call-stack at the current instruction pointer. The // functions on the call-stack at the current instruction pointer. The
// addresses are stored in order from the current executing function // addresses are stored in order from the current executing function
// first to the most ancestor function last in the walk. // first to the most ancestor function last in the walk.
DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, /*depth limit*/ 128); DN_StackTraceWalkResult walk = DN_StackTraceWalk(scratch.arena, /*depth limit*/ 128);
// Loop over the addresses produced in the stack trace // Loop over the addresses produced in the stack trace
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);) { for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);) {
@ -663,7 +654,7 @@ void DN_Demo()
// //
// Converts the base address into a human readable stack trace // Converts the base address into a human readable stack trace
// entry (e.g. address, line number, file and function name). // entry (e.g. address, line number, file and function name).
DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(tmem.arena, it.raw_frame); DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(scratch.arena, it.raw_frame);
// You may then print out the frame like so // You may then print out the frame like so
if (0) if (0)
@ -675,13 +666,15 @@ void DN_Demo()
// to resolve the new addresses. // to resolve the new addresses.
DN_StackTraceReloadSymbols(); DN_StackTraceReloadSymbols();
// NOTE: DN_StackTraceGetFrames // NOTE: DN_OS_StackTraceGetFrames
// //
// Helper function to create a stack trace and automatically convert the // Helper function to create a stack trace and automatically convert the
// raw frames into human readable frames. This function effectively // raw frames into human readable frames. This function effectively
// calls 'Walk' followed by 'RawFrameToFrame'. // calls 'Walk' followed by 'RawFrameToFrame'.
DN_Slice<DN_StackTraceFrame> frames = DN_StackTraceGetFrames(tmem.arena, /*depth limit*/ 128); DN_StackTraceFrameSlice frames = DN_StackTraceGetFrames(scratch.arena, /*depth limit*/ 128);
(void)frames; (void)frames;
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_Str8FromArena // NOTE: DN_Str8FromArena
@ -693,10 +686,11 @@ void DN_Demo()
// The returned string's 'size' member variable does *not* include this // The returned string's 'size' member variable does *not* include this
// additional null-terminating byte. // additional null-terminating byte.
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8FromArena(tmem.arena, /*size*/ 1, DN_ZMem_Yes); DN_Str8 string = DN_Str8FromArena(scratch.arena, /*size*/ 1, DN_ZMem_Yes);
DN_Assert(string.size == 1); DN_Assert(string.size == 1);
DN_Assert(string.data[string.size] == 0); // It is null-terminated! DN_Assert(string.data[string.size] == 0); // It is null-terminated!
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_Str8BSplit // NOTE: DN_Str8BSplit
@ -773,14 +767,15 @@ void DN_Demo()
// always be a newly allocated copy, irrespective of if any replacements // always be a newly allocated copy, irrespective of if any replacements
// were done or not. // were done or not.
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8Replace(/*string*/ DN_Str8Lit("Foo Foo Bar"), DN_Str8 string = DN_Str8Replace(/*string*/ DN_Str8Lit("Foo Foo Bar"),
/*find*/ DN_Str8Lit("Foo"), /*find*/ DN_Str8Lit("Foo"),
/*replace*/ DN_Str8Lit("Moo"), /*replace*/ DN_Str8Lit("Moo"),
/*start_index*/ 1, /*start_index*/ 1,
/*arena*/ tmem.arena, /*arena*/ scratch.arena,
/*eq_case*/ DN_Str8EqCase_Sensitive); /*eq_case*/ DN_Str8EqCase_Sensitive);
DN_Assert(DN_Str8Eq(string, DN_Str8Lit("Foo Moo Bar"))); DN_Assert(DN_Str8Eq(string, DN_Str8Lit("Foo Moo Bar")));
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_Str8Segment // NOTE: DN_Str8Segment
@ -791,18 +786,19 @@ void DN_Demo()
// Reverse segment delimits the string counting 'segment_size' from the back // Reverse segment delimits the string counting 'segment_size' from the back
// of the string. // of the string.
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8Segment(tmem.arena, /*string*/ DN_Str8Lit("123456789"), /*segment_size*/ 3, /*segment_char*/ ','); DN_Str8 string = DN_Str8Segment(scratch.arena, /*string*/ DN_Str8Lit("123456789"), /*segment_size*/ 3, /*segment_char*/ ',');
DN_Assert(DN_Str8Eq(string, DN_Str8Lit("123,456,789"))); DN_Assert(DN_Str8Eq(string, DN_Str8Lit("123,456,789")));
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_Str8Split // NOTE: DN_Str8Split
{ {
// Splits the string at each delimiter into substrings occuring prior and // Splits the string at each delimiter into substrings occuring prior and
// after until the next delimiter. // after until the next delimiter.
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
{ {
DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ tmem.arena, DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ scratch.arena,
/*string*/ DN_Str8Lit("192.168.8.1"), /*string*/ DN_Str8Lit("192.168.8.1"),
/*delimiter*/ DN_Str8Lit("."), /*delimiter*/ DN_Str8Lit("."),
/*mode*/ DN_Str8SplitIncludeEmptyStrings_No); /*mode*/ DN_Str8SplitIncludeEmptyStrings_No);
@ -816,7 +812,7 @@ void DN_Demo()
// You can include empty strings that occur when splitting by setting // You can include empty strings that occur when splitting by setting
// the split mode to include empty strings. // the split mode to include empty strings.
{ {
DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ tmem.arena, DN_Str8SplitResult splits = DN_Str8SplitArena(/*arena*/ scratch.arena,
/*string*/ DN_Str8Lit("a--b"), /*string*/ DN_Str8Lit("a--b"),
/*delimiter*/ DN_Str8Lit("-"), /*delimiter*/ DN_Str8Lit("-"),
/*mode*/ DN_Str8SplitIncludeEmptyStrings_Yes); /*mode*/ DN_Str8SplitIncludeEmptyStrings_Yes);
@ -825,6 +821,8 @@ void DN_Demo()
DN_Str8Eq(splits.data[1], DN_Str8Lit("")) && DN_Str8Eq(splits.data[1], DN_Str8Lit("")) &&
DN_Str8Eq(splits.data[2], DN_Str8Lit("b"))); DN_Str8Eq(splits.data[2], DN_Str8Lit("b")));
} }
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_I64FromStr8, DN_U64FromStr8 // NOTE: DN_I64FromStr8, DN_U64FromStr8
@ -931,7 +929,7 @@ void DN_Demo()
// NOTE: DN_ThreadContext // NOTE: DN_ThreadContext
// //
// Each thread is assigned in their thread-local storage (TLS) tmem and // Each thread is assigned in their thread-local storage (TLS) scratch and
// permanent arena allocators. These can be used for allocations with a // permanent arena allocators. These can be used for allocations with a
// lifetime scoped to the lexical scope or for storing data permanently // lifetime scoped to the lexical scope or for storing data permanently
// using the arena paradigm. // using the arena paradigm.
@ -939,40 +937,43 @@ void DN_Demo()
// TLS in this implementation is implemented using the `thread_local` C/C++ // TLS in this implementation is implemented using the `thread_local` C/C++
// keyword. // keyword.
// //
// 99% of the time you will want DN_OS_TLSTMem(...) which returns you a // 99% of the time you will want DN_OS_TLSTMem...) which returns you a
// temporary arena for function lifetime allocations. On scope exit, the // temporary arena for function lifetime allocations. On scope exit, the
// arena is cleared out. // arena is cleared out.
// //
// This library's paradigm revolves heavily around arenas including tmem // This library's paradigm revolves heavily around arenas including scratch
// arenas into child functions for temporary calculations. If an arena is // arenas into child functions for temporary calculations. If an arena is
// passed into a function, this poses a problem sometimes known as // passed into a function, this poses a problem sometimes known as
// 'arena aliasing'. // 'arena aliasing'.
// //
// If an arena aliases another arena (e.g. the arena passed in) is the same // If an arena aliases another arena (e.g. the arena passed in) is the same
// as the tmem arena requested in the function, we risk the tmem arena // as the scratch arena requested in the function, we risk the scratch arena
// on scope exit deallocating memory belonging to the caller. // on scope exit deallocating memory belonging to the caller.
// //
// To avoid this we the 'DN_OS_TLSTMem(...)' API takes in a list of arenas // To avoid this we the 'DN_OS_TLSTMem...)' API takes in a list of arenas
// to ensure that we provide a tmem arena that *won't* alias with the // to ensure that we provide a scratch arena that *won't* alias with the
// caller's arena. If arena aliasing occurs, with ASAN on, generally // caller's arena. If arena aliasing occurs, with ASAN on, generally
// the library will trap and report use-after-poison once violated. // the library will trap and report use-after-poison once violated.
{ {
DN_OSTLSTMem tmem_a = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch_a = DN_TCScratchBegin(nullptr, 0);
// Now imagine we call a function where we pass tmem_a.arena down // Now imagine we call a function where we pass scratch_a.arena down
// into it .. If we call tmem again, we need to pass in the arena // into it .. If we call scratch again, we need to pass in the arena
// to prevent aliasing. // to prevent aliasing.
DN_OSTLSTMem tmem_b = DN_OS_TLSTMem(tmem_a.arena); DN_TCScratch scratch_b = DN_TCScratchBegin(&scratch_a.arena, 1);
DN_Assert(tmem_a.arena != tmem_b.arena); DN_Assert(scratch_a.arena != scratch_b.arena);
DN_TCScratchEnd(&scratch_b);
DN_TCScratchEnd(&scratch_a);
} }
// @proc DN_Thread_GetTMem // @proc DN_Thread_Getscratch
// @desc Retrieve the per-thread temporary arena allocator that is reset on scope // @desc Retrieve the per-thread temporary arena allocator that is reset on scope
// exit. // exit.
// The tmem arena must be deconflicted with any existing arenas in the // The scratch arena must be deconflicted with any existing arenas in the
// function to avoid trampling over each other's memory. Consider the situation // function to avoid trampling over each other's memory. Consider the situation
// where the tmem arena is passed into the function. Inside the function, if // where the scratch arena is passed into the function. Inside the function, if
// the same arena is reused then, if both arenas allocate, when the inner arena // the same arena is reused then, if both arenas allocate, when the inner arena
// is reset, this will undo the passed in arena's allocations in the function. // is reset, this will undo the passed in arena's allocations in the function.
@ -988,9 +989,10 @@ void DN_Demo()
// NOTE: DN_CVT_AgeFromU64 // NOTE: DN_CVT_AgeFromU64
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8x128 string = DN_AgeStr8FromSecF64(DN_SecFromHours(2) + DN_SecFromMins(30), DN_AgeUnit_All); DN_Str8x128 string = DN_AgeStr8FromSecF64(DN_SecFromHours(2) + DN_SecFromMins(30), DN_AgeUnit_All);
DN_Assert(DN_Str8Eq(DN_Str8FromStruct(&string), DN_Str8Lit("2h 30m"))); DN_Assert(DN_Str8Eq(DN_Str8FromStruct(&string), DN_Str8Lit("2h 30m")));
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_VArray // NOTE: DN_VArray
@ -1017,21 +1019,21 @@ void DN_Demo()
// In addition to no realloc on expansion or shrinking. // In addition to no realloc on expansion or shrinking.
// //
{ {
// NOTE: DN_VArray_Init // NOTE: DN_OS_VArrayInit
// NOTE: DN_VArray_InitByteSize // NOTE: DN_OS_VArrayInitByteSize
// //
// Initialise an array with the requested byte size or item capacity // Initialise an array with the requested byte size or item capacity
// respectively. The returned array may have a higher capacity than the // respectively. The returned array may have a higher capacity than the
// requested amount since requested memory from the OS may have a certain // requested amount since requested memory from the OS may have a certain
// alignment requirement (e.g. on Windows reserve/commit are 64k/4k // alignment requirement (e.g. on Windows reserve/commit are 64k/4k
// aligned). // aligned).
DN_VArray<int> array = DN_VArray_Init<int>(1024); DN_VArray<int> array = DN_OS_VArrayInit<int>(1024);
DN_Assert(array.size == 0 && array.max >= 1024); DN_Assert(array.size == 0 && array.max >= 1024);
// NOTE: DN_VArray_Make // NOTE: DN_OS_VArrayMake
// NOTE: DN_VArray_Add // NOTE: DN_OS_VArrayAdd
// NOTE: DN_VArray_MakeArray // NOTE: DN_OS_VArrayMakeArray
// NOTE: DN_VArray_AddArray // NOTE: DN_OS_VArrayAddArray
// //
// Allocate items from the array where: // Allocate items from the array where:
// //
@ -1040,11 +1042,11 @@ void DN_Demo()
// //
// If the array has run out of capacity or was never initialised, a null // If the array has run out of capacity or was never initialised, a null
// pointer is returned. // pointer is returned.
int *item = DN_VArray_Add(&array, 0xCAFE); int *item = DN_OS_VArrayAdd(&array, 0xCAFE);
DN_Assert(*item == 0xCAFE && array.size == 1); DN_Assert(*item == 0xCAFE && array.size == 1);
// NOTE: DN_VArray_AddCArray // NOTE: DN_OS_VArrayAddCArray
DN_VArray_AddCArray(&array, {1, 2, 3}); DN_OS_VArrayAddCArray(&array, {1, 2, 3});
DN_Assert(array.size == 4); DN_Assert(array.size == 4);
// TODO(doyle): There's a bug here with the negative erase! // TODO(doyle): There's a bug here with the negative erase!
@ -1054,7 +1056,7 @@ void DN_Demo()
if (index != 1) if (index != 1)
continue; continue;
// NOTE: DN_VArray_EraseRange // NOTE: DN_OS_VArrayEraseRange
// //
// Erase the next 'count' items at 'begin_index' in the array. // Erase the next 'count' items at 'begin_index' in the array.
// 'count' can be positive or negative which dictates the if we // 'count' can be positive or negative which dictates the if we
@ -1072,7 +1074,7 @@ void DN_Demo()
// TODO(doyle): There's a bug here! This doesn't work. // TODO(doyle): There's a bug here! This doesn't work.
// Erase index 0 with the negative count! // Erase index 0 with the negative count!
DN_ArrayEraseResult erase_result = DN_VArray_EraseRange(&array, DN_ArrayEraseResult erase_result = DN_OS_VArrayEraseRange(&array,
/*begin_index*/ index, /*begin_index*/ index,
/*count*/ -1, /*count*/ -1,
/*erase*/ DN_ArrayErase_Stable); /*erase*/ DN_ArrayErase_Stable);
@ -1089,7 +1091,7 @@ void DN_Demo()
array.data[2] == 3); array.data[2] == 3);
#endif #endif
// NOTE: DN_VArray_Reserve // NOTE: DN_OS_VArrayReserve
// //
// Ensure that the requested number of items are backed by physical pages // Ensure that the requested number of items are backed by physical pages
// from the OS. Calling this pre-emptively will minimise syscalls into the // from the OS. Calling this pre-emptively will minimise syscalls into the
@ -1097,9 +1099,9 @@ void DN_Demo()
// in bytes to the allocation granularity of OS allocation APIs hence the // in bytes to the allocation granularity of OS allocation APIs hence the
// reserved space may be greater than the requested amount (e.g. this is 4k // reserved space may be greater than the requested amount (e.g. this is 4k
// on Windows). // on Windows).
DN_VArray_Reserve(&array, /*count*/ 8); DN_OS_VArrayReserve(&array, /*count*/ 8);
DN_VArray_Deinit(&array); DN_OS_VArrayDeinit(&array);
} }
// NOTE: DN_W32_LastError // NOTE: DN_W32_LastError
@ -1108,13 +1110,14 @@ void DN_Demo()
if (0) { if (0) {
// Generate the error string for the last Win32 API called that return // Generate the error string for the last Win32 API called that return
// an error value. // an error value.
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_W32Error get_last_error = DN_W32_LastError(tmem.arena); DN_OSW32Error get_last_error = DN_OS_W32LastError(scratch.arena);
printf("Error (%lu): %.*s", get_last_error.code, DN_Str8PrintFmt(get_last_error.msg)); printf("Error (%lu): %.*s", get_last_error.code, DN_Str8PrintFmt(get_last_error.msg));
// Alternatively, pass in the error code directly // Alternatively, pass in the error code directly
DN_W32Error error_msg_for_code = DN_W32_ErrorCodeToMsg(tmem.arena, /*error_code*/ 0); DN_OSW32Error error_msg_for_code = DN_OS_W32ErrorCodeToMsg(scratch.arena, /*error_code*/ 0);
printf("Error (%lu): %.*s", error_msg_for_code.code, DN_Str8PrintFmt(error_msg_for_code.msg)); printf("Error (%lu): %.*s", error_msg_for_code.code, DN_Str8PrintFmt(error_msg_for_code.msg));
DN_TCScratchEnd(&scratch);
} }
// NOTE: DN_W32_MakeProcessDPIAware // NOTE: DN_W32_MakeProcessDPIAware

View File

@ -1,269 +0,0 @@
#define DN_HASH_CPP
#if defined(_CLANGD)
#include "dn_hash.h"
#endif
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$\ $$\ $$$$$$\ $$$$$$\ $$\ $$\
// $$ | $$ |$$ __$$\ $$ __$$\ $$ | $$ |
// $$ | $$ |$$ / $$ |$$ / \__|$$ | $$ |
// $$$$$$$$ |$$$$$$$$ |\$$$$$$\ $$$$$$$$ |
// $$ __$$ |$$ __$$ | \____$$\ $$ __$$ |
// $$ | $$ |$$ | $$ |$$\ $$ |$$ | $$ |
// $$ | $$ |$$ | $$ |\$$$$$$ |$$ | $$ |
// \__| \__|\__| \__| \______/ \__| \__|
//
// dn_hash.cpp
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
// NOTE: DN_FNV1A
// Default values recommended by: http://isthe.com/chongo/tech/comp/fnv/
DN_API DN_U32 DN_FNV1A32_Iterate(void const *bytes, DN_USize size, DN_U32 hash)
{
auto buffer = DN_Cast(DN_U8 const *)bytes;
for (DN_USize i = 0; i < size; i++)
hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/;
return hash;
}
DN_API DN_U32 DN_FNV1A32_Hash(void const *bytes, DN_USize size)
{
DN_U32 result = DN_FNV1A32_Iterate(bytes, size, DN_FNV1A32_SEED);
return result;
}
DN_API DN_U64 DN_FNV1A64_Iterate(void const *bytes, DN_USize size, DN_U64 hash)
{
auto buffer = DN_Cast(DN_U8 const *)bytes;
for (DN_USize i = 0; i < size; i++)
hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/;
return hash;
}
DN_API DN_U64 DN_FNV1A64_Hash(void const *bytes, DN_USize size)
{
DN_U64 result = DN_FNV1A64_Iterate(bytes, size, DN_FNV1A64_SEED);
return result;
}
// NOTE: DN_MurmurHash3 ////////////////////////////////////////////////////////////////////////////
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
#define DN_MMH3_ROTL32(x, y) _rotl(x, y)
#define DN_MMH3_ROTL64(x, y) _rotl64(x, y)
#else
#define DN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y)))
#define DN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y)))
#endif
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
DN_FORCE_INLINE DN_U32 DN_MurmurHash3_GetBlock32(DN_U32 const *p, int i)
{
return p[i];
}
DN_FORCE_INLINE DN_U64 DN_MurmurHash3_GetBlock64(DN_U64 const *p, int i)
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
DN_FORCE_INLINE DN_U32 DN_MurmurHash3_FMix32(DN_U32 h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
DN_FORCE_INLINE DN_U64 DN_MurmurHash3_FMix64(DN_U64 k)
{
k ^= k >> 33;
k *= 0xff51afd7ed558ccd;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53;
k ^= k >> 33;
return k;
}
DN_API DN_U32 DN_MurmurHash3_x86U32(void const *key, int len, DN_U32 seed)
{
const DN_U8 *data = (const DN_U8 *)key;
const int nblocks = len / 4;
DN_U32 h1 = seed;
const DN_U32 c1 = 0xcc9e2d51;
const DN_U32 c2 = 0x1b873593;
//----------
// body
const DN_U32 *blocks = (const DN_U32 *)(data + nblocks * 4);
for (int i = -nblocks; i; i++)
{
DN_U32 k1 = DN_MurmurHash3_GetBlock32(blocks, i);
k1 *= c1;
k1 = DN_MMH3_ROTL32(k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = DN_MMH3_ROTL32(h1, 13);
h1 = h1 * 5 + 0xe6546b64;
}
//----------
// tail
const DN_U8 *tail = (const DN_U8 *)(data + nblocks * 4);
DN_U32 k1 = 0;
switch (len & 3)
{
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = DN_MMH3_ROTL32(k1, 15);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h1 = DN_MurmurHash3_FMix32(h1);
return h1;
}
DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128(void const *key, int len, DN_U32 seed)
{
const DN_U8 *data = (const DN_U8 *)key;
const int nblocks = len / 16;
DN_U64 h1 = seed;
DN_U64 h2 = seed;
const DN_U64 c1 = 0x87c37b91114253d5;
const DN_U64 c2 = 0x4cf5ad432745937f;
//----------
// body
const DN_U64 *blocks = (const DN_U64 *)(data);
for (int i = 0; i < nblocks; i++)
{
DN_U64 k1 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 0);
DN_U64 k2 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 1);
k1 *= c1;
k1 = DN_MMH3_ROTL64(k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = DN_MMH3_ROTL64(h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
k2 *= c2;
k2 = DN_MMH3_ROTL64(k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = DN_MMH3_ROTL64(h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
//----------
// tail
const DN_U8 *tail = (const DN_U8 *)(data + nblocks * 16);
DN_U64 k1 = 0;
DN_U64 k2 = 0;
switch (len & 15)
{
case 15:
k2 ^= ((DN_U64)tail[14]) << 48;
case 14:
k2 ^= ((DN_U64)tail[13]) << 40;
case 13:
k2 ^= ((DN_U64)tail[12]) << 32;
case 12:
k2 ^= ((DN_U64)tail[11]) << 24;
case 11:
k2 ^= ((DN_U64)tail[10]) << 16;
case 10:
k2 ^= ((DN_U64)tail[9]) << 8;
case 9:
k2 ^= ((DN_U64)tail[8]) << 0;
k2 *= c2;
k2 = DN_MMH3_ROTL64(k2, 33);
k2 *= c1;
h2 ^= k2;
case 8:
k1 ^= ((DN_U64)tail[7]) << 56;
case 7:
k1 ^= ((DN_U64)tail[6]) << 48;
case 6:
k1 ^= ((DN_U64)tail[5]) << 40;
case 5:
k1 ^= ((DN_U64)tail[4]) << 32;
case 4:
k1 ^= ((DN_U64)tail[3]) << 24;
case 3:
k1 ^= ((DN_U64)tail[2]) << 16;
case 2:
k1 ^= ((DN_U64)tail[1]) << 8;
case 1:
k1 ^= ((DN_U64)tail[0]) << 0;
k1 *= c1;
k1 = DN_MMH3_ROTL64(k1, 31);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 = DN_MurmurHash3_FMix64(h1);
h2 = DN_MurmurHash3_FMix64(h2);
h1 += h2;
h2 += h1;
DN_MurmurHash3 result = {};
result.e[0] = h1;
result.e[1] = h2;
return result;
}

View File

@ -1,49 +0,0 @@
#if !defined(DN_HASH_H)
#define DN_HASH_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#endif
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$\ $$\ $$$$$$\ $$$$$$\ $$\ $$\
// $$ | $$ |$$ __$$\ $$ __$$\ $$ | $$ |
// $$ | $$ |$$ / $$ |$$ / \__|$$ | $$ |
// $$$$$$$$ |$$$$$$$$ |\$$$$$$\ $$$$$$$$ |
// $$ __$$ |$$ __$$ | \____$$\ $$ __$$ |
// $$ | $$ |$$ | $$ |$$\ $$ |$$ | $$ |
// $$ | $$ |$$ | $$ |\$$$$$$ |$$ | $$ |
// \__| \__|\__| \__| \______/ \__| \__|
//
// dn_hash.h -- Hashing functions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
// NOTE: DN_FNV1A //////////////////////////////////////////////////////////////////////////////////
#if !defined(DN_FNV1A32_SEED)
#define DN_FNV1A32_SEED 2166136261U
#endif
#if !defined(DN_FNV1A64_SEED)
#define DN_FNV1A64_SEED 14695981039346656037ULL
#endif
// NOTE: DN_MurmurHash3 ////////////////////////////////////////////////////////////////////////////
struct DN_MurmurHash3 { uint64_t e[2]; };
// NOTE: DN_FNV1A //////////////////////////////////////////////////////////////////////////////////
DN_API uint32_t DN_FNV1A32_Hash (void const *bytes, DN_USize size);
DN_API uint64_t DN_FNV1A64_Hash (void const *bytes, DN_USize size);
DN_API uint32_t DN_FNV1A32_Iterate (void const *bytes, DN_USize size, uint32_t hash);
DN_API uint64_t DN_FNV1A64_Iterate (void const *bytes, DN_USize size, uint64_t hash);
// NOTE: DN_MurmurHash3 ////////////////////////////////////////////////////////////////////////////
DN_API uint32_t DN_MurmurHash3_x86U32 (void const *key, int len, uint32_t seed);
DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128 (void const *key, int len, uint32_t seed);
#define DN_MurmurHash3_x64U128AsU64(key, len, seed) (DN_MurmurHash3_x64U128(key, len, seed).e[0])
#define DN_MurmurHash3_x64U128AsU32(key, len, seed) (DN_Cast(uint32_t)DN_MurmurHash3_x64U128(key, len, seed).e[0])
#endif // !defined(DN_HASH_H)

View File

@ -4,102 +4,6 @@
#include "dn_helpers.h" #include "dn_helpers.h"
#endif #endif
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$\ $$\ $$$$$$$$\ $$\ $$$$$$$\ $$$$$$$$\ $$$$$$$\ $$$$$$\
// $$ | $$ |$$ _____|$$ | $$ __$$\ $$ _____|$$ __$$\ $$ __$$\
// $$ | $$ |$$ | $$ | $$ | $$ |$$ | $$ | $$ |$$ / \__|
// $$$$$$$$ |$$$$$\ $$ | $$$$$$$ |$$$$$\ $$$$$$$ |\$$$$$$\
// $$ __$$ |$$ __| $$ | $$ ____/ $$ __| $$ __$$< \____$$\
// $$ | $$ |$$ | $$ | $$ | $$ | $$ | $$ |$$\ $$ |
// $$ | $$ |$$$$$$$$\ $$$$$$$$\ $$ | $$$$$$$$\ $$ | $$ |\$$$$$$ |
// \__| \__|\________|\________|\__| \________|\__| \__| \______/
//
// dn_helpers.cpp
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
// NOTE: DN_PCG32 //////////////////////////////////////////////////////////////////////////////////
#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL
#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL
DN_API DN_PCG32 DN_PCG32_Init(uint64_t seed)
{
DN_PCG32 result = {};
DN_PCG32_Next(&result);
result.state += seed;
DN_PCG32_Next(&result);
return result;
}
DN_API uint32_t DN_PCG32_Next(DN_PCG32 *rng)
{
uint64_t state = rng->state;
rng->state = state * DN_PCG_DEFAULT_MULTIPLIER_64 + DN_PCG_DEFAULT_INCREMENT_64;
// XSH-RR
uint32_t value = (uint32_t)((state ^ (state >> 18)) >> 27);
int rot = state >> 59;
return rot ? (value >> rot) | (value << (32 - rot)) : value;
}
DN_API uint64_t DN_PCG32_Next64(DN_PCG32 *rng)
{
uint64_t value = DN_PCG32_Next(rng);
value <<= 32;
value |= DN_PCG32_Next(rng);
return value;
}
DN_API uint32_t DN_PCG32_Range(DN_PCG32 *rng, uint32_t low, uint32_t high)
{
uint32_t bound = high - low;
uint32_t threshold = -(int32_t)bound % bound;
for (;;) {
uint32_t r = DN_PCG32_Next(rng);
if (r >= threshold)
return low + (r % bound);
}
}
DN_API float DN_PCG32_NextF32(DN_PCG32 *rng)
{
uint32_t x = DN_PCG32_Next(rng);
return (float)(int32_t)(x >> 8) * 0x1.0p-24f;
}
DN_API double DN_PCG32_NextF64(DN_PCG32 *rng)
{
uint64_t x = DN_PCG32_Next64(rng);
return (double)(int64_t)(x >> 11) * 0x1.0p-53;
}
DN_API void DN_PCG32_Advance(DN_PCG32 *rng, uint64_t delta)
{
uint64_t cur_mult = DN_PCG_DEFAULT_MULTIPLIER_64;
uint64_t cur_plus = DN_PCG_DEFAULT_INCREMENT_64;
uint64_t acc_mult = 1;
uint64_t acc_plus = 0;
while (delta != 0) {
if (delta & 1) {
acc_mult *= cur_mult;
acc_plus = acc_plus * cur_mult + cur_plus;
}
cur_plus = (cur_mult + 1) * cur_plus;
cur_mult *= cur_mult;
delta >>= 1;
}
rng->state = acc_mult * rng->state + acc_plus;
}
#if !defined(DN_NO_JSON_BUILDER)
// NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
DN_API DN_JSONBuilder DN_JSONBuilder_Init(DN_Arena *arena, int spaces_per_indent) DN_API DN_JSONBuilder DN_JSONBuilder_Init(DN_Arena *arena, int spaces_per_indent)
{ {
DN_JSONBuilder result = {}; DN_JSONBuilder result = {};
@ -167,9 +71,10 @@ DN_API void DN_JSONBuilder_KeyValue(DN_JSONBuilder *builder, DN_Str8 key, DN_Str
DN_API void DN_JSONBuilder_KeyValueFV(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, va_list args) DN_API void DN_JSONBuilder_KeyValueFV(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, va_list args)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(builder->string_builder.arena); DN_TCScratch scratch = DN_TCScratchBegin(&builder->string_builder.arena, 1);
DN_Str8 value = DN_Str8FromFmtVArena(tmem.arena, value_fmt, args); DN_Str8 value = DN_Str8FromFmtVArena(scratch.arena, value_fmt, args);
DN_JSONBuilder_KeyValue(builder, key, value); DN_JSONBuilder_KeyValue(builder, key, value);
DN_TCScratchEnd(&scratch);
} }
DN_API void DN_JSONBuilder_KeyValueF(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...) DN_API void DN_JSONBuilder_KeyValueF(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...)
@ -246,4 +151,3 @@ DN_API void DN_JSONBuilder_BoolNamed(DN_JSONBuilder *builder, DN_Str8 key, bool
DN_Str8 value_string = value ? DN_Str8Lit("true") : DN_Str8Lit("false"); DN_Str8 value_string = value ? DN_Str8Lit("true") : DN_Str8Lit("false");
DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data); DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data);
} }
#endif // !defined(DN_NO_JSON_BUILDER)

View File

@ -2,16 +2,7 @@
#define DN_HELPERS_H #define DN_HELPERS_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#include "dn_math.h"
#endif
#if !defined(DN_BASE_H)
#error dn_base_inc.h must be included before this
#endif
#if !defined(DN_MATH_H)
#error dn_math.h must be included before this
#endif #endif
/* /*
@ -31,11 +22,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
*/ */
// NOTE: DN_PCG32 //////////////////////////////////////////////////////////////////////////////////
struct DN_PCG32 { uint64_t state; };
#if !defined(DN_NO_JSON_BUILDER) #if !defined(DN_NO_JSON_BUILDER)
// NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
enum DN_JSONBuilderItem enum DN_JSONBuilderItem
{ {
DN_JSONBuilderItem_Empty, DN_JSONBuilderItem_Empty,
@ -100,15 +87,6 @@ struct DN_BinarySearchResult
template <typename T> template <typename T>
using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context); using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context);
// NOTE: DN_PCG32 //////////////////////////////////////////////////////////////////////////////////
DN_API DN_PCG32 DN_PCG32_Init (uint64_t seed);
DN_API uint32_t DN_PCG32_Next (DN_PCG32 *rng);
DN_API uint64_t DN_PCG32_Next64 (DN_PCG32 *rng);
DN_API uint32_t DN_PCG32_Range (DN_PCG32 *rng, uint32_t low, uint32_t high);
DN_API DN_F32 DN_PCG32_NextF32 (DN_PCG32 *rng);
DN_API DN_F64 DN_PCG32_NextF64 (DN_PCG32 *rng);
DN_API void DN_PCG32_Advance (DN_PCG32 *rng, uint64_t delta);
#if !defined(DN_NO_JSON_BUILDER) #if !defined(DN_NO_JSON_BUILDER)
// NOTE: DN_JSONBuilder //////////////////////////////////////////////////////////////////////////// // NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
#define DN_JSONBuilder_Object(builder) \ #define DN_JSONBuilder_Object(builder) \

View File

@ -407,7 +407,7 @@ void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site)
json_string_s const *key = curr->name; json_string_s const *key = curr->name;
if (it->flags & json_parse_flags_allow_location_information) { if (it->flags & json_parse_flags_allow_location_information) {
json_string_ex_s const *info = DN_Cast(json_string_ex_s const *)key; json_string_ex_s const *info = DN_Cast(json_string_ex_s const *)key;
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning),
call_site, call_site,
"Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]", "Unknown key-value pair in object [loc=%zu:%zu, key=%.*s, value=%.*s]",
info->line_no, info->line_no,
@ -417,7 +417,7 @@ void DN_JSON_ItErrorUnknownKeyValue_(DN_JSONIt *it, DN_CallSite call_site)
DN_Cast(int) value_type_size, DN_Cast(int) value_type_size,
value_type); value_type);
} else { } else {
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning),
call_site, call_site,
"Unknown key-value pair in object [key=%.*s, value=%.*s]", "Unknown key-value pair in object [key=%.*s, value=%.*s]",
DN_Cast(int) key->string_size, DN_Cast(int) key->string_size,

View File

@ -2,7 +2,7 @@
#define DN_JSON_H #define DN_JSON_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#include "../External/json.h" #include "../External/json.h"
#endif #endif
@ -10,13 +10,13 @@
#error Sheredom json.h (github.com/sheredom/json.h) must be included before this file #error Sheredom json.h (github.com/sheredom/json.h) must be included before this file
#endif #endif
// NOTE: DN_JSON ////////////////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON
void *DN_JSON_ArenaAllocFunc (void *user_data, size_t count); void *DN_JSON_ArenaAllocFunc (void *user_data, size_t count);
char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size); char const *DN_JSON_TypeEnumCString(json_type_e type, size_t *size);
bool DN_JSON_String8Cmp (json_string_s const *lhs, DN_Str8 rhs); bool DN_JSON_String8Cmp (json_string_s const *lhs, DN_Str8 rhs);
// NOTE: DN_JSON_It ///////////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_It
enum DN_JSONItEntryType enum DN_JSONItEntryType
{ {
DN_JSON_ItEntryTypeObjElement, DN_JSON_ItEntryTypeObjElement,
@ -42,7 +42,7 @@ struct DN_JSONIt
DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json); DN_JSONIt DN_JSON_LoadFileToIt(DN_Arena *arena, DN_Str8 json);
// NOTE: DN_JSON_ItPush/Pop ///////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItPush/Pop
bool DN_JSON_ItPushObjElement (DN_JSONIt *it, json_object_element_s *element); bool DN_JSON_ItPushObjElement (DN_JSONIt *it, json_object_element_s *element);
bool DN_JSON_ItPushObj (DN_JSONIt *it, json_object_s *obj); bool DN_JSON_ItPushObj (DN_JSONIt *it, json_object_s *obj);
bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element); bool DN_JSON_ItPushArrayElement(DN_JSONIt *it, json_array_element_s *element);
@ -50,7 +50,7 @@ bool DN_JSON_ItPushArray (DN_JSONIt *it, json_value_s *value);
bool DN_JSON_ItPushValue (DN_JSONIt *it, json_value_s *value); bool DN_JSON_ItPushValue (DN_JSONIt *it, json_value_s *value);
void DN_JSON_ItPop (DN_JSONIt *it); void DN_JSON_ItPop (DN_JSONIt *it);
// NOTE: DN_JSON_It tree navigation ///////////////////////////////////////////////////////// // NOTE: DN_JSON_It tree navigation
json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it); json_value_s *DN_JSON_ItPushCurrValue(DN_JSONIt *it);
bool DN_JSON_ItNext(DN_JSONIt *it); bool DN_JSON_ItNext(DN_JSONIt *it);
@ -58,12 +58,12 @@ bool DN_JSON_ItNext(DN_JSONIt *it);
for(void *DN_UniqueName(ptr) = DN_JSON_ItPushCurrValue(it); DN_UniqueName(ptr); DN_JSON_ItPop(it), DN_UniqueName(ptr) = nullptr) \ for(void *DN_UniqueName(ptr) = DN_JSON_ItPushCurrValue(it); DN_UniqueName(ptr); DN_JSON_ItPop(it), DN_UniqueName(ptr) = nullptr) \
while (DN_JSON_ItNext(it)) while (DN_JSON_ItNext(it))
// NOTE: DN_JSON_ItCurr ///////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItCurr
DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it); DN_JSONItEntry *DN_JSON_ItCurr(DN_JSONIt *it);
json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it); json_value_s *DN_JSON_ItCurrValue(DN_JSONIt *it);
json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it); json_object_element_s *DN_JSON_ItCurrObjElement(DN_JSONIt *it);
// NOTE: DN_JSON_ItValueIs ////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItValueIs
json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type); json_value_s *DN_JSON_ItValueIs(DN_JSONIt *it, json_type_e type);
json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it); json_object_s *DN_JSON_ItValueIsObj(DN_JSONIt *it);
json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it); json_array_s *DN_JSON_ItValueIsArray(DN_JSONIt *it);
@ -74,7 +74,7 @@ json_value_s *DN_JSON_ItValueIsNull(DN_JSONIt *it);
size_t DN_JSON_ItValueArraySize(DN_JSONIt *it); size_t DN_JSON_ItValueArraySize(DN_JSONIt *it);
// NOTE: DN_JSON_ItKeyValueIs /////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItKeyValueIs
DN_Str8 DN_JSON_ItKey(DN_JSONIt *it); DN_Str8 DN_JSON_ItKey(DN_JSONIt *it);
bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key); bool DN_JSON_ItKeyIs(DN_JSONIt *it, DN_Str8 key);
json_object_s *DN_JSON_ItKeyValueIsObj(DN_JSONIt *it, DN_Str8 key); json_object_s *DN_JSON_ItKeyValueIsObj(DN_JSONIt *it, DN_Str8 key);
@ -84,7 +84,7 @@ json_number_s *DN_JSON_ItKeyValueIsNumber(DN_JSONIt *it, DN_Str8 key);
json_value_s *DN_JSON_ItKeyValueIsBool(DN_JSONIt *it, DN_Str8 key); json_value_s *DN_JSON_ItKeyValueIsBool(DN_JSONIt *it, DN_Str8 key);
json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key); json_value_s *DN_JSON_ItKeyValueIsNull(DN_JSONIt *it, DN_Str8 key);
// NOTE: DN_JSON_ItValueTo ////////////////////////////////////////////////////////////////// // NOTE: DN_JSON_ItValueTo
DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it); DN_Str8 DN_JSON_ItValueToString(DN_JSONIt *it);
int64_t DN_JSON_ItValueToI64(DN_JSONIt *it); int64_t DN_JSON_ItValueToI64(DN_JSONIt *it);
uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it); uint64_t DN_JSON_ItValueToU64(DN_JSONIt *it);

View File

@ -1255,18 +1255,18 @@ DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset)
return result; return result;
} }
DN_API DN_V2F32 DN_M2x3_ScaleGet(DN_M2x3 m2x3)
{
DN_V2F32 result = DN_V2F32_From2N(m2x3.row[0][0], m2x3.row[1][1]);
return result;
}
DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale)
{ {
DN_M2x3 result = { DN_M2x3 result = {{
{ scale.x, 0, 0,
scale.x, 0, scale.y, 0,
0, }};
0,
0,
scale.y,
0,
}
};
return result; return result;
} }

View File

@ -2,7 +2,7 @@
#define DN_MATH_H #define DN_MATH_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
DN_MSVC_WARNING_PUSH DN_MSVC_WARNING_PUSH
@ -34,25 +34,25 @@ union DN_V2F32
struct { DN_F32 w, h; }; struct { DN_F32 w, h; };
DN_F32 data[2]; DN_F32 data[2];
}; };
DN_DArrayStructDecl(DN_V2F32);
union DN_V3F32 union DN_V3F32
{ {
struct { DN_F32 x, y, z; }; struct { DN_F32 x, y, z; };
struct { DN_F32 r, g, b; }; struct { DN_F32 r, g, b; };
DN_F32 data[3]; DN_V2F32 xy;
DN_F32 data[3];
}; };
union DN_V4F32 union DN_V4F32
{ {
struct { DN_F32 x, y, z, w; }; struct { DN_F32 x, y, z, w; };
struct { DN_F32 r, g, b, a; }; struct { DN_F32 r, g, b, a; };
#if !defined(DN_NO_V3)
DN_V3F32 rgb; DN_V3F32 rgb;
DN_V3F32 xyz; DN_V3F32 xyz;
#endif DN_F32 data[4];
DN_F32 data[4];
}; };
DN_DArrayStructDecl(DN_V4F32);
DN_MSVC_WARNING_POP DN_MSVC_WARNING_POP
struct DN_M4 struct DN_M4
@ -137,10 +137,10 @@ DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN
DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b);
DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a);
#define DN_V2U16_Zero DN_Literal(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} #define DN_V2U16_Zero DN_Literal(DN_V2U16){{(DN_U16)(0), (DN_U16)(0)}}
#define DN_V2U16_One DN_Literal(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} #define DN_V2U16_One DN_Literal(DN_V2U16){{(DN_U16)(1), (DN_U16)(1)}}
#define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} #define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(DN_U16)(x), (DN_U16)(x)}}
#define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} #define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(DN_U16)(x), (DN_U16)(y)}}
DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs);
DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs);
@ -165,6 +165,11 @@ DN_API DN_V2U16 & operator/= (DN_V2U16& lhs,
DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs);
DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs);
#define DN_V2U32_Zero DN_Literal(DN_V2U32){{(DN_U32)(0), (DN_U32)(0)}}
#define DN_V2U32_One DN_Literal(DN_V2U32){{(DN_U32)(1), (DN_U32)(1)}}
#define DN_V2U32_From1N(x) DN_Literal(DN_V2U32){{(DN_U32)(x), (DN_U32)(x)}}
#define DN_V2U32_From2N(x, y) DN_Literal(DN_V2U32){{(DN_U32)(x), (DN_U32)(y)}}
#define DN_V2F32_Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} #define DN_V2F32_Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}}
#define DN_V2F32_One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} #define DN_V2F32_One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}}
#define DN_V2F32_From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} #define DN_V2F32_From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}}
@ -315,6 +320,7 @@ DN_API bool operator== (DN_M2x3 const
DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs);
DN_API DN_M2x3 DN_M2x3_Identity (); DN_API DN_M2x3 DN_M2x3_Identity ();
DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset);
DN_API DN_V2F32 DN_M2x3_ScaleGet (DN_M2x3 m2x3);
DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale);
DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians);
DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2);
@ -323,6 +329,7 @@ DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN
#define DN_Rect_From2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)} #define DN_Rect_From2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)}
#define DN_Rect_From4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}} #define DN_Rect_From4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}}
#define DN_Rect_Zero DN_Rect_From4N(0, 0, 0, 0)
DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs);
DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect);

View File

@ -91,14 +91,14 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_OS_ThreadSetName(DN_Str8FromPtr(curl->thread.name.data, curl->thread.name.size)); DN_OS_ThreadSetName(DN_Str8FromPtr(curl->thread.name.data, curl->thread.name.size));
while (!curl->kill_thread) { while (!curl->kill_thread) {
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
// NOTE: Handle events sitting in the ring queue // NOTE: Handle events sitting in the ring queue
for (bool dequeue_ring = true; dequeue_ring;) { for (bool dequeue_ring = true; dequeue_ring;) {
DN_NETCurlRingEvent event = {}; DN_NETCurlRingEvent event = {};
for (DN_OS_MutexScope(&curl->ring_mutex)) { for (DN_OS_MutexScope(&curl->ring_mutex)) {
if (DN_Ring_HasData(&curl->ring, sizeof(event))) if (DN_RingHasData(&curl->ring, sizeof(event)))
DN_Ring_Read(&curl->ring, &event, sizeof(event)); DN_RingRead(&curl->ring, &event, sizeof(event));
} }
DN_NETRequest *req = DN_NET_RequestFromHandle(event.request); DN_NETRequest *req = DN_NET_RequestFromHandle(event.request);
@ -126,9 +126,9 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
case DN_NETCurlRingEventType_SendWS: { case DN_NETCurlRingEventType_SendWS: {
DN_Str8 payload = {}; DN_Str8 payload = {};
for (DN_OS_MutexScope(&curl->ring_mutex)) { for (DN_OS_MutexScope(&curl->ring_mutex)) {
DN_Assert(DN_Ring_HasData(&curl->ring, event.ws_send_size)); DN_Assert(DN_RingHasData(&curl->ring, event.ws_send_size));
payload = DN_Str8FromArena(tmem.arena, event.ws_send_size, DN_ZMem_No); payload = DN_Str8FromArena(tmem.arena, event.ws_send_size, DN_ZMem_No);
DN_Ring_Read(&curl->ring, payload.data, payload.size); DN_RingRead(&curl->ring, payload.data, payload.size);
} }
DN_U32 curlws_flag = 0; DN_U32 curlws_flag = 0;
@ -370,6 +370,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_I32 sleep_time_ms = ws_count > 0 ? 16 : INT32_MAX; DN_I32 sleep_time_ms = ws_count > 0 ? 16 : INT32_MAX;
curl_multi_poll(curl->thread_curlm, nullptr, 0, sleep_time_ms, nullptr); curl_multi_poll(curl->thread_curlm, nullptr, 0, sleep_time_ms, nullptr);
DN_TCScratchEnd(&tmem);
} }
return 0; return 0;
@ -526,7 +527,7 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D
event.type = DN_NETCurlRingEventType_DoRequest; event.type = DN_NETCurlRingEventType_DoRequest;
event.request = result; event.request = result;
for (DN_OS_MutexScope(&curl_core->ring_mutex)) for (DN_OS_MutexScope(&curl_core->ring_mutex))
DN_Ring_WriteStruct(&curl_core->ring, &event); DN_RingWriteStruct(&curl_core->ring, &event);
curl_multi_wakeup(curl_core->thread_curlm); curl_multi_wakeup(curl_core->thread_curlm);
} }
@ -569,9 +570,9 @@ void DN_NET_CurlDoWSSend(DN_NETRequestHandle handle, DN_Str8 payload, DN_NETWSSe
event.ws_send = send; event.ws_send = send;
for (DN_OS_MutexScope(&curl->ring_mutex)) { for (DN_OS_MutexScope(&curl->ring_mutex)) {
DN_Assert(DN_Ring_HasSpace(&curl->ring, payload.size)); DN_Assert(DN_RingHasSpace(&curl->ring, payload.size));
DN_Ring_WriteStruct(&curl->ring, &event); DN_RingWriteStruct(&curl->ring, &event);
DN_Ring_Write(&curl->ring, payload.data, payload.size); DN_RingWrite(&curl->ring, payload.data, payload.size);
} }
curl_multi_wakeup(curl->thread_curlm); curl_multi_wakeup(curl->thread_curlm);
} }
@ -627,7 +628,7 @@ static DN_NETResponse DN_NET_CurlHandleFinishedRequest_(DN_NETCurlCore *curl, DN
} }
for (DN_OS_MutexScope(&curl->ring_mutex)) for (DN_OS_MutexScope(&curl->ring_mutex))
DN_Ring_WriteStruct(&curl->ring, &event); DN_RingWriteStruct(&curl->ring, &event);
curl_multi_wakeup(curl->thread_curlm); curl_multi_wakeup(curl->thread_curlm);
return result; return result;

View File

@ -1,6 +1,6 @@
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#endif #endif
#if !defined(DN_UT_H) #if !defined(DN_UT_H)
@ -440,7 +440,7 @@ static DN_UTCore DN_Tests_Arena()
static DN_UTCore DN_Tests_Bin() static DN_UTCore DN_Tests_Bin()
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_UTCore test = DN_UT_Init(); DN_UTCore test = DN_UT_Init();
DN_UT_LogF(&test, "DN_Bin\n"); DN_UT_LogF(&test, "DN_Bin\n");
{ {
@ -502,25 +502,26 @@ static DN_UTCore DN_Tests_Bin()
uint32_t number = 0xd095f6; uint32_t number = 0xd095f6;
for (DN_UT_Test(&test, "Convert %x to string", number)) { for (DN_UT_Test(&test, "Convert %x to string", number)) {
DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), tmem.arena); DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), scratch.arena);
DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("f695d000")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex)); DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("f695d000")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
} }
number = 0xf6ed00; number = 0xf6ed00;
for (DN_UT_Test(&test, "Convert %x to string", number)) { for (DN_UT_Test(&test, "Convert %x to string", number)) {
DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), tmem.arena); DN_Str8 number_hex = DN_HexFromBytesPtrArena(&number, sizeof(number), scratch.arena);
DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("00edf600")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex)); DN_UT_AssertF(&test, DN_Str8Eq(number_hex, DN_Str8Lit("00edf600")), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
} }
DN_Str8 hex = DN_Str8Lit("0xf6ed00"); DN_Str8 hex = DN_Str8Lit("0xf6ed00");
for (DN_UT_Test(&test, "Convert %.*s to bytes", DN_Str8PrintFmt(hex))) { for (DN_UT_Test(&test, "Convert %.*s to bytes", DN_Str8PrintFmt(hex))) {
DN_Str8 bytes = DN_BytesFromHexStr8Arena(hex, tmem.arena); DN_Str8 bytes = DN_BytesFromHexStr8Arena(hex, scratch.arena);
DN_UT_AssertF(&test, DN_UT_AssertF(&test,
DN_Str8Eq(bytes, DN_Str8Lit("\xf6\xed\x00")), DN_Str8Eq(bytes, DN_Str8Lit("\xf6\xed\x00")),
"number_hex=%.*s", "number_hex=%.*s",
DN_Str8PrintFmt(DN_HexFromBytesPtrArena(bytes.data, bytes.size, tmem.arena))); DN_Str8PrintFmt(DN_HexFromBytesPtrArena(bytes.data, bytes.size, scratch.arena)));
} }
} }
DN_TCScratchEnd(&scratch);
return test; return test;
} }
@ -838,40 +839,40 @@ static DN_UTCore DN_Tests_BaseContainers()
DN_UT_LogF(&result, "DN_DSMap\n"); DN_UT_LogF(&result, "DN_DSMap\n");
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
{ {
DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil);
uint32_t const MAP_SIZE = 64; uint32_t const MAP_SIZE = 64;
DN_DSMap<uint64_t> map = DN_DSMap_Init<uint64_t>(&arena, MAP_SIZE, DN_DSMapFlags_Nil); DN_DSMap<uint64_t> map = DN_DSMapInit<uint64_t>(&arena, MAP_SIZE, DN_DSMapFlags_Nil);
DN_DEFER DN_DEFER
{ {
DN_DSMap_Deinit(&map, DN_ZMem_Yes); DN_DSMapDeinit(&map, DN_ZMem_Yes);
}; };
for (DN_UT_Test(&result, "Find non-existent value")) { for (DN_UT_Test(&result, "Find non-existent value")) {
DN_DSMapResult<uint64_t> find = DN_DSMap_FindKeyStr8(&map, DN_Str8Lit("Foo")); DN_DSMapResult<uint64_t> find = DN_DSMapFindKeyStr8(&map, DN_Str8Lit("Foo"));
DN_UT_Assert(&result, !find.found); DN_UT_Assert(&result, !find.found);
DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.size == MAP_SIZE);
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/);
} }
DN_DSMapKey key = DN_DSMap_KeyCStr8(&map, "Bar"); DN_DSMapKey key = DN_DSMapKeyCStr8(&map, "Bar");
for (DN_UT_Test(&result, "Insert value and lookup")) { for (DN_UT_Test(&result, "Insert value and lookup")) {
uint64_t desired_value = 0xF00BAA; uint64_t desired_value = 0xF00BAA;
uint64_t *slot_value = DN_DSMap_Set(&map, key, desired_value).value; uint64_t *slot_value = DN_DSMapSet(&map, key, desired_value).value;
DN_UT_Assert(&result, slot_value); DN_UT_Assert(&result, slot_value);
DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.size == MAP_SIZE);
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.occupied == 2); DN_UT_Assert(&result, map.occupied == 2);
uint64_t *value = DN_DSMap_Find(&map, key).value; uint64_t *value = DN_DSMapFind(&map, key).value;
DN_UT_Assert(&result, value); DN_UT_Assert(&result, value);
DN_UT_Assert(&result, *value == desired_value); DN_UT_Assert(&result, *value == desired_value);
} }
for (DN_UT_Test(&result, "Remove key")) { for (DN_UT_Test(&result, "Remove key")) {
DN_DSMap_Erase(&map, key); DN_DSMapErase(&map, key);
DN_UT_Assert(&result, map.size == MAP_SIZE); DN_UT_Assert(&result, map.size == MAP_SIZE);
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/);
@ -892,13 +893,13 @@ static DN_UTCore DN_Tests_BaseContainers()
case DSMapTestType_MakeSlot: prefix = DN_Str8Lit("Make slot"); break; case DSMapTestType_MakeSlot: prefix = DN_Str8Lit("Make slot"); break;
} }
DN_ArenaTempMemScope temp_mem_scope = DN_ArenaTempMemScope(tmem.arena); DN_ArenaTempMemScope temp_mem_scope = DN_ArenaTempMemScope(scratch.arena);
DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil); DN_Arena arena = DN_ArenaFromVMem(0, 0, DN_ArenaFlags_Nil);
uint32_t const MAP_SIZE = 64; uint32_t const MAP_SIZE = 64;
DN_DSMap<uint64_t> map = DN_DSMap_Init<uint64_t>(&arena, MAP_SIZE, DN_DSMapFlags_Nil); DN_DSMap<uint64_t> map = DN_DSMapInit<uint64_t>(&arena, MAP_SIZE, DN_DSMapFlags_Nil);
DN_DEFER DN_DEFER
{ {
DN_DSMap_Deinit(&map, DN_ZMem_Yes); DN_DSMapDeinit(&map, DN_ZMem_Yes);
}; };
for (DN_UT_Test(&result, "%.*s: Test growing", DN_Str8PrintFmt(prefix))) { for (DN_UT_Test(&result, "%.*s: Test growing", DN_Str8PrintFmt(prefix))) {
@ -906,27 +907,27 @@ static DN_UTCore DN_Tests_BaseContainers()
uint64_t value = 0; uint64_t value = 0;
uint64_t grow_threshold = map_start_size * 3 / 4; uint64_t grow_threshold = map_start_size * 3 / 4;
for (; map.occupied != grow_threshold; value++) { for (; map.occupied != grow_threshold; value++) {
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_UT_Assert(&result, !DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, !DN_DSMapFind<uint64_t>(&map, key).found);
DN_DSMapResult<uint64_t> make_result = {}; DN_DSMapResult<uint64_t> make_result = {};
if (result_type == DSMapTestType_Set) if (result_type == DSMapTestType_Set)
make_result = DN_DSMap_Set(&map, key, value); make_result = DN_DSMapSet(&map, key, value);
else else
make_result = DN_DSMap_Make(&map, key); make_result = DN_DSMapMake(&map, key);
DN_UT_Assert(&result, !make_result.found); DN_UT_Assert(&result, !make_result.found);
DN_UT_Assert(&result, DN_DSMap_Find<uint64_t>(&map, key).value); DN_UT_Assert(&result, DN_DSMapFind<uint64_t>(&map, key).value);
} }
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.size == map_start_size); DN_UT_Assert(&result, map.size == map_start_size);
DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/ + value); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/ + value);
{ // NOTE: One more item should cause the table to grow by 2x { // NOTE: One more item should cause the table to grow by 2x
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_DSMapResult<uint64_t> make_result = {}; DN_DSMapResult<uint64_t> make_result = {};
if (result_type == DSMapTestType_Set) if (result_type == DSMapTestType_Set)
make_result = DN_DSMap_Set(&map, key, value); make_result = DN_DSMapSet(&map, key, value);
else else
make_result = DN_DSMap_Make(&map, key); make_result = DN_DSMapMake(&map, key);
value++; value++;
DN_UT_Assert(&result, !make_result.found); DN_UT_Assert(&result, !make_result.found);
@ -948,16 +949,16 @@ static DN_UTCore DN_Tests_BaseContainers()
// NOTE: Validate each slot value // NOTE: Validate each slot value
uint64_t value_result = index - 1; uint64_t value_result = index - 1;
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value_result); DN_DSMapKey key = DN_DSMapKeyU64(&map, value_result);
DN_UT_Assert(&result, DN_DSMap_KeyEquals(slot->key, key)); DN_UT_Assert(&result, DN_DSMapKeyEquals(slot->key, key));
if (result_type == DSMapTestType_Set) if (result_type == DSMapTestType_Set)
DN_UT_Assert(&result, slot->value == value_result); DN_UT_Assert(&result, slot->value == value_result);
else else
DN_UT_Assert(&result, slot->value == 0); // NOTE: Make slot does not set the key so should be 0 DN_UT_Assert(&result, slot->value == 0); // NOTE: Make slot does not set the key so should be 0
DN_UT_Assert(&result, slot->key.hash == DN_DSMap_Hash(&map, slot->key)); DN_UT_Assert(&result, slot->key.hash == DN_DSMapHash(&map, slot->key));
// NOTE: Check the reverse lookup is correct // NOTE: Check the reverse lookup is correct
DN_DSMapResult<uint64_t> check = DN_DSMap_Find(&map, slot->key); DN_DSMapResult<uint64_t> check = DN_DSMapFind(&map, slot->key);
DN_UT_Assert(&result, slot->value == *check.value); DN_UT_Assert(&result, slot->value == *check.value);
} }
} }
@ -968,17 +969,17 @@ static DN_UTCore DN_Tests_BaseContainers()
uint64_t value = 0; uint64_t value = 0;
uint64_t shrink_threshold = map.size * 1 / 4; uint64_t shrink_threshold = map.size * 1 / 4;
for (; map.occupied != shrink_threshold; value++) { for (; map.occupied != shrink_threshold; value++) {
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_UT_Assert(&result, DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, DN_DSMapFind<uint64_t>(&map, key).found);
DN_DSMap_Erase(&map, key); DN_DSMapErase(&map, key);
DN_UT_Assert(&result, !DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, !DN_DSMapFind<uint64_t>(&map, key).found);
} }
DN_UT_Assert(&result, map.size == start_map_size); DN_UT_Assert(&result, map.size == start_map_size);
DN_UT_Assert(&result, map.occupied == start_map_occupied - value); DN_UT_Assert(&result, map.occupied == start_map_occupied - value);
{ // NOTE: One more item should cause the table to shrink by 2x { // NOTE: One more item should cause the table to shrink by 2x
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_DSMap_Erase(&map, key); DN_DSMapErase(&map, key);
value++; value++;
DN_UT_Assert(&result, map.size == start_map_size / 2); DN_UT_Assert(&result, map.size == start_map_size / 2);
@ -995,34 +996,35 @@ static DN_UTCore DN_Tests_BaseContainers()
for (uint64_t index = 1 /*Sentinel*/; index < map.occupied; index++) { for (uint64_t index = 1 /*Sentinel*/; index < map.occupied; index++) {
// NOTE: Generate the key // NOTE: Generate the key
uint64_t value_result = value + (index - 1); uint64_t value_result = value + (index - 1);
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value_result); DN_DSMapKey key = DN_DSMapKeyU64(&map, value_result);
// NOTE: Validate each slot value // NOTE: Validate each slot value
DN_DSMapResult<uint64_t> find_result = DN_DSMap_Find(&map, key); DN_DSMapResult<uint64_t> find_result = DN_DSMapFind(&map, key);
DN_UT_Assert(&result, find_result.value); DN_UT_Assert(&result, find_result.value);
DN_UT_Assert(&result, find_result.slot->key == key); DN_UT_Assert(&result, find_result.slot->key == key);
if (result_type == DSMapTestType_Set) if (result_type == DSMapTestType_Set)
DN_UT_Assert(&result, *find_result.value == value_result); DN_UT_Assert(&result, *find_result.value == value_result);
else else
DN_UT_Assert(&result, *find_result.value == 0); // NOTE: Make slot does not set the key so should be 0 DN_UT_Assert(&result, *find_result.value == 0); // NOTE: Make slot does not set the key so should be 0
DN_UT_Assert(&result, find_result.slot->key.hash == DN_DSMap_Hash(&map, find_result.slot->key)); DN_UT_Assert(&result, find_result.slot->key.hash == DN_DSMapHash(&map, find_result.slot->key));
// NOTE: Check the reverse lookup is correct // NOTE: Check the reverse lookup is correct
DN_DSMapResult<uint64_t> check = DN_DSMap_Find(&map, find_result.slot->key); DN_DSMapResult<uint64_t> check = DN_DSMapFind(&map, find_result.slot->key);
DN_UT_Assert(&result, *find_result.value == *check.value); DN_UT_Assert(&result, *find_result.value == *check.value);
} }
for (; map.occupied != 1; value++) { // NOTE: Remove all items from the table for (; map.occupied != 1; value++) { // NOTE: Remove all items from the table
DN_DSMapKey key = DN_DSMap_KeyU64(&map, value); DN_DSMapKey key = DN_DSMapKeyU64(&map, value);
DN_UT_Assert(&result, DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, DN_DSMapFind<uint64_t>(&map, key).found);
DN_DSMap_Erase(&map, key); DN_DSMapErase(&map, key);
DN_UT_Assert(&result, !DN_DSMap_Find<uint64_t>(&map, key).found); DN_UT_Assert(&result, !DN_DSMapFind<uint64_t>(&map, key).found);
} }
DN_UT_Assert(&result, map.initial_size == MAP_SIZE); DN_UT_Assert(&result, map.initial_size == MAP_SIZE);
DN_UT_Assert(&result, map.size == map.initial_size); DN_UT_Assert(&result, map.size == map.initial_size);
DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/); DN_UT_Assert(&result, map.occupied == 1 /*Sentinel*/);
} }
} }
DN_TCScratchEnd(&scratch);
} }
DN_UT_LogF(&result, "DN_IArray\n"); DN_UT_LogF(&result, "DN_IArray\n");
@ -1040,7 +1042,7 @@ static DN_UTCore DN_Tests_BaseContainers()
array.max = DN_ArrayCountU(array_buffer); array.max = DN_ArrayCountU(array_buffer);
for (DN_UT_Test(&result, "Make item")) { for (DN_UT_Test(&result, "Make item")) {
int *item = DN_IArray_Make(&array, DN_ZMem_Yes); int *item = DN_IArrayMake(&array, DN_ZMem_Yes);
DN_UT_Assert(&result, item && array.size == 1); DN_UT_Assert(&result, item && array.size == 1);
} }
} }
@ -1050,7 +1052,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Positive count, middle of array, stable erase")) { for (DN_UT_Test(&result, "Positive count, middle of array, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 5, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 2); DN_UT_Assert(&result, erase.items_erased == 2);
DN_UT_Assert(&result, erase.it_index == 3); DN_UT_Assert(&result, erase.it_index == 3);
@ -1061,7 +1063,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Negative count, middle of array, stable erase")) { for (DN_UT_Test(&result, "Negative count, middle of array, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 3); DN_UT_Assert(&result, erase.items_erased == 3);
DN_UT_Assert(&result, erase.it_index == 3); DN_UT_Assert(&result, erase.it_index == 3);
@ -1072,7 +1074,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "count = -1, stable erase")) { for (DN_UT_Test(&result, "count = -1, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -1, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -1, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 3, 4, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 1); DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 5); DN_UT_Assert(&result, erase.it_index == 5);
@ -1083,7 +1085,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Positive count, unstable erase")) { for (DN_UT_Test(&result, "Positive count, unstable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Unstable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Unstable);
int expected[] = {0, 1, 2, 8, 9, 5, 6, 7}; int expected[] = {0, 1, 2, 8, 9, 5, 6, 7};
DN_UT_Assert(&result, erase.items_erased == 2); DN_UT_Assert(&result, erase.items_erased == 2);
DN_UT_Assert(&result, erase.it_index == 3); DN_UT_Assert(&result, erase.it_index == 3);
@ -1094,7 +1096,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Negative count, unstable erase")) { for (DN_UT_Test(&result, "Negative count, unstable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Unstable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Unstable);
int expected[] = {0, 1, 2, 7, 8, 9, 6}; int expected[] = {0, 1, 2, 7, 8, 9, 6};
DN_UT_Assert(&result, erase.items_erased == 3); DN_UT_Assert(&result, erase.items_erased == 3);
DN_UT_Assert(&result, erase.it_index == 3); DN_UT_Assert(&result, erase.it_index == 3);
@ -1105,18 +1107,18 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Edge case - begin_index at start, negative count")) { for (DN_UT_Test(&result, "Edge case - begin_index at start, negative count")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 0, -2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 0, -2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
DN_UT_Assert(&result, size == 10); DN_UT_Assert(&result, size == 9);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
} }
for (DN_UT_Test(&result, "Edge case - begin_index at end, positive count")) { for (DN_UT_Test(&result, "Edge case - begin_index at end, positive count")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 9, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 9, 2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
DN_UT_Assert(&result, erase.items_erased == 1); DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 9); DN_UT_Assert(&result, erase.it_index == 9);
@ -1127,7 +1129,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Invalid input - count = 0")) { for (DN_UT_Test(&result, "Invalid input - count = 0")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, 0, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 0, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
@ -1137,7 +1139,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Invalid input - null data")) { for (DN_UT_Test(&result, "Invalid input - null data")) {
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(nullptr, &size, sizeof(int), 5, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(nullptr, &size, sizeof(int), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
DN_UT_Assert(&result, size == 10); DN_UT_Assert(&result, size == 10);
@ -1145,7 +1147,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Invalid input - null size")) { for (DN_UT_Test(&result, "Invalid input - null size")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, NULL, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, NULL, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
} }
@ -1153,7 +1155,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Invalid input - empty array")) { for (DN_UT_Test(&result, "Invalid input - empty array")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 0; DN_USize size = 0;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0); DN_UT_Assert(&result, erase.it_index == 0);
DN_UT_Assert(&result, size == 0); DN_UT_Assert(&result, size == 0);
@ -1162,7 +1164,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Out-of-bounds begin_index")) { for (DN_UT_Test(&result, "Out-of-bounds begin_index")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10; DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArray2_EraseRange(arr, &size, sizeof(arr[0]), 15, 2, DN_ArrayErase_Stable); DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 15, 2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 0); DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 10); DN_UT_Assert(&result, erase.it_index == 10);
@ -1171,77 +1173,31 @@ static DN_UTCore DN_Tests_BaseContainers()
} }
} }
DN_UT_LogF(&result, "DN_FArray\n");
{
for (DN_UT_Test(&result, "Initialise from raw array")) {
int raw_array[] = {1, 2};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_UT_Assert(&result, array.size == 2);
DN_UT_Assert(&result, array.data[0] == 1);
DN_UT_Assert(&result, array.data[1] == 2);
}
for (DN_UT_Test(&result, "Erase stable 1 element from array")) {
int raw_array[] = {1, 2, 3};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_FArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable);
DN_UT_Assert(&result, array.size == 2);
DN_UT_Assert(&result, array.data[0] == 1);
DN_UT_Assert(&result, array.data[1] == 3);
}
for (DN_UT_Test(&result, "Erase unstable 1 element from array")) {
int raw_array[] = {1, 2, 3};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_FArray_EraseRange(&array, 0 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable);
DN_UT_Assert(&result, array.size == 2);
DN_UT_Assert(&result, array.data[0] == 3);
DN_UT_Assert(&result, array.data[1] == 2);
}
for (DN_UT_Test(&result, "Add 1 element to array")) {
int const ITEM = 2;
int raw_array[] = {1};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_FArray_Add(&array, ITEM);
DN_UT_Assert(&result, array.size == 2);
DN_UT_Assert(&result, array.data[0] == 1);
DN_UT_Assert(&result, array.data[1] == ITEM);
}
for (DN_UT_Test(&result, "Clear array")) {
int raw_array[] = {1};
auto array = DN_FArray_Init<int, 4>(raw_array, DN_ArrayCountU(raw_array));
DN_FArray_Clear(&array);
DN_UT_Assert(&result, array.size == 0);
}
}
DN_UT_LogF(&result, "DN_VArray\n"); DN_UT_LogF(&result, "DN_VArray\n");
{ {
{ {
DN_VArray<uint32_t> array = DN_VArray_InitByteSize<uint32_t>(DN_Kilobytes(64)); DN_VArray<uint32_t> array = DN_OS_VArrayInitByteSize<uint32_t>(DN_Kilobytes(64));
DN_DEFER DN_DEFER
{ {
DN_VArray_Deinit(&array); DN_OS_VArrayDeinit(&array);
}; };
for (DN_UT_Test(&result, "Test adding an array of items to the array")) { for (DN_UT_Test(&result, "Test adding an array of items to the array")) {
uint32_t array_literal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; uint32_t array_literal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
DN_VArray_AddArray<uint32_t>(&array, array_literal, DN_ArrayCountU(array_literal)); DN_OS_VArrayAddArray<uint32_t>(&array, array_literal, DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test stable erase, 1 item, the '2' value from the array")) { for (DN_UT_Test(&result, "Test stable erase, 1 item, the '2' value from the array")) {
DN_VArray_EraseRange(&array, 2 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable); DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Stable);
uint32_t array_literal[] = {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; uint32_t array_literal[] = {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test unstable erase, 1 item, the '1' value from the array")) { for (DN_UT_Test(&result, "Test unstable erase, 1 item, the '1' value from the array")) {
DN_VArray_EraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable); DN_OS_VArrayEraseRange(&array, 1 /*begin_index*/, 1 /*count*/, DN_ArrayErase_Unstable);
uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
@ -1251,49 +1207,49 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Test un/stable erase, OOB")) { for (DN_UT_Test(&result, "Test un/stable erase, OOB")) {
for (DN_ArrayErase erase : erase_enums) { for (DN_ArrayErase erase : erase_enums) {
uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; uint32_t array_literal[] = {0, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
DN_VArray_EraseRange(&array, DN_ArrayCountU(array_literal) /*begin_index*/, DN_ArrayCountU(array_literal) + 100 /*count*/, erase); DN_OS_VArrayEraseRange(&array, DN_ArrayCountU(array_literal) /*begin_index*/, DN_ArrayCountU(array_literal) + 100 /*count*/, erase);
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
} }
for (DN_UT_Test(&result, "Test flipped begin/end index stable erase, 2 items, the '15, 3' value from the array")) { for (DN_UT_Test(&result, "Test flipped begin/end index stable erase, 2 items, the '15, 3' value from the array")) {
DN_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Stable); DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Stable);
uint32_t array_literal[] = {0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; uint32_t array_literal[] = {0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test flipped begin/end index unstable erase, 2 items, the '4, 5' value from the array")) { for (DN_UT_Test(&result, "Test flipped begin/end index unstable erase, 2 items, the '4, 5' value from the array")) {
DN_VArray_EraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Unstable); DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, -2 /*count*/, DN_ArrayErase_Unstable);
uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10, 11, 12}; uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10, 11, 12};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test stable erase range, 2+1 (oob) item, the '13, 14, +1 OOB' value from the array")) { for (DN_UT_Test(&result, "Test stable erase range, 2+1 (oob) item, the '13, 14, +1 OOB' value from the array")) {
DN_VArray_EraseRange(&array, 8 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Stable); DN_OS_VArrayEraseRange(&array, 8 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Stable);
uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10}; uint32_t array_literal[] = {0, 13, 14, 6, 7, 8, 9, 10};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test unstable erase range, 3+1 (oob) item, the '11, 12, +1 OOB' value from the array")) { for (DN_UT_Test(&result, "Test unstable erase range, 3+1 (oob) item, the '11, 12, +1 OOB' value from the array")) {
DN_VArray_EraseRange(&array, 6 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Unstable); DN_OS_VArrayEraseRange(&array, 6 /*begin_index*/, 3 /*count*/, DN_ArrayErase_Unstable);
uint32_t array_literal[] = {0, 13, 14, 6, 7, 8}; uint32_t array_literal[] = {0, 13, 14, 6, 7, 8};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test stable erase -overflow OOB, erasing the '0, 13' value from the array")) { for (DN_UT_Test(&result, "Test stable erase -overflow OOB, erasing the '0, 13' value from the array")) {
DN_VArray_EraseRange(&array, 1 /*begin_index*/, -DN_ISIZE_MAX /*count*/, DN_ArrayErase_Stable); DN_OS_VArrayEraseRange(&array, 1 /*begin_index*/, -DN_ISIZE_MAX /*count*/, DN_ArrayErase_Stable);
uint32_t array_literal[] = {14, 6, 7, 8}; uint32_t array_literal[] = {14, 6, 7, 8};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
} }
for (DN_UT_Test(&result, "Test unstable erase +overflow OOB, erasing the '7, 8' value from the array")) { for (DN_UT_Test(&result, "Test unstable erase +overflow OOB, erasing the '7, 8' value from the array")) {
DN_VArray_EraseRange(&array, 2 /*begin_index*/, DN_ISIZE_MAX /*count*/, DN_ArrayErase_Unstable); DN_OS_VArrayEraseRange(&array, 2 /*begin_index*/, DN_ISIZE_MAX /*count*/, DN_ArrayErase_Unstable);
uint32_t array_literal[] = {14, 6}; uint32_t array_literal[] = {14, 6};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(array_literal));
DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0); DN_UT_Assert(&result, DN_Memcmp(array.data, array_literal, DN_ArrayCountU(array_literal) * sizeof(array_literal[0])) == 0);
@ -1301,7 +1257,7 @@ static DN_UTCore DN_Tests_BaseContainers()
for (DN_UT_Test(&result, "Test adding an array of items after erase")) { for (DN_UT_Test(&result, "Test adding an array of items after erase")) {
uint32_t array_literal[] = {0, 1, 2, 3}; uint32_t array_literal[] = {0, 1, 2, 3};
DN_VArray_AddArray<uint32_t>(&array, array_literal, DN_ArrayCountU(array_literal)); DN_OS_VArrayAddArray<uint32_t>(&array, array_literal, DN_ArrayCountU(array_literal));
uint32_t expected_literal[] = {14, 6, 0, 1, 2, 3}; uint32_t expected_literal[] = {14, 6, 0, 1, 2, 3};
DN_UT_Assert(&result, array.size == DN_ArrayCountU(expected_literal)); DN_UT_Assert(&result, array.size == DN_ArrayCountU(expected_literal));
@ -1331,16 +1287,16 @@ static DN_UTCore DN_Tests_BaseContainers()
DN_MSVC_WARNING_POP DN_MSVC_WARNING_POP
DN_VArray<UnalignedObject> array = DN_VArray_InitByteSize<UnalignedObject>(DN_Kilobytes(64)); DN_VArray<UnalignedObject> array = DN_OS_VArrayInitByteSize<UnalignedObject>(DN_Kilobytes(64));
DN_DEFER DN_DEFER
{ {
DN_VArray_Deinit(&array); DN_OS_VArrayDeinit(&array);
}; };
// NOTE: Verify that the items returned from the data array are // NOTE: Verify that the items returned from the data array are
// contiguous in memory. // contiguous in memory.
UnalignedObject *make_item_a = DN_VArray_MakeArray(&array, 1, DN_ZMem_Yes); UnalignedObject *make_item_a = DN_OS_VArrayMakeArray(&array, 1, DN_ZMem_Yes);
UnalignedObject *make_item_b = DN_VArray_MakeArray(&array, 1, DN_ZMem_Yes); UnalignedObject *make_item_b = DN_OS_VArrayMakeArray(&array, 1, DN_ZMem_Yes);
DN_Memset(make_item_a->data, 'a', sizeof(make_item_a->data)); DN_Memset(make_item_a->data, 'a', sizeof(make_item_a->data));
DN_Memset(make_item_b->data, 'b', sizeof(make_item_b->data)); DN_Memset(make_item_b->data, 'b', sizeof(make_item_b->data));
DN_UT_Assert(&result, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1)); DN_UT_Assert(&result, (uintptr_t)make_item_b == (uintptr_t)(make_item_a + 1));
@ -1642,8 +1598,8 @@ DN_Str8 const DN_UT_HASH_STRING_[] =
void DN_Tests_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input) void DN_Tests_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 input_hex = DN_HexFromBytesPtrArena(input.data, input.size, tmem.arena); DN_Str8 input_hex = DN_HexFromBytesPtrArena(input.data, input.size, scratch.arena);
switch (hash_type) { switch (hash_type) {
case Hash_SHA3_224: { case Hash_SHA3_224: {
@ -1754,10 +1710,11 @@ void DN_Tests_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input)
"\nhash: %.*s" "\nhash: %.*s"
"\nexpect: %.*s", "\nexpect: %.*s",
DN_Str8PrintFmt(input_hex), DN_Str8PrintFmt(input_hex),
DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&hash).data), DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&hash).data),
DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&expect).data)); DN_KC_STRING128_FMT(DN_KC_Bytes64ToHex(&expect).data));
} break; } break;
} }
DN_TCScratchEnd(&scratch);
} }
#endif // defined(DN_UNIT_TESTS_WITH_KECCAK) #endif // defined(DN_UNIT_TESTS_WITH_KECCAK)
@ -1845,10 +1802,11 @@ static DN_UTCore DN_Tests_OS()
} }
for (DN_UT_Test(&result, "Query executable directory")) { for (DN_UT_Test(&result, "Query executable directory")) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 os_result = DN_OS_EXEDir(tmem.arena); DN_Str8 os_result = DN_OS_EXEDir(scratch.arena);
DN_UT_Assert(&result, os_result.size); DN_UT_Assert(&result, os_result.size);
DN_UT_AssertF(&result, DN_OS_PathIsDir(os_result), "result(%zu): %.*s", os_result.size, DN_Str8PrintFmt(os_result)); DN_UT_AssertF(&result, DN_OS_PathIsDir(os_result), "result(%zu): %.*s", os_result.size, DN_Str8PrintFmt(os_result));
DN_TCScratchEnd(&scratch);
} }
for (DN_UT_Test(&result, "DN_OS_PerfCounterNow")) { for (DN_UT_Test(&result, "DN_OS_PerfCounterNow")) {
@ -1895,8 +1853,8 @@ static DN_UTCore DN_Tests_OS()
DN_UT_Assert(&result, DN_OS_PathIsFile(SRC_FILE)); DN_UT_Assert(&result, DN_OS_PathIsFile(SRC_FILE));
// NOTE: Read step // NOTE: Read step
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 read_file = DN_OS_FileReadAllArena(tmem.arena, SRC_FILE, nullptr); DN_Str8 read_file = DN_OS_FileReadAllArena(scratch.arena, SRC_FILE, nullptr);
DN_UT_AssertF(&result, read_file.size, "Failed to load file"); DN_UT_AssertF(&result, read_file.size, "Failed to load file");
DN_UT_AssertF(&result, read_file.size == 4, "File read wrong amount of bytes (%zu)", read_file.size); DN_UT_AssertF(&result, read_file.size == 4, "File read wrong amount of bytes (%zu)", read_file.size);
DN_UT_AssertF(&result, DN_Str8Eq(read_file, DN_Str8Lit("1234")), "Read %zu bytes instead of the expected 4: '%.*s'", read_file.size, DN_Str8PrintFmt(read_file)); DN_UT_AssertF(&result, DN_Str8Eq(read_file, DN_Str8Lit("1234")), "Read %zu bytes instead of the expected 4: '%.*s'", read_file.size, DN_Str8PrintFmt(read_file));
@ -1925,6 +1883,7 @@ static DN_UTCore DN_Tests_OS()
DN_B32 delete_non_existent_moved_file = DN_OS_PathDelete(MOVE_FILE); DN_B32 delete_non_existent_moved_file = DN_OS_PathDelete(MOVE_FILE);
DN_UT_Assert(&result, delete_non_existent_moved_file == false); DN_UT_Assert(&result, delete_non_existent_moved_file == false);
DN_UT_Assert(&result, delete_non_existent_src_file == false); DN_UT_Assert(&result, delete_non_existent_src_file == false);
DN_TCScratchEnd(&scratch);
} }
} }
@ -2147,22 +2106,24 @@ static DN_UTCore DN_Tests_Str8()
} }
for (DN_UT_Test(&result, "Initialise with format string")) { for (DN_UT_Test(&result, "Initialise with format string")) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8FromFmtArena(tmem.arena, "%s", "AB"); DN_Str8 string = DN_Str8FromFmtArena(scratch.arena, "%s", "AB");
DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size); DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size);
DN_UT_AssertF(&result, string.data[0] == 'A', "string[0]: %c", string.data[0]); DN_UT_AssertF(&result, string.data[0] == 'A', "string[0]: %c", string.data[0]);
DN_UT_AssertF(&result, string.data[1] == 'B', "string[1]: %c", string.data[1]); DN_UT_AssertF(&result, string.data[1] == 'B', "string[1]: %c", string.data[1]);
DN_UT_AssertF(&result, string.data[2] == 0, "string[2]: %c", string.data[2]); DN_UT_AssertF(&result, string.data[2] == 0, "string[2]: %c", string.data[2]);
DN_TCScratchEnd(&scratch);
} }
for (DN_UT_Test(&result, "Copy string")) { for (DN_UT_Test(&result, "Copy string")) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8Lit("AB"); DN_Str8 string = DN_Str8Lit("AB");
DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, string); DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, string);
DN_UT_AssertF(&result, copy.size == 2, "size: %zu", copy.size); DN_UT_AssertF(&result, copy.size == 2, "size: %zu", copy.size);
DN_UT_AssertF(&result, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]); DN_UT_AssertF(&result, copy.data[0] == 'A', "copy[0]: %c", copy.data[0]);
DN_UT_AssertF(&result, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]); DN_UT_AssertF(&result, copy.data[1] == 'B', "copy[1]: %c", copy.data[1]);
DN_UT_AssertF(&result, copy.data[2] == 0, "copy[2]: %c", copy.data[2]); DN_UT_AssertF(&result, copy.data[2] == 0, "copy[2]: %c", copy.data[2]);
DN_TCScratchEnd(&scratch);
} }
for (DN_UT_Test(&result, "Trim whitespace around string")) { for (DN_UT_Test(&result, "Trim whitespace around string")) {
@ -2171,9 +2132,10 @@ static DN_UTCore DN_Tests_Str8()
} }
for (DN_UT_Test(&result, "Allocate string from arena")) { for (DN_UT_Test(&result, "Allocate string from arena")) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 string = DN_Str8FromArena(tmem.arena, 2, DN_ZMem_No); DN_Str8 string = DN_Str8FromArena(scratch.arena, 2, DN_ZMem_No);
DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size); DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size);
DN_TCScratchEnd(&scratch);
} }
// NOTE: TrimPrefix/Suffix ///////////////////////////////////////////////////////////////////// // NOTE: TrimPrefix/Suffix /////////////////////////////////////////////////////////////////////
@ -2448,28 +2410,28 @@ static DN_UTCore DN_Tests_Win()
#if defined(DN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
DN_UT_LogF(&result, "OS Win32\n"); DN_UT_LogF(&result, "OS Win32\n");
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 input8 = DN_Str8Lit("String"); DN_Str8 input8 = DN_Str8Lit("String");
DN_Str16 input16 = DN_Str16{(wchar_t *)(L"String"), sizeof(L"String") / sizeof(L"String"[0]) - 1}; DN_Str16 input16 = DN_Str16{(wchar_t *)(L"String"), sizeof(L"String") / sizeof(L"String"[0]) - 1};
for (DN_UT_Test(&result, "Str8 to Str16")) { for (DN_UT_Test(&result, "Str8 to Str16")) {
DN_Str16 str_result = DN_W32_Str8ToStr16(tmem.arena, input8); DN_Str16 str_result = DN_OS_W32Str8ToStr16(scratch.arena, input8);
DN_UT_Assert(&result, DN_Str16Eq(str_result, input16)); DN_UT_Assert(&result, DN_Str16Eq(str_result, input16));
} }
for (DN_UT_Test(&result, "Str16 to Str8")) { for (DN_UT_Test(&result, "Str16 to Str8")) {
DN_Str8 str_result = DN_W32_Str16ToStr8(tmem.arena, input16); DN_Str8 str_result = DN_OS_W32Str16ToStr8(scratch.arena, input16);
DN_UT_Assert(&result, DN_Str8Eq(str_result, input8)); DN_UT_Assert(&result, DN_Str8Eq(str_result, input8));
} }
for (DN_UT_Test(&result, "Str16 to Str8: Null terminates string")) { for (DN_UT_Test(&result, "Str16 to Str8: Null terminates string")) {
int size_required = DN_W32_Str16ToStr8Buffer(input16, nullptr, 0); int size_required = DN_OS_W32Str16ToStr8Buffer(input16, nullptr, 0);
char *string = DN_ArenaNewArray(tmem.arena, char, size_required + 1, DN_ZMem_No); char *string = DN_ArenaNewArray(scratch.arena, char, size_required + 1, DN_ZMem_No);
// Fill the string with error sentinels // Fill the string with error sentinels
DN_Memset(string, 'Z', size_required + 1); DN_Memset(string, 'Z', size_required + 1);
int size_returned = DN_W32_Str16ToStr8Buffer(input16, string, size_required + 1); int size_returned = DN_OS_W32Str16ToStr8Buffer(input16, string, size_required + 1);
char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0};
DN_UT_AssertF(&result, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned); DN_UT_AssertF(&result, size_required == size_returned, "string_size: %d, result: %d", size_required, size_returned);
@ -2478,14 +2440,15 @@ static DN_UTCore DN_Tests_Win()
} }
for (DN_UT_Test(&result, "Str16 to Str8: Arena null terminates string")) { for (DN_UT_Test(&result, "Str16 to Str8: Arena null terminates string")) {
DN_Str8 string8 = DN_W32_Str16ToStr8(tmem.arena, input16); DN_Str8 string8 = DN_OS_W32Str16ToStr8(scratch.arena, input16);
int size_returned = DN_W32_Str16ToStr8Buffer(input16, nullptr, 0); int size_returned = DN_OS_W32Str16ToStr8Buffer(input16, nullptr, 0);
char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0}; char const EXPECTED[] = {'S', 't', 'r', 'i', 'n', 'g', 0};
DN_UT_AssertF(&result, DN_Cast(int) string8.size == size_returned, "string_size: %d, result: %d", DN_Cast(int) string8.size, size_returned); DN_UT_AssertF(&result, DN_Cast(int) string8.size == size_returned, "string_size: %d, result: %d", DN_Cast(int) string8.size, size_returned);
DN_UT_AssertF(&result, DN_Cast(int) string8.size == DN_ArrayCountU(EXPECTED) - 1, "string_size: %d, expected: %zu", DN_Cast(int) string8.size, DN_ArrayCountU(EXPECTED) - 1); DN_UT_AssertF(&result, DN_Cast(int) string8.size == DN_ArrayCountU(EXPECTED) - 1, "string_size: %d, expected: %zu", DN_Cast(int) string8.size, DN_ArrayCountU(EXPECTED) - 1);
DN_UT_Assert(&result, DN_Memcmp(EXPECTED, string8.data, sizeof(EXPECTED)) == 0); DN_UT_Assert(&result, DN_Memcmp(EXPECTED, string8.data, sizeof(EXPECTED)) == 0);
} }
DN_TCScratchEnd(&scratch);
} }
#endif // DN_PLATFORM_WIN32 #endif // DN_PLATFORM_WIN32
return result; return result;

View File

@ -2,7 +2,7 @@
#define DN_TYPE_INFO_H #define DN_TYPE_INFO_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
/* /*

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,8 @@
#define DN_OS_H #define DN_OS_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#endif #endif
#include <new> // operator new #include <new> // operator new
@ -123,7 +123,7 @@ struct DN_OSPath
DN_OSPathLink *head; DN_OSPathLink *head;
DN_OSPathLink *tail; DN_OSPathLink *tail;
DN_USize string_size; DN_USize string_size;
DN_U16 links_size; DN_U16 links_size;
}; };
// NOTE: DN_OSExec // NOTE: DN_OSExec
@ -197,8 +197,7 @@ typedef DN_I32(DN_OSThreadFunc)(struct DN_OSThread *);
struct DN_OSThread struct DN_OSThread
{ {
DN_Str8x64 name; DN_Str8x64 name;
DN_OSTLS tls; DN_TCCore context;
DN_OSTLSInitArgs tls_init_args;
void *handle; void *handle;
DN_U64 thread_id; DN_U64 thread_id;
void *user_context; void *user_context;
@ -229,7 +228,7 @@ struct DN_OSHttpResponse
// Synchronous HTTP response uses the TLS scratch arena whereas async // Synchronous HTTP response uses the TLS scratch arena whereas async
// calls use their own dedicated arena. // calls use their own dedicated arena.
DN_Arena tmp_arena; DN_Arena tmp_arena;
DN_Arena *tmem_arena; DN_Arena *scratch_arena;
DN_Str8Builder builder; DN_Str8Builder builder;
DN_OSSemaphore on_complete_semaphore; DN_OSSemaphore on_complete_semaphore;
@ -245,10 +244,9 @@ struct DN_OSHttpResponse
struct DN_OSCore struct DN_OSCore
{ {
DN_CPUReport cpu_report; DN_CPUReport cpu_report;
DN_OSTLS tls; // Thread local storage state for the main thread.
// NOTE: Logging // NOTE: Logging
DN_LOGEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine DN_LogEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine
void * log_user_data; // User pointer passed into 'log_callback' void * log_user_data; // User pointer passed into 'log_callback'
bool log_to_file; // Output logs to file as well as standard out bool log_to_file; // Output logs to file as well as standard out
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ? DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
@ -280,14 +278,19 @@ struct DN_OSDiskSpace
DN_U64 size; DN_U64 size;
}; };
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet (DN_ArenaMemFuncType type);
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults ();
DN_API DN_Arena DN_ArenaFromHeap (DN_U64 size, DN_ArenaFlags flags);
DN_API DN_Arena DN_ArenaFromVMem (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder);
DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os); DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os);
DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path); DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path);
DN_API DN_Str8 DN_OS_BytesFromHexPtrArenaFrame (void const *hex, DN_USize hex_count);
DN_API DN_Str8 DN_OS_BytesFromHexStr8ArenaFrame (DN_Str8 hex);
DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaFrame (void const *bytes, DN_USize bytes_count);
DN_API DN_Str8 DN_OS_HexFromBytesPtrArenaTLS (void const *bytes, DN_USize bytes_count);
DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags); DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags); DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags);
DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size); DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size);
@ -312,7 +315,6 @@ DN_API bool DN_OS_SetEnvVar (D
DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path); DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path);
DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena); DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena); DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena);
#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena())
DN_API void DN_OS_SleepMs (DN_UInt milliseconds); DN_API void DN_OS_SleepMs (DN_UInt milliseconds);
DN_API DN_U64 DN_OS_PerfCounterNow (); DN_API DN_U64 DN_OS_PerfCounterNow ();
@ -329,28 +331,28 @@ DN_API DN_F64 DN_OS_TimerUs (D
DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer); DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer);
DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency); DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency);
DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err); DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_ErrSink *err);
DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err); DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err);
DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err); DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_ErrSink *err);
DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err); DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *err);
DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err); DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_ErrSink *err);
DN_API void DN_OS_FileClose (DN_OSFile *file); DN_API void DN_OS_FileClose (DN_OSFile *file);
DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err); DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_ErrSink *err);
DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err); DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_ErrSink *err);
DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err); DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_ErrSink *err);
DN_API DN_Str8 DN_OS_FileReadAllTLS (DN_Str8 path, DN_OSErrSink *err);
DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path); DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path);
DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against); DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against);
@ -361,42 +363,25 @@ DN_API bool DN_OS_PathMakeDir (D
DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it); DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it);
DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
DN_API bool DN_OS_PathAddRefTLS (DN_OSPath *fs_path, DN_Str8 path);
DN_API bool DN_OS_PathAddRefFrame (DN_OSPath *fs_path, DN_Str8 path);
DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
#define DN_OS_PathAddFromTLS(...) DN_OS_PathAdd(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathAddFromFrame(...) DN_OS_PathAdd(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...); DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_OS_PathAddFFromTLS(...) DN_OS_PathAddF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathAddFFromFrame(...) DN_OS_PathAddF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API bool DN_OS_PathPop (DN_OSPath *fs_path); DN_API bool DN_OS_PathPop (DN_OSPath *fs_path);
DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator); DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator);
#define DN_OS_PathBuildWithSeperatorFromTLS(...) DN_OS_PathBuildWithSeperator(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathBuildWithSeperatorFromFrame(...) DN_OS_PathBuildWithSeperator(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor); DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor);
#define DN_OS_PathToFromTLS(...) DN_OS_PathTo(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathToFromFrame(...) DN_OS_PathTo(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_OS_PathToFFromTLS(...) DN_OS_PathToF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathToFFromFrame(...) DN_OS_PathToF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path); DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path);
#define DN_OS_PathFromTLS(...) DN_OS_Path(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathFromFrame(...) DN_OS_Path(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_OS_PathFFromTLS(...) DN_OS_PathF(DN_OS_TLSTopArena(), ##__VA_ARGS__)
#define DN_OS_PathFFromFrame(...) DN_OS_PathF(DN_OS_TLSFrameArena(), ##__VA_ARGS__)
#define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("/")) #define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("/"))
#define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("\\")) #define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("\\"))
#define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString) #define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString)
DN_API void DN_OS_Exit (int32_t exit_code); DN_API void DN_OS_Exit (int32_t exit_code);
DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err); DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_ErrSink *err);
DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err); DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_ErrSink *err);
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err); DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_ErrSink *err);
DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err); DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_ErrSink *err);
DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena); DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
#define DN_OS_ExecOrAbortFromTLS (...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena())
DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count); DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count);
DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore); DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore);
@ -426,4 +411,104 @@ DN_API void DN_OS_HttpRequestAsync (D
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response); DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);
DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response); DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response);
DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
// NOTE: DN_OSPrint
enum DN_OSPrintDest
{
DN_OSPrintDest_Out,
DN_OSPrintDest_Err,
};
// NOTE: Print Macros
#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string)
#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args)
#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string)
#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args)
#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string)
#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args)
#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string);
#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args);
#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string)
#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args)
#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string)
#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args)
#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string)
#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args)
#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string);
#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args);
// NOTE: Print
DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string);
DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string);
DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string);
DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string);
DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
// NOTE: DN_VArray
// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS.
template <typename T> struct DN_VArray
{
T *data; // Pointer to the start of the array items in the block of memory
DN_USize size; // Number of items currently in the array
DN_USize max; // Maximum number of items this array can store
DN_USize commit; // Bytes committed
T *begin() { return data; }
T *end () { return data + size; }
T const *begin() const { return data; }
T const *end () const { return data + size; }
};
template <typename T> DN_VArray<T> DN_OS_VArrayInitByteSize (DN_USize byte_size);
template <typename T> DN_VArray<T> DN_OS_VArrayInit (DN_USize max);
template <typename T> DN_VArray<T> DN_OS_VArrayInitSlice (DN_Slice<T> slice, DN_USize max);
template <typename T, DN_USize N> DN_VArray<T> DN_OS_VArrayInitCArray (T const (&items)[N], DN_USize max);
template <typename T> void DN_OS_VArrayDeinit (DN_VArray<T> *array);
template <typename T> bool DN_OS_VArrayIsValid (DN_VArray<T> const *array);
template <typename T> bool DN_OS_VArrayReserve (DN_VArray<T> *array, DN_USize count);
template <typename T> T * DN_OS_VArrayAddArray (DN_VArray<T> *array, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_OS_VArrayAddCArray (DN_VArray<T> *array, T const (&items)[N]);
template <typename T> T * DN_OS_VArrayAdd (DN_VArray<T> *array, T const &item);
#define DN_OS_VArrayAddArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddArray(__VA_ARGS__))
#define DN_OS_VArrayAddCArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddCArray(__VA_ARGS__))
#define DN_OS_VArrayAddAssert(...) DN_HardAssert(DN_OS_VArrayAdd(__VA_ARGS__))
template <typename T> T * DN_OS_VArrayMakeArray (DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem);
template <typename T> T * DN_OS_VArrayMake (DN_VArray<T> *array, DN_ZMem z_mem);
#define DN_OS_VArrayMakeArrayAssert(...) DN_HardAssert(DN_OS_VArrayMakeArray(__VA_ARGS__))
#define DN_OS_VArrayMakeAssert(...) DN_HardAssert(DN_OS_VArrayMake(__VA_ARGS__))
template <typename T> T * DN_OS_VArrayInsertArray (DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_OS_VArrayInsertCArray (DN_VArray<T> *array, DN_USize index, T const (&items)[N]);
template <typename T> T * DN_OS_VArrayInsert (DN_VArray<T> *array, DN_USize index, T const &item);
#define DN_OS_VArrayInsertArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertArray(__VA_ARGS__))
#define DN_OS_VArrayInsertCArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertCArray(__VA_ARGS__))
#define DN_OS_VArrayInsertAssert(...) DN_HardAssert(DN_OS_VArrayInsert(__VA_ARGS__))
template <typename T> T DN_OS_VArrayPopFront (DN_VArray<T> *array, DN_USize count);
template <typename T> T DN_OS_VArrayPopBack (DN_VArray<T> *array, DN_USize count);
template <typename T> DN_ArrayEraseResult DN_OS_VArrayEraseRange (DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T> void DN_OS_VArrayClear (DN_VArray<T> *array, DN_ZMem z_mem);
#endif // !defined(DN_OS_H) #endif // !defined(DN_OS_H)

View File

@ -1,36 +0,0 @@
#define DN_OS_ALLOCATOR_CPP
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#include "../dn_inc.h"
#endif
static void *DN_ArenaBasicAllocFromOSHeap(DN_USize size)
{
void *result = DN_OS_MemAlloc(size, DN_ZMem_Yes);
return result;
}
DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags)
{
DN_ArenaMemFuncs mem_funcs = {};
mem_funcs.type = DN_ArenaMemFuncType_Basic;
mem_funcs.basic_alloc = DN_ArenaBasicAllocFromOSHeap;
mem_funcs.basic_dealloc = DN_OS_MemDealloc;
DN_Arena result = DN_ArenaFromMemFuncs(size, size, flags, mem_funcs);
return result;
}
DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags)
{
DN_ArenaMemFuncs mem_funcs = {};
mem_funcs.type = DN_ArenaMemFuncType_VMem;
mem_funcs.vmem_page_size = g_dn_->os.page_size;
mem_funcs.vmem_reserve = DN_OS_MemReserve;
mem_funcs.vmem_commit = DN_OS_MemCommit;
mem_funcs.vmem_release = DN_OS_MemRelease;
DN_Arena result = DN_ArenaFromMemFuncs(reserve, commit, flags, mem_funcs);
return result;
}

View File

@ -1,11 +0,0 @@
#if !defined(DN_OS_ALLOCATOR_H)
#define DN_OS_ALLOCATOR_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#endif
DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_ArenaFlags flags);
DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags);
#endif // !defined(DN_OS_ALLOCATOR_H)

View File

@ -1,204 +0,0 @@
#define DN_OS_CONTAINERS_CPP
#include "dn_os_containers.h"
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$$\ $$$$$$\
// $$ __$$\ $$ __$$\ $$$\ $$ |\__$$ __|$$ __$$\ \_$$ _|$$$\ $$ |$$ _____|$$ __$$\ $$ __$$\
// $$ / \__|$$ / $$ |$$$$\ $$ | $$ | $$ / $$ | $$ | $$$$\ $$ |$$ | $$ | $$ |$$ / \__|
// $$ | $$ | $$ |$$ $$\$$ | $$ | $$$$$$$$ | $$ | $$ $$\$$ |$$$$$\ $$$$$$$ |\$$$$$$\
// $$ | $$ | $$ |$$ \$$$$ | $$ | $$ __$$ | $$ | $$ \$$$$ |$$ __| $$ __$$< \____$$\
// $$ | $$\ $$ | $$ |$$ |\$$$ | $$ | $$ | $$ | $$ | $$ |\$$$ |$$ | $$ | $$ |$$\ $$ |
// \$$$$$$ | $$$$$$ |$$ | \$$ | $$ | $$ | $$ |$$$$$$\ $$ | \$$ |$$$$$$$$\ $$ | $$ |\$$$$$$ |
// \______/ \______/ \__| \__| \__| \__| \__|\______|\__| \__|\________|\__| \__| \______/
//
// dn_containers.cpp
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
// NOTE: DN_VArray /////////////////////////////////////////////////////////////////////////////////
template <typename T>
DN_VArray<T> DN_VArray_InitByteSize(DN_USize byte_size)
{
DN_VArray<T> result = {};
result.data = DN_Cast(T *) DN_OS_MemReserve(byte_size, DN_MemCommit_No, DN_MemPage_ReadWrite);
if (result.data)
result.max = byte_size / sizeof(T);
return result;
}
template <typename T>
DN_VArray<T> DN_VArray_Init(DN_USize max)
{
DN_VArray<T> result = DN_VArray_InitByteSize<T>(max * sizeof(T));
DN_Assert(result.max >= max);
return result;
}
template <typename T>
DN_VArray<T> DN_VArray_InitSlice(DN_Slice<T> slice, DN_USize max)
{
DN_USize real_max = DN_Max(slice.size, max);
DN_VArray<T> result = DN_VArray_Init<T>(real_max);
if (DN_VArray_IsValid(&result))
DN_VArray_AddArray(&result, slice.data, slice.size);
return result;
}
template <typename T, DN_USize N>
DN_VArray<T> DN_VArray_InitCArray(T const (&items)[N], DN_USize max)
{
DN_USize real_max = DN_Max(N, max);
DN_VArray<T> result = DN_VArray_InitSlice(DN_Slice_Init(items, N), real_max);
return result;
}
template <typename T>
void DN_VArray_Deinit(DN_VArray<T> *array)
{
DN_OS_MemRelease(array->data, array->max * sizeof(T));
*array = {};
}
template <typename T>
bool DN_VArray_IsValid(DN_VArray<T> const *array)
{
bool result = array->data && array->size <= array->max;
return result;
}
template <typename T>
DN_Slice<T> DN_VArray_Slice(DN_VArray<T> const *array)
{
DN_Slice<T> result = {};
if (array)
result = DN_Slice_Init<T>(array->data, array->size);
return result;
}
template <typename T>
T *DN_VArray_AddArray(DN_VArray<T> *array, T const *items, DN_USize count)
{
T *result = DN_VArray_MakeArray(array, count, DN_ZMem_No);
if (result)
DN_Memcpy(result, items, count * sizeof(T));
return result;
}
template <typename T, DN_USize N>
T *DN_VArray_AddCArray(DN_VArray<T> *array, T const (&items)[N])
{
T *result = DN_VArray_AddArray(array, items, N);
return result;
}
template <typename T>
T *DN_VArray_Add(DN_VArray<T> *array, T const &item)
{
T *result = DN_VArray_AddArray(array, &item, 1);
return result;
}
template <typename T>
T *DN_VArray_MakeArray(DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem)
{
if (!DN_VArray_IsValid(array))
return nullptr;
if (!DN_CheckF((array->size + count) < array->max, "Array is out of space (user requested +%zu items, array has %zu/%zu items)", count, array->size, array->max))
return nullptr;
if (!DN_VArray_Reserve(array, count))
return nullptr;
// TODO: Use placement new
T *result = array->data + array->size;
array->size += count;
if (z_mem == DN_ZMem_Yes)
DN_Memset(result, 0, count * sizeof(T));
return result;
}
template <typename T>
T *DN_VArray_Make(DN_VArray<T> *array, DN_ZMem z_mem)
{
T *result = DN_VArray_MakeArray(array, 1, z_mem);
return result;
}
template <typename T>
T *DN_VArray_InsertArray(DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count)
{
T *result = nullptr;
if (!DN_VArray_IsValid(array))
return result;
if (DN_VArray_Reserve(array, array->size + count))
result = DN_CArray_InsertArray(array->data, &array->size, array->max, index, items, count);
return result;
}
template <typename T, DN_USize N>
T *DN_VArray_InsertCArray(DN_VArray<T> *array, DN_USize index, T const (&items)[N])
{
T *result = DN_VArray_InsertArray(array, index, items, N);
return result;
}
template <typename T>
T *DN_VArray_Insert(DN_VArray<T> *array, DN_USize index, T const &item)
{
T *result = DN_VArray_InsertArray(array, index, &item, 1);
return result;
}
template <typename T>
T *DN_VArray_PopFront(DN_VArray<T> *array, DN_USize count)
{
T *result = DN_CArray_PopFront(array->data, &array->size, count);
return result;
}
template <typename T>
T *DN_VArray_PopBack(DN_VArray<T> *array, DN_USize count)
{
T *result = DN_CArray_PopBack(array->data, &array->size, count);
return result;
}
template <typename T>
DN_ArrayEraseResult DN_VArray_EraseRange(DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase)
{
DN_ArrayEraseResult result = {};
if (!DN_VArray_IsValid(array))
return result;
result = DN_CArray_EraseRange<T>(array->data, &array->size, begin_index, count, erase);
return result;
}
template <typename T>
void DN_VArray_Clear(DN_VArray<T> *array, DN_ZMem z_mem)
{
if (array) {
if (z_mem == DN_ZMem_Yes)
DN_Memset(array->data, 0, array->size * sizeof(T));
array->size = 0;
}
}
template <typename T>
bool DN_VArray_Reserve(DN_VArray<T> *array, DN_USize count)
{
if (!DN_VArray_IsValid(array) || count == 0)
return false;
DN_USize real_commit = (array->size + count) * sizeof(T);
DN_USize aligned_commit = DN_AlignUpPowerOfTwo(real_commit, g_dn_->os.page_size);
if (array->commit >= aligned_commit)
return true;
bool result = DN_OS_MemCommit(array->data, aligned_commit, DN_MemPage_ReadWrite);
array->commit = aligned_commit;
return result;
}

View File

@ -1,51 +0,0 @@
#if !defined(DN_OS_CONTAINERS_H)
#define DN_OS_CONTAINERS_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#endif
// NOTE: DN_VArray
// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS.
template <typename T> struct DN_VArray
{
T *data; // Pointer to the start of the array items in the block of memory
DN_USize size; // Number of items currently in the array
DN_USize max; // Maximum number of items this array can store
DN_USize commit; // Bytes committed
T *begin() { return data; }
T *end () { return data + size; }
T const *begin() const { return data; }
T const *end () const { return data + size; }
};
template <typename T> DN_VArray<T> DN_VArray_InitByteSize (DN_USize byte_size);
template <typename T> DN_VArray<T> DN_VArray_Init (DN_USize max);
template <typename T> DN_VArray<T> DN_VArray_InitSlice (DN_Slice<T> slice, DN_USize max);
template <typename T, DN_USize N> DN_VArray<T> DN_VArray_InitCArray (T const (&items)[N], DN_USize max);
template <typename T> void DN_VArray_Deinit (DN_VArray<T> *array);
template <typename T> bool DN_VArray_IsValid (DN_VArray<T> const *array);
template <typename T> DN_Slice<T> DN_VArray_Slice (DN_VArray<T> const *array);
template <typename T> bool DN_VArray_Reserve (DN_VArray<T> *array, DN_USize count);
template <typename T> T * DN_VArray_AddArray (DN_VArray<T> *array, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_VArray_AddCArray (DN_VArray<T> *array, T const (&items)[N]);
template <typename T> T * DN_VArray_Add (DN_VArray<T> *array, T const &item);
#define DN_VArray_AddArrayAssert(...) DN_HardAssert(DN_VArray_AddArray(__VA_ARGS__))
#define DN_VArray_AddCArrayAssert(...) DN_HardAssert(DN_VArray_AddCArray(__VA_ARGS__))
#define DN_VArray_AddAssert(...) DN_HardAssert(DN_VArray_Add(__VA_ARGS__))
template <typename T> T * DN_VArray_MakeArray (DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem);
template <typename T> T * DN_VArray_Make (DN_VArray<T> *array, DN_ZMem z_mem);
#define DN_VArray_MakeArrayAssert(...) DN_HardAssert(DN_VArray_MakeArray(__VA_ARGS__))
#define DN_VArray_MakeAssert(...) DN_HardAssert(DN_VArray_Make(__VA_ARGS__))
template <typename T> T * DN_VArray_InsertArray (DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count);
template <typename T, DN_USize N> T * DN_VArray_InsertCArray (DN_VArray<T> *array, DN_USize index, T const (&items)[N]);
template <typename T> T * DN_VArray_Insert (DN_VArray<T> *array, DN_USize index, T const &item);
#define DN_VArray_InsertArrayAssert(...) DN_HardAssert(DN_VArray_InsertArray(__VA_ARGS__))
#define DN_VArray_InsertCArrayAssert(...) DN_HardAssert(DN_VArray_InsertCArray(__VA_ARGS__))
#define DN_VArray_InsertAssert(...) DN_HardAssert(DN_VArray_Insert(__VA_ARGS__))
template <typename T> T DN_VArray_PopFront (DN_VArray<T> *array, DN_USize count);
template <typename T> T DN_VArray_PopBack (DN_VArray<T> *array, DN_USize count);
template <typename T> DN_ArrayEraseResult DN_VArray_EraseRange (DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
template <typename T> void DN_VArray_Clear (DN_VArray<T> *array, DN_ZMem z_mem);
#endif // !defined(DN_OS_CONTAINERS_H)

View File

@ -1,12 +1,14 @@
#define DN_OS_POSIX_CPP #define DN_OS_POSIX_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn_os_inc.h" #include "../dn.h"
#include "dn_os_posix.h"
#endif #endif
#include <dirent.h> // readdir, opendir, closedir #include <dirent.h> // readdir, opendir, closedir
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <sys/mman.h>
// NOTE: DN_OSMem // NOTE: DN_OSMem
static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect) static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect)
@ -226,17 +228,20 @@ DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value)
DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path) DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_OSDiskSpace result = {}; DN_OSDiskSpace result = {};
DN_Str8 path_z_terminated = DN_Str8FromStr8Arena(tmem.arena, path); DN_Str8 path_z_terminated = DN_Str8FromStr8Arena(tmem.arena, path);
struct statvfs info = {}; struct statvfs info = {};
if (statvfs(path_z_terminated.data, &info) != 0) if (statvfs(path_z_terminated.data, &info) != 0) {
DN_TCScratchEnd(&tmem);
return result; return result;
}
result.success = true; result.success = true;
result.avail = info.f_bavail * info.f_frsize; result.avail = info.f_bavail * info.f_frsize;
result.size = info.f_blocks * info.f_frsize; result.size = info.f_blocks * info.f_frsize;
DN_TCScratchEnd(&tmem);
return result; return result;
} }
@ -313,23 +318,23 @@ DN_API DN_U64 DN_OS_PerfCounterFrequency()
return result; return result;
} }
static DN_POSIXCore *DN_OS_GetPOSIXCore_() static DN_OSPosixCore *DN_OS_GetPOSIXCore_()
{ {
DN_Assert(g_dn_ && g_dn_->os.platform_context); DN_Assert(g_dn_ && g_dn_->os.platform_context);
DN_POSIXCore *result = DN_Cast(DN_POSIXCore *)g_dn_->os.platform_context; DN_OSPosixCore *result = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context;
return result; return result;
} }
DN_API DN_U64 DN_OS_PerfCounterNow() DN_API DN_U64 DN_OS_PerfCounterNow()
{ {
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
struct timespec ts; struct timespec ts;
clock_gettime(posix->clock_monotonic_raw ? CLOCK_MONOTONIC_RAW : CLOCK_MONOTONIC, &ts); clock_gettime(posix->clock_monotonic_raw ? CLOCK_MONOTONIC_RAW : CLOCK_MONOTONIC, &ts);
DN_U64 result = DN_Cast(DN_U64) ts.tv_sec * 1'000'000'000 + DN_Cast(DN_U64) ts.tv_nsec; DN_U64 result = DN_Cast(DN_U64) ts.tv_sec * 1'000'000'000 + DN_Cast(DN_U64) ts.tv_nsec;
return result; return result;
} }
DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error)
{ {
bool result = false; bool result = false;
#if defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
@ -385,9 +390,9 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
result = (bytes_written == stat_existing.st_size); result = (bytes_written == stat_existing.st_size);
if (!result) { if (!result) {
int error_code = errno; int error_code = errno;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 file_size_str8 = DN_Str8FromByteCount(tmem.arena, stat_existing.st_size, DN_ByteCountType_Auto); DN_Str8 file_size_str8 = DN_Str8FromByteCount(scratch.arena, stat_existing.st_size, DN_ByteCountType_Auto);
DN_Str8 bytes_written_str8 = DN_Str8FromByteCount(tmem.arena, bytes_written, DN_ByteCountType_Auto); DN_Str8 bytes_written_str8 = DN_Str8FromByteCount(scratch.arena, bytes_written, DN_ByteCountType_Auto);
DN_OS_ErrSinkAppendF(error, DN_OS_ErrSinkAppendF(error,
error_code, error_code,
"Failed to copy file '%.*s' to '%.*s', we copied %.*s but the file " "Failed to copy file '%.*s' to '%.*s', we copied %.*s but the file "
@ -398,13 +403,14 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
DN_Str8PrintFmt(file_size_str8), DN_Str8PrintFmt(file_size_str8),
error_code, error_code,
strerror(error_code)); strerror(error_code));
DN_TCScratchEnd(&scratch);
} }
#endif #endif
return result; return result;
} }
DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *error)
{ {
// See: https://github.com/gingerBill/gb/blob/master/gb.h // See: https://github.com/gingerBill/gb/blob/master/gb.h
bool result = false; bool result = false;
@ -435,7 +441,7 @@ DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi
DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path,
DN_OSFileOpen open_mode, DN_OSFileOpen open_mode,
DN_OSFileAccess access, DN_OSFileAccess access,
DN_OSErrSink *error) DN_ErrSink *error)
{ {
DN_OSFile result = {}; DN_OSFile result = {};
if (path.size == 0 || path.size <= 0) if (path.size == 0 || path.size <= 0)
@ -506,7 +512,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path,
return result; return result;
} }
DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err) DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err)
{ {
DN_OSFileRead result = {}; DN_OSFileRead result = {};
if (!file || !file->handle || file->error || !buffer || size <= 0) if (!file || !file->handle || file->error || !buffer || size <= 0)
@ -514,9 +520,10 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size
result.bytes_read = fread(buffer, 1, size, DN_Cast(FILE *) file->handle); result.bytes_read = fread(buffer, 1, size, DN_Cast(FILE *) file->handle);
if (feof(DN_Cast(FILE*)file->handle)) { if (feof(DN_Cast(FILE*)file->handle)) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
DN_OS_ErrSinkAppendF(err, 1, "Failed to read %S from file", buffer_size_str8); DN_OS_ErrSinkAppendF(err, 1, "Failed to read %S from file", buffer_size_str8);
DN_TCScratchEnd(&scratch);
return result; return result;
} }
@ -524,7 +531,7 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size
return result; return result;
} }
DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_OSErrSink *err) DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize size, DN_ErrSink *err)
{ {
if (!file || !file->handle || file->error || !buffer || size <= 0) if (!file || !file->handle || file->error || !buffer || size <= 0)
return false; return false;
@ -532,14 +539,15 @@ DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize siz
fwrite(buffer, DN_Cast(DN_USize) size, 1 /*count*/, DN_Cast(FILE *) file->handle) == fwrite(buffer, DN_Cast(DN_USize) size, 1 /*count*/, DN_Cast(FILE *) file->handle) ==
1 /*count*/; 1 /*count*/;
if (!result) { if (!result) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size); DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
DN_OS_ErrSinkAppendF(err, 1, "Failed to write buffer (%s) to file handle", DN_Str8PrintFmt(buffer_size_str8)); DN_OS_ErrSinkAppendF(err, 1, "Failed to write buffer (%s) to file handle", DN_Str8PrintFmt(buffer_size_str8));
DN_TCScratchEnd(&scratch);
} }
return result; return result;
} }
DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_OSErrSink *err) DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_ErrSink *err)
{ {
// TODO: errno is not thread safe // TODO: errno is not thread safe
int fd = fileno(DN_Cast(FILE *) file->handle); int fd = fileno(DN_Cast(FILE *) file->handle);
@ -622,7 +630,7 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
DN_API bool DN_OS_PathMakeDir(DN_Str8 path) DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
{ {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
bool result = true; bool result = true;
// TODO(doyle): Implement this without using the path indexes, it's not // TODO(doyle): Implement this without using the path indexes, it's not
@ -630,7 +638,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
DN_USize path_indexes_size = 0; DN_USize path_indexes_size = 0;
uint16_t path_indexes[64] = {}; uint16_t path_indexes[64] = {};
DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, path); DN_Str8 copy = DN_Str8FromStr8Arena(scratch.arena, path);
for (DN_USize index = copy.size - 1; index < copy.size; index--) { for (DN_USize index = copy.size - 1; index < copy.size; index--) {
bool first_char = index == (copy.size - 1); bool first_char = index == (copy.size - 1);
char ch = copy.data[index]; char ch = copy.data[index];
@ -649,6 +657,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
// NOTE: There's something that exists in at this path, but // NOTE: There's something that exists in at this path, but
// it's not a directory. This request to make a directory is // it's not a directory. This request to make a directory is
// invalid. // invalid.
DN_TCScratchEnd(&scratch);
return false; return false;
} else if (DN_OS_PathIsDir(copy)) { } else if (DN_OS_PathIsDir(copy)) {
// NOTE: We found a directory, we can stop here and start // NOTE: We found a directory, we can stop here and start
@ -673,6 +682,7 @@ DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
if (index != 0) if (index != 0)
copy.data[path_index] = temp; copy.data[path_index] = temp;
} }
DN_TCScratchEnd(&scratch);
return result; return result;
} }
@ -723,7 +733,7 @@ enum DN_OSPipeType_
DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
DN_Arena *arena, DN_Arena *arena,
DN_OSErrSink *error) DN_ErrSink *error)
{ {
DN_OSExecResult result = {}; DN_OSExecResult result = {};
if (!handle.process || handle.os_error_code || handle.exit_code) { if (!handle.process || handle.os_error_code || handle.exit_code) {
@ -786,10 +796,10 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
// NOTE: Read the data from the read end of the pipe // NOTE: Read the data from the read end of the pipe
if (result.os_error_code == 0) { if (result.os_error_code == 0) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena); DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
if (arena && handle.stdout_read) { if (arena && handle.stdout_read) {
char buffer[4096]; char buffer[4096];
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena); DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena);
for (;;) { for (;;) {
ssize_t bytes_read = ssize_t bytes_read =
read(stdout_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer)); read(stdout_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer));
@ -803,7 +813,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
if (arena && handle.stderr_read) { if (arena && handle.stderr_read) {
char buffer[4096]; char buffer[4096];
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena); DN_Str8Builder builder = DN_Str8BuilderFromArena(scratch.arena);
for (;;) { for (;;) {
ssize_t bytes_read = ssize_t bytes_read =
read(stderr_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer)); read(stderr_pipe[DN_OSPipeType__Read], buffer, sizeof(buffer));
@ -814,6 +824,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
result.stderr_text = DN_Str8BuilderBuild(&builder, arena); result.stderr_text = DN_Str8BuilderBuild(&builder, arena);
} }
DN_TCScratchEnd(&scratch);
} }
close(stdout_pipe[DN_OSPipeType__Read]); close(stdout_pipe[DN_OSPipeType__Read]);
@ -823,7 +834,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle,
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line, DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
DN_OSExecArgs *args, DN_OSExecArgs *args,
DN_OSErrSink *error) DN_ErrSink *error)
{ {
#if defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
DN_InvalidCodePathF("Unsupported operation"); DN_InvalidCodePathF("Unsupported operation");
@ -834,12 +845,13 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
if (cmd_line.size == 0) if (cmd_line.size == 0)
return result; return result;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 cmd_rendered = DN_Slice_Str8Render(tmem.arena, cmd_line, DN_Str8Lit(" ")); DN_DEFER { DN_TCScratchEnd(&scratch); };
DN_Str8 cmd_rendered = DN_Slice_Str8Render(scratch.arena, cmd_line, DN_Str8Lit(" "));
int stdout_pipe[DN_OSPipeType__Count] = {}; int stdout_pipe[DN_OSPipeType__Count] = {};
int stderr_pipe[DN_OSPipeType__Count] = {}; int stderr_pipe[DN_OSPipeType__Count] = {};
// NOTE: Open stdout pipe ////////////////////////////////////////////////////////////////////// // NOTE: Open stdout pipe
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) { if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) {
if (pipe(stdout_pipe) == -1) { if (pipe(stdout_pipe) == -1) {
result.os_error_code = errno; result.os_error_code = errno;
@ -929,7 +941,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
// NOTE: Convert the command into something suitable for execvp // NOTE: Convert the command into something suitable for execvp
char **argv = char **argv =
DN_ArenaNewArray(tmem.arena, char *, cmd_line.size + 1 /*null*/, DN_ZMem_Yes); DN_ArenaNewArray(scratch.arena, char *, cmd_line.size + 1 /*null*/, DN_ZMem_Yes);
if (!argv) { if (!argv) {
result.exit_code = -1; result.exit_code = -1;
DN_OS_ErrSinkAppendF( DN_OS_ErrSinkAppendF(
@ -942,7 +954,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
for (DN_ForIndexU(arg_index, cmd_line.size)) { for (DN_ForIndexU(arg_index, cmd_line.size)) {
DN_Str8 arg = cmd_line.data[arg_index]; DN_Str8 arg = cmd_line.data[arg_index];
argv[arg_index] = DN_Str8FromStr8Arena(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated argv[arg_index] = DN_Str8FromStr8Arena(scratch.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated
} }
// NOTE: Change the working directory if there is one // NOTE: Change the working directory if there is one
@ -960,7 +972,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
if (args->working_dir.size) { if (args->working_dir.size) {
prev_working_dir = get_current_dir_name(); prev_working_dir = get_current_dir_name();
DN_Str8 working_dir = DN_Str8FromStr8Arena(tmem.arena, args->working_dir); DN_Str8 working_dir = DN_Str8FromStr8Arena(scratch.arena, args->working_dir);
if (chdir(working_dir.data) == -1) { if (chdir(working_dir.data) == -1) {
result.os_error_code = errno; result.os_error_code = errno;
DN_OS_ErrSinkAppendF( DN_OS_ErrSinkAppendF(
@ -1014,21 +1026,21 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
char *stderr_buffer, char *stderr_buffer,
size_t *stderr_size, size_t *stderr_size,
DN_U32 timeout_ms, DN_U32 timeout_ms,
DN_OSErrSink *err) DN_ErrSink *err)
{ {
DN_InvalidCodePath; DN_InvalidCodePath;
DN_OSExecResult result = {}; DN_OSExecResult result = {};
return result; return result;
} }
static DN_POSIXSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64) static DN_OSPosixSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64)
{ {
DN_POSIXSyncPrimitive *result = nullptr; DN_OSPosixSyncPrimitive *result = nullptr;
DN_Memcpy(&result, &u64, sizeof(result)); DN_Memcpy(&result, &u64, sizeof(result));
return result; return result;
} }
static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive) static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_OSPosixSyncPrimitive *primitive)
{ {
DN_U64 result = 0; DN_U64 result = 0;
static_assert(sizeof(result) >= sizeof(primitive), "Pointer size mis-match"); static_assert(sizeof(result) >= sizeof(primitive), "Pointer size mis-match");
@ -1036,10 +1048,10 @@ static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive)
return result; return result;
} }
static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_() static DN_OSPosixSyncPrimitive *DN_POSIX_AllocSyncPrimitive_()
{ {
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
DN_POSIXSyncPrimitive *result = nullptr; DN_OSPosixSyncPrimitive *result = nullptr;
pthread_mutex_lock(&posix->sync_primitive_free_list_mutex); pthread_mutex_lock(&posix->sync_primitive_free_list_mutex);
{ {
if (posix->sync_primitive_free_list) { if (posix->sync_primitive_free_list) {
@ -1048,17 +1060,17 @@ static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_()
result->next = nullptr; result->next = nullptr;
} else { } else {
DN_OSCore *os = &g_dn_->os; DN_OSCore *os = &g_dn_->os;
result = DN_ArenaNew(&os->arena, DN_POSIXSyncPrimitive, DN_ZMem_Yes); result = DN_ArenaNew(&os->arena, DN_OSPosixSyncPrimitive, DN_ZMem_Yes);
} }
} }
pthread_mutex_unlock(&posix->sync_primitive_free_list_mutex); pthread_mutex_unlock(&posix->sync_primitive_free_list_mutex);
return result; return result;
} }
static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive) static void DN_POSIX_DeallocSyncPrimitive_(DN_OSPosixSyncPrimitive *primitive)
{ {
if (primitive) { if (primitive) {
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_(); DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_();
pthread_mutex_lock(&posix->sync_primitive_free_list_mutex); pthread_mutex_lock(&posix->sync_primitive_free_list_mutex);
primitive->next = posix->sync_primitive_free_list; primitive->next = posix->sync_primitive_free_list;
posix->sync_primitive_free_list = primitive; posix->sync_primitive_free_list = primitive;
@ -1070,7 +1082,7 @@ static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive)
DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count)
{ {
DN_OSSemaphore result = {}; DN_OSSemaphore result = {};
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
if (primitive) { if (primitive) {
int pshared = 0; // Share the semaphore across all threads in the process int pshared = 0; // Share the semaphore across all threads in the process
if (sem_init(&primitive->sem, pshared, initial_count) == 0) if (sem_init(&primitive->sem, pshared, initial_count) == 0)
@ -1084,7 +1096,7 @@ DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count)
DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore)
{ {
if (semaphore && semaphore->handle != 0) { if (semaphore && semaphore->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
sem_destroy(&primitive->sem); sem_destroy(&primitive->sem);
DN_POSIX_DeallocSyncPrimitive_(primitive); DN_POSIX_DeallocSyncPrimitive_(primitive);
*semaphore = {}; *semaphore = {};
@ -1094,7 +1106,7 @@ DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore)
DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount) DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount)
{ {
if (semaphore && semaphore->handle != 0) { if (semaphore && semaphore->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
#if defined(DN_OS_WIN32) #if defined(DN_OS_WIN32)
sem_post_multiple(&primitive->sem, amount); // mingw extension sem_post_multiple(&primitive->sem, amount); // mingw extension
#else #else
@ -1111,7 +1123,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore,
if (!semaphore || semaphore->handle == 0) if (!semaphore || semaphore->handle == 0)
return result; return result;
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) { if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) {
int wait_result = 0; int wait_result = 0;
do { do {
@ -1138,7 +1150,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore,
// NOTE: DN_OSMutex //////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSMutex ////////////////////////////////////////////////////////////////////////////////
DN_API DN_OSMutex DN_OS_MutexInit() DN_API DN_OSMutex DN_OS_MutexInit()
{ {
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
DN_OSMutex result = {}; DN_OSMutex result = {};
if (primitive) { if (primitive) {
if (pthread_mutex_init(&primitive->mutex, nullptr) == 0) if (pthread_mutex_init(&primitive->mutex, nullptr) == 0)
@ -1152,7 +1164,7 @@ DN_API DN_OSMutex DN_OS_MutexInit()
DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex)
{ {
if (mutex && mutex->handle != 0) { if (mutex && mutex->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
pthread_mutex_destroy(&primitive->mutex); pthread_mutex_destroy(&primitive->mutex);
DN_POSIX_DeallocSyncPrimitive_(primitive); DN_POSIX_DeallocSyncPrimitive_(primitive);
*mutex = {}; *mutex = {};
@ -1162,7 +1174,7 @@ DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex)
DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) DN_API void DN_OS_MutexLock(DN_OSMutex *mutex)
{ {
if (mutex && mutex->handle != 0) { if (mutex && mutex->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
pthread_mutex_lock(&primitive->mutex); pthread_mutex_lock(&primitive->mutex);
} }
} }
@ -1170,14 +1182,14 @@ DN_API void DN_OS_MutexLock(DN_OSMutex *mutex)
DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex) DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex)
{ {
if (mutex && mutex->handle != 0) { if (mutex && mutex->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
pthread_mutex_unlock(&primitive->mutex); pthread_mutex_unlock(&primitive->mutex);
} }
} }
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit() DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit()
{ {
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
DN_OSConditionVariable result = {}; DN_OSConditionVariable result = {};
if (primitive) { if (primitive) {
if (pthread_cond_init(&primitive->cv, nullptr) == 0) if (pthread_cond_init(&primitive->cv, nullptr) == 0)
@ -1191,7 +1203,7 @@ DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit()
DN_API void DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv)
{ {
if (cv && cv->handle != 0) { if (cv && cv->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
pthread_cond_destroy(&primitive->cv); pthread_cond_destroy(&primitive->cv);
DN_POSIX_DeallocSyncPrimitive_(primitive); DN_POSIX_DeallocSyncPrimitive_(primitive);
*cv = {}; *cv = {};
@ -1202,8 +1214,8 @@ DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMu
{ {
bool result = false; bool result = false;
if (cv && mutex && mutex->handle != 0 && cv->handle != 0) { if (cv && mutex && mutex->handle != 0 && cv->handle != 0) {
DN_POSIXSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); DN_OSPosixSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
DN_POSIXSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); DN_OSPosixSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
struct timespec time = {}; struct timespec time = {};
time.tv_sec = end_ts_ms / 1'000; time.tv_sec = end_ts_ms / 1'000;
@ -1224,7 +1236,7 @@ DN_API bool DN_OS_ConditionVariableWait(DN_OSConditionVariable *cv, DN_OSMutex *
DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv)
{ {
if (cv && cv->handle != 0) { if (cv && cv->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
pthread_cond_signal(&primitive->cv); pthread_cond_signal(&primitive->cv);
} }
} }
@ -1232,7 +1244,7 @@ DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv)
DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv)
{ {
if (cv && cv->handle != 0) { if (cv && cv->handle != 0) {
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
pthread_cond_broadcast(&primitive->cv); pthread_cond_broadcast(&primitive->cv);
} }
} }
@ -1307,7 +1319,7 @@ DN_API DN_U32 DN_OS_ThreadID()
return DN_Cast(DN_U32) result; return DN_Cast(DN_U32) result;
} }
DN_API void DN_Posix_Init(DN_POSIXCore *posix) DN_API void DN_OS_PosixInit(DN_OSPosixCore *posix)
{ {
int mutex_init = pthread_mutex_init(&posix->sync_primitive_free_list_mutex, nullptr); int mutex_init = pthread_mutex_init(&posix->sync_primitive_free_list_mutex, nullptr);
DN_Assert(mutex_init == 0); DN_Assert(mutex_init == 0);
@ -1320,21 +1332,22 @@ DN_API void DN_Posix_Init(DN_POSIXCore *posix)
} }
} }
DN_API void DN_Posix_ThreadSetName(DN_Str8 name) DN_API void DN_OS_PosixThreadSetName(DN_Str8 name)
{ {
#if defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
(void)name; (void)name;
#else #else
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, name); DN_Str8 copy = DN_Str8FromStr8Arena(tmem.arena, name);
pthread_t thread = pthread_self(); pthread_t thread = pthread_self();
pthread_setname_np(thread, (char *)copy.data); pthread_setname_np(thread, (char *)copy.data);
DN_TCScratchEnd(&tmem);
#endif #endif
} }
DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus() DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus()
{ {
DN_POSIXProcSelfStatus result = {}; DN_OSPosixProcSelfStatus result = {};
// NOTE: Example // NOTE: Example
// //
@ -1346,11 +1359,11 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
// //
// VmSize is the total virtual memory used // VmSize is the total virtual memory used
DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/proc/self/status"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, nullptr); DN_OSFile file = DN_OS_FileOpen(DN_Str8Lit("/proc/self/status"), DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, nullptr);
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
if (!file.error) { if (!file.error) {
DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
char buf[256]; char buf[256];
DN_Str8Builder builder = DN_Str8BuilderFromTLS(); DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena);
for (;;) { for (;;) {
DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr); DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr);
if (!read.success || read.bytes_read == 0) if (!read.success || read.bytes_read == 0)
@ -1362,8 +1375,8 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
DN_Str8 const PID = DN_Str8Lit("Pid:"); DN_Str8 const PID = DN_Str8Lit("Pid:");
DN_Str8 const VM_PEAK = DN_Str8Lit("VmPeak:"); DN_Str8 const VM_PEAK = DN_Str8Lit("VmPeak:");
DN_Str8 const VM_SIZE = DN_Str8Lit("VmSize:"); DN_Str8 const VM_SIZE = DN_Str8Lit("VmSize:");
DN_Str8 status_buf = DN_Str8BuilderBuildFromTLS(&builder); DN_Str8 status_buf = DN_Str8BuilderBuild(&builder, tmem.arena);
DN_Str8SplitResult lines = DN_Str8SplitFromTLS(status_buf, DN_Str8Lit("\n"), DN_Str8SplitIncludeEmptyStrings_No); DN_Str8SplitResult lines = DN_Str8Split(tmem.arena, status_buf, DN_Str8Lit("\n"), DN_Str8SplitIncludeEmptyStrings_No);
for (DN_ForItSize(line_it, DN_Str8, lines.data, lines.count)) { for (DN_ForItSize(line_it, DN_Str8, lines.data, lines.count)) {
DN_Str8 line = DN_Str8TrimWhitespaceAround(*line_it.data); DN_Str8 line = DN_Str8TrimWhitespaceAround(*line_it.data);
@ -1392,6 +1405,7 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
DN_Assert(to_u64.success); DN_Assert(to_u64.success);
} }
} }
DN_TCScratchEnd(&tmem);
} }
DN_OS_FileClose(&file); DN_OS_FileClose(&file);
return result; return result;
@ -1406,7 +1420,7 @@ static EM_BOOL EMWebSocketOnOpenCallback(int type, const EmscriptenWebSocketOpen
(void)event; (void)event;
// EMSCRIPTEN_RESULT result = emscripten_websocket_send_utf8_text(event->socket, R"({"jsonrpc":"2.0","id":1,"method": "eth_subscribe","params":["newHeads"]})"); // EMSCRIPTEN_RESULT result = emscripten_websocket_send_utf8_text(event->socket, R"({"jsonrpc":"2.0","id":1,"method": "eth_subscribe","params":["newHeads"]})");
// if (result) // if (result)
// DN_LOG_InfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result); // DN_LogInfoF("Failed to emscripten_websocket_send_utf8_text(): %d\n", result);
return EM_TRUE; return EM_TRUE;
} }
@ -1416,9 +1430,9 @@ static EM_BOOL EMWebSocketOnMsgCallback(int type, const EmscriptenWebSocketMessa
(void)user_context; (void)user_context;
(void)event; (void)event;
if (event->isText) { if (event->isText) {
DN_LOG_InfoF("Received: %.*s", event->numBytes, event->data); DN_LogInfoF("Received: %.*s", event->numBytes, event->data);
} else { } else {
DN_LOG_InfoF("Received: %d bytes", event->numBytes); DN_LogInfoF("Received: %d bytes", event->numBytes);
} }
return EM_TRUE; return EM_TRUE;
} }
@ -1486,12 +1500,13 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
response->arena = arena; response->arena = arena;
response->builder.arena = response->builder.arena =
response->tmem_arena ? response->tmem_arena : &response->tmp_arena; response->scratch_arena ? response->scratch_arena : &response->tmp_arena;
DN_Arena *tmem = response->tmem_arena; DN_Arena *scratch = response->scratch_arena;
DN_OSTLSTMem tmem_ = DN_OS_TLSTMem(arena); DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1);
if (!tmem) DN_DEFER { DN_TCScratchEnd(&scratch_); };
tmem = tmem_.arena; if (!scratch)
scratch = scratch_.arena;
#if defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_EMSCRIPTEN)
emscripten_fetch_attr_t fetch_attribs = {}; emscripten_fetch_attr_t fetch_attribs = {};
@ -1521,8 +1536,8 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
fetch_attribs.onerror = DN_OS_HttpRequestEMFetchOnErrorCallback; fetch_attribs.onerror = DN_OS_HttpRequestEMFetchOnErrorCallback;
fetch_attribs.userData = response; fetch_attribs.userData = response;
DN_Str8 url = DN_Str8FromFmtArena(tmem, "%.*s%.*s", DN_Str8PrintFmt(host), DN_Str8PrintFmt(path)); DN_Str8 url = DN_Str8FromFmtArena(scratch, "%.*s%.*s", DN_Str8PrintFmt(host), DN_Str8PrintFmt(path));
DN_LOG_InfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'", DN_LogInfoF("Initiating HTTP '%s' request to '%.*s' with payload '%.*s'",
fetch_attribs.requestMethod, fetch_attribs.requestMethod,
DN_Str8PrintFmt(url), DN_Str8PrintFmt(url),
DN_Str8PrintFmt(body)); DN_Str8PrintFmt(body));

View File

@ -2,30 +2,13 @@
#define DN_OS_POSIX_H #define DN_OS_POSIX_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
#include <pthread.h> #include <pthread.h>
#include <semaphore.h> #include <semaphore.h>
/* struct DN_OSPosixProcSelfStatus
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\
// $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ $$ __$$\ \_$$ _|$$ | $$ |
// $$ / $$ |$$ / \__| $$ | $$ |$$ / $$ |$$ / \__| $$ | \$$\ $$ |
// $$ | $$ |\$$$$$$\ $$$$$$$ |$$ | $$ |\$$$$$$\ $$ | \$$$$ /
// $$ | $$ | \____$$\ $$ ____/ $$ | $$ | \____$$\ $$ | $$ $$<
// $$ | $$ |$$\ $$ | $$ | $$ | $$ |$$\ $$ | $$ | $$ /\$$\
// $$$$$$ |\$$$$$$ | $$ | $$$$$$ |\$$$$$$ |$$$$$$\ $$ / $$ |
// \______/ \______/ \__| \______/ \______/ \______|\__| \__|
//
// dn_os_posix.h
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
struct DN_POSIXProcSelfStatus
{ {
char name[64]; char name[64];
DN_U8 name_size; DN_U8 name_size;
@ -52,15 +35,14 @@ struct DN_POSIXProcSelfStatus
// unlocking, or destroying the object is undefined. [...] The effect of // unlocking, or destroying the object is undefined. [...] The effect of
// referring to a copy of the object when locking, unlocking, or destroying it // referring to a copy of the object when locking, unlocking, or destroying it
// is undefined. // is undefined.
enum DN_OSPosixSyncPrimitiveType
enum DN_POSIXSyncPrimitiveType
{ {
DN_OSPOSIXSyncPrimitiveType_Semaphore, DN_OSPosixSyncPrimitiveType_Semaphore,
DN_OSPOSIXSyncPrimitiveType_Mutex, DN_OSPosixSyncPrimitiveType_Mutex,
DN_OSPOSIXSyncPrimitiveType_ConditionVariable, DN_OSPosixSyncPrimitiveType_ConditionVariable,
}; };
struct DN_POSIXSyncPrimitive struct DN_OSPosixSyncPrimitive
{ {
union union
{ {
@ -68,17 +50,17 @@ struct DN_POSIXSyncPrimitive
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t cv; pthread_cond_t cv;
}; };
DN_POSIXSyncPrimitive *next; DN_OSPosixSyncPrimitive *next;
}; };
struct DN_POSIXCore struct DN_OSPosixCore
{ {
DN_POSIXSyncPrimitive *sync_primitive_free_list; DN_OSPosixSyncPrimitive *sync_primitive_free_list;
pthread_mutex_t sync_primitive_free_list_mutex; pthread_mutex_t sync_primitive_free_list_mutex;
bool clock_monotonic_raw; bool clock_monotonic_raw;
}; };
DN_API void DN_Posix_Init(DN_POSIXCore *posix); DN_API void DN_OS_PosixInit (DN_OSPosixCore *posix);
DN_API void DN_Posix_ThreadSetName(DN_Str8 name); DN_API void DN_OS_PosixThreadSetName (DN_Str8 name);
DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus(); DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus();
#endif // !defined(DN_OS_POSIX_H) #endif // !defined(DN_OS_POSIX_H)

View File

@ -1,170 +0,0 @@
#define DN_OS_PRINT_CPP
DN_API DN_LOGStyle DN_OS_PrintStyleColour(uint8_t r, uint8_t g, uint8_t b, DN_LOGBold bold)
{
DN_LOGStyle result = {};
result.bold = bold;
result.colour = true;
result.r = r;
result.g = g;
result.b = b;
return result;
}
DN_API DN_LOGStyle DN_OS_PrintStyleColourU32(uint32_t rgb, DN_LOGBold bold)
{
uint8_t r = (rgb >> 24) & 0xFF;
uint8_t g = (rgb >> 16) & 0xFF;
uint8_t b = (rgb >> 8) & 0xFF;
DN_LOGStyle result = DN_OS_PrintStyleColour(r, g, b, bold);
return result;
}
DN_API DN_LOGStyle DN_OS_PrintStyleBold()
{
DN_LOGStyle result = {};
result.bold = DN_LOGBold_Yes;
return result;
}
DN_API void DN_OS_Print(DN_OSPrintDest dest, DN_Str8 string)
{
DN_Assert(dest == DN_OSPrintDest_Out || dest == DN_OSPrintDest_Err);
#if defined(DN_PLATFORM_WIN32)
// NOTE: Get the output handles from kernel ////////////////////////////////////////////////////
DN_THREAD_LOCAL void *std_out_print_handle = nullptr;
DN_THREAD_LOCAL void *std_err_print_handle = nullptr;
DN_THREAD_LOCAL bool std_out_print_to_console = false;
DN_THREAD_LOCAL bool std_err_print_to_console = false;
if (!std_out_print_handle) {
unsigned long mode = 0;
(void)mode;
std_out_print_handle = GetStdHandle(STD_OUTPUT_HANDLE);
std_out_print_to_console = GetConsoleMode(std_out_print_handle, &mode) != 0;
std_err_print_handle = GetStdHandle(STD_ERROR_HANDLE);
std_err_print_to_console = GetConsoleMode(std_err_print_handle, &mode) != 0;
}
// NOTE: Select the output handle //////////////////////////////////////////////////////////////
void *print_handle = std_out_print_handle;
bool print_to_console = std_out_print_to_console;
if (dest == DN_OSPrintDest_Err) {
print_handle = std_err_print_handle;
print_to_console = std_err_print_to_console;
}
// NOTE: Write the string //////////////////////////////////////////////////////////////////////
DN_Assert(string.size < DN_Cast(unsigned long) - 1);
unsigned long bytes_written = 0;
(void)bytes_written;
if (print_to_console)
WriteConsoleA(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr);
else
WriteFile(print_handle, string.data, DN_Cast(unsigned long) string.size, &bytes_written, nullptr);
#else
fprintf(dest == DN_OSPrintDest_Out ? stdout : stderr, "%.*s", DN_Str8PrintFmt(string));
#endif
}
DN_API void DN_OS_PrintF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_PrintFV(dest, fmt, args);
va_end(args);
}
DN_API void DN_OS_PrintFStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_PrintFVStyle(dest, style, fmt, args);
va_end(args);
}
DN_API void DN_OS_PrintStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string)
{
if (string.data && string.size) {
if (style.colour)
DN_OS_Print(dest, DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b));
if (style.bold == DN_LOGBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_BoldEscapeCode));
DN_OS_Print(dest, string);
if (style.colour || style.bold == DN_LOGBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_ResetEscapeCode));
}
}
static char *DN_OS_PrintVSPrintfChunker_(const char *buf, void *user, int len)
{
DN_Str8 string = {};
string.data = DN_Cast(char *) buf;
string.size = len;
DN_OSPrintDest dest = DN_Cast(DN_OSPrintDest) DN_Cast(uintptr_t) user;
DN_OS_Print(dest, string);
return (char *)buf;
}
DN_API void DN_OS_PrintFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args)
{
char buffer[STB_SPRINTF_MIN];
STB_SPRINTF_DECORATE(vsprintfcb)
(DN_OS_PrintVSPrintfChunker_, DN_Cast(void *) DN_Cast(uintptr_t) dest, buffer, fmt, args);
}
DN_API void DN_OS_PrintFVStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args)
{
if (fmt) {
if (style.colour)
DN_OS_Print(dest, DN_LOG_ColourEscapeCodeStr8FromRGB(DN_LOGColourType_Fg, style.r, style.g, style.b));
if (style.bold == DN_LOGBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_BoldEscapeCode));
DN_OS_PrintFV(dest, fmt, args);
if (style.colour || style.bold == DN_LOGBold_Yes)
DN_OS_Print(dest, DN_Str8Lit(DN_LOG_ResetEscapeCode));
}
}
DN_API void DN_OS_PrintLn(DN_OSPrintDest dest, DN_Str8 string)
{
DN_OS_Print(dest, string);
DN_OS_Print(dest, DN_Str8Lit("\n"));
}
DN_API void DN_OS_PrintLnF(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_PrintLnFV(dest, fmt, args);
va_end(args);
}
DN_API void DN_OS_PrintLnFV(DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_OS_PrintFV(dest, fmt, args);
DN_OS_Print(dest, DN_Str8Lit("\n"));
}
DN_API void DN_OS_PrintLnStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string)
{
DN_OS_PrintStyle(dest, style, string);
DN_OS_Print(dest, DN_Str8Lit("\n"));
}
DN_API void DN_OS_PrintLnFStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_PrintLnFVStyle(dest, style, fmt, args);
va_end(args);
}
DN_API void DN_OS_PrintLnFVStyle(DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_OS_PrintFVStyle(dest, style, fmt, args);
DN_OS_Print(dest, DN_Str8Lit("\n"));
}

View File

@ -1,59 +0,0 @@
#if !defined(DN_OS_PRINT_H)
#define DN_OS_PRINT_H
enum DN_OSPrintDest
{
DN_OSPrintDest_Out,
DN_OSPrintDest_Err,
};
// NOTE: Print Macros
#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string)
#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args)
#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string)
#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args)
#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string)
#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args)
#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string);
#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args);
#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string)
#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args)
#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string)
#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args)
#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string)
#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args)
#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string);
#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args);
// NOTE: Print
DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string);
DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string);
DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string);
DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_Str8 string);
DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LOGStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
#endif // !defined(DN_OS_PRINT_H)

View File

@ -1,211 +0,0 @@
#define DN_CORE_DEBUG_CPP
#if defined(_CLANGD)
#define DN_H_WITH_OS 1
#include "../dn.h"
#endif
DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, uint16_t limit)
{
DN_StackTraceWalkResult result = {};
#if defined(DN_OS_WIN32)
if (!arena)
return result;
static DN_TicketMutex mutex = {};
DN_TicketMutex_Begin(&mutex);
HANDLE thread = GetCurrentThread();
result.process = GetCurrentProcess();
DN_W32Core *w32 = DN_OS_GetW32Core_();
if (!w32->sym_initialised) {
w32->sym_initialised = true;
SymSetOptions(SYMOPT_LOAD_LINES);
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
DN_W32Error error = DN_W32_LastError(tmem.arena);
DN_LOG_ErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_Str8PrintFmt(error.msg));
}
}
CONTEXT context;
RtlCaptureContext(&context);
STACKFRAME64 frame = {};
frame.AddrPC.Offset = context.Rip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Rbp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Rsp;
frame.AddrStack.Mode = AddrModeFlat;
DN_FArray<uint64_t, 256> raw_frames = {};
while (raw_frames.size < limit) {
if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64,
result.process,
thread,
&frame,
&context,
nullptr /*ReadMemoryRoutine*/,
SymFunctionTableAccess64,
SymGetModuleBase64,
nullptr /*TranslateAddress*/))
break;
// NOTE: It might be useful one day to use frame.AddrReturn.Offset.
// If AddrPC.Offset == AddrReturn.Offset then we can detect recursion.
DN_FArray_Add(&raw_frames, frame.AddrPC.Offset);
}
DN_TicketMutex_End(&mutex);
result.base_addr = DN_ArenaNewArray(arena, uint64_t, raw_frames.size, DN_ZMem_No);
result.size = DN_Cast(uint16_t) raw_frames.size;
DN_Memcpy(result.base_addr, raw_frames.data, raw_frames.size * sizeof(raw_frames.data[0]));
#else
(void)limit;
(void)arena;
#endif
return result;
}
static void DN_StackTraceAddWalkToStr8Builder(DN_StackTraceWalkResult const *walk, DN_Str8Builder *builder, DN_USize skip)
{
DN_StackTraceRawFrame raw_frame = {};
raw_frame.process = walk->process;
for (DN_USize index = skip; index < walk->size; index++) {
raw_frame.base_addr = walk->base_addr[index];
DN_StackTraceFrame frame = DN_StackTraceRawFrameToFrame(builder->arena, raw_frame);
DN_Str8BuilderAppendF(builder, "%.*s(%zu): %.*s%s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name), (DN_Cast(int) index == walk->size - 1) ? "" : "\n");
}
}
DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk)
{
bool result = false;
if (!it || !walk || !walk->base_addr || !walk->process)
return result;
if (it->index >= walk->size)
return false;
result = true;
it->raw_frame.process = walk->process;
it->raw_frame.base_addr = walk->base_addr[it->index++];
return result;
}
DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkResult const *walk, uint16_t skip)
{
DN_Str8 result{};
if (!walk || !arena)
return result;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
DN_Str8Builder builder = DN_Str8BuilderFromArena(tmem.arena);
DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip);
result = DN_Str8BuilderBuild(&builder, arena);
return result;
}
DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, uint16_t limit, uint16_t skip)
{
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, limit);
DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip);
return result;
}
DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap(uint16_t limit, uint16_t skip)
{
// NOTE: We don't use WalkResultToStr8 because that uses the TLS arenas which
// does not use the OS heap.
DN_Arena arena = DN_ArenaFromHeap(DN_Kilobytes(64), DN_ArenaFlags_NoAllocTrack);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&arena);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&arena, limit);
DN_StackTraceAddWalkToStr8Builder(&walk, &builder, skip);
DN_Str8 result = DN_Str8BuilderBuildFromOSHeap(&builder);
DN_ArenaDeinit(&arena);
return result;
}
DN_API DN_Slice<DN_StackTraceFrame> DN_StackTraceGetFrames(DN_Arena *arena, uint16_t limit)
{
DN_Slice<DN_StackTraceFrame> result = {};
if (!arena)
return result;
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(tmem.arena, limit);
if (!walk.size)
return result;
DN_USize slice_index = 0;
result = DN_Slice_Alloc<DN_StackTraceFrame>(arena, walk.size, DN_ZMem_No);
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);)
result.data[slice_index++] = DN_StackTraceRawFrameToFrame(arena, it.raw_frame);
return result;
}
DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame(DN_Arena *arena, DN_StackTraceRawFrame raw_frame)
{
#if defined(DN_OS_WIN32)
// NOTE: Get line+filename
// TODO: Why does zero-initialising this with `line = {};` cause
// SymGetLineFromAddr64 function to fail once we are at
// __scrt_commain_main_seh and hit BaseThreadInitThunk frame? The
// line and file number are still valid in the result which we use, so,
// we silently ignore this error.
IMAGEHLP_LINEW64 line;
line.SizeOfStruct = sizeof(line);
DWORD line_displacement = 0;
if (!SymGetLineFromAddrW64(raw_frame.process, raw_frame.base_addr, &line_displacement, &line))
line = {};
// NOTE: Get function name
alignas(SYMBOL_INFOW) char buffer[sizeof(SYMBOL_INFOW) + (MAX_SYM_NAME * sizeof(wchar_t))] = {};
SYMBOL_INFOW *symbol = DN_Cast(SYMBOL_INFOW *) buffer;
symbol->SizeOfStruct = sizeof(*symbol);
symbol->MaxNameLen = sizeof(buffer) - sizeof(*symbol);
uint64_t symbol_displacement = 0; // Offset to the beginning of the symbol to the address
SymFromAddrW(raw_frame.process, raw_frame.base_addr, &symbol_displacement, symbol);
// NOTE: Construct result
DN_Str16 file_name16 = DN_Str16{line.FileName, DN_CStr16Size(line.FileName)};
DN_Str16 function_name16 = DN_Str16{symbol->Name, symbol->NameLen};
DN_StackTraceFrame result = {};
result.address = raw_frame.base_addr;
result.line_number = line.LineNumber;
result.file_name = DN_W32_Str16ToStr8(arena, file_name16);
result.function_name = DN_W32_Str16ToStr8(arena, function_name16);
if (result.function_name.size == 0)
result.function_name = DN_Str8Lit("<unknown function>");
if (result.file_name.size == 0)
result.file_name = DN_Str8Lit("<unknown file>");
#else
DN_StackTraceFrame result = {};
#endif
return result;
}
DN_API void DN_StackTracePrint(uint16_t limit)
{
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
DN_Slice<DN_StackTraceFrame> stack_trace = DN_StackTraceGetFrames(tmem.arena, limit);
for (DN_StackTraceFrame &frame : stack_trace)
DN_OS_PrintErrLnF("%.*s(%I64u): %.*s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name));
}
DN_API void DN_StackTraceReloadSymbols()
{
#if defined(DN_OS_WIN32)
HANDLE process = GetCurrentProcess();
SymRefreshModuleList(process);
#endif
}

View File

@ -1,305 +0,0 @@
#define DN_OS_STRING_CPP
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#endif
// NOTE: DN_Str8
DN_API DN_Str8 DN_Str8FromFmtArenaFrame(DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
DN_Str8 result = DN_Str8FromFmtVArena(frame_arena, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FromFmtVArenaFrame(DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
DN_Str8 result = DN_Str8FromFmtVArena(frame_arena, fmt, args);
return result;
}
DN_API DN_Str8 DN_Str8FromArenaFrame(DN_USize size, DN_ZMem z_mem)
{
DN_Arena *frame_arena = DN_OS_TLSGet()->frame_arena;
DN_Str8 result = DN_Str8FromArena(frame_arena, size, z_mem);
return result;
}
DN_API DN_Str8 DN_Str8FromHeapF(DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_USize size = DN_FmtVSize(fmt, args);
DN_Str8 result = DN_Str8FromHeap(size, DN_ZMem_No);
DN_VSNPrintF(result.data, DN_Cast(int)(result.size + 1), fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FromHeap(DN_USize size, DN_ZMem z_mem)
{
DN_Str8 result = {};
result.data = DN_Cast(char *)DN_OS_MemAlloc(size + 1, z_mem);
if (result.data) {
result.size = size;
result.data[result.size] = 0;
}
return result;
}
DN_API DN_Str8 DN_Str8FromTLSFV(DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_Str8 result = DN_Str8FromFmtVArena(DN_OS_TLSTopArena(), fmt, args);
return result;
}
DN_API DN_Str8 DN_Str8FromTLSF(DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8FromFmtVArena(DN_OS_TLSTopArena(), fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FromTLS(DN_USize size, DN_ZMem z_mem)
{
DN_Str8 result = DN_Str8FromArena(DN_OS_TLSTopArena(), size, z_mem);
return result;
}
DN_API DN_Str8 DN_Str8FromStr8Frame(DN_Str8 string)
{
DN_Str8 result = DN_Str8FromStr8Arena(DN_OS_TLSGet()->frame_arena, string);
return result;
}
DN_API DN_Str8 DN_Str8FromStr8TLS(DN_Str8 string)
{
DN_Str8 result = DN_Str8FromStr8Arena(DN_OS_TLSTopArena(), string);
return result;
}
DN_API DN_Str8SplitResult DN_Str8SplitFromFrame(DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode)
{
DN_Str8SplitResult result = DN_Str8SplitArena(DN_OS_TLSGet()->frame_arena, string, delimiter, mode);
return result;
}
DN_API DN_Str8SplitResult DN_Str8SplitFromTLS(DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode)
{
DN_Str8SplitResult result = DN_Str8SplitArena(DN_OS_TLSTopArena(), string, delimiter, mode);
return result;
}
DN_API DN_Str8 DN_Str8SegmentFromFrame(DN_Str8 src, DN_USize segment_size, char segment_char)
{
DN_Str8 result = DN_Str8Segment(DN_OS_TLSGet()->frame_arena, src, segment_size, segment_char);
return result;
}
DN_API DN_Str8 DN_Str8SegmentFromTLS(DN_Str8 src, DN_USize segment_size, char segment_char)
{
DN_Str8 result = DN_Str8Segment(DN_OS_TLSTopArena(), src, segment_size, segment_char);
return result;
}
DN_API DN_Str8 DN_Str8ReverseSegmentFromFrame(DN_Str8 src, DN_USize segment_size, char segment_char)
{
DN_Str8 result = DN_Str8ReverseSegment(DN_OS_TLSGet()->frame_arena, src, segment_size, segment_char);
return result;
}
DN_API DN_Str8 DN_Str8ReverseSegmentFromTLS(DN_Str8 src, DN_USize segment_size, char segment_char)
{
DN_Str8 result = DN_Str8ReverseSegment(DN_OS_TLSTopArena(), src, segment_size, segment_char);
return result;
}
DN_API DN_Str8 DN_Str8AppendFFromFrame(DN_Str8 string, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8AppendFV(DN_OS_TLSGet()->frame_arena, string, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8AppendFFromTLS(DN_Str8 string, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8AppendFV(DN_OS_TLSTopArena(), string, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FillFFromFrame(DN_USize count, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8FillFV(DN_OS_TLSGet()->frame_arena, count, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8 DN_Str8FillFFromTLS(DN_USize count, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_Str8 result = DN_Str8FillFV(DN_OS_TLSTopArena(), count, fmt, args);
va_end(args);
return result;
}
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaFrame(DN_Str8 str8, uint32_t side_size, DN_Str8 truncator)
{
DN_Str8TruncateResult result = DN_Str8TruncateMiddle(DN_OS_TLSGet()->frame_arena, str8, side_size, truncator);
return result;
}
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaTLS(DN_Str8 str8, uint32_t side_size, DN_Str8 truncator)
{
DN_Str8TruncateResult result = DN_Str8TruncateMiddle(DN_OS_TLSTopArena(), str8, side_size, truncator);
return result;
}
DN_API DN_Str8 DN_Str8PadNewLines(DN_Arena *arena, DN_Str8 src, DN_Str8 pad)
{
// TODO: Implement this without requiring TLS so it can go into base strings
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
DN_Str8BSplitResult split = DN_Str8BSplit(src, DN_Str8Lit("\n"));
while (split.lhs.size) {
DN_Str8BuilderAppendRef(&builder, pad);
DN_Str8BuilderAppendRef(&builder, split.lhs);
split = DN_Str8BSplit(split.rhs, DN_Str8Lit("\n"));
if (split.lhs.size)
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
}
DN_Str8 result = DN_Str8BuilderBuild(&builder, arena);
return result;
}
DN_API DN_Str8 DN_Str8PadNewLinesFromFrame(DN_Str8 src, DN_Str8 pad)
{
DN_Str8 result = DN_Str8PadNewLines(DN_OS_TLSGet()->frame_arena, src, pad);
return result;
}
DN_API DN_Str8 DN_Str8PadNewLinesFromTLS(DN_Str8 src, DN_Str8 pad)
{
DN_Str8 result = DN_Str8PadNewLines(DN_OS_TLSTopArena(), src, pad);
return result;
}
DN_API DN_Str8 DN_Str8UpperFromFrame(DN_Str8 string)
{
DN_Str8 result = DN_Str8Upper(DN_OS_TLSGet()->frame_arena, string);
return result;
}
DN_API DN_Str8 DN_Str8UpperFromTLS(DN_Str8 string)
{
DN_Str8 result = DN_Str8Upper(DN_OS_TLSTopArena(), string);
return result;
}
DN_API DN_Str8 DN_Str8LowerFromFrame(DN_Str8 string)
{
DN_Str8 result = DN_Str8Lower(DN_OS_TLSGet()->frame_arena, string);
return result;
}
DN_API DN_Str8 DN_Str8LowerFromTLS(DN_Str8 string)
{
DN_Str8 result = DN_Str8Lower(DN_OS_TLSTopArena(), string);
return result;
}
DN_API DN_Str8 DN_Str8Replace(DN_Str8 string,
DN_Str8 find,
DN_Str8 replace,
DN_USize start_index,
DN_Arena *arena,
DN_Str8EqCase eq_case)
{
// TODO: Implement this without requiring TLS so it can go into base strings
DN_Str8 result = {};
if (string.size == 0 || find.size == 0 || find.size > string.size || find.size == 0 || string.size == 0) {
result = DN_Str8FromStr8Arena(arena, string);
return result;
}
DN_OSTLSTMem tmem = DN_OS_TLSTMem(arena);
DN_Str8Builder string_builder = DN_Str8BuilderFromArena(tmem.arena);
DN_USize max = string.size - find.size;
DN_USize head = start_index;
for (DN_USize tail = head; tail <= max; tail++) {
DN_Str8 check = DN_Str8Slice(string, tail, find.size);
if (!DN_Str8Eq(check, find, eq_case))
continue;
if (start_index > 0 && string_builder.string_size == 0) {
// User provided a hint in the string to start searching from, we
// need to add the string up to the hint. We only do this if there's
// a replacement action, otherwise we have a special case for no
// replacements, where the entire string gets copied.
DN_Str8 slice = DN_Str8FromPtr(string.data, head);
DN_Str8BuilderAppendRef(&string_builder, slice);
}
DN_Str8 range = DN_Str8Slice(string, head, (tail - head));
DN_Str8BuilderAppendRef(&string_builder, range);
DN_Str8BuilderAppendRef(&string_builder, replace);
head = tail + find.size;
tail += find.size - 1; // NOTE: -1 since the for loop will post increment us past the end of the find string
}
if (string_builder.string_size == 0) {
// NOTE: No replacement possible, so we just do a full-copy
result = DN_Str8FromStr8Arena(arena, string);
} else {
DN_Str8 remainder = DN_Str8FromPtr(string.data + head, string.size - head);
DN_Str8BuilderAppendRef(&string_builder, remainder);
result = DN_Str8BuilderBuild(&string_builder, arena);
}
return result;
}
DN_API DN_Str8 DN_Str8ReplaceInsensitive(DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena)
{
DN_Str8 result = DN_Str8Replace(string, find, replace, start_index, arena, DN_Str8EqCase_Insensitive);
return result;
}
// NOTE: DN_Str8Builder ////////////////////////////////////////////////////////////////////////////
DN_API DN_Str8 DN_Str8BuilderBuildFromOSHeap(DN_Str8Builder const *builder)
{
DN_Str8 result = DN_ZeroInit;
if (!builder || builder->string_size <= 0 || builder->count <= 0)
return result;
result.data = DN_Cast(char *) DN_OS_MemAlloc(builder->string_size + 1, DN_ZMem_No);
if (!result.data)
return result;
for (DN_Str8Link *link = builder->head; link; link = link->next) {
DN_Memcpy(result.data + result.size, link->string.data, link->string.size);
result.size += link->string.size;
}
result.data[result.size] = 0;
DN_Assert(result.size == builder->string_size);
return result;
}

View File

@ -1,76 +0,0 @@
#if !defined(DN_OS_STRING_H)
#define DN_OS_STRING_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#endif
// NOTE: DN_Str8
DN_API DN_Str8 DN_Str8FromFmtVArenaFrame (DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_Str8 DN_Str8FromFmtArenaFrame (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromArenaFrame (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8FromTLSFV (DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API DN_Str8 DN_Str8FromTLSF (DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_Str8 DN_Str8FromTLS (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8FromStr8Frame (DN_Str8 string);
DN_API DN_Str8 DN_Str8FromStr8TLS (DN_Str8 string);
DN_API DN_Str8SplitResult DN_Str8SplitFromFrame (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
DN_API DN_Str8SplitResult DN_Str8SplitFromTLS (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode);
DN_API DN_Str8 DN_Str8SegmentFromFrame (DN_Str8 src, DN_USize segment_size, char segment_char);
DN_API DN_Str8 DN_Str8SegmentFromTLS (DN_Str8 src, DN_USize segment_size, char segment_char);
DN_API DN_Str8 DN_Str8ReverseSegmentFromFrame (DN_Str8 src, DN_USize segment_size, char segment_char);
DN_API DN_Str8 DN_Str8ReverseSegmentFromTLS (DN_Str8 src, DN_USize segment_size, char segment_char);
DN_API DN_Str8 DN_Str8AppendFFromFrame (DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8 DN_Str8AppendFFromTLS (DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8 DN_Str8FillFFromFrame (DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8 DN_Str8FillFFromTLS (DN_Str8 string, char const *fmt, ...);
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaFrame (DN_Str8 str8, uint32_t side_size, DN_Str8 truncator);
DN_API DN_Str8TruncateResult DN_Str8TruncateMiddleArenaTLS (DN_Str8 str8, uint32_t side_size, DN_Str8 truncator);
DN_API DN_Str8 DN_Str8PadNewLines (DN_Arena *arena, DN_Str8 src, DN_Str8 pad);
DN_API DN_Str8 DN_Str8PadNewLinesFromFrame (DN_Str8 src, DN_Str8 pad);
DN_API DN_Str8 DN_Str8PadNewLinesFromTLS (DN_Str8 src, DN_Str8 pad);
DN_API DN_Str8 DN_Str8UpperFromFrame (DN_Str8 string);
DN_API DN_Str8 DN_Str8UpperFromTLS (DN_Str8 string);
DN_API DN_Str8 DN_Str8LowerFromFrame (DN_Str8 string);
DN_API DN_Str8 DN_Str8LowerFromTLS (DN_Str8 string);
DN_API DN_Str8 DN_Str8Replace (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
DN_API DN_Str8 DN_Str8ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
// NOTE: DN_Str8Builder ////////////////////////////////////////////////////////////////////////////
DN_API DN_Str8Builder DN_Str8BuilderFromArena () { return DN_Str8BuilderFromArena(DN_OS_TLSGet()->frame_arena); }
DN_API DN_Str8Builder DN_Str8BuilderFromTLS () { return DN_Str8BuilderFromArena(DN_OS_TLSTopArena()); }
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRefFrame (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrRef(DN_OS_TLSGet()->frame_arena, strings, size); }
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRefTLS (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrRef(DN_OS_TLSTopArena(), strings, size); }
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopyFrame (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrCopy(DN_OS_TLSGet()->frame_arena, strings, size); }
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopyTLS (DN_Str8 const *strings, DN_USize size) { return DN_Str8BuilderFromStr8PtrCopy(DN_OS_TLSTopArena(), strings, size); }
DN_API DN_Str8Builder DN_Str8BuilderFromBuilderFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderFromBuilder(DN_OS_TLSGet()->frame_arena, builder); }
DN_API DN_Str8Builder DN_Str8BuilderFromBuilderTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderFromBuilder(DN_OS_TLSTopArena(), builder); }
DN_API DN_Str8 DN_Str8BuilderBuildFromFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderBuild(builder, DN_OS_TLSGet()->frame_arena); }
DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder, DN_Arena *arena);
DN_API DN_Str8 DN_Str8BuilderBuildFromTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderBuild(builder, DN_OS_TLSTopArena()); }
DN_API DN_Str8 DN_Str8BuilderBuildDelimitedFromFrame(DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8BuilderBuildDelimited(builder, delimiter, DN_OS_TLSGet()->frame_arena); }
DN_API DN_Str8 DN_Str8BuilderBuildDelimitedFromTLS (DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8BuilderBuildDelimited(builder, delimiter, DN_OS_TLSTopArena()); }
DN_API DN_Slice<DN_Str8> DN_Str8BuilderBuildSliceFromFrame (DN_Str8Builder const *builder) { return DN_Str8BuilderBuildSlice(builder, DN_OS_TLSGet()->frame_arena); }
DN_API DN_Slice<DN_Str8> DN_Str8BuilderBuildSliceFromTLS (DN_Str8Builder const *builder) { return DN_Str8BuilderBuildSlice(builder, DN_OS_TLSTopArena()); }
#endif // !defined(DN_OS_STRING_H)

View File

@ -1,418 +0,0 @@
#define DN_OS_TLSCPP
#if defined(_CLANGD)
#include "dn_os_tls.h"
#endif
// NOTE: DN_OSTLS ////////////////////////////////////////////////////////////////////////////////////
DN_OSTLSTMem::DN_OSTLSTMem(DN_OSTLS *tls, DN_U8 arena_index, DN_OSTLSPushTMem push_tmem)
{
DN_Assert(arena_index == DN_OSTLSArena_TMem0 || arena_index == DN_OSTLSArena_TMem1);
arena = tls->arenas + arena_index;
temp_mem = DN_ArenaTempMemBegin(arena);
destructed = false;
push_arena = push_tmem;
if (push_arena)
DN_OS_TLSPushArena(arena);
}
DN_OSTLSTMem::~DN_OSTLSTMem()
{
DN_Assert(destructed == false);
DN_ArenaTempMemEnd(temp_mem);
destructed = true;
if (push_arena)
DN_OS_TLSPopArena();
}
DN_API void DN_OS_TLSInit(DN_OSTLS *tls, DN_OSTLSInitArgs args)
{
DN_Check(tls);
if (tls->init)
return;
DN_U64 reserve = args.reserve ? args.reserve : DN_Kilobytes(64);
DN_U64 err_sink_reserve = args.err_sink_reserve ? args.err_sink_reserve : DN_Kilobytes(64);
#if !defined(DN_PLATFORM_EMSCRIPTEN)
DN_U64 commit = args.commit ? args.commit : DN_Kilobytes(4);
DN_U64 err_sink_commit = args.err_sink_commit ? args.err_sink_commit : DN_Kilobytes(4);
#endif
// TODO: We shouldn't have the no alloc track flag here but the initial TLS
// init on OS init happens before CORE init. CORE init is the one responsible
// for setting up the alloc tracking data structures.
for (DN_ForItCArray(it, DN_Arena, tls->arenas)) {
DN_Arena *arena = it.data;
switch (DN_Cast(DN_OSTLSArena) it.index) {
default: {
#if defined(DN_PLATFORM_EMSCRIPTEN)
*arena = DN_ArenaFromHeap(reserve, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
#else
*arena = DN_ArenaFromVMem(reserve, commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
#endif
} break;
case DN_OSTLSArena_ErrorSink: {
#if defined(DN_PLATFORM_EMSCRIPTEN)
*arena = DN_ArenaFromHeap(err_sink_reserve, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
#else
*arena = DN_ArenaFromVMem(err_sink_reserve, err_sink_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack);
#endif
} break;
case DN_OSTLSArena_Count: DN_InvalidCodePath; break;
}
}
tls->thread_id = DN_OS_ThreadID();
tls->err_sink.arena = tls->arenas + DN_OSTLSArena_ErrorSink;
tls->init = true;
}
DN_API void DN_OS_TLSDeinit(DN_OSTLS *tls)
{
tls->init = false;
tls->err_sink = {};
tls->arena_stack_index = {};
for (DN_ForItCArray(it, DN_Arena, tls->arenas))
DN_ArenaDeinit(it.data);
}
DN_THREAD_LOCAL DN_OSTLS *g_dn_curr_thread_tls;
DN_API void DN_OS_TLSSetCurrentThreadTLS(DN_OSTLS *tls)
{
g_dn_curr_thread_tls = tls;
}
DN_API DN_OSTLS *DN_OS_TLSGet()
{
DN_RawAssert(g_dn_curr_thread_tls &&
"DN must be initialised (via DN_Core_Init) before calling any functions depending on "
"TLS if this is the main thread, OR, the created thread has not called "
"SetCurrentThreadTLS yet so the TLS data structure hasn't been assigned yet");
return g_dn_curr_thread_tls;
}
DN_API DN_Arena *DN_OS_TLSArena()
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Arena *result = tls->arenas + DN_OSTLSArena_Main;
return result;
}
// TODO: Is there a way to handle conflict arenas without the user needing to
// manually pass it in?
DN_API DN_OSTLSTMem DN_OS_TLSGetTMem(void const *conflict_arena, DN_OSTLSPushTMem push_tmem)
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_U8 tls_index = (DN_U8)-1;
for (DN_U8 index = DN_OSTLSArena_TMem0; index <= DN_OSTLSArena_TMem1; index++) {
DN_Arena *arena = tls->arenas + index;
if (!conflict_arena || arena != conflict_arena) {
tls_index = index;
break;
}
}
DN_Assert(tls_index != (DN_U8)-1);
return DN_OSTLSTMem(tls, tls_index, push_tmem);
}
DN_API void DN_OS_TLSPushArena(DN_Arena *arena)
{
DN_Assert(arena);
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Assert(tls->arena_stack_index < DN_ArrayCountU(tls->arena_stack));
tls->arena_stack[tls->arena_stack_index++] = arena;
}
DN_API void DN_OS_TLSPopArena()
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Assert(tls->arena_stack_index > 0);
tls->arena_stack_index--;
}
DN_API DN_Arena *DN_OS_TLSTopArena()
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Arena *result = nullptr;
if (tls->arena_stack_index)
result = tls->arena_stack[tls->arena_stack_index - 1];
return result;
}
DN_API void DN_OS_TLSBeginFrame(DN_Arena *frame_arena)
{
DN_OSTLS *tls = DN_OS_TLSGet();
tls->frame_arena = frame_arena;
}
DN_API DN_Arena *DN_OS_TLSFrameArena()
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_Arena *result = tls->frame_arena;
DN_AssertF(result, "Frame arena must be set by calling DN_OS_TLSBeginFrame at the beginning of the frame");
return result;
}
// NOTE: DN_OSErrSink ////////////////////////////////////////////////////////////////////////////////
static void DN_OS_ErrSinkCheck_(DN_OSErrSink const *err)
{
DN_AssertF(err->arena, "Arena should be assigned in TLS init");
if (err->stack_size == 0)
return;
DN_OSErrSinkNode const *node = err->stack + (err->stack_size - 1);
DN_Assert(node->mode >= DN_OSErrSinkMode_Nil && node->mode <= DN_OSErrSinkMode_ExitOnError);
DN_Assert(node->msg_sentinel);
// NOTE: Walk the list ensuring we eventually terminate at the sentinel (e.g. we have a
// well formed doubly-linked-list terminated by a sentinel, or otherwise we will hit the
// walk limit or dereference a null pointer and assert)
size_t WALK_LIMIT = 99'999;
size_t walk = 0;
for (DN_OSErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next, walk++) {
DN_AssertF(it, "Encountered null pointer which should not happen in a sentinel DLL");
DN_Assert(walk < WALK_LIMIT);
}
}
DN_API DN_OSErrSink *DN_OS_ErrSinkBegin_(DN_OSErrSinkMode mode, DN_CallSite call_site)
{
DN_OSTLS *tls = DN_OS_TLSGet();
DN_OSErrSink *err = &tls->err_sink;
DN_OSErrSink *result = err;
DN_USize arena_pos = DN_ArenaPos(result->arena);
if (tls->err_sink.stack_size == DN_ArrayCountU(err->stack)) {
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
DN_USize counter = 0;
for (DN_ForItSize(it, DN_OSErrSinkNode, err->stack, err->stack_size)) {
DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(4) when a string is required in call to 'DN_Str8BuilderAppendF' Actual type: 'struct DN_Str8'.
DN_Str8BuilderAppendF(&builder, " [%04zu] %S:%u %S\n", counter++, it.data->call_site.file, it.data->call_site.line, it.data->call_site.function);
DN_MSVC_WARNING_POP
}
DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(6) when a string is required in call to 'DN_LOG_EmitFromType' Actual type: 'struct DN_Str8'.
DN_AssertF(tls->err_sink.stack_size < DN_ArrayCountU(err->stack),
"Error sink has run out of error scopes, potential leak. Scopes were\n%S", DN_Str8BuilderBuildFromTLS(&builder));
DN_MSVC_WARNING_POP
}
DN_OSErrSinkNode *node = tls->err_sink.stack + tls->err_sink.stack_size++;
node->arena_pos = arena_pos;
node->mode = mode;
node->call_site = call_site;
DN_DLList_InitArena(node->msg_sentinel, DN_OSErrSinkMsg, result->arena);
// NOTE: Handle allocation error
if (!DN_Check(node && node->msg_sentinel)) {
DN_ArenaPopTo(result->arena, arena_pos);
node->msg_sentinel = nullptr;
tls->err_sink.stack_size--;
}
return result;
}
DN_API bool DN_OS_ErrSinkHasError(DN_OSErrSink *err)
{
bool result = false;
if (err && err->stack_size) {
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
result = DN_DLList_HasItems(node->msg_sentinel);
}
return result;
}
DN_API DN_OSErrSinkMsg *DN_OS_ErrSinkEnd(DN_Arena *arena, DN_OSErrSink *err)
{
DN_OSErrSinkMsg *result = nullptr;
DN_OS_ErrSinkCheck_(err);
if (!err || err->stack_size == 0)
return result;
DN_AssertF(arena != err->arena,
"You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost");
// NOTE: Walk the list and allocate it onto the user's arena
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
DN_OSErrSinkMsg *prev = nullptr;
for (DN_OSErrSinkMsg *it = node->msg_sentinel->next; it != node->msg_sentinel; it = it->next) {
DN_OSErrSinkMsg *entry = DN_ArenaNew(arena, DN_OSErrSinkMsg, DN_ZMem_Yes);
entry->msg = DN_Str8FromStr8Arena(arena, it->msg);
entry->call_site = it->call_site;
entry->error_code = it->error_code;
if (!result)
result = entry; // Assign first entry if we haven't yet
if (prev)
prev->next = entry; // Link the prev message to the current one
prev = entry; // Update prev to latest
}
// NOTE: Deallocate all the memory for this scope
err->stack_size--;
DN_ArenaPopTo(err->arena, node->arena_pos);
return result;
}
static void DN_OS_ErrSinkAddMsgToStr8Builder(DN_Str8Builder *builder, DN_OSErrSinkMsg *msg, DN_OSErrSinkMsg *end)
{
if (msg == end) // NOTE: No error messages to add
return;
if (msg->next == end) {
DN_OSErrSinkMsg *it = msg;
DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file);
DN_Str8BuilderAppendF(builder,
"%.*s:%05I32u:%.*s %.*s",
DN_Str8PrintFmt(file_name),
it->call_site.line,
DN_Str8PrintFmt(it->call_site.function),
DN_Str8PrintFmt(it->msg));
} else {
// NOTE: More than one message
for (DN_OSErrSinkMsg *it = msg; it != end; it = it->next) {
DN_Str8 file_name = DN_Str8FileNameFromPath(it->call_site.file);
DN_Str8BuilderAppendF(builder,
"%s - %.*s:%05I32u:%.*s%s%.*s",
it == msg ? "" : "\n",
DN_Str8PrintFmt(file_name),
it->call_site.line,
DN_Str8PrintFmt(it->call_site.function),
it->msg.size ? " " : "",
DN_Str8PrintFmt(it->msg));
}
}
}
DN_API DN_Str8 DN_OS_ErrSinkEndStr8(DN_Arena *arena, DN_OSErrSink *err)
{
DN_Str8 result = {};
DN_OS_ErrSinkCheck_(err);
if (!err || err->stack_size == 0)
return result;
DN_AssertF(arena != err->arena,
"You are not allowed to reuse the arena for ending the error sink because the memory would get popped and lost");
// NOTE: Walk the list and allocate it onto the user's arena
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(arena);
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
DN_OS_ErrSinkAddMsgToStr8Builder(&builder, node->msg_sentinel->next, node->msg_sentinel);
// NOTE: Deallocate all the memory for this scope
err->stack_size--;
DN_U64 arena_pos = node->arena_pos;
DN_ArenaPopTo(err->arena, arena_pos);
result = DN_Str8BuilderBuild(&builder, arena);
return result;
}
DN_API void DN_OS_ErrSinkEndAndIgnore(DN_OSErrSink *err)
{
DN_OS_ErrSinkEnd(nullptr, err);
}
DN_API bool DN_OS_ErrSinkEndAndLogError_(DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 err_msg)
{
DN_AssertF(err->stack_size, "Begin must be called before calling end");
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
DN_AssertF(node->msg_sentinel, "Begin must be called before calling end");
DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr);
DN_OSErrSinkMode mode = node->mode;
DN_OSErrSinkMsg *msg = DN_OS_ErrSinkEnd(tmem.arena, err);
if (!msg)
return false;
DN_Str8Builder builder = DN_Str8BuilderFromTLS();
if (err_msg.size) {
DN_Str8BuilderAppendRef(&builder, err_msg);
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit(":"));
} else {
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("Error(s) encountered:"));
}
if (msg->next) // NOTE: More than 1 message
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
DN_OS_ErrSinkAddMsgToStr8Builder(&builder, msg, nullptr);
DN_Str8 log = DN_Str8BuilderBuildFromTLS(&builder);
DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), call_site, "%.*s", DN_Str8PrintFmt(log));
if (mode == DN_OSErrSinkMode_DebugBreakOnEndAndLog)
DN_DebugBreak;
return true;
}
DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_(DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
DN_Str8 log = DN_Str8FromFmtVArena(tmem.arena, fmt, args);
bool result = DN_OS_ErrSinkEndAndLogError_(err, call_site, log);
return result;
}
DN_API bool DN_OS_ErrSinkEndAndLogErrorF_(DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr);
DN_Str8 log = DN_Str8FromFmtVArena(tmem.arena, fmt, args);
bool result = DN_OS_ErrSinkEndAndLogError_(err, call_site, log);
va_end(args);
return result;
}
DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_(DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args)
{
if (DN_OS_ErrSinkEndAndLogErrorFV_(err, call_site, fmt, args)) {
DN_DebugBreak;
DN_OS_Exit(exit_val);
}
}
DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_(DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
DN_OS_ErrSinkEndAndExitIfErrorFV_(err, call_site, exit_val, fmt, args);
va_end(args);
}
DN_API void DN_OS_ErrSinkAppendFV_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args)
{
if (!err)
return;
DN_Assert(err && err->stack_size);
DN_OSErrSinkNode *node = err->stack + (err->stack_size - 1);
DN_AssertF(node, "Error sink must be begun by calling 'Begin' before using this function.");
DN_OSErrSinkMsg *msg = DN_ArenaNew(err->arena, DN_OSErrSinkMsg, DN_ZMem_Yes);
if (DN_Check(msg)) {
msg->msg = DN_Str8FromFmtVArena(err->arena, fmt, args);
msg->error_code = error_code;
msg->call_site = DN_OS_TLSGet()->call_site;
DN_DLList_Prepend(node->msg_sentinel, msg);
if (node->mode == DN_OSErrSinkMode_ExitOnError)
DN_OS_ErrSinkEndAndExitIfErrorF_(err, msg->call_site, error_code, "Fatal error %u", error_code);
}
}
DN_API void DN_OS_ErrSinkAppendF_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...)
{
if (!err)
return;
va_list args;
va_start(args, fmt);
DN_OS_ErrSinkAppendFV_(err, error_code, fmt, args);
va_end(args);
}

View File

@ -1,142 +0,0 @@
#if !defined(DN_OS_TLS_H)
#define DN_OS_TLS_H
#if defined(_CLANGD)
#include "../dn_base_inc.h"
#include "../dn_os_inc.h"
#endif
// NOTE: DN_OSErrSink
enum DN_OSErrSinkMode
{
DN_OSErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
DN_OSErrSinkMode_DebugBreakOnEndAndLog, // Debug break (int3) when error is encountered and the sink is ended by the 'end and log' functions.
DN_OSErrSinkMode_ExitOnError, // When an error is encountered, exit the program with the error code of the error that was caught.
};
struct DN_OSErrSinkMsg
{
DN_I32 error_code;
DN_Str8 msg;
DN_CallSite call_site;
DN_OSErrSinkMsg *next;
DN_OSErrSinkMsg *prev;
};
struct DN_OSErrSinkNode
{
DN_CallSite call_site; // Call site that the node was created
DN_OSErrSinkMode mode; // Controls how the sink behaves when an error is registered onto the sink.
DN_OSErrSinkMsg *msg_sentinel; // List of error messages accumulated for the current scope
DN_U64 arena_pos; // Position to reset the arena when the scope is ended
};
struct DN_OSErrSink
{
DN_Arena * arena; // Dedicated allocator from the thread's local storage
DN_OSErrSinkNode stack[128]; // Each entry contains errors accumulated between a [begin, end] region of the active sink.
DN_USize stack_size;
};
enum DN_OSTLSArena
{
DN_OSTLSArena_Main, // NOTE: Arena for permanent allocations
DN_OSTLSArena_ErrorSink, // NOTE: Arena for logging error information for this thread
// NOTE: Per-thread scratch arenas (2 to prevent aliasing)
DN_OSTLSArena_TMem0,
DN_OSTLSArena_TMem1,
DN_OSTLSArena_Count,
};
struct DN_OSTLS
{
DN_B32 init; // Flag to track if TLS has been initialised
DN_U64 thread_id;
DN_CallSite call_site; // Stores call-site information when requested by thread
DN_OSErrSink err_sink; // Error handling state
DN_Arena arenas[DN_OSTLSArena_Count]; // Default arenas that the thread has access to implicitly
DN_Arena * arena_stack[8]; // Active stack of arenas push/popped arenas on into the TLS
DN_USize arena_stack_index;
DN_Arena * frame_arena;
char name[64];
DN_U8 name_size;
};
// Push the temporary memory arena when retrieved, popped when the arena goes
// out of scope. Pushed arenas are used automatically as the allocator in TLS
// suffixed function.
enum DN_OSTLSPushTMem
{
DN_OSTLSPushTMem_No,
DN_OSTLSPushTMem_Yes,
};
struct DN_OSTLSTMem
{
DN_OSTLSTMem(DN_OSTLS *context, uint8_t context_index, DN_OSTLSPushTMem push_scratch);
~DN_OSTLSTMem();
DN_Arena *arena;
DN_B32 destructed;
DN_OSTLSPushTMem push_arena;
DN_ArenaTempMem temp_mem;
};
struct DN_OSTLSInitArgs
{
DN_U64 reserve;
DN_U64 commit;
DN_U64 err_sink_reserve;
DN_U64 err_sink_commit;
};
DN_API void DN_OS_TLSInit (DN_OSTLS *tls, DN_OSTLSInitArgs args);
DN_API void DN_OS_TLSDeinit (DN_OSTLS *tls);
DN_API DN_OSTLS * DN_OS_TLSGet ();
DN_API void DN_OS_TLSSetCurrentThreadTLS (DN_OSTLS *tls);
DN_API DN_Arena * DN_OS_TLSArena ();
DN_API DN_OSTLSTMem DN_OS_TLSGetTMem (void const *conflict_arena, DN_OSTLSPushTMem push_tmp_mem);
DN_API void DN_OS_TLSPushArena (DN_Arena *arena);
DN_API void DN_OS_TLSPopArena ();
DN_API DN_Arena * DN_OS_TLSTopArena ();
DN_API void DN_OS_TLSBeginFrame (DN_Arena *frame_arena);
DN_API DN_Arena * DN_OS_TLSFrameArena ();
#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0)
#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No)
#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes)
DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site);
#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE)
#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil)
DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err);
DN_API DN_OSErrSinkMsg * DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err);
DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err);
DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err);
DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg);
DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...);
DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...);
#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg)
#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args)
#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args)
#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__)
#define DN_OS_ErrSinkAppendFV(error, error_code, fmt, args) \
do { \
DN_OS_TLSSaveCallSite; \
DN_OS_ErrSinkAppendFV_(error, error_code, fmt, args); \
} while (0)
#define DN_OS_ErrSinkAppendF(error, error_code, fmt, ...) \
do { \
DN_OS_TLSSaveCallSite; \
DN_OS_ErrSinkAppendF_(error, error_code, fmt, ##__VA_ARGS__); \
} while (0)
#endif // defined(DN_OS_TLS_H)

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,33 @@
#if !defined(DN_OS_WIN32_H) #if !defined(DN_OS_W32_H)
#define DN_OS_WIN32_H #define DN_OS_W32_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #define DN_H_WITH_OS 1
#include "../dn.h"
#include "dn_os_windows.h" #include "dn_os_windows.h"
#endif #endif
struct DN_W32Error struct DN_OSW32Error
{ {
unsigned long code; unsigned long code;
DN_Str8 msg; DN_Str8 msg;
}; };
struct DN_W32FolderIteratorW struct DN_OSW32FolderIteratorW
{ {
void *handle; void *handle;
DN_Str16 file_name; DN_Str16 file_name;
wchar_t file_name_buf[512]; wchar_t file_name_buf[512];
}; };
enum DN_W32SyncPrimitiveType enum DN_OSW32SyncPrimitiveType
{ {
DN_OSW32SyncPrimitiveType_Semaphore, DN_OSW32SyncPrimitiveType_Semaphore,
DN_OSW32SyncPrimitiveType_Mutex, DN_OSW32SyncPrimitiveType_Mutex,
DN_OSW32SyncPrimitiveType_ConditionVariable, DN_OSW32SyncPrimitiveType_ConditionVariable,
}; };
struct DN_W32SyncPrimitive struct DN_OSW32SyncPrimitive
{ {
union union
{ {
@ -35,42 +36,43 @@ struct DN_W32SyncPrimitive
CONDITION_VARIABLE cv; CONDITION_VARIABLE cv;
}; };
DN_W32SyncPrimitive *next; DN_OSW32SyncPrimitive *next;
}; };
typedef HRESULT DN_W32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription); typedef HRESULT DN_OSW32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription);
struct DN_W32Core struct DN_OSW32Core
{ {
DN_W32SetThreadDescriptionFunc *set_thread_description; DN_OSW32SetThreadDescriptionFunc *set_thread_description;
LARGE_INTEGER qpc_frequency; LARGE_INTEGER qpc_frequency;
void *bcrypt_rng_handle; void *bcrypt_rng_handle;
bool bcrypt_init_success; bool bcrypt_init_success;
bool sym_initialised; bool sym_initialised;
CRITICAL_SECTION sync_primitive_free_list_mutex; CRITICAL_SECTION sync_primitive_free_list_mutex;
DN_W32SyncPrimitive *sync_primitive_free_list; DN_OSW32SyncPrimitive *sync_primitive_free_list;
}; };
DN_API void DN_W32_ThreadSetName (DN_Str8 name); DN_API DN_OSW32Core* DN_OS_W32GetCore ();
DN_API void DN_OS_W32ThreadSetName (DN_Str8 name);
DN_API DN_Str16 DN_W32_ErrorCodeToMsg16Alloc(DN_U32 error_code); DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code);
DN_API DN_W32Error DN_W32_ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code); DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code);
DN_API DN_W32Error DN_W32_ErrorCodeToMsgAlloc (DN_U32 error_code); DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsgAlloc (DN_U32 error_code);
DN_API DN_W32Error DN_W32_LastError (DN_Arena *arena); DN_API DN_OSW32Error DN_OS_W32LastError (DN_Arena *arena);
DN_API DN_W32Error DN_W32_LastErrorAlloc (); DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc ();
DN_API void DN_W32_MakeProcessDPIAware (); DN_API void DN_OS_W32MakeProcessDPIAware ();
// NOTE: Windows Str8 <-> Str16 //////////////////////////////////////////////////////////////////// // NOTE: Windows Str8 <-> Str16
DN_API DN_Str16 DN_W32_Str8ToStr16 (DN_Arena *arena, DN_Str8 src); DN_API DN_Str16 DN_OS_W32Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
DN_API int DN_W32_Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size); DN_API int DN_OS_W32Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
DN_API DN_Str8 DN_W32_Str16ToStr8 (DN_Arena *arena, DN_Str16 src); DN_API DN_Str8 DN_OS_W32Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
DN_API int DN_W32_Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size); DN_API int DN_OS_W32Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
DN_API DN_Str8 DN_W32_Str16ToStr8FromHeap(DN_Str16 src); DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap (DN_Str16 src);
// NOTE: Path navigation /////////////////////////////////////////////////////////////////////////// // NOTE: Path navigation
DN_API DN_Str16 DN_W32_EXEPathW (DN_Arena *arena); DN_API DN_Str16 DN_OS_W32EXEPathW (DN_Arena *arena);
DN_API DN_Str16 DN_W32_EXEDirW (DN_Arena *arena); DN_API DN_Str16 DN_OS_W32EXEDirW (DN_Arena *arena);
DN_API DN_Str8 DN_W32_WorkingDir (DN_Arena *arena, DN_Str8 suffix); DN_API DN_Str8 DN_OS_W32WorkingDir (DN_Arena *arena, DN_Str8 suffix);
DN_API DN_Str16 DN_W32_WorkingDirW (DN_Arena *arena, DN_Str16 suffix); DN_API DN_Str16 DN_OS_W32WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
DN_API bool DN_W32_DirWIterate (DN_Str16 path, DN_W32FolderIteratorW *it); DN_API bool DN_OS_W32DirWIterate (DN_Str16 path, DN_OSW32FolderIteratorW *it);
#endif // !defined(DN_OS_WIN32) #endif // !defined(DN_OS_W32_H)

View File

@ -2,7 +2,7 @@
#define DN_OS_WINDOWS_H #define DN_OS_WINDOWS_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../dn_base_inc.h" #include "../dn.h"
#endif #endif
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) #if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)

View File

@ -45,6 +45,83 @@ DN_INIStr8 DN_INI_Str8FromPtr(char const *data, size_t count)
return result; return result;
} }
static void DN_INI_Str8BuilderAppend_(DN_INIStr8Builder *builder, char const *fmt, ...)
{
va_list args;
va_list args_copy;
va_start(args, fmt);
va_copy(args_copy, args);
int size_req = vsnprintf(0, 0, fmt, args);
va_end(args);
builder->size_req += size_req;
if (builder->used + size_req <= builder->max) {
vsnprintf(builder->data + builder->used, builder->max - builder->used, fmt, args_copy);
builder->used += size_req;
}
va_end(args_copy);
}
DN_INIStr8FromResult DN_INI_Str8FromINI(DN_INICore const *ini, char *buffer, size_t size)
{
DN_INIStr8FromResult result = {};
DN_INISection const *section_stack[64] = {};
size_t section_stack_count = 0;
if (ini->first_section.child_first)
section_stack[section_stack_count++] = &ini->first_section;
DN_INIStr8Builder builder = {};
builder.data = buffer;
builder.max = size;
DN_INISection *parent_stack[32] = {};
size_t parent_stack_count = 0;
for (; section_stack_count;) {
DN_INISection const *it = section_stack[--section_stack_count];
if (it != &ini->first_section) {
DN_INI_Str8BuilderAppend_(&builder, "[");
for (DN_INISection *parent = it->parent; parent; parent = parent->parent)
if (parent->name.size)
parent_stack[parent_stack_count++] = parent;
for (size_t index = parent_stack_count - 1; index < parent_stack_count; index--) {
DN_INISection *parent = parent_stack[index];
DN_INI_Str8BuilderAppend_(&builder, "%.*s.", (int)parent->name.size, parent->name.data);
}
parent_stack_count = 0;
DN_INI_Str8BuilderAppend_(&builder, "%.*s]\n", (int)it->name.size, it->name.data);
}
for (DN_INIField *field = it->first_field; field; field = field->next) {
DN_INI_Str8BuilderAppend_(&builder, "%.*s = ", (int)field->key.size, field->key.data);
switch (field->value_type) {
case DN_INIFieldType_String: DN_INI_Str8BuilderAppend_(&builder, "%.*s\n", (int)field->value.size, field->value.data); break;
case DN_INIFieldType_Bool: DN_INI_Str8BuilderAppend_(&builder, "%d\n", field->value_bool); break;
case DN_INIFieldType_USize: DN_INI_Str8BuilderAppend_(&builder, "%zu\n", field->value_usize); break;
}
}
if (it->next)
section_stack[section_stack_count++] = it->next;
if (it->child_first)
section_stack[section_stack_count++] = it->child_first;
if (section_stack_count && it != &ini->first_section)
DN_INI_Str8BuilderAppend_(&builder, "\n");
}
result.size_req = builder.size_req;
if (buffer) {
result.str8.data = builder.data;
result.str8.size = builder.used;
result.success = true;
} else {
result.success = true;
}
return result;
}
static bool DN_INI_Str8Eq(DN_INIStr8 lhs, DN_INIStr8 rhs) static bool DN_INI_Str8Eq(DN_INIStr8 lhs, DN_INIStr8 rhs)
{ {
bool result = lhs.size == rhs.size && DN_INI_Memcmp(lhs.data, rhs.data, lhs.size) == 0; bool result = lhs.size == rhs.size && DN_INI_Memcmp(lhs.data, rhs.data, lhs.size) == 0;
@ -442,8 +519,8 @@ DN_INICore DN_INI_ParseFromPtr(char const *buf, size_t count, char *base, size_t
arena.max = base_count; arena.max = base_count;
DN_INICore result = {}; DN_INICore result = {};
DN_INISection *curr_section = &result.first_section; DN_INISection *curr_section = &result.first_section;
DN_INIField *field = 0; DN_INIField *field = 0;
for (;;) { for (;;) {
DN_INIToken token = DN_INI_NextToken(&tokeniser); DN_INIToken token = DN_INI_NextToken(&tokeniser);
if (token.type == DN_INITokenType_EndOfStream) if (token.type == DN_INITokenType_EndOfStream)
@ -651,6 +728,8 @@ DN_INISection *DN_INI_AppendSectionF(DN_INICore *ini, DN_INIArena *arena, DN_INI
result->name.data = (char *)DN_INI_ArenaAlloc(arena, size_req + 1); result->name.data = (char *)DN_INI_ArenaAlloc(arena, size_req + 1);
result->name.size = size_req; result->name.size = size_req;
vsnprintf(result->name.data, result->name.size + 1, fmt, args_copy); vsnprintf(result->name.data, result->name.size + 1, fmt, args_copy);
if (!section)
section = &ini->first_section;
if (result) { if (result) {
if (section) { if (section) {
@ -770,83 +849,6 @@ DN_INIField *DN_INI_AppendKeyF(DN_INICore *ini, DN_INIArena *arena, DN_INISectio
return result; return result;
} }
static void DN_INI_Str8BuilderAppend(DN_INIStr8Builder *builder, char const *fmt, ...)
{
va_list args;
va_list args_copy;
va_start(args, fmt);
va_copy(args_copy, args);
int size_req = vsnprintf(0, 0, fmt, args);
va_end(args);
builder->size_req += size_req;
if (builder->used + size_req <= builder->max) {
vsnprintf(builder->data + builder->used, builder->max - builder->used, fmt, args_copy);
builder->used += size_req;
}
va_end(args_copy);
}
DN_INIStr8FromResult DN_INI_Str8FromINI(DN_INICore const *ini, char *buffer, size_t size)
{
DN_INIStr8FromResult result = {};
DN_INISection const *section_stack[64] = {};
size_t section_stack_count = 0;
if (ini->first_section.child_first)
section_stack[section_stack_count++] = &ini->first_section;
DN_INIStr8Builder builder = {};
builder.data = buffer;
builder.max = size;
DN_INISection *parent_stack[32] = {};
size_t parent_stack_count = 0;
for (; section_stack_count;) {
DN_INISection const *it = section_stack[--section_stack_count];
if (it != &ini->first_section) {
DN_INI_Str8BuilderAppend(&builder, "[");
for (DN_INISection *parent = it->parent; parent; parent = parent->parent)
if (parent->name.size)
parent_stack[parent_stack_count++] = parent;
for (size_t index = parent_stack_count - 1; index < parent_stack_count; index--) {
DN_INISection *parent = parent_stack[index];
DN_INI_Str8BuilderAppend(&builder, "%.*s.", (int)parent->name.size, parent->name.data);
}
parent_stack_count = 0;
DN_INI_Str8BuilderAppend(&builder, "%.*s]\n", (int)it->name.size, it->name.data);
}
for (DN_INIField *field = it->first_field; field; field = field->next) {
DN_INI_Str8BuilderAppend(&builder, "%.*s = ", (int)field->key.size, field->key.data);
switch (field->value_type) {
case DN_INIFieldType_String: DN_INI_Str8BuilderAppend(&builder, "%.*s\n", (int)field->value.size, field->value.data); break;
case DN_INIFieldType_Bool: DN_INI_Str8BuilderAppend(&builder, "%d\n", field->value_bool); break;
case DN_INIFieldType_USize: DN_INI_Str8BuilderAppend(&builder, "%zu\n", field->value_usize); break;
}
}
if (it->next)
section_stack[section_stack_count++] = it->next;
if (it->child_first)
section_stack[section_stack_count++] = it->child_first;
if (section_stack_count)
DN_INI_Str8BuilderAppend(&builder, "\n");
}
result.size_req = builder.size_req;
if (buffer) {
result.str8.data = builder.data;
result.str8.size = builder.used;
result.success = true;
} else {
result.success = true;
}
return result;
}
#if defined(DN_INI_WITH_UNIT_TESTS) || 1 #if defined(DN_INI_WITH_UNIT_TESTS) || 1
void DN_INI_UnitTests() void DN_INI_UnitTests()
{ {

View File

@ -153,34 +153,37 @@ struct DN_INIFieldBool
// NOTE: Utilities // NOTE: Utilities
int DN_INI_SNPrintF_ (char const *buffer, size_t size, char const *fmt, ...); // Str8FromINI's `size` parameter must include space for the null-terminator, i.e:
void * DN_INI_ArenaAlloc (DN_INIArena *arena, size_t size); // `DN_INIStr8FromResult.size_req + 1` bytes
DN_INIStr8 DN_INI_Str8FromPtr (char const *data, size_t count); int DN_INI_SNPrintF_ (char const *buffer, size_t size, char const *fmt, ...);
void * DN_INI_ArenaAlloc (DN_INIArena *arena, size_t size);
DN_INIStr8 DN_INI_Str8FromPtr (char const *data, size_t count);
DN_INIStr8FromResult DN_INI_Str8FromINI (DN_INICore const *ini, char *buffer, size_t size);
// NOTE: Tokeniser/Parsing // NOTE: Tokeniser/Parsing
DN_INITokeniser DN_INI_TokeniserFromPtr (char const *buf, size_t count); DN_INITokeniser DN_INI_TokeniserFromPtr (char const *buf, size_t count);
DN_INIToken DN_INI_NextToken (DN_INITokeniser const *tokeniser); DN_INIToken DN_INI_NextToken (DN_INITokeniser const *tokeniser);
void DN_INI_EatToken (DN_INITokeniser *tokeniser, DN_INIToken token); void DN_INI_EatToken (DN_INITokeniser *tokeniser, DN_INIToken token);
// NOTE: Lookup // NOTE: Lookup
DN_INISection * DN_INI_ChildSectionFromStr8 (DN_INISection *section, DN_INIStr8 str8); DN_INISection * DN_INI_ChildSectionFromStr8 (DN_INISection *section, DN_INIStr8 str8);
DN_INISection * DN_INI_ChildSectionFromCStr (DN_INISection *section, char const *name, size_t name_size); DN_INISection * DN_INI_ChildSectionFromCStr (DN_INISection *section, char const *name, size_t name_size);
DN_INIField * DN_INI_FieldFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); DN_INIField * DN_INI_FieldFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8);
DN_INIField * DN_INI_FieldFromSection (DN_INISection *section, char const *key, size_t key_size); DN_INIField * DN_INI_FieldFromSection (DN_INISection *section, char const *key, size_t key_size);
DN_INIFieldUSize DN_INI_FieldUSizeFromSectionStr8(DN_INISection *section, DN_INIStr8 str8); DN_INIFieldUSize DN_INI_FieldUSizeFromSectionStr8(DN_INISection *section, DN_INIStr8 str8);
DN_INIFieldStr8 DN_INI_FieldStr8FromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); DN_INIFieldStr8 DN_INI_FieldStr8FromSectionStr8 (DN_INISection *section, DN_INIStr8 str8);
DN_INIFieldBool DN_INI_FieldBoolFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8); DN_INIFieldBool DN_INI_FieldBoolFromSectionStr8 (DN_INISection *section, DN_INIStr8 str8);
DN_INICore DN_INI_ParseFromPtr (char const *buf, size_t count, char *base, size_t base_count); DN_INICore DN_INI_ParseFromPtr (char const *buf, size_t count, char *base, size_t base_count);
// NOTE: Building // NOTE: Building
DN_INISection * DN_INI_AppendSectionF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *fmt, ...); DN_INISection * DN_INI_AppendSectionF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *fmt, ...);
DN_INIField * DN_INI_AppendKeyBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, bool value); DN_INIField * DN_INI_AppendKeyBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, bool value);
DN_INIField * DN_INI_AppendKeyPtrBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, bool value); DN_INIField * DN_INI_AppendKeyPtrBool (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, bool value);
DN_INIField * DN_INI_AppendKeyUSize (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, size_t value); DN_INIField * DN_INI_AppendKeyUSize (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, size_t value);
DN_INIField * DN_INI_AppendKeyPtrUSize (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, size_t value); DN_INIField * DN_INI_AppendKeyPtrUSize (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, char const *key, size_t key_size, size_t value);
DN_INIField * DN_INI_AppendKeyCStr8 (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, char const *value, size_t value_size); DN_INIField * DN_INI_AppendKeyCStr8 (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, char const *value, size_t value_size);
DN_INIField * DN_INI_AppendKeyF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, char const *fmt, ...); DN_INIField * DN_INI_AppendKeyF (DN_INICore *ini, DN_INIArena *arena, DN_INISection *section, DN_INIStr8 key, char const *fmt, ...);
void DN_INI_AppendField (DN_INISection *section, DN_INIField *field); void DN_INI_AppendField (DN_INISection *section, DN_INIField *field);
#if defined(DN_INI_WITH_UNIT_TESTS) #if defined(DN_INI_WITH_UNIT_TESTS)
void DN_INI_UnitTests (); void DN_INI_UnitTests ();

View File

@ -1,16 +1,9 @@
#include "Base/dn_base.cpp" #include "Base/dn_base.cpp"
#include "Base/dn_base_containers.cpp" #include "Base/dn_base_containers.cpp"
#include "Base/dn_base_log.cpp"
#include "Base/dn_base_leak.cpp" #include "Base/dn_base_leak.cpp"
#if DN_H_WITH_OS #if DN_H_WITH_OS
#include "OS/dn_os_tls.cpp"
#include "OS/dn_os.cpp" #include "OS/dn_os.cpp"
#include "OS/dn_os_allocator.cpp"
#include "OS/dn_os_containers.cpp"
#include "OS/dn_os_print.cpp"
#include "OS/dn_os_string.cpp"
#if defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN) #if defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN)
#include "OS/dn_os_posix.cpp" #include "OS/dn_os_posix.cpp"
#elif defined(DN_PLATFORM_WIN32) #elif defined(DN_PLATFORM_WIN32)
@ -18,8 +11,6 @@
#else #else
#error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs #error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
#endif #endif
#include "OS/dn_os_stacktrace.cpp"
#endif #endif
#if DN_H_WITH_CORE #if DN_H_WITH_CORE
@ -30,10 +21,6 @@
#include "Extra/dn_math.cpp" #include "Extra/dn_math.cpp"
#endif #endif
#if DN_H_WITH_HASH
#include "Extra/dn_hash.cpp"
#endif
#if DN_H_WITH_HELPERS #if DN_H_WITH_HELPERS
#include "Extra/dn_helpers.cpp" #include "Extra/dn_helpers.cpp"
#endif #endif

View File

@ -9,7 +9,6 @@
#define DN_H_WITH_OS 1 #define DN_H_WITH_OS 1
#define DN_H_WITH_CORE 1 #define DN_H_WITH_CORE 1
#define DN_H_WITH_MATH 1 #define DN_H_WITH_MATH 1
#define DN_H_WITH_HASH 1
#define DN_H_WITH_HELPERS 1 #define DN_H_WITH_HELPERS 1
#define DN_H_WITH_ASYNC 1 #define DN_H_WITH_ASYNC 1
#define DN_H_WITH_NET 1 #define DN_H_WITH_NET 1
@ -66,11 +65,8 @@
// This means functionality that relies on the OS like printing, memory allocation, stack traces // This means functionality that relies on the OS like printing, memory allocation, stack traces
// and so forth are disabled. // and so forth are disabled.
#include "Base/dn_base_compiler.h"
#include "Base/dn_base.h" #include "Base/dn_base.h"
#include "Base/dn_base_os.h"
#include "Base/dn_base_assert.h" #include "Base/dn_base_assert.h"
#include "Base/dn_base_log.h"
#include "Base/dn_base_containers.h" #include "Base/dn_base_containers.h"
#include "Base/dn_base_leak.h" #include "Base/dn_base_leak.h"
@ -84,12 +80,7 @@
#error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs #error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
#endif #endif
#include "OS/dn_os_tls.h"
#include "OS/dn_os.h" #include "OS/dn_os.h"
#include "OS/dn_os_allocator.h"
#include "OS/dn_os_containers.h"
#include "OS/dn_os_print.h"
#include "OS/dn_os_string.h"
#endif #endif
#if DN_H_WITH_CORE #if DN_H_WITH_CORE
@ -100,10 +91,6 @@
#include "Extra/dn_math.h" #include "Extra/dn_math.h"
#endif #endif
#if DN_H_WITH_HASH
#include "Extra/dn_hash.h"
#endif
#if DN_H_WITH_HELPERS #if DN_H_WITH_HELPERS
#include "Extra/dn_helpers.h" #include "Extra/dn_helpers.h"
#endif #endif

View File

@ -1,12 +1,13 @@
#define DN_INC_CPP #define DN_INC_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#include "dn_inc.h" #include "../Base/dn_base.h"
#include "../OS/dn_os.h"
#endif #endif
DN_Core *g_dn_; DN_Core *g_dn_;
static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args) static void DN_InitOS_(DN_OSCore *os)
{ {
#if defined(DN_OS_H) && defined(DN_OS_CPP) #if defined(DN_OS_H) && defined(DN_OS_CPP)
// NOTE: OS // NOTE: OS
@ -40,19 +41,19 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args)
#endif #endif
#if defined(DN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
os->platform_context = DN_ArenaNew(&os->arena, DN_W32Core, DN_ZMem_Yes); os->platform_context = DN_ArenaNew(&os->arena, DN_OSW32Core, DN_ZMem_Yes);
#elif defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN) #elif defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN)
os->platform_context = DN_ArenaNew(&os->arena, DN_POSIXCore, DN_ZMem_Yes); os->platform_context = DN_ArenaNew(&os->arena, DN_OSPOSIXCore, DN_ZMem_Yes);
#endif #endif
#if defined(DN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
DN_W32Core *w32 = DN_Cast(DN_W32Core *) os->platform_context; DN_OSW32Core *w32 = DN_Cast(DN_OSW32Core *) os->platform_context;
InitializeCriticalSection(&w32->sync_primitive_free_list_mutex); InitializeCriticalSection(&w32->sync_primitive_free_list_mutex);
QueryPerformanceFrequency(&w32->qpc_frequency); QueryPerformanceFrequency(&w32->qpc_frequency);
HMODULE module = LoadLibraryA("kernel32.dll"); HMODULE module = LoadLibraryA("kernel32.dll");
if (module) { if (module) {
w32->set_thread_description = DN_Cast(DN_W32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription"); w32->set_thread_description = DN_Cast(DN_OSW32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription");
FreeLibrary(module); FreeLibrary(module);
} }
@ -62,27 +63,12 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args)
if (w32->bcrypt_rng_handle && init_status == 0) if (w32->bcrypt_rng_handle && init_status == 0)
w32->bcrypt_init_success = true; w32->bcrypt_init_success = true;
else else
DN_LOG_ErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status); DN_LogErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status);
#else #else
DN_Posix_Init(DN_Cast(DN_POSIXCore *)os->platform_context); DN_OS_PosixInit(DN_Cast(DN_OSPosixCore *)os->platform_context);
#endif #endif
} }
// NOTE: Initialise tmem arenas which allocate memory and will be
// recorded to the now initialised allocation table. The initialisation
// of tmem memory may request tmem memory itself in leak tracing mode.
// This is supported as the tmem arenas defer allocation tracking until
// initialisation is done.
DN_OSTLSInitArgs tls_init_args = {};
if (args) {
tls_init_args.commit = args->os_tls_commit;
tls_init_args.reserve = args->os_tls_reserve;
tls_init_args.err_sink_reserve = args->os_tls_err_sink_reserve;
tls_init_args.err_sink_commit = args->os_tls_err_sink_commit;
}
DN_OS_TLSInit(&os->tls, tls_init_args);
DN_OS_TLSSetCurrentThreadTLS(&os->tls);
os->cpu_report = DN_CPUGetReport(); os->cpu_report = DN_CPUGetReport();
#define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_Str8Lit(#label)}; #define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_Str8Lit(#label)};
@ -92,20 +78,19 @@ static void DN_InitOS_(DN_OSCore *os, DN_InitArgs *args)
#endif // defined(DN_OS_H) && defined(DN_OS_CPP) #endif // defined(DN_OS_H) && defined(DN_OS_CPP)
} }
DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags)
DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
{ {
g_dn_ = dn; g_dn_ = dn;
dn->init_flags = flags; dn->init_flags = flags;
if (flags & DN_InitFlags_OS) { if (flags & DN_InitFlags_OS) {
#if defined(DN_OS_H) && defined(DN_OS_CPP) #if defined(DN_OS_H) && defined(DN_OS_CPP)
DN_InitOS_(&dn->os, args); DN_InitOS_(&dn->os);
if (flags & DN_InitFlags_OSLeakTracker) { if (flags & DN_InitFlags_OSLeakTracker) {
// NOTE: Setup the allocation table with allocation tracking turned off on // NOTE: Setup the allocation table with allocation tracking turned off on
// the arena we're using to initialise the table. // the arena we're using to initialise the table.
dn->leak.alloc_table_arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak); dn->leak.alloc_table_arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak);
dn->leak.alloc_table = DN_DSMap_Init<DN_LeakAlloc>(&dn->leak.alloc_table_arena, 4096, DN_DSMapFlags_Nil); dn->leak.alloc_table = DN_DSMapInit<DN_LeakAlloc>(&dn->leak.alloc_table_arena, 4096, DN_DSMapFlags_Nil);
} }
#endif #endif
} }
@ -141,7 +126,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
#endif #endif
#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) #if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX)
DN_POSIXCore *posix = DN_Cast(DN_POSIXCore *)g_dn_->os.platform_context; DN_OSPosixCore *posix = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context;
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Clock GetTime: %S\n", posix->clock_monotonic_raw ? DN_Str8Lit("CLOCK_MONOTONIC_RAW") : DN_Str8Lit("CLOCK_MONOTONIC")); DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Clock GetTime: %S\n", posix->clock_monotonic_raw ? DN_Str8Lit("CLOCK_MONOTONIC_RAW") : DN_Str8Lit("CLOCK_MONOTONIC"));
#endif #endif
// TODO(doyle): Add stacktrace feature log // TODO(doyle): Add stacktrace feature log
@ -177,7 +162,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
} }
if (buf_size) if (buf_size)
DN_LOG_DebugF("%.*s", DN_Cast(int)buf_size, buf); DN_LogDebugF("%.*s", DN_Cast(int)buf_size, buf);
} }
DN_API void DN_BeginFrame() DN_API void DN_BeginFrame()

View File

@ -2,8 +2,8 @@
#define DN_INC_H #define DN_INC_H
#if defined(_CLANGD) #if defined(_CLANGD)
#include "dn_base_inc.h" #define DN_H_WITH_OS 1
#include "dn_os_inc.h" #include "dn.h"
#endif #endif
struct DN_InitArgs struct DN_InitArgs
@ -38,6 +38,7 @@ struct DN_Core
extern DN_Core *g_dn_; extern DN_Core *g_dn_;
DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args); DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args);
DN_API void DN_ThreadContextInit();
DN_API void DN_BeginFrame(); DN_API void DN_BeginFrame();
#endif // !defined(DN_INC_H) #endif // !defined(DN_INC_H)