/* \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

#include <stdio.h>
#include <stdlib.h>

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

void* xmalloc(int size){

	void* memptr=NULL;

	if(!size)_error2_("attempting to 0 size allocation!");

	/* Use the c library to do the allocation: */
	memptr=malloc(size);
	if(!memptr) _error2_("memory allocation failed!");

	return memptr;
}

void* xcalloc(int n,int size){

	void* memptr=NULL;
	
	if(!size)_error2_("attempting to 0 size allocation!");

	/* Use the c library to do the allocation: */
	memptr=calloc(n,size);
	if(!memptr) _error2_("memory allocation failed!");

	return memptr;
}

void xfree(void* *pv){

	if (pv && *pv){
		free(*pv);

		*pv=NULL;
	}
}

void xdelete(Matrix** pv){
	
	if (pv && *pv){
		/*There is no mxDelete in the Matlab API -> using delete trips up Matlab. So we 
		 * don't actually free memory in Matlab, we let the memory manager do that. We only
		 * free in parallel: */
		delete *pv;
		*pv=NULL;
	}
}

void xdelete(Vector** pv){

	if (pv && *pv){
		/*There is no mxDelete in the Matlab API -> using delete trips up Matlab. So we 
		 * don't actually free memory in Matlab, we let the memory manager do that. We only
		 * free in parallel: */
		delete *pv;
		*pv=NULL;
	}
}

void* xrealloc( void* pv, int size){
	
	register void* value=NULL;
	
	if(!size)_error2_("attempting to realloc to zero");
	value = (void*)realloc(pv,size);

	if (value == NULL) {
		_error2_("virtual memory exhausted");
	}
	return value;
}
