#ifndef _SPASS_MEMORY_
#define _SPASS_MEMORY_ 
#include "misc.h"
#define memory_MALLOCPAGESIZE 4096
typedef struct MEMORY_RESOURCEHELP
{
  POINTER free;
  POINTER next;
  POINTER page;
  POINTER end_of_page;
  unsigned total_size;
  unsigned aligned_size;
  unsigned offset;
} MEMORY_RESOURCENODE, *MEMORY_RESOURCE;
#if defined(SPASS_CHECK)
typedef struct MEMORY_INFOHELP
{
  const char * mallocInFile;
  const char * freeInFile;
  unsigned short int mallocAtLine;
  unsigned short int freeAtLine;
} MEMORY_INFONODE, * MEMORY_INFO;
#endif
typedef struct MEMORY_BIGBLOCKHEADERHELP {
  struct MEMORY_BIGBLOCKHEADERHELP * previous, * next;
} MEMORY_BIGBLOCKHEADERNODE, * MEMORY_BIGBLOCKHEADER;
typedef struct MEMORY_HELP
{
  MEMORY_RESOURCE resources;
  unsigned dynmaxsize;
  char freeshredder;
#if defined(SPASS_CHECK)
  char inuse;
#endif
  int unlimited;
  unsigned int pagesize;
  long maxmem;
  const char* outofmem;
  unsigned long newbytes;
  unsigned long freebytes;
  MEMORY_BIGBLOCKHEADER bigblocks;
} MEMORY_NODE, *MEMORY;
#ifdef SPASS_CHECK
void memory_CheckFree(MEMORY, POINTER, unsigned, unsigned int, const char *, unsigned short int);
void memory_CheckPointer(MEMORY, POINTER, unsigned);
#endif
#ifdef SPASS_CHECK
void memory_SetBlockStatusAndSize(MEMORY, POINTER, unsigned int, unsigned);
unsigned memory_GetBlockSize(POINTER);
unsigned memory_GetRealBlockSize(MEMORY, POINTER);
unsigned memory_GetBlockStatus(MEMORY, POINTER);
void memory_SetInfo(MEMORY_INFO, const char *, unsigned short int, const char *, unsigned short int);
#endif
unsigned long memory_DemandedBytes(MEMORY);
unsigned long memory_UsedBytes(MEMORY);
MEMORY memory_Create(void);
MEMORY memory_Init(MEMORY);
void memory_SetOutOfMemString(MEMORY, const char*);
void memory_Delete(MEMORY);
void memory_Reset(MEMORY);
unsigned memory_GetDynmaxSize(MEMORY);
void memory_SetDynmaxSize(MEMORY, unsigned);
void memory_SetFreeShredder(MEMORY, char);
void memory_SetMaxMem(MEMORY, int);
void memory_Print(MEMORY, char);
void memory_FPrint(MEMORY, FILE*, char);
#ifdef SPASS_CHECK
void memory_PrintLeaks(MEMORY);
void memory_PrintDetailed(MEMORY);
void memory_PrintAllocatedBlocks(MEMORY, unsigned int Size);
void memory_PrintFreedBlocks(MEMORY, unsigned int Size);
void memory_PrintAllocatedBigBlocks(MEMORY);
#endif
void memory_FreeAllMem(MEMORY);
unsigned long memory_GetRemainingMemory(MEMORY);
#if defined(SPASS_CHECK) && !defined(SPASS_NO_MEMORY_MANAGEMENT)
POINTER memory_MallocAndCheck(MEMORY, unsigned, const char *, unsigned short int);
POINTER memory_MallocAlignedAndCheck(MEMORY, unsigned, unsigned char, const char *, unsigned short int);
POINTER memory_ReallocAndCheck(MEMORY, POINTER, unsigned int, unsigned int, const char *, unsigned short int);
void memory_FreeAndCheck(MEMORY, POINTER, unsigned, const char *, unsigned short int);
void memory_FreeAlignedAndCheck(MEMORY, POINTER, unsigned, unsigned char, const char *, unsigned short int);
POINTER memory_CallocAndCheck(MEMORY,unsigned int, unsigned int, const char *, unsigned short int);
#define memory_Malloc(Memory,Size) memory_MallocAndCheck((Memory), (Size), __FILE__, __LINE__)
#define memory_MallocAligned(Memory,Size,Alignment) memory_MallocAlignedAndCheck((Memory), (Size), (Alignment), __FILE__, __LINE__)
#define memory_Realloc(Memory,Ptr,OldSize,NewSize) memory_ReallocAndCheck((Memory), (Ptr), (OldSize), (NewSize), __FILE__, __LINE__)
#define memory_Calloc(Memory,Elements,Size) memory_CallocAndCheck((Memory),(Elements), (Size), __FILE__, __LINE__)
#define memory_Free(Memory,Pointer,Size) memory_FreeAndCheck((Memory), (Pointer), (Size), __FILE__, __LINE__)
#define memory_FreeAligned(Memory,Pointer,Size,Alignment) memory_FreeAlignedAndCheck((Memory), (Pointer), (Size), (Alignment), __FILE__, __LINE__)
#else
POINTER memory_Malloc(MEMORY, unsigned);
POINTER memory_Realloc(MEMORY, POINTER, unsigned int, unsigned int);
void memory_Free(MEMORY, POINTER, unsigned);
POINTER memory_Calloc(MEMORY,unsigned int, unsigned int);
#if defined(SPASS_NO_MEMORY_MANAGEMENT)
#define memory_MallocAligned(Memory,Size,Alignment) memory_Malloc((Memory), (Size))
#define memory_FreeAligned(Memory,Ptr,Size,Alignment) memory_Free((Memory), (Ptr), (Size))
#else
POINTER memory_MallocAligned(MEMORY, unsigned, unsigned char);
void memory_FreeAligned(MEMORY, POINTER, unsigned, unsigned char);
#endif
#endif
#endif
