Add unit tests for allocators/arrays
This commit is contained in:
parent
b34226498c
commit
d31c63cbb7
@ -14,5 +14,5 @@ REM Tp Treat header file as CPP source file
|
|||||||
cl /MT /EHa /GR- /Od /Oi /Z7 /W4 /WX /wd4201 /D DQN_HEADER_IMPLEMENTATION /Tp ../Code/DqnHeader.h /link /nologo
|
cl /MT /EHa /GR- /Od /Oi /Z7 /W4 /WX /wd4201 /D DQN_HEADER_IMPLEMENTATION /Tp ../Code/DqnHeader.h /link /nologo
|
||||||
DqnHeader.exe ..\Code\Dqn.h > ..\Code\DqnHeader_Generated.h
|
DqnHeader.exe ..\Code\Dqn.h > ..\Code\DqnHeader_Generated.h
|
||||||
|
|
||||||
cl /MT /EHa /GR- /Od /Oi /Z7 /W4 /WX /wd4201 /D DQN_IMPLEMENTATION ../Code/Dqn_UnitTests.cpp /link /nologo
|
cl /MT /EHa /GR- /Od /Oi /Z7 /W4 /WX /wd4201 ../Code/Dqn_UnitTests.cpp /link /nologo
|
||||||
popd
|
popd
|
||||||
|
258
Code/Dqn.h
258
Code/Dqn.h
@ -1,3 +1,7 @@
|
|||||||
|
// #define DQN_USE_PRIMITIVE_TYPEDEFS to enable typical typedefs such as i32 = int32_t .. etc
|
||||||
|
// #define DQN_IMPLEMENTATION in one and only one C++ file to enable the header file
|
||||||
|
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS // NOTE: Undefined at end of header file
|
||||||
#if defined(DQN_IMPLEMENTATION)
|
#if defined(DQN_IMPLEMENTATION)
|
||||||
#define STB_SPRINTF_IMPLEMENTATION
|
#define STB_SPRINTF_IMPLEMENTATION
|
||||||
#endif
|
#endif
|
||||||
@ -198,6 +202,7 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char peri
|
|||||||
// @ NOTE: Typedefs, Macros, Utils
|
// @ NOTE: Typedefs, Macros, Utils
|
||||||
// @
|
// @
|
||||||
// @ -------------------------------------------------------------------------------------------------
|
// @ -------------------------------------------------------------------------------------------------
|
||||||
|
#define DQN_CAST(val) (val)
|
||||||
#define DQN_ABS(val) (((val) < 0) ? (-(val)) : (val))
|
#define DQN_ABS(val) (((val) < 0) ? (-(val)) : (val))
|
||||||
#define DQN_SQUARED(val) ((val) * (val))
|
#define DQN_SQUARED(val) ((val) * (val))
|
||||||
#define DQN_MIN(a, b) ((a < b) ? (a) : (b))
|
#define DQN_MIN(a, b) ((a < b) ? (a) : (b))
|
||||||
@ -606,12 +611,12 @@ struct Dqn_MemArenaScopedRegion
|
|||||||
#define DQN_DEBUG_PARAMS
|
#define DQN_DEBUG_PARAMS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DQN_MEM_ARENA_ALLOC(arena, size) Dqn_MemArena_Alloc(arena, size DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_ALLOC(arena, size) Dqn_MemArena_Alloc(arena, size DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_ALLOC_ARRAY(arena, T, num) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) * num DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_ALLOC_ARRAY(arena, T, num) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) * num DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_ALLOC_STRUCT(arena, T) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_ALLOC_STRUCT(arena, T) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_RESERVE(arena, size) Dqn_MemArena_Reserve(arena, size DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_RESERVE(arena, size) Dqn_MemArena_Reserve(arena, size DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_RESERVE_FROM(arena, src, size) Dqn_MemArena_ReserveFrom(arena, src, size DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_RESERVE_FROM(arena, src, size) Dqn_MemArena_ReserveFrom(arena, src, size DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_CLEAR_USED(arena) Dqn_MemArena_ClearUsed(arena DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_CLEAR_USED(arena) Dqn_MemArena_ClearUsed(arena DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_FREE(arena) Dqn_MemArena_Free
|
#define DQN_MEM_ARENA_FREE(arena) Dqn_MemArena_Free
|
||||||
DQN_HEADER_COPY_END
|
DQN_HEADER_COPY_END
|
||||||
|
|
||||||
@ -1057,17 +1062,36 @@ template <typename T, int MAX_> T *Dqn_FixedStack_Push (Dqn_FixedStack<T, MAX_
|
|||||||
template <typename T, int MAX_> void Dqn_FixedStack_Clear(Dqn_FixedStack<T, MAX_> *array) { Dqn_FixedArray_Clear(array); }
|
template <typename T, int MAX_> void Dqn_FixedStack_Clear(Dqn_FixedStack<T, MAX_> *array) { Dqn_FixedArray_Clear(array); }
|
||||||
DQN_HEADER_COPY_END
|
DQN_HEADER_COPY_END
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_BEGIN
|
||||||
|
enum struct Dqn_Allocator_Type
|
||||||
|
{
|
||||||
|
Heap, // Malloc, realloc, free
|
||||||
|
XHeap, // Malloc realloc, free, crash on failure
|
||||||
|
Arena,
|
||||||
|
NullAllocator,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Dqn_Allocator
|
||||||
|
{
|
||||||
|
Dqn_Allocator_Type type;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
DQN_HEADER_COPY_END
|
||||||
|
|
||||||
// @ -------------------------------------------------------------------------------------------------
|
// @ -------------------------------------------------------------------------------------------------
|
||||||
// @
|
// @
|
||||||
// @ NOTE: Dqn_StaticArray
|
// @ NOTE: Dqn_Array
|
||||||
// @
|
// @
|
||||||
// @ -------------------------------------------------------------------------------------------------
|
// @ -------------------------------------------------------------------------------------------------
|
||||||
DQN_HEADER_COPY_BEGIN
|
DQN_HEADER_COPY_BEGIN
|
||||||
template <typename T> struct Dqn_StaticArray
|
// TODO(doyle): Make this either initialised from memory or dynamically allocating
|
||||||
|
template <typename T> struct Dqn_Array
|
||||||
{
|
{
|
||||||
|
Dqn_Allocator allocator;
|
||||||
T *data;
|
T *data;
|
||||||
Dqn_isize len;
|
Dqn_isize len;
|
||||||
Dqn_isize max;
|
Dqn_isize max;
|
||||||
|
|
||||||
T const operator[](Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
T const operator[](Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||||
T operator[](Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
T operator[](Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||||
T const *begin () const { return data; }
|
T const *begin () const { return data; }
|
||||||
@ -1079,15 +1103,101 @@ template <typename T> struct Dqn_StaticArray
|
|||||||
};
|
};
|
||||||
DQN_HEADER_COPY_END
|
DQN_HEADER_COPY_END
|
||||||
|
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> Dqn_StaticArray<T> , Dqn_StaticArray_InitMemory (T *memory, Dqn_isize max, Dqn_isize len = 0)) { Dqn_StaticArray<T> result = {}; result.data = memory; result.len = len; result.max = max; return result; }
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> Dqn_Array<T>, Dqn_Array_InitMemory(T *memory, Dqn_isize max, Dqn_isize len = 0))
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_StaticArray_Add (Dqn_StaticArray<T> *a, T const *items, Dqn_isize num)) { DQN_ASSERT(a->len + num <= a->max); T *result = static_cast<T *>(Dqn_MemCopy(a->data + a->len, items, sizeof(T) * num)); a->len += num; return result; }
|
{
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_StaticArray_Add (Dqn_StaticArray<T> *a, T const item)) { DQN_ASSERT(a->len < a->max); a->data[a->len++] = item; return &a->data[a->len - 1]; }
|
Dqn_Array<T> result = {};
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_StaticArray_Make (Dqn_StaticArray<T> *a, Dqn_isize num)) { DQN_ASSERT(a->len + num <= a->max); T *result = a->data + a->len; a->len += num; return result;}
|
result.allocator = Dqn_Allocator_NullAllocator();
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void , Dqn_StaticArray_Clear (Dqn_StaticArray<T> *a)) { a->len = 0; }
|
result.data = memory;
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void , Dqn_StaticArray_EraseStable (Dqn_StaticArray<T> *a, Dqn_isize index)) { Dqn__EraseStableFromCArray<T>(a->data, a->len--, a->max, index); }
|
result.len = len;
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void , Dqn_StaticArray_EraseUnstable(Dqn_StaticArray<T> *a, Dqn_isize index)) { DQN_ASSERT(index >= 0 && index < a->len); if (--a->len == 0) return; a->data[index] = a->data[a->len]; }
|
result.max = max;
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void , Dqn_StaticArray_Pop (Dqn_StaticArray<T> *a, Dqn_isize num)) { DQN_ASSERT(a->len - num >= 0); a->len -= num; }
|
return result;
|
||||||
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_StaticArray_Peek (Dqn_StaticArray<T> *a)) { T *result = (a->len == 0) ? nullptr : a->data + (a->len - 1); return result; }
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> bool, Dqn_Array_Reserve(Dqn_Array<T> *a, Dqn_isize size))
|
||||||
|
{
|
||||||
|
if (size <= a->len) return true;
|
||||||
|
T *new_ptr = nullptr;
|
||||||
|
if (a->data) new_ptr = DQN_CAST(T *)Dqn_Allocator_Realloc (&a->allocator, a->data, sizeof(T) * a->max, sizeof(T) * size);
|
||||||
|
else new_ptr = DQN_CAST(T *)Dqn_Allocator_Allocate(&a->allocator, sizeof(T) * size);
|
||||||
|
if (!new_ptr) return false;
|
||||||
|
a->data = new_ptr;
|
||||||
|
a->max = size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void, Dqn_Array_Free(Dqn_Array<T> *a))
|
||||||
|
{
|
||||||
|
Dqn_Allocator_Free(&a->allocator, a->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T> bool Dqn_Array__GrowIfNeeded(Dqn_Array<T> *a, Dqn_isize num_to_add)
|
||||||
|
{
|
||||||
|
Dqn_isize new_len = a->len + num_to_add;
|
||||||
|
bool result = true;
|
||||||
|
if (new_len > a->max)
|
||||||
|
{
|
||||||
|
Dqn_isize num_items = DQN_MAX(4, DQN_MAX(new_len, (a->max * 2)));
|
||||||
|
result = Dqn_Array_Reserve(a, num_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_Array_Add(Dqn_Array<T> *a, T const *items, Dqn_isize num))
|
||||||
|
{
|
||||||
|
if (!Dqn_Array__GrowIfNeeded(a, num))
|
||||||
|
return nullptr;
|
||||||
|
T *result = static_cast<T *>(Dqn_MemCopy(a->data + a->len, items, sizeof(T) * num));
|
||||||
|
a->len += num;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_Array_Add(Dqn_Array<T> *a, T const item))
|
||||||
|
{
|
||||||
|
if (!Dqn_Array__GrowIfNeeded(a, 1))
|
||||||
|
return nullptr;
|
||||||
|
a->data[a->len++] = item;
|
||||||
|
return &a->data[a->len - 1];
|
||||||
|
}
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_Array_Make(Dqn_Array<T> *a, Dqn_isize num))
|
||||||
|
{
|
||||||
|
if (!Dqn_Array__GrowIfNeeded(a, num))
|
||||||
|
return nullptr;
|
||||||
|
T *result = a->data + a->len;
|
||||||
|
a->len += num;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void, Dqn_Array_Clear(Dqn_Array<T> *a, bool zero_mem = false))
|
||||||
|
{
|
||||||
|
a->len = 0;
|
||||||
|
if (zero_mem) memset(a->data, 0, sizeof(T) * a->max);
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void, Dqn_Array_EraseStable(Dqn_Array<T> *a, Dqn_isize index))
|
||||||
|
{
|
||||||
|
Dqn__EraseStableFromCArray<T>(a->data, a->len--, a->max, index);
|
||||||
|
}
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void,
|
||||||
|
Dqn_Array_EraseUnstable(Dqn_Array<T> *a, Dqn_isize index))
|
||||||
|
{
|
||||||
|
DQN_ASSERT(index >= 0 && index < a->len);
|
||||||
|
if (--a->len == 0) return;
|
||||||
|
a->data[index] = a->data[a->len];
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> void, Dqn_Array_Pop(Dqn_Array<T> *a, Dqn_isize num))
|
||||||
|
{
|
||||||
|
DQN_ASSERT(a->len - num >= 0);
|
||||||
|
a->len -= num;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_Array_Peek(Dqn_Array<T> *a))
|
||||||
|
{
|
||||||
|
T *result = (a->len == 0) ? nullptr : a->data + (a->len - 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// @ -------------------------------------------------------------------------------------------------
|
// @ -------------------------------------------------------------------------------------------------
|
||||||
// @
|
// @
|
||||||
@ -1163,9 +1273,11 @@ struct Dqn_U64Str
|
|||||||
int len;
|
int len;
|
||||||
};
|
};
|
||||||
DQN_HEADER_COPY_END
|
DQN_HEADER_COPY_END
|
||||||
|
#undef _CRT_SECURE_NO_WARNINGS
|
||||||
#endif // DQN_H
|
#endif // DQN_H
|
||||||
|
|
||||||
#ifdef DQN_IMPLEMENTATION
|
#ifdef DQN_IMPLEMENTATION
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -1451,6 +1563,114 @@ Dqn_MemArenaScopedRegion::~Dqn_MemArenaScopedRegion()
|
|||||||
this->arena->curr_mem_block->used = this->curr_mem_block_used;
|
this->arena->curr_mem_block->used = this->curr_mem_block_used;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ -------------------------------------------------------------------------------------------------
|
||||||
|
// @
|
||||||
|
// @ NOTE: Dqn_Allocator
|
||||||
|
// @
|
||||||
|
// @ -------------------------------------------------------------------------------------------------
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, Dqn_Allocator_NullAllocator())
|
||||||
|
{
|
||||||
|
Dqn_Allocator result = {};
|
||||||
|
result.type = Dqn_Allocator_Type::NullAllocator;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, Dqn_Allocator_HeapAllocator())
|
||||||
|
{
|
||||||
|
Dqn_Allocator result = {};
|
||||||
|
result.type = Dqn_Allocator_Type::Heap;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, Dqn_Allocator_XHeapAllocator())
|
||||||
|
{
|
||||||
|
Dqn_Allocator result = {};
|
||||||
|
result.type = Dqn_Allocator_Type::XHeap;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, Dqn_Allocator_ArenaAllocator(Dqn_MemArena *arena))
|
||||||
|
{
|
||||||
|
Dqn_Allocator result = {};
|
||||||
|
result.type = Dqn_Allocator_Type::Arena;
|
||||||
|
result.data = arena;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_usize size))
|
||||||
|
{
|
||||||
|
void *result = nullptr;
|
||||||
|
switch (allocator->type)
|
||||||
|
{
|
||||||
|
default: break;
|
||||||
|
case Dqn_Allocator_Type::Heap:
|
||||||
|
case Dqn_Allocator_Type::XHeap:
|
||||||
|
{
|
||||||
|
result = malloc(size);
|
||||||
|
if (!result && allocator->type == Dqn_Allocator_Type::XHeap)
|
||||||
|
DQN_ASSERT(result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Dqn_Allocator_Type::Arena:
|
||||||
|
{
|
||||||
|
auto *arena = static_cast<Dqn_MemArena *>(allocator->data);
|
||||||
|
result = DQN_MEM_ARENA_ALLOC(arena, size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Realloc(Dqn_Allocator *allocator, void *old_ptr, Dqn_isize old_size, Dqn_isize new_size))
|
||||||
|
{
|
||||||
|
void *result = nullptr;
|
||||||
|
switch (allocator->type)
|
||||||
|
{
|
||||||
|
default: break;
|
||||||
|
case Dqn_Allocator_Type::Heap:
|
||||||
|
case Dqn_Allocator_Type::XHeap:
|
||||||
|
{
|
||||||
|
result = realloc(old_ptr, new_size);
|
||||||
|
if (!result && allocator->type == Dqn_Allocator_Type::XHeap)
|
||||||
|
DQN_ASSERT(result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Dqn_Allocator_Type::Arena:
|
||||||
|
{
|
||||||
|
auto *arena = static_cast<Dqn_MemArena *>(allocator->data);
|
||||||
|
if (DQN_MEM_ARENA_RESERVE(arena, new_size))
|
||||||
|
{
|
||||||
|
result = DQN_MEM_ARENA_ALLOC(arena, new_size);
|
||||||
|
if (result) memcpy(result, old_ptr, old_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(void, Dqn_Allocator_Free(Dqn_Allocator *allocator, void *ptr))
|
||||||
|
{
|
||||||
|
switch (allocator->type)
|
||||||
|
{
|
||||||
|
default: break;
|
||||||
|
case Dqn_Allocator_Type::Heap:
|
||||||
|
case Dqn_Allocator_Type::XHeap:
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Dqn_Allocator_Type::Arena:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// @ -------------------------------------------------------------------------------------------------
|
// @ -------------------------------------------------------------------------------------------------
|
||||||
// @
|
// @
|
||||||
// @ NOTE: Vectors
|
// @ NOTE: Vectors
|
||||||
@ -1842,8 +2062,9 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsWhitespace(char ch))
|
|||||||
// @ NOTE: String Helpers
|
// @ NOTE: String Helpers
|
||||||
// @
|
// @
|
||||||
// @ -------------------------------------------------------------------------------------------------
|
// @ -------------------------------------------------------------------------------------------------
|
||||||
DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Str_Equals(char const *a, Dqn_isize a_len, char const *b, Dqn_isize b_len = -1))
|
DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Str_Equals(char const *a, char const *b, Dqn_isize a_len = -1, Dqn_isize b_len = -1))
|
||||||
{
|
{
|
||||||
|
if (a_len == -1) a_len = strlen(a);
|
||||||
if (b_len == -1) b_len = strlen(b);
|
if (b_len == -1) b_len = strlen(b);
|
||||||
if (a_len != b_len) return false;
|
if (a_len != b_len) return false;
|
||||||
return (strncmp(a, b, a_len) == 0);
|
return (strncmp(a, b, a_len) == 0);
|
||||||
@ -2081,6 +2302,7 @@ DQN_HEADER_COPY_PROTOTYPE(char *, Dqn_File_ReadWithArena(Dqn_MemArena *arena, ch
|
|||||||
if (file_size) *file_size = file_size_;
|
if (file_size) *file_size = file_size_;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#undef _CRT_SECURE_NO_WARNINGS
|
||||||
#endif // DQN_IMPLEMENTATION
|
#endif // DQN_IMPLEMENTATION
|
||||||
|
|
||||||
#ifdef STB_SPRINTF_IMPLEMENTATION
|
#ifdef STB_SPRINTF_IMPLEMENTATION
|
||||||
|
@ -252,12 +252,12 @@ struct Dqn_MemArenaScopedRegion
|
|||||||
#define DQN_DEBUG_PARAMS
|
#define DQN_DEBUG_PARAMS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DQN_MEM_ARENA_ALLOC(arena, size) Dqn_MemArena_Alloc(arena, size DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_ALLOC(arena, size) Dqn_MemArena_Alloc(arena, size DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_ALLOC_ARRAY(arena, T, num) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) * num DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_ALLOC_ARRAY(arena, T, num) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) * num DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_ALLOC_STRUCT(arena, T) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_ALLOC_STRUCT(arena, T) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_RESERVE(arena, size) Dqn_MemArena_Reserve(arena, size DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_RESERVE(arena, size) Dqn_MemArena_Reserve(arena, size DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_RESERVE_FROM(arena, src, size) Dqn_MemArena_ReserveFrom(arena, src, size DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_RESERVE_FROM(arena, src, size) Dqn_MemArena_ReserveFrom(arena, src, size DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_CLEAR_USED(arena) Dqn_MemArena_ClearUsed(arena DQN_DEBUG_PARAMS);
|
#define DQN_MEM_ARENA_CLEAR_USED(arena) Dqn_MemArena_ClearUsed(arena DQN_DEBUG_PARAMS)
|
||||||
#define DQN_MEM_ARENA_FREE(arena) Dqn_MemArena_Free
|
#define DQN_MEM_ARENA_FREE(arena) Dqn_MemArena_Free
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
@ -362,16 +362,33 @@ template <typename T, int MAX_> T *Dqn_FixedStack_Peek (Dqn_FixedStack<T, MAX_
|
|||||||
template <typename T, int MAX_> T *Dqn_FixedStack_Push (Dqn_FixedStack<T, MAX_> *array, T item) { return Dqn_FixedArray_Add(array, item); }
|
template <typename T, int MAX_> T *Dqn_FixedStack_Push (Dqn_FixedStack<T, MAX_> *array, T item) { return Dqn_FixedArray_Add(array, item); }
|
||||||
template <typename T, int MAX_> void Dqn_FixedStack_Clear(Dqn_FixedStack<T, MAX_> *array) { Dqn_FixedArray_Clear(array); }
|
template <typename T, int MAX_> void Dqn_FixedStack_Clear(Dqn_FixedStack<T, MAX_> *array) { Dqn_FixedArray_Clear(array); }
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
enum struct Dqn_Allocator_Type
|
||||||
//
|
|
||||||
// NOTE: Dqn_StaticArray
|
|
||||||
//
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
|
||||||
template <typename T> struct Dqn_StaticArray
|
|
||||||
{
|
{
|
||||||
|
Heap, // Malloc, realloc, free
|
||||||
|
XHeap, // Malloc realloc, free, crash on failure
|
||||||
|
Arena,
|
||||||
|
NullAllocator,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Dqn_Allocator
|
||||||
|
{
|
||||||
|
Dqn_Allocator_Type type;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// NOTE: Dqn_Array
|
||||||
|
//
|
||||||
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
// TODO(doyle): Make this either initialised from memory or dynamically allocating
|
||||||
|
template <typename T> struct Dqn_Array
|
||||||
|
{
|
||||||
|
Dqn_Allocator allocator;
|
||||||
T *data;
|
T *data;
|
||||||
Dqn_isize len;
|
Dqn_isize len;
|
||||||
Dqn_isize max;
|
Dqn_isize max;
|
||||||
|
|
||||||
T const operator[](Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
T const operator[](Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||||
T operator[](Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
T operator[](Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||||
T const *begin () const { return data; }
|
T const *begin () const { return data; }
|
||||||
@ -382,15 +399,17 @@ template <typename T> struct Dqn_StaticArray
|
|||||||
T *operator+(Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; }
|
T *operator+(Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> Dqn_StaticArray<T> Dqn_StaticArray_InitMemory (T *memory, Dqn_isize max, Dqn_isize len = 0);
|
template <typename T> Dqn_Array<T> Dqn_Array_InitMemory(T *memory, Dqn_isize max, Dqn_isize len = 0);
|
||||||
template <typename T> T * Dqn_StaticArray_Add (Dqn_StaticArray<T> *a, T const *items, Dqn_isize num);
|
template <typename T> bool Dqn_Array_Reserve(Dqn_Array<T> *a, Dqn_isize size);
|
||||||
template <typename T> T * Dqn_StaticArray_Add (Dqn_StaticArray<T> *a, T const item);
|
template <typename T> void Dqn_Array_Free(Dqn_Array<T> *a);
|
||||||
template <typename T> T * Dqn_StaticArray_Make (Dqn_StaticArray<T> *a, Dqn_isize num);
|
template <typename T> T * Dqn_Array_Add(Dqn_Array<T> *a, T const *items, Dqn_isize num);
|
||||||
template <typename T> void Dqn_StaticArray_Clear (Dqn_StaticArray<T> *a);
|
template <typename T> T * Dqn_Array_Add(Dqn_Array<T> *a, T const item);
|
||||||
template <typename T> void Dqn_StaticArray_EraseStable (Dqn_StaticArray<T> *a, Dqn_isize index);
|
template <typename T> T * Dqn_Array_Make(Dqn_Array<T> *a, Dqn_isize num);
|
||||||
template <typename T> void Dqn_StaticArray_EraseUnstable(Dqn_StaticArray<T> *a, Dqn_isize index);
|
template <typename T> void Dqn_Array_Clear(Dqn_Array<T> *a, bool zero_mem = false);
|
||||||
template <typename T> void Dqn_StaticArray_Pop (Dqn_StaticArray<T> *a, Dqn_isize num);
|
template <typename T> void Dqn_Array_EraseStable(Dqn_Array<T> *a, Dqn_isize index);
|
||||||
template <typename T> T * Dqn_StaticArray_Peek (Dqn_StaticArray<T> *a);
|
template <typename T> void Dqn_Array_EraseUnstable(Dqn_Array<T> *a, Dqn_isize index);
|
||||||
|
template <typename T> void Dqn_Array_Pop(Dqn_Array<T> *a, Dqn_isize num);
|
||||||
|
template <typename T> T * Dqn_Array_Peek(Dqn_Array<T> *a);
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// NOTE: Dqn_FixedString
|
// NOTE: Dqn_FixedString
|
||||||
@ -468,6 +487,18 @@ void Dqn_MemArena_ClearUsed(Dqn_MemArena *a
|
|||||||
Dqn_MemArenaScopedRegion Dqn_MemArena_MakeScopedRegion(Dqn_MemArena *arena);
|
Dqn_MemArenaScopedRegion Dqn_MemArena_MakeScopedRegion(Dqn_MemArena *arena);
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
// NOTE: Dqn_Allocator
|
||||||
|
//
|
||||||
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
Dqn_Allocator Dqn_Allocator_NullAllocator();
|
||||||
|
Dqn_Allocator Dqn_Allocator_HeapAllocator();
|
||||||
|
Dqn_Allocator Dqn_Allocator_XHeapAllocator();
|
||||||
|
Dqn_Allocator Dqn_Allocator_ArenaAllocator(Dqn_MemArena *arena);
|
||||||
|
void * Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_usize size);
|
||||||
|
void * Dqn_Allocator_Realloc(Dqn_Allocator *allocator, void *old_ptr, Dqn_isize old_size, Dqn_isize new_size);
|
||||||
|
void Dqn_Allocator_Free(Dqn_Allocator *allocator, void *ptr);
|
||||||
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
// NOTE: Vectors
|
// NOTE: Vectors
|
||||||
//
|
//
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
@ -549,7 +580,7 @@ Dqn_b32 Dqn_Char_IsWhitespace(char ch);
|
|||||||
// NOTE: String Helpers
|
// NOTE: String Helpers
|
||||||
//
|
//
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
Dqn_b32 Dqn_Str_Equals(char const *a, Dqn_isize a_len, char const *b, Dqn_isize b_len = -1);
|
Dqn_b32 Dqn_Str_Equals(char const *a, char const *b, Dqn_isize a_len = -1, Dqn_isize b_len = -1);
|
||||||
char const * Dqn_Str_FindMulti(char const *buf, char const *find_list[], Dqn_isize const *find_string_lens, Dqn_isize find_len, Dqn_isize *match_index, Dqn_isize buf_len = -1);
|
char const * Dqn_Str_FindMulti(char const *buf, char const *find_list[], Dqn_isize const *find_string_lens, Dqn_isize find_len, Dqn_isize *match_index, Dqn_isize buf_len = -1);
|
||||||
char const * Dqn_Str_Find(char const *buf, char const *find, Dqn_isize buf_len = -1, Dqn_isize find_len = -1);
|
char const * Dqn_Str_Find(char const *buf, char const *find, Dqn_isize buf_len = -1, Dqn_isize find_len = -1);
|
||||||
Dqn_b32 Dqn_Str_Match(char const *src, char const *find, int find_len);
|
Dqn_b32 Dqn_Str_Match(char const *src, char const *find, int find_len);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#define DQN_USE_PRIMITIVE_TYPEDEFS
|
#define DQN_USE_PRIMITIVE_TYPEDEFS
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define DQN_IMPLEMENTATION
|
||||||
#include "Dqn.h"
|
#include "Dqn.h"
|
||||||
|
|
||||||
struct TestState
|
struct TestState
|
||||||
@ -106,6 +106,173 @@ void TestState_PrintResult(TestState const *result)
|
|||||||
FILE_SCOPE void UnitTests()
|
FILE_SCOPE void UnitTests()
|
||||||
{
|
{
|
||||||
TestingState testing_state = {};
|
TestingState testing_state = {};
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// NOTE: Dqn_Allocator
|
||||||
|
//
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
{
|
||||||
|
TEST_DECLARE_GROUP_SCOPED(testing_state, "Dqn_Allocator");
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "HeapAllocator - Allocate Small");
|
||||||
|
Dqn_Allocator allocator = Dqn_Allocator_HeapAllocator();
|
||||||
|
char constexpr EXPECT[] = "hello_world";
|
||||||
|
char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, Dqn_ArrayCount(EXPECT));
|
||||||
|
DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); };
|
||||||
|
memcpy(buf, EXPECT, Dqn_ArrayCount(EXPECT));
|
||||||
|
TEST_EXPECT_MSG(testing_state, memcmp(EXPECT, buf, Dqn_ArrayCount(EXPECT)) == 0, "buf: %s, expect: %s", buf, EXPECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "XHeapAllocator - Allocate Small");
|
||||||
|
Dqn_Allocator allocator = Dqn_Allocator_XHeapAllocator();
|
||||||
|
char constexpr EXPECT[] = "hello_world";
|
||||||
|
char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, Dqn_ArrayCount(EXPECT));
|
||||||
|
DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); };
|
||||||
|
memcpy(buf, EXPECT, Dqn_ArrayCount(EXPECT));
|
||||||
|
TEST_EXPECT_MSG(testing_state, memcmp(EXPECT, buf, Dqn_ArrayCount(EXPECT)) == 0, "buf: %s, expect: %s", buf, EXPECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "ArenaAllocator - Allocate Small");
|
||||||
|
Dqn_MemArena arena = {};
|
||||||
|
Dqn_Allocator allocator = Dqn_Allocator_ArenaAllocator(&arena);
|
||||||
|
char constexpr EXPECT[] = "hello_world";
|
||||||
|
char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, Dqn_ArrayCount(EXPECT));
|
||||||
|
DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); };
|
||||||
|
memcpy(buf, EXPECT, Dqn_ArrayCount(EXPECT));
|
||||||
|
TEST_EXPECT_MSG(testing_state, memcmp(EXPECT, buf, Dqn_ArrayCount(EXPECT)) == 0, "buf: %s, expect: %s", buf, EXPECT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// NOTE: Dqn_Array
|
||||||
|
//
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
{
|
||||||
|
TEST_DECLARE_GROUP_SCOPED(testing_state, "Dqn_Array");
|
||||||
|
// NOTE: Dqn_Array_InitMemory
|
||||||
|
{
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "Fixed Memory: Test add single item and can't allocate more");
|
||||||
|
int memory[4] = {};
|
||||||
|
Dqn_Array<int> array = Dqn_Array_InitMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||||
|
Dqn_Array_Add(&array, 1);
|
||||||
|
Dqn_Array_Add(&array, 2);
|
||||||
|
Dqn_Array_Add(&array, 3);
|
||||||
|
Dqn_Array_Add(&array, 4);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data %d", array.data[0]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[1] == 2, "array.data %d", array.data[1]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[2] == 3, "array.data %d", array.data[2]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[3] == 4, "array.data %d", array.data[3]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 4, "array.len: %d", array.len);
|
||||||
|
|
||||||
|
int *added_item = Dqn_Array_Add(&array, 5);
|
||||||
|
TEST_EXPECT(testing_state, added_item == nullptr);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 4, "array.len: %d", array.len);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "Fixed Memory: Test add array of items");
|
||||||
|
int memory[4] = {};
|
||||||
|
int DATA[] = {1, 2, 3};
|
||||||
|
Dqn_Array<int> array = Dqn_Array_InitMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||||
|
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data %d", array.data[0]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[1] == 2, "array.data %d", array.data[1]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[2] == 3, "array.data %d", array.data[2]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 3, "array.len: %d", array.len);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "Fixed Memory: Test clear and clear with memory zeroed");
|
||||||
|
int memory[4] = {};
|
||||||
|
int DATA[] = {1, 2, 3};
|
||||||
|
Dqn_Array<int> array = Dqn_Array_InitMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||||
|
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||||
|
Dqn_Array_Clear(&array, false /*zero_mem*/);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 0, "array.len: %d", array.len);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data %d. Clear but don't zero memory so old values should still remain", array.data[0]);
|
||||||
|
|
||||||
|
Dqn_Array_Clear(&array, true /*zero_mem*/);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[0] == 0, "array.data %d. Clear but zero memory old values should not remain", array.data[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "Fixed Memory: Test erase stable and erase unstable");
|
||||||
|
int memory[4] = {};
|
||||||
|
int DATA[] = {1, 2, 3, 4};
|
||||||
|
Dqn_Array<int> array = Dqn_Array_InitMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||||
|
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||||
|
Dqn_Array_EraseUnstable(&array, 1);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data %d", array.data[0]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[1] == 4, "array.data %d", array.data[1]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[2] == 3, "array.data %d", array.data[2]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 3, "array.len: %d", array.len);
|
||||||
|
|
||||||
|
Dqn_Array_EraseStable(&array, 0);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[0] == 4, "array.data: %d", array.data[0]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[1] == 3, "array.data: %d", array.data[1]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 2, "array.len: %d", array.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "Fixed Memory: Test array pop and peek");
|
||||||
|
int memory[4] = {};
|
||||||
|
int DATA[] = {1, 2, 3};
|
||||||
|
Dqn_Array<int> array = Dqn_Array_InitMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||||
|
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||||
|
Dqn_Array_Pop(&array, 2);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data: %d", array.data[0]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 1, "array.len: %d", array.len);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||||
|
|
||||||
|
int *peek_item = Dqn_Array_Peek(&array);
|
||||||
|
TEST_EXPECT_MSG(testing_state, *peek_item == 1, "peek: %d", *peek_item);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 1, "array.len: %d", array.len);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "Fixed Memory: Test free on fixed memory array does nothing");
|
||||||
|
int memory[4] = {};
|
||||||
|
Dqn_Array<int> array = Dqn_Array_InitMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||||
|
DQN_DEFER { Dqn_Array_Free(&array); };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Dynamic Memory: Dqn_Array
|
||||||
|
{
|
||||||
|
{
|
||||||
|
TEST_START_SCOPE(testing_state, "Dynamic Memory: Test reserve and over commit reallocates");
|
||||||
|
Dqn_Array<int> array = {};
|
||||||
|
DQN_DEFER { Dqn_Array_Free(&array); };
|
||||||
|
|
||||||
|
Dqn_Array_Reserve(&array, 4);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 0, "array.len: %d", array.len);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||||
|
|
||||||
|
int DATA[] = {1, 2, 3, 4};
|
||||||
|
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data: %d", array.data[0]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[1] == 2, "array.data: %d", array.data[1]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[2] == 3, "array.data: %d", array.data[2]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[3] == 4, "array.data: %d", array.data[3]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 4, "array.len: %d", array.len);
|
||||||
|
|
||||||
|
int *added_item = Dqn_Array_Add(&array, 5);
|
||||||
|
TEST_EXPECT_MSG(testing_state, *added_item == 5, "added_item: %d", *added_item);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.data[4] == 5, "array.data: %d", array.data[4]);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.len == 5, "array.len: %d", array.len);
|
||||||
|
TEST_EXPECT_MSG(testing_state, array.max >= 5, "array.max: %d", array.max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// NOTE: Dqn_StringBuilder
|
// NOTE: Dqn_StringBuilder
|
||||||
|
Loading…
Reference in New Issue
Block a user