1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/string.cpp 
   3 // Purpose:     wxString class 
   4 // Author:      Vadim Zeitlin, Ryan Norton 
   8 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 //              (c) 2004 Ryan Norton <wxprojects@comcast.net> 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  15  *  1) all empty strings use g_strEmpty, nRefs = -1 (set in Init()) 
  16  *  2) AllocBuffer() sets nRefs to 1, Lock() increments it by one 
  17  *  3) Unlock() decrements nRefs and frees memory if it goes to 0 
  20 // =========================================================================== 
  21 // headers, declarations, constants 
  22 // =========================================================================== 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  32     #include "wx/string.h" 
  34     #include "wx/thread.h" 
  46 // allocating extra space for each string consumes more memory but speeds up 
  47 // the concatenation operations (nLen is the current string's length) 
  48 // NB: EXTRA_ALLOC must be >= 0! 
  49 #define EXTRA_ALLOC       (19 - nLen % 16) 
  51 // --------------------------------------------------------------------------- 
  52 // static class variables definition 
  53 // --------------------------------------------------------------------------- 
  56   //According to STL _must_ be a -1 size_t 
  57   const size_t wxStringBase::npos 
= (size_t) -1; 
  60 // ---------------------------------------------------------------------------- 
  62 // ---------------------------------------------------------------------------- 
  66 extern const wxChar WXDLLIMPEXP_BASE 
*wxEmptyString 
= _T(""); 
  70 // for an empty string, GetStringData() will return this address: this 
  71 // structure has the same layout as wxStringData and it's data() method will 
  72 // return the empty string (dummy pointer) 
  77 } g_strEmpty 
= { {-1, 0, 0}, wxT('\0') }; 
  79 // empty C style string: points to 'string data' byte of g_strEmpty 
  80 extern const wxChar WXDLLIMPEXP_BASE 
*wxEmptyString 
= &g_strEmpty
.dummy
; 
  84 // ---------------------------------------------------------------------------- 
  86 // ---------------------------------------------------------------------------- 
  88 #if wxUSE_STD_IOSTREAM 
  92 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxString
& str
) 
 102 #endif // wxUSE_STD_IOSTREAM 
 104 // ---------------------------------------------------------------------------- 
 106 // ---------------------------------------------------------------------------- 
 108 // this small class is used to gather statistics for performance tuning 
 109 //#define WXSTRING_STATISTICS 
 110 #ifdef  WXSTRING_STATISTICS 
 114     Averager(const wxChar 
*sz
) { m_sz 
= sz
; m_nTotal 
= m_nCount 
= 0; } 
 116    { wxPrintf("wxString: average %s = %f\n", m_sz
, ((float)m_nTotal
)/m_nCount
); } 
 118     void Add(size_t n
) { m_nTotal 
+= n
; m_nCount
++; } 
 121     size_t m_nCount
, m_nTotal
; 
 123   } g_averageLength("allocation size"), 
 124     g_averageSummandLength("summand length"), 
 125     g_averageConcatHit("hit probability in concat"), 
 126     g_averageInitialLength("initial string length"); 
 128   #define STATISTICS_ADD(av, val) g_average##av.Add(val) 
 130   #define STATISTICS_ADD(av, val) 
 131 #endif // WXSTRING_STATISTICS 
 135 // =========================================================================== 
 136 // wxStringData class deallocation 
 137 // =========================================================================== 
 139 #if defined(__VISUALC__) && defined(_MT) && !defined(_DLL) 
 140 #  pragma message (__FILE__ ": building with Multithreaded non DLL runtime has a performance impact on wxString!") 
 141 void wxStringData::Free() 
 147 // =========================================================================== 
 149 // =========================================================================== 
 151 // takes nLength elements of psz starting at nPos 
 152 void wxStringBase::InitWith(const wxChar 
*psz
, size_t nPos
, size_t nLength
) 
 156   // if the length is not given, assume the string to be NUL terminated 
 157   if ( nLength 
== npos 
) { 
 158     wxASSERT_MSG( nPos 
<= wxStrlen(psz
), _T("index out of bounds") ); 
 160     nLength 
= wxStrlen(psz 
+ nPos
); 
 163   STATISTICS_ADD(InitialLength
, nLength
); 
 166     // trailing '\0' is written in AllocBuffer() 
 167     if ( !AllocBuffer(nLength
) ) { 
 168       wxFAIL_MSG( _T("out of memory in wxStringBase::InitWith") ); 
 171     wxTmemcpy(m_pchData
, psz 
+ nPos
, nLength
); 
 175 // poor man's iterators are "void *" pointers 
 176 wxStringBase::wxStringBase(const void *pStart
, const void *pEnd
) 
 178   if ( pEnd 
>= pStart 
) 
 180     InitWith((const wxChar 
*)pStart
, 0, 
 181              (const wxChar 
*)pEnd 
- (const wxChar 
*)pStart
); 
 185     wxFAIL_MSG( _T("pStart is not before pEnd") ); 
 190 wxStringBase::wxStringBase(size_type n
, wxChar ch
) 
 196 // --------------------------------------------------------------------------- 
 198 // --------------------------------------------------------------------------- 
 200 // allocates memory needed to store a C string of length nLen 
 201 bool wxStringBase::AllocBuffer(size_t nLen
) 
 203   // allocating 0 sized buffer doesn't make sense, all empty strings should 
 205   wxASSERT( nLen 
>  0 ); 
 207   // make sure that we don't overflow 
 208   wxASSERT( nLen 
< (INT_MAX 
/ sizeof(wxChar
)) - 
 209                    (sizeof(wxStringData
) + EXTRA_ALLOC 
+ 1) ); 
 211   STATISTICS_ADD(Length
, nLen
); 
 214   // 1) one extra character for '\0' termination 
 215   // 2) sizeof(wxStringData) for housekeeping info 
 216   wxStringData
* pData 
= (wxStringData
*) 
 217     malloc(sizeof(wxStringData
) + (nLen 
+ EXTRA_ALLOC 
+ 1)*sizeof(wxChar
)); 
 219   if ( pData 
== NULL 
) { 
 220     // allocation failures are handled by the caller 
 225   pData
->nDataLength  
= nLen
; 
 226   pData
->nAllocLength 
= nLen 
+ EXTRA_ALLOC
; 
 227   m_pchData           
= pData
->data();  // data starts after wxStringData 
 228   m_pchData
[nLen
]     = wxT('\0'); 
 232 // must be called before changing this string 
 233 bool wxStringBase::CopyBeforeWrite() 
 235   wxStringData
* pData 
= GetStringData(); 
 237   if ( pData
->IsShared() ) { 
 238     pData
->Unlock();                // memory not freed because shared 
 239     size_t nLen 
= pData
->nDataLength
; 
 240     if ( !AllocBuffer(nLen
) ) { 
 241       // allocation failures are handled by the caller 
 244     wxTmemcpy(m_pchData
, pData
->data(), nLen
); 
 247   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner 
 252 // must be called before replacing contents of this string 
 253 bool wxStringBase::AllocBeforeWrite(size_t nLen
) 
 255   wxASSERT( nLen 
!= 0 );  // doesn't make any sense 
 257   // must not share string and must have enough space 
 258   wxStringData
* pData 
= GetStringData(); 
 259   if ( pData
->IsShared() || pData
->IsEmpty() ) { 
 260     // can't work with old buffer, get new one 
 262     if ( !AllocBuffer(nLen
) ) { 
 263       // allocation failures are handled by the caller 
 268     if ( nLen 
> pData
->nAllocLength 
) { 
 269       // realloc the buffer instead of calling malloc() again, this is more 
 271       STATISTICS_ADD(Length
, nLen
); 
 275       pData 
= (wxStringData
*) 
 276           realloc(pData
, sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 278       if ( pData 
== NULL 
) { 
 279         // allocation failures are handled by the caller 
 280         // keep previous data since reallocation failed 
 284       pData
->nAllocLength 
= nLen
; 
 285       m_pchData 
= pData
->data(); 
 289   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner 
 291   // it doesn't really matter what the string length is as it's going to be 
 292   // overwritten later but, for extra safety, set it to 0 for now as we may 
 293   // have some junk in m_pchData 
 294   GetStringData()->nDataLength 
= 0; 
 299 wxStringBase
& wxStringBase::append(size_t n
, wxChar ch
) 
 301     size_type len 
= length(); 
 303     if ( !Alloc(len 
+ n
) || !CopyBeforeWrite() ) { 
 304       wxFAIL_MSG( _T("out of memory in wxStringBase::append") ); 
 306     GetStringData()->nDataLength 
= len 
+ n
; 
 307     m_pchData
[len 
+ n
] = '\0'; 
 308     for ( size_t i 
= 0; i 
< n
; ++i 
) 
 309         m_pchData
[len 
+ i
] = ch
; 
 313 void wxStringBase::resize(size_t nSize
, wxChar ch
) 
 315     size_t len 
= length(); 
 319         erase(begin() + nSize
, end()); 
 321     else if ( nSize 
> len 
) 
 323         append(nSize 
- len
, ch
); 
 325     //else: we have exactly the specified length, nothing to do 
 328 // allocate enough memory for nLen characters 
 329 bool wxStringBase::Alloc(size_t nLen
) 
 331   wxStringData 
*pData 
= GetStringData(); 
 332   if ( pData
->nAllocLength 
<= nLen 
) { 
 333     if ( pData
->IsEmpty() ) { 
 336       pData 
= (wxStringData 
*) 
 337                 malloc(sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 339       if ( pData 
== NULL 
) { 
 340         // allocation failure handled by caller 
 345       pData
->nDataLength 
= 0; 
 346       pData
->nAllocLength 
= nLen
; 
 347       m_pchData 
= pData
->data();  // data starts after wxStringData 
 348       m_pchData
[0u] = wxT('\0'); 
 350     else if ( pData
->IsShared() ) { 
 351       pData
->Unlock();                // memory not freed because shared 
 352       size_t nOldLen 
= pData
->nDataLength
; 
 353       if ( !AllocBuffer(nLen
) ) { 
 354         // allocation failure handled by caller 
 357       // +1 to copy the terminator, too 
 358       memcpy(m_pchData
, pData
->data(), (nOldLen
+1)*sizeof(wxChar
)); 
 359       GetStringData()->nDataLength 
= nOldLen
; 
 364       pData 
= (wxStringData 
*) 
 365         realloc(pData
, sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 367       if ( pData 
== NULL 
) { 
 368         // allocation failure handled by caller 
 369         // keep previous data since reallocation failed 
 373       // it's not important if the pointer changed or not (the check for this 
 374       // is not faster than assigning to m_pchData in all cases) 
 375       pData
->nAllocLength 
= nLen
; 
 376       m_pchData 
= pData
->data(); 
 379   //else: we've already got enough 
 383 wxStringBase::iterator 
wxStringBase::begin() 
 390 wxStringBase::iterator 
wxStringBase::end() 
 394     return m_pchData 
+ length(); 
 397 wxStringBase::iterator 
wxStringBase::erase(iterator it
) 
 399     size_type idx 
= it 
- begin(); 
 401     return begin() + idx
; 
 404 wxStringBase
& wxStringBase::erase(size_t nStart
, size_t nLen
) 
 406     wxASSERT(nStart 
<= length()); 
 407     size_t strLen 
= length() - nStart
; 
 408     // delete nLen or up to the end of the string characters 
 409     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 410     wxString 
strTmp(c_str(), nStart
); 
 411     strTmp
.append(c_str() + nStart 
+ nLen
, length() - nStart 
- nLen
); 
 417 wxStringBase
& wxStringBase::insert(size_t nPos
, const wxChar 
*sz
, size_t n
) 
 419     wxASSERT( nPos 
<= length() ); 
 421     if ( n 
== npos 
) n 
= wxStrlen(sz
); 
 422     if ( n 
== 0 ) return *this; 
 424     if ( !Alloc(length() + n
) || !CopyBeforeWrite() ) { 
 425         wxFAIL_MSG( _T("out of memory in wxStringBase::insert") ); 
 428     memmove(m_pchData 
+ nPos 
+ n
, m_pchData 
+ nPos
, 
 429             (length() - nPos
) * sizeof(wxChar
)); 
 430     memcpy(m_pchData 
+ nPos
, sz
, n 
* sizeof(wxChar
)); 
 431     GetStringData()->nDataLength 
= length() + n
; 
 432     m_pchData
[length()] = '\0'; 
 437 void wxStringBase::swap(wxStringBase
& str
) 
 439     wxChar
* tmp 
= str
.m_pchData
; 
 440     str
.m_pchData 
= m_pchData
; 
 444 size_t wxStringBase::find(const wxStringBase
& str
, size_t nStart
) const 
 446     // deal with the special case of empty string first 
 447     const size_t nLen 
= length(); 
 448     const size_t nLenOther 
= str
.length(); 
 452         // empty string is a substring of anything 
 458         // the other string is non empty so can't be our substring 
 462     wxASSERT( str
.GetStringData()->IsValid() ); 
 463     wxASSERT( nStart 
<= nLen 
); 
 465     const wxChar 
* const other 
= str
.c_str(); 
 468     const wxChar
* p 
= (const wxChar
*)wxTmemchr(c_str() + nStart
, 
 475     while ( p 
- c_str() + nLenOther 
<= nLen 
&& wxTmemcmp(p
, other
, nLenOther
) ) 
 480         p 
= (const wxChar
*)wxTmemchr(p
, *other
, nLen 
- (p 
- c_str())); 
 486     return p 
- c_str() + nLenOther 
<= nLen 
? p 
- c_str() : npos
; 
 489 size_t wxStringBase::find(const wxChar
* sz
, size_t nStart
, size_t n
) const 
 491     return find(wxStringBase(sz
, n
), nStart
); 
 494 size_t wxStringBase::find(wxChar ch
, size_t nStart
) const 
 496     wxASSERT( nStart 
<= length() ); 
 498     const wxChar 
*p 
= (const wxChar
*)wxTmemchr(c_str() + nStart
, ch
, length() - nStart
); 
 500     return p 
== NULL 
? npos 
: p 
- c_str(); 
 503 size_t wxStringBase::rfind(const wxStringBase
& str
, size_t nStart
) const 
 505     wxASSERT( str
.GetStringData()->IsValid() ); 
 506     wxASSERT( nStart 
== npos 
|| nStart 
<= length() ); 
 508     if ( length() >= str
.length() ) 
 510         // avoids a corner case later 
 511         if ( length() == 0 && str
.length() == 0 ) 
 514         // "top" is the point where search starts from 
 515         size_t top 
= length() - str
.length(); 
 517         if ( nStart 
== npos 
) 
 518             nStart 
= length() - 1; 
 522         const wxChar 
*cursor 
= c_str() + top
; 
 525             if ( wxTmemcmp(cursor
, str
.c_str(), 
 528                 return cursor 
- c_str(); 
 530         } while ( cursor
-- > c_str() ); 
 536 size_t wxStringBase::rfind(const wxChar
* sz
, size_t nStart
, size_t n
) const 
 538     return rfind(wxStringBase(sz
, n
), nStart
); 
 541 size_t wxStringBase::rfind(wxChar ch
, size_t nStart
) const 
 543     if ( nStart 
== npos 
) 
 549         wxASSERT( nStart 
<= length() ); 
 552     const wxChar 
*actual
; 
 553     for ( actual 
= c_str() + ( nStart 
== npos 
? length() : nStart 
+ 1 ); 
 554           actual 
> c_str(); --actual 
) 
 556         if ( *(actual 
- 1) == ch 
) 
 557             return (actual 
- 1) - c_str(); 
 563 size_t wxStringBase::find_first_of(const wxChar
* sz
, size_t nStart
) const 
 565     wxASSERT(nStart 
<= length()); 
 567     size_t len 
= wxStrlen(sz
); 
 570     for(i 
= nStart
; i 
< this->length(); ++i
) 
 572         if (wxTmemchr(sz
, *(c_str() + i
), len
)) 
 576     if(i 
== this->length()) 
 582 size_t wxStringBase::find_first_of(const wxChar
* sz
, size_t nStart
, 
 585     return find_first_of(wxStringBase(sz
, n
), nStart
); 
 588 size_t wxStringBase::find_last_of(const wxChar
* sz
, size_t nStart
) const 
 590     if ( nStart 
== npos 
) 
 592         nStart 
= length() - 1; 
 596         wxASSERT_MSG( nStart 
<= length(), 
 597                         _T("invalid index in find_last_of()") ); 
 600     size_t len 
= wxStrlen(sz
); 
 602     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 604         if ( wxTmemchr(sz
, *p
, len
) ) 
 611 size_t wxStringBase::find_last_of(const wxChar
* sz
, size_t nStart
, 
 614     return find_last_of(wxStringBase(sz
, n
), nStart
); 
 617 size_t wxStringBase::find_first_not_of(const wxChar
* sz
, size_t nStart
) const 
 619     if ( nStart 
== npos 
) 
 625         wxASSERT( nStart 
<= length() ); 
 628     size_t len 
= wxStrlen(sz
); 
 631     for(i 
= nStart
; i 
< this->length(); ++i
) 
 633         if (!wxTmemchr(sz
, *(c_str() + i
), len
)) 
 637     if(i 
== this->length()) 
 643 size_t wxStringBase::find_first_not_of(const wxChar
* sz
, size_t nStart
, 
 646     return find_first_not_of(wxStringBase(sz
, n
), nStart
); 
 649 size_t wxStringBase::find_first_not_of(wxChar ch
, size_t nStart
) const 
 651     wxASSERT( nStart 
<= length() ); 
 653     for ( const wxChar 
*p 
= c_str() + nStart
; *p
; p
++ ) 
 662 size_t wxStringBase::find_last_not_of(const wxChar
* sz
, size_t nStart
) const 
 664     if ( nStart 
== npos 
) 
 666         nStart 
= length() - 1; 
 670         wxASSERT( nStart 
<= length() ); 
 673     size_t len 
= wxStrlen(sz
); 
 675     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 677         if ( !wxTmemchr(sz
, *p
,len
) ) 
 684 size_t wxStringBase::find_last_not_of(const wxChar
* sz
, size_t nStart
, 
 687     return find_last_not_of(wxStringBase(sz
, n
), nStart
); 
 690 size_t wxStringBase::find_last_not_of(wxChar ch
, size_t nStart
) const 
 692     if ( nStart 
== npos 
) 
 694         nStart 
= length() - 1; 
 698         wxASSERT( nStart 
<= length() ); 
 701     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 710 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 713   wxASSERT_MSG( nStart 
<= length(), 
 714                 _T("index out of bounds in wxStringBase::replace") ); 
 715   size_t strLen 
= length() - nStart
; 
 716   nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 719   strTmp
.reserve(length()); // micro optimisation to avoid multiple mem allocs 
 721   //This is kind of inefficient, but its pretty good considering... 
 722   //we don't want to use character access operators here because on STL 
 723   //it will freeze the reference count of strTmp, which means a deep copy 
 724   //at the end when swap is called 
 726   //Also, we can't use append with the full character pointer and must 
 727   //do it manually because this string can contain null characters 
 728   for(size_t i1 
= 0; i1 
< nStart
; ++i1
) 
 729       strTmp
.append(1, this->c_str()[i1
]); 
 731   //its safe to do the full version here because 
 732   //sz must be a normal c string 
 735   for(size_t i2 
= nStart 
+ nLen
; i2 
< length(); ++i2
) 
 736       strTmp
.append(1, this->c_str()[i2
]); 
 742 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 743                                     size_t nCount
, wxChar ch
) 
 745   return replace(nStart
, nLen
, wxStringBase(nCount
, ch
).c_str()); 
 748 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 749                                     const wxStringBase
& str
, 
 750                                     size_t nStart2
, size_t nLen2
) 
 752   return replace(nStart
, nLen
, str
.substr(nStart2
, nLen2
)); 
 755 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 756                                     const wxChar
* sz
, size_t nCount
) 
 758   return replace(nStart
, nLen
, wxStringBase(sz
, nCount
).c_str()); 
 761 wxStringBase 
wxStringBase::substr(size_t nStart
, size_t nLen
) const 
 764     nLen 
= length() - nStart
; 
 765   return wxStringBase(*this, nStart
, nLen
); 
 768 // assigns one string to another 
 769 wxStringBase
& wxStringBase::operator=(const wxStringBase
& stringSrc
) 
 771   wxASSERT( stringSrc
.GetStringData()->IsValid() ); 
 773   // don't copy string over itself 
 774   if ( m_pchData 
!= stringSrc
.m_pchData 
) { 
 775     if ( stringSrc
.GetStringData()->IsEmpty() ) { 
 780       GetStringData()->Unlock(); 
 781       m_pchData 
= stringSrc
.m_pchData
; 
 782       GetStringData()->Lock(); 
 789 // assigns a single character 
 790 wxStringBase
& wxStringBase::operator=(wxChar ch
) 
 792   if ( !AssignCopy(1, &ch
) ) { 
 793     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") ); 
 799 wxStringBase
& wxStringBase::operator=(const wxChar 
*psz
) 
 801   if ( !AssignCopy(wxStrlen(psz
), psz
) ) { 
 802     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") ); 
 807 // helper function: does real copy 
 808 bool wxStringBase::AssignCopy(size_t nSrcLen
, const wxChar 
*pszSrcData
) 
 810   if ( nSrcLen 
== 0 ) { 
 814     if ( !AllocBeforeWrite(nSrcLen
) ) { 
 815       // allocation failure handled by caller 
 818     memcpy(m_pchData
, pszSrcData
, nSrcLen
*sizeof(wxChar
)); 
 819     GetStringData()->nDataLength 
= nSrcLen
; 
 820     m_pchData
[nSrcLen
] = wxT('\0'); 
 825 // --------------------------------------------------------------------------- 
 826 // string concatenation 
 827 // --------------------------------------------------------------------------- 
 829 // add something to this string 
 830 bool wxStringBase::ConcatSelf(size_t nSrcLen
, const wxChar 
*pszSrcData
, 
 833   STATISTICS_ADD(SummandLength
, nSrcLen
); 
 835   nSrcLen 
= nSrcLen 
< nMaxLen 
? nSrcLen 
: nMaxLen
; 
 837   // concatenating an empty string is a NOP 
 839     wxStringData 
*pData 
= GetStringData(); 
 840     size_t nLen 
= pData
->nDataLength
; 
 841     size_t nNewLen 
= nLen 
+ nSrcLen
; 
 843     // alloc new buffer if current is too small 
 844     if ( pData
->IsShared() ) { 
 845       STATISTICS_ADD(ConcatHit
, 0); 
 847       // we have to allocate another buffer 
 848       wxStringData
* pOldData 
= GetStringData(); 
 849       if ( !AllocBuffer(nNewLen
) ) { 
 850           // allocation failure handled by caller 
 853       memcpy(m_pchData
, pOldData
->data(), nLen
*sizeof(wxChar
)); 
 856     else if ( nNewLen 
> pData
->nAllocLength 
) { 
 857       STATISTICS_ADD(ConcatHit
, 0); 
 860       // we have to grow the buffer 
 861       if ( capacity() < nNewLen 
) { 
 862           // allocation failure handled by caller 
 867       STATISTICS_ADD(ConcatHit
, 1); 
 869       // the buffer is already big enough 
 872     // should be enough space 
 873     wxASSERT( nNewLen 
<= GetStringData()->nAllocLength 
); 
 875     // fast concatenation - all is done in our buffer 
 876     memcpy(m_pchData 
+ nLen
, pszSrcData
, nSrcLen
*sizeof(wxChar
)); 
 878     m_pchData
[nNewLen
] = wxT('\0');          // put terminating '\0' 
 879     GetStringData()->nDataLength 
= nNewLen
; // and fix the length 
 881   //else: the string to append was empty 
 885 // --------------------------------------------------------------------------- 
 886 // simple sub-string extraction 
 887 // --------------------------------------------------------------------------- 
 889 // helper function: clone the data attached to this string 
 890 bool wxStringBase::AllocCopy(wxString
& dest
, int nCopyLen
, int nCopyIndex
) const 
 892   if ( nCopyLen 
== 0 ) { 
 896     if ( !dest
.AllocBuffer(nCopyLen
) ) { 
 897       // allocation failure handled by caller 
 900     memcpy(dest
.m_pchData
, m_pchData 
+ nCopyIndex
, nCopyLen
*sizeof(wxChar
)); 
 907 #if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE) 
 910     #define STRINGCLASS wxStringBase 
 912     #define STRINGCLASS wxString 
 915 static inline int wxDoCmp(const wxChar
* s1
, size_t l1
, 
 916                           const wxChar
* s2
, size_t l2
) 
 919         return wxTmemcmp(s1
, s2
, l1
); 
 922         int ret 
= wxTmemcmp(s1
, s2
, l1
); 
 923         return ret 
== 0 ? -1 : ret
; 
 927         int ret 
= wxTmemcmp(s1
, s2
, l2
); 
 928         return ret 
== 0 ? +1 : ret
; 
 932 int STRINGCLASS::compare(const wxStringBase
& str
) const 
 934     return ::wxDoCmp(data(), length(), str
.data(), str
.length()); 
 937 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 938                          const wxStringBase
& str
) const 
 940     wxASSERT(nStart 
<= length()); 
 941     size_type strLen 
= length() - nStart
; 
 942     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 943     return ::wxDoCmp(data() + nStart
, nLen
, str
.data(), str
.length()); 
 946 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 947                          const wxStringBase
& str
, 
 948                          size_t nStart2
, size_t nLen2
) const 
 950     wxASSERT(nStart 
<= length()); 
 951     wxASSERT(nStart2 
<= str
.length()); 
 952     size_type strLen  
=     length() - nStart
, 
 953               strLen2 
= str
.length() - nStart2
; 
 954     nLen  
= strLen  
< nLen  
? strLen  
: nLen
; 
 955     nLen2 
= strLen2 
< nLen2 
? strLen2 
: nLen2
; 
 956     return ::wxDoCmp(data() + nStart
, nLen
, str
.data() + nStart2
, nLen2
); 
 959 int STRINGCLASS::compare(const wxChar
* sz
) const 
 961     size_t nLen 
= wxStrlen(sz
); 
 962     return ::wxDoCmp(data(), length(), sz
, nLen
); 
 965 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 966                          const wxChar
* sz
, size_t nCount
) const 
 968     wxASSERT(nStart 
<= length()); 
 969     size_type strLen 
= length() - nStart
; 
 970     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 972         nCount 
= wxStrlen(sz
); 
 974     return ::wxDoCmp(data() + nStart
, nLen
, sz
, nCount
); 
 979 #endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE) 
 981 // =========================================================================== 
 982 // wxString class core 
 983 // =========================================================================== 
 985 // --------------------------------------------------------------------------- 
 986 // construction and conversion 
 987 // --------------------------------------------------------------------------- 
 991 // from multibyte string 
 992 wxString::wxString(const char *psz
, const wxMBConv
& conv
, size_t nLength
) 
 995     if ( psz 
&& nLength 
!= 0 ) 
 997         if ( nLength 
== npos 
) 
1003         wxWCharBuffer wbuf 
= conv
.cMB2WC(psz
, nLength
, &nLenWide
); 
1006             assign(wbuf
, nLenWide
); 
1010 //Convert wxString in Unicode mode to a multi-byte string 
1011 const wxCharBuffer 
wxString::mb_str(const wxMBConv
& conv
) const 
1013     return conv
.cWC2MB(c_str(), length() + 1 /* size, not length */, NULL
); 
1021 wxString::wxString(const wchar_t *pwz
, const wxMBConv
& conv
, size_t nLength
) 
1024     if ( pwz 
&& nLength 
!= 0 ) 
1026         if ( nLength 
== npos 
) 
1032         wxCharBuffer buf 
= conv
.cWC2MB(pwz
, nLength
, &nLenMB
); 
1035             assign(buf
, nLenMB
); 
1039 //Converts this string to a wide character string if unicode 
1040 //mode is not enabled and wxUSE_WCHAR_T is enabled 
1041 const wxWCharBuffer 
wxString::wc_str(const wxMBConv
& conv
) const 
1043     return conv
.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL
); 
1046 #endif // wxUSE_WCHAR_T 
1048 #endif // Unicode/ANSI 
1050 // shrink to minimal size (releasing extra memory) 
1051 bool wxString::Shrink() 
1053   wxString 
tmp(begin(), end()); 
1055   return tmp
.length() == length(); 
1059 // get the pointer to writable buffer of (at least) nLen bytes 
1060 wxChar 
*wxString::GetWriteBuf(size_t nLen
) 
1062   if ( !AllocBeforeWrite(nLen
) ) { 
1063     // allocation failure handled by caller 
1067   wxASSERT( GetStringData()->nRefs 
== 1 ); 
1068   GetStringData()->Validate(false); 
1073 // put string back in a reasonable state after GetWriteBuf 
1074 void wxString::UngetWriteBuf() 
1076   GetStringData()->nDataLength 
= wxStrlen(m_pchData
); 
1077   GetStringData()->Validate(true); 
1080 void wxString::UngetWriteBuf(size_t nLen
) 
1082   GetStringData()->nDataLength 
= nLen
; 
1083   GetStringData()->Validate(true); 
1087 // --------------------------------------------------------------------------- 
1089 // --------------------------------------------------------------------------- 
1091 // all functions are inline in string.h 
1093 // --------------------------------------------------------------------------- 
1094 // assignment operators 
1095 // --------------------------------------------------------------------------- 
1099 // same as 'signed char' variant 
1100 wxString
& wxString::operator=(const unsigned char* psz
) 
1102   *this = (const char *)psz
; 
1107 wxString
& wxString::operator=(const wchar_t *pwz
) 
1118  * concatenation functions come in 5 flavours: 
1120  *  char   + string      and      string + char 
1121  *  C str  + string      and      string + C str 
1124 wxString 
operator+(const wxString
& str1
, const wxString
& str2
) 
1127     wxASSERT( str1
.GetStringData()->IsValid() ); 
1128     wxASSERT( str2
.GetStringData()->IsValid() ); 
1137 wxString 
operator+(const wxString
& str
, wxChar ch
) 
1140     wxASSERT( str
.GetStringData()->IsValid() ); 
1149 wxString 
operator+(wxChar ch
, const wxString
& str
) 
1152     wxASSERT( str
.GetStringData()->IsValid() ); 
1161 wxString 
operator+(const wxString
& str
, const wxChar 
*psz
) 
1164     wxASSERT( str
.GetStringData()->IsValid() ); 
1168     if ( !s
.Alloc(wxStrlen(psz
) + str
.length()) ) { 
1169         wxFAIL_MSG( _T("out of memory in wxString::operator+") ); 
1177 wxString 
operator+(const wxChar 
*psz
, const wxString
& str
) 
1180     wxASSERT( str
.GetStringData()->IsValid() ); 
1184     if ( !s
.Alloc(wxStrlen(psz
) + str
.length()) ) { 
1185         wxFAIL_MSG( _T("out of memory in wxString::operator+") ); 
1193 // =========================================================================== 
1194 // other common string functions 
1195 // =========================================================================== 
1197 int wxString::Cmp(const wxString
& s
) const 
1202 int wxString::Cmp(const wxChar
* psz
) const 
1204     return compare(psz
); 
1207 static inline int wxDoCmpNoCase(const wxChar
* s1
, size_t l1
, 
1208                                 const wxChar
* s2
, size_t l2
) 
1214         for(i 
= 0; i 
< l1
; ++i
) 
1216             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1219         return i 
== l1 
? 0 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1223         for(i 
= 0; i 
< l1
; ++i
) 
1225             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1228         return i 
== l1 
? -1 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1232         for(i 
= 0; i 
< l2
; ++i
) 
1234             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1237         return i 
== l2 
? 1 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1241 int wxString::CmpNoCase(const wxString
& s
) const 
1243     return wxDoCmpNoCase(data(), length(), s
.data(), s
.length()); 
1246 int wxString::CmpNoCase(const wxChar
* psz
) const 
1248     int nLen 
= wxStrlen(psz
); 
1250     return wxDoCmpNoCase(data(), length(), psz
, nLen
); 
1257 #ifndef __SCHAR_MAX__ 
1258 #define __SCHAR_MAX__ 127 
1262 wxString 
wxString::FromAscii(const char *ascii
) 
1265        return wxEmptyString
; 
1267     size_t len 
= strlen( ascii 
); 
1272         wxStringBuffer 
buf(res
, len
); 
1274         wchar_t *dest 
= buf
; 
1278            if ( (*dest
++ = (wchar_t)(unsigned char)*ascii
++) == L
'\0' ) 
1286 wxString 
wxString::FromAscii(const char ascii
) 
1288     // What do we do with '\0' ? 
1291     res 
+= (wchar_t)(unsigned char) ascii
; 
1296 const wxCharBuffer 
wxString::ToAscii() const 
1298     // this will allocate enough space for the terminating NUL too 
1299     wxCharBuffer 
buffer(length()); 
1302     char *dest 
= buffer
.data(); 
1304     const wchar_t *pwc 
= c_str(); 
1307         *dest
++ = (char)(*pwc 
> SCHAR_MAX 
? wxT('_') : *pwc
); 
1309         // the output string can't have embedded NULs anyhow, so we can safely 
1310         // stop at first of them even if we do have any 
1320 // extract string of length nCount starting at nFirst 
1321 wxString 
wxString::Mid(size_t nFirst
, size_t nCount
) const 
1323     size_t nLen 
= length(); 
1325     // default value of nCount is npos and means "till the end" 
1326     if ( nCount 
== npos 
) 
1328         nCount 
= nLen 
- nFirst
; 
1331     // out-of-bounds requests return sensible things 
1332     if ( nFirst 
+ nCount 
> nLen 
) 
1334         nCount 
= nLen 
- nFirst
; 
1337     if ( nFirst 
> nLen 
) 
1339         // AllocCopy() will return empty string 
1340         return wxEmptyString
; 
1343     wxString 
dest(*this, nFirst
, nCount
); 
1344     if ( dest
.length() != nCount 
) 
1346         wxFAIL_MSG( _T("out of memory in wxString::Mid") ); 
1352 // check that the string starts with prefix and return the rest of the string 
1353 // in the provided pointer if it is not NULL, otherwise return false 
1354 bool wxString::StartsWith(const wxChar 
*prefix
, wxString 
*rest
) const 
1356     wxASSERT_MSG( prefix
, _T("invalid parameter in wxString::StartsWith") ); 
1358     // first check if the beginning of the string matches the prefix: note 
1359     // that we don't have to check that we don't run out of this string as 
1360     // when we reach the terminating NUL, either prefix string ends too (and 
1361     // then it's ok) or we break out of the loop because there is no match 
1362     const wxChar 
*p 
= c_str(); 
1365         if ( *prefix
++ != *p
++ ) 
1374         // put the rest of the string into provided pointer 
1382 // check that the string ends with suffix and return the rest of it in the 
1383 // provided pointer if it is not NULL, otherwise return false 
1384 bool wxString::EndsWith(const wxChar 
*suffix
, wxString 
*rest
) const 
1386     wxASSERT_MSG( suffix
, _T("invalid parameter in wxString::EndssWith") ); 
1388     int start 
= length() - wxStrlen(suffix
); 
1389     if ( start 
< 0 || wxStrcmp(c_str() + start
, suffix
) != 0 ) 
1394         // put the rest of the string into provided pointer 
1395         rest
->assign(*this, 0, start
); 
1402 // extract nCount last (rightmost) characters 
1403 wxString 
wxString::Right(size_t nCount
) const 
1405   if ( nCount 
> length() ) 
1408   wxString 
dest(*this, length() - nCount
, nCount
); 
1409   if ( dest
.length() != nCount 
) { 
1410     wxFAIL_MSG( _T("out of memory in wxString::Right") ); 
1415 // get all characters after the last occurence of ch 
1416 // (returns the whole string if ch not found) 
1417 wxString 
wxString::AfterLast(wxChar ch
) const 
1420   int iPos 
= Find(ch
, true); 
1421   if ( iPos 
== wxNOT_FOUND 
) 
1424     str 
= c_str() + iPos 
+ 1; 
1429 // extract nCount first (leftmost) characters 
1430 wxString 
wxString::Left(size_t nCount
) const 
1432   if ( nCount 
> length() ) 
1435   wxString 
dest(*this, 0, nCount
); 
1436   if ( dest
.length() != nCount 
) { 
1437     wxFAIL_MSG( _T("out of memory in wxString::Left") ); 
1442 // get all characters before the first occurence of ch 
1443 // (returns the whole string if ch not found) 
1444 wxString 
wxString::BeforeFirst(wxChar ch
) const 
1446   int iPos 
= Find(ch
); 
1447   if ( iPos 
== wxNOT_FOUND 
) iPos 
= length(); 
1448   return wxString(*this, 0, iPos
); 
1451 /// get all characters before the last occurence of ch 
1452 /// (returns empty string if ch not found) 
1453 wxString 
wxString::BeforeLast(wxChar ch
) const 
1456   int iPos 
= Find(ch
, true); 
1457   if ( iPos 
!= wxNOT_FOUND 
&& iPos 
!= 0 ) 
1458     str 
= wxString(c_str(), iPos
); 
1463 /// get all characters after the first occurence of ch 
1464 /// (returns empty string if ch not found) 
1465 wxString 
wxString::AfterFirst(wxChar ch
) const 
1468   int iPos 
= Find(ch
); 
1469   if ( iPos 
!= wxNOT_FOUND 
) 
1470     str 
= c_str() + iPos 
+ 1; 
1475 // replace first (or all) occurences of some substring with another one 
1476 size_t wxString::Replace(const wxChar 
*szOld
, 
1477                   const wxChar 
*szNew
, bool bReplaceAll
) 
1479     // if we tried to replace an empty string we'd enter an infinite loop below 
1480     wxCHECK_MSG( szOld 
&& *szOld 
&& szNew
, 0, 
1481                  _T("wxString::Replace(): invalid parameter") ); 
1483     size_t uiCount 
= 0;   // count of replacements made 
1485     size_t uiOldLen 
= wxStrlen(szOld
); 
1486     size_t uiNewLen 
= wxStrlen(szNew
); 
1490     while ( this->c_str()[dwPos
] != wxT('\0') ) 
1492         //DO NOT USE STRSTR HERE 
1493         //this string can contain embedded null characters, 
1494         //so strstr will function incorrectly 
1495         dwPos 
= find(szOld
, dwPos
); 
1496         if ( dwPos 
== npos 
) 
1497             break;                  // exit the loop 
1500             //replace this occurance of the old string with the new one 
1501             replace(dwPos
, uiOldLen
, szNew
, uiNewLen
); 
1503             //move up pos past the string that was replaced 
1506             //increase replace count 
1511                 break;                  // exit the loop 
1518 bool wxString::IsAscii() const 
1520   const wxChar 
*s 
= (const wxChar
*) *this; 
1522     if(!isascii(*s
)) return(false); 
1528 bool wxString::IsWord() const 
1530   const wxChar 
*s 
= (const wxChar
*) *this; 
1532     if(!wxIsalpha(*s
)) return(false); 
1538 bool wxString::IsNumber() const 
1540   const wxChar 
*s 
= (const wxChar
*) *this; 
1542      if ((s
[0] == wxT('-')) || (s
[0] == wxT('+'))) s
++; 
1544     if(!wxIsdigit(*s
)) return(false); 
1550 wxString 
wxString::Strip(stripType w
) const 
1553     if ( w 
& leading 
) s
.Trim(false); 
1554     if ( w 
& trailing 
) s
.Trim(true); 
1558 // --------------------------------------------------------------------------- 
1560 // --------------------------------------------------------------------------- 
1562 wxString
& wxString::MakeUpper() 
1564   for ( iterator it 
= begin(), en 
= end(); it 
!= en
; ++it 
) 
1565     *it 
= (wxChar
)wxToupper(*it
); 
1570 wxString
& wxString::MakeLower() 
1572   for ( iterator it 
= begin(), en 
= end(); it 
!= en
; ++it 
) 
1573     *it 
= (wxChar
)wxTolower(*it
); 
1578 // --------------------------------------------------------------------------- 
1579 // trimming and padding 
1580 // --------------------------------------------------------------------------- 
1582 // some compilers (VC++ 6.0 not to name them) return true for a call to 
1583 // isspace('ê') in the C locale which seems to be broken to me, but we have to 
1584 // live with this by checking that the character is a 7 bit one - even if this 
1585 // may fail to detect some spaces (I don't know if Unicode doesn't have 
1586 // space-like symbols somewhere except in the first 128 chars), it is arguably 
1587 // still better than trimming away accented letters 
1588 inline int wxSafeIsspace(wxChar ch
) { return (ch 
< 127) && wxIsspace(ch
); } 
1590 // trims spaces (in the sense of isspace) from left or right side 
1591 wxString
& wxString::Trim(bool bFromRight
) 
1593     // first check if we're going to modify the string at all 
1596           (bFromRight 
&& wxSafeIsspace(GetChar(length() - 1))) || 
1597           (!bFromRight 
&& wxSafeIsspace(GetChar(0u))) 
1603             // find last non-space character 
1604             reverse_iterator psz 
= rbegin(); 
1605             while ( (psz 
!= rend()) && wxSafeIsspace(*psz
) ) 
1608             // truncate at trailing space start 
1609             erase(psz
.base(), end()); 
1613             // find first non-space character 
1614             iterator psz 
= begin(); 
1615             while ( (psz 
!= end()) && wxSafeIsspace(*psz
) ) 
1618             // fix up data and length 
1619             erase(begin(), psz
); 
1626 // adds nCount characters chPad to the string from either side 
1627 wxString
& wxString::Pad(size_t nCount
, wxChar chPad
, bool bFromRight
) 
1629     wxString 
s(chPad
, nCount
); 
1642 // truncate the string 
1643 wxString
& wxString::Truncate(size_t uiLen
) 
1645     if ( uiLen 
< length() ) 
1647         erase(begin() + uiLen
, end()); 
1649     //else: nothing to do, string is already short enough 
1654 // --------------------------------------------------------------------------- 
1655 // finding (return wxNOT_FOUND if not found and index otherwise) 
1656 // --------------------------------------------------------------------------- 
1659 int wxString::Find(wxChar ch
, bool bFromEnd
) const 
1661     size_type idx 
= bFromEnd 
? find_last_of(ch
) : find_first_of(ch
); 
1663     return (idx 
== npos
) ? wxNOT_FOUND 
: (int)idx
; 
1666 // find a sub-string (like strstr) 
1667 int wxString::Find(const wxChar 
*pszSub
) const 
1669     size_type idx 
= find(pszSub
); 
1671     return (idx 
== npos
) ? wxNOT_FOUND 
: (int)idx
; 
1674 // ---------------------------------------------------------------------------- 
1675 // conversion to numbers 
1676 // ---------------------------------------------------------------------------- 
1678 // the implementation of all the functions below is exactly the same so factor 
1680 template <typename T
> 
1681 bool wxStringToIntType(const wxChar 
*start
, 
1684                        T (*func
)(const wxChar 
*, wxChar 
**, int)) 
1686     wxCHECK_MSG( val
, false, _T("NULL output pointer") ); 
1687     wxASSERT_MSG( !base 
|| (base 
> 1 && base 
<= 36), _T("invalid base") ); 
1690     *val 
= (*func
)(start
, &end
, base
); 
1692     // return true only if scan was stopped by the terminating NUL and if the 
1693     // string was not empty to start with and no under/overflow occurred 
1694     return !*end 
&& (end 
!= start
) && (errno 
!= ERANGE
); 
1697 bool wxString::ToLong(long *val
, int base
) const 
1699     return wxStringToIntType(c_str(), val
, base
, wxStrtol
); 
1702 bool wxString::ToULong(unsigned long *val
, int base
) const 
1704     return wxStringToIntType(c_str(), val
, base
, wxStrtoul
); 
1707 bool wxString::ToDouble(double *val
) const 
1709     wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToDouble") ); 
1711     const wxChar 
*start 
= c_str(); 
1713     *val 
= wxStrtod(start
, &end
); 
1715     // return true only if scan was stopped by the terminating NUL and if the 
1716     // string was not empty to start with and no under/overflow occurred 
1717     return !*end 
&& (end 
!= start
) && (errno 
!= ERANGE
); 
1720 // --------------------------------------------------------------------------- 
1722 // --------------------------------------------------------------------------- 
1725 wxString 
wxString::Format(const wxChar 
*pszFormat
, ...) 
1728     va_start(argptr
, pszFormat
); 
1731     s
.PrintfV(pszFormat
, argptr
); 
1739 wxString 
wxString::FormatV(const wxChar 
*pszFormat
, va_list argptr
) 
1742     s
.PrintfV(pszFormat
, argptr
); 
1746 int wxString::Printf(const wxChar 
*pszFormat
, ...) 
1749     va_start(argptr
, pszFormat
); 
1751     int iLen 
= PrintfV(pszFormat
, argptr
); 
1758 int wxString::PrintfV(const wxChar
* pszFormat
, va_list argptr
) 
1764         wxStringBuffer 
tmp(*this, size 
+ 1); 
1773         // wxVsnprintf() may modify the original arg pointer, so pass it 
1776         wxVaCopy(argptrcopy
, argptr
); 
1777         int len 
= wxVsnprintf(buf
, size
, pszFormat
, argptrcopy
); 
1780         // some implementations of vsnprintf() don't NUL terminate 
1781         // the string if there is not enough space for it so 
1782         // always do it manually 
1783         buf
[size
] = _T('\0'); 
1785         // vsnprintf() may return either -1 (traditional Unix behaviour) or the 
1786         // total number of characters which would have been written if the 
1787         // buffer were large enough (newer standards such as Unix98) 
1790             // still not enough, as we don't know how much we need, double the 
1791             // current size of the buffer 
1794         else if ( len 
> size 
) 
1798         else // ok, there was enough space 
1804     // we could have overshot 
1810 // ---------------------------------------------------------------------------- 
1811 // misc other operations 
1812 // ---------------------------------------------------------------------------- 
1814 // returns true if the string matches the pattern which may contain '*' and 
1815 // '?' metacharacters (as usual, '?' matches any character and '*' any number 
1817 bool wxString::Matches(const wxChar 
*pszMask
) const 
1819     // I disable this code as it doesn't seem to be faster (in fact, it seems 
1820     // to be much slower) than the old, hand-written code below and using it 
1821     // here requires always linking with libregex even if the user code doesn't 
1823 #if 0 // wxUSE_REGEX 
1824     // first translate the shell-like mask into a regex 
1826     pattern
.reserve(wxStrlen(pszMask
)); 
1838                 pattern 
+= _T(".*"); 
1849                 // these characters are special in a RE, quote them 
1850                 // (however note that we don't quote '[' and ']' to allow 
1851                 // using them for Unix shell like matching) 
1852                 pattern 
+= _T('\\'); 
1856                 pattern 
+= *pszMask
; 
1864     return wxRegEx(pattern
, wxRE_NOSUB 
| wxRE_EXTENDED
).Matches(c_str()); 
1865 #else // !wxUSE_REGEX 
1866   // TODO: this is, of course, awfully inefficient... 
1868   // the char currently being checked 
1869   const wxChar 
*pszTxt 
= c_str(); 
1871   // the last location where '*' matched 
1872   const wxChar 
*pszLastStarInText 
= NULL
; 
1873   const wxChar 
*pszLastStarInMask 
= NULL
; 
1876   for ( ; *pszMask 
!= wxT('\0'); pszMask
++, pszTxt
++ ) { 
1877     switch ( *pszMask 
) { 
1879         if ( *pszTxt 
== wxT('\0') ) 
1882         // pszTxt and pszMask will be incremented in the loop statement 
1888           // remember where we started to be able to backtrack later 
1889           pszLastStarInText 
= pszTxt
; 
1890           pszLastStarInMask 
= pszMask
; 
1892           // ignore special chars immediately following this one 
1893           // (should this be an error?) 
1894           while ( *pszMask 
== wxT('*') || *pszMask 
== wxT('?') ) 
1897           // if there is nothing more, match 
1898           if ( *pszMask 
== wxT('\0') ) 
1901           // are there any other metacharacters in the mask? 
1903           const wxChar 
*pEndMask 
= wxStrpbrk(pszMask
, wxT("*?")); 
1905           if ( pEndMask 
!= NULL 
) { 
1906             // we have to match the string between two metachars 
1907             uiLenMask 
= pEndMask 
- pszMask
; 
1910             // we have to match the remainder of the string 
1911             uiLenMask 
= wxStrlen(pszMask
); 
1914           wxString 
strToMatch(pszMask
, uiLenMask
); 
1915           const wxChar
* pMatch 
= wxStrstr(pszTxt
, strToMatch
); 
1916           if ( pMatch 
== NULL 
) 
1919           // -1 to compensate "++" in the loop 
1920           pszTxt 
= pMatch 
+ uiLenMask 
- 1; 
1921           pszMask 
+= uiLenMask 
- 1; 
1926         if ( *pszMask 
!= *pszTxt 
) 
1932   // match only if nothing left 
1933   if ( *pszTxt 
== wxT('\0') ) 
1936   // if we failed to match, backtrack if we can 
1937   if ( pszLastStarInText 
) { 
1938     pszTxt 
= pszLastStarInText 
+ 1; 
1939     pszMask 
= pszLastStarInMask
; 
1941     pszLastStarInText 
= NULL
; 
1943     // don't bother resetting pszLastStarInMask, it's unnecessary 
1949 #endif // wxUSE_REGEX/!wxUSE_REGEX 
1952 // Count the number of chars 
1953 int wxString::Freq(wxChar ch
) const 
1957     for (int i 
= 0; i 
< len
; i
++) 
1959         if (GetChar(i
) == ch
) 
1965 // convert to upper case, return the copy of the string 
1966 wxString 
wxString::Upper() const 
1967 { wxString 
s(*this); return s
.MakeUpper(); } 
1969 // convert to lower case, return the copy of the string 
1970 wxString 
wxString::Lower() const { wxString 
s(*this); return s
.MakeLower(); } 
1972 int wxString::sprintf(const wxChar 
*pszFormat
, ...) 
1975     va_start(argptr
, pszFormat
); 
1976     int iLen 
= PrintfV(pszFormat
, argptr
); 
1981 // ============================================================================ 
1983 // ============================================================================ 
1985 #include "wx/arrstr.h" 
1987 wxArrayString::wxArrayString(size_t sz
, const wxChar
** a
) 
1992     for (size_t i
=0; i 
< sz
; i
++) 
1996 wxArrayString::wxArrayString(size_t sz
, const wxString
* a
) 
2001     for (size_t i
=0; i 
< sz
; i
++) 
2007 // size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT) 
2008 #define   ARRAY_MAXSIZE_INCREMENT       4096 
2010 #ifndef   ARRAY_DEFAULT_INITIAL_SIZE    // also defined in dynarray.h 
2011 #define   ARRAY_DEFAULT_INITIAL_SIZE    (16) 
2014 #define   STRING(p)   ((wxString *)(&(p))) 
2017 void wxArrayString::Init(bool autoSort
) 
2021   m_pItems 
= (wxChar 
**) NULL
; 
2022   m_autoSort 
= autoSort
; 
2026 wxArrayString::wxArrayString(const wxArrayString
& src
) 
2028   Init(src
.m_autoSort
); 
2033 // assignment operator 
2034 wxArrayString
& wxArrayString::operator=(const wxArrayString
& src
) 
2041   m_autoSort 
= src
.m_autoSort
; 
2046 void wxArrayString::Copy(const wxArrayString
& src
) 
2048   if ( src
.m_nCount 
> ARRAY_DEFAULT_INITIAL_SIZE 
) 
2049     Alloc(src
.m_nCount
); 
2051   for ( size_t n 
= 0; n 
< src
.m_nCount
; n
++ ) 
2056 void wxArrayString::Grow(size_t nIncrement
) 
2058   // only do it if no more place 
2059   if ( (m_nSize 
- m_nCount
) < nIncrement 
) { 
2060     // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would 
2061     // be never resized! 
2062     #if ARRAY_DEFAULT_INITIAL_SIZE == 0 
2063       #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!" 
2066     if ( m_nSize 
== 0 ) { 
2067       // was empty, alloc some memory 
2068       m_nSize 
= ARRAY_DEFAULT_INITIAL_SIZE
; 
2069       if (m_nSize 
< nIncrement
) 
2070           m_nSize 
= nIncrement
; 
2071       m_pItems 
= new wxChar 
*[m_nSize
]; 
2074       // otherwise when it's called for the first time, nIncrement would be 0 
2075       // and the array would never be expanded 
2076       // add 50% but not too much 
2077       size_t ndefIncrement 
= m_nSize 
< ARRAY_DEFAULT_INITIAL_SIZE
 
2078                           ? ARRAY_DEFAULT_INITIAL_SIZE 
: m_nSize 
>> 1; 
2079       if ( ndefIncrement 
> ARRAY_MAXSIZE_INCREMENT 
) 
2080         ndefIncrement 
= ARRAY_MAXSIZE_INCREMENT
; 
2081       if ( nIncrement 
< ndefIncrement 
) 
2082         nIncrement 
= ndefIncrement
; 
2083       m_nSize 
+= nIncrement
; 
2084       wxChar 
**pNew 
= new wxChar 
*[m_nSize
]; 
2086       // copy data to new location 
2087       memcpy(pNew
, m_pItems
, m_nCount
*sizeof(wxChar 
*)); 
2089       // delete old memory (but do not release the strings!) 
2090       wxDELETEA(m_pItems
); 
2097 void wxArrayString::Free() 
2099   for ( size_t n 
= 0; n 
< m_nCount
; n
++ ) { 
2100     STRING(m_pItems
[n
])->GetStringData()->Unlock(); 
2104 // deletes all the strings from the list 
2105 void wxArrayString::Empty() 
2112 // as Empty, but also frees memory 
2113 void wxArrayString::Clear() 
2120   wxDELETEA(m_pItems
); 
2124 wxArrayString::~wxArrayString() 
2128   wxDELETEA(m_pItems
); 
2131 void wxArrayString::reserve(size_t nSize
) 
2136 // pre-allocates memory (frees the previous data!) 
2137 void wxArrayString::Alloc(size_t nSize
) 
2139   // only if old buffer was not big enough 
2140   if ( nSize 
> m_nSize 
) { 
2142     wxDELETEA(m_pItems
); 
2143     m_pItems 
= new wxChar 
*[nSize
]; 
2150 // minimizes the memory usage by freeing unused memory 
2151 void wxArrayString::Shrink() 
2153   // only do it if we have some memory to free 
2154   if( m_nCount 
< m_nSize 
) { 
2155     // allocates exactly as much memory as we need 
2156     wxChar 
**pNew 
= new wxChar 
*[m_nCount
]; 
2158     // copy data to new location 
2159     memcpy(pNew
, m_pItems
, m_nCount
*sizeof(wxChar 
*)); 
2165 #if WXWIN_COMPATIBILITY_2_4 
2167 // return a wxString[] as required for some control ctors. 
2168 wxString
* wxArrayString::GetStringArray() const 
2170     wxString 
*array 
= 0; 
2174         array 
= new wxString
[m_nCount
]; 
2175         for( size_t i 
= 0; i 
< m_nCount
; i
++ ) 
2176             array
[i
] = m_pItems
[i
]; 
2182 void wxArrayString::Remove(size_t nIndex
, size_t nRemove
) 
2184     RemoveAt(nIndex
, nRemove
); 
2187 #endif // WXWIN_COMPATIBILITY_2_4 
2189 // searches the array for an item (forward or backwards) 
2190 int wxArrayString::Index(const wxChar 
*sz
, bool bCase
, bool bFromEnd
) const 
2193     // use binary search in the sorted array 
2194     wxASSERT_MSG( bCase 
&& !bFromEnd
, 
2195                   wxT("search parameters ignored for auto sorted array") ); 
2204       res 
= wxStrcmp(sz
, m_pItems
[i
]); 
2216     // use linear search in unsorted array 
2218       if ( m_nCount 
> 0 ) { 
2219         size_t ui 
= m_nCount
; 
2221           if ( STRING(m_pItems
[--ui
])->IsSameAs(sz
, bCase
) ) 
2228       for( size_t ui 
= 0; ui 
< m_nCount
; ui
++ ) { 
2229         if( STRING(m_pItems
[ui
])->IsSameAs(sz
, bCase
) ) 
2238 // add item at the end 
2239 size_t wxArrayString::Add(const wxString
& str
, size_t nInsert
) 
2242     // insert the string at the correct position to keep the array sorted 
2250       res 
= str
.Cmp(m_pItems
[i
]); 
2261     wxASSERT_MSG( lo 
== hi
, wxT("binary search broken") ); 
2263     Insert(str
, lo
, nInsert
); 
2268     wxASSERT( str
.GetStringData()->IsValid() ); 
2272     for (size_t i 
= 0; i 
< nInsert
; i
++) 
2274         // the string data must not be deleted! 
2275         str
.GetStringData()->Lock(); 
2278         m_pItems
[m_nCount 
+ i
] = (wxChar 
*)str
.c_str(); // const_cast 
2280     size_t ret 
= m_nCount
; 
2281     m_nCount 
+= nInsert
; 
2286 // add item at the given position 
2287 void wxArrayString::Insert(const wxString
& str
, size_t nIndex
, size_t nInsert
) 
2289   wxASSERT( str
.GetStringData()->IsValid() ); 
2291   wxCHECK_RET( nIndex 
<= m_nCount
, wxT("bad index in wxArrayString::Insert") ); 
2292   wxCHECK_RET( m_nCount 
<= m_nCount 
+ nInsert
, 
2293                wxT("array size overflow in wxArrayString::Insert") ); 
2297   memmove(&m_pItems
[nIndex 
+ nInsert
], &m_pItems
[nIndex
], 
2298           (m_nCount 
- nIndex
)*sizeof(wxChar 
*)); 
2300   for (size_t i 
= 0; i 
< nInsert
; i
++) 
2302       str
.GetStringData()->Lock(); 
2303       m_pItems
[nIndex 
+ i
] = (wxChar 
*)str
.c_str(); 
2305   m_nCount 
+= nInsert
; 
2308 // range insert (STL 23.2.4.3) 
2310 wxArrayString::insert(iterator it
, const_iterator first
, const_iterator last
) 
2312     const int idx 
= it 
- begin(); 
2317     // reset "it" since it can change inside Grow() 
2320     while ( first 
!= last 
) 
2322         it 
= insert(it
, *first
); 
2324         // insert returns an iterator to the last element inserted but we need 
2325         // insert the next after this one, that is before the next one 
2333 void wxArrayString::SetCount(size_t count
) 
2338     while ( m_nCount 
< count 
) 
2339         m_pItems
[m_nCount
++] = (wxChar 
*)s
.c_str(); 
2342 // removes item from array (by index) 
2343 void wxArrayString::RemoveAt(size_t nIndex
, size_t nRemove
) 
2345   wxCHECK_RET( nIndex 
< m_nCount
, wxT("bad index in wxArrayString::Remove") ); 
2346   wxCHECK_RET( nIndex 
+ nRemove 
<= m_nCount
, 
2347                wxT("removing too many elements in wxArrayString::Remove") ); 
2350   for (size_t i 
= 0; i 
< nRemove
; i
++) 
2351       Item(nIndex 
+ i
).GetStringData()->Unlock(); 
2353   memmove(&m_pItems
[nIndex
], &m_pItems
[nIndex 
+ nRemove
], 
2354           (m_nCount 
- nIndex 
- nRemove
)*sizeof(wxChar 
*)); 
2355   m_nCount 
-= nRemove
; 
2358 // removes item from array (by value) 
2359 void wxArrayString::Remove(const wxChar 
*sz
) 
2361   int iIndex 
= Index(sz
); 
2363   wxCHECK_RET( iIndex 
!= wxNOT_FOUND
, 
2364                wxT("removing inexistent element in wxArrayString::Remove") ); 
2369 void wxArrayString::assign(const_iterator first
, const_iterator last
) 
2371     reserve(last 
- first
); 
2372     for(; first 
!= last
; ++first
) 
2376 // ---------------------------------------------------------------------------- 
2378 // ---------------------------------------------------------------------------- 
2380 // we can only sort one array at a time with the quick-sort based 
2383   // need a critical section to protect access to gs_compareFunction and 
2384   // gs_sortAscending variables 
2385   static wxCriticalSection gs_critsectStringSort
; 
2386 #endif // wxUSE_THREADS 
2388 // function to use for string comparaison 
2389 static wxArrayString::CompareFunction gs_compareFunction 
= NULL
; 
2391 // if we don't use the compare function, this flag tells us if we sort the 
2392 // array in ascending or descending order 
2393 static bool gs_sortAscending 
= true; 
2395 // function which is called by quick sort 
2396 extern "C" int wxC_CALLING_CONV     
// LINKAGEMODE 
2397 wxStringCompareFunction(const void *first
, const void *second
) 
2399   wxString 
*strFirst 
= (wxString 
*)first
; 
2400   wxString 
*strSecond 
= (wxString 
*)second
; 
2402   if ( gs_compareFunction 
) { 
2403     return gs_compareFunction(*strFirst
, *strSecond
); 
2406     // maybe we should use wxStrcoll 
2407     int result 
= strFirst
->Cmp(*strSecond
); 
2409     return gs_sortAscending 
? result 
: -result
; 
2413 // sort array elements using passed comparaison function 
2414 void wxArrayString::Sort(CompareFunction compareFunction
) 
2416   wxCRIT_SECT_LOCKER(lockCmpFunc
, gs_critsectStringSort
); 
2418   wxASSERT( !gs_compareFunction 
);  // must have been reset to NULL 
2419   gs_compareFunction 
= compareFunction
; 
2423   // reset it to NULL so that Sort(bool) will work the next time 
2424   gs_compareFunction 
= NULL
; 
2429     typedef int (wxC_CALLING_CONV 
* wxStringCompareFn
)(const void *first
, 
2430                                                        const void *second
); 
2433 void wxArrayString::Sort(CompareFunction2 compareFunction
) 
2435   qsort(m_pItems
, m_nCount
, sizeof(wxChar 
*), (wxStringCompareFn
)compareFunction
); 
2438 void wxArrayString::Sort(bool reverseOrder
) 
2440   Sort(reverseOrder 
? wxStringSortDescending 
: wxStringSortAscending
); 
2443 void wxArrayString::DoSort() 
2445   wxCHECK_RET( !m_autoSort
, wxT("can't use this method with sorted arrays") ); 
2447   // just sort the pointers using qsort() - of course it only works because 
2448   // wxString() *is* a pointer to its data 
2449   qsort(m_pItems
, m_nCount
, sizeof(wxChar 
*), wxStringCompareFunction
); 
2452 bool wxArrayString::operator==(const wxArrayString
& a
) const 
2454     if ( m_nCount 
!= a
.m_nCount 
) 
2457     for ( size_t n 
= 0; n 
< m_nCount
; n
++ ) 
2459         if ( Item(n
) != a
[n
] ) 
2466 #endif // !wxUSE_STL 
2468 int wxCMPFUNC_CONV 
wxStringSortAscending(wxString
* s1
, wxString
* s2
) 
2470     return  s1
->Cmp(*s2
); 
2473 int wxCMPFUNC_CONV 
wxStringSortDescending(wxString
* s1
, wxString
* s2
) 
2475     return -s1
->Cmp(*s2
);