/////////////////////////////////////////////////////////////////////////////// // Copyright (C) Microsoft Corporation, 1998. // // temparr.hpp // // Template class used by Direct3D RefDev for stateset and so on. // // The following error codes should be defined before included this file: // DDERR_OUTOFMEMORY // D3D_OK // DDERR_INVALIDPARAMS /////////////////////////////////////////////////////////////////////////////// #ifndef _TEMPLARR_HPP #define _TEMPLARR_HPP //-------------------------------------------------------------------------- // // Template for growable arrays // //-------------------------------------------------------------------------- template <class ARRAY_ELEMENT> class GArrayT { public: GArrayT() { m_pArray = NULL; m_dwArraySize = 0; m_dwGrowSize = 8; } ~GArrayT() { char tmp[256]; wsprintf( tmp, "m_dwArraySize = %d, m_pArray = %08x\n", m_dwArraySize, m_pArray ); _ASSERT( !((m_dwArraySize == 0)^(m_pArray == NULL)), tmp ); if( m_pArray ) delete[] m_pArray; } virtual void SetGrowSize( DWORD dwGrowSize) { m_dwGrowSize = dwGrowSize; } virtual HRESULT Grow( DWORD dwIndex ) { if( dwIndex < m_dwArraySize ) return S_OK; DWORD dwNewArraySize = (dwIndex/m_dwGrowSize + 1) * m_dwGrowSize; ARRAY_ELEMENT *pNewArray = AllocArray( dwNewArraySize ); if( pNewArray == NULL ) return DDERR_OUTOFMEMORY; for( DWORD i = 0; i<m_dwArraySize; i++ ) pNewArray[i] = m_pArray[i]; delete[] m_pArray; m_pArray = pNewArray; m_dwArraySize = dwNewArraySize; return S_OK; } virtual HRESULT Grow( DWORD dwIndex, BOOL* pRealloc ) { if( dwIndex < m_dwArraySize ) { if( pRealloc ) *pRealloc = FALSE; return S_OK; } if( pRealloc ) *pRealloc = TRUE; DWORD dwNewArraySize = m_dwArraySize; while( dwNewArraySize <= dwIndex ) dwNewArraySize += m_dwGrowSize; ARRAY_ELEMENT *pNewArray = AllocArray( dwNewArraySize ); if( pNewArray == NULL ) return DDERR_OUTOFMEMORY; for( DWORD i = 0; i<m_dwArraySize; i++ ) pNewArray[i] = m_pArray[i]; delete[] m_pArray; m_pArray = pNewArray; m_dwArraySize = dwNewArraySize; return S_OK; } virtual ARRAY_ELEMENT *AllocArray( DWORD dwSize ) const { return new ARRAY_ELEMENT[dwSize]; } virtual ARRAY_ELEMENT& operator []( DWORD dwIndex ) const { char tmp[256]; wsprintf( tmp, "dwIndex = %d, m_dwArraySize = %d\n", dwIndex, m_dwArraySize ); _ASSERT(dwIndex < m_dwArraySize, tmp); return m_pArray[dwIndex]; } virtual BOOL IsValidIndex( DWORD dwIndex ) const { return (dwIndex < m_dwArraySize); } virtual DWORD GetSize() const { return m_dwArraySize; } virtual DWORD GetGrowSize() const { return m_dwGrowSize; } protected: ARRAY_ELEMENT *m_pArray; DWORD m_dwArraySize; DWORD m_dwGrowSize; }; //-------------------------------------------------------------------------- // // A more powerful template for a growable array // //-------------------------------------------------------------------------- template <class T> class TemplArray { public: TemplArray( void ); ~TemplArray( void ); // It is the user of this operator who makes sure 0<=iIndex<m_dwArraySize. T& operator []( int iIndex ); HRESULT CheckAndGrow( DWORD iIndex, DWORD dwGrowDelta = 16 ); HRESULT CheckRange ( DWORD iIndex ); // The user needs to make sure 0<=m_dwCurrent<m_dwArraySize. inline T CurrentItem(void) { return m_pArray[m_dwCurrent];}; inline void SetCurrentItem(T item) { m_pArray[m_dwCurrent] = item;}; inline DWORD CurrentIndex(void) { return m_dwCurrent;}; inline void SetCurrentIndex(DWORD dwIdx) {m_dwCurrent = dwIdx;}; inline DWORD ArraySize(void) { return m_dwArraySize;}; private: T *m_pArray; DWORD m_dwArraySize; // Index to the current item or the size of data stored in the array DWORD m_dwCurrent; }; template <class T> TemplArray< T >::TemplArray( void ) { m_pArray = NULL; m_dwArraySize = 0; m_dwCurrent = 0; } template <class T> TemplArray< T >::~TemplArray( void ) { if (m_pArray != NULL) delete m_pArray; m_dwArraySize = 0; } template <class T> T& TemplArray< T >::operator[]( int iIndex ) { return m_pArray[iIndex]; } template <class T> HRESULT TemplArray< T >::CheckAndGrow( DWORD iIndex, DWORD dwGrowDelta ) { if (iIndex >= m_dwArraySize) { DWORD dwNewArraySize = m_dwArraySize + dwGrowDelta; while (iIndex >= dwNewArraySize) dwNewArraySize += dwGrowDelta; T *pTmpArray = new T[dwNewArraySize]; if (pTmpArray == NULL) return DDERR_OUTOFMEMORY; memset(pTmpArray, 0, sizeof(T) * dwNewArraySize); if (m_pArray != NULL) { _ASSERT(m_dwArraySize != 0, "CheckAndGrow: Array size cannot be NULL" ); // Copy existing stuff into new array memcpy(pTmpArray, m_pArray, m_dwArraySize * sizeof(T)); // Free up existing array delete [] m_pArray; } // Assign new array m_pArray = pTmpArray; m_dwArraySize = dwNewArraySize; } return D3D_OK; } template <class T> HRESULT TemplArray< T >::CheckRange( DWORD iIndex ) { if (iIndex >= m_dwArraySize) { return DDERR_INVALIDPARAMS; } return D3D_OK; } #endif _TEMPLARR_HPP