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