]> git.saurik.com Git - wxWidgets.git/blame - src/common/string.cpp
non-pch build fix
[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 1350// isspace('\xEA') in the C locale which seems to be broken to me, but we have
c95e653c 1351// to live with this by checking that the character is a 7 bit one - even if
9d55bfef 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
c95e653c
VZ
1447#define WX_STRING_TO_INT_TYPE(out, base, func, T) \
1448 wxCHECK_MSG( out, false, _T("NULL output pointer") ); \
941a4e62
VS
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; \
c95e653c 1455 T val = func(start, &end, base); \
941a4e62
VS
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: */ \
c95e653c
VZ
1460 if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) ) \
1461 return false; \
1462 *out = val; \
1463 return true
cd0b1709 1464
c95e653c 1465bool wxString::ToLong(long *pVal, int base) const
cd0b1709 1466{
c95e653c 1467 WX_STRING_TO_INT_TYPE(pVal, base, wxStrtol, long);
619dcb09 1468}
cd0b1709 1469
c95e653c 1470bool wxString::ToULong(unsigned long *pVal, int base) const
619dcb09 1471{
c95e653c 1472 WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoul, unsigned long);
cd0b1709
VZ
1473}
1474
c95e653c 1475bool wxString::ToLongLong(wxLongLong_t *pVal, int base) const
d6718dd1 1476{
c95e653c 1477 WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoll, wxLongLong_t);
d6718dd1
VZ
1478}
1479
c95e653c 1480bool wxString::ToULongLong(wxULongLong_t *pVal, int base) const
d6718dd1 1481{
c95e653c 1482 WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoull, wxULongLong_t);
d6718dd1
VZ
1483}
1484
c95e653c 1485bool wxString::ToDouble(double *pVal) const
cd0b1709 1486{
c95e653c 1487 wxCHECK_MSG( pVal, false, _T("NULL output pointer") );
cd0b1709 1488
c95e653c 1489 DO_IF_NOT_WINCE( errno = 0; )
e71e5b37 1490
cd0b1709
VZ
1491 const wxChar *start = c_str();
1492 wxChar *end;
c95e653c 1493 double val = wxStrtod(start, &end);
cd0b1709 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
c95e653c
VZ
1497 if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) )
1498 return false;
1499
1500 *pVal = val;
1501
1502 return true;
cd0b1709
VZ
1503}
1504
c801d85f 1505// ---------------------------------------------------------------------------
9efd3367 1506// formatted output
c801d85f 1507// ---------------------------------------------------------------------------
378b05f7 1508
d1f6e2cf 1509#if !wxUSE_UTF8_LOCALE_ONLY
341e7d28 1510/* static */
c9f78968 1511#ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1528e0b8 1512wxString wxStringPrintfMixinBase::DoFormatWchar(const wxChar *format, ...)
c9f78968 1513#else
d1f6e2cf 1514wxString wxString::DoFormatWchar(const wxChar *format, ...)
c9f78968 1515#endif
341e7d28 1516{
77c3e48a 1517 va_list argptr;
c9f78968 1518 va_start(argptr, format);
341e7d28 1519
77c3e48a 1520 wxString s;
c9f78968 1521 s.PrintfV(format, argptr);
341e7d28 1522
77c3e48a 1523 va_end(argptr);
341e7d28 1524
77c3e48a 1525 return s;
341e7d28 1526}
d1f6e2cf
VS
1527#endif // !wxUSE_UTF8_LOCALE_ONLY
1528
1529#if wxUSE_UNICODE_UTF8
1530/* static */
1531wxString wxString::DoFormatUtf8(const char *format, ...)
1532{
1533 va_list argptr;
1534 va_start(argptr, format);
1535
1536 wxString s;
1537 s.PrintfV(format, argptr);
1538
1539 va_end(argptr);
1540
1541 return s;
1542}
1543#endif // wxUSE_UNICODE_UTF8
341e7d28
VZ
1544
1545/* static */
c9f78968 1546wxString wxString::FormatV(const wxString& format, va_list argptr)
341e7d28
VZ
1547{
1548 wxString s;
c9f78968 1549 s.PrintfV(format, argptr);
341e7d28
VZ
1550 return s;
1551}
1552
d1f6e2cf 1553#if !wxUSE_UTF8_LOCALE_ONLY
c9f78968 1554#ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
d1f6e2cf 1555int wxStringPrintfMixinBase::DoPrintfWchar(const wxChar *format, ...)
c9f78968 1556#else
d1f6e2cf 1557int wxString::DoPrintfWchar(const wxChar *format, ...)
c9f78968 1558#endif
c801d85f 1559{
ba9bbf13 1560 va_list argptr;
c9f78968 1561 va_start(argptr, format);
c801d85f 1562
c9f78968
VS
1563#ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1564 // get a pointer to the wxString instance; we have to use dynamic_cast<>
1565 // because it's the only cast that works safely for downcasting when
1566 // multiple inheritance is used:
1567 wxString *str = static_cast<wxString*>(this);
1568#else
1569 wxString *str = this;
1570#endif
1571
1572 int iLen = str->PrintfV(format, argptr);
c801d85f 1573
ba9bbf13 1574 va_end(argptr);
c801d85f 1575
ba9bbf13 1576 return iLen;
c801d85f 1577}
d1f6e2cf
VS
1578#endif // !wxUSE_UTF8_LOCALE_ONLY
1579
1580#if wxUSE_UNICODE_UTF8
1581int wxString::DoPrintfUtf8(const char *format, ...)
1582{
1583 va_list argptr;
1584 va_start(argptr, format);
1585
1586 int iLen = PrintfV(format, argptr);
1587
1588 va_end(argptr);
1589
1590 return iLen;
1591}
1592#endif // wxUSE_UNICODE_UTF8
c801d85f 1593
67612ff1
DE
1594/*
1595 Uses wxVsnprintf and places the result into the this string.
1596
1597 In ANSI build, wxVsnprintf is effectively vsnprintf but in Unicode build
1598 it is vswprintf. Due to a discrepancy between vsnprintf and vswprintf in
1599 the ISO C99 (and thus SUSv3) standard the return value for the case of
1600 an undersized buffer is inconsistent. For conforming vsnprintf
1601 implementations the function must return the number of characters that
1602 would have been printed had the buffer been large enough. For conforming
1603 vswprintf implementations the function must return a negative number
1604 and set errno.
1605
1606 What vswprintf sets errno to is undefined but Darwin seems to set it to
a9a854d7
DE
1607 EOVERFLOW. The only expected errno are EILSEQ and EINVAL. Both of
1608 those are defined in the standard and backed up by several conformance
1609 statements. Note that ENOMEM mentioned in the manual page does not
1610 apply to swprintf, only wprintf and fwprintf.
1611
1612 Official manual page:
1613 http://www.opengroup.org/onlinepubs/009695399/functions/swprintf.html
1614
1615 Some conformance statements (AIX, Solaris):
1616 http://www.opengroup.org/csq/view.mhtml?RID=ibm%2FSD1%2F3
1617 http://www.theopengroup.org/csq/view.mhtml?norationale=1&noreferences=1&RID=Fujitsu%2FSE2%2F10
1618
1619 Since EILSEQ and EINVAL are rather common but EOVERFLOW is not and since
1620 EILSEQ and EINVAL are specifically defined to mean the error is other than
1621 an undersized buffer and no other errno are defined we treat those two
1622 as meaning hard errors and everything else gets the old behavior which
1623 is to keep looping and increasing buffer size until the function succeeds.
c95e653c 1624
67612ff1
DE
1625 In practice it's impossible to determine before compilation which behavior
1626 may be used. The vswprintf function may have vsnprintf-like behavior or
1627 vice-versa. Behavior detected on one release can theoretically change
1628 with an updated release. Not to mention that configure testing for it
1629 would require the test to be run on the host system, not the build system
1630 which makes cross compilation difficult. Therefore, we make no assumptions
1631 about behavior and try our best to handle every known case, including the
1632 case where wxVsnprintf returns a negative number and fails to set errno.
1633
1634 There is yet one more non-standard implementation and that is our own.
1635 Fortunately, that can be detected at compile-time.
1636
1637 On top of all that, ISO C99 explicitly defines snprintf to write a null
1638 character to the last position of the specified buffer. That would be at
1639 at the given buffer size minus 1. It is supposed to do this even if it
1640 turns out that the buffer is sized too small.
1641
1642 Darwin (tested on 10.5) follows the C99 behavior exactly.
1643
1644 Glibc 2.6 almost follows the C99 behavior except vswprintf never sets
1645 errno even when it fails. However, it only seems to ever fail due
1646 to an undersized buffer.
1647*/
2523e9b7
VS
1648#if wxUSE_UNICODE_UTF8
1649template<typename BufferType>
1650#else
1651// we only need one version in non-UTF8 builds and at least two Windows
1652// compilers have problems with this function template, so use just one
1653// normal function here
1654#endif
1655static int DoStringPrintfV(wxString& str,
1656 const wxString& format, va_list argptr)
c801d85f 1657{
f6f5941b 1658 int size = 1024;
e87b7833 1659
f6f5941b
VZ
1660 for ( ;; )
1661 {
2523e9b7
VS
1662#if wxUSE_UNICODE_UTF8
1663 BufferType tmp(str, size + 1);
1664 typename BufferType::CharType *buf = tmp;
1665#else
1666 wxStringBuffer tmp(str, size + 1);
de2589be 1667 wxChar *buf = tmp;
2523e9b7 1668#endif
2bb67b80 1669
ba9bbf13
WS
1670 if ( !buf )
1671 {
1672 // out of memory
a33c7045
VS
1673
1674 // in UTF-8 build, leaving uninitialized junk in the buffer
1675 // could result in invalid non-empty UTF-8 string, so just
1676 // reset the string to empty on failure:
1677 buf[0] = '\0';
ba9bbf13 1678 return -1;
e87b7833 1679 }
f6f5941b 1680
ba9bbf13
WS
1681 // wxVsnprintf() may modify the original arg pointer, so pass it
1682 // only a copy
1683 va_list argptrcopy;
1684 wxVaCopy(argptrcopy, argptr);
67612ff1
DE
1685
1686#ifndef __WXWINCE__
1687 // Set errno to 0 to make it determinate if wxVsnprintf fails to set it.
1688 errno = 0;
1689#endif
2523e9b7 1690 int len = wxVsnprintf(buf, size, format, argptrcopy);
ba9bbf13
WS
1691 va_end(argptrcopy);
1692
1693 // some implementations of vsnprintf() don't NUL terminate
1694 // the string if there is not enough space for it so
1695 // always do it manually
67612ff1
DE
1696 // FIXME: This really seems to be the wrong and would be an off-by-one
1697 // bug except the code above allocates an extra character.
ba9bbf13
WS
1698 buf[size] = _T('\0');
1699
caff62f2
VZ
1700 // vsnprintf() may return either -1 (traditional Unix behaviour) or the
1701 // total number of characters which would have been written if the
b1727cfe 1702 // buffer were large enough (newer standards such as Unix98)
de2589be
VZ
1703 if ( len < 0 )
1704 {
52de37c7
VS
1705 // NB: wxVsnprintf() may call either wxCRT_VsnprintfW or
1706 // wxCRT_VsnprintfA in UTF-8 build; wxUSE_WXVSNPRINTF
1707 // is true if *both* of them use our own implementation,
1708 // otherwise we can't be sure
f2bbe5b6
VZ
1709#if wxUSE_WXVSNPRINTF
1710 // we know that our own implementation of wxVsnprintf() returns -1
1711 // only for a format error - thus there's something wrong with
1712 // the user's format string
a33c7045 1713 buf[0] = '\0';
f2bbe5b6 1714 return -1;
52de37c7
VS
1715#else // possibly using system version
1716 // assume it only returns error if there is not enough space, but
1717 // as we don't know how much we need, double the current size of
1718 // the buffer
67612ff1 1719#ifndef __WXWINCE__
a9a854d7
DE
1720 if( (errno == EILSEQ) || (errno == EINVAL) )
1721 // If errno was set to one of the two well-known hard errors
1722 // then fail immediately to avoid an infinite loop.
1723 return -1;
1724 else
1725#endif // __WXWINCE__
67612ff1
DE
1726 // still not enough, as we don't know how much we need, double the
1727 // current size of the buffer
1728 size *= 2;
f2bbe5b6 1729#endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
de2589be 1730 }
64f8f94c 1731 else if ( len >= size )
de2589be 1732 {
f2bbe5b6 1733#if wxUSE_WXVSNPRINTF
c95e653c 1734 // we know that our own implementation of wxVsnprintf() returns
f2bbe5b6
VZ
1735 // size+1 when there's not enough space but that's not the size
1736 // of the required buffer!
1737 size *= 2; // so we just double the current size of the buffer
1738#else
64f8f94c
VZ
1739 // some vsnprintf() implementations NUL-terminate the buffer and
1740 // some don't in len == size case, to be safe always add 1
67612ff1
DE
1741 // FIXME: I don't quite understand this comment. The vsnprintf
1742 // function is specifically defined to return the number of
1743 // characters printed not including the null terminator.
1744 // So OF COURSE you need to add 1 to get the right buffer size.
1745 // The following line is definitely correct, no question.
64f8f94c 1746 size = len + 1;
f2bbe5b6 1747#endif
de2589be
VZ
1748 }
1749 else // ok, there was enough space
f6f5941b 1750 {
f6f5941b
VZ
1751 break;
1752 }
f6f5941b
VZ
1753 }
1754
1755 // we could have overshot
2523e9b7
VS
1756 str.Shrink();
1757
1758 return str.length();
1759}
c801d85f 1760
2523e9b7
VS
1761int wxString::PrintfV(const wxString& format, va_list argptr)
1762{
2523e9b7
VS
1763#if wxUSE_UNICODE_UTF8
1764 #if wxUSE_STL_BASED_WXSTRING
1765 typedef wxStringTypeBuffer<char> Utf8Buffer;
1766 #else
6798451b 1767 typedef wxStringInternalBuffer Utf8Buffer;
2523e9b7
VS
1768 #endif
1769#endif
1770
1771#if wxUSE_UTF8_LOCALE_ONLY
c6255a6e 1772 return DoStringPrintfV<Utf8Buffer>(*this, format, argptr);
2523e9b7
VS
1773#else
1774 #if wxUSE_UNICODE_UTF8
1775 if ( wxLocaleIsUtf8 )
c6255a6e 1776 return DoStringPrintfV<Utf8Buffer>(*this, format, argptr);
2523e9b7
VS
1777 else
1778 // wxChar* version
c6255a6e 1779 return DoStringPrintfV<wxStringBuffer>(*this, format, argptr);
2523e9b7 1780 #else
c6255a6e 1781 return DoStringPrintfV(*this, format, argptr);
2523e9b7
VS
1782 #endif // UTF8/WCHAR
1783#endif
c801d85f
KB
1784}
1785
097c080b
VZ
1786// ----------------------------------------------------------------------------
1787// misc other operations
1788// ----------------------------------------------------------------------------
0c5d3e1c 1789
d775fa82 1790// returns true if the string matches the pattern which may contain '*' and
0c5d3e1c
VZ
1791// '?' metacharacters (as usual, '?' matches any character and '*' any number
1792// of them)
8a540c88 1793bool wxString::Matches(const wxString& mask) const
097c080b 1794{
d6044f58
VZ
1795 // I disable this code as it doesn't seem to be faster (in fact, it seems
1796 // to be much slower) than the old, hand-written code below and using it
1797 // here requires always linking with libregex even if the user code doesn't
1798 // use it
1799#if 0 // wxUSE_REGEX
706c2ac9
VZ
1800 // first translate the shell-like mask into a regex
1801 wxString pattern;
1802 pattern.reserve(wxStrlen(pszMask));
1803
1804 pattern += _T('^');
1805 while ( *pszMask )
1806 {
1807 switch ( *pszMask )
1808 {
1809 case _T('?'):
1810 pattern += _T('.');
1811 break;
1812
1813 case _T('*'):
1814 pattern += _T(".*");
1815 break;
1816
1817 case _T('^'):
1818 case _T('.'):
1819 case _T('$'):
1820 case _T('('):
1821 case _T(')'):
1822 case _T('|'):
1823 case _T('+'):
1824 case _T('\\'):
1825 // these characters are special in a RE, quote them
1826 // (however note that we don't quote '[' and ']' to allow
1827 // using them for Unix shell like matching)
1828 pattern += _T('\\');
1829 // fall through
1830
1831 default:
1832 pattern += *pszMask;
1833 }
1834
1835 pszMask++;
1836 }
1837 pattern += _T('$');
1838
1839 // and now use it
1840 return wxRegEx(pattern, wxRE_NOSUB | wxRE_EXTENDED).Matches(c_str());
1841#else // !wxUSE_REGEX
9a4232dc
VZ
1842 // TODO: this is, of course, awfully inefficient...
1843
8a540c88
VS
1844 // FIXME-UTF8: implement using iterators, remove #if
1845#if wxUSE_UNICODE_UTF8
1846 wxWCharBuffer maskBuf = mask.wc_str();
1847 wxWCharBuffer txtBuf = wc_str();
1848 const wxChar *pszMask = maskBuf.data();
1849 const wxChar *pszTxt = txtBuf.data();
1850#else
1851 const wxChar *pszMask = mask.wx_str();
9a4232dc 1852 // the char currently being checked
8a540c88
VS
1853 const wxChar *pszTxt = wx_str();
1854#endif
9a4232dc
VZ
1855
1856 // the last location where '*' matched
1857 const wxChar *pszLastStarInText = NULL;
1858 const wxChar *pszLastStarInMask = NULL;
1859
1860match:
1861 for ( ; *pszMask != wxT('\0'); pszMask++, pszTxt++ ) {
097c080b 1862 switch ( *pszMask ) {
223d09f6
KB
1863 case wxT('?'):
1864 if ( *pszTxt == wxT('\0') )
d775fa82 1865 return false;
097c080b 1866
9a4232dc 1867 // pszTxt and pszMask will be incremented in the loop statement
0c5d3e1c 1868
097c080b
VZ
1869 break;
1870
223d09f6 1871 case wxT('*'):
097c080b 1872 {
9a4232dc
VZ
1873 // remember where we started to be able to backtrack later
1874 pszLastStarInText = pszTxt;
1875 pszLastStarInMask = pszMask;
1876
097c080b 1877 // ignore special chars immediately following this one
9a4232dc 1878 // (should this be an error?)
223d09f6 1879 while ( *pszMask == wxT('*') || *pszMask == wxT('?') )
097c080b
VZ
1880 pszMask++;
1881
1882 // if there is nothing more, match
223d09f6 1883 if ( *pszMask == wxT('\0') )
d775fa82 1884 return true;
097c080b
VZ
1885
1886 // are there any other metacharacters in the mask?
c86f1403 1887 size_t uiLenMask;
223d09f6 1888 const wxChar *pEndMask = wxStrpbrk(pszMask, wxT("*?"));
097c080b
VZ
1889
1890 if ( pEndMask != NULL ) {
1891 // we have to match the string between two metachars
1892 uiLenMask = pEndMask - pszMask;
1893 }
1894 else {
1895 // we have to match the remainder of the string
2bb67b80 1896 uiLenMask = wxStrlen(pszMask);
097c080b
VZ
1897 }
1898
1899 wxString strToMatch(pszMask, uiLenMask);
2bb67b80 1900 const wxChar* pMatch = wxStrstr(pszTxt, strToMatch);
097c080b 1901 if ( pMatch == NULL )
d775fa82 1902 return false;
097c080b
VZ
1903
1904 // -1 to compensate "++" in the loop
1905 pszTxt = pMatch + uiLenMask - 1;
1906 pszMask += uiLenMask - 1;
1907 }
1908 break;
1909
1910 default:
1911 if ( *pszMask != *pszTxt )
d775fa82 1912 return false;
097c080b
VZ
1913 break;
1914 }
1915 }
1916
1917 // match only if nothing left
9a4232dc 1918 if ( *pszTxt == wxT('\0') )
d775fa82 1919 return true;
9a4232dc
VZ
1920
1921 // if we failed to match, backtrack if we can
1922 if ( pszLastStarInText ) {
1923 pszTxt = pszLastStarInText + 1;
1924 pszMask = pszLastStarInMask;
1925
1926 pszLastStarInText = NULL;
1927
1928 // don't bother resetting pszLastStarInMask, it's unnecessary
1929
1930 goto match;
1931 }
1932
d775fa82 1933 return false;
706c2ac9 1934#endif // wxUSE_REGEX/!wxUSE_REGEX
097c080b
VZ
1935}
1936
1fc5dd6f 1937// Count the number of chars
c9f78968 1938int wxString::Freq(wxUniChar ch) const
1fc5dd6f
JS
1939{
1940 int count = 0;
8f93a29f 1941 for ( const_iterator i = begin(); i != end(); ++i )
1fc5dd6f 1942 {
8f93a29f 1943 if ( *i == ch )
1fc5dd6f
JS
1944 count ++;
1945 }
1946 return count;
1947}
1948
03ab016d
JS
1949// convert to upper case, return the copy of the string
1950wxString wxString::Upper() const
1951{ wxString s(*this); return s.MakeUpper(); }
1952
1953// convert to lower case, return the copy of the string
1954wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }
628f87da
VS
1955
1956// ----------------------------------------------------------------------------
1957// wxUTF8StringBuffer
1958// ----------------------------------------------------------------------------
1959
7d46f92b 1960#if wxUSE_UNICODE_WCHAR
628f87da
VS
1961wxUTF8StringBuffer::~wxUTF8StringBuffer()
1962{
1963 wxMBConvStrictUTF8 conv;
1964 size_t wlen = conv.ToWChar(NULL, 0, m_buf);
1965 wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
1966
1967 wxStringInternalBuffer wbuf(m_str, wlen);
1968 conv.ToWChar(wbuf, wlen, m_buf);
1969}
1970
1971wxUTF8StringBufferLength::~wxUTF8StringBufferLength()
1972{
1973 wxCHECK_RET(m_lenSet, "length not set");
1974
1975 wxMBConvStrictUTF8 conv;
1976 size_t wlen = conv.ToWChar(NULL, 0, m_buf, m_len);
1977 wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
1978
1979 wxStringInternalBufferLength wbuf(m_str, wlen);
1980 conv.ToWChar(wbuf, wlen, m_buf, m_len);
1981 wbuf.SetLength(wlen);
1982}
7d46f92b 1983#endif // wxUSE_UNICODE_WCHAR