#ifndef __ARRAY_H__ #define __ARRAY_H__ class CPtrArray { public: // Granularity void SetGranularity( int nGrowBy ) { if(nGrowBy >= 0) m_nGrowBy = nGrowBy;} // Construction CPtrArray(); // Attributes int GetSize(); int GetUpperBound(); void SetSize(int nNewSize, int nGrowBy = -1); // Operations // Clean up void FreeExtra(); void RemoveAll(); // Accessing elements void* GetAt(int nIndex) const; void SetAt(int nIndex, void* newElement); void*& ElementAt(int nIndex); // overloaded operator helpers void* operator[](int nIndex) const; void*& operator[](int nIndex); // Direct Access to the element data (may return NULL) const void** GetData() const; void** GetData(); // Potentially growing the array void SetAtGrow(int nIndex, void* newElement); int Add(void* newElement); // Operations that move elements around void InsertAt(int nIndex, void* newElement, int nCount = 1); void RemoveAt(int nIndex, int nCount = 1); void InsertAt(int nStartIndex, CPtrArray* pNewArray); // Implementation protected: void** m_pData; // the actual array of data int m_nSize; // # of elements (upperBound - 1) int m_nMaxSize; // max allocated int m_nGrowBy; // grow amount public: ~CPtrArray(); }; inline int CPtrArray::GetSize() { return m_nSize; } inline int CPtrArray::GetUpperBound() { return m_nSize-1; } inline void CPtrArray::RemoveAll() { SetSize(0); } inline void* CPtrArray::GetAt(int nIndex) const { if(nIndex < 0 || nIndex >= m_nSize) return NULL; return m_pData[nIndex]; } inline void CPtrArray::SetAt(int nIndex, void* newElement) { if(nIndex < 0 || nIndex >= m_nSize) return; m_pData[nIndex] = newElement; } inline int CPtrArray::Add(void* newElement) { int nIndex = m_nSize; SetAtGrow(nIndex, newElement); return nIndex; } inline void*& CPtrArray::ElementAt(int nIndex){if(nIndex < 0 || nIndex >= m_nSize){void ** res = NULL; return *res;} return m_pData[nIndex]; } inline const void** CPtrArray::GetData() const { return (const void**)m_pData; } inline void** CPtrArray::GetData() { return (void**)m_pData; } inline void* CPtrArray::operator[](int nIndex) const { return GetAt(nIndex); } inline void*& CPtrArray::operator[](int nIndex) { return ElementAt(nIndex); } ///////////////////////////////////////////////////////////////////////////// // CTypedPtrArray template class CTypedPtrArray : public CPtrArray { public: // Accessing elements TYPE GetAt(int nIndex) const { return (TYPE)CPtrArray::GetAt(nIndex); } TYPE& ElementAt(int nIndex) { return (TYPE&)CPtrArray::ElementAt(nIndex); } // overloaded operator helpers TYPE operator[](int nIndex) const { return (TYPE)CPtrArray::operator[](nIndex); } TYPE& operator[](int nIndex) { return (TYPE&)CPtrArray::operator[](nIndex); } // Deleting Elements void DeleteAt(int nIndex); void DeleteAll(); }; // Deleting Elements template void CTypedPtrArray::DeleteAt(int nIndex) { TYPE p; p = GetAt(nIndex); RemoveAt(nIndex); if(p) delete p; } template void CTypedPtrArray::DeleteAll() { TYPE p; for(int i = GetUpperBound(); i>=0; i--) if(p = GetAt(i)) delete p; RemoveAll(); } ///////////////////////////////////////////////////////////////////////////// // CSTPArray > class Sorted Typed Pointer Array // Created byCatalin Cocos template class CSTPArray : public CTypedPtrArray { static CRITICAL_SECTION m_CriticalSection; static int m_iNumObjects; static int m_qsort_Key; int m_iKey; static int SCompare(TYPE**,TYPE**); public: // Constructor CSTPArray(int iKey = 0); // Destructor ~CSTPArray(); // Sorting elements void QSort(int iKey = 0); // Adding elements int SAdd(TYPE* newElement, BOOL & NotAdded, BOOL AdmitDuplicates = TRUE); // Searching elements int Index(TYPE* newElement, int *p_iidx = NULL); int UpperBound(int idx); int LowerBound(int idx); }; // the static members template int CSTPArray::m_iNumObjects = 0; template int CSTPArray::m_qsort_Key = 0; template CRITICAL_SECTION CSTPArray::m_CriticalSection; // Constructor template CSTPArray::CSTPArray(int iKey) { m_iKey = iKey; if(!m_iNumObjects++) InitializeCriticalSection(&m_CriticalSection); } // Destructor template CSTPArray::~CSTPArray() { if(!--m_iNumObjects) DeleteCriticalSection(&m_CriticalSection); } // sorting the array template int CSTPArray::SCompare(TYPE** a,TYPE** b) { return TYPE::Compare(*a,*b,m_qsort_Key); } template void CSTPArray::QSort(int iKey) { EnterCriticalSection(&m_CriticalSection); m_qsort_Key = m_iKey = iKey; qsort(GetData(),GetSize(),sizeof(TYPE*),(int (*)(const void *,const void *))SCompare); LeaveCriticalSection(&m_CriticalSection); } // Adding elements template int CSTPArray::SAdd(TYPE* newElement, BOOL& NotAdded, BOOL AdmitDuplicates ) { int iidx, idx = Index( newElement, &iidx ); NotAdded = idx>=0 && ( !AdmitDuplicates || (newElement == GetAt(idx)) ); return (NotAdded? idx: InsertAt(iidx, newElement, 1),iidx ); } // Searching elements template int CSTPArray::Index(TYPE* newElement, int *p_iidx) { if(p_iidx) *p_iidx = 0; if(!newElement) return -1; int hidx = GetUpperBound(), lidx = 0, cidx, val; if(hidx<0) return hidx; while(hidx > lidx) { val = TYPE::Compare(newElement,GetAt(cidx = (hidx+lidx)/2),m_iKey); if( !val ) hidx = lidx = cidx; else if( val<0 ) hidx = cidx; else lidx = cidx+1; } if(p_iidx) *p_iidx = lidx+1; val = TYPE::Compare(newElement,GetAt(lidx),m_iKey); if( !val ) { if(p_iidx) *p_iidx = lidx+1; return lidx; } else if( val<0 ) { if(p_iidx) (*p_iidx)--; } return -1; } // finding the bounds of equivalence intervals (upper & lower) template int CSTPArray::UpperBound(int idx) { int Midx = GetUpperBound(), lidx, hidx, cidx; // the upper limit if(idx<0 || idx>=Midx ) return Midx; // the item is out of bounds or the last in the array TYPE* pCrt = GetAt(lidx = hidx = idx); // this is the target // if the last element of the array is <=> with the target, return its index (no use for further search) if(!TYPE::Compare(pCrt,GetAt(Midx),m_iKey)) return Midx; // find the interval bound (kinda' confusing method, isn't it?) for(hidx ++ ;!TYPE::Compare(pCrt,GetAt(hidx),m_iKey); lidx = hidx, hidx = min(Midx,idx+(hidx-idx)*2)); hidx--; while(hidx > lidx) if(TYPE::Compare(pCrt,GetAt(cidx = (hidx+lidx+1)/2),m_iKey) < 0 ) hidx = cidx-1; else lidx = cidx; return lidx; } template int CSTPArray::LowerBound(int idx) { int lidx, hidx, cidx; if(idx<=0 || idx>GetUpperBound()) return 0; // the item is out of bounds or the last in the array TYPE* pCrt = GetAt(lidx = hidx = idx); // this is the target // if the first element of the array is <=> with the target, return its index (no use for further search) if(!TYPE::Compare(pCrt,GetAt(0),m_iKey)) return 0; // find the interval bound for(lidx--; !TYPE::Compare(pCrt,GetAt(lidx),m_iKey); hidx = lidx, lidx = max(0,idx-(idx-lidx)*2)); lidx++; while(hidx > lidx) if(TYPE::Compare(pCrt,GetAt(cidx = (hidx+lidx)/2),m_iKey)>0) lidx = cidx+1; else hidx = cidx; return lidx; } #include "arrtempl.inl" // the CArray class #endif