/*
 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 *  SCR_Mem.h
 *  Scripts, Beaudet Christophe
 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 *
 */
 
#ifndef __SCR_Mem_h__Types
#define __SCR_Mem_h__Types
 
#ifndef __Only_Types__
#define __SCR_Mem_h__Undef
#define __Only_Types__
#endif /* !__Only_Types__ */
 
/*
 *=================================================================================================
 *  Includes.
 *=================================================================================================
 */
 
#include "ErrScr.h"		/* ERM */
#include "MmgScr.h"		/* MMG */
#include "Malloc.h"
 
#ifdef __SCR_Mem_h__Undef
#undef __Only_Types__
#undef __SCR_Mem_h__Undef
#endif /* __SCR_Mem_h__Undef */
 
/*
 *=================================================================================================
 *  Constants.
 *=================================================================================================
 */
 
/*
 *  To export code.
 */
#undef CPA_EXPORT
#if defined(CPA_WANTS_IMPORT)
#define CPA_EXPORT __declspec(dllimport)
#elif defined(CPA_WANTS_EXPORT)
#define CPA_EXPORT __declspec(dllexport)
#else /* CPA_WANTS_IMPORT */
#define CPA_EXPORT
#endif /* CPA_WANTS_IMPORT */
 
#endif /* !__SCR_Mem_h__Types */
 
/*
 *=================================================================================================
 *  Global variables.
 *=================================================================================================
 */
 
#if !defined(__SCR_Mem_h__Globals) && !defined(__Only_Types__)
#define __SCR_Mem_h__Globals
 
extern unsigned char	g_uc_Mem_CurrentAllocationType;	
extern unsigned long	g_a_ul_Mem_BlocAllocationSize[E_ucScrMaxBlocksNb];
extern unsigned long	g_a_ul_Mem_MemoryAllocated[256];
extern unsigned char	g_uc_Mem_CurrentMemLevel;
extern unsigned char	g_uc_Mem_CurrentLinkLevel;
extern unsigned char	g_uc_Mem_LastMemLevel;
 
#endif /* !__SCR_Mem_h__Globals && !__Only_Types__ */
 
/*
 *=================================================================================================
 *  Macros.
 *=================================================================================================
 */
 
#if !defined(__SCR_Mem_h__Macros) && !defined(__Only_Types__)
#define __SCR_Mem_h__Macros
 
/*
 *  A macro for a simple malloc.
 *	A macro for a simple malloc with an init of allocated memory.
 *  A macro for a realloc.
 *  A macro to free.
 */
#define SCR_M_Mem_Alloc(_Cast, _Pointer, _Size)\
{\
	_Pointer = NULL;\
	if(_Size)\
	{\
		g_a_ul_Mem_MemoryAllocated[g_uc_Mem_LastMemLevel] += (_Size * sizeof(_Cast));\
		Mmg_M_SetModeAlloc4Ch(Scr, g_uc_Mem_CurrentAllocationType, C_ucMmgDefaultChannel);\
        MMG_fn_vAddMemoryInfo(MMG_C_lTypeScript, MMG_C_lSubTypeScript, NULL);\
		_Pointer = (_Cast *) Mmg_fn_p_vAlloc4Ch(_Size * sizeof(_Cast), C_ucMmgDefaultChannel);\
		if(Erm_M_uwCheckError(Mmg, C_ucErmDefaultChannel))\
			Erm_M_ClearLastError(C_ucErmDefaultChannel);\
		if(_Pointer == NULL)\
		{\
			*g_st_Err_GlobalError.a_szBufferTmp1 = '\0';\
			*g_st_Err_GlobalError.a_szBufferTmp2 = '\0';\
			SCR_M_Err_RaiseError(SCR_EI_Err_NotEnoughMemory);\
		}\
	}\
}
 
#define SCR_M_Mem_AllocAndSet(_Cast, _Pointer, _Size)\
{\
	SCR_M_Mem_Alloc(_Cast, _Pointer, _Size);\
    if(_Pointer == NULL)\
    {\
        *g_st_Err_GlobalError.a_szBufferTmp1 = '\0';\
        *g_st_Err_GlobalError.a_szBufferTmp2 = '\0';\
        SCR_M_Err_RaiseError(SCR_EI_Err_NotEnoughMemory);\
    }\
    memset(_Pointer, 0, _Size * sizeof(_Cast));\
}
 
#define SCR_M_Mem_Realloc(_Cast, _PointerSrc, _PointerDest, _Size, _AddSize)\
{\
	g_a_ul_Mem_MemoryAllocated[g_uc_Mem_LastMemLevel] += (_AddSize * sizeof(_Cast));\
	Mmg_M_SetModeAlloc4Ch(Scr, g_uc_Mem_CurrentAllocationType, C_ucMmgDefaultChannel);\
	_PointerSrc = (_Cast *) Mmg_fn_p_vRealloc4Ch(_PointerDest, _Size * sizeof(_Cast), C_ucMmgDefaultChannel);\
	if(Erm_M_uwCheckError(Mmg, C_ucErmDefaultChannel))\
		Erm_M_ClearLastError(C_ucErmDefaultChannel);\
    if(_PointerSrc == NULL)\
    {\
        *g_st_Err_GlobalError.a_szBufferTmp1 = '\0';\
        *g_st_Err_GlobalError.a_szBufferTmp2 = '\0';\
        SCR_M_Err_RaiseError(SCR_EI_Err_NotEnoughMemory);\
    }\
}
 
#define SCR_M_Mem_Free(_Pointer)\
{\
	if(_Pointer)\
	{\
		/*g_a_ul_Mem_MemoryAllocated[g_uc_Mem_LastMemLevel] -= _msize(((char *) _Pointer) - 1);*/\
		Mmg_M_SetModeAlloc4Ch(Scr, g_uc_Mem_CurrentAllocationType, C_ucMmgDefaultChannel);\
		if(Erm_M_uwCheckError(Mmg, C_ucErmDefaultChannel))\
			Erm_M_ClearLastError(C_ucErmDefaultChannel);\
		Mmg_fn_vFree4Ch(_Pointer, C_ucMmgDefaultChannel);\
		_Pointer = NULL;\
	}\
}
 
#endif /* !__SCR_Mem_h__Macros && !__Only_Types__ */
 
/*
 *=================================================================================================
 *  Protos.
 *=================================================================================================
 */
 
#if !defined(__SCR_Mem_h__Protos) && !defined(__Only_Types__)
#define __SCR_Mem_h__Protos
 
extern void						fn_v_Mem_InitModule(void);
extern void						fn_v_Mem_CloseModule(void);
 
CPA_EXPORT extern void			SCR_fn_v_Mem_InitWithMemLevel(unsigned long *);
CPA_EXPORT extern void			SCR_fn_v_Mem_DeleteWithMemLevel(unsigned char, unsigned char);
CPA_EXPORT extern void			SCR_fn_v_Mem_ReduceMemory(void);
 
CPA_EXPORT extern unsigned char SCR_fn_uc_Mem_GetCurrentLevel(void);
CPA_EXPORT extern void			SCR_fn_v_Mem_SetCurrentLevel(unsigned char);
CPA_EXPORT extern unsigned char SCR_fn_uc_Mem_GetCurrentLinkLevel(void);
CPA_EXPORT extern void			SCR_fn_v_Mem_SetCurrentLinkLevel(unsigned char);
 
extern void						fn_v_Mem_SetMode(unsigned char);
CPA_EXPORT extern unsigned long	SCR_fn_ul_Mem_GetAllocationSize(unsigned char, unsigned long);
 
CPA_EXPORT extern void			Scr_PrintUsedStaticMemory(void);
 
#endif /* !__SCR_Mem_h__Protos && !__Only_Types__ */
