#define DN_OS_CONTAINERS_CPP /* //////////////////////////////////////////////////////////////////////////////////////////////////// // // $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$$\ $$$$$$\ // $$ __$$\ $$ __$$\ $$$\ $$ |\__$$ __|$$ __$$\ \_$$ _|$$$\ $$ |$$ _____|$$ __$$\ $$ __$$\ // $$ / \__|$$ / $$ |$$$$\ $$ | $$ | $$ / $$ | $$ | $$$$\ $$ |$$ | $$ | $$ |$$ / \__| // $$ | $$ | $$ |$$ $$\$$ | $$ | $$$$$$$$ | $$ | $$ $$\$$ |$$$$$\ $$$$$$$ |\$$$$$$\ // $$ | $$ | $$ |$$ \$$$$ | $$ | $$ __$$ | $$ | $$ \$$$$ |$$ __| $$ __$$< \____$$\ // $$ | $$\ $$ | $$ |$$ |\$$$ | $$ | $$ | $$ | $$ | $$ |\$$$ |$$ | $$ | $$ |$$\ $$ | // \$$$$$$ | $$$$$$ |$$ | \$$ | $$ | $$ | $$ |$$$$$$\ $$ | \$$ |$$$$$$$$\ $$ | $$ |\$$$$$$ | // \______/ \______/ \__| \__| \__| \__| \__|\______|\__| \__|\________|\__| \__| \______/ // // dn_containers.cpp // //////////////////////////////////////////////////////////////////////////////////////////////////// */ // NOTE: DN_VArray ///////////////////////////////////////////////////////////////////////////////// template DN_VArray DN_VArray_InitByteSize(DN_USize byte_size) { DN_VArray 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 DN_VArray DN_VArray_Init(DN_USize max) { DN_VArray result = DN_VArray_InitByteSize(max * sizeof(T)); DN_Assert(result.max >= max); return result; } template DN_VArray DN_VArray_InitSlice(DN_Slice slice, DN_USize max) { DN_USize real_max = DN_Max(slice.size, max); DN_VArray result = DN_VArray_Init(real_max); if (DN_VArray_IsValid(&result)) DN_VArray_AddArray(&result, slice.data, slice.size); return result; } template DN_VArray DN_VArray_InitCArray(T const (&items)[N], DN_USize max) { DN_USize real_max = DN_Max(N, max); DN_VArray result = DN_VArray_InitSlice(DN_Slice_Init(items, N), real_max); return result; } template void DN_VArray_Deinit(DN_VArray *array) { DN_OS_MemRelease(array->data, array->max * sizeof(T)); *array = {}; } template bool DN_VArray_IsValid(DN_VArray const *array) { bool result = array->data && array->size <= array->max; return result; } template DN_Slice DN_VArray_Slice(DN_VArray const *array) { DN_Slice result = {}; if (array) result = DN_Slice_Init(array->data, array->size); return result; } template T *DN_VArray_AddArray(DN_VArray *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 T *DN_VArray_AddCArray(DN_VArray *array, T const (&items)[N]) { T *result = DN_VArray_AddArray(array, items, N); return result; } template T *DN_VArray_Add(DN_VArray *array, T const &item) { T *result = DN_VArray_AddArray(array, &item, 1); return result; } template T *DN_VArray_MakeArray(DN_VArray *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 T *DN_VArray_Make(DN_VArray *array, DN_ZeroMem zero_mem) { T *result = DN_VArray_MakeArray(array, 1, zero_mem); return result; } template T *DN_VArray_InsertArray(DN_VArray *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 T *DN_VArray_InsertCArray(DN_VArray *array, DN_USize index, T const (&items)[N]) { T *result = DN_VArray_InsertArray(array, index, items, N); return result; } template T *DN_VArray_Insert(DN_VArray *array, DN_USize index, T const &item) { T *result = DN_VArray_InsertArray(array, index, &item, 1); return result; } template T *DN_VArray_PopFront(DN_VArray *array, DN_USize count) { T *result = DN_CArray_PopFront(array->data, &array->size, count); return result; } template T *DN_VArray_PopBack(DN_VArray *array, DN_USize count) { T *result = DN_CArray_PopBack(array->data, &array->size, count); return result; } template DN_ArrayEraseResult DN_VArray_EraseRange(DN_VArray *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(array->data, &array->size, begin_index, count, erase); return result; } template void DN_VArray_Clear(DN_VArray *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 bool DN_VArray_Reserve(DN_VArray *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; }