1 ///////////////////////////////////////////////////////////////////////////// 
   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" 
  33   #include "wx/string.h" 
  35   #include "wx/thread.h" 
  50 // allocating extra space for each string consumes more memory but speeds up 
  51 // the concatenation operations (nLen is the current string's length) 
  52 // NB: EXTRA_ALLOC must be >= 0! 
  53 #define EXTRA_ALLOC       (19 - nLen % 16) 
  55 // --------------------------------------------------------------------------- 
  56 // static class variables definition 
  57 // --------------------------------------------------------------------------- 
  60   //According to STL _must_ be a -1 size_t 
  61   const size_t wxStringBase::npos 
= (size_t) -1; 
  64 // ---------------------------------------------------------------------------- 
  66 // ---------------------------------------------------------------------------- 
  70 extern const wxChar WXDLLIMPEXP_BASE 
*wxEmptyString 
= _T(""); 
  74 // for an empty string, GetStringData() will return this address: this 
  75 // structure has the same layout as wxStringData and it's data() method will 
  76 // return the empty string (dummy pointer) 
  81 } g_strEmpty 
= { {-1, 0, 0}, wxT('\0') }; 
  83 // empty C style string: points to 'string data' byte of g_strEmpty 
  84 extern const wxChar WXDLLIMPEXP_BASE 
*wxEmptyString 
= &g_strEmpty
.dummy
; 
  88 // ---------------------------------------------------------------------------- 
  90 // ---------------------------------------------------------------------------- 
  92 #if wxUSE_STD_IOSTREAM 
  94 // MS Visual C++ version 5.0 provides the new STL headers as well as the old 
  97 // ATTN: you can _not_ use both of these in the same program! 
 101 wxSTD istream
& operator>>(wxSTD istream
& is
, wxString
& WXUNUSED(str
)) 
 106     streambuf 
*sb 
= is
.rdbuf(); 
 109       int ch 
= sb
->sbumpc (); 
 111         is
.setstate(ios::eofbit
); 
 114       else if ( isspace(ch
) ) { 
 126   if ( str
.length() == 0 ) 
 127     is
.setstate(ios::failbit
); 
 132 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxString
& str
) 
 138 #endif // wxUSE_STD_IOSTREAM 
 140 // ---------------------------------------------------------------------------- 
 142 // ---------------------------------------------------------------------------- 
 144 // this small class is used to gather statistics for performance tuning 
 145 //#define WXSTRING_STATISTICS 
 146 #ifdef  WXSTRING_STATISTICS 
 150     Averager(const wxChar 
*sz
) { m_sz 
= sz
; m_nTotal 
= m_nCount 
= 0; } 
 152    { wxPrintf("wxString: average %s = %f\n", m_sz
, ((float)m_nTotal
)/m_nCount
); } 
 154     void Add(size_t n
) { m_nTotal 
+= n
; m_nCount
++; } 
 157     size_t m_nCount
, m_nTotal
; 
 159   } g_averageLength("allocation size"), 
 160     g_averageSummandLength("summand length"), 
 161     g_averageConcatHit("hit probability in concat"), 
 162     g_averageInitialLength("initial string length"); 
 164   #define STATISTICS_ADD(av, val) g_average##av.Add(val) 
 166   #define STATISTICS_ADD(av, val) 
 167 #endif // WXSTRING_STATISTICS 
 171 // =========================================================================== 
 172 // wxStringData class deallocation 
 173 // =========================================================================== 
 175 #if defined(__VISUALC__) && defined(_MT) && !defined(_DLL) 
 176 #  pragma message (__FILE__ ": building with Multithreaded non DLL runtime has a performance impact on wxString!") 
 177 void wxStringData::Free() 
 183 // =========================================================================== 
 185 // =========================================================================== 
 187 // takes nLength elements of psz starting at nPos 
 188 void wxStringBase::InitWith(const wxChar 
*psz
, size_t nPos
, size_t nLength
) 
 192   // if the length is not given, assume the string to be NUL terminated 
 193   if ( nLength 
== npos 
) { 
 194     wxASSERT_MSG( nPos 
<= wxStrlen(psz
), _T("index out of bounds") ); 
 196     nLength 
= wxStrlen(psz 
+ nPos
); 
 199   STATISTICS_ADD(InitialLength
, nLength
); 
 202     // trailing '\0' is written in AllocBuffer() 
 203     if ( !AllocBuffer(nLength
) ) { 
 204       wxFAIL_MSG( _T("out of memory in wxStringBase::InitWith") ); 
 207     wxTmemcpy(m_pchData
, psz 
+ nPos
, nLength
); 
 211 // poor man's iterators are "void *" pointers 
 212 wxStringBase::wxStringBase(const void *pStart
, const void *pEnd
) 
 214   InitWith((const wxChar 
*)pStart
, 0, 
 215            (const wxChar 
*)pEnd 
- (const wxChar 
*)pStart
); 
 218 wxStringBase::wxStringBase(size_type n
, wxChar ch
) 
 224 // --------------------------------------------------------------------------- 
 226 // --------------------------------------------------------------------------- 
 228 // allocates memory needed to store a C string of length nLen 
 229 bool wxStringBase::AllocBuffer(size_t nLen
) 
 231   // allocating 0 sized buffer doesn't make sense, all empty strings should 
 233   wxASSERT( nLen 
>  0 ); 
 235   // make sure that we don't overflow 
 236   wxASSERT( nLen 
< (INT_MAX 
/ sizeof(wxChar
)) - 
 237                    (sizeof(wxStringData
) + EXTRA_ALLOC 
+ 1) ); 
 239   STATISTICS_ADD(Length
, nLen
); 
 242   // 1) one extra character for '\0' termination 
 243   // 2) sizeof(wxStringData) for housekeeping info 
 244   wxStringData
* pData 
= (wxStringData
*) 
 245     malloc(sizeof(wxStringData
) + (nLen 
+ EXTRA_ALLOC 
+ 1)*sizeof(wxChar
)); 
 247   if ( pData 
== NULL 
) { 
 248     // allocation failures are handled by the caller 
 253   pData
->nDataLength  
= nLen
; 
 254   pData
->nAllocLength 
= nLen 
+ EXTRA_ALLOC
; 
 255   m_pchData           
= pData
->data();  // data starts after wxStringData 
 256   m_pchData
[nLen
]     = wxT('\0'); 
 260 // must be called before changing this string 
 261 bool wxStringBase::CopyBeforeWrite() 
 263   wxStringData
* pData 
= GetStringData(); 
 265   if ( pData
->IsShared() ) { 
 266     pData
->Unlock();                // memory not freed because shared 
 267     size_t nLen 
= pData
->nDataLength
; 
 268     if ( !AllocBuffer(nLen
) ) { 
 269       // allocation failures are handled by the caller 
 272     wxTmemcpy(m_pchData
, pData
->data(), nLen
); 
 275   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner 
 280 // must be called before replacing contents of this string 
 281 bool wxStringBase::AllocBeforeWrite(size_t nLen
) 
 283   wxASSERT( nLen 
!= 0 );  // doesn't make any sense 
 285   // must not share string and must have enough space 
 286   wxStringData
* pData 
= GetStringData(); 
 287   if ( pData
->IsShared() || pData
->IsEmpty() ) { 
 288     // can't work with old buffer, get new one 
 290     if ( !AllocBuffer(nLen
) ) { 
 291       // allocation failures are handled by the caller 
 296     if ( nLen 
> pData
->nAllocLength 
) { 
 297       // realloc the buffer instead of calling malloc() again, this is more 
 299       STATISTICS_ADD(Length
, nLen
); 
 303       pData 
= (wxStringData
*) 
 304           realloc(pData
, sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 306       if ( pData 
== NULL 
) { 
 307         // allocation failures are handled by the caller 
 308         // keep previous data since reallocation failed 
 312       pData
->nAllocLength 
= nLen
; 
 313       m_pchData 
= pData
->data(); 
 317   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner 
 319   // it doesn't really matter what the string length is as it's going to be 
 320   // overwritten later but, for extra safety, set it to 0 for now as we may 
 321   // have some junk in m_pchData 
 322   GetStringData()->nDataLength 
= 0; 
 327 wxStringBase
& wxStringBase::append(size_t n
, wxChar ch
) 
 329     size_type len 
= length(); 
 331     if ( !Alloc(len 
+ n
) || !CopyBeforeWrite() ) { 
 332       wxFAIL_MSG( _T("out of memory in wxStringBase::append") ); 
 334     GetStringData()->nDataLength 
= len 
+ n
; 
 335     m_pchData
[len 
+ n
] = '\0'; 
 336     for ( size_t i 
= 0; i 
< n
; ++i 
) 
 337         m_pchData
[len 
+ i
] = ch
; 
 341 void wxStringBase::resize(size_t nSize
, wxChar ch
) 
 343     size_t len 
= length(); 
 347         erase(begin() + nSize
, end()); 
 349     else if ( nSize 
> len 
) 
 351         append(nSize 
- len
, ch
); 
 353     //else: we have exactly the specified length, nothing to do 
 356 // allocate enough memory for nLen characters 
 357 bool wxStringBase::Alloc(size_t nLen
) 
 359   wxStringData 
*pData 
= GetStringData(); 
 360   if ( pData
->nAllocLength 
<= nLen 
) { 
 361     if ( pData
->IsEmpty() ) { 
 364       wxStringData
* pData 
= (wxStringData
*) 
 365           malloc(sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 367       if ( pData 
== NULL 
) { 
 368         // allocation failure handled by caller 
 373       pData
->nDataLength 
= 0; 
 374       pData
->nAllocLength 
= nLen
; 
 375       m_pchData 
= pData
->data();  // data starts after wxStringData 
 376       m_pchData
[0u] = wxT('\0'); 
 378     else if ( pData
->IsShared() ) { 
 379       pData
->Unlock();                // memory not freed because shared 
 380       size_t nOldLen 
= pData
->nDataLength
; 
 381       if ( !AllocBuffer(nLen
) ) { 
 382         // allocation failure handled by caller 
 385       // +1 to copy the terminator, too 
 386       memcpy(m_pchData
, pData
->data(), (nOldLen
+1)*sizeof(wxChar
)); 
 387       GetStringData()->nDataLength 
= nOldLen
; 
 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 ( !Alloc(length() + n
) || !CopyBeforeWrite() ) { 
 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() ); 
 478   const wxChar
* p 
= (const wxChar
*)wxTmemchr(c_str() + nStart
, 
 485   while(p 
- c_str() + str
.length() <= length() && 
 486         wxTmemcmp(p
, str
.c_str(), str
.length()) ) 
 488       //Previosly passed as the first argument to wxTmemchr, 
 489       //but C/C++ standard does not specify evaluation order 
 490       //of arguments to functions - 
 491       //http://embedded.com/showArticle.jhtml?articleID=9900607 
 495       p 
= (const wxChar
*)wxTmemchr(p
, 
 497                                   length() - (p 
- c_str())); 
 503    return (p 
- c_str() + str
.length() <= length()) ? p 
- c_str() : npos
; 
 506 size_t wxStringBase::find(const wxChar
* sz
, size_t nStart
, size_t n
) const 
 508   return find(wxStringBase(sz
, n
), nStart
); 
 511 size_t wxStringBase::find(wxChar ch
, size_t nStart
) const 
 513   wxASSERT( nStart 
<= length() ); 
 515   const wxChar 
*p 
= (const wxChar
*)wxTmemchr(c_str() + nStart
, ch
, length() - nStart
); 
 517   return p 
== NULL 
? npos 
: p 
- c_str(); 
 520 size_t wxStringBase::rfind(const wxStringBase
& str
, size_t nStart
) const 
 522     wxASSERT( str
.GetStringData()->IsValid() ); 
 523     wxASSERT( nStart 
== npos 
|| nStart 
<= length() ); 
 525     if ( length() >= str
.length() ) 
 527         // avoids a corner case later 
 528         if ( length() == 0 && str
.length() == 0 ) 
 531         // "top" is the point where search starts from 
 532         size_t top 
= length() - str
.length(); 
 534         if ( nStart 
== npos 
) 
 535             nStart 
= length() - 1; 
 539         const wxChar 
*cursor 
= c_str() + top
; 
 542             if ( wxTmemcmp(cursor
, str
.c_str(), 
 545                 return cursor 
- c_str(); 
 547         } while ( cursor
-- > c_str() ); 
 553 size_t wxStringBase::rfind(const wxChar
* sz
, size_t nStart
, size_t n
) const 
 555     return rfind(wxStringBase(sz
, n
), nStart
); 
 558 size_t wxStringBase::rfind(wxChar ch
, size_t nStart
) const 
 560     if ( nStart 
== npos 
) 
 566         wxASSERT( nStart 
<= length() ); 
 569     const wxChar 
*actual
; 
 570     for ( actual 
= c_str() + ( nStart 
== npos 
? length() : nStart 
+ 1 ); 
 571           actual 
> c_str(); --actual 
) 
 573         if ( *(actual 
- 1) == ch 
) 
 574             return (actual 
- 1) - c_str(); 
 580 size_t wxStringBase::find_first_of(const wxChar
* sz
, size_t nStart
) const 
 582     wxASSERT(nStart 
<= length()); 
 584     size_t len 
= wxStrlen(sz
); 
 587     for(i 
= nStart
; i 
< this->length(); ++i
) 
 589         if (wxTmemchr(sz
, *(c_str() + i
), len
)) 
 593     if(i 
== this->length()) 
 599 size_t wxStringBase::find_first_of(const wxChar
* sz
, size_t nStart
, 
 602     return find_first_of(wxStringBase(sz
, n
), nStart
); 
 605 size_t wxStringBase::find_last_of(const wxChar
* sz
, size_t nStart
) const 
 607     if ( nStart 
== npos 
) 
 609         nStart 
= length() - 1; 
 613         wxASSERT_MSG( nStart 
<= length(), 
 614                         _T("invalid index in find_last_of()") ); 
 617     size_t len 
= wxStrlen(sz
); 
 619     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 621         if ( wxTmemchr(sz
, *p
, len
) ) 
 628 size_t wxStringBase::find_last_of(const wxChar
* sz
, size_t nStart
, 
 631     return find_last_of(wxStringBase(sz
, n
), nStart
); 
 634 size_t wxStringBase::find_first_not_of(const wxChar
* sz
, size_t nStart
) const 
 636     if ( nStart 
== npos 
) 
 642         wxASSERT( nStart 
<= length() ); 
 645     size_t len 
= wxStrlen(sz
); 
 648     for(i 
= nStart
; i 
< this->length(); ++i
) 
 650         if (!wxTmemchr(sz
, *(c_str() + i
), len
)) 
 654     if(i 
== this->length()) 
 660 size_t wxStringBase::find_first_not_of(const wxChar
* sz
, size_t nStart
, 
 663     return find_first_not_of(wxStringBase(sz
, n
), nStart
); 
 666 size_t wxStringBase::find_first_not_of(wxChar ch
, size_t nStart
) const 
 668     wxASSERT( nStart 
<= length() ); 
 670     for ( const wxChar 
*p 
= c_str() + nStart
; *p
; p
++ ) 
 679 size_t wxStringBase::find_last_not_of(const wxChar
* sz
, size_t nStart
) const 
 681     if ( nStart 
== npos 
) 
 683         nStart 
= length() - 1; 
 687         wxASSERT( nStart 
<= length() ); 
 690     size_t len 
= wxStrlen(sz
); 
 692     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 694         if ( !wxTmemchr(sz
, *p
,len
) ) 
 701 size_t wxStringBase::find_last_not_of(const wxChar
* sz
, size_t nStart
, 
 704     return find_last_not_of(wxStringBase(sz
, n
), nStart
); 
 707 size_t wxStringBase::find_last_not_of(wxChar ch
, size_t nStart
) const 
 709     if ( nStart 
== npos 
) 
 711         nStart 
= length() - 1; 
 715         wxASSERT( nStart 
<= length() ); 
 718     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 727 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 730   wxASSERT_MSG( nStart 
<= length(), 
 731                 _T("index out of bounds in wxStringBase::replace") ); 
 732   size_t strLen 
= length() - nStart
; 
 733   nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 736   strTmp
.reserve(length()); // micro optimisation to avoid multiple mem allocs 
 739     strTmp
.append(c_str(), nStart
); 
 741   strTmp
.append(c_str() + nStart 
+ nLen
); 
 747 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 748                                     size_t nCount
, wxChar ch
) 
 750   return replace(nStart
, nLen
, wxStringBase(nCount
, ch
).c_str()); 
 753 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 754                                     const wxStringBase
& str
, 
 755                                     size_t nStart2
, size_t nLen2
) 
 757   return replace(nStart
, nLen
, str
.substr(nStart2
, nLen2
)); 
 760 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 761                                     const wxChar
* sz
, size_t nCount
) 
 763   return replace(nStart
, nLen
, wxStringBase(sz
, nCount
).c_str()); 
 766 wxStringBase 
wxStringBase::substr(size_t nStart
, size_t nLen
) const 
 769     nLen 
= length() - nStart
; 
 770   return wxStringBase(*this, nStart
, nLen
); 
 773 // assigns one string to another 
 774 wxStringBase
& wxStringBase::operator=(const wxStringBase
& stringSrc
) 
 776   wxASSERT( stringSrc
.GetStringData()->IsValid() ); 
 778   // don't copy string over itself 
 779   if ( m_pchData 
!= stringSrc
.m_pchData 
) { 
 780     if ( stringSrc
.GetStringData()->IsEmpty() ) { 
 785       GetStringData()->Unlock(); 
 786       m_pchData 
= stringSrc
.m_pchData
; 
 787       GetStringData()->Lock(); 
 794 // assigns a single character 
 795 wxStringBase
& wxStringBase::operator=(wxChar ch
) 
 797   if ( !AssignCopy(1, &ch
) ) { 
 798     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") ); 
 804 wxStringBase
& wxStringBase::operator=(const wxChar 
*psz
) 
 806   if ( !AssignCopy(wxStrlen(psz
), psz
) ) { 
 807     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") ); 
 812 // helper function: does real copy 
 813 bool wxStringBase::AssignCopy(size_t nSrcLen
, const wxChar 
*pszSrcData
) 
 815   if ( nSrcLen 
== 0 ) { 
 819     if ( !AllocBeforeWrite(nSrcLen
) ) { 
 820       // allocation failure handled by caller 
 823     memcpy(m_pchData
, pszSrcData
, nSrcLen
*sizeof(wxChar
)); 
 824     GetStringData()->nDataLength 
= nSrcLen
; 
 825     m_pchData
[nSrcLen
] = wxT('\0'); 
 830 // --------------------------------------------------------------------------- 
 831 // string concatenation 
 832 // --------------------------------------------------------------------------- 
 834 // add something to this string 
 835 bool wxStringBase::ConcatSelf(size_t nSrcLen
, const wxChar 
*pszSrcData
, 
 838   STATISTICS_ADD(SummandLength
, nSrcLen
); 
 840   nSrcLen 
= nSrcLen 
< nMaxLen 
? nSrcLen 
: nMaxLen
; 
 842   // concatenating an empty string is a NOP 
 844     wxStringData 
*pData 
= GetStringData(); 
 845     size_t nLen 
= pData
->nDataLength
; 
 846     size_t nNewLen 
= nLen 
+ nSrcLen
; 
 848     // alloc new buffer if current is too small 
 849     if ( pData
->IsShared() ) { 
 850       STATISTICS_ADD(ConcatHit
, 0); 
 852       // we have to allocate another buffer 
 853       wxStringData
* pOldData 
= GetStringData(); 
 854       if ( !AllocBuffer(nNewLen
) ) { 
 855           // allocation failure handled by caller 
 858       memcpy(m_pchData
, pOldData
->data(), nLen
*sizeof(wxChar
)); 
 861     else if ( nNewLen 
> pData
->nAllocLength 
) { 
 862       STATISTICS_ADD(ConcatHit
, 0); 
 865       // we have to grow the buffer 
 866       if ( capacity() < nNewLen 
) { 
 867           // allocation failure handled by caller 
 872       STATISTICS_ADD(ConcatHit
, 1); 
 874       // the buffer is already big enough 
 877     // should be enough space 
 878     wxASSERT( nNewLen 
<= GetStringData()->nAllocLength 
); 
 880     // fast concatenation - all is done in our buffer 
 881     memcpy(m_pchData 
+ nLen
, pszSrcData
, nSrcLen
*sizeof(wxChar
)); 
 883     m_pchData
[nNewLen
] = wxT('\0');          // put terminating '\0' 
 884     GetStringData()->nDataLength 
= nNewLen
; // and fix the length 
 886   //else: the string to append was empty 
 890 // --------------------------------------------------------------------------- 
 891 // simple sub-string extraction 
 892 // --------------------------------------------------------------------------- 
 894 // helper function: clone the data attached to this string 
 895 bool wxStringBase::AllocCopy(wxString
& dest
, int nCopyLen
, int nCopyIndex
) const 
 897   if ( nCopyLen 
== 0 ) { 
 901     if ( !dest
.AllocBuffer(nCopyLen
) ) { 
 902       // allocation failure handled by caller 
 905     memcpy(dest
.m_pchData
, m_pchData 
+ nCopyIndex
, nCopyLen
*sizeof(wxChar
)); 
 912 #if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE) 
 915     #define STRINGCLASS wxStringBase 
 917     #define STRINGCLASS wxString 
 920 static inline int wxDoCmp(const wxChar
* s1
, size_t l1
, 
 921                           const wxChar
* s2
, size_t l2
) 
 924         return wxTmemcmp(s1
, s2
, l1
); 
 927         int ret 
= wxTmemcmp(s1
, s2
, l1
); 
 928         return ret 
== 0 ? -1 : ret
; 
 932         int ret 
= wxTmemcmp(s1
, s2
, l2
); 
 933         return ret 
== 0 ? +1 : ret
; 
 937 int STRINGCLASS::compare(const wxStringBase
& str
) const 
 939     return ::wxDoCmp(data(), length(), str
.data(), str
.length()); 
 942 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 943                          const wxStringBase
& str
) const 
 945     wxASSERT(nStart 
<= length()); 
 946     size_type strLen 
= length() - nStart
; 
 947     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 948     return ::wxDoCmp(data() + nStart
, nLen
, str
.data(), str
.length()); 
 951 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 952                          const wxStringBase
& str
, 
 953                          size_t nStart2
, size_t nLen2
) const 
 955     wxASSERT(nStart 
<= length()); 
 956     wxASSERT(nStart2 
<= str
.length()); 
 957     size_type strLen  
=     length() - nStart
, 
 958               strLen2 
= str
.length() - nStart2
; 
 959     nLen  
= strLen  
< nLen  
? strLen  
: nLen
; 
 960     nLen2 
= strLen2 
< nLen2 
? strLen2 
: nLen2
; 
 961     return ::wxDoCmp(data() + nStart
, nLen
, str
.data() + nStart2
, nLen2
); 
 964 int STRINGCLASS::compare(const wxChar
* sz
) const 
 966     size_t nLen 
= wxStrlen(sz
); 
 967     return ::wxDoCmp(data(), length(), sz
, nLen
); 
 970 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 971                          const wxChar
* sz
, size_t nCount
) const 
 973     wxASSERT(nStart 
<= length()); 
 974     size_type strLen 
= length() - nStart
; 
 975     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 977         nCount 
= wxStrlen(sz
); 
 979     return ::wxDoCmp(data() + nStart
, nLen
, sz
, nCount
); 
 984 #endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE) 
 986 // =========================================================================== 
 987 // wxString class core 
 988 // =========================================================================== 
 990 // --------------------------------------------------------------------------- 
 991 // construction and conversion 
 992 // --------------------------------------------------------------------------- 
 996 // from multibyte string 
 997 wxString::wxString(const char *psz
, wxMBConv
& conv
, size_t nLength
) 
 999     // if nLength != npos, then we have to make a NULL-terminated copy 
1000     // of first nLength bytes of psz first because the input buffer to MB2WC 
1001     // must always be NULL-terminated: 
1002     wxCharBuffer 
inBuf((const char *)NULL
); 
1003     if (nLength 
!= npos
) 
1005         wxASSERT( psz 
!= NULL 
); 
1006         wxCharBuffer 
tmp(nLength
); 
1007         memcpy(tmp
.data(), psz
, nLength
); 
1008         tmp
.data()[nLength
] = '\0'; 
1013     // first get the size of the buffer we need 
1017         // calculate the needed size ourselves or use the provided one 
1018         if (nLength 
== npos
) 
1025         // nothing to convert 
1031     if ( (nLen 
!= 0) && (nLen 
!= (size_t)-1) ) 
1035         wxWCharBuffer theBuffer 
= conv
.cMB2WC(psz
, nLen
, &nRealSize
); 
1039             assign( theBuffer
.data() , nRealSize 
- 1 ); 
1043 //Convert wxString in Unicode mode to a multi-byte string 
1044 const wxCharBuffer 
wxString::mb_str(wxMBConv
& conv
) const 
1047     return conv
.cWC2MB(c_str(), length(), &dwOutSize
); 
1054 wxString::wxString(const wchar_t *pwz
, wxMBConv
& conv
, size_t nLength
) 
1056     // if nLength != npos, then we have to make a NULL-terminated copy 
1057     // of first nLength chars of psz first because the input buffer to WC2MB 
1058     // must always be NULL-terminated: 
1059     wxWCharBuffer 
inBuf((const wchar_t *)NULL
); 
1060     if (nLength 
!= npos
) 
1062         wxASSERT( pwz 
!= NULL 
); 
1063         wxWCharBuffer 
tmp(nLength
); 
1064         memcpy(tmp
.data(), pwz
, nLength 
* sizeof(wchar_t)); 
1065         tmp
.data()[nLength
] = '\0'; 
1070     // first get the size of the buffer we need 
1074         // calculate the needed size ourselves or use the provided one 
1075         if (nLength 
== npos
) 
1076             nLen 
= wxWcslen(pwz
); 
1082         // nothing to convert 
1087     if ( (nLen 
!= 0) && (nLen 
!= (size_t)-1) ) 
1091         wxCharBuffer theBuffer 
= conv
.cWC2MB(pwz
, nLen
, &nRealSize
); 
1095             assign( theBuffer
.data() , nRealSize 
- 1 ); 
1099 //Converts this string to a wide character string if unicode 
1100 //mode is not enabled and wxUSE_WCHAR_T is enabled 
1101 const wxWCharBuffer 
wxString::wc_str(wxMBConv
& conv
) const 
1104     return conv
.cMB2WC(c_str(), length(), &dwOutSize
); 
1107 #endif // wxUSE_WCHAR_T 
1109 #endif // Unicode/ANSI 
1111 // shrink to minimal size (releasing extra memory) 
1112 bool wxString::Shrink() 
1114   wxString 
tmp(begin(), end()); 
1116   return tmp
.length() == length(); 
1120 // get the pointer to writable buffer of (at least) nLen bytes 
1121 wxChar 
*wxString::GetWriteBuf(size_t nLen
) 
1123   if ( !AllocBeforeWrite(nLen
) ) { 
1124     // allocation failure handled by caller 
1128   wxASSERT( GetStringData()->nRefs 
== 1 ); 
1129   GetStringData()->Validate(false); 
1134 // put string back in a reasonable state after GetWriteBuf 
1135 void wxString::UngetWriteBuf() 
1137   GetStringData()->nDataLength 
= wxStrlen(m_pchData
); 
1138   GetStringData()->Validate(true); 
1141 void wxString::UngetWriteBuf(size_t nLen
) 
1143   GetStringData()->nDataLength 
= nLen
; 
1144   GetStringData()->Validate(true); 
1148 // --------------------------------------------------------------------------- 
1150 // --------------------------------------------------------------------------- 
1152 // all functions are inline in string.h 
1154 // --------------------------------------------------------------------------- 
1155 // assignment operators 
1156 // --------------------------------------------------------------------------- 
1160 // same as 'signed char' variant 
1161 wxString
& wxString::operator=(const unsigned char* psz
) 
1163   *this = (const char *)psz
; 
1168 wxString
& wxString::operator=(const wchar_t *pwz
) 
1179  * concatenation functions come in 5 flavours: 
1181  *  char   + string      and      string + char 
1182  *  C str  + string      and      string + C str 
1185 wxString 
operator+(const wxString
& str1
, const wxString
& str2
) 
1188   wxASSERT( str1
.GetStringData()->IsValid() ); 
1189   wxASSERT( str2
.GetStringData()->IsValid() ); 
1198 wxString 
operator+(const wxString
& str
, wxChar ch
) 
1201   wxASSERT( str
.GetStringData()->IsValid() ); 
1210 wxString 
operator+(wxChar ch
, const wxString
& str
) 
1213   wxASSERT( str
.GetStringData()->IsValid() ); 
1222 wxString 
operator+(const wxString
& str
, const wxChar 
*psz
) 
1225   wxASSERT( str
.GetStringData()->IsValid() ); 
1229   if ( !s
.Alloc(wxStrlen(psz
) + str
.Len()) ) { 
1230     wxFAIL_MSG( _T("out of memory in wxString::operator+") ); 
1238 wxString 
operator+(const wxChar 
*psz
, const wxString
& str
) 
1241   wxASSERT( str
.GetStringData()->IsValid() ); 
1245   if ( !s
.Alloc(wxStrlen(psz
) + str
.Len()) ) { 
1246     wxFAIL_MSG( _T("out of memory in wxString::operator+") ); 
1254 // =========================================================================== 
1255 // other common string functions 
1256 // =========================================================================== 
1258 int wxString::Cmp(const wxString
& s
) const 
1263 int wxString::Cmp(const wxChar
* psz
) const 
1265     return compare(psz
); 
1268 static inline int wxDoCmpNoCase(const wxChar
* s1
, size_t l1
, 
1269                                 const wxChar
* s2
, size_t l2
) 
1275         for(i 
= 0; i 
< l1
; ++i
) 
1277             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1280         return i 
== l1 
? 0 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1284         for(i 
= 0; i 
< l1
; ++i
) 
1286             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1289         return i 
== l1 
? -1 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1293         for(i 
= 0; i 
< l2
; ++i
) 
1295             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1298         return i 
== l2 
? 1 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1302 int wxString::CmpNoCase(const wxString
& s
) const 
1304     return wxDoCmpNoCase(data(), length(), s
.data(), s
.length()); 
1307 int wxString::CmpNoCase(const wxChar
* psz
) const 
1309     int nLen 
= wxStrlen(psz
); 
1311     return wxDoCmpNoCase(data(), length(), psz
, nLen
); 
1318 #ifndef __SCHAR_MAX__ 
1319 #define __SCHAR_MAX__ 127 
1323 wxString 
wxString::FromAscii(const char *ascii
) 
1326        return wxEmptyString
; 
1328     size_t len 
= strlen( ascii 
); 
1333         wxStringBuffer 
buf(res
, len
); 
1335         wchar_t *dest 
= buf
; 
1339            if ( (*dest
++ = (wchar_t)(unsigned char)*ascii
++) == L
'\0' ) 
1347 wxString 
wxString::FromAscii(const char ascii
) 
1349     // What do we do with '\0' ? 
1352     res 
+= (wchar_t)(unsigned char) ascii
; 
1357 const wxCharBuffer 
wxString::ToAscii() const 
1359     // this will allocate enough space for the terminating NUL too 
1360     wxCharBuffer 
buffer(length()); 
1363     char *dest 
= buffer
.data(); 
1365     const wchar_t *pwc 
= c_str(); 
1368         *dest
++ = (char)(*pwc 
> SCHAR_MAX 
? wxT('_') : *pwc
); 
1370         // the output string can't have embedded NULs anyhow, so we can safely 
1371         // stop at first of them even if we do have any 
1381 // extract string of length nCount starting at nFirst 
1382 wxString 
wxString::Mid(size_t nFirst
, size_t nCount
) const 
1384   size_t nLen 
= length(); 
1386   // default value of nCount is npos and means "till the end" 
1387   if ( nCount 
== npos 
) 
1389     nCount 
= nLen 
- nFirst
; 
1392   // out-of-bounds requests return sensible things 
1393   if ( nFirst 
+ nCount 
> nLen 
) 
1395     nCount 
= nLen 
- nFirst
; 
1398   if ( nFirst 
> nLen 
) 
1400     // AllocCopy() will return empty string 
1404   wxString 
dest(*this, nFirst
, nCount
); 
1405   if ( dest
.length() != nCount 
) { 
1406       wxFAIL_MSG( _T("out of memory in wxString::Mid") ); 
1412 // check that the string starts with prefix and return the rest of the string 
1413 // in the provided pointer if it is not NULL, otherwise return false 
1414 bool wxString::StartsWith(const wxChar 
*prefix
, wxString 
*rest
) const 
1416     wxASSERT_MSG( prefix
, _T("invalid parameter in wxString::StartsWith") ); 
1418     // first check if the beginning of the string matches the prefix: note 
1419     // that we don't have to check that we don't run out of this string as 
1420     // when we reach the terminating NUL, either prefix string ends too (and 
1421     // then it's ok) or we break out of the loop because there is no match 
1422     const wxChar 
*p 
= c_str(); 
1425         if ( *prefix
++ != *p
++ ) 
1434         // put the rest of the string into provided pointer 
1441 // extract nCount last (rightmost) characters 
1442 wxString 
wxString::Right(size_t nCount
) const 
1444   if ( nCount 
> length() ) 
1447   wxString 
dest(*this, length() - nCount
, nCount
); 
1448   if ( dest
.length() != nCount 
) { 
1449     wxFAIL_MSG( _T("out of memory in wxString::Right") ); 
1454 // get all characters after the last occurence of ch 
1455 // (returns the whole string if ch not found) 
1456 wxString 
wxString::AfterLast(wxChar ch
) const 
1459   int iPos 
= Find(ch
, true); 
1460   if ( iPos 
== wxNOT_FOUND 
) 
1463     str 
= c_str() + iPos 
+ 1; 
1468 // extract nCount first (leftmost) characters 
1469 wxString 
wxString::Left(size_t nCount
) const 
1471   if ( nCount 
> length() ) 
1474   wxString 
dest(*this, 0, nCount
); 
1475   if ( dest
.length() != nCount 
) { 
1476     wxFAIL_MSG( _T("out of memory in wxString::Left") ); 
1481 // get all characters before the first occurence of ch 
1482 // (returns the whole string if ch not found) 
1483 wxString 
wxString::BeforeFirst(wxChar ch
) const 
1485   int iPos 
= Find(ch
); 
1486   if ( iPos 
== wxNOT_FOUND 
) iPos 
= length(); 
1487   return wxString(*this, 0, iPos
); 
1490 /// get all characters before the last occurence of ch 
1491 /// (returns empty string if ch not found) 
1492 wxString 
wxString::BeforeLast(wxChar ch
) const 
1495   int iPos 
= Find(ch
, true); 
1496   if ( iPos 
!= wxNOT_FOUND 
&& iPos 
!= 0 ) 
1497     str 
= wxString(c_str(), iPos
); 
1502 /// get all characters after the first occurence of ch 
1503 /// (returns empty string if ch not found) 
1504 wxString 
wxString::AfterFirst(wxChar ch
) const 
1507   int iPos 
= Find(ch
); 
1508   if ( iPos 
!= wxNOT_FOUND 
) 
1509     str 
= c_str() + iPos 
+ 1; 
1514 // replace first (or all) occurences of some substring with another one 
1516 wxString::Replace(const wxChar 
*szOld
, const wxChar 
*szNew
, bool bReplaceAll
) 
1518     // if we tried to replace an empty string we'd enter an infinite loop below 
1519     wxCHECK_MSG( szOld 
&& *szOld 
&& szNew
, 0, 
1520                  _T("wxString::Replace(): invalid parameter") ); 
1522   size_t uiCount 
= 0;   // count of replacements made 
1524   size_t uiOldLen 
= wxStrlen(szOld
); 
1527   const wxChar 
*pCurrent 
= c_str(); 
1528   const wxChar 
*pSubstr
; 
1529   while ( *pCurrent 
!= wxT('\0') ) { 
1530     pSubstr 
= wxStrstr(pCurrent
, szOld
); 
1531     if ( pSubstr 
== NULL 
) { 
1532       // strTemp is unused if no replacements were made, so avoid the copy 
1536       strTemp 
+= pCurrent
;    // copy the rest 
1537       break;                  // exit the loop 
1540       // take chars before match 
1541       size_type len 
= strTemp
.length(); 
1542       strTemp
.append(pCurrent
, pSubstr 
- pCurrent
); 
1543       if ( strTemp
.length() != (size_t)(len 
+ pSubstr 
- pCurrent
) ) { 
1544         wxFAIL_MSG( _T("out of memory in wxString::Replace") ); 
1548       pCurrent 
= pSubstr 
+ uiOldLen
;  // restart after match 
1553       if ( !bReplaceAll 
) { 
1554         strTemp 
+= pCurrent
;    // copy the rest 
1555         break;                  // exit the loop 
1560   // only done if there were replacements, otherwise would have returned above 
1566 bool wxString::IsAscii() const 
1568   const wxChar 
*s 
= (const wxChar
*) *this; 
1570     if(!isascii(*s
)) return(false); 
1576 bool wxString::IsWord() const 
1578   const wxChar 
*s 
= (const wxChar
*) *this; 
1580     if(!wxIsalpha(*s
)) return(false); 
1586 bool wxString::IsNumber() const 
1588   const wxChar 
*s 
= (const wxChar
*) *this; 
1590      if ((s
[0] == wxT('-')) || (s
[0] == wxT('+'))) s
++; 
1592     if(!wxIsdigit(*s
)) return(false); 
1598 wxString 
wxString::Strip(stripType w
) const 
1601     if ( w 
& leading 
) s
.Trim(false); 
1602     if ( w 
& trailing 
) s
.Trim(true); 
1606 // --------------------------------------------------------------------------- 
1608 // --------------------------------------------------------------------------- 
1610 wxString
& wxString::MakeUpper() 
1612   for ( iterator it 
= begin(), en 
= end(); it 
!= en
; ++it 
) 
1613     *it 
= (wxChar
)wxToupper(*it
); 
1618 wxString
& wxString::MakeLower() 
1620   for ( iterator it 
= begin(), en 
= end(); it 
!= en
; ++it 
) 
1621     *it 
= (wxChar
)wxTolower(*it
); 
1626 // --------------------------------------------------------------------------- 
1627 // trimming and padding 
1628 // --------------------------------------------------------------------------- 
1630 // some compilers (VC++ 6.0 not to name them) return true for a call to 
1631 // isspace('ê') in the C locale which seems to be broken to me, but we have to 
1632 // live with this by checking that the character is a 7 bit one - even if this 
1633 // may fail to detect some spaces (I don't know if Unicode doesn't have 
1634 // space-like symbols somewhere except in the first 128 chars), it is arguably 
1635 // still better than trimming away accented letters 
1636 inline int wxSafeIsspace(wxChar ch
) { return (ch 
< 127) && wxIsspace(ch
); } 
1638 // trims spaces (in the sense of isspace) from left or right side 
1639 wxString
& wxString::Trim(bool bFromRight
) 
1641   // first check if we're going to modify the string at all 
1644         (bFromRight 
&& wxSafeIsspace(GetChar(Len() - 1))) || 
1645         (!bFromRight 
&& wxSafeIsspace(GetChar(0u))) 
1651       // find last non-space character 
1652       iterator psz 
= begin() + length() - 1; 
1653       while ( wxSafeIsspace(*psz
) && (psz 
>= begin()) ) 
1656       // truncate at trailing space start 
1662       // find first non-space character 
1663       iterator psz 
= begin(); 
1664       while ( wxSafeIsspace(*psz
) ) 
1667       // fix up data and length 
1668       erase(begin(), psz
); 
1675 // adds nCount characters chPad to the string from either side 
1676 wxString
& wxString::Pad(size_t nCount
, wxChar chPad
, bool bFromRight
) 
1678   wxString 
s(chPad
, nCount
); 
1691 // truncate the string 
1692 wxString
& wxString::Truncate(size_t uiLen
) 
1694   if ( uiLen 
< Len() ) { 
1695     erase(begin() + uiLen
, end()); 
1697   //else: nothing to do, string is already short enough 
1702 // --------------------------------------------------------------------------- 
1703 // finding (return wxNOT_FOUND if not found and index otherwise) 
1704 // --------------------------------------------------------------------------- 
1707 int wxString::Find(wxChar ch
, bool bFromEnd
) const 
1709   size_type idx 
= bFromEnd 
? find_last_of(ch
) : find_first_of(ch
); 
1711   return (idx 
== npos
) ? wxNOT_FOUND 
: (int)idx
; 
1714 // find a sub-string (like strstr) 
1715 int wxString::Find(const wxChar 
*pszSub
) const 
1717   size_type idx 
= find(pszSub
); 
1719   return (idx 
== npos
) ? wxNOT_FOUND 
: (int)idx
; 
1722 // ---------------------------------------------------------------------------- 
1723 // conversion to numbers 
1724 // ---------------------------------------------------------------------------- 
1726 bool wxString::ToLong(long *val
, int base
) const 
1728     wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToLong") ); 
1729     wxASSERT_MSG( !base 
|| (base 
> 1 && base 
<= 36), _T("invalid base") ); 
1731     const wxChar 
*start 
= c_str(); 
1733     *val 
= wxStrtol(start
, &end
, base
); 
1735     // return true only if scan was stopped by the terminating NUL and if the 
1736     // string was not empty to start with 
1737     return !*end 
&& (end 
!= start
); 
1740 bool wxString::ToULong(unsigned long *val
, int base
) const 
1742     wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToULong") ); 
1743     wxASSERT_MSG( !base 
|| (base 
> 1 && base 
<= 36), _T("invalid base") ); 
1745     const wxChar 
*start 
= c_str(); 
1747     *val 
= wxStrtoul(start
, &end
, base
); 
1749     // return true only if scan was stopped by the terminating NUL and if the 
1750     // string was not empty to start with 
1751     return !*end 
&& (end 
!= start
); 
1754 bool wxString::ToDouble(double *val
) const 
1756     wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToDouble") ); 
1758     const wxChar 
*start 
= c_str(); 
1760     *val 
= wxStrtod(start
, &end
); 
1762     // return true only if scan was stopped by the terminating NUL and if the 
1763     // string was not empty to start with 
1764     return !*end 
&& (end 
!= start
); 
1767 // --------------------------------------------------------------------------- 
1769 // --------------------------------------------------------------------------- 
1772 wxString 
wxString::Format(const wxChar 
*pszFormat
, ...) 
1775     va_start(argptr
, pszFormat
); 
1778     s
.PrintfV(pszFormat
, argptr
); 
1786 wxString 
wxString::FormatV(const wxChar 
*pszFormat
, va_list argptr
) 
1789     s
.PrintfV(pszFormat
, argptr
); 
1793 int wxString::Printf(const wxChar 
*pszFormat
, ...) 
1796     va_start(argptr
, pszFormat
); 
1798     int iLen 
= PrintfV(pszFormat
, argptr
); 
1805 int wxString::PrintfV(const wxChar
* pszFormat
, va_list argptr
) 
1811         wxStringBuffer 
tmp(*this, size 
+ 1); 
1820         // wxVsnprintf() may modify the original arg pointer, so pass it 
1823         wxVaCopy(argptrcopy
, argptr
); 
1824         int len 
= wxVsnprintf(buf
, size
, pszFormat
, argptrcopy
); 
1827         // some implementations of vsnprintf() don't NUL terminate 
1828         // the string if there is not enough space for it so 
1829         // always do it manually 
1830         buf
[size
] = _T('\0'); 
1832         // vsnprintf() may return either -1 (traditional Unix behaviour) or the 
1833         // total number of characters which would have been written if the 
1834         // buffer were large enough 
1835         // also, it may return an errno may be something like EILSEQ, 
1836         // in which case we need to break out 
1837         if ( (len 
>= 0 && len 
<= size
) 
1838         // No EOVERFLOW on Windows nor Palm 6.0 nor OpenVMS nor MacOS (not X) 
1839         // not OS/2 (not Innotek libc). 
1840 #if !defined(__WXMSW__) && !defined(__WXPALMOS__) && !defined( __VMS ) && !(defined(__WXMAC__) && !defined(__WXMAC_OSX__)) && !(defined(__EMX__) && !defined(__INNOTEK_LIBC__)) 
1841             || errno 
!= EOVERFLOW
 
1845             // ok, there was enough space 
1849         // still not enough, double it again 
1853     // we could have overshot 
1859 // ---------------------------------------------------------------------------- 
1860 // misc other operations 
1861 // ---------------------------------------------------------------------------- 
1863 // returns true if the string matches the pattern which may contain '*' and 
1864 // '?' metacharacters (as usual, '?' matches any character and '*' any number 
1866 bool wxString::Matches(const wxChar 
*pszMask
) const 
1868     // I disable this code as it doesn't seem to be faster (in fact, it seems 
1869     // to be much slower) than the old, hand-written code below and using it 
1870     // here requires always linking with libregex even if the user code doesn't 
1872 #if 0 // wxUSE_REGEX 
1873     // first translate the shell-like mask into a regex 
1875     pattern
.reserve(wxStrlen(pszMask
)); 
1887                 pattern 
+= _T(".*"); 
1898                 // these characters are special in a RE, quote them 
1899                 // (however note that we don't quote '[' and ']' to allow 
1900                 // using them for Unix shell like matching) 
1901                 pattern 
+= _T('\\'); 
1905                 pattern 
+= *pszMask
; 
1913     return wxRegEx(pattern
, wxRE_NOSUB 
| wxRE_EXTENDED
).Matches(c_str()); 
1914 #else // !wxUSE_REGEX 
1915   // TODO: this is, of course, awfully inefficient... 
1917   // the char currently being checked 
1918   const wxChar 
*pszTxt 
= c_str(); 
1920   // the last location where '*' matched 
1921   const wxChar 
*pszLastStarInText 
= NULL
; 
1922   const wxChar 
*pszLastStarInMask 
= NULL
; 
1925   for ( ; *pszMask 
!= wxT('\0'); pszMask
++, pszTxt
++ ) { 
1926     switch ( *pszMask 
) { 
1928         if ( *pszTxt 
== wxT('\0') ) 
1931         // pszTxt and pszMask will be incremented in the loop statement 
1937           // remember where we started to be able to backtrack later 
1938           pszLastStarInText 
= pszTxt
; 
1939           pszLastStarInMask 
= pszMask
; 
1941           // ignore special chars immediately following this one 
1942           // (should this be an error?) 
1943           while ( *pszMask 
== wxT('*') || *pszMask 
== wxT('?') ) 
1946           // if there is nothing more, match 
1947           if ( *pszMask 
== wxT('\0') ) 
1950           // are there any other metacharacters in the mask? 
1952           const wxChar 
*pEndMask 
= wxStrpbrk(pszMask
, wxT("*?")); 
1954           if ( pEndMask 
!= NULL 
) { 
1955             // we have to match the string between two metachars 
1956             uiLenMask 
= pEndMask 
- pszMask
; 
1959             // we have to match the remainder of the string 
1960             uiLenMask 
= wxStrlen(pszMask
); 
1963           wxString 
strToMatch(pszMask
, uiLenMask
); 
1964           const wxChar
* pMatch 
= wxStrstr(pszTxt
, strToMatch
); 
1965           if ( pMatch 
== NULL 
) 
1968           // -1 to compensate "++" in the loop 
1969           pszTxt 
= pMatch 
+ uiLenMask 
- 1; 
1970           pszMask 
+= uiLenMask 
- 1; 
1975         if ( *pszMask 
!= *pszTxt 
) 
1981   // match only if nothing left 
1982   if ( *pszTxt 
== wxT('\0') ) 
1985   // if we failed to match, backtrack if we can 
1986   if ( pszLastStarInText 
) { 
1987     pszTxt 
= pszLastStarInText 
+ 1; 
1988     pszMask 
= pszLastStarInMask
; 
1990     pszLastStarInText 
= NULL
; 
1992     // don't bother resetting pszLastStarInMask, it's unnecessary 
1998 #endif // wxUSE_REGEX/!wxUSE_REGEX 
2001 // Count the number of chars 
2002 int wxString::Freq(wxChar ch
) const 
2006     for (int i 
= 0; i 
< len
; i
++) 
2008         if (GetChar(i
) == ch
) 
2014 // convert to upper case, return the copy of the string 
2015 wxString 
wxString::Upper() const 
2016 { wxString 
s(*this); return s
.MakeUpper(); } 
2018 // convert to lower case, return the copy of the string 
2019 wxString 
wxString::Lower() const { wxString 
s(*this); return s
.MakeLower(); } 
2021 int wxString::sprintf(const wxChar 
*pszFormat
, ...) 
2024     va_start(argptr
, pszFormat
); 
2025     int iLen 
= PrintfV(pszFormat
, argptr
); 
2030 // ============================================================================ 
2032 // ============================================================================ 
2034 #include "wx/arrstr.h" 
2036 wxArrayString::wxArrayString(size_t sz
, const wxChar
** a
) 
2041     for (size_t i
=0; i 
< sz
; i
++) 
2045 wxArrayString::wxArrayString(size_t sz
, const wxString
* a
) 
2050     for (size_t i
=0; i 
< sz
; i
++) 
2056 // size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT) 
2057 #define   ARRAY_MAXSIZE_INCREMENT       4096 
2059 #ifndef   ARRAY_DEFAULT_INITIAL_SIZE    // also defined in dynarray.h 
2060 #define   ARRAY_DEFAULT_INITIAL_SIZE    (16) 
2063 #define   STRING(p)   ((wxString *)(&(p))) 
2066 void wxArrayString::Init(bool autoSort
) 
2070   m_pItems 
= (wxChar 
**) NULL
; 
2071   m_autoSort 
= autoSort
; 
2075 wxArrayString::wxArrayString(const wxArrayString
& src
) 
2077   Init(src
.m_autoSort
); 
2082 // assignment operator 
2083 wxArrayString
& wxArrayString::operator=(const wxArrayString
& src
) 
2090   m_autoSort 
= src
.m_autoSort
; 
2095 void wxArrayString::Copy(const wxArrayString
& src
) 
2097   if ( src
.m_nCount 
> ARRAY_DEFAULT_INITIAL_SIZE 
) 
2098     Alloc(src
.m_nCount
); 
2100   for ( size_t n 
= 0; n 
< src
.m_nCount
; n
++ ) 
2105 void wxArrayString::Grow(size_t nIncrement
) 
2107   // only do it if no more place 
2108   if ( (m_nSize 
- m_nCount
) < nIncrement 
) { 
2109     // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would 
2110     // be never resized! 
2111     #if ARRAY_DEFAULT_INITIAL_SIZE == 0 
2112       #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!" 
2115     if ( m_nSize 
== 0 ) { 
2116       // was empty, alloc some memory 
2117       m_nSize 
= ARRAY_DEFAULT_INITIAL_SIZE
; 
2118       if (m_nSize 
< nIncrement
) 
2119           m_nSize 
= nIncrement
; 
2120       m_pItems 
= new wxChar 
*[m_nSize
]; 
2123       // otherwise when it's called for the first time, nIncrement would be 0 
2124       // and the array would never be expanded 
2125       // add 50% but not too much 
2126       size_t ndefIncrement 
= m_nSize 
< ARRAY_DEFAULT_INITIAL_SIZE
 
2127                           ? ARRAY_DEFAULT_INITIAL_SIZE 
: m_nSize 
>> 1; 
2128       if ( ndefIncrement 
> ARRAY_MAXSIZE_INCREMENT 
) 
2129         ndefIncrement 
= ARRAY_MAXSIZE_INCREMENT
; 
2130       if ( nIncrement 
< ndefIncrement 
) 
2131         nIncrement 
= ndefIncrement
; 
2132       m_nSize 
+= nIncrement
; 
2133       wxChar 
**pNew 
= new wxChar 
*[m_nSize
]; 
2135       // copy data to new location 
2136       memcpy(pNew
, m_pItems
, m_nCount
*sizeof(wxChar 
*)); 
2138       // delete old memory (but do not release the strings!) 
2139       wxDELETEA(m_pItems
); 
2146 void wxArrayString::Free() 
2148   for ( size_t n 
= 0; n 
< m_nCount
; n
++ ) { 
2149     STRING(m_pItems
[n
])->GetStringData()->Unlock(); 
2153 // deletes all the strings from the list 
2154 void wxArrayString::Empty() 
2161 // as Empty, but also frees memory 
2162 void wxArrayString::Clear() 
2169   wxDELETEA(m_pItems
); 
2173 wxArrayString::~wxArrayString() 
2177   wxDELETEA(m_pItems
); 
2180 void wxArrayString::reserve(size_t nSize
) 
2185 // pre-allocates memory (frees the previous data!) 
2186 void wxArrayString::Alloc(size_t nSize
) 
2188   // only if old buffer was not big enough 
2189   if ( nSize 
> m_nSize 
) { 
2191     wxDELETEA(m_pItems
); 
2192     m_pItems 
= new wxChar 
*[nSize
]; 
2199 // minimizes the memory usage by freeing unused memory 
2200 void wxArrayString::Shrink() 
2202   // only do it if we have some memory to free 
2203   if( m_nCount 
< m_nSize 
) { 
2204     // allocates exactly as much memory as we need 
2205     wxChar 
**pNew 
= new wxChar 
*[m_nCount
]; 
2207     // copy data to new location 
2208     memcpy(pNew
, m_pItems
, m_nCount
*sizeof(wxChar 
*)); 
2214 #if WXWIN_COMPATIBILITY_2_4 
2216 // return a wxString[] as required for some control ctors. 
2217 wxString
* wxArrayString::GetStringArray() const 
2219     wxString 
*array 
= 0; 
2223         array 
= new wxString
[m_nCount
]; 
2224         for( size_t i 
= 0; i 
< m_nCount
; i
++ ) 
2225             array
[i
] = m_pItems
[i
]; 
2231 void wxArrayString::Remove(size_t nIndex
, size_t nRemove
) 
2233     RemoveAt(nIndex
, nRemove
); 
2236 #endif // WXWIN_COMPATIBILITY_2_4 
2238 // searches the array for an item (forward or backwards) 
2239 int wxArrayString::Index(const wxChar 
*sz
, bool bCase
, bool bFromEnd
) const 
2242     // use binary search in the sorted array 
2243     wxASSERT_MSG( bCase 
&& !bFromEnd
, 
2244                   wxT("search parameters ignored for auto sorted array") ); 
2253       res 
= wxStrcmp(sz
, m_pItems
[i
]); 
2265     // use linear search in unsorted array 
2267       if ( m_nCount 
> 0 ) { 
2268         size_t ui 
= m_nCount
; 
2270           if ( STRING(m_pItems
[--ui
])->IsSameAs(sz
, bCase
) ) 
2277       for( size_t ui 
= 0; ui 
< m_nCount
; ui
++ ) { 
2278         if( STRING(m_pItems
[ui
])->IsSameAs(sz
, bCase
) ) 
2287 // add item at the end 
2288 size_t wxArrayString::Add(const wxString
& str
, size_t nInsert
) 
2291     // insert the string at the correct position to keep the array sorted 
2299       res 
= str
.Cmp(m_pItems
[i
]); 
2310     wxASSERT_MSG( lo 
== hi
, wxT("binary search broken") ); 
2312     Insert(str
, lo
, nInsert
); 
2317     wxASSERT( str
.GetStringData()->IsValid() ); 
2321     for (size_t i 
= 0; i 
< nInsert
; i
++) 
2323         // the string data must not be deleted! 
2324         str
.GetStringData()->Lock(); 
2327         m_pItems
[m_nCount 
+ i
] = (wxChar 
*)str
.c_str(); // const_cast 
2329     size_t ret 
= m_nCount
; 
2330     m_nCount 
+= nInsert
; 
2335 // add item at the given position 
2336 void wxArrayString::Insert(const wxString
& str
, size_t nIndex
, size_t nInsert
) 
2338   wxASSERT( str
.GetStringData()->IsValid() ); 
2340   wxCHECK_RET( nIndex 
<= m_nCount
, wxT("bad index in wxArrayString::Insert") ); 
2341   wxCHECK_RET( m_nCount 
<= m_nCount 
+ nInsert
, 
2342                wxT("array size overflow in wxArrayString::Insert") ); 
2346   memmove(&m_pItems
[nIndex 
+ nInsert
], &m_pItems
[nIndex
], 
2347           (m_nCount 
- nIndex
)*sizeof(wxChar 
*)); 
2349   for (size_t i 
= 0; i 
< nInsert
; i
++) 
2351       str
.GetStringData()->Lock(); 
2352       m_pItems
[nIndex 
+ i
] = (wxChar 
*)str
.c_str(); 
2354   m_nCount 
+= nInsert
; 
2357 // range insert (STL 23.2.4.3) 
2359 wxArrayString::insert(iterator it
, const_iterator first
, const_iterator last
) 
2361     const int idx 
= it 
- begin(); 
2366     // reset "it" since it can change inside Grow() 
2369     while ( first 
!= last 
) 
2371         it 
= insert(it
, *first
); 
2373         // insert returns an iterator to the last element inserted but we need 
2374         // insert the next after this one, that is before the next one 
2382 void wxArrayString::SetCount(size_t count
) 
2387     while ( m_nCount 
< count 
) 
2388         m_pItems
[m_nCount
++] = (wxChar 
*)s
.c_str(); 
2391 // removes item from array (by index) 
2392 void wxArrayString::RemoveAt(size_t nIndex
, size_t nRemove
) 
2394   wxCHECK_RET( nIndex 
< m_nCount
, wxT("bad index in wxArrayString::Remove") ); 
2395   wxCHECK_RET( nIndex 
+ nRemove 
<= m_nCount
, 
2396                wxT("removing too many elements in wxArrayString::Remove") ); 
2399   for (size_t i 
= 0; i 
< nRemove
; i
++) 
2400       Item(nIndex 
+ i
).GetStringData()->Unlock(); 
2402   memmove(&m_pItems
[nIndex
], &m_pItems
[nIndex 
+ nRemove
], 
2403           (m_nCount 
- nIndex 
- nRemove
)*sizeof(wxChar 
*)); 
2404   m_nCount 
-= nRemove
; 
2407 // removes item from array (by value) 
2408 void wxArrayString::Remove(const wxChar 
*sz
) 
2410   int iIndex 
= Index(sz
); 
2412   wxCHECK_RET( iIndex 
!= wxNOT_FOUND
, 
2413                wxT("removing inexistent element in wxArrayString::Remove") ); 
2418 void wxArrayString::assign(const_iterator first
, const_iterator last
) 
2420     reserve(last 
- first
); 
2421     for(; first 
!= last
; ++first
) 
2425 // ---------------------------------------------------------------------------- 
2427 // ---------------------------------------------------------------------------- 
2429 // we can only sort one array at a time with the quick-sort based 
2432   // need a critical section to protect access to gs_compareFunction and 
2433   // gs_sortAscending variables 
2434   static wxCriticalSection 
*gs_critsectStringSort 
= NULL
; 
2436   // call this before the value of the global sort vars is changed/after 
2437   // you're finished with them 
2438   #define START_SORT()     wxASSERT( !gs_critsectStringSort );                \ 
2439                            gs_critsectStringSort = new wxCriticalSection;     \ 
2440                            gs_critsectStringSort->Enter() 
2441   #define END_SORT()       gs_critsectStringSort->Leave();                    \ 
2442                            delete gs_critsectStringSort;                      \ 
2443                            gs_critsectStringSort = NULL 
2445   #define START_SORT() 
2447 #endif // wxUSE_THREADS 
2449 // function to use for string comparaison 
2450 static wxArrayString::CompareFunction gs_compareFunction 
= NULL
; 
2452 // if we don't use the compare function, this flag tells us if we sort the 
2453 // array in ascending or descending order 
2454 static bool gs_sortAscending 
= true; 
2456 // function which is called by quick sort 
2457 extern "C" int wxC_CALLING_CONV     
// LINKAGEMODE 
2458 wxStringCompareFunction(const void *first
, const void *second
) 
2460   wxString 
*strFirst 
= (wxString 
*)first
; 
2461   wxString 
*strSecond 
= (wxString 
*)second
; 
2463   if ( gs_compareFunction 
) { 
2464     return gs_compareFunction(*strFirst
, *strSecond
); 
2467     // maybe we should use wxStrcoll 
2468     int result 
= strFirst
->Cmp(*strSecond
); 
2470     return gs_sortAscending 
? result 
: -result
; 
2474 // sort array elements using passed comparaison function 
2475 void wxArrayString::Sort(CompareFunction compareFunction
) 
2479   wxASSERT( !gs_compareFunction 
);  // must have been reset to NULL 
2480   gs_compareFunction 
= compareFunction
; 
2484   // reset it to NULL so that Sort(bool) will work the next time 
2485   gs_compareFunction 
= NULL
; 
2490 typedef  int (wxC_CALLING_CONV 
* wxStringCompareFn
)(const void *first
, const void *second
); 
2492 void wxArrayString::Sort(CompareFunction2 compareFunction
) 
2494   qsort(m_pItems
, m_nCount
, sizeof(wxChar 
*), (wxStringCompareFn
)compareFunction
); 
2497 void wxArrayString::Sort(bool reverseOrder
) 
2499   Sort(reverseOrder 
? wxStringSortDescending 
: wxStringSortAscending
); 
2502 void wxArrayString::DoSort() 
2504   wxCHECK_RET( !m_autoSort
, wxT("can't use this method with sorted arrays") ); 
2506   // just sort the pointers using qsort() - of course it only works because 
2507   // wxString() *is* a pointer to its data 
2508   qsort(m_pItems
, m_nCount
, sizeof(wxChar 
*), wxStringCompareFunction
); 
2511 bool wxArrayString::operator==(const wxArrayString
& a
) const 
2513     if ( m_nCount 
!= a
.m_nCount 
) 
2516     for ( size_t n 
= 0; n 
< m_nCount
; n
++ ) 
2518         if ( Item(n
) != a
[n
] ) 
2525 #endif // !wxUSE_STL 
2527 int wxCMPFUNC_CONV 
wxStringSortAscending(wxString
* s1
, wxString
* s2
) 
2529     return  s1
->Cmp(*s2
); 
2532 int wxCMPFUNC_CONV 
wxStringSortDescending(wxString
* s1
, wxString
* s2
) 
2534     return -s1
->Cmp(*s2
);