274 lines
7.4 KiB
C++
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
|