/* ++[   MP5 - collection.C  ]+++++++++++++++++++++++++++++++++++
   +                                                            +
   + Zaczek, Mariusz                                            +
   + CS 223 - Monday 11:00am - 1:00 pm                          +
   + 4/29/98                                                    + 
   +                                                            +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */

#include <iostream.h>
#include <assert.h>
#include "collection.h"

/* ++[  A  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  cCollection - constructor                                 +
   +                                                            +
   +    * Initializes the lengths and builds the first array    +
   +                                                            + 
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T> 
cCollection<T>::cCollection(int initialLength=0,int allocLengthHint=5)
{
  /* Assign values to logical and physical lengths */
  logical_length=initialLength;
  physical_length=allocLengthHint;
 
  /* Make new array */
  data = new T[physical_length];
 
  /* Test assertion */
  assert( data != 0 );
  
  /* Clear new array */
  for (int i=0;i<physical_length;i++)
    data[i]=0; 
}

/* ++[  B  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  cCollection - copy constructor                            +
   +                                                            +
   +    * Makes deep copies                                     +
   +                                                            +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T> 
cCollection<T>::cCollection(const cCollection<T> &source)
{
  /* make new array */
  data = new T[physical_length];

  /* Test assertion */
  assert( data != 0 );

  /* copy values to new array */
  for (int i=0;i<physical_length;i++)
    data[i] = source.data[i];
}


/* ++[  C  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  cCollection - destructor                                  +
   +                                                            +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T>
cCollection<T>::~cCollection()
{
  delete [] data;
}

/* ++[  D  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +   operator=                                                +
   +                                                            +
   +    * makes deep copies                                     +
   +                                                            +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T>
cCollection<T>& cCollection<T>::operator= (const cCollection<T> &source)
{
  if (this != &source)
  {
    delete [] data;
    data = new T[logical_length];
    
    for (int i=0;i<logical_length;i++)
      data[i]=source.data[i];
  }
  return *this;
}


/* ++[  E  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  AddElem                                                   +
   +                                                            +
   +    * (member function) adds element to the end of          +
   +      cCollection, increasing logical length by 1           +
   +                                                            +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T>
void cCollection<T>::AddElem(const T &elem)
{
  /* Test if array is large enough for next element. If not, call
     resize function */
  if (logical_length == physical_length)
    Resize(5);  

  /* Place element in next available position */
  data[logical_length] = elem; 

  /* Increase logical length */
  logical_length++;

  return;
}

/* ++[  F  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  Resize                                                    +
   +                                                            +
   +    * (member function) resizes the array if the next       +
   +      element to be added to the array.                     +
   +                                                            +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T>
void cCollection<T>::Resize(int newLength)
{
  /* Declare temporary array */ 
  T *temp_array;
  
  /* Increase physical length to hold more elements */
  physical_length=logical_length + newLength;
  
  /* Define the temporary array */
  temp_array = new T[physical_length];

  /* Copy data from old array to temporary array */
  for(int i=0;i<physical_length;i++)
    temp_array[i]=data[i];
  
  /* Delete old array */  
  delete [] data;

  /* assign temporary array to old array */
  data = temp_array;

  return;
}

/* ++[  G  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  operator[]                                                +
   +                                                            +
   +    * (accessor) - returns referemce to element numbered    +
   +      elemNum. Numbering is array like.                     +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T>
T & cCollection<T>::operator[] (int elemNum)
{
  /* Test assertion */
//  assert(elemNum >= 0 && elemNum < logical_length);
                                                         

  /* return element from array position elemNum */
  return data[elemNum];
}

/* ++[  H  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  const operator[]                                          +
   +                                                            +
   +    * (accessor) - returns referemce to element numbered    +
   +      elemNum. Numbering is array like.                     +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T>
const T & cCollection<T>::operator[] (int elemNum) const
{
    /* Test assertion */
//  assert(elemNum >= 0 && elemNum < logical_length);
                                                         

  /* Return element from array position elemNum */
  return data[elemNum];
}

/* ++[  I  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  Length()                                                  +
   +                                                            +
   +    * returns the logical length of the array               +
   +                                                            +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T>
int cCollection<T>::Length(void) const
{
  return logical_length;
}

/* ++[  J  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   +                                                            +
   +  operator<<                                                +
   +                                                            +
   +    * prints out each student in the array on separate lines+
   +                                                            +
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
template<class T>
ostream& operator<<(ostream& out, const cCollection<T>& col)
{
  /* Print out individual students */
  for(int i=0;i<col.Length();i++)
    out << col[i] << endl;
  return out;
}
