reman3/Rayman_X/cpa/Appli/WinS2B/ArrTempl.inl

274 lines
7.4 KiB
C++

#ifndef __ARRTEMPL_INL__
#define __ARRTEMPL_INL__
template< class TYPE >
static inline void ConstructElements( TYPE* pElements, int nCount )
{
memset( (void*)pElements, 0, nCount * sizeof( TYPE ) );
for( ; nCount--; pElements++ ) *pElements = TYPE();
//::new( (void*)pElements ) TYPE;
}
template< class TYPE >
inline void DestructElements( TYPE* pElements, int nCount )
{
for (; nCount--; pElements++ )
pElements->~TYPE();
}
template< class TYPE >
inline void CopyElements( TYPE* pDest, const TYPE* pSrc, int nCount )
{
for( ; nCount; nCount--, pDest++, pSrc++ )
*pDest = *pSrc;
}
/////////////////////////////////////////////////////////////////////////////
// CArray<TYPE, ARG_TYPE>
template<class TYPE, class ARG_TYPE>
class CArray
{
public:
// Construction
CArray();
// Attributes
int GetSize() const;
int GetUpperBound() const;
void SetSize(int nNewSize, int nGrowBy = -1);
// Operations
// Clean up
void FreeExtra();
void RemoveAll();
// Accessing elements
TYPE GetAt(int nIndex) const;
void SetAt(int nIndex, ARG_TYPE newElement);
TYPE& ElementAt(int nIndex);
// Direct Access to the element data (may return NULL)
const TYPE* GetData() const;
TYPE* GetData();
// Potentially growing the array
void SetAtGrow(int nIndex, ARG_TYPE newElement);
int Add(ARG_TYPE newElement);
int Append(const CArray& src);
void Copy(const CArray& src);
const CArray& operator = ( const CArray& src );
// overloaded operator helpers
TYPE operator[](int nIndex) const;
TYPE& operator[](int nIndex);
// Operations that move elements around
void InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);
void RemoveAt(int nIndex, int nCount = 1);
void InsertAt(int nStartIndex, CArray* pNewArray);
// Implementation
protected:
TYPE* 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:
~CArray();
};
/////////////////////////////////////////////////////////////////////////////
// CArray<TYPE, ARG_TYPE> inline functions
template<class TYPE, class ARG_TYPE>
inline int CArray<TYPE, ARG_TYPE>::GetSize() const
{ return m_nSize; }
template<class TYPE, class ARG_TYPE>
inline int CArray<TYPE, ARG_TYPE>::GetUpperBound() const
{ return m_nSize-1; }
template<class TYPE, class ARG_TYPE>
inline void CArray<TYPE, ARG_TYPE>::RemoveAll()
{ SetSize( 0, -1 ); }
template<class TYPE, class ARG_TYPE>
inline TYPE CArray<TYPE, ARG_TYPE>::GetAt(int nIndex) const
{ return m_pData[nIndex];}
template<class TYPE, class ARG_TYPE>
inline void CArray<TYPE, ARG_TYPE>::SetAt(int nIndex, ARG_TYPE newElement)
{ m_pData[nIndex] = newElement; }
template<class TYPE, class ARG_TYPE>
inline TYPE& CArray<TYPE, ARG_TYPE>::ElementAt(int nIndex)
{ return m_pData[nIndex]; }
template<class TYPE, class ARG_TYPE>
inline const TYPE* CArray<TYPE, ARG_TYPE>::GetData() const
{ return (const TYPE*)m_pData; }
template<class TYPE, class ARG_TYPE>
inline TYPE* CArray<TYPE, ARG_TYPE>::GetData()
{ return (TYPE*)m_pData; }
template<class TYPE, class ARG_TYPE>
inline int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
{ int nIndex = m_nSize;
SetAtGrow( nIndex, newElement );
return nIndex; }
template<class TYPE, class ARG_TYPE>
inline TYPE CArray<TYPE, ARG_TYPE>::operator[](int nIndex) const
{ return GetAt( nIndex ); }
template<class TYPE, class ARG_TYPE>
inline TYPE& CArray<TYPE, ARG_TYPE>::operator[](int nIndex)
{ return ElementAt( nIndex ); }
template<class TYPE, class ARG_TYPE>
inline const CArray<TYPE, ARG_TYPE>& CArray<TYPE, ARG_TYPE>::operator = ( const CArray& src )
{ Copy( src ); return *this; }
/////////////////////////////////////////////////////////////////////////////
// CArray<TYPE, ARG_TYPE> out-of-line functions
template<class TYPE, class ARG_TYPE>
CArray<TYPE, ARG_TYPE>::CArray()
{
m_pData = NULL;
m_nSize = m_nMaxSize = m_nGrowBy = 0;
}
template<class TYPE, class ARG_TYPE>
CArray<TYPE, ARG_TYPE>::~CArray()
{
RemoveAll();
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::SetSize(int nNewSize, int nGrowBy)
{
if( nGrowBy != -1 )
m_nGrowBy = nGrowBy;
if( nNewSize == 0 )
{
if( m_pData != NULL )
{
DestructElements( m_pData, m_nSize );
delete [] (BYTE*)m_pData;
m_pData = NULL;
}
m_nSize = m_nMaxSize = 0;
}
else if( m_pData == NULL )
{
m_pData = (TYPE*)new BYTE[nNewSize * sizeof( TYPE )];
ConstructElements( m_pData, nNewSize );
m_nSize = m_nMaxSize = nNewSize;
}
else if( nNewSize <= m_nMaxSize )
{
if( nNewSize > m_nSize )
ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
else if( m_nSize > nNewSize )
DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
m_nSize = nNewSize;
}
else
{
int nGrowBy = m_nGrowBy;
if( nGrowBy == 0 )
{
nGrowBy = m_nSize / 8;
nGrowBy = (nGrowBy < 4) ? 4 : ((nGrowBy > 1024) ? 1024 : nGrowBy);
}
int nNewMax;
if( nNewSize < m_nMaxSize + nGrowBy )
nNewMax = m_nMaxSize + nGrowBy;
else
nNewMax = nNewSize;
TYPE* pNewData = (TYPE*)new BYTE[nNewMax * sizeof( TYPE )];
memcpy( pNewData, m_pData, m_nSize * sizeof( TYPE ) );
ConstructElements( &pNewData[m_nSize], nNewSize-m_nSize );
delete [] (BYTE*)m_pData;
m_pData = pNewData;
m_nSize = nNewSize;
m_nMaxSize = nNewMax;
}
}
template<class TYPE, class ARG_TYPE>
int CArray<TYPE, ARG_TYPE>::Append(const CArray& src)
{
int nOldSize = m_nSize;
SetSize( m_nSize + src.m_nSize );
CopyElements( m_pData + nOldSize, src.m_pData, src.m_nSize );
return nOldSize;
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::Copy(const CArray& src)
{
RemoveAll();
SetSize( src.m_nSize );
CopyElements( m_pData, src.m_pData, src.m_nSize );
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::FreeExtra()
{
if( m_nSize != m_nMaxSize )
{
TYPE* pNewData = NULL;
if (m_nSize != 0)
{
pNewData = (TYPE*)new BYTE[m_nSize * sizeof( TYPE )];
memcpy( pNewData, m_pData, m_nSize * sizeof( TYPE ) );
}
delete[] (BYTE*)m_pData;
m_pData = pNewData;
m_nMaxSize = m_nSize;
}
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::SetAtGrow(int nIndex, ARG_TYPE newElement)
{
if (nIndex >= m_nSize)
SetSize(nIndex + 1, -1);
m_pData[nIndex] = newElement;
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::InsertAt(int nIndex, ARG_TYPE newElement, int nCount /*=1*/)
{
if (nIndex >= m_nSize)
SetSize(nIndex + nCount, -1);
else
{
int nOldSize = m_nSize;
SetSize( m_nSize + nCount, -1 );
memmove( &m_pData[nIndex + nCount], &m_pData[nIndex], ( nOldSize - nIndex) * sizeof( TYPE ) );
ConstructElements( &m_pData[nIndex], nCount );
}
while( nCount-- )
m_pData[nIndex++] = newElement;
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::RemoveAt(int nIndex, int nCount)
{
int nMoveCount = m_nSize - ( nIndex + nCount );
DestructElements( &m_pData[nIndex], nCount );
if( nMoveCount )
memcpy( &m_pData[nIndex], &m_pData[nIndex + nCount], nMoveCount * sizeof( TYPE ) );
m_nSize -= nCount;
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::InsertAt( int nStartIndex, CArray* pNewArray )
{
if( pNewArray->GetSize() > 0 )
{
InsertAt( nStartIndex, pNewArray->GetAt( 0 ), pNewArray->GetSize() );
for( int i = 0; i < pNewArray->GetSize(); i++ )
SetAt( nStartIndex + i, pNewArray->GetAt( i ) );
}
}
#endif