#ifndef	DUMBARRAY_H
#define DUMBARRAY_H

#include <typedefs.h>


/*!
\brief Array of pointers to elements accessed by overloaded [] operator.

  The direct analogy is an array of pointers to the objects. However there
  is no need for contiguous memory.

  It is a smart pointer for a few reasons, however I call it a dumb array
  because each element access de references a pointer as compared with
  the usual array access on contiguous memory. Roughly doubling the access time.

  The client can manage the memory directly.  Assignment does not pass
  control of xi because in the end someone has to clean the memory up
  and there can only be one de allocation point.  (This is a more 
  primitive technique than reference counting and can have dangling pointers)

  \par Examples
\verbatim
  dumbarray<double> vi(3);
  cout << "Set the pointers" << endl;
  vi(0) = & a;
  vi(1) = & b;
  vi(2) = & c;
  ...
  cout << "Access an element" << endl;
  vi[2] = 2.5;  // c=2.5

  cout << "Have multiple arrays to same array" << endl; 
  dumbarray<double> v2();
  v2 = vi;
  y= v2[1];  // y=b
\endverbatim
*/
template< typename T>
class dumbarray
{
public:

  /** Array of pointers.  To modify the pointer
  the client writes to xi. To modify the value
  use the [] operator. */
  T ** xi;

  /** The number of dimensions. */
  uint N;

  /** Is this class managing the xi array? */
  bool memoryManaged;

  /** Copy without passing ownership of xi. */
  dumbarray(dumbarray<T> const & x);

  /** Default - do something later constructor. */
  dumbarray()
    : xi(0), N(0), memoryManaged(false) {}

  /** The client initializes xi and can pass 
      ownership to this class. */
  dumbarray
  (
    T ** xi_, 
    uintc N_,
    boolc memoryManaged_
  )
    : xi(xi_), N(N_), memoryManaged(memoryManaged_) {}

  /** Cleanup if requested. */
  ~dumbarray();

  /** Create a N dimensional array of T* pointers. */
  dumbarray(uintc N_);

  /** Create a N dimensional array of T* pointers. */
  void create(uintc N_);

  /** If memory allocated delete it. */
  void clean();

  /** Memory ownership of xi is not transfered. */
  void operator = ( dumbarray<T> const & x );

 
  /** Access an element and can modify value. */
  T & operator[](uintc i)
    { return *xi[i]; }

  /** Access an element. */
  T const operator[](uintc i) const
    { return *xi[i]; }

  /** Access a pointer to an element and can modify the pointers value. */
  T * & operator () (uint i)
    { return xi[i]; }

};


//----------------------------------------------------------
//  Implementation

template< typename T>
void dumbarray<T>::create(uintc N_)
{
  clean();
  N = N_;
  xi = new T*[N];
  memoryManaged=true;
}

template< typename T>
dumbarray<T>::~dumbarray()
{
  clean();
}


template< typename T>
dumbarray<T>::dumbarray(uintc N_)
  : xi(0), memoryManaged(false)
{
  create(N_);
}

template< typename T>
dumbarray<T>::dumbarray(dumbarray<T> const & x)
{
  xi = x.xi;
  N = x.N;
  memoryManaged = false;
}

template< typename T>
void dumbarray<T>::operator = ( dumbarray<T> const & x )
{
  if (&x==this)
    return;

  clean();

  xi = x.xi;
  N = x.N;
  memoryManaged = false;
}



template< typename T>
void dumbarray<T>::clean()
{
  if (memoryManaged) 
    delete[] xi;
  xi=0;
  N=0;
}



/*

  Purpose

  Why was this class written?  To plug into templates so
  an array could be accessed as a contiguous array but the
  elements are stored anywhere.

  This solves an fundamental problem between C and OOP.  Lets say two
  objects A and B process information in X variables.  If there is no
  global structure which both A and B see then how do they process
  the data efficiently?  The data could be copied. For example A processes
  X and copies it to B. B processes X. A and B are completely separate
  (which is good).

  OOP has a problem that C does not.  Data is locked up in objects which
  are not an array of contiguous memory. Further for efficiency the 
  processing of data is associated with its locality. 
  With this class this information
  can be formed into a contiguous memory (through the underneath pointer).
  
  Remember that in the example processing in A and B is both intensive.
  So if A owns the data then B will have to bend in some way to accomadate
  A.  Where redesignes are not practical the objects in B have the classes
  access A's data by the dumb array. 

*/

#endif



