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 /////////////////////////////////////////////////////////////////////////////
13 // ===========================================================================
14 // headers, declarations, constants
15 // ===========================================================================
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
25 #include "wx/string.h"
26 #include "wx/wxcrtvararg.h"
42 #include "wx/hashmap.h"
44 // string handling functions used by wxString:
45 #if wxUSE_UNICODE_UTF8
46 #define wxStringMemcpy memcpy
47 #define wxStringMemcmp memcmp
48 #define wxStringMemchr memchr
49 #define wxStringStrlen strlen
51 #define wxStringMemcpy wxTmemcpy
52 #define wxStringMemcmp wxTmemcmp
53 #define wxStringMemchr wxTmemchr
54 #define wxStringStrlen wxStrlen
58 // ---------------------------------------------------------------------------
59 // static class variables definition
60 // ---------------------------------------------------------------------------
62 //According to STL _must_ be a -1 size_t
63 const size_t wxString::npos
= (size_t) -1;
65 // ----------------------------------------------------------------------------
67 // ----------------------------------------------------------------------------
69 #if wxUSE_STD_IOSTREAM
73 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxCStrData
& str
)
75 // FIXME-UTF8: always, not only if wxUSE_UNICODE
76 #if wxUSE_UNICODE && !defined(__BORLANDC__)
77 return os
<< (const wchar_t*)str
.AsWCharBuf();
79 return os
<< (const char*)str
.AsCharBuf();
83 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxString
& str
)
85 return os
<< str
.c_str();
88 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxCharBuffer
& str
)
90 return os
<< str
.data();
94 wxSTD ostream
& operator<<(wxSTD ostream
& os
, const wxWCharBuffer
& str
)
96 return os
<< str
.data();
100 #endif // wxUSE_STD_IOSTREAM
102 // ===========================================================================
103 // wxString class core
104 // ===========================================================================
106 #if wxUSE_UNICODE_UTF8
108 void wxString::PosLenToImpl(size_t pos
, size_t len
,
109 size_t *implPos
, size_t *implLen
) const
115 const_iterator i
= begin() + pos
;
116 *implPos
= wxStringImpl::const_iterator(i
.impl()) - m_impl
.begin();
121 // too large length is interpreted as "to the end of the string"
122 // FIXME-UTF8: verify this is the case in std::string, assert
124 if ( pos
+ len
> length() )
125 len
= length() - pos
;
127 *implLen
= (i
+ len
).impl() - i
.impl();
132 #endif // wxUSE_UNICODE_UTF8
134 // ----------------------------------------------------------------------------
135 // wxCStrData converted strings caching
136 // ----------------------------------------------------------------------------
138 // FIXME-UTF8: temporarily disabled because it doesn't work with global
139 // string objects; re-enable after fixing this bug and benchmarking
140 // performance to see if using a hash is a good idea at all
143 // For backward compatibility reasons, it must be possible to assign the value
144 // returned by wxString::c_str() to a char* or wchar_t* variable and work with
145 // it. Returning wxCharBuffer from (const char*)c_str() wouldn't do the trick,
146 // because the memory would be freed immediately, but it has to be valid as long
147 // as the string is not modified, so that code like this still works:
149 // const wxChar *s = str.c_str();
150 // while ( s ) { ... }
152 // FIXME-UTF8: not thread safe!
153 // FIXME-UTF8: we currently clear the cached conversion only when the string is
154 // destroyed, but we should do it when the string is modified, to
155 // keep memory usage down
156 // FIXME-UTF8: we do the conversion every time As[W]Char() is called, but if we
157 // invalidated the cache on every change, we could keep the previous
159 // FIXME-UTF8: add tracing of usage of these two methods - new code is supposed
160 // to use mb_str() or wc_str() instead of (const [w]char*)c_str()
163 static inline void DeleteStringFromConversionCache(T
& hash
, const wxString
*s
)
165 typename
T::iterator i
= hash
.find(wxConstCast(s
, wxString
));
166 if ( i
!= hash
.end() )
174 // NB: non-STL implementation doesn't compile with "const wxString*" key type,
175 // so we have to use wxString* here and const-cast when used
176 WX_DECLARE_HASH_MAP(wxString
*, char*, wxPointerHash
, wxPointerEqual
,
177 wxStringCharConversionCache
);
178 static wxStringCharConversionCache gs_stringsCharCache
;
180 const char* wxCStrData::AsChar() const
182 // remove previously cache value, if any (see FIXMEs above):
183 DeleteStringFromConversionCache(gs_stringsCharCache
, m_str
);
185 // convert the string and keep it:
186 const char *s
= gs_stringsCharCache
[wxConstCast(m_str
, wxString
)] =
187 m_str
->mb_str().release();
191 #endif // wxUSE_UNICODE
193 #if !wxUSE_UNICODE_WCHAR
194 WX_DECLARE_HASH_MAP(wxString
*, wchar_t*, wxPointerHash
, wxPointerEqual
,
195 wxStringWCharConversionCache
);
196 static wxStringWCharConversionCache gs_stringsWCharCache
;
198 const wchar_t* wxCStrData::AsWChar() const
200 // remove previously cache value, if any (see FIXMEs above):
201 DeleteStringFromConversionCache(gs_stringsWCharCache
, m_str
);
203 // convert the string and keep it:
204 const wchar_t *s
= gs_stringsWCharCache
[wxConstCast(m_str
, wxString
)] =
205 m_str
->wc_str().release();
209 #endif // !wxUSE_UNICODE_WCHAR
211 wxString::~wxString()
214 // FIXME-UTF8: do this only if locale is not UTF8 if wxUSE_UNICODE_UTF8
215 DeleteStringFromConversionCache(gs_stringsCharCache
, this);
217 #if !wxUSE_UNICODE_WCHAR
218 DeleteStringFromConversionCache(gs_stringsWCharCache
, this);
223 #if wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
224 const char* wxCStrData::AsChar() const
226 #if wxUSE_UNICODE_UTF8
227 if ( wxLocaleIsUtf8
)
230 // under non-UTF8 locales, we have to convert the internal UTF-8
231 // representation using wxConvLibc and cache the result
233 wxString
*str
= wxConstCast(m_str
, wxString
);
235 // convert the string:
236 wxCharBuffer
buf(str
->mb_str());
238 // FIXME-UTF8: do the conversion in-place in the existing buffer
239 if ( str
->m_convertedToChar
&&
240 strlen(buf
) == strlen(str
->m_convertedToChar
) )
242 // keep the same buffer for as long as possible, so that several calls
243 // to c_str() in a row still work:
244 strcpy(str
->m_convertedToChar
, buf
);
248 str
->m_convertedToChar
= buf
.release();
252 return str
->m_convertedToChar
+ m_offset
;
254 #endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
256 #if !wxUSE_UNICODE_WCHAR
257 const wchar_t* wxCStrData::AsWChar() const
259 wxString
*str
= wxConstCast(m_str
, wxString
);
261 // convert the string:
262 wxWCharBuffer
buf(str
->wc_str());
264 // FIXME-UTF8: do the conversion in-place in the existing buffer
265 if ( str
->m_convertedToWChar
&&
266 wxWcslen(buf
) == wxWcslen(str
->m_convertedToWChar
) )
268 // keep the same buffer for as long as possible, so that several calls
269 // to c_str() in a row still work:
270 memcpy(str
->m_convertedToWChar
, buf
, sizeof(wchar_t) * wxWcslen(buf
));
274 str
->m_convertedToWChar
= buf
.release();
278 return str
->m_convertedToWChar
+ m_offset
;
280 #endif // !wxUSE_UNICODE_WCHAR
282 // ===========================================================================
283 // wxString class core
284 // ===========================================================================
286 // ---------------------------------------------------------------------------
287 // construction and conversion
288 // ---------------------------------------------------------------------------
290 #if wxUSE_UNICODE_WCHAR
292 wxString::SubstrBufFromMB
wxString::ConvertStr(const char *psz
, size_t nLength
,
293 const wxMBConv
& conv
)
296 if ( !psz
|| nLength
== 0 )
297 return SubstrBufFromMB(L
"", 0);
299 if ( nLength
== npos
)
303 wxWCharBuffer
wcBuf(conv
.cMB2WC(psz
, nLength
, &wcLen
));
305 return SubstrBufFromMB(_T(""), 0);
307 return SubstrBufFromMB(wcBuf
, wcLen
);
309 #endif // wxUSE_UNICODE_WCHAR
311 #if wxUSE_UNICODE_UTF8
313 wxString::SubstrBufFromMB
wxString::ConvertStr(const char *psz
, size_t nLength
,
314 const wxMBConv
& conv
)
317 if ( !psz
|| nLength
== 0 )
318 return SubstrBufFromMB("", 0);
320 // if psz is already in UTF-8, we don't have to do the roundtrip to
321 // wchar_t* and back:
324 // we need to validate the input because UTF8 iterators assume valid
325 // UTF-8 sequence and psz may be invalid:
326 if ( wxStringOperations::IsValidUtf8String(psz
, nLength
) )
328 return SubstrBufFromMB(wxCharBuffer::CreateNonOwned(psz
), nLength
);
330 // else: do the roundtrip through wchar_t*
333 if ( nLength
== npos
)
336 // first convert to wide string:
338 wxWCharBuffer
wcBuf(conv
.cMB2WC(psz
, nLength
, &wcLen
));
340 return SubstrBufFromMB("", 0);
342 // and then to UTF-8:
343 SubstrBufFromMB
buf(ConvertStr(wcBuf
, wcLen
, wxMBConvUTF8()));
344 // widechar -> UTF-8 conversion isn't supposed to ever fail:
345 wxASSERT_MSG( buf
.data
, _T("conversion to UTF-8 failed") );
349 #endif // wxUSE_UNICODE_UTF8
351 #if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
353 wxString::SubstrBufFromWC
wxString::ConvertStr(const wchar_t *pwz
, size_t nLength
,
354 const wxMBConv
& conv
)
357 if ( !pwz
|| nLength
== 0 )
358 return SubstrBufFromWC("", 0);
360 if ( nLength
== npos
)
364 wxCharBuffer
mbBuf(conv
.cWC2MB(pwz
, nLength
, &mbLen
));
366 return SubstrBufFromWC("", 0);
368 return SubstrBufFromWC(mbBuf
, mbLen
);
370 #endif // wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
373 #if wxUSE_UNICODE_WCHAR
375 //Convert wxString in Unicode mode to a multi-byte string
376 const wxCharBuffer
wxString::mb_str(const wxMBConv
& conv
) const
378 return conv
.cWC2MB(wx_str(), length() + 1 /* size, not length */, NULL
);
381 #elif wxUSE_UNICODE_UTF8
383 const wxWCharBuffer
wxString::wc_str() const
385 return wxMBConvUTF8().cMB2WC(m_impl
.c_str(),
386 m_impl
.length() + 1 /* size, not length */,
390 const wxCharBuffer
wxString::mb_str(const wxMBConv
& conv
) const
393 return wxCharBuffer::CreateNonOwned(m_impl
.c_str());
395 // FIXME-UTF8: use wc_str() here once we have buffers with length
399 wxMBConvUTF8().cMB2WC(m_impl
.c_str(),
400 m_impl
.length() + 1 /* size, not length */,
403 return wxCharBuffer("");
405 return conv
.cWC2MB(wcBuf
, wcLen
, NULL
);
410 //Converts this string to a wide character string if unicode
411 //mode is not enabled and wxUSE_WCHAR_T is enabled
412 const wxWCharBuffer
wxString::wc_str(const wxMBConv
& conv
) const
414 return conv
.cMB2WC(wx_str(), length() + 1 /* size, not length */, NULL
);
417 #endif // Unicode/ANSI
419 // shrink to minimal size (releasing extra memory)
420 bool wxString::Shrink()
422 wxString
tmp(begin(), end());
424 return tmp
.length() == length();
427 // deprecated compatibility code:
428 #if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
429 wxStringCharType
*wxString::GetWriteBuf(size_t nLen
)
431 return DoGetWriteBuf(nLen
);
434 void wxString::UngetWriteBuf()
439 void wxString::UngetWriteBuf(size_t nLen
)
441 DoUngetWriteBuf(nLen
);
443 #endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
446 // ---------------------------------------------------------------------------
448 // ---------------------------------------------------------------------------
450 // all functions are inline in string.h
452 // ---------------------------------------------------------------------------
453 // concatenation operators
454 // ---------------------------------------------------------------------------
457 * concatenation functions come in 5 flavours:
459 * char + string and string + char
460 * C str + string and string + C str
463 wxString
operator+(const wxString
& str1
, const wxString
& str2
)
465 #if !wxUSE_STL_BASED_WXSTRING
466 wxASSERT( str1
.IsValid() );
467 wxASSERT( str2
.IsValid() );
476 wxString
operator+(const wxString
& str
, wxUniChar ch
)
478 #if !wxUSE_STL_BASED_WXSTRING
479 wxASSERT( str
.IsValid() );
488 wxString
operator+(wxUniChar ch
, const wxString
& str
)
490 #if !wxUSE_STL_BASED_WXSTRING
491 wxASSERT( str
.IsValid() );
500 wxString
operator+(const wxString
& str
, const char *psz
)
502 #if !wxUSE_STL_BASED_WXSTRING
503 wxASSERT( str
.IsValid() );
507 if ( !s
.Alloc(strlen(psz
) + str
.length()) ) {
508 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
516 wxString
operator+(const wxString
& str
, const wchar_t *pwz
)
518 #if !wxUSE_STL_BASED_WXSTRING
519 wxASSERT( str
.IsValid() );
523 if ( !s
.Alloc(wxWcslen(pwz
) + str
.length()) ) {
524 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
532 wxString
operator+(const char *psz
, const wxString
& str
)
534 #if !wxUSE_STL_BASED_WXSTRING
535 wxASSERT( str
.IsValid() );
539 if ( !s
.Alloc(strlen(psz
) + str
.length()) ) {
540 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
548 wxString
operator+(const wchar_t *pwz
, const wxString
& str
)
550 #if !wxUSE_STL_BASED_WXSTRING
551 wxASSERT( str
.IsValid() );
555 if ( !s
.Alloc(wxWcslen(pwz
) + str
.length()) ) {
556 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
564 // ---------------------------------------------------------------------------
566 // ---------------------------------------------------------------------------
568 #ifdef HAVE_STD_STRING_COMPARE
570 // NB: Comparison code (both if HAVE_STD_STRING_COMPARE and if not) works with
571 // UTF-8 encoded strings too, thanks to UTF-8's design which allows us to
572 // sort strings in characters code point order by sorting the byte sequence
573 // in byte values order (i.e. what strcmp() and memcmp() do).
575 int wxString::compare(const wxString
& str
) const
577 return m_impl
.compare(str
.m_impl
);
580 int wxString::compare(size_t nStart
, size_t nLen
,
581 const wxString
& str
) const
584 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
585 return m_impl
.compare(pos
, len
, str
.m_impl
);
588 int wxString::compare(size_t nStart
, size_t nLen
,
590 size_t nStart2
, size_t nLen2
) const
593 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
596 str
.PosLenToImpl(nStart2
, nLen2
, &pos2
, &len2
);
598 return m_impl
.compare(pos
, len
, str
.m_impl
, pos2
, len2
);
601 int wxString::compare(const char* sz
) const
603 return m_impl
.compare(ImplStr(sz
));
606 int wxString::compare(const wchar_t* sz
) const
608 return m_impl
.compare(ImplStr(sz
));
611 int wxString::compare(size_t nStart
, size_t nLen
,
612 const char* sz
, size_t nCount
) const
615 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
617 SubstrBufFromMB
str(ImplStr(sz
, nCount
));
619 return m_impl
.compare(pos
, len
, str
.data
, str
.len
);
622 int wxString::compare(size_t nStart
, size_t nLen
,
623 const wchar_t* sz
, size_t nCount
) const
626 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
628 SubstrBufFromWC
str(ImplStr(sz
, nCount
));
630 return m_impl
.compare(pos
, len
, str
.data
, str
.len
);
633 #else // !HAVE_STD_STRING_COMPARE
635 static inline int wxDoCmp(const wxStringCharType
* s1
, size_t l1
,
636 const wxStringCharType
* s2
, size_t l2
)
639 return wxStringMemcmp(s1
, s2
, l1
);
642 int ret
= wxStringMemcmp(s1
, s2
, l1
);
643 return ret
== 0 ? -1 : ret
;
647 int ret
= wxStringMemcmp(s1
, s2
, l2
);
648 return ret
== 0 ? +1 : ret
;
652 int wxString::compare(const wxString
& str
) const
654 return ::wxDoCmp(m_impl
.data(), m_impl
.length(),
655 str
.m_impl
.data(), str
.m_impl
.length());
658 int wxString::compare(size_t nStart
, size_t nLen
,
659 const wxString
& str
) const
661 wxASSERT(nStart
<= length());
662 size_type strLen
= length() - nStart
;
663 nLen
= strLen
< nLen
? strLen
: nLen
;
666 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
668 return ::wxDoCmp(m_impl
.data() + pos
, len
,
669 str
.m_impl
.data(), str
.m_impl
.length());
672 int wxString::compare(size_t nStart
, size_t nLen
,
674 size_t nStart2
, size_t nLen2
) const
676 wxASSERT(nStart
<= length());
677 wxASSERT(nStart2
<= str
.length());
678 size_type strLen
= length() - nStart
,
679 strLen2
= str
.length() - nStart2
;
680 nLen
= strLen
< nLen
? strLen
: nLen
;
681 nLen2
= strLen2
< nLen2
? strLen2
: nLen2
;
684 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
686 str
.PosLenToImpl(nStart2
, nLen2
, &pos2
, &len2
);
688 return ::wxDoCmp(m_impl
.data() + pos
, len
,
689 str
.m_impl
.data() + pos2
, len2
);
692 int wxString::compare(const char* sz
) const
694 SubstrBufFromMB
str(ImplStr(sz
, npos
));
695 if ( str
.len
== npos
)
696 str
.len
= wxStringStrlen(str
.data
);
697 return ::wxDoCmp(m_impl
.data(), m_impl
.length(), str
.data
, str
.len
);
700 int wxString::compare(const wchar_t* sz
) const
702 SubstrBufFromWC
str(ImplStr(sz
, npos
));
703 if ( str
.len
== npos
)
704 str
.len
= wxStringStrlen(str
.data
);
705 return ::wxDoCmp(m_impl
.data(), m_impl
.length(), str
.data
, str
.len
);
708 int wxString::compare(size_t nStart
, size_t nLen
,
709 const char* sz
, size_t nCount
) const
711 wxASSERT(nStart
<= length());
712 size_type strLen
= length() - nStart
;
713 nLen
= strLen
< nLen
? strLen
: nLen
;
716 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
718 SubstrBufFromMB
str(ImplStr(sz
, nCount
));
719 if ( str
.len
== npos
)
720 str
.len
= wxStringStrlen(str
.data
);
722 return ::wxDoCmp(m_impl
.data() + pos
, len
, str
.data
, str
.len
);
725 int wxString::compare(size_t nStart
, size_t nLen
,
726 const wchar_t* sz
, size_t nCount
) const
728 wxASSERT(nStart
<= length());
729 size_type strLen
= length() - nStart
;
730 nLen
= strLen
< nLen
? strLen
: nLen
;
733 PosLenToImpl(nStart
, nLen
, &pos
, &len
);
735 SubstrBufFromWC
str(ImplStr(sz
, nCount
));
736 if ( str
.len
== npos
)
737 str
.len
= wxStringStrlen(str
.data
);
739 return ::wxDoCmp(m_impl
.data() + pos
, len
, str
.data
, str
.len
);
742 #endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE
745 // ---------------------------------------------------------------------------
746 // find_{first,last}_[not]_of functions
747 // ---------------------------------------------------------------------------
749 #if !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
751 // NB: All these functions are implemented with the argument being wxChar*,
752 // i.e. widechar string in any Unicode build, even though native string
753 // representation is char* in the UTF-8 build. This is because we couldn't
754 // use memchr() to determine if a character is in a set encoded as UTF-8.
756 size_t wxString::find_first_of(const wxChar
* sz
, size_t nStart
) const
758 return find_first_of(sz
, nStart
, wxStrlen(sz
));
761 size_t wxString::find_first_not_of(const wxChar
* sz
, size_t nStart
) const
763 return find_first_not_of(sz
, nStart
, wxStrlen(sz
));
766 size_t wxString::find_first_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
768 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
771 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
773 if ( wxTmemchr(sz
, *i
, n
) )
780 size_t wxString::find_first_not_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
782 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
785 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
787 if ( !wxTmemchr(sz
, *i
, n
) )
795 size_t wxString::find_last_of(const wxChar
* sz
, size_t nStart
) const
797 return find_last_of(sz
, nStart
, wxStrlen(sz
));
800 size_t wxString::find_last_not_of(const wxChar
* sz
, size_t nStart
) const
802 return find_last_not_of(sz
, nStart
, wxStrlen(sz
));
805 size_t wxString::find_last_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
807 size_t len
= length();
809 if ( nStart
== npos
)
815 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
819 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
820 i
!= rend(); --idx
, ++i
)
822 if ( wxTmemchr(sz
, *i
, n
) )
829 size_t wxString::find_last_not_of(const wxChar
* sz
, size_t nStart
, size_t n
) const
831 size_t len
= length();
833 if ( nStart
== npos
)
839 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
843 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
844 i
!= rend(); --idx
, ++i
)
846 if ( !wxTmemchr(sz
, *i
, n
) )
853 size_t wxString::find_first_not_of(wxUniChar ch
, size_t nStart
) const
855 wxASSERT_MSG( nStart
<= length(), _T("invalid index") );
858 for ( const_iterator i
= begin() + nStart
; i
!= end(); ++idx
, ++i
)
867 size_t wxString::find_last_not_of(wxUniChar ch
, size_t nStart
) const
869 size_t len
= length();
871 if ( nStart
== npos
)
877 wxASSERT_MSG( nStart
<= len
, _T("invalid index") );
881 for ( const_reverse_iterator i
= rbegin() + (len
- nStart
- 1);
882 i
!= rend(); --idx
, ++i
)
891 // the functions above were implemented for wchar_t* arguments in Unicode
892 // build and char* in ANSI build; below are implementations for the other
895 #define wxOtherCharType char
896 #define STRCONV (const wxChar*)wxConvLibc.cMB2WC
898 #define wxOtherCharType wchar_t
899 #define STRCONV (const wxChar*)wxConvLibc.cWC2MB
902 size_t wxString::find_first_of(const wxOtherCharType
* sz
, size_t nStart
) const
903 { return find_first_of(STRCONV(sz
), nStart
); }
905 size_t wxString::find_first_of(const wxOtherCharType
* sz
, size_t nStart
,
907 { return find_first_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
908 size_t wxString::find_last_of(const wxOtherCharType
* sz
, size_t nStart
) const
909 { return find_last_of(STRCONV(sz
), nStart
); }
910 size_t wxString::find_last_of(const wxOtherCharType
* sz
, size_t nStart
,
912 { return find_last_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
913 size_t wxString::find_first_not_of(const wxOtherCharType
* sz
, size_t nStart
) const
914 { return find_first_not_of(STRCONV(sz
), nStart
); }
915 size_t wxString::find_first_not_of(const wxOtherCharType
* sz
, size_t nStart
,
917 { return find_first_not_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
918 size_t wxString::find_last_not_of(const wxOtherCharType
* sz
, size_t nStart
) const
919 { return find_last_not_of(STRCONV(sz
), nStart
); }
920 size_t wxString::find_last_not_of(const wxOtherCharType
* sz
, size_t nStart
,
922 { return find_last_not_of(STRCONV(sz
, n
, NULL
), nStart
, n
); }
924 #undef wxOtherCharType
927 #endif // !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
929 // ===========================================================================
930 // other common string functions
931 // ===========================================================================
933 int wxString::CmpNoCase(const wxString
& s
) const
935 // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
938 const_iterator i1
= begin();
939 const_iterator end1
= end();
940 const_iterator i2
= s
.begin();
941 const_iterator end2
= s
.end();
943 for ( ; i1
!= end1
&& i2
!= end2
; ++idx
, ++i1
, ++i2
)
945 wxUniChar lower1
= (wxChar
)wxTolower(*i1
);
946 wxUniChar lower2
= (wxChar
)wxTolower(*i2
);
947 if ( lower1
!= lower2
)
948 return lower1
< lower2
? -1 : 1;
951 size_t len1
= length();
952 size_t len2
= s
.length();
956 else if ( len1
> len2
)
965 #ifndef __SCHAR_MAX__
966 #define __SCHAR_MAX__ 127
970 wxString
wxString::FromAscii(const char *ascii
)
973 return wxEmptyString
;
975 size_t len
= strlen(ascii
);
980 wxImplStringBuffer
buf(res
, len
);
981 wxStringCharType
*dest
= buf
;
985 unsigned char c
= (unsigned char)*ascii
++;
986 wxASSERT_MSG( c
< 0x80,
987 _T("Non-ASCII value passed to FromAscii().") );
989 *dest
++ = (wchar_t)c
;
999 wxString
wxString::FromAscii(const char ascii
)
1001 // What do we do with '\0' ?
1003 unsigned char c
= (unsigned char)ascii
;
1005 wxASSERT_MSG( c
< 0x80, _T("Non-ASCII value passed to FromAscii().") );
1007 // NB: the cast to wchar_t causes interpretation of 'ascii' as Latin1 value
1008 return wxString(wxUniChar((wchar_t)c
));
1011 const wxCharBuffer
wxString::ToAscii() const
1013 // this will allocate enough space for the terminating NUL too
1014 wxCharBuffer
buffer(length());
1015 char *dest
= buffer
.data();
1017 for ( const_iterator i
= begin(); i
!= end(); ++i
)
1020 // FIXME-UTF8: unify substituted char ('_') with wxUniChar ('?')
1021 *dest
++ = c
.IsAscii() ? (char)c
: '_';
1023 // the output string can't have embedded NULs anyhow, so we can safely
1024 // stop at first of them even if we do have any
1032 #endif // wxUSE_UNICODE
1034 // extract string of length nCount starting at nFirst
1035 wxString
wxString::Mid(size_t nFirst
, size_t nCount
) const
1037 size_t nLen
= length();
1039 // default value of nCount is npos and means "till the end"
1040 if ( nCount
== npos
)
1042 nCount
= nLen
- nFirst
;
1045 // out-of-bounds requests return sensible things
1046 if ( nFirst
+ nCount
> nLen
)
1048 nCount
= nLen
- nFirst
;
1051 if ( nFirst
> nLen
)
1053 // AllocCopy() will return empty string
1054 return wxEmptyString
;
1057 wxString
dest(*this, nFirst
, nCount
);
1058 if ( dest
.length() != nCount
)
1060 wxFAIL_MSG( _T("out of memory in wxString::Mid") );
1066 // check that the string starts with prefix and return the rest of the string
1067 // in the provided pointer if it is not NULL, otherwise return false
1068 bool wxString::StartsWith(const wxString
& prefix
, wxString
*rest
) const
1070 if ( compare(0, prefix
.length(), prefix
) != 0 )
1075 // put the rest of the string into provided pointer
1076 rest
->assign(*this, prefix
.length(), npos
);
1083 // check that the string ends with suffix and return the rest of it in the
1084 // provided pointer if it is not NULL, otherwise return false
1085 bool wxString::EndsWith(const wxString
& suffix
, wxString
*rest
) const
1087 int start
= length() - suffix
.length();
1089 if ( start
< 0 || compare(start
, npos
, suffix
) != 0 )
1094 // put the rest of the string into provided pointer
1095 rest
->assign(*this, 0, start
);
1102 // extract nCount last (rightmost) characters
1103 wxString
wxString::Right(size_t nCount
) const
1105 if ( nCount
> length() )
1108 wxString
dest(*this, length() - nCount
, nCount
);
1109 if ( dest
.length() != nCount
) {
1110 wxFAIL_MSG( _T("out of memory in wxString::Right") );
1115 // get all characters after the last occurence of ch
1116 // (returns the whole string if ch not found)
1117 wxString
wxString::AfterLast(wxUniChar ch
) const
1120 int iPos
= Find(ch
, true);
1121 if ( iPos
== wxNOT_FOUND
)
1124 str
= wx_str() + iPos
+ 1;
1129 // extract nCount first (leftmost) characters
1130 wxString
wxString::Left(size_t nCount
) const
1132 if ( nCount
> length() )
1135 wxString
dest(*this, 0, nCount
);
1136 if ( dest
.length() != nCount
) {
1137 wxFAIL_MSG( _T("out of memory in wxString::Left") );
1142 // get all characters before the first occurence of ch
1143 // (returns the whole string if ch not found)
1144 wxString
wxString::BeforeFirst(wxUniChar ch
) const
1146 int iPos
= Find(ch
);
1147 if ( iPos
== wxNOT_FOUND
) iPos
= length();
1148 return wxString(*this, 0, iPos
);
1151 /// get all characters before the last occurence of ch
1152 /// (returns empty string if ch not found)
1153 wxString
wxString::BeforeLast(wxUniChar ch
) const
1156 int iPos
= Find(ch
, true);
1157 if ( iPos
!= wxNOT_FOUND
&& iPos
!= 0 )
1158 str
= wxString(c_str(), iPos
);
1163 /// get all characters after the first occurence of ch
1164 /// (returns empty string if ch not found)
1165 wxString
wxString::AfterFirst(wxUniChar ch
) const
1168 int iPos
= Find(ch
);
1169 if ( iPos
!= wxNOT_FOUND
)
1170 str
= wx_str() + iPos
+ 1;
1175 // replace first (or all) occurences of some substring with another one
1176 size_t wxString::Replace(const wxString
& strOld
,
1177 const wxString
& strNew
, bool bReplaceAll
)
1179 // if we tried to replace an empty string we'd enter an infinite loop below
1180 wxCHECK_MSG( !strOld
.empty(), 0,
1181 _T("wxString::Replace(): invalid parameter") );
1183 size_t uiCount
= 0; // count of replacements made
1185 size_t uiOldLen
= strOld
.length();
1186 size_t uiNewLen
= strNew
.length();
1190 while ( (*this)[dwPos
] != wxT('\0') )
1192 //DO NOT USE STRSTR HERE
1193 //this string can contain embedded null characters,
1194 //so strstr will function incorrectly
1195 dwPos
= find(strOld
, dwPos
);
1196 if ( dwPos
== npos
)
1197 break; // exit the loop
1200 //replace this occurance of the old string with the new one
1201 replace(dwPos
, uiOldLen
, strNew
, uiNewLen
);
1203 //move up pos past the string that was replaced
1206 //increase replace count
1211 break; // exit the loop
1218 bool wxString::IsAscii() const
1220 for ( const_iterator i
= begin(); i
!= end(); ++i
)
1222 if ( !(*i
).IsAscii() )
1229 bool wxString::IsWord() const
1231 for ( const_iterator i
= begin(); i
!= end(); ++i
)
1233 if ( !wxIsalpha(*i
) )
1240 bool wxString::IsNumber() const
1245 const_iterator i
= begin();
1247 if ( *i
== _T('-') || *i
== _T('+') )
1250 for ( ; i
!= end(); ++i
)
1252 if ( !wxIsdigit(*i
) )
1259 wxString
wxString::Strip(stripType w
) const
1262 if ( w
& leading
) s
.Trim(false);
1263 if ( w
& trailing
) s
.Trim(true);
1267 // ---------------------------------------------------------------------------
1269 // ---------------------------------------------------------------------------
1271 wxString
& wxString::MakeUpper()
1273 for ( iterator it
= begin(), en
= end(); it
!= en
; ++it
)
1274 *it
= (wxChar
)wxToupper(*it
);
1279 wxString
& wxString::MakeLower()
1281 for ( iterator it
= begin(), en
= end(); it
!= en
; ++it
)
1282 *it
= (wxChar
)wxTolower(*it
);
1287 // ---------------------------------------------------------------------------
1288 // trimming and padding
1289 // ---------------------------------------------------------------------------
1291 // some compilers (VC++ 6.0 not to name them) return true for a call to
1292 // isspace('ê') in the C locale which seems to be broken to me, but we have to
1293 // live with this by checking that the character is a 7 bit one - even if this
1294 // may fail to detect some spaces (I don't know if Unicode doesn't have
1295 // space-like symbols somewhere except in the first 128 chars), it is arguably
1296 // still better than trimming away accented letters
1297 inline int wxSafeIsspace(wxChar ch
) { return (ch
< 127) && wxIsspace(ch
); }
1299 // trims spaces (in the sense of isspace) from left or right side
1300 wxString
& wxString::Trim(bool bFromRight
)
1302 // first check if we're going to modify the string at all
1305 (bFromRight
&& wxSafeIsspace(GetChar(length() - 1))) ||
1306 (!bFromRight
&& wxSafeIsspace(GetChar(0u)))
1312 // find last non-space character
1313 reverse_iterator psz
= rbegin();
1314 while ( (psz
!= rend()) && wxSafeIsspace(*psz
) )
1317 // truncate at trailing space start
1318 erase(psz
.base(), end());
1322 // find first non-space character
1323 iterator psz
= begin();
1324 while ( (psz
!= end()) && wxSafeIsspace(*psz
) )
1327 // fix up data and length
1328 erase(begin(), psz
);
1335 // adds nCount characters chPad to the string from either side
1336 wxString
& wxString::Pad(size_t nCount
, wxUniChar chPad
, bool bFromRight
)
1338 wxString
s(chPad
, nCount
);
1351 // truncate the string
1352 wxString
& wxString::Truncate(size_t uiLen
)
1354 if ( uiLen
< length() )
1356 erase(begin() + uiLen
, end());
1358 //else: nothing to do, string is already short enough
1363 // ---------------------------------------------------------------------------
1364 // finding (return wxNOT_FOUND if not found and index otherwise)
1365 // ---------------------------------------------------------------------------
1368 int wxString::Find(wxUniChar ch
, bool bFromEnd
) const
1370 size_type idx
= bFromEnd
? find_last_of(ch
) : find_first_of(ch
);
1372 return (idx
== npos
) ? wxNOT_FOUND
: (int)idx
;
1375 // ----------------------------------------------------------------------------
1376 // conversion to numbers
1377 // ----------------------------------------------------------------------------
1379 // the implementation of all the functions below is exactly the same so factor
1382 template <typename T
, typename F
>
1383 bool wxStringToIntType(const wxChar
*start
,
1388 wxCHECK_MSG( val
, false, _T("NULL output pointer") );
1389 wxASSERT_MSG( !base
|| (base
> 1 && base
<= 36), _T("invalid base") );
1396 *val
= (*func
)(start
, &end
, base
);
1398 // return true only if scan was stopped by the terminating NUL and if the
1399 // string was not empty to start with and no under/overflow occurred
1400 return !*end
&& (end
!= start
)
1402 && (errno
!= ERANGE
)
1407 bool wxString::ToLong(long *val
, int base
) const
1409 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtol
);
1412 bool wxString::ToULong(unsigned long *val
, int base
) const
1414 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoul
);
1417 bool wxString::ToLongLong(wxLongLong_t
*val
, int base
) const
1419 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoll
);
1422 bool wxString::ToULongLong(wxULongLong_t
*val
, int base
) const
1424 return wxStringToIntType((const wxChar
*)c_str(), val
, base
, wxStrtoull
);
1427 bool wxString::ToDouble(double *val
) const
1429 wxCHECK_MSG( val
, false, _T("NULL pointer in wxString::ToDouble") );
1435 const wxChar
*start
= c_str();
1437 *val
= wxStrtod(start
, &end
);
1439 // return true only if scan was stopped by the terminating NUL and if the
1440 // string was not empty to start with and no under/overflow occurred
1441 return !*end
&& (end
!= start
)
1443 && (errno
!= ERANGE
)
1448 // ---------------------------------------------------------------------------
1450 // ---------------------------------------------------------------------------
1452 #if !wxUSE_UTF8_LOCALE_ONLY
1454 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1455 wxString
wxStringPrintfMixinBase::DoFormatWchar(const wxChar
*format
, ...)
1457 wxString
wxString::DoFormatWchar(const wxChar
*format
, ...)
1461 va_start(argptr
, format
);
1464 s
.PrintfV(format
, argptr
);
1470 #endif // !wxUSE_UTF8_LOCALE_ONLY
1472 #if wxUSE_UNICODE_UTF8
1474 wxString
wxString::DoFormatUtf8(const char *format
, ...)
1477 va_start(argptr
, format
);
1480 s
.PrintfV(format
, argptr
);
1486 #endif // wxUSE_UNICODE_UTF8
1489 wxString
wxString::FormatV(const wxString
& format
, va_list argptr
)
1492 s
.PrintfV(format
, argptr
);
1496 #if !wxUSE_UTF8_LOCALE_ONLY
1497 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1498 int wxStringPrintfMixinBase::DoPrintfWchar(const wxChar
*format
, ...)
1500 int wxString::DoPrintfWchar(const wxChar
*format
, ...)
1504 va_start(argptr
, format
);
1506 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
1507 // get a pointer to the wxString instance; we have to use dynamic_cast<>
1508 // because it's the only cast that works safely for downcasting when
1509 // multiple inheritance is used:
1510 wxString
*str
= static_cast<wxString
*>(this);
1512 wxString
*str
= this;
1515 int iLen
= str
->PrintfV(format
, argptr
);
1521 #endif // !wxUSE_UTF8_LOCALE_ONLY
1523 #if wxUSE_UNICODE_UTF8
1524 int wxString::DoPrintfUtf8(const char *format
, ...)
1527 va_start(argptr
, format
);
1529 int iLen
= PrintfV(format
, argptr
);
1535 #endif // wxUSE_UNICODE_UTF8
1537 #if wxUSE_UNICODE_UTF8
1538 template<typename BufferType
>
1540 // we only need one version in non-UTF8 builds and at least two Windows
1541 // compilers have problems with this function template, so use just one
1542 // normal function here
1544 static int DoStringPrintfV(wxString
& str
,
1545 const wxString
& format
, va_list argptr
)
1551 #if wxUSE_UNICODE_UTF8
1552 BufferType
tmp(str
, size
+ 1);
1553 typename
BufferType::CharType
*buf
= tmp
;
1555 wxStringBuffer
tmp(str
, size
+ 1);
1565 // wxVsnprintf() may modify the original arg pointer, so pass it
1568 wxVaCopy(argptrcopy
, argptr
);
1569 int len
= wxVsnprintf(buf
, size
, format
, argptrcopy
);
1572 // some implementations of vsnprintf() don't NUL terminate
1573 // the string if there is not enough space for it so
1574 // always do it manually
1575 buf
[size
] = _T('\0');
1577 // vsnprintf() may return either -1 (traditional Unix behaviour) or the
1578 // total number of characters which would have been written if the
1579 // buffer were large enough (newer standards such as Unix98)
1582 #if wxUSE_WXVSNPRINTF
1583 // we know that our own implementation of wxVsnprintf() returns -1
1584 // only for a format error - thus there's something wrong with
1585 // the user's format string
1587 #else // assume that system version only returns error if not enough space
1588 // still not enough, as we don't know how much we need, double the
1589 // current size of the buffer
1591 #endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
1593 else if ( len
>= size
)
1595 #if wxUSE_WXVSNPRINTF
1596 // we know that our own implementation of wxVsnprintf() returns
1597 // size+1 when there's not enough space but that's not the size
1598 // of the required buffer!
1599 size
*= 2; // so we just double the current size of the buffer
1601 // some vsnprintf() implementations NUL-terminate the buffer and
1602 // some don't in len == size case, to be safe always add 1
1606 else // ok, there was enough space
1612 // we could have overshot
1615 return str
.length();
1618 int wxString::PrintfV(const wxString
& format
, va_list argptr
)
1620 #if wxUSE_UNICODE_UTF8
1621 #if wxUSE_STL_BASED_WXSTRING
1622 typedef wxStringTypeBuffer
<char> Utf8Buffer
;
1624 typedef wxImplStringBuffer Utf8Buffer
;
1628 #if wxUSE_UTF8_LOCALE_ONLY
1629 return DoStringPrintfV
<Utf8Buffer
>(*this, format
, argptr
);
1631 #if wxUSE_UNICODE_UTF8
1632 if ( wxLocaleIsUtf8
)
1633 return DoStringPrintfV
<Utf8Buffer
>(*this, format
, argptr
);
1636 return DoStringPrintfV
<wxStringBuffer
>(*this, format
, argptr
);
1638 return DoStringPrintfV(*this, format
, argptr
);
1639 #endif // UTF8/WCHAR
1643 // ----------------------------------------------------------------------------
1644 // misc other operations
1645 // ----------------------------------------------------------------------------
1647 // returns true if the string matches the pattern which may contain '*' and
1648 // '?' metacharacters (as usual, '?' matches any character and '*' any number
1650 bool wxString::Matches(const wxString
& mask
) const
1652 // I disable this code as it doesn't seem to be faster (in fact, it seems
1653 // to be much slower) than the old, hand-written code below and using it
1654 // here requires always linking with libregex even if the user code doesn't
1656 #if 0 // wxUSE_REGEX
1657 // first translate the shell-like mask into a regex
1659 pattern
.reserve(wxStrlen(pszMask
));
1671 pattern
+= _T(".*");
1682 // these characters are special in a RE, quote them
1683 // (however note that we don't quote '[' and ']' to allow
1684 // using them for Unix shell like matching)
1685 pattern
+= _T('\\');
1689 pattern
+= *pszMask
;
1697 return wxRegEx(pattern
, wxRE_NOSUB
| wxRE_EXTENDED
).Matches(c_str());
1698 #else // !wxUSE_REGEX
1699 // TODO: this is, of course, awfully inefficient...
1701 // FIXME-UTF8: implement using iterators, remove #if
1702 #if wxUSE_UNICODE_UTF8
1703 wxWCharBuffer maskBuf
= mask
.wc_str();
1704 wxWCharBuffer txtBuf
= wc_str();
1705 const wxChar
*pszMask
= maskBuf
.data();
1706 const wxChar
*pszTxt
= txtBuf
.data();
1708 const wxChar
*pszMask
= mask
.wx_str();
1709 // the char currently being checked
1710 const wxChar
*pszTxt
= wx_str();
1713 // the last location where '*' matched
1714 const wxChar
*pszLastStarInText
= NULL
;
1715 const wxChar
*pszLastStarInMask
= NULL
;
1718 for ( ; *pszMask
!= wxT('\0'); pszMask
++, pszTxt
++ ) {
1719 switch ( *pszMask
) {
1721 if ( *pszTxt
== wxT('\0') )
1724 // pszTxt and pszMask will be incremented in the loop statement
1730 // remember where we started to be able to backtrack later
1731 pszLastStarInText
= pszTxt
;
1732 pszLastStarInMask
= pszMask
;
1734 // ignore special chars immediately following this one
1735 // (should this be an error?)
1736 while ( *pszMask
== wxT('*') || *pszMask
== wxT('?') )
1739 // if there is nothing more, match
1740 if ( *pszMask
== wxT('\0') )
1743 // are there any other metacharacters in the mask?
1745 const wxChar
*pEndMask
= wxStrpbrk(pszMask
, wxT("*?"));
1747 if ( pEndMask
!= NULL
) {
1748 // we have to match the string between two metachars
1749 uiLenMask
= pEndMask
- pszMask
;
1752 // we have to match the remainder of the string
1753 uiLenMask
= wxStrlen(pszMask
);
1756 wxString
strToMatch(pszMask
, uiLenMask
);
1757 const wxChar
* pMatch
= wxStrstr(pszTxt
, strToMatch
);
1758 if ( pMatch
== NULL
)
1761 // -1 to compensate "++" in the loop
1762 pszTxt
= pMatch
+ uiLenMask
- 1;
1763 pszMask
+= uiLenMask
- 1;
1768 if ( *pszMask
!= *pszTxt
)
1774 // match only if nothing left
1775 if ( *pszTxt
== wxT('\0') )
1778 // if we failed to match, backtrack if we can
1779 if ( pszLastStarInText
) {
1780 pszTxt
= pszLastStarInText
+ 1;
1781 pszMask
= pszLastStarInMask
;
1783 pszLastStarInText
= NULL
;
1785 // don't bother resetting pszLastStarInMask, it's unnecessary
1791 #endif // wxUSE_REGEX/!wxUSE_REGEX
1794 // Count the number of chars
1795 int wxString::Freq(wxUniChar ch
) const
1798 for ( const_iterator i
= begin(); i
!= end(); ++i
)
1806 // convert to upper case, return the copy of the string
1807 wxString
wxString::Upper() const
1808 { wxString
s(*this); return s
.MakeUpper(); }
1810 // convert to lower case, return the copy of the string
1811 wxString
wxString::Lower() const { wxString
s(*this); return s
.MakeLower(); }