"L. Spiro Engine"
|
00001 00022 #ifndef __LSTL_SVECTORCRTP_H__ 00023 #define __LSTL_SVECTORCRTP_H__ 00024 00025 #include "../LSTLib.h" 00026 #include "LSTLVectorBase.h" 00027 #include <cassert> 00028 #include <new> 00029 00030 namespace lstl { 00031 00038 template <typename _tDerivedType, 00039 typename _tType, typename _tDataType = LSUINT16, unsigned _uAllocSize = 512UL> 00040 class CSVectorCrtp : protected CVectorBase { 00041 public : 00042 // == Various constructors. 00043 LSE_CALL CSVectorCrtp() : 00044 m_tLen( 0 ), 00045 m_tAllocated( 0 ), 00046 m_ptData( NULL ) { 00047 } 00048 LSE_CALL CSVectorCrtp( const CSVectorCrtp<_tDerivedType, _tType, _tDataType, _uAllocSize> &_vcSource ) : 00049 m_tLen( 0 ), 00050 m_tAllocated( 0 ), 00051 m_ptData( NULL ) { 00052 (*this) = _vcSource; 00053 } 00054 00055 00056 // == Operators. 00063 const _tType & LSE_CALL operator [] ( LSUINT32 _ui32Index ) const { 00064 assert( _ui32Index < m_tLen ); 00065 return m_ptData[_ui32Index]; 00066 } 00067 00074 _tType & LSE_CALL operator [] ( LSUINT32 _ui32Index ) { 00075 assert( _ui32Index < m_tLen ); 00076 return m_ptData[_ui32Index]; 00077 } 00078 00086 CSVectorCrtp<_tDerivedType, _tType, _tDataType, _uAllocSize> & LSE_CALL 00087 operator = ( const CSVectorCrtp<_tDerivedType, _tType, _tDataType, _uAllocSize> &_vcOther ) { 00088 // Clear every item in this list. 00089 static_cast<_tDerivedType *>(this)->ResetNoDealloc(); 00090 00091 // If the allocation is too small or too high, reallocate. 00092 if ( m_tAllocated < _vcOther.m_tLen || m_tAllocated >= (_vcOther.m_tLen << 1UL) ) { 00093 static_cast<_tDerivedType *>(this)->Allocate( _vcOther.m_tLen ); 00094 } 00095 00096 // Copy items one-by-one. 00097 for ( LSUINT32 I = 0UL; I < _vcOther.Length(); ++I ) { 00098 if ( !static_cast<_tDerivedType *>(this)->Push( _vcOther[I] ) ) { throw LSSTD_E_OUTOFMEMORY; } 00099 } 00100 return (*this); 00101 } 00102 00103 00104 // == Functions. 00108 LSVOID LSE_CALL Reset() { 00109 for ( LSINT32 I = static_cast<LSINT32>(m_tLen); --I >= 0; ) { 00110 Destroy( static_cast<_tDataType>(I) ); 00111 } 00112 m_paDefaultAllocator->Free( m_ptData ); 00113 m_ptData = NULL; 00114 m_tLen = m_tAllocated = 0; 00115 } 00116 00120 LSVOID LSE_CALL ResetNoDealloc() { 00121 for ( LSINT32 I = static_cast<LSINT32>(m_tLen); --I >= 0; ) { 00122 Destroy( static_cast<_tDataType>(I) ); 00123 } 00124 m_tLen = 0; 00125 } 00126 00134 LSVOID LSE_CALL Trash() { 00135 for ( _tDataType I = m_tLen; I--; ) { 00136 Destroy( I ); 00137 } 00138 m_ptData = NULL; 00139 m_tLen = m_tAllocated = 0; 00140 } 00141 00149 LSBOOL LSE_CALL Allocate( LSUINT32 _ui32Total ) { 00150 // If allocating 0 bytes, just reset the list. 00151 if ( !_ui32Total ) { 00152 static_cast<_tDerivedType *>(this)->Reset(); 00153 return true; 00154 } 00155 00156 // Destroy items that are going to be removed. 00157 if ( m_tLen ) { 00158 for ( _tDataType I = m_tLen; --I >= _ui32Total; ) { 00159 Destroy( I ); 00160 } 00161 } 00162 // Adjust the length. 00163 if ( m_tLen > static_cast<_tDataType>(_ui32Total) ) { 00164 m_tLen = static_cast<_tDataType>(_ui32Total); 00165 } 00166 00167 // Attempt to allocate. 00168 _tType * ptNew = reinterpret_cast<_tType *>(m_paDefaultAllocator->ReAlloc( m_ptData, _ui32Total * sizeof( _tType ) )); 00169 if ( !ptNew ) { return false; } 00170 00171 // Success. 00172 m_ptData = ptNew; 00173 m_tAllocated = static_cast<_tDataType>(_ui32Total); 00174 return true; 00175 } 00176 00182 _tDataType LSE_CALL GetAllocated() const { return m_tAllocated; } 00183 00190 LSBOOL LSE_CALL Resize( LSUINT32 _ui32Total ) { 00191 if ( !static_cast<_tDerivedType *>(this)->Allocate( _ui32Total ) ) { return false; } 00192 for ( ; m_tLen < _ui32Total; ++m_tLen ) { 00193 Construct( m_tLen ); 00194 } 00195 return true; 00196 } 00197 00204 LSBOOL LSE_CALL ResizeOver( LSUINT32 _ui32Total ) { 00205 if ( m_tAllocated < _ui32Total ) { 00206 if ( !static_cast<_tDerivedType *>(this)->Allocate( _ui32Total + _uAllocSize ) ) { return false; } 00207 } 00208 for ( ; m_tLen < _ui32Total; ++m_tLen ) { 00209 Construct( m_tLen ); 00210 } 00211 return true; 00212 } 00213 00220 LSBOOL LSE_CALL Push( const _tType &_tVal ) { 00221 // Do we need to allocate more space? 00222 if ( m_tLen == m_tAllocated ) { 00223 // Overflow checking. 00224 _tDataType tNewTotal = static_cast<_tDataType>(m_tAllocated + _uAllocSize); 00225 assert( tNewTotal > m_tAllocated ); 00226 if ( !static_cast<_tDerivedType *>(this)->Allocate( tNewTotal ) ) { return false; } 00227 } 00228 Construct( m_tLen ); 00229 m_ptData[m_tLen++] = _tVal; 00230 return true; 00231 } 00232 00236 LSVOID LSE_CALL Pop() { 00237 if ( m_tLen == 0 ) { return; } 00238 Destroy( --m_tLen ); 00239 // If there are fewer than half of the allocated space worth of objects, 00240 // adjust the allocation. 00241 if ( m_tLen < (m_tAllocated >> 1) ) { 00242 static_cast<_tDerivedType *>(this)->Allocate( (m_tAllocated >> 1) ); 00243 } 00244 } 00245 00249 LSVOID LSE_CALL PopNoDealloc() { 00250 if ( m_tLen == 0 ) { return; } 00251 Destroy( --m_tLen ); 00252 } 00253 00261 LSBOOL LSE_CALL Insert( const _tType &_tVal, LSUINT32 _ui32Index ) { 00262 assert( _ui32Index <= m_tLen ); 00263 if ( m_tLen == m_tAllocated ) { 00264 // Overflow checking. 00265 _tDataType tNewTotal = m_tAllocated + _uAllocSize; 00266 assert( tNewTotal > m_tAllocated ); 00267 if ( !static_cast<_tDerivedType *>(this)->Allocate( tNewTotal ) ) { return false; } 00268 } 00269 00270 // Move other items. 00271 CStd::MemMove( &m_ptData[_ui32Index+1], &m_ptData[_ui32Index], sizeof( _tType ) * (m_tLen - _ui32Index) ); 00272 // Construct and add. 00273 Construct( static_cast<_tDataType>(_ui32Index) ); 00274 m_ptData[_ui32Index] = _tVal; 00275 ++m_tLen; 00276 return true; 00277 } 00278 00286 LSBOOL LSE_CALL Append( const _tType * _ptValues, _tDataType _tTotal ) { 00287 LSUINTPTR uiptrNewLen = m_tLen + _tTotal; 00288 if ( uiptrNewLen >= m_tAllocated ) { 00289 if ( !static_cast<_tDerivedType *>(this)->Allocate( static_cast<_tDataType>(uiptrNewLen + _uAllocSize) ) ) { return false; } 00290 } 00291 CStd::MemCpy( &m_ptData[m_tLen], _ptValues, sizeof( _tType ) * _tTotal ); 00292 m_tLen += _tTotal; 00293 return true; 00294 } 00295 00301 LSVOID LSE_CALL Remove( LSUINT32 _ui32Index ) { 00302 static_cast<_tDerivedType *>(this)->RemoveRange( _ui32Index, 1 ); 00303 } 00304 00310 LSVOID LSE_CALL RemoveNoDealloc( LSUINT32 _ui32Index ) { 00311 static_cast<_tDerivedType *>(this)->RemoveRangeNoDealloc( _ui32Index, 1 ); 00312 } 00313 00320 LSVOID LSE_CALL RemoveRange( LSUINT32 _ui32Index, LSUINT32 _ui32Total ) { 00321 static_cast<_tDerivedType *>(this)->RemoveRangeNoDealloc( _ui32Index, _ui32Total ); 00322 00323 // If there are fewer than half of the allocated space worth of objects, 00324 // adjust the allocation. 00325 if ( m_tLen < (m_tAllocated >> 1) ) { 00326 static_cast<_tDerivedType *>(this)->Allocate( (m_tAllocated >> 1) ); 00327 } 00328 } 00329 00336 LSVOID LSE_CALL RemoveRangeNoDealloc( LSUINT32 _ui32Index, LSUINT32 _ui32Total ) { 00337 assert( _ui32Index < m_tLen ); 00338 assert( _ui32Index + _ui32Total <= m_tLen ); 00339 LSUINT32 ui32End = _ui32Index + _ui32Total; 00340 for ( LSINT32 I = static_cast<LSINT32>(ui32End); --I >= static_cast<LSINT32>(_ui32Index); ) { 00341 // Destruct the item. 00342 Destroy( static_cast<_tDataType>(I) ); 00343 } 00344 00345 // Copy items over it. 00346 CStd::MemMove( &m_ptData[_ui32Index], &m_ptData[_ui32Index+_ui32Total], sizeof( _tType ) * ((m_tLen - _ui32Total) - _ui32Index) ); 00347 m_tLen = m_tLen - static_cast<_tDataType>(_ui32Total); 00348 } 00349 00355 _tDataType LSE_CALL Length() const { 00356 return m_tLen; 00357 } 00358 00362 LSVOID LSE_CALL Snap() { 00363 static_cast<_tDerivedType *>(this)->Allocate( m_tLen ); 00364 } 00365 00366 00367 00368 protected : 00369 // == Members. 00373 _tType * m_ptData; 00374 00378 _tDataType m_tLen; 00379 00383 _tDataType m_tAllocated; 00384 00385 00386 // == Functions. 00392 LSVOID LSE_CALL Construct( _tDataType _tIndex ) { 00393 new( &m_ptData[_tIndex] ) _tType; 00394 } 00395 00401 LSVOID LSE_CALL Destroy( _tDataType _tIndex ) { 00402 // This gives warning C4100 when this class is created with types that have no destructor, 00403 // claiming _tIndex is unreferenced. 00404 // Erase this warning with some do-nothing code. 00405 #ifdef LSE_VISUALSTUDIO 00406 static_cast<_tDataType>(_tIndex); 00407 #endif // #ifdef LSE_VISUALSTUDIO 00408 m_ptData[_tIndex].~_tType(); 00409 } 00410 00411 }; 00412 00413 } // namespace lstl 00414 00415 #endif // __LSTL_SVECTORCRTP_H__