]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/string.cpp
Fixed compile problem and warning
[wxWidgets.git] / src / common / string.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/string.cpp
3// Purpose: wxString class
4// Author: Vadim Zeitlin, Ryan Norton
5// Modified by:
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// (c) 2004 Ryan Norton <wxprojects@comcast.net>
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13/*
14 * 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__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/string.h"
33#endif
34
35#include <ctype.h>
36
37#ifndef __WXWINCE__
38 #include <errno.h>
39#endif
40
41#include <string.h>
42#include <stdlib.h>
43
44#ifdef __SALFORDC__
45 #include <clib.h>
46#endif
47
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
58 #define wxStringMemchr wxTmemchr
59 #define wxStringStrlen wxStrlen
60#endif
61
62
63// ---------------------------------------------------------------------------
64// static class variables definition
65// ---------------------------------------------------------------------------
66
67//According to STL _must_ be a -1 size_t
68const size_t wxString::npos = (size_t) -1;
69
70// ----------------------------------------------------------------------------
71// global functions
72// ----------------------------------------------------------------------------
73
74#if wxUSE_STD_IOSTREAM
75
76#include <iostream>
77
78wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
79{
80 return os << str.c_str();
81}
82
83wxSTD ostream& operator<<(wxSTD ostream& os, const wxCStrData& str)
84{
85#if wxUSE_UNICODE && !defined(__BORLANDC__)
86 return os << str.AsWChar();
87#else
88 return os << str.AsChar();
89#endif
90}
91
92#endif // wxUSE_STD_IOSTREAM
93
94// ===========================================================================
95// wxString class core
96// ===========================================================================
97
98// ---------------------------------------------------------------------------
99// construction and conversion
100// ---------------------------------------------------------------------------
101
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
143#if wxUSE_UNICODE
144
145// from multibyte string
146wxString::wxString(const char *psz, const wxMBConv& conv, size_t nLength)
147{
148 // FIXME-UTF8: this will need changes
149
150 // anything to do?
151 if ( psz && nLength != 0 )
152 {
153 if ( nLength == npos )
154 {
155 nLength = wxNO_LEN;
156 }
157
158 size_t nLenWide;
159 wxWCharBuffer wbuf = conv.cMB2WC(psz, nLength, &nLenWide);
160
161 if ( nLenWide )
162 assign(wbuf, nLenWide);
163 }
164}
165
166wxString::wxString(const char *psz, size_t nLength)
167{
168 assign(psz, nLength);
169}
170
171//Convert wxString in Unicode mode to a multi-byte string
172const wxCharBuffer wxString::mb_str(const wxMBConv& conv) const
173{
174 return conv.cWC2MB(c_str(), length() + 1 /* size, not length */, NULL);
175}
176
177#else // ANSI
178
179#if wxUSE_WCHAR_T
180
181// from wide string
182wxString::wxString(const wchar_t *pwz, const wxMBConv& conv, size_t nLength)
183{
184 // FIXME-UTF8: this will need changes
185
186 // anything to do?
187 if ( pwz && nLength != 0 )
188 {
189 if ( nLength == npos )
190 {
191 nLength = wxNO_LEN;
192 }
193
194 size_t nLenMB;
195 wxCharBuffer buf = conv.cWC2MB(pwz, nLength, &nLenMB);
196
197 if ( nLenMB )
198 assign(buf, nLenMB);
199 }
200
201}
202
203wxString::wxString(const wchar_t *pwz, size_t nLength)
204{
205 assign(pwz, nLength);
206}
207
208//Converts this string to a wide character string if unicode
209//mode is not enabled and wxUSE_WCHAR_T is enabled
210const wxWCharBuffer wxString::wc_str(const wxMBConv& conv) const
211{
212 return conv.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL);
213}
214
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
227// deprecated compatibility code:
228#if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
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}
243#endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
244
245
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;
271}
272#endif
273
274#endif
275
276/*
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
283wxString operator+(const wxString& str1, const wxString& str2)
284{
285#if !wxUSE_STL_BASED_WXSTRING
286 wxASSERT( str1.IsValid() );
287 wxASSERT( str2.IsValid() );
288#endif
289
290 wxString s = str1;
291 s += str2;
292
293 return s;
294}
295
296wxString operator+(const wxString& str, wxUniChar ch)
297{
298#if !wxUSE_STL_BASED_WXSTRING
299 wxASSERT( str.IsValid() );
300#endif
301
302 wxString s = str;
303 s += ch;
304
305 return s;
306}
307
308wxString operator+(wxUniChar ch, const wxString& str)
309{
310#if !wxUSE_STL_BASED_WXSTRING
311 wxASSERT( str.IsValid() );
312#endif
313
314 wxString s = ch;
315 s += str;
316
317 return s;
318}
319
320wxString operator+(const wxString& str, const char *psz)
321{
322#if !wxUSE_STL_BASED_WXSTRING
323 wxASSERT( str.IsValid() );
324#endif
325
326 wxString s;
327 if ( !s.Alloc(strlen(psz) + str.length()) ) {
328 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
329 }
330 s += str;
331 s += psz;
332
333 return s;
334}
335
336wxString operator+(const wxString& str, const wchar_t *pwz)
337{
338#if !wxUSE_STL_BASED_WXSTRING
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{
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;
534
535 size_t pos, len;
536 PosLenToImpl(nStart, nLen, &pos, &len);
537
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);
543}
544
545int wxString::compare(size_t nStart, size_t nLen,
546 const wchar_t* sz, size_t nCount) const
547{
548 wxASSERT(nStart <= length());
549 size_type strLen = length() - nStart;
550 nLen = strLen < nLen ? strLen : nLen;
551
552 size_t pos, len;
553 PosLenToImpl(nStart, nLen, &pos, &len);
554
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);
560}
561
562#endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE
563
564
565// ---------------------------------------------------------------------------
566// find_{first,last}_[not]_of functions
567// ---------------------------------------------------------------------------
568
569#if !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
570
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
577{
578 return find_first_of(sz, nStart, wxStrlen(sz));
579}
580
581size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart) const
582{
583 return find_first_not_of(sz, nStart, wxStrlen(sz));
584}
585
586size_t wxString::find_first_of(const wxChar* sz, size_t nStart, size_t n) const
587{
588 wxASSERT_MSG( nStart <= length(), _T("invalid index") );
589
590 size_t idx = nStart;
591 for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
592 {
593 if ( wxTmemchr(sz, *i, n) )
594 return idx;
595 }
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 )
606 {
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;
632 }
633 else
634 {
635 wxASSERT_MSG( nStart <= len, _T("invalid index") );
636 }
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;
647}
648
649size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart, size_t n) const
650{
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;
671}
672
673size_t wxString::find_first_not_of(wxUniChar ch, size_t nStart) const
674{
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();
773
774 if ( len1 < len2 )
775 return -1;
776 else if ( len1 > len2 )
777 return 1;
778 return 0;
779}
780
781
782#if wxUSE_UNICODE
783
784#ifdef __MWERKS__
785#ifndef __SCHAR_MAX__
786#define __SCHAR_MAX__ 127
787#endif
788#endif
789
790wxString wxString::FromAscii(const char *ascii)
791{
792 if (!ascii)
793 return wxEmptyString;
794
795 size_t len = strlen( ascii );
796 wxString res;
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
811 return res;
812}
813
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;
820
821 return res;
822}
823
824const wxCharBuffer wxString::ToAscii() const
825{
826 // this will allocate enough space for the terminating NUL too
827 wxCharBuffer buffer(length());
828
829
830 char *dest = buffer.data();
831
832 const wchar_t *pwc = c_str();
833 for ( ;; )
834 {
835 *dest++ = (char)(*pwc > SCHAR_MAX ? wxT('_') : *pwc);
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;
841 }
842
843 return buffer;
844}
845
846#endif // Unicode
847
848// extract string of length nCount starting at nFirst
849wxString wxString::Mid(size_t nFirst, size_t nCount) const
850{
851 size_t nLen = length();
852
853 // default value of nCount is npos and means "till the end"
854 if ( nCount == npos )
855 {
856 nCount = nLen - nFirst;
857 }
858
859 // out-of-bounds requests return sensible things
860 if ( nFirst + nCount > nLen )
861 {
862 nCount = nLen - nFirst;
863 }
864
865 if ( nFirst > nLen )
866 {
867 // AllocCopy() will return empty string
868 return wxEmptyString;
869 }
870
871 wxString dest(*this, nFirst, nCount);
872 if ( dest.length() != nCount )
873 {
874 wxFAIL_MSG( _T("out of memory in wxString::Mid") );
875 }
876
877 return dest;
878}
879
880// check that the string starts with prefix and return the rest of the string
881// in the provided pointer if it is not NULL, otherwise return false
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
896 return false;
897 }
898 }
899
900 if ( rest )
901 {
902 // put the rest of the string into provided pointer
903 *rest = p;
904 }
905
906 return true;
907}
908
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);
917 if ( start < 0 || wxStrcmp(wx_str() + start, suffix) != 0 )
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
930// extract nCount last (rightmost) characters
931wxString wxString::Right(size_t nCount) const
932{
933 if ( nCount > length() )
934 nCount = length();
935
936 wxString dest(*this, length() - nCount, nCount);
937 if ( dest.length() != nCount ) {
938 wxFAIL_MSG( _T("out of memory in wxString::Right") );
939 }
940 return dest;
941}
942
943// get all characters after the last occurence of ch
944// (returns the whole string if ch not found)
945wxString wxString::AfterLast(wxUniChar ch) const
946{
947 wxString str;
948 int iPos = Find(ch, true);
949 if ( iPos == wxNOT_FOUND )
950 str = *this;
951 else
952 str = wx_str() + iPos + 1;
953
954 return str;
955}
956
957// extract nCount first (leftmost) characters
958wxString wxString::Left(size_t nCount) const
959{
960 if ( nCount > length() )
961 nCount = length();
962
963 wxString dest(*this, 0, nCount);
964 if ( dest.length() != nCount ) {
965 wxFAIL_MSG( _T("out of memory in wxString::Left") );
966 }
967 return dest;
968}
969
970// get all characters before the first occurence of ch
971// (returns the whole string if ch not found)
972wxString wxString::BeforeFirst(wxUniChar ch) const
973{
974 int iPos = Find(ch);
975 if ( iPos == wxNOT_FOUND ) iPos = length();
976 return wxString(*this, 0, iPos);
977}
978
979/// get all characters before the last occurence of ch
980/// (returns empty string if ch not found)
981wxString wxString::BeforeLast(wxUniChar ch) const
982{
983 wxString str;
984 int iPos = Find(ch, true);
985 if ( iPos != wxNOT_FOUND && iPos != 0 )
986 str = wxString(c_str(), iPos);
987
988 return str;
989}
990
991/// get all characters after the first occurence of ch
992/// (returns empty string if ch not found)
993wxString wxString::AfterFirst(wxUniChar ch) const
994{
995 wxString str;
996 int iPos = Find(ch);
997 if ( iPos != wxNOT_FOUND )
998 str = wx_str() + iPos + 1;
999
1000 return str;
1001}
1002
1003// replace first (or all) occurences of some substring with another one
1004size_t wxString::Replace(const wxChar *szOld,
1005 const wxChar *szNew, bool bReplaceAll)
1006{
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
1011 size_t uiCount = 0; // count of replacements made
1012
1013 size_t uiOldLen = wxStrlen(szOld);
1014 size_t uiNewLen = wxStrlen(szNew);
1015
1016 size_t dwPos = 0;
1017
1018 while ( this->c_str()[dwPos] != wxT('\0') )
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);
1024 if ( dwPos == npos )
1025 break; // exit the loop
1026 else
1027 {
1028 //replace this occurance of the old string with the new one
1029 replace(dwPos, uiOldLen, szNew, uiNewLen);
1030
1031 //move up pos past the string that was replaced
1032 dwPos += uiNewLen;
1033
1034 //increase replace count
1035 ++uiCount;
1036
1037 // stop now?
1038 if ( !bReplaceAll )
1039 break; // exit the loop
1040 }
1041 }
1042
1043 return uiCount;
1044}
1045
1046bool wxString::IsAscii() const
1047{
1048 const wxChar *s = (const wxChar*) *this;
1049 while(*s){
1050 if(!isascii(*s)) return(false);
1051 s++;
1052 }
1053 return(true);
1054}
1055
1056bool wxString::IsWord() const
1057{
1058 const wxChar *s = (const wxChar*) *this;
1059 while(*s){
1060 if(!wxIsalpha(*s)) return(false);
1061 s++;
1062 }
1063 return(true);
1064}
1065
1066bool wxString::IsNumber() const
1067{
1068 const wxChar *s = (const wxChar*) *this;
1069 if (wxStrlen(s))
1070 if ((s[0] == wxT('-')) || (s[0] == wxT('+'))) s++;
1071 while(*s){
1072 if(!wxIsdigit(*s)) return(false);
1073 s++;
1074 }
1075 return(true);
1076}
1077
1078wxString wxString::Strip(stripType w) const
1079{
1080 wxString s = *this;
1081 if ( w & leading ) s.Trim(false);
1082 if ( w & trailing ) s.Trim(true);
1083 return s;
1084}
1085
1086// ---------------------------------------------------------------------------
1087// case conversion
1088// ---------------------------------------------------------------------------
1089
1090wxString& wxString::MakeUpper()
1091{
1092 for ( iterator it = begin(), en = end(); it != en; ++it )
1093 *it = (wxChar)wxToupper(*it);
1094
1095 return *this;
1096}
1097
1098wxString& wxString::MakeLower()
1099{
1100 for ( iterator it = begin(), en = end(); it != en; ++it )
1101 *it = (wxChar)wxTolower(*it);
1102
1103 return *this;
1104}
1105
1106// ---------------------------------------------------------------------------
1107// trimming and padding
1108// ---------------------------------------------------------------------------
1109
1110// some compilers (VC++ 6.0 not to name them) return true for a call to
1111