#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 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::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::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::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& 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& 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 sdVoid* operator new(size_t size, TDynamicAr& ar) { int index = ar.CDynamicAr::Add(1, sizeof(T)); return &ar[index]; } template sdVoid* operator new(size_t size, TDynamicAr& ar, sdInt index) { ar.CDynamicAr::Insert(index, 1, sizeof(T)); return &ar[index]; } // array exchanger template sdVoid ExchangeArray(TDynamicAr& elemA, TDynamicAr& elemB) { appMemorySwap(&elemA, &elemB, sizeof(CDynamicAr)); } } #endif