/* \file alloc.h
 * \brief: wrappers to "C" or "Matlab" memory allocators.
 * These wrappers try to insulate ISSM from any library dependency.
 * Ie: if we are running in matlab, matlab has to handle all memory allocations, 
 * otherwise, we get big segfaults. If running in stand alone mode (pure C or C++ 
 * application), we rely on the "C" library implementation of dynamic memory allocation.
 * Why don't we use the "new" and "delete" c++ implementations? Because so far there 
 * are no matlab wrappers to these, which implies having tons of segfaults when 
 * running a mex module.
 * Still, we try to throw memory allocation exceptions a la "C++" style when 
 * the allocation routines described here do not work.
 */


#ifdef HAVE_CONFIG_H
	#include "config.h"
#else
#error "Cannot compile without HAVE_CONFIG_H symbol! run configure first!"
#endif

#if defined(_SERIAL_) && defined(_HAVE_MATLAB_)
#include "mex.h"
#endif

#include "stdio.h"

#include  "./alloc.h"
#include "../Exceptions/exceptions.h"

#undef __FUNCT__
#define __FUNCT__ "xmalloc"
void* xmalloc(int size){

	void* memptr=NULL;

	if(!size)throw ErrorException(__FUNCT__," attempting to 0 size allocation!");

	#if defined(_HAVE_MATLAB_) && defined(_SERIAL_)
	/* Use the matlab api to do the allocation: */
	memptr=mxMalloc(size);
	#else
	/* Use the c library to do the allocation: */
	memptr=malloc(size);
	#endif
	if(!memptr) throw ErrorException(__FUNCT__," memory allocation failed!");

	return memptr;
}

#undef __FUNCT__
#define __FUNCT__ "xcalloc"
void* xcalloc(int n,int size){

	void* memptr=NULL;
	
	if(!size)throw ErrorException(__FUNCT__," attempting to 0 size allocation!");

	#if defined(_HAVE_MATLAB_) && defined(_SERIAL_)
	/* Use the matlab api to do the allocation: */
	memptr=mxCalloc(n,size);
	#else
	/* Use the c library to do the allocation: */
	memptr=calloc(n,size);
	#endif
	if(!memptr) throw ErrorException(__FUNCT__," memory allocation failed!");

	return memptr;
}

void xfree( void* *pv)
{

	if (pv && *pv) {

		#ifdef _SERIAL_
		mxFree(*pv);
		#else
		free(*pv);
		#endif

		*pv=NULL;
	}
}


#undef __FUNCT__
#define __FUNCT__ "xrealloc"
void* xrealloc ( void* pv, int size){
	
	register void* value=NULL;
	
	if(!size)throw ErrorException(__FUNCT__," attempting to realloc to zero");

	#ifndef MATLAB
	value = (void*)realloc(pv,size);
	#else
	value = (void*)mxRealloc(pv,size);
	#endif

	if (value == NULL) {
		throw ErrorException(__FUNCT__,"virtual memory exhausted");
	}
	return value;
}
