]>
git.saurik.com Git - wxWidgets.git/blob - src/common/string.cpp
6cdcaef00353117df4ec4fd16b7951cb32c02700
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/string.cpp
3 // Purpose: wxString class
4 // Author: Vadim Zeitlin, Ryan Norton
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // (c) 2004 Ryan Norton <wxprojects@comcast.net>
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
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
20 // ===========================================================================
21 // headers, declarations, constants
22 // ===========================================================================
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
32 #include "wx/string.h"
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
56 #define wxStringMemcpy wxTmemcpy
57 #define wxStringMemcmp wxTmemcmp
58 #define wxStringMemchr wxTmemchr
59 #define wxStringStrlen wxStrlen
63 // ---------------------------------------------------------------------------
64 // static class variables definition
65 // ---------------------------------------------------------------------------
67 //According to STL _must_ be a -1 size_t
68 const size_t wxString::npos
= (size_t) -1;
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 #if wxUSE_STD_IOSTREAM
78 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxCStrData
& str
)
80 // FIXME-UTF8: always, not only if wxUSE_UNICODE
81 #if wxUSE_UNICODE && !defined(__BORLANDC__)
82 return os
<< str
.AsWChar();
84 return os
<< str
.AsChar();
88 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxString
& str
)
90 return os
<< str
.c_str();
93 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxCharBuffer
& str
)
95 return os
<< str
.data();
99 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxWCharBuffer
& str
)
101 return os
<< str
.data();
105 #endif // wxUSE_STD_IOSTREAM
107 // ===========================================================================
108 // wxString class core
109 // ===========================================================================
111 // ---------------------------------------------------------------------------
112 // construction and conversion
113 // ---------------------------------------------------------------------------
117 wxString::SubstrBufFromMB
wxString::ConvertStr(const char *psz
, size_t nLength
,
118 const wxMBConv
& conv
)
121 if ( !psz
|| nLength
== 0 )
122 return SubstrBufFromMB();
124 if ( nLength
== npos
)
128 wxWCharBuffer
wcBuf(conv
.cMB2WC(psz
, nLength
, &wcLen
));
130 return SubstrBufFromMB();
132 return SubstrBufFromMB(wcBuf
, wcLen
);
136 wxString::SubstrBufFromWC
wxString::ConvertStr(const wchar_t *pwz
, size_t nLength
,
137 const wxMBConv
& conv
)
140 if ( !pwz
|| nLength
== 0 )
141 return SubstrBufFromWC();
143 if ( nLength
== npos
)
147 wxCharBuffer
mbBuf(conv
.cWC2MB(pwz
, nLength
, &mbLen
));
149 return SubstrBufFromWC();
151 return SubstrBufFromWC(mbBuf
, mbLen
);
158 //Convert wxString in Unicode mode to a multi-byte string
159 const wxCharBuffer
wxString::mb_str(const wxMBConv
& conv
) const
161 return conv
.cWC2MB(c_str(), length() + 1 /* size, not length */, NULL
);
168 //Converts this string to a wide character string if unicode
169 //mode is not enabled and wxUSE_WCHAR_T is enabled
170 const wxWCharBuffer
wxString::wc_str(const wxMBConv
& conv
) const
172 return conv
.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL
);
175 #endif // wxUSE_WCHAR_T
177 #endif // Unicode/ANSI
179 // shrink to minimal size (releasing extra memory)
180 bool wxString::Shrink()
182 wxString
tmp(begin(), end());
184 return tmp
.length() == length();
187 // deprecated compatibility code:
188 #if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
189 wxChar
*wxString::GetWriteBuf(size_t nLen
)
191 return DoGetWriteBuf(nLen
);
194 void wxString::UngetWriteBuf()
199 void wxString::UngetWriteBuf(size_t nLen
)
201 DoUngetWriteBuf(nLen
);
203 #endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
206 // ---------------------------------------------------------------------------
208 // ---------------------------------------------------------------------------
210 // all functions are inline in string.h
212 // ---------------------------------------------------------------------------
213 // assignment operators
214 // ---------------------------------------------------------------------------
218 // same as 'signed char' variant
219 wxString
& wxString::operator=(const unsigned char* psz
)
221 *this = (const char *)psz
;
226 wxString
& wxString::operator=(const wchar_t *pwz
)
237 * concatenation functions come in 5 flavours:
239 * char + string and string + char
240 * C str + string and string + C str
243 wxString
operator+(const wxString
& str1
, const wxString
& str2
)
245 #if !wxUSE_STL_BASED_WXSTRING
246 wxASSERT( str1
.IsValid() );
247 wxASSERT( str2
.IsValid() );
256 wxString
operator+(const wxString
& str
, wxUniChar ch
)
258 #if !wxUSE_STL_BASED_WXSTRING
259 wxASSERT( str
.IsValid() );
268 wxString
operator+(wxUniChar ch
, const wxString
& str
)
270 #if !wxUSE_STL_BASED_WXSTRING
271 wxASSERT( str
.IsValid() );
280 wxString
operator+(const wxString
& str
, const char *psz
)
282 #if !wxUSE_STL_BASED_WXSTRING
283 wxASSERT( str
.IsValid() );
287 if ( !s
.Alloc(strlen(psz
) + str
.length()) ) {
288 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
296 wxString
operator+(const wxString
& str
, const wchar_t *pwz
)
298 #if !wxUSE_STL_BASED_WXSTRING
299 wxASSERT( str
.IsValid() );
303 if ( !s
.Alloc(wxWcslen(pwz
) + str
.length()) ) {
304 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
312 wxString
operator+(const char *psz
, const wxString
& str
)
314 #if !wxUSE_STL_BASED_WXSTRING
315 wxASSERT( str
.IsValid() );
319 if ( !s
.Alloc(strlen(psz
) + str
.length()) ) {
320 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
328 wxString
operator+(const wchar_t *pwz
, const wxString
& str
)
330 #if !wxUSE_STL_BASED_WXSTRING
331 wxASSERT( str
.IsValid() );
335 if ( !s
.Alloc(wxWcslen(pwz
) + str
.length()) ) {
336 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
344 // ---------------------------------------------------------------------------
346 // ---------------------------------------------------------------------------
348 #ifdef HAVE_STD_STRING_COMPARE
350 // NB: Comparison code (both if HAVE_STD_STRING_COMPARE and if not) works with
351 // UTF-8 encoded strings too, thanks to UTF-8's design which allows us to
352 // sort strings in characters code point order by sorting the byte sequence
353 // in byte values order (i.e. what strcmp() and memcmp() do).
355 int wxString::compare(const wxString
& str
) const
357 return m_impl
.compare(str
.m_impl
);
360 int wxString::compare(size_t nStart
, size_t nLen
,
361 const wxString
& str
) const
364 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
365 return m_impl
.compare(pos
, len
, str
.m_impl
);
368 int wxString::compare(size_t nStart
, size_t nLen
,
370 size_t nStart2
, size_t nLen2
) const
373 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
376 str
.PosLenToImpl(nStart2
, nLen2
, &pos2
, &len2
);
378 return m_impl
.compare(pos
, len
, str
.m_impl
, pos2
, len2
);
381 int wxString::compare(const char* sz
) const
383 return m_impl
.compare(ImplStr(sz
));
386 int wxString::compare(const wchar_t* sz
) const
388 return m_impl
.compare(ImplStr(sz
));
391 int wxString::compare(size_t nStart
, size_t nLen
,
392 const char* sz
, size_t nCount
) const
395 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
397 SubstrBufFromMB
str(ImplStr(sz
, nCount
));
399 return m_impl
.compare(pos
, len
, str
.data
, str
.len
);
402 int wxString::compare(size_t nStart
, size_t nLen
,
403 const wchar_t* sz
, size_t nCount
) const
406 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
408 SubstrBufFromWC
str(ImplStr(sz
, nCount
));
410 return m_impl
.compare(pos
, len
, str
.data
, str
.len
);
413 #else // !HAVE_STD_STRING_COMPARE
415 static inline int wxDoCmp(const wxStringCharType
* s1
, size_t l1
,
416 const wxStringCharType
* s2
, size_t l2
)
419 return wxStringMemcmp(s1
, s2
, l1
);
422 int ret
= wxStringMemcmp(s1
, s2
, l1
);
423 return ret
== 0 ? -1 : ret
;
427 int ret
= wxStringMemcmp(s1
, s2
, l2
);
428 return ret
== 0 ? +1 : ret
;
432 int wxString::compare(const wxString
& str
) const
434 return ::wxDoCmp(m_impl
.data(), m_impl
.length(),
435 str
.m_impl
.data(), str
.m_impl
.length());
438 int wxString::compare(size_t nStart
, size_t nLen
,
439 const wxString
& str
) const
441 wxASSERT(nStart
<= length());
442 size_type strLen
= length() - nStart
;
443 nLen
= strLen
< nLen
? strLen
: nLen
;
446 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
448 return ::wxDoCmp(m_impl
.data() + pos
, len
,
449 str
.m_impl
.data(), str
.m_impl
.length());
452 int wxString::compare(size_t nStart
, size_t nLen
,
454 size_t nStart2
, size_t nLen2
) const
456 wxASSERT(nStart
<= length());
457 wxASSERT(nStart2
<= str
.length());
458 size_type strLen
= length() - nStart
,
459 strLen2
= str
.length() - nStart2
;
460 nLen
= strLen
< nLen
? strLen
: nLen
;
461 nLen2
= strLen2
< nLen2
? strLen2
: nLen2
;
464 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
466 str
.PosLenToImpl(nStart2
, nLen2
, &pos2
, &len2
);
468 return ::wxDoCmp(m_impl
.data() + pos
, len
,
469 str
.m_impl
.data() + pos2
, len2
);
472 int wxString::compare(const char* sz
) const
474 SubstrBufFromMB
str(ImplStr(sz
, npos
));
475 if ( str
.len
== npos
)
476 str
.len
= wxStringStrlen(str
.data
);
477 return ::wxDoCmp(m_impl
.data(), m_impl
.length(), str
.data
, str
.len
);
480 int wxString::compare(const wchar_t* sz
) const
482 SubstrBufFromWC
str(ImplStr(sz
, npos
));
483 if ( str
.len
== npos
)
484 str
.len
= wxStringStrlen(str
.data
);
485 return ::wxDoCmp(m_impl
.data(), m_impl
.length(), str
.data
, str
.len
);
488 int wxString::compare(size_t nStart
, size_t nLen
,
489 const char* sz
, size_t nCount
) const
491 wxASSERT(nStart
<= length());
492 size_type strLen
= length() - nStart
;
493 nLen
= strLen
< nLen
? strLen
: nLen
;
496 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
498 SubstrBufFromMB
str(ImplStr(sz
, nCount
));
499 if ( str
.len
== npos
)
500 str
.len
= wxStringStrlen(str
.data
);
502 return ::wxDoCmp(m_impl
.data() + pos
, len
, str
.data
, str
.len
);
505 int wxString::compare(size_t nStart
, size_t nLen
,
506 const wchar_t* sz
, size_t nCount
) const
508 wxASSERT(nStart
<= length());
509 size_type strLen
= length() - nStart
;
510 nLen
= strLen
< nLen
? strLen
: nLen
;
513 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
515 SubstrBufFromWC
str(ImplStr(sz
, nCount
));
516 if ( str
.len
== npos
)
517 str
.len
= wxStringStrlen(str
.data
);
519 return ::wxDoCmp(m_impl
.data() + pos
, len
, str
.data
, str
.len
);
522 #endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE
525 // ---------------------------------------------------------------------------
526 // find_{first,last}_[not]_of functions
527 // ---------------------------------------------------------------------------
529 #if !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
531 // NB: All these functions are implemented with the argument being wxChar*,
532 // i.e. widechar string in any Unicode build, even though native string
533 // representation is char* in the UTF-8 build. This is because we couldn't
534 // use memchr() to determine if a character is in a set encoded as UTF-8.
536 size_t wxString::find_first_of(const wxChar
* sz
, size_t nStart
) const
538 return find_first_of(sz
, nStart
, wxStrlen(sz
));
541 size_t wxString::find_first_not_of(const wxChar
* sz
, size_t nStart
) const
543 return find_first_not_of(sz
, nStart
, wxStrlen(sz
));
546 size_t wxString::find_first_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
548 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
551 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
553 if ( wxTmemchr(sz
, *i
, n
) )
560 size_t wxString::find_first_not_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
562 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
565 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
567 if ( !wxTmemchr(sz
, *i
, n
) )
575 size_t wxString::find_last_of(const wxChar
* sz
, size_t nStart
) const
577 return find_last_of(sz
, nStart
, wxStrlen(sz
));
580 size_t wxString::find_last_not_of(const wxChar
* sz
, size_t nStart
) const
582 return find_last_not_of(sz
, nStart
, wxStrlen(sz
));
585 size_t wxString::find_last_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
587 size_t len
= length();
589 if ( nStart
== npos
)
595 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
599 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
600 i
!= rend(); --idx
, ++i
)
602 if ( wxTmemchr(sz
, *i
, n
) )
609 size_t wxString::find_last_not_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
611 size_t len
= length();
613 if ( nStart
== npos
)
619 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
623 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
624 i
!= rend(); --idx
, ++i
)
626 if ( !wxTmemchr(sz
, *i
, n
) )
633 size_t wxString::find_first_not_of(wxUniChar ch
, size_t nStart
) const
635 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
638 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
647 size_t wxString::find_last_not_of(wxUniChar ch
, size_t nStart
) const
649 size_t len
= length();
651 if ( nStart
== npos
)
657 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
661 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
662 i
!= rend(); --idx
, ++i
)
671 // the functions above were implemented for wchar_t* arguments in Unicode
672 // build and char* in ANSI build; below are implementations for the other
675 #define wxOtherCharType char
676 #define STRCONV (const wxChar*)wxConvLibc.cMB2WC
678 #define wxOtherCharType wchar_t
679 #define STRCONV (const wxChar*)wxConvLibc.cWC2MB
682 size_t wxString::find_first_of(const wxOtherCharType
* sz
, size_t nStart
) const
683 { return find_first_of(STRCONV(sz
), nStart
); }
685 size_t wxString::find_first_of(const wxOtherCharType
* sz
, size_t nStart
,
687 { return find_first_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
688 size_t wxString::find_last_of(const wxOtherCharType
* sz
, size_t nStart
) const
689 { return find_last_of(STRCONV(sz
), nStart
); }
690 size_t wxString::find_last_of(const wxOtherCharType
* sz
, size_t nStart
,
692 { return find_last_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
693 size_t wxString::find_first_not_of(const wxOtherCharType
* sz
, size_t nStart
) const
694 { return find_first_not_of(STRCONV(sz
), nStart
); }
695 size_t wxString::find_first_not_of(const wxOtherCharType
* sz
, size_t nStart
,
697 { return find_first_not_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
698 size_t wxString::find_last_not_of(const wxOtherCharType
* sz
, size_t nStart
) const
699 { return find_last_not_of(STRCONV(sz
), nStart
); }
700 size_t wxString::find_last_not_of(const wxOtherCharType
* sz
, size_t nStart
,
702 { return find_last_not_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
704 #undef wxOtherCharType
707 #endif // !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
709 // ===========================================================================
710 // other common string functions
711 // ===========================================================================
713 int wxString::CmpNoCase(const wxString
& s
) const
715 // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
718 const_iterator i1
= begin();
719 const_iterator end1
= end();
720 const_iterator i2
= s
.begin();
721 const_iterator end2
= s
.end();
723 for ( ; i1
!= end1
&& i2
!= end2
; ++idx
, ++i1
, ++i2
)
725 wxUniChar lower1
= (wxChar
)wxTolower(*i1
);
726 wxUniChar lower2
= (wxChar
)wxTolower(*i2
);
727 if ( lower1
!= lower2
)
728 return lower1
< lower2
? -1 : 1;
731 size_t len1
= length();
732 size_t len2
= s
.length();
736 else if ( len1
> len2
)
745 #ifndef __SCHAR_MAX__
746 #define __SCHAR_MAX__ 127
750 wxString
wxString::FromAscii(const char *ascii
)
753 return wxEmptyString
;
755 size_t len
= strlen( ascii
);
760 wxStringBuffer
buf(res
, len
);
766 if ( (*dest
++ = (wchar_t)(unsigned char)*ascii
++) == L
'\0' )
774 wxString
wxString::FromAscii(const char ascii
)
776 // What do we do with '\0' ?
779 res
+= (wchar_t)(unsigned char) ascii
;
784 const wxCharBuffer
wxString::ToAscii() const
786 // this will allocate enough space for the terminating NUL too
787 wxCharBuffer
buffer(length());
790 char *dest
= buffer
.data();
792 const wchar_t *pwc
= c_str();
795 *dest
++ = (char)(*pwc
> SCHAR_MAX
? wxT('_') : *pwc
);
797 // the output string can't have embedded NULs anyhow, so we can safely
798 // stop at first of them even if we do have any
808 // extract string of length nCount starting at nFirst
809 wxString
wxString::Mid(size_t nFirst
, size_t nCount
) const
811 size_t nLen
= length();
813 // default value of nCount is npos and means "till the end"
814 if ( nCount
== npos
)
816 nCount
= nLen
- nFirst
;
819 // out-of-bounds requests return sensible things
820 if ( nFirst
+ nCount
> nLen
)
822 nCount
= nLen
- nFirst
;
827 // AllocCopy() will return empty string
828 return wxEmptyString
;
831 wxString
dest(*this, nFirst
, nCount
);
832 if ( dest
.length() != nCount
)
834 wxFAIL_MSG( _T("out of memory in wxString::Mid") );
840 // check that the string starts with prefix and return the rest of the string
841 // in the provided pointer if it is not NULL, otherwise return false
842 bool wxString::StartsWith(const wxChar
*prefix
, wxString
*rest
) const
844 wxASSERT_MSG( prefix
, _T("invalid parameter in wxString::StartsWith") );
846 // first check if the beginning of the string matches the prefix: note
847 // that we don't have to check that we don't run out of this string as
848 // when we reach the terminating NUL, either prefix string ends too (and
849 // then it's ok) or we break out of the loop because there is no match
850 const wxChar
*p
= c_str();
853 if ( *prefix
++ != *p
++ )
862 // put the rest of the string into provided pointer
870 // check that the string ends with suffix and return the rest of it in the
871 // provided pointer if it is not NULL, otherwise return false
872 bool wxString::EndsWith(const wxChar
*suffix
, wxString
*rest
) const
874 wxASSERT_MSG( suffix
, _T("invalid parameter in wxString::EndssWith") );
876 int start
= length() - wxStrlen(suffix
);
877 if ( start
< 0 || wxStrcmp(wx_str() + start
, suffix
) != 0 )
882 // put the rest of the string into provided pointer
883 rest
->assign(*this, 0, start
);
890 // extract nCount last (rightmost) characters
891 wxString
wxString::Right(size_t nCount
) const
893 if ( nCount
> length() )
896 wxString
dest(*this, length() - nCount
, nCount
);
897 if ( dest
.length() != nCount
) {
898 wxFAIL_MSG( _T("out of memory in wxString::Right") );
903 // get all characters after the last occurence of ch
904 // (returns the whole string if ch not found)
905 wxString
wxString::AfterLast(wxUniChar ch
) const
908 int iPos
= Find(ch
, true);
909 if ( iPos
== wxNOT_FOUND
)
912 str
= wx_str() + iPos
+ 1;
917 // extract nCount first (leftmost) characters
918 wxString
wxString::Left(size_t nCount
) const
920 if ( nCount
> length() )
923 wxString
dest(*this, 0, nCount
);
924 if ( dest
.length() != nCount
) {
925 wxFAIL_MSG( _T("out of memory in wxString::Left") );
930 // get all characters before the first occurence of ch
931 // (returns the whole string if ch not found)
932 wxString
wxString::BeforeFirst(wxUniChar ch
) const
935 if ( iPos
== wxNOT_FOUND
) iPos
= length();
936 return wxString(*this, 0, iPos
);
939 /// get all characters before the last occurence of ch
940 /// (returns empty string if ch not found)
941 wxString
wxString::BeforeLast(wxUniChar ch
) const
944 int iPos
= Find(ch
, true);
945 if ( iPos
!= wxNOT_FOUND
&& iPos
!= 0 )
946 str
= wxString(c_str(), iPos
);
951 /// get all characters after the first occurence of ch
952 /// (returns empty string if ch not found)
953 wxString
wxString::AfterFirst(wxUniChar ch
) const
957 if ( iPos
!= wxNOT_FOUND
)
958 str
= wx_str() + iPos
+ 1;
963 // replace first (or all) occurences of some substring with another one
964 size_t wxString::Replace(const wxChar
*szOld
,
965 const wxChar
*szNew
, bool bReplaceAll
)
967 // if we tried to replace an empty string we'd enter an infinite loop below
968 wxCHECK_MSG( szOld
&& *szOld
&& szNew
, 0,
969 _T("wxString::Replace(): invalid parameter") );
971 size_t uiCount
= 0; // count of replacements made
973 size_t uiOldLen
= wxStrlen(szOld
);
974 size_t uiNewLen
= wxStrlen(szNew
);
978 while ( this->c_str()[dwPos
] != wxT('\0') )
980 //DO NOT USE STRSTR HERE
981 //this string can contain embedded null characters,
982 //so strstr will function incorrectly
983 dwPos
= find(szOld
, dwPos
);
985 break; // exit the loop
988 //replace this occurance of the old string with the new one
989 replace(dwPos
, uiOldLen
, szNew
, uiNewLen
);
991 //move up pos past the string that was replaced
994 //increase replace count
999 break; // exit the loop
1006 bool wxString::IsAscii() const
1008 const wxChar
*s
= (const wxChar
*) *this;
1010 if(!isascii(*s
)) return(false);
1016 bool wxString::IsWord() const
1018 const wxChar
*s
= (const wxChar
*) *this;
1020 if(!wxIsalpha(*s
)) return(false);
1026 bool wxString::IsNumber() const
1028 const wxChar
*s
= (const wxChar
*) *this;
1030 if ((s
[0] == wxT('-')) || (s
[0] == wxT('+'))) s
++;
1032 if(!wxIsdigit(*s
)) return(false);
1038 wxString
wxString::Strip(stripType w
) const
1041 if ( w
& leading
) s
.Trim(false);
1042 if ( w
& trailing
) s
.Trim(true);
1046 // ---------------------------------------------------------------------------
1048 // ---------------------------------------------------------------------------
1050 wxString
& wxString::MakeUpper()
1052 for ( iterator it
= begin(), en
= end(); it
!= en
; ++it
)
1053 *it
= (wxChar
)wxToupper(*it
);
1058 wxString
& wxString::MakeLower()
1060 for ( iterator it
= begin(), en
= end(); it
!= en
; ++it
)
1061 *it
= (wxChar
)wxTolower(*it
);
1066 // ---------------------------------------------------------------------------
1067 // trimming and padding
1068 // ---------------------------------------------------------------------------
1070 // some compilers (VC++ 6.0 not to name them) return true for a call to
1071 // isspace('ê') in the C locale which seems to be broken to me, but we have to
1072 // live with this by checking that the character is a 7 bit one - even if this
1073 // may fail to detect some spaces (I don't know if Unicode doesn't have
1074 // space-like symbols somewhere except in the first 128 chars), it is arguably
1075 // still better than trimming away accented letters
1076 inline int wxSafeIsspace(wxChar ch
) { return (ch
< 127) && wxIsspace(ch
); }
1078 // trims spaces (in the sense of isspace) from left or right side
1079 wxString
& wxString::Trim(bool bFromRight
)
1081 // first check if we're going to modify the string at all
1084 (bFromRight
&& wxSafeIsspace(GetChar(length() - 1))) ||
1085 (!bFromRight
&& wxSafeIsspace(GetChar(0u)))
1091 // find last non-space character
1092 reverse_iterator psz
= rbegin();
1093 while ( (psz
!= rend()) && wxSafeIsspace(*psz
) )
1096 // truncate at trailing space start
1097 erase(psz
.base(), end());
1101 // find first non-space character
1102 iterator psz
= begin();
1103 while ( (psz
!= end()) && wxSafeIsspace(*psz
) )
1106 // fix up data and length
1107 erase(begin(), psz
);
1114 // adds nCount characters chPad to the string from either side
1115 wxString
& wxString::Pad(size_t nCount
, wxUniChar chPad
, bool bFromRight
)
1117 wxString
s(chPad
, nCount
);
1130 // truncate the string
1131 wxString
& wxString::Truncate(size_t uiLen
)
1133 if ( uiLen
< length() )
1135 erase(begin() + uiLen
, end());
1137 //else: nothing to do, string is already short enough
1142 // ---------------------------------------------------------------------------
1143 // finding (return wxNOT_FOUND if not found and index otherwise)
1144 // ---------------------------------------------------------------------------
1147 int wxString::Find(wxUniChar ch
, bool bFromEnd
) const
1149 size_type idx
= bFromEnd
? find_last_of(ch
) : find_first_of(ch
);
1151 return (idx
== npos
) ? wxNOT_FOUND
: (int)idx
;
1154 // find a sub-string (like strstr)
1155 int wxString::Find(const wxChar
*pszSub
) const
1157 size_type idx
= find(pszSub
);
1159 return (idx
== npos
) ? wxNOT_FOUND
: (int)idx
;
1162 // ----------------------------------------------------------------------------
1163 // conversion to numbers
1164 // ----------------------------------------------------------------------------
1166 // the implementation of all the functions below is exactly the same so factor
1169 template <typename T
, typename F
>
1170 bool wxStringToIntType(const wxChar
*start
,
1175 wxCHECK_MSG( val
, false, _T("NULL output pointer") );
1176 wxASSERT_MSG( !base
|| (base
> 1 && base
<= 36), _T("invalid base") );
1183 *val
= (*func
)(start
, &end
, base
);
1185 // return true only if scan was stopped by the terminating NUL and if the
1186 // string was not empty to start with and no under/overflow occurred
1187 return !*end
&& (end
!= start
)
1189 && (errno
!= ERANGE
)
1194 bool wxString::ToLong(long *val
, int base
) const
1196 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtol
);
1199 bool wxString::ToULong(unsigned long *val
, int base
) const
1201 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoul
);
1204 bool wxString::ToLongLong(wxLongLong_t
*val
, int base
) const
1206 #ifdef wxHAS_STRTOLL
1207 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoll
);
1209 // TODO: implement this ourselves
1213 #endif // wxHAS_STRTOLL
1216 bool wxString::ToULongLong(wxULongLong_t
*val
, int base
) const
1218 #ifdef wxHAS_STRTOLL
1219 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoull
);
1221 // TODO: implement this ourselves
1228 bool wxString::ToDouble(double *val
) const
1230 wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToDouble") );
1236 const wxChar
*start
= c_str();
1238 *val
= wxStrtod(start
, &end
);
1240 // return true only if scan was stopped by the terminating NUL and if the
1241 // string was not empty to start with and no under/overflow occurred
1242 return !*end
&& (end
!= start
)
1244 && (errno
!= ERANGE
)
1249 // ---------------------------------------------------------------------------
1251 // ---------------------------------------------------------------------------
1254 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1255 wxString
wxStringPrintfMixinBase::DoFormat(const wxChar
*format
, ...)
1257 wxString
wxString::DoFormat(const wxChar
*format
, ...)
1261 va_start(argptr
, format
);
1264 s
.PrintfV(format
, argptr
);
1272 wxString
wxString::FormatV(const wxString
& format
, va_list argptr
)
1275 s
.PrintfV(format
, argptr
);
1279 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1280 int wxStringPrintfMixinBase::DoPrintf(const wxChar
*format
, ...)
1282 int wxString::DoPrintf(const wxChar
*format
, ...)
1286 va_start(argptr
, format
);
1288 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1289 // get a pointer to the wxString instance; we have to use dynamic_cast<>
1290 // because it's the only cast that works safely for downcasting when
1291 // multiple inheritance is used:
1292 wxString
*str
= static_cast<wxString
*>(this);
1294 wxString
*str
= this;
1297 int iLen
= str
->PrintfV(format
, argptr
);
1304 int wxString::PrintfV(const wxString
& format
, va_list argptr
)
1310 wxStringBuffer
tmp(*this, size
+ 1);
1319 // wxVsnprintf() may modify the original arg pointer, so pass it
1322 wxVaCopy(argptrcopy
, argptr
);
1323 int len
= wxVsnprintf(buf
, size
, format
, argptrcopy
);
1326 // some implementations of vsnprintf() don't NUL terminate
1327 // the string if there is not enough space for it so
1328 // always do it manually
1329 buf
[size
] = _T('\0');
1331 // vsnprintf() may return either -1 (traditional Unix behaviour) or the
1332 // total number of characters which would have been written if the
1333 // buffer were large enough (newer standards such as Unix98)
1336 #if wxUSE_WXVSNPRINTF
1337 // we know that our own implementation of wxVsnprintf() returns -1
1338 // only for a format error - thus there's something wrong with
1339 // the user's format string
1341 #else // assume that system version only returns error if not enough space
1342 // still not enough, as we don't know how much we need, double the
1343 // current size of the buffer
1345 #endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
1347 else if ( len
>= size
)
1349 #if wxUSE_WXVSNPRINTF
1350 // we know that our own implementation of wxVsnprintf() returns
1351 // size+1 when there's not enough space but that's not the size
1352 // of the required buffer!
1353 size
*= 2; // so we just double the current size of the buffer
1355 // some vsnprintf() implementations NUL-terminate the buffer and
1356 // some don't in len == size case, to be safe always add 1
1360 else // ok, there was enough space
1366 // we could have overshot
1372 // ----------------------------------------------------------------------------
1373 // misc other operations
1374 // ----------------------------------------------------------------------------
1376 // returns true if the string matches the pattern which may contain '*' and
1377 // '?' metacharacters (as usual, '?' matches any character and '*' any number
1379 bool wxString::Matches(const wxChar
*pszMask
) const
1381 // I disable this code as it doesn't seem to be faster (in fact, it seems
1382 // to be much slower) than the old, hand-written code below and using it
1383 // here requires always linking with libregex even if the user code doesn't
1385 #if 0 // wxUSE_REGEX
1386 // first translate the shell-like mask into a regex
1388 pattern
.reserve(wxStrlen(pszMask
));
1400 pattern
+= _T(".*");
1411 // these characters are special in a RE, quote them
1412 // (however note that we don't quote '[' and ']' to allow
1413 // using them for Unix shell like matching)
1414 pattern
+= _T('\\');
1418 pattern
+= *pszMask
;
1426 return wxRegEx(pattern
, wxRE_NOSUB
| wxRE_EXTENDED
).Matches(c_str());
1427 #else // !wxUSE_REGEX
1428 // TODO: this is, of course, awfully inefficient...
1430 // the char currently being checked
1431 const wxChar
*pszTxt
= c_str();
1433 // the last location where '*' matched
1434 const wxChar
*pszLastStarInText
= NULL
;
1435 const wxChar
*pszLastStarInMask
= NULL
;
1438 for ( ; *pszMask
!= wxT('\0'); pszMask
++, pszTxt
++ ) {
1439 switch ( *pszMask
) {
1441 if ( *pszTxt
== wxT('\0') )
1444 // pszTxt and pszMask will be incremented in the loop statement
1450 // remember where we started to be able to backtrack later
1451 pszLastStarInText
= pszTxt
;
1452 pszLastStarInMask
= pszMask
;
1454 // ignore special chars immediately following this one
1455 // (should this be an error?)
1456 while ( *pszMask
== wxT('*') || *pszMask
== wxT('?') )
1459 // if there is nothing more, match
1460 if ( *pszMask
== wxT('\0') )
1463 // are there any other metacharacters in the mask?
1465 const wxChar
*pEndMask
= wxStrpbrk(pszMask
, wxT("*?"));
1467 if ( pEndMask
!= NULL
) {
1468 // we have to match the string between two metachars
1469 uiLenMask
= pEndMask
- pszMask
;
1472 // we have to match the remainder of the string
1473 uiLenMask
= wxStrlen(pszMask
);
1476 wxString
strToMatch(pszMask
, uiLenMask
);
1477 const wxChar
* pMatch
= wxStrstr(pszTxt
, strToMatch
);
1478 if ( pMatch
== NULL
)
1481 // -1 to compensate "++" in the loop
1482 pszTxt
= pMatch
+ uiLenMask
- 1;
1483 pszMask
+= uiLenMask
- 1;
1488 if ( *pszMask
!= *pszTxt
)
1494 // match only if nothing left
1495 if ( *pszTxt
== wxT('\0') )
1498 // if we failed to match, backtrack if we can
1499 if ( pszLastStarInText
) {
1500 pszTxt
= pszLastStarInText
+ 1;
1501 pszMask
= pszLastStarInMask
;
1503 pszLastStarInText
= NULL
;
1505 // don't bother resetting pszLastStarInMask, it's unnecessary
1511 #endif // wxUSE_REGEX/!wxUSE_REGEX
1514 // Count the number of chars
1515 int wxString::Freq(wxUniChar ch
) const
1518 for ( const_iterator i
= begin(); i
!= end(); ++i
)
1526 // convert to upper case, return the copy of the string
1527 wxString
wxString::Upper() const
1528 { wxString
s(*this); return s
.MakeUpper(); }
1530 // convert to lower case, return the copy of the string
1531 wxString
wxString::Lower() const { wxString
s(*this); return s
.MakeLower(); }