"L. Spiro Engine"

F:/My Projects/LSEngine/Modules/LSTL/Src/Vector/LSTLSVectorCrtp.h

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__
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator