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
) 
 142 #endif // wxUSE_STD_IOSTREAM 
 144 // ---------------------------------------------------------------------------- 
 146 // ---------------------------------------------------------------------------- 
 148 // this small class is used to gather statistics for performance tuning 
 149 //#define WXSTRING_STATISTICS 
 150 #ifdef  WXSTRING_STATISTICS 
 154     Averager(const wxChar 
*sz
) { m_sz 
= sz
; m_nTotal 
= m_nCount 
= 0; } 
 156    { wxPrintf("wxString: average %s = %f\n", m_sz
, ((float)m_nTotal
)/m_nCount
); } 
 158     void Add(size_t n
) { m_nTotal 
+= n
; m_nCount
++; } 
 161     size_t m_nCount
, m_nTotal
; 
 163   } g_averageLength("allocation size"), 
 164     g_averageSummandLength("summand length"), 
 165     g_averageConcatHit("hit probability in concat"), 
 166     g_averageInitialLength("initial string length"); 
 168   #define STATISTICS_ADD(av, val) g_average##av.Add(val) 
 170   #define STATISTICS_ADD(av, val) 
 171 #endif // WXSTRING_STATISTICS 
 175 // =========================================================================== 
 176 // wxStringData class deallocation 
 177 // =========================================================================== 
 179 #if defined(__VISUALC__) && defined(_MT) && !defined(_DLL) 
 180 #  pragma message (__FILE__ ": building with Multithreaded non DLL runtime has a performance impact on wxString!") 
 181 void wxStringData::Free() 
 187 // =========================================================================== 
 189 // =========================================================================== 
 191 // takes nLength elements of psz starting at nPos 
 192 void wxStringBase::InitWith(const wxChar 
*psz
, size_t nPos
, size_t nLength
) 
 196   // if the length is not given, assume the string to be NUL terminated 
 197   if ( nLength 
== npos 
) { 
 198     wxASSERT_MSG( nPos 
<= wxStrlen(psz
), _T("index out of bounds") ); 
 200     nLength 
= wxStrlen(psz 
+ nPos
); 
 203   STATISTICS_ADD(InitialLength
, nLength
); 
 206     // trailing '\0' is written in AllocBuffer() 
 207     if ( !AllocBuffer(nLength
) ) { 
 208       wxFAIL_MSG( _T("out of memory in wxStringBase::InitWith") ); 
 211     wxTmemcpy(m_pchData
, psz 
+ nPos
, nLength
); 
 215 // poor man's iterators are "void *" pointers 
 216 wxStringBase::wxStringBase(const void *pStart
, const void *pEnd
) 
 218   InitWith((const wxChar 
*)pStart
, 0, 
 219            (const wxChar 
*)pEnd 
- (const wxChar 
*)pStart
); 
 222 wxStringBase::wxStringBase(size_type n
, wxChar ch
) 
 228 // --------------------------------------------------------------------------- 
 230 // --------------------------------------------------------------------------- 
 232 // allocates memory needed to store a C string of length nLen 
 233 bool wxStringBase::AllocBuffer(size_t nLen
) 
 235   // allocating 0 sized buffer doesn't make sense, all empty strings should 
 237   wxASSERT( nLen 
>  0 ); 
 239   // make sure that we don't overflow 
 240   wxASSERT( nLen 
< (INT_MAX 
/ sizeof(wxChar
)) - 
 241                    (sizeof(wxStringData
) + EXTRA_ALLOC 
+ 1) ); 
 243   STATISTICS_ADD(Length
, nLen
); 
 246   // 1) one extra character for '\0' termination 
 247   // 2) sizeof(wxStringData) for housekeeping info 
 248   wxStringData
* pData 
= (wxStringData
*) 
 249     malloc(sizeof(wxStringData
) + (nLen 
+ EXTRA_ALLOC 
+ 1)*sizeof(wxChar
)); 
 251   if ( pData 
== NULL 
) { 
 252     // allocation failures are handled by the caller 
 257   pData
->nDataLength  
= nLen
; 
 258   pData
->nAllocLength 
= nLen 
+ EXTRA_ALLOC
; 
 259   m_pchData           
= pData
->data();  // data starts after wxStringData 
 260   m_pchData
[nLen
]     = wxT('\0'); 
 264 // must be called before changing this string 
 265 bool wxStringBase::CopyBeforeWrite() 
 267   wxStringData
* pData 
= GetStringData(); 
 269   if ( pData
->IsShared() ) { 
 270     pData
->Unlock();                // memory not freed because shared 
 271     size_t nLen 
= pData
->nDataLength
; 
 272     if ( !AllocBuffer(nLen
) ) { 
 273       // allocation failures are handled by the caller 
 276     wxTmemcpy(m_pchData
, pData
->data(), nLen
); 
 279   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner 
 284 // must be called before replacing contents of this string 
 285 bool wxStringBase::AllocBeforeWrite(size_t nLen
) 
 287   wxASSERT( nLen 
!= 0 );  // doesn't make any sense 
 289   // must not share string and must have enough space 
 290   wxStringData
* pData 
= GetStringData(); 
 291   if ( pData
->IsShared() || pData
->IsEmpty() ) { 
 292     // can't work with old buffer, get new one 
 294     if ( !AllocBuffer(nLen
) ) { 
 295       // allocation failures are handled by the caller 
 300     if ( nLen 
> pData
->nAllocLength 
) { 
 301       // realloc the buffer instead of calling malloc() again, this is more 
 303       STATISTICS_ADD(Length
, nLen
); 
 307       pData 
= (wxStringData
*) 
 308           realloc(pData
, sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 310       if ( pData 
== NULL 
) { 
 311         // allocation failures are handled by the caller 
 312         // keep previous data since reallocation failed 
 316       pData
->nAllocLength 
= nLen
; 
 317       m_pchData 
= pData
->data(); 
 321   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner 
 323   // it doesn't really matter what the string length is as it's going to be 
 324   // overwritten later but, for extra safety, set it to 0 for now as we may 
 325   // have some junk in m_pchData 
 326   GetStringData()->nDataLength 
= 0; 
 331 wxStringBase
& wxStringBase::append(size_t n
, wxChar ch
) 
 333     size_type len 
= length(); 
 335     if ( !Alloc(len 
+ n
) || !CopyBeforeWrite() ) { 
 336       wxFAIL_MSG( _T("out of memory in wxStringBase::append") ); 
 338     GetStringData()->nDataLength 
= len 
+ n
; 
 339     m_pchData
[len 
+ n
] = '\0'; 
 340     for ( size_t i 
= 0; i 
< n
; ++i 
) 
 341         m_pchData
[len 
+ i
] = ch
; 
 345 void wxStringBase::resize(size_t nSize
, wxChar ch
) 
 347     size_t len 
= length(); 
 351         erase(begin() + nSize
, end()); 
 353     else if ( nSize 
> len 
) 
 355         append(nSize 
- len
, ch
); 
 357     //else: we have exactly the specified length, nothing to do 
 360 // allocate enough memory for nLen characters 
 361 bool wxStringBase::Alloc(size_t nLen
) 
 363   wxStringData 
*pData 
= GetStringData(); 
 364   if ( pData
->nAllocLength 
<= nLen 
) { 
 365     if ( pData
->IsEmpty() ) { 
 368       wxStringData
* pData 
= (wxStringData
*) 
 369           malloc(sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 371       if ( pData 
== NULL 
) { 
 372         // allocation failure handled by caller 
 377       pData
->nDataLength 
= 0; 
 378       pData
->nAllocLength 
= nLen
; 
 379       m_pchData 
= pData
->data();  // data starts after wxStringData 
 380       m_pchData
[0u] = wxT('\0'); 
 382     else if ( pData
->IsShared() ) { 
 383       pData
->Unlock();                // memory not freed because shared 
 384       size_t nOldLen 
= pData
->nDataLength
; 
 385       if ( !AllocBuffer(nLen
) ) { 
 386         // allocation failure handled by caller 
 389       // +1 to copy the terminator, too 
 390       memcpy(m_pchData
, pData
->data(), (nOldLen
+1)*sizeof(wxChar
)); 
 391       GetStringData()->nDataLength 
= nOldLen
; 
 396       pData 
= (wxStringData 
*) 
 397         realloc(pData
, sizeof(wxStringData
) + (nLen 
+ 1)*sizeof(wxChar
)); 
 399       if ( pData 
== NULL 
) { 
 400         // allocation failure handled by caller 
 401         // keep previous data since reallocation failed 
 405       // it's not important if the pointer changed or not (the check for this 
 406       // is not faster than assigning to m_pchData in all cases) 
 407       pData
->nAllocLength 
= nLen
; 
 408       m_pchData 
= pData
->data(); 
 411   //else: we've already got enough 
 415 wxStringBase::iterator 
wxStringBase::begin() 
 422 wxStringBase::iterator 
wxStringBase::end() 
 426     return m_pchData 
+ length(); 
 429 wxStringBase::iterator 
wxStringBase::erase(iterator it
) 
 431     size_type idx 
= it 
- begin(); 
 433     return begin() + idx
; 
 436 wxStringBase
& wxStringBase::erase(size_t nStart
, size_t nLen
) 
 438   wxASSERT(nStart 
<= length()); 
 439   size_t strLen 
= length() - nStart
; 
 440   // delete nLen or up to the end of the string characters 
 441   nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 442   wxString 
strTmp(c_str(), nStart
); 
 443   strTmp
.append(c_str() + nStart 
+ nLen
, length() - nStart 
- nLen
); 
 449 wxStringBase
& wxStringBase::insert(size_t nPos
, const wxChar 
*sz
, size_t n
) 
 451   wxASSERT( nPos 
<= length() ); 
 453   if ( n 
== npos 
) n 
= wxStrlen(sz
); 
 454   if ( n 
== 0 ) return *this; 
 456   if ( !Alloc(length() + n
) || !CopyBeforeWrite() ) { 
 457     wxFAIL_MSG( _T("out of memory in wxStringBase::insert") ); 
 460   memmove(m_pchData 
+ nPos 
+ n
, m_pchData 
+ nPos
, 
 461           (length() - nPos
) * sizeof(wxChar
)); 
 462   memcpy(m_pchData 
+ nPos
, sz
, n 
* sizeof(wxChar
)); 
 463   GetStringData()->nDataLength 
= length() + n
; 
 464   m_pchData
[length()] = '\0'; 
 469 void wxStringBase::swap(wxStringBase
& str
) 
 471     wxChar
* tmp 
= str
.m_pchData
; 
 472     str
.m_pchData 
= m_pchData
; 
 476 size_t wxStringBase::find(const wxStringBase
& str
, size_t nStart
) const 
 478   wxASSERT( str
.GetStringData()->IsValid() ); 
 479   wxASSERT( nStart 
<= length() ); 
 482   const wxChar
* p 
= (const wxChar
*)wxTmemchr(c_str() + nStart
, 
 489   while(p 
- c_str() + str
.length() <= length() && 
 490         wxTmemcmp(p
, str
.c_str(), str
.length()) ) 
 492       //Previosly passed as the first argument to wxTmemchr, 
 493       //but C/C++ standard does not specify evaluation order 
 494       //of arguments to functions - 
 495       //http://embedded.com/showArticle.jhtml?articleID=9900607 
 499       p 
= (const wxChar
*)wxTmemchr(p
, 
 501                                   length() - (p 
- c_str())); 
 507    return (p 
- c_str() + str
.length() <= length()) ? p 
- c_str() : npos
; 
 510 size_t wxStringBase::find(const wxChar
* sz
, size_t nStart
, size_t n
) const 
 512   return find(wxStringBase(sz
, n
), nStart
); 
 515 size_t wxStringBase::find(wxChar ch
, size_t nStart
) const 
 517   wxASSERT( nStart 
<= length() ); 
 519   const wxChar 
*p 
= (const wxChar
*)wxTmemchr(c_str() + nStart
, ch
, length() - nStart
); 
 521   return p 
== NULL 
? npos 
: p 
- c_str(); 
 524 size_t wxStringBase::rfind(const wxStringBase
& str
, size_t nStart
) const 
 526     wxASSERT( str
.GetStringData()->IsValid() ); 
 527     wxASSERT( nStart 
== npos 
|| nStart 
<= length() ); 
 529     if ( length() >= str
.length() ) 
 531         // avoids a corner case later 
 532         if ( length() == 0 && str
.length() == 0 ) 
 535         // "top" is the point where search starts from 
 536         size_t top 
= length() - str
.length(); 
 538         if ( nStart 
== npos 
) 
 539             nStart 
= length() - 1; 
 543         const wxChar 
*cursor 
= c_str() + top
; 
 546             if ( wxTmemcmp(cursor
, str
.c_str(), 
 549                 return cursor 
- c_str(); 
 551         } while ( cursor
-- > c_str() ); 
 557 size_t wxStringBase::rfind(const wxChar
* sz
, size_t nStart
, size_t n
) const 
 559     return rfind(wxStringBase(sz
, n
), nStart
); 
 562 size_t wxStringBase::rfind(wxChar ch
, size_t nStart
) const 
 564     if ( nStart 
== npos 
) 
 570         wxASSERT( nStart 
<= length() ); 
 573     const wxChar 
*actual
; 
 574     for ( actual 
= c_str() + ( nStart 
== npos 
? length() : nStart 
+ 1 ); 
 575           actual 
> c_str(); --actual 
) 
 577         if ( *(actual 
- 1) == ch 
) 
 578             return (actual 
- 1) - c_str(); 
 584 size_t wxStringBase::find_first_of(const wxChar
* sz
, size_t nStart
) const 
 586     wxASSERT(nStart 
<= length()); 
 588     size_t len 
= wxStrlen(sz
); 
 591     for(i 
= nStart
; i 
< this->length(); ++i
) 
 593         if (wxTmemchr(sz
, *(c_str() + i
), len
)) 
 597     if(i 
== this->length()) 
 603 size_t wxStringBase::find_first_of(const wxChar
* sz
, size_t nStart
, 
 606     return find_first_of(wxStringBase(sz
, n
), nStart
); 
 609 size_t wxStringBase::find_last_of(const wxChar
* sz
, size_t nStart
) const 
 611     if ( nStart 
== npos 
) 
 613         nStart 
= length() - 1; 
 617         wxASSERT_MSG( nStart 
<= length(), 
 618                         _T("invalid index in find_last_of()") ); 
 621     size_t len 
= wxStrlen(sz
); 
 623     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 625         if ( wxTmemchr(sz
, *p
, len
) ) 
 632 size_t wxStringBase::find_last_of(const wxChar
* sz
, size_t nStart
, 
 635     return find_last_of(wxStringBase(sz
, n
), nStart
); 
 638 size_t wxStringBase::find_first_not_of(const wxChar
* sz
, size_t nStart
) const 
 640     if ( nStart 
== npos 
) 
 646         wxASSERT( nStart 
<= length() ); 
 649     size_t len 
= wxStrlen(sz
); 
 652     for(i 
= nStart
; i 
< this->length(); ++i
) 
 654         if (!wxTmemchr(sz
, *(c_str() + i
), len
)) 
 658     if(i 
== this->length()) 
 664 size_t wxStringBase::find_first_not_of(const wxChar
* sz
, size_t nStart
, 
 667     return find_first_not_of(wxStringBase(sz
, n
), nStart
); 
 670 size_t wxStringBase::find_first_not_of(wxChar ch
, size_t nStart
) const 
 672     wxASSERT( nStart 
<= length() ); 
 674     for ( const wxChar 
*p 
= c_str() + nStart
; *p
; p
++ ) 
 683 size_t wxStringBase::find_last_not_of(const wxChar
* sz
, size_t nStart
) const 
 685     if ( nStart 
== npos 
) 
 687         nStart 
= length() - 1; 
 691         wxASSERT( nStart 
<= length() ); 
 694     size_t len 
= wxStrlen(sz
); 
 696     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 698         if ( !wxTmemchr(sz
, *p
,len
) ) 
 705 size_t wxStringBase::find_last_not_of(const wxChar
* sz
, size_t nStart
, 
 708     return find_last_not_of(wxStringBase(sz
, n
), nStart
); 
 711 size_t wxStringBase::find_last_not_of(wxChar ch
, size_t nStart
) const 
 713     if ( nStart 
== npos 
) 
 715         nStart 
= length() - 1; 
 719         wxASSERT( nStart 
<= length() ); 
 722     for ( const wxChar 
*p 
= c_str() + nStart
; p 
>= c_str(); --p 
) 
 731 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 734   wxASSERT_MSG( nStart 
<= length(), 
 735                 _T("index out of bounds in wxStringBase::replace") ); 
 736   size_t strLen 
= length() - nStart
; 
 737   nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 740   strTmp
.reserve(length()); // micro optimisation to avoid multiple mem allocs 
 742   //This is kind of inefficient, but its pretty good considering... 
 743   //we don't want to use character access operators here because on STL 
 744   //it will freeze the reference count of strTmp, which means a deep copy 
 745   //at the end when swap is called 
 747   //Also, we can't use append with the full character pointer and must 
 748   //do it manually because this string can contain null characters 
 749   for(size_t i1 
= 0; i1 
< nStart
; ++i1
) 
 750       strTmp
.append(1, this->c_str()[i1
]); 
 752   //its safe to do the full version here because 
 753   //sz must be a normal c string 
 756   for(size_t i2 
= nStart 
+ nLen
; i2 
< length(); ++i2
) 
 757       strTmp
.append(1, this->c_str()[i2
]); 
 763 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 764                                     size_t nCount
, wxChar ch
) 
 766   return replace(nStart
, nLen
, wxStringBase(nCount
, ch
).c_str()); 
 769 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 770                                     const wxStringBase
& str
, 
 771                                     size_t nStart2
, size_t nLen2
) 
 773   return replace(nStart
, nLen
, str
.substr(nStart2
, nLen2
)); 
 776 wxStringBase
& wxStringBase::replace(size_t nStart
, size_t nLen
, 
 777                                     const wxChar
* sz
, size_t nCount
) 
 779   return replace(nStart
, nLen
, wxStringBase(sz
, nCount
).c_str()); 
 782 wxStringBase 
wxStringBase::substr(size_t nStart
, size_t nLen
) const 
 785     nLen 
= length() - nStart
; 
 786   return wxStringBase(*this, nStart
, nLen
); 
 789 // assigns one string to another 
 790 wxStringBase
& wxStringBase::operator=(const wxStringBase
& stringSrc
) 
 792   wxASSERT( stringSrc
.GetStringData()->IsValid() ); 
 794   // don't copy string over itself 
 795   if ( m_pchData 
!= stringSrc
.m_pchData 
) { 
 796     if ( stringSrc
.GetStringData()->IsEmpty() ) { 
 801       GetStringData()->Unlock(); 
 802       m_pchData 
= stringSrc
.m_pchData
; 
 803       GetStringData()->Lock(); 
 810 // assigns a single character 
 811 wxStringBase
& wxStringBase::operator=(wxChar ch
) 
 813   if ( !AssignCopy(1, &ch
) ) { 
 814     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") ); 
 820 wxStringBase
& wxStringBase::operator=(const wxChar 
*psz
) 
 822   if ( !AssignCopy(wxStrlen(psz
), psz
) ) { 
 823     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") ); 
 828 // helper function: does real copy 
 829 bool wxStringBase::AssignCopy(size_t nSrcLen
, const wxChar 
*pszSrcData
) 
 831   if ( nSrcLen 
== 0 ) { 
 835     if ( !AllocBeforeWrite(nSrcLen
) ) { 
 836       // allocation failure handled by caller 
 839     memcpy(m_pchData
, pszSrcData
, nSrcLen
*sizeof(wxChar
)); 
 840     GetStringData()->nDataLength 
= nSrcLen
; 
 841     m_pchData
[nSrcLen
] = wxT('\0'); 
 846 // --------------------------------------------------------------------------- 
 847 // string concatenation 
 848 // --------------------------------------------------------------------------- 
 850 // add something to this string 
 851 bool wxStringBase::ConcatSelf(size_t nSrcLen
, const wxChar 
*pszSrcData
, 
 854   STATISTICS_ADD(SummandLength
, nSrcLen
); 
 856   nSrcLen 
= nSrcLen 
< nMaxLen 
? nSrcLen 
: nMaxLen
; 
 858   // concatenating an empty string is a NOP 
 860     wxStringData 
*pData 
= GetStringData(); 
 861     size_t nLen 
= pData
->nDataLength
; 
 862     size_t nNewLen 
= nLen 
+ nSrcLen
; 
 864     // alloc new buffer if current is too small 
 865     if ( pData
->IsShared() ) { 
 866       STATISTICS_ADD(ConcatHit
, 0); 
 868       // we have to allocate another buffer 
 869       wxStringData
* pOldData 
= GetStringData(); 
 870       if ( !AllocBuffer(nNewLen
) ) { 
 871           // allocation failure handled by caller 
 874       memcpy(m_pchData
, pOldData
->data(), nLen
*sizeof(wxChar
)); 
 877     else if ( nNewLen 
> pData
->nAllocLength 
) { 
 878       STATISTICS_ADD(ConcatHit
, 0); 
 881       // we have to grow the buffer 
 882       if ( capacity() < nNewLen 
) { 
 883           // allocation failure handled by caller 
 888       STATISTICS_ADD(ConcatHit
, 1); 
 890       // the buffer is already big enough 
 893     // should be enough space 
 894     wxASSERT( nNewLen 
<= GetStringData()->nAllocLength 
); 
 896     // fast concatenation - all is done in our buffer 
 897     memcpy(m_pchData 
+ nLen
, pszSrcData
, nSrcLen
*sizeof(wxChar
)); 
 899     m_pchData
[nNewLen
] = wxT('\0');          // put terminating '\0' 
 900     GetStringData()->nDataLength 
= nNewLen
; // and fix the length 
 902   //else: the string to append was empty 
 906 // --------------------------------------------------------------------------- 
 907 // simple sub-string extraction 
 908 // --------------------------------------------------------------------------- 
 910 // helper function: clone the data attached to this string 
 911 bool wxStringBase::AllocCopy(wxString
& dest
, int nCopyLen
, int nCopyIndex
) const 
 913   if ( nCopyLen 
== 0 ) { 
 917     if ( !dest
.AllocBuffer(nCopyLen
) ) { 
 918       // allocation failure handled by caller 
 921     memcpy(dest
.m_pchData
, m_pchData 
+ nCopyIndex
, nCopyLen
*sizeof(wxChar
)); 
 928 #if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE) 
 931     #define STRINGCLASS wxStringBase 
 933     #define STRINGCLASS wxString 
 936 static inline int wxDoCmp(const wxChar
* s1
, size_t l1
, 
 937                           const wxChar
* s2
, size_t l2
) 
 940         return wxTmemcmp(s1
, s2
, l1
); 
 943         int ret 
= wxTmemcmp(s1
, s2
, l1
); 
 944         return ret 
== 0 ? -1 : ret
; 
 948         int ret 
= wxTmemcmp(s1
, s2
, l2
); 
 949         return ret 
== 0 ? +1 : ret
; 
 953 int STRINGCLASS::compare(const wxStringBase
& str
) const 
 955     return ::wxDoCmp(data(), length(), str
.data(), str
.length()); 
 958 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 959                          const wxStringBase
& str
) const 
 961     wxASSERT(nStart 
<= length()); 
 962     size_type strLen 
= length() - nStart
; 
 963     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 964     return ::wxDoCmp(data() + nStart
, nLen
, str
.data(), str
.length()); 
 967 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 968                          const wxStringBase
& str
, 
 969                          size_t nStart2
, size_t nLen2
) const 
 971     wxASSERT(nStart 
<= length()); 
 972     wxASSERT(nStart2 
<= str
.length()); 
 973     size_type strLen  
=     length() - nStart
, 
 974               strLen2 
= str
.length() - nStart2
; 
 975     nLen  
= strLen  
< nLen  
? strLen  
: nLen
; 
 976     nLen2 
= strLen2 
< nLen2 
? strLen2 
: nLen2
; 
 977     return ::wxDoCmp(data() + nStart
, nLen
, str
.data() + nStart2
, nLen2
); 
 980 int STRINGCLASS::compare(const wxChar
* sz
) const 
 982     size_t nLen 
= wxStrlen(sz
); 
 983     return ::wxDoCmp(data(), length(), sz
, nLen
); 
 986 int STRINGCLASS::compare(size_t nStart
, size_t nLen
, 
 987                          const wxChar
* sz
, size_t nCount
) const 
 989     wxASSERT(nStart 
<= length()); 
 990     size_type strLen 
= length() - nStart
; 
 991     nLen 
= strLen 
< nLen 
? strLen 
: nLen
; 
 993         nCount 
= wxStrlen(sz
); 
 995     return ::wxDoCmp(data() + nStart
, nLen
, sz
, nCount
); 
1000 #endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE) 
1002 // =========================================================================== 
1003 // wxString class core 
1004 // =========================================================================== 
1006 // --------------------------------------------------------------------------- 
1007 // construction and conversion 
1008 // --------------------------------------------------------------------------- 
1012 // from multibyte string 
1013 wxString::wxString(const char *psz
, wxMBConv
& conv
, size_t nLength
) 
1015     // if nLength != npos, then we have to make a NULL-terminated copy 
1016     // of first nLength bytes of psz first because the input buffer to MB2WC 
1017     // must always be NULL-terminated: 
1018     wxCharBuffer 
inBuf((const char *)NULL
); 
1019     if (nLength 
!= npos
) 
1021         wxASSERT( psz 
!= NULL 
); 
1022         wxCharBuffer 
tmp(nLength
); 
1023         memcpy(tmp
.data(), psz
, nLength
); 
1024         tmp
.data()[nLength
] = '\0'; 
1029     // first get the size of the buffer we need 
1033         // calculate the needed size ourselves or use the provided one 
1034         if (nLength 
== npos
) 
1041         // nothing to convert 
1047     if ( (nLen 
!= 0) && (nLen 
!= (size_t)-1) ) 
1051         wxWCharBuffer theBuffer 
= conv
.cMB2WC(psz
, nLen
, &nRealSize
); 
1055             assign( theBuffer
.data() , nRealSize 
- 1 ); 
1059 //Convert wxString in Unicode mode to a multi-byte string 
1060 const wxCharBuffer 
wxString::mb_str(wxMBConv
& conv
) const 
1063     return conv
.cWC2MB(c_str(), length(), &dwOutSize
); 
1070 wxString::wxString(const wchar_t *pwz
, wxMBConv
& conv
, size_t nLength
) 
1072     // if nLength != npos, then we have to make a NULL-terminated copy 
1073     // of first nLength chars of psz first because the input buffer to WC2MB 
1074     // must always be NULL-terminated: 
1075     wxWCharBuffer 
inBuf((const wchar_t *)NULL
); 
1076     if (nLength 
!= npos
) 
1078         wxASSERT( pwz 
!= NULL 
); 
1079         wxWCharBuffer 
tmp(nLength
); 
1080         memcpy(tmp
.data(), pwz
, nLength 
* sizeof(wchar_t)); 
1081         tmp
.data()[nLength
] = '\0'; 
1086     // first get the size of the buffer we need 
1090         // calculate the needed size ourselves or use the provided one 
1091         if (nLength 
== npos
) 
1092             nLen 
= wxWcslen(pwz
); 
1098         // nothing to convert 
1103     if ( (nLen 
!= 0) && (nLen 
!= (size_t)-1) ) 
1107         wxCharBuffer theBuffer 
= conv
.cWC2MB(pwz
, nLen
, &nRealSize
); 
1111             assign( theBuffer
.data() , nRealSize 
- 1 ); 
1115 //Converts this string to a wide character string if unicode 
1116 //mode is not enabled and wxUSE_WCHAR_T is enabled 
1117 const wxWCharBuffer 
wxString::wc_str(wxMBConv
& conv
) const 
1120     return conv
.cMB2WC(c_str(), length(), &dwOutSize
); 
1123 #endif // wxUSE_WCHAR_T 
1125 #endif // Unicode/ANSI 
1127 // shrink to minimal size (releasing extra memory) 
1128 bool wxString::Shrink() 
1130   wxString 
tmp(begin(), end()); 
1132   return tmp
.length() == length(); 
1136 // get the pointer to writable buffer of (at least) nLen bytes 
1137 wxChar 
*wxString::GetWriteBuf(size_t nLen
) 
1139   if ( !AllocBeforeWrite(nLen
) ) { 
1140     // allocation failure handled by caller 
1144   wxASSERT( GetStringData()->nRefs 
== 1 ); 
1145   GetStringData()->Validate(false); 
1150 // put string back in a reasonable state after GetWriteBuf 
1151 void wxString::UngetWriteBuf() 
1153   GetStringData()->nDataLength 
= wxStrlen(m_pchData
); 
1154   GetStringData()->Validate(true); 
1157 void wxString::UngetWriteBuf(size_t nLen
) 
1159   GetStringData()->nDataLength 
= nLen
; 
1160   GetStringData()->Validate(true); 
1164 // --------------------------------------------------------------------------- 
1166 // --------------------------------------------------------------------------- 
1168 // all functions are inline in string.h 
1170 // --------------------------------------------------------------------------- 
1171 // assignment operators 
1172 // --------------------------------------------------------------------------- 
1176 // same as 'signed char' variant 
1177 wxString
& wxString::operator=(const unsigned char* psz
) 
1179   *this = (const char *)psz
; 
1184 wxString
& wxString::operator=(const wchar_t *pwz
) 
1195  * concatenation functions come in 5 flavours: 
1197  *  char   + string      and      string + char 
1198  *  C str  + string      and      string + C str 
1201 wxString 
operator+(const wxString
& str1
, const wxString
& str2
) 
1204   wxASSERT( str1
.GetStringData()->IsValid() ); 
1205   wxASSERT( str2
.GetStringData()->IsValid() ); 
1214 wxString 
operator+(const wxString
& str
, wxChar ch
) 
1217   wxASSERT( str
.GetStringData()->IsValid() ); 
1226 wxString 
operator+(wxChar ch
, const wxString
& str
) 
1229   wxASSERT( str
.GetStringData()->IsValid() ); 
1238 wxString 
operator+(const wxString
& str
, const wxChar 
*psz
) 
1241   wxASSERT( str
.GetStringData()->IsValid() ); 
1245   if ( !s
.Alloc(wxStrlen(psz
) + str
.Len()) ) { 
1246     wxFAIL_MSG( _T("out of memory in wxString::operator+") ); 
1254 wxString 
operator+(const wxChar 
*psz
, const wxString
& str
) 
1257   wxASSERT( str
.GetStringData()->IsValid() ); 
1261   if ( !s
.Alloc(wxStrlen(psz
) + str
.Len()) ) { 
1262     wxFAIL_MSG( _T("out of memory in wxString::operator+") ); 
1270 // =========================================================================== 
1271 // other common string functions 
1272 // =========================================================================== 
1274 int wxString::Cmp(const wxString
& s
) const 
1279 int wxString::Cmp(const wxChar
* psz
) const 
1281     return compare(psz
); 
1284 static inline int wxDoCmpNoCase(const wxChar
* s1
, size_t l1
, 
1285                                 const wxChar
* s2
, size_t l2
) 
1291         for(i 
= 0; i 
< l1
; ++i
) 
1293             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1296         return i 
== l1 
? 0 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1300         for(i 
= 0; i 
< l1
; ++i
) 
1302             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1305         return i 
== l1 
? -1 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1309         for(i 
= 0; i 
< l2
; ++i
) 
1311             if(wxTolower(s1
[i
]) != wxTolower(s2
[i
])) 
1314         return i 
== l2 
? 1 : wxTolower(s1
[i
]) < wxTolower(s2
[i
]) ? -1 : 1; 
1318 int wxString::CmpNoCase(const wxString
& s
) const 
1320     return wxDoCmpNoCase(data(), length(), s
.data(), s
.length()); 
1323 int wxString::CmpNoCase(const wxChar
* psz
) const 
1325     int nLen 
= wxStrlen(psz
); 
1327     return wxDoCmpNoCase(data(), length(), psz
, nLen
); 
1334 #ifndef __SCHAR_MAX__ 
1335 #define __SCHAR_MAX__ 127 
1339 wxString 
wxString::FromAscii(const char *ascii
) 
1342        return wxEmptyString
; 
1344     size_t len 
= strlen( ascii 
); 
1349         wxStringBuffer 
buf(res
, len
); 
1351         wchar_t *dest 
= buf
; 
1355            if ( (*dest
++ = (wchar_t)(unsigned char)*ascii
++) == L
'\0' ) 
1363 wxString 
wxString::FromAscii(const char ascii
) 
1365     // What do we do with '\0' ? 
1368     res 
+= (wchar_t)(unsigned char) ascii
; 
1373 const wxCharBuffer 
wxString::ToAscii() const 
1375     // this will allocate enough space for the terminating NUL too 
1376     wxCharBuffer 
buffer(length()); 
1379     char *dest 
= buffer
.data(); 
1381     const wchar_t *pwc 
= c_str(); 
1384         *dest
++ = (char)(*pwc 
> SCHAR_MAX 
? wxT('_') : *pwc
); 
1386         // the output string can't have embedded NULs anyhow, so we can safely 
1387         // stop at first of them even if we do have any 
1397 // extract string of length nCount starting at nFirst 
1398 wxString 
wxString::Mid(size_t nFirst
, size_t nCount
) const 
1400   size_t nLen 
= length(); 
1402   // default value of nCount is npos and means "till the end" 
1403   if ( nCount 
== npos 
) 
1405     nCount 
= nLen 
- nFirst
; 
1408   // out-of-bounds requests return sensible things 
1409   if ( nFirst 
+ nCount 
> nLen 
) 
1411     nCount 
= nLen 
- nFirst
; 
1414   if ( nFirst 
> nLen 
) 
1416     // AllocCopy() will return empty string 
1420   wxString 
dest(*this, nFirst
, nCount
); 
1421   if ( dest
.length() != nCount 
) { 
1422       wxFAIL_MSG( _T("out of memory in wxString::Mid") ); 
1428 // check that the string starts with prefix and return the rest of the string 
1429 // in the provided pointer if it is not NULL, otherwise return false 
1430 bool wxString::StartsWith(const wxChar 
*prefix
, wxString 
*rest
) const 
1432     wxASSERT_MSG( prefix
, _T("invalid parameter in wxString::StartsWith") ); 
1434     // first check if the beginning of the string matches the prefix: note 
1435     // that we don't have to check that we don't run out of this string as 
1436     // when we reach the terminating NUL, either prefix string ends too (and 
1437     // then it's ok) or we break out of the loop because there is no match 
1438     const wxChar 
*p 
= c_str(); 
1441         if ( *prefix
++ != *p
++ ) 
1450         // put the rest of the string into provided pointer 
1457 // extract nCount last (rightmost) characters 
1458 wxString 
wxString::Right(size_t nCount
) const 
1460   if ( nCount 
> length() ) 
1463   wxString 
dest(*this, length() - nCount
, nCount
); 
1464   if ( dest
.length() != nCount 
) { 
1465     wxFAIL_MSG( _T("out of memory in wxString::Right") ); 
1470 // get all characters after the last occurence of ch 
1471 // (returns the whole string if ch not found) 
1472 wxString 
wxString::AfterLast(wxChar ch
) const 
1475   int iPos 
= Find(ch
, true); 
1476   if ( iPos 
== wxNOT_FOUND 
) 
1479     str 
= c_str() + iPos 
+ 1; 
1484 // extract nCount first (leftmost) characters 
1485 wxString 
wxString::Left(size_t nCount
) const 
1487   if ( nCount 
> length() ) 
1490   wxString 
dest(*this, 0, nCount
); 
1491   if ( dest
.length() != nCount 
) { 
1492     wxFAIL_MSG( _T("out of memory in wxString::Left") ); 
1497 // get all characters before the first occurence of ch 
1498 // (returns the whole string if ch not found) 
1499 wxString 
wxString::BeforeFirst(wxChar ch
) const 
1501   int iPos 
= Find(ch
); 
1502   if ( iPos 
== wxNOT_FOUND 
) iPos 
= length(); 
1503   return wxString(*this, 0, iPos
); 
1506 /// get all characters before the last occurence of ch 
1507 /// (returns empty string if ch not found) 
1508 wxString 
wxString::BeforeLast(wxChar ch
) const 
1511   int iPos 
= Find(ch
, true); 
1512   if ( iPos 
!= wxNOT_FOUND 
&& iPos 
!= 0 ) 
1513     str 
= wxString(c_str(), iPos
); 
1518 /// get all characters after the first occurence of ch 
1519 /// (returns empty string if ch not found) 
1520 wxString 
wxString::AfterFirst(wxChar ch
) const 
1523   int iPos 
= Find(ch
); 
1524   if ( iPos 
!= wxNOT_FOUND 
) 
1525     str 
= c_str() + iPos 
+ 1; 
1530 // replace first (or all) occurences of some substring with another one 
1531 size_t wxString::Replace(const wxChar 
*szOld
, 
1532                   const wxChar 
*szNew
, bool bReplaceAll
) 
1534     // if we tried to replace an empty string we'd enter an infinite loop below 
1535     wxCHECK_MSG( szOld 
&& *szOld 
&& szNew
, 0, 
1536                  _T("wxString::Replace(): invalid parameter") ); 
1538     size_t uiCount 
= 0;   // count of replacements made 
1540     size_t uiOldLen 
= wxStrlen(szOld
); 
1541     size_t uiNewLen 
= wxStrlen(szNew
); 
1545     while ( this->c_str()[dwPos
] != wxT('\0') ) 
1547         //DO NOT USE STRSTR HERE 
1548         //this string can contain embedded null characters, 
1549         //so strstr will function incorrectly 
1550         dwPos 
= find(szOld
, dwPos
); 
1551         if ( dwPos 
== npos 
) 
1552             break;                  // exit the loop 
1555             //replace this occurance of the old string with the new one 
1556             replace(dwPos
, uiOldLen
, szNew
, uiNewLen
); 
1558             //move up pos past the string that was replaced 
1561             //increase replace count 
1566                 break;                  // exit the loop 
1573 bool wxString::IsAscii() const 
1575   const wxChar 
*s 
= (const wxChar
*) *this; 
1577     if(!isascii(*s
)) return(false); 
1583 bool wxString::IsWord() const 
1585   const wxChar 
*s 
= (const wxChar
*) *this; 
1587     if(!wxIsalpha(*s
)) return(false); 
1593 bool wxString::IsNumber() const 
1595   const wxChar 
*s 
= (const wxChar
*) *this; 
1597      if ((s
[0] == wxT('-')) || (s
[0] == wxT('+'))) s
++; 
1599     if(!wxIsdigit(*s
)) return(false); 
1605 wxString 
wxString::Strip(stripType w
) const 
1608     if ( w 
& leading 
) s
.Trim(false); 
1609     if ( w 
& trailing 
) s
.Trim(true); 
1613 // --------------------------------------------------------------------------- 
1615 // --------------------------------------------------------------------------- 
1617 wxString
& wxString::MakeUpper() 
1619   for ( iterator it 
= begin(), en 
= end(); it 
!= en
; ++it 
) 
1620     *it 
= (wxChar
)wxToupper(*it
); 
1625 wxString
& wxString::MakeLower() 
1627   for ( iterator it 
= begin(), en 
= end(); it 
!= en
; ++it 
) 
1628     *it 
= (wxChar
)wxTolower(*it
); 
1633 // --------------------------------------------------------------------------- 
1634 // trimming and padding 
1635 // --------------------------------------------------------------------------- 
1637 // some compilers (VC++ 6.0 not to name them) return true for a call to 
1638 // isspace('ê') in the C locale which seems to be broken to me, but we have to 
1639 // live with this by checking that the character is a 7 bit one - even if this 
1640 // may fail to detect some spaces (I don't know if Unicode doesn't have 
1641 // space-like symbols somewhere except in the first 128 chars), it is arguably 
1642 // still better than trimming away accented letters 
1643 inline int wxSafeIsspace(wxChar ch
) { return (ch 
< 127) && wxIsspace(ch
); } 
1645 // trims spaces (in the sense of isspace) from left or right side 
1646 wxString
& wxString::Trim(bool bFromRight
) 
1648   // first check if we're going to modify the string at all 
1651         (bFromRight 
&& wxSafeIsspace(GetChar(Len() - 1))) || 
1652         (!bFromRight 
&& wxSafeIsspace(GetChar(0u))) 
1658       // find last non-space character 
1659       iterator psz 
= begin() + length() - 1; 
1660       while ( wxSafeIsspace(*psz
) && (psz 
>= begin()) ) 
1663       // truncate at trailing space start 
1669       // find first non-space character 
1670       iterator psz 
= begin(); 
1671       while ( wxSafeIsspace(*psz
) ) 
1674       // fix up data and length 
1675       erase(begin(), psz
); 
1682 // adds nCount characters chPad to the string from either side 
1683 wxString
& wxString::Pad(size_t nCount
, wxChar chPad
, bool bFromRight
) 
1685   wxString 
s(chPad
, nCount
); 
1698 // truncate the string 
1699 wxString
& wxString::Truncate(size_t uiLen
) 
1701   if ( uiLen 
< Len() ) { 
1702     erase(begin() + uiLen
, end()); 
1704   //else: nothing to do, string is already short enough 
1709 // --------------------------------------------------------------------------- 
1710 // finding (return wxNOT_FOUND if not found and index otherwise) 
1711 // --------------------------------------------------------------------------- 
1714 int wxString::Find(wxChar ch
, bool bFromEnd
) const 
1716   size_type idx 
= bFromEnd 
? find_last_of(ch
) : find_first_of(ch
); 
1718   return (idx 
== npos
) ? wxNOT_FOUND 
: (int)idx
; 
1721 // find a sub-string (like strstr) 
1722 int wxString::Find(const wxChar 
*pszSub
) const 
1724   size_type idx 
= find(pszSub
); 
1726   return (idx 
== npos
) ? wxNOT_FOUND 
: (int)idx
; 
1729 // ---------------------------------------------------------------------------- 
1730 // conversion to numbers 
1731 // ---------------------------------------------------------------------------- 
1733 bool wxString::ToLong(long *val
, int base
) const 
1735     wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToLong") ); 
1736     wxASSERT_MSG( !base 
|| (base 
> 1 && base 
<= 36), _T("invalid base") ); 
1738     const wxChar 
*start 
= c_str(); 
1740     *val 
= wxStrtol(start
, &end
, base
); 
1742     // return true only if scan was stopped by the terminating NUL and if the 
1743     // string was not empty to start with 
1744     return !*end 
&& (end 
!= start
); 
1747 bool wxString::ToULong(unsigned long *val
, int base
) const 
1749     wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToULong") ); 
1750     wxASSERT_MSG( !base 
|| (base 
> 1 && base 
<= 36), _T("invalid base") ); 
1752     const wxChar 
*start 
= c_str(); 
1754     *val 
= wxStrtoul(start
, &end
, base
); 
1756     // return true only if scan was stopped by the terminating NUL and if the 
1757     // string was not empty to start with 
1758     return !*end 
&& (end 
!= start
); 
1761 bool wxString::ToDouble(double *val
) const 
1763     wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToDouble") ); 
1765     const wxChar 
*start 
= c_str(); 
1767     *val 
= wxStrtod(start
, &end
); 
1769     // return true only if scan was stopped by the terminating NUL and if the 
1770     // string was not empty to start with 
1771     return !*end 
&& (end 
!= start
); 
1774 // --------------------------------------------------------------------------- 
1776 // --------------------------------------------------------------------------- 
1779 wxString 
wxString::Format(const wxChar 
*pszFormat
, ...) 
1782     va_start(argptr
, pszFormat
); 
1785     s
.PrintfV(pszFormat
, argptr
); 
1793 wxString 
wxString::FormatV(const wxChar 
*pszFormat
, va_list argptr
) 
1796     s
.PrintfV(pszFormat
, argptr
); 
1800 int wxString::Printf(const wxChar 
*pszFormat
, ...) 
1803     va_start(argptr
, pszFormat
); 
1805     int iLen 
= PrintfV(pszFormat
, argptr
); 
1812 int wxString::PrintfV(const wxChar
* pszFormat
, va_list argptr
) 
1818         wxStringBuffer 
tmp(*this, size 
+ 1); 
1827         // wxVsnprintf() may modify the original arg pointer, so pass it 
1830         wxVaCopy(argptrcopy
, argptr
); 
1831         int len 
= wxVsnprintf(buf
, size
, pszFormat
, argptrcopy
); 
1834         // some implementations of vsnprintf() don't NUL terminate 
1835         // the string if there is not enough space for it so 
1836         // always do it manually 
1837         buf
[size
] = _T('\0'); 
1839         // vsnprintf() may return either -1 (traditional Unix behaviour) or the 
1840         // total number of characters which would have been written if the 
1841         // buffer were large enough 
1842         if ( len 
>= 0 && len 
<= size 
) 
1844             // ok, there was enough space 
1849         // if the error is not due to not having enough space (it could be e.g. 
1850         // EILSEQ), break too -- we'd just eat all available memory uselessly 
1851         if ( errno 
!= EOVERFLOW 
) 
1853             // no sense in continuing 
1858         // still not enough, double it again 
1862     // we could have overshot 
1868 // ---------------------------------------------------------------------------- 
1869 // misc other operations 
1870 // ---------------------------------------------------------------------------- 
1872 // returns true if the string matches the pattern which may contain '*' and 
1873 // '?' metacharacters (as usual, '?' matches any character and '*' any number 
1875 bool wxString::Matches(const wxChar 
*pszMask
) const 
1877     // I disable this code as it doesn't seem to be faster (in fact, it seems 
1878     // to be much slower) than the old, hand-written code below and using it 
1879     // here requires always linking with libregex even if the user code doesn't 
1881 #if 0 // wxUSE_REGEX 
1882     // first translate the shell-like mask into a regex 
1884     pattern
.reserve(wxStrlen(pszMask
)); 
1896                 pattern 
+= _T(".*"); 
1907                 // these characters are special in a RE, quote them 
1908                 // (however note that we don't quote '[' and ']' to allow 
1909                 // using them for Unix shell like matching) 
1910                 pattern 
+= _T('\\'); 
1914                 pattern 
+= *pszMask
; 
1922     return wxRegEx(pattern
, wxRE_NOSUB 
| wxRE_EXTENDED
).Matches(c_str()); 
1923 #else // !wxUSE_REGEX 
1924   // TODO: this is, of course, awfully inefficient... 
1926   // the char currently being checked 
1927   const wxChar 
*pszTxt 
= c_str(); 
1929   // the last location where '*' matched 
1930   const wxChar 
*pszLastStarInText 
= NULL
; 
1931   const wxChar 
*pszLastStarInMask 
= NULL
; 
1934   for ( ; *pszMask 
!= wxT('\0'); pszMask
++, pszTxt
++ ) { 
1935     switch ( *pszMask 
) { 
1937         if ( *pszTxt 
== wxT('\0') ) 
1940         // pszTxt and pszMask will be incremented in the loop statement 
1946           // remember where we started to be able to backtrack later 
1947           pszLastStarInText 
= pszTxt
; 
1948           pszLastStarInMask 
= pszMask
; 
1950           // ignore special chars immediately following this one 
1951           // (should this be an error?) 
1952           while ( *pszMask 
== wxT('*') || *pszMask 
== wxT('?') ) 
1955           // if there is nothing more, match 
1956           if ( *pszMask 
== wxT('\0') ) 
1959           // are there any other metacharacters in the mask? 
1961           const wxChar 
*pEndMask 
= wxStrpbrk(pszMask
, wxT("*?")); 
1963           if ( pEndMask 
!= NULL 
) { 
1964             // we have to match the string between two metachars 
1965             uiLenMask 
= pEndMask 
- pszMask
; 
1968             // we have to match the remainder of the string 
1969             uiLenMask 
= wxStrlen(pszMask
); 
1972           wxString 
strToMatch(pszMask
, uiLenMask
); 
1973           const wxChar
* pMatch 
= wxStrstr(pszTxt
, strToMatch
); 
1974           if ( pMatch 
== NULL 
) 
1977           // -1 to compensate "++" in the loop 
1978           pszTxt 
= pMatch 
+ uiLenMask 
- 1; 
1979           pszMask 
+= uiLenMask 
- 1; 
1984         if ( *pszMask 
!= *pszTxt 
) 
1990   // match only if nothing left 
1991   if ( *pszTxt 
== wxT('\0') ) 
1994   // if we failed to match, backtrack if we can 
1995   if ( pszLastStarInText 
) { 
1996     pszTxt 
= pszLastStarInText 
+ 1; 
1997     pszMask 
= pszLastStarInMask
; 
1999     pszLastStarInText 
= NULL
; 
2001     // don't bother resetting pszLastStarInMask, it's unnecessary 
2007 #endif // wxUSE_REGEX/!wxUSE_REGEX 
2010 // Count the number of chars 
2011 int wxString::Freq(wxChar ch
) const 
2015     for (int i 
= 0; i 
< len
; i
++) 
2017         if (GetChar(i
) == ch
) 
2023 // convert to upper case, return the copy of the string 
2024 wxString 
wxString::Upper() const 
2025 { wxString 
s(*this); return s
.MakeUpper(); } 
2027 // convert to lower case, return the copy of the string 
2028 wxString 
wxString::Lower() const { wxString 
s(*this); return s
.MakeLower(); } 
2030 int wxString::sprintf(const wxChar 
*pszFormat
, ...) 
2033     va_start(argptr
, pszFormat
); 
2034     int iLen 
= PrintfV(pszFormat
, argptr
); 
2039 // ============================================================================ 
2041 // ============================================================================ 
2043 #include "wx/arrstr.h" 
2045 wxArrayString::wxArrayString(size_t sz
, const wxChar
** a
) 
2050     for (size_t i
=0; i 
< sz
; i
++) 
2054 wxArrayString::wxArrayString(size_t sz
, const wxString
* a
) 
2059     for (size_t i
=0; i 
< sz
; i
++) 
2065 // size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT) 
2066 #define   ARRAY_MAXSIZE_INCREMENT       4096 
2068 #ifndef   ARRAY_DEFAULT_INITIAL_SIZE    // also defined in dynarray.h 
2069 #define   ARRAY_DEFAULT_INITIAL_SIZE    (16) 
2072 #define   STRING(p)   ((wxString *)(&(p))) 
2075 void wxArrayString::Init(bool autoSort
) 
2079   m_pItems 
= (wxChar 
**) NULL
; 
2080   m_autoSort 
= autoSort
; 
2084 wxArrayString::wxArrayString(const wxArrayString
& src
) 
2086   Init(src
.m_autoSort
); 
2091 // assignment operator 
2092 wxArrayString
& wxArrayString::operator=(const wxArrayString
& src
) 
2099   m_autoSort 
= src
.m_autoSort
; 
2104 void wxArrayString::Copy(const wxArrayString
& src
) 
2106   if ( src
.m_nCount 
> ARRAY_DEFAULT_INITIAL_SIZE 
) 
2107     Alloc(src
.m_nCount
); 
2109   for ( size_t n 
= 0; n 
< src
.m_nCount
; n
++ ) 
2114 void wxArrayString::Grow(size_t nIncrement
) 
2116   // only do it if no more place 
2117   if ( (m_nSize 
- m_nCount
) < nIncrement 
) { 
2118     // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would 
2119     // be never resized! 
2120     #if ARRAY_DEFAULT_INITIAL_SIZE == 0 
2121       #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!" 
2124     if ( m_nSize 
== 0 ) { 
2125       // was empty, alloc some memory 
2126       m_nSize 
= ARRAY_DEFAULT_INITIAL_SIZE
; 
2127       if (m_nSize 
< nIncrement
) 
2128           m_nSize 
= nIncrement
; 
2129       m_pItems 
= new wxChar 
*[m_nSize
]; 
2132       // otherwise when it's called for the first time, nIncrement would be 0 
2133       // and the array would never be expanded 
2134       // add 50% but not too much 
2135       size_t ndefIncrement 
= m_nSize 
< ARRAY_DEFAULT_INITIAL_SIZE
 
2136                           ? ARRAY_DEFAULT_INITIAL_SIZE 
: m_nSize 
>> 1; 
2137       if ( ndefIncrement 
> ARRAY_MAXSIZE_INCREMENT 
) 
2138         ndefIncrement 
= ARRAY_MAXSIZE_INCREMENT
; 
2139       if ( nIncrement 
< ndefIncrement 
) 
2140         nIncrement 
= ndefIncrement
; 
2141       m_nSize 
+= nIncrement
; 
2142       wxChar 
**pNew 
= new wxChar 
*[m_nSize
]; 
2144       // copy data to new location 
2145       memcpy(pNew
, m_pItems
, m_nCount
*sizeof(wxChar 
*)); 
2147       // delete old memory (but do not release the strings!) 
2148       wxDELETEA(m_pItems
); 
2155 void wxArrayString::Free() 
2157   for ( size_t n 
= 0; n 
< m_nCount
; n
++ ) { 
2158     STRING(m_pItems
[n
])->GetStringData()->Unlock(); 
2162 // deletes all the strings from the list 
2163 void wxArrayString::Empty() 
2170 // as Empty, but also frees memory 
2171 void wxArrayString::Clear() 
2178   wxDELETEA(m_pItems
); 
2182 wxArrayString::~wxArrayString() 
2186   wxDELETEA(m_pItems
); 
2189 void wxArrayString::reserve(size_t nSize
) 
2194 // pre-allocates memory (frees the previous data!) 
2195 void wxArrayString::Alloc(size_t nSize
) 
2197   // only if old buffer was not big enough 
2198   if ( nSize 
> m_nSize 
) { 
2200     wxDELETEA(m_pItems
); 
2201     m_pItems 
= new wxChar 
*[nSize
]; 
2208 // minimizes the memory usage by freeing unused memory 
2209 void wxArrayString::Shrink() 
2211   // only do it if we have some memory to free 
2212   if( m_nCount 
< m_nSize 
) { 
2213     // allocates exactly as much memory as we need 
2214     wxChar 
**pNew 
= new wxChar 
*[m_nCount
]; 
2216     // copy data to new location 
2217     memcpy(pNew
, m_pItems
, m_nCount
*sizeof(wxChar 
*)); 
2223 #if WXWIN_COMPATIBILITY_2_4 
2225 // return a wxString[] as required for some control ctors. 
2226 wxString
* wxArrayString::GetStringArray() const 
2228     wxString 
*array 
= 0; 
2232         array 
= new wxString
[m_nCount
]; 
2233         for( size_t i 
= 0; i 
< m_nCount
; i
++ ) 
2234             array
[i
] = m_pItems
[i
]; 
2240 void wxArrayString::Remove(size_t nIndex
, size_t nRemove
) 
2242     RemoveAt(nIndex
, nRemove
); 
2245 #endif // WXWIN_COMPATIBILITY_2_4 
2247 // searches the array for an item (forward or backwards) 
2248 int wxArrayString::Index(const wxChar 
*sz
, bool bCase
, bool bFromEnd
) const 
2251     // use binary search in the sorted array 
2252     wxASSERT_MSG( bCase 
&& !bFromEnd
, 
2253                   wxT("search parameters ignored for auto sorted array") ); 
2262       res 
= wxStrcmp(sz
, m_pItems
[i
]); 
2274     // use linear search in unsorted array 
2276       if ( m_nCount 
> 0 ) { 
2277         size_t ui 
= m_nCount
; 
2279           if ( STRING(m_pItems
[--ui
])->IsSameAs(sz
, bCase
) ) 
2286       for( size_t ui 
= 0; ui 
< m_nCount
; ui
++ ) { 
2287         if( STRING(m_pItems
[ui
])->IsSameAs(sz
, bCase
) ) 
2296 // add item at the end 
2297 size_t wxArrayString::Add(const wxString
& str
, size_t nInsert
) 
2300     // insert the string at the correct position to keep the array sorted 
2308       res 
= str
.Cmp(m_pItems
[i
]); 
2319     wxASSERT_MSG( lo 
== hi
, wxT("binary search broken") ); 
2321     Insert(str
, lo
, nInsert
); 
2326     wxASSERT( str
.GetStringData()->IsValid() ); 
2330     for (size_t i 
= 0; i 
< nInsert
; i
++) 
2332         // the string data must not be deleted! 
2333         str
.GetStringData()->Lock(); 
2336         m_pItems
[m_nCount 
+ i
] = (wxChar 
*)str
.c_str(); // const_cast 
2338     size_t ret 
= m_nCount
; 
2339     m_nCount 
+= nInsert
; 
2344 // add item at the given position 
2345 void wxArrayString::Insert(const wxString
& str
, size_t nIndex
, size_t nInsert
) 
2347   wxASSERT( str
.GetStringData()->IsValid() ); 
2349   wxCHECK_RET( nIndex 
<= m_nCount
, wxT("bad index in wxArrayString::Insert") ); 
2350   wxCHECK_RET( m_nCount 
<= m_nCount 
+ nInsert
, 
2351                wxT("array size overflow in wxArrayString::Insert") ); 
2355   memmove(&m_pItems
[nIndex 
+ nInsert
], &m_pItems
[nIndex
], 
2356           (m_nCount 
- nIndex
)*sizeof(wxChar 
*)); 
2358   for (size_t i 
= 0; i 
< nInsert
; i
++) 
2360       str
.GetStringData()->Lock(); 
2361       m_pItems
[nIndex 
+ i
] = (wxChar 
*)str
.c_str(); 
2363   m_nCount 
+= nInsert
; 
2366 // range insert (STL 23.2.4.3) 
2368 wxArrayString::insert(iterator it
, const_iterator first
, const_iterator last
) 
2370     const int idx 
= it 
- begin(); 
2375     // reset "it" since it can change inside Grow() 
2378     while ( first 
!= last 
) 
2380         it 
= insert(it
, *first
); 
2382         // insert returns an iterator to the last element inserted but we need 
2383         // insert the next after this one, that is before the next one 
2391 void wxArrayString::SetCount(size_t count
) 
2396     while ( m_nCount 
< count 
) 
2397         m_pItems
[m_nCount
++] = (wxChar 
*)s
.c_str(); 
2400 // removes item from array (by index) 
2401 void wxArrayString::RemoveAt(size_t nIndex
, size_t nRemove
) 
2403   wxCHECK_RET( nIndex 
< m_nCount
, wxT("bad index in wxArrayString::Remove") ); 
2404   wxCHECK_RET( nIndex 
+ nRemove 
<= m_nCount
, 
2405                wxT("removing too many elements in wxArrayString::Remove") ); 
2408   for (size_t i 
= 0; i 
< nRemove
; i
++) 
2409       Item(nIndex 
+ i
).GetStringData()->Unlock(); 
2411   memmove(&m_pItems
[nIndex
], &m_pItems
[nIndex 
+ nRemove
], 
2412           (m_nCount 
- nIndex 
- nRemove
)*sizeof(wxChar 
*)); 
2413   m_nCount 
-= nRemove
; 
2416 // removes item from array (by value) 
2417 void wxArrayString::Remove(const wxChar 
*sz
) 
2419   int iIndex 
= Index(sz
); 
2421   wxCHECK_RET( iIndex 
!= wxNOT_FOUND
, 
2422                wxT("removing inexistent element in wxArrayString::Remove") ); 
2427 void wxArrayString::assign(const_iterator first
, const_iterator last
) 
2429     reserve(last 
- first
); 
2430     for(; first 
!= last
; ++first
) 
2434 // ---------------------------------------------------------------------------- 
2436 // ---------------------------------------------------------------------------- 
2438 // we can only sort one array at a time with the quick-sort based 
2441   // need a critical section to protect access to gs_compareFunction and 
2442   // gs_sortAscending variables 
2443   static wxCriticalSection 
*gs_critsectStringSort 
= NULL
; 
2445   // call this before the value of the global sort vars is changed/after 
2446   // you're finished with them 
2447   #define START_SORT()     wxASSERT( !gs_critsectStringSort );                \ 
2448                            gs_critsectStringSort = new wxCriticalSection;     \ 
2449                            gs_critsectStringSort->Enter() 
2450   #define END_SORT()       gs_critsectStringSort->Leave();                    \ 
2451                            delete gs_critsectStringSort;                      \ 
2452                            gs_critsectStringSort = NULL 
2454   #define START_SORT() 
2456 #endif // wxUSE_THREADS 
2458 // function to use for string comparaison 
2459 static wxArrayString::CompareFunction gs_compareFunction 
= NULL
; 
2461 // if we don't use the compare function, this flag tells us if we sort the 
2462 // array in ascending or descending order 
2463 static bool gs_sortAscending 
= true; 
2465 // function which is called by quick sort 
2466 extern "C" int wxC_CALLING_CONV     
// LINKAGEMODE 
2467 wxStringCompareFunction(const void *first
, const void *second
) 
2469   wxString 
*strFirst 
= (wxString 
*)first
; 
2470   wxString 
*strSecond 
= (wxString 
*)second
; 
2472   if ( gs_compareFunction 
) { 
2473     return gs_compareFunction(*strFirst
, *strSecond
); 
2476     // maybe we should use wxStrcoll 
2477     int result 
= strFirst
->Cmp(*strSecond
); 
2479     return gs_sortAscending 
? result 
: -result
; 
2483 // sort array elements using passed comparaison function 
2484 void wxArrayString::Sort(CompareFunction compareFunction
) 
2488   wxASSERT( !gs_compareFunction 
);  // must have been reset to NULL 
2489   gs_compareFunction 
= compareFunction
; 
2493   // reset it to NULL so that Sort(bool) will work the next time 
2494   gs_compareFunction 
= NULL
; 
2499 typedef  int (wxC_CALLING_CONV 
* wxStringCompareFn
)(const void *first
, const void *second
); 
2501 void wxArrayString::Sort(CompareFunction2 compareFunction
) 
2503   qsort(m_pItems
, m_nCount
, sizeof(wxChar 
*), (wxStringCompareFn
)compareFunction
); 
2506 void wxArrayString::Sort(bool reverseOrder
) 
2508   Sort(reverseOrder 
? wxStringSortDescending 
: wxStringSortAscending
); 
2511 void wxArrayString::DoSort() 
2513   wxCHECK_RET( !m_autoSort
, wxT("can't use this method with sorted arrays") ); 
2515   // just sort the pointers using qsort() - of course it only works because 
2516   // wxString() *is* a pointer to its data 
2517   qsort(m_pItems
, m_nCount
, sizeof(wxChar 
*), wxStringCompareFunction
); 
2520 bool wxArrayString::operator==(const wxArrayString
& a
) const 
2522     if ( m_nCount 
!= a
.m_nCount 
) 
2525     for ( size_t n 
= 0; n 
< m_nCount
; n
++ ) 
2527         if ( Item(n
) != a
[n
] ) 
2534 #endif // !wxUSE_STL 
2536 int wxCMPFUNC_CONV 
wxStringSortAscending(wxString
* s1
, wxString
* s2
) 
2538     return  s1
->Cmp(*s2
); 
2541 int wxCMPFUNC_CONV 
wxStringSortDescending(wxString
* s1
, wxString
* s2
) 
2543     return -s1
->Cmp(*s2
);