1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxString class 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13   #pragma implementation "string.h" 
  18  *  1) all empty strings use g_strEmpty, nRefs = -1 (set in Init()) 
  19  *  2) AllocBuffer() sets nRefs to 1, Lock() increments it by one 
  20  *  3) Unlock() decrements nRefs and frees memory if it goes to 0 
  23 // =========================================================================== 
  24 // headers, declarations, constants 
  25 // =========================================================================== 
  27 // For compilers that support precompilation, includes "wx.h". 
  28 #include "wx/wxprec.h" 
  36   #include "wx/string.h" 
  38   #include "wx/thread.h" 
  49 // allocating extra space for each string consumes more memory but speeds up 
  50 // the concatenation operations (nLen is the current string's length) 
  51 // NB: EXTRA_ALLOC must be >= 0! 
  52 #define EXTRA_ALLOC       (19 - nLen % 16) 
  54 // --------------------------------------------------------------------------- 
  55 // static class variables definition 
  56 // --------------------------------------------------------------------------- 
  58 #if defined(__VISAGECPP__) && __IBMCPP__ >= 400 
  59 // must define this static for VA or else you get multiply defined symbols 
  61 const unsigned int wxSTRING_MAXLEN 
= UINT_MAX 
- 100; 
  65   const size_t wxStringBase::npos 
= wxSTRING_MAXLEN
; 
  68 // ---------------------------------------------------------------------------- 
  70 // ---------------------------------------------------------------------------- 
  74 extern const wxChar WXDLLIMPEXP_BASE 
*wxEmptyString 
= _T(""); 
  78 // for an empty string, GetStringData() will return this address: this 
  79 // structure has the same layout as wxStringData and it's data() method will 
  80 // return the empty string (dummy pointer) 
  85 } g_strEmpty 
= { {-1, 0, 0}, wxT('\0') }; 
  87 // empty C style string: points to 'string data' byte of g_strEmpty 
  88 extern const wxChar WXDLLIMPEXP_BASE 
*wxEmptyString 
= &g_strEmpty
.dummy
; 
  92 // ---------------------------------------------------------------------------- 
  94 // ---------------------------------------------------------------------------- 
  96 #if wxUSE_STD_IOSTREAM 
  98 // MS Visual C++ version 5.0 provides the new STL headers as well as the old 
 101 // ATTN: you can _not_ use both of these in the same program! 
 105 wxSTD istream
& operator>>(wxSTD istream
& is
, wxString
& WXUNUSED(str
)) 
 110     streambuf 
*sb 
= is
.rdbuf(); 
 113       int ch 
= sb
->sbumpc (); 
 115         is
.setstate(ios::eofbit
); 
 118       else if ( isspace(ch
) ) { 
 130   if ( str
.length() == 0 ) 
 131     is
.setstate(ios::failbit
); 
 136 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxString
& str
) 
 142 #endif // wxUSE_STD_IOSTREAM 
 144 // ---------------------------------------------------------------------------- 
 146 // ---------------------------------------------------------------------------- 
 148 // this small class is used to gather statistics for performance tuning 
 149 //#define WXSTRING_STATISTICS 
 150 #ifdef  WXSTRING_STATISTICS 
 154     Averager(const wxChar 
*sz
) { m_sz 
= sz
; m_nTotal 
= m_nCount 
= 0; } 
 156    { wxPrintf("wxString: average %s = %f\n", m_sz
, ((float)m_nTotal
)/m_nCount
); } 
 158     void Add(size_t n
) { m_nTotal 
+= n
; m_nCount
++; } 
 161     size_t m_nCount
, m_nTotal
; 
 163   } g_averageLength("allocation size"), 
 164     g_averageSummandLength("summand length"), 
 165     g_averageConcatHit("hit probability in concat"), 
 166     g_averageInitialLength("initial string length"); 
 168   #define STATISTICS_ADD(av, val) g_average##av.Add(val) 
 170   #define STATISTICS_ADD(av, val) 
 171 #endif // WXSTRING_STATISTICS 
 175 // =========================================================================== 
 176 // wxStringData class deallocation 
 177 // =========================================================================== 
 179 #if defined(__VISUALC__) && defined(_MT) && !defined(_DLL) 
 180 #  pragma message (__FILE__ ": building with Multithreaded non DLL runtime has a performance impact on wxString!") 
 181 void wxStringData::Free() 
 187 // =========================================================================== 
 189 // =========================================================================== 
 191 // takes nLength elements of psz starting at nPos 
 192 void wxStringBase::InitWith(const wxChar 
*psz
, size_t nPos
, size_t nLength
) 
 196   // if the length is not given, assume the string to be NUL terminated 
 197   if ( nLength 
== npos 
) { 
 198     wxASSERT_MSG( nPos 
<= wxStrlen(psz
), _T("index out of bounds") ); 
 200     nLength 
= wxStrlen(psz 
+ nPos
); 
 203   STATISTICS_ADD(InitialLength
, nLength
); 
 206     // trailing '\0' is written in AllocBuffer() 
 207     if ( !AllocBuffer(nLength
) ) { 
 208       wxFAIL_MSG( _T("out of memory in wxStringBase::InitWith") ); 
 211     memcpy(m_pchData
, psz 
+ nPos
, nLength
*sizeof(wxChar
)); 
 215 // poor man's iterators are "void *" pointers 
 216 wxStringBase::wxStringBase(const void *pStart
, const void *pEnd
) 
 218   InitWith((const wxChar 
*)pStart
, 0, 
 219            (const wxChar 
*)pEnd 
- (const wxChar 
*)pStart
); 
 222 wxStringBase::wxStringBase(size_type n
, wxChar ch
) 
 228 // --------------------------------------------------------------------------- 
 230 // --------------------------------------------------------------------------- 
 232 // allocates memory needed to store a C string of length nLen 
 233 bool wxStringBase::AllocBuffer(size_t nLen
) 
 235   // allocating 0 sized buffer doesn't make sense, all empty strings should 
 237   wxASSERT( nLen 
>  0 ); 
 239   // make sure that we don't overflow 
 240   wxASSERT( nLen 
< (INT_MAX 
/ sizeof(wxChar
)) - 
 241                    (sizeof(wxStringData
) + EXTRA_ALLOC 
+ 1) ); 
 243   STATISTICS_ADD(Length
, nLen
); 
 246   // 1) one extra character for '\0' termination 
 247   // 2) sizeof(wxStringData) for housekeeping info 
 248   wxStringData
* pData 
= (wxStringData
*) 
 249     malloc(sizeof(wxStringData
) + (nLen 
+ EXTRA_ALLOC 
+ 1)*sizeof(wxChar
)); 
 251   if ( pData 
== NULL 
) { 
 252     // allocation failures are handled by the caller 
 257   pData
->nDataLength  
= nLen
; 
 258   pData
->nAllocLength 
= nLen 
+ EXTRA_ALLOC
; 
 259   m_pchData           
= pData
->data();  // data starts after wxStringData 
 260   m_pchData
[nLen
]     = wxT('\0'); 
 264 // must be called before changing this string 
 265 bool wxStringBase::CopyBeforeWrite() 
 267   wxStringData
* pData 
= GetStringData(); 
 269   if ( pData
->IsShared() ) { 
 270     pData
->Unlock();                // memory not freed because shared 
 271     size_t nLen 
= pData
->nDataLength
; 
 272     if ( !AllocBuffer(nLen
) ) { 
 273       // allocation failures are handled by the caller 
 276     memcpy(m_pchData
, pData
->data(), nLen
*sizeof(wxChar
)); 
 279   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner 
 284 // must be called before replacing contents of this string 
 285 bool wxStringBase::AllocBeforeWrite(size_t nLen
) 
 287   wxASSERT( nLen 
!= 0 );  // doesn't make any sense 
 289   // must not share string and must have enough space 
 290   wxStringData
* pData 
= GetStringData(); 
 291   if ( pData
->IsShared() || pData
->IsEmpty() ) { 
 292     // can't work with old buffer, get new one 
 294     if ( !AllocBuffer(nLen
) ) { 
 295       // allocation failures are handled by the caller 
 300     if ( nLen 
> pData
->nAllocLength 
) { 
 301       // realloc the buffer instead of calling malloc() again, this is more 
 303       STATISTICS_ADD(Length
, nLen
); 
 307       pData 
= (wxStringData
*) 
 308           realloc(pData
, sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 310       if ( pData 
== NULL 
) { 
 311         // allocation failures are handled by the caller 
 312         // keep previous data since reallocation failed 
 316       pData
->nAllocLength 
= nLen
; 
 317       m_pchData 
= pData
->data(); 
 320     // now we have enough space, just update the string length 
 321     pData
->nDataLength 
= nLen
; 
 324   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner 
 329 wxStringBase
& wxStringBase::append(size_t n
, wxChar ch
) 
 331     size_type len 
= length(); 
 333     if ( !CopyBeforeWrite() || !Alloc(len 
+ n
) ) { 
 334       wxFAIL_MSG( _T("out of memory in wxStringBase::append") ); 
 336     GetStringData()->nDataLength 
= len 
+ n
; 
 337     m_pchData
[len 
+ n
] = '\0'; 
 338     for ( size_t i 
= 0; i 
< n
; ++i 
) 
 339         m_pchData
[len 
+ i
] = ch
; 
 343 void wxStringBase::resize(size_t nSize
, wxChar ch
) 
 345     size_t len 
= length(); 
 349         erase(begin() + nSize
, end()); 
 351     else if ( nSize 
> len 
) 
 353         append(nSize 
- len
, ch
); 
 355     //else: we have exactly the specified length, nothing to do 
 358 // allocate enough memory for nLen characters 
 359 bool wxStringBase::Alloc(size_t nLen
) 
 361   wxStringData 
*pData 
= GetStringData(); 
 362   if ( pData
->nAllocLength 
<= nLen 
) { 
 363     if ( pData
->IsEmpty() ) { 
 366       wxStringData
* pData 
= (wxStringData
*) 
 367           malloc(sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 369       if ( pData 
== NULL 
) { 
 370         // allocation failure handled by caller 
 375       pData
->nDataLength 
= 0; 
 376       pData
->nAllocLength 
= nLen
; 
 377       m_pchData 
= pData
->data();  // data starts after wxStringData 
 378       m_pchData
[0u] = wxT('\0'); 
 380     else if ( pData
->IsShared() ) { 
 381       pData
->Unlock();                // memory not freed because shared 
 382       size_t nOldLen 
= pData
->nDataLength
; 
 383       if ( !AllocBuffer(nLen
) ) { 
 384         // allocation failure handled by caller 
 387       memcpy(m_pchData
, pData
->data(), nOldLen
*sizeof(wxChar
)); 
 392       pData 
= (wxStringData 
*) 
 393         realloc(pData
, sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 395       if ( pData 
== NULL 
) { 
 396         // allocation failure handled by caller 
 397         // keep previous data since reallocation failed 
 401       // it's not important if the pointer changed or not (the check for this 
 402       // is not faster than assigning to m_pchData in all cases) 
 403       pData
->nAllocLength 
= nLen
; 
 404       m_pchData 
= pData
->data(); 
 407   //else: we've already got enough 
 411 wxStringBase::iterator 
wxStringBase::begin() 
 418 wxStringBase::iterator 
wxStringBase::end() 
 422     return m_pchData 
+ length(); 
 425 wxStringBase::iterator 
wxStringBase::erase(iterator it
) 
 427     size_type idx 
= it 
- begin(); 
 429     return begin() + idx
; 
 432 wxStringBase
& wxStringBase::erase(size_t nStart
, size_t nLen
) 
 434   wxASSERT(nStart 
<= length()); 
 435   size_t strLen 
= length() - nStart
; 
 436   // delete nLen or up to the end of the string characters 
 437   nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 438   wxString 
strTmp(c_str(), nStart
); 
 439   strTmp
.append(c_str() + nStart 
+ nLen
, length() - nStart 
- nLen
); 
 445 wxStringBase
& wxStringBase::insert(size_t nPos
, const wxChar 
*sz
, size_t n
) 
 447   wxASSERT( nPos 
<= length() ); 
 449   if ( n 
== npos 
) n 
= wxStrlen(sz
); 
 450   if ( n 
== 0 ) return *this; 
 452   if ( !CopyBeforeWrite() || !Alloc(length() + n
) ) { 
 453     wxFAIL_MSG( _T("out of memory in wxStringBase::insert") ); 
 456   memmove(m_pchData 
+ nPos 
+ n
, m_pchData 
+ nPos
, 
 457           (length() - nPos
) * sizeof(wxChar
)); 
 458   memcpy(m_pchData 
+ nPos
, sz
, n 
* sizeof(wxChar
)); 
 459   GetStringData()->nDataLength 
= length() + n
; 
 460   m_pchData
[length()] = '\0'; 
 465 void wxStringBase::swap(wxStringBase
& str
) 
 467     wxChar
* tmp 
= str
.m_pchData
; 
 468     str
.m_pchData 
= m_pchData
; 
 472 size_t wxStringBase::find(const wxStringBase
& str
, size_t nStart
) const 
 474   wxASSERT( str
.GetStringData()->IsValid() ); 
 475   wxASSERT( nStart 
<= length() ); 
 477   const wxChar 
*p 
= wxStrstr(c_str() + nStart
, str
.c_str()); 
 479   return p 
== NULL 
? npos 
: p 
- c_str(); 
 482 size_t wxStringBase::find(const wxChar
* sz
, size_t nStart
, size_t n
) const 
 484   return find(wxStringBase(sz
, n
), nStart
); 
 487 size_t wxStringBase::find(wxChar ch
, size_t nStart
) const 
 489   wxASSERT( nStart 
<= length() ); 
 491   const wxChar 
*p 
= wxStrchr(c_str() + nStart
, ch
); 
 493   return p 
== NULL 
? npos 
: p 
- c_str(); 
 496 size_t wxStringBase::rfind(const wxStringBase
& str
, size_t nStart
) const 
 498     wxASSERT( str
.GetStringData()->IsValid() ); 
 499     wxASSERT( nStart 
== npos 
|| nStart 
<= length() ); 
 501     if ( length() >= str
.length() ) 
 503         // avoids a corner case later 
 504         if ( length() == 0 && str
.length() == 0 ) 
 507         // "top" is the point where search starts from 
 508         size_t top 
= length() - str
.length(); 
 510         if ( nStart 
== npos 
) 
 511             nStart 
= length() - 1; 
 515         const wxChar 
*cursor 
= c_str() + top
; 
 518             if ( memcmp(cursor
, str
.c_str(), 
 519                         str
.length() * sizeof(wxChar
)) == 0 ) 
 521                 return cursor 
- c_str(); 
 523         } while ( cursor
-- > c_str() ); 
 529 size_t wxStringBase::rfind(const wxChar
* sz
, size_t nStart
, size_t n
) const 
 531     return rfind(wxStringBase(sz
, n
), nStart
); 
 534 size_t wxStringBase::rfind(wxChar ch
, size_t nStart
) const 
 536     if ( nStart 
== npos 
) 
 542         wxASSERT( nStart 
<= length() ); 
 545     const wxChar 
*actual
; 
 546     for ( actual 
= c_str() + ( nStart 
== npos 
? length() : nStart 
+ 1 ); 
 547           actual 
> c_str(); --actual 
) 
 549         if ( *(actual 
- 1) == ch 
) 
 550             return (actual 
- 1) - c_str(); 
 556 size_t wxStringBase::find_first_of(const wxChar
* sz
, size_t nStart
) const 
 558     const wxChar 
*start 
= c_str() + nStart
; 
 559     const wxChar 
*firstOf 
= wxStrpbrk(start
, sz
); 
 561         return firstOf 
- c_str(); 
 566 size_t wxStringBase::find_first_of(const wxChar
* sz
, size_t nStart
, 
 569     return find_first_of(wxStringBase(sz
, n
), nStart
); 
 572 size_t wxStringBase::find_last_of(const wxChar
* sz
, size_t nStart
) const 
 574     if ( nStart 
== npos 
) 
 576         nStart 
= length() - 1; 
 580         wxASSERT_MSG( nStart 
<= length(), 
 581                         _T("invalid index in find_last_of()") ); 
 584     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 586         if ( wxStrchr(sz
, *p
) ) 
 593 size_t wxStringBase::find_last_of(const wxChar
* sz
, size_t nStart
, 
 596     return find_last_of(wxStringBase(sz
, n
), nStart
); 
 599 size_t wxStringBase::find_first_not_of(const wxChar
* sz
, size_t nStart
) const 
 601     if ( nStart 
== npos 
) 
 607         wxASSERT( nStart 
<= length() ); 
 610     size_t nAccept 
= wxStrspn(c_str() + nStart
, sz
); 
 611     if ( nAccept 
>= length() - nStart 
) 
 614         return nStart 
+ nAccept
; 
 617 size_t wxStringBase::find_first_not_of(const wxChar
* sz
, size_t nStart
, 
 620     return find_first_not_of(wxStringBase(sz
, n
), nStart
); 
 623 size_t wxStringBase::find_first_not_of(wxChar ch
, size_t nStart
) const 
 625     wxASSERT( nStart 
<= length() ); 
 627     for ( const wxChar 
*p 
= c_str() + nStart
; *p
; p
++ ) 
 636 size_t wxStringBase::find_last_not_of(const wxChar
* sz
, size_t nStart
) const 
 638     if ( nStart 
== npos 
) 
 640         nStart 
= length() - 1; 
 644         wxASSERT( nStart 
<= length() ); 
 647     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 649         if ( !wxStrchr(sz
, *p
) ) 
 656 size_t wxStringBase::find_last_not_of(const wxChar
* sz
, size_t nStart
, 
 659     return find_last_not_of(wxStringBase(sz
, n
), nStart
); 
 662 size_t wxStringBase::find_last_not_of(wxChar ch
, size_t nStart
) const 
 664     if ( nStart 
== npos 
) 
 666         nStart 
= length() - 1; 
 670         wxASSERT( nStart 
<= length() ); 
 673     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 682 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 685   wxASSERT_MSG( nStart 
<= length(), 
 686                 _T("index out of bounds in wxStringBase::replace") ); 
 687   size_t strLen 
= length() - nStart
; 
 688   nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 691   strTmp
.reserve(length()); // micro optimisation to avoid multiple mem allocs 
 694     strTmp
.append(c_str(), nStart
); 
 696   strTmp
.append(c_str() + nStart 
+ nLen
); 
 702 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 703                                     size_t nCount
, wxChar ch
) 
 705   return replace(nStart
, nLen
, wxStringBase(ch
, nCount
).c_str()); 
 708 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 709                                     const wxStringBase
& str
, 
 710                                     size_t nStart2
, size_t nLen2
) 
 712   return replace(nStart
, nLen
, str
.substr(nStart2
, nLen2
)); 
 715 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 716                                     const wxChar
* sz
, size_t nCount
) 
 718   return replace(nStart
, nLen
, wxStringBase(sz
, nCount
).c_str()); 
 721 wxStringBase 
wxStringBase::substr(size_t nStart
, size_t nLen
) const 
 724     nLen 
= length() - nStart
; 
 725   return wxStringBase(*this, nStart
, nLen
); 
 728 // assigns one string to another 
 729 wxStringBase
& wxStringBase::operator=(const wxStringBase
& stringSrc
) 
 731   wxASSERT( stringSrc
.GetStringData()->IsValid() ); 
 733   // don't copy string over itself 
 734   if ( m_pchData 
!= stringSrc
.m_pchData 
) { 
 735     if ( stringSrc
.GetStringData()->IsEmpty() ) { 
 740       GetStringData()->Unlock(); 
 741       m_pchData 
= stringSrc
.m_pchData
; 
 742       GetStringData()->Lock(); 
 749 // assigns a single character 
 750 wxStringBase
& wxStringBase::operator=(wxChar ch
) 
 752   if ( !AssignCopy(1, &ch
) ) { 
 753     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") ); 
 759 wxStringBase
& wxStringBase::operator=(const wxChar 
*psz
) 
 761   if ( !AssignCopy(wxStrlen(psz
), psz
) ) { 
 762     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") ); 
 767 // helper function: does real copy 
 768 bool wxStringBase::AssignCopy(size_t nSrcLen
, const wxChar 
*pszSrcData
) 
 770   if ( nSrcLen 
== 0 ) { 
 774     if ( !AllocBeforeWrite(nSrcLen
) ) { 
 775       // allocation failure handled by caller 
 778     memcpy(m_pchData
, pszSrcData
, nSrcLen
*sizeof(wxChar
)); 
 779     GetStringData()->nDataLength 
= nSrcLen
; 
 780     m_pchData
[nSrcLen
] = wxT('\0'); 
 785 // --------------------------------------------------------------------------- 
 786 // string concatenation 
 787 // --------------------------------------------------------------------------- 
 789 // add something to this string 
 790 bool wxStringBase::ConcatSelf(size_t nSrcLen
, const wxChar 
*pszSrcData
, 
 793   STATISTICS_ADD(SummandLength
, nSrcLen
); 
 795   nSrcLen 
= nSrcLen 
< nMaxLen 
? nSrcLen 
: nMaxLen
; 
 797   // concatenating an empty string is a NOP 
 799     wxStringData 
*pData 
= GetStringData(); 
 800     size_t nLen 
= pData
->nDataLength
; 
 801     size_t nNewLen 
= nLen 
+ nSrcLen
; 
 803     // alloc new buffer if current is too small 
 804     if ( pData
->IsShared() ) { 
 805       STATISTICS_ADD(ConcatHit
, 0); 
 807       // we have to allocate another buffer 
 808       wxStringData
* pOldData 
= GetStringData(); 
 809       if ( !AllocBuffer(nNewLen
) ) { 
 810           // allocation failure handled by caller 
 813       memcpy(m_pchData
, pOldData
->data(), nLen
*sizeof(wxChar
)); 
 816     else if ( nNewLen 
> pData
->nAllocLength 
) { 
 817       STATISTICS_ADD(ConcatHit
, 0); 
 820       // we have to grow the buffer 
 821       if ( capacity() < nNewLen 
) { 
 822           // allocation failure handled by caller 
 827       STATISTICS_ADD(ConcatHit
, 1); 
 829       // the buffer is already big enough 
 832     // should be enough space 
 833     wxASSERT( nNewLen 
<= GetStringData()->nAllocLength 
); 
 835     // fast concatenation - all is done in our buffer 
 836     memcpy(m_pchData 
+ nLen
, pszSrcData
, nSrcLen
*sizeof(wxChar
)); 
 838     m_pchData
[nNewLen
] = wxT('\0');          // put terminating '\0' 
 839     GetStringData()->nDataLength 
= nNewLen
; // and fix the length 
 841   //else: the string to append was empty 
 845 // --------------------------------------------------------------------------- 
 846 // simple sub-string extraction 
 847 // --------------------------------------------------------------------------- 
 849 // helper function: clone the data attached to this string 
 850 bool wxStringBase::AllocCopy(wxString
& dest
, int nCopyLen
, int nCopyIndex
) const 
 852   if ( nCopyLen 
== 0 ) { 
 856     if ( !dest
.AllocBuffer(nCopyLen
) ) { 
 857       // allocation failure handled by caller 
 860     memcpy(dest
.m_pchData
, m_pchData 
+ nCopyIndex
, nCopyLen
*sizeof(wxChar
)); 
 867 #if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE) 
 870     #define STRINGCLASS wxStringBase 
 872     #define STRINGCLASS wxString 
 875 static inline int wxDoCmp(const wxChar
* s1
, size_t l1
, 
 876                           const wxChar
* s2
, size_t l2
) 
 879         return wxStrncmp(s1
, s2
, l1
); 
 882         int ret 
= wxStrncmp(s1
, s2
, l1
); 
 883         return ret 
== 0 ? -1 : ret
; 
 887         int ret 
= wxStrncmp(s1
, s2
, l2
); 
 888         return ret 
== 0 ? +1 : ret
; 
 891     wxFAIL
;   // must never get there 
 892     return 0; // quiet compilers 
 897 int STRINGCLASS::compare(const wxStringBase
& str
) const 
 899     return ::wxDoCmp(data(), length(), str
.data(), str
.length()); 
 904 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 905                          const wxStringBase
& str
) const 
 907     wxASSERT(nStart 
<= length()); 
 908     size_type strLen 
= length() - nStart
; 
 909     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 910     return ::wxDoCmp(data() + nStart
, nLen
, str
.data(), str
.length()); 
 913 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 914                          const wxStringBase
& str
, 
 915                          size_t nStart2
, size_t nLen2
) const 
 917     wxASSERT(nStart 
<= length()); 
 918     wxASSERT(nStart2 
<= str
.length()); 
 919     size_type strLen  
=     length() - nStart
, 
 920               strLen2 
= str
.length() - nStart2
; 
 921     nLen  
= strLen  
< nLen  
? strLen  
: nLen
; 
 922     nLen2 
= strLen2 
< nLen2 
? strLen2 
: nLen2
; 
 923     return ::wxDoCmp(data() + nStart
, nLen
, str
.data() + nStart2
, nLen2
); 
 928 int STRINGCLASS::compare(const wxChar
* sz
) const 
 930     size_t nLen 
= wxStrlen(sz
); 
 931     return ::wxDoCmp(data(), length(), sz
, nLen
); 
 936 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 937                          const wxChar
* sz
, size_t nCount
) const 
 939     wxASSERT(nStart 
<= length()); 
 940     size_type strLen 
= length() - nStart
; 
 941     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 943         nCount 
= wxStrlen(sz
); 
 945     return ::wxDoCmp(data() + nStart
, nLen
, sz
, nCount
); 
 950 #endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE) 
 952 // =========================================================================== 
 953 // wxString class core 
 954 // =========================================================================== 
 956 // --------------------------------------------------------------------------- 
 958 // --------------------------------------------------------------------------- 
 962 // from multibyte string 
 963 wxString::wxString(const char *psz
, wxMBConv
& conv
, size_t nLength
) 
 965     // first get the size of the buffer we need 
 969         // calculate the needed size ourselves or use the provided one 
 970         nLen 
= nLength 
== npos 
? conv
.MB2WC(NULL
, psz
, 0) : nLength
; 
 974         // nothing to convert 
 979     if ( (nLen 
!= 0) && (nLen 
!= (size_t)-1) ) 
 983             wxFAIL_MSG( _T("out of memory in wxString::wxString") ); 
 987             // the input buffer to MB2WC must always be NUL-terminated 
 988             wxCharBuffer 
inBuf(nLen
); 
 989             memcpy(inBuf
.data(), psz
, nLen
); 
 990             inBuf
.data()[nLen
] = '\0'; 
 992             wxWCharBuffer 
buf(nLen
); 
 993             // MB2WC wants the buffer size, not the string length hence +1 
 994             nLen 
= conv
.MB2WC(buf
.data(), inBuf
.data(), nLen 
+ 1); 
 996             if ( nLen 
!= (size_t)-1 ) 
 998                 // initialized ok, set the real length as nLength specified by 
 999                 // the caller could be greater than the real string length 
1000                 assign(buf
.data(), nLen
); 
1003             //else: the conversion failed -- leave the string empty (what else?) 
1012 wxString::wxString(const wchar_t *pwz
, wxMBConv
& conv
, size_t nLength
) 
1014     // first get the size of the buffer we need 
1018         // calculate the needed size ourselves or use the provided one 
1019         nLen 
= nLength 
== npos 
? conv
.WC2MB(NULL
, pwz
, 0) : nLength
; 
1023         // nothing to convert 
1028     if ( (nLen 
!= 0) && (nLen 
!= (size_t)-1) ) 
1032             wxFAIL_MSG( _T("out of memory in wxString::wxString") ); 
1036             wxCharBuffer 
buf(nLen
); 
1037             // WC2MB wants the buffer size, not the string length 
1038             if ( conv
.WC2MB(buf
.data(), pwz
, nLen 
+ 1) != (size_t)-1 ) 
1041                 assign(buf
.data(), nLen
); 
1044             //else: the conversion failed -- leave the string empty (what else?) 
1050 #endif // wxUSE_WCHAR_T 
1052 #endif // Unicode/ANSI 
1054 // shrink to minimal size (releasing extra memory) 
1055 bool wxString::Shrink() 
1057   wxString 
tmp(begin(), end()); 
1059   return tmp
.length() == length(); 
1063 // get the pointer to writable buffer of (at least) nLen bytes 
1064 wxChar 
*wxString::GetWriteBuf(size_t nLen
) 
1066   if ( !AllocBeforeWrite(nLen
) ) { 
1067     // allocation failure handled by caller 
1071   wxASSERT( GetStringData()->nRefs 
== 1 ); 
1072   GetStringData()->Validate(FALSE
); 
1077 // put string back in a reasonable state after GetWriteBuf 
1078 void wxString::UngetWriteBuf() 
1080   GetStringData()->nDataLength 
= wxStrlen(m_pchData
); 
1081   GetStringData()->Validate(TRUE
); 
1084 void wxString::UngetWriteBuf(size_t nLen
) 
1086   GetStringData()->nDataLength 
= nLen
; 
1087   GetStringData()->Validate(TRUE
); 
1091 // --------------------------------------------------------------------------- 
1093 // --------------------------------------------------------------------------- 
1095 // all functions are inline in string.h 
1097 // --------------------------------------------------------------------------- 
1098 // assignment operators 
1099 // --------------------------------------------------------------------------- 
1103 // same as 'signed char' variant 
1104 wxString
& wxString::operator=(const unsigned char* psz
) 
1106   *this = (const char *)psz
; 
1111 wxString
& wxString::operator=(const wchar_t *pwz
) 
1122  * concatenation functions come in 5 flavours: 
1124  *  char   + string      and      string + char 
1125  *  C str  + string      and      string + C str 
1128 wxString 
operator+(const wxString
& str1
, const wxString
& str2
) 
1131   wxASSERT( str1
.GetStringData()->IsValid() ); 
1132   wxASSERT( str2
.GetStringData()->IsValid() ); 
1141 wxString 
operator+(const wxString
& str
, wxChar ch
) 
1144   wxASSERT( str
.GetStringData()->IsValid() ); 
1153 wxString 
operator+(wxChar ch
, const wxString
& str
) 
1156   wxASSERT( str
.GetStringData()->IsValid() ); 
1165 wxString 
operator+(const wxString
& str
, const wxChar 
*psz
) 
1168   wxASSERT( str
.GetStringData()->IsValid() ); 
1172   if ( !s
.Alloc(wxStrlen(psz
) + str
.Len()) ) { 
1173     wxFAIL_MSG( _T("out of memory in wxString::operator+") ); 
1181 wxString 
operator+(const wxChar 
*psz
, const wxString
& str
) 
1184   wxASSERT( str
.GetStringData()->IsValid() ); 
1188   if ( !s
.Alloc(wxStrlen(psz
) + str
.Len()) ) { 
1189     wxFAIL_MSG( _T("out of memory in wxString::operator+") ); 
1197 // =========================================================================== 
1198 // other common string functions 
1199 // =========================================================================== 
1203 wxString 
wxString::FromAscii(const char *ascii
) 
1206        return wxEmptyString
; 
1208     size_t len 
= strlen( ascii 
); 
1213         wxStringBuffer 
buf(res
, len
); 
1215         wchar_t *dest 
= buf
; 
1219            if ( (*dest
++ = (wchar_t)(unsigned char)*ascii
++) == L
'\0' ) 
1227 wxString 
wxString::FromAscii(const char ascii
) 
1229     // What do we do with '\0' ? 
1232     res 
+= (wchar_t)(unsigned char) ascii
; 
1237 const wxCharBuffer 
wxString::ToAscii() const 
1239     // this will allocate enough space for the terminating NUL too 
1240     wxCharBuffer 
buffer(length()); 
1242     signed char *dest 
= (signed char *)buffer
.data(); 
1244     const wchar_t *pwc 
= c_str(); 
1247         *dest
++ = *pwc 
> SCHAR_MAX 
? '_' : *pwc
; 
1249         // the output string can't have embedded NULs anyhow, so we can safely 
1250         // stop at first of them even if we do have any 
1260 // extract string of length nCount starting at nFirst 
1261 wxString 
wxString::Mid(size_t nFirst
, size_t nCount
) const 
1263   size_t nLen 
= length(); 
1265   // default value of nCount is npos and means "till the end" 
1266   if ( nCount 
== npos 
) 
1268     nCount 
= nLen 
- nFirst
; 
1271   // out-of-bounds requests return sensible things 
1272   if ( nFirst 
+ nCount 
> nLen 
) 
1274     nCount 
= nLen 
- nFirst
; 
1277   if ( nFirst 
> nLen 
) 
1279     // AllocCopy() will return empty string 
1283   wxString 
dest(*this, nFirst
, nCount
); 
1284   if ( dest
.length() != nCount 
) { 
1285       wxFAIL_MSG( _T("out of memory in wxString::Mid") ); 
1291 // check that the string starts with prefix and return the rest of the string 
1292 // in the provided pointer if it is not NULL, otherwise return FALSE 
1293 bool wxString::StartsWith(const wxChar 
*prefix
, wxString 
*rest
) const 
1295     wxASSERT_MSG( prefix
, _T("invalid parameter in wxString::StartsWith") ); 
1297     // first check if the beginning of the string matches the prefix: note 
1298     // that we don't have to check that we don't run out of this string as 
1299     // when we reach the terminating NUL, either prefix string ends too (and 
1300     // then it's ok) or we break out of the loop because there is no match 
1301     const wxChar 
*p 
= c_str(); 
1304         if ( *prefix
++ != *p
++ ) 
1313         // put the rest of the string into provided pointer 
1320 // extract nCount last (rightmost) characters 
1321 wxString 
wxString::Right(size_t nCount
) const 
1323   if ( nCount 
> length() ) 
1326   wxString 
dest(*this, length() - nCount
, nCount
); 
1327   if ( dest
.length() != nCount 
) { 
1328     wxFAIL_MSG( _T("out of memory in wxString::Right") ); 
1333 // get all characters after the last occurence of ch 
1334 // (returns the whole string if ch not found) 
1335 wxString 
wxString::AfterLast(wxChar ch
) const 
1338   int iPos 
= Find(ch
, TRUE
); 
1339   if ( iPos 
== wxNOT_FOUND 
) 
1342     str 
= c_str() + iPos 
+ 1; 
1347 // extract nCount first (leftmost) characters 
1348 wxString 
wxString::Left(size_t nCount
) const 
1350   if ( nCount 
> length() ) 
1353   wxString 
dest(*this, 0, nCount
); 
1354   if ( dest
.length() != nCount 
) { 
1355     wxFAIL_MSG( _T("out of memory in wxString::Left") ); 
1360 // get all characters before the first occurence of ch 
1361 // (returns the whole string if ch not found) 
1362 wxString 
wxString::BeforeFirst(wxChar ch
) const 
1364   int iPos 
= Find(ch
); 
1365   if ( iPos 
== wxNOT_FOUND 
) iPos 
= length(); 
1366   return wxString(*this, 0, iPos
); 
1369 /// get all characters before the last occurence of ch 
1370 /// (returns empty string if ch not found) 
1371 wxString 
wxString::BeforeLast(wxChar ch
) const 
1374   int iPos 
= Find(ch
, TRUE
); 
1375   if ( iPos 
!= wxNOT_FOUND 
&& iPos 
!= 0 ) 
1376     str 
= wxString(c_str(), iPos
); 
1381 /// get all characters after the first occurence of ch 
1382 /// (returns empty string if ch not found) 
1383 wxString 
wxString::AfterFirst(wxChar ch
) const 
1386   int iPos 
= Find(ch
); 
1387   if ( iPos 
!= wxNOT_FOUND 
) 
1388     str 
= c_str() + iPos 
+ 1; 
1393 // replace first (or all) occurences of some substring with another one 
1395 wxString::Replace(const wxChar 
*szOld
, const wxChar 
*szNew
, bool bReplaceAll
) 
1397     // if we tried to replace an empty string we'd enter an infinite loop below 
1398     wxCHECK_MSG( szOld 
&& *szOld 
&& szNew
, 0, 
1399                  _T("wxString::Replace(): invalid parameter") ); 
1401   size_t uiCount 
= 0;   // count of replacements made 
1403   size_t uiOldLen 
= wxStrlen(szOld
); 
1406   const wxChar 
*pCurrent 
= c_str(); 
1407   const wxChar 
*pSubstr
; 
1408   while ( *pCurrent 
!= wxT('\0') ) { 
1409     pSubstr 
= wxStrstr(pCurrent
, szOld
); 
1410     if ( pSubstr 
== NULL 
) { 
1411       // strTemp is unused if no replacements were made, so avoid the copy 
1415       strTemp 
+= pCurrent
;    // copy the rest 
1416       break;                  // exit the loop 
1419       // take chars before match 
1420       size_type len 
= strTemp
.length(); 
1421       strTemp
.append(pCurrent
, pSubstr 
- pCurrent
); 
1422       if ( strTemp
.length() != (size_t)(len 
+ pSubstr 
- pCurrent
) ) { 
1423         wxFAIL_MSG( _T("out of memory in wxString::Replace") ); 
1427       pCurrent 
= pSubstr 
+ uiOldLen
;  // restart after match 
1432       if ( !bReplaceAll 
) { 
1433         strTemp 
+= pCurrent
;    // copy the rest 
1434         break;                  // exit the loop 
1439   // only done if there were replacements, otherwise would have returned above 
1445 bool wxString::IsAscii() const 
1447   const wxChar 
*s 
= (const wxChar
*) *this; 
1449     if(!isascii(*s
)) return(FALSE
); 
1455 bool wxString::IsWord() const 
1457   const wxChar 
*s 
= (const wxChar
*) *this; 
1459     if(!wxIsalpha(*s
)) return(FALSE
); 
1465 bool wxString::IsNumber() const 
1467   const wxChar 
*s 
= (const wxChar
*) *this; 
1469      if ((s
[0] == '-') || (s
[0] == '+')) s
++; 
1471     if(!wxIsdigit(*s
)) return(FALSE
); 
1477 wxString 
wxString::Strip(stripType w
) const 
1480     if ( w 
& leading 
) s
.Trim(FALSE
); 
1481     if ( w 
& trailing 
) s
.Trim(TRUE
); 
1485 // --------------------------------------------------------------------------- 
1487 // --------------------------------------------------------------------------- 
1489 wxString
& wxString::MakeUpper() 
1491   for ( iterator it 
= begin(), en 
= end(); it 
!= en
; ++it 
) 
1492     *it 
= (wxChar
)wxToupper(*it
); 
1497 wxString
& wxString::MakeLower() 
1499   for ( iterator it 
= begin(), en 
= end(); it 
!= en
; ++it 
) 
1500     *it 
= (wxChar
)wxTolower(*it
); 
1505 // --------------------------------------------------------------------------- 
1506 // trimming and padding 
1507 // --------------------------------------------------------------------------- 
1509 // some compilers (VC++ 6.0 not to name them) return TRUE for a call to 
1510 // isspace('ê') in the C locale which seems to be broken to me, but we have to 
1511 // live with this by checking that the character is a 7 bit one - even if this 
1512 // may fail to detect some spaces (I don't know if Unicode doesn't have 
1513 // space-like symbols somewhere except in the first 128 chars), it is arguably 
1514 // still better than trimming away accented letters 
1515 inline int wxSafeIsspace(wxChar ch
) { return (ch 
< 127) && wxIsspace(ch
); } 
1517 // trims spaces (in the sense of isspace) from left or right side 
1518 wxString
& wxString::Trim(bool bFromRight
) 
1520   // first check if we're going to modify the string at all 
1523         (bFromRight 
&& wxSafeIsspace(GetChar(Len() - 1))) || 
1524         (!bFromRight 
&& wxSafeIsspace(GetChar(0u))) 
1530       // find last non-space character 
1531       iterator psz 
= begin() + length() - 1; 
1532       while ( wxSafeIsspace(*psz
) && (psz 
>= begin()) ) 
1535       // truncate at trailing space start 
1541       // find first non-space character 
1542       iterator psz 
= begin(); 
1543       while ( wxSafeIsspace(*psz
) ) 
1546       // fix up data and length 
1547       erase(begin(), psz
); 
1554 // adds nCount characters chPad to the string from either side 
1555 wxString
& wxString::Pad(size_t nCount
, wxChar chPad
, bool bFromRight
) 
1557   wxString 
s(chPad
, nCount
); 
1570 // truncate the string 
1571 wxString
& wxString::Truncate(size_t uiLen
) 
1573   if ( uiLen 
< Len() ) { 
1574     erase(begin() + uiLen
, end()); 
1576   //else: nothing to do, string is already short enough 
1581 // --------------------------------------------------------------------------- 
1582 // finding (return wxNOT_FOUND if not found and index otherwise) 
1583 // --------------------------------------------------------------------------- 
1586 int wxString::Find(wxChar ch
, bool bFromEnd
) const 
1588   size_type idx 
= bFromEnd 
? find_last_of(ch
) : find_first_of(ch
); 
1590   return (idx 
== npos
) ? wxNOT_FOUND 
: (int)idx
; 
1593 // find a sub-string (like strstr) 
1594 int wxString::Find(const wxChar 
*pszSub
) const 
1596   size_type idx 
= find(pszSub
); 
1598   return (idx 
== npos
) ? wxNOT_FOUND 
: (int)idx
; 
1601 // ---------------------------------------------------------------------------- 
1602 // conversion to numbers 
1603 // ---------------------------------------------------------------------------- 
1605 bool wxString::ToLong(long *val
, int base
) const 
1607     wxCHECK_MSG( val
, FALSE
, _T("NULL pointer in wxString::ToLong") ); 
1608     wxASSERT_MSG( !base 
|| (base 
> 1 && base 
<= 36), _T("invalid base") ); 
1610     const wxChar 
*start 
= c_str(); 
1612     *val 
= wxStrtol(start
, &end
, base
); 
1614     // return TRUE only if scan was stopped by the terminating NUL and if the 
1615     // string was not empty to start with 
1616     return !*end 
&& (end 
!= start
); 
1619 bool wxString::ToULong(unsigned long *val
, int base
) const 
1621     wxCHECK_MSG( val
, FALSE
, _T("NULL pointer in wxString::ToULong") ); 
1622     wxASSERT_MSG( !base 
|| (base 
> 1 && base 
<= 36), _T("invalid base") ); 
1624     const wxChar 
*start 
= c_str(); 
1626     *val 
= wxStrtoul(start
, &end
, base
); 
1628     // return TRUE only if scan was stopped by the terminating NUL and if the 
1629     // string was not empty to start with 
1630     return !*end 
&& (end 
!= start
); 
1633 bool wxString::ToDouble(double *val
) const 
1635     wxCHECK_MSG( val
, FALSE
, _T("NULL pointer in wxString::ToDouble") ); 
1637     const wxChar 
*start 
= c_str(); 
1639     *val 
= wxStrtod(start
, &end
); 
1641     // return TRUE only if scan was stopped by the terminating NUL and if the 
1642     // string was not empty to start with 
1643     return !*end 
&& (end 
!= start
); 
1646 // --------------------------------------------------------------------------- 
1648 // --------------------------------------------------------------------------- 
1651 wxString 
wxString::Format(const wxChar 
*pszFormat
, ...) 
1654     va_start(argptr
, pszFormat
); 
1657     s
.PrintfV(pszFormat
, argptr
); 
1665 wxString 
wxString::FormatV(const wxChar 
*pszFormat
, va_list argptr
) 
1668     s
.PrintfV(pszFormat
, argptr
); 
1672 int wxString::Printf(const wxChar 
*pszFormat
, ...) 
1675   va_start(argptr
, pszFormat
); 
1677   int iLen 
= PrintfV(pszFormat
, argptr
); 
1684 int wxString::PrintfV(const wxChar
* pszFormat
, va_list argptr
) 
1692             wxStringBuffer 
tmp(*this, size 
+ 1); 
1701             len 
= wxVsnprintf(buf
, size
, pszFormat
, argptr
); 
1703             // some implementations of vsnprintf() don't NUL terminate 
1704             // the string if there is not enough space for it so 
1705             // always do it manually 
1706             buf
[size
] = _T('\0'); 
1709         // vsnprintf() may return either -1 (traditional Unix behaviour) or the 
1710         // total number of characters which would have been written if the 
1711         // buffer were large enough 
1712         if ( len 
>= 0 && len 
<= size 
) 
1714             // ok, there was enough space 
1718         // still not enough, double it again 
1722     // we could have overshot 
1728 // ---------------------------------------------------------------------------- 
1729 // misc other operations 
1730 // ---------------------------------------------------------------------------- 
1732 // returns TRUE if the string matches the pattern which may contain '*' and 
1733 // '?' metacharacters (as usual, '?' matches any character and '*' any number 
1735 bool wxString::Matches(const wxChar 
*pszMask
) const 
1737     // I disable this code as it doesn't seem to be faster (in fact, it seems 
1738     // to be much slower) than the old, hand-written code below and using it 
1739     // here requires always linking with libregex even if the user code doesn't 
1741 #if 0 // wxUSE_REGEX 
1742     // first translate the shell-like mask into a regex 
1744     pattern
.reserve(wxStrlen(pszMask
)); 
1756                 pattern 
+= _T(".*"); 
1767                 // these characters are special in a RE, quote them 
1768                 // (however note that we don't quote '[' and ']' to allow 
1769                 // using them for Unix shell like matching) 
1770                 pattern 
+= _T('\\'); 
1774                 pattern 
+= *pszMask
; 
1782     return wxRegEx(pattern
, wxRE_NOSUB 
| wxRE_EXTENDED
).Matches(c_str()); 
1783 #else // !wxUSE_REGEX 
1784   // TODO: this is, of course, awfully inefficient... 
1786   // the char currently being checked 
1787   const wxChar 
*pszTxt 
= c_str(); 
1789   // the last location where '*' matched 
1790   const wxChar 
*pszLastStarInText 
= NULL
; 
1791   const wxChar 
*pszLastStarInMask 
= NULL
; 
1794   for ( ; *pszMask 
!= wxT('\0'); pszMask
++, pszTxt
++ ) { 
1795     switch ( *pszMask 
) { 
1797         if ( *pszTxt 
== wxT('\0') ) 
1800         // pszTxt and pszMask will be incremented in the loop statement 
1806           // remember where we started to be able to backtrack later 
1807           pszLastStarInText 
= pszTxt
; 
1808           pszLastStarInMask 
= pszMask
; 
1810           // ignore special chars immediately following this one 
1811           // (should this be an error?) 
1812           while ( *pszMask 
== wxT('*') || *pszMask 
== wxT('?') ) 
1815           // if there is nothing more, match 
1816           if ( *pszMask 
== wxT('\0') ) 
1819           // are there any other metacharacters in the mask? 
1821           const wxChar 
*pEndMask 
= wxStrpbrk(pszMask
, wxT("*?")); 
1823           if ( pEndMask 
!= NULL 
) { 
1824             // we have to match the string between two metachars 
1825             uiLenMask 
= pEndMask 
- pszMask
; 
1828             // we have to match the remainder of the string 
1829             uiLenMask 
= wxStrlen(pszMask
); 
1832           wxString 
strToMatch(pszMask
, uiLenMask
); 
1833           const wxChar
* pMatch 
= wxStrstr(pszTxt
, strToMatch
); 
1834           if ( pMatch 
== NULL 
) 
1837           // -1 to compensate "++" in the loop 
1838           pszTxt 
= pMatch 
+ uiLenMask 
- 1; 
1839           pszMask 
+= uiLenMask 
- 1; 
1844         if ( *pszMask 
!= *pszTxt 
) 
1850   // match only if nothing left 
1851   if ( *pszTxt 
== wxT('\0') ) 
1854   // if we failed to match, backtrack if we can 
1855   if ( pszLastStarInText 
) { 
1856     pszTxt 
= pszLastStarInText 
+ 1; 
1857     pszMask 
= pszLastStarInMask
; 
1859     pszLastStarInText 
= NULL
; 
1861     // don't bother resetting pszLastStarInMask, it's unnecessary 
1867 #endif // wxUSE_REGEX/!wxUSE_REGEX 
1870 // Count the number of chars 
1871 int wxString::Freq(wxChar ch
) const 
1875     for (int i 
= 0; i 
< len
; i
++) 
1877         if (GetChar(i
) == ch
) 
1883 // convert to upper case, return the copy of the string 
1884 wxString 
wxString::Upper() const 
1885 { wxString 
s(*this); return s
.MakeUpper(); } 
1887 // convert to lower case, return the copy of the string 
1888 wxString 
wxString::Lower() const { wxString 
s(*this); return s
.MakeLower(); } 
1890 int wxString::sprintf(const wxChar 
*pszFormat
, ...) 
1893     va_start(argptr
, pszFormat
); 
1894     int iLen 
= PrintfV(pszFormat
, argptr
); 
1899 // ============================================================================ 
1901 // ============================================================================ 
1903 #include "wx/arrstr.h" 
1907 // size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT) 
1908 #define   ARRAY_MAXSIZE_INCREMENT       4096 
1910 #ifndef   ARRAY_DEFAULT_INITIAL_SIZE    // also defined in dynarray.h 
1911 #define   ARRAY_DEFAULT_INITIAL_SIZE    (16) 
1914 #define   STRING(p)   ((wxString *)(&(p))) 
1917 void wxArrayString::Init(bool autoSort
) 
1921   m_pItems 
= (wxChar 
**) NULL
; 
1922   m_autoSort 
= autoSort
; 
1926 wxArrayString::wxArrayString(const wxArrayString
& src
) 
1928   Init(src
.m_autoSort
); 
1933 // assignment operator 
1934 wxArrayString
& wxArrayString::operator=(const wxArrayString
& src
) 
1941   m_autoSort 
= src
.m_autoSort
; 
1946 void wxArrayString::Copy(const wxArrayString
& src
) 
1948   if ( src
.m_nCount 
> ARRAY_DEFAULT_INITIAL_SIZE 
) 
1949     Alloc(src
.m_nCount
); 
1951   for ( size_t n 
= 0; n 
< src
.m_nCount
; n
++ ) 
1956 void wxArrayString::Grow(size_t nIncrement
) 
1958   // only do it if no more place 
1959   if ( (m_nSize 
- m_nCount
) < nIncrement 
) { 
1960     // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would 
1961     // be never resized! 
1962     #if ARRAY_DEFAULT_INITIAL_SIZE == 0 
1963       #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!" 
1966     if ( m_nSize 
== 0 ) { 
1967       // was empty, alloc some memory 
1968       m_nSize 
= ARRAY_DEFAULT_INITIAL_SIZE
; 
1969       if (m_nSize 
< nIncrement
) 
1970           m_nSize 
= nIncrement
; 
1971       m_pItems 
= new wxChar 
*[m_nSize
]; 
1974       // otherwise when it's called for the first time, nIncrement would be 0 
1975       // and the array would never be expanded 
1976       // add 50% but not too much 
1977       size_t ndefIncrement 
= m_nSize 
< ARRAY_DEFAULT_INITIAL_SIZE
 
1978                           ? ARRAY_DEFAULT_INITIAL_SIZE 
: m_nSize 
>> 1; 
1979       if ( ndefIncrement 
> ARRAY_MAXSIZE_INCREMENT 
) 
1980         ndefIncrement 
= ARRAY_MAXSIZE_INCREMENT
; 
1981       if ( nIncrement 
< ndefIncrement 
) 
1982         nIncrement 
= ndefIncrement
; 
1983       m_nSize 
+= nIncrement
; 
1984       wxChar 
**pNew 
= new wxChar 
*[m_nSize
]; 
1986       // copy data to new location 
1987       memcpy(pNew
, m_pItems
, m_nCount
*sizeof(wxChar 
*)); 
1989       // delete old memory (but do not release the strings!) 
1990       wxDELETEA(m_pItems
); 
1997 void wxArrayString::Free() 
1999   for ( size_t n 
= 0; n 
< m_nCount
; n
++ ) { 
2000     STRING(m_pItems
[n
])->GetStringData()->Unlock(); 
2004 // deletes all the strings from the list 
2005 void wxArrayString::Empty() 
2012 // as Empty, but also frees memory 
2013 void wxArrayString::Clear() 
2020   wxDELETEA(m_pItems
); 
2024 wxArrayString::~wxArrayString() 
2028   wxDELETEA(m_pItems
); 
2031 void wxArrayString::reserve(size_t nSize
) 
2036 // pre-allocates memory (frees the previous data!) 
2037 void wxArrayString::Alloc(size_t nSize
) 
2039   // only if old buffer was not big enough 
2040   if ( nSize 
> m_nSize 
) { 
2042     wxDELETEA(m_pItems
); 
2043     m_pItems 
= new wxChar 
*[nSize
]; 
2050 // minimizes the memory usage by freeing unused memory 
2051 void wxArrayString::Shrink() 
2053   // only do it if we have some memory to free 
2054   if( m_nCount 
< m_nSize 
) { 
2055     // allocates exactly as much memory as we need 
2056     wxChar 
**pNew 
= new wxChar 
*[m_nCount
]; 
2058     // copy data to new location 
2059     memcpy(pNew
, m_pItems
, m_nCount
*sizeof(wxChar 
*)); 
2065 #if WXWIN_COMPATIBILITY_2_4 
2067 // return a wxString[] as required for some control ctors. 
2068 wxString
* wxArrayString::GetStringArray() const 
2070     wxString 
*array 
= 0; 
2074         array 
= new wxString
[m_nCount
]; 
2075         for( size_t i 
= 0; i 
< m_nCount
; i
++ ) 
2076             array
[i
] = m_pItems
[i
]; 
2082 #endif // WXWIN_COMPATIBILITY_2_4 
2084 // searches the array for an item (forward or backwards) 
2085 int wxArrayString::Index(const wxChar 
*sz
, bool bCase
, bool bFromEnd
) const 
2088     // use binary search in the sorted array 
2089     wxASSERT_MSG( bCase 
&& !bFromEnd
, 
2090                   wxT("search parameters ignored for auto sorted array") ); 
2099       res 
= wxStrcmp(sz
, m_pItems
[i
]); 
2111     // use linear search in unsorted array 
2113       if ( m_nCount 
> 0 ) { 
2114         size_t ui 
= m_nCount
; 
2116           if ( STRING(m_pItems
[--ui
])->IsSameAs(sz
, bCase
) ) 
2123       for( size_t ui 
= 0; ui 
< m_nCount
; ui
++ ) { 
2124         if( STRING(m_pItems
[ui
])->IsSameAs(sz
, bCase
) ) 
2133 // add item at the end 
2134 size_t wxArrayString::Add(const wxString
& str
, size_t nInsert
) 
2137     // insert the string at the correct position to keep the array sorted 
2145       res 
= wxStrcmp(str
, m_pItems
[i
]); 
2156     wxASSERT_MSG( lo 
== hi
, wxT("binary search broken") ); 
2158     Insert(str
, lo
, nInsert
); 
2163     wxASSERT( str
.GetStringData()->IsValid() ); 
2167     for (size_t i 
= 0; i 
< nInsert
; i
++) 
2169         // the string data must not be deleted! 
2170         str
.GetStringData()->Lock(); 
2173         m_pItems
[m_nCount 
+ i
] = (wxChar 
*)str
.c_str(); // const_cast 
2175     size_t ret 
= m_nCount
; 
2176     m_nCount 
+= nInsert
; 
2181 // add item at the given position 
2182 void wxArrayString::Insert(const wxString
& str
, size_t nIndex
, size_t nInsert
) 
2184   wxASSERT( str
.GetStringData()->IsValid() ); 
2186   wxCHECK_RET( nIndex 
<= m_nCount
, wxT("bad index in wxArrayString::Insert") ); 
2187   wxCHECK_RET( m_nCount 
<= m_nCount 
+ nInsert
, 
2188                wxT("array size overflow in wxArrayString::Insert") ); 
2192   memmove(&m_pItems
[nIndex 
+ nInsert
], &m_pItems
[nIndex
], 
2193           (m_nCount 
- nIndex
)*sizeof(wxChar 
*)); 
2195   for (size_t i 
= 0; i 
< nInsert
; i
++) 
2197       str
.GetStringData()->Lock(); 
2198       m_pItems
[nIndex 
+ i
] = (wxChar 
*)str
.c_str(); 
2200   m_nCount 
+= nInsert
; 
2204 void wxArrayString::SetCount(size_t count
) 
2209     while ( m_nCount 
< count 
) 
2210         m_pItems
[m_nCount
++] = (wxChar 
*)s
.c_str(); 
2213 // removes item from array (by index) 
2214 void wxArrayString::RemoveAt(size_t nIndex
, size_t nRemove
) 
2216   wxCHECK_RET( nIndex 
< m_nCount
, wxT("bad index in wxArrayString::Remove") ); 
2217   wxCHECK_RET( nIndex 
+ nRemove 
<= m_nCount
, 
2218                wxT("removing too many elements in wxArrayString::Remove") ); 
2221   for (size_t i 
= 0; i 
< nRemove
; i
++) 
2222       Item(nIndex 
+ i
).GetStringData()->Unlock(); 
2224   memmove(&m_pItems
[nIndex
], &m_pItems
[nIndex 
+ nRemove
], 
2225           (m_nCount 
- nIndex 
- nRemove
)*sizeof(wxChar 
*)); 
2226   m_nCount 
-= nRemove
; 
2229 // removes item from array (by value) 
2230 void wxArrayString::Remove(const wxChar 
*sz
) 
2232   int iIndex 
= Index(sz
); 
2234   wxCHECK_RET( iIndex 
!= wxNOT_FOUND
, 
2235                wxT("removing inexistent element in wxArrayString::Remove") ); 
2240 void wxArrayString::assign(const_iterator first
, const_iterator last
) 
2242     reserve(last 
- first
); 
2243     for(; first 
!= last
; ++first
) 
2247 // ---------------------------------------------------------------------------- 
2249 // ---------------------------------------------------------------------------- 
2251 // we can only sort one array at a time with the quick-sort based 
2254   // need a critical section to protect access to gs_compareFunction and 
2255   // gs_sortAscending variables 
2256   static wxCriticalSection 
*gs_critsectStringSort 
= NULL
; 
2258   // call this before the value of the global sort vars is changed/after 
2259   // you're finished with them 
2260   #define START_SORT()     wxASSERT( !gs_critsectStringSort );                \ 
2261                            gs_critsectStringSort = new wxCriticalSection;     \ 
2262                            gs_critsectStringSort->Enter() 
2263   #define END_SORT()       gs_critsectStringSort->Leave();                    \ 
2264                            delete gs_critsectStringSort;                      \ 
2265                            gs_critsectStringSort = NULL 
2267   #define START_SORT() 
2269 #endif // wxUSE_THREADS 
2271 // function to use for string comparaison 
2272 static wxArrayString::CompareFunction gs_compareFunction 
= NULL
; 
2274 // if we don't use the compare function, this flag tells us if we sort the 
2275 // array in ascending or descending order 
2276 static bool gs_sortAscending 
= TRUE
; 
2278 // function which is called by quick sort 
2279 extern "C" int wxC_CALLING_CONV     
// LINKAGEMODE 
2280 wxStringCompareFunction(const void *first
, const void *second
) 
2282   wxString 
*strFirst 
= (wxString 
*)first
; 
2283   wxString 
*strSecond 
= (wxString 
*)second
; 
2285   if ( gs_compareFunction 
) { 
2286     return gs_compareFunction(*strFirst
, *strSecond
); 
2289     // maybe we should use wxStrcoll 
2290     int result 
= wxStrcmp(strFirst
->c_str(), strSecond
->c_str()); 
2292     return gs_sortAscending 
? result 
: -result
; 
2296 // sort array elements using passed comparaison function 
2297 void wxArrayString::Sort(CompareFunction compareFunction
) 
2301   wxASSERT( !gs_compareFunction 
);  // must have been reset to NULL 
2302   gs_compareFunction 
= compareFunction
; 
2306   // reset it to NULL so that Sort(bool) will work the next time 
2307   gs_compareFunction 
= NULL
; 
2312 typedef  int (wxC_CALLING_CONV 
* wxStringCompareFn
)(const void *first
, const void *second
); 
2314 void wxArrayString::Sort(CompareFunction2 compareFunction
) 
2316   qsort(m_pItems
, m_nCount
, sizeof(wxChar 
*), (wxStringCompareFn
)compareFunction
); 
2319 void wxArrayString::Sort(bool reverseOrder
) 
2321   Sort(reverseOrder 
? wxStringSortDescending 
: wxStringSortAscending
); 
2324 void wxArrayString::DoSort() 
2326   wxCHECK_RET( !m_autoSort
, wxT("can't use this method with sorted arrays") ); 
2328   // just sort the pointers using qsort() - of course it only works because 
2329   // wxString() *is* a pointer to its data 
2330   qsort(m_pItems
, m_nCount
, sizeof(wxChar 
*), wxStringCompareFunction
); 
2333 bool wxArrayString::operator==(const wxArrayString
& a
) const 
2335     if ( m_nCount 
!= a
.m_nCount 
) 
2338     for ( size_t n 
= 0; n 
< m_nCount
; n
++ ) 
2340         if ( Item(n
) != a
[n
] ) 
2347 #endif // !wxUSE_STL 
2349 int wxCMPFUNC_CONV 
wxStringSortAscending(wxString
* s1
, wxString
* s2
) 
2351     return wxStrcmp(s1
->c_str(), s2
->c_str()); 
2354 int wxCMPFUNC_CONV 
wxStringSortDescending(wxString
* s1
, wxString
* s2
) 
2356     return -wxStrcmp(s1
->c_str(), s2
->c_str());