1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-07 19:18:19 +02:00
Beef/BeefySysLib/util/ChunkedDataBuffer.cpp

242 lines
4.9 KiB
C++

#include "ChunkedDataBuffer.h"
#include "DataStream.h"
USING_NS_BF;
int Beefy::ChunkedDataBuffer::sBlocksAllocated = 0;
/*static void Log(const char* fmt ...)
{
static FILE* fp = fopen("chunked_dbg.txt", "wb");
va_list argList;
va_start(argList, fmt);
String aResult = vformat(fmt, argList);
va_end(argList);
fwrite(aResult.c_str(), 1, aResult.length(), fp);
fflush(fp);
}*/
ChunkedDataBuffer::ChunkedDataBuffer()
{
mWriteCurAlloc = NULL;
mWriteCurPtr = (uint8*)(intptr)ALLOC_SIZE;
mReadCurAlloc = NULL;
mReadCurPtr = (uint8*)(intptr)ALLOC_SIZE;
mReadNextAlloc = mReadCurPtr;
mReadPoolIdx = -1;
mSize = 0;
}
ChunkedDataBuffer::~ChunkedDataBuffer()
{
Clear();
}
void ChunkedDataBuffer::InitFlatRef(void* ptr, int size)
{
mReadPoolIdx = 0;
mReadCurPtr = (uint8*)ptr;
mReadCurAlloc = mReadCurPtr;
mReadNextAlloc = mReadCurPtr + size;
}
void ChunkedDataBuffer::Clear()
{
mWriteCurAlloc = NULL;
mWriteCurPtr = (uint8*)(intptr)ALLOC_SIZE;
mReadCurAlloc = NULL;
mReadCurPtr = (uint8*)(intptr)ALLOC_SIZE;
mReadNextAlloc = mReadCurPtr;
mReadPoolIdx = -1;
mSize = 0;
for (auto ptr : mPools)
{
//Log("Free %p\n", ptr);
free(ptr);
sBlocksAllocated--;
}
mPools.Clear();
}
int ChunkedDataBuffer::GetSize()
{
//int calcSize = (int)(((mPools.mSize - 1) * ALLOC_SIZE) + (mWriteCurPtr - mWriteCurAlloc));
//BF_ASSERT(calcSize == mSize);
return mSize;
}
void ChunkedDataBuffer::GrowPool()
{
int curSize = (int)(mWriteCurPtr - mWriteCurAlloc);
mWriteCurAlloc = (uint8*)malloc(ALLOC_SIZE);
//Log("Alloc %p\n", mWriteCurAlloc);
sBlocksAllocated++;
memset(mWriteCurAlloc, 0, ALLOC_SIZE);
mPools.push_back(mWriteCurAlloc);
mWriteCurPtr = mWriteCurAlloc;
}
void ChunkedDataBuffer::Write(const void* data, int size)
{
while (mWriteCurPtr + size >= mWriteCurAlloc + ALLOC_SIZE)
{
int curSize = (int)((mWriteCurAlloc + ALLOC_SIZE) - mWriteCurPtr);
if (curSize > 0)
memcpy(mWriteCurPtr, data, curSize);
GrowPool();
data = (uint8*)data + curSize;
size -= curSize;
mSize += curSize;
if (size == 0)
break;
}
memcpy(mWriteCurPtr, data, size);
mWriteCurPtr += size;
mSize += size;
}
void ChunkedDataBuffer::Write(uint8 byte)
{
while (mWriteCurPtr == mWriteCurAlloc + ALLOC_SIZE)
GrowPool();
*(mWriteCurPtr++) = byte;
mSize++;
}
void ChunkedDataBuffer::Write_2(uint16 val)
{
while (mWriteCurPtr + 2 > mWriteCurAlloc + ALLOC_SIZE)
{
Write((uint8*)&val, 2);
return;
}
*(uint16*)mWriteCurPtr = val;
mWriteCurPtr += 2;
mSize += 2;
}
void ChunkedDataBuffer::Write_3(uint32 val)
{
while (mWriteCurPtr + 3 > mWriteCurAlloc + ALLOC_SIZE)
{
Write((uint8*)&val, 3);
return;
}
*(uint32*)mWriteCurPtr = val;
mWriteCurPtr += 3;
mSize += 3;
}
void ChunkedDataBuffer::Write_4(uint32 val)
{
while (mWriteCurPtr + 4 > mWriteCurAlloc + ALLOC_SIZE)
{
Write((uint8*)&val, 4);
return;
}
*(uint32*)mWriteCurPtr = val;
mWriteCurPtr += 4;
mSize += 4;
}
int ChunkedDataBuffer::GetReadPos()
{
return mReadPoolIdx * ALLOC_SIZE + (int)(mReadCurPtr - mReadCurAlloc);
}
void ChunkedDataBuffer::SetReadPos(int pos)
{
mReadPoolIdx = pos / ALLOC_SIZE;
if (mReadPoolIdx < mPools.mSize)
{
mReadCurAlloc = mPools[mReadPoolIdx];
mReadCurPtr = mReadCurAlloc + pos % ALLOC_SIZE;
mReadNextAlloc = mReadCurPtr + ALLOC_SIZE;
}
else
{
// Place at end of last pool
mReadPoolIdx = mPools.mSize - 1;
mReadCurAlloc = mPools[mReadPoolIdx];
mReadCurPtr = mReadCurAlloc + ALLOC_SIZE;
mReadNextAlloc = mReadCurPtr;
}
}
void ChunkedDataBuffer::NextReadPool()
{
mReadCurAlloc = mPools[++mReadPoolIdx];
mReadCurPtr = mReadCurAlloc;
mReadNextAlloc = mReadCurPtr + ALLOC_SIZE;
}
void ChunkedDataBuffer::Read(void* data, int size)
{
while (mReadCurPtr + size > mReadNextAlloc)
{
int curSize = (int)(mReadNextAlloc - mReadCurPtr);
if (curSize > 0)
memcpy(data, mReadCurPtr, curSize);
NextReadPool();
data = (uint8*)data + curSize;
size -= curSize;
}
memcpy(data, mReadCurPtr, size);
mReadCurPtr += size;
}
void* ChunkedDataBuffer::FastRead(void * data, int size)
{
// Fast case- no crossing chunk boundary
if (mReadCurPtr + size <= mReadNextAlloc)
{
void* retVal = mReadCurPtr;
mReadCurPtr += size;
return retVal;
}
void* dataHead = data;
while (mReadCurPtr + size > mReadNextAlloc)
{
int curSize = (int)(mReadNextAlloc - mReadCurPtr);
if (curSize > 0)
memcpy(data, mReadCurPtr, curSize);
NextReadPool();
data = (uint8*)data + curSize;
size -= curSize;
}
memcpy(data, mReadCurPtr, size);
mReadCurPtr += size;
return dataHead;
}
uint8 ChunkedDataBuffer::Read()
{
if (mReadCurPtr == mReadNextAlloc)
NextReadPool();
return *(mReadCurPtr++);
}
void ChunkedDataBuffer::Read(DataStream& stream, int size)
{
while (mReadCurPtr + size > mReadNextAlloc)
{
int curSize = (int)(mReadNextAlloc - mReadCurPtr);
if (curSize > 0)
stream.Write(mReadCurPtr, curSize);
NextReadPool();
size -= curSize;
}
stream.Write(mReadCurPtr, size);
mReadCurPtr += size;
}