Remove C-style api for strings, fix stack alloc bug

This commit is contained in:
Doyle Thai 2017-10-28 23:25:17 +11:00
parent bfa00944c6
commit 3ee5500124
2 changed files with 153 additions and 181 deletions

281
dqn.h
View File

@ -202,6 +202,7 @@ DQN_FILE_SCOPE void *DqnMem_Calloc (const size_t size);
DQN_FILE_SCOPE void DqnMem_Clear (void *const memory, const u8 clearValue, const size_t size); DQN_FILE_SCOPE void DqnMem_Clear (void *const memory, const u8 clearValue, const size_t size);
DQN_FILE_SCOPE void *DqnMem_Realloc(void *memory, const size_t newSize); DQN_FILE_SCOPE void *DqnMem_Realloc(void *memory, const size_t newSize);
DQN_FILE_SCOPE void DqnMem_Free (void *memory); DQN_FILE_SCOPE void DqnMem_Free (void *memory);
DQN_FILE_SCOPE void DqnMem_Copy (u8 *const dest, u8 *const src, const i64 numBytesToCopy);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// #DqnMemStack Public API - Memory Allocator, Push, Pop Style // #DqnMemStack Public API - Memory Allocator, Push, Pop Style
@ -545,7 +546,7 @@ bool DqnArray<T>::Grow()
const f32 GROWTH_FACTOR = 2.0f; const f32 GROWTH_FACTOR = 2.0f;
i64 newMax = (i64)(this->max * GROWTH_FACTOR); i64 newMax = (i64)(this->max * GROWTH_FACTOR);
if (newMax == this->capacity) newMax++; if (newMax == this->max) newMax++;
bool result = this->Resize(newMax); bool result = this->Resize(newMax);
return result; return result;
@ -555,9 +556,9 @@ template <typename T>
T *DqnArray<T>::Push(const T *item, const i64 num) T *DqnArray<T>::Push(const T *item, const i64 num)
{ {
i64 newSize = this->count + num; i64 newSize = this->count + num;
if (this->count + num > this->max) if (newSize > this->max)
{ {
if (!this->Resize(newSize)) return NULL; if (!this->Grow()) return NULL;
} }
DQN_ASSERT(this->count < this->max); DQN_ASSERT(this->count < this->max);
@ -999,20 +1000,6 @@ struct DqnString
wchar_t *ToWChar(DqnMemAPI api = DqnMemAPI_HeapAllocator()); wchar_t *ToWChar(DqnMemAPI api = DqnMemAPI_HeapAllocator());
}; };
bool DqnString_InitSize (DqnString *const str, const i32 size, const DqnMemAPI api);
bool DqnString_InitFixedMem (DqnString *const str, char *const memory, const i32 sizeInBytes);
bool DqnString_InitLiteral (DqnString *const str, const char *const cstr, const DqnMemAPI api);
bool DqnString_InitWLiteral (DqnString *const str, const wchar_t *const cstr, const DqnMemAPI api);
bool DqnString_InitLiteralNoAlloc(DqnString *const str, char *const cstr, i32 cstrLen = -1);
bool DqnString_Expand (DqnString *const str, const i32 newMax);
bool DqnString_AppendCStr(DqnString *const str, const char *const cstr, i32 bytesToCopy = -1);
bool DqnString_AppendStr (DqnString *const str, const DqnString strToAppend, i32 bytesToCopy = -1);
void DqnString_Free (DqnString *const str);
i32 DqnString_ToWCharUseBuf(const DqnString *const str, wchar_t *const buf, const i32 bufSize);
wchar_t *DqnString_ToWChar (const DqnString *const str, const DqnMemAPI api);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// #DqnRnd Public API - Random Number Generator // #DqnRnd Public API - Random Number Generator
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -2038,6 +2025,12 @@ DQN_FILE_SCOPE void DqnMem_Free(void *memory)
if (memory) free(memory); if (memory) free(memory);
} }
DQN_FILE_SCOPE void DqnMem_Copy(u8 *const dest, u8 *const src, const i64 numBytesToCopy)
{
for (auto i = 0; i < numBytesToCopy; i++)
dest[i] = src[i];
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// #DqnMemStackInternal Implementation // #DqnMemStackInternal Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -2517,68 +2510,71 @@ FILE_SCOPE DqnMemAPICallbackResult DqnMemAPIInternal_StackAllocatorCallback(DqnM
break; break;
case DqnMemAPICallbackType_Realloc: case DqnMemAPICallbackType_Realloc:
case DqnMemAPICallbackType_Free:
{ {
// IMPORTANT: This is a _naive_ realloc scheme for stack allocation. // IMPORTANT: This is a _naive_ realloc scheme for stack allocation.
result.type = info.type; result.type = info.type;
DqnMemStackBlock *block = stack->block; DqnMemStackBlock *block = stack->block;
u8 *currUsagePtr = (u8 *)(block->memory + block->used); u8 *currUsagePtr = (u8 *)(block->memory + block->used);
u8 *checkPtr = currUsagePtr - info.oldSize; u8 *checkPtr = currUsagePtr - DQN_ALIGN_POW_N(info.oldSize, stack->byteAlign);
// Last allocation, can safely allocate the remainder space. if (info.type == DqnMemAPICallbackType_Realloc)
if (checkPtr == (u8 *)info.oldMemPtr)
{ {
size_t remainingBytesToAlloc = info.newRequestSize - info.oldSize; // Last allocation, can safely allocate the remainder space.
DQN_ASSERT_HARD(remainingBytesToAlloc > 0); if (checkPtr == (u8 *)info.oldMemPtr || info.oldMemPtr == block->memory)
bool enoughSpace =
(currUsagePtr + remainingBytesToAlloc) < (block->memory + block->size);
if (enoughSpace)
{ {
result.newMemPtr = info.oldMemPtr; size_t remainingBytesToAlloc = info.newRequestSize - info.oldSize;
u8 *startPtr = (u8 *)stack->Push(remainingBytesToAlloc); DQN_ASSERT_HARD(remainingBytesToAlloc > 0);
if (info.clearToZero) bool enoughSpace =
(currUsagePtr + remainingBytesToAlloc) < (block->memory + block->size);
if (enoughSpace)
{ {
DqnMem_Clear(startPtr, 0, remainingBytesToAlloc); result.newMemPtr = info.oldMemPtr;
u8 *startPtr = (u8 *)stack->Push(remainingBytesToAlloc);
DQN_ASSERT_HARD(stack->block == block);
if (info.clearToZero)
{
DqnMem_Clear(startPtr, 0, remainingBytesToAlloc);
}
return result;
} }
return result; // Else, last allocation but not enough space in block. Create a new block and
// copy
DqnMemStackBlock *newBlock =
stack->AllocateCompatibleBlock(info.newRequestSize, info.clearToZero);
if (newBlock)
{
DqnMem_Copy((u8 *)result.newMemPtr, (u8 *)info.oldMemPtr, info.oldSize);
stack->Pop(info.oldMemPtr, info.oldSize);
stack->AttachBlock(block);
result.newMemPtr = stack->block->memory;
}
}
else
{
// NOTE: Lost memory when this case occurs.
result.newMemPtr = stack->Push(info.newRequestSize);
if (result.newMemPtr)
{
DqnMem_Copy((u8 *)result.newMemPtr, (u8 *)info.oldMemPtr, info.oldSize);
}
} }
// Else, last allocation but not enough space in block. Pop does
// not destroy the memory contents so this is safe.
stack->Pop(info.oldMemPtr, info.oldSize);
result.newMemPtr = stack->Push(info.newRequestSize);
return result; return result;
} }
else
// NOTE: Lost memory when this case occurs.
result.newMemPtr = stack->Push(info.newRequestSize);
if (result.newMemPtr)
{ {
u8 *dest = (u8 *)result.newMemPtr; if (checkPtr == (u8 *)info.oldMemPtr)
u8 *src = (u8 *)info.oldMemPtr; stack->Pop(info.oldMemPtr, info.oldSize);
for (size_t i = 0; i < info.oldSize; i++)
dest[i] = src[i];
} }
return result;
}
break;
case DqnMemAPICallbackType_Free:
{
result.type = info.type;
DqnMemStackBlock *block = stack->block;
u8 *currUsagePtr = (u8 *)(block->memory + block->used);
u8 *checkPtr = currUsagePtr - info.oldSize;
if (checkPtr == (u8 *)info.oldMemPtr)
stack->Pop(info.oldMemPtr, info.oldSize);
} }
break; break;
@ -4341,83 +4337,78 @@ DQN_FILE_SCOPE i32 Dqn_I32ToWstr(i32 value, wchar_t *buf, i32 bufSize)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// #DqnString Impleemntation // #DqnString Impleemntation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE bool DqnString_InitSize(DqnString *const str, const i32 size, const DqnMemAPI api) DQN_FILE_SCOPE bool DqnString::InitSize(const i32 size, const DqnMemAPI api)
{ {
if (!str) return false; size_t allocSize = sizeof(*(this->str)) * (size + 1);
size_t allocSize = sizeof(*(str->str)) * (size + 1);
DqnMemAPICallbackInfo info = DqnMemAPIInternal_CallbackInfoAskAlloc(api, allocSize); DqnMemAPICallbackInfo info = DqnMemAPIInternal_CallbackInfoAskAlloc(api, allocSize);
DqnMemAPICallbackResult result = api.callback(info); DqnMemAPICallbackResult result = api.callback(info);
str->str = (char *)result.newMemPtr; this->str = (char *)result.newMemPtr;
if (!str->str) return false; if (!this->str) return false;
str->len = 0; this->len = 0;
str->max = size; this->max = size;
str->isFreeable = true; this->isFreeable = true;
str->memAPI = api; this->memAPI = api;
return true; return true;
} }
DQN_FILE_SCOPE bool DqnString_InitFixedMem(DqnString *const str, char *const memory, DQN_FILE_SCOPE bool DqnString::InitFixedMem(char *const memory, const i32 sizeInBytes)
const i32 sizeInBytes)
{ {
if (!str || !memory) return false; if (!str || !memory) return false;
str->str = (char *)memory; this->str = (char *)memory;
str->len = 0; this->len = 0;
str->max = sizeInBytes - 1; this->max = sizeInBytes - 1;
str->memAPI = {}; this->memAPI = {};
str->isFreeable = false; this->isFreeable = false;
return true; return true;
} }
DQN_FILE_SCOPE bool DqnString_InitLiteral(DqnString *const str, const char *const cstr, DQN_FILE_SCOPE bool DqnString::InitLiteral(const char *const cstr, const DqnMemAPI api)
const DqnMemAPI api)
{ {
i32 utf8LenInBytes = 0; i32 utf8LenInBytes = 0;
str->len = DqnStr_LenUTF8((u32 *)cstr, &utf8LenInBytes); this->len = DqnStr_LenUTF8((u32 *)cstr, &utf8LenInBytes);
size_t allocSize = sizeof(*(str->str)) * (utf8LenInBytes + 1); size_t allocSize = sizeof(*(this->str)) * (utf8LenInBytes + 1);
DqnMemAPICallbackInfo info = DqnMemAPIInternal_CallbackInfoAskAlloc(api, allocSize); DqnMemAPICallbackInfo info = DqnMemAPIInternal_CallbackInfoAskAlloc(api, allocSize);
DqnMemAPICallbackResult result = api.callback(info); DqnMemAPICallbackResult result = api.callback(info);
str->str = (char *)result.newMemPtr; this->str = (char *)result.newMemPtr;
str->max = str->len; this->max = this->len;
str->memAPI = api; this->memAPI = api;
if (!str->str) return false; if (!this->str) return false;
for (i32 i = 0; i < str->len; i++) str->str[i] = cstr[i]; for (i32 i = 0; i < this->len; i++) this->str[i] = cstr[i];
str->str[str->len] = 0; this->str[this->len] = 0;
str->isFreeable = true; this->isFreeable = true;
return true; return true;
} }
DQN_FILE_SCOPE bool DqnString_InitWLiteral(DqnString *const str, const wchar_t *const cstr, DQN_FILE_SCOPE bool DqnString::InitWLiteral(const wchar_t *const cstr, const DqnMemAPI api)
const DqnMemAPI api)
{ {
#if defined(DQN_IS_WIN32) && defined(DQN_WIN32_IMPLEMENTATION) #if defined(DQN_IS_WIN32) && defined(DQN_WIN32_IMPLEMENTATION)
i32 requiredLen = DqnWin32_WCharToUTF8(cstr, nullptr, 0); i32 requiredLen = DqnWin32_WCharToUTF8(cstr, nullptr, 0);
str->len = requiredLen - 1; this->len = requiredLen - 1;
size_t allocSize = sizeof(*(str->str)) * (str->len + 1); size_t allocSize = sizeof(*(this->str)) * (this->len + 1);
DqnMemAPICallbackInfo info = DqnMemAPIInternal_CallbackInfoAskAlloc(api, allocSize); DqnMemAPICallbackInfo info = DqnMemAPIInternal_CallbackInfoAskAlloc(api, allocSize);
DqnMemAPICallbackResult result = api.callback(info); DqnMemAPICallbackResult result = api.callback(info);
str->str = (char *)result.newMemPtr; this->str = (char *)result.newMemPtr;
str->max = str->len; this->max = this->len;
str->memAPI = api; this->memAPI = api;
if (!str->str) return false; if (!this->str) return false;
i32 convertResult = DqnWin32_WCharToUTF8(cstr, str->str, str->len + 1); i32 convertResult = DqnWin32_WCharToUTF8(cstr, this->str, this->len + 1);
DQN_ASSERT(convertResult != -1); DQN_ASSERT(convertResult != -1);
str->str[str->len] = 0; this->str[this->len] = 0;
str->isFreeable = true; this->isFreeable = true;
return true; return true;
#else #else
@ -4427,51 +4418,50 @@ DQN_FILE_SCOPE bool DqnString_InitWLiteral(DqnString *const str, const wchar_t *
#endif #endif
} }
DQN_FILE_SCOPE bool DqnString_InitLiteralNoAlloc(DqnString *const str, char *const cstr, DQN_FILE_SCOPE bool DqnString::InitLiteralNoAlloc(char *const cstr, i32 cstrLen)
i32 cstrLen)
{ {
if (!str || !cstr) return false; if (!str || !cstr) return false;
str->str = cstr; this->str = cstr;
if (cstrLen == -1) if (cstrLen == -1)
{ {
i32 utf8LenInBytes = 0; i32 utf8LenInBytes = 0;
DqnStr_LenUTF8((u32 *)cstr, &utf8LenInBytes); DqnStr_LenUTF8((u32 *)cstr, &utf8LenInBytes);
str->len = utf8LenInBytes; this->len = utf8LenInBytes;
} }
else else
{ {
str->len = cstrLen; this->len = cstrLen;
} }
str->max = str->len; this->max = this->len;
return true; return true;
} }
DQN_FILE_SCOPE bool DqnString_Expand(DqnString *const str, const i32 newMax) DQN_FILE_SCOPE bool DqnString::Expand(const i32 newMax)
{ {
if (!str->isFreeable) return false; if (!this->isFreeable) return false;
if (!str->memAPI.callback) return false; if (!this->memAPI.callback) return false;
if (newMax < str->max) return true; if (newMax < this->max) return true;
size_t allocSize = sizeof(*(str->str)) * (newMax + 1); size_t allocSize = sizeof(*(this->str)) * (newMax + 1);
DqnMemAPICallbackInfo info = {}; DqnMemAPICallbackInfo info = {};
if (str->str) if (this->str)
{ {
info = DqnMemAPIInternal_CallbackInfoAskRealloc(str->memAPI, str->str, str->len, allocSize); info = DqnMemAPIInternal_CallbackInfoAskRealloc(this->memAPI, this->str, this->len, allocSize);
} }
else else
{ {
info = DqnMemAPIInternal_CallbackInfoAskAlloc(str->memAPI, allocSize); info = DqnMemAPIInternal_CallbackInfoAskAlloc(this->memAPI, allocSize);
} }
DqnMemAPICallbackResult result = str->memAPI.callback(info); DqnMemAPICallbackResult result = this->memAPI.callback(info);
if (result.newMemPtr) if (result.newMemPtr)
{ {
str->str = (char *)result.newMemPtr; this->str = (char *)result.newMemPtr;
str->max = newMax; this->max = newMax;
return true; return true;
} }
@ -4486,7 +4476,7 @@ DQN_FILE_SCOPE bool DqnStringInternal_AppendCStr(DqnString *const str, const cha
i32 totalLen = str->len + bytesToCopy; i32 totalLen = str->len + bytesToCopy;
if (totalLen > str->max) if (totalLen > str->max)
{ {
bool result = DqnString_Expand(str, totalLen); bool result = str->Expand(totalLen);
if (!result) return false; if (!result) return false;
} }
@ -4498,8 +4488,7 @@ DQN_FILE_SCOPE bool DqnStringInternal_AppendCStr(DqnString *const str, const cha
return true; return true;
} }
DQN_FILE_SCOPE bool DqnString_AppendCStr(DqnString *const str, const char *const cstr, DQN_FILE_SCOPE bool DqnString::AppendCStr(const char *const cstr, i32 bytesToCopy)
i32 bytesToCopy)
{ {
i32 cstrLen = 0; i32 cstrLen = 0;
if (bytesToCopy == -1) if (bytesToCopy == -1)
@ -4513,41 +4502,39 @@ DQN_FILE_SCOPE bool DqnString_AppendCStr(DqnString *const str, const char *const
cstrLen = bytesToCopy; cstrLen = bytesToCopy;
} }
bool result = DqnStringInternal_AppendCStr(str, cstr, cstrLen); bool result = DqnStringInternal_AppendCStr(this, cstr, cstrLen);
return result; return result;
} }
DQN_FILE_SCOPE bool DqnString_AppendStr(DqnString *const str, const DqnString strToAppend, DQN_FILE_SCOPE bool DqnString::AppendStr(const DqnString strToAppend, i32 bytesToCopy)
i32 bytesToCopy)
{ {
i32 cstrLen = (bytesToCopy == -1) ? strToAppend.len : bytesToCopy; i32 cstrLen = (bytesToCopy == -1) ? strToAppend.len : bytesToCopy;
bool result = DqnStringInternal_AppendCStr(str, strToAppend.str, cstrLen); bool result = DqnStringInternal_AppendCStr(this, strToAppend.str, cstrLen);
return result; return result;
} }
DQN_FILE_SCOPE void DqnString_Free(DqnString *const str) DQN_FILE_SCOPE void DqnString::Free()
{ {
if (str && str->str) if (this->str)
{ {
if (str->isFreeable) if (this->isFreeable)
{ {
DqnMemAPICallbackInfo info = DqnMemAPICallbackInfo info =
DqnMemAPIInternal_CallbackInfoAskFree(str->memAPI, str->str, str->len); DqnMemAPIInternal_CallbackInfoAskFree(this->memAPI, this->str, this->len);
str->memAPI.callback(info); this->memAPI.callback(info);
} }
str->str = NULL; this->str = NULL;
str->len = 0; this->len = 0;
str->max = 0; this->max = 0;
str->isFreeable = false; this->isFreeable = false;
} }
} }
DQN_FILE_SCOPE i32 DqnString_ToWCharUseBuf(const DqnString *const str, wchar_t *const buf, DQN_FILE_SCOPE i32 DqnString::ToWCharUseBuf(wchar_t *const buf, const i32 bufSize)
const i32 bufSize)
{ {
#if defined(DQN_IS_WIN32) && defined(DQN_WIN32_IMPLEMENTATION) #if defined(DQN_IS_WIN32) && defined(DQN_WIN32_IMPLEMENTATION)
i32 result = DqnWin32_UTF8ToWChar(str->str, buf, bufSize); i32 result = DqnWin32_UTF8ToWChar(this->str, buf, bufSize);
return result; return result;
#else #else
@ -4557,13 +4544,13 @@ DQN_FILE_SCOPE i32 DqnString_ToWCharUseBuf(const DqnString *const str, wchar_t *
#endif #endif
} }
DQN_FILE_SCOPE wchar_t *DqnString_ToWChar(const DqnString *const str, const DqnMemAPI api) DQN_FILE_SCOPE wchar_t *DqnString::ToWChar(const DqnMemAPI api)
{ {
// TODO(doyle): Should the "in" string allow specifyign len? probably // TODO(doyle): Should the "in" string allow specifyign len? probably
// Otherwise a c-string and a literal initiated string might have different lengths // Otherwise a c-string and a literal initiated string might have different lengths
// to wchar will produce an unintuitive output // to wchar will produce an unintuitive output
#if defined(DQN_IS_WIN32) && defined(DQN_WIN32_IMPLEMENTATION) #if defined(DQN_IS_WIN32) && defined(DQN_WIN32_IMPLEMENTATION)
i32 requiredLenInclNull = DqnWin32_UTF8ToWChar(str->str, nullptr, 0); i32 requiredLenInclNull = DqnWin32_UTF8ToWChar(this->str, nullptr, 0);
i32 allocSize = sizeof(wchar_t) * requiredLenInclNull; i32 allocSize = sizeof(wchar_t) * requiredLenInclNull;
DqnMemAPICallbackInfo info = DqnMemAPIInternal_CallbackInfoAskAlloc(api, allocSize); DqnMemAPICallbackInfo info = DqnMemAPIInternal_CallbackInfoAskAlloc(api, allocSize);
@ -4572,7 +4559,7 @@ DQN_FILE_SCOPE wchar_t *DqnString_ToWChar(const DqnString *const str, const DqnM
wchar_t *result = (wchar_t *)memResult.newMemPtr; wchar_t *result = (wchar_t *)memResult.newMemPtr;
if (!result) return nullptr; if (!result) return nullptr;
DqnWin32_UTF8ToWChar(str->str, result, requiredLenInclNull); DqnWin32_UTF8ToWChar(this->str, result, requiredLenInclNull);
result[requiredLenInclNull - 1] = 0; result[requiredLenInclNull - 1] = 0;
return result; return result;
@ -4583,22 +4570,6 @@ DQN_FILE_SCOPE wchar_t *DqnString_ToWChar(const DqnString *const str, const DqnM
#endif #endif
} }
////////////////////////////////////////////////////////////////////////////////
// #DqnString CPP Implementation
////////////////////////////////////////////////////////////////////////////////
bool DqnString::InitSize (const i32 size, const DqnMemAPI api) { return DqnString_InitSize(this, size, api); }
bool DqnString::InitFixedMem(char *const memory, const i32 sizeInBytes) { return DqnString_InitFixedMem(this, memory, sizeInBytes); }
bool DqnString::InitLiteral (const char *const cstr, const DqnMemAPI api) { return DqnString_InitLiteral(this, cstr, api); }
bool DqnString::InitWLiteral(const wchar_t *const cstr, const DqnMemAPI api) { return DqnString_InitWLiteral(this, cstr, api); }
bool DqnString::InitLiteralNoAlloc(char *const cstr, i32 cstrLen) { return DqnString_InitLiteralNoAlloc(this, cstr, cstrLen); }
bool DqnString::Expand (const i32 newMax) { return DqnString_Expand(this, newMax); }
bool DqnString::AppendCStr (const char *const cstr, i32 bytesToCopy) { return DqnString_AppendCStr(this, cstr, bytesToCopy); }
bool DqnString::AppendStr (const DqnString strToAppend, i32 bytesToCopy) { return DqnString_AppendStr(this, strToAppend, bytesToCopy); }
void DqnString::Free () { DqnString_Free(this); }
i32 DqnString::ToWCharUseBuf(wchar_t *const buf, const i32 bufSize) { return DqnString_ToWCharUseBuf(this, buf, bufSize); }
wchar_t *DqnString::ToWChar(const DqnMemAPI api) { return DqnString_ToWChar(this, api); }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// #DqnRnd Implementation // #DqnRnd Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -975,12 +975,12 @@ void VecTest()
void ArrayTestMemAPIInternal(const DqnMemAPI memAPI) void ArrayTestMemAPIInternal(const DqnMemAPI memAPI)
{ {
printf("Array with Default Mem API Test"); printf("Array with Default Mem API Test\n");
DqnArray<DqnV2> array = {}; DqnArray<DqnV2> array = {};
if (1) if (1)
{ {
DQN_ASSERT(array.Init(1, memAPI)); DQN_ASSERT(array.Init(1, memAPI));
DQN_ASSERT(array.max == 1); DQN_ASSERT(array.max >= 1);
DQN_ASSERT(array.count == 0); DQN_ASSERT(array.count == 0);
// Test basic insert // Test basic insert
@ -992,7 +992,7 @@ void ArrayTestMemAPIInternal(const DqnMemAPI memAPI)
DqnV2 vb = array.data[0]; DqnV2 vb = array.data[0];
DQN_ASSERT(DqnV2_Equals(va, vb)); DQN_ASSERT(DqnV2_Equals(va, vb));
DQN_ASSERT(array.max == 1); DQN_ASSERT(array.max >= 1);
DQN_ASSERT(array.count == 1); DQN_ASSERT(array.count == 1);
} }
@ -1008,48 +1008,48 @@ void ArrayTestMemAPIInternal(const DqnMemAPI memAPI)
vb = array.data[1]; vb = array.data[1];
DQN_ASSERT(DqnV2_Equals(va, vb) == true); DQN_ASSERT(DqnV2_Equals(va, vb) == true);
DQN_ASSERT(array.max == 2); DQN_ASSERT(array.max >= 2);
DQN_ASSERT(array.count == 2); DQN_ASSERT(array.count == 2);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 3); DQN_ASSERT(array.max >= 3);
DQN_ASSERT(array.count == 3); DQN_ASSERT(array.count == 3);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 4); DQN_ASSERT(array.max >= 4);
DQN_ASSERT(array.count == 4); DQN_ASSERT(array.count == 4);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 5); DQN_ASSERT(array.max >= 5);
DQN_ASSERT(array.count == 5); DQN_ASSERT(array.count == 5);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 6); DQN_ASSERT(array.max >= 6);
DQN_ASSERT(array.count == 6); DQN_ASSERT(array.count == 6);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 7); DQN_ASSERT(array.max >= 7);
DQN_ASSERT(array.count == 7); DQN_ASSERT(array.count == 7);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 8); DQN_ASSERT(array.max >= 8);
DQN_ASSERT(array.count == 8); DQN_ASSERT(array.count == 8);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 9); DQN_ASSERT(array.max >= 9);
DQN_ASSERT(array.count == 9); DQN_ASSERT(array.count == 9);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 10); DQN_ASSERT(array.max >= 10);
DQN_ASSERT(array.count == 10); DQN_ASSERT(array.count == 10);
DQN_ASSERT(array.Push(va)); DQN_ASSERT(array.Push(va));
DQN_ASSERT(array.max == 11); DQN_ASSERT(array.max >= 11);
DQN_ASSERT(array.count == 11); DQN_ASSERT(array.count == 11);
DqnV2 vc = DqnV2_2f(90, 100); DqnV2 vc = DqnV2_2f(90, 100);
DQN_ASSERT(array.Push(vc)); DQN_ASSERT(array.Push(vc));
DQN_ASSERT(array.max == 12); DQN_ASSERT(array.max >= 12);
DQN_ASSERT(array.count == 12); DQN_ASSERT(array.count == 12);
DQN_ASSERT(DqnV2_Equals(vc, array.data[11])); DQN_ASSERT(DqnV2_Equals(vc, array.data[11]));
} }
@ -1059,7 +1059,7 @@ void ArrayTestMemAPIInternal(const DqnMemAPI memAPI)
if (1) if (1)
{ {
DQN_ASSERT(array.Init(1, memAPI)); DQN_ASSERT(array.Init(1, memAPI));
DQN_ASSERT(array.max == 1); DQN_ASSERT(array.max >= 1);
DQN_ASSERT(array.count == 0); DQN_ASSERT(array.count == 0);
} }
DQN_ASSERT(array.Free()); DQN_ASSERT(array.Free());
@ -1073,41 +1073,41 @@ void ArrayTestMemAPIInternal(const DqnMemAPI memAPI)
DQN_ASSERT(array.Init(16, memAPI)); DQN_ASSERT(array.Init(16, memAPI));
DQN_ASSERT(array.Remove(0) == false); DQN_ASSERT(array.Remove(0) == false);
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 0); DQN_ASSERT(array.count == 0);
array.Clear(); array.Clear();
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 0); DQN_ASSERT(array.count == 0);
DQN_ASSERT(array.Push(a)); DQN_ASSERT(array.Push(a));
DQN_ASSERT(array.Push(b)); DQN_ASSERT(array.Push(b));
DQN_ASSERT(array.Push(c)); DQN_ASSERT(array.Push(c));
DQN_ASSERT(array.Push(d)); DQN_ASSERT(array.Push(d));
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 4); DQN_ASSERT(array.count == 4);
DQN_ASSERT(array.Remove(0)); DQN_ASSERT(array.Remove(0));
DQN_ASSERT(DqnV2_Equals(array.data[0], d)); DQN_ASSERT(DqnV2_Equals(array.data[0], d));
DQN_ASSERT(DqnV2_Equals(array.data[1], b)); DQN_ASSERT(DqnV2_Equals(array.data[1], b));
DQN_ASSERT(DqnV2_Equals(array.data[2], c)); DQN_ASSERT(DqnV2_Equals(array.data[2], c));
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 3); DQN_ASSERT(array.count == 3);
DQN_ASSERT(array.Remove(2)); DQN_ASSERT(array.Remove(2));
DQN_ASSERT(DqnV2_Equals(array.data[0], d)); DQN_ASSERT(DqnV2_Equals(array.data[0], d));
DQN_ASSERT(DqnV2_Equals(array.data[1], b)); DQN_ASSERT(DqnV2_Equals(array.data[1], b));
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 2); DQN_ASSERT(array.count == 2);
DQN_ASSERT(array.Remove(100) == false); DQN_ASSERT(array.Remove(100) == false);
DQN_ASSERT(DqnV2_Equals(array.data[0], d)); DQN_ASSERT(DqnV2_Equals(array.data[0], d));
DQN_ASSERT(DqnV2_Equals(array.data[1], b)); DQN_ASSERT(DqnV2_Equals(array.data[1], b));
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 2); DQN_ASSERT(array.count == 2);
array.Clear(); array.Clear();
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 0); DQN_ASSERT(array.count == 0);
} }
DQN_ASSERT(array.Free()); DQN_ASSERT(array.Free());
@ -1125,25 +1125,25 @@ void ArrayTestMemAPIInternal(const DqnMemAPI memAPI)
DQN_ASSERT(array.Push(b)); DQN_ASSERT(array.Push(b));
DQN_ASSERT(array.Push(c)); DQN_ASSERT(array.Push(c));
DQN_ASSERT(array.Push(d)); DQN_ASSERT(array.Push(d));
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 4); DQN_ASSERT(array.count == 4);
array.RemoveStable(0); array.RemoveStable(0);
DQN_ASSERT(DqnV2_Equals(array.data[0], b)); DQN_ASSERT(DqnV2_Equals(array.data[0], b));
DQN_ASSERT(DqnV2_Equals(array.data[1], c)); DQN_ASSERT(DqnV2_Equals(array.data[1], c));
DQN_ASSERT(DqnV2_Equals(array.data[2], d)); DQN_ASSERT(DqnV2_Equals(array.data[2], d));
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 3); DQN_ASSERT(array.count == 3);
array.RemoveStable(1); array.RemoveStable(1);
DQN_ASSERT(DqnV2_Equals(array.data[0], b)); DQN_ASSERT(DqnV2_Equals(array.data[0], b));
DQN_ASSERT(DqnV2_Equals(array.data[1], d)); DQN_ASSERT(DqnV2_Equals(array.data[1], d));
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 2); DQN_ASSERT(array.count == 2);
array.RemoveStable(1); array.RemoveStable(1);
DQN_ASSERT(DqnV2_Equals(array.data[0], b)); DQN_ASSERT(DqnV2_Equals(array.data[0], b));
DQN_ASSERT(array.max == 16); DQN_ASSERT(array.max >= 16);
DQN_ASSERT(array.count == 1); DQN_ASSERT(array.count == 1);
} }
DQN_ASSERT(array.Free()); DQN_ASSERT(array.Free());
@ -1206,6 +1206,7 @@ void ArrayTest()
auto memGuard0 = stack.TempRegionGuard(); auto memGuard0 = stack.TempRegionGuard();
DqnArray<char> array = {}; DqnArray<char> array = {};
DQN_ASSERT(array.Init(128, memAPI)); DQN_ASSERT(array.Init(128, memAPI));
stack.Push(1024);
ArrayTestRealData(&array); ArrayTestRealData(&array);
} }