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