Dqn/OS/dn_os_containers.cpp
2025-05-12 17:09:03 +10:00

203 lines
6.0 KiB
C++

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