diff --git a/saco/d3d9/common/DXUTmisc.h b/saco/d3d9/common/DXUTmisc.h index 8017693..55699c1 100644 --- a/saco/d3d9/common/DXUTmisc.h +++ b/saco/d3d9/common/DXUTmisc.h @@ -18,9 +18,32 @@ class CGrowableArray { public: CGrowableArray() { m_pData = NULL; m_nSize = 0; m_nMaxSize = 0; } + CGrowableArray( const CGrowableArray& a ) { for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); } ~CGrowableArray() { RemoveAll(); } + const TYPE& operator[]( int nIndex ) const { return GetAt( nIndex ); } + TYPE& operator[]( int nIndex ) { return GetAt( nIndex ); } + + CGrowableArray& operator=( const CGrowableArray& a ) { if( this == &a ) return *this; RemoveAll(); for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); return *this; } + HRESULT SetSize( int nNewMaxSize ); + HRESULT Add( const TYPE& value ); + HRESULT Insert( int nIndex, const TYPE& value ); + HRESULT SetAt( int nIndex, const TYPE& value ); + TYPE& GetAt( int nIndex ) { assert( nIndex >= 0 && nIndex < m_nSize ); return m_pData[nIndex]; } + int GetSize() const { return m_nSize; } + TYPE* GetData() { return m_pData; } + bool Contains( const TYPE& value ){ return ( -1 != IndexOf( value ) ); } + + int IndexOf( const TYPE& value ) { return ( m_nSize > 0 ) ? IndexOf( value, 0, m_nSize ) : -1; } + int IndexOf( const TYPE& value, int iStart ) { return IndexOf( value, iStart, m_nSize - iStart ); } + int IndexOf( const TYPE& value, int nIndex, int nNumElements ); + + int LastIndexOf( const TYPE& value ) { return ( m_nSize > 0 ) ? LastIndexOf( value, m_nSize-1, m_nSize ) : -1; } + int LastIndexOf( const TYPE& value, int nIndex ) { return LastIndexOf( value, nIndex, nIndex+1 ); } + int LastIndexOf( const TYPE& value, int nIndex, int nNumElements ); + + HRESULT Remove( int nIndex ); void RemoveAll() { SetSize(0); } protected: @@ -134,4 +157,156 @@ HRESULT CGrowableArray::SetSize( int nNewMaxSize ) } +//-------------------------------------------------------------------------------------- +template< typename TYPE > +HRESULT CGrowableArray::Add( const TYPE& value ) +{ + HRESULT hr; + if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) ) + return hr; + + // Construct the new element + ::new (&m_pData[m_nSize]) TYPE; + + // Assign + m_pData[m_nSize] = value; + ++m_nSize; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +template< typename TYPE > +HRESULT CGrowableArray::Insert( int nIndex, const TYPE& value ) +{ + HRESULT hr; + + // Validate index + if( nIndex < 0 || + nIndex > m_nSize ) + { + assert( false ); + return E_INVALIDARG; + } + + // Prepare the buffer + if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) ) + return hr; + + // Shift the array + MoveMemory( &m_pData[nIndex+1], &m_pData[nIndex], sizeof(TYPE) * (m_nSize - nIndex) ); + + // Construct the new element + ::new (&m_pData[nIndex]) TYPE; + + // Set the value and increase the size + m_pData[nIndex] = value; + ++m_nSize; + + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +template< typename TYPE > +HRESULT CGrowableArray::SetAt( int nIndex, const TYPE& value ) +{ + // Validate arguments + if( nIndex < 0 || + nIndex >= m_nSize ) + { + assert( false ); + return E_INVALIDARG; + } + + m_pData[nIndex] = value; + return S_OK; +} + + +//-------------------------------------------------------------------------------------- +// Searches for the specified value and returns the index of the first occurrence +// within the section of the data array that extends from iStart and contains the +// specified number of elements. Returns -1 if value is not found within the given +// section. +//-------------------------------------------------------------------------------------- +template< typename TYPE > +int CGrowableArray::IndexOf( const TYPE& value, int iStart, int nNumElements ) +{ + // Validate arguments + if( iStart < 0 || + iStart >= m_nSize || + nNumElements < 0 || + iStart + nNumElements > m_nSize ) + { + assert( false ); + return -1; + } + + // Search + for( int i = iStart; i < (iStart + nNumElements); i++ ) + { + if( value == m_pData[i] ) + return i; + } + + // Not found + return -1; +} + + +//-------------------------------------------------------------------------------------- +// Searches for the specified value and returns the index of the last occurrence +// within the section of the data array that contains the specified number of elements +// and ends at iEnd. Returns -1 if value is not found within the given section. +//-------------------------------------------------------------------------------------- +template< typename TYPE > +int CGrowableArray::LastIndexOf( const TYPE& value, int iEnd, int nNumElements ) +{ + // Validate arguments + if( iEnd < 0 || + iEnd >= m_nSize || + nNumElements < 0 || + iEnd - nNumElements < 0 ) + { + assert( false ); + return -1; + } + + // Search + for( int i = iEnd; i > (iEnd - nNumElements); i-- ) + { + if( value == m_pData[i] ) + return i; + } + + // Not found + return -1; +} + + + +//-------------------------------------------------------------------------------------- +template< typename TYPE > +HRESULT CGrowableArray::Remove( int nIndex ) +{ + if( nIndex < 0 || + nIndex >= m_nSize ) + { + assert( false ); + return E_INVALIDARG; + } + + // Destruct the element to be removed + m_pData[nIndex].~TYPE(); + + // Compact the array and decrease the size + MoveMemory( &m_pData[nIndex], &m_pData[nIndex+1], sizeof(TYPE) * (m_nSize - (nIndex+1)) ); + --m_nSize; + + return S_OK; +} + + #endif