added our own implementation of strto[u]ll() if the system doesn't have one (patch...
[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 #endif
34
35 #include <ctype.h>
36
37 #ifndef __WXWINCE__
38 #include <errno.h>
39 #endif
40
41 #include <string.h>
42 #include <stdlib.h>
43
44 #ifdef __SALFORDC__
45 #include <clib.h>
46 #endif
47
48 #include "wx/hashmap.h"
49
50 // string handling functions used by wxString:
51 #if wxUSE_UNICODE_UTF8
52 #define wxStringMemcpy memcpy
53 #define wxStringMemcmp memcmp
54 #define wxStringMemchr memchr
55 #define wxStringStrlen strlen
56 #else
57 #define wxStringMemcpy wxTmemcpy
58 #define wxStringMemcmp wxTmemcmp
59 #define wxStringMemchr wxTmemchr
60 #define wxStringStrlen wxStrlen
61 #endif
62
63
64 // ---------------------------------------------------------------------------
65 // static class variables definition
66 // ---------------------------------------------------------------------------
67
68 //According to STL _must_ be a -1 size_t
69 const size_t wxString::npos = (size_t) -1;
70
71 // ----------------------------------------------------------------------------
72 // global functions
73 // ----------------------------------------------------------------------------
74
75 #if wxUSE_STD_IOSTREAM
76
77 #include <iostream>
78
79 wxSTD ostream& operator<<(wxSTD ostream& os, const wxCStrData& str)
80 {
81 // FIXME-UTF8: always, not only if wxUSE_UNICODE
82 #if wxUSE_UNICODE && !defined(__BORLANDC__)
83 return os << str.AsWChar();
84 #else
85 return os << str.AsChar();
86 #endif
87 }
88
89 wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
90 {
91 return os << str.c_str();
92 }
93
94 wxSTD ostream& operator<<(wxSTD ostream& os, const wxCharBuffer& str)
95 {
96 return os << str.data();
97 }
98
99 #ifndef __BORLANDC__
100 wxSTD ostream& operator<<(wxSTD ostream& os, const wxWCharBuffer& str)
101 {
102 return os << str.data();
103 }
104 #endif
105
106 #endif // wxUSE_STD_IOSTREAM
107
108 // ----------------------------------------------------------------------------
109 // wxCStrData converted strings caching
110 // ----------------------------------------------------------------------------
111
112 // FIXME-UTF8: temporarily disabled because it doesn't work with global
113 // string objects; re-enable after fixing this bug and benchmarking
114 // performance to see if using a hash is a good idea at all
115 #if 0
116
117 // For backward compatibility reasons, it must be possible to assign the value
118 // returned by wxString::c_str() to a char* or wchar_t* variable and work with
119 // it. Returning wxCharBuffer from (const char*)c_str() wouldn't do the trick,
120 // because the memory would be freed immediately, but it has to be valid as long
121 // as the string is not modified, so that code like this still works:
122 //
123 // const wxChar *s = str.c_str();
124 // while ( s ) { ... }
125
126 // FIXME-UTF8: not thread safe!
127 // FIXME-UTF8: we currently clear the cached conversion only when the string is
128 // destroyed, but we should do it when the string is modified, to
129 // keep memory usage down
130 // FIXME-UTF8: we do the conversion every time As[W]Char() is called, but if we
131 // invalidated the cache on every change, we could keep the previous
132 // conversion
133 // FIXME-UTF8: add tracing of usage of these two methods - new code is supposed
134 // to use mb_str() or wc_str() instead of (const [w]char*)c_str()
135
136 template<typename T>
137 static inline void DeleteStringFromConversionCache(T& hash, const wxString *s)
138 {
139 typename T::iterator i = hash.find(wxConstCast(s, wxString));
140 if ( i != hash.end() )
141 {
142 free(i->second);
143 hash.erase(i);
144 }
145 }
146
147 #if wxUSE_UNICODE
148 // NB: non-STL implementation doesn't compile with "const wxString*" key type,
149 // so we have to use wxString* here and const-cast when used
150 WX_DECLARE_HASH_MAP(wxString*, char*, wxPointerHash, wxPointerEqual,
151 wxStringCharConversionCache);
152 static wxStringCharConversionCache gs_stringsCharCache;
153
154 const char* wxCStrData::AsChar() const
155 {
156 // remove previously cache value, if any (see FIXMEs above):
157 DeleteStringFromConversionCache(gs_stringsCharCache, m_str);
158
159 // convert the string and keep it:
160 const char *s = gs_stringsCharCache[wxConstCast(m_str, wxString)] =
161 m_str->mb_str().release();
162
163 return s + m_offset;
164 }
165 #endif // wxUSE_UNICODE
166
167 #if !wxUSE_UNICODE_WCHAR
168 WX_DECLARE_HASH_MAP(wxString*, wchar_t*, wxPointerHash, wxPointerEqual,
169 wxStringWCharConversionCache);
170 static wxStringWCharConversionCache gs_stringsWCharCache;
171
172 const wchar_t* wxCStrData::AsWChar() const
173 {
174 // remove previously cache value, if any (see FIXMEs above):
175 DeleteStringFromConversionCache(gs_stringsWCharCache, m_str);
176
177 // convert the string and keep it:
178 const wchar_t *s = gs_stringsWCharCache[wxConstCast(m_str, wxString)] =
179 m_str->wc_str().release();
180
181 return s + m_offset;
182 }
183 #endif // !wxUSE_UNICODE_WCHAR
184
185 wxString::~wxString()
186 {
187 #if wxUSE_UNICODE
188 // FIXME-UTF8: do this only if locale is not UTF8 if wxUSE_UNICODE_UTF8
189 DeleteStringFromConversionCache(gs_stringsCharCache, this);
190 #endif
191 #if !wxUSE_UNICODE_WCHAR
192 DeleteStringFromConversionCache(gs_stringsWCharCache, this);
193 #endif
194 }
195 #endif
196
197 #if wxUSE_UNICODE
198 const char* wxCStrData::AsChar() const
199 {
200 wxString *str = wxConstCast(m_str, wxString);
201
202 // convert the string:
203 wxCharBuffer buf(str->mb_str());
204
205 // FIXME-UTF8: do the conversion in-place in the existing buffer
206 if ( str->m_convertedToChar &&
207 strlen(buf) == strlen(str->m_convertedToChar) )
208 {
209 // keep the same buffer for as long as possible, so that several calls
210 // to c_str() in a row still work:
211 strcpy(str->m_convertedToChar, buf);
212 }
213 else
214 {
215 str->m_convertedToChar = buf.release();
216 }
217
218 // and keep it:
219 return str->m_convertedToChar + m_offset;
220 }
221 #endif // wxUSE_UNICODE
222
223 #if !wxUSE_UNICODE_WCHAR
224 const wchar_t* wxCStrData::AsWChar() const
225 {
226 wxString *str = wxConstCast(m_str, wxString);
227
228 // convert the string:
229 wxWCharBuffer buf(str->wc_str());
230
231 // FIXME-UTF8: do the conversion in-place in the existing buffer
232 if ( str->m_convertedToWChar &&
233 wxWcslen(buf) == wxWcslen(str->m_convertedToWChar) )
234 {
235 // keep the same buffer for as long as possible, so that several calls
236 // to c_str() in a row still work:
237 memcpy(str->m_convertedToWChar, buf, sizeof(wchar_t) * wxWcslen(buf));
238 }
239 else
240 {
241 str->m_convertedToWChar = buf.release();
242 }
243
244 // and keep it:
245 return str->m_convertedToWChar + m_offset;
246 }
247 #endif // !wxUSE_UNICODE_WCHAR
248
249 // ===========================================================================
250 // wxString class core
251 // ===========================================================================
252
253 // ---------------------------------------------------------------------------
254 // construction and conversion
255 // ---------------------------------------------------------------------------
256
257 #if wxUSE_UNICODE
258 /* static */
259 wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
260 const wxMBConv& conv)
261 {
262 // anything to do?
263 if ( !psz || nLength == 0 )
264 return SubstrBufFromMB();
265
266 if ( nLength == npos )
267 nLength = wxNO_LEN;
268
269 size_t wcLen;
270 wxWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
271 if ( !wcLen )
272 return SubstrBufFromMB();
273 else
274 return SubstrBufFromMB(wcBuf, wcLen);
275 }
276 #else
277 /* static */
278 wxString::SubstrBufFromWC wxString::ConvertStr(const wchar_t *pwz, size_t nLength,
279 const wxMBConv& conv)
280 {
281 // anything to do?
282 if ( !pwz || nLength == 0 )
283 return SubstrBufFromWC();
284
285 if ( nLength == npos )
286 nLength = wxNO_LEN;
287
288 size_t mbLen;
289 wxCharBuffer mbBuf(conv.cWC2MB(pwz, nLength, &mbLen));
290 if ( !mbLen )
291 return SubstrBufFromWC();
292 else
293 return SubstrBufFromWC(mbBuf, mbLen);
294 }
295 #endif
296
297
298 #if wxUSE_UNICODE
299
300 //Convert wxString in Unicode mode to a multi-byte string
301 const wxCharBuffer wxString::mb_str(const wxMBConv& conv) const
302 {
303 return conv.cWC2MB(c_str(), length() + 1 /* size, not length */, NULL);
304 }
305
306 #else // ANSI
307
308 #if wxUSE_WCHAR_T
309
310 //Converts this string to a wide character string if unicode
311 //mode is not enabled and wxUSE_WCHAR_T is enabled
312 const wxWCharBuffer wxString::wc_str(const wxMBConv& conv) const
313 {
314 return conv.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL);
315 }
316
317 #endif // wxUSE_WCHAR_T
318
319 #endif // Unicode/ANSI
320
321 // shrink to minimal size (releasing extra memory)
322 bool wxString::Shrink()
323 {
324 wxString tmp(begin(), end());
325 swap(tmp);
326 return tmp.length() == length();
327 }
328
329 // deprecated compatibility code:
330 #if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
331 wxChar *wxString::GetWriteBuf(size_t nLen)
332 {
333 return DoGetWriteBuf(nLen);
334 }
335
336 void wxString::UngetWriteBuf()
337 {
338 DoUngetWriteBuf();
339 }
340
341 void wxString::UngetWriteBuf(size_t nLen)
342 {
343 DoUngetWriteBuf(nLen);
344 }
345 #endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
346
347
348 // ---------------------------------------------------------------------------
349 // data access
350 // ---------------------------------------------------------------------------
351
352 // all functions are inline in string.h
353
354 // ---------------------------------------------------------------------------
355 // concatenation operators
356 // ---------------------------------------------------------------------------
357
358 /*
359 * concatenation functions come in 5 flavours:
360 * string + string
361 * char + string and string + char
362 * C str + string and string + C str
363 */
364
365 wxString operator+(const wxString& str1, const wxString& str2)
366 {
367 #if !wxUSE_STL_BASED_WXSTRING
368 wxASSERT( str1.IsValid() );
369 wxASSERT( str2.IsValid() );
370 #endif
371
372 wxString s = str1;
373 s += str2;
374
375 return s;
376 }
377
378 wxString operator+(const wxString& str, wxUniChar ch)
379 {
380 #if !wxUSE_STL_BASED_WXSTRING
381 wxASSERT( str.IsValid() );
382 #endif
383
384 wxString s = str;
385 s += ch;
386
387 return s;
388 }
389
390 wxString operator+(wxUniChar ch, const wxString& str)
391 {
392 #if !wxUSE_STL_BASED_WXSTRING
393 wxASSERT( str.IsValid() );
394 #endif
395
396 wxString s = ch;
397 s += str;
398
399 return s;
400 }
401
402 wxString operator+(const wxString& str, const char *psz)
403 {
404 #if !wxUSE_STL_BASED_WXSTRING
405 wxASSERT( str.IsValid() );
406 #endif
407
408 wxString s;
409 if ( !s.Alloc(strlen(psz) + str.length()) ) {
410 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
411 }
412 s += str;
413 s += psz;
414
415 return s;
416 }
417
418 wxString operator+(const wxString& str, const wchar_t *pwz)
419 {
420 #if !wxUSE_STL_BASED_WXSTRING
421 wxASSERT( str.IsValid() );
422 #endif
423
424 wxString s;
425 if ( !s.Alloc(wxWcslen(pwz) + str.length()) ) {
426 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
427 }
428 s += str;
429 s += pwz;
430
431 return s;
432 }
433
434 wxString operator+(const char *psz, const wxString& str)
435 {
436 #if !wxUSE_STL_BASED_WXSTRING
437 wxASSERT( str.IsValid() );
438 #endif
439
440 wxString s;
441 if ( !s.Alloc(strlen(psz) + str.length()) ) {
442 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
443 }
444 s = psz;
445 s += str;
446
447 return s;
448 }
449
450 wxString operator+(const wchar_t *pwz, const wxString& str)
451 {
452 #if !wxUSE_STL_BASED_WXSTRING
453 wxASSERT( str.IsValid() );
454 #endif
455
456 wxString s;
457 if ( !s.Alloc(wxWcslen(pwz) + str.length()) ) {
458 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
459 }
460 s = pwz;
461 s += str;
462
463 return s;
464 }
465
466 // ---------------------------------------------------------------------------
467 // string comparison
468 // ---------------------------------------------------------------------------
469
470 #ifdef HAVE_STD_STRING_COMPARE
471
472 // NB: Comparison code (both if HAVE_STD_STRING_COMPARE and if not) works with
473 // UTF-8 encoded strings too, thanks to UTF-8's design which allows us to
474 // sort strings in characters code point order by sorting the byte sequence
475 // in byte values order (i.e. what strcmp() and memcmp() do).
476
477 int wxString::compare(const wxString& str) const
478 {
479 return m_impl.compare(str.m_impl);
480 }
481
482 int wxString::compare(size_t nStart, size_t nLen,
483 const wxString& str) const
484 {
485 size_t pos, len;
486 PosLenToImpl(nStart, nLen, &pos, &len);
487 return m_impl.compare(pos, len, str.m_impl);
488 }
489
490 int wxString::compare(size_t nStart, size_t nLen,
491 const wxString& str,
492 size_t nStart2, size_t nLen2) const
493 {
494 size_t pos, len;
495 PosLenToImpl(nStart, nLen, &pos, &len);
496
497 size_t pos2, len2;
498 str.PosLenToImpl(nStart2, nLen2, &pos2, &len2);
499
500 return m_impl.compare(pos, len, str.m_impl, pos2, len2);
501 }
502
503 int wxString::compare(const char* sz) const
504 {
505 return m_impl.compare(ImplStr(sz));
506 }
507
508 int wxString::compare(const wchar_t* sz) const
509 {
510 return m_impl.compare(ImplStr(sz));
511 }
512
513 int wxString::compare(size_t nStart, size_t nLen,
514 const char* sz, size_t nCount) const
515 {
516 size_t pos, len;
517 PosLenToImpl(nStart, nLen, &pos, &len);
518
519 SubstrBufFromMB str(ImplStr(sz, nCount));
520
521 return m_impl.compare(pos, len, str.data, str.len);
522 }
523
524 int wxString::compare(size_t nStart, size_t nLen,
525 const wchar_t* sz, size_t nCount) const
526 {
527 size_t pos, len;
528 PosLenToImpl(nStart, nLen, &pos, &len);
529
530 SubstrBufFromWC str(ImplStr(sz, nCount));
531
532 return m_impl.compare(pos, len, str.data, str.len);
533 }
534
535 #else // !HAVE_STD_STRING_COMPARE
536
537 static inline int wxDoCmp(const wxStringCharType* s1, size_t l1,
538 const wxStringCharType* s2, size_t l2)
539 {
540 if( l1 == l2 )
541 return wxStringMemcmp(s1, s2, l1);
542 else if( l1 < l2 )
543 {
544 int ret = wxStringMemcmp(s1, s2, l1);
545 return ret == 0 ? -1 : ret;
546 }
547 else
548 {
549 int ret = wxStringMemcmp(s1, s2, l2);
550 return ret == 0 ? +1 : ret;
551 }
552 }
553
554 int wxString::compare(const wxString& str) const
555 {
556 return ::wxDoCmp(m_impl.data(), m_impl.length(),
557 str.m_impl.data(), str.m_impl.length());
558 }
559
560 int wxString::compare(size_t nStart, size_t nLen,
561 const wxString& str) const
562 {
563 wxASSERT(nStart <= length());
564 size_type strLen = length() - nStart;
565 nLen = strLen < nLen ? strLen : nLen;
566
567 size_t pos, len;
568 PosLenToImpl(nStart, nLen, &pos, &len);
569
570 return ::wxDoCmp(m_impl.data() + pos, len,
571 str.m_impl.data(), str.m_impl.length());
572 }
573
574 int wxString::compare(size_t nStart, size_t nLen,
575 const wxString& str,
576 size_t nStart2, size_t nLen2) const
577 {
578 wxASSERT(nStart <= length());
579 wxASSERT(nStart2 <= str.length());
580 size_type strLen = length() - nStart,
581 strLen2 = str.length() - nStart2;
582 nLen = strLen < nLen ? strLen : nLen;
583 nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
584
585 size_t pos, len;
586 PosLenToImpl(nStart, nLen, &pos, &len);
587 size_t pos2, len2;
588 str.PosLenToImpl(nStart2, nLen2, &pos2, &len2);
589
590 return ::wxDoCmp(m_impl.data() + pos, len,
591 str.m_impl.data() + pos2, len2);
592 }
593
594 int wxString::compare(const char* sz) const
595 {
596 SubstrBufFromMB str(ImplStr(sz, npos));
597 if ( str.len == npos )
598 str.len = wxStringStrlen(str.data);
599 return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len);
600 }
601
602 int wxString::compare(const wchar_t* sz) const
603 {
604 SubstrBufFromWC str(ImplStr(sz, npos));
605 if ( str.len == npos )
606 str.len = wxStringStrlen(str.data);
607 return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len);
608 }
609
610 int wxString::compare(size_t nStart, size_t nLen,
611 const char* sz, size_t nCount) const
612 {
613 wxASSERT(nStart <= length());
614 size_type strLen = length() - nStart;
615 nLen = strLen < nLen ? strLen : nLen;
616
617 size_t pos, len;
618 PosLenToImpl(nStart, nLen, &pos, &len);
619
620 SubstrBufFromMB str(ImplStr(sz, nCount));
621 if ( str.len == npos )
622 str.len = wxStringStrlen(str.data);
623
624 return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len);
625 }
626
627 int wxString::compare(size_t nStart, size_t nLen,
628 const wchar_t* sz, size_t nCount) const
629 {
630 wxASSERT(nStart <= length());
631 size_type strLen = length() - nStart;
632 nLen = strLen < nLen ? strLen : nLen;
633
634 size_t pos, len;
635 PosLenToImpl(nStart, nLen, &pos, &len);
636
637 SubstrBufFromWC str(ImplStr(sz, nCount));
638 if ( str.len == npos )
639 str.len = wxStringStrlen(str.data);
640
641 return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len);
642 }
643
644 #endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE
645
646
647 // ---------------------------------------------------------------------------
648 // find_{first,last}_[not]_of functions
649 // ---------------------------------------------------------------------------
650
651 #if !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
652
653 // NB: All these functions are implemented with the argument being wxChar*,
654 // i.e. widechar string in any Unicode build, even though native string
655 // representation is char* in the UTF-8 build. This is because we couldn't
656 // use memchr() to determine if a character is in a set encoded as UTF-8.
657
658 size_t wxString::find_first_of(const wxChar* sz, size_t nStart) const
659 {
660 return find_first_of(sz, nStart, wxStrlen(sz));
661 }
662
663 size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart) const
664 {
665 return find_first_not_of(sz, nStart, wxStrlen(sz));
666 }
667
668 size_t wxString::find_first_of(const wxChar* sz, size_t nStart, size_t n) const
669 {
670 wxASSERT_MSG( nStart <= length(), _T("invalid index") );
671
672 size_t idx = nStart;
673 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
674 {
675 if ( wxTmemchr(sz, *i, n) )
676 return idx;
677 }
678
679 return npos;
680 }
681
682 size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart, size_t n) const
683 {
684 wxASSERT_MSG( nStart <= length(), _T("invalid index") );
685
686 size_t idx = nStart;
687 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
688 {
689 if ( !wxTmemchr(sz, *i, n) )
690 return idx;
691 }
692
693 return npos;
694 }
695
696
697 size_t wxString::find_last_of(const wxChar* sz, size_t nStart) const
698 {
699 return find_last_of(sz, nStart, wxStrlen(sz));
700 }
701
702 size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart) const
703 {
704 return find_last_not_of(sz, nStart, wxStrlen(sz));
705 }
706
707 size_t wxString::find_last_of(const wxChar* sz, size_t nStart, size_t n) const
708 {
709 size_t len = length();
710
711 if ( nStart == npos )
712 {
713 nStart = len - 1;
714 }
715 else
716 {
717 wxASSERT_MSG( nStart <= len, _T("invalid index") );
718 }
719
720 size_t idx = nStart;
721 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
722 i != rend(); --idx, ++i )
723 {
724 if ( wxTmemchr(sz, *i, n) )
725 return idx;
726 }
727
728 return npos;
729 }
730
731 size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart, size_t n) const
732 {
733 size_t len = length();
734
735 if ( nStart == npos )
736 {
737 nStart = len - 1;
738 }
739 else
740 {
741 wxASSERT_MSG( nStart <= len, _T("invalid index") );
742 }
743
744 size_t idx = nStart;
745 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
746 i != rend(); --idx, ++i )
747 {
748 if ( !wxTmemchr(sz, *i, n) )
749 return idx;
750 }
751
752 return npos;
753 }
754
755 size_t wxString::find_first_not_of(wxUniChar ch, size_t nStart) const
756 {
757 wxASSERT_MSG( nStart <= length(), _T("invalid index") );
758
759 size_t idx = nStart;
760 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
761 {
762 if ( *i != ch )
763 return idx;
764 }
765
766 return npos;
767 }
768
769 size_t wxString::find_last_not_of(wxUniChar ch, size_t nStart) const
770 {
771 size_t len = length();
772
773 if ( nStart == npos )
774 {
775 nStart = len - 1;
776 }
777 else
778 {
779 wxASSERT_MSG( nStart <= len, _T("invalid index") );
780 }
781
782 size_t idx = nStart;
783 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
784 i != rend(); --idx, ++i )
785 {
786 if ( *i != ch )
787 return idx;
788 }
789
790 return npos;
791 }
792
793 // the functions above were implemented for wchar_t* arguments in Unicode
794 // build and char* in ANSI build; below are implementations for the other
795 // version:
796 #if wxUSE_UNICODE
797 #define wxOtherCharType char
798 #define STRCONV (const wxChar*)wxConvLibc.cMB2WC
799 #else
800 #define wxOtherCharType wchar_t
801 #define STRCONV (const wxChar*)wxConvLibc.cWC2MB
802 #endif
803
804 size_t wxString::find_first_of(const wxOtherCharType* sz, size_t nStart) const
805 { return find_first_of(STRCONV(sz), nStart); }
806
807 size_t wxString::find_first_of(const wxOtherCharType* sz, size_t nStart,
808 size_t n) const
809 { return find_first_of(STRCONV(sz, n, NULL), nStart, n); }
810 size_t wxString::find_last_of(const wxOtherCharType* sz, size_t nStart) const
811 { return find_last_of(STRCONV(sz), nStart); }
812 size_t wxString::find_last_of(const wxOtherCharType* sz, size_t nStart,
813 size_t n) const
814 { return find_last_of(STRCONV(sz, n, NULL), nStart, n); }
815 size_t wxString::find_first_not_of(const wxOtherCharType* sz, size_t nStart) const
816 { return find_first_not_of(STRCONV(sz), nStart); }
817 size_t wxString::find_first_not_of(const wxOtherCharType* sz, size_t nStart,
818 size_t n) const
819 { return find_first_not_of(STRCONV(sz, n, NULL), nStart, n); }
820 size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart) const
821 { return find_last_not_of(STRCONV(sz), nStart); }
822 size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart,
823 size_t n) const
824 { return find_last_not_of(STRCONV(sz, n, NULL), nStart, n); }
825
826 #undef wxOtherCharType
827 #undef STRCONV
828
829 #endif // !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
830
831 // ===========================================================================
832 // other common string functions
833 // ===========================================================================
834
835 int wxString::CmpNoCase(const wxString& s) const
836 {
837 // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
838
839 size_t idx = 0;
840 const_iterator i1 = begin();
841 const_iterator end1 = end();
842 const_iterator i2 = s.begin();
843 const_iterator end2 = s.end();
844
845 for ( ; i1 != end1 && i2 != end2; ++idx, ++i1, ++i2 )
846 {
847 wxUniChar lower1 = (wxChar)wxTolower(*i1);
848 wxUniChar lower2 = (wxChar)wxTolower(*i2);
849 if ( lower1 != lower2 )
850 return lower1 < lower2 ? -1 : 1;
851 }
852
853 size_t len1 = length();
854 size_t len2 = s.length();
855
856 if ( len1 < len2 )
857 return -1;
858 else if ( len1 > len2 )
859 return 1;
860 return 0;
861 }
862
863
864 #if wxUSE_UNICODE
865
866 #ifdef __MWERKS__
867 #ifndef __SCHAR_MAX__
868 #define __SCHAR_MAX__ 127
869 #endif
870 #endif
871
872 wxString wxString::FromAscii(const char *ascii)
873 {
874 if (!ascii)
875 return wxEmptyString;
876
877 size_t len = strlen( ascii );
878 wxString res;
879
880 if ( len )
881 {
882 wxStringBuffer buf(res, len);
883
884 wchar_t *dest = buf;
885
886 for ( ;; )
887 {
888 if ( (*dest++ = (wchar_t)(unsigned char)*ascii++) == L'\0' )
889 break;
890 }
891 }
892
893 return res;
894 }
895
896 wxString wxString::FromAscii(const char ascii)
897 {
898 // What do we do with '\0' ?
899
900 wxString res;
901 res += (wchar_t)(unsigned char) ascii;
902
903 return res;
904 }
905
906 const wxCharBuffer wxString::ToAscii() const
907 {
908 // this will allocate enough space for the terminating NUL too
909 wxCharBuffer buffer(length());
910
911
912 char *dest = buffer.data();
913
914 const wchar_t *pwc = c_str();
915 for ( ;; )
916 {
917 *dest++ = (char)(*pwc > SCHAR_MAX ? wxT('_') : *pwc);
918
919 // the output string can't have embedded NULs anyhow, so we can safely
920 // stop at first of them even if we do have any
921 if ( !*pwc++ )
922 break;
923 }
924
925 return buffer;
926 }
927
928 #endif // Unicode
929
930 // extract string of length nCount starting at nFirst
931 wxString wxString::Mid(size_t nFirst, size_t nCount) const
932 {
933 size_t nLen = length();
934
935 // default value of nCount is npos and means "till the end"
936 if ( nCount == npos )
937 {
938 nCount = nLen - nFirst;
939 }
940
941 // out-of-bounds requests return sensible things
942 if ( nFirst + nCount > nLen )
943 {
944 nCount = nLen - nFirst;
945 }
946
947 if ( nFirst > nLen )
948 {
949 // AllocCopy() will return empty string
950 return wxEmptyString;
951 }
952
953 wxString dest(*this, nFirst, nCount);
954 if ( dest.length() != nCount )
955 {
956 wxFAIL_MSG( _T("out of memory in wxString::Mid") );
957 }
958
959 return dest;
960 }
961
962 // check that the string starts with prefix and return the rest of the string
963 // in the provided pointer if it is not NULL, otherwise return false
964 bool wxString::StartsWith(const wxChar *prefix, wxString *rest) const
965 {
966 wxASSERT_MSG( prefix, _T("invalid parameter in wxString::StartsWith") );
967
968 // first check if the beginning of the string matches the prefix: note
969 // that we don't have to check that we don't run out of this string as
970 // when we reach the terminating NUL, either prefix string ends too (and
971 // then it's ok) or we break out of the loop because there is no match
972 const wxChar *p = c_str();
973 while ( *prefix )
974 {
975 if ( *prefix++ != *p++ )
976 {
977 // no match
978 return false;
979 }
980 }
981
982 if ( rest )
983 {
984 // put the rest of the string into provided pointer
985 *rest = p;
986 }
987
988 return true;
989 }
990
991
992 // check that the string ends with suffix and return the rest of it in the
993 // provided pointer if it is not NULL, otherwise return false
994 bool wxString::EndsWith(const wxChar *suffix, wxString *rest) const
995 {
996 wxASSERT_MSG( suffix, _T("invalid parameter in wxString::EndssWith") );
997
998 int start = length() - wxStrlen(suffix);
999 if ( start < 0 || wxStrcmp(wx_str() + start, suffix) != 0 )
1000 return false;
1001
1002 if ( rest )
1003 {
1004 // put the rest of the string into provided pointer
1005 rest->assign(*this, 0, start);
1006 }
1007
1008 return true;
1009 }
1010
1011
1012 // extract nCount last (rightmost) characters
1013 wxString wxString::Right(size_t nCount) const
1014 {
1015 if ( nCount > length() )
1016 nCount = length();
1017
1018 wxString dest(*this, length() - nCount, nCount);
1019 if ( dest.length() != nCount ) {
1020 wxFAIL_MSG( _T("out of memory in wxString::Right") );
1021 }
1022 return dest;
1023 }
1024
1025 // get all characters after the last occurence of ch
1026 // (returns the whole string if ch not found)
1027 wxString wxString::AfterLast(wxUniChar ch) const
1028 {
1029 wxString str;
1030 int iPos = Find(ch, true);
1031 if ( iPos == wxNOT_FOUND )
1032 str = *this;
1033 else
1034 str = wx_str() + iPos + 1;
1035
1036 return str;
1037 }
1038
1039 // extract nCount first (leftmost) characters
1040 wxString wxString::Left(size_t nCount) const
1041 {
1042 if ( nCount > length() )
1043 nCount = length();
1044
1045 wxString dest(*this, 0, nCount);
1046 if ( dest.length() != nCount ) {
1047 wxFAIL_MSG( _T("out of memory in wxString::Left") );
1048 }
1049 return dest;
1050 }
1051
1052 // get all characters before the first occurence of ch
1053 // (returns the whole string if ch not found)
1054 wxString wxString::BeforeFirst(wxUniChar ch) const
1055 {
1056 int iPos = Find(ch);
1057 if ( iPos == wxNOT_FOUND ) iPos = length();
1058 return wxString(*this, 0, iPos);
1059 }
1060
1061 /// get all characters before the last occurence of ch
1062 /// (returns empty string if ch not found)
1063 wxString wxString::BeforeLast(wxUniChar ch) const
1064 {
1065 wxString str;
1066 int iPos = Find(ch, true);
1067 if ( iPos != wxNOT_FOUND && iPos != 0 )
1068 str = wxString(c_str(), iPos);
1069
1070 return str;
1071 }
1072
1073 /// get all characters after the first occurence of ch
1074 /// (returns empty string if ch not found)
1075 wxString wxString::AfterFirst(wxUniChar ch) const
1076 {
1077 wxString str;
1078 int iPos = Find(ch);
1079 if ( iPos != wxNOT_FOUND )
1080 str = wx_str() + iPos + 1;
1081
1082 return str;
1083 }
1084
1085 // replace first (or all) occurences of some substring with another one
1086 size_t wxString::Replace(const wxString& strOld,
1087 const wxString& strNew, bool bReplaceAll)
1088 {
1089 // if we tried to replace an empty string we'd enter an infinite loop below
1090 wxCHECK_MSG( !strOld.empty(), 0,
1091 _T("wxString::Replace(): invalid parameter") );
1092
1093 size_t uiCount = 0; // count of replacements made
1094
1095 size_t uiOldLen = strOld.length();
1096 size_t uiNewLen = strNew.length();
1097
1098 size_t dwPos = 0;
1099
1100 while ( (*this)[dwPos] != wxT('\0') )
1101 {
1102 //DO NOT USE STRSTR HERE
1103 //this string can contain embedded null characters,
1104 //so strstr will function incorrectly
1105 dwPos = find(strOld, dwPos);
1106 if ( dwPos == npos )
1107 break; // exit the loop
1108 else
1109 {
1110 //replace this occurance of the old string with the new one
1111 replace(dwPos, uiOldLen, strNew, uiNewLen);
1112
1113 //move up pos past the string that was replaced
1114 dwPos += uiNewLen;
1115
1116 //increase replace count
1117 ++uiCount;
1118
1119 // stop now?
1120 if ( !bReplaceAll )
1121 break; // exit the loop
1122 }
1123 }
1124
1125 return uiCount;
1126 }
1127
1128 bool wxString::IsAscii() const
1129 {
1130 const wxChar *s = (const wxChar*) *this;
1131 while(*s){
1132 if(!isascii(*s)) return(false);
1133 s++;
1134 }
1135 return(true);
1136 }
1137
1138 bool wxString::IsWord() const
1139 {
1140 const wxChar *s = (const wxChar*) *this;
1141 while(*s){
1142 if(!wxIsalpha(*s)) return(false);
1143 s++;
1144 }
1145 return(true);
1146 }
1147
1148 bool wxString::IsNumber() const
1149 {
1150 const wxChar *s = (const wxChar*) *this;
1151 if (wxStrlen(s))
1152 if ((s[0] == wxT('-')) || (s[0] == wxT('+'))) s++;
1153 while(*s){
1154 if(!wxIsdigit(*s)) return(false);
1155 s++;
1156 }
1157 return(true);
1158 }
1159
1160 wxString wxString::Strip(stripType w) const
1161 {
1162 wxString s = *this;
1163 if ( w & leading ) s.Trim(false);
1164 if ( w & trailing ) s.Trim(true);
1165 return s;
1166 }
1167
1168 // ---------------------------------------------------------------------------
1169 // case conversion
1170 // ---------------------------------------------------------------------------
1171
1172 wxString& wxString::MakeUpper()
1173 {
1174 for ( iterator it = begin(), en = end(); it != en; ++it )
1175 *it = (wxChar)wxToupper(*it);
1176
1177 return *this;
1178 }
1179
1180 wxString& wxString::MakeLower()
1181 {
1182 for ( iterator it = begin(), en = end(); it != en; ++it )
1183 *it = (wxChar)wxTolower(*it);
1184
1185 return *this;
1186 }
1187
1188 // ---------------------------------------------------------------------------
1189 // trimming and padding
1190 // ---------------------------------------------------------------------------
1191
1192 // some compilers (VC++ 6.0 not to name them) return true for a call to
1193 // isspace('ê') in the C locale which seems to be broken to me, but we have to
1194 // live with this by checking that the character is a 7 bit one - even if this
1195 // may fail to detect some spaces (I don't know if Unicode doesn't have
1196 // space-like symbols somewhere except in the first 128 chars), it is arguably
1197 // still better than trimming away accented letters
1198 inline int wxSafeIsspace(wxChar ch) { return (ch < 127) && wxIsspace(ch); }
1199
1200 // trims spaces (in the sense of isspace) from left or right side
1201 wxString& wxString::Trim(bool bFromRight)
1202 {
1203 // first check if we're going to modify the string at all
1204 if ( !empty() &&
1205 (
1206 (bFromRight && wxSafeIsspace(GetChar(length() - 1))) ||
1207 (!bFromRight && wxSafeIsspace(GetChar(0u)))
1208 )
1209 )
1210 {
1211 if ( bFromRight )
1212 {
1213 // find last non-space character
1214 reverse_iterator psz = rbegin();
1215 while ( (psz != rend()) && wxSafeIsspace(*psz) )
1216 psz++;
1217
1218 // truncate at trailing space start
1219 erase(psz.base(), end());
1220 }
1221 else
1222 {
1223 // find first non-space character
1224 iterator psz = begin();
1225 while ( (psz != end()) && wxSafeIsspace(*psz) )
1226 psz++;
1227
1228 // fix up data and length
1229 erase(begin(), psz);
1230 }
1231 }
1232
1233 return *this;
1234 }
1235
1236 // adds nCount characters chPad to the string from either side
1237 wxString& wxString::Pad(size_t nCount, wxUniChar chPad, bool bFromRight)
1238 {
1239 wxString s(chPad, nCount);
1240
1241 if ( bFromRight )
1242 *this += s;
1243 else
1244 {
1245 s += *this;
1246 swap(s);
1247 }
1248
1249 return *this;
1250 }
1251
1252 // truncate the string
1253 wxString& wxString::Truncate(size_t uiLen)
1254 {
1255 if ( uiLen < length() )
1256 {
1257 erase(begin() + uiLen, end());
1258 }
1259 //else: nothing to do, string is already short enough
1260
1261 return *this;
1262 }
1263
1264 // ---------------------------------------------------------------------------
1265 // finding (return wxNOT_FOUND if not found and index otherwise)
1266 // ---------------------------------------------------------------------------
1267
1268 // find a character
1269 int wxString::Find(wxUniChar ch, bool bFromEnd) const
1270 {
1271 size_type idx = bFromEnd ? find_last_of(ch) : find_first_of(ch);
1272
1273 return (idx == npos) ? wxNOT_FOUND : (int)idx;
1274 }
1275
1276 // ----------------------------------------------------------------------------
1277 // conversion to numbers
1278 // ----------------------------------------------------------------------------
1279
1280 // the implementation of all the functions below is exactly the same so factor
1281 // it out
1282
1283 template <typename T, typename F>
1284 bool wxStringToIntType(const wxChar *start,
1285 T *val,
1286 int base,
1287 F func)
1288 {
1289 wxCHECK_MSG( val, false, _T("NULL output pointer") );
1290 wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
1291
1292 #ifndef __WXWINCE__
1293 errno = 0;
1294 #endif
1295
1296 wxChar *end;
1297 *val = (*func)(start, &end, base);
1298
1299 // return true only if scan was stopped by the terminating NUL and if the
1300 // string was not empty to start with and no under/overflow occurred
1301 return !*end && (end != start)
1302 #ifndef __WXWINCE__
1303 && (errno != ERANGE)
1304 #endif
1305 ;
1306 }
1307
1308 bool wxString::ToLong(long *val, int base) const
1309 {
1310 return wxStringToIntType((const wxChar*)c_str(), val, base, wxStrtol);
1311 }
1312
1313 bool wxString::ToULong(unsigned long *val, int base) const
1314 {
1315 return wxStringToIntType((const wxChar*)c_str(), val, base, wxStrtoul);
1316 }
1317
1318 bool wxString::ToLongLong(wxLongLong_t *val, int base) const
1319 {
1320 return wxStringToIntType((const wxChar*)c_str(), val, base, wxStrtoll);
1321 }
1322
1323 bool wxString::ToULongLong(wxULongLong_t *val, int base) const
1324 {
1325 return wxStringToIntType((const wxChar*)c_str(), val, base, wxStrtoull);
1326 }
1327
1328 bool wxString::ToDouble(double *val) const
1329 {
1330 wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToDouble") );
1331
1332 #ifndef __WXWINCE__
1333 errno = 0;
1334 #endif
1335
1336 const wxChar *start = c_str();
1337 wxChar *end;
1338 *val = wxStrtod(start, &end);
1339
1340 // return true only if scan was stopped by the terminating NUL and if the
1341 // string was not empty to start with and no under/overflow occurred
1342 return !*end && (end != start)
1343 #ifndef __WXWINCE__
1344 && (errno != ERANGE)
1345 #endif
1346 ;
1347 }
1348
1349 // ---------------------------------------------------------------------------
1350 // formatted output
1351 // ---------------------------------------------------------------------------
1352
1353 /* static */
1354 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1355 wxString wxStringPrintfMixinBase::DoFormat(const wxChar *format, ...)
1356 #else
1357 wxString wxString::DoFormat(const wxChar *format, ...)
1358 #endif
1359 {
1360 va_list argptr;
1361 va_start(argptr, format);
1362
1363 wxString s;
1364 s.PrintfV(format, argptr);
1365
1366 va_end(argptr);
1367
1368 return s;
1369 }
1370
1371 /* static */
1372 wxString wxString::FormatV(const wxString& format, va_list argptr)
1373 {
1374 wxString s;
1375 s.PrintfV(format, argptr);
1376 return s;
1377 }
1378
1379 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1380 int wxStringPrintfMixinBase::DoPrintf(const wxChar *format, ...)
1381 #else
1382 int wxString::DoPrintf(const wxChar *format, ...)
1383 #endif
1384 {
1385 va_list argptr;
1386 va_start(argptr, format);
1387
1388 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1389 // get a pointer to the wxString instance; we have to use dynamic_cast<>
1390 // because it's the only cast that works safely for downcasting when
1391 // multiple inheritance is used:
1392 wxString *str = static_cast<wxString*>(this);
1393 #else
1394 wxString *str = this;
1395 #endif
1396
1397 int iLen = str->PrintfV(format, argptr);
1398
1399 va_end(argptr);
1400
1401 return iLen;
1402 }
1403
1404 int wxString::PrintfV(const wxString& format, va_list argptr)
1405 {
1406 int size = 1024;
1407
1408 for ( ;; )
1409 {
1410 wxStringBuffer tmp(*this, size + 1);
1411 wxChar *buf = tmp;
1412
1413 if ( !buf )
1414 {
1415 // out of memory
1416 return -1;
1417 }
1418
1419 // wxVsnprintf() may modify the original arg pointer, so pass it
1420 // only a copy
1421 va_list argptrcopy;
1422 wxVaCopy(argptrcopy, argptr);
1423 int len = wxVsnprintf(buf, size, format, argptrcopy);
1424 va_end(argptrcopy);
1425
1426 // some implementations of vsnprintf() don't NUL terminate
1427 // the string if there is not enough space for it so
1428 // always do it manually
1429 buf[size] = _T('\0');
1430
1431 // vsnprintf() may return either -1 (traditional Unix behaviour) or the
1432 // total number of characters which would have been written if the
1433 // buffer were large enough (newer standards such as Unix98)
1434 if ( len < 0 )
1435 {
1436 #if wxUSE_WXVSNPRINTF
1437 // we know that our own implementation of wxVsnprintf() returns -1
1438 // only for a format error - thus there's something wrong with
1439 // the user's format string
1440 return -1;
1441 #else // assume that system version only returns error if not enough space
1442 // still not enough, as we don't know how much we need, double the
1443 // current size of the buffer
1444 size *= 2;
1445 #endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
1446 }
1447 else if ( len >= size )
1448 {
1449 #if wxUSE_WXVSNPRINTF
1450 // we know that our own implementation of wxVsnprintf() returns
1451 // size+1 when there's not enough space but that's not the size
1452 // of the required buffer!
1453 size *= 2; // so we just double the current size of the buffer
1454 #else
1455 // some vsnprintf() implementations NUL-terminate the buffer and
1456 // some don't in len == size case, to be safe always add 1
1457 size = len + 1;
1458 #endif
1459 }
1460 else // ok, there was enough space
1461 {
1462 break;
1463 }
1464 }
1465
1466 // we could have overshot
1467 Shrink();
1468
1469 return length();
1470 }
1471
1472 // ----------------------------------------------------------------------------
1473 // misc other operations
1474 // ----------------------------------------------------------------------------
1475
1476 // returns true if the string matches the pattern which may contain '*' and
1477 // '?' metacharacters (as usual, '?' matches any character and '*' any number
1478 // of them)
1479 bool wxString::Matches(const wxString& mask) const
1480 {
1481 // I disable this code as it doesn't seem to be faster (in fact, it seems
1482 // to be much slower) than the old, hand-written code below and using it
1483 // here requires always linking with libregex even if the user code doesn't
1484 // use it
1485 #if 0 // wxUSE_REGEX
1486 // first translate the shell-like mask into a regex
1487 wxString pattern;
1488 pattern.reserve(wxStrlen(pszMask));
1489
1490 pattern += _T('^');
1491 while ( *pszMask )
1492 {
1493 switch ( *pszMask )
1494 {
1495 case _T('?'):
1496 pattern += _T('.');
1497 break;
1498
1499 case _T('*'):
1500 pattern += _T(".*");
1501 break;
1502
1503 case _T('^'):
1504 case _T('.'):
1505 case _T('$'):
1506 case _T('('):
1507 case _T(')'):
1508 case _T('|'):
1509 case _T('+'):
1510 case _T('\\'):
1511 // these characters are special in a RE, quote them
1512 // (however note that we don't quote '[' and ']' to allow
1513 // using them for Unix shell like matching)
1514 pattern += _T('\\');
1515 // fall through
1516
1517 default:
1518 pattern += *pszMask;
1519 }
1520
1521 pszMask++;
1522 }
1523 pattern += _T('$');
1524
1525 // and now use it
1526 return wxRegEx(pattern, wxRE_NOSUB | wxRE_EXTENDED).Matches(c_str());
1527 #else // !wxUSE_REGEX
1528 // TODO: this is, of course, awfully inefficient...
1529
1530 // FIXME-UTF8: implement using iterators, remove #if
1531 #if wxUSE_UNICODE_UTF8
1532 wxWCharBuffer maskBuf = mask.wc_str();
1533 wxWCharBuffer txtBuf = wc_str();
1534 const wxChar *pszMask = maskBuf.data();
1535 const wxChar *pszTxt = txtBuf.data();
1536 #else
1537 const wxChar *pszMask = mask.wx_str();
1538 // the char currently being checked
1539 const wxChar *pszTxt = wx_str();
1540 #endif
1541
1542 // the last location where '*' matched
1543 const wxChar *pszLastStarInText = NULL;
1544 const wxChar *pszLastStarInMask = NULL;
1545
1546 match:
1547 for ( ; *pszMask != wxT('\0'); pszMask++, pszTxt++ ) {
1548 switch ( *pszMask ) {
1549 case wxT('?'):
1550 if ( *pszTxt == wxT('\0') )
1551 return false;
1552
1553 // pszTxt and pszMask will be incremented in the loop statement
1554
1555 break;
1556
1557 case wxT('*'):
1558 {
1559 // remember where we started to be able to backtrack later
1560 pszLastStarInText = pszTxt;
1561 pszLastStarInMask = pszMask;
1562
1563 // ignore special chars immediately following this one
1564 // (should this be an error?)
1565 while ( *pszMask == wxT('*') || *pszMask == wxT('?') )
1566 pszMask++;
1567
1568 // if there is nothing more, match
1569 if ( *pszMask == wxT('\0') )
1570 return true;
1571
1572 // are there any other metacharacters in the mask?
1573 size_t uiLenMask;
1574 const wxChar *pEndMask = wxStrpbrk(pszMask, wxT("*?"));
1575
1576 if ( pEndMask != NULL ) {
1577 // we have to match the string between two metachars
1578 uiLenMask = pEndMask - pszMask;
1579 }
1580 else {
1581 // we have to match the remainder of the string
1582 uiLenMask = wxStrlen(pszMask);
1583 }
1584
1585 wxString strToMatch(pszMask, uiLenMask);
1586 const wxChar* pMatch = wxStrstr(pszTxt, strToMatch);
1587 if ( pMatch == NULL )
1588 return false;
1589
1590 // -1 to compensate "++" in the loop
1591 pszTxt = pMatch + uiLenMask - 1;
1592 pszMask += uiLenMask - 1;
1593 }
1594 break;
1595
1596 default:
1597 if ( *pszMask != *pszTxt )
1598 return false;
1599 break;
1600 }
1601 }
1602
1603 // match only if nothing left
1604 if ( *pszTxt == wxT('\0') )
1605 return true;
1606
1607 // if we failed to match, backtrack if we can
1608 if ( pszLastStarInText ) {
1609 pszTxt = pszLastStarInText + 1;
1610 pszMask = pszLastStarInMask;
1611
1612 pszLastStarInText = NULL;
1613
1614 // don't bother resetting pszLastStarInMask, it's unnecessary
1615
1616 goto match;
1617 }
1618
1619 return false;
1620 #endif // wxUSE_REGEX/!wxUSE_REGEX
1621 }
1622
1623 // Count the number of chars
1624 int wxString::Freq(wxUniChar ch) const
1625 {
1626 int count = 0;
1627 for ( const_iterator i = begin(); i != end(); ++i )
1628 {
1629 if ( *i == ch )
1630 count ++;
1631 }
1632 return count;
1633 }
1634
1635 // convert to upper case, return the copy of the string
1636 wxString wxString::Upper() const
1637 { wxString s(*this); return s.MakeUpper(); }
1638
1639 // convert to lower case, return the copy of the string
1640 wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }