"L. Spiro Engine"

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

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