]> git.saurik.com Git - wxWidgets.git/blame - src/common/string.cpp
implement GetBestSize() (patch 1386199)
[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 * About ref counting:
15 * 1) all empty strings use g_strEmpty, nRefs = -1 (set in Init())
16 * 2) AllocBuffer() sets nRefs to 1, Lock() increments it by one
17 * 3) Unlock() decrements nRefs and frees memory if it goes to 0
18 */
19
20// ===========================================================================
21// headers, declarations, constants
22// ===========================================================================
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
8898456d 28 #pragma hdrstop
c801d85f
KB
29#endif
30
31#ifndef WX_PRECOMP
8898456d 32 #include "wx/string.h"
6b769f3d 33#endif
c801d85f
KB
34
35#include <ctype.h>
92df97b8
WS
36
37#ifndef __WXWINCE__
38 #include <errno.h>
39#endif
40
c801d85f
KB
41#include <string.h>
42#include <stdlib.h>
9a08c20e 43
ce3ed50d 44#ifdef __SALFORDC__
8898456d 45 #include <clib.h>
ce3ed50d
JS
46#endif
47
8f93a29f
VS
48
49// string handling functions used by wxString:
50#if wxUSE_UNICODE_UTF8
51 #define wxStringMemcpy memcpy
52 #define wxStringMemcmp memcmp
53 #define wxStringMemchr memchr
54 #define wxStringStrlen strlen
55#else
56 #define wxStringMemcpy wxTmemcpy
57 #define wxStringMemcmp wxTmemcmp
a7ea63e2
VS
58 #define wxStringMemchr wxTmemchr
59 #define wxStringStrlen wxStrlen
60#endif
8f93a29f 61
e87b7833 62
a7ea63e2
VS
63// ---------------------------------------------------------------------------
64// static class variables definition
65// ---------------------------------------------------------------------------
e87b7833 66
a7ea63e2
VS
67//According to STL _must_ be a -1 size_t
68const size_t wxString::npos = (size_t) -1;
8f93a29f 69
a7ea63e2
VS
70// ----------------------------------------------------------------------------
71// global functions
72// ----------------------------------------------------------------------------
e87b7833 73
a7ea63e2 74#if wxUSE_STD_IOSTREAM
8f93a29f 75
a7ea63e2 76#include <iostream>
8f93a29f 77
a7ea63e2
VS
78wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
79{
80 return os << str.c_str();
e87b7833
MB
81}
82
a7ea63e2 83wxSTD ostream& operator<<(wxSTD ostream& os, const wxCStrData& str)
8f93a29f 84{
a7ea63e2
VS
85#if wxUSE_UNICODE && !defined(__BORLANDC__)
86 return os << str.AsWChar();
87#else
88 return os << str.AsChar();
89#endif
8f93a29f
VS
90}
91
a7ea63e2 92#endif // wxUSE_STD_IOSTREAM
e87b7833
MB
93
94// ===========================================================================
95// wxString class core
96// ===========================================================================
97
06386448
RN
98// ---------------------------------------------------------------------------
99// construction and conversion
e87b7833
MB
100// ---------------------------------------------------------------------------
101
8f93a29f
VS
102#if wxUSE_UNICODE
103/* static */
104wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
105 const wxMBConv& conv)
106{
107 // anything to do?
108 if ( !psz || nLength == 0 )
109 return SubstrBufFromMB();
110
111 if ( nLength == npos )
112 nLength = wxNO_LEN;
113
114 size_t wcLen;
115 wxWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
116 if ( !wcLen )
117 return SubstrBufFromMB();
118 else
119 return SubstrBufFromMB(wcBuf, wcLen);
120}
121#else
122/* static */
123wxString::SubstrBufFromWC wxString::ConvertStr(const wchar_t *pwz, size_t nLength,
124 const wxMBConv& conv)
125{
126 // anything to do?
127 if ( !pwz || nLength == 0 )
128 return SubstrBufFromWC();
129
130 if ( nLength == npos )
131 nLength = wxNO_LEN;
132
133 size_t mbLen;
134 wxCharBuffer mbBuf(conv.cWC2MB(pwz, nLength, &mbLen));
135 if ( !mbLen )
136 return SubstrBufFromWC();
137 else
138 return SubstrBufFromWC(mbBuf, mbLen);
139}
140#endif
141
142
e87b7833
MB
143#if wxUSE_UNICODE
144
145// from multibyte string
830f8f11 146wxString::wxString(const char *psz, const wxMBConv& conv, size_t nLength)
e87b7833 147{
8f93a29f
VS
148 // FIXME-UTF8: this will need changes
149
e87b7833 150 // anything to do?
eec47cc6 151 if ( psz && nLength != 0 )
e87b7833 152 {
eec47cc6
VZ
153 if ( nLength == npos )
154 {
467e0479 155 nLength = wxNO_LEN;
eec47cc6
VZ
156 }
157
158 size_t nLenWide;
159 wxWCharBuffer wbuf = conv.cMB2WC(psz, nLength, &nLenWide);
e4e3bbb4 160
eec47cc6
VZ
161 if ( nLenWide )
162 assign(wbuf, nLenWide);
e87b7833 163 }
7663d0d4 164}
265d5cce 165
8f93a29f
VS
166wxString::wxString(const char *psz, size_t nLength)
167{
168 assign(psz, nLength);
169}
170
06386448 171//Convert wxString in Unicode mode to a multi-byte string
830f8f11 172const wxCharBuffer wxString::mb_str(const wxMBConv& conv) const
265d5cce 173{
eec47cc6 174 return conv.cWC2MB(c_str(), length() + 1 /* size, not length */, NULL);
e87b7833
MB
175}
176
177#else // ANSI
178
179#if wxUSE_WCHAR_T
eec47cc6 180
e87b7833 181// from wide string
830f8f11 182wxString::wxString(const wchar_t *pwz, const wxMBConv& conv, size_t nLength)
e87b7833 183{
8f93a29f
VS
184 // FIXME-UTF8: this will need changes
185
e87b7833 186 // anything to do?
eec47cc6 187 if ( pwz && nLength != 0 )
e87b7833 188 {
eec47cc6
VZ
189 if ( nLength == npos )
190 {
467e0479 191 nLength = wxNO_LEN;
eec47cc6
VZ
192 }
193
194 size_t nLenMB;
195 wxCharBuffer buf = conv.cWC2MB(pwz, nLength, &nLenMB);
e4e3bbb4 196
eec47cc6
VZ
197 if ( nLenMB )
198 assign(buf, nLenMB);
e87b7833 199 }
8f93a29f
VS
200
201}
202
203wxString::wxString(const wchar_t *pwz, size_t nLength)
204{
205 assign(pwz, nLength);
e87b7833 206}
265d5cce 207
7663d0d4 208//Converts this string to a wide character string if unicode
06386448 209//mode is not enabled and wxUSE_WCHAR_T is enabled
830f8f11 210const wxWCharBuffer wxString::wc_str(const wxMBConv& conv) const
265d5cce 211{
eec47cc6 212 return conv.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL);
265d5cce 213}
7663d0d4 214
e87b7833
MB
215#endif // wxUSE_WCHAR_T
216
217#endif // Unicode/ANSI
218
219// shrink to minimal size (releasing extra memory)
220bool wxString::Shrink()
221{
222 wxString tmp(begin(), end());
223 swap(tmp);
224 return tmp.length() == length();
225}
226
d8a4b666 227// deprecated compatibility code:
a7ea63e2 228#if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
d8a4b666
VS
229wxChar *wxString::GetWriteBuf(size_t nLen)
230{
231 return DoGetWriteBuf(nLen);
232}
233
234void wxString::UngetWriteBuf()
235{
236 DoUngetWriteBuf();
237}
238
239void wxString::UngetWriteBuf(size_t nLen)
240{
241 DoUngetWriteBuf(nLen);
242}
a7ea63e2 243#endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
e87b7833 244
d8a4b666 245
e87b7833
MB
246// ---------------------------------------------------------------------------
247// data access
248// ---------------------------------------------------------------------------
249
250// all functions are inline in string.h
251
252// ---------------------------------------------------------------------------
253// assignment operators
254// ---------------------------------------------------------------------------
255
256#if !wxUSE_UNICODE
257
258// same as 'signed char' variant
259wxString& wxString::operator=(const unsigned char* psz)
260{
261 *this = (const char *)psz;
262 return *this;
263}
264
265#if wxUSE_WCHAR_T
266wxString& wxString::operator=(const wchar_t *pwz)
267{
268 wxString str(pwz);
269 swap(str);
270 return *this;
c801d85f 271}
e87b7833
MB
272#endif
273
274#endif
c801d85f
KB
275
276/*
c801d85f
KB
277 * concatenation functions come in 5 flavours:
278 * string + string
279 * char + string and string + char
280 * C str + string and string + C str
281 */
282
b1801e0e 283wxString operator+(const wxString& str1, const wxString& str2)
c801d85f 284{
992527a5 285#if !wxUSE_STL_BASED_WXSTRING
8f93a29f
VS
286 wxASSERT( str1.IsValid() );
287 wxASSERT( str2.IsValid() );
e87b7833 288#endif
097c080b 289
3458e408
WS
290 wxString s = str1;
291 s += str2;
3168a13f 292
3458e408 293 return s;
c801d85f
KB
294}
295
c9f78968 296wxString operator+(const wxString& str, wxUniChar ch)
c801d85f 297{
992527a5 298#if !wxUSE_STL_BASED_WXSTRING
8f93a29f 299 wxASSERT( str.IsValid() );
e87b7833 300#endif
3168a13f 301
3458e408
WS
302 wxString s = str;
303 s += ch;
097c080b 304
3458e408 305 return s;
c801d85f
KB
306}
307
c9f78968 308wxString operator+(wxUniChar ch, const wxString& str)
c801d85f 309{
992527a5 310#if !wxUSE_STL_BASED_WXSTRING
8f93a29f 311 wxASSERT( str.IsValid() );
e87b7833 312#endif
097c080b 313
3458e408
WS
314 wxString s = ch;
315 s += str;
3168a13f 316
3458e408 317 return s;
c801d85f
KB
318}
319
8f93a29f 320wxString operator+(const wxString& str, const char *psz)
c801d85f 321{
992527a5 322#if !wxUSE_STL_BASED_WXSTRING
8f93a29f 323 wxASSERT( str.IsValid() );
e87b7833 324#endif
097c080b 325
3458e408 326 wxString s;
8f93a29f 327 if ( !s.Alloc(strlen(psz) + str.length()) ) {
3458e408
WS
328 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
329 }
330 s += str;
331 s += psz;
3168a13f 332
3458e408 333 return s;
c801d85f
KB
334}
335
8f93a29f 336wxString operator+(const wxString& str, const wchar_t *pwz)
c801d85f 337{
992527a5 338#if !wxUSE_STL_BASED_WXSTRING
8f93a29f
VS
339 wxASSERT( str.IsValid() );
340#endif
341
342 wxString s;
343 if ( !s.Alloc(wxWcslen(pwz) + str.length()) ) {
344 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
345 }
346 s += str;
347 s += pwz;
348
349 return s;
350}
351
352wxString operator+(const char *psz, const wxString& str)
353{
a7ea63e2
VS
354#if !wxUSE_STL_BASED_WXSTRING
355 wxASSERT( str.IsValid() );
356#endif
357
358 wxString s;
359 if ( !s.Alloc(strlen(psz) + str.length()) ) {
360 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
361 }
362 s = psz;
363 s += str;
364
365 return s;
366}
367
368wxString operator+(const wchar_t *pwz, const wxString& str)
369{
370#if !wxUSE_STL_BASED_WXSTRING
371 wxASSERT( str.IsValid() );
372#endif
373
374 wxString s;
375 if ( !s.Alloc(wxWcslen(pwz) + str.length()) ) {
376 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
377 }
378 s = pwz;
379 s += str;
380
381 return s;
382}
383
384// ---------------------------------------------------------------------------
385// string comparison
386// ---------------------------------------------------------------------------
387
388#ifdef HAVE_STD_STRING_COMPARE
389
390// NB: Comparison code (both if HAVE_STD_STRING_COMPARE and if not) works with
391// UTF-8 encoded strings too, thanks to UTF-8's design which allows us to
392// sort strings in characters code point order by sorting the byte sequence
393// in byte values order (i.e. what strcmp() and memcmp() do).
394
395int wxString::compare(const wxString& str) const
396{
397 return m_impl.compare(str.m_impl);
398}
399
400int wxString::compare(size_t nStart, size_t nLen,
401 const wxString& str) const
402{
403 size_t pos, len;
404 PosLenToImpl(nStart, nLen, &pos, &len);
405 return m_impl.compare(pos, len, str.m_impl);
406}
407
408int wxString::compare(size_t nStart, size_t nLen,
409 const wxString& str,
410 size_t nStart2, size_t nLen2) const
411{
412 size_t pos, len;
413 PosLenToImpl(nStart, nLen, &pos, &len);
414
415 size_t pos2, len2;
416 str.PosLenToImpl(nStart2, nLen2, &pos2, &len2);
417
418 return m_impl.compare(pos, len, str.m_impl, pos2, len2);
419}
420
421int wxString::compare(const char* sz) const
422{
423 return m_impl.compare(ImplStr(sz));
424}
425
426int wxString::compare(const wchar_t* sz) const
427{
428 return m_impl.compare(ImplStr(sz));
429}
430
431int wxString::compare(size_t nStart, size_t nLen,
432 const char* sz, size_t nCount) const
433{
434 size_t pos, len;
435 PosLenToImpl(nStart, nLen, &pos, &len);
436
437 SubstrBufFromMB str(ImplStr(sz, nCount));
438
439 return m_impl.compare(pos, len, str.data, str.len);
440}
441
442int wxString::compare(size_t nStart, size_t nLen,
443 const wchar_t* sz, size_t nCount) const
444{
445 size_t pos, len;
446 PosLenToImpl(nStart, nLen, &pos, &len);
447
448 SubstrBufFromWC str(ImplStr(sz, nCount));
449
450 return m_impl.compare(pos, len, str.data, str.len);
451}
452
453#else // !HAVE_STD_STRING_COMPARE
454
455static inline int wxDoCmp(const wxStringCharType* s1, size_t l1,
456 const wxStringCharType* s2, size_t l2)
457{
458 if( l1 == l2 )
459 return wxStringMemcmp(s1, s2, l1);
460 else if( l1 < l2 )
461 {
462 int ret = wxStringMemcmp(s1, s2, l1);
463 return ret == 0 ? -1 : ret;
464 }
465 else
466 {
467 int ret = wxStringMemcmp(s1, s2, l2);
468 return ret == 0 ? +1 : ret;
469 }
470}
471
472int wxString::compare(const wxString& str) const
473{
474 return ::wxDoCmp(m_impl.data(), m_impl.length(),
475 str.m_impl.data(), str.m_impl.length());
476}
477
478int wxString::compare(size_t nStart, size_t nLen,
479 const wxString& str) const
480{
481 wxASSERT(nStart <= length());
482 size_type strLen = length() - nStart;
483 nLen = strLen < nLen ? strLen : nLen;
484
485 size_t pos, len;
486 PosLenToImpl(nStart, nLen, &pos, &len);
487
488 return ::wxDoCmp(m_impl.data() + pos, len,
489 str.m_impl.data(), str.m_impl.length());
490}
491
492int wxString::compare(size_t nStart, size_t nLen,
493 const wxString& str,
494 size_t nStart2, size_t nLen2) const
495{
496 wxASSERT(nStart <= length());
497 wxASSERT(nStart2 <= str.length());
498 size_type strLen = length() - nStart,
499 strLen2 = str.length() - nStart2;
500 nLen = strLen < nLen ? strLen : nLen;
501 nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
502
503 size_t pos, len;
504 PosLenToImpl(nStart, nLen, &pos, &len);
505 size_t pos2, len2;
506 str.PosLenToImpl(nStart2, nLen2, &pos2, &len2);
507
508 return ::wxDoCmp(m_impl.data() + pos, len,
509 str.m_impl.data() + pos2, len2);
510}
511
512int wxString::compare(const char* sz) const
513{
514 SubstrBufFromMB str(ImplStr(sz, npos));
515 if ( str.len == npos )
516 str.len = wxStringStrlen(str.data);
517 return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len);
518}
519
520int wxString::compare(const wchar_t* sz) const
521{
522 SubstrBufFromWC str(ImplStr(sz, npos));
523 if ( str.len == npos )
524 str.len = wxStringStrlen(str.data);
525 return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len);
526}
527
528int wxString::compare(size_t nStart, size_t nLen,
529 const char* sz, size_t nCount) const
530{
531 wxASSERT(nStart <= length());
532 size_type strLen = length() - nStart;
533 nLen = strLen < nLen ? strLen : nLen;
097c080b 534
a7ea63e2
VS
535 size_t pos, len;
536 PosLenToImpl(nStart, nLen, &pos, &len);
3168a13f 537
a7ea63e2
VS
538 SubstrBufFromMB str(ImplStr(sz, nCount));
539 if ( str.len == npos )
540 str.len = wxStringStrlen(str.data);
541
542 return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len);
c801d85f
KB
543}
544
a7ea63e2
VS
545int wxString::compare(size_t nStart, size_t nLen,
546 const wchar_t* sz, size_t nCount) const
8f93a29f 547{
a7ea63e2
VS
548 wxASSERT(nStart <= length());
549 size_type strLen = length() - nStart;
550 nLen = strLen < nLen ? strLen : nLen;
8f93a29f 551
a7ea63e2
VS
552 size_t pos, len;
553 PosLenToImpl(nStart, nLen, &pos, &len);
8f93a29f 554
a7ea63e2
VS
555 SubstrBufFromWC str(ImplStr(sz, nCount));
556 if ( str.len == npos )
557 str.len = wxStringStrlen(str.data);
558
559 return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len);
8f93a29f
VS
560}
561
a7ea63e2
VS
562#endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE
563
564
8f93a29f
VS
565// ---------------------------------------------------------------------------
566// find_{first,last}_[not]_of functions
567// ---------------------------------------------------------------------------
568
569#if !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
c801d85f 570
8f93a29f
VS
571// NB: All these functions are implemented with the argument being wxChar*,
572// i.e. widechar string in any Unicode build, even though native string
573// representation is char* in the UTF-8 build. This is because we couldn't
574// use memchr() to determine if a character is in a set encoded as UTF-8.
575
576size_t wxString::find_first_of(const wxChar* sz, size_t nStart) const
dcb68102 577{
8f93a29f 578 return find_first_of(sz, nStart, wxStrlen(sz));
dcb68102
RN
579}
580
8f93a29f 581size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart) const
dcb68102 582{
8f93a29f 583 return find_first_not_of(sz, nStart, wxStrlen(sz));
dcb68102
RN
584}
585
8f93a29f 586size_t wxString::find_first_of(const wxChar* sz, size_t nStart, size_t n) const
dcb68102 587{
8f93a29f 588 wxASSERT_MSG( nStart <= length(), _T("invalid index") );
dcb68102 589
8f93a29f
VS
590 size_t idx = nStart;
591 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
dcb68102 592 {
8f93a29f
VS
593 if ( wxTmemchr(sz, *i, n) )
594 return idx;
dcb68102 595 }
8f93a29f
VS
596
597 return npos;
598}
599
600size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart, size_t n) const
601{
602 wxASSERT_MSG( nStart <= length(), _T("invalid index") );
603
604 size_t idx = nStart;
605 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
dcb68102 606 {
8f93a29f
VS
607 if ( !wxTmemchr(sz, *i, n) )
608 return idx;
609 }
610
611 return npos;
612}
613
614
615size_t wxString::find_last_of(const wxChar* sz, size_t nStart) const
616{
617 return find_last_of(sz, nStart, wxStrlen(sz));
618}
619
620size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart) const
621{
622 return find_last_not_of(sz, nStart, wxStrlen(sz));
623}
624
625size_t wxString::find_last_of(const wxChar* sz, size_t nStart, size_t n) const
626{
627 size_t len = length();
628
629 if ( nStart == npos )
630 {
631 nStart = len - 1;
dcb68102 632 }
2c09fb3b 633 else
dcb68102 634 {
8f93a29f 635 wxASSERT_MSG( nStart <= len, _T("invalid index") );
dcb68102 636 }
8f93a29f
VS
637
638 size_t idx = nStart;
639 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
640 i != rend(); --idx, ++i )
641 {
642 if ( wxTmemchr(sz, *i, n) )
643 return idx;
644 }
645
646 return npos;
dcb68102
RN
647}
648
8f93a29f 649size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart, size_t n) const
dcb68102 650{
8f93a29f
VS
651 size_t len = length();
652
653 if ( nStart == npos )
654 {
655 nStart = len - 1;
656 }
657 else
658 {
659 wxASSERT_MSG( nStart <= len, _T("invalid index") );
660 }
661
662 size_t idx = nStart;
663 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
664 i != rend(); --idx, ++i )
665 {
666 if ( !wxTmemchr(sz, *i, n) )
667 return idx;
668 }
669
670 return npos;
dcb68102
RN
671}
672
8f93a29f 673size_t wxString::find_first_not_of(wxUniChar ch, size_t nStart) const
dcb68102 674{
8f93a29f
VS
675 wxASSERT_MSG( nStart <= length(), _T("invalid index") );
676
677 size_t idx = nStart;
678 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
679 {
680 if ( *i != ch )
681 return idx;
682 }
683
684 return npos;
685}
686
687size_t wxString::find_last_not_of(wxUniChar ch, size_t nStart) const
688{
689 size_t len = length();
690
691 if ( nStart == npos )
692 {
693 nStart = len - 1;
694 }
695 else
696 {
697 wxASSERT_MSG( nStart <= len, _T("invalid index") );
698 }
699
700 size_t idx = nStart;
701 for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
702 i != rend(); --idx, ++i )
703 {
704 if ( *i != ch )
705 return idx;
706 }
707
708 return npos;
709}
710
711// the functions above were implemented for wchar_t* arguments in Unicode
712// build and char* in ANSI build; below are implementations for the other
713// version:
714#if wxUSE_UNICODE
715 #define wxOtherCharType char
716 #define STRCONV (const wxChar*)wxConvLibc.cMB2WC
717#else
718 #define wxOtherCharType wchar_t
719 #define STRCONV (const wxChar*)wxConvLibc.cWC2MB
720#endif
721
722size_t wxString::find_first_of(const wxOtherCharType* sz, size_t nStart) const
723 { return find_first_of(STRCONV(sz), nStart); }
724
725size_t wxString::find_first_of(const wxOtherCharType* sz, size_t nStart,
726 size_t n) const
727 { return find_first_of(STRCONV(sz, n, NULL), nStart, n); }
728size_t wxString::find_last_of(const wxOtherCharType* sz, size_t nStart) const
729 { return find_last_of(STRCONV(sz), nStart); }
730size_t wxString::find_last_of(const wxOtherCharType* sz, size_t nStart,
731 size_t n) const
732 { return find_last_of(STRCONV(sz, n, NULL), nStart, n); }
733size_t wxString::find_first_not_of(const wxOtherCharType* sz, size_t nStart) const
734 { return find_first_not_of(STRCONV(sz), nStart); }
735size_t wxString::find_first_not_of(const wxOtherCharType* sz, size_t nStart,
736 size_t n) const
737 { return find_first_not_of(STRCONV(sz, n, NULL), nStart, n); }
738size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart) const
739 { return find_last_not_of(STRCONV(sz), nStart); }
740size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart,
741 size_t n) const
742 { return find_last_not_of(STRCONV(sz, n, NULL), nStart, n); }
743
744#undef wxOtherCharType
745#undef STRCONV
746
747#endif // !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
748
749// ===========================================================================
750// other common string functions
751// ===========================================================================
752
753int wxString::CmpNoCase(const wxString& s) const
754{
755 // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
756
757 size_t idx = 0;
758 const_iterator i1 = begin();
759 const_iterator end1 = end();
760 const_iterator i2 = s.begin();
761 const_iterator end2 = s.end();
762
763 for ( ; i1 != end1 && i2 != end2; ++idx, ++i1, ++i2 )
764 {
765 wxUniChar lower1 = (wxChar)wxTolower(*i1);
766 wxUniChar lower2 = (wxChar)wxTolower(*i2);
767 if ( lower1 != lower2 )
768 return lower1 < lower2 ? -1 : 1;
769 }
770
771 size_t len1 = length();
772 size_t len2 = s.length();
dcb68102 773
8f93a29f
VS
774 if ( len1 < len2 )
775 return -1;
776 else if ( len1 > len2 )
777 return 1;
778 return 0;
dcb68102
RN
779}
780
781
b1ac3b56 782#if wxUSE_UNICODE
e015c2a3 783
cf6bedce
SC
784#ifdef __MWERKS__
785#ifndef __SCHAR_MAX__
786#define __SCHAR_MAX__ 127
787#endif
788#endif
789
e015c2a3 790wxString wxString::FromAscii(const char *ascii)
b1ac3b56
RR
791{
792 if (!ascii)
793 return wxEmptyString;
e015c2a3 794
b1ac3b56
RR
795 size_t len = strlen( ascii );
796 wxString res;
e015c2a3
VZ
797
798 if ( len )
799 {
800 wxStringBuffer buf(res, len);
801
802 wchar_t *dest = buf;
803
804 for ( ;; )
805 {
806 if ( (*dest++ = (wchar_t)(unsigned char)*ascii++) == L'\0' )
807 break;
808 }
809 }
810
b1ac3b56
RR
811 return res;
812}
813
2b5f62a0
VZ
814wxString wxString::FromAscii(const char ascii)
815{
816 // What do we do with '\0' ?
817
818 wxString res;
819 res += (wchar_t)(unsigned char) ascii;
8760bc65 820
2b5f62a0
VZ
821 return res;
822}
823
b1ac3b56
RR
824const wxCharBuffer wxString::ToAscii() const
825{
e015c2a3
VZ
826 // this will allocate enough space for the terminating NUL too
827 wxCharBuffer buffer(length());
b1ac3b56 828
be7eecf8 829
6e394fc6 830 char *dest = buffer.data();
e015c2a3
VZ
831
832 const wchar_t *pwc = c_str();
833 for ( ;; )
b1ac3b56 834 {
6e394fc6 835 *dest++ = (char)(*pwc > SCHAR_MAX ? wxT('_') : *pwc);
e015c2a3
VZ
836
837 // the output string can't have embedded NULs anyhow, so we can safely
838 // stop at first of them even if we do have any
839 if ( !*pwc++ )
840 break;
b1ac3b56 841 }
e015c2a3 842
b1ac3b56
RR
843 return buffer;
844}
e015c2a3
VZ
845
846#endif // Unicode
b1ac3b56 847
c801d85f 848// extract string of length nCount starting at nFirst
c801d85f
KB
849wxString wxString::Mid(size_t nFirst, size_t nCount) const
850{
73f507f5 851 size_t nLen = length();
30d9011f 852
73f507f5
WS
853 // default value of nCount is npos and means "till the end"
854 if ( nCount == npos )
855 {
856 nCount = nLen - nFirst;
857 }
30d9011f 858
73f507f5
WS
859 // out-of-bounds requests return sensible things
860 if ( nFirst + nCount > nLen )
861 {
862 nCount = nLen - nFirst;
863 }
c801d85f 864
73f507f5
WS
865 if ( nFirst > nLen )
866 {
867 // AllocCopy() will return empty string
868 return wxEmptyString;
869 }
c801d85f 870
73f507f5
WS
871 wxString dest(*this, nFirst, nCount);
872 if ( dest.length() != nCount )
873 {
874 wxFAIL_MSG( _T("out of memory in wxString::Mid") );
875 }
30d9011f 876
73f507f5 877 return dest;
c801d85f
KB
878}
879
e87b7833 880// check that the string starts with prefix and return the rest of the string
d775fa82 881// in the provided pointer if it is not NULL, otherwise return false
f6bcfd97
BP
882bool wxString::StartsWith(const wxChar *prefix, wxString *rest) const
883{
884 wxASSERT_MSG( prefix, _T("invalid parameter in wxString::StartsWith") );
885
886 // first check if the beginning of the string matches the prefix: note
887 // that we don't have to check that we don't run out of this string as
888 // when we reach the terminating NUL, either prefix string ends too (and
889 // then it's ok) or we break out of the loop because there is no match
890 const wxChar *p = c_str();
891 while ( *prefix )
892 {
893 if ( *prefix++ != *p++ )
894 {
895 // no match
d775fa82 896 return false;
f6bcfd97
BP
897 }
898 }
899
900 if ( rest )
901 {
902 // put the rest of the string into provided pointer
903 *rest = p;
904 }
905
d775fa82 906 return true;
f6bcfd97
BP
907}
908
3affcd07
VZ
909
910// check that the string ends with suffix and return the rest of it in the
911// provided pointer if it is not NULL, otherwise return false
912bool wxString::EndsWith(const wxChar *suffix, wxString *rest) const
913{
914 wxASSERT_MSG( suffix, _T("invalid parameter in wxString::EndssWith") );
915
916 int start = length() - wxStrlen(suffix);
c9f78968 917 if ( start < 0 || wxStrcmp(wx_str() + start, suffix) != 0 )
3affcd07
VZ
918 return false;
919
920 if ( rest )
921 {
922 // put the rest of the string into provided pointer
923 rest->assign(*this, 0, start);
924 }
925
926 return true;
927}
928
929
c801d85f
KB
930// extract nCount last (rightmost) characters
931wxString wxString::Right(size_t nCount) const
932{
e87b7833
MB
933 if ( nCount > length() )
934 nCount = length();
c801d85f 935
e87b7833
MB
936 wxString dest(*this, length() - nCount, nCount);
937 if ( dest.length() != nCount ) {
b1801e0e
GD
938 wxFAIL_MSG( _T("out of memory in wxString::Right") );
939 }
c801d85f
KB
940 return dest;
941}
942
943// get all characters after the last occurence of ch
944// (returns the whole string if ch not found)
c9f78968 945wxString wxString::AfterLast(wxUniChar ch) const
c801d85f
KB
946{
947 wxString str;
d775fa82 948 int iPos = Find(ch, true);
3c67202d 949 if ( iPos == wxNOT_FOUND )
c801d85f
KB
950 str = *this;
951 else
c9f78968 952 str = wx_str() + iPos + 1;
c801d85f
KB
953
954 return str;
955}
956
957// extract nCount first (leftmost) characters
958wxString wxString::Left(size_t nCount) const
959{
e87b7833
MB
960 if ( nCount > length() )
961 nCount = length();
c801d85f 962
e87b7833
MB
963 wxString dest(*this, 0, nCount);
964 if ( dest.length() != nCount ) {
b1801e0e
GD
965 wxFAIL_MSG( _T("out of memory in wxString::Left") );
966 }
c801d85f
KB
967 return dest;
968}
969
970// get all characters before the first occurence of ch
971// (returns the whole string if ch not found)
c9f78968 972wxString wxString::BeforeFirst(wxUniChar ch) const
c801d85f 973{
e87b7833
MB
974 int iPos = Find(ch);
975 if ( iPos == wxNOT_FOUND ) iPos = length();
976 return wxString(*this, 0, iPos);
c801d85f
KB
977}
978
979/// get all characters before the last occurence of ch
980/// (returns empty string if ch not found)
c9f78968 981wxString wxString::BeforeLast(wxUniChar ch) const
c801d85f
KB
982{
983 wxString str;
d775fa82 984 int iPos = Find(ch, true);
3c67202d 985 if ( iPos != wxNOT_FOUND && iPos != 0 )
d1c9bbf6 986 str = wxString(c_str(), iPos);
c801d85f
KB
987
988 return str;
989}
990
991/// get all characters after the first occurence of ch
992/// (returns empty string if ch not found)
c9f78968 993wxString wxString::AfterFirst(wxUniChar ch) const
c801d85f
KB
994{
995 wxString str;
996 int iPos = Find(ch);
3c67202d 997 if ( iPos != wxNOT_FOUND )
c9f78968 998 str = wx_str() + iPos + 1;
c801d85f
KB
999
1000 return str;
1001}
1002
1003// replace first (or all) occurences of some substring with another one
ad5bb7d6 1004size_t wxString::Replace(const wxChar *szOld,
510bb748 1005 const wxChar *szNew, bool bReplaceAll)
c801d85f 1006{
a8f1f1b2
VZ
1007 // if we tried to replace an empty string we'd enter an infinite loop below
1008 wxCHECK_MSG( szOld && *szOld && szNew, 0,
1009 _T("wxString::Replace(): invalid parameter") );
1010
510bb748 1011 size_t uiCount = 0; // count of replacements made
c801d85f 1012
510bb748
RN
1013 size_t uiOldLen = wxStrlen(szOld);
1014 size_t uiNewLen = wxStrlen(szNew);
c801d85f 1015
510bb748 1016 size_t dwPos = 0;
c801d85f 1017
ad5bb7d6 1018 while ( this->c_str()[dwPos] != wxT('\0') )
510bb748
RN
1019 {
1020 //DO NOT USE STRSTR HERE
1021 //this string can contain embedded null characters,
1022 //so strstr will function incorrectly
1023 dwPos = find(szOld, dwPos);
ad5bb7d6 1024 if ( dwPos == npos )
510bb748 1025 break; // exit the loop
ad5bb7d6 1026 else
510bb748
RN
1027 {
1028 //replace this occurance of the old string with the new one
1029 replace(dwPos, uiOldLen, szNew, uiNewLen);
1030
2df0258e
RN
1031 //move up pos past the string that was replaced
1032 dwPos += uiNewLen;
510bb748
RN
1033
1034 //increase replace count
1035 ++uiCount;
ad5bb7d6 1036
510bb748 1037 // stop now?
ad5bb7d6 1038 if ( !bReplaceAll )
510bb748
RN
1039 break; // exit the loop
1040 }
c801d85f 1041 }
c801d85f 1042
510bb748 1043 return uiCount;
c801d85f
KB
1044}
1045
1046bool wxString::IsAscii() const
1047{
2bb67b80 1048 const wxChar *s = (const wxChar*) *this;
c801d85f 1049 while(*s){
d775fa82 1050 if(!isascii(*s)) return(false);
c801d85f
KB
1051 s++;
1052 }
d775fa82 1053 return(true);
c801d85f 1054}
dd1eaa89 1055
c801d85f
KB
1056bool wxString::IsWord() const
1057{
2bb67b80 1058 const wxChar *s = (const wxChar*) *this;
c801d85f 1059 while(*s){
d775fa82 1060 if(!wxIsalpha(*s)) return(false);
c801d85f
KB
1061 s++;
1062 }
d775fa82 1063 return(true);
c801d85f 1064}
dd1eaa89 1065
c801d85f
KB
1066bool wxString::IsNumber() const
1067{
2bb67b80 1068 const wxChar *s = (const wxChar*) *this;
2f74ed28 1069 if (wxStrlen(s))
930357bd 1070 if ((s[0] == wxT('-')) || (s[0] == wxT('+'))) s++;
c801d85f 1071 while(*s){
d775fa82 1072 if(!wxIsdigit(*s)) return(false);
c801d85f
KB
1073 s++;
1074 }
d775fa82 1075 return(true);
c801d85f
KB
1076}
1077
c801d85f
KB
1078wxString wxString::Strip(stripType w) const
1079{
1080 wxString s = *this;
d775fa82
WS
1081 if ( w & leading ) s.Trim(false);
1082 if ( w & trailing ) s.Trim(true);
c801d85f
KB
1083 return s;
1084}
1085
c801d85f
KB
1086// ---------------------------------------------------------------------------
1087// case conversion
1088// ---------------------------------------------------------------------------
1089
1090wxString& wxString::MakeUpper()
1091{
e87b7833
MB
1092 for ( iterator it = begin(), en = end(); it != en; ++it )
1093 *it = (wxChar)wxToupper(*it);
c801d85f
KB
1094
1095 return *this;
1096}
1097
1098wxString& wxString::MakeLower()
1099{
e87b7833
MB
1100 for ( iterator it = begin(), en = end(); it != en; ++it )
1101 *it = (wxChar)wxTolower(*it);
c801d85f
KB
1102
1103 return *this;
1104}
1105
1106// ---------------------------------------------------------------------------
1107// trimming and padding
1108// ---------------------------------------------------------------------------
1109
d775fa82 1110// some compilers (VC++ 6.0 not to name them) return true for a call to
576c608d
VZ
1111