#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 template 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 inline functions template inline int CArray::GetSize() const { return m_nSize; } template inline int CArray::GetUpperBound() const { return m_nSize-1; } template inline void CArray::RemoveAll() { SetSize( 0, -1 ); } template inline TYPE CArray::GetAt(int nIndex) const { return m_pData[nIndex];} template inline void CArray::SetAt(int nIndex, ARG_TYPE newElement) { m_pData[nIndex] = newElement; } template inline TYPE& CArray::ElementAt(int nIndex) { return m_pData[nIndex]; } template inline const TYPE* CArray::GetData() const { return (const TYPE*)m_pData; } template inline TYPE* CArray::GetData() { return (TYPE*)m_pData; } template inline int CArray::Add(ARG_TYPE newElement) { int nIndex = m_nSize; SetAtGrow( nIndex, newElement ); return nIndex; } template inline TYPE CArray::operator[](int nIndex) const { return GetAt( nIndex ); } template inline TYPE& CArray::operator[](int nIndex) { return ElementAt( nIndex ); } template inline const CArray& CArray::operator = ( const CArray& src ) { Copy( src ); return *this; } ///////////////////////////////////////////////////////////////////////////// // CArray out-of-line functions template CArray::CArray() { m_pData = NULL; m_nSize = m_nMaxSize = m_nGrowBy = 0; } template CArray::~CArray() { RemoveAll(); } template void CArray::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 int CArray::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 void CArray::Copy(const CArray& src) { RemoveAll(); SetSize( src.m_nSize ); CopyElements( m_pData, src.m_pData, src.m_nSize ); } template void CArray::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 void CArray::SetAtGrow(int nIndex, ARG_TYPE newElement) { if (nIndex >= m_nSize) SetSize(nIndex + 1, -1); m_pData[nIndex] = newElement; } template void CArray::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 void CArray::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 void CArray::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