]>
git.saurik.com Git - wxWidgets.git/blob - src/common/string.cpp
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 wxString
& str
)
80 return os
<< str
.c_str();
83 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxCStrData
& str
)
85 #if wxUSE_UNICODE && !defined(__BORLANDC__)
86 return os
<< str
.AsWChar();
88 return os
<< str
.AsChar();
92 #endif // wxUSE_STD_IOSTREAM
94 // ===========================================================================
95 // wxString class core
96 // ===========================================================================
98 // ---------------------------------------------------------------------------
99 // construction and conversion
100 // ---------------------------------------------------------------------------
104 wxString::SubstrBufFromMB
wxString::ConvertStr(const char *psz
, size_t nLength
,
105 const wxMBConv
& conv
)
108 if ( !psz
|| nLength
== 0 )
109 return SubstrBufFromMB();
111 if ( nLength
== npos
)
115 wxWCharBuffer
wcBuf(conv
.cMB2WC(psz
, nLength
, &wcLen
));
117 return SubstrBufFromMB();
119 return SubstrBufFromMB(wcBuf
, wcLen
);
123 wxString::SubstrBufFromWC
wxString::ConvertStr(const wchar_t *pwz
, size_t nLength
,
124 const wxMBConv
& conv
)
127 if ( !pwz
|| nLength
== 0 )
128 return SubstrBufFromWC();
130 if ( nLength
== npos
)
134 wxCharBuffer
mbBuf(conv
.cWC2MB(pwz
, nLength
, &mbLen
));
136 return SubstrBufFromWC();
138 return SubstrBufFromWC(mbBuf
, mbLen
);
145 // from multibyte string
146 wxString::wxString(const char *psz
, const wxMBConv
& conv
, size_t nLength
)
148 // FIXME-UTF8: this will need changes
151 if ( psz
&& nLength
!= 0 )
153 if ( nLength
== npos
)
159 wxWCharBuffer wbuf
= conv
.cMB2WC(psz
, nLength
, &nLenWide
);
162 assign(wbuf
, nLenWide
);
166 wxString::wxString(const char *psz
, size_t nLength
)
168 assign(psz
, nLength
);
171 //Convert wxString in Unicode mode to a multi-byte string
172 const wxCharBuffer
wxString::mb_str(const wxMBConv
& conv
) const
174 return conv
.cWC2MB(c_str(), length() + 1 /* size, not length */, NULL
);
182 wxString::wxString(const wchar_t *pwz
, const wxMBConv
& conv
, size_t nLength
)
184 // FIXME-UTF8: this will need changes
187 if ( pwz
&& nLength
!= 0 )
189 if ( nLength
== npos
)
195 wxCharBuffer buf
= conv
.cWC2MB(pwz
, nLength
, &nLenMB
);
203 wxString::wxString(const wchar_t *pwz
, size_t nLength
)
205 assign(pwz
, nLength
);
208 //Converts this string to a wide character string if unicode
209 //mode is not enabled and wxUSE_WCHAR_T is enabled
210 const wxWCharBuffer
wxString::wc_str(const wxMBConv
& conv
) const
212 return conv
.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL
);
215 #endif // wxUSE_WCHAR_T
217 #endif // Unicode/ANSI
219 // shrink to minimal size (releasing extra memory)
220 bool wxString::Shrink()
222 wxString
tmp(begin(), end());
224 return tmp
.length() == length();
227 // deprecated compatibility code:
228 #if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
229 wxChar
*wxString::GetWriteBuf(size_t nLen
)
231 return DoGetWriteBuf(nLen
);
234 void wxString::UngetWriteBuf()
239 void wxString::UngetWriteBuf(size_t nLen
)
241 DoUngetWriteBuf(nLen
);
243 #endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
246 // ---------------------------------------------------------------------------
248 // ---------------------------------------------------------------------------
250 // all functions are inline in string.h
252 // ---------------------------------------------------------------------------
253 // assignment operators
254 // ---------------------------------------------------------------------------
258 // same as 'signed char' variant
259 wxString
& wxString::operator=(const unsigned char* psz
)
261 *this = (const char *)psz
;
266 wxString
& wxString::operator=(const wchar_t *pwz
)
277 * concatenation functions come in 5 flavours:
279 * char + string and string + char
280 * C str + string and string + C str
283 wxString
operator+(const wxString
& str1
, const wxString
& str2
)
285 #if !wxUSE_STL_BASED_WXSTRING
286 wxASSERT( str1
.IsValid() );
287 wxASSERT( str2
.IsValid() );
296 wxString
operator+(const wxString
& str
, wxUniChar ch
)
298 #if !wxUSE_STL_BASED_WXSTRING
299 wxASSERT( str
.IsValid() );
308 wxString
operator+(wxUniChar ch
, const wxString
& str
)
310 #if !wxUSE_STL_BASED_WXSTRING
311 wxASSERT( str
.IsValid() );
320 wxString
operator+(const wxString
& str
, const char *psz
)
322 #if !wxUSE_STL_BASED_WXSTRING
323 wxASSERT( str
.IsValid() );
327 if ( !s
.Alloc(strlen(psz
) + str
.length()) ) {
328 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
336 wxString
operator+(const wxString
& str
, const wchar_t *pwz
)
338 #if !wxUSE_STL_BASED_WXSTRING
339 wxASSERT( str
.IsValid() );
343 if ( !s
.Alloc(wxWcslen(pwz
) + str
.length()) ) {
344 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
352 wxString
operator+(const char *psz
, const wxString
& str
)
354 #if !wxUSE_STL_BASED_WXSTRING
355 wxASSERT( str
.IsValid() );
359 if ( !s
.Alloc(strlen(psz
) + str
.length()) ) {
360 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
368 wxString
operator+(const wchar_t *pwz
, const wxString
& str
)
370 #if !wxUSE_STL_BASED_WXSTRING
371 wxASSERT( str
.IsValid() );
375 if ( !s
.Alloc(wxWcslen(pwz
) + str
.length()) ) {
376 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
384 // ---------------------------------------------------------------------------
386 // ---------------------------------------------------------------------------
388 #ifdef HAVE_STD_STRING_COMPARE
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).
395 int wxString::compare(const wxString
& str
) const
397 return m_impl
.compare(str
.m_impl
);
400 int wxString::compare(size_t nStart
, size_t nLen
,
401 const wxString
& str
) const
404 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
405 return m_impl
.compare(pos
, len
, str
.m_impl
);
408 int wxString::compare(size_t nStart
, size_t nLen
,
410 size_t nStart2
, size_t nLen2
) const
413 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
416 str
.PosLenToImpl(nStart2
, nLen2
, &pos2
, &len2
);
418 return m_impl
.compare(pos
, len
, str
.m_impl
, pos2
, len2
);
421 int wxString::compare(const char* sz
) const
423 return m_impl
.compare(ImplStr(sz
));
426 int wxString::compare(const wchar_t* sz
) const
428 return m_impl
.compare(ImplStr(sz
));
431 int wxString::compare(size_t nStart
, size_t nLen
,
432 const char* sz
, size_t nCount
) const
435 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
437 SubstrBufFromMB
str(ImplStr(sz
, nCount
));
439 return m_impl
.compare(pos
, len
, str
.data
, str
.len
);
442 int wxString::compare(size_t nStart
, size_t nLen
,
443 const wchar_t* sz
, size_t nCount
) const
446 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
448 SubstrBufFromWC
str(ImplStr(sz
, nCount
));
450 return m_impl
.compare(pos
, len
, str
.data
, str
.len
);
453 #else // !HAVE_STD_STRING_COMPARE
455 static inline int wxDoCmp(const wxStringCharType
* s1
, size_t l1
,
456 const wxStringCharType
* s2
, size_t l2
)
459 return wxStringMemcmp(s1
, s2
, l1
);
462 int ret
= wxStringMemcmp(s1
, s2
, l1
);
463 return ret
== 0 ? -1 : ret
;
467 int ret
= wxStringMemcmp(s1
, s2
, l2
);
468 return ret
== 0 ? +1 : ret
;
472 int wxString::compare(const wxString
& str
) const
474 return ::wxDoCmp(m_impl
.data(), m_impl
.length(),
475 str
.m_impl
.data(), str
.m_impl
.length());
478 int wxString::compare(size_t nStart
, size_t nLen
,
479 const wxString
& str
) const
481 wxASSERT(nStart
<= length());
482 size_type strLen
= length() - nStart
;
483 nLen
= strLen
< nLen
? strLen
: nLen
;
486 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
488 return ::wxDoCmp(m_impl
.data() + pos
, len
,
489 str
.m_impl
.data(), str
.m_impl
.length());
492 int wxString::compare(size_t nStart
, size_t nLen
,
494 size_t nStart2
, size_t nLen2
) const
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
;
504 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
506 str
.PosLenToImpl(nStart2
, nLen2
, &pos2
, &len2
);
508 return ::wxDoCmp(m_impl
.data() + pos
, len
,
509 str
.m_impl
.data() + pos2
, len2
);
512 int wxString::compare(const char* sz
) const
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
);
520 int wxString::compare(const wchar_t* sz
) const
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
);
528 int wxString::compare(size_t nStart
, size_t nLen
,
529 const char* sz
, size_t nCount
) const
531 wxASSERT(nStart
<= length());
532 size_type strLen
= length() - nStart
;
533 nLen
= strLen
< nLen
? strLen
: nLen
;
536 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
538 SubstrBufFromMB
str(ImplStr(sz
, nCount
));
539 if ( str
.len
== npos
)
540 str
.len
= wxStringStrlen(str
.data
);
542 return ::wxDoCmp(m_impl
.data() + pos
, len
, str
.data
, str
.len
);
545 int wxString::compare(size_t nStart
, size_t nLen
,
546 const wchar_t* sz
, size_t nCount
) const
548 wxASSERT(nStart
<= length());
549 size_type strLen
= length() - nStart
;
550 nLen
= strLen
< nLen
? strLen
: nLen
;
553 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
555 SubstrBufFromWC
str(ImplStr(sz
, nCount
));
556 if ( str
.len
== npos
)
557 str
.len
= wxStringStrlen(str
.data
);
559 return ::wxDoCmp(m_impl
.data() + pos
, len
, str
.data
, str
.len
);
562 #endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE
565 // ---------------------------------------------------------------------------
566 // find_{first,last}_[not]_of functions
567 // ---------------------------------------------------------------------------
569 #if !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
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.
576 size_t wxString::find_first_of(const wxChar
* sz
, size_t nStart
) const
578 return find_first_of(sz
, nStart
, wxStrlen(sz
));
581 size_t wxString::find_first_not_of(const wxChar
* sz
, size_t nStart
) const
583 return find_first_not_of(sz
, nStart
, wxStrlen(sz
));
586 size_t wxString::find_first_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
588 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
591 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
593 if ( wxTmemchr(sz
, *i
, n
) )
600 size_t wxString::find_first_not_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
602 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
605 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
607 if ( !wxTmemchr(sz
, *i
, n
) )
615 size_t wxString::find_last_of(const wxChar
* sz
, size_t nStart
) const
617 return find_last_of(sz
, nStart
, wxStrlen(sz
));
620 size_t wxString::find_last_not_of(const wxChar
* sz
, size_t nStart
) const
622 return find_last_not_of(sz
, nStart
, wxStrlen(sz
));
625 size_t wxString::find_last_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
627 size_t len
= length();
629 if ( nStart
== npos
)
635 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
639 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
640 i
!= rend(); --idx
, ++i
)
642 if ( wxTmemchr(sz
, *i
, n
) )
649 size_t wxString::find_last_not_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
651 size_t len
= length();
653 if ( nStart
== npos
)
659 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
663 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
664 i
!= rend(); --idx
, ++i
)
666 if ( !wxTmemchr(sz
, *i
, n
) )
673 size_t wxString::find_first_not_of(wxUniChar ch
, size_t nStart
) const
675 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
678 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
687 size_t wxString::find_last_not_of(wxUniChar ch
, size_t nStart
) const
689 size_t len
= length();
691 if ( nStart
== npos
)
697 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
701 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
702 i
!= rend(); --idx
, ++i
)
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
715 #define wxOtherCharType char
716 #define STRCONV (const wxChar*)wxConvLibc.cMB2WC
718 #define wxOtherCharType wchar_t
719 #define STRCONV (const wxChar*)wxConvLibc.cWC2MB
722 size_t wxString::find_first_of(const wxOtherCharType
* sz
, size_t nStart
) const
723 { return find_first_of(STRCONV(sz
), nStart
); }
725 size_t wxString::find_first_of(const wxOtherCharType
* sz
, size_t nStart
,
727 { return find_first_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
728 size_t wxString::find_last_of(const wxOtherCharType
* sz
, size_t nStart
) const
729 { return find_last_of(STRCONV(sz
), nStart
); }
730 size_t wxString::find_last_of(const wxOtherCharType
* sz
, size_t nStart
,
732 { return find_last_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
733 size_t wxString::find_first_not_of(const wxOtherCharType
* sz
, size_t nStart
) const
734 { return find_first_not_of(STRCONV(sz
), nStart
); }
735 size_t wxString::find_first_not_of(const wxOtherCharType
* sz
, size_t nStart
,
737 { return find_first_not_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
738 size_t wxString::find_last_not_of(const wxOtherCharType
* sz
, size_t nStart
) const
739 { return find_last_not_of(STRCONV(sz
), nStart
); }
740 size_t wxString::find_last_not_of(const wxOtherCharType
* sz
, size_t nStart
,
742 { return find_last_not_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
744 #undef wxOtherCharType
747 #endif // !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
749 // ===========================================================================
750 // other common string functions
751 // ===========================================================================
753 int wxString::CmpNoCase(const wxString
& s
) const
755 // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
758 const_iterator i1
= begin();
759 const_iterator end1
= end();
760 const_iterator i2
= s
.begin();
761 const_iterator end2
= s
.end();
763 for ( ; i1
!= end1
&& i2
!= end2
; ++idx
, ++i1
, ++i2
)
765 wxUniChar lower1
= (wxChar
)wxTolower(*i1
);
766 wxUniChar lower2
= (wxChar
)wxTolower(*i2
);
767 if ( lower1
!= lower2
)
768 return lower1
< lower2
? -1 : 1;
771 size_t len1
= length();
772 size_t len2
= s
.length();
776 else if ( len1
> len2
)
785 #ifndef __SCHAR_MAX__
786 #define __SCHAR_MAX__ 127
790 wxString
wxString::FromAscii(const char *ascii
)
793 return wxEmptyString
;
795 size_t len
= strlen( ascii
);
800 wxStringBuffer
buf(res
, len
);
806 if ( (*dest
++ = (wchar_t)(unsigned char)*ascii
++) == L
'\0' )
814 wxString
wxString::FromAscii(const char ascii
)
816 // What do we do with '\0' ?
819 res
+= (wchar_t)(unsigned char) ascii
;
824 const wxCharBuffer
wxString::ToAscii() const
826 // this will allocate enough space for the terminating NUL too
827 wxCharBuffer
buffer(length());
830 char *dest
= buffer
.data();
832 const wchar_t *pwc
= c_str();
835 *dest
++ = (char)(*pwc
> SCHAR_MAX
? wxT('_') : *pwc
);
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
848 // extract string of length nCount starting at nFirst
849 wxString
wxString::Mid(size_t nFirst
, size_t nCount
) const
851 size_t nLen
= length();
853 // default value of nCount is npos and means "till the end"
854 if ( nCount
== npos
)
856 nCount
= nLen
- nFirst
;
859 // out-of-bounds requests return sensible things
860 if ( nFirst
+ nCount
> nLen
)
862 nCount
= nLen
- nFirst
;
867 // AllocCopy() will return empty string
868 return wxEmptyString
;
871 wxString
dest(*this, nFirst
, nCount
);
872 if ( dest
.length() != nCount
)
874 wxFAIL_MSG( _T("out of memory in wxString::Mid") );
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
882 bool wxString::StartsWith(const wxChar
*prefix
, wxString
*rest
) const
884 wxASSERT_MSG( prefix
, _T("invalid parameter in wxString::StartsWith") );
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();
893 if ( *prefix
++ != *p
++ )
902 // put the rest of the string into provided pointer
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
912 bool wxString::EndsWith(const wxChar
*suffix
, wxString
*rest
) const
914 wxASSERT_MSG( suffix
, _T("invalid parameter in wxString::EndssWith") );
916 int start
= length() - wxStrlen(suffix
);
917 if ( start
< 0 || wxStrcmp(wx_str() + start
, suffix
) != 0 )
922 // put the rest of the string into provided pointer
923 rest
->assign(*this, 0, start
);
930 // extract nCount last (rightmost) characters
931 wxString
wxString::Right(size_t nCount
) const
933 if ( nCount
> length() )
936 wxString
dest(*this, length() - nCount
, nCount
);
937 if ( dest
.length() != nCount
) {
938 wxFAIL_MSG( _T("out of memory in wxString::Right") );
943 // get all characters after the last occurence of ch
944 // (returns the whole string if ch not found)
945 wxString
wxString::AfterLast(wxUniChar ch
) const
948 int iPos
= Find(ch
, true);
949 if ( iPos
== wxNOT_FOUND
)
952 str
= wx_str() + iPos
+ 1;
957 // extract nCount first (leftmost) characters
958 wxString
wxString::Left(size_t nCount
) const
960 if ( nCount
> length() )
963 wxString
dest(*this, 0, nCount
);
964 if ( dest
.length() != nCount
) {
965 wxFAIL_MSG( _T("out of memory in wxString::Left") );
970 // get all characters before the first occurence of ch
971 // (returns the whole string if ch not found)
972 wxString
wxString::BeforeFirst(wxUniChar ch
) const
975 if ( iPos
== wxNOT_FOUND
) iPos
= length();
976 return wxString(*this, 0, iPos
);
979 /// get all characters before the last occurence of ch
980 /// (returns empty string if ch not found)
981 wxString
wxString::BeforeLast(wxUniChar ch
) const
984 int iPos
= Find(ch
, true);
985 if ( iPos
!= wxNOT_FOUND
&& iPos
!= 0 )
986 str
= wxString(c_str(), iPos
);
991 /// get all characters after the first occurence of ch
992 /// (returns empty string if ch not found)
993 wxString
wxString::AfterFirst(wxUniChar ch
) const
997 if ( iPos
!= wxNOT_FOUND
)
998 str
= wx_str() + iPos
+ 1;
1003 // replace first (or all) occurences of some substring with another one
1004 size_t wxString::Replace(const wxChar
*szOld
,
1005 const wxChar
*szNew
, bool bReplaceAll
)
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") );
1011 size_t uiCount
= 0; // count of replacements made
1013 size_t uiOldLen
= wxStrlen(szOld
);
1014 size_t uiNewLen
= wxStrlen(szNew
);
1018 while ( this->c_str()[dwPos
] != wxT('\0') )
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
1028 //replace this occurance of the old string with the new one
1029 replace(dwPos
, uiOldLen
, szNew
, uiNewLen
);
1031 //move up pos past the string that was replaced
1034 //increase replace count
1039 break; // exit the loop
1046 bool wxString::IsAscii() const
1048 const wxChar
*s
= (const wxChar
*) *this;
1050 if(!isascii(*s
)) return(false);
1056 bool wxString::IsWord() const
1058 const wxChar
*s
= (const wxChar
*) *this;
1060 if(!wxIsalpha(*s
)) return(false);
1066 bool wxString::IsNumber() const
1068 const wxChar
*s
= (const wxChar
*) *this;
1070 if ((s
[0] == wxT('-')) || (s
[0] == wxT('+'))) s
++;
1072 if(!wxIsdigit(*s
)) return(false);
1078 wxString
wxString::Strip(stripType w
) const
1081 if ( w
& leading
) s
.Trim(false);
1082 if ( w
& trailing
) s
.Trim(true);
1086 // ---------------------------------------------------------------------------
1088 // ---------------------------------------------------------------------------
1090 wxString
& wxString::MakeUpper()
1092 for ( iterator it
= begin(), en
= end(); it
!= en
; ++it
)
1093 *it
= (wxChar
)wxToupper(*it
);
1098 wxString
& wxString::MakeLower()
1100 for ( iterator it
= begin(), en
= end(); it
!= en
; ++it
)
1101 *it
= (wxChar
)wxTolower(*it
);
1106 // ---------------------------------------------------------------------------
1107 // trimming and padding
1108 // ---------------------------------------------------------------------------
1110 // some compilers (VC++ 6.0 not to name them) return true for a call to
1111 // isspace('ê') in the C locale which seems to be broken to me, but we have to
1112 // live with this by checking that the character is a 7 bit one - even if this
1113 // may fail to detect some spaces (I don't know if Unicode doesn't have
1114 // space-like symbols somewhere except in the first 128 chars), it is arguably
1115 // still better than trimming away accented letters
1116 inline int wxSafeIsspace(wxChar ch
) { return (ch
< 127) && wxIsspace(ch
); }
1118 // trims spaces (in the sense of isspace) from left or right side
1119 wxString
& wxString::Trim(bool bFromRight
)
1121 // first check if we're going to modify the string at all
1124 (bFromRight
&& wxSafeIsspace(GetChar(length() - 1))) ||
1125 (!bFromRight
&& wxSafeIsspace(GetChar(0u)))
1131 // find last non-space character
1132 reverse_iterator psz
= rbegin();
1133 while ( (psz
!= rend()) && wxSafeIsspace(*psz
) )
1136 // truncate at trailing space start
1137 erase(psz
.base(), end());
1141 // find first non-space character
1142 iterator psz
= begin();
1143 while ( (psz
!= end()) && wxSafeIsspace(*psz
) )
1146 // fix up data and length
1147 erase(begin(), psz
);
1154 // adds nCount characters chPad to the string from either side
1155 wxString
& wxString::Pad(size_t nCount
, wxUniChar chPad
, bool bFromRight
)
1157 wxString
s(chPad
, nCount
);
1170 // truncate the string
1171 wxString
& wxString::Truncate(size_t uiLen
)
1173 if ( uiLen
< length() )
1175 erase(begin() + uiLen
, end());
1177 //else: nothing to do, string is already short enough
1182 // ---------------------------------------------------------------------------
1183 // finding (return wxNOT_FOUND if not found and index otherwise)
1184 // ---------------------------------------------------------------------------
1187 int wxString::Find(wxUniChar ch
, bool bFromEnd
) const
1189 size_type idx
= bFromEnd
? find_last_of(ch
) : find_first_of(ch
);
1191 return (idx
== npos
) ? wxNOT_FOUND
: (int)idx
;
1194 // find a sub-string (like strstr)
1195 int wxString::Find(const wxChar
*pszSub
) const
1197 size_type idx
= find(pszSub
);
1199 return (idx
== npos
) ? wxNOT_FOUND
: (int)idx
;
1202 // ----------------------------------------------------------------------------
1203 // conversion to numbers
1204 // ----------------------------------------------------------------------------
1206 // the implementation of all the functions below is exactly the same so factor
1209 template <typename T
, typename F
>
1210 bool wxStringToIntType(const wxChar
*start
,
1215 wxCHECK_MSG( val
, false, _T("NULL output pointer") );
1216 wxASSERT_MSG( !base
|| (base
> 1 && base
<= 36), _T("invalid base") );
1223 *val
= (*func
)(start
, &end
, base
);
1225 // return true only if scan was stopped by the terminating NUL and if the
1226 // string was not empty to start with and no under/overflow occurred
1227 return !*end
&& (end
!= start
)
1229 && (errno
!= ERANGE
)
1234 bool wxString::ToLong(long *val
, int base
) const
1236 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtol
);
1239 bool wxString::ToULong(unsigned long *val
, int base
) const
1241 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoul
);
1244 bool wxString::ToLongLong(wxLongLong_t
*val
, int base
) const
1246 #ifdef wxHAS_STRTOLL
1247 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoll
);
1249 // TODO: implement this ourselves
1253 #endif // wxHAS_STRTOLL
1256 bool wxString::ToULongLong(wxULongLong_t
*val
, int base
) const
1258 #ifdef wxHAS_STRTOLL
1259 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoull
);
1261 // TODO: implement this ourselves
1268 bool wxString::ToDouble(double *val
) const
1270 wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToDouble") );
1276 const wxChar
*start
= c_str();
1278 *val
= wxStrtod(start
, &end
);
1280 // return true only if scan was stopped by the terminating NUL and if the
1281 // string was not empty to start with and no under/overflow occurred
1282 return !*end
&& (end
!= start
)
1284 && (errno
!= ERANGE
)
1289 // ---------------------------------------------------------------------------
1291 // ---------------------------------------------------------------------------
1294 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1295 wxString
wxStringPrintfMixinBase::DoFormat(const wxChar
*format
, ...)
1297 wxString
wxString::DoFormat(const wxChar
*format
, ...)
1301 va_start(argptr
, format
);
1304 s
.PrintfV(format
, argptr
);
1312 wxString
wxString::FormatV(const wxString
& format
, va_list argptr
)
1315 s
.PrintfV(format
, argptr
);
1319 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1320 int wxStringPrintfMixinBase::DoPrintf(const wxChar
*format
, ...)
1322 int wxString::DoPrintf(const wxChar
*format
, ...)
1326 va_start(argptr
, format
);
1328 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1329 // get a pointer to the wxString instance; we have to use dynamic_cast<>
1330 // because it's the only cast that works safely for downcasting when
1331 // multiple inheritance is used:
1332 wxString
*str
= static_cast<wxString
*>(this);
1334 wxString
*str
= this;
1337 int iLen
= str
->PrintfV(format
, argptr
);
1344 int wxString::PrintfV(const wxString
& format
, va_list argptr
)
1350 wxStringBuffer
tmp(*this, size
+ 1);
1359 // wxVsnprintf() may modify the original arg pointer, so pass it
1362 wxVaCopy(argptrcopy
, argptr
);
1363 int len
= wxVsnprintf(buf
, size
, format
, argptrcopy
);
1366 // some implementations of vsnprintf() don't NUL terminate
1367 // the string if there is not enough space for it so
1368 // always do it manually
1369 buf
[size
] = _T('\0');
1371 // vsnprintf() may return either -1 (traditional Unix behaviour) or the
1372 // total number of characters which would have been written if the
1373 // buffer were large enough (newer standards such as Unix98)
1376 #if wxUSE_WXVSNPRINTF
1377 // we know that our own implementation of wxVsnprintf() returns -1
1378 // only for a format error - thus there's something wrong with
1379 // the user's format string
1381 #else // assume that system version only returns error if not enough space
1382 // still not enough, as we don't know how much we need, double the
1383 // current size of the buffer
1385 #endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
1387 else if ( len
>= size
)
1389 #if wxUSE_WXVSNPRINTF
1390 // we know that our own implementation of wxVsnprintf() returns
1391 // size+1 when there's not enough space but that's not the size
1392 // of the required buffer!
1393 size
*= 2; // so we just double the current size of the buffer
1395 // some vsnprintf() implementations NUL-terminate the buffer and
1396 // some don't in len == size case, to be safe always add 1
1400 else // ok, there was enough space
1406 // we could have overshot
1412 // ----------------------------------------------------------------------------
1413 // misc other operations
1414 // ----------------------------------------------------------------------------
1416 // returns true if the string matches the pattern which may contain '*' and
1417 // '?' metacharacters (as usual, '?' matches any character and '*' any number
1419 bool wxString::Matches(const wxChar
*pszMask
) const
1421 // I disable this code as it doesn't seem to be faster (in fact, it seems
1422 // to be much slower) than the old, hand-written code below and using it
1423 // here requires always linking with libregex even if the user code doesn't
1425 #if 0 // wxUSE_REGEX
1426 // first translate the shell-like mask into a regex
1428 pattern
.reserve(wxStrlen(pszMask
));
1440 pattern
+= _T(".*");
1451 // these characters are special in a RE, quote them
1452 // (however note that we don't quote '[' and ']' to allow
1453 // using them for Unix shell like matching)
1454 pattern
+= _T('\\');
1458 pattern
+= *pszMask
;
1466 return wxRegEx(pattern
, wxRE_NOSUB
| wxRE_EXTENDED
).Matches(c_str());
1467 #else // !wxUSE_REGEX
1468 // TODO: this is, of course, awfully inefficient...
1470 // the char currently being checked
1471 const wxChar
*pszTxt
= c_str();
1473 // the last location where '*' matched
1474 const wxChar
*pszLastStarInText
= NULL
;
1475 const wxChar
*pszLastStarInMask
= NULL
;
1478 for ( ; *pszMask
!= wxT('\0'); pszMask
++, pszTxt
++ ) {
1479 switch ( *pszMask
) {
1481 if ( *pszTxt
== wxT('\0') )
1484 // pszTxt and pszMask will be incremented in the loop statement
1490 // remember where we started to be able to backtrack later
1491 pszLastStarInText
= pszTxt
;
1492 pszLastStarInMask
= pszMask
;
1494 // ignore special chars immediately following this one
1495 // (should this be an error?)
1496 while ( *pszMask
== wxT('*') || *pszMask
== wxT('?') )
1499 // if there is nothing more, match
1500 if ( *pszMask
== wxT('\0') )
1503 // are there any other metacharacters in the mask?
1505 const wxChar
*pEndMask
= wxStrpbrk(pszMask
, wxT("*?"));
1507 if ( pEndMask
!= NULL
) {
1508 // we have to match the string between two metachars
1509 uiLenMask
= pEndMask
- pszMask
;
1512 // we have to match the remainder of the string
1513 uiLenMask
= wxStrlen(pszMask
);
1516 wxString
strToMatch(pszMask
, uiLenMask
);
1517 const wxChar
* pMatch
= wxStrstr(pszTxt
, strToMatch
);
1518 if ( pMatch
== NULL
)
1521 // -1 to compensate "++" in the loop
1522 pszTxt
= pMatch
+ uiLenMask
- 1;
1523 pszMask
+= uiLenMask
- 1;
1528 if ( *pszMask
!= *pszTxt
)
1534 // match only if nothing left
1535 if ( *pszTxt
== wxT('\0') )
1538 // if we failed to match, backtrack if we can
1539 if ( pszLastStarInText
) {
1540 pszTxt
= pszLastStarInText
+ 1;
1541 pszMask
= pszLastStarInMask
;
1543 pszLastStarInText
= NULL
;
1545 // don't bother resetting pszLastStarInMask, it's unnecessary
1551 #endif // wxUSE_REGEX/!wxUSE_REGEX
1554 // Count the number of chars
1555 int wxString::Freq(wxUniChar ch
) const
1558 for ( const_iterator i
= begin(); i
!= end(); ++i
)
1566 // convert to upper case, return the copy of the string
1567 wxString
wxString::Upper() const
1568 { wxString
s(*this); return s
.MakeUpper(); }
1570 // convert to lower case, return the copy of the string
1571 wxString
wxString::Lower() const { wxString
s(*this); return s
.MakeLower(); }