Get latest changes from upstream

This commit is contained in:
2026-06-01 21:40:33 +10:00
parent e8075e7a97
commit cbf7416220
22 changed files with 3822 additions and 2124 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+731 -248
View File
File diff suppressed because it is too large Load Diff
+875 -60
View File
File diff suppressed because it is too large Load Diff
-77
View File
@@ -1,77 +0,0 @@
#if !defined(DN_BASE_ASSERT_H)
#define DN_BASE_ASSERT_H
#define DN_HardAssertF(expr, fmt, ...) \
do { \
if (!(expr)) { \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LogErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \
DN_DebugBreak; \
} \
} while (0)
#define DN_HardAssert(expr) DN_HardAssertF(expr, "")
// NOTE: Our default assert requires stack traces which has a bit of a chicken-and-egg problem if
// we're trying to detect some code related to the DN startup sequence. If we try to assert before
// the OS layer is initialised stack-traces will try to use temporary memory which requires TLS to
// be setup which belongs to the OS.
//
// This causes recursion errors as they call into each other. We use RawAsserts for these kind of
// checks.
#if defined(DN_NO_ASSERT)
#define DN_RawAssert(...)
#define DN_Assert(...)
#define DN_AssertOnce(...)
#define DN_AssertF(...)
#define DN_AssertFOnce(...)
#else
#define DN_RawAssert(expr) do { if (!(expr)) DN_DebugBreak; } while (0)
#define DN_AssertF(expr, fmt, ...) \
do { \
if (!(expr)) { \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \
DN_DebugBreak; \
} \
} while (0)
#define DN_AssertFOnce(expr, fmt, ...) \
do { \
static bool once = true; \
if (!(expr) && once) { \
once = false; \
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
DN_Str8PrintFmt(stack_trace_), \
##__VA_ARGS__); \
DN_DebugBreak; \
} \
} while (0)
#define DN_Assert(expr) DN_AssertF((expr), "")
#define DN_AssertOnce(expr) DN_AssertFOnce((expr), "")
#endif
#define DN_InvalidCodePathF(fmt, ...) DN_HardAssertF(0, fmt, ##__VA_ARGS__)
#define DN_InvalidCodePath DN_InvalidCodePathF("Invalid code path triggered")
#define DN_StaticAssert(expr) \
DN_GCC_WARNING_PUSH \
DN_GCC_WARNING_DISABLE(-Wunused-local-typedefs) \
typedef char DN_TokenCombine(static_assert_dummy__, __LINE__)[(expr) ? 1 : -1]; \
DN_GCC_WARNING_POP
#define DN_Check(expr) DN_CheckF(expr, "")
#if defined(DN_NO_CHECK_BREAK)
#define DN_CheckF(expr, fmt, ...) \
((expr) ? true : (DN_LogWarningF(fmt, ##__VA_ARGS__), false))
#else
#define DN_CheckF(expr, fmt, ...) \
((expr) ? true : (DN_LogErrorF(fmt, ##__VA_ARGS__), DN_StackTracePrint(128 /*limit*/), DN_DebugBreak, false))
#endif
#endif
+75 -34
View File
@@ -2,6 +2,13 @@
#include "../dn.h"
#endif
struct DN_ArrayFindEqMemcmpContext_
{
DN_USize elem_size;
void const *find;
};
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)
{
void *result = *data;
@@ -11,7 +18,42 @@ DN_API void *DN_SliceAllocArena(void **data, DN_USize *slice_size_field, DN_USiz
return result;
}
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)
DN_API DN_ArrayFindResult DN_ArrayFind(void *data, DN_USize size, DN_USize elem_size, void const *find, DN_ArrayFindEqFunc *eq_func)
{
DN_ArrayFindResult result = {};
DN_Assert(data);
DN_Assert(elem_size);
if (find) {
for (DN_ForIndexU(index, size)) {
DN_U8 *it = DN_Cast(DN_U8 *) data + (index * elem_size);
if (eq_func(it, find)) {
result.index = index;
result.value = it;
result.success = true;
break;
}
}
}
return result;
}
static bool DN_ArrayFindEqMemEqUnsafe_(void const *lhs, void const *find)
{
DN_ArrayFindEqMemcmpContext_ *context = DN_Cast(DN_ArrayFindEqMemcmpContext_ *) find;
bool result = DN_MemEqUnsafe(lhs, context->find, context->elem_size);
return result;
}
DN_API DN_ArrayFindResult DN_ArrayFindMemEq(void *data, DN_USize size, DN_USize elem_size, void const *find)
{
DN_ArrayFindEqMemcmpContext_ context = {};
context.elem_size = elem_size;
context.find = find;
DN_ArrayFindResult result = DN_ArrayFind(data, size, elem_size, &context, DN_ArrayFindEqMemEqUnsafe_);
return result;
}
DN_API void *DN_ArrayInsertArray(void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count)
{
void *result = nullptr;
if (!data || !size || !items || count <= 0 || ((*size + count) > max))
@@ -32,7 +74,7 @@ DN_API void *DN_CArrayInsertArray(void *data, DN_USize *size, DN_USize max, DN_U
return result;
}
DN_API void *DN_CArrayPopFront(void *data, DN_USize *size, DN_USize elem_size, DN_USize count)
DN_API void *DN_ArrayPopFront(void *data, DN_USize *size, DN_USize elem_size, DN_USize count)
{
if (!data || !size || *size == 0 || count == 0)
return nullptr;
@@ -51,7 +93,7 @@ DN_API void *DN_CArrayPopFront(void *data, DN_USize *size, DN_USize elem_size, D
return result;
}
DN_API void *DN_CArrayPopBack(void *data, DN_USize *size, DN_USize elem_size, DN_USize count)
DN_API void *DN_ArrayPopBack(void *data, DN_USize *size, DN_USize elem_size, DN_USize count)
{
if (!data || !size || *size == 0 || count == 0)
return nullptr;
@@ -62,7 +104,7 @@ DN_API void *DN_CArrayPopBack(void *data, DN_USize *size, DN_USize elem_size, DN
return DN_Cast(char *)data + (*size * elem_size);
}
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)
DN_API DN_ArrayEraseResult DN_ArrayEraseRange(void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase)
{
DN_ArrayEraseResult result = {};
if (!data || !size || *size == 0 || count == 0)
@@ -104,48 +146,47 @@ DN_API DN_ArrayEraseResult DN_CArrayEraseRange(void *data, DN_USize *size, DN_US
}
result.items_erased = erase_count;
result.it_index = start;
result.it_index = start ? start - 1 : start;
return result;
}
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)
DN_API void *DN_ArrayMakeArray(void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize make_count, DN_ZMem z_mem)
{
void *result = nullptr;
DN_USize new_size = *size + make_size;
void *result = nullptr;
DN_USize new_size = *size + make_count;
if (new_size <= max) {
result = DN_Cast(char *) data + (data_size * size[0]);
result = DN_Cast(char *) data + (elem_size * size[0]);
*size = new_size;
if (z_mem == DN_ZMem_Yes)
DN_Memset(result, 0, data_size * make_size);
DN_Memset(result, 0, elem_size * make_count);
}
return result;
}
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)
DN_API void *DN_ArrayAddArray(void *data, DN_USize *size, DN_USize max, DN_USize elem_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add)
{
void *result = DN_CArrayMakeArray(data, size, max, data_size, elems_count, DN_ZMem_No);
void *result = DN_ArrayMakeArray(data, size, max, elem_size, elems_count, DN_ZMem_No);
if (result) {
if (add == DN_ArrayAdd_Append) {
DN_Memcpy(result, elems, elems_count * data_size);
DN_Memcpy(result, elems, elems_count * elem_size);
} else {
char *move_dest = DN_Cast(char *)data + (elems_count * data_size); // Shift elements forward
char *move_dest = DN_Cast(char *)data + (elems_count * elem_size); // Shift elements forward
char *move_src = DN_Cast(char *)data;
DN_Memmove(move_dest, move_src, data_size * size[0]);
DN_Memcpy(data, elems, data_size * elems_count);
DN_Memmove(move_dest, move_src, elem_size * size[0]);
DN_Memcpy(data, elems, elem_size * elems_count);
}
}
return result;
}
DN_API bool DN_CArrayResizeFromArena(void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max)
DN_API bool DN_ArrayResizeFromArena(void **data, DN_USize *size, DN_USize *max, DN_USize elem_size, DN_Pool *pool, DN_USize new_max)
{
bool result = true;
if (new_max != *max) {
DN_USize bytes_to_alloc = data_size * new_max;
DN_USize bytes_to_alloc = elem_size * new_max;
void *buffer = DN_PoolNewArray(pool, DN_U8, bytes_to_alloc);
if (buffer) {
DN_USize bytes_to_copy = data_size * DN_Min(*size, new_max);
DN_USize bytes_to_copy = elem_size * DN_Min(*size, new_max);
DN_Memcpy(buffer, *data, bytes_to_copy);
DN_PoolDealloc(pool, *data);
*data = buffer;
@@ -159,14 +200,14 @@ DN_API bool DN_CArrayResizeFromArena(void **data, DN_USize *size, DN_USize *max,
return result;
}
DN_API bool DN_CArrayResizeFromPool(void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max)
DN_API bool DN_ArrayResizeFromPool(void **data, DN_USize *size, DN_USize *max, DN_USize elem_size, DN_Pool *pool, DN_USize new_max)
{
bool result = true;
if (new_max != *max) {
DN_USize bytes_to_alloc = data_size * new_max;
DN_USize bytes_to_alloc = elem_size * new_max;
void *buffer = DN_PoolNewArray(pool, DN_U8, bytes_to_alloc);
if (buffer) {
DN_USize bytes_to_copy = data_size * DN_Min(*size, new_max);
DN_USize bytes_to_copy = elem_size * DN_Min(*size, new_max);
DN_Memcpy(buffer, *data, bytes_to_copy);
DN_PoolDealloc(pool, *data);
*data = buffer;
@@ -180,14 +221,14 @@ DN_API bool DN_CArrayResizeFromPool(void **data, DN_USize *size, DN_USize *max,
return result;
}
DN_API bool DN_CArrayResizeFromArena(void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Arena *arena, DN_USize new_max)
DN_API bool DN_ArrayResizeFromArena(void **data, DN_USize *size, DN_USize *max, DN_USize elem_size, DN_Arena *arena, DN_USize new_max)
{
bool result = true;
if (new_max != *max) {
DN_USize bytes_to_alloc = data_size * new_max;
DN_USize bytes_to_alloc = elem_size * new_max;
void *buffer = DN_ArenaNewArray(arena, DN_U8, bytes_to_alloc, DN_ZMem_No);
if (buffer) {
DN_USize bytes_to_copy = data_size * DN_Min(*size, new_max);
DN_USize bytes_to_copy = elem_size * DN_Min(*size, new_max);
DN_Memcpy(buffer, *data, bytes_to_copy);
*data = buffer;
*max = new_max;
@@ -200,41 +241,41 @@ DN_API bool DN_CArrayResizeFromArena(void **data, DN_USize *size, DN_USize *max,
return result;
}
DN_API bool DN_CArrayGrowFromPool(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max)
DN_API bool DN_ArrayGrowFromPool(void **data, DN_USize size, DN_USize *max, DN_USize elem_size, DN_Pool *pool, DN_USize new_max)
{
bool result = true;
if (new_max > *max)
result = DN_CArrayResizeFromPool(data, &size, max, data_size, pool, new_max);
result = DN_ArrayResizeFromPool(data, &size, max, elem_size, pool, new_max);
return result;
}
DN_API bool DN_CArrayGrowFromArena(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Arena *arena, DN_USize new_max)
DN_API bool DN_ArrayGrowFromArena(void **data, DN_USize size, DN_USize *max, DN_USize elem_size, DN_Arena *arena, DN_USize new_max)
{
bool result = true;
if (new_max > *max)
result = DN_CArrayResizeFromArena(data, &size, max, data_size, arena, new_max);
result = DN_ArrayResizeFromArena(data, &size, max, elem_size, arena, new_max);
return result;
}
DN_API bool DN_CArrayGrowIfNeededFromPool(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize add_count)
DN_API bool DN_ArrayGrowIfNeededFromPool(void **data, DN_USize size, DN_USize *max, DN_USize elem_size, DN_Pool *pool, DN_USize add_count)
{
bool result = true;
DN_USize new_size = size + add_count;
if (new_size > *max) {
DN_USize new_max = DN_Max(DN_Max(*max * 2, new_size), 8);
result = DN_CArrayResizeFromPool(data, &size, max, data_size, pool, new_max);
result = DN_ArrayResizeFromPool(data, &size, max, elem_size, pool, new_max);
}
return result;
}
DN_API bool DN_CArrayGrowIfNeededFromArena(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Arena *arena, DN_USize add_count)
DN_API bool DN_ArrayGrowIfNeededFromArena(void **data, DN_USize size, DN_USize *max, DN_USize elem_size, DN_Arena *arena, DN_USize add_count)
{
bool result = true;
DN_USize new_size = size + add_count;
if (new_size > *max) {
DN_USize new_max = DN_Max(DN_Max(*max * 2, new_size), 8);
result = DN_CArrayResizeFromArena(data, &size, max, data_size, arena, new_max);
result = DN_ArrayResizeFromArena(data, &size, max, elem_size, arena, new_max);
}
return result;
}
-463
View File
@@ -1,463 +0,0 @@
#if !defined(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.
//
// Arrays
//
// Data structures that have a `T *data`, `DN_USize count` and `DN_USize max` capacity that can be
// dynamically shrunk or expanded.
//
// API
// ResizeFrom: Resizes the array to `new_max` erase elements if resizing to a smaller size
// GrowFrom: Expands the capacity of the array if `new_max > array.max` otherwise no-op
// GrowIfNeeded: Expands the capacity of the array if `array.size + add_count > array.max` otherwise no-op
//
// Variants
// 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 = {};
// DN_Arena arena = {};
// DN_IArrayResizeFromArena(&my_array, &arena, 256);
// MyStruct *item = DN_IArrayMake(&my_array, DN_ZMem_No);
//
// Slices
//
// Fixed size container allocated up front that have a `T *data` and `DN_USize count` elements.
//
// API
// AllocArena: Allocates the container with the requested `count` elements
//
// 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) { /* ... */ }
//
// SinglyHeadTailLL => Singly Linked List with Head and Tail pointer (or First and Last pointer)
/*
struct MyLinkItem {
int data;
MyLinkItem *next;
} my_list = {};
struct MyContainer {
MyLinkItem *head;
MyLinkItem *tail;
};
MyLinkItem item = {};
MyContainer container = {};
DN_ISinglyHeadTailLLAppend(container, item);
// ... or alternatively, DN_SinglyHeadTailLLAppend(container.head, container.tail, item);
for (MyLinkItem *it = container.head; it; it = it->next) { }
*/
#if defined(_CLANGD)
#include "../dn.h"
#endif
struct DN_Ring
{
DN_U64 size;
char *base;
DN_U64 write_pos;
DN_U64 read_pos;
};
enum DN_ArrayErase
{
DN_ArrayErase_Unstable,
DN_ArrayErase_Stable,
};
enum DN_ArrayAdd
{
DN_ArrayAdd_Append,
DN_ArrayAdd_Prepend,
};
struct DN_ArrayEraseResult
{
// The next index your for-index should be set to such that you can continue
// to iterate the remainder of the array, e.g:
//
// for (DN_USize index = 0; index < array.size; index++) {
// if (erase)
// index = DN_FArray_EraseRange(&array, index, -3, DN_ArrayErase_Unstable);
// }
DN_USize it_index;
DN_USize items_erased; // The number of items erased
};
template <typename T> struct DN_ArrayFindResult
{
T *data; // Pointer to the value if a match is found, null pointer otherwise
DN_USize index; // Index to the value if a match is found, 0 otherwise
};
enum DN_DSMapKeyType
{
// Key | Key Hash | Map Index
DN_DSMapKeyType_Invalid,
DN_DSMapKeyType_U64, // U64 | Hash(U64) | Hash(U64) % map_size
DN_DSMapKeyType_U64NoHash, // U64 | U64 | U64 % map_size
DN_DSMapKeyType_Buffer, // Buffer | Hash(buffer) | Hash(buffer) % map_size
DN_DSMapKeyType_BufferAsU64NoHash, // Buffer | U64(buffer[0:4]) | U64(buffer[0:4]) % map_size
};
struct DN_DSMapKey
{
DN_DSMapKeyType type;
DN_U32 hash; // Hash to lookup in the map. If it equals, we check that the original key payload matches
void const *buffer_data;
DN_U32 buffer_size;
DN_U64 u64;
bool no_copy_buffer;
};
template <typename T>
struct DN_DSMapSlot
{
DN_DSMapKey key; // Hash table lookup key
T value; // Hash table value
};
typedef DN_U32 DN_DSMapFlags;
enum DN_DSMapFlags_
{
DN_DSMapFlags_Nil = 0,
DN_DSMapFlags_DontFreeArenaOnResize = 1 << 0,
};
using DN_DSMapHashFunction = DN_U32(DN_DSMapKey key, DN_U32 seed);
template <typename T> struct DN_DSMap
{
DN_U32 *hash_to_slot; // Mapping from hash to a index in the slots array
DN_DSMapSlot<T> *slots; // Values of the array stored contiguously, non-sorted order
DN_U32 size; // Total capacity of the map and is a power of two
DN_U32 occupied; // Number of slots used in the hash table
DN_Arena *arena; // Backing arena for the hash table
DN_Pool pool; // Allocator for keys that are variable-sized buffers
DN_U32 initial_size; // Initial map size, map cannot shrink on erase below this size
DN_DSMapHashFunction *hash_function; // Custom hashing function to use if field is set
DN_U32 hash_seed; // Seed for the hashing function, when 0, DN_DS_MAP_DEFAULT_HASH_SEED is used
DN_DSMapFlags flags;
};
template <typename T> struct DN_DSMapResult
{
bool found;
DN_DSMapSlot<T> *slot;
T *value;
};
#define DN_ISinglyLLDetach(list) (decltype(list))DN_SinglyLLDetach((void **)&(list), (void **)&(list)->next)
#define DN_SinglyHeadTailLLAppend(head, tail, to_append) \
do { \
if (!head) \
head = to_append; \
if (tail) \
tail->next = to_append; \
tail = to_append; \
} while (0)
#define DN_ISinglyHeadTailLLAppend(container_ptr, to_append) DN_SinglyHeadTailLLAppend((container_ptr)->head, (container_ptr)->tail, to_append)
#define DN_SentinelDoublyLLInit(list) (list)->next = (list)->prev = (list)
#define DN_SentinelDoublyLLIsSentinel(list, item) ((list) == (item))
#define DN_SentinelDoublyLLIsEmpty(list) (!(list) || ((list) == (list)->next))
#define DN_SentinelDoublyLLIsInit(list) ((list)->next && (list)->prev)
#define DN_SentinelDoublyLLHasItems(list) ((list) && ((list) != (list)->next))
#define DN_SentinelDoublyLLForEach(it, list) auto *it = (list)->next; (it) != (list); (it) = (it)->next
#define DN_SentinelDoublyLLInitArena(list, T, ptr_arena) \
do { \
(list) = DN_ArenaNew(ptr_arena, T, DN_ZMem_Yes); \
DN_SentinelDoublyLLInit(list); \
} while (0)
#define DN_SentinelDoublyLLInitPool(list, T, pool) \
do { \
(list) = DN_PoolNew(pool, T); \
DN_SentinelDoublyLLInit(list); \
} while (0)
#define DN_SentinelDoublyLLDetach(item) \
do { \
if (item) { \
(item)->prev->next = (item)->next; \
(item)->next->prev = (item)->prev; \
(item)->next = nullptr; \
(item)->prev = nullptr; \
} \
} while (0)
#define DN_SentinelDoublyLLDequeue(list, dest_ptr) \
if (DN_SentinelDoublyLLHasItems(list)) { \
dest_ptr = (list)->next; \
DN_SentinelDoublyLLDetach(dest_ptr); \
}
#define DN_SentinelDoublyLLAppend(list, item) \
do { \
if (item) { \
if ((item)->next) \
DN_SentinelDoublyLLDetach(item); \
(item)->next = (list)->next; \
(item)->prev = (list); \
(item)->next->prev = (item); \
(item)->prev->next = (item); \
} \
} while (0)
#define DN_SentinelDoublyLLPrepend(list, item) \
do { \
if (item) { \
if ((item)->next) \
DN_SentinelDoublyLLDetach(item); \
(item)->next = (list); \
(item)->prev = (list)->prev; \
(item)->next->prev = (item); \
(item)->prev->next = (item); \
} \
} while (0)
// DoublyLL => Non-intrusive Doubly Linked List
// 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.
//
// struct MyLinkItem {
// int data;
// MyLinkItem *next;
// MyLinkItem *prev;
// } *head = nullptr;
// DN_DoublyLLAppend(&head, new_item);
// for (MyLinkItem *it = head; it; it = it->next) { /* ... */ }
#define DN_DoublyLLDetach(head, ptr) \
do { \
if ((head) && (head) == (ptr)) \
(head) = (head)->next; \
if ((ptr)) { \
if ((ptr)->next) \
(ptr)->next->prev = (ptr)->prev; \
if ((ptr)->prev) \
(ptr)->prev->next = (ptr)->next; \
(ptr)->prev = (ptr)->next = 0; \
} \
} while (0)
#define DN_DoublyLLAppend(head, ptr) \
do { \
if ((ptr)) { \
DN_AssertF((ptr)->prev == 0 && (ptr)->next == 0, "Detach the pointer first"); \
(ptr)->prev = (head); \
(ptr)->next = 0; \
if ((head)) { \
(ptr)->next = (head)->next; \
(head)->next = (ptr); \
} else { \
(head) = (ptr); \
} \
} \
} while (0)
#define DN_DoublyLLPrepend(head, ptr) \
do { \
if ((ptr)) { \
DN_AssertF((ptr)->prev == 0 && (ptr)->next == 0, "Detach the pointer first"); \
(ptr)->prev = nullptr; \
(ptr)->next = (head); \
if ((head)) { \
(ptr)->prev = (head)->prev; \
(head)->prev = (ptr); \
} else { \
(head) = (ptr); \
} \
} \
} while (0)
// 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_PArrayResizeFromPool(ptr, ptr_size, ptr_max, pool, new_max) DN_CArrayResizeFromPool((void **)&(ptr), ptr_size, ptr_max, sizeof((ptr)[0]), pool, new_max)
#define DN_PArrayResizeFromArena(ptr, ptr_size, ptr_max, arena, new_max) DN_CArrayResizeFromArena((void **)&(ptr), ptr_size, ptr_max, sizeof((ptr)[0]), arena, new_max)
#define DN_PArrayGrowFromPool(ptr, size, ptr_max, pool, new_max) DN_CArrayGrowFromPool((void **)&(ptr), size, ptr_max, sizeof((ptr)[0]), pool, new_max)
#define DN_PArrayGrowFromArena(ptr, size, ptr_max, arena, new_max) DN_CArrayGrowFromArena((void **)&(ptr), size, ptr_max, sizeof((ptr)[0]), arena, new_max)
#define DN_PArrayGrowIfNeededFromPool(ptr, size, ptr_max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, ptr_max, sizeof((*ptr)[0]), pool, add_count)
#define DN_PArrayGrowIfNeededFromArena(ptr, size, ptr_max, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(ptr), size, ptr_max, sizeof((*ptr)[0]), arena, add_count)
#define DN_PArrayMakeArray(ptr, ptr_size, max, count, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), count, z_mem)
#define DN_PArrayMakeArrayZ(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), count, DN_ZMem_Yes)
#define DN_PArrayMake(ptr, ptr_size, max, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), 1, z_mem)
#define DN_PArrayMakeZ(ptr, ptr_size, max) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), 1, DN_ZMem_Yes)
#define DN_PArrayAddArray(ptr, ptr_size, max, items, count, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, add)
#define DN_PArrayAdd(ptr, ptr_size, max, item, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, add)
#define DN_PArrayAppendArray(ptr, ptr_size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, DN_ArrayAdd_Append)
#define DN_PArrayAppend(ptr, ptr_size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Append)
#define DN_PArrayPrependArray(ptr, ptr_size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, DN_ArrayAdd_Prepend)
#define DN_PArrayPrepend(ptr, ptr_size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Prepend)
#define DN_PArrayEraseRange(ptr, ptr_size, begin_index, count, erase) DN_CArrayEraseRange(ptr, ptr_size, sizeof((ptr)[0]), begin_index, count, erase)
#define DN_PArrayErase(ptr, ptr_size, index, erase) DN_CArrayEraseRange(ptr, ptr_size, sizeof((ptr)[0]), index, 1, erase)
#define DN_PArrayInsertArray(ptr, ptr_size, max, index, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, ptr_size, max, sizeof((ptr)[0]), index, items, count)
#define DN_PArrayInsert(ptr, ptr_size, max, index, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, ptr_size, max, sizeof((ptr)[0]), index, &item, 1)
#define DN_PArrayPopFront(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopFront(ptr, ptr_size, sizeof((ptr)[0]), count)
#define DN_PArrayPopBack(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopBack(ptr, ptr_size, sizeof((ptr)[0]), count)
#define DN_LArrayResizeFromPool(c_array, size, pool, new_max) DN_PArrayResizeFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max)
#define DN_LArrayResizeFromArena(c_array, size, arena, new_max) DN_PArrayResizeFromArena(c_array, size, DN_ArrayCountU(c_array), arena, 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_LArrayGrowFromArena(c_array, size, arena, new_max) DN_PArrayGrowFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max)
#define DN_LArrayGrowIfNeededFromPool(c_array, size, pool, add_count) DN_PArrayGrowIfNeededFromPool(c_array, size, DN_ArrayCountU(c_array), pool, add_count)
#define DN_LArrayGrowIfNeededFromArena(c_array, size, arena, add_count) DN_PArrayGrowIfNeededFromArena(c_array, size, DN_ArrayCountU(c_array), arena, add_count)
#define DN_LArrayMakeArray(c_array, ptr_size, count, z_mem) DN_PArrayMakeArray(c_array, ptr_size, DN_ArrayCountU(c_array), count, z_mem)
#define DN_LArrayMakeArrayZ(c_array, ptr_size, count) DN_PArrayMakeArrayZ(c_array, ptr_size, DN_ArrayCountU(c_array), count)
#define DN_LArrayMake(c_array, ptr_size, z_mem) DN_PArrayMake(c_array, ptr_size, DN_ArrayCountU(c_array), z_mem)
#define DN_LArrayMakeZ(c_array, ptr_size) DN_PArrayMakeZ(c_array, ptr_size, DN_ArrayCountU(c_array))
#define DN_LArrayAddArray(c_array, ptr_size, items, count, add) DN_PArrayAddArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count, add)
#define DN_LArrayAdd(c_array, ptr_size, item, add) DN_PArrayAdd(c_array, ptr_size, DN_ArrayCountU(c_array), item, add)
#define DN_LArrayAppendArray(c_array, ptr_size, items, count) DN_PArrayAppendArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count)
#define DN_LArrayAppend(c_array, ptr_size, item) DN_PArrayAppend(c_array, ptr_size, DN_ArrayCountU(c_array), item)
#define DN_LArrayPrependArray(c_array, ptr_size, items, count) DN_PArrayPrependArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count)
#define DN_LArrayPrepend(c_array, ptr_size, item) DN_PArrayPrepend(c_array, ptr_size, DN_ArrayCountU(c_array), item)
#define DN_LArrayEraseRange(c_array, ptr_size, begin_index, count, erase) DN_PArrayEraseRange(c_array, ptr_size, begin_index, count, erase)
#define DN_LArrayErase(c_array, ptr_size, index, erase) DN_PArrayErase(c_array, ptr_size, index, erase)
#define DN_LArrayInsertArray(c_array, ptr_size, index, items, count) DN_PArrayInsertArray(c_array, ptr_size, DN_ArrayCountU(c_array), index, items, count)
#define DN_LArrayInsert(c_array, ptr_size, index, item) DN_PArrayInsert(c_array, ptr_size, DN_ArrayCountU(c_array), index, item)
#define DN_LArrayPopFront(c_array, ptr_size, count) DN_PArrayPopFront(c_array, ptr_size, DN_ArrayCountU(c_array), count)
#define DN_LArrayPopBack(c_array, ptr_size, count) DN_PArrayPopBack(c_array, ptr_size, DN_ArrayCountU(c_array), count)
#define DN_IArrayResizeFromPool(ptr_array, pool, new_max) DN_CArrayResizeFromPool((void **)(&(ptr_array)->data), &(ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, new_max)
#define DN_IArrayResizeFromArena(ptr_array, arena, new_max) DN_CArrayResizeFromArena((void **)(&(ptr_array)->data), &(ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, new_max)
#define DN_IArrayGrowFromPool(ptr_array, pool, new_max) DN_CArrayGrowFromPool((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, new_max)
#define DN_IArrayGrowFromArena(ptr_array, arena, new_max) DN_CArrayGrowFromArena((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, new_max)
#define DN_IArrayGrowIfNeededFromPool(ptr_array, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, add_count)
#define DN_IArrayGrowIfNeededFromArena(ptr_array, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, add_count)
#define DN_IArrayMakeArray(ptr_array, count, z_mem) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), count, z_mem)
#define DN_IArrayMakeArrayZ(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), count, DN_ZMem_Yes)
#define DN_IArrayMake(ptr_array, z_mem) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), 1, z_mem)
#define DN_IArrayMakeZ(ptr_array) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), 1, DN_ZMem_Yes)
#define DN_IArrayAddArray(ptr_array, items, count, add) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), items, count, add)
#define DN_IArrayAdd(ptr_array, item, add) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), &item, 1, add)
#define DN_IArrayAppendArray(ptr_array, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), items, count, DN_ArrayAdd_Append)
#define DN_IArrayAppend(ptr_array, item) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), &item, 1, DN_ArrayAdd_Append)
#define DN_IArrayPrependArray(ptr_array, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), items, count, DN_ArrayAdd_Prepend)
#define DN_IArrayPrepend(ptr_array, item) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend)
#define DN_IArrayEraseRange(ptr_array, begin_index, count, erase) DN_CArrayEraseRange((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), begin_index, count, erase)
#define DN_IArrayErase(ptr_array, index, erase) DN_CArrayEraseRange((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), index, 1, erase)
#define DN_IArrayInsertArray(ptr_array, index, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayInsertArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), index, items, count)
#define DN_IArrayInsert(ptr_array, index, item, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayInsertArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), index, &item, 1)
#define DN_IArrayPopFront(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayPopFront((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), count)
#define DN_IArrayPopBack(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayPopBack((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), count)
#define DN_ISliceAllocArena(slice_ptr, count_, zmem, arena) (DN_CppDeclType(&((slice_ptr)->data[0])))DN_SliceAllocArena((void **)&((slice_ptr)->data), &((slice_ptr)->count), count_, sizeof((slice_ptr)->data[0]), alignof(DN_CppDeclType((slice_ptr)->data[0])), zmem, arena)
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);
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);
DN_API void* DN_CArrayPopFront (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
DN_API void* DN_CArrayPopBack (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
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);
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);
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);
DN_API bool DN_CArrayResizeFromPool (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayResizeFromArena (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Arena *arena, DN_USize new_max);
DN_API bool DN_CArrayGrowFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayGrowFromArena (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
DN_API bool DN_CArrayGrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize add_count);
DN_API bool DN_CArrayGrowIfNeededFromArena (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Arena *pool, DN_USize add_count);
DN_API void* DN_SinglyLLDetach (void **link, void **next);
DN_API bool DN_RingHasSpace (DN_Ring const *ring, DN_U64 size);
DN_API bool DN_RingHasData (DN_Ring const *ring, DN_U64 size);
DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size);
#define DN_RingWriteStruct(ring, item) DN_RingWrite((ring), (item), sizeof(*(item)))
DN_API void DN_RingRead (DN_Ring *ring, void *dest, DN_U64 dest_size);
#define DN_RingReadStruct(ring, dest) DN_RingRead((ring), (dest), sizeof(*(dest)))
DN_U32 const DN_DS_MAP_DEFAULT_HASH_SEED = 0x8a1ced49;
DN_U32 const DN_DS_MAP_SENTINEL_SLOT = 0;
template <typename T> DN_DSMap<T> DN_DSMapInit (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> bool DN_DSMapIsValid (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_DSMapHashToSlotIndex (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_DSMapMake (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_DSMapFindKeyU64 (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_DSMapSetKeyU64 (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_DSMapMakeKeyStr8 (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> bool DN_DSMapResize (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_DSMapEraseKeyU64 (DN_DSMap<T> *map, DN_U64 key);
template <typename T> bool DN_DSMapEraseKeyStr8 (DN_DSMap<T> *map, DN_Str8 key);
template <typename T> DN_DSMapKey DN_DSMapKeyBuffer (DN_DSMap<T> const *map, void const *data, DN_USize size);
template <typename T> DN_DSMapKey DN_DSMapKeyBufferAsU64NoHash (DN_DSMap<T> const *map, void const *data, DN_USize size);
template <typename T> DN_DSMapKey DN_DSMapKeyU64 (DN_DSMap<T> const *map, DN_U64 u64);
template <typename T> DN_DSMapKey DN_DSMapKeyStr8 (DN_DSMap<T> const *map, DN_Str8 string);
#define DN_DSMapKeyCStr8(map, string) DN_DSMapKeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1)
DN_API DN_DSMapKey DN_DSMapKeyU64NoHash (DN_U64 u64);
DN_API bool DN_DSMapKeyEquals (DN_DSMapKey lhs, DN_DSMapKey rhs);
DN_API bool operator== (DN_DSMapKey lhs, DN_DSMapKey rhs);
#endif // !defined(DN_CONTAINER_H)
+9 -15
View File
@@ -10,19 +10,15 @@ DN_API void DN_LeakTrackAlloc_(DN_LeakTracker *leak, void *ptr, DN_USize size, b
return;
DN_TicketMutex_Begin(&leak->alloc_table_mutex);
DN_DEFER
{
DN_TicketMutex_End(&leak->alloc_table_mutex);
};
DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/);
DN_Str8 stack_trace = DN_Str8FromStackTraceNowHeap(128, 3 /*skip*/);
DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table;
DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMapMakeKeyU64(alloc_table, DN_Cast(DN_U64) ptr);
DN_LeakAlloc *alloc = alloc_entry.value;
if (alloc_entry.found) {
if ((alloc->flags & DN_LeakAllocFlag_Freed) == 0) {
DN_Str8x32 alloc_size = DN_ByteCountStr8x32(alloc->size);
DN_Str8x32 new_alloc_size = DN_ByteCountStr8x32(size);
DN_Str8x32 alloc_size = DN_Str8x32FromByteCountU64Auto(alloc->size);
DN_Str8x32 new_alloc_size = DN_Str8x32FromByteCountU64Auto(size);
DN_HardAssertF(
alloc->flags & DN_LeakAllocFlag_Freed,
"This pointer is already in the leak tracker, however it has not been freed yet. This "
@@ -58,6 +54,7 @@ DN_API void DN_LeakTrackAlloc_(DN_LeakTracker *leak, void *ptr, DN_USize size, b
alloc->stack_trace = stack_trace;
alloc->flags |= leak_permitted ? DN_LeakAllocFlag_LeakPermitted : 0;
leak->alloc_table_bytes_allocated_for_stack_traces += alloc->stack_trace.size;
DN_TicketMutex_End(&leak->alloc_table_mutex);
}
DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr)
@@ -66,12 +63,8 @@ DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr)
return;
DN_TicketMutex_Begin(&leak->alloc_table_mutex);
DN_DEFER
{
DN_TicketMutex_End(&leak->alloc_table_mutex);
};
DN_Str8 stack_trace = DN_StackTraceWalkStr8FromHeap(128, 3 /*skip*/);
DN_Str8 stack_trace = DN_Str8FromStackTraceNowHeap(128, 3 /*skip*/);
DN_DSMap<DN_LeakAlloc> *alloc_table = &leak->alloc_table;
DN_DSMapResult<DN_LeakAlloc> alloc_entry = DN_DSMapFindKeyU64(alloc_table, DN_Cast(uintptr_t) ptr);
DN_HardAssertF(alloc_entry.found,
@@ -82,7 +75,7 @@ DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr)
DN_LeakAlloc *alloc = alloc_entry.value;
if (alloc->flags & DN_LeakAllocFlag_Freed) {
DN_Str8x32 freed_size = DN_ByteCountStr8x32(alloc->freed_size);
DN_Str8x32 freed_size = DN_Str8x32FromByteCountU64Auto(alloc->freed_size);
DN_HardAssertF((alloc->flags & DN_LeakAllocFlag_Freed) == 0,
"Double free detected, pointer to free was already marked "
"as freed. Either the pointer was reallocated but not "
@@ -110,6 +103,7 @@ DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr)
alloc->flags |= DN_LeakAllocFlag_Freed;
alloc->freed_stack_trace = stack_trace;
leak->alloc_table_bytes_allocated_for_stack_traces += alloc->freed_stack_trace.size;
DN_TicketMutex_End(&leak->alloc_table_mutex);
}
DN_API void DN_LeakDump_(DN_LeakTracker *leak)
@@ -124,7 +118,7 @@ DN_API void DN_LeakDump_(DN_LeakTracker *leak)
if (alloc_leaked && !leak_permitted) {
leaked_bytes += alloc->size;
leak_count++;
DN_Str8x32 alloc_size = DN_ByteCountStr8x32(alloc->size);
DN_Str8x32 alloc_size = DN_Str8x32FromByteCountU64Auto(alloc->size);
DN_LogWarningF(
"Pointer (0x%p) leaked %.*s at:\n"
"%.*s",
@@ -135,7 +129,7 @@ DN_API void DN_LeakDump_(DN_LeakTracker *leak)
}
if (leak_count) {
DN_Str8x32 leak_size = DN_ByteCountStr8x32(leaked_bytes);
DN_Str8x32 leak_size = DN_Str8x32FromByteCountU64Auto(leaked_bytes);
DN_LogWarningF("There were %I64u leaked allocations totalling %.*s", leak_count, DN_Str8PrintFmt(leak_size));
}
}
+1 -1
View File
@@ -201,6 +201,6 @@ DN_API void DN_BinPackCBuffer(DN_BinPack *pack, DN_BinPackMode mode, char *ptr,
DN_API DN_Str8 DN_BinPackBuild(DN_BinPack const *pack, DN_Arena *arena)
{
DN_Str8 result = DN_Str8BuilderBuild(&pack->writer, arena);
DN_Str8 result = DN_Str8FromStr8BuilderArena(&pack->writer, arena);
return result;
}
+2 -2
View File
@@ -14,7 +14,7 @@ DN_API DN_JSONBuilder DN_JSONBuilder_Init(DN_Arena *arena, int spaces_per_indent
DN_API DN_Str8 DN_JSONBuilder_Build(DN_JSONBuilder const *builder, DN_Arena *arena)
{
DN_Str8 result = DN_Str8BuilderBuild(&builder->string_builder, arena);
DN_Str8 result = DN_Str8FromStr8BuilderArena(&builder->string_builder, arena);
return result;
}
@@ -71,7 +71,7 @@ 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_TCScratch scratch = DN_TCScratchBegin(&builder->string_builder.arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&builder->string_builder.arena, 1);
DN_Str8 value = DN_Str8FromFmtVArena(&scratch.arena, value_fmt, args);
DN_JSONBuilder_KeyValue(builder, key, value);
DN_TCScratchEnd(&scratch);
+3 -82
View File
@@ -79,15 +79,12 @@ enum DN_BinarySearchType
struct DN_BinarySearchResult
{
bool found;
DN_USize index;
bool found;
DN_USize index;
};
template <typename T>
using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context);
#if !defined(DN_NO_JSON_BUILDER)
// NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
// NOTE: DN_JSONBuilder
#define DN_JSONBuilder_Object(builder) \
DN_DeferLoop(DN_JSONBuilder_ObjectBegin(builder), \
DN_JSONBuilder_ObjectEnd(builder))
@@ -133,10 +130,6 @@ DN_API void DN_JSONBuilder_BoolNamed (DN_JSONBuilde
template <typename T> bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
template <typename T> DN_BinarySearchResult DN_BinarySearch (T const *array, DN_USize array_size, T const &find, DN_BinarySearchType type = DN_BinarySearchType_Match, DN_BinarySearchLessThanProc<T> less_than = DN_BinarySearch_DefaultLessThan);
// NOTE: DN_QSort
template <typename T> bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context);
template <typename T> void DN_QSort (T *array, DN_USize array_size, void *user_context, DN_QSortLessThanProc<T> less_than = DN_QSort_DefaultLessThan);
// NOTE: DN_BinarySearch
template <typename T>
bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs)
@@ -189,76 +182,4 @@ DN_BinarySearchResult DN_BinarySearch(T const *array,
result.index = first - array;
return result;
}
// NOTE: DN_QSort //////////////////////////////////////////////////////////////////////////////////
template <typename T>
bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context)
{
(void)user_context;
bool result = lhs < rhs;
return result;
}
template <typename T>
void DN_QSort(T *array, DN_USize array_size, void *user_context, DN_QSortLessThanProc<T> less_than)
{
if (!array || array_size <= 1 || !less_than)
return;
// NOTE: Insertion Sort, under 24->32 is an optimal amount /////////////////////////////////////
const DN_USize QSORT_THRESHOLD = 24;
if (array_size < QSORT_THRESHOLD) {
for (DN_USize item_to_insert_index = 1; item_to_insert_index < array_size; item_to_insert_index++) {
for (DN_USize index = 0; index < item_to_insert_index; index++) {
if (!less_than(array[index], array[item_to_insert_index], user_context)) {
T item_to_insert = array[item_to_insert_index];
for (DN_USize i = item_to_insert_index; i > index; i--)
array[i] = array[i - 1];
array[index] = item_to_insert;
break;
}
}
}
return;
}
// NOTE: Quick sort, under 24->32 is an optimal amount /////////////////////////////////////////
DN_USize last_index = array_size - 1;
DN_USize pivot_index = array_size / 2;
DN_USize partition_index = 0;
DN_USize start_index = 0;
// Swap pivot with last index, so pivot is always at the end of the array.
// This makes logic much simpler.
DN_Swap(array[last_index], array[pivot_index]);
pivot_index = last_index;
// 4^, 8, 7, 5, 2, 3, 6
if (less_than(array[start_index], array[pivot_index], user_context))
partition_index++;
start_index++;
// 4, |8, 7, 5^, 2, 3, 6*
// 4, 5, |7, 8, 2^, 3, 6*
// 4, 5, 2, |8, 7, ^3, 6*
// 4, 5, 2, 3, |7, 8, ^6*
for (DN_USize index = start_index; index < last_index; index++) {
if (less_than(array[index], array[pivot_index], user_context)) {
DN_Swap(array[partition_index], array[index]);
partition_index++;
}
}
// Move pivot to right of partition
// 4, 5, 2, 3, |6, 8, ^7*
DN_Swap(array[partition_index], array[pivot_index]);
DN_QSort(array, partition_index, user_context, less_than);
// Skip the value at partion index since that is guaranteed to be sorted.
// 4, 5, 2, 3, (x), 8, 7
DN_USize one_after_partition_index = partition_index + 1;
DN_QSort(array + one_after_partition_index, (array_size - one_after_partition_index), user_context, less_than);
}
#endif // !defined(DN_HELPERS_H)
+41 -7
View File
@@ -42,15 +42,40 @@ DN_NETRequestHandle DN_NET_HandleFromRequest(DN_NETRequest *request)
return result;
}
void DN_NET_EndFinishedRequest_(DN_NETRequest *request)
bool DN_NET_ResponseHasFailed(DN_NETResponse const* resp)
{
// NOTE: Deallocate the memory used in the request and reset the string builder
DN_ArenaTempEnd(&request->start_response_arena, DN_ArenaReset_Yes);
// NOTE: Check that the request is completely detached
DN_Assert(request->next == nullptr);
bool result = false;
if (resp->type == DN_NETRequestType_HTTP)
result = resp->state == DN_NETResponseState_Error || resp->http_status >= 400;
else
result = resp->state == DN_NETResponseState_Error;
return result;
}
void DN_NET_BaseInit_(DN_NETCore *net, char *base, DN_U64 base_size)
DN_Str8 DN_NET_Str8DiagnosticFromResponse(DN_NETResponse const* resp, DN_Arena *arena)
{
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
bool resp_failed = DN_NET_ResponseHasFailed(resp);
DN_Str8BuilderAppendF(&builder, "Request %s (%s", resp_failed ? "failed" : "succeeded", resp->type == DN_NETRequestType_HTTP ? "HTTP" : "WS");
if (resp->type == DN_NETRequestType_HTTP) {
if (resp->http_status)
DN_Str8BuilderAppendF(&builder, " %u", resp->http_status);
}
DN_Str8BuilderAppendF(&builder, ")");
if (resp->body.size || resp->error_str8.size) {
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit(" with "));
if (resp->body.size)
DN_Str8BuilderAppendF(&builder, "%.*s", DN_Str8PrintFmt(resp->body));
if (resp->error_str8.size)
DN_Str8BuilderAppendF(&builder, "%s%.*s", resp->body.size ? ". " : "", DN_Str8PrintFmt(resp->error_str8));
}
DN_Str8 result = DN_Str8FromStr8BuilderArena(&builder, arena);
DN_TCScratchEnd(&scratch);
return result;
}
void DN_NET_BaseInit(DN_NETCore *net, char *base, DN_U64 base_size)
{
net->base = base;
net->base_size = base_size;
@@ -59,7 +84,7 @@ void DN_NET_BaseInit_(DN_NETCore *net, char *base, DN_U64 base_size)
net->completion_sem = DN_OS_SemaphoreInit(0);
}
DN_NETRequestHandle DN_NET_SetupRequest_(DN_NETRequest *request, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type)
DN_NETRequestHandle DN_NET_SetupRequest(DN_NETRequest *request, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type)
{
// NOTE: Setup request
DN_Assert(request);
@@ -94,5 +119,14 @@ DN_NETRequestHandle DN_NET_SetupRequest_(DN_NETRequest *request, DN_Str8 url, DN
DN_NETRequestHandle result = DN_NET_HandleFromRequest(request);
request->response.request = result;
request->response.type = request->type;
return result;
}
void DN_NET_EndFinishedRequest(DN_NETRequest *request)
{
// NOTE: Deallocate the memory used in the request and reset the string builder
DN_ArenaTempEnd(&request->start_response_arena, DN_ArenaReset_Yes);
// NOTE: Check that the request is completely detached
DN_Assert(request->next == nullptr);
}
+10 -7
View File
@@ -51,7 +51,7 @@ struct DN_NETDoHTTPArgs
DN_U16 headers_size;
// NOTE: HTTP args only
DN_Str8 payload;
DN_Str8 payload;
};
struct DN_NETRequestHandle
@@ -63,6 +63,7 @@ struct DN_NETRequestHandle
struct DN_NETResponse
{
// NOTE: Common to WS and HTTP responses
DN_NETRequestType type;
DN_NETResponseState state;
DN_NETRequestHandle request;
DN_Str8 error_str8;
@@ -119,13 +120,15 @@ struct DN_NETCore
DN_NETInterface api;
};
DN_Str8 DN_NET_Str8FromResponseState(DN_NETResponseState state);
DN_NETRequest * DN_NET_RequestFromHandle (DN_NETRequestHandle handle);
DN_NETRequestHandle DN_NET_HandleFromRequest (DN_NETRequest *request);
DN_Str8 DN_NET_Str8FromResponseState (DN_NETResponseState state);
DN_NETRequest * DN_NET_RequestFromHandle (DN_NETRequestHandle handle);
DN_NETRequestHandle DN_NET_HandleFromRequest (DN_NETRequest *request);
bool DN_NET_ResponseHasFailed (DN_NETResponse const* resp);
DN_Str8 DN_NET_Str8DiagnosticFromResponse(DN_NETResponse const* resp, DN_Arena *arena);
// NOTE: Internal functions for different networking implementations to use
void DN_NET_BaseInit_ (DN_NETCore *net, char *base, DN_U64 base_size);
DN_NETRequestHandle DN_NET_SetupRequest_ (DN_NETRequest *request, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type);
void DN_NET_EndFinishedRequest_ (DN_NETRequest *request);
void DN_NET_BaseInit (DN_NETCore *net, char *base, DN_U64 base_size);
DN_NETRequestHandle DN_NET_SetupRequest (DN_NETRequest *request, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type);
void DN_NET_EndFinishedRequest (DN_NETRequest *request);
#endif // DN_NET_H
+15 -11
View File
@@ -93,7 +93,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_OS_ThreadSetNameFmt("%.*s", DN_Str8PrintFmt(curl->thread.name));
while (!curl->kill_thread) {
DN_TCScratch tmem = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch tmem = DN_TCScratchBeginArena(nullptr, 0);
// NOTE: Handle events sitting in the ring queue
for (bool dequeue_ring = true; dequeue_ring;) {
@@ -159,7 +159,7 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
// NOTE: End the temp memory storing the WS data we just read and the user returned to us
// (we got their receipt back). Then restart the temp memory scope for the next websocket
// payload
DN_NET_EndFinishedRequest_(req);
DN_NET_EndFinishedRequest(req);
req->start_response_arena = DN_ArenaTempBeginFromArena(&req->arena);
curl_req->str8_builder = DN_Str8BuilderFromArena(&req->start_response_arena);
@@ -175,12 +175,15 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
DN_NETRequest *request = DN_Cast(DN_NETRequest *) event.request.handle;
// NOTE: Release resources
DN_NET_EndFinishedRequest_(request);
DN_NET_EndFinishedRequest(request);
DN_OS_SemaphoreDeinit(&request->completion_sem);
curl_multi_remove_handle(curl->thread_curlm, curl_req->handle);
curl_easy_reset(curl_req->handle);
curl_slist_free_all(curl_req->slist);
curl_easy_reset(curl_req->handle);
CURL *copy = curl_req->handle;
*curl_req = {};
curl_req->handle = copy;
// NOTE: Zero the struct preserving just the data we need to retain
DN_NETRequest resetter = {};
@@ -230,13 +233,13 @@ static int32_t DN_NET_CurlThreadEntryPoint_(DN_OSThread *thread)
req->response.state = DN_NETResponseState_WSOpen;
}
} else {
req->response.error_str8 = DN_Str8FromFmtArena(&req->arena, "Failed to get HTTP response status (CURL %d): %s", msg->data.result, curl_easy_strerror(get_result));
req->response.error_str8 = DN_Str8FromFmtArena(&req->start_response_arena, "Failed to get HTTP response status (CURL %d): %s", msg->data.result, curl_easy_strerror(get_result));
req->response.state = DN_NETResponseState_Error;
}
} else {
DN_USize curl_extended_error_size = DN_CStr8Size(curl_req->error);
req->response.state = DN_NETResponseState_Error;
req->response.error_str8 = DN_Str8FromFmtArena(&req->arena,
req->response.error_str8 = DN_Str8FromFmtArena(&req->start_response_arena,
"HTTP request '%.*s' failed (CURL %d): %s%s%s%s",
DN_Str8PrintFmt(req->url),
msg->data.result,
@@ -400,7 +403,7 @@ DN_NETInterface DN_NET_CurlInterface()
void DN_NET_CurlInit(DN_NETCore *net, char *base, DN_U64 base_size)
{
DN_NET_BaseInit_(net, base, base_size);
DN_NET_BaseInit(net, base, base_size);
DN_NETCurlCore *curl = DN_ArenaNew(&net->arena, DN_NETCurlCore, DN_ZMem_Yes);
net->context = curl;
net->api = DN_NET_CurlInterface();
@@ -458,8 +461,7 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D
// NOTE: Setup the request
DN_NETCurlRequest *curl_req = DN_NET_CurlRequestFromRequest_(req);
{
result = DN_NET_SetupRequest_(req, url, method, args, type);
req->response.request = result;
result = DN_NET_SetupRequest(req, url, method, args, type);
req->context[1] = DN_Cast(DN_UPtr) net;
curl_req->str8_builder = DN_Str8BuilderFromArena(&req->start_response_arena);
}
@@ -480,8 +482,10 @@ static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, D
curl_easy_setopt(curl, CURLOPT_WRITEDATA, req);
// NOTE: Assign HTTP headers
for (DN_ForItSize(it, DN_Str8, req->args.headers, req->args.headers_size))
for (DN_ForItSize(it, DN_Str8, req->args.headers, req->args.headers_size)) {
DN_Assert(it.data->data[it.data->size] == 0);
curl_req->slist = curl_slist_append(curl_req->slist, it.data->data);
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_req->slist);
// NOTE: Setup handle for protocol
@@ -593,7 +597,7 @@ static DN_NETResponse DN_NET_CurlHandleFinishedRequest_(DN_NETCurlCore *curl, DN
DN_NETResponse result = req->response;
DN_NETCurlRequest *curl_req = DN_NET_CurlRequestFromRequest_(req);
{
result.body = DN_Str8BuilderBuild(&curl_req->str8_builder, arena);
result.body = DN_Str8FromStr8BuilderArena(&curl_req->str8_builder, arena);
if (result.error_str8.size)
result.error_str8 = DN_Str8FromStr8Arena(result.error_str8, arena);
}
+94 -34
View File
@@ -365,6 +365,66 @@ static DN_UTCore DN_TST_Base()
DN_UT_Assert(&result, mutex.ticket == ticket_b + 1);
}
for (DN_UT_Test(&result, "QSort String (Natural)")) {
DN_Str8 list[] = {
DN_Str8Lit("item10"),
DN_Str8Lit("item2"),
DN_Str8Lit("item1"),
DN_Str8Lit("item20"),
DN_Str8Lit("item12"),
DN_Str8Lit("Afile"),
DN_Str8Lit("file2"),
DN_Str8Lit("file10"),
DN_Str8Lit("file1"),
DN_Str8Lit("z_last"),
DN_Str8Lit("m_middle"),
DN_Str8Lit("a_first"),
DN_Str8Lit("version-1.2.10"),
DN_Str8Lit("version-1.2.2"),
DN_Str8Lit("version-1.10.0"),
};
DN_QSortStr8NaturalAsc(list, DN_ArrayCountU(list), DN_Str8EqCase_Sensitive);
DN_USize list_index = 0;
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("Afile")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("a_first")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("file1")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("file2")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("file10")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("item1")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("item2")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("item10")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("item12")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("item20")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("m_middle")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("version-1.2.2")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("version-1.2.10")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("version-1.10.0")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("z_last")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
}
for (DN_UT_Test(&result, "QSort String (Lexicographic)")) {
DN_Str8 list[] = {
DN_Str8Lit("z_last"),
DN_Str8Lit("m_middle"),
DN_Str8Lit("a_first"),
DN_Str8Lit("version-1.2.10"),
DN_Str8Lit("version-1.2.2"),
DN_Str8Lit("version-1.10.0"),
};
DN_QSortStr8LexicographicAsc(list, DN_ArrayCountU(list), DN_Str8EqCase_Insensitive);
DN_USize list_index = 0;
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("a_first")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("m_middle")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("version-1.10.0")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("version-1.2.10")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("version-1.2.2")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
DN_AssertF(DN_Str8Eq(list[list_index++], DN_Str8Lit("z_last")), "%.*s", DN_Str8PrintFmt(list[list_index-1]));
}
// NOTE: MSVC SAL complains that we are using Interlocked functionality on
// variables it has detected as *not* being shared across threads. This is
// fine, we're just running some basic results, so permit it.
@@ -529,7 +589,7 @@ static DN_UTCore DN_TST_BaseArena()
static DN_UTCore DN_TST_BaseBytesHex()
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_UTCore test = DN_UT_Init();
DN_UT_LogF(&test, "Bytes <-> Hex\n");
{
@@ -935,7 +995,7 @@ static DN_UTCore DN_TST_BaseDSMap()
DN_UTCore result = DN_UT_Init();
DN_UT_LogF(&result, "DN_DSMap\n");
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
{
DN_MemList mem = DN_MemListFromVMem(0, 0, DN_MemFlags_Nil);
DN_Arena arena = DN_ArenaFromMemList(&mem);
@@ -1134,7 +1194,7 @@ static DN_UTCore DN_TST_BaseIArray()
struct CustomArray
{
int *data;
DN_USize size;
DN_USize count;
DN_USize max;
};
@@ -1145,24 +1205,24 @@ static DN_UTCore DN_TST_BaseIArray()
for (DN_UT_Test(&result, "Make item")) {
int *item = DN_IArrayMake(&array, DN_ZMem_Yes);
DN_UT_Assert(&result, item && array.size == 1);
DN_UT_Assert(&result, item && array.count == 1);
}
}
return result;
}
static DN_UTCore DN_TST_BaseCArray2()
static DN_UTCore DN_TST_BaseArray()
{
DN_UTCore result = DN_UT_Init();
DN_UT_LogF(&result, "DN_CArray2\n");
DN_UT_LogF(&result, "DN_Array\n");
{
for (DN_UT_Test(&result, "Positive count, middle of array, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 2);
DN_UT_Assert(&result, erase.it_index == 3);
DN_UT_AssertF(&result, erase.it_index == 2, "erase.it_index=%zu", erase.it_index);
DN_UT_Assert(&result, size == 8);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
}
@@ -1170,10 +1230,10 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "Negative count, middle of array, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 3);
DN_UT_Assert(&result, erase.it_index == 3);
DN_UT_Assert(&result, erase.it_index == 2);
DN_UT_Assert(&result, size == 7);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
}
@@ -1181,10 +1241,10 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "count = -1, stable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -1, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -1, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 5);
DN_UT_Assert(&result, erase.it_index == 4);
DN_UT_Assert(&result, size == 9);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
}
@@ -1192,10 +1252,10 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "Positive count, unstable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Unstable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 3, 2, DN_ArrayErase_Unstable);
int expected[] = {0, 1, 2, 8, 9, 5, 6, 7};
DN_UT_Assert(&result, erase.items_erased == 2);
DN_UT_Assert(&result, erase.it_index == 3);
DN_UT_Assert(&result, erase.it_index == 2);
DN_UT_Assert(&result, size == 8);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
}
@@ -1203,10 +1263,10 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "Negative count, unstable erase")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Unstable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 5, -3, DN_ArrayErase_Unstable);
int expected[] = {0, 1, 2, 7, 8, 9, 6};
DN_UT_Assert(&result, erase.items_erased == 3);
DN_UT_Assert(&result, erase.it_index == 3);
DN_UT_Assert(&result, erase.it_index == 2);
DN_UT_Assert(&result, size == 7);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
}
@@ -1214,7 +1274,7 @@ static DN_UTCore DN_TST_BaseCArray2()
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};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 0, -2, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 0, -2, DN_ArrayErase_Stable);
int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 0);
@@ -1225,10 +1285,10 @@ static DN_UTCore DN_TST_BaseCArray2()
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};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 9, 2, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 9, 2, DN_ArrayErase_Stable);
int expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
DN_UT_Assert(&result, erase.items_erased == 1);
DN_UT_Assert(&result, erase.it_index == 9);
DN_UT_Assert(&result, erase.it_index == 8);
DN_UT_Assert(&result, size == 9);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
}
@@ -1236,7 +1296,7 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "Invalid input - count = 0")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 0, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 0, DN_ArrayErase_Stable);
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.it_index == 0);
@@ -1246,7 +1306,7 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "Invalid input - null data")) {
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(nullptr, &size, sizeof(int), 5, 2, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(nullptr, &size, sizeof(int), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0);
DN_UT_Assert(&result, size == 10);
@@ -1254,7 +1314,7 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "Invalid input - null size")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, NULL, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, NULL, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0);
}
@@ -1262,7 +1322,7 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "Invalid input - empty array")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 0;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 5, 2, DN_ArrayErase_Stable);
DN_UT_Assert(&result, erase.items_erased == 0);
DN_UT_Assert(&result, erase.it_index == 0);
DN_UT_Assert(&result, size == 0);
@@ -1271,10 +1331,10 @@ static DN_UTCore DN_TST_BaseCArray2()
for (DN_UT_Test(&result, "Out-of-bounds begin_index")) {
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
DN_USize size = 10;
DN_ArrayEraseResult erase = DN_CArrayEraseRange(arr, &size, sizeof(arr[0]), 15, 2, DN_ArrayErase_Stable);
DN_ArrayEraseResult erase = DN_ArrayEraseRange(arr, &size, sizeof(arr[0]), 15, 2, DN_ArrayErase_Stable);
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.it_index == 10);
DN_UT_Assert(&result, erase.it_index == 9);
DN_UT_Assert(&result, size == 10);
DN_UT_Assert(&result, DN_Memcmp(arr, expected, size * sizeof(arr[0])) == 0);
}
@@ -1632,7 +1692,7 @@ DN_Str8 const DN_UT_HASH_STRING_[] =
void DN_TST_KeccakDispatch_(DN_UTCore *test, int hash_type, DN_Str8 input)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 input_hex = DN_HexFromPtrBytesArena(input.data, input.size, &scratch.arena, DN_TrimLeadingZero_No);
switch (hash_type) {
@@ -1860,7 +1920,7 @@ static DN_UTCore DN_TST_OS()
}
for (DN_UT_Test(&result, "Query executable directory")) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 os_result = DN_OS_EXEDir(&scratch.arena);
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));
@@ -1911,7 +1971,7 @@ static DN_UTCore DN_TST_OS()
DN_UT_Assert(&result, DN_OS_PathIsFile(SRC_FILE));
// NOTE: Read step
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
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 == 4, "File read wrong amount of bytes (%zu)", read_file.size);
@@ -2166,7 +2226,7 @@ static DN_UTCore DN_TST_BaseStrings()
}
for (DN_UT_Test(&result, "Initialise with format string")) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
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.data[0] == 'A', "string[0]: %c", string.data[0]);
@@ -2176,7 +2236,7 @@ static DN_UTCore DN_TST_BaseStrings()
}
for (DN_UT_Test(&result, "Copy string")) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 string = DN_Str8Lit("AB");
DN_Str8 copy = DN_Str8FromStr8Arena(string, &scratch.arena);
DN_UT_AssertF(&result, copy.size == 2, "size: %zu", copy.size);
@@ -2192,7 +2252,7 @@ static DN_UTCore DN_TST_BaseStrings()
}
for (DN_UT_Test(&result, "Allocate string from arena")) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 string = DN_Str8AllocArena(2, DN_ZMem_No, &scratch.arena);
DN_UT_AssertF(&result, string.size == 2, "size: %zu", string.size);
DN_TCScratchEnd(&scratch);
@@ -2530,7 +2590,7 @@ static DN_UTCore DN_TST_BaseStrings()
// NOTE: DN_Str8TruncMiddle (arena wrapper)
for (DN_UT_Test(&result, "TruncMiddle: Arena wrapper allocates and truncates correctly")) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 str = DN_Str8Lit("HelloBeautifulWorld");
DN_Str8 trunc = DN_Str8Lit("...");
DN_Str8TruncResult res = DN_Str8TruncMiddle(str, 5, trunc, &scratch.arena);
@@ -2551,7 +2611,7 @@ static DN_UTCore DN_TST_Win()
#if defined(DN_PLATFORM_WIN32)
DN_UT_LogF(&result, "OS Win32\n");
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 input8 = DN_Str8Lit("String");
DN_Str16 input16 = DN_Str16{(wchar_t *)(L"String"), sizeof(L"String") / sizeof(L"String"[0]) - 1};
@@ -2700,7 +2760,7 @@ DN_TSTResult DN_TST_RunSuite(DN_TSTPrint print)
#endif
DN_TST_BaseDSMap(),
DN_TST_BaseIArray(),
DN_TST_BaseCArray2(),
DN_TST_BaseArray(),
DN_TST_BaseVArray(),
DN_TST_Keccak(),
DN_TST_M4(),
+2 -2
View File
@@ -35,8 +35,8 @@ DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(6262) // Function uses '29804' bytes of stack. Consider moving some data to heap.
int main(int, char**)
{
DN_Core dn = {};
DN_Init(&dn, DN_InitFlags_LogAllFeatures | DN_InitFlags_OS | DN_InitFlags_ThreadContext, nullptr);
DN_Core dn = {};
DN_Init(&dn, DN_InitFlags_LogAllFeatures | DN_InitFlags_OS | DN_InitFlags_ThreadContext, DN_TCInitArgsDefault());
DN_TST_RunSuite(DN_TSTPrint_Yes);
return 0;
}
+106 -57
View File
@@ -67,6 +67,30 @@ DN_API DN_MemList DN_MemListFromVMem(DN_U64 reserve, DN_U64 commit, DN_MemFlags
return result;
}
DN_API DN_Arena DN_ArenaFromHeap(DN_U64 size, DN_MemFlags flags)
{
DN_MemList mem = DN_MemListFromHeap(size, flags);
DN_Arena result = {};
result.flags |= DN_ArenaFlags_OwnsMemList;
result.mem = DN_MemListNewCopy(&mem, DN_MemList, &mem);
return result;
}
DN_API DN_Arena DN_ArenaFromVMem(DN_U64 reserve, DN_U64 commit, DN_MemFlags flags)
{
DN_MemList mem = DN_MemListFromVMem(reserve, commit, flags);
DN_Arena result = {};
result.flags |= DN_ArenaFlags_OwnsMemList;
result.mem = DN_MemListNewCopy(&mem, DN_MemList, &mem);
return result;
}
DN_API void DN_ArenaDeinit(DN_Arena *arena)
{
if (arena->flags & DN_ArenaFlags_OwnsMemList)
DN_MemListDeinit(arena->mem);
}
DN_API DN_Str8 DN_Str8FromHeapF(DN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
@@ -92,7 +116,7 @@ DN_API DN_Str8 DN_Str8FromHeap(DN_USize size, DN_ZMem z_mem)
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_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_Str8BSplitResult split = DN_Str8BSplit(src, DN_Str8Lit("\n"));
while (split.lhs.size) {
@@ -102,7 +126,7 @@ DN_API DN_Str8 DN_Str8PadNewLines(DN_Arena *arena, DN_Str8 src, DN_Str8 pad)
if (split.lhs.size)
DN_Str8BuilderAppendRef(&builder, DN_Str8Lit("\n"));
}
DN_Str8 result = DN_Str8BuilderBuild(&builder, arena);
DN_Str8 result = DN_Str8FromStr8BuilderArena(&builder, arena);
DN_TCScratchEnd(&scratch);
return result;
}
@@ -135,7 +159,7 @@ DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite ca
// NOTE: Open log file for appending if requested
DN_TicketMutex_Begin(&os->log_file_mutex);
if (os->log_to_file && !os->log_file.handle && !os->log_file.error) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 exe_dir = DN_OS_EXEDir(&scratch.arena);
DN_Str8 log_path = DN_OS_PathF(&scratch.arena, "%.*s/dn.log", DN_Str8PrintFmt(exe_dir));
os->log_file = DN_OS_FileOpen(log_path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_AppendOnly, nullptr);
@@ -250,7 +274,7 @@ DN_API DN_Str8 DN_OS_EXEDir(DN_Arena *arena)
DN_Str8 result = {};
if (!arena)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str8 exe_path = DN_OS_EXEPath(&scratch.arena);
DN_Str8 separators[] = {DN_Str8Lit("/"), DN_Str8Lit("\\")};
DN_Str8BSplitResult split = DN_Str8BSplitLastArray(exe_path, separators, DN_ArrayCountU(separators));
@@ -421,7 +445,7 @@ DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator allocator, DN_Str8 path, DN_ErrSin
}
if (!result.data) {
DN_Str8x32 bytes_str = DN_ByteCountStr8x32(path_info.size);
DN_Str8x32 bytes_str = DN_Str8x32FromByteCountU64Auto(path_info.size);
DN_ErrSinkAppendF(err, 1 /*err_code*/, "Failed to allocate %.*s for reading file '%.*s'", DN_Str8PrintFmt(bytes_str), DN_Str8PrintFmt(path));
return result;
}
@@ -475,7 +499,7 @@ DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error)
DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 buffer = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
bool result = DN_OS_FileWriteAll(file_path, buffer, error);
DN_TCScratchEnd(&scratch);
@@ -493,7 +517,7 @@ DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_ErrSink *error, DN_FMT_ATT
DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_ErrSink *error)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 tmp_path = DN_Str8FromFmtArena(&scratch.arena, "%.*s.tmp", DN_Str8PrintFmt(path));
if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) {
DN_TCScratchEnd(&scratch);
@@ -513,7 +537,7 @@ 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_ErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 buffer = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
bool result = DN_OS_FileWriteAllSafe(path, buffer, error);
DN_TCScratchEnd(&scratch);
@@ -630,7 +654,7 @@ DN_API DN_Str8 DN_OS_PathTo(DN_Arena *arena, DN_Str8 path, DN_Str8 path_separato
DN_API DN_Str8 DN_OS_PathToF(DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...)
{
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
va_list args;
va_start(args, fmt);
DN_Str8 path = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
@@ -648,7 +672,7 @@ DN_API DN_Str8 DN_OS_Path(DN_Arena *arena, DN_Str8 path)
DN_API DN_Str8 DN_OS_PathF(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...)
{
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
va_list args;
va_start(args, fmt);
DN_Str8 path = DN_Str8FromFmtVArena(&scratch.arena, fmt, args);
@@ -714,9 +738,8 @@ DN_API DN_OSExecResult DN_OS_ExecOrAbort(DN_Str8Slice cmd_line, DN_OSExecArgs *a
// NOTE: DN_OSThread
static void DN_OS_ThreadExecute_(void *user_context)
{
DN_OSThread *thread = DN_Cast(DN_OSThread *) user_context;
DN_MemFuncs mem_funcs = DN_MemFuncsDefault();
DN_TCInitFromMemFuncs(&thread->context, thread->thread_id, /*args=*/nullptr, mem_funcs);
DN_OSThread *thread = DN_Cast(DN_OSThread *) user_context;
DN_TCInitFromMemFuncs(&thread->context, thread->thread_id, DN_TCInitArgsDefault(), DN_MemFuncsDefault());
DN_TCEquip(&thread->context);
if (thread->is_lane_set) {
DN_OS_TCThreadLaneEquip(thread->lane);
@@ -833,7 +856,7 @@ DN_API DN_OSHttpResponse DN_OS_HttpRequest(DN_Arena *arena, DN_Str8 host, DN_Str
{
// TODO(doyle): Revise the memory allocation and its lifetime
DN_OSHttpResponse result = {};
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
result.scratch_arena = scratch.arena;
DN_OS_HttpRequestAsync(&result, arena, host, path, secure, method, body, headers);
@@ -1116,7 +1139,7 @@ T *DN_OS_VArrayInsertArray(DN_VArray<T> *array, DN_USize index, T const *items,
if (!DN_OS_VArrayIsValid(array))
return result;
if (DN_OS_VArrayReserve(array, array->size + count))
result = DN_CArrayInsertArray(array->data, &array->size, array->max, index, items, count);
result = DN_ArrayInsertArray(array->data, &array->size, array->max, index, items, count);
return result;
}
@@ -1137,14 +1160,14 @@ T *DN_OS_VArrayInsert(DN_VArray<T> *array, DN_USize index, T const &item)
template <typename T>
T *DN_OS_VArrayPopFront(DN_VArray<T> *array, DN_USize count)
{
T *result = DN_Cast(T *)DN_CArrayPopFront(array->data, &array->size, sizeof(T), count);
T *result = DN_Cast(T *)DN_ArrayPopFront(array->data, &array->size, sizeof(T), count);
return result;
}
template <typename T>
T *DN_OS_VArrayPopBack(DN_VArray<T> *array, DN_USize count)
{
T *result = DN_Cast(T *)DN_CArrayPopBack(array->data, &array->size, sizeof(T), count);
T *result = DN_Cast(T *)DN_ArrayPopBack(array->data, &array->size, sizeof(T), count);
return result;
}
@@ -1154,7 +1177,7 @@ DN_ArrayEraseResult DN_OS_VArrayEraseRange(DN_VArray<T> *array, DN_USize begin_i
DN_ArrayEraseResult result = {};
if (!DN_OS_VArrayIsValid(array))
return result;
result = DN_CArrayEraseRange(array->data, &array->size, sizeof(T), begin_index, count, erase);
result = DN_ArrayEraseRange(array->data, &array->size, sizeof(T), begin_index, count, erase);
return result;
}
@@ -1183,12 +1206,11 @@ bool DN_OS_VArrayReserve(DN_VArray<T> *array, DN_USize count)
return result;
}
// NOTE: Stack Trace
DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, DN_U16 limit)
DN_API DN_StackTrace DN_StackTraceFromAllocator(DN_Allocator allocator, DN_U16 limit)
{
DN_StackTraceWalkResult result = {};
DN_StackTrace result = {};
#if defined(DN_OS_WIN32)
if (!arena)
if (!allocator.context)
return result;
static DN_TicketMutex mutex = {};
@@ -1202,7 +1224,7 @@ DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, DN_U16 limit)
w32->sym_initialised = true;
SymSetOptions(SYMOPT_LOAD_LINES);
if (!SymInitialize(result.process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/)) {
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginAllocator(&allocator, 1);
DN_OSW32Error error = DN_OS_W32LastError(&scratch.arena);
DN_LogErrorF("SymInitialize failed, stack trace can not be generated (%lu): %.*s\n", error.code, DN_Str8PrintFmt(error.msg));
DN_TCScratchEnd(&scratch);
@@ -1240,7 +1262,9 @@ DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, DN_U16 limit)
}
DN_TicketMutex_End(&mutex);
result.base_addr = DN_ArenaNewArray(arena, DN_U64, raw_frames_count, DN_ZMem_No);
result.base_addr = DN_Cast(DN_U64 *)DN_AllocatorAlloc(allocator, raw_frames_count * sizeof(DN_U64), alignof(DN_U64), DN_ZMem_No);
DN_Assert(result.base_addr);
result.size = DN_Cast(DN_U16) raw_frames_count;
DN_Memcpy(result.base_addr, raw_frames, raw_frames_count * sizeof(raw_frames[0]));
#else
@@ -1250,66 +1274,91 @@ DN_API DN_StackTraceWalkResult DN_StackTraceWalk(DN_Arena *arena, DN_U16 limit)
return result;
}
static void DN_StackTraceAddWalkToStr8Builder(DN_StackTraceWalkResult const *walk, DN_Str8Builder *builder, DN_USize skip)
DN_API DN_StackTrace DN_StackTraceFromArena(DN_Arena *arena, DN_U16 limit)
{
DN_Allocator allocator = DN_AllocatorFromArena(arena);
DN_StackTrace result = DN_StackTraceFromAllocator(allocator, limit);
return result;
}
static void DN_StackTraceAddToStr8Builder_(DN_StackTrace const *trace, 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];
raw_frame.process = trace->process;
for (DN_USize index = skip; index < trace->size; index++) {
raw_frame.base_addr = trace->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_Str8BuilderAppendF(builder, "%.*s(%zu): %.*s%s", DN_Str8PrintFmt(frame.file_name), frame.line_number, DN_Str8PrintFmt(frame.function_name), (DN_Cast(int) index == trace->size - 1) ? "" : "\n");
}
}
DN_API bool DN_StackTraceWalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk)
DN_API bool DN_StackTraceIterate(DN_StackTraceIterator *it, DN_StackTrace const *trace)
{
bool result = false;
if (!it || !walk || !walk->base_addr || !walk->process)
if (!it || !trace || !trace->base_addr || !trace->process)
return result;
if (it->index >= walk->size)
if (it->index >= trace->size)
return false;
result = true;
it->raw_frame.process = walk->process;
it->raw_frame.base_addr = walk->base_addr[it->index++];
it->raw_frame.process = trace->process;
it->raw_frame.base_addr = trace->base_addr[it->index++];
return result;
}
DN_API DN_Str8 DN_StackTraceWalkResultToStr8(DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip)
DN_API DN_Str8 DN_Str8FromStackTraceAllocator(DN_Allocator allocator, DN_StackTrace const *trace, DN_U16 skip)
{
DN_Str8 result{};
if (!walk || !arena)
DN_Str8 result = {};
if (!trace)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginAllocator(&allocator, 1);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_StackTraceAddWalkToStr8Builder(walk, &builder, skip);
result = DN_Str8BuilderBuild(&builder, arena);
DN_StackTraceAddToStr8Builder_(trace, &builder, skip);
result = DN_Str8FromStr8BuilderAllocator(&builder, allocator);
DN_TCScratchEnd(&scratch);
return result;
}
DN_API DN_Str8 DN_StackTraceWalkStr8(DN_Arena *arena, DN_U16 limit, DN_U16 skip)
DN_API DN_Str8 DN_Str8FromStackTraceArena(DN_Arena *arena, DN_StackTrace const *trace, DN_U16 skip)
{
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&scratch.arena, limit);
DN_Str8 result = DN_StackTraceWalkResultToStr8(arena, &walk, skip);
DN_Str8 result = {};
if (!trace || !arena)
return result;
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_StackTraceAddToStr8Builder_(trace, &builder, skip);
result = DN_Str8FromStr8BuilderArena(&builder, arena);
DN_TCScratchEnd(&scratch);
return result;
}
DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap(DN_U16 limit, DN_U16 skip)
DN_API DN_Str8 DN_Str8FromStackTraceNowAllocator(DN_Allocator allocator, DN_U16 limit, DN_U16 skip)
{
// NOTE: We don't use WalkResultToStr8 because that uses the TLS arenas which
// does not use the OS heap.
DN_MemList mem = DN_MemListFromHeap(DN_Kilobytes(64), DN_MemFlags_NoAllocTrack);
DN_Arena arena = DN_ArenaFromMemList(&mem);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&arena);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&arena, limit);
DN_StackTraceAddWalkToStr8Builder(&walk, &builder, skip);
DN_TCScratch scratch = DN_TCScratchBeginArena(DN_Cast(DN_Arena **) & allocator.context, 1);
DN_StackTrace walk = DN_StackTraceFromArena(&scratch.arena, limit);
DN_Str8 result = DN_Str8FromStackTraceAllocator(allocator, &walk, skip);
DN_TCScratchEnd(&scratch);
return result;
}
DN_API DN_Str8 DN_Str8FromStackTraceNowArena(DN_Arena *arena, DN_U16 limit, DN_U16 skip)
{
DN_Str8 result = DN_Str8FromStackTraceNowAllocator(DN_AllocatorFromArena(arena), limit, skip);
return result;
}
DN_API DN_Str8 DN_Str8FromStackTraceNowHeap(DN_U16 limit, DN_U16 skip)
{
DN_Arena arena = DN_ArenaFromHeap(DN_Kilobytes(64), DN_MemFlags_NoAllocTrack);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&arena);
DN_StackTrace walk = DN_StackTraceFromArena(&arena, limit);
DN_StackTraceAddToStr8Builder_(&walk, &builder, skip);
DN_Str8 result = DN_Str8BuilderBuildFromHeap(&builder);
DN_MemListDeinit(&mem);
DN_ArenaDeinit(&arena);
return result;
}
@@ -1319,12 +1368,12 @@ DN_API DN_StackTraceFrameSlice DN_StackTraceGetFrames(DN_Arena *arena, DN_U16 li
if (!arena)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_StackTraceWalkResult walk = DN_StackTraceWalk(&scratch.arena, limit);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_StackTrace walk = DN_StackTraceFromArena(&scratch.arena, limit);
if (walk.size) {
if (DN_ISliceAllocArena(&result, walk.size, DN_ZMem_No, arena)) {
DN_USize slice_index = 0;
for (DN_StackTraceWalkResultIterator it = {}; DN_StackTraceWalkResultIterate(&it, &walk);)
for (DN_StackTraceIterator it = {}; DN_StackTraceIterate(&it, &walk);)
result.data[slice_index++] = DN_StackTraceRawFrameToFrame(arena, it.raw_frame);
}
}
@@ -1381,7 +1430,7 @@ DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame(DN_Arena *arena, DN_Stack
DN_API void DN_StackTracePrint(DN_U16 limit)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_StackTraceFrameSlice stack_trace = DN_StackTraceGetFrames(&scratch.arena, limit);
for (DN_ForItSize(it, DN_StackTraceFrame, stack_trace.data, stack_trace.count)) {
DN_StackTraceFrame frame = *it.data;
+2 -1
View File
@@ -297,7 +297,8 @@ DN_API DN_MemFuncs DN_MemFuncsFromType (D
DN_API DN_MemFuncs DN_MemFuncsDefault ();
DN_API DN_MemList DN_MemListFromHeap (DN_U64 size, DN_MemFlags flags);
DN_API DN_MemList DN_MemListFromVMem (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags);
DN_API DN_Arena DN_ArenaFromHeap (DN_U64 wize, DN_MemFlags flags);
DN_API DN_Arena DN_ArenaFromVMem (DN_U64 reserve, DN_U64 commit, DN_MemFlags 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);
+30 -30
View File
@@ -209,7 +209,7 @@ DN_API void DN_OS_GenBytesSecure(void *buffer, DN_U32 size)
DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_OSDiskSpace result = {};
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
@@ -233,7 +233,7 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value)
{
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 name16 = DN_OS_W32Str8ToStr16(&scratch.arena, name);
DN_Str16 value16 = DN_OS_W32Str8ToStr16(&scratch.arena, value);
bool result = SetEnvironmentVariableW(name16.data, value16.data) != 0;
@@ -246,7 +246,7 @@ DN_API DN_Str8 DN_OS_EXEPath(DN_Arena *arena)
DN_Str8 result = {};
if (!arena)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(&scratch.arena);
result = DN_OS_W32Str16ToStr8(arena, exe_dir16);
DN_TCScratchEnd(&scratch);
@@ -286,7 +286,7 @@ static DN_U64 DN_OS_W32FileTimeToSeconds_(FILETIME const *time)
DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err)
{
bool result = false;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 src16 = DN_OS_W32Str8ToStr16(&scratch.arena, src);
DN_Str16 dest16 = DN_OS_W32Str8ToStr16(&scratch.arena, dest);
@@ -310,7 +310,7 @@ DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink
DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err)
{
bool result = false;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 src16 = DN_OS_W32Str8ToStr16(&scratch.arena, src);
DN_Str16 dest16 = DN_OS_W32Str8ToStr16(&scratch.arena, dest);
@@ -366,7 +366,7 @@ DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFile
access_mode |= GENERIC_EXECUTE;
}
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
void *handle = CreateFileW(/*LPCWSTR lpFileName*/ path16.data,
/*DWORD dwDesiredAccess*/ access_mode,
@@ -395,9 +395,9 @@ DN_API DN_OSFileRead DN_OS_FileRead(DN_OSFile *file, void *buffer, DN_USize size
if (!file || !file->handle || file->error || !buffer || size <= 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
if (!DN_Check(size <= (unsigned long)-1)) {
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
DN_Str8x32 buffer_size_str8 = DN_Str8x32FromByteCountU64Auto(size);
DN_ErrSinkAppendF(
err,
1 /*error_code*/,
@@ -455,9 +455,9 @@ DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *buffer, DN_USize siz
}
if (!result) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_Str8x32 buffer_size_str8 = DN_ByteCountStr8x32(size);
DN_Str8x32 buffer_size_str8 = DN_Str8x32FromByteCountU64Auto(size);
DN_ErrSinkAppendF(err, win_error.code, "Failed to write buffer (%.*s) to file handle: %.*s", DN_Str8PrintFmt(buffer_size_str8), DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch);
}
@@ -471,7 +471,7 @@ DN_API bool DN_OS_FileFlush(DN_OSFile *file, DN_ErrSink *err)
BOOL result = FlushFileBuffers(DN_Cast(HANDLE) file->handle);
if (!result) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
DN_ErrSinkAppendF(err, win_error.code, "Failed to flush file buffer to disk: %.*s", DN_Str8PrintFmt(win_error.msg));
DN_TCScratchEnd(&scratch);
@@ -494,7 +494,7 @@ DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path)
if (path.size == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
@@ -530,7 +530,7 @@ DN_API bool DN_OS_PathDelete(DN_Str8 path)
if (path.size == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) {
result = DeleteFileW(path16.data);
@@ -547,7 +547,7 @@ DN_API bool DN_OS_PathIsFile(DN_Str8 path)
if (path.size == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) {
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
@@ -565,7 +565,7 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
if (path.size == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
if (path16.size) {
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {};
@@ -581,7 +581,7 @@ DN_API bool DN_OS_PathIsDir(DN_Str8 path)
DN_API bool DN_OS_PathMakeDir(DN_Str8 path)
{
bool result = true;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
// NOTE: Go back from the end of the string to all the directories in the
@@ -636,7 +636,7 @@ DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it)
if (path.size == 0 || !it || path.size <= 0)
return false;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_OSW32FolderIteratorW wide_it = {};
DN_Str16 path16 = {};
if (it->handle) {
@@ -716,7 +716,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
return result;
}
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DWORD stdout_bytes_available = 0;
DWORD stderr_bytes_available = 0;
PeekNamedPipe(handle.stdout_read, nullptr, 0, nullptr, &stdout_bytes_available, nullptr);
@@ -822,7 +822,7 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *are
return result;
}
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str8Builder stdout_builder = {};
DN_Str8Builder stderr_builder = {};
if (arena) {
@@ -845,8 +845,8 @@ DN_API DN_OSExecResult DN_OS_ExecWait(DN_OSExecAsyncHandle handle, DN_Arena *are
}
// NOTE: Get stdout/stderr. If no arena is passed this is a no-op
result.stdout_text = DN_Str8BuilderBuild(&stdout_builder, arena);
result.stderr_text = DN_Str8BuilderBuild(&stderr_builder, arena);
result.stdout_text = DN_Str8FromStr8BuilderArena(&stdout_builder, arena);
result.stderr_text = DN_Str8FromStr8BuilderArena(&stderr_builder, arena);
DN_TCScratchEnd(&scratch);
return result;
}
@@ -858,7 +858,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
if (cmd_line.count == 0)
return result;
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8 cmd_rendered = DN_Str8SliceRender(cmd_line, DN_Str8Lit(" "), &scratch.arena);
DN_Str16 cmd16 = DN_OS_W32Str8ToStr16(&scratch.arena, cmd_rendered);
DN_Str16 working_dir16 = DN_OS_W32Str8ToStr16(&scratch.arena, args->working_dir);
@@ -868,7 +868,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
if (env_builder.string_size)
DN_Str8BuilderAppendRef(&env_builder, DN_Str8Lit("\0"));
DN_Str8 env_block8 = DN_Str8BuilderBuildDelimited(&env_builder, DN_Str8Lit("\0"), &scratch.arena);
DN_Str8 env_block8 = DN_Str8FromStr8BuilderDelimitArena(&env_builder, DN_Str8Lit("\0"), &scratch.arena);
DN_Str16 env_block16 = {};
if (env_block8.size)
env_block16 = DN_OS_W32Str8ToStr16(&scratch.arena, env_block8);
@@ -1305,7 +1305,7 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
//
// See: https://learn.microsoft.com/en-us/windows/w32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
DN_OSW32Core *w32 = DN_OS_W32GetCore();
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
if (w32->set_thread_description) {
DN_Str16 name16 = DN_OS_W32Str8ToStr16(&scratch.arena, name);
w32->set_thread_description(GetCurrentThread(), (WCHAR *)name16.data);
@@ -1420,7 +1420,7 @@ void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD d
if (request) {
bool read_complete = dwInternetStatus == WINHTTP_CALLBACK_STATUS_READ_COMPLETE && dwStatusInformationLength == 0;
if (read_complete)
response->body = DN_Str8BuilderBuild(&response->builder, response->arena);
response->body = DN_Str8FromStr8BuilderArena(&response->builder, response->arena);
if (read_complete || dwInternetStatus == WINHTTP_CALLBACK_STATUS_REQUEST_ERROR || error.code) {
DN_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1);
@@ -1449,7 +1449,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
response->arena = arena;
response->builder = DN_Str8BuilderFromArena(response->scratch_arena.mem ? &response->scratch_arena : &response->tmp_arena);
DN_TCScratch scratch_ = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch_ = DN_TCScratchBeginArena(&arena, 1);
if (!response->scratch_arena.mem)
response->scratch_arena = scratch_.arena;
@@ -1743,7 +1743,7 @@ DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap(DN_Str16 src)
// NOTE: Windows Executable Directory //////////////////////////////////////////
DN_API DN_Str16 DN_OS_W32EXEPathW(DN_Arena *arena)
{
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str16 result = {};
DN_USize module_size = 0;
wchar_t *module_path = nullptr;
@@ -1772,7 +1772,7 @@ DN_API DN_Str16 DN_OS_W32EXEPathW(DN_Arena *arena)
DN_API DN_Str16 DN_OS_W32EXEDirW(DN_Arena *arena)
{
// TODO(doyle): Implement a DN_Str16_BinarySearchReverse
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str16 result = {};
DN_USize module_size = 0;
wchar_t *module_path = nullptr;
@@ -1800,7 +1800,7 @@ DN_API DN_Str16 DN_OS_W32EXEDirW(DN_Arena *arena)
DN_API DN_Str8 DN_OS_W32WorkingDir(DN_Arena *arena, DN_Str8 suffix)
{
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
DN_Str16 suffix16 = DN_OS_W32Str8ToStr16(&scratch.arena, suffix);
DN_Str16 dir16 = DN_OS_W32WorkingDirW(&scratch.arena, suffix16);
DN_Str8 result = DN_OS_W32Str16ToStr8(arena, dir16);
@@ -1814,7 +1814,7 @@ DN_API DN_Str16 DN_OS_W32WorkingDirW(DN_Arena *arena, DN_Str16 suffix)
DN_Str16 result = {};
// NOTE: required_size is the size required *including* the null-terminator
DN_TCScratch scratch = DN_TCScratchBegin(&arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
unsigned long required_size = GetCurrentDirectoryW(0, nullptr);
unsigned long desired_size = required_size + DN_Cast(unsigned long) suffix.size;
+14 -21
View File
@@ -20,7 +20,7 @@ DN_Core *g_dn_;
#endif
#endif
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_TCInitArgs args)
{
DN_Set(dn);
dn->init_flags = flags;
@@ -106,8 +106,7 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
if (DN_BitIsSet(flags, DN_InitFlags_ThreadContext)) {
DN_Assert(dn->os_init);
#if DN_H_WITH_OS
DN_TCInitArgs *tc_init_args = args ? &args->thread_context_init_args : nullptr;
DN_TCInitFromMemFuncs(&dn->main_tc, DN_OS_ThreadID(), tc_init_args, DN_MemFuncsDefault());
DN_TCInitFromMemFuncs(&dn->main_tc, DN_OS_ThreadID(), args, DN_MemFuncsDefault());
DN_TCEquip(&dn->main_tc);
#endif
}
@@ -139,24 +138,18 @@ DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
case DN_MemFuncsType_Heap: mem_funcs = DN_Str8Lit("Heap"); break;
case DN_MemFuncsType_Virtual: mem_funcs = DN_Str8Lit("Virtual"); break;
}
DN_Str8x32 main_commit = DN_ByteCountStr8x32(dn->main_tc.main_arena->mem->curr->commit);
DN_Str8x32 main_reserve = DN_ByteCountStr8x32(dn->main_tc.main_arena->mem->curr->reserve);
DN_Str8x32 temp_commit = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->mem->curr->commit);
DN_Str8x32 temp_reserve = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->mem->curr->reserve);
DN_Str8x32 err_commit = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->mem->curr->commit);
DN_Str8x32 err_reserve = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->mem->curr->reserve);
DN_FmtAppendTruncate(buf,
&buf_size,
sizeof(buf),
DN_Str8Lit("..."),
"M %.*s/%.*s S(x2) %.*s/%.*s E %.*s/%.*s (%.*s)\n",
DN_Str8PrintFmt(main_commit),
DN_Str8PrintFmt(main_reserve),
DN_Str8PrintFmt(temp_commit),
DN_Str8PrintFmt(temp_reserve),
DN_Str8PrintFmt(err_commit),
DN_Str8PrintFmt(err_reserve),
DN_Str8PrintFmt(mem_funcs));
DN_Str8x32 main_commit = DN_Str8x32FromByteCountU64Auto(dn->main_tc.main_arena->mem->curr->commit);
DN_Str8x32 main_reserve = DN_Str8x32FromByteCountU64Auto(dn->main_tc.main_arena->mem->curr->reserve);
DN_Str8x32 err_commit = DN_Str8x32FromByteCountU64Auto(dn->main_tc.err_sink.arena->mem->curr->commit);
DN_Str8x32 err_reserve = DN_Str8x32FromByteCountU64Auto(dn->main_tc.err_sink.arena->mem->curr->reserve);
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), "M %.*s/%.*s", DN_Str8PrintFmt(main_commit), DN_Str8PrintFmt(main_reserve));
if (dn->main_tc.temp_arenas_count) {
DN_Arena *temp = dn->main_tc.temp_arenas[0];
DN_Str8x32 temp_commit = DN_Str8x32FromByteCountU64Auto(temp->mem->curr->commit);
DN_Str8x32 temp_reserve = DN_Str8x32FromByteCountU64Auto(temp->mem->curr->reserve);
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " T(x%zu) %.*s/%.*s", dn->main_tc.temp_arenas_count, DN_Str8PrintFmt(temp_commit), DN_Str8PrintFmt(temp_reserve));
}
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " E %.*s/%.*s (%.*s)\n", DN_Str8PrintFmt(err_commit), DN_Str8PrintFmt(err_reserve), DN_Str8PrintFmt(mem_funcs));
} else {
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), "N/A\n");
}
+1 -8
View File
@@ -143,8 +143,6 @@
// occurs.
#include "Base/dn_base.h"
#include "Base/dn_base_assert.h"
#include "Base/dn_base_containers.h"
#include "Base/dn_base_leak.h"
#if DN_H_WITH_OS
@@ -159,11 +157,6 @@
#include "OS/dn_os.h"
#endif
struct DN_InitArgs
{
DN_TCInitArgs thread_context_init_args;
};
typedef DN_USize DN_InitFlags;
enum DN_InitFlags_
{
@@ -193,7 +186,7 @@ struct DN_Core
#endif
};
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_TCInitArgs args);
DN_API void DN_Set (DN_Core *dn);
DN_API DN_Core *DN_Get ();
DN_API void DN_BeginFrame();
+4 -4
View File
@@ -29,7 +29,7 @@ struct File
static void AppendCppFileLineByLine(DN_Str8Builder *dest, DN_Str8 cpp_path)
{
DN_TCScratch scratch = DN_TCScratchBegin(&dest->arena, 1);
DN_TCScratch scratch = DN_TCScratchBeginArena(&dest->arena, 1);
DN_ErrSink *err = DN_TCErrSinkBeginDefault();
DN_Str8 buffer = DN_OS_FileReadAllArena(&scratch.arena, cpp_path, err);
DN_ErrSinkEndExitIfErrorF(err, -1, "Failed to load file from '%S' for appending", cpp_path);
@@ -93,7 +93,7 @@ static void AppendCppFileLineByLine(DN_Str8Builder *dest, DN_Str8 cpp_path)
int main(int argc, char **argv)
{
DN_Core dn = {};
DN_Init(&dn, DN_InitFlags_OS | DN_InitFlags_ThreadContext, nullptr);
DN_Init(&dn, DN_InitFlags_OS | DN_InitFlags_ThreadContext, DN_TCInitArgsDefault());
if (argc != 3) {
DN_OS_PrintErrF("USAGE: %s <path/to/dn/Source> <output_dir>", argv[0]);
@@ -114,7 +114,7 @@ int main(int argc, char **argv)
};
for (DN_ForIndexU(type, FileType_Count)) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_TCScratch scratch = DN_TCScratchBeginArena(nullptr, 0);
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
DN_Str8 suffix = type == FileType_Header ? DN_Str8Lit("h") : DN_Str8Lit("cpp");
for (DN_ForItCArray(it, DN_Str8 const, REL_FILE_PATHS)) {
@@ -125,7 +125,7 @@ int main(int argc, char **argv)
DN_Date date = DN_OS_DateLocalTimeNow();
DN_Str8BuilderPrependF(&builder, "// Generated by the DN single header generator %04u-%02u-%02u %02u:%02u:%02u\n\n", date.year, date.month, date.day, date.hour, date.minutes, date.seconds);
DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8BuilderBuild(&builder, &scratch.arena));
DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8FromStr8BuilderArena(&builder, &scratch.arena));
DN_Str8 single_header_path = DN_OS_PathF(&scratch.arena, "%S/dn_single_header.%S", output_dir, suffix);
DN_ErrSink *err = DN_TCErrSinkBeginDefault();
DN_OS_FileWriteAllSafe(single_header_path, buffer, err);