Add const iterator for arrays, remove head/tail API for memstacks

This commit is contained in:
Doyle T 2018-08-03 23:30:58 +10:00
parent ed3f11dc7b
commit 2c80e53089
3 changed files with 82 additions and 46 deletions

View File

@ -385,6 +385,7 @@ FILE_SCOPE void DqnMemStack_Test()
// Check stack allocator mem api callbacks // Check stack allocator mem api callbacks
if (1) if (1)
{ {
#if 0
// Realloc in same block and allow it to grow in place. // Realloc in same block and allow it to grow in place.
if (1) if (1)
{ {
@ -517,6 +518,7 @@ FILE_SCOPE void DqnMemStack_Test()
} }
// TODO(doyle): Realloc to smaller size logic // TODO(doyle): Realloc to smaller size logic
#endif
} }
} }

View File

@ -1684,7 +1684,8 @@ void DqnArray_Test()
{ {
auto stack = auto stack =
DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard); DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroClear::Yes, DqnMemStack::Flag::BoundsGuard);
DQN_DEFER(stack.Free());
#if 0
if (1) if (1)
{ {
auto memGuard0 = stack.TempRegionGuard(); auto memGuard0 = stack.TempRegionGuard();
@ -1702,7 +1703,7 @@ void DqnArray_Test()
stack.Push(1024); stack.Push(1024);
DqnArray_TestRealDataInternal(&array); DqnArray_TestRealDataInternal(&array);
} }
stack.Free(); #endif
} }
} }
} }
@ -1863,9 +1864,7 @@ void DqnFile_Test()
u8 *buffer = (u8 *)memStack.Push(reqSize); u8 *buffer = (u8 *)memStack.Push(reqSize);
DQN_ASSERT(buffer); DQN_ASSERT(buffer);
size_t bytesRead = 0; DQN_ASSERT(DqnFile_ReadAll(fileNames[i], buffer, reqSize));
DQN_ASSERT(DqnFile_ReadAll(fileNames[i], buffer, reqSize, &bytesRead));
DQN_ASSERT(bytesRead == reqSize);
// Verify the data is the same as we wrote out // Verify the data is the same as we wrote out
DQN_ASSERT(DqnStr_Cmp((char *)buffer, (writeData[i]), (i32)reqSize) == 0); DQN_ASSERT(DqnStr_Cmp((char *)buffer, (writeData[i]), (i32)reqSize) == 0);

117
dqn.h
View File

@ -1352,7 +1352,9 @@ struct DqnArray
T &operator[] (isize i) const { DQN_ASSERT(i < count && i > 0); return this->data[i]; } T &operator[] (isize i) const { DQN_ASSERT(i < count && i > 0); return this->data[i]; }
T *begin () { return data; } T *begin () { return data; }
T *begin () const { return data; }
T *end () { return data + count; } T *end () { return data + count; }
T *end () const { return data + count; }
private: private:
isize GrowCapacity_(isize size) const { isize newMax = max ? (max * 2) : 8; return newMax > size ? newMax : size; } isize GrowCapacity_(isize size) const { isize newMax = max ? (max * 2) : 8; return newMax > size ? newMax : size; }
@ -1504,8 +1506,6 @@ struct DqnMemStack
DqnMemTracker tracker; // Read: Metadata for managing ptr allocation DqnMemTracker tracker; // Read: Metadata for managing ptr allocation
DqnMemAPI *memAPI; // Read: API used to add additional memory blocks to this stack. DqnMemAPI *memAPI; // Read: API used to add additional memory blocks to this stack.
DqnMemAPI myTailAPI; // Read: API for data structures to allocate to the tail of the stack
DqnMemAPI myHeadAPI; // Read: API for data structures to allocate to the head of the stack
Block *block; // Read: Memory block allocated for the stack Block *block; // Read: Memory block allocated for the stack
u32 flags; // Read u32 flags; // Read
i32 tempRegionCount; // Read: The number of temp memory regions in use i32 tempRegionCount; // Read: The number of temp memory regions in use
@ -2379,13 +2379,15 @@ struct DqnFileInfo
// NOTE: You want size + 1 and add the null-terminator yourself if you want a null terminated buffer. // NOTE: You want size + 1 and add the null-terminator yourself if you want a null terminated buffer.
// bytesRead: Pass in to get how many bytes of the buf was used. Basically the return value of Read // bytesRead: Pass in to get how many bytes of the buf was used. Basically the return value of Read
// return: False if insufficient bufSize OR file access failure OR nullptr arguments. // return: False if insufficient bufSize OR file access failure OR nullptr arguments.
DQN_FILE_SCOPE bool DqnFile_ReadAll(char const *path, u8 *buf, usize const bufSize, usize *bytesRead); DQN_FILE_SCOPE bool DqnFile_ReadAll(char const *path, u8 *buf, usize bufSize);
DQN_FILE_SCOPE bool DqnFile_ReadAll(wchar_t const *path, u8 *buf, usize const bufSize, usize *bytesRead); DQN_FILE_SCOPE bool DqnFile_ReadAll(wchar_t const *path, u8 *buf, usize bufSize);
// Buffer is null-terminated and should be freed when done with. // Buffer is null-terminated and should be freed when done with.
// return: False if file access failure OR nullptr arguments. // return: False if file access failure OR nullptr arguments.
DQN_FILE_SCOPE u8 *DqnFile_ReadAll(char const *path, usize *bufSize, DqnMemAPI *api = DQN_DEFAULT_HEAP_ALLOCATOR); DQN_FILE_SCOPE u8 *DqnFile_ReadAll(char const *path, usize *bufSize, DqnMemAPI *api = DQN_DEFAULT_HEAP_ALLOCATOR);
DQN_FILE_SCOPE u8 *DqnFile_ReadAll(wchar_t const *path, usize *bufSize, DqnMemAPI *api = DQN_DEFAULT_HEAP_ALLOCATOR); DQN_FILE_SCOPE u8 *DqnFile_ReadAll(wchar_t const *path, usize *bufSize, DqnMemAPI *api = DQN_DEFAULT_HEAP_ALLOCATOR);
DQN_FILE_SCOPE u8 *DqnFile_ReadAll(wchar_t const *path, usize *bufSize, DqnMemStack *stack, DqnMemStack::AllocTo allocTo = DqnMemStack::AllocTo::Head);
DQN_FILE_SCOPE u8 *DqnFile_ReadAll(char const *path, usize *bufSize, DqnMemStack *stack, DqnMemStack::AllocTo allocTo = DqnMemStack::AllocTo::Head);
DQN_FILE_SCOPE bool DqnFile_WriteAll(char const *path, u8 const *buf, usize const bufSize); DQN_FILE_SCOPE bool DqnFile_WriteAll(char const *path, u8 const *buf, usize const bufSize);
DQN_FILE_SCOPE bool DqnFile_WriteAll(wchar_t const *path, u8 const *buf, usize const bufSize); DQN_FILE_SCOPE bool DqnFile_WriteAll(wchar_t const *path, u8 const *buf, usize const bufSize);
@ -2760,7 +2762,7 @@ DQN_FILE_SCOPE void DqnLog(char const *file, char const *functionName, i32 lineN
char const *const formatStr = "%s:%s,%d: DqnLog: %s\n"; char const *const formatStr = "%s:%s,%d: DqnLog: %s\n";
fprintf(stderr, formatStr, file, functionName, lineNum, userMsg); fprintf(stderr, formatStr, file, functionName, lineNum, userMsg);
#if defined(DQN_IS_WIN32) #if defined(DQN_PLATFORM_IMPLEMENTATION) && defined(DQN_IS_WIN32)
DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, userMsg); DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, userMsg);
#endif #endif
} }
@ -2795,7 +2797,7 @@ DQN_FILE_SCOPE void DqnLogExpr(char const *file, char const *functionName, i32 l
char const *const formatStr = ":%s:%s,%d(%s): DqnLog: %s\n"; char const *const formatStr = ":%s:%s,%d(%s): DqnLog: %s\n";
fprintf(stderr, formatStr, file, functionName, lineNum, expr, userMsg); fprintf(stderr, formatStr, file, functionName, lineNum, expr, userMsg);
#if defined(DQN_IS_WIN32) #if defined(DQN_PLATFORM_IMPLEMENTATION) && defined(DQN_IS_WIN32)
DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, expr, userMsg); DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, expr, userMsg);
#endif #endif
} }
@ -3313,8 +3315,6 @@ DqnMemStack::DqnMemStack(void *mem, isize size, Dqn::ZeroClear clear, u32 flags_
this->block = static_cast<DqnMemStack::Block *>(mem); this->block = static_cast<DqnMemStack::Block *>(mem);
*this->block = Block(blockOffset, blockSize); *this->block = Block(blockOffset, blockSize);
this->myHeadAPI = DqnMemAPI::StackAllocator(this, DqnMemAPI::StackPushType::Head);
this->myTailAPI = DqnMemAPI::StackAllocator(this, DqnMemAPI::StackPushType::Tail);
this->flags = (flags_ | Flag::NonExpandable); this->flags = (flags_ | Flag::NonExpandable);
bool boundsGuard = Dqn_BitIsSet(this->flags, Flag::BoundsGuard); bool boundsGuard = Dqn_BitIsSet(this->flags, Flag::BoundsGuard);
@ -3329,9 +3329,6 @@ DqnMemStack::DqnMemStack(isize size, Dqn::ZeroClear clear, u32 flags_, DqnMemAPI
this->block = DqnMemStack__AllocateBlock(size, clear, api); this->block = DqnMemStack__AllocateBlock(size, clear, api);
this->flags = flags_; this->flags = flags_;
this->memAPI = api; this->memAPI = api;
this->myHeadAPI = DqnMemAPI::StackAllocator(this, DqnMemAPI::StackPushType::Head);
this->myTailAPI = DqnMemAPI::StackAllocator(this, DqnMemAPI::StackPushType::Tail);
bool boundsGuard = Dqn_BitIsSet(this->flags, Flag::BoundsGuard); bool boundsGuard = Dqn_BitIsSet(this->flags, Flag::BoundsGuard);
this->tracker.Init(boundsGuard); this->tracker.Init(boundsGuard);
} }
@ -3366,6 +3363,12 @@ void *DqnMemStack::Push(isize size, AllocTo allocTo, u8 alignment)
return nullptr; return nullptr;
} }
if (!this->block && !this->memAPI) // we assume this is a zero initialised mem stack
{
this->memAPI = DQN_DEFAULT_HEAP_ALLOCATOR;
this->tracker.Init(Dqn_BitIsSet(this->flags, DqnMemStack::Flag::BoundsGuard));
}
isize newBlockSize = DQN_MAX(sizeToAllocate, MINIMUM_BLOCK_SIZE); isize newBlockSize = DQN_MAX(sizeToAllocate, MINIMUM_BLOCK_SIZE);
Block *newBlock = DqnMemStack__AllocateBlock(newBlockSize, Dqn::ZeroClear::No, this->memAPI); Block *newBlock = DqnMemStack__AllocateBlock(newBlockSize, Dqn::ZeroClear::No, this->memAPI);
newBlock->prevBlock = this->block; newBlock->prevBlock = this->block;
@ -5727,7 +5730,7 @@ DQN_FILE_SCOPE DqnJson DqnJson_Get(char const *buf, i32 bufLen, char const *find
bufLen = static_cast<int>((buf + bufLen) - tmp); bufLen = static_cast<int>((buf + bufLen) - tmp);
buf = tmp; buf = tmp;
bool const findStructureInGlobalScope = (findPropertyLen == 1 && (findProperty[0] == '{' || findProperty[0] == '[')); bool const findStructureInGlobalScope = ((findProperty[0] == '{' || findProperty[0] == '['));
if ((buf[0] == '{' || buf[1] == '[') && !findStructureInGlobalScope) if ((buf[0] == '{' || buf[1] == '[') && !findStructureInGlobalScope)
{ {
@ -8005,7 +8008,7 @@ usize DqnFile::Write(u8 const *buf, usize numBytesToWrite, usize fileOffset)
usize DqnFile::Read(u8 *buf, usize numBytesToRead) usize DqnFile::Read(u8 *buf, usize numBytesToRead)
{ {
usize numBytesRead = 0; usize numBytesRead = 0;
if (this->handle) if (buf && this->handle)
{ {
#if defined(DQN_IS_WIN32) #if defined(DQN_IS_WIN32)
DWORD bytesToRead = (DWORD)numBytesToRead; DWORD bytesToRead = (DWORD)numBytesToRead;
@ -8043,21 +8046,12 @@ u8 *DqnFile_ReadAll(wchar_t const *path, usize *bufSize, DqnMemAPI *api)
// TODO(doyle): Logging // TODO(doyle): Logging
usize requiredSize = 0; usize requiredSize = 0;
if (!DqnFile_Size(path, &requiredSize) || requiredSize == 0) if (!DqnFile_Size(path, &requiredSize) || requiredSize == 0)
{
return nullptr; return nullptr;
}
auto *buf = (u8 *)api->Alloc(requiredSize, Dqn::ZeroClear::No); auto *buf = (u8 *)api->Alloc(requiredSize, Dqn::ZeroClear::No);
if (!buf) if (DqnFile_ReadAll(path, buf, requiredSize))
{ {
return nullptr; *bufSize = requiredSize;
}
usize bytesRead = 0;
if (DqnFile_ReadAll(path, buf, requiredSize, &bytesRead))
{
*bufSize = requiredSize;
DQN_ASSERTM(bytesRead == requiredSize, "%zu != %zu", bytesRead, requiredSize);
return buf; return buf;
} }
@ -8065,26 +8059,17 @@ u8 *DqnFile_ReadAll(wchar_t const *path, usize *bufSize, DqnMemAPI *api)
return nullptr; return nullptr;
} }
u8 *DqnFile_ReadAll(char const *path, usize *bufSize, DqnMemAPI *api) DQN_FILE_SCOPE u8 *DqnFile_ReadAll(char const *path, usize *bufSize, DqnMemAPI *api)
{ {
// TODO(doyle): Logging // TODO(doyle): Logging
usize requiredSize = 0; usize requiredSize = 0;
if (!DqnFile_Size(path, &requiredSize) || requiredSize == 0) if (!DqnFile_Size(path, &requiredSize) || requiredSize == 0)
{
return nullptr; return nullptr;
}
auto *buf = (u8 *)api->Alloc(requiredSize, Dqn::ZeroClear::No); auto *buf = (u8 *)api->Alloc(requiredSize, Dqn::ZeroClear::No);
if (!buf) if (DqnFile_ReadAll(path, buf, requiredSize))
{
return nullptr;
}
usize bytesRead = 0;
if (DqnFile_ReadAll(path, buf, requiredSize, &bytesRead))
{ {
*bufSize = requiredSize; *bufSize = requiredSize;
DQN_ASSERTM(bytesRead == requiredSize, "%zu != %zu", bytesRead, requiredSize);
return buf; return buf;
} }
@ -8092,6 +8077,56 @@ u8 *DqnFile_ReadAll(char const *path, usize *bufSize, DqnMemAPI *api)
return nullptr; return nullptr;
} }
DQN_FILE_SCOPE u8 *DqnFile_ReadAll(wchar_t const *path, usize *bufSize, DqnMemStack *stack, DqnMemStack::AllocTo allocTo)
{
u8 *result = nullptr;
DqnFile file = {};
if (!file.Open(path, DqnFile::Flag::FileRead, DqnFile::Action::OpenOnly))
{
DQN_LOGE("Could not open file: %s", path);
return result;
}
DQN_DEFER(file.Close());
result = static_cast<u8 *>(stack->Push(file.size, allocTo));
usize bytesRead = file.Read(result, file.size);
if (bytesRead == file.size)
{
*bufSize = file.size;
}
else
{
DQN_LOGE("bytesRead != file.size", bytesRead, file.size);
}
return result;
}
DQN_FILE_SCOPE u8 *DqnFile_ReadAll(char const *path, usize *bufSize, DqnMemStack *stack, DqnMemStack::AllocTo allocTo)
{
u8 *result = nullptr;
DqnFile file = {};
if (!file.Open(path, DqnFile::Flag::FileRead, DqnFile::Action::OpenOnly))
{
DQN_LOGE("Could not open file: %s", path);
return result;
}
DQN_DEFER(file.Close());
result = static_cast<u8 *>(stack->Push(file.size, allocTo));
usize bytesRead = file.Read(result, file.size);
if (bytesRead == file.size)
{
*bufSize = file.size;
}
else
{
DQN_LOGE("bytesRead != file.size", bytesRead, file.size);
}
return result;
}
DQN_FILE_SCOPE bool DqnFile_WriteAll(char const *path, u8 const *buf, usize const bufSize) DQN_FILE_SCOPE bool DqnFile_WriteAll(char const *path, u8 const *buf, usize const bufSize)
{ {
DqnFile file = {}; DqnFile file = {};
@ -8132,7 +8167,7 @@ DQN_FILE_SCOPE bool DqnFile_WriteAll(wchar_t const *path, u8 const *buf, usize c
return true; return true;
} }
bool DqnFile_ReadAll(wchar_t const *path, u8 *buf, usize bufSize, usize *bytesRead) DQN_FILE_SCOPE bool DqnFile_ReadAll(wchar_t const *path, u8 *buf, usize bufSize)
{ {
DqnFile file = {}; DqnFile file = {};
bool result = file.Open(path, DqnFile::Flag::FileRead, DqnFile::Action::OpenOnly); bool result = file.Open(path, DqnFile::Flag::FileRead, DqnFile::Action::OpenOnly);
@ -8145,12 +8180,12 @@ bool DqnFile_ReadAll(wchar_t const *path, u8 *buf, usize bufSize, usize *bytesRe
return false; return false;
} }
*bytesRead = file.Read(buf, file.size); usize bytesRead = file.Read(buf, file.size);
DQN_ASSERT(*bytesRead == file.size); DQN_ASSERT(bytesRead == file.size);
return result; return result;
} }
bool DqnFile_ReadAll(const char *path, u8 *buf, usize bufSize, usize *bytesRead) DQN_FILE_SCOPE bool DqnFile_ReadAll(char const *path, u8 *buf, usize bufSize)
{ {
DqnFile file = {}; DqnFile file = {};
bool result = file.Open(path, DqnFile::Flag::FileRead, DqnFile::Action::OpenOnly); bool result = file.Open(path, DqnFile::Flag::FileRead, DqnFile::Action::OpenOnly);
@ -8161,8 +8196,8 @@ bool DqnFile_ReadAll(const char *path, u8 *buf, usize bufSize, usize *bytesRead)
return false; return false;
} }
*bytesRead = file.Read(buf, file.size); usize bytesRead = file.Read(buf, file.size);
DQN_ASSERTM(*bytesRead == file.size, "%zu != %zu", *bytesRead, file.size); DQN_ASSERTM(bytesRead == file.size, "%zu != %zu", bytesRead, file.size);
return result; return result;
} }