]> git.saurik.com Git - wxWidgets.git/blob - src/common/string.cpp
Improve mouse handling code in wxAuiToolBar.
[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 // headers, declarations, constants
15 // ===========================================================================
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/string.h"
26 #include "wx/wxcrtvararg.h"
27 #include "wx/intl.h"
28 #include "wx/log.h"
29 #endif
30
31 #include <ctype.h>
32
33 #ifndef __WXWINCE__
34 #include <errno.h>
35 #endif
36
37 #include <string.h>
38 #include <stdlib.h>
39
40 #include "wx/hashmap.h"
41 #include "wx/vector.h"
42 #include "wx/xlocale.h"
43
44 #ifdef __WXMSW__
45 #include "wx/msw/wrapwin.h"
46 #endif // __WXMSW__
47
48 #if wxUSE_STD_IOSTREAM
49 #include <sstream>
50 #endif
51
52 // string handling functions used by wxString:
53 #if wxUSE_UNICODE_UTF8
54 #define wxStringMemcpy memcpy
55 #define wxStringMemcmp memcmp
56 #define wxStringMemchr memchr
57 #define wxStringStrlen strlen
58 #else
59 #define wxStringMemcpy wxTmemcpy
60 #define wxStringMemcmp wxTmemcmp
61 #define wxStringMemchr wxTmemchr
62 #define wxStringStrlen wxStrlen
63 #endif
64
65 // define a function declared in wx/buffer.h here as we don't have buffer.cpp
66 // and don't want to add it just because of this simple function
67 namespace wxPrivate
68 {
69
70 // wxXXXBuffer classes can be (implicitly) used during global statics
71 // initialization so wrap the status UntypedBufferData variable in a function
72 // to make it safe to access it even before all global statics are initialized
73 UntypedBufferData *GetUntypedNullData()
74 {
75 static UntypedBufferData s_untypedNullData(NULL, 0);
76
77 return &s_untypedNullData;
78 }
79
80 } // namespace wxPrivate
81
82 // ---------------------------------------------------------------------------
83 // static class variables definition
84 // ---------------------------------------------------------------------------
85
86 //According to STL _must_ be a -1 size_t
87 const size_t wxString::npos = (size_t) -1;
88
89 #if wxUSE_STRING_POS_CACHE
90
91 #ifdef wxHAS_COMPILER_TLS
92
93 wxTLS_TYPE(wxString::Cache) wxString::ms_cache;
94
95 #else // !wxHAS_COMPILER_TLS
96
97 struct wxStrCacheInitializer
98 {
99 wxStrCacheInitializer()
100 {
101 // calling this function triggers s_cache initialization in it, and
102 // from now on it becomes safe to call from multiple threads
103 wxString::GetCache();
104 }
105 };
106
107 /*
108 wxString::Cache& wxString::GetCache()
109 {
110 static wxTLS_TYPE(Cache) s_cache;
111
112 return wxTLS_VALUE(s_cache);
113 }
114 */
115
116 static wxStrCacheInitializer gs_stringCacheInit;
117
118 #endif // wxHAS_COMPILER_TLS/!wxHAS_COMPILER_TLS
119
120 // gdb seems to be unable to display thread-local variables correctly, at least
121 // not my 6.4.98 version under amd64, so provide this debugging helper to do it
122 #if wxDEBUG_LEVEL >= 2
123
124 struct wxStrCacheDumper
125 {
126 static void ShowAll()
127 {
128 puts("*** wxString cache dump:");
129 for ( unsigned n = 0; n < wxString::Cache::SIZE; n++ )
130 {
131 const wxString::Cache::Element&
132 c = wxString::GetCacheBegin()[n];
133
134 printf("\t%u%s\t%p: pos=(%lu, %lu), len=%ld\n",
135 n,
136 n == wxString::LastUsedCacheElement() ? " [*]" : "",
137 c.str,
138 (unsigned long)c.pos,
139 (unsigned long)c.impl,
140 (long)c.len);
141 }
142 }
143 };
144
145 void wxDumpStrCache() { wxStrCacheDumper::ShowAll(); }
146
147 #endif // wxDEBUG_LEVEL >= 2
148
149 #ifdef wxPROFILE_STRING_CACHE
150
151 wxString::CacheStats wxString::ms_cacheStats;
152
153 struct wxStrCacheStatsDumper
154 {
155 ~wxStrCacheStatsDumper()
156 {
157 const wxString::CacheStats& stats = wxString::ms_cacheStats;
158
159 if ( stats.postot )
160 {
161 puts("*** wxString cache statistics:");
162 printf("\tTotal non-trivial calls to PosToImpl(): %u\n",
163 stats.postot);
164 printf("\tHits %u (of which %u not used) or %.2f%%\n",
165 stats.poshits,
166 stats.mishits,
167 100.*float(stats.poshits - stats.mishits)/stats.postot);
168 printf("\tAverage position requested: %.2f\n",
169 float(stats.sumpos) / stats.postot);
170 printf("\tAverage offset after cached hint: %.2f\n",
171 float(stats.sumofs) / stats.postot);
172 }
173
174 if ( stats.lentot )
175 {
176 printf("\tNumber of calls to length(): %u, hits=%.2f%%\n",
177 stats.lentot, 100.*float(stats.lenhits)/stats.lentot);
178 }
179 }
180 };
181
182 static wxStrCacheStatsDumper s_showCacheStats;
183
184 #endif // wxPROFILE_STRING_CACHE
185
186 #endif // wxUSE_STRING_POS_CACHE
187
188 // ----------------------------------------------------------------------------
189 // global functions
190 // ----------------------------------------------------------------------------
191
192 #if wxUSE_STD_IOSTREAM
193
194 #include <iostream>
195
196 wxSTD ostream& operator<<(wxSTD ostream& os, const wxCStrData& str)
197 {
198 #if wxUSE_UNICODE && !wxUSE_UNICODE_UTF8
199 const wxScopedCharBuffer buf(str.AsCharBuf());
200 if ( !buf )
201 os.clear(wxSTD ios_base::failbit);
202 else
203 os << buf.data();
204
205 return os;
206 #else
207 return os << str.AsInternal();
208 #endif
209 }
210
211 wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
212 {
213 return os << str.c_str();
214 }
215
216 wxSTD ostream& operator<<(wxSTD ostream& os, const wxScopedCharBuffer& str)
217 {
218 return os << str.data();
219 }
220
221 #ifndef __BORLANDC__
222 wxSTD ostream& operator<<(wxSTD ostream& os, const wxScopedWCharBuffer& str)
223 {
224 return os << str.data();
225 }
226 #endif
227
228 #if wxUSE_UNICODE && defined(HAVE_WOSTREAM)
229
230 wxSTD wostream& operator<<(wxSTD wostream& wos, const wxString& str)
231 {
232 return wos << str.wc_str();
233 }
234
235 wxSTD wostream& operator<<(wxSTD wostream& wos, const wxCStrData& str)
236 {
237 return wos << str.AsWChar();
238 }
239
240 wxSTD wostream& operator<<(wxSTD wostream& wos, const wxScopedWCharBuffer& str)
241 {
242 return wos << str.data();
243 }
244
245 #endif // wxUSE_UNICODE && defined(HAVE_WOSTREAM)
246
247 #endif // wxUSE_STD_IOSTREAM
248
249 // ===========================================================================
250 // wxString class core
251 // ===========================================================================
252
253 #if wxUSE_UNICODE_UTF8
254
255 void wxString::PosLenToImpl(size_t pos, size_t len,
256 size_t *implPos, size_t *implLen) const
257 {
258 if ( pos == npos )
259 {
260 *implPos = npos;
261 }
262 else // have valid start position
263 {
264 const const_iterator b = GetIterForNthChar(pos);
265 *implPos = wxStringImpl::const_iterator(b.impl()) - m_impl.begin();
266 if ( len == npos )
267 {
268 *implLen = npos;
269 }
270 else // have valid length too
271 {
272 // we need to handle the case of length specifying a substring
273 // going beyond the end of the string, just as std::string does
274 const const_iterator e(end());
275 const_iterator i(b);
276 while ( len && i <= e )
277 {
278 ++i;
279 --len;
280 }
281
282 *implLen = i.impl() - b.impl();
283 }
284 }
285 }
286
287 #endif // wxUSE_UNICODE_UTF8
288
289 // ----------------------------------------------------------------------------
290 // wxCStrData converted strings caching
291 // ----------------------------------------------------------------------------
292
293 // FIXME-UTF8: temporarily disabled because it doesn't work with global
294 // string objects; re-enable after fixing this bug and benchmarking
295 // performance to see if using a hash is a good idea at all
296 #if 0
297
298 // For backward compatibility reasons, it must be possible to assign the value
299 // returned by wxString::c_str() to a char* or wchar_t* variable and work with
300 // it. Returning wxCharBuffer from (const char*)c_str() wouldn't do the trick,
301 // because the memory would be freed immediately, but it has to be valid as long
302 // as the string is not modified, so that code like this still works:
303 //
304 // const wxChar *s = str.c_str();
305 // while ( s ) { ... }
306
307 // FIXME-UTF8: not thread safe!
308 // FIXME-UTF8: we currently clear the cached conversion only when the string is
309 // destroyed, but we should do it when the string is modified, to
310 // keep memory usage down
311 // FIXME-UTF8: we do the conversion every time As[W]Char() is called, but if we
312 // invalidated the cache on every change, we could keep the previous
313 // conversion
314 // FIXME-UTF8: add tracing of usage of these two methods - new code is supposed
315 // to use mb_str() or wc_str() instead of (const [w]char*)c_str()
316
317 template<typename T>
318 static inline void DeleteStringFromConversionCache(T& hash, const wxString *s)
319 {
320 typename T::iterator i = hash.find(wxConstCast(s, wxString));
321 if ( i != hash.end() )
322 {
323 free(i->second);
324 hash.erase(i);
325 }
326 }
327
328 #if wxUSE_UNICODE
329 // NB: non-STL implementation doesn't compile with "const wxString*" key type,
330 // so we have to use wxString* here and const-cast when used
331 WX_DECLARE_HASH_MAP(wxString*, char*, wxPointerHash, wxPointerEqual,
332 wxStringCharConversionCache);
333 static wxStringCharConversionCache gs_stringsCharCache;
334
335 const char* wxCStrData::AsChar() const
336 {
337 // remove previously cache value, if any (see FIXMEs above):
338 DeleteStringFromConversionCache(gs_stringsCharCache, m_str);
339
340 // convert the string and keep it:
341 const char *s = gs_stringsCharCache[wxConstCast(m_str, wxString)] =
342 m_str->mb_str().release();
343
344 return s + m_offset;
345 }
346 #endif // wxUSE_UNICODE
347
348 #if !wxUSE_UNICODE_WCHAR
349 WX_DECLARE_HASH_MAP(wxString*, wchar_t*, wxPointerHash, wxPointerEqual,
350 wxStringWCharConversionCache);
351 static wxStringWCharConversionCache gs_stringsWCharCache;
352
353 const wchar_t* wxCStrData::AsWChar() const
354 {
355 // remove previously cache value, if any (see FIXMEs above):
356 DeleteStringFromConversionCache(gs_stringsWCharCache, m_str);
357
358 // convert the string and keep it:
359 const wchar_t *s = gs_stringsWCharCache[wxConstCast(m_str, wxString)] =
360 m_str->wc_str().release();
361
362 return s + m_offset;
363 }
364 #endif // !wxUSE_UNICODE_WCHAR
365
366 wxString::~wxString()
367 {
368 #if wxUSE_UNICODE
369 // FIXME-UTF8: do this only if locale is not UTF8 if wxUSE_UNICODE_UTF8
370 DeleteStringFromConversionCache(gs_stringsCharCache, this);
371 #endif
372 #if !wxUSE_UNICODE_WCHAR
373 DeleteStringFromConversionCache(gs_stringsWCharCache, this);
374 #endif
375 }
376 #endif
377
378 // ===========================================================================
379 // wxString class core
380 // ===========================================================================
381
382 // ---------------------------------------------------------------------------
383 // construction and conversion
384 // ---------------------------------------------------------------------------
385
386 #if wxUSE_UNICODE_WCHAR
387 /* static */
388 wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
389 const wxMBConv& conv)
390 {
391 // anything to do?
392 if ( !psz || nLength == 0 )
393 return SubstrBufFromMB(wxWCharBuffer(L""), 0);
394
395 if ( nLength == npos )
396 nLength = wxNO_LEN;
397
398 size_t wcLen;
399 wxScopedWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
400 if ( !wcLen )
401 return SubstrBufFromMB(wxWCharBuffer(L""), 0);
402 else
403 return SubstrBufFromMB(wcBuf, wcLen);
404 }
405 #endif // wxUSE_UNICODE_WCHAR
406
407 #if wxUSE_UNICODE_UTF8
408 /* static */
409 wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
410 const wxMBConv& conv)
411 {
412 // anything to do?
413 if ( !psz || nLength == 0 )
414 return SubstrBufFromMB(wxCharBuffer(""), 0);
415
416 // if psz is already in UTF-8, we don't have to do the roundtrip to
417 // wchar_t* and back:
418 if ( conv.IsUTF8() )
419 {
420 // we need to validate the input because UTF8 iterators assume valid
421 // UTF-8 sequence and psz may be invalid:
422 if ( wxStringOperations::IsValidUtf8String(psz, nLength) )
423 {
424 // we must pass the real string length to SubstrBufFromMB ctor
425 if ( nLength == npos )
426 nLength = psz ? strlen(psz) : 0;
427 return SubstrBufFromMB(wxScopedCharBuffer::CreateNonOwned(psz, nLength),
428 nLength);
429 }
430 // else: do the roundtrip through wchar_t*
431 }
432
433 if ( nLength == npos )
434 nLength = wxNO_LEN;
435
436 // first convert to wide string:
437 size_t wcLen;
438 wxScopedWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
439 if ( !wcLen )
440 return SubstrBufFromMB(wxCharBuffer(""), 0);
441
442 // and then to UTF-8:
443 SubstrBufFromMB buf(ConvertStr(wcBuf, wcLen, wxMBConvStrictUTF8()));
444 // widechar -> UTF-8 conversion isn't supposed to ever fail:
445 wxASSERT_MSG( buf.data, wxT("conversion to UTF-8 failed") );
446
447 return buf;
448 }
449 #endif // wxUSE_UNICODE_UTF8
450
451 #if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
452 /* static */
453 wxString::SubstrBufFromWC wxString::ConvertStr(const wchar_t *pwz, size_t nLength,
454 const wxMBConv& conv)
455 {
456 // anything to do?
457 if ( !pwz || nLength == 0 )
458 return SubstrBufFromWC(wxCharBuffer(""), 0);
459
460 if ( nLength == npos )
461 nLength = wxNO_LEN;
462
463 size_t mbLen;
464 wxScopedCharBuffer mbBuf(conv.cWC2MB(pwz, nLength, &mbLen));
465 if ( !mbLen )
466 return SubstrBufFromWC(wxCharBuffer(""), 0);
467 else
468 return SubstrBufFromWC(mbBuf, mbLen);
469 }
470 #endif // wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
471
472 // This std::string::c_str()-like method returns a wide char pointer to string
473 // contents. In wxUSE_UNICODE_WCHAR case it is trivial as it can simply return
474 // a pointer to the internal representation. Otherwise a conversion is required
475 // and it returns a temporary buffer.
476 //
477 // However for compatibility with c_str() and to avoid breaking existing code
478 // doing
479 //
480 // for ( const wchar_t *p = s.wc_str(); *p; p++ )
481 // ... use *p...
482 //
483 // we actually need to ensure that the returned buffer is _not_ temporary and
484 // so we use wxString::m_convertedToWChar to store the returned data
485 #if !wxUSE_UNICODE_WCHAR
486
487 const wchar_t *wxString::AsWChar(const wxMBConv& conv) const
488 {
489 const char * const strMB = m_impl.c_str();
490 const size_t lenMB = m_impl.length();
491
492 // find out the size of the buffer needed
493 const size_t lenWC = conv.ToWChar(NULL, 0, strMB, lenMB);
494 if ( lenWC == wxCONV_FAILED )
495 return NULL;
496
497 // keep the same buffer if the string size didn't change: this is not only
498 // an optimization but also ensure that code which modifies string
499 // character by character (without changing its length) can continue to use
500 // the pointer returned by a previous wc_str() call even after changing the
501 // string
502
503 // TODO-UTF8: we could check for ">" instead of "!=" here as this would
504 // allow to save on buffer reallocations but at the cost of
505 // consuming (even) more memory, we should benchmark this to
506 // determine if it's worth doing
507 if ( !m_convertedToWChar.m_str || lenWC != m_convertedToWChar.m_len )
508 {
509 if ( !const_cast<wxString *>(this)->m_convertedToWChar.Extend(lenWC) )
510 return NULL;
511 }
512
513 // finally do convert
514 m_convertedToWChar.m_str[lenWC] = L'\0';
515 if ( conv.ToWChar(m_convertedToWChar.m_str, lenWC,
516 strMB, lenMB) == wxCONV_FAILED )
517 return NULL;
518
519 return m_convertedToWChar.m_str;
520 }
521
522 #endif // !wxUSE_UNICODE_WCHAR
523
524
525 // Same thing for mb_str() which returns a normal char pointer to string
526 // contents: this always requires converting it to the specified encoding in
527 // non-ANSI build except if we need to convert to UTF-8 and this is what we
528 // already use internally.
529 #if wxUSE_UNICODE
530
531 const char *wxString::AsChar(const wxMBConv& conv) const
532 {
533 #if wxUSE_UNICODE_UTF8
534 if ( conv.IsUTF8() )
535 return m_impl.c_str();
536
537 const wchar_t * const strWC = AsWChar(wxMBConvStrictUTF8());
538 const size_t lenWC = m_convertedToWChar.m_len;
539 #else // wxUSE_UNICODE_WCHAR
540 const wchar_t * const strWC = m_impl.c_str();
541 const size_t lenWC = m_impl.length();
542 #endif // wxUSE_UNICODE_UTF8/wxUSE_UNICODE_WCHAR
543
544 const size_t lenMB = conv.FromWChar(NULL, 0, strWC, lenWC);
545 if ( lenMB == wxCONV_FAILED )
546 return NULL;
547
548 if ( !m_convertedToChar.m_str || lenMB != m_convertedToChar.m_len )
549 {
550 if ( !const_cast<wxString *>(this)->m_convertedToChar.Extend(lenMB) )
551 return NULL;
552 }
553
554 m_convertedToChar.m_str[lenMB] = '\0';
555 if ( conv.FromWChar(m_convertedToChar.m_str, lenMB,
556 strWC, lenWC) == wxCONV_FAILED )
557 return NULL;
558
559 return m_convertedToChar.m_str;
560 }
561
562 #endif // wxUSE_UNICODE
563
564 // shrink to minimal size (releasing extra memory)
565 bool wxString::Shrink()
566 {
567 wxString tmp(begin(), end());
568 swap(tmp);
569 return tmp.length() == length();
570 }
571
572 // deprecated compatibility code:
573 #if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
574 wxStringCharType *wxString::GetWriteBuf(size_t nLen)
575 {
576 return DoGetWriteBuf(nLen);
577 }
578
579 void wxString::UngetWriteBuf()
580 {
581 DoUngetWriteBuf();
582 }
583
584 void wxString::UngetWriteBuf(size_t nLen)
585 {
586 DoUngetWriteBuf(nLen);
587 }
588 #endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
589
590
591 // ---------------------------------------------------------------------------
592 // data access
593 // ---------------------------------------------------------------------------
594
595 // all functions are inline in string.h
596
597 // ---------------------------------------------------------------------------
598 // concatenation operators
599 // ---------------------------------------------------------------------------
600
601 /*
602 * concatenation functions come in 5 flavours:
603 * string + string
604 * char + string and string + char
605 * C str + string and string + C str
606 */
607
608 wxString operator+(const wxString& str1, const wxString& str2)
609 {
610 #if !wxUSE_STL_BASED_WXSTRING
611 wxASSERT( str1.IsValid() );
612 wxASSERT( str2.IsValid() );
613 #endif
614
615 wxString s = str1;
616 s += str2;
617
618 return s;
619 }
620
621 wxString operator+(const wxString& str, wxUniChar ch)
622 {
623 #if !wxUSE_STL_BASED_WXSTRING
624 wxASSERT( str.IsValid() );
625 #endif
626
627 wxString s = str;
628 s += ch;
629
630 return s;
631 }
632
633 wxString operator+(wxUniChar ch, const wxString& str)
634 {
635 #if !wxUSE_STL_BASED_WXSTRING
636 wxASSERT( str.IsValid() );
637 #endif
638
639 wxString s = ch;
640 s += str;
641
642 return s;
643 }
644
645 wxString operator+(const wxString& str, const char *psz)
646 {
647 #if !wxUSE_STL_BASED_WXSTRING
648 wxASSERT( str.IsValid() );
649 #endif
650
651 wxString s;
652 if ( !s.Alloc(strlen(psz) + str.length()) ) {
653 wxFAIL_MSG( wxT("out of memory in wxString::operator+") );
654 }
655 s += str;
656 s += psz;
657
658 return s;
659 }
660
661 wxString operator+(const wxString& str, const wchar_t *pwz)
662 {
663 #if !wxUSE_STL_BASED_WXSTRING
664 wxASSERT( str.IsValid() );
665 #endif
666
667 wxString s;
668 if ( !s.Alloc(wxWcslen(pwz) + str.length()) ) {
669 wxFAIL_MSG( wxT("out of memory in wxString::operator+") );
670 }
671 s += str;
672 s += pwz;
673
674 return s;
675 }
676
677 wxString operator+(const char *psz, const wxString& str)
678 {
679 #if !wxUSE_STL_BASED_WXSTRING
680 wxASSERT( str.IsValid() );
681 #endif
682
683 wxString s;
684 if ( !s.Alloc(strlen(psz) + str.length()) ) {
685 wxFAIL_MSG( wxT("out of memory in wxString::operator+") );
686 }
687 s = psz;
688 s += str;
689
690 return s;
691 }
692
693 wxString operator+(const wchar_t *pwz, const wxString& str)
694 {
695 #if !wxUSE_STL_BASED_WXSTRING
696 wxASSERT( str.IsValid() );
697 #endif
698
699 wxString s;
700 if ( !s.Alloc(wxWcslen(pwz) + str.length()) ) {
701 wxFAIL_MSG( wxT("out of memory in wxString::operator+") );
702 }
703 s = pwz;
704 s += str;
705
706 return s;
707 }
708
709 // ---------------------------------------------------------------------------
710 // string comparison
711 // ---------------------------------------------------------------------------
712
713 bool wxString::IsSameAs(wxUniChar c, bool compareWithCase) const
714 {
715 return (length() == 1) && (compareWithCase ? GetChar(0u) == c
716 : wxToupper(GetChar(0u)) == wxToupper(c));
717 }
718
719 #ifdef HAVE_STD_STRING_COMPARE
720
721 // NB: Comparison code (both if HAVE_STD_STRING_COMPARE and if not) works with
722 // UTF-8 encoded strings too, thanks to UTF-8's design which allows us to
723 // sort strings in characters code point order by sorting the byte sequence
724 // in byte values order (i.e. what strcmp() and memcmp() do).
725
726 int wxString::compare(const wxString& str) const
727 {
728 return m_impl.compare(str.m_impl);
729 }
730
731 int wxString::compare(size_t nStart, size_t nLen,
732 const wxString& str) const
733 {
734 size_t pos, len;
735 PosLenToImpl(nStart, nLen, &pos, &len);
736 return m_impl.compare(pos, len, str.m_impl);
737 }
738
739 int wxString::compare(size_t nStart, size_t nLen,
740 const wxString& str,
741 size_t nStart2, size_t nLen2) const
742 {
743 size_t pos, len;
744 PosLenToImpl(nStart, nLen, &pos, &len);
745
746 size_t pos2, len2;
747 str.PosLenToImpl(nStart2, nLen2, &pos2, &len2);
748
749 return m_impl.compare(pos, len, str.m_impl, pos2, len2);
750 }
751
752 int wxString::compare(const char* sz) const
753 {
754 return m_impl.compare(ImplStr(sz));
755 }
756
757 int wxString::compare(const wchar_t* sz) const
758 {
759 return m_impl.compare(ImplStr(sz));
760 }
761
762 int wxString::compare(size_t nStart, size_t nLen,
763 const char* sz, size_t nCount) const
764 {
765 size_t pos, len;
766 PosLenToImpl(nStart, nLen, &pos, &len);
767
768 SubstrBufFromMB str(ImplStr(sz, nCount));
769
770 return m_impl.compare(pos, len, str.data, str.len);
771 }
772
773 int wxString::compare(size_t nStart, size_t nLen,
774 const wchar_t* sz, size_t nCount) const
775 {
776 size_t pos, len;
777 PosLenToImpl(nStart, nLen, &pos, &len);
778
779 SubstrBufFromWC str(ImplStr(sz, nCount));
780
781 return m_impl.compare(pos, len, str.data, str.len);
782 }
783
784 #else // !HAVE_STD_STRING_COMPARE
785
786 static inline int wxDoCmp(const wxStringCharType* s1, size_t l1,
787 const wxStringCharType* s2, size_t l2)
788 {
789 if( l1 == l2 )
790 return wxStringMemcmp(s1, s2, l1);
791 else if( l1 < l2 )
792 {
793 int ret = wxStringMemcmp(s1, s2, l1);
794 return ret == 0 ? -1 : ret;
795 }
796 else
797 {
798 int ret = wxStringMemcmp(s1, s2, l2);
799 return ret == 0 ? +1 : ret;
800 }
801 }
802
803 int wxString::compare(const wxString& str) const
804 {
805 return ::wxDoCmp(m_impl.data(), m_impl.length(),
806 str.m_impl.data(), str.m_impl.length());
807 }
808
809 int wxString::compare(size_t nStart, size_t nLen,
810 const wxString& str) const
811 {
812 wxASSERT(nStart <= length());
813 size_type strLen = length() - nStart;
814 nLen = strLen < nLen ? strLen : nLen;
815
816 size_t pos, len;
817 PosLenToImpl(nStart, nLen, &pos, &len);
818
819 return ::wxDoCmp(m_impl.data() + pos, len,
820 str.m_impl.data(), str.m_impl.length());
821 }
822
823 int wxString::compare(size_t nStart, size_t nLen,
824 const wxString& str,
825 size_t nStart2, size_t nLen2) const
826 {
827 wxASSERT(nStart <= length());
828 wxASSERT(nStart2 <= str.length());
829 size_type strLen = length() - nStart,
830 strLen2 = str.length() - nStart2;
831 nLen = strLen < nLen ? strLen : nLen;
832 nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
833
834 size_t pos, len;
835 PosLenToImpl(nStart, nLen, &pos, &len);
836 size_t pos2, len2;
837 str.PosLenToImpl(nStart2, nLen2, &pos2, &len2);
838
839 return ::wxDoCmp(m_impl.data() + pos, len,
840 str.m_impl.data() + pos2, len2);
841 }
842
843 int wxString::compare(const char* sz) const
844 {
845 SubstrBufFromMB str(ImplStr(sz, npos));
846 if ( str.len == npos )
847 str.len = wxStringStrlen(str.data);
848 return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len);
849 }
850
851 int wxString::compare(const wchar_t* sz) const
852 {
853 SubstrBufFromWC str(ImplStr(sz, npos));
854 if ( str.len == npos )
855 str.len = wxStringStrlen(str.data);
856 return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len);
857 }
858
859 int wxString::compare(size_t nStart, size_t nLen,
860 const char* sz, size_t nCount) const
861 {
862 wxASSERT(nStart <= length());
863 size_type strLen = length() - nStart;
864 nLen = strLen < nLen ? strLen : nLen;
865
866 size_t pos, len;
867 PosLenToImpl(nStart, nLen, &pos, &len);
868
869 SubstrBufFromMB str(ImplStr(sz, nCount));
870 if ( str.len == npos )
871 str.len = wxStringStrlen(str.data);
872
873 return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len);
874 }
875
876 int wxString::compare(size_t nStart, size_t nLen,
877 const wchar_t* sz, size_t nCount) const
878 {
879 wxASSERT(nStart <= length());
880 size_type strLen = length() - nStart;
881 nLen = strLen < nLen ? strLen : nLen;
882
883 size_t pos, len;
884 PosLenToImpl(nStart, nLen, &pos, &len);
885
886 SubstrBufFromWC str(ImplStr(sz, nCount));
887 if ( str.len == npos )
888 str.len = wxStringStrlen(str.data);
889
890 return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len);
891 }
892
893 #endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE
894
895
896 // ---------------------------------------------------------------------------
897 // find_{first,last}_[not]_of functions
898 // ---------------------------------------------------------------------------
899
900 #if !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
901
902 // NB: All these functions are implemented with the argument being wxChar*,
903 // i.e. widechar string in any Unicode build, even though native string
904 // representation is char* in the UTF-8 build. This is because we couldn't
905 // use memchr() to determine if a character is in a set encoded as UTF-8.
906
907 size_t wxString::find_first_of(const wxChar* sz, size_t nStart) const
908 {
909 return find_first_of(sz, nStart, wxStrlen(sz));
910 }
911
912 size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart) const
913 {
914 return find_first_not_of(sz, nStart, wxStrlen(sz));
915 }
916
917 size_t wxString::find_first_of(const wxChar* sz, size_t nStart, size_t n) const
918 {
919 wxASSERT_MSG( nStart <= length(), wxT("invalid index") );
920
921 size_t idx = nStart;
922 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
923 {
924 if ( wxTmemchr(sz, *i, n) )
925 return idx;
926 }
927
928 return npos;
929 }
930
931 size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart, size_t n) const
932 {
933 wxASSERT_MSG( nStart <= length(), wxT("invalid index") );
934
935 size_t idx = nStart;
936 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
937 {
938 if ( !wxTmemchr(sz, *i, n) )
939 return idx;
940 }
941
942 return npos;
943 }
944
945
946 size_t wxString::find_last_of(const wxChar* sz, size_t nStart) const
947 {
948 return find_last_of(sz, nStart, wxStrlen(sz));
949 }
950
951 size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart) const
952 {
953 return find_last_not_of(sz, nStart, wxStrlen(sz));
954 }
955
956 size_t wxString::find_last_of(const wxChar* sz, size_t nStart, size_t n) const
957 {
958 size_t len = length();
959
960 if ( nStart == npos )
961 {
962 nStart = len - 1;
963 }
964 else
965 {
966 wxASSERT_MSG( nStart <= len, wxT("invalid index") );
967 }
968
969 size_t idx = nStart;
970 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
971 i != rend(); --idx, ++i )
972 {
973 if ( wxTmemchr(sz, *i, n) )
974 return idx;
975 }
976
977 return npos;
978 }
979
980 size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart, size_t n) const
981 {
982 size_t len = length();
983
984 if ( nStart == npos )
985 {
986 nStart = len - 1;
987 }
988 else
989 {
990 wxASSERT_MSG( nStart <= len, wxT("invalid index") );
991 }
992
993 size_t idx = nStart;
994 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
995 i != rend(); --idx, ++i )
996 {
997 if ( !wxTmemchr(sz, *i, n) )
998 return idx;
999 }
1000
1001 return npos;
1002 }
1003
1004 size_t wxString::find_first_not_of(wxUniChar ch, size_t nStart) const
1005 {
1006 wxASSERT_MSG( nStart <= length(), wxT("invalid index") );
1007
1008 size_t idx = nStart;
1009 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
1010 {
1011 if ( *i != ch )
1012 return idx;
1013 }
1014
1015 return npos;
1016 }
1017
1018 size_t wxString::find_last_not_of(wxUniChar ch, size_t nStart) const
1019 {
1020 size_t len = length();
1021
1022 if ( nStart == npos )
1023 {
1024 nStart = len - 1;
1025 }
1026 else
1027 {
1028 wxASSERT_MSG( nStart <= len, wxT("invalid index") );
1029 }
1030
1031 size_t idx = nStart;
1032 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
1033 i != rend(); --idx, ++i )
1034 {
1035 if ( *i != ch )
1036 return idx;
1037 }
1038
1039 return npos;
1040 }
1041
1042 // the functions above were implemented for wchar_t* arguments in Unicode
1043 // build and char* in ANSI build; below are implementations for the other
1044 // version:
1045 #if wxUSE_UNICODE
1046 #define wxOtherCharType char
1047 #define STRCONV (const wxChar*)wxConvLibc.cMB2WC
1048 #else
1049 #define wxOtherCharType wchar_t
1050 #define STRCONV (const wxChar*)wxConvLibc.cWC2MB
1051 #endif
1052
1053 size_t wxString::find_first_of(const wxOtherCharType* sz, size_t nStart) const
1054 { return find_first_of(STRCONV(sz), nStart); }
1055
1056 size_t wxString::find_first_of(const wxOtherCharType* sz, size_t nStart,
1057 size_t n) const
1058 { return find_first_of(STRCONV(sz, n, NULL), nStart, n); }
1059 size_t wxString::find_last_of(const wxOtherCharType* sz, size_t nStart) const
1060 { return find_last_of(STRCONV(sz), nStart); }
1061 size_t wxString::find_last_of(const wxOtherCharType* sz, size_t nStart,
1062 size_t n) const
1063 { return find_last_of(STRCONV(sz, n, NULL), nStart, n); }
1064 size_t wxString::find_first_not_of(const wxOtherCharType* sz, size_t nStart) const
1065 { return find_first_not_of(STRCONV(sz), nStart); }
1066 size_t wxString::find_first_not_of(const wxOtherCharType* sz, size_t nStart,
1067 size_t n) const
1068 { return find_first_not_of(STRCONV(sz, n, NULL), nStart, n); }
1069 size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart) const
1070 { return find_last_not_of(STRCONV(sz), nStart); }
1071 size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart,
1072 size_t n) const
1073 { return find_last_not_of(STRCONV(sz, n, NULL), nStart, n); }
1074
1075 #undef wxOtherCharType
1076 #undef STRCONV
1077
1078 #endif // !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
1079
1080 // ===========================================================================
1081 // other common string functions
1082 // ===========================================================================
1083
1084 int wxString::CmpNoCase(const wxString& s) const
1085 {
1086 #if !wxUSE_UNICODE_UTF8
1087 // We compare NUL-delimited chunks of the strings inside the loop. We will
1088 // do as many iterations as there are embedded NULs in the string, i.e.
1089 // usually we will run it just once.
1090
1091 typedef const wxStringImpl::value_type *pchar_type;
1092 const pchar_type thisBegin = m_impl.c_str();
1093 const pchar_type thatBegin = s.m_impl.c_str();
1094
1095 const pchar_type thisEnd = thisBegin + m_impl.length();
1096 const pchar_type thatEnd = thatBegin + s.m_impl.length();
1097
1098 pchar_type thisCur = thisBegin;
1099 pchar_type thatCur = thatBegin;
1100
1101 int rc;
1102 for ( ;; )
1103 {
1104 // Compare until the next NUL, if the strings differ this is the final
1105 // result.
1106 rc = wxStricmp(thisCur, thatCur);
1107 if ( rc )
1108 break;
1109
1110 const size_t lenChunk = wxStrlen(thisCur);
1111 thisCur += lenChunk;
1112 thatCur += lenChunk;
1113
1114 // Skip all the NULs as wxStricmp() doesn't handle them.
1115 for ( ; !*thisCur; thisCur++, thatCur++ )
1116 {
1117 // Check if we exhausted either of the strings.
1118 if ( thisCur == thisEnd )
1119 {
1120 // This one is exhausted, is the other one too?
1121 return thatCur == thatEnd ? 0 : -1;
1122 }
1123
1124 if ( thatCur == thatEnd )
1125 {
1126 // Because of the test above we know that this one is not
1127 // exhausted yet so it's greater than the other one that is.
1128 return 1;
1129 }
1130
1131 if ( *thatCur )
1132 {
1133 // Anything non-NUL is greater than NUL.
1134 return -1;
1135 }
1136 }
1137 }
1138
1139 return rc;
1140 #else // wxUSE_UNICODE_UTF8
1141 // CRT functions can't be used for case-insensitive comparison of UTF-8
1142 // strings so do it in the naive, simple and inefficient way.
1143
1144 // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
1145 const_iterator i1 = begin();
1146 const_iterator end1 = end();
1147 const_iterator i2 = s.begin();
1148 const_iterator end2 = s.end();
1149
1150 for ( ; i1 != end1 && i2 != end2; ++i1, ++i2 )
1151 {
1152 wxUniChar lower1 = (wxChar)wxTolower(*i1);
1153 wxUniChar lower2 = (wxChar)wxTolower(*i2);
1154 if ( lower1 != lower2 )
1155 return lower1 < lower2 ? -1 : 1;
1156 }
1157
1158 size_t len1 = length();
1159 size_t len2 = s.length();
1160
1161 if ( len1 < len2 )
1162 return -1;
1163 else if ( len1 > len2 )
1164 return 1;
1165 return 0;
1166 #endif // !wxUSE_UNICODE_UTF8/wxUSE_UNICODE_UTF8
1167 }
1168
1169
1170 #if wxUSE_UNICODE
1171
1172 #ifdef __MWERKS__
1173 #ifndef __SCHAR_MAX__
1174 #define __SCHAR_MAX__ 127
1175 #endif
1176 #endif
1177
1178 wxString wxString::FromAscii(const char *ascii, size_t len)
1179 {
1180 if (!ascii || len == 0)
1181 return wxEmptyString;
1182
1183 wxString res;
1184
1185 {
1186 wxStringInternalBuffer buf(res, len);
1187 wxStringCharType *dest = buf;
1188
1189 for ( ; len > 0; --len )
1190 {
1191 unsigned char c = (unsigned char)*ascii++;
1192 wxASSERT_MSG( c < 0x80,
1193 wxT("Non-ASCII value passed to FromAscii().") );
1194
1195 *dest++ = (wchar_t)c;
1196 }
1197 }
1198
1199 return res;
1200 }
1201
1202 wxString wxString::FromAscii(const char *ascii)
1203 {
1204 return FromAscii(ascii, wxStrlen(ascii));
1205 }
1206
1207 wxString wxString::FromAscii(char ascii)
1208 {
1209 // What do we do with '\0' ?
1210
1211 unsigned char c = (unsigned char)ascii;
1212
1213 wxASSERT_MSG( c < 0x80, wxT("Non-ASCII value passed to FromAscii().") );
1214
1215 // NB: the cast to wchar_t causes interpretation of 'ascii' as Latin1 value
1216 return wxString(wxUniChar((wchar_t)c));
1217 }
1218
1219 const wxScopedCharBuffer wxString::ToAscii() const
1220 {
1221 // this will allocate enough space for the terminating NUL too
1222 wxCharBuffer buffer(length());
1223 char *dest = buffer.data();
1224
1225 for ( const_iterator i = begin(); i != end(); ++i )
1226 {
1227 wxUniChar c(*i);
1228 // FIXME-UTF8: unify substituted char ('_') with wxUniChar ('?')
1229 *dest++ = c.IsAscii() ? (char)c : '_';
1230
1231 // the output string can't have embedded NULs anyhow, so we can safely
1232 // stop at first of them even if we do have any
1233 if ( !c )
1234 break;
1235 }
1236
1237 return buffer;
1238 }
1239
1240 #endif // wxUSE_UNICODE
1241
1242 // extract string of length nCount starting at nFirst
1243 wxString wxString::Mid(size_t nFirst, size_t nCount) const
1244 {
1245 size_t nLen = length();
1246
1247 // default value of nCount is npos and means "till the end"
1248 if ( nCount == npos )
1249 {
1250 nCount = nLen - nFirst;
1251 }
1252
1253 // out-of-bounds requests return sensible things
1254 if ( nFirst + nCount > nLen )
1255 {
1256 nCount = nLen - nFirst;
1257 }
1258
1259 if ( nFirst > nLen )
1260 {
1261 // AllocCopy() will return empty string
1262 return wxEmptyString;
1263 }
1264
1265 wxString dest(*this, nFirst, nCount);
1266 if ( dest.length() != nCount )
1267 {
1268 wxFAIL_MSG( wxT("out of memory in wxString::Mid") );
1269 }
1270
1271 return dest;
1272 }
1273
1274 // check that the string starts with prefix and return the rest of the string
1275 // in the provided pointer if it is not NULL, otherwise return false
1276 bool wxString::StartsWith(const wxString& prefix, wxString *rest) const
1277 {
1278 if ( compare(0, prefix.length(), prefix) != 0 )
1279 return false;
1280
1281 if ( rest )
1282 {
1283 // put the rest of the string into provided pointer
1284 rest->assign(*this, prefix.length(), npos);
1285 }
1286
1287 return true;
1288 }
1289
1290
1291 // check that the string ends with suffix and return the rest of it in the
1292 // provided pointer if it is not NULL, otherwise return false
1293 bool wxString::EndsWith(const wxString& suffix, wxString *rest) const
1294 {
1295 int start = length() - suffix.length();
1296
1297 if ( start < 0 || compare(start, npos, suffix) != 0 )
1298 return false;
1299
1300 if ( rest )
1301 {
1302 // put the rest of the string into provided pointer
1303 rest->assign(*this, 0, start);
1304 }
1305
1306 return true;
1307 }
1308
1309
1310 // extract nCount last (rightmost) characters
1311 wxString wxString::Right(size_t nCount) const
1312 {
1313 if ( nCount > length() )
1314 nCount = length();
1315
1316 wxString dest(*this, length() - nCount, nCount);
1317 if ( dest.length() != nCount ) {
1318 wxFAIL_MSG( wxT("out of memory in wxString::Right") );
1319 }
1320 return dest;
1321 }
1322
1323 // get all characters after the last occurrence of ch
1324 // (returns the whole string if ch not found)
1325 wxString wxString::AfterLast(wxUniChar ch) const
1326 {
1327 wxString str;
1328 int iPos = Find(ch, true);
1329 if ( iPos == wxNOT_FOUND )
1330 str = *this;
1331 else
1332 str.assign(*this, iPos + 1, npos);
1333
1334 return str;
1335 }
1336
1337 // extract nCount first (leftmost) characters
1338 wxString wxString::Left(size_t nCount) const
1339 {
1340 if ( nCount > length() )
1341 nCount = length();
1342
1343 wxString dest(*this, 0, nCount);
1344 if ( dest.length() != nCount ) {
1345 wxFAIL_MSG( wxT("out of memory in wxString::Left") );
1346 }
1347 return dest;
1348 }
1349
1350 // get all characters before the first occurrence of ch
1351 // (returns the whole string if ch not found)
1352 wxString wxString::BeforeFirst(wxUniChar ch) const
1353 {
1354 int iPos = Find(ch);
1355 if ( iPos == wxNOT_FOUND )
1356 iPos = length();
1357 return wxString(*this, 0, iPos);
1358 }
1359
1360 /// get all characters before the last occurrence of ch
1361 /// (returns empty string if ch not found)
1362 wxString wxString::BeforeLast(wxUniChar ch) const
1363 {
1364 wxString str;
1365 int iPos = Find(ch, true);
1366 if ( iPos != wxNOT_FOUND && iPos != 0 )
1367 str = wxString(c_str(), iPos);
1368
1369 return str;
1370 }
1371
1372 /// get all characters after the first occurrence of ch
1373 /// (returns empty string if ch not found)
1374 wxString wxString::AfterFirst(wxUniChar ch) const
1375 {
1376 wxString str;
1377 int iPos = Find(ch);
1378 if ( iPos != wxNOT_FOUND )
1379 str.assign(*this, iPos + 1, npos);
1380
1381 return str;
1382 }
1383
1384 // replace first (or all) occurrences of some substring with another one
1385 size_t wxString::Replace(const wxString& strOld,
1386 const wxString& strNew, bool bReplaceAll)
1387 {
1388 // if we tried to replace an empty string we'd enter an infinite loop below
1389 wxCHECK_MSG( !strOld.empty(), 0,
1390 wxT("wxString::Replace(): invalid parameter") );
1391
1392 wxSTRING_INVALIDATE_CACHE();
1393
1394 size_t uiCount = 0; // count of replacements made
1395
1396 // optimize the special common case: replacement of one character by
1397 // another one (in UTF-8 case we can only do this for ASCII characters)
1398 //
1399 // benchmarks show that this special version is around 3 times faster
1400 // (depending on the proportion of matching characters and UTF-8/wchar_t
1401 // build)
1402 if ( strOld.m_impl.length() == 1 && strNew.m_impl.length() == 1 )
1403 {
1404 const wxStringCharType chOld = strOld.m_impl[0],
1405 chNew = strNew.m_impl[0];
1406
1407 // this loop is the simplified version of the one below
1408 for ( size_t pos = 0; ; )
1409 {
1410 pos = m_impl.find(chOld, pos);
1411 if ( pos == npos )
1412 break;
1413
1414 m_impl[pos++] = chNew;
1415
1416 uiCount++;
1417
1418 if ( !bReplaceAll )
1419 break;
1420 }
1421 }
1422 else if ( !bReplaceAll)
1423 {
1424 size_t pos = m_impl.find(strOld, 0);
1425 if ( pos != npos )
1426 {
1427 m_impl.replace(pos, strOld.m_impl.length(), strNew.m_impl);
1428 uiCount = 1;
1429 }
1430 }
1431 else // replace all occurrences
1432 {
1433 const size_t uiOldLen = strOld.m_impl.length();
1434 const size_t uiNewLen = strNew.m_impl.length();
1435
1436 // first scan the string to find all positions at which the replacement
1437 // should be made
1438 wxVector<size_t> replacePositions;
1439
1440 size_t pos;
1441 for ( pos = m_impl.find(strOld.m_impl, 0);
1442 pos != npos;
1443 pos = m_impl.find(strOld.m_impl, pos + uiOldLen))
1444 {
1445 replacePositions.push_back(pos);
1446 ++uiCount;
1447 }
1448
1449 if ( !uiCount )
1450 return 0;
1451
1452 // allocate enough memory for the whole new string
1453 wxString tmp;
1454 tmp.m_impl.reserve(m_impl.length() + uiCount*(uiNewLen - uiOldLen));
1455
1456 // copy this string to tmp doing replacements on the fly
1457 size_t replNum = 0;
1458 for ( pos = 0; replNum < uiCount; replNum++ )
1459 {
1460 const size_t nextReplPos = replacePositions[replNum];
1461
1462 if ( pos != nextReplPos )
1463 {
1464 tmp.m_impl.append(m_impl, pos, nextReplPos - pos);
1465 }
1466
1467 tmp.m_impl.append(strNew.m_impl);
1468 pos = nextReplPos + uiOldLen;
1469 }
1470
1471 if ( pos != m_impl.length() )
1472 {
1473 // append the rest of the string unchanged
1474 tmp.m_impl.append(m_impl, pos, m_impl.length() - pos);
1475 }
1476
1477 swap(tmp);
1478 }
1479
1480 return uiCount;
1481 }
1482
1483 bool wxString::IsAscii() const
1484 {
1485 for ( const_iterator i = begin(); i != end(); ++i )
1486 {
1487 if ( !(*i).IsAscii() )
1488 return false;
1489 }
1490
1491 return true;
1492 }
1493
1494 bool wxString::IsWord() const
1495 {
1496 for ( const_iterator i = begin(); i != end(); ++i )
1497 {
1498 if ( !wxIsalpha(*i) )
1499 return false;
1500 }
1501
1502 return true;
1503 }
1504
1505 bool wxString::IsNumber() const
1506 {
1507 if ( empty() )
1508 return true;
1509
1510 const_iterator i = begin();
1511
1512 if ( *i == wxT('-') || *i == wxT('+') )
1513 ++i;
1514
1515 for ( ; i != end(); ++i )
1516 {
1517 if ( !wxIsdigit(*i) )
1518 return false;
1519 }
1520
1521 return true;
1522 }
1523
1524 wxString wxString::Strip(stripType w) const
1525 {
1526 wxString s = *this;
1527 if ( w & leading ) s.Trim(false);
1528 if ( w & trailing ) s.Trim(true);
1529 return s;
1530 }
1531
1532 // ---------------------------------------------------------------------------
1533 // case conversion
1534 // ---------------------------------------------------------------------------
1535
1536 wxString& wxString::MakeUpper()
1537 {
1538 for ( iterator it = begin(), en = end(); it != en; ++it )
1539 *it = (wxChar)wxToupper(*it);
1540
1541 return *this;
1542 }
1543
1544 wxString& wxString::MakeLower()
1545 {
1546 for ( iterator it = begin(), en = end(); it != en; ++it )
1547 *it = (wxChar)wxTolower(*it);
1548
1549 return *this;
1550 }
1551
1552 wxString& wxString::MakeCapitalized()
1553 {
1554 const iterator en = end();
1555 iterator it = begin();
1556 if ( it != en )
1557 {
1558 *it = (wxChar)wxToupper(*it);
1559 for ( ++it; it != en; ++it )
1560 *it = (wxChar)wxTolower(*it);
1561 }
1562
1563 return *this;
1564 }
1565
1566 // ---------------------------------------------------------------------------
1567 // trimming and padding
1568 // ---------------------------------------------------------------------------
1569
1570 // some compilers (VC++ 6.0 not to name them) return true for a call to
1571 // isspace('\xEA') in the C locale which seems to be broken to me, but we have
1572 // to live with this by checking that the character is a 7 bit one - even if
1573 // this may fail to detect some spaces (I don't know if Unicode doesn't have
1574 // space-like symbols somewhere except in the first 128 chars), it is arguably
1575 // still better than trimming away accented letters
1576 inline int wxSafeIsspace(wxChar ch) { return (ch < 127) && wxIsspace(ch); }
1577
1578 // trims spaces (in the sense of isspace) from left or right side
1579 wxString& wxString::Trim(bool bFromRight)
1580 {
1581 // first check if we're going to modify the string at all
1582 if ( !empty() &&
1583 (
1584 (bFromRight && wxSafeIsspace(GetChar(length() - 1))) ||
1585 (!bFromRight && wxSafeIsspace(GetChar(0u)))
1586 )
1587 )
1588 {
1589 if ( bFromRight )
1590 {
1591 // find last non-space character
1592 reverse_iterator psz = rbegin();
1593 while ( (psz != rend()) && wxSafeIsspace(*psz) )
1594 ++psz;
1595
1596 // truncate at trailing space start
1597 erase(psz.base(), end());
1598 }
1599 else
1600 {
1601 // find first non-space character
1602 iterator psz = begin();
1603 while ( (psz != end()) && wxSafeIsspace(*psz) )
1604 ++psz;
1605
1606 // fix up data and length
1607 erase(begin(), psz);
1608 }
1609 }
1610
1611 return *this;
1612 }
1613
1614 // adds nCount characters chPad to the string from either side
1615 wxString& wxString::Pad(size_t nCount, wxUniChar chPad, bool bFromRight)
1616 {
1617 wxString s(chPad, nCount);
1618
1619 if ( bFromRight )
1620 *this += s;
1621 else
1622 {
1623 s += *this;
1624 swap(s);
1625 }
1626
1627 return *this;
1628 }
1629
1630 // truncate the string
1631 wxString& wxString::Truncate(size_t uiLen)
1632 {
1633 if ( uiLen < length() )
1634 {
1635 erase(begin() + uiLen, end());
1636 }
1637 //else: nothing to do, string is already short enough
1638
1639 return *this;
1640 }
1641
1642 // ---------------------------------------------------------------------------
1643 // finding (return wxNOT_FOUND if not found and index otherwise)
1644 // ---------------------------------------------------------------------------
1645
1646 // find a character
1647 int wxString::Find(wxUniChar ch, bool bFromEnd) const
1648 {
1649 size_type idx = bFromEnd ? find_last_of(ch) : find_first_of(ch);
1650
1651 return (idx == npos) ? wxNOT_FOUND : (int)idx;
1652 }
1653
1654 // ----------------------------------------------------------------------------
1655 // conversion to numbers
1656 // ----------------------------------------------------------------------------
1657
1658 // The implementation of all the functions below is exactly the same so factor
1659 // it out. Note that number extraction works correctly on UTF-8 strings, so
1660 // we can use wxStringCharType and wx_str() for maximum efficiency.
1661
1662 #ifndef __WXWINCE__
1663 #define DO_IF_NOT_WINCE(x) x
1664 #else
1665 #define DO_IF_NOT_WINCE(x)
1666 #endif
1667
1668 #define WX_STRING_TO_X_TYPE_START \
1669 wxCHECK_MSG( pVal, false, wxT("NULL output pointer") ); \
1670 DO_IF_NOT_WINCE( errno = 0; ) \
1671 const wxStringCharType *start = wx_str(); \
1672 wxStringCharType *end;
1673
1674 // notice that we return false without modifying the output parameter at all if
1675 // nothing could be parsed but we do modify it and return false then if we did
1676 // parse something successfully but not the entire string
1677 #define WX_STRING_TO_X_TYPE_END \
1678 if ( end == start DO_IF_NOT_WINCE(|| errno == ERANGE) ) \
1679 return false; \
1680 *pVal = val; \
1681 return !*end;
1682
1683 bool wxString::ToLong(long *pVal, int base) const
1684 {
1685 wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );
1686
1687 WX_STRING_TO_X_TYPE_START
1688 long val = wxStrtol(start, &end, base);
1689 WX_STRING_TO_X_TYPE_END
1690 }
1691
1692 bool wxString::ToULong(unsigned long *pVal, int base) const
1693 {
1694 wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );
1695
1696 WX_STRING_TO_X_TYPE_START
1697 unsigned long val = wxStrtoul(start, &end, base);
1698 WX_STRING_TO_X_TYPE_END
1699 }
1700
1701 bool wxString::ToLongLong(wxLongLong_t *pVal, int base) const
1702 {
1703 wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );
1704
1705 WX_STRING_TO_X_TYPE_START
1706 wxLongLong_t val = wxStrtoll(start, &end, base);
1707 WX_STRING_TO_X_TYPE_END
1708 }
1709
1710 bool wxString::ToULongLong(wxULongLong_t *pVal, int base) const
1711 {
1712 wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );
1713
1714 WX_STRING_TO_X_TYPE_START
1715 wxULongLong_t val = wxStrtoull(start, &end, base);
1716 WX_STRING_TO_X_TYPE_END
1717 }
1718
1719 bool wxString::ToDouble(double *pVal) const
1720 {
1721 WX_STRING_TO_X_TYPE_START
1722 double val = wxStrtod(start, &end);
1723 WX_STRING_TO_X_TYPE_END
1724 }
1725
1726 #if wxUSE_XLOCALE
1727
1728 bool wxString::ToCLong(long *pVal, int base) const
1729 {
1730 wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );
1731
1732 WX_STRING_TO_X_TYPE_START
1733 #if (wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE) && defined(wxHAS_XLOCALE_SUPPORT)
1734 long val = wxStrtol_lA(start, &end, base, wxCLocale);
1735 #else
1736 long val = wxStrtol_l(start, &end, base, wxCLocale);
1737 #endif
1738 WX_STRING_TO_X_TYPE_END
1739 }
1740
1741 bool wxString::ToCULong(unsigned long *pVal, int base) const
1742 {
1743 wxASSERT_MSG( !base || (base > 1 && base <= 36), wxT("invalid base") );
1744
1745 WX_STRING_TO_X_TYPE_START
1746 #if (wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE) && defined(wxHAS_XLOCALE_SUPPORT)
1747 unsigned long val = wxStrtoul_lA(start, &end, base, wxCLocale);
1748 #else
1749 unsigned long val = wxStrtoul_l(start, &end, base, wxCLocale);
1750 #endif
1751 WX_STRING_TO_X_TYPE_END
1752 }
1753
1754 bool wxString::ToCDouble(double *pVal) const
1755 {
1756 WX_STRING_TO_X_TYPE_START
1757 #if (wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE) && defined(wxHAS_XLOCALE_SUPPORT)
1758 double val = wxStrtod_lA(start, &end, wxCLocale);
1759 #else
1760 double val = wxStrtod_l(start, &end, wxCLocale);
1761 #endif
1762 WX_STRING_TO_X_TYPE_END
1763 }
1764
1765 #else // wxUSE_XLOCALE
1766
1767 // Provide implementation of these functions even when wxUSE_XLOCALE is
1768 // disabled, we still need them in wxWidgets internal code.
1769
1770 // For integers we just assume the current locale uses the same number
1771 // representation as the C one as there is nothing else we can do.
1772 bool wxString::ToCLong(long *pVal, int base) const
1773 {
1774 return ToLong(pVal, base);
1775 }
1776
1777 bool wxString::ToCULong(unsigned long *pVal, int base) const
1778 {
1779 return ToULong(pVal, base);
1780 }
1781
1782 // For floating point numbers we have to handle the problem of the decimal
1783 // point which is different in different locales.
1784 bool wxString::ToCDouble(double *pVal) const
1785 {
1786 // Create a copy of this string using the decimal point instead of whatever
1787 // separator the current locale uses.
1788 #if wxUSE_INTL
1789 wxString sep = wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT,
1790 wxLOCALE_CAT_NUMBER);
1791 if ( sep == "." )
1792 {
1793 // We can avoid an unnecessary string copy in this case.
1794 return ToDouble(pVal);
1795 }
1796 #else // !wxUSE_INTL
1797 // We don't know what the current separator is so it might even be a point
1798 // already, try to parse the string as a double:
1799 if ( ToDouble(pVal) )
1800 {
1801 // It must have been the point, nothing else to do.
1802 return true;
1803 }
1804
1805 // Try to guess the separator, using the most common alternative value.
1806 wxString sep(",");
1807 #endif // wxUSE_INTL/!wxUSE_INTL
1808 wxString cstr(*this);
1809 cstr.Replace(".", sep);
1810
1811 return cstr.ToDouble(pVal);
1812 }
1813
1814 #endif // wxUSE_XLOCALE/!wxUSE_XLOCALE
1815
1816 // ----------------------------------------------------------------------------
1817 // number to string conversion
1818 // ----------------------------------------------------------------------------
1819
1820 /* static */
1821 wxString wxString::FromCDouble(double val)
1822 {
1823 #if wxUSE_STD_IOSTREAM && wxUSE_STD_STRING
1824 // We assume that we can use the ostream and not wstream for numbers.
1825 wxSTD ostringstream os;
1826 os << val;
1827 return os.str();
1828 #else // wxUSE_STD_IOSTREAM
1829 // Can't use iostream locale support, fall back to the manual method
1830 // instead.
1831 wxString s = FromDouble(val);
1832 #if wxUSE_INTL
1833 wxString sep = wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT,
1834 wxLOCALE_CAT_NUMBER);
1835 #else // !wxUSE_INTL
1836 // As above, this is the most common alternative value. Notice that here it
1837 // doesn't matter if we guess wrongly and the current separator is already
1838 // ".": we'll just waste a call to Replace() in this case.
1839 wxString sep(",");
1840 #endif // wxUSE_INTL/!wxUSE_INTL
1841
1842 s.Replace(sep, ".");
1843 return s;
1844 #endif // wxUSE_STD_IOSTREAM/!wxUSE_STD_IOSTREAM
1845 }
1846
1847 // ---------------------------------------------------------------------------
1848 // formatted output
1849 // ---------------------------------------------------------------------------
1850
1851 #if !wxUSE_UTF8_LOCALE_ONLY
1852 /* static */
1853 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1854 wxString wxStringPrintfMixinBase::DoFormatWchar(const wxChar *format, ...)
1855 #else
1856 wxString wxString::DoFormatWchar(const wxChar *format, ...)
1857 #endif
1858 {
1859 va_list argptr;
1860 va_start(argptr, format);
1861
1862 wxString s;
1863 s.PrintfV(format, argptr);
1864
1865 va_end(argptr);
1866
1867 return s;
1868 }
1869 #endif // !wxUSE_UTF8_LOCALE_ONLY
1870
1871 #if wxUSE_UNICODE_UTF8
1872 /* static */
1873 wxString wxString::DoFormatUtf8(const char *format, ...)
1874 {
1875 va_list argptr;
1876 va_start(argptr, format);
1877
1878 wxString s;
1879 s.PrintfV(format, argptr);
1880
1881 va_end(argptr);
1882
1883 return s;
1884 }
1885 #endif // wxUSE_UNICODE_UTF8
1886
1887 /* static */
1888 wxString wxString::FormatV(const wxString& format, va_list argptr)
1889 {
1890 wxString s;
1891 s.PrintfV(format, argptr);
1892 return s;
1893 }
1894
1895 #if !wxUSE_UTF8_LOCALE_ONLY
1896 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1897 int wxStringPrintfMixinBase::DoPrintfWchar(const wxChar *format, ...)
1898 #else
1899 int wxString::DoPrintfWchar(const wxChar *format, ...)
1900 #endif
1901 {
1902 va_list argptr;
1903 va_start(argptr, format);
1904
1905 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1906 // get a pointer to the wxString instance; we have to use dynamic_cast<>
1907 // because it's the only cast that works safely for downcasting when
1908 // multiple inheritance is used:
1909 wxString *str = static_cast<wxString*>(this);
1910 #else
1911 wxString *str = this;
1912 #endif
1913
1914 int iLen = str->PrintfV(format, argptr);
1915
1916 va_end(argptr);
1917
1918 return iLen;
1919 }
1920 #endif // !wxUSE_UTF8_LOCALE_ONLY
1921
1922 #if wxUSE_UNICODE_UTF8
1923 int wxString::DoPrintfUtf8(const char *format, ...)
1924 {
1925 va_list argptr;
1926 va_start(argptr, format);
1927
1928 int iLen = PrintfV(format, argptr);
1929
1930 va_end(argptr);
1931
1932 return iLen;
1933 }
1934 #endif // wxUSE_UNICODE_UTF8
1935
1936 /*
1937 Uses wxVsnprintf and places the result into the this string.
1938
1939 In ANSI build, wxVsnprintf is effectively vsnprintf but in Unicode build
1940 it is vswprintf. Due to a discrepancy between vsnprintf and vswprintf in
1941 the ISO C99 (and thus SUSv3) standard the return value for the case of
1942 an undersized buffer is inconsistent. For conforming vsnprintf
1943 implementations the function must return the number of characters that
1944 would have been printed had the buffer been large enough. For conforming
1945 vswprintf implementations the function must return a negative number
1946 and set errno.
1947
1948 What vswprintf sets errno to is undefined but Darwin seems to set it to
1949 EOVERFLOW. The only expected errno are EILSEQ and EINVAL. Both of
1950 those are defined in the standard and backed up by several conformance
1951 statements. Note that ENOMEM mentioned in the manual page does not
1952 apply to swprintf, only wprintf and fwprintf.
1953
1954 Official manual page:
1955 http://www.opengroup.org/onlinepubs/009695399/functions/swprintf.html
1956
1957 Some conformance statements (AIX, Solaris):
1958 http://www.opengroup.org/csq/view.mhtml?RID=ibm%2FSD1%2F3
1959 http://www.theopengroup.org/csq/view.mhtml?norationale=1&noreferences=1&RID=Fujitsu%2FSE2%2F10
1960
1961 Since EILSEQ and EINVAL are rather common but EOVERFLOW is not and since
1962 EILSEQ and EINVAL are specifically defined to mean the error is other than
1963 an undersized buffer and no other errno are defined we treat those two
1964 as meaning hard errors and everything else gets the old behavior which
1965 is to keep looping and increasing buffer size until the function succeeds.
1966
1967 In practice it's impossible to determine before compilation which behavior
1968 may be used. The vswprintf function may have vsnprintf-like behavior or
1969 vice-versa. Behavior detected on one release can theoretically change
1970 with an updated release. Not to mention that configure testing for it
1971 would require the test to be run on the host system, not the build system
1972 which makes cross compilation difficult. Therefore, we make no assumptions
1973 about behavior and try our best to handle every known case, including the
1974 case where wxVsnprintf returns a negative number and fails to set errno.
1975
1976 There is yet one more non-standard implementation and that is our own.
1977 Fortunately, that can be detected at compile-time.
1978
1979 On top of all that, ISO C99 explicitly defines snprintf to write a null
1980 character to the last position of the specified buffer. That would be at
1981 at the given buffer size minus 1. It is supposed to do this even if it
1982 turns out that the buffer is sized too small.
1983
1984 Darwin (tested on 10.5) follows the C99 behavior exactly.
1985
1986 Glibc 2.6 almost follows the C99 behavior except vswprintf never sets
1987 errno even when it fails. However, it only seems to ever fail due
1988 to an undersized buffer.
1989 */
1990 #if wxUSE_UNICODE_UTF8
1991 template<typename BufferType>
1992 #else
1993 // we only need one version in non-UTF8 builds and at least two Windows
1994 // compilers have problems with this function template, so use just one
1995 // normal function here
1996 #endif
1997 static int DoStringPrintfV(wxString& str,
1998 const wxString& format, va_list argptr)
1999 {
2000 int size = 1024;
2001
2002 for ( ;; )
2003 {
2004 #if wxUSE_UNICODE_UTF8
2005 BufferType tmp(str, size + 1);
2006 typename BufferType::CharType *buf = tmp;
2007 #else
2008 wxStringBuffer tmp(str, size + 1);
2009 wxChar *buf = tmp;
2010 #endif
2011
2012 if ( !buf )
2013 {
2014 // out of memory
2015
2016 // in UTF-8 build, leaving uninitialized junk in the buffer
2017 // could result in invalid non-empty UTF-8 string, so just
2018 // reset the string to empty on failure:
2019 buf[0] = '\0';
2020 return -1;
2021 }
2022
2023 // wxVsnprintf() may modify the original arg pointer, so pass it
2024 // only a copy
2025 va_list argptrcopy;
2026 wxVaCopy(argptrcopy, argptr);
2027
2028 #ifndef __WXWINCE__
2029 // Set errno to 0 to make it determinate if wxVsnprintf fails to set it.
2030 errno = 0;
2031 #endif
2032 int len = wxVsnprintf(buf, size, format, argptrcopy);
2033 va_end(argptrcopy);
2034
2035 // some implementations of vsnprintf() don't NUL terminate
2036 // the string if there is not enough space for it so
2037 // always do it manually
2038 // FIXME: This really seems to be the wrong and would be an off-by-one
2039 // bug except the code above allocates an extra character.
2040 buf[size] = wxT('\0');
2041
2042 // vsnprintf() may return either -1 (traditional Unix behaviour) or the
2043 // total number of characters which would have been written if the
2044 // buffer were large enough (newer standards such as Unix98)
2045 if ( len < 0 )
2046 {
2047 // NB: wxVsnprintf() may call either wxCRT_VsnprintfW or
2048 // wxCRT_VsnprintfA in UTF-8 build; wxUSE_WXVSNPRINTF
2049 // is true if *both* of them use our own implementation,
2050 // otherwise we can't be sure
2051 #if wxUSE_WXVSNPRINTF
2052 // we know that our own implementation of wxVsnprintf() returns -1
2053 // only for a format error - thus there's something wrong with
2054 // the user's format string
2055 buf[0] = '\0';
2056 return -1;
2057 #else // possibly using system version
2058 // assume it only returns error if there is not enough space, but
2059 // as we don't know how much we need, double the current size of
2060 // the buffer
2061 #ifndef __WXWINCE__
2062 if( (errno == EILSEQ) || (errno == EINVAL) )
2063 // If errno was set to one of the two well-known hard errors
2064 // then fail immediately to avoid an infinite loop.
2065 return -1;
2066 else
2067 #endif // __WXWINCE__
2068 // still not enough, as we don't know how much we need, double the
2069 // current size of the buffer
2070 size *= 2;
2071 #endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
2072 }
2073 else if ( len >= size )
2074 {
2075 #if wxUSE_WXVSNPRINTF
2076 // we know that our own implementation of wxVsnprintf() returns
2077 // size+1 when there's not enough space but that's not the size
2078 // of the required buffer!
2079 size *= 2; // so we just double the current size of the buffer
2080 #else
2081 // some vsnprintf() implementations NUL-terminate the buffer and
2082 // some don't in len == size case, to be safe always add 1
2083 // FIXME: I don't quite understand this comment. The vsnprintf
2084 // function is specifically defined to return the number of
2085 // characters printed not including the null terminator.
2086 // So OF COURSE you need to add 1 to get the right buffer size.
2087 // The following line is definitely correct, no question.
2088 size = len + 1;
2089 #endif
2090 }
2091 else // ok, there was enough space
2092 {
2093 break;
2094 }
2095 }
2096
2097 // we could have overshot
2098 str.Shrink();
2099
2100 return str.length();
2101 }
2102
2103 int wxString::PrintfV(const wxString& format, va_list argptr)
2104 {
2105 #if wxUSE_UNICODE_UTF8
2106 #if wxUSE_STL_BASED_WXSTRING
2107 typedef wxStringTypeBuffer<char> Utf8Buffer;
2108 #else
2109 typedef wxStringInternalBuffer Utf8Buffer;
2110 #endif
2111 #endif
2112
2113 #if wxUSE_UTF8_LOCALE_ONLY
2114 return DoStringPrintfV<Utf8Buffer>(*this, format, argptr);
2115 #else
2116 #if wxUSE_UNICODE_UTF8
2117 if ( wxLocaleIsUtf8 )
2118 return DoStringPrintfV<Utf8Buffer>(*this, format, argptr);
2119 else
2120 // wxChar* version
2121 return DoStringPrintfV<wxStringBuffer>(*this, format, argptr);
2122 #else
2123 return DoStringPrintfV(*this, format, argptr);
2124 #endif // UTF8/WCHAR
2125 #endif
2126 }
2127
2128 // ----------------------------------------------------------------------------
2129 // misc other operations
2130 // ----------------------------------------------------------------------------
2131
2132 // returns true if the string matches the pattern which may contain '*' and
2133 // '?' metacharacters (as usual, '?' matches any character and '*' any number
2134 // of them)
2135 bool wxString::Matches(const wxString& mask) const
2136 {
2137 // I disable this code as it doesn't seem to be faster (in fact, it seems
2138 // to be much slower) than the old, hand-written code below and using it
2139 // here requires always linking with libregex even if the user code doesn't
2140 // use it
2141 #if 0 // wxUSE_REGEX
2142 // first translate the shell-like mask into a regex
2143 wxString pattern;
2144 pattern.reserve(wxStrlen(pszMask));
2145
2146 pattern += wxT('^');
2147 while ( *pszMask )
2148 {
2149 switch ( *pszMask )
2150 {
2151 case wxT('?'):
2152 pattern += wxT('.');
2153 break;
2154
2155 case wxT('*'):
2156 pattern += wxT(".*");
2157 break;
2158
2159 case wxT('^'):
2160 case wxT('.'):
2161 case wxT('$'):
2162 case wxT('('):
2163 case wxT(')'):
2164 case wxT('|'):
2165 case wxT('+'):
2166 case wxT('\\'):
2167 // these characters are special in a RE, quote them
2168 // (however note that we don't quote '[' and ']' to allow
2169 // using them for Unix shell like matching)
2170 pattern += wxT('\\');
2171 // fall through
2172
2173 default:
2174 pattern += *pszMask;
2175 }
2176
2177 pszMask++;
2178 }
2179 pattern += wxT('$');
2180
2181 // and now use it
2182 return wxRegEx(pattern, wxRE_NOSUB | wxRE_EXTENDED).Matches(c_str());
2183 #else // !wxUSE_REGEX
2184 // TODO: this is, of course, awfully inefficient...
2185
2186 // FIXME-UTF8: implement using iterators, remove #if
2187 #if wxUSE_UNICODE_UTF8
2188 const wxScopedWCharBuffer maskBuf = mask.wc_str();
2189 const wxScopedWCharBuffer txtBuf = wc_str();
2190 const wxChar *pszMask = maskBuf.data();
2191 const wxChar *pszTxt = txtBuf.data();
2192 #else
2193 const wxChar *pszMask = mask.wx_str();
2194 // the char currently being checked
2195 const wxChar *pszTxt = wx_str();
2196 #endif
2197
2198 // the last location where '*' matched
2199 const wxChar *pszLastStarInText = NULL;
2200 const wxChar *pszLastStarInMask = NULL;
2201
2202 match:
2203 for ( ; *pszMask != wxT('\0'); pszMask++, pszTxt++ ) {
2204 switch ( *pszMask ) {
2205 case wxT('?'):
2206 if ( *pszTxt == wxT('\0') )
2207 return false;
2208
2209 // pszTxt and pszMask will be incremented in the loop statement
2210
2211 break;
2212
2213 case wxT('*'):
2214 {
2215 // remember where we started to be able to backtrack later
2216 pszLastStarInText = pszTxt;
2217 pszLastStarInMask = pszMask;
2218
2219 // ignore special chars immediately following this one
2220 // (should this be an error?)
2221 while ( *pszMask == wxT('*') || *pszMask == wxT('?') )
2222 pszMask++;
2223
2224 // if there is nothing more, match
2225 if ( *pszMask == wxT('\0') )
2226 return true;
2227
2228 // are there any other metacharacters in the mask?
2229 size_t uiLenMask;
2230 const wxChar *pEndMask = wxStrpbrk(pszMask, wxT("*?"));
2231
2232 if ( pEndMask != NULL ) {
2233 // we have to match the string between two metachars
2234 uiLenMask = pEndMask - pszMask;
2235 }
2236 else {
2237 // we have to match the remainder of the string
2238 uiLenMask = wxStrlen(pszMask);
2239 }
2240
2241 wxString strToMatch(pszMask, uiLenMask);
2242 const wxChar* pMatch = wxStrstr(pszTxt, strToMatch);
2243 if ( pMatch == NULL )
2244 return false;
2245
2246 // -1 to compensate "++" in the loop
2247 pszTxt = pMatch + uiLenMask - 1;
2248 pszMask += uiLenMask - 1;
2249 }
2250 break;
2251
2252 default:
2253 if ( *pszMask != *pszTxt )
2254 return false;
2255 break;
2256 }
2257 }
2258
2259 // match only if nothing left
2260 if ( *pszTxt == wxT('\0') )
2261 return true;
2262
2263 // if we failed to match, backtrack if we can
2264 if ( pszLastStarInText ) {
2265 pszTxt = pszLastStarInText + 1;
2266 pszMask = pszLastStarInMask;
2267
2268 pszLastStarInText = NULL;
2269
2270 // don't bother resetting pszLastStarInMask, it's unnecessary
2271
2272 goto match;
2273 }
2274
2275 return false;
2276 #endif // wxUSE_REGEX/!wxUSE_REGEX
2277 }
2278
2279 // Count the number of chars
2280 int wxString::Freq(wxUniChar ch) const
2281 {
2282 int count = 0;
2283 for ( const_iterator i = begin(); i != end(); ++i )
2284 {
2285 if ( *i == ch )
2286 count ++;
2287 }
2288 return count;
2289 }
2290