//#define BioAPI_MEMTRACK_ON
#define _DEBUG

using System;
using BioAPI.include.bioapi_type;
using System.Runtime.InteropServices;

namespace BioAPI.framework.bioapi_util
{

	public class memfuncs
	{
#if (! BioAPI_MEMTRACK_ON)
		public static  IntPtr _BioAPI_malloc(uint size, IntPtr buf)
		{ return Win32API.malloc(size);	}
		public static  IntPtr _BioAPI_realloc(IntPtr ptr, uint size, IntPtr buf)
		{ return Win32API.realloc(ptr, size);}
		public static  IntPtr _BioAPI_calloc(uint num, uint size,IntPtr buf)
		{ return Win32API.calloc(num, size); }
		public static  void _BioAPI_free(IntPtr ptr, IntPtr buf)
		{ if (ptr != IntPtr.Zero) Win32API.free(ptr); }

		public static  IntPtr _BioAPI_Win_malloc(uint size, IntPtr buf)
		{ return Win32API.GlobalAlloc((uint) Win32API.Consts.GPTR, size); }
		public static  IntPtr _BioAPI_Win_realloc(IntPtr ptr, uint size, IntPtr buf)
		{ return Win32API.GlobalReAlloc(ptr, size, (uint) Win32API.Consts.GMEM_MOVEABLE);}
		public static  IntPtr _BioAPI_Win_calloc(uint num, uint size,IntPtr buf)
		{ return Win32API.GlobalAlloc((uint) Win32API.Consts.GPTR, num*size);}
		public static  void _BioAPI_Win_free(IntPtr ptr, IntPtr buf)
		{ Win32API.GlobalFree(ptr);	}
#else
		public static  IntPtr _BioAPI_malloc(uint size, IntPtr buf, string szFilename, uint u32LineNumber)
		{ 
#if (_DEBUG)
			return Win32API._malloc_dbg(size, (int) Win32API.MEM_BLOCK_TYPE._NORMAL_BLOCK, szFilename, (int)u32LineNumber);
#else
			return Win32API.malloc(size);
#endif
		}
		public static  IntPtr _BioAPI_realloc(IntPtr ptr, uint size, IntPtr buf, string szFilename, uint u32LineNumber)
		{ 
#if (_DEBUG)
			return Win32API._realloc_dbg( ptr, size, (int) Win32API.MEM_BLOCK_TYPE._NORMAL_BLOCK, szFilename, (int)u32LineNumber );
#else
			return Win32API.realloc(ptr, size);
#endif
		}
		public static  IntPtr _BioAPI_calloc(uint num, uint size,IntPtr buf, string szFilename, uint u32LineNumber)
		{ 
#if (_DEBUG)
			return Win32API._calloc_dbg( num, size, (int) Win32API.MEM_BLOCK_TYPE._NORMAL_BLOCK, szFilename, (int)u32LineNumber );
#else
			return Win32API.calloc(num, size); 
#endif
		}
		public static  void _BioAPI_free(IntPtr ptr, IntPtr buf, string szFilename, uint u32LineNumber)
		{ 
			if (ptr != IntPtr.Zero) 
#if (_DEBUG)
				Win32API._free_dbg( ptr, (int) Win32API.MEM_BLOCK_TYPE._NORMAL_BLOCK );
#else
				Win32API.free(ptr); 
#endif
		}

		public static  IntPtr _BioAPI_Win_malloc(uint size, IntPtr buf, string szFilename, uint u32LineNumber)
		{ return Win32API.GlobalAlloc((uint) Win32API.Consts.GPTR, size); }
		public static  IntPtr _BioAPI_Win_realloc(IntPtr ptr, uint size, IntPtr buf, string szFilename, uint u32LineNumber)
		{ return Win32API.GlobalReAlloc(ptr, size, (uint) Win32API.Consts.GMEM_MOVEABLE);}
		public static  IntPtr _BioAPI_Win_calloc(uint num, uint size,IntPtr buf, string szFilename, uint u32LineNumber)
		{ return Win32API.GlobalAlloc((uint) Win32API.Consts.GPTR, num*size);}
		public static  void _BioAPI_Win_free(IntPtr ptr, IntPtr buf, string szFilename, uint u32LineNumber)
		{ Win32API.GlobalFree(ptr);	}	
#endif

		static public BioAPI_MEMORY_FUNCS BioAPIMemoryFuncs = new BioAPI_MEMORY_FUNCS(
			new BioAPI_MALLOC(_BioAPI_malloc),
			new BioAPI_FREE(_BioAPI_free),
			new BioAPI_REALLOC(_BioAPI_realloc),
			new BioAPI_CALLOC(_BioAPI_calloc),
			null);
		static public BioAPI_MEMORY_FUNCS BioAPIWinMemoryFuncs = new BioAPI_MEMORY_FUNCS(
			new BioAPI_MALLOC(_BioAPI_Win_malloc),
			new BioAPI_FREE(_BioAPI_Win_free),
			new BioAPI_REALLOC(_BioAPI_Win_realloc),
			new BioAPI_CALLOC(_BioAPI_Win_calloc),
			null);
	}


	public class Win32API
	{
		internal enum Consts: uint
		{
			GHND			= GMEM_MOVEABLE | GMEM_ZEROINIT, 
			GMEM_FIXED		= 0x0000, 
			GMEM_MOVEABLE	= 0x0002, 
			GMEM_ZEROINIT	= 0x0040, 
			GPTR			= GMEM_FIXED | GMEM_ZEROINIT
		}
		internal enum MEM_BLOCK_TYPE: int
		{
			_FREE_BLOCK     = 0,
			_NORMAL_BLOCK   = 1,
			_CRT_BLOCK      = 2,
			_IGNORE_BLOCK   = 3,
			_CLIENT_BLOCK   = 4,
			_MAX_BLOCKS     = 5
		}
		[DllImport("msvcrt.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr malloc(uint size);
		[DllImport("msvcr70d.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr _malloc_dbg(uint size, int blockType, string filename, int linenumber );

		[DllImport("msvcrt.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr realloc(IntPtr ptr, uint size);
		[DllImport("msvcr70d.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr _realloc_dbg(IntPtr ptr, uint size, int blockType, string filename, int linenumber );

		[DllImport("msvcrt.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr calloc(uint num, uint size);
		[DllImport("msvcr70d.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr _calloc_dbg(uint num, uint size, int blockType, string filename, int linenumber );

		[DllImport("msvcrt.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern void free(IntPtr ptr);
		[DllImport("msvcr70d.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr _free_dbg(IntPtr ptr, int blockType);

		[DllImport("kernel32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr GlobalAlloc(uint uFlgs, uint size);
		[DllImport("kernel32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern IntPtr GlobalReAlloc(IntPtr ptr, uint size, uint uFlgs);
		[DllImport("kernel32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern void GlobalFree(IntPtr ptr);
	}
}