/*

MATT STL VECTOR CLASS.

Author: Matthew W. Coan
Date: Fri Oct  5 17:03:49 EDT 2012

*/
#ifndef _MATT_STL_VECTOR_H
#define _MATT_STL_VECTOR_H


#include <sys/types.h>
#include <stdio.h>
#include <iostream>

namespace std {

template< class T >
class vector_iterator {
public:
   size_t index;
   T * array;
   size_t array_size;

   vector_iterator() {
      array = 0;
      index = 0;
      array_size = 0;
   }
   vector_iterator(size_t i, T * a, size_t as) {
      index = i;
      array = a;
      array_size = as;
   }
   vector_iterator(const vector_iterator & cp) {
      index = cp.index;
      array = cp.array;
      array_size = cp.array_size;
   }
   ~vector_iterator() {
   }
   
   bool operator==(const vector_iterator & right) {
      bool ret = false;
      if(index == right.index) ret = true;
      return ret;
   }
   bool operator!=(const vector_iterator & right) {
      bool ret = false;
      if(index != right.index) ret = true;
      return ret;
   }
   vector_iterator & operator=(const vector_iterator & right) {
      index = right.index;
      array = right.array;
      array_size = right.array_size;
      return *this;
   }
   vector_iterator & operator++() { 
      if(index < array_size)
         index++; 
      return *this; 
   }
   vector_iterator & operator--() { 
      if(index > 0)
         index--; 
      return *this; 
   }
   vector_iterator & operator++(int a) { 
      if(index < array_size) 
         index++; 
      return *this; 
   }
   vector_iterator & operator--(int a) { 
      if(index > 0)
         index--; 
      return *this; 
   }
   T & operator*() {
      return array[index]; 
   }
   T * operator->() {
      return &array[index];
   }
};

template< class T >
class vector {
public:
   typedef vector_iterator< T > iterator;

private:
   T * array;
   size_t the_size;

public:
   vector() { 
      the_size = 0; 
      array = 0;
   }

   vector(const size_t sz) { 
      the_size = sz; 
      array = new T [ sz ]; 
   }

   vector(const vector & cp) {
      the_size = cp.the_size;
      array = new T [ the_size ];
      for(size_t i = 0; i < the_size; i++) {
         array[i] = cp.array[i];
      }
   }

   ~vector() { 
      if(array)
         delete [] array; 
      the_size = 0;
      array = 0;
   }
 
   void resize(const size_t sz) {
      size_t i;

      if(array)
         delete [] array;

      the_size = sz;

      array = new T [the_size];
   }

   void push_back(const T & d) {
      the_size++;
      T * temp = new T [the_size];
      temp[the_size - 1] = d;
      size_t i;
      if(array) {
         for(i = 0; i < the_size-1; i++) {
            temp[i] = array[i];
         }
         delete [] array;
      }
      array = temp;
   }

   void erase() {
      if(array)
         delete [] array;
      the_size = 0;
      array = 0;
   }

   void pop_back() {
      T ret = array[the_size - 1];
      the_size--;
   }

   void pop_front() {
      T ret = array[0];
      for(size_t i = 0; i < the_size-1; i++) {
         array[i] = array[i+1];
      }
      the_size--;
      delete ret;
   }

   void push_front(const T & d) {
      the_size++;
      T * temp = new T [the_size];
      temp[0] = d;
      size_t i;
      for(i = 1; i < the_size; i++) {
         temp[i] = array[i-1];
      }
      if(array)
         delete [] array;
      array = temp;
   }

   void insert(const iterator & it, const T & value) {
      if(it.index == 0) {
         push_front(value);
         return;
      }
      if(it.index == the_size) {
         push_back(value);
         return;
      }
      the_size++;
      T * temp = new T [ the_size ];
      size_t j = 0;
      size_t i;
      for(i = 0; i < the_size && j < the_size-1; i++) {
         if(i == it.index) {
            temp[i] = value;
         }
         else {
            temp[i] = array[j];
            j++;
         }
      }
      if(array)
         delete [] array;
      array = temp;
   }

   void erase(const iterator & it) {
      size_t i;
      size_t val = 0;
      for(i = 0; (val + i) < the_size; i++) {
         if(i == it.index && val == 0) {
            val = 1;
            i--;
         }
         else {
            array[i] = array[i+val];
         }    
      }
      the_size--;
   }

   T & operator[](const size_t & i) const { 
      return array[i]; 
   }

   T & operator[](const size_t & i) { 
      return array[i]; 
   }

   size_t size() const { 
      return the_size; 
   }

   size_t size() { 
      return the_size; 
   }

   void clear() {
      if(the_size == 0) return;
      if(array)
         delete [] array;
      the_size = 0;
      array = 0;
   }

   vector & operator=(const vector & v) {
      if(array == v.array) {
         return *this;
      }
      size_t i;
      if(array)
         delete [] array;
      the_size = v.the_size;
      if(the_size == 0)
         array = 0;
      else 
         array = new T[the_size];
      for(i = 0; i < the_size; i++) {
         array[i] = v.array[i];
      }
      return *this;
   }

   iterator begin() { 
      iterator it(0, array, the_size);
      return it;
   }

   iterator end() { 
      iterator it(the_size, array, the_size);
      return it;
   }

   const T & back() const {
      return array[the_size-1];
   }

   const T & front() const {
      return array[0];
   }

   T & back() {
      return array[the_size-1];
   }
      
   T & front() {
      return array[0];
   }

};

}

#endif /* _MATT_STL_VECTOR_H */
