"L. Spiro Engine"
|
00001 00017 #ifndef __LSTL_VECTOR_H__ 00018 #define __LSTL_VECTOR_H__ 00019 00020 #include "../LSTLib.h" 00021 #include "LSTLSVectorCrtp.h" 00022 00023 namespace lstl { 00024 00032 template <typename _tType, typename _tDataType = LSUINT16, unsigned _uAllocSize = 512UL> 00033 class CVector : public CSVectorCrtp<CVector<_tType, _tDataType, _uAllocSize>, _tType, _tDataType, _uAllocSize> { 00034 public : 00035 // == Various constructors. 00036 LSE_CALL CVector() : 00037 m_paOurAllocator( Parent::m_paDefaultAllocator ) { 00038 } 00039 explicit LSE_CALL CVector( LSUINT32 _tTotal ) : 00040 m_paOurAllocator( Parent::m_paDefaultAllocator ) { 00041 Allocate( _tTotal ); 00042 } 00043 explicit LSE_CALL CVector( CAllocator * _paAllocator ) : 00044 m_paOurAllocator( _paAllocator ) { 00045 if ( !m_paOurAllocator ) { 00046 m_paOurAllocator = Parent::m_paDefaultAllocator; 00047 } 00048 } 00049 LSE_CALL CVector( LSUINT32 _tTotal, CAllocator * _paAllocator ) : 00050 m_paOurAllocator( _paAllocator ) { 00051 if ( !m_paOurAllocator ) { 00052 m_paOurAllocator = Parent::m_paDefaultAllocator; 00053 } 00054 Allocate( _tTotal ); 00055 } 00056 LSE_CALL CVector( const CVector<_tType, _tDataType, _uAllocSize> &_vOther, CAllocator * _paAllocator = NULL ) : 00057 m_paOurAllocator( _paAllocator ) { 00058 if ( !m_paOurAllocator ) { 00059 m_paOurAllocator = Parent::m_paDefaultAllocator; 00060 } 00061 (*this) = _vOther; 00062 } 00063 LSE_CALL ~CVector() { 00064 Reset(); 00065 } 00066 00067 00068 // == Functions. 00077 LSBOOL LSE_CALL Allocate( LSUINT32 _ui32Total ) { 00078 // If allocating 0 bytes, just reset the list. 00079 if ( !_ui32Total ) { 00080 Reset(); 00081 return true; 00082 } 00083 00084 // Destroy items that are going to be removed. 00085 if ( Parent::m_tLen ) { 00086 for ( LSUINT32 I = Parent::m_tLen; --I >= _ui32Total; ) { 00087 Parent::Destroy( static_cast<_tDataType>(I) ); 00088 } 00089 } 00090 // Adjust the length. 00091 if ( Parent::m_tLen > static_cast<_tDataType>(_ui32Total) ) { 00092 Parent::m_tLen = static_cast<_tDataType>(_ui32Total); 00093 } 00094 00095 // Attempt to allocate. 00096 _tType * ptNew = reinterpret_cast<_tType *>(m_paOurAllocator->Alloc( _ui32Total * sizeof( _tType ) )); 00097 if ( !ptNew ) { return false; } 00098 00099 // Construct and copy all the items in the newly allocated array. 00100 for ( LSUINT32 I = Parent::m_tLen; I--; ) { 00101 // Construct new. 00102 new( &ptNew[I] ) _tType; 00103 // Copy from old to new. 00104 ptNew[I] = Parent::m_ptData[I]; 00105 // Destroy old. 00106 Parent::Destroy( static_cast<_tDataType>(I) ); 00107 } 00108 // Remove the old list. 00109 if ( Parent::m_ptData ) { 00110 m_paOurAllocator->Free( Parent::m_ptData ); 00111 } 00112 00113 // Success. 00114 Parent::m_ptData = ptNew; 00115 Parent::m_tAllocated = static_cast<_tDataType>(_ui32Total); 00116 return true; 00117 } 00118 00122 LSVOID LSE_CALL Reset() { 00123 for ( LSUINT32 I = Parent::m_tLen; I--; ) { 00124 Parent::Destroy( static_cast<_tDataType>(I) ); 00125 } 00126 if ( Parent::m_ptData ) { 00127 m_paOurAllocator->Free( Parent::m_ptData ); 00128 Parent::m_ptData = NULL; 00129 } 00130 Parent::m_tLen = Parent::m_tAllocated = 0; 00131 } 00132 00140 LSBOOL LSE_CALL Insert( const _tType &_tVal, LSUINT32 _ui32Index ) { 00141 assert( _ui32Index <= Parent::m_tLen ); 00142 // If inserting at the end, just push the item. 00143 if ( _ui32Index == Parent::m_tLen ) { return this->Push( _tVal ); } 00144 00145 // Now we know we are inserting in the middle somewhere. 00146 if ( Parent::m_tLen == Parent::m_tAllocated ) { 00147 // Overflow checking. 00148 _tDataType tNewTotal = Parent::m_tAllocated + _uAllocSize; 00149 assert( tNewTotal > Parent::m_tAllocated ); 00150 if ( !Allocate( tNewTotal ) ) { return false; } 00151 } 00152 00153 // Move other items. 00154 // Since this is not a PoD handler, we cannot simply move memory. 00155 // The last item has not been constructed yet, so we cannot call its copy operator yet. 00156 this->Construct( Parent::m_tLen ); 00157 // Move items up one-by-one. 00158 for ( LSUINT32 I = Parent::m_tLen; I > _ui32Index; --I ) { 00159 Parent::m_ptData[I] = Parent::m_ptData[I-1UL]; 00160 } 00161 // No need to destroy/construct the item at the given location. Its copy operator should handle freeing of 00162 // its memory. 00163 Parent::m_ptData[_ui32Index] = _tVal; 00164 ++Parent::m_tLen; 00165 return true; 00166 } 00167 00174 LSVOID LSE_CALL RemoveRangeNoDealloc( LSUINT32 _ui32Index, LSUINT32 _ui32Total ) { 00175 if ( _ui32Total == 0UL ) { return; } 00176 assert( _ui32Index < Parent::m_tLen ); 00177 assert( _ui32Index + _ui32Total <= Parent::m_tLen ); 00178 LSUINT32 ui32End = Parent::m_tLen - _ui32Total; 00179 00180 // Copy items over it. 00181 // Since this is not a PoD handler, we cannot simply move memory. 00182 LSUINT32 ui32CopyEnd = Parent::m_tLen - _ui32Total; 00183 for ( LSUINT32 I = _ui32Index; I < ui32CopyEnd; ++I ) { 00184 Parent::m_ptData[I] = Parent::m_ptData[I+_ui32Total]; 00185 } 00186 00187 // Destroy the tail items that were moved down. 00188 for ( LSINT32 I = static_cast<LSINT32>(Parent::m_tLen); --I >= static_cast<LSINT32>(ui32End); ) { 00189 // Destruct the item. 00190 Parent::Destroy( static_cast<_tDataType>(I) ); 00191 } 00192 Parent::m_tLen = Parent::m_tLen - static_cast<_tDataType>(_ui32Total); 00193 } 00194 00195 // Set the allocator. Causes the object to be fully reset. Cannot be used on 00196 // lists that have contents already. 00197 LSVOID LSE_CALL SetAllocator( CAllocator * _paAllocator ) { 00198 Reset(); 00199 m_paOurAllocator = _paAllocator; 00200 if ( !m_paOurAllocator ) { 00201 m_paOurAllocator = Parent::m_paDefaultAllocator; 00202 } 00203 } 00204 00205 // Get our allocator. 00206 CAllocator * LSE_CALL GetAllocator() { 00207 return m_paOurAllocator; 00208 } 00209 00219 LSVOID LSE_CALL Trash() { 00220 for ( _tDataType I = Parent::m_tLen; I--; ) { 00221 Parent::m_ptData[I].Trash(); 00222 Parent::Destroy( I ); 00223 } 00224 Parent::m_ptData = NULL; 00225 Parent::m_tLen = Parent::m_tAllocated = 0; 00226 } 00227 00228 protected : 00229 // == Members. 00230 // The allocator we should use. 00231 CAllocator * m_paOurAllocator; 00232 00233 private : 00234 typedef CSVectorCrtp<CVector<_tType, _tDataType, _uAllocSize>, _tType, _tDataType, _uAllocSize> 00235 Parent; 00236 }; 00237 00238 } // namespace lstl 00239 00240 #endif // __LSTL_VECTOR_H__