diff --git a/saco/d3d9/common/DXUTmisc.h b/saco/d3d9/common/DXUTmisc.h index 68cb58e..8017693 100644 --- a/saco/d3d9/common/DXUTmisc.h +++ b/saco/d3d9/common/DXUTmisc.h @@ -10,6 +10,28 @@ #define DXUT_MISC_H +//-------------------------------------------------------------------------------------- +// A growable array +//-------------------------------------------------------------------------------------- +template< typename TYPE > +class CGrowableArray +{ +public: + CGrowableArray() { m_pData = NULL; m_nSize = 0; m_nMaxSize = 0; } + ~CGrowableArray() { RemoveAll(); } + + HRESULT SetSize( int nNewMaxSize ); + void RemoveAll() { SetSize(0); } + +protected: + TYPE* m_pData; // the actual array of data + int m_nSize; // # of elements (upperBound - 1) + int m_nMaxSize; // max allocated + + HRESULT SetSizeInternal( int nNewMaxSize ); // This version doesn't call ctor or dtor. +}; + + //-------------------------------------------------------------------------------------- // Performs timer operations // Use DXUTGetGlobalTimer() to get the global instance @@ -38,4 +60,78 @@ protected: LONGLONG m_llBaseTime; }; +//-------------------------------------------------------------------------------------- +// Implementation of CGrowableArray +//-------------------------------------------------------------------------------------- + +// This version doesn't call ctor or dtor. +template< typename TYPE > +HRESULT CGrowableArray::SetSizeInternal( int nNewMaxSize ) +{ + if( nNewMaxSize < 0 ) + { + assert( false ); + return E_INVALIDARG; + } + + if( nNewMaxSize == 0 ) + { + // Shrink to 0 size & cleanup + if( m_pData ) + { + free( m_pData ); + m_pData = NULL; + } + + m_nMaxSize = 0; + m_nSize = 0; + } + else if( m_pData == NULL || nNewMaxSize > m_nMaxSize ) + { + // Grow array + int nGrowBy = ( m_nMaxSize == 0 ) ? 16 : m_nMaxSize; + nNewMaxSize = __max( nNewMaxSize, m_nMaxSize + nGrowBy ); + + TYPE* pDataNew = (TYPE*) realloc( m_pData, nNewMaxSize * sizeof(TYPE) ); + if( pDataNew == NULL ) + return E_OUTOFMEMORY; + + m_pData = pDataNew; + m_nMaxSize = nNewMaxSize; + } + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +template< typename TYPE > +HRESULT CGrowableArray::SetSize( int nNewMaxSize ) +{ + int nOldSize = m_nSize; + + if( nOldSize > nNewMaxSize ) + { + // Removing elements. Call dtor. + + for( int i = nNewMaxSize; i < nOldSize; ++i ) + m_pData[i].~TYPE(); + } + + // Adjust buffer. Note that there's no need to check for error + // since if it happens, nOldSize == nNewMaxSize will be true.) + HRESULT hr = SetSizeInternal( nNewMaxSize ); + + if( nOldSize < nNewMaxSize ) + { + // Adding elements. Call ctor. + + for( int i = nOldSize; i < nNewMaxSize; ++i ) + ::new (&m_pData[i]) TYPE; + } + + return hr; +} + + #endif