Newer
Older
Import / projects / Gameloft / glwebtools / source / glwebtools / glwebtools_mutabledata.cpp
#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