#ifndef _COMMON_VARARRAY_HPP_
#define _COMMON_VARARRAY_HPP_
#ifndef _COMMON_ARRAY_HPP_
#include <common/array.hpp>
#endif

template <class T>
class VarArray : public Array<T>
{
public:
  enum{Granularity=64,InitialSize=Granularity};
	VarArray(DWORD initialSize=InitialSize,DWORD granularity=Granularity);
	VarArray(const VarArray &someVarArray);
	virtual ~VarArray();
	T &operator[](DWORD index);
	VarArray<T> &operator=(const VarArray<T> &someVarArray);
	BOOL operator==(const VarArray<T> &someVarArray);
	BOOL insert(const T &someItem);
	DWORD granularity(void)const;
	void granularity(DWORD granularity,BOOL clean=FALSE);
	DWORD elements(void)const;
	void reset(void);
	void guarantee(DWORD elements);
	void commit(DWORD elements);
private:
	void elements(DWORD elements);
	DWORD size(void)const;
	void size(DWORD size);

  DWORD mGranularity;
	DWORD mCacheEntries;
};

template <class T>
inline
VarArray<T>::VarArray(DWORD initialSize,DWORD granularity)
: mGranularity(granularity), mCacheEntries(0)
{
  size(initialSize);
}

template <class T>
inline
VarArray<T>::VarArray(const VarArray<T> &someVarArray)
{
  *this=cache
}

template <class T>
inline
VarArray<T>::~VarArray()
{
}

template <class T>
inline
T &VarArray<T>::operator[](DWORD index)
{
  assert(index<elements());
	return Array<T>::operator[](index);
}

template <class T>
inline
VarArray<T> &VarArray<T>::operator=(const VarArray<T> &someVarArray)
{
  elements(someVarArray.elements());
	granularity(someVarArray.granularity());
	Array<T>::size(someVarArray.size());
	for(int index=0;index<someVarArray.elements();index++)Array<T>::operator[](index)=((VarArray<T>&)someVarArray)[index];
	return *this;
}

template <class T>
inline
BOOL VarArray<T>::operator==(const VarArray<T> &someVarArray)
{
  for(int index=0;index<elements();index++)if(!(Array<T>::operator[](index)==someVarArray[index]))return FALSE;
	return TRUE;
}

template <class T>
inline
BOOL VarArray<T>::insert(const T &someItem)
{
  if(elements()+1>Array<T>::size())
	{
		Array<T> copyArray;
		copyArray=(Array<T>&)*this;
		Array<T>::size(Array<T>::size()+granularity());
		for(int index=0;index<elements();index++)Array<T>::operator[](index)=copyArray[index];
	}
  Array<T>::operator[](elements())=someItem;
	elements(elements()+1);
	return TRUE;
}

template <class T>
inline
DWORD VarArray<T>::granularity(void)const
{
  return mGranularity;
}

template <class T>
inline
void VarArray<T>::granularity(DWORD granularity,BOOL clean)
{
  mGranularity=granularity;
	if(!clean)return;
	Array<T>::size(VarArray<T>::granularity());
	elements(0);
}

template <class T>
inline
void VarArray<T>::guarantee(DWORD elements)
{
	reset();
	if(elements<Array<T>::size())return;
	Array<T>::size(elements);
}

template <class T>
inline
void VarArray<T>::commit(DWORD elements)
{
  guarantee(elements);
	this->elements(elements);
}

template <class T>
inline
void VarArray<T>::reset(void)
{
  elements(0);
}

template <class T>
inline
DWORD VarArray<T>::elements(void)const
{
  return mCacheEntries;
}

template <class T>
inline
void VarArray<T>::elements(DWORD elements)
{
  mCacheEntries=elements;
}

template <class T>
inline
DWORD VarArray<T>::size(void)const
{ // private implementation
  return Array<T>::size();
}

template <class T>
inline
void VarArray<T>::size(DWORD size)
{ // private implementation
  Array<T>::size(size);
}
#endif