Switch darray implementation to C++ with templates
This commit is contained in:
parent
9106f185a3
commit
e0cae3029d
@ -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=
|
||||||
|
430
dqn.h
430
dqn.h
@ -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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
dqn_darray_free(uintArray);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 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;
|
u64 count;
|
||||||
u32 itemSize;
|
u64 capacity;
|
||||||
u32 capacity;
|
T *data;
|
||||||
u32 signature;
|
};
|
||||||
|
|
||||||
void *data;
|
template <typename T>
|
||||||
} DqnDArrayHeader;
|
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);
|
||||||
|
|
||||||
// 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,239 +296,140 @@ 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);
|
|
||||||
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);
|
array->count = 0;
|
||||||
u32 storageSize = header->itemSize * newCapacity;
|
return true;
|
||||||
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 false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool dqn_darray_free(DqnArray<T> *array)
|
||||||
|
{
|
||||||
|
if (array && array->data)
|
||||||
|
{
|
||||||
|
free(array->data);
|
||||||
|
array->count = 0;
|
||||||
|
array->capacity = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool dqn_darray_remove(DqnArray<T> *array, u64 index)
|
||||||
|
{
|
||||||
|
if (!array) return false;
|
||||||
|
if (index >= array->count) return false;
|
||||||
|
|
||||||
|
bool firstElementAndOnlyElement = (index == 0 && array->count == 1);
|
||||||
|
bool isLastElement = (index == (array->count - 1));
|
||||||
|
if (firstElementAndOnlyElement || isLastElement)
|
||||||
|
{
|
||||||
|
array->count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
array->data[index] = array->data[array->count - 1];
|
||||||
|
array->count--;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dqn_darray_push_internal(void **array, void *element, u32 itemSize)
|
template <typename T>
|
||||||
|
bool dqn_darray_remove_stable(DqnArray<T> *array, u64 index)
|
||||||
{
|
{
|
||||||
if (!element || !array) return false;
|
if (!array) return false;
|
||||||
|
if (index >= array->count) return false;
|
||||||
|
|
||||||
DqnDArrayHeader *header = dqn_darray_get_header(*array);
|
bool firstElementAndOnlyElement = (index == 0 && array->count == 1);
|
||||||
if (!header || header->itemSize != itemSize) return false;
|
bool isLastElement = (index == (array->count - 1));
|
||||||
|
if (firstElementAndOnlyElement || isLastElement)
|
||||||
|
{
|
||||||
|
array->count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Array is grown before this step happens. If at this point it still
|
size_t itemToRemoveByteOffset = (size_t)(index * sizeof(T));
|
||||||
// doesn't fit then we've had a mem alloc problem.
|
size_t oneAfterItemToRemoveByteOffset = (size_t)((index + 1) * sizeof(T));
|
||||||
if (header->index >= header->capacity)
|
size_t lastItemByteOffset = (size_t)(array->count * sizeof(T));
|
||||||
return false;
|
size_t numBytesToMove = lastItemByteOffset - oneAfterItemToRemoveByteOffset;
|
||||||
|
|
||||||
u32 arrayOffset = header->itemSize * header->index++;
|
u8 *bytePtr = (u8 *)array->data;
|
||||||
DQN_ASSERT(header->index <= header->capacity);
|
u8 *dest = &bytePtr[itemToRemoveByteOffset];
|
||||||
u8 *dataPtr = (u8 *)header->data;
|
u8 *src = &bytePtr[oneAfterItemToRemoveByteOffset];
|
||||||
|
memmove(dest, src, numBytesToMove);
|
||||||
void *dest = (void *)&dataPtr[arrayOffset];
|
|
||||||
void *src = element;
|
|
||||||
memcpy(dest, src, header->itemSize);
|
|
||||||
|
|
||||||
|
array->count--;
|
||||||
return true;
|
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 false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DQN_FILE_SCOPE bool dqn_darray_remove(void *array, u32 index)
|
|
||||||
{
|
|
||||||
DqnDArrayHeader *header = dqn_darray_get_header(array);
|
|
||||||
if (header)
|
|
||||||
{
|
|
||||||
// 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 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 false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DQN_FILE_SCOPE bool dqn_darray_remove_stable(void *array, u32 index)
|
|
||||||
{
|
|
||||||
DqnDArrayHeader *header = dqn_darray_get_header(array);
|
|
||||||
if (header)
|
|
||||||
{
|
|
||||||
// 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
|
|
||||||
if (index == (header->index - 1))
|
|
||||||
{
|
|
||||||
header->index--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's the first entry we just need to decrement index
|
|
||||||
if (index == 0 && header->index == 1)
|
|
||||||
{
|
|
||||||
header->index--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 removeEntryIndex = index;
|
|
||||||
u32 removeEntryByteOffset = removeEntryIndex * header->itemSize;
|
|
||||||
|
|
||||||
u32 oneAfterRemove = index + 1;
|
|
||||||
u32 oneAfterRemoveByteOffset = oneAfterRemove * header->itemSize;
|
|
||||||
u32 endOfListIndex = header->index - 1;
|
|
||||||
u32 endOfListByteOffset = endOfListIndex * header->itemSize;
|
|
||||||
|
|
||||||
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 false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DQN_FILE_SCOPE inline bool dqn_darray_free(void *array)
|
|
||||||
{
|
|
||||||
DqnDArrayHeader *header = dqn_darray_get_header(array);
|
|
||||||
if (header)
|
|
||||||
{
|
|
||||||
header->index = 0;
|
|
||||||
header->itemSize = 0;
|
|
||||||
header->capacity = 0;
|
|
||||||
header->signature = 0;
|
|
||||||
|
|
||||||
free(header);
|
|
||||||
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 */
|
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user