#ifndef __DYNAMICAR_H__
#define __DYNAMICAR_H__
#include "stdafx.h"
#include "SdiObject.h"
#include "TypeInfo.h"
#include "MemAlloc.h"
namespace SDICW
{
// Base Dynamic array
class CDynamicAr : CSdiObject
{
public:
// constructors
CDynamicAr(void);
virtual ~CDynamicAr(void);
// methods
sdVoid *GetData();
const sdVoid *GetData() const;
sdBool IsValidIndex(sdInt i) const;
sdInt Count() const;
sdVoid Insert(sdInt index, sdInt count, sdInt elementSize);
sdVoid InsertZeroed(sdInt index, sdInt count, sdInt elementSize);
sdInt Add(sdInt count, sdInt elementSize);
sdInt AddZeroed(sdInt elementSize, sdInt count = 1);
sdBool Shrink(sdInt elementSize);
sdVoid Empty(sdInt elementSize, sdInt slack = 0);
sdVoid Swap(sdInt elemA, sdInt elemB, sdInt elementSize);
sdBool Remove(sdInt index, sdInt count, sdInt elementSize);
protected:
// reallocates the memory space on m_data
sdVoid ReAllocate(sdInt elementSize);
CDynamicAr(sdInt inNum, sdInt elementSize);
// vars
sdVoid *m_data; // memory space where we store the elements
sdInt m_arrayNum; // number of elements in array
sdInt m_arrayMax; // array capacity
};
typedef CDynamicAr ParentClass;
// Dynamic array with template
template<class _T> class TDynamicAr : public CDynamicAr
{
public:
typedef _T ElementType;
TDynamicAr() : ParentClass()
{
}
TDynamicAr(sdInt num) : ParentClass(num, sizeof(ElementType)), m_iterator(NULL)
{
}
TDynamicAr(const TDynamicAr &another)
: ParentClass(another.m_arrayNum, sizeof(ElementType)), m_iterator(NULL)
{
// if its class type
if(TTypeInfo<ElementType>::IsDestructorNeeded())
{
m_arrayNum = 0;
for(int i = 0; i < another.Count(); i++)
{
new(*this)ElementType(another[i]);
}
}
else if(sizeof(ElementType) != 1) // if its not class type
{
for(int i = 0; i < m_arrayNum; i++)
{
(*this)[i] = another[i];
}
}
else // in another case copy the whole thing, we don't care
{
memcpy(&(*this)[0], &another[0], m_arrayNum * sizeof(ElementType));
}
}
~TDynamicAr()
{
Remove(0, m_arrayNum);
}
// operator overloads
ElementType& operator[](sdInt i)
{
return ((ElementType *)m_data)[i];
}
const ElementType& operator[](sdInt i) const
{
return ((ElementType *)m_data)[i];
}
// concatenate with another dynamic array. e.g arrayVar1 + arrayVar2
TDynamicAr& operator+(const TDynamicAr& another)
{
if(this != &another)
{
for(sdInt i = 0; i < another.Count(); i++)
{
new(*this)ElementType(another[i]);
}
}
return *this;
}
TDynamicAr& operator+=(const TDynamicAr& another)
{
if(this != &another)
{
*this = *this + another;
}
return *this;
}
TDynamicAr& operator=(const TDynamicAr& another)
{
if(this != &another)
{
Empty(another.Count());
for(sdInt i = 0; i < another.Count(); i++)
{
new(*this)ElementType(another[i]);
}
}
return *this;
}
// methods
sdInt AddItem(const ElementType& element)
{
new(*this) ElementType(element);
return Count() - 1; // return the index of the element
}
sdInt AddZeroed(sdInt count = 1)
{
return ParentClass::AddZeroed(sizeof(ElementType), count);
}
sdInt Add(sdInt count = 1)
{
return ParentClass::Add(count, sizeof(ElementType));
}
sdInt AddUnique(const ElementType& element)
{
for(int i = 0; i < m_arrayNum; i++)
{
// if its already in the array, return its index
if((*this)[i] == element)
{
return i;
}
}
return AddItem(element);
}
sdVoid InsertItem(const ElementType& element, sdInt index)
{
sdInt idx = Insert(index);
(*this)[idx] = element; // todo: debug this
}
sdVoid Insert(sdInt index, sdInt count = 1)
{
return ParentClass::Insert(index, count, sizeof(ElementType));
}
sdVoid InsertZeroed(sdInt index, sdInt count = 1)
{
return ParentClass::InsertZeroed(index, count, sizeof(ElementType));
}
ElementType Pop()
{
ElementType result = ((ElementType *)m_data)[m_arrayNum - 1];
Remove(m_arrayNum - 1);
return result;
}
ElementType& Last(sdInt c = 0)
{
return ((ElementType *)m_data)[m_arrayNum - count - 1];
}
const ElementType& Last(sdInt c = 0) const
{
return ((ElementType *)m_data)[m_arrayNum - count - 1];
}
sdVoid Shrink()
{
ParentClass::Shrink(sizeof(ElementType));
}
sdBool FindItem(const ElementType& item, __out sdInt& index) const
{
for(index = 0; index < m_arrayNum; index++)
{
if((*this)[index] == item)
return TRUE;
}
return FALSE;
}
sdInt FindItemIndex(const ElementType& item) const
{
for(sdInt index = 0; index < m_arrayNum; index++)
{
if((*this)[index] == item)
return index;
}
return INDEX_NONE;
}
sdBool Contains(const ElementType& item) const
{
return (FindItemIndex(item) != INDEX_NONE);
}
sdBool Remove(sdInt index, sdInt count = 1)
{
// if its class type, then we need to call its destructor
if(TTypeInfo<ElementType>::IsDestructorNeeded())
{
for(sdInt i = index; i < index + count; i++ )
{
(&(*this)[i])->~ElementType();
}
}
return ParentClass::Remove(index, count, sizeof(ElementType));
}
sdBool Remove(const ElementType& element)
{
sdInt idx = FindItemIndex(element);
return Remove(idx);
}
sdBool Empty(sdInt slack = 0)
{
if(TTypeInfo<ElementType>::IsDestructorNeeded())
{
for(sdInt i = 0; i < m_arrayNum; i++ )
{
(&(*this)[i])->~ElementType();
}
}
return ParentClass::Empty(sizeof(ElementType), slack);
}
sdVoid SwapItems(sdInt indexA, sdInt indexB)
{
ParentClass::Swap(indexA, indexB, sizeof(ElementType));
}
class Iterator
{
public:
// constructor
Iterator(TDynamicAr<ElementType>& inArray)
{
++*this;
}
// operator overloads
sdVoid operator++()
{
return m_array[m_index];
}
ElementType& operator*()
{
return m_array[m_index];
}
ElementType* operator->()
{
return &m_array[m_index];
}
operator sdBool() const
{
return m_index < m_array.Count();
}
sdVoid RemoveCurrent()
{
m_array.Remove(--m_index);
}
ElementType& GetCurrent() const
{
return m_index;
}
sdInt GetIndex() const
{
return m_array[m_index];
}
ElementType& GetNext() const
{
return m_array[m_index < m_array.Count() - 1 ? m_index + 1 : 0];
}
ElementType& GetPrev() const
{
return m_array[m_index ? m_index - 1 : m_array.Count() - 1];
}
private:
TDynamicAr<ElementType>& m_array;
sdInt m_index;
};
Iterator& GetIterator() const
{
if(m_iterator == NULL || !m_iterator)
{
m_iterator = new Iterator(this);
}
return m_iterator;
}
private:
Iterator *m_iterator;
};
template<class T> sdVoid* operator new(size_t size, TDynamicAr<T>& ar)
{
int index = ar.CDynamicAr::Add(1, sizeof(T));
return &ar[index];
}
template<class T> sdVoid* operator new(size_t size, TDynamicAr<T>& ar, sdInt index)
{
ar.CDynamicAr::Insert(index, 1, sizeof(T));
return &ar[index];
}
// array exchanger
template<class T> sdVoid ExchangeArray(TDynamicAr<T>& elemA, TDynamicAr<T>& elemB)
{
appMemorySwap(&elemA, &elemB, sizeof(CDynamicAr));
}
}
#endif
Comments