"L. Spiro Engine"

F:/My Projects/LSEngine/Modules/LSTL/Src/String/LSTLStringBase.h

00001 
00020 #ifndef __LSTL_STRINGBASE_H__
00021 #define __LSTL_STRINGBASE_H__
00022 
00023 #include "../LSTLib.h"
00024 #include "../Allocator/LSTLAllocator.h"
00025 #include "../Vector/LSTLVectorPoD.h"
00026 
00027 
00028 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00029 // MACROS
00030 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00031 // Do we want the operators to throw exceptions?  Define this if so.
00032 //#define __LSTL_STRINGS_THROW_EXCEPTIONS__
00033 
00034 #if defined( __LSTL_STRINGS_THROW_EXCEPTIONS__ )
00035 #define LSTL_STRINGS_THROW_DECL                                                                                         throw( ... )
00036 #define LSTL_STRINGS_THROW( VAL )                                                                                       throw( VAL )
00037 #else
00038 #define LSTL_STRINGS_THROW_DECL
00039 #define LSTL_STRINGS_THROW( VAL )
00040 #endif  // #if defined( __LSTL_STRINGS_THROW_EXCEPTIONS__ )
00041 
00042 
00043 namespace lstl {
00044 
00045         // == Enumerations.
00046         // String exceptions.
00047         enum LSTL_STRING_EXCEPTIONS {
00048                 LSTL_SE_OUTOFMEMORY
00049         };
00050 
00056         template <typename _tDerived, typename _tDataType, unsigned _uAllocSize = 32>
00057         class CStringBase : protected CVectorPoD<_tDataType, LSUINT32, _uAllocSize> {
00058         public :
00059                 // == Various constructors.
00060                 explicit LSE_CALL                                                                                                       CStringBase( CAllocator * _paAllocator = NULL ) :
00061                         Parent( _paAllocator ) {
00062                 }
00063                 LSE_CALL                                                                                                                        CStringBase( const _tDataType &_dtValue, CAllocator * _paAllocator = NULL ) :
00064                         Parent( _paAllocator ) {
00065                         Append( _dtValue );
00066                 }
00067                 LSE_CALL                                                                                                                        CStringBase( const _tDataType * _pdtValue, CAllocator * _paAllocator = NULL ) :
00068                         Parent( _paAllocator ) {
00069                         Set( _pdtValue );
00070                 }
00071                 LSE_CALL                                                                                                                        CStringBase( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString, CAllocator * _paAllocator = NULL ) :
00072                         Parent( _paAllocator ) {
00073                         Set( _sbString );
00074                 }
00075 
00076 
00077                 // == Types.
00081                 typedef struct LSSTD_RANGE {
00085                         LSUINT32                                                                                                                ui32Start;
00086 
00090                         LSUINT32                                                                                                                ui32End;
00091                 } * LPLSSTD_RANGE, * const LPCLSSTD_RANGE;
00092 
00093 
00094                 // == Operators.
00095                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00096                 // +
00097                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00105                 CStringBase<_tDerived, _tDataType, _uAllocSize> LSE_CALL                        operator + ( const _tDataType &_dtValue ) LSTL_STRINGS_THROW_DECL {
00106                         CStringBase sbRet( (*this), Parent::m_paOurAllocator );
00107                         if ( !sbRet.Append( _dtValue ) ) {
00108                                 LSTL_STRINGS_THROW( LSTL_SE_OUTOFMEMORY );
00109                         }
00110                         return sbRet;
00111                 }
00112 
00120                 CStringBase<_tDerived, _tDataType, _uAllocSize> LSE_CALL                        operator + ( const _tDataType * _pdtValue ) LSTL_STRINGS_THROW_DECL {
00121                         CStringBase sbRet( (*this), Parent::m_paOurAllocator );
00122                         if ( !sbRet.Append( _pdtValue ) ) {
00123                                 LSTL_STRINGS_THROW( LSTL_SE_OUTOFMEMORY );
00124                         }
00125                         return sbRet;
00126                 }
00127 
00135                 CStringBase<_tDerived, _tDataType, _uAllocSize> LSE_CALL                        operator + ( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) LSTL_STRINGS_THROW_DECL {
00136                         CStringBase sbRet( (*this), Parent::m_paOurAllocator );
00137                         if ( !sbRet.Append( _sbString ) ) {
00138                                 LSTL_STRINGS_THROW( LSTL_SE_OUTOFMEMORY );
00139                         }
00140                         return sbRet;
00141                 }
00142 
00143 
00144 
00145                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00146                 // +=
00147                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00154                 CStringBase<_tDerived, _tDataType, _uAllocSize> & LSE_CALL                      operator += ( const _tDataType &_dtValue ) LSTL_STRINGS_THROW_DECL {
00155                         if ( !Append( _dtValue ) ) { LSTL_STRINGS_THROW( LSTL_SE_OUTOFMEMORY ); }
00156                         return (*this);
00157                 }
00158 
00165                 CStringBase<_tDerived, _tDataType, _uAllocSize> & LSE_CALL                      operator += ( const _tDataType * _pdtValue ) LSTL_STRINGS_THROW_DECL {
00166                         if ( !Append( _pdtValue ) ) { LSTL_STRINGS_THROW( LSTL_SE_OUTOFMEMORY ); }
00167                         return (*this);
00168                 }
00169 
00176                 CStringBase<_tDerived, _tDataType, _uAllocSize> & LSE_CALL                      operator += ( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) LSTL_STRINGS_THROW_DECL {
00177                         if ( !Append( _sbString ) ) { LSTL_STRINGS_THROW( LSTL_SE_OUTOFMEMORY ); }
00178                         return (*this);
00179                 }
00180 
00181 
00182 
00183                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00184                 // COMPARISONS
00185                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00192                 LSBOOL LSE_CALL                                                                                                         operator == ( const _tDataType * _pdtValue ) const {
00193                         const _tDataType * pdtCopy = _pdtValue;
00194                         LSUINT32 ui32Len = 0;
00195                         while ( (*pdtCopy) && ui32Len < Length() ) {
00196                                 if ( (*pdtCopy++) != Parent::m_ptData[ui32Len++] ) { return false; }
00197                         }
00198                         // One or both of the strings ended.  If their lengths are the same, they are equal.
00199                         if ( (*pdtCopy) ) { return false; }
00200                         return static_cast<LSUINT32>(pdtCopy - _pdtValue) == Length();
00201                 }
00202 
00209                 LSBOOL LSE_CALL                                                                                                         operator == ( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
00210                         return Equals( _sbString );
00211                 }
00212 
00219                 LSBOOL LSE_CALL                                                                                                         operator != ( const _tDataType * _pdtValue ) const {
00220                         const _tDataType * pdtCopy = _pdtValue;
00221                         LSUINT32 ui32Len = 0;
00222                         while ( (*pdtCopy) && ui32Len < Length() ) {
00223                                 if ( (*pdtCopy++) != Parent::m_ptData[ui32Len++] ) { return true; }
00224                         }
00225                         // One or both of the strings ended.  If their lengths are the same, they are equal.
00226                         return ui32Len != Length();
00227                 }
00228 
00235                 LSBOOL LSE_CALL                                                                                                         operator != ( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
00236                         return !Equals( _sbString );
00237                 }
00238 
00246                 LSBOOL LSE_CALL                                                                                                         operator < ( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
00247                         return Cmp( _sbString ) < 0;
00248                 }
00249 
00257                 LSBOOL LSE_CALL                                                                                                         operator > ( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
00258                         return Cmp( _sbString ) > 0;
00259                 }
00260 
00261 
00262                 // == Functions.
00263                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00264                 // ALLOCATION
00265                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00272                 LSBOOL LSE_CALL                                                                                                         AllocateAtLeast( LSUINT32 _ui32Total ) {
00273                         if ( _ui32Total <= Parent::m_tLen + 1UL ) { return true; }      // Nothing to do.
00274                         return Parent::Allocate( _ui32Total );
00275                 }
00276 
00281                 LSVOID LSE_CALL                                                                                                         Reset() { Parent::Reset(); }
00282 
00287                 LSVOID LSE_CALL                                                                                                         Trash() {
00288                         Parent::m_tLen = Parent::m_tAllocated = 0;
00289                         Parent::m_ptData = NULL;
00290                 }
00291 
00296                 LSVOID LSE_CALL                                                                                                         ResetNoDealloc() { Parent::ResetNoDealloc(); }
00297 
00303                 LSVOID LSE_CALL                                                                                                         SetAllocator( CAllocator * _paAllocator ) { Parent::SetAllocator( _paAllocator ); }
00304 
00310                 CAllocator * LSE_CALL                                                                                           GetAllocator() { return Parent::GetAllocator(); }
00311 
00317                 LSVOID LSE_CALL                                                                                                         Snap() {
00318                         this->Allocate( Parent::m_tLen + 1 );
00319                 }
00320 
00321 
00322 
00323                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00324                 // C-STRING
00325                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00331                 LSUINT32 LSE_CALL                                                                                                       Length() const { return Parent::Length(); }
00332 
00339                 const _tDataType * LSE_CALL                                                                                     CStr() const {
00340                         // An empty string handles the cases where our string is empty.  When our string is
00341                         //      empty the data pointer may also be NULL.  Avoid trouble by returning a valid 0-length
00342                         //      character array when our length is 0.
00343                         static const _tDataType dtDefault( 0 );
00344                         return Length() ? Parent::m_ptData : &dtDefault;
00345                 }
00346 
00347 
00348 
00349                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00350                 // APPEND/REMOVE/SET
00351                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00359                 LSBOOL LSE_CALL                                                                                                         Append( const _tDataType &_dtValue ) {
00360                         LSUINT32 ui32NewLen = Parent::m_tLen + 2;
00361                         if ( ui32NewLen >= Parent::m_tAllocated ) {
00362                                 if ( !Parent::Allocate( ui32NewLen + _uAllocSize ) ) { return false; }
00363                         }
00364                         Parent::m_ptData[Parent::m_tLen++] = _dtValue;
00365                         Parent::m_ptData[Parent::m_tLen] = _tDataType( 0 );
00366                         return true;
00367                 }
00368 
00377                 LSBOOL LSE_CALL                                                                                                         Append( const _tDataType * _pdtValue, LSUINT32 _ui32Len ) {
00378                         LSUINT32 ui32NewLen = Parent::m_tLen + _ui32Len + 1;
00379                         if ( ui32NewLen >= Parent::m_tAllocated ) {
00380                                 if ( !Parent::Allocate( ui32NewLen + _uAllocSize ) ) { return false; }
00381                         }
00382                         CStd::MemCpy( &Parent::m_ptData[Parent::m_tLen], _pdtValue, sizeof( _tDataType ) * _ui32Len );
00383                         Parent::m_tLen += _ui32Len;
00384                         Parent::m_ptData[Parent::m_tLen] = _tDataType( 0 );
00385                         return true;
00386                 }
00387 
00395                 LSBOOL LSE_CALL                                                                                                         Append( const _tDataType * _pdtValue ) {
00396                         // Redirect.
00397                         return Append( _pdtValue, static_cast<_tDerived *>(this)->StrLen( _pdtValue ) );
00398                 }
00399 
00406                 LSBOOL LSE_CALL                                                                                                         Append( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) {
00407                         // Redirect.
00408                         return Append( _sbString.Parent::m_ptData, _sbString.Length() );
00409                 }
00410 
00416                 LSVOID LSE_CALL                                                                                                         RemChar( LSUINT32 _ui32Index ) {
00417                         if ( _ui32Index >= Length() ) { return; }
00418                         Parent::RemoveNoDealloc( _ui32Index );
00419                         Parent::m_ptData[Parent::m_tLen] = _tDataType( 0 );
00420                 }
00421 
00429                 LSVOID LSE_CALL                                                                                                         RemChars( LSUINT32 _ui32Index, LSUINT32 _ui32Total ) {
00430                         if ( _ui32Index >= Length() ) { return; }
00431                         if ( _ui32Index + _ui32Total > Length() ) {
00432                                 _ui32Total = Length() - _ui32Index;
00433                         }
00434                         Parent::RemoveRangeNoDealloc( _ui32Index, _ui32Total );
00435                         Parent::m_ptData[Parent::m_tLen] = _tDataType( 0 );
00436                 }
00437 
00443                 LSVOID LSE_CALL                                                                                                         RemRange( const LSSTD_RANGE &_rRange ) {
00444                         RemChars( _rRange.ui32Start, _rRange.ui32End - _rRange.ui32Start );
00445                 }
00446 
00452                 LSBOOL LSE_CALL                                                                                                         RemLastChar() {
00453                         if ( Parent::m_tLen == 0 ) { return false; }
00454                         RemChar( Parent::m_tLen - 1 );
00455                         return true;
00456                 }
00457 
00466                 LSBOOL LSE_CALL                                                                                                         Set( const _tDataType * _pdtValue, LSUINT32 _ui32Len ) {
00467                         if ( (_ui32Len + 1) > Parent::m_tAllocated ) {
00468                                 if ( !Parent::Allocate( (_ui32Len + 1) ) ) { return false; }
00469                         }
00470                         CStd::MemCpy( &Parent::m_ptData[0], _pdtValue, sizeof( _tDataType ) * _ui32Len );
00471                         Parent::m_tLen = _ui32Len;
00472                         Parent::m_ptData[Parent::m_tLen] = _tDataType( 0 );
00473                         return true;
00474                 }
00475 
00483                 LSBOOL LSE_CALL                                                                                                         Set( const _tDataType * _pdtValue ) {
00484                         return Set( _pdtValue, static_cast<_tDerived *>(this)->StrLen( _pdtValue ) );
00485                 }
00486 
00494                 LSBOOL LSE_CALL                                                                                                         Set( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) {
00495                         return Set( _sbString.Parent::m_ptData, _sbString.Length() );
00496                 }
00497 
00507                 LSBOOL LSE_CALL                                                                                                         Replace( const LSSTD_RANGE &_rRange,
00508                         const _tDataType * _pdtValue, LSUINT32 _ui32Len ) {
00509                         // Firstly, if the start of the range is beyond the last character, do nothing.
00510                         if ( _rRange.ui32Start > Parent::m_tLen ) {
00511                                 return false;
00512                         }
00513                         // If adding to the end, just append.
00514                         if ( _rRange.ui32Start == Parent::m_tLen ) {
00515                                 return Append( _pdtValue, _ui32Len );
00516                         }
00517 
00518 
00519                         LSUINT32 ui32End = CStd::Min( Parent::m_tLen - _rRange.ui32Start, _rRange.ui32End - _rRange.ui32Start );
00520                         // If the new value has the same length as the old, simply copy the value over.
00521                         if ( ui32End == _ui32Len ) {
00522                                 CStd::MemCpy( &Parent::m_ptData[_rRange.ui32Start], _pdtValue, sizeof( _tDataType ) * _ui32Len );
00523                                 return true;
00524                         }
00525                         // Remove the given range.
00526                         RemRange( _rRange );
00527                         // Insert the given string.
00528                         return Insert( _rRange.ui32Start, _pdtValue, _ui32Len );
00529                 }
00530 
00539                 LSBOOL LSE_CALL                                                                                                         Replace( const LSSTD_RANGE &_rRange,
00540                         const _tDataType * _pdtValue ) {
00541                         return Replace( _rRange, _pdtValue, static_cast<_tDerived *>(this)->StrLen( _pdtValue ) );
00542                 }
00543 
00553                 LSBOOL LSE_CALL                                                                                                         Insert( LSUINT32 _ui32Pos,
00554                         const _tDataType * _pdtValue, LSUINT32 _ui32Len ) {
00555                         if ( !_pdtValue ) { return false; }
00556                         if ( _ui32Pos > Parent::m_tLen ) {
00557                                 return false;
00558                         }
00559                         if ( _ui32Pos == Parent::m_tLen ) {
00560                                 return Append( _pdtValue, _ui32Len );
00561                         }
00562 
00563                         // Expand the string to give us enough room to insert.
00564                         LSUINT32 ui32NewLen = Parent::m_tLen + _ui32Len + 1;
00565                         if ( ui32NewLen >= Parent::m_tAllocated ) {
00566                                 if ( !Parent::Allocate( ui32NewLen + _uAllocSize ) ) { return false; }
00567                         }
00568                         CStd::MemMove( &Parent::m_ptData[_ui32Pos+_ui32Len], &Parent::m_ptData[_ui32Pos], sizeof( _tDataType ) * (Parent::m_tLen - _ui32Pos) );
00569                         CStd::MemCpy( &Parent::m_ptData[_ui32Pos], _pdtValue, sizeof( _tDataType ) * _ui32Len );
00570                         Parent::m_tLen += _ui32Len;
00571                         Parent::m_ptData[Parent::m_tLen] = _tDataType( 0 ); 
00572                         return true;
00573                 }
00574 
00583                 LSBOOL LSE_CALL                                                                                                         Insert( LSUINT32 _ui32Pos,
00584                         const _tDataType * _pdtValue ) {
00585                         if ( !_pdtValue ) { return false; }
00586                         return Insert( _ui32Pos, _pdtValue, StrLen( _pdtValue ) );
00587                 }
00588 
00597                 LSBOOL LSE_CALL                                                                                                         Insert( LSUINT32 _ui32Pos,
00598                         _tDataType _dtValue ) {
00599                         
00600                         return Insert( _ui32Pos, &_dtValue, 1UL );
00601                 }
00602 
00608                 _tDataType LSE_CALL                                                                                                     GetLastChar() const {
00609                         if ( !Parent::m_tLen ) { return _tDataType( 0 ); }
00610                         return Parent::m_ptData[Parent::m_tLen-1];
00611                 }
00612 
00620                 CStringBase<_tDerived, _tDataType, _uAllocSize> LSE_CALL                        GetToken( _tDataType _tDelimiter, LSUINT32 _ui32Index ) const {
00621                         CStringBase<_tDerived, _tDataType, _uAllocSize> sbRet;
00622 
00623                         LSUINT32 I = 0UL;
00624                         for ( ++_ui32Index; _ui32Index > 0UL; --_ui32Index ) {
00625                                 if ( I == Parent::m_tLen ) { break; }
00626 
00627                                 // Skip the delimiter tokens, if any.
00628                                 _tDataType tThis = Parent::m_ptData[I++];
00629                                 while ( tThis == _tDelimiter && I < Parent::m_tLen ) {
00630                                         tThis = Parent::m_ptData[I++];
00631                                 }
00632 
00633                                 // The next set of characters make a token until the next delimiter.
00634                                 //      If _ui32Index is 1, we store these characters, otherwise not.
00635                                 while ( tThis != _tDelimiter ) {
00636                                         if ( _ui32Index == 1 ) {
00637                                                 sbRet += tThis;
00638                                         }
00639 
00640                                         if ( I == Parent::m_tLen ) {
00641                                                 break;
00642                                         }
00643                                         tThis = Parent::m_ptData[I++];
00644                                 }
00645                         }
00646 
00647                         return sbRet;
00648                 }
00649 
00658                 LSSTD_RANGE LSE_CALL                                                                                            FindStringMatchCase( LSUINT32 _ui32Start,
00659                         const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
00660                         LSSTD_RANGE rRet;
00661                         rRet.ui32Start = Parent::m_tLen;
00662                         rRet.ui32End = 0UL;
00663 
00664                         // Sanity check.
00665                         if ( _sbString.Length() + _ui32Start > Parent::m_tLen || _ui32Start >= Parent::m_tLen ) {
00666                                 return rRet;
00667                         }
00668                         
00669                         rRet.ui32Start = _ui32Start;
00670                         LSUINT32 ui32End = Parent::m_tLen - _sbString.Length();
00671                         while ( rRet.ui32Start <= ui32End ) {
00672                                 if ( CStd::MemCmpF( &Parent::m_ptData[rRet.ui32Start], _sbString.CStr(), sizeof( _tDataType ) * _sbString.Length() ) ) {
00673                                         rRet.ui32End = rRet.ui32Start + _sbString.Length();
00674                                         return rRet;
00675                                 }
00676                                 ++rRet.ui32Start;
00677                         }
00678                         rRet.ui32Start = Parent::m_tLen;
00679                         return rRet;
00680                 }
00681 
00691                 LSSTD_RANGE LSE_CALL                                                                                            FindString( LSUINT32 _ui32Start,
00692                         const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
00693                         LSSTD_RANGE rRet;
00694                         rRet.ui32Start = Parent::m_tLen;
00695                         rRet.ui32End = 0UL;
00696 
00697                         // Sanity check.
00698                         if ( _sbString.Length() + _ui32Start > Parent::m_tLen || _ui32Start >= Parent::m_tLen ) {
00699                                 return rRet;
00700                         }
00701                         
00702                         rRet.ui32Start = _ui32Start;
00703                         LSUINT32 ui32End = Parent::m_tLen - _sbString.Length();
00704                         while ( rRet.ui32Start <= ui32End ) {
00705                                 if ( ICmpSubString( rRet.ui32Start, _sbString ) == 0 ) {
00706                                         rRet.ui32End = rRet.ui32Start + _sbString.Length();
00707                                         return rRet;
00708                                 }
00709                                 ++rRet.ui32Start;
00710                         }
00711                         rRet.ui32Start = Parent::m_tLen;
00712                         return rRet;
00713                 }
00714 
00723                 LSSTD_RANGE LSE_CALL                                                                                            FindWildcardStringMatchCase( LSUINT32 _ui32Start,
00724                         const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
00725                         LSSTD_RANGE rRet;
00726                         rRet.ui32Start = Parent::m_tLen;
00727                         rRet.ui32End = 0UL;
00728 
00729                         // Sanity check.
00730                         if ( _sbString.Length() + _ui32Start > Parent::m_tLen || _ui32Start >= Parent::m_tLen ) {
00731                                 return rRet;
00732                         }
00733                         
00734                         rRet.ui32Start = _ui32Start;
00735                         LSUINT32 ui32End = Parent::m_tLen - _sbString.Length();
00736                         while ( rRet.ui32Start <= ui32End ) {
00737                                 LSUINT32 ui32Len = CmpWildcard( rRet.ui32Start, _sbString, 2048UL );
00738                                 if ( ui32Len ) {
00739                                         rRet.ui32End = rRet.ui32Start + ui32Len;
00740                                         return rRet;
00741                                 }
00742                                 ++rRet.ui32Start;
00743                         }
00744                         rRet.ui32Start = Parent::m_tLen;
00745                         return rRet;
00746                 }
00747 
00756                 LSUINT32 LSE_CALL                                                                                                       FindAndReplaceWildcardStringMatchCase( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbReplaceMe,
00757                         const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbWithMe,
00758                         LSBOOL _bWholeWords = false ) {
00759 
00760                         LSSTD_RANGE rRange = {
00761                                 0UL,
00762                                 0UL
00763                         };
00764                         LSUINT32 ui32Count = 0UL;
00765                         while ( rRange.ui32Start < Parent::m_tLen ) {
00766                                 rRange = FindWildcardStringMatchCase( rRange.ui32Start, _sbReplaceMe );
00767                                 if ( rRange.ui32End ) {
00768                                         if ( !_bWholeWords || IsWholeWord( rRange ) ) {
00769                                                 if ( Replace( rRange, _sbWithMe.CStr(), _sbWithMe.Length() ) ) {
00770                                                         ++ui32Count;
00771                                                 }
00772                                         }
00773                                         rRange.ui32Start += _sbWithMe.Length();
00774                                 }
00775                         }
00776                         return ui32Count;
00777                 }
00778 
00786                 LSUINT32 LSE_CALL                                                                                                       FindAndReplaceChar( _tDataType _tReplaceMe, _tDataType _tWithMe ) {
00787                         LSUINT32 ui32Count = 0UL;
00788                         for ( LSUINT32 I = Length(); I--; ) {
00789                                 if ( Parent::m_ptData[I] == _tReplaceMe ) {
00790                                         Parent::m_ptData[I] = _tWithMe;
00791                                         ++ui32Count;
00792                                 }
00793                         }
00794                         return ui32Count;
00795                 }
00796 
00803                 LSBOOL LSE_CALL                                                                                                         IsWholeWord( LSSTD_RANGE _rRange ) const {
00804                         // Firstly, is the range valid?
00805                         if ( _rRange.ui32Start >= Parent::m_tLen ) { return true; }
00806                         if ( _rRange.ui32End >= Parent::m_tLen ) { return true; }
00807                         if ( _rRange.ui32Start >= _rRange.ui32End ) { return false; }
00808 
00809                         // Try to eliminate by the data to the left of the start.
00810                         _tDataType dtValue = Parent::m_ptData[_rRange.ui32Start];
00811                         // If either the left- or the right- most characters are not word characters, return true immediately.
00812                         if ( !((dtValue >= static_cast<_tDataType>('a') && dtValue <= static_cast<_tDataType>('z')) ||
00813                                 (dtValue >= static_cast<_tDataType>('A') && dtValue <= static_cast<_tDataType>('Z')) ||
00814                                 (dtValue >= static_cast<_tDataType>('0') && dtValue <= static_cast<_tDataType>('9')) ||                 
00815                                 dtValue == static_cast<_tDataType>('_')) ) {
00816                                 return true;
00817                         }
00818                         dtValue = Parent::m_ptData[_rRange.ui32End-1];
00819                         if ( !((dtValue >= static_cast<_tDataType>('a') && dtValue <= static_cast<_tDataType>('z')) ||
00820                                 (dtValue >= static_cast<_tDataType>('A') && dtValue <= static_cast<_tDataType>('Z')) ||
00821                                 (dtValue >= static_cast<_tDataType>('0') && dtValue <= static_cast<_tDataType>('9')) ||                 
00822                                 dtValue == static_cast<_tDataType>('_')) ) {
00823                                 return true;
00824                         }
00825 
00826                         // Both the left and right border characters are word characters, so check the next character to the left and right.
00827                         if ( _rRange.ui32Start ) {
00828                                 dtValue = Parent::m_ptData[_rRange.ui32Start-1];
00829                                 if ( ((dtValue >= static_cast<_tDataType>('a') && dtValue <= static_cast<_tDataType>('z')) ||
00830                                         (dtValue >= static_cast<_tDataType>('A') && dtValue <= static_cast<_tDataType>('Z')) ||
00831                                         (dtValue >= static_cast<_tDataType>('0') && dtValue <= static_cast<_tDataType>('9')) ||                 
00832                                         dtValue == static_cast<_tDataType>('_')) ) {
00833                                         return false;
00834                                 }
00835                         }
00836                         if ( _rRange.ui32End < Parent::m_tLen ) {
00837                                 dtValue = Parent::m_ptData[_rRange.ui32End];
00838                                 if ( ((dtValue >= static_cast<_tDataType>('a') && dtValue <= static_cast<_tDataType>('z')) ||
00839                                         (dtValue >= static_cast<_tDataType>('A') && dtValue <= static_cast<_tDataType>('Z')) ||
00840                                         (dtValue >= static_cast<_tDataType>('0') && dtValue <= static_cast<_tDataType>('9')) ||                 
00841                                         dtValue == static_cast<_tDataType>('_')) ) {
00842                                         return false;
00843                                 }
00844                         }
00845 
00846                         // 
00847                         return true;
00848                 }
00849 
00855                 CStringBase<_tDerived, _tDataType, _uAllocSize> & LSE_CALL                      RemoveWhitespace() {
00856                         if ( !Parent::m_ptData ) { return (*this); }
00857 
00858                         // Start at the end of the string since removing characters from there is faster.
00859                         while ( Parent::m_tLen && CStd::IsWhitespace( Parent::m_ptData[Parent::m_tLen-1] ) ) {
00860                                 --Parent::m_tLen;
00861                         }
00862                         Parent::m_ptData[Parent::m_tLen] = _tDataType( 0 );
00863 
00864 
00865                         // Count the number of characters from the front that need to be removed.
00866                         LSUINT32 ui32Total = 0UL;
00867                         for ( ; ui32Total < Parent::m_tLen; ++ui32Total ) {
00868                                 if ( !CStd::IsWhitespace( Parent::m_ptData[ui32Total] ) ) { break; }
00869                         }
00870                         if ( ui32Total ) {
00871                                 RemChars( 0UL, ui32Total );
00872                         }
00873 
00874                         return (*this);
00875                 }
00876 
00905                 CStringBase<_tDerived, _tDataType, _uAllocSize> LSE_CALL                        DecodeEscapeSequences() const {
00906                         CStringBase<_tDerived, _tDataType, _uAllocSize> sbRet( Parent::m_paOurAllocator );
00907                         
00908                         LSUINT32 ui32Size;
00909                         for ( LSUINT32 I = 0UL; I < Parent::m_tLen; I += ui32Size ) {
00910                                 sbRet.Append( DecodeEscape( &Parent::m_ptData[I], Parent::m_tLen - I, ui32Size ) );
00911                         }
00912                         return sbRet;
00913                 }
00914 
00923                 static _tDataType LSE_CALL                                                                                      DecodeEscape( const _tDataType * _pdtValue, LSUINT32 _ui32Len, LSUINT32 &_ui32Size ) {
00924                         struct {
00928                                 _tDataType                              dtEscape;
00929 
00933                                 _tDataType                              dtValue;
00934                         } sEscapes[] = {
00935                                 { 'a', '\a' },
00936                                 { 'b', '\b' },
00937                                 { 'f', '\f' },
00938                                 { 'n', '\n' },
00939                                 { 'r', '\r' },
00940                                 { 't', '\t' },
00941                                 { 'v', '\v' },
00942                                 { '\\', '\\' },
00943                                 { '\'', '\'' },
00944                                 { '"', '\"' },
00945                                 { '?', '\?' },
00946                                 { ' ', ' ' },
00947                         };
00948 
00949                         if ( _ui32Len == 0UL ) {
00950                                 _ui32Size = 0UL;
00951                                 return static_cast<_tDataType>(0);
00952                         }
00953                         // If the length is 1 or the next character is not a back slash, the next character is the return.
00954                         _ui32Size = 1UL;
00955                         if ( _ui32Len == 1UL || _pdtValue[0] != static_cast<_tDataType>('\\') ) {
00956                                 return _pdtValue[0];
00957                         }
00958                         // Possible sequence here.
00959                         switch ( _pdtValue[1] ) {
00960                                 case 'x' : {
00961                                         // Hex sequence.  Decode.
00962                                         if ( _ui32Len == 2UL ) {
00963                                                 return _pdtValue[0];
00964                                         }
00965                                         _tDataType dtReturn = 0;
00966                                         _tDataType dtThis;
00967                                         // Decode the hex characters (maximum of 2).
00968                                         for ( LSUINT32 I = 2UL; I < _ui32Len && I < 4UL; I++ ) {
00969                                                 if ( _pdtValue[I] >= static_cast<_tDataType>('0') && _pdtValue[I] <= static_cast<_tDataType>('9') ) {
00970                                                         dtThis = _pdtValue[I] - static_cast<_tDataType>('0');
00971                                                 }
00972                                                 else if ( _pdtValue[I] >= static_cast<_tDataType>('A') && _pdtValue[I] <= static_cast<_tDataType>('F') ) {
00973                                                         dtThis = _pdtValue[I] - static_cast<_tDataType>('A') + 0xA;
00974                                                 }
00975                                                 else if ( _pdtValue[I] >= static_cast<_tDataType>('a') && _pdtValue[I] <= static_cast<_tDataType>('f') ) {
00976                                                         dtThis = _pdtValue[I] - static_cast<_tDataType>('a') + 0xA;
00977                                                 }
00978                                                 else {
00979                                                         // No characters were eaten?
00980                                                         if ( I == 2 ) { return _pdtValue[0]; }
00981 
00982                                                         // Eat the x.
00983                                                         ++_ui32Size;
00984                                                         return dtReturn;
00985                                                 }
00986                                                 dtReturn <<= 4;
00987                                                 dtReturn |= dtThis;
00988                                                 ++_ui32Size;
00989                                         }
00990                                         // Eat the x.
00991                                         ++_ui32Size;
00992                                         return dtReturn;
00993                                 }
00994                                 default : {
00995                                         if ( _pdtValue[1] >= '0' && _pdtValue[1] <= '7' ) {
00996                                                 // Decode octal sequences.
00997                                                 _tDataType dtReturn = 0;
00998                                                 _tDataType dtThis;
00999                                                 for ( LSUINT32 I = 1UL; I < _ui32Len && I < 4UL; I++ ) {
01000                                                         if ( _pdtValue[I] >= '0' && _pdtValue[I] <= '7' ) {
01001                                                                 dtThis = _pdtValue[I] - '0';
01002                                                         }
01003                                                         else {
01004                                                                 // No characters were eaten?
01005                                                                 if ( I == 1 ) { return _pdtValue[0]; }
01006                                                                 return dtReturn;
01007                                                         }
01008                                                         dtReturn <<= 3UL;
01009                                                         dtReturn |= dtThis;
01010                                                         ++_ui32Size;
01011                                                 }
01012                                                 return dtReturn;
01013                                         }
01014                                         else {
01015                                                 for ( LSUINT32 J = 0UL; sEscapes[J].dtEscape != ' '; J++ ) {
01016                                                         if ( _pdtValue[1] == sEscapes[J].dtEscape ) {
01017                                                                 ++_ui32Size;
01018                                                                 return sEscapes[J].dtValue;
01019                                                         }
01020                                                 }
01021                                         }
01022                                 }
01023                         }
01024                         return _pdtValue[0];
01025                 }
01026 
01027 
01028 
01029                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
01030                 // COMPARISONS
01031                 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
01045                 LSINT32 LSE_CALL                                                                                                        Cmp( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
01046                         LSUINT32 ui32Max = CStd::Max( _sbString.Length(), Length() );
01047                         for ( LSUINT32 I = 0; I < ui32Max; ++I ) {
01048                                 _tDataType dtLeft = I < Length() ? Parent::m_ptData[I] : _tDataType( 0 );
01049                                 _tDataType dtRight = I < _sbString.Length() ? _sbString.Parent::m_ptData[I] : _tDataType( 0 );
01050                                 LSINT32 i32Dif = dtLeft - dtRight;
01051                                 if ( i32Dif != 0 ) {
01052                                         // Something somewhere needs a change.  They'll need a crane!
01053                                         return i32Dif;
01054                                 }
01055                         }
01056                         if ( _sbString.Length() == Length() ) { return 0; }
01057                         return _sbString.Length() > Length() ? -_sbString[Length()] : Parent::m_ptData[_sbString.Length()];
01058                 }
01059 
01066                 LSINT32 LSE_CALL                                                                                                        ICmp( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
01067                         LSUINT32 ui32Max = CStd::Max( _sbString.Length(), Length() );
01068                         for ( LSUINT32 I = 0; I < ui32Max; ++I ) {
01069                                 _tDataType dtLeft = I < Length() ? Parent::m_ptData[I] : _tDataType( 0 );
01070                                 _tDataType dtRight = I < _sbString.Length() ? _sbString.Parent::m_ptData[I] : _tDataType( 0 );
01071                                 LSINT32 i32Dif = CStd::ToLower( dtLeft ) - CStd::ToLower( dtRight );
01072                                 if ( i32Dif != 0 ) {
01073                                         // Somewhere something needs a change.  They'll need a crane!
01074                                         return i32Dif;
01075                                 }
01076                         }
01077                         if ( _sbString.Length() == Length() ) { return 0; }
01078                         return _sbString.Length() > Length() ? -_sbString[Length()] : Parent::m_ptData[_sbString.Length()];
01079                 }
01080 
01088                 LSINT32 LSE_CALL                                                                                                        ICmpSubString( LSUINT32 _ui32Loc,
01089                         const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
01090                         if ( _ui32Loc >= Length() ) {
01091                                 return -1;
01092                         }
01093                         LSUINT32 ui32Max = CStd::Min( _sbString.Length(), Length() - _ui32Loc );
01094                         for ( LSUINT32 I = 0; I < ui32Max; ++I ) {
01095                                 _tDataType dtLeft = I < Length() ? Parent::m_ptData[_ui32Loc+I] : _tDataType( 0 );
01096                                 _tDataType dtRight = I < _sbString.Length() ? _sbString.Parent::m_ptData[I] : _tDataType( 0 );
01097                                 LSINT32 i32Dif = CStd::ToLower( dtLeft ) - CStd::ToLower( dtRight );
01098                                 if ( i32Dif != 0 ) {
01099                                         // Somewhere something needs a change.  They'll need a crane!
01100                                         return i32Dif;
01101                                 }
01102                         }
01103                         return _sbString.Length() == Length() - _ui32Loc;
01104                 }
01105 
01114                 LSUINT32 LSE_CALL                                                                                                       CmpWildcard( LSUINT32 _ui32Start,
01115                         const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString, LSUINT32 _ui32MaxWildcardLen ) const {
01116                         if ( _ui32Start >= Length() ) {
01117                                 return 0;
01118                         }
01119                         LSUINT32 ui32BufPos = 0UL;
01120                         LSUINT32 I = 0UL;
01121                         LSUINT32 ui32Len = Length() - _ui32Start;
01122                         _tDataType * pdtBuffer = &Parent::m_ptData[_ui32Start];
01123                         for ( ; I < _sbString.Length(); I++, ui32BufPos++ ) {
01124                                 if ( ui32BufPos == ui32Len ) { goto End; }
01125                                 switch ( _sbString.CStr()[I] ) {
01126                                         case '?' : { continue; }
01127                                         case '*' : {
01128                                                 // Skip all the * and ? characters.
01129                                                 while ( I < _sbString.Length() && (_sbString.CStr()[I] == static_cast<_tDataType>('*') || _sbString.CStr()[I] == static_cast<_tDataType>('?')) ) { I++; }
01130                                                 if ( I == _sbString.Length() ) { goto End; }
01131 
01132                                                 // Within the wildcard match length, find the next character.
01133                                                 LSUINT8 ui8This = _sbString.CStr()[I];
01134 
01135                                                 for ( LSUINT32 J = 0; J < _ui32MaxWildcardLen && ui32BufPos < ui32Len && pdtBuffer[ui32BufPos] != ui8This; ui32BufPos++ ) {}
01136 
01137                                                 // If this caused us to reach the end of the buffer, fail.
01138                                                 if ( ui32BufPos == ui32Len ) { return 0UL; }
01139 
01140                                                 // Everything is good.
01141                                                 break;
01142                                         }
01143                                         default : {
01144                                                 if ( _sbString.CStr()[I] != pdtBuffer[ui32BufPos] ) { return 0UL; }
01145                                         }
01146                                 }
01147                         }
01148 End :
01149                         // Skip all the * characters.
01150                         while ( I < _sbString.Length() && _sbString.CStr()[I] == static_cast<_tDataType>('*') ) { I++; }
01151 
01152                         return I == _sbString.Length() ? ui32BufPos : 0UL;
01153                 }
01154 
01162                 LSBOOL LSE_CALL                                                                                                         Equals( const CStringBase<_tDerived, _tDataType, _uAllocSize> &_sbString ) const {
01163                         if ( Length() != _sbString.Length() ) { return false; }
01164                         return CStd::MemCmpF( Parent::m_ptData, _sbString.Parent::m_ptData, sizeof( _tDataType ) * Length() );
01165                 }
01166 
01167 
01168         protected :
01169                 // == Members.
01170 
01171 
01172                 // == Functions.
01177                 LSUINT32 LSE_CALL                                                                                                       StrLen( const _tDataType * _pdtValue ) const {
01178                         const _tDataType * pdtCopy = _pdtValue;
01179                         while ( (*pdtCopy++) ) {}
01180                         return static_cast<LSUINT32>((pdtCopy - _pdtValue) - 1);
01181                 }
01182 
01183         private :
01184                 typedef CVectorPoD<_tDataType, LSUINT32, _uAllocSize>                           Parent;
01185         };
01186 
01187 }       // namespace lstl
01188 
01189 #endif  // __LSTL_STRINGBASE_H__
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator