#include <glwebtools/internal/glwebtools_default_config.h>
#include <glwebtools/tool/glwebtools_mutabledata.h>
#include <glwebtools/internal/glwebtools_memory.h>
#include <stdlib.h>
#include <string.h>
namespace glwebtools
{
size_t roundAllocToPowerOfTwo(size_t size)
{
size_t count = 0;
size_t msb=0;
for(size_t i = 0; i < (sizeof(size_t) << 3); ++i)
{
if(size & (((size_t)1) << i))
{
++count;
msb = i;
}
}
size = (1LL << (msb + static_cast<size_t>(((count < 2) ? 0 : 1))));
return (size < sizeof(void*)) ? sizeof(void*) : size;
}
MutableData::MutableData(size_t minAllocationSize)
{
m_dataSize = 0;
m_allocatedSize = 0;
m_minAllocationSize = roundAllocToPowerOfTwo(minAllocationSize);
m_data = 0;
}
MutableData::~MutableData()
{
if(m_data)
{
GLWEBTOOLS_FREE(m_data);
m_data = 0;
m_dataSize = 0;
m_allocatedSize = 0;
}
}
size_t MutableData::GetSize()
{
return m_dataSize;
}
size_t MutableData::GetAllocatedSize()
{
return m_allocatedSize;
}
bool MutableData::Resize(size_t newSize)
{
if(newSize <= m_allocatedSize)
{
m_dataSize = newSize;
return true;
}
else
{
bool result = Reserve(newSize);
if(result)
{
m_dataSize = newSize;
return true;
}
return false;
}
}
bool MutableData::Reserve(size_t reserveSize)
{
if(reserveSize <= m_allocatedSize)
return true;
size_t realReserveSize = (reserveSize % m_minAllocationSize == 0) ? reserveSize : ( ((reserveSize / m_minAllocationSize) + 1) * m_minAllocationSize);
void* temp = GLWEBTOOLS_REALLOC(m_data, realReserveSize);
if(temp)
{
m_data = temp;
m_allocatedSize = realReserveSize;
return true;
}
return false;
}
bool MutableData::Purge()
{
if(m_dataSize == 0 && m_data)
{
GLWEBTOOLS_FREE(m_data);
m_data = 0;
m_allocatedSize = 0;
return true;
}
else if(m_allocatedSize > m_dataSize)
{
void* temp = GLWEBTOOLS_REALLOC(m_data, m_dataSize);
if(temp)
{
m_data = temp;
m_allocatedSize = m_dataSize;
return true;
}
return false;
}
return true;
}
bool MutableData::GetData(const void*& dataPtr, size_t& dataSize ) const
{
dataPtr = m_data;
dataSize = m_dataSize;
return true;
}
bool MutableData::GetMutableData(void*& dataPtr, size_t& dataSize )
{
dataPtr = m_data;
dataSize = m_dataSize;
return true;
}
bool MutableData::AppendData(const void* data, size_t size)
{
if(data && size > 0)
{
const unsigned char* srcbytes = static_cast<const unsigned char*>(data);
if(m_dataSize + size > m_allocatedSize)
{
bool result = Reserve(m_dataSize + size);
if(!result)
return false;
}
unsigned char* destbytes = static_cast<unsigned char*>(m_data);
memcpy(destbytes + m_dataSize, srcbytes, size);
m_dataSize += size;
return true;
}
return false;
}
bool MutableData::Swap(MutableData& data)
{
size_t swapDataSize = data.m_dataSize;
size_t swapAllocatedSize = data.m_allocatedSize;
size_t swapMinAllocationSize = data.m_minAllocationSize;
void* swapData = data.m_data;
data.m_dataSize = m_dataSize;
data.m_allocatedSize = m_allocatedSize;
data.m_minAllocationSize = m_minAllocationSize;
data.m_data = m_data;
m_dataSize = swapDataSize;
m_allocatedSize = swapAllocatedSize;
m_minAllocationSize = swapMinAllocationSize;
m_data = swapData;
return true;
}
}; //namespace glwebtools