Switch darray implementation to C++ with templates

This commit is contained in:
Doyle Thai 2017-04-11 21:05:40 +10:00
parent 9106f185a3
commit e0cae3029d
3 changed files with 248 additions and 408 deletions

View File

@ -34,7 +34,7 @@ REM wd4100 ignore: unused argument parameters
REM wd4201 ignore: nonstandard extension used: nameless struct/union REM wd4201 ignore: nonstandard extension used: nameless struct/union
REM wd4189 ignore: local variable is initialised but not referenced REM wd4189 ignore: local variable is initialised but not referenced
set CompileFlags=-EHa- -GR- -Oi -MT -Z7 -W4 -WX -wd4100 -wd4201 -wd4189 -FC -O2 set CompileFlags=-EHa- -GR- -Oi -MT -Z7 -W4 -WX -wd4100 -wd4201 -wd4189 -FC -Od
REM Include directories REM Include directories
set IncludeFlags= set IncludeFlags=

392
dqn.h
View File

@ -20,6 +20,11 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "stdint.h" #include "stdint.h"
#include "math.h" #include "math.h"
#define STB_SPRINTF_IMPLEMENTATION
#ifdef _WIN32
#define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK);
#endif
#define LOCAL_PERSIST static #define LOCAL_PERSIST static
#define FILE_SCOPE static #define FILE_SCOPE static
@ -51,88 +56,31 @@ typedef float f32;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// DArray - Dynamic Array // DArray - Dynamic Array
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// The DArray stores metadata in the header and returns you a pointer straight template <typename T>
// to the data, to allow direct read/modify access. Adding elements should be struct DqnArray
// done using the provided functions since it manages internal state.
/*
Example Usage:
uint32_t *uintArray = DQN_DARRAY_INIT(uint32_t, 16);
uint32_t numberA = 48;
uint32_t numberB = 52;
DQN_DARRAY_PUSH(&uintArray, &numberA);
DQN_DARRAY_PUSH(&uintArray, &numberB);
for (uint32_t i = 0; i < dqn_darray_get_num_items(uintArray); i++)
{ {
printf(%d\n", uintArray[i]); u64 count;
} u64 capacity;
T *data;
};
dqn_darray_free(uintArray); template <typename T>
*/ bool dqn_darray_init (DqnArray<T> *array, size_t capacity);
template <typename T>
bool dqn_darray_grow (DqnArray<T> *array);
template <typename T>
bool dqn_darray_push(DqnArray<T> *array, T item);
template <typename T>
T *dqn_darray_get (DqnArray<T> *array, u64 index);
template <typename T>
bool dqn_darray_clear(DqnArray<T> *array);
template <typename T>
bool dqn_darray_free (DqnArray<T> *array);
template <typename T>
bool dqn_darray_remove(DqnArray<T> *array, u64 index);
template <typename T>
bool dqn_darray_remove_stable(DqnArray<T> *array, u64 index);
// Typical operations should not require using the header directly, and it's
// recommended to use the API, but it can be used to have a faster way to track
// metadata.
typedef struct DqnDArrayHeader
{
u32 index;
u32 itemSize;
u32 capacity;
u32 signature;
void *data;
} DqnDArrayHeader;
// Returns the DArray header IF is a valid DArray
// Returns NULL IF not a valid DArray
DQN_FILE_SCOPE DqnDArrayHeader *dqn_darray_get_header(void *array);
// The init macro RETURNS a pointer to your type, you can index this as normal
// with array notation [].
// u32 type - The data type to initiate a dynamic array with
// u32 startingCapacity - Initial number of available slots
#define DQN_DARRAY_INIT(type, startingCapacity) \
(type *)dqn_darray_init_internal(sizeof(type), startingCapacity)
// Pass in the pointer returned by DQN_DARRAY_INIT. If the pointer is not
// a valid DArray pointer, this will return 0.
DQN_FILE_SCOPE u32 dqn_darray_get_capacity(void *array);
DQN_FILE_SCOPE u32 dqn_darray_get_num_items(void *array);
// Returns true and array modified in-place IF
// - The capacity change was successful OR
// - The newCapacity is equal to current capacity (no changes).
// Returns false and array is unmodified IF
// - Invalid DArray passed in OR realloc failed OR
// - More items in array than new capacity
DQN_FILE_SCOPE bool dqn_darray_capacity_change(void **array, i32 newCapacity);
// WARNING: This macro currently asserts if it's unable to push elements
// void **array - the address of the pointer returned by DQN_DARRAY_INIT
// void item - the object to insert
#define DQN_DARRAY_PUSH(array, item) \
{ \
if (dqn_darray_capacity_grow_if_need_internal((void **)array)) \
{ \
DqnDArrayHeader *header = dqn_darray_get_header(*array); \
*array[header->index++] = item; \
} \
else \
{ \
DQN_ASSERT(DQN_INVALID_CODE_PATH); \
} \
}
DQN_FILE_SCOPE bool dqn_darray_clear (void *array);
DQN_FILE_SCOPE bool dqn_darray_remove (void *array, u32 index);
DQN_FILE_SCOPE bool dqn_darray_remove_stable(void *array, u32 index);
// Pass in the pointer returned by DQN_DARRAY_INIT. Returns if the free was
// successful. This will return false if the array is not a valid DArray and
// won't touch the pointer.
DQN_FILE_SCOPE bool dqn_darray_free(void *array);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Math // Math
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -335,6 +283,9 @@ DQN_FILE_SCOPE i32 dqn_rnd_pcg_range(DqnRandPCGState *pcg, i32 min, i32 max);
#ifdef DQN_IMPLEMENTATION #ifdef DQN_IMPLEMENTATION
#undef DQN_IMPLEMENTATION #undef DQN_IMPLEMENTATION
// Enable sprintf implementation only when we enable DQN implementation
#define STB_SPRINTF_IMPLEMENTATION
#ifdef _WIN32 #ifdef _WIN32
#define DQN_WIN32 #define DQN_WIN32
@ -345,238 +296,139 @@ DQN_FILE_SCOPE i32 dqn_rnd_pcg_range(DqnRandPCGState *pcg, i32 min, i32 max);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// DArray - Dynamic Array // DArray - Dynamic Array
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#define DQN_DARRAY_SIGNATURE_INTERNAL 0xAC83DB81 // Implementation taken from Milton, developed by Serge at
FILE_SCOPE void *dqn_darray_init_internal(u32 itemSize, u32 startingCapacity) // https://github.com/serge-rgb/milton#license
template <typename T>
bool dqn_darray_init(DqnArray<T> *array, size_t capacity)
{ {
if (startingCapacity <= 0 || itemSize == 0) return NULL; if (!array) return false;
u32 metadataSize = sizeof(DqnDArrayHeader); array->data = (T *)calloc((size_t)capacity, sizeof(T));
u32 storageSize = itemSize * startingCapacity; if (!array->data) return false;
void *memory = calloc(1, metadataSize + storageSize); array->count = 0;
if (!memory) return NULL; array->capacity = capacity;
return true;
DqnDArrayHeader *array = (DqnDArrayHeader *)memory;
array->signature = DQN_DARRAY_SIGNATURE_INTERNAL;
array->itemSize = itemSize;
array->capacity = startingCapacity;
array->data = (u8 *)memory + metadataSize;
return array->data;
} }
DQN_FILE_SCOPE DqnDArrayHeader *dqn_darray_get_header(void *array) template <typename T>
bool dqn_darray_grow(DqnArray<T> *array)
{ {
if (!array) return NULL; if (!array || !array->data) return false;
DqnDArrayHeader *result = (DqnDArrayHeader *)((u8 *)array - sizeof(DqnDArrayHeader)); const f32 GROWTH_FACTOR = 1.2f;
if (result->signature != DQN_DARRAY_SIGNATURE_INTERNAL) return NULL; size_t newCapacity = (size_t)(array->capacity * GROWTH_FACTOR);
if (newCapacity == array->capacity) newCapacity++;
T *newMem = (T *)realloc(array->data, (size_t)(newCapacity * sizeof(T)));
if (newMem)
{
array->data = newMem;
array->capacity = newCapacity;
return true;
}
else
{
return false;
}
}
template <typename T>
bool dqn_darray_push(DqnArray<T> *array, T item)
{
if (!array) return false;
if (array->count >= array->capacity)
{
if (!dqn_darray_grow(array)) return false;
}
DQN_ASSERT(array->count < array->capacity);
array->data[array->count++] = item;
return true;
}
template <typename T>
T *dqn_darray_get(DqnArray<T> *array, u64 index)
{
T *result = NULL;
if (index >= 0 && index <= array->count) result = &array->data[index];
return result; return result;
} }
DQN_FILE_SCOPE u32 dqn_darray_get_capacity(void *array) template <typename T>
bool dqn_darray_clear(DqnArray<T> *array)
{ {
DqnDArrayHeader *header = dqn_darray_get_header(array); if (array)
if (!header) return 0;
return header->capacity;
}
DQN_FILE_SCOPE u32 dqn_darray_get_num_items(void *array)
{ {
DqnDArrayHeader *header = dqn_darray_get_header(array); array->count = 0;
if (!header) return 0;
return header->index;
}
DQN_FILE_SCOPE bool dqn_darray_capacity_change(void **array, u32 newCapacity)
{
DqnDArrayHeader *header = dqn_darray_get_header(*array);
if (!header) return false;
if (header->capacity == newCapacity) return true;
if (newCapacity > header->index)
{
u32 metadataSize = sizeof(DqnDArrayHeader);
u32 storageSize = header->itemSize * newCapacity;
void *newMem = realloc(header, metadataSize + storageSize);
if (newMem)
{
header = (DqnDArrayHeader *)newMem;
header->capacity = newCapacity;
header->data = (u8 *)newMem + metadataSize;
*array = header->data;
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
FILE_SCOPE bool dqn_darray_capacity_grow_if_need_internal(void **array)
{
DqnDArrayHeader *header = dqn_darray_get_header(*array);
if (!header) return false;
if (header->index >= header->capacity)
{
const f32 GROWTH_FACTOR = 1.2f;
u32 newCapacity = (i32)(header->capacity * GROWTH_FACTOR);
if (newCapacity == header->capacity) newCapacity++;
return dqn_darray_capacity_change(array, newCapacity);
}
return true;
}
bool dqn_darray_push_internal(void **array, void *element, u32 itemSize)
{
if (!element || !array) return false;
DqnDArrayHeader *header = dqn_darray_get_header(*array);
if (!header || header->itemSize != itemSize) return false;
// NOTE: Array is grown before this step happens. If at this point it still
// doesn't fit then we've had a mem alloc problem.
if (header->index >= header->capacity)
return false;
u32 arrayOffset = header->itemSize * header->index++;
DQN_ASSERT(header->index <= header->capacity);
u8 *dataPtr = (u8 *)header->data;
void *dest = (void *)&dataPtr[arrayOffset];
void *src = element;
memcpy(dest, src, header->itemSize);
return true;
}
DQN_FILE_SCOPE bool dqn_darray_clear(void *array)
{
DqnDArrayHeader *header = dqn_darray_get_header(array);
if (header)
{
header->index = 0;
return true; return true;
} }
return false; return false;
} }
DQN_FILE_SCOPE bool dqn_darray_remove(void *array, u32 index) template <typename T>
bool dqn_darray_free(DqnArray<T> *array)
{ {
DqnDArrayHeader *header = dqn_darray_get_header(array); if (array && array->data)
if (header)
{ {
// NOTE: header->index is the index where the next entry will be push to free(array->data);
// Array is empty, or index is out of bounds array->count = 0;
if (header->index == 0 || index >= header->index) return false; array->capacity = 0;
// If it's the first entry we just need to decrement index
if (index == 0 && header->index == 1)
{
header->index--;
return true;
}
// If it's the last entry we just need to decrement index
if (index == (header->index - 1))
{
header->index--;
return true;
}
u32 lastEntryIndex = header->index - 1;
u32 lastEntryByteOffset = lastEntryIndex * header->itemSize;
u32 removeEntryIndex = index;
u32 removeEntryByteOffset = removeEntryIndex * header->itemSize;
u8 *dataPtr = (u8 *)header->data;
void *dest = (void *)&dataPtr[removeEntryByteOffset];
void *src = (void *)&dataPtr[lastEntryByteOffset];
memcpy(dest, src, header->itemSize);
header->index--;
return true; return true;
} }
return false; return false;
} }
DQN_FILE_SCOPE bool dqn_darray_remove_stable(void *array, u32 index) template <typename T>
bool dqn_darray_remove(DqnArray<T> *array, u64 index)
{ {
DqnDArrayHeader *header = dqn_darray_get_header(array); if (!array) return false;
if (header) if (index >= array->count) return false;
{
// NOTE: header->index is the index where the next entry will be push to
// Array is empty, or index is out of bounds
if (header->index == 0 || index >= header->index) return false;
// If it's the last entry we just need to decrement index bool firstElementAndOnlyElement = (index == 0 && array->count == 1);
if (index == (header->index - 1)) bool isLastElement = (index == (array->count - 1));
if (firstElementAndOnlyElement || isLastElement)
{ {
header->index--; array->count--;
return true; return true;
} }
// If it's the first entry we just need to decrement index array->data[index] = array->data[array->count - 1];
if (index == 0 && header->index == 1) array->count--;
{
header->index--;
return true; return true;
} }
u32 removeEntryIndex = index; template <typename T>
u32 removeEntryByteOffset = removeEntryIndex * header->itemSize; bool dqn_darray_remove_stable(DqnArray<T> *array, u64 index)
{
if (!array) return false;
if (index >= array->count) return false;
u32 oneAfterRemove = index + 1; bool firstElementAndOnlyElement = (index == 0 && array->count == 1);
u32 oneAfterRemoveByteOffset = oneAfterRemove * header->itemSize; bool isLastElement = (index == (array->count - 1));
u32 endOfListIndex = header->index - 1; if (firstElementAndOnlyElement || isLastElement)
u32 endOfListByteOffset = endOfListIndex * header->itemSize; {
array->count--;
u32 numBytesToShift = endOfListByteOffset - oneAfterRemoveByteOffset;
DQN_ASSERT(numBytesToShift <= (header->itemSize * header->capacity));
u8 *dataPtr = (u8 *)header->data;
void *dest = (void *)&dataPtr[removeEntryByteOffset];
void *src = (void *)&dataPtr[oneAfterRemoveByteOffset];
memmove(dest, src, endOfListByteOffset);
header->index--;
return true; return true;
} }
return false; size_t itemToRemoveByteOffset = (size_t)(index * sizeof(T));
} size_t oneAfterItemToRemoveByteOffset = (size_t)((index + 1) * sizeof(T));
size_t lastItemByteOffset = (size_t)(array->count * sizeof(T));
size_t numBytesToMove = lastItemByteOffset - oneAfterItemToRemoveByteOffset;
DQN_FILE_SCOPE inline bool dqn_darray_free(void *array) u8 *bytePtr = (u8 *)array->data;
{ u8 *dest = &bytePtr[itemToRemoveByteOffset];
DqnDArrayHeader *header = dqn_darray_get_header(array); u8 *src = &bytePtr[oneAfterItemToRemoveByteOffset];
if (header) memmove(dest, src, numBytesToMove);
{
header->index = 0;
header->itemSize = 0;
header->capacity = 0;
header->signature = 0;
free(header); array->count--;
return true; return true;
} }
else
{
return false;
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Math // Math
@ -1387,7 +1239,6 @@ DQN_FILE_SCOPE u32 dqn_utf8_to_ucs(u32 *dest, u32 character)
// File Operations // File Operations
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifdef DQN_WIN32 #ifdef DQN_WIN32
#define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK);
DQN_FILE_SCOPE bool dqn_win32_utf8_to_wchar(char *in, wchar_t *out, i32 outLen) DQN_FILE_SCOPE bool dqn_win32_utf8_to_wchar(char *in, wchar_t *out, i32 outLen)
{ {
@ -1690,14 +1541,13 @@ DQN_FILE_SCOPE i32 dqn_rnd_pcg_range(DqnRandPCGState *pcg, i32 min, i32 max)
i32 const value = (i32)(dqn_rnd_pcg_nextf(pcg) * range); i32 const value = (i32)(dqn_rnd_pcg_nextf(pcg) * range);
return min + value; return min + value;
} }
#endif /* DQN_IMPLEMENTATION */
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// //
// STB_Sprintf // STB_Sprintf
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#define STB_SPRINTF_IMPLEMENTATION
// stb_sprintf - v1.02 - public domain snprintf() implementation // stb_sprintf - v1.02 - public domain snprintf() implementation
// originally by Jeff Roberts / RAD Game Tools, 2015/10/20 // originally by Jeff Roberts / RAD Game Tools, 2015/10/20
// http://github.com/nothings/stb // http://github.com/nothings/stb
@ -2896,5 +2746,3 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*/ */
#endif /* DQN_IMPLEMENTATION */

View File

@ -553,90 +553,89 @@ void dqn_vec_test()
void dqn_darray_test() void dqn_darray_test()
{ {
{ {
DqnV2 *vecDArray = DQN_DARRAY_INIT(DqnV2, 1); DqnArray<DqnV2> array = {};
DQN_ASSERT(vecDArray); DQN_ASSERT(dqn_darray_init(&array, 1));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 1); DQN_ASSERT(array.capacity == 1);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 0); DQN_ASSERT(array.count == 0);
// Test basic insert // Test basic insert
{ {
DqnV2 va = dqn_v2(5, 10); DqnV2 va = dqn_v2(5, 10);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DqnV2 vb = vecDArray[0]; DqnV2 vb = array.data[0];
DQN_ASSERT(dqn_v2_equals(va, vb)); DQN_ASSERT(dqn_v2_equals(va, vb));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 1); DQN_ASSERT(array.capacity == 1);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 1); DQN_ASSERT(array.count == 1);
} }
// Test array resizing and freeing // Test array resizing and freeing
{ {
DqnV2 va = dqn_v2(10, 15); DqnV2 va = dqn_v2(10, 15);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DqnV2 vb = vecDArray[0]; DqnV2 vb = array.data[0];
DQN_ASSERT(dqn_v2_equals(va, vb) == false); DQN_ASSERT(dqn_v2_equals(va, vb) == false);
vb = vecDArray[1]; vb = array.data[1];
DQN_ASSERT(dqn_v2_equals(va, vb) == true); DQN_ASSERT(dqn_v2_equals(va, vb) == true);
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 2); DQN_ASSERT(array.capacity == 2);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 2); DQN_ASSERT(array.count == 2);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 3); DQN_ASSERT(array.capacity == 3);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 3); DQN_ASSERT(array.count == 3);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 4); DQN_ASSERT(array.capacity == 4);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 4); DQN_ASSERT(array.count == 4);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 5); DQN_ASSERT(array.capacity == 5);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 5); DQN_ASSERT(array.count == 5);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 6); DQN_ASSERT(array.capacity == 6);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 6); DQN_ASSERT(array.count == 6);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 7); DQN_ASSERT(array.capacity == 7);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 7); DQN_ASSERT(array.count == 7);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 8); DQN_ASSERT(array.capacity == 8);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 8); DQN_ASSERT(array.count == 8);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 9); DQN_ASSERT(array.capacity == 9);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 9); DQN_ASSERT(array.count == 9);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 10); DQN_ASSERT(array.capacity == 10);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 10); DQN_ASSERT(array.count == 10);
DQN_DARRAY_PUSH(&vecDArray, va); DQN_ASSERT(dqn_darray_push(&array, va));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 12); DQN_ASSERT(array.capacity == 12);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 11); DQN_ASSERT(array.count == 11);
DqnV2 vc = dqn_v2(90, 100); DqnV2 vc = dqn_v2(90, 100);
DQN_DARRAY_PUSH(&vecDArray, vc); DQN_ASSERT(dqn_darray_push(&array, vc));
DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 12); DQN_ASSERT(array.capacity == 12);
DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 12); DQN_ASSERT(array.count == 12);
DQN_ASSERT(dqn_v2_equals(vc, vecDArray[11])); DQN_ASSERT(dqn_v2_equals(vc, array.data[11]));
DQN_ASSERT(dqn_darray_free(vecDArray) == true); DQN_ASSERT(dqn_darray_free(&array) == true);
} }
} }
{ {
f32 *array = DQN_DARRAY_INIT(f32, 1); DqnArray<f32> array = {};
DQN_ASSERT(array); DQN_ASSERT(dqn_darray_init(&array, 1));
DQN_ASSERT(dqn_darray_get_capacity(array) == 1); DQN_ASSERT(array.capacity == 1);
DQN_ASSERT(dqn_darray_get_num_items(array) == 0); DQN_ASSERT(array.count == 0);
dqn_darray_free(&array);
dqn_darray_free(array);
} }
{ {
@ -645,47 +644,47 @@ void dqn_darray_test()
DqnV2 c = dqn_v2(5, 6); DqnV2 c = dqn_v2(5, 6);
DqnV2 d = dqn_v2(7, 8); DqnV2 d = dqn_v2(7, 8);
DqnV2 *array = DQN_DARRAY_INIT(DqnV2, 16); DqnArray<DqnV2> array = {};
DQN_ASSERT(array); DQN_ASSERT(dqn_darray_init(&array, 16));
DQN_ASSERT(dqn_darray_remove(array, 0) == false); DQN_ASSERT(dqn_darray_remove(&array, 0) == false);
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 0); DQN_ASSERT(array.count == 0);
DQN_ASSERT(dqn_darray_clear(array)); DQN_ASSERT(dqn_darray_clear(&array));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 0); DQN_ASSERT(array.count == 0);
DQN_DARRAY_PUSH(&array, a); DQN_ASSERT(dqn_darray_push(&array, a));
DQN_DARRAY_PUSH(&array, b); DQN_ASSERT(dqn_darray_push(&array, b));
DQN_DARRAY_PUSH(&array, c); DQN_ASSERT(dqn_darray_push(&array, c));
DQN_DARRAY_PUSH(&array, d); DQN_ASSERT(dqn_darray_push(&array, d));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 4); DQN_ASSERT(array.count == 4);
DQN_ASSERT(dqn_darray_remove(array, 0)); DQN_ASSERT(dqn_darray_remove(&array, 0));
DQN_ASSERT(dqn_v2_equals(array[0], d)); DQN_ASSERT(dqn_v2_equals(array.data[0], d));
DQN_ASSERT(dqn_v2_equals(array[1], b)); DQN_ASSERT(dqn_v2_equals(array.data[1], b));
DQN_ASSERT(dqn_v2_equals(array[2], c)); DQN_ASSERT(dqn_v2_equals(array.data[2], c));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 3); DQN_ASSERT(array.count == 3);
DQN_ASSERT(dqn_darray_remove(array, 2)); DQN_ASSERT(dqn_darray_remove(&array, 2));
DQN_ASSERT(dqn_v2_equals(array[0], d)); DQN_ASSERT(dqn_v2_equals(array.data[0], d));
DQN_ASSERT(dqn_v2_equals(array[1], b)); DQN_ASSERT(dqn_v2_equals(array.data[1], b));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 2); DQN_ASSERT(array.count == 2);
DQN_ASSERT(dqn_darray_remove(array, 100) == false); DQN_ASSERT(dqn_darray_remove(&array, 100) == false);
DQN_ASSERT(dqn_v2_equals(array[0], d)); DQN_ASSERT(dqn_v2_equals(array.data[0], d));
DQN_ASSERT(dqn_v2_equals(array[1], b)); DQN_ASSERT(dqn_v2_equals(array.data[1], b));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 2); DQN_ASSERT(array.count == 2);
DQN_ASSERT(dqn_darray_clear(array)); DQN_ASSERT(dqn_darray_clear(&array));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 0); DQN_ASSERT(array.count == 0);
dqn_darray_free(array); dqn_darray_free(&array);
} }
{ {
@ -694,43 +693,36 @@ void dqn_darray_test()
DqnV2 c = dqn_v2(5, 6); DqnV2 c = dqn_v2(5, 6);
DqnV2 d = dqn_v2(7, 8); DqnV2 d = dqn_v2(7, 8);
DqnV2 *array = DQN_DARRAY_INIT(DqnV2, 16); DqnArray<DqnV2> array = {};
DQN_ASSERT(array); DQN_ASSERT(dqn_darray_init(&array, 16));
DQN_DARRAY_PUSH(&array, a); DQN_ASSERT(dqn_darray_push(&array, a));
DQN_DARRAY_PUSH(&array, b); DQN_ASSERT(dqn_darray_push(&array, b));
DQN_DARRAY_PUSH(&array, c); DQN_ASSERT(dqn_darray_push(&array, c));
DQN_DARRAY_PUSH(&array, d); DQN_ASSERT(dqn_darray_push(&array, d));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 4); DQN_ASSERT(array.count == 4);
dqn_darray_remove_stable(array, 0); dqn_darray_remove_stable(&array, 0);
DQN_ASSERT(dqn_v2_equals(array[0], b)); DQN_ASSERT(dqn_v2_equals(array.data[0], b));
DQN_ASSERT(dqn_v2_equals(array[1], c)); DQN_ASSERT(dqn_v2_equals(array.data[1], c));
DQN_ASSERT(dqn_v2_equals(array[2], d)); DQN_ASSERT(dqn_v2_equals(array.data[2], d));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 3); DQN_ASSERT(array.count == 3);
dqn_darray_remove_stable(array, 1); dqn_darray_remove_stable(&array, 1);
DQN_ASSERT(dqn_v2_equals(array[0], b)); DQN_ASSERT(dqn_v2_equals(array.data[0], b));
DQN_ASSERT(dqn_v2_equals(array[1], d)); DQN_ASSERT(dqn_v2_equals(array.data[1], d));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 2); DQN_ASSERT(array.count == 2);
dqn_darray_remove_stable(array, 1); dqn_darray_remove_stable(&array, 1);
DQN_ASSERT(dqn_v2_equals(array[0], b)); DQN_ASSERT(dqn_v2_equals(array.data[0], b));
DQN_ASSERT(dqn_darray_get_capacity(array) == 16); DQN_ASSERT(array.capacity == 16);
DQN_ASSERT(dqn_darray_get_num_items(array) == 1); DQN_ASSERT(array.count == 1);
dqn_darray_free(array); dqn_darray_free(&array);
} }
{
DQN_ASSERT(dqn_darray_clear(NULL) == false);
DQN_ASSERT(dqn_darray_clear(NULL) == false);
DQN_ASSERT(dqn_darray_free(NULL) == false);
}
printf("dqn_darray_test(): Completed successfully\n"); printf("dqn_darray_test(): Completed successfully\n");
} }