/* \file xNewDelete.h
 * \brief: header file for templated new/delete checking for non-null pointers
 */

#ifndef _XNEWDELETE_H_
#define _XNEWDELETE_H_

#include <cassert>


// memory management of types 
// T with non-trivial constructors require 
// C++ style memory management
#define USE_CXX_MEMORY_MANAGMENT_FOR_NON_POD_TYPES
// but for speed on may alternatively use C memory managment
// but can do so safely only for T that are at most 
// plain old data structures (POD)
#ifndef USE_CXX_MEMORY_MANAGMENT_FOR_NON_POD_TYPES
#include <cstdlib>
#endif 

template <class T> 
T* xNew(unsigned int size) {
#ifdef USE_CXX_MEMORY_MANAGMENT_FOR_NON_POD_TYPES
  T* aT_p=new T[size];
  assert(aT_p);
  return aT_p;
#else
  T* aT_p=(T*)malloc(size*sizeof(T));
  assert(aT_p);
  return aT_p;
#endif  
}

template <class T> 
T* xNewZeroInit(unsigned int size) {
#ifdef USE_CXX_MEMORY_MANAGMENT_FOR_NON_POD_TYPES
  T* aT_p=xNew<T>(size);
  for (unsigned int i=0; i<size;++i) 
    aT_p[i]=(T)0;
  return aT_p;
#else
  T* aT_p=(T*)calloc(size,sizeof(T));
  assert(aT_p);
  return aT_p;
#endif
}

template <class T>
void xDelete(T*& aT_p) { 
  if (aT_p) 
#ifdef USE_CXX_MEMORY_MANAGMENT_FOR_NON_POD_TYPES
    delete []aT_p;
#else
    free((void*)aT_p);
#endif
  aT_p=0;
}

template <class T> 
T* xReNew(T* old, unsigned int old_size, unsigned int size) {
#ifdef USE_CXX_MEMORY_MANAGMENT_FOR_NON_POD_TYPES
  T* aT_p=0;
  if (!old) { // no old memory
    if (size)  
      aT_p=xNew<T>(size); // according to realloc behavior in manual page 
  }
  else { // have old memory
    if (!size)  // but 0 size
      xDelete<T>(old); // according to realloc behavior in manual page
    else { // non-zero size
      assert(old_size); // have old memory - need to have old_size set or this call is bad
      // allocate new, delete old; ; even for the case when size is 
      // less than old_size we can't just keep the memory unchanged 
      // because otherwise classes that have ctors/dtors with side-effects 
      // may misbehave, for example classes with static instance/operations counters. 
      aT_p=xNew<T>(size);
      unsigned int iMax=(old_size<size)?old_size:size;
      for (unsigned int i=0; i<iMax;++i) { 
	// we need to copy the items by explicit assignments
	aT_p[i]=old[i];
      }
      xDelete<T>(old);
    }
  }
  return aT_p;
#else
  T* aT_p=0;
  aT_p=(T*)realloc((void*)old,size*sizeof(T));
  if (size) 
    assert(aT_p); // according to realloc behavior in manual page
  return aT_p;
#endif 
}

#endif

