reman3/Rayman_X/cpa/Appli/WinS2B/Array.h

259 lines
7.3 KiB
C++

#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<TYPE>
template<class TYPE>
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<class TYPE>
void CTypedPtrArray<TYPE>::DeleteAt(int nIndex)
{
TYPE p;
p = GetAt(nIndex);
RemoveAt(nIndex);
if(p) delete p;
}
template<class TYPE>
void CTypedPtrArray<TYPE>::DeleteAll()
{
TYPE p;
for(int i = GetUpperBound(); i>=0; i--)
if(p = GetAt(i)) delete p;
RemoveAll();
}
/////////////////////////////////////////////////////////////////////////////
// CSTPArray<TYPE> > class Sorted Typed Pointer Array
// Created byCatalin Cocos
template<class TYPE>
class CSTPArray : public CTypedPtrArray<TYPE*>
{
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<class TYPE>
int CSTPArray<TYPE>::m_iNumObjects = 0;
template<class TYPE>
int CSTPArray<TYPE>::m_qsort_Key = 0;
template<class TYPE>
CRITICAL_SECTION CSTPArray<TYPE>::m_CriticalSection;
// Constructor
template<class TYPE>
CSTPArray<TYPE>::CSTPArray(int iKey)
{
m_iKey = iKey;
if(!m_iNumObjects++)
InitializeCriticalSection(&m_CriticalSection);
}
// Destructor
template<class TYPE>
CSTPArray<TYPE>::~CSTPArray()
{
if(!--m_iNumObjects)
DeleteCriticalSection(&m_CriticalSection);
}
// sorting the array
template<class TYPE>
int CSTPArray<TYPE>::SCompare(TYPE** a,TYPE** b)
{
return TYPE::Compare(*a,*b,m_qsort_Key);
}
template<class TYPE>
void CSTPArray<TYPE>::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<class TYPE>
int CSTPArray<TYPE>::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<class TYPE>
int CSTPArray<TYPE>::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<class TYPE>
int CSTPArray<TYPE>::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<class TYPE>
int CSTPArray<TYPE>::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