#include "YaRRIncludes.h"


/************************************** Polite Request ***************************************
** I have put a lot of time and effort into YaRR. If you want to use some of the source     **
** please tell me. Anything used from YaRR must be open source, as is scripts.dll.          **
***************************************** Thank you *****************************************/




void *YaRRMemory::Heap = 0;

#ifdef _YaRRDebug
bool YaRRMemory::LogMem = 0;
bool YaRRMemory::LogMem_ = 0;
FILE *YaRRMemory::LogFile = 0;
#endif

void YaRRMemory::Load()
{
	DLOG;
	if(!Heap)
	{
		Heap = HeapCreate(0, 1024*1024*5, 1024*1024*20); //1Mb of initial memory, 20Mb of maximum memory
		if(!Heap)
		{
			YaRRFunctions::YaRRError("Unable to create heap\n");
		}
	}
}
#ifndef _YaRRDebug
void *YaRRMemory::Allocate2(size_t Size)
{
	DLOG;
	if(!Heap)
	{
		Load();
	}
	HeapLock(Heap);
	void *tmp = HeapAlloc(Heap, HEAP_ZERO_MEMORY, Size);
	if(!tmp)
	{
		//god forbid the day this comes true...
		HeapUnlock(Heap);
		YaRRFunctions::YaRRError("YaRR has ran out of memory. Please report this at forums.dcomproductions.net");
		return 0;
	}
	HeapUnlock(Heap);
	return tmp;
}



void YaRRMemory::Deallocate2(void *Ptr)
{	 
	DLOG;
	if(!Heap)
	{
		Load();
	}
	HeapLock(Heap);
	HeapFree(Heap, 0, Ptr);
	HeapUnlock(Heap);
}

void *YaRRMemory::ReAllocate(void *Ptr, size_t newsize)
{
	DLOG;
	if(!Heap)
	{
		Load();
	}
	HeapLock(Heap);
	void *tmp = HeapReAlloc(Heap, 0, Ptr, newsize);
	if(!tmp)
	{
		//god forbid the day this comes true...
		HeapUnlock(Heap);
		YaRRFunctions::YaRRError("YaRR has ran out of memory. Please report this at forums.dcomproductions.net");
	}
	HeapUnlock(Heap);
	return tmp;
}
#else

void *YaRRMemory::Allocate2(size_t Size, int l, const char *s)
{
	
	DLOG;
	if(!Heap)
	{
		Load();
	}
	HeapLock(Heap);
	void *tmp = HeapAlloc(Heap, HEAP_ZERO_MEMORY, Size);
	if(!tmp)
	{
		//god forbid the day this comes true...
		HeapUnlock(Heap);
		YaRRFunctions::YaRRError("YaRR has ran out of memory (Function: %s, requested size: %d, Line: %d, File: %s). Please report this at forums.dcomproductions.net.", __FUNCTION__, Size, l, s);
	}
	HeapUnlock(Heap);
	
	if(LogMem_)
	{
		fprintf(LogFile, "1 %p %d %d %s\n", tmp, Size, l, s);
	}
	return tmp;
}



void YaRRMemory::Deallocate2(void *Ptr, int l, const char *s)
{	
	DLOG;
	if(!Heap)
	{
		Load();
	}

	printf("Dealloc %p: %d: %s\n", Ptr, l, s);
	HeapLock(Heap);
	HeapFree(Heap, 0, Ptr);
	HeapUnlock(Heap);
	

	if(LogMem_)
	{
		fprintf(LogFile, "2 %p %d %s\n", Ptr, l, s);
	}
}

void *YaRRMemory::ReAllocate(void *Ptr, size_t newsize, int l, const char *s)
{
	DLOG;
	if(!Heap)
	{
		Load();
	}
	HeapLock(Heap);
	void *tmp = HeapReAlloc(Heap, 0, Ptr, newsize);
	if(!tmp)
	{
		//god forbid the day this comes true...
		HeapUnlock(Heap);
		YaRRFunctions::YaRRError("YaRR has ran out of memory (Function: %s, requested size: %d, Line: %d, File: %s). Please report this at forums.dcomproductions.net.", __FUNCTION__, newsize, l, s);
	}
	HeapUnlock(Heap);
	
	if(LogMem_)
	{
		fprintf(LogFile, "3 %p %p %d %d %s\n", Ptr, tmp, newsize, l, s);
	}
	return tmp;
}

#endif

void YaRRMemory::Unload()
{
	DLOG;
	if(Heap)
	{
		HeapDestroy(Heap);
		Heap = 0;
	}
}
int YaRRMemory::Usage(bool PrivHeap)
{
	DLOG;
	void *h;
	if(PrivHeap)
	{
		h = Heap;
	}
	else
	{
		h = GetProcessHeap();
	}
	int ret = 0;
	HeapLock(h);
	PROCESS_HEAP_ENTRY pHeapEntry;
	ZeroMemory(&pHeapEntry,sizeof(pHeapEntry));
	pHeapEntry.lpData = NULL;
	while (HeapWalk(h, &pHeapEntry))
	{
		if(pHeapEntry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
		{
			ret += pHeapEntry.cbData;
		}
	}
	HeapUnlock(h);
	return ret;
}

void YaRRMemory::Dump(bool PrivHeap)
{
	DLOG;
	FILE *f = fopen(PrivHeap ? "log\\privheap.txt" : "log\\globheap.txt", "w");

	void *h;
	if(PrivHeap)
	{
		h = Heap;
	}
	else
	{
		h = GetProcessHeap();
	}
	HeapLock(h);
	PROCESS_HEAP_ENTRY pHeapEntry;
	ZeroMemory(&pHeapEntry,sizeof(pHeapEntry));
	pHeapEntry.lpData = NULL;
	while (HeapWalk(h, &pHeapEntry))
	{
		if(pHeapEntry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
		{
			fprintf(f, "%-10d : %p\n", pHeapEntry.cbData, pHeapEntry.lpData);
		}
	}
	HeapUnlock(h);
	fclose(f);
}

void YaRRMemory::LogMemory(bool log)
{
#ifdef _YaRRDebug
	DLOG;
	if(log == LogMem_)
	{
		return;
	}
	if(log == true)
	{
		LogFile = fopen("log\\MemLog.txt", "a");
	}
	else
	{
		fclose(LogFile);
	}
	LogMem_ = log;
#endif
}

