//---------------------------------------------------------------------------
//
// Heap.h -- This file contains the definition for the Base HEAP
//		 			Manager Class.  The Base HEAP manager creates,
//					manages and destroys block of memory using Win32
//					virtual memory calls.
//
//      Honor Bound -- FASA Interactive Technologies
//
//      Copyright (c) 1995 FASA Interactive Technologies
//
//---------------------------------------------------------------------------

#ifndef ABLHEAP_H
#define ABLHEAP_H

//---------------------------------------------------------------------------
// Include Files

#include <gameos\gameos.hpp>


#ifndef ABLDHEAP_H
#include "abldheap.h"
#endif
namespace MW4AI
{
	extern HGOSHEAP g_RootAIHeap;
}

namespace ABL
{

typedef unsigned char* MemoryPtr;
#pragma warning (push)
#include <stlport\vector>
#pragma warning (pop)

#include <memory.h>
//---------------------------------------------------------------------------
// Macro Definitions
#ifndef NO_ERR
#define NO_ERR	0
#endif

#define OUT_OF_MEMORY	0xBADD0001
#define ALLOC_ZERO		0xBADD0002
#define ALLOC_OVERFLOW	0xBADD0003
#define NULL_FREE_LIST	0xBADD0004
#define HEAP_CORRUPTED	0xBADD0005
#define BAD_FREED_PTR	0xBADD0006
#define ALLOC_TOO_BIG	0xBADD0007
#define COULDNT_COMMIT	0xBADD0008
#define COULDNT_CREATE	0xBADD0009

#ifdef _DEBUG
#define allocatedBlockSize 12
#else
#define allocatedBlockSize 8
#endif

#define BASE_HEAP		0
#define USER_HEAP		1

#define MAX_HEAPS		256
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Class Definitions
class HeapManager
{
	//Data Members
	//-------------
	protected:
		unsigned long			whoMadeMe;
		unsigned long   		committedSize;
    HGOSHEAP m_Heap;
		stlport::vector<void *> m_AllocVector;


	//Member Functions
	//-----------------
	public:

		void init (void)
		{ m_Heap = NULL;}
		HeapManager (void)
		{ m_Heap = NULL; }
		
		void destroy (void)
		{
			stlport::vector<void *>::iterator iter;
			for (iter = m_AllocVector.begin ();iter != m_AllocVector.end ();iter++)
			{
				if ((*iter))
				{
					::gos_Free ((*iter));
					(*iter) = NULL;
				}
			}
			m_AllocVector.clear ();

			if (m_Heap)
			{
        gos_DestroyMemoryHeap (m_Heap,false);
				m_Heap = NULL;
			}
		}
		~HeapManager (void)
		{
			destroy ();
		}

		long createHeap (unsigned long memSize,char *name=NULL)
		{
			if (name)
				m_Heap = gos_CreateMemoryHeap (name,0,MW4AI::g_RootAIHeap);
			else
				m_Heap = gos_CreateMemoryHeap ("Abl Heap",0,MW4AI::g_RootAIHeap);
			if (!m_Heap)
				return COULDNT_CREATE;
      committedSize = memSize;
			m_AllocVector.reserve (10000);
			m_AllocVector.clear ();
			return NO_ERR;
		}
//		long commitHeap (unsigned long commitSize = 0);
//		long decommitHeap (unsigned long decommitSize = 0);
		
//		MemoryPtr getHeapPtr (void);
//		operator MemoryPtr (void);

//		void HeapManager::MemoryDump();
		
		virtual unsigned char heapType (void)
		{
			return BASE_HEAP;
		}
		
		unsigned long owner (void)
		{
			return whoMadeMe;
		}
		
		unsigned long tSize (void)
		{
			return committedSize;
		}
};

//---------------------------------------------------------------------------
class UserHeap : public HeapManager
{
	//Data Members
	//-------------	
	protected:
		unsigned long		heapSize;
		bool				mallocFatals;
		char *heapName;
		
	//Member Functions
	//-----------------
	protected:
		
	public:
	
		UserHeap (void)
		{
			heapSize = NULL;
			mallocFatals = true;
		}
		long init (unsigned long memSize, char *heapId = NULL)
		{
			long toret;

			heapSize = memSize;
			HeapManager::init ();
			toret = HeapManager::createHeap (memSize,heapId);
			if (toret)
				return toret;
			if (heapId)
			{
				heapName = (char *)::gos_Malloc(strlen(heapId)+1);
				strcpy(heapName,heapId);
			}
			else
				heapName = NULL;
			return NO_ERR;
		}
		
		~UserHeap (void)
		{
			destroy ();
		}
		void destroy (void)
		{
			HeapManager::destroy ();
			heapSize = 0;
			if (heapName)
			{
				::gos_Free(heapName);
				heapName = NULL;
			}
		}
		
//		unsigned long totalCoreLeft (void);
//		unsigned long coreLeft (void);
		
		void *Malloc (unsigned long memSize)
		{
			if (m_Heap)
			{
				void *toret;
				toret = gos_Malloc (memSize,m_Heap);
				m_AllocVector.push_back (toret);
				return toret;
			}
			return NULL;
		}
		long Free (void *memBlock)
		{
			if (!memBlock)
        return NO_ERR;
			stlport::vector<void *>::iterator iter;
			iter = m_AllocVector.begin ();
			while (iter != m_AllocVector.end ())
			{
				if ((*iter) == memBlock)
					iter = m_AllocVector.erase (iter);
				else
					iter++;
			}
			gosASSERT (m_Heap);
      gos_Free (memBlock);
			return NO_ERR;
		}
		
		void *calloc (unsigned long memSize)
		{
			void *toret;

			if (!m_Heap)
				return NULL;
			toret = gos_Malloc (memSize,m_Heap);
			if (mallocFatals && (!toret))
				gosASSERT (FALSE);
			m_AllocVector.push_back (toret);
			memset (toret,0,memSize);
			return toret;
		}
		
//		void walkHeap (bool printIt = FALSE, bool skipAllocated = FALSE);
		
//		long getLastError (void);

		bool heapReady (void)
		{
			return (heapSize != 0);
		}

		void setMallocFatals (bool fatalFlag)
		{
			mallocFatals = fatalFlag;
		}
		
		virtual unsigned char heapType (void)
		{
			return USER_HEAP;
		}
		
		char *getHeapName (void)
		{
			return "ABL Heap";
		}

		void startHeapMallocLog (void)		//DOES NOTHING IN RELEASE/PROFILE BUILDS!
		{
		}
										
		void stopHeapMallocLog (void)
		{
		}
		
		void dumpRecordLog (void)
		{
		}
};

}
//---------------------------------------------------------------------------
#endif

//---------------------------------------------------------------------------
//
// Edit Log
//
//---------------------------------------------------------------------------

