1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/common/string.cpp
3// Purpose:     wxString class
4// Author:      Vadim Zeitlin, Ryan Norton
5// Modified by:
6// Created:     29/01/98
7// RCS-ID:      $Id: string.cpp 63008 2009-12-28 20:01:39Z VZ $
8// Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9//              (c) 2004 Ryan Norton <wxprojects@comcast.net>
10// Licence:     wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13/*
14 * About ref counting:
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
18 */
19
20// ===========================================================================
21// headers, declarations, constants
22// ===========================================================================
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28    #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32    #include "wx/string.h"
33    #include "wx/intl.h"
34    #include "wx/thread.h"
35#endif
36
37#include <ctype.h>
38
39#ifndef __WXWINCE__
40    #include <errno.h>
41#endif
42
43#include <string.h>
44#include <stdlib.h>
45
46#ifdef __SALFORDC__
47    #include <clib.h>
48#endif
49
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)
54
55// ---------------------------------------------------------------------------
56// static class variables definition
57// ---------------------------------------------------------------------------
58
59#if !wxUSE_STL
60  //According to STL _must_ be a -1 size_t
61  const size_t wxStringBase::npos = (size_t) -1;
62#endif
63
64// ----------------------------------------------------------------------------
65// static data
66// ----------------------------------------------------------------------------
67
68#if wxUSE_STL
69
70extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = _T("");
71
72#else
73
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)
77static const struct
78{
79  wxStringData data;
80  wxChar dummy;
81} g_strEmpty = { {-1, 0, 0}, wxT('\0') };
82
83// empty C style string: points to 'string data' byte of g_strEmpty
84extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy;
85
86#endif
87
88// ----------------------------------------------------------------------------
89// global functions
90// ----------------------------------------------------------------------------
91
92#if wxUSE_STD_IOSTREAM
93
94#include <iostream>
95
96wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
97{
98#ifdef __BORLANDC__
99    os << str.mb_str();
100#else
101    os << str.c_str();
102#endif
103    return os;
104}
105
106#endif // wxUSE_STD_IOSTREAM
107
108// ----------------------------------------------------------------------------
109// private classes
110// ----------------------------------------------------------------------------
111
112// this small class is used to gather statistics for performance tuning
113//#define WXSTRING_STATISTICS
114#ifdef  WXSTRING_STATISTICS
115  class Averager
116  {
117  public:
118    Averager(const wxChar *sz) { m_sz = sz; m_nTotal = m_nCount = 0; }
119   ~Averager()
120   { wxPrintf("wxString: average %s = %f\n", m_sz, ((float)m_nTotal)/m_nCount); }
121
122    void Add(size_t n) { m_nTotal += n; m_nCount++; }
123
124  private:
125    size_t m_nCount, m_nTotal;
126    const wxChar *m_sz;
127  } g_averageLength("allocation size"),
128    g_averageSummandLength("summand length"),
129    g_averageConcatHit("hit probability in concat"),
130    g_averageInitialLength("initial string length");
131
132  #define STATISTICS_ADD(av, val) g_average##av.Add(val)
133#else
134  #define STATISTICS_ADD(av, val)
135#endif // WXSTRING_STATISTICS
136
137#if !wxUSE_STL
138
139// ===========================================================================
140// wxStringData class deallocation
141// ===========================================================================
142
143#if defined(__VISUALC__) && defined(_MT) && !defined(_DLL)
144#  pragma message (__FILE__ ": building with Multithreaded non DLL runtime has a performance impact on wxString!")
145void wxStringData::Free()
146{
147    free(this);
148}
149#endif
150
151// ===========================================================================
152// wxStringBase
153// ===========================================================================
154
155// takes nLength elements of psz starting at nPos
156void wxStringBase::InitWith(const wxChar *psz, size_t nPos, size_t nLength)
157{
158  Init();
159
160  // if the length is not given, assume the string to be NUL terminated
161  if ( nLength == npos ) {
162    wxASSERT_MSG( nPos <= wxStrlen(psz), _T("index out of bounds") );
163
164    nLength = wxStrlen(psz + nPos);
165  }
166
167  STATISTICS_ADD(InitialLength, nLength);
168
169  if ( nLength > 0 ) {
170    // trailing '\0' is written in AllocBuffer()
171    if ( !AllocBuffer(nLength) ) {
172      wxFAIL_MSG( _T("out of memory in wxStringBase::InitWith") );
173      return;
174    }
175    wxTmemcpy(m_pchData, psz + nPos, nLength);
176  }
177}
178
179// poor man's iterators are "void *" pointers
180wxStringBase::wxStringBase(const void *pStart, const void *pEnd)
181{
182  if ( pEnd >= pStart )
183  {
184    InitWith((const wxChar *)pStart, 0,
185             (const wxChar *)pEnd - (const wxChar *)pStart);
186  }
187  else
188  {
189    wxFAIL_MSG( _T("pStart is not before pEnd") );
190    Init();
191  }
192}
193
194wxStringBase::wxStringBase(size_type n, wxChar ch)
195{
196  Init();
197  append(n, ch);
198}
199
200// ---------------------------------------------------------------------------
201// memory allocation
202// ---------------------------------------------------------------------------
203
204// allocates memory needed to store a C string of length nLen
205bool wxStringBase::AllocBuffer(size_t nLen)
206{
207  // allocating 0 sized buffer doesn't make sense, all empty strings should
208  // reuse g_strEmpty
209  wxASSERT( nLen >  0 );
210
211  // make sure that we don't overflow
212  wxCHECK( nLen < (INT_MAX / sizeof(wxChar)) -
213                  (sizeof(wxStringData) + EXTRA_ALLOC + 1), false );
214
215  STATISTICS_ADD(Length, nLen);
216
217  // allocate memory:
218  // 1) one extra character for '\0' termination
219  // 2) sizeof(wxStringData) for housekeeping info
220  wxStringData* pData = (wxStringData*)
221    malloc(sizeof(wxStringData) + (nLen + EXTRA_ALLOC + 1)*sizeof(wxChar));
222
223  if ( pData == NULL ) {
224    // allocation failures are handled by the caller
225    return false;
226  }
227
228  pData->nRefs        = 1;
229  pData->nDataLength  = nLen;
230  pData->nAllocLength = nLen + EXTRA_ALLOC;
231  m_pchData           = pData->data();  // data starts after wxStringData
232  m_pchData[nLen]     = wxT('\0');
233  return true;
234}
235
236// must be called before changing this string
237bool wxStringBase::CopyBeforeWrite()
238{
239  wxStringData* pData = GetStringData();
240
241  if ( pData->IsShared() ) {
242    pData->Unlock();                // memory not freed because shared
243    size_t nLen = pData->nDataLength;
244    if ( !AllocBuffer(nLen) ) {
245      // allocation failures are handled by the caller
246      return false;
247    }
248    wxTmemcpy(m_pchData, pData->data(), nLen);
249  }
250
251  wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner
252
253  return true;
254}
255
256// must be called before replacing contents of this string
257bool wxStringBase::AllocBeforeWrite(size_t nLen)
258{
259  wxASSERT( nLen != 0 );  // doesn't make any sense
260
261  // must not share string and must have enough space
262  wxStringData* pData = GetStringData();
263  if ( pData->IsShared() || pData->IsEmpty() ) {
264    // can't work with old buffer, get new one
265    pData->Unlock();
266    if ( !AllocBuffer(nLen) ) {
267      // allocation failures are handled by the caller
268      return false;
269    }
270  }
271  else {
272    if ( nLen > pData->nAllocLength ) {
273      // realloc the buffer instead of calling malloc() again, this is more
274      // efficient
275      STATISTICS_ADD(Length, nLen);
276
277      nLen += EXTRA_ALLOC;
278
279      pData = (wxStringData*)
280          realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
281
282      if ( pData == NULL ) {
283        // allocation failures are handled by the caller
284        // keep previous data since reallocation failed
285        return false;
286      }
287
288      pData->nAllocLength = nLen;
289      m_pchData = pData->data();
290    }
291  }
292
293  wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner
294
295  // it doesn't really matter what the string length is as it's going to be
296  // overwritten later but, for extra safety, set it to 0 for now as we may
297  // have some junk in m_pchData
298  GetStringData()->nDataLength = 0;
299
300  return true;
301}
302
303wxStringBase& wxStringBase::append(size_t n, wxChar ch)
304{
305    size_type len = length();
306
307    if ( !Alloc(len + n) || !CopyBeforeWrite() ) {
308      wxFAIL_MSG( _T("out of memory in wxStringBase::append") );
309    }
310    GetStringData()->nDataLength = len + n;
311    m_pchData[len + n] = '\0';
312    for ( size_t i = 0; i < n; ++i )
313        m_pchData[len + i] = ch;
314    return *this;
315}
316
317void wxStringBase::resize(size_t nSize, wxChar ch)
318{
319    size_t len = length();
320
321    if ( nSize < len )
322    {
323        erase(begin() + nSize, end());
324    }
325    else if ( nSize > len )
326    {
327        append(nSize - len, ch);
328    }
329    //else: we have exactly the specified length, nothing to do
330}
331
332// allocate enough memory for nLen characters
333bool wxStringBase::Alloc(size_t nLen)
334{
335  wxStringData *pData = GetStringData();
336  if ( pData->nAllocLength <= nLen ) {
337    if ( pData->IsEmpty() ) {
338      nLen += EXTRA_ALLOC;
339
340      pData = (wxStringData *)
341                malloc(sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
342
343      if ( pData == NULL ) {
344        // allocation failure handled by caller
345        return false;
346      }
347
348      pData->nRefs = 1;
349      pData->nDataLength = 0;
350      pData->nAllocLength = nLen;
351      m_pchData = pData->data();  // data starts after wxStringData
352      m_pchData[0u] = wxT('\0');
353    }
354    else if ( pData->IsShared() ) {
355      pData->Unlock();                // memory not freed because shared
356      size_t nOldLen = pData->nDataLength;
357      if ( !AllocBuffer(nLen) ) {
358        // allocation failure handled by caller
359        return false;
360      }
361      // +1 to copy the terminator, too
362      memcpy(m_pchData, pData->data(), (nOldLen+1)*sizeof(wxChar));
363      GetStringData()->nDataLength = nOldLen;
364    }
365    else {
366      nLen += EXTRA_ALLOC;
367
368      pData = (wxStringData *)
369        realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
370
371      if ( pData == NULL ) {
372        // allocation failure handled by caller
373        // keep previous data since reallocation failed
374        return false;
375      }
376
377      // it's not important if the pointer changed or not (the check for this
378      // is not faster than assigning to m_pchData in all cases)
379      pData->nAllocLength = nLen;
380      m_pchData = pData->data();
381    }
382  }
383  //else: we've already got enough
384  return true;
385}
386
387wxStringBase::iterator wxStringBase::begin()
388{
389    if (length() > 0)
390        CopyBeforeWrite();
391    return m_pchData;
392}
393
394wxStringBase::iterator wxStringBase::end()
395{
396    if (length() > 0)
397        CopyBeforeWrite();
398    return m_pchData + length();
399}
400
401wxStringBase::iterator wxStringBase::erase(iterator it)
402{
403    size_type idx = it - begin();
404    erase(idx, 1);
405    return begin() + idx;
406}
407
408wxStringBase& wxStringBase::erase(size_t nStart, size_t nLen)
409{
410    wxASSERT(nStart <= length());
411    size_t strLen = length() - nStart;
412    // delete nLen or up to the end of the string characters
413    nLen = strLen < nLen ? strLen : nLen;
414    wxString strTmp(c_str(), nStart);
415    strTmp.append(c_str() + nStart + nLen, length() - nStart - nLen);
416
417    swap(strTmp);
418    return *this;
419}
420
421wxStringBase& wxStringBase::insert(size_t nPos, const wxChar *sz, size_t n)
422{
423    wxASSERT( nPos <= length() );
424
425    if ( n == npos ) n = wxStrlen(sz);
426    if ( n == 0 ) return *this;
427
428    if ( !Alloc(length() + n) || !CopyBeforeWrite() ) {
429        wxFAIL_MSG( _T("out of memory in wxStringBase::insert") );
430    }
431
432    memmove(m_pchData + nPos + n, m_pchData + nPos,
433            (length() - nPos) * sizeof(wxChar));
434    memcpy(m_pchData + nPos, sz, n * sizeof(wxChar));
435    GetStringData()->nDataLength = length() + n;
436    m_pchData[length()] = '\0';
437
438    return *this;
439}
440
441void wxStringBase::swap(wxStringBase& str)
442{
443    wxChar* tmp = str.m_pchData;
444    str.m_pchData = m_pchData;
445    m_pchData = tmp;
446}
447
448size_t wxStringBase::find(const wxStringBase& str, size_t nStart) const
449{
450    // deal with the special case of empty string first
451    const size_t nLen = length();
452    const size_t nLenOther = str.length();
453
454    if ( !nLenOther )
455    {
456        // empty string is a substring of anything
457        return 0;
458    }
459
460    if ( !nLen )
461    {
462        // the other string is non empty so can't be our substring
463        return npos;
464    }
465
466    wxASSERT( str.GetStringData()->IsValid() );
467    wxASSERT( nStart <= nLen );
468
469    const wxChar * const other = str.c_str();
470
471    // anchor
472    const wxChar* p = (const wxChar*)wxTmemchr(c_str() + nStart,
473                                               *other,
474                                               nLen - nStart);
475
476    if ( !p )
477        return npos;
478
479    while ( p - c_str() + nLenOther <= nLen && wxTmemcmp(p, other, nLenOther) )
480    {
481        p++;
482
483        // anchor again
484        p = (const wxChar*)wxTmemchr(p, *other, nLen - (p - c_str()));
485
486        if ( !p )
487            return npos;
488    }
489
490    return p - c_str() + nLenOther <= nLen ? p - c_str() : npos;
491}
492
493size_t wxStringBase::find(const wxChar* sz, size_t nStart, size_t n) const
494{
495    return find(wxStringBase(sz, n), nStart);
496}
497
498size_t wxStringBase::find(wxChar ch, size_t nStart) const
499{
500    wxASSERT( nStart <= length() );
501
502    const wxChar *p = (const wxChar*)wxTmemchr(c_str() + nStart, ch, length() - nStart);
503
504    return p == NULL ? npos : p - c_str();
505}
506
507size_t wxStringBase::rfind(const wxStringBase& str, size_t nStart) const
508{
509    wxASSERT( str.GetStringData()->IsValid() );
510    wxASSERT( nStart == npos || nStart <= length() );
511
512    if ( length() >= str.length() )
513    {
514        // avoids a corner case later
515        if ( length() == 0 && str.length() == 0 )
516            return 0;
517
518        // "top" is the point where search starts from
519        size_t top = length() - str.length();
520
521        if ( nStart == npos )
522            nStart = length() - 1;
523        if ( nStart < top )
524            top = nStart;
525
526        const wxChar *cursor = c_str() + top;
527        do
528        {
529            if ( wxTmemcmp(cursor, str.c_str(),
530                        str.length()) == 0 )
531            {
532                return cursor - c_str();
533            }
534        } while ( cursor-- > c_str() );
535    }
536
537    return npos;
538}
539
540size_t wxStringBase::rfind(const wxChar* sz, size_t nStart, size_t n) const
541{
542    return rfind(wxStringBase(sz, n), nStart);
543}
544
545size_t wxStringBase::rfind(wxChar ch, size_t nStart) const
546{
547    if ( nStart == npos )
548    {
549        nStart = length();
550    }
551    else
552    {
553        wxASSERT( nStart <= length() );
554    }
555
556    const wxChar *actual;
557    for ( actual = c_str() + ( nStart == npos ? length() : nStart + 1 );
558          actual > c_str(); --actual )
559    {
560        if ( *(actual - 1) == ch )
561            return (actual - 1) - c_str();
562    }
563
564    return npos;
565}
566
567size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
568{
569    wxASSERT(nStart <= length());
570
571    size_t len = wxStrlen(sz);
572
573    size_t i;
574    for(i = nStart; i < this->length(); ++i)
575    {
576        if (wxTmemchr(sz, *(c_str() + i), len))
577            break;
578    }
579
580    if(i == this->length())
581        return npos;
582    else
583        return i;
584}
585
586size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart,
587                                   size_t n) const
588{
589    return find_first_of(wxStringBase(sz, n), nStart);
590}
591
592size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
593{
594    if ( nStart == npos )
595    {
596        nStart = length() - 1;
597    }
598    else
599    {
600        wxASSERT_MSG( nStart <= length(),
601                        _T("invalid index in find_last_of()") );
602    }
603
604    size_t len = wxStrlen(sz);
605
606    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
607    {
608        if ( wxTmemchr(sz, *p, len) )
609            return p - c_str();
610    }
611
612    return npos;
613}
614
615size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart,
616                                   size_t n) const
617{
618    return find_last_of(wxStringBase(sz, n), nStart);
619}
620
621size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
622{
623    if ( nStart == npos )
624    {
625        nStart = length();
626    }
627    else
628    {
629        wxASSERT( nStart <= length() );
630    }
631
632    size_t len = wxStrlen(sz);
633
634    size_t i;
635    for(i = nStart; i < this->length(); ++i)
636    {
637        if (!wxTmemchr(sz, *(c_str() + i), len))
638            break;
639    }
640
641    if(i == this->length())
642         return npos;
643     else
644        return i;
645}
646
647size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart,
648                                       size_t n) const
649{
650    return find_first_not_of(wxStringBase(sz, n), nStart);
651}
652
653size_t wxStringBase::find_first_not_of(wxChar ch, size_t nStart) const
654{
655    wxASSERT( nStart <= length() );
656
657    for ( const wxChar *p = c_str() + nStart; *p; p++ )
658    {
659        if ( *p != ch )
660            return p - c_str();
661    }
662
663    return npos;
664}
665
666size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
667{
668    if ( nStart == npos )
669    {
670        nStart = length() - 1;
671    }
672    else
673    {
674        wxASSERT( nStart <= length() );
675    }
676
677    size_t len = wxStrlen(sz);
678
679    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
680    {
681        if ( !wxTmemchr(sz, *p,len) )
682             return p - c_str();
683    }
684
685    return npos;
686}
687
688size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart,
689                                      size_t n) const
690{
691    return find_last_not_of(wxStringBase(sz, n), nStart);
692}
693
694size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
695{
696    if ( nStart == npos )
697    {
698        nStart = length() - 1;
699    }
700    else
701    {
702        wxASSERT( nStart <= length() );
703    }
704
705    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
706    {
707        if ( *p != ch )
708            return p - c_str();
709    }
710
711    return npos;
712}
713
714wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
715                                    const wxChar *sz)
716{
717  wxASSERT_MSG( nStart <= length(),
718                _T("index out of bounds in wxStringBase::replace") );
719  size_t strLen = length() - nStart;
720  nLen = strLen < nLen ? strLen : nLen;
721
722  wxStringBase strTmp;
723  strTmp.reserve(length()); // micro optimisation to avoid multiple mem allocs
724
725  //This is kind of inefficient, but its pretty good considering...
726  //we don't want to use character access operators here because on STL
727  //it will freeze the reference count of strTmp, which means a deep copy
728  //at the end when swap is called
729  //
730  //Also, we can't use append with the full character pointer and must
731  //do it manually because this string can contain null characters
732  for(size_t i1 = 0; i1 < nStart; ++i1)
733      strTmp.append(1, this->c_str()[i1]);
734
735  //its safe to do the full version here because
736  //sz must be a normal c string
737  strTmp.append(sz);
738
739  for(size_t i2 = nStart + nLen; i2 < length(); ++i2)
740      strTmp.append(1, this->c_str()[i2]);
741
742  swap(strTmp);
743  return *this;
744}
745
746wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
747                                    size_t nCount, wxChar ch)
748{
749  return replace(nStart, nLen, wxStringBase(nCount, ch).c_str());
750}
751
752wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
753                                    const wxStringBase& str,
754                                    size_t nStart2, size_t nLen2)
755{
756  return replace(nStart, nLen, str.substr(nStart2, nLen2));
757}
758
759wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
760                                    const wxChar* sz, size_t nCount)
761{
762  return replace(nStart, nLen, wxStringBase(sz, nCount).c_str());
763}
764
765wxStringBase wxStringBase::substr(size_t nStart, size_t nLen) const
766{
767  if ( nLen == npos )
768    nLen = length() - nStart;
769  return wxStringBase(*this, nStart, nLen);
770}
771
772// assigns one string to another
773wxStringBase& wxStringBase::operator=(const wxStringBase& stringSrc)
774{
775  wxASSERT( stringSrc.GetStringData()->IsValid() );
776
777  // don't copy string over itself
778  if ( m_pchData != stringSrc.m_pchData ) {
779    if ( stringSrc.GetStringData()->IsEmpty() ) {
780      Reinit();
781    }
782    else {
783      // adjust references
784      GetStringData()->Unlock();
785      m_pchData = stringSrc.m_pchData;
786      GetStringData()->Lock();
787    }
788  }
789
790  return *this;
791}
792
793// assigns a single character
794wxStringBase& wxStringBase::operator=(wxChar ch)
795{
796  if ( !AssignCopy(1, &ch) ) {
797    wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") );
798  }
799  return *this;
800}
801
802// assigns C string
803wxStringBase& wxStringBase::operator=(const wxChar *psz)
804{
805  if ( !AssignCopy(wxStrlen(psz), psz) ) {
806    wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") );
807  }
808  return *this;
809}
810
811// helper function: does real copy
812bool wxStringBase::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData)
813{
814  if ( nSrcLen == 0 ) {
815    Reinit();
816  }
817  else {
818    if ( !AllocBeforeWrite(nSrcLen) ) {
819      // allocation failure handled by caller
820      return false;
821    }
822
823    // use memmove() and not memcpy() here as we might be copying from our own
824    // buffer in case of assignment such as "s = s.c_str()" (see #11294)
825    memmove(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
826
827    GetStringData()->nDataLength = nSrcLen;
828    m_pchData[nSrcLen] = wxT('\0');
829  }
830  return true;
831}
832
833// ---------------------------------------------------------------------------
834// string concatenation
835// ---------------------------------------------------------------------------
836
837// add something to this string
838bool wxStringBase::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData,
839                              size_t nMaxLen)
840{
841  STATISTICS_ADD(SummandLength, nSrcLen);
842
843  nSrcLen = nSrcLen < nMaxLen ? nSrcLen : nMaxLen;
844
845  // concatenating an empty string is a NOP
846  if ( nSrcLen > 0 ) {
847    wxStringData *pData = GetStringData();
848    size_t nLen = pData->nDataLength;
849    size_t nNewLen = nLen + nSrcLen;
850
851    // take special care when appending part of this string to itself: the code
852    // below reallocates our buffer and this invalidates pszSrcData pointer so
853    // we have to copy it in another temporary string in this case (but avoid
854    // doing this unnecessarily)
855    if ( pszSrcData >= m_pchData && pszSrcData < m_pchData + nLen )
856    {
857        wxStringBase tmp(pszSrcData, nSrcLen);
858        return ConcatSelf(nSrcLen, tmp.m_pchData, nSrcLen);
859    }
860
861    // alloc new buffer if current is too small
862    if ( pData->IsShared() ) {
863      STATISTICS_ADD(ConcatHit, 0);
864
865      // we have to allocate another buffer
866      wxStringData* pOldData = GetStringData();
867      if ( !AllocBuffer(nNewLen) ) {
868          // allocation failure handled by caller
869          return false;
870      }
871      memcpy(m_pchData, pOldData->data(), nLen*sizeof(wxChar));
872      pOldData->Unlock();
873    }
874    else if ( nNewLen > pData->nAllocLength ) {
875      STATISTICS_ADD(ConcatHit, 0);
876
877      reserve(nNewLen);
878      // we have to grow the buffer
879      if ( capacity() < nNewLen ) {
880          // allocation failure handled by caller
881          return false;
882      }
883    }
884    else {
885      STATISTICS_ADD(ConcatHit, 1);
886
887      // the buffer is already big enough
888    }
889
890    // should be enough space
891    wxASSERT( nNewLen <= GetStringData()->nAllocLength );
892
893    // fast concatenation - all is done in our buffer
894    memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar));
895
896    m_pchData[nNewLen] = wxT('\0');          // put terminating '\0'
897    GetStringData()->nDataLength = nNewLen; // and fix the length
898  }
899  //else: the string to append was empty
900  return true;
901}
902
903// ---------------------------------------------------------------------------
904// simple sub-string extraction
905// ---------------------------------------------------------------------------
906
907// helper function: clone the data attached to this string
908bool wxStringBase::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
909{
910  if ( nCopyLen == 0 ) {
911    dest.Init();
912  }
913  else {
914    if ( !dest.AllocBuffer(nCopyLen) ) {
915      // allocation failure handled by caller
916      return false;
917    }
918    memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen*sizeof(wxChar));
919  }
920  return true;
921}
922
923#endif // !wxUSE_STL
924
925#if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
926
927#if !wxUSE_STL
928    #define STRINGCLASS wxStringBase
929#else
930    #define STRINGCLASS wxString
931#endif
932
933static inline int wxDoCmp(const wxChar* s1, size_t l1,
934                          const wxChar* s2, size_t l2)
935{
936    if( l1 == l2 )
937        return wxTmemcmp(s1, s2, l1);
938    else if( l1 < l2 )
939    {
940        int ret = wxTmemcmp(s1, s2, l1);
941        return ret == 0 ? -1 : ret;
942    }
943    else
944    {
945        int ret = wxTmemcmp(s1, s2, l2);
946        return ret == 0 ? +1 : ret;
947    }
948}
949
950int STRINGCLASS::compare(const wxStringBase& str) const
951{
952    return ::wxDoCmp(data(), length(), str.data(), str.length());
953}
954
955int STRINGCLASS::compare(size_t nStart, size_t nLen,
956                         const wxStringBase& str) const
957{
958    wxASSERT(nStart <= length());
959    size_type strLen = length() - nStart;
960    nLen = strLen < nLen ? strLen : nLen;
961    return ::wxDoCmp(data() + nStart, nLen, str.data(), str.length());
962}
963
964int STRINGCLASS::compare(size_t nStart, size_t nLen,
965                         const wxStringBase& str,
966                         size_t nStart2, size_t nLen2) const
967{
968    wxASSERT(nStart <= length());
969    wxASSERT(nStart2 <= str.length());
970    size_type strLen  =     length() - nStart,
971              strLen2 = str.length() - nStart2;
972    nLen  = strLen  < nLen  ? strLen  : nLen;
973    nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
974    return ::wxDoCmp(data() + nStart, nLen, str.data() + nStart2, nLen2);
975}
976
977int STRINGCLASS::compare(const wxChar* sz) const
978{
979    size_t nLen = wxStrlen(sz);
980    return ::wxDoCmp(data(), length(), sz, nLen);
981}
982
983int STRINGCLASS::compare(size_t nStart, size_t nLen,
984                         const wxChar* sz, size_t nCount) const
985{
986    wxASSERT(nStart <= length());
987    size_type strLen = length() - nStart;
988    nLen = strLen < nLen ? strLen : nLen;
989    if( nCount == npos )
990        nCount = wxStrlen(sz);
991
992    return ::wxDoCmp(data() + nStart, nLen, sz, nCount);
993}
994
995#undef STRINGCLASS
996
997#endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
998
999// ===========================================================================
1000// wxString class core
1001// ===========================================================================
1002
1003// ---------------------------------------------------------------------------
1004// construction and conversion
1005// ---------------------------------------------------------------------------
1006
1007#if wxUSE_UNICODE
1008
1009// from multibyte string
1010wxString::wxString(const char *psz, const wxMBConv& conv, size_t nLength)
1011{
1012    // anything to do?
1013    if ( psz && nLength != 0 )
1014    {
1015        if ( nLength == npos )
1016        {
1017            nLength = wxNO_LEN;
1018        }
1019
1020        size_t nLenWide;
1021        wxWCharBuffer wbuf = conv.cMB2WC(psz, nLength, &nLenWide);
1022
1023        if ( nLenWide )
1024            assign(wbuf, nLenWide);
1025    }
1026}
1027
1028//Convert wxString in Unicode mode to a multi-byte string
1029const wxCharBuffer wxString::mb_str(const wxMBConv& conv) const
1030{
1031    return conv.cWC2MB(c_str(), length() + 1 /* size, not length */, NULL);
1032}
1033
1034#else // ANSI
1035
1036#if wxUSE_WCHAR_T
1037
1038// from wide string
1039wxString::wxString(const wchar_t *pwz, const wxMBConv& conv, size_t nLength)
1040{
1041    // anything to do?
1042    if ( pwz && nLength != 0 )
1043    {
1044        if ( nLength == npos )
1045        {
1046            nLength = wxNO_LEN;
1047        }
1048
1049        size_t nLenMB;
1050        wxCharBuffer buf = conv.cWC2MB(pwz, nLength, &nLenMB);
1051
1052        if ( nLenMB )
1053            assign(buf, nLenMB);
1054    }
1055}
1056
1057//Converts this string to a wide character string if unicode
1058//mode is not enabled and wxUSE_WCHAR_T is enabled
1059const wxWCharBuffer wxString::wc_str(const wxMBConv& conv) const
1060{
1061    return conv.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL);
1062}
1063
1064#endif // wxUSE_WCHAR_T
1065
1066#endif // Unicode/ANSI
1067
1068// shrink to minimal size (releasing extra memory)
1069bool wxString::Shrink()
1070{
1071  wxString tmp(begin(), end());
1072  swap(tmp);
1073  return tmp.length() == length();
1074}
1075
1076#if !wxUSE_STL
1077// get the pointer to writable buffer of (at least) nLen bytes
1078wxChar *wxString::GetWriteBuf(size_t nLen)
1079{
1080  if ( !AllocBeforeWrite(nLen) ) {
1081    // allocation failure handled by caller
1082    return NULL;
1083  }
1084
1085  wxASSERT( GetStringData()->nRefs == 1 );
1086  GetStringData()->Validate(false);
1087
1088  return m_pchData;
1089}
1090
1091// put string back in a reasonable state after GetWriteBuf
1092void wxString::UngetWriteBuf()
1093{
1094  UngetWriteBuf(wxStrlen(m_pchData));
1095}
1096
1097void wxString::UngetWriteBuf(size_t nLen)
1098{
1099  wxStringData * const pData = GetStringData();
1100
1101  wxASSERT_MSG( nLen < pData->nAllocLength, _T("buffer overrun") );
1102
1103  // the strings we store are always NUL-terminated
1104  pData->data()[nLen] = _T('\0');
1105  pData->nDataLength = nLen;
1106  pData->Validate(true);
1107}
1108#endif // !wxUSE_STL
1109
1110// ---------------------------------------------------------------------------
1111// data access
1112// ---------------------------------------------------------------------------
1113
1114// all functions are inline in string.h
1115
1116// ---------------------------------------------------------------------------
1117// assignment operators
1118// ---------------------------------------------------------------------------
1119
1120#if !wxUSE_UNICODE
1121
1122// same as 'signed char' variant
1123wxString& wxString::operator=(const unsigned char* psz)
1124{
1125  *this = (const char *)psz;
1126  return *this;
1127}
1128
1129#if wxUSE_WCHAR_T
1130wxString& wxString::operator=(const wchar_t *pwz)
1131{
1132  wxString str(pwz);
1133  swap(str);
1134  return *this;
1135}
1136#endif
1137
1138#endif
1139
1140/*
1141 * concatenation functions come in 5 flavours:
1142 *  string + string
1143 *  char   + string      and      string + char
1144 *  C str  + string      and      string + C str
1145 */
1146
1147wxString operator+(const wxString& str1, const wxString& str2)
1148{
1149#if !wxUSE_STL
1150    wxASSERT( str1.GetStringData()->IsValid() );
1151    wxASSERT( str2.GetStringData()->IsValid() );
1152#endif
1153
1154    wxString s = str1;
1155    s += str2;
1156
1157    return s;
1158}
1159
1160wxString operator+(const wxString& str, wxChar ch)
1161{
1162#if !wxUSE_STL
1163    wxASSERT( str.GetStringData()->IsValid() );
1164#endif
1165
1166    wxString s = str;
1167    s += ch;
1168
1169    return s;
1170}
1171
1172wxString operator+(wxChar ch, const wxString& str)
1173{
1174#if !wxUSE_STL
1175    wxASSERT( str.GetStringData()->IsValid() );
1176#endif
1177
1178    wxString s = ch;
1179    s += str;
1180
1181    return s;
1182}
1183
1184wxString operator+(const wxString& str, const wxChar *psz)
1185{
1186#if !wxUSE_STL
1187    wxASSERT( str.GetStringData()->IsValid() );
1188#endif
1189
1190    wxString s;
1191    if ( !s.Alloc(wxStrlen(psz) + str.length()) ) {
1192        wxFAIL_MSG( _T("out of memory in wxString::operator+") );
1193    }
1194    s += str;
1195    s += psz;
1196
1197    return s;
1198}
1199
1200wxString operator+(const wxChar *psz, const wxString& str)
1201{
1202#if !wxUSE_STL
1203    wxASSERT( str.GetStringData()->IsValid() );
1204#endif
1205
1206    wxString s;
1207    if ( !s.Alloc(wxStrlen(psz) + str.length()) ) {
1208        wxFAIL_MSG( _T("out of memory in wxString::operator+") );
1209    }
1210    s = psz;
1211    s += str;
1212
1213    return s;
1214}
1215
1216// ===========================================================================
1217// other common string functions
1218// ===========================================================================
1219
1220int wxString::Cmp(const wxString& s) const
1221{
1222    return compare(s);
1223}
1224
1225int wxString::Cmp(const wxChar* psz) const
1226{
1227    return compare(psz);
1228}
1229
1230static inline int wxDoCmpNoCase(const wxChar* s1, size_t l1,
1231                                const wxChar* s2, size_t l2)
1232{
1233    size_t i;
1234
1235    if( l1 == l2 )
1236    {
1237        for(i = 0; i < l1; ++i)
1238        {
1239            if(wxTolower(s1[i]) != wxTolower(s2[i]))
1240                break;
1241        }
1242        return i == l1 ? 0 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;
1243    }
1244    else if( l1 < l2 )
1245    {
1246        for(i = 0; i < l1; ++i)
1247        {
1248            if(wxTolower(s1[i]) != wxTolower(s2[i]))
1249                break;
1250        }
1251        return i == l1 ? -1 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;
1252    }
1253    else
1254    {
1255        for(i = 0; i < l2; ++i)
1256        {
1257            if(wxTolower(s1[i]) != wxTolower(s2[i]))
1258                break;
1259        }
1260        return i == l2 ? 1 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;
1261    }
1262}
1263
1264int wxString::CmpNoCase(const wxString& s) const
1265{
1266    return wxDoCmpNoCase(data(), length(), s.data(), s.length());
1267}
1268
1269int wxString::CmpNoCase(const wxChar* psz) const
1270{
1271    int nLen = wxStrlen(psz);
1272
1273    return wxDoCmpNoCase(data(), length(), psz, nLen);
1274}
1275
1276
1277#if wxUSE_UNICODE
1278
1279#ifdef __MWERKS__
1280#ifndef __SCHAR_MAX__
1281#define __SCHAR_MAX__ 127
1282#endif
1283#endif
1284
1285wxString wxString::FromAscii(const char *ascii)
1286{
1287    if (!ascii)
1288       return wxEmptyString;
1289
1290    size_t len = strlen( ascii );
1291    wxString res;
1292
1293    if ( len )
1294    {
1295        wxStringBuffer buf(res, len);
1296
1297        wchar_t *dest = buf;
1298
1299        for ( ;; )
1300        {
1301           if ( (*dest++ = (wchar_t)(unsigned char)*ascii++) == L'\0' )
1302               break;
1303        }
1304    }
1305
1306    return res;
1307}
1308
1309wxString wxString::FromAscii(const char ascii)
1310{
1311    // What do we do with '\0' ?
1312
1313    wxString res;
1314    res += (wchar_t)(unsigned char) ascii;
1315
1316    return res;
1317}
1318
1319const wxCharBuffer wxString::ToAscii() const
1320{
1321    // this will allocate enough space for the terminating NUL too
1322    wxCharBuffer buffer(length());
1323
1324
1325    char *dest = buffer.data();
1326
1327    const wchar_t *pwc = c_str();
1328    for ( ;; )
1329    {
1330        *dest++ = (char)(*pwc > SCHAR_MAX ? wxT('_') : *pwc);
1331
1332        // the output string can't have embedded NULs anyhow, so we can safely
1333        // stop at first of them even if we do have any
1334        if ( !*pwc++ )
1335            break;
1336    }
1337
1338    return buffer;
1339}
1340
1341#endif // Unicode
1342
1343// extract string of length nCount starting at nFirst
1344wxString wxString::Mid(size_t nFirst, size_t nCount) const
1345{
1346    size_t nLen = length();
1347
1348    // default value of nCount is npos and means "till the end"
1349    if ( nCount == npos )
1350    {
1351        nCount = nLen - nFirst;
1352    }
1353
1354    // out-of-bounds requests return sensible things
1355    if ( nFirst + nCount > nLen )
1356    {
1357        nCount = nLen - nFirst;
1358    }
1359
1360    if ( nFirst > nLen )
1361    {
1362        // AllocCopy() will return empty string
1363        return wxEmptyString;
1364    }
1365
1366    wxString dest(*this, nFirst, nCount);
1367    if ( dest.length() != nCount )
1368    {
1369        wxFAIL_MSG( _T("out of memory in wxString::Mid") );
1370    }
1371
1372    return dest;
1373}
1374
1375// check that the string starts with prefix and return the rest of the string
1376// in the provided pointer if it is not NULL, otherwise return false
1377bool wxString::StartsWith(const wxChar *prefix, wxString *rest) const
1378{
1379    wxASSERT_MSG( prefix, _T("invalid parameter in wxString::StartsWith") );
1380
1381    // first check if the beginning of the string matches the prefix: note
1382    // that we don't have to check that we don't run out of this string as
1383    // when we reach the terminating NUL, either prefix string ends too (and
1384    // then it's ok) or we break out of the loop because there is no match
1385    const wxChar *p = c_str();
1386    while ( *prefix )
1387    {
1388        if ( *prefix++ != *p++ )
1389        {
1390            // no match
1391            return false;
1392        }
1393    }
1394
1395    if ( rest )
1396    {
1397        // put the rest of the string into provided pointer
1398        *rest = p;
1399    }
1400
1401    return true;
1402}
1403
1404
1405// check that the string ends with suffix and return the rest of it in the
1406// provided pointer if it is not NULL, otherwise return false
1407bool wxString::EndsWith(const wxChar *suffix, wxString *rest) const
1408{
1409    wxASSERT_MSG( suffix, _T("invalid parameter in wxString::EndssWith") );
1410
1411    int start = length() - wxStrlen(suffix);
1412    if ( start < 0 || wxStrcmp(c_str() + start, suffix) != 0 )
1413        return false;
1414
1415    if ( rest )
1416    {
1417        // put the rest of the string into provided pointer
1418        rest->assign(*this, 0, start);
1419    }
1420
1421    return true;
1422}
1423
1424
1425// extract nCount last (rightmost) characters
1426wxString wxString::Right(size_t nCount) const
1427{
1428  if ( nCount > length() )
1429    nCount = length();
1430
1431  wxString dest(*this, length() - nCount, nCount);
1432  if ( dest.length() != nCount ) {
1433    wxFAIL_MSG( _T("out of memory in wxString::Right") );
1434  }
1435  return dest;
1436}
1437
1438// get all characters after the last occurence of ch
1439// (returns the whole string if ch not found)
1440wxString wxString::AfterLast(wxChar ch) const
1441{
1442  wxString str;
1443  int iPos = Find(ch, true);
1444  if ( iPos == wxNOT_FOUND )
1445    str = *this;
1446  else
1447    str = c_str() + iPos + 1;
1448
1449  return str;
1450}
1451
1452// extract nCount first (leftmost) characters
1453wxString wxString::Left(size_t nCount) const
1454{
1455  if ( nCount > length() )
1456    nCount = length();
1457
1458  wxString dest(*this, 0, nCount);
1459  if ( dest.length() != nCount ) {
1460    wxFAIL_MSG( _T("out of memory in wxString::Left") );
1461  }
1462  return dest;
1463}
1464
1465// get all characters before the first occurence of ch
1466// (returns the whole string if ch not found)
1467wxString wxString::BeforeFirst(wxChar ch) const
1468{
1469  int iPos = Find(ch);
1470  if ( iPos == wxNOT_FOUND ) iPos = length();
1471  return wxString(*this, 0, iPos);
1472}
1473
1474/// get all characters before the last occurence of ch
1475/// (returns empty string if ch not found)
1476wxString wxString::BeforeLast(wxChar ch) const
1477{
1478  wxString str;
1479  int iPos = Find(ch, true);
1480  if ( iPos != wxNOT_FOUND && iPos != 0 )
1481    str = wxString(c_str(), iPos);
1482
1483  return str;
1484}
1485
1486/// get all characters after the first occurence of ch
1487/// (returns empty string if ch not found)
1488wxString wxString::AfterFirst(wxChar ch) const
1489{
1490  wxString str;
1491  int iPos = Find(ch);
1492  if ( iPos != wxNOT_FOUND )
1493    str = c_str() + iPos + 1;
1494
1495  return str;
1496}
1497
1498// replace first (or all) occurences of some substring with another one
1499size_t
1500wxString::Replace(const wxChar *szOld, const wxChar *szNew, bool bReplaceAll)
1501{
1502    // if we tried to replace an empty string we'd enter an infinite loop below
1503    wxCHECK_MSG( szOld && *szOld && szNew, 0,
1504                 _T("wxString::Replace(): invalid parameter") );
1505
1506    size_t uiCount = 0;   // count of replacements made
1507
1508    // optimize the special common case of replacing one character with another
1509    // one
1510    if ( szOld[1] == '\0' && (szNew[0] != '\0' && szNew[1] == '\0') )
1511    {
1512        // this loop is the simplified version of the one below
1513        for ( size_t pos = 0; ; )
1514        {
1515            pos = find(*szOld, pos);
1516            if ( pos == npos )
1517                break;
1518
1519            (*this)[pos++] = *szNew;
1520
1521            uiCount++;
1522
1523            if ( !bReplaceAll )
1524                break;
1525        }
1526    }
1527    else // general case
1528    {
1529        const size_t uiOldLen = wxStrlen(szOld);
1530        const size_t uiNewLen = wxStrlen(szNew);
1531
1532        for ( size_t pos = 0; ; )
1533        {
1534            pos = find(szOld, pos);
1535            if ( pos == npos )
1536                break;
1537
1538            // replace this occurrence of the old string with the new one
1539            replace(pos, uiOldLen, szNew, uiNewLen);
1540
1541            // move past the string that was replaced
1542            pos += uiNewLen;
1543
1544            // increase replace count
1545            uiCount++;
1546
1547            // stop now?
1548            if ( !bReplaceAll )
1549                break;
1550        }
1551    }
1552
1553    return uiCount;
1554}
1555
1556bool wxString::IsAscii() const
1557{
1558  const wxChar *s = (const wxChar*) *this;
1559  while(*s){
1560    if(!isascii(*s)) return(false);
1561    s++;
1562  }
1563  return(true);
1564}
1565
1566bool wxString::IsWord() const
1567{
1568  const wxChar *s = (const wxChar*) *this;
1569  while(*s){
1570    if(!wxIsalpha(*s)) return(false);
1571    s++;
1572  }
1573  return(true);
1574}
1575
1576bool wxString::IsNumber() const
1577{
1578  const wxChar *s = (const wxChar*) *this;
1579  if (wxStrlen(s))
1580     if ((s[0] == wxT('-')) || (s[0] == wxT('+'))) s++;
1581  while(*s){
1582    if(!wxIsdigit(*s)) return(false);
1583    s++;
1584  }
1585  return(true);
1586}
1587
1588wxString wxString::Strip(stripType w) const
1589{
1590    wxString s = *this;
1591    if ( w & leading ) s.Trim(false);
1592    if ( w & trailing ) s.Trim(true);
1593    return s;
1594}
1595
1596// ---------------------------------------------------------------------------
1597// case conversion
1598// ---------------------------------------------------------------------------
1599
1600wxString& wxString::MakeUpper()
1601{
1602  for ( iterator it = begin(), en = end(); it != en; ++it )
1603    *it = (wxChar)wxToupper(*it);
1604
1605  return *this;
1606}
1607
1608wxString& wxString::MakeLower()
1609{
1610  for ( iterator it = begin(), en = end(); it != en; ++it )
1611    *it = (wxChar)wxTolower(*it);
1612
1613  return *this;
1614}
1615
1616// ---------------------------------------------------------------------------
1617// trimming and padding
1618// ---------------------------------------------------------------------------
1619
1620// some compilers (VC++ 6.0 not to name them) return true for a call to
1621// isspace('\xEA') in the C locale which seems to be broken to me, but we have
1622// to live with this by checking that the character is a 7 bit one - even if
1623// this may fail to detect some spaces (I don't know if Unicode doesn't have
1624// space-like symbols somewhere except in the first 128 chars), it is arguably
1625// still better than trimming away accented letters
1626inline int wxSafeIsspace(wxChar ch) { return (ch < 127) && wxIsspace(ch); }
1627
1628// trims spaces (in the sense of isspace) from left or right side
1629wxString& wxString::Trim(bool bFromRight)
1630{
1631    // first check if we're going to modify the string at all
1632    if ( !empty() &&
1633         (
1634          (bFromRight && wxSafeIsspace(GetChar(length() - 1))) ||
1635          (!bFromRight && wxSafeIsspace(GetChar(0u)))
1636         )
1637       )
1638    {
1639        if ( bFromRight )
1640        {
1641            // find last non-space character
1642            reverse_iterator psz = rbegin();
1643            while ( (psz != rend()) && wxSafeIsspace(*psz) )
1644                psz++;
1645
1646            // truncate at trailing space start
1647            erase(psz.base(), end());
1648        }
1649        else
1650        {
1651            // find first non-space character
1652            iterator psz = begin();
1653            while ( (psz != end()) && wxSafeIsspace(*psz) )
1654                psz++;
1655
1656            // fix up data and length
1657            erase(begin(), psz);
1658        }
1659    }
1660
1661    return *this;
1662}
1663
1664// adds nCount characters chPad to the string from either side
1665wxString& wxString::Pad(size_t nCount, wxChar chPad, bool bFromRight)
1666{
1667    wxString s(chPad, nCount);
1668
1669    if ( bFromRight )
1670        *this += s;
1671    else
1672    {
1673        s += *this;
1674        swap(s);
1675    }
1676
1677    return *this;
1678}
1679
1680// truncate the string
1681wxString& wxString::Truncate(size_t uiLen)
1682{
1683    if ( uiLen < length() )
1684    {
1685        erase(begin() + uiLen, end());
1686    }
1687    //else: nothing to do, string is already short enough
1688
1689    return *this;
1690}
1691
1692// ---------------------------------------------------------------------------
1693// finding (return wxNOT_FOUND if not found and index otherwise)
1694// ---------------------------------------------------------------------------
1695
1696// find a character
1697int wxString::Find(wxChar ch, bool bFromEnd) const
1698{
1699    size_type idx = bFromEnd ? find_last_of(ch) : find_first_of(ch);
1700
1701    return (idx == npos) ? wxNOT_FOUND : (int)idx;
1702}
1703
1704// find a sub-string (like strstr)
1705int wxString::Find(const wxChar *pszSub) const
1706{
1707    size_type idx = find(pszSub);
1708
1709    return (idx == npos) ? wxNOT_FOUND : (int)idx;
1710}
1711
1712// ----------------------------------------------------------------------------
1713// conversion to numbers
1714// ----------------------------------------------------------------------------
1715
1716// the implementation of all the functions below is exactly the same so factor
1717// it out
1718
1719template <typename T, typename F>
1720bool wxStringToIntType(const wxChar *start,
1721                       T *val,
1722                       int base,
1723                       F func)
1724{
1725    wxCHECK_MSG( val, false, _T("NULL output pointer") );
1726    wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
1727
1728#ifndef __WXWINCE__
1729    errno = 0;
1730#endif
1731
1732    wxChar *end;
1733    *val = (*func)(start, &end, base);
1734
1735    // return true only if scan was stopped by the terminating NUL and if the
1736    // string was not empty to start with and no under/overflow occurred
1737    return !*end && (end != start)
1738#ifndef __WXWINCE__
1739        && (errno != ERANGE)
1740#endif
1741    ;
1742}
1743
1744bool wxString::ToLong(long *val, int base) const
1745{
1746    return wxStringToIntType(c_str(), val, base, wxStrtol);
1747}
1748
1749bool wxString::ToULong(unsigned long *val, int base) const
1750{
1751    return wxStringToIntType(c_str(), val, base, wxStrtoul);
1752}
1753
1754bool wxString::ToLongLong(wxLongLong_t *val, int base) const
1755{
1756#ifdef wxHAS_STRTOLL
1757    return wxStringToIntType(c_str(), val, base, wxStrtoll);
1758#else
1759    // TODO: implement this ourselves
1760    wxUnusedVar(val);
1761    wxUnusedVar(base);
1762    return false;
1763#endif // wxHAS_STRTOLL
1764}
1765
1766bool wxString::ToULongLong(wxULongLong_t *val, int base) const
1767{
1768#ifdef wxHAS_STRTOLL
1769    return wxStringToIntType(c_str(), val, base, wxStrtoull);
1770#else
1771    // TODO: implement this ourselves
1772    wxUnusedVar(val);
1773    wxUnusedVar(base);
1774    return false;
1775#endif
1776}
1777
1778bool wxString::ToDouble(double *val) const
1779{
1780    wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToDouble") );
1781
1782#ifndef __WXWINCE__
1783    errno = 0;
1784#endif
1785
1786    const wxChar *start = c_str();
1787    wxChar *end;
1788    *val = wxStrtod(start, &end);
1789
1790    // return true only if scan was stopped by the terminating NUL and if the
1791    // string was not empty to start with and no under/overflow occurred
1792    return !*end && (end != start)
1793#ifndef __WXWINCE__
1794        && (errno != ERANGE)
1795#endif
1796    ;
1797}
1798
1799// ---------------------------------------------------------------------------
1800// formatted output
1801// ---------------------------------------------------------------------------
1802
1803/* static */
1804wxString wxString::Format(const wxChar *pszFormat, ...)
1805{
1806    va_list argptr;
1807    va_start(argptr, pszFormat);
1808
1809    wxString s;
1810    s.PrintfV(pszFormat, argptr);
1811
1812    va_end(argptr);
1813
1814    return s;
1815}
1816
1817/* static */
1818wxString wxString::FormatV(const wxChar *pszFormat, va_list argptr)
1819{
1820    wxString s;
1821    s.PrintfV(pszFormat, argptr);
1822    return s;
1823}
1824
1825int wxString::Printf(const wxChar *pszFormat, ...)
1826{
1827    va_list argptr;
1828    va_start(argptr, pszFormat);
1829
1830    int iLen = PrintfV(pszFormat, argptr);
1831
1832    va_end(argptr);
1833
1834    return iLen;
1835}
1836
1837/*
1838    Uses wxVsnprintf and places the result into the this string.
1839
1840    In ANSI build, wxVsnprintf is effectively vsnprintf but in Unicode build
1841    it is vswprintf.  Due to a discrepancy between vsnprintf and vswprintf in
1842    the ISO C99 (and thus SUSv3) standard the return value for the case of
1843    an undersized buffer is inconsistent.  For conforming vsnprintf
1844    implementations the function must return the number of characters that
1845    would have been printed had the buffer been large enough.  For conforming
1846    vswprintf implementations the function must return a negative number
1847    and set errno.
1848
1849    What vswprintf sets errno to is undefined but Darwin seems to set it to
1850    EOVERFLOW.  The only expected errno are EILSEQ and EINVAL.  Both of
1851    those are defined in the standard and backed up by several conformance
1852    statements.  Note that ENOMEM mentioned in the manual page does not
1853    apply to swprintf, only wprintf and fwprintf.
1854
1855    Official manual page:
1856    http://www.opengroup.org/onlinepubs/009695399/functions/swprintf.html
1857
1858    Some conformance statements (AIX, Solaris):
1859    http://www.opengroup.org/csq/view.mhtml?RID=ibm%2FSD1%2F3
1860    http://www.theopengroup.org/csq/view.mhtml?norationale=1&noreferences=1&RID=Fujitsu%2FSE2%2F10
1861
1862    Since EILSEQ and EINVAL are rather common but EOVERFLOW is not and since
1863    EILSEQ and EINVAL are specifically defined to mean the error is other than
1864    an undersized buffer and no other errno are defined we treat those two
1865    as meaning hard errors and everything else gets the old behavior which
1866    is to keep looping and increasing buffer size until the function succeeds.
1867
1868    In practice it's impossible to determine before compilation which behavior
1869    may be used.  The vswprintf function may have vsnprintf-like behavior or
1870    vice-versa.  Behavior detected on one release can theoretically change
1871    with an updated release.  Not to mention that configure testing for it
1872    would require the test to be run on the host system, not the build system
1873    which makes cross compilation difficult. Therefore, we make no assumptions
1874    about behavior and try our best to handle every known case, including the
1875    case where wxVsnprintf returns a negative number and fails to set errno.
1876
1877    There is yet one more non-standard implementation and that is our own.
1878    Fortunately, that can be detected at compile-time.
1879
1880    On top of all that, ISO C99 explicitly defines snprintf to write a null
1881    character to the last position of the specified buffer.  That would be at
1882    at the given buffer size minus 1.  It is supposed to do this even if it
1883    turns out that the buffer is sized too small.
1884
1885    Darwin (tested on 10.5) follows the C99 behavior exactly.
1886
1887    Glibc 2.6 almost follows the C99 behavior except vswprintf never sets
1888    errno even when it fails.  However, it only seems to ever fail due
1889    to an undersized buffer.
1890*/
1891int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
1892{
1893    int size = 1024;
1894
1895    for ( ;; )
1896    {
1897        // Allocate 1 more character than we tell wxVsnprintf about
1898        // just in case it is buggy.
1899        // FIXME: I have a feeling that the underlying function was not buggy
1900        // and I suspect it was to fix the buf[size] = '\0' line below
1901        wxStringBuffer tmp(*this, size + 1);
1902        wxChar *buf = tmp;
1903
1904        if ( !buf )
1905        {
1906            // out of memory
1907            return -1;
1908        }
1909
1910        // wxVsnprintf() may modify the original arg pointer, so pass it
1911        // only a copy
1912        va_list argptrcopy;
1913        wxVaCopy(argptrcopy, argptr);
1914
1915#ifndef __WXWINCE__
1916        // Set errno to 0 to make it determinate if wxVsnprintf fails to set it.
1917        errno = 0;
1918#endif
1919        int len = wxVsnprintf(buf, size, pszFormat, argptrcopy);
1920        va_end(argptrcopy);
1921
1922        // some implementations of vsnprintf() don't NUL terminate
1923        // the string if there is not enough space for it so
1924        // always do it manually
1925        // FIXME: This really seems to be the wrong and would be an off-by-one
1926        // bug except the code above allocates an extra character.
1927        buf[size] = _T('\0');
1928
1929        // vsnprintf() may return either -1 (traditional Unix behaviour) or the
1930        // total number of characters which would have been written if the
1931        // buffer were large enough (newer standards such as Unix98)
1932        if ( len < 0 )
1933        {
1934#if wxUSE_WXVSNPRINTF
1935            // we know that our own implementation of wxVsnprintf() returns -1
1936            // only for a format error - thus there's something wrong with
1937            // the user's format string
1938            return -1;
1939#else // assume that system version only returns error if not enough space
1940#if !defined(__WXWINCE__) && (!defined(__OS2__) || defined(__INNOTEK_LIBC__))
1941            if( (errno == EILSEQ) || (errno == EINVAL) )
1942            // If errno was set to one of the two well-known hard errors
1943            // then fail immediately to avoid an infinite loop.
1944                return -1;
1945            else
1946#endif // __WXWINCE__
1947            // still not enough, as we don't know how much we need, double the
1948            // current size of the buffer
1949                size *= 2;
1950#endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
1951        }
1952        else if ( len >= size )
1953        {
1954#if wxUSE_WXVSNPRINTF
1955            // we know that our own implementation of wxVsnprintf() returns
1956            // size+1 when there's not enough space but that's not the size
1957            // of the required buffer!
1958            size *= 2;      // so we just double the current size of the buffer
1959#else
1960            // some vsnprintf() implementations NUL-terminate the buffer and
1961            // some don't in len == size case, to be safe always add 1
1962            // FIXME: I don't quite understand this comment.  The vsnprintf
1963            // function is specifically defined to return the number of
1964            // characters printed not including the null terminator.
1965            // So OF COURSE you need to add 1 to get the right buffer size.
1966            // The following line is definitely correct, no question.
1967            size = len + 1;
1968#endif
1969        }
1970        else // ok, there was enough space
1971        {
1972            break;
1973        }
1974    }
1975
1976    // we could have overshot
1977    Shrink();
1978
1979    return length();
1980}
1981
1982// ----------------------------------------------------------------------------
1983// misc other operations
1984// ----------------------------------------------------------------------------
1985
1986// returns true if the string matches the pattern which may contain '*' and
1987// '?' metacharacters (as usual, '?' matches any character and '*' any number
1988// of them)
1989bool wxString::Matches(const wxChar *pszMask) const
1990{
1991    // I disable this code as it doesn't seem to be faster (in fact, it seems
1992    // to be much slower) than the old, hand-written code below and using it
1993    // here requires always linking with libregex even if the user code doesn't
1994    // use it
1995#if 0 // wxUSE_REGEX
1996    // first translate the shell-like mask into a regex
1997    wxString pattern;
1998    pattern.reserve(wxStrlen(pszMask));
1999
2000    pattern += _T('^');
2001    while ( *pszMask )
2002    {
2003        switch ( *pszMask )
2004        {
2005            case _T('?'):
2006                pattern += _T('.');
2007                break;
2008
2009            case _T('*'):
2010                pattern += _T(".*");
2011                break;
2012
2013            case _T('^'):
2014            case _T('.'):
2015            case _T('$'):
2016            case _T('('):
2017            case _T(')'):
2018            case _T('|'):
2019            case _T('+'):
2020            case _T('\\'):
2021                // these characters are special in a RE, quote them
2022                // (however note that we don't quote '[' and ']' to allow
2023                // using them for Unix shell like matching)
2024                pattern += _T('\\');
2025                // fall through
2026
2027            default:
2028                pattern += *pszMask;
2029        }
2030
2031        pszMask++;
2032    }
2033    pattern += _T('$');
2034
2035    // and now use it
2036    return wxRegEx(pattern, wxRE_NOSUB | wxRE_EXTENDED).Matches(c_str());
2037#else // !wxUSE_REGEX
2038  // TODO: this is, of course, awfully inefficient...
2039
2040  // the char currently being checked
2041  const wxChar *pszTxt = c_str();
2042
2043  // the last location where '*' matched
2044  const wxChar *pszLastStarInText = NULL;
2045  const wxChar *pszLastStarInMask = NULL;
2046
2047match:
2048  for ( ; *pszMask != wxT('\0'); pszMask++, pszTxt++ ) {
2049    switch ( *pszMask ) {
2050      case wxT('?'):
2051        if ( *pszTxt == wxT('\0') )
2052          return false;
2053
2054        // pszTxt and pszMask will be incremented in the loop statement
2055
2056        break;
2057
2058      case wxT('*'):
2059        {
2060          // remember where we started to be able to backtrack later
2061          pszLastStarInText = pszTxt;
2062          pszLastStarInMask = pszMask;
2063
2064          // ignore special chars immediately following this one
2065          // (should this be an error?)
2066          while ( *pszMask == wxT('*') || *pszMask == wxT('?') )
2067            pszMask++;
2068
2069          // if there is nothing more, match
2070          if ( *pszMask == wxT('\0') )
2071            return true;
2072
2073          // are there any other metacharacters in the mask?
2074          size_t uiLenMask;
2075          const wxChar *pEndMask = wxStrpbrk(pszMask, wxT("*?"));
2076
2077          if ( pEndMask != NULL ) {
2078            // we have to match the string between two metachars
2079            uiLenMask = pEndMask - pszMask;
2080          }
2081          else {
2082            // we have to match the remainder of the string
2083            uiLenMask = wxStrlen(pszMask);
2084          }
2085
2086          wxString strToMatch(pszMask, uiLenMask);
2087          const wxChar* pMatch = wxStrstr(pszTxt, strToMatch);
2088          if ( pMatch == NULL )
2089            return false;
2090
2091          // -1 to compensate "++" in the loop
2092          pszTxt = pMatch + uiLenMask - 1;
2093          pszMask += uiLenMask - 1;
2094        }
2095        break;
2096
2097      default:
2098        if ( *pszMask != *pszTxt )
2099          return false;
2100        break;
2101    }
2102  }
2103
2104  // match only if nothing left
2105  if ( *pszTxt == wxT('\0') )
2106    return true;
2107
2108  // if we failed to match, backtrack if we can
2109  if ( pszLastStarInText ) {
2110    pszTxt = pszLastStarInText + 1;
2111    pszMask = pszLastStarInMask;
2112
2113    pszLastStarInText = NULL;
2114
2115    // don't bother resetting pszLastStarInMask, it's unnecessary
2116
2117    goto match;
2118  }
2119
2120  return false;
2121#endif // wxUSE_REGEX/!wxUSE_REGEX
2122}
2123
2124// Count the number of chars
2125int wxString::Freq(wxChar ch) const
2126{
2127    int count = 0;
2128    int len = length();
2129    for (int i = 0; i < len; i++)
2130    {
2131        if (GetChar(i) == ch)
2132            count ++;
2133    }
2134    return count;
2135}
2136
2137// convert to upper case, return the copy of the string
2138wxString wxString::Upper() const
2139{ wxString s(*this); return s.MakeUpper(); }
2140
2141// convert to lower case, return the copy of the string
2142wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }
2143
2144int wxString::sprintf(const wxChar *pszFormat, ...)
2145  {
2146    va_list argptr;
2147    va_start(argptr, pszFormat);
2148    int iLen = PrintfV(pszFormat, argptr);
2149    va_end(argptr);
2150    return iLen;
2151  }
2152
2153// ============================================================================
2154// ArrayString
2155// ============================================================================
2156
2157#include "wx/arrstr.h"
2158
2159wxArrayString::wxArrayString(size_t sz, const wxChar** a)
2160{
2161#if !wxUSE_STL
2162    Init(false);
2163#endif
2164    for (size_t i=0; i < sz; i++)
2165        Add(a[i]);
2166}
2167
2168wxArrayString::wxArrayString(size_t sz, const wxString* a)
2169{
2170#if !wxUSE_STL
2171    Init(false);
2172#endif
2173    for (size_t i=0; i < sz; i++)
2174        Add(a[i]);
2175}
2176
2177#if !wxUSE_STL
2178
2179// size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT)
2180#define   ARRAY_MAXSIZE_INCREMENT       4096
2181
2182#ifndef   ARRAY_DEFAULT_INITIAL_SIZE    // also defined in dynarray.h
2183#define   ARRAY_DEFAULT_INITIAL_SIZE    (16)
2184#endif
2185
2186#define   STRING(p)   ((wxString *)(&(p)))
2187
2188// ctor
2189void wxArrayString::Init(bool autoSort)
2190{
2191  m_nSize  =
2192  m_nCount = 0;
2193  m_pItems = (wxChar **) NULL;
2194  m_autoSort = autoSort;
2195}
2196
2197// copy ctor
2198wxArrayString::wxArrayString(const wxArrayString& src)
2199{
2200  Init(src.m_autoSort);
2201
2202  *this = src;
2203}
2204
2205// assignment operator
2206wxArrayString& wxArrayString::operator=(const wxArrayString& src)
2207{
2208  if ( m_nSize > 0 )
2209    Clear();
2210
2211  Copy(src);
2212
2213  m_autoSort = src.m_autoSort;
2214
2215  return *this;
2216}
2217
2218void wxArrayString::Copy(const wxArrayString& src)
2219{
2220  if ( src.m_nCount > ARRAY_DEFAULT_INITIAL_SIZE )
2221    Alloc(src.m_nCount);
2222
2223  for ( size_t n = 0; n < src.m_nCount; n++ )
2224    Add(src[n]);
2225}
2226
2227// grow the array
2228void wxArrayString::Grow(size_t nIncrement)
2229{
2230  // only do it if no more place
2231  if ( (m_nSize - m_nCount) < nIncrement ) {
2232    // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would
2233    // be never resized!
2234    #if ARRAY_DEFAULT_INITIAL_SIZE == 0
2235      #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!"
2236    #endif
2237
2238    if ( m_nSize == 0 ) {
2239      // was empty, alloc some memory
2240      m_nSize = ARRAY_DEFAULT_INITIAL_SIZE;
2241      if (m_nSize < nIncrement)
2242          m_nSize = nIncrement;
2243      m_pItems = new wxChar *[m_nSize];
2244    }
2245    else {
2246      // otherwise when it's called for the first time, nIncrement would be 0
2247      // and the array would never be expanded
2248      // add 50% but not too much
2249      size_t ndefIncrement = m_nSize < ARRAY_DEFAULT_INITIAL_SIZE
2250                          ? ARRAY_DEFAULT_INITIAL_SIZE : m_nSize >> 1;
2251      if ( ndefIncrement > ARRAY_MAXSIZE_INCREMENT )
2252        ndefIncrement = ARRAY_MAXSIZE_INCREMENT;
2253      if ( nIncrement < ndefIncrement )
2254        nIncrement = ndefIncrement;
2255      m_nSize += nIncrement;
2256      wxChar **pNew = new wxChar *[m_nSize];
2257
2258      // copy data to new location
2259      memcpy(pNew, m_pItems, m_nCount*sizeof(wxChar *));
2260
2261      // delete old memory (but do not release the strings!)
2262      wxDELETEA(m_pItems);
2263
2264      m_pItems = pNew;
2265    }
2266  }
2267}
2268
2269void wxArrayString::Free()
2270{
2271  for ( size_t n = 0; n < m_nCount; n++ ) {
2272    STRING(m_pItems[n])->GetStringData()->Unlock();
2273  }
2274}
2275
2276// deletes all the strings from the list
2277void wxArrayString::Empty()
2278{
2279  Free();
2280
2281  m_nCount = 0;
2282}
2283
2284// as Empty, but also frees memory
2285void wxArrayString::Clear()
2286{
2287  Free();
2288
2289  m_nSize  =
2290  m_nCount = 0;
2291
2292  wxDELETEA(m_pItems);
2293}
2294
2295// dtor
2296wxArrayString::~wxArrayString()
2297{
2298  Free();
2299
2300  wxDELETEA(m_pItems);
2301}
2302
2303void wxArrayString::reserve(size_t nSize)
2304{
2305    Alloc(nSize);
2306}
2307
2308// pre-allocates memory (frees the previous data!)
2309void wxArrayString::Alloc(size_t nSize)
2310{
2311  // only if old buffer was not big enough
2312  if ( nSize > m_nSize ) {
2313    wxChar **pNew = new wxChar *[nSize];
2314    if ( !pNew )
2315        return;
2316
2317    memcpy(pNew, m_pItems, m_nCount*sizeof(wxChar *));
2318    delete [] m_pItems;
2319
2320    m_pItems = pNew;
2321    m_nSize  = nSize;
2322  }
2323}
2324
2325// minimizes the memory usage by freeing unused memory
2326void wxArrayString::Shrink()
2327{
2328  // only do it if we have some memory to free
2329  if( m_nCount < m_nSize ) {
2330    // allocates exactly as much memory as we need
2331    wxChar **pNew = new wxChar *[m_nCount];
2332
2333    // copy data to new location
2334    memcpy(pNew, m_pItems, m_nCount*sizeof(wxChar *));
2335    delete [] m_pItems;
2336    m_pItems = pNew;
2337    m_nSize = m_nCount;
2338  }
2339}
2340
2341#if WXWIN_COMPATIBILITY_2_4
2342
2343// return a wxString[] as required for some control ctors.
2344wxString* wxArrayString::GetStringArray() const
2345{
2346    wxString *array = 0;
2347
2348    if( m_nCount > 0 )
2349    {
2350        array = new wxString[m_nCount];
2351        for( size_t i = 0; i < m_nCount; i++ )
2352            array[i] = m_pItems[i];
2353    }
2354
2355    return array;
2356}
2357
2358void wxArrayString::Remove(size_t nIndex, size_t nRemove)
2359{
2360    RemoveAt(nIndex, nRemove);
2361}
2362
2363#endif // WXWIN_COMPATIBILITY_2_4
2364
2365// searches the array for an item (forward or backwards)
2366int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const
2367{
2368  if ( m_autoSort ) {
2369    // use binary search in the sorted array
2370    wxASSERT_MSG( bCase && !bFromEnd,
2371                  wxT("search parameters ignored for auto sorted array") );
2372
2373    size_t i,
2374           lo = 0,
2375           hi = m_nCount;
2376    int res;
2377    while ( lo < hi ) {
2378      i = (lo + hi)/2;
2379
2380      res = wxStrcmp(sz, m_pItems[i]);
2381      if ( res < 0 )
2382        hi = i;
2383      else if ( res > 0 )
2384        lo = i + 1;
2385      else
2386        return i;
2387    }
2388
2389    return wxNOT_FOUND;
2390  }
2391  else {
2392    // use linear search in unsorted array
2393    if ( bFromEnd ) {
2394      if ( m_nCount > 0 ) {
2395        size_t ui = m_nCount;
2396        do {
2397          if ( STRING(m_pItems[--ui])->IsSameAs(sz, bCase) )
2398            return ui;
2399        }
2400        while ( ui != 0 );
2401      }
2402    }
2403    else {
2404      for( size_t ui = 0; ui < m_nCount; ui++ ) {
2405        if( STRING(m_pItems[ui])->IsSameAs(sz, bCase) )
2406          return ui;
2407      }
2408    }
2409  }
2410
2411  return wxNOT_FOUND;
2412}
2413
2414// add item at the end
2415size_t wxArrayString::Add(const wxString& str, size_t nInsert)
2416{
2417  if ( m_autoSort ) {
2418    // insert the string at the correct position to keep the array sorted
2419    size_t i,
2420           lo = 0,
2421           hi = m_nCount;
2422    int res;
2423    while ( lo < hi ) {
2424      i = (lo + hi)/2;
2425
2426      res = str.Cmp(m_pItems[i]);
2427      if ( res < 0 )
2428        hi = i;
2429      else if ( res > 0 )
2430        lo = i + 1;
2431      else {
2432        lo = hi = i;
2433        break;
2434      }
2435    }
2436
2437    wxASSERT_MSG( lo == hi, wxT("binary search broken") );
2438
2439    Insert(str, lo, nInsert);
2440
2441    return (size_t)lo;
2442  }
2443  else {
2444    wxASSERT( str.GetStringData()->IsValid() );
2445
2446    Grow(nInsert);
2447
2448    for (size_t i = 0; i < nInsert; i++)
2449    {
2450        // the string data must not be deleted!
2451        str.GetStringData()->Lock();
2452
2453        // just append
2454        m_pItems[m_nCount + i] = (wxChar *)str.c_str(); // const_cast
2455    }
2456    size_t ret = m_nCount;
2457    m_nCount += nInsert;
2458    return ret;
2459  }
2460}
2461
2462// add item at the given position
2463void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert)
2464{
2465  wxASSERT( str.GetStringData()->IsValid() );
2466
2467  wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Insert") );
2468  wxCHECK_RET( m_nCount <= m_nCount + nInsert,
2469               wxT("array size overflow in wxArrayString::Insert") );
2470
2471  Grow(nInsert);
2472
2473  memmove(&m_pItems[nIndex + nInsert], &m_pItems[nIndex],
2474          (m_nCount - nIndex)*sizeof(wxChar *));
2475
2476  for (size_t i = 0; i < nInsert; i++)
2477  {
2478      str.GetStringData()->Lock();
2479      m_pItems[nIndex + i] = (wxChar *)str.c_str();
2480  }
2481  m_nCount += nInsert;
2482}
2483
2484// range insert (STL 23.2.4.3)
2485void
2486wxArrayString::insert(iterator it, const_iterator first, const_iterator last)
2487{
2488    const int idx = it - begin();
2489
2490    // grow it once
2491    Grow(last - first);
2492
2493    // reset "it" since it can change inside Grow()
2494    it = begin() + idx;
2495
2496    while ( first != last )
2497    {
2498        it = insert(it, *first);
2499
2500        // insert returns an iterator to the last element inserted but we need
2501        // insert the next after this one, that is before the next one
2502        ++it;
2503
2504        ++first;
2505    }
2506}
2507
2508// expand the array
2509void wxArrayString::SetCount(size_t count)
2510{
2511    Alloc(count);
2512
2513    wxString s;
2514    while ( m_nCount < count )
2515        m_pItems[m_nCount++] = (wxChar *)s.c_str();
2516}
2517
2518// removes item from array (by index)
2519void wxArrayString::RemoveAt(size_t nIndex, size_t nRemove)
2520{
2521  wxCHECK_RET( nIndex < m_nCount, wxT("bad index in wxArrayString::Remove") );
2522  wxCHECK_RET( nIndex + nRemove <= m_nCount,
2523               wxT("removing too many elements in wxArrayString::Remove") );
2524
2525  // release our lock
2526  for (size_t i = 0; i < nRemove; i++)
2527      Item(nIndex + i).GetStringData()->Unlock();
2528
2529  memmove(&m_pItems[nIndex], &m_pItems[nIndex + nRemove],
2530          (m_nCount - nIndex - nRemove)*sizeof(wxChar *));
2531  m_nCount -= nRemove;
2532}
2533
2534// removes item from array (by value)
2535void wxArrayString::Remove(const wxChar *sz)
2536{
2537  int iIndex = Index(sz);
2538
2539  wxCHECK_RET( iIndex != wxNOT_FOUND,
2540               wxT("removing inexistent element in wxArrayString::Remove") );
2541
2542  RemoveAt(iIndex);
2543}
2544
2545void wxArrayString::assign(const_iterator first, const_iterator last)
2546{
2547    reserve(last - first);
2548    for(; first != last; ++first)
2549        push_back(*first);
2550}
2551
2552// ----------------------------------------------------------------------------
2553// sorting
2554// ----------------------------------------------------------------------------
2555
2556// we can only sort one array at a time with the quick-sort based
2557// implementation
2558#if wxUSE_THREADS
2559  // need a critical section to protect access to gs_compareFunction and
2560  // gs_sortAscending variables
2561  static wxCriticalSection gs_critsectStringSort;
2562#endif // wxUSE_THREADS
2563
2564// function to use for string comparaison
2565static wxArrayString::CompareFunction gs_compareFunction = NULL;
2566
2567// if we don't use the compare function, this flag tells us if we sort the
2568// array in ascending or descending order
2569static bool gs_sortAscending = true;
2570
2571// function which is called by quick sort
2572extern "C" int wxC_CALLING_CONV     // LINKAGEMODE
2573wxStringCompareFunction(const void *first, const void *second)
2574{
2575  wxString *strFirst = (wxString *)first;
2576  wxString *strSecond = (wxString *)second;
2577
2578  if ( gs_compareFunction ) {
2579    return gs_compareFunction(*strFirst, *strSecond);
2580  }
2581  else {
2582    // maybe we should use wxStrcoll
2583    int result = strFirst->Cmp(*strSecond);
2584
2585    return gs_sortAscending ? result : -result;
2586  }
2587}
2588
2589// sort array elements using passed comparaison function
2590void wxArrayString::Sort(CompareFunction compareFunction)
2591{
2592  wxCRIT_SECT_LOCKER(lockCmpFunc, gs_critsectStringSort);
2593
2594  wxASSERT( !gs_compareFunction );  // must have been reset to NULL
2595  gs_compareFunction = compareFunction;
2596
2597  DoSort();
2598
2599  // reset it to NULL so that Sort(bool) will work the next time
2600  gs_compareFunction = NULL;
2601}
2602
2603extern "C"
2604{
2605    typedef int (wxC_CALLING_CONV * wxStringCompareFn)(const void *first,
2606                                                       const void *second);
2607}
2608
2609void wxArrayString::Sort(CompareFunction2 compareFunction)
2610{
2611  qsort(m_pItems, m_nCount, sizeof(wxChar *), (wxStringCompareFn)compareFunction);
2612}
2613
2614void wxArrayString::Sort(bool reverseOrder)
2615{
2616  Sort(reverseOrder ? wxStringSortDescending : wxStringSortAscending);
2617}
2618
2619void wxArrayString::DoSort()
2620{
2621  wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") );
2622
2623  // just sort the pointers using qsort() - of course it only works because
2624  // wxString() *is* a pointer to its data
2625  qsort(m_pItems, m_nCount, sizeof(wxChar *), wxStringCompareFunction);
2626}
2627
2628bool wxArrayString::operator==(const wxArrayString& a) const
2629{
2630    if ( m_nCount != a.m_nCount )
2631        return false;
2632
2633    for ( size_t n = 0; n < m_nCount; n++ )
2634    {
2635        if ( Item(n) != a[n] )
2636            return false;
2637    }
2638
2639    return true;
2640}
2641
2642#endif // !wxUSE_STL
2643
2644int wxCMPFUNC_CONV wxStringSortAscending(wxString* s1, wxString* s2)
2645{
2646    return  s1->Cmp(*s2);
2647}
2648
2649int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2)
2650{
2651    return -s1->Cmp(*s2);
2652}
2653
2654wxString* wxCArrayString::Release()
2655{
2656    wxString *r = GetStrings();
2657    m_strings = NULL;
2658    return r;
2659}
2660