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