/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/sgx/core/memory/allocheap.cpp

*/

#include "sgx/core/core.hpp"

CSGXMemoryAllocatorHeap::CSGXMemoryAllocatorHeap(void *ptr, const tMEM_SIZE size, const CSGXMemoryAlignment &alignment) :
	CSGXMemoryAllocator(ptr, size, alignment) {
}

class MemoryMetaData {
public:
	CSGXMemoryAllocator		*pAllocator;
	tMEM_SIZE 				size;
#if SGX_DEBUG
	tCHAR					m_Filename[256];
	tUINT32					m_LineNumber;
#endif	

	static void *prepare(const tMEM_SIZE size, tMEM_SIZE customMemory) {
		SGX_UNUSED(size);
		SGX_UNUSED(customMemory);
		return NULL;
	}
	
	void apply(const tCHAR *filename, int lineNum) {
#if SGX_DEBUG
		if (filename) {
			sgxStrncpy(m_Filename, filename, sizeof(m_Filename));
			m_Filename[sizeof(m_Filename)-1] = '\0';
			m_LineNumber = lineNum;
		} else {
			sgxStrcpy(m_Filename, (tCHAR *)"Unknown");
			m_LineNumber = 0;
		}
#else
		SGX_UNUSED(filename);
		SGX_UNUSED(lineNum);
#endif
	}
	
	};

class HeapMetaData{
public:
	CSGXMemoryAllocator	*pAllocator;
	tMEM_SIZE size;
	};

void *CSGXMemoryAllocatorHeap::alloc(const tMEM_SIZE size) {
	int metaSize = sizeof(tMEM_SIZE) + sizeof(HeapMetaData);

	tMEM_SIZE newSize = size + metaSize;

	tBYTE *ptr = new tBYTE[newSize];
	if (ptr+metaSize == (void *)0x901a0e4c) {
		sgxTrace("THIS ONE!");
	}
	
	HeapMetaData *pMeta = (HeapMetaData *)ptr;
	pMeta->pAllocator = this;
	pMeta->size = size;
	
	*(tMEM_SIZE *)(ptr + sizeof(HeapMetaData)) = (tMEM_SIZE)pMeta;

	return (void *)(ptr + metaSize);
}
 
tMEM_SIZE CSGXMemoryAllocatorHeap::getBlockSize(void *ptr) {
	int metaSize = sizeof(tMEM_SIZE) + sizeof(HeapMetaData);
	HeapMetaData *pMeta = (HeapMetaData *)((tBYTE *)ptr - metaSize);
	return pMeta->size;
}

tBOOL CSGXMemoryAllocatorHeap::freePtr(void *ptr) {
	int metaSize = sizeof(tMEM_SIZE) + sizeof(HeapMetaData);
	tBYTE *pb = (tBYTE *)ptr;
	HeapMetaData *pMeta = (HeapMetaData *)(pb - metaSize);
	delete[] (tBYTE *)(pb - metaSize);
	return TRUE;
}
 
tBOOL CSGXMemoryAllocatorHeap::freeAll() {
	return FALSE;
}


