//
// Asura_DemonWare_MemoryManager.h
//
// Created by Andrew Catlender - 06 February 2006 12:59:10
//
// Copyright (C) 2006 Rebellion (Derby), All Rights Reserved.
//
//
// Wrapper class to allow integration of DemonWare's Matchmaking+ SDK
//

#if defined(ASURA_USE_PRAGMA_ONCE)
#pragma once
#endif

#if !defined(__ASURA_DEMONWARE_MEMORYMANAGER_H__)
#define __ASURA_DEMONWARE_MEMORYMANAGER_H__

#if defined(ASURA_SUPPORT_EXTERNAL_NETWORK) && defined (ASURA_SUPPORT_DEMONWARE)

#if defined(_WIN32)
	#define ASURA_UINT __w64 unsigned int
#else
	#define ASURA_UINT unsigned int
#endif // _WIN32

#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
#include "Core/Asura_String.h"
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE

// Forward declaraion
class Asura_MemHeap;

//
//	Asura_DemonWare_MemoryManager
//
class Asura_DemonWare_MemoryManager
{
public:
	static void Initialise(void);
	static void ShutDown(void);

	static void* Allocate(ASURA_UINT uiBytes);
	static void Deallocate(void* pAddress);
	static void* Reallocate(void* pAddress, ASURA_UINT uiBytes);

	static void* AllocateAligned(ASURA_UINT uiBytes, ASURA_UINT uiAlignment);
	static void DeallocateAligned(void* pAddress);
	static void* ReallocateAligned(void* pAddress, ASURA_UINT uiBytes, ASURA_UINT uiAlignment);

#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
	static int s_iAllocationIndex;
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE

protected:
	static bool s_bInitialised;
#if defined(ASURA_DEMONWARE_USE_ASURA_MEMHEAP)
	static Asura_MemHeap* s_pxMemoryHeap;
	static void* s_pHeapBuffer;
#endif // ASURA_DEMONWARE_USE_ASURA_MEMHEAP

#if defined(ASURA_LOGFILES_ENABLED)
	static char s_szMessage[100];

	static int s_iAllocateCount;
	static int s_iDeallocateCount;
	static int s_iReallocateCount;
	static int s_iAllocateAlignedCount;
	static int s_iDeallocateAlignedCount;
	static int s_iReallocateAlignedCount;
#endif // ASURA_LOGFILES_ENABLED

private:
};

//
// Inline accessors
//
inline void* Asura_DemonWare_Allocate(ASURA_UINT uiBytes)
{
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
	void* pAddress = Asura_DemonWare_MemoryManager::Allocate(uiBytes);

	ASURA_DEMONWARE_LOG(("Allocate\t\t\tAddress 0x%08X\tBytes 0x%08X\t\tIndex (%i)", pAddress, uiBytes, Asura_DemonWare_MemoryManager::s_iAllocationIndex++));

	return pAddress;
#else
	return Asura_DemonWare_MemoryManager::Allocate(uiBytes);
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE
}

inline void Asura_DemonWare_Deallocate(void* pAddress)
{
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
	ASURA_DEMONWARE_LOG(("Deallocate\t\tAddress 0x%08X", pAddress));
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE

	return Asura_DemonWare_MemoryManager::Deallocate(pAddress);
}

inline void* Asura_DemonWare_Reallocate(void* pAddress, ASURA_UINT uiBytes)
{
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
	void* pNewAddress = Asura_DemonWare_MemoryManager::Reallocate(pAddress, uiBytes);

	ASURA_DEMONWARE_LOG(("Reallocate\t\tAddress 0x%08X\tAddress 0x%08X\tBytes 0x%08X", pAddress, pNewAddress, uiBytes));

	return pNewAddress;
#else
	return Asura_DemonWare_MemoryManager::Reallocate(pAddress, uiBytes);
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE
}

inline void* Asura_DemonWare_AllocateAlign(ASURA_UINT uiBytes, ASURA_UINT uiAlignment)
{
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
	void* pAddress = Asura_DemonWare_MemoryManager::AllocateAligned(uiBytes, uiAlignment);

	ASURA_DEMONWARE_LOG(("Allocate Aligned\tAddress 0x%08X\tBytes 0x%08X\tAlignment %i\t\tIndex (%i)", pAddress, uiBytes, uiAlignment, Asura_DemonWare_MemoryManager::s_iAllocationIndex++));

	return pAddress;
#else
	return Asura_DemonWare_MemoryManager::AllocateAligned(uiBytes, uiAlignment);
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE
}

inline void Asura_DemonWare_DeallocateAlign(void* pAddress)
{
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
	ASURA_DEMONWARE_LOG(("Deallocate Aligned\tAddress 0x%08X", pAddress));
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE

	return Asura_DemonWare_MemoryManager::DeallocateAligned(pAddress);
}

inline void* Asura_DemonWare_ReallocateAlign(void* pAddress, ASURA_UINT uiBytes, ASURA_UINT uiAlignment)
{
#if defined(ASURA_LOGFILES_ENABLED) && defined(ASURA_DEMONWARE_LOG_VERBOSE)
	void* pNewAddress = Asura_DemonWare_MemoryManager::ReallocateAligned(pAddress, uiBytes, uiAlignment);

	ASURA_DEMONWARE_LOG(("Reallocate Aligned\tAddress 0x%08X\tAddress 0x%08X\tBytes 0x%08X\tAlignment %i", pAddress, pNewAddress, uiBytes, uiAlignment));

	return pNewAddress;
#else
	return Asura_DemonWare_MemoryManager::ReallocateAligned(pAddress, uiBytes, uiAlignment);
#endif // ASURA_LOGFILES_ENABLED && ASURA_DEMONWARE_LOG_VERBOSE
}

#endif // ASURA_SUPPORT_EXTERNAL_NETWORK && ASURA_SUPPORT_DEMONWARE

#endif // __ASURA_DEMONWARE_MEMORYMANAGER_H__