Introduce new intrusive container macros
This commit is contained in:
parent
1720cae8db
commit
a01b773655
@ -2,6 +2,94 @@
|
|||||||
|
|
||||||
#include "../dn_base_inc.h"
|
#include "../dn_base_inc.h"
|
||||||
|
|
||||||
|
DN_API void *DN_CArray2_MakeArray(void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZeroMem zero_mem)
|
||||||
|
{
|
||||||
|
void *result = nullptr;
|
||||||
|
DN_USize new_size = *size + make_size;
|
||||||
|
if (new_size <= max) {
|
||||||
|
result = DN_CAST(char *) data + (data_size * size[0]);
|
||||||
|
*size = new_size;
|
||||||
|
if (zero_mem == DN_ZeroMem_Yes)
|
||||||
|
DN_Memset(result, 0, data_size * make_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API bool DN_CArray2_GrowIfNeededFromPool(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
if (size >= *max) {
|
||||||
|
DN_USize new_max = DN_Max(*max * 2, 8);
|
||||||
|
DN_USize bytes_to_alloc = data_size * new_max;
|
||||||
|
void *buffer = DN_Pool_NewArray(pool, DN_U8, bytes_to_alloc);
|
||||||
|
if (buffer) {
|
||||||
|
DN_USize bytes_to_copy = data_size * size;
|
||||||
|
DN_Memcpy(buffer, *data, bytes_to_copy);
|
||||||
|
DN_Pool_Dealloc(pool, *data);
|
||||||
|
*data = buffer;
|
||||||
|
*max = new_max;
|
||||||
|
} else {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_ArrayEraseResult DN_CArray2_EraseRange(void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase)
|
||||||
|
{
|
||||||
|
DN_ArrayEraseResult result = {};
|
||||||
|
if (!data || !size || *size == 0 || count == 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Compute the range to erase
|
||||||
|
DN_USize start = 0, end = 0;
|
||||||
|
if (count < 0) {
|
||||||
|
DN_USize abs_count = DN_Abs(count);
|
||||||
|
start = begin_index >= abs_count ? begin_index - abs_count + 1 : 0;
|
||||||
|
end = begin_index >= abs_count ? begin_index + 1 : 0;
|
||||||
|
} else {
|
||||||
|
start = begin_index;
|
||||||
|
end = begin_index + count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp indices to valid bounds
|
||||||
|
start = DN_Min(start, *size);
|
||||||
|
end = DN_Min(end, *size);
|
||||||
|
|
||||||
|
// Erase the range [start, end)
|
||||||
|
DN_USize erase_count = end > start ? end - start : 0;
|
||||||
|
if (erase_count) {
|
||||||
|
char *dest = (char *)data + (elem_size * start);
|
||||||
|
char *array_end = (char *)data + (elem_size * *size);
|
||||||
|
char *src = dest + (elem_size * erase_count);
|
||||||
|
if (erase == DN_ArrayErase_Stable) {
|
||||||
|
DN_USize move_size = array_end - src;
|
||||||
|
DN_Memmove(dest, src, move_size);
|
||||||
|
} else {
|
||||||
|
char *unstable_src = array_end - (elem_size * erase_count);
|
||||||
|
DN_USize move_size = array_end - unstable_src;
|
||||||
|
DN_Memcpy(dest, unstable_src, move_size);
|
||||||
|
}
|
||||||
|
*size -= erase_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.items_erased = erase_count;
|
||||||
|
result.it_index = start;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API void *DN_CSLList_Detach(void **link, void **next)
|
||||||
|
{
|
||||||
|
void *result = *link;
|
||||||
|
if (*link) {
|
||||||
|
*link = *next;
|
||||||
|
*next = nullptr;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
DN_API bool DN_Ring_HasSpace(DN_Ring const *ring, DN_U64 size)
|
DN_API bool DN_Ring_HasSpace(DN_Ring const *ring, DN_U64 size)
|
||||||
{
|
{
|
||||||
DN_U64 avail = ring->write_pos - ring->read_pos;
|
DN_U64 avail = ring->write_pos - ring->read_pos;
|
||||||
|
@ -159,6 +159,64 @@ template <typename T> struct DN_List
|
|||||||
};
|
};
|
||||||
#endif // !defined(DN_NO_LIST)
|
#endif // !defined(DN_NO_LIST)
|
||||||
|
|
||||||
|
// NOTE: Macros for operating on data structures that are embedded into a C style struct or from a
|
||||||
|
// set of defined variables from the available scope. Keep it stupid simple, structs and functions.
|
||||||
|
// Minimal amount of container types with flexible construction leads to less duplicated container
|
||||||
|
// code and less template meta-programming.
|
||||||
|
//
|
||||||
|
// LArray => Literal Array
|
||||||
|
// Define a C array and size:
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// MyStruct buffer[TB_ASType_Count] = {};
|
||||||
|
// DN_USize size = 0;
|
||||||
|
// MyStruct *item = DN_LArray_Make(buffer, size, DN_ArrayCountU(buffer), DN_ZeroMem_No);
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// IArray => Intrusive Array
|
||||||
|
// Define a struct with the members 'data', 'size' and 'max':
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// struct MyArray {
|
||||||
|
// MyStruct *data;
|
||||||
|
// DN_USize size;
|
||||||
|
// DN_USize max;
|
||||||
|
// } my_array = {};
|
||||||
|
//
|
||||||
|
// MyStruct *item = DN_IArray_Make(&my_array, MyArray, DN_ZeroMem_No);
|
||||||
|
// ```
|
||||||
|
// ISLList => Intrusive Singly Linked List
|
||||||
|
// Define a struct with the members 'next':
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// struct MyLinkItem {
|
||||||
|
// int data;
|
||||||
|
// MyLinkItem *next;
|
||||||
|
// } my_link = {};
|
||||||
|
//
|
||||||
|
// MyLinkItem *first_item = DN_ISLList_Detach(&my_link, MyLinkItem);
|
||||||
|
// ```
|
||||||
|
|
||||||
|
#define DN_ISLList_Detach(list) (decltype(list)) DN_CSLList_Detach((void **)&(list), (void **)&(list)->next)
|
||||||
|
|
||||||
|
#define DN_LArray_MakeArray(c_array, size, max, count, zero_mem) (decltype(&(c_array)[0])) DN_CArray2_MakeArray(c_array, size, max, sizeof(c_array[0]), count, zero_mem)
|
||||||
|
#define DN_LArray_MakeArrayZ(c_array, size, max, count) DN_LArray_MakeArray(c_array, size, max, count, DN_ZeroMem_Yes)
|
||||||
|
#define DN_LArray_Make(c_array, size, max, zero_mem) DN_LArray_MakeArray(c_array, size, max, 1, zero_mem)
|
||||||
|
#define DN_LArray_MakeZ(c_array, size, max) DN_LArray_Make(c_array, size, max, DN_ZeroMem_Yes)
|
||||||
|
|
||||||
|
#define DN_IArray_Front(array) (array)->data
|
||||||
|
#define DN_IArray_GrowIfNeededFromPool(array, pool) DN_CArray2_GrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool)
|
||||||
|
#define DN_IArray_MakeArray(array, count, zero_mem) DN_LArray_MakeArray((array)->data, &(array)->size, (array)->max, count, zero_mem)
|
||||||
|
#define DN_IArray_MakeArrayZ(array, count) DN_LArray_MakeArray(array, count, DN_ZeroMem_Yes)
|
||||||
|
#define DN_IArray_Make(array, zero_mem) DN_IArray_MakeArray(array, 1, zero_mem)
|
||||||
|
#define DN_IArray_MakeZ(array) DN_IArray_Make(array, DN_ZeroMem_Yes)
|
||||||
|
|
||||||
|
|
||||||
|
DN_API DN_ArrayEraseResult DN_CArray2_EraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
|
||||||
|
DN_API void *DN_CArray2_MakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZeroMem zero_mem);
|
||||||
|
DN_API bool DN_CArray2_GrowIfNeededFromPool(void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool);
|
||||||
|
DN_API void *DN_CSLList_Detach (void **link, void **next);
|
||||||
|
|
||||||
DN_API bool DN_Ring_HasSpace (DN_Ring const *ring, DN_U64 size);
|
DN_API bool DN_Ring_HasSpace (DN_Ring const *ring, DN_U64 size);
|
||||||
DN_API bool DN_Ring_HasData (DN_Ring const *ring, DN_U64 size);
|
DN_API bool DN_Ring_HasData (DN_Ring const *ring, DN_U64 size);
|
||||||
DN_API void DN_Ring_Write (DN_Ring *ring, void const *src, DN_U64 src_size);
|
DN_API void DN_Ring_Write (DN_Ring *ring, void const *src, DN_U64 src_size);
|
||||||
|
1102
Extra/dn_tests.cpp
1102
Extra/dn_tests.cpp
File diff suppressed because it is too large
Load Diff
@ -124,13 +124,13 @@ DN_API DN_Arena *DN_OS_TLSTopArena()
|
|||||||
|
|
||||||
DN_API void DN_OS_TLSBeginFrame(DN_Arena *frame_arena)
|
DN_API void DN_OS_TLSBeginFrame(DN_Arena *frame_arena)
|
||||||
{
|
{
|
||||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||||
tls->frame_arena = frame_arena;
|
tls->frame_arena = frame_arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Arena *DN_OS_TLSFrameArena()
|
DN_API DN_Arena *DN_OS_TLSFrameArena()
|
||||||
{
|
{
|
||||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||||
DN_Arena *result = tls->frame_arena;
|
DN_Arena *result = tls->frame_arena;
|
||||||
DN_AssertF(result, "Frame arena must be set by calling DN_OS_TLSBeginFrame at the beginning of the frame");
|
DN_AssertF(result, "Frame arena must be set by calling DN_OS_TLSBeginFrame at the beginning of the frame");
|
||||||
return result;
|
return result;
|
||||||
|
@ -79,10 +79,10 @@
|
|||||||
|
|
||||||
#define DN_UT_COLOR_RESET "\x1b[0m"
|
#define DN_UT_COLOR_RESET "\x1b[0m"
|
||||||
|
|
||||||
#define DN_UT_Test(test, fmt, ...) \
|
#define DN_UT_Test(test, fmt, ...) \
|
||||||
for (int dummy_ = (DN_UT_BeginF((test), fmt, ##__VA_ARGS__), 0); \
|
int dummy_ = (DN_UT_BeginF((test), fmt, ##__VA_ARGS__), 0); \
|
||||||
(void)dummy_, (test)->state == DN_UTState_TestBegun; \
|
(void)dummy_, (test)->state == DN_UTState_TestBegun; \
|
||||||
DN_UT_End(test))
|
DN_UT_End(test)
|
||||||
|
|
||||||
#define DN_UT_AssertF(test, expr, fmt, ...) \
|
#define DN_UT_AssertF(test, expr, fmt, ...) \
|
||||||
DN_UT_AssertAtF((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__)
|
DN_UT_AssertAtF((test), __FILE__, __LINE__, (expr), fmt, ##__VA_ARGS__)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user