/*
 * Instituto Superior de Engenharia do Porto
 *
 * Estruturas de Informação
 *
 * 2000/2001
 *
 * ------------------------------------------
 *
 * Classe Template de Vector 
 *
 * t_vector.h
 *
 */


#ifndef NULL
#define NULL    0
#endif


const int DIM_INICIAL = 10;


template <class T>
class Vector
{
private:
	T *m_vector;
	int m_count;
	int m_nTamanhoReal;

private:
	void copia(const Vector<T>& o);
	bool crescer(int nNovoTamanho);

public:
	Vector(int nCount = DIM_INICIAL);
	Vector(const Vector<T>& o);
	~Vector();
	
	bool colocar(int pos, T valor);
	T obter(int pos) const;
	int tamanho() const;

	T& operator[](int iPos);
	Vector<T>& operator=(const Vector<T>& o);
};

template <class T>
bool operator==(const Vector<T>& a, const Vector<T>& b);

template <class T>
ostream& operator<<(ostream& output, const Vector<T>& obj);


////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////



#include <memory.h>

const int PER_CRESCE = 10;

template <class T>
Vector<T>::Vector(int nCount /* = DIM_INICIAL */)
{
	if (nCount <= 0)
	{
		m_nTamanhoReal = m_count = -1;
		m_vector = NULL;
		return;
	}

	m_nTamanhoReal = m_count = nCount;
	m_vector = new T[nCount];
	if (m_vector == NULL)
		//throw Erro(SEM_MEMORIA);
		m_count = 0;
}

template <class T>
Vector<T>::Vector(const Vector<T>& o)
{
	m_vector = NULL;
	copia(o);
}

template <class T>
Vector<T>::~Vector()
{
	if (m_vector != NULL)
		delete [] m_vector;
}
	
template <class T>
bool Vector<T>::colocar(int pos, T valor)
{
	if (pos < 0 || pos >= m_count)
		crescer(pos);
	
	m_vector[pos] = valor;
	return true;
}

template <class T>
T Vector<T>::obter(int pos) const
{
	if (pos < 0 || pos >= m_count)
		throw Erro(POSICAO_INVALIDA);
	
	return m_vector[pos];
}

template <class T>
int Vector<T>::tamanho() const
{
	return m_count;
}

template <class T>
bool Vector<T>::crescer(int pos)
{
	if (pos < m_nTamanhoReal)
		m_count = pos + 1;	
	else
	{
		m_nTamanhoReal = pos + PER_CRESCE;
		int* pV = new T[m_nTamanhoReal];
		if (pV == NULL)
			throw Erro(SEM_MEMORIA);

		//memset(pV, 0, m_nTamanhoReal*sizeof(int));
		
		//memcpy(pV, m_vector, (size_t)(m_count*sizeof(int)));
		for(int i = 0; i < m_count; i++)
			pV[i] = m_vector[i];

		delete [] m_vector;
		m_vector = pV;

		m_count = pos + 1;
	}

	return true;
}

template <class T>
T& Vector<T>::operator[](int iPos)
{
	if (iPos < 0 || iPos >= m_count)
		throw Erro(POSICAO_INVALIDA);
	
	return m_vector[iPos];
}

template <class T>
Vector<T>& Vector<T>::operator=(const Vector<T>& o)
{
	copia(o);
	return *this;
}

template <class T>
void Vector<T>::copia(const Vector<T>& o)
{
	if (m_vector != NULL)
		delete [] m_vector;

	m_nTamanhoReal = m_count = o.tamanho();
	m_vector = new T[o.tamanho()];
	for(int i = 0; i < o.tamanho(); i++)
		m_vector[i] = o.obter(i);
}

template <class T>
bool operator==(const Vector<T>& a, const Vector<T>& b)
{
	if (a.tamanho() != b.tamanho())
		return false;

	for(int i = 0; i < a.tamanho(); i++)
		if (a.obter(i) != b.obter(i))
			return false;

	return true;
}

template <class T>
ostream& operator<<(ostream& output, const Vector<T>& obj)
{
	for(int i = 0; i < obj.tamanho(); i++)
		output << obj.obter(i) << "  ";
	return output;
}

