/*
 * marray.h
 * MArray means My Array or Minimal Array Class
 */
#ifndef	_MARRAY_H
#define _MARRAY_H

#include    <assert.h>

template<class T>
class MArray
{
private:
  enum{ALLOCINC=20};
  T *a;
  int cnt;
  int allocated;
  int allocinc;
  void grow(void);	// make array grow

protected:
  void remove(const int i); // This is protected
			    // because it is dangerous
public:
  MArray(int n= ALLOCINC) // default constructor   
  {
  a= new T[n];
  cnt= 0;
  allocated= n;
  allocinc= n;
  }

  MArray(const MArray<T>& n); // copy constructor

  // assignment operator
  MArray<T>& MArray<T>::operator=(const MArray<T>& n);

  virtual ~MArray(){ // destructor
    delete [] a;
  }

  // index operator
  T& operator[](const int i) const{
    // generate an assert error if indices don't make sense
    assert((i >= 0) && (i < cnt));
    return a[i];
  }

  int count(void) const{ return cnt; } // length of array

  void add(const T& n);    // add an element

  // add an element at a specific place
  void add(const int i, const T& n); 
};

// copy constructor
template <class T>
MArray<T>::MArray(const MArray<T>& n)
{
  allocated= n.allocated;
  allocinc= n.allocinc;
  cnt= n.cnt;
  a= new T[allocated];
  for(int i=0;i<cnt;i++) a[i]= n.a[i];
}

// assignment operator
template <class T>
MArray<T>& MArray<T>::operator=(const MArray<T>& n){
  // check we are not assigning to ourselves
  if(this == &n) return *this;
  delete [] a; // get rid of old one
  allocated= n.allocated;
  allocinc= n.allocinc;
  cnt= n.cnt;
  a= new T[allocated];
  for(int i=0;i<cnt;i++) a[i]= n.a[i];
  return *this;
};

// a private member function used by the
// implementation to grow the array
template <class T>
void MArray<T>::grow(){
  allocated += allocinc;
  T *tmp= new T[allocated];
  for(int i=0;i<cnt;i++) tmp[i]= a[i];
  delete [] a;
  a= tmp;
};

// add an element to the end of the array
template <class T>
void MArray<T>::add(const T& n){
  if(cnt >= allocated) grow();
  a[cnt++]= n;
};

// add an element to the array at the index ip
template <class T>
void MArray<T>::add(const int ip, const T& n){
  assert((ip >= 0) && (ip <= cnt));
  if(cnt >= allocated) grow();

  for(int i=cnt;i>ip;i--) // shuffle up
  a[i]= a[i-1];

  a[ip]= n;
  cnt++;
};

// remove the element at the index ip, and shuffle the
// rest of the elements down
template <class T>
void MArray<T>::remove(const int n){
int i;
  assert((n >= 0) && (n < cnt));

  // shuffle down starting at n
  for(i=n;i<cnt-1;i++){
    a[i]= a[i+1];
  }
  cnt--;
};
#endif

