#ifndef WX_PRECOMP
#include "wx/string.h"
#include "wx/wxcrtvararg.h"
+ #include "wx/log.h"
#endif
#include <ctype.h>
#include "wx/vector.h"
#include "wx/xlocale.h"
+#ifdef __WXMSW__
+ #include "wx/msw/wrapwin.h"
+#endif // __WXMSW__
+
// string handling functions used by wxString:
#if wxUSE_UNICODE_UTF8
#define wxStringMemcpy memcpy
namespace wxPrivate
{
-static UntypedBufferData s_untypedNullData(NULL);
+static UntypedBufferData s_untypedNullData(NULL, 0);
UntypedBufferData * const untypedNullDataPtr = &s_untypedNullData;
// gdb seems to be unable to display thread-local variables correctly, at least
// not my 6.4.98 version under amd64, so provide this debugging helper to do it
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL >= 2
struct wxStrCacheDumper
{
void wxDumpStrCache() { wxStrCacheDumper::ShowAll(); }
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL >= 2
#ifdef wxPROFILE_STRING_CACHE
wxSTD ostream& operator<<(wxSTD ostream& os, const wxCStrData& str)
{
#if wxUSE_UNICODE && !wxUSE_UNICODE_UTF8
- const wxCharBuffer buf(str.AsCharBuf());
+ const wxScopedCharBuffer buf(str.AsCharBuf());
if ( !buf )
os.clear(wxSTD ios_base::failbit);
else
return os << str.c_str();
}
-wxSTD ostream& operator<<(wxSTD ostream& os, const wxCharBuffer& str)
+wxSTD ostream& operator<<(wxSTD ostream& os, const wxScopedCharBuffer& str)
{
return os << str.data();
}
#ifndef __BORLANDC__
-wxSTD ostream& operator<<(wxSTD ostream& os, const wxWCharBuffer& str)
+wxSTD ostream& operator<<(wxSTD ostream& os, const wxScopedWCharBuffer& str)
{
return os << str.data();
}
return wos << str.AsWChar();
}
-wxSTD wostream& operator<<(wxSTD wostream& wos, const wxWCharBuffer& str)
+wxSTD wostream& operator<<(wxSTD wostream& wos, const wxScopedWCharBuffer& str)
{
return wos << str.data();
}
// adding more fields to wxString and require profiling results
// to be sure that we really gain enough from them to justify
// doing it.
- wxCharBuffer buf(str->mb_str());
+ wxScopedCharBuffer buf(str->mb_str());
// if it failed, return empty string and not NULL to avoid crashes in code
// written with either wxWidgets 2 wxString or std::string behaviour in
wxString *str = wxConstCast(m_str, wxString);
// convert the string:
- wxWCharBuffer buf(str->wc_str());
+ wxScopedWCharBuffer buf(str->wc_str());
// notice that here, unlike above in AsChar(), conversion can't fail as our
// internal UTF-8 is always well-formed -- or the string was corrupted and
{
// anything to do?
if ( !psz || nLength == 0 )
- return SubstrBufFromMB(L"", 0);
+ return SubstrBufFromMB(wxWCharBuffer(L""), 0);
if ( nLength == npos )
nLength = wxNO_LEN;
size_t wcLen;
- wxWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
+ wxScopedWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
if ( !wcLen )
- return SubstrBufFromMB(_T(""), 0);
+ return SubstrBufFromMB(wxWCharBuffer(L""), 0);
else
return SubstrBufFromMB(wcBuf, wcLen);
}
{
// anything to do?
if ( !psz || nLength == 0 )
- return SubstrBufFromMB("", 0);
+ return SubstrBufFromMB(wxCharBuffer(""), 0);
// if psz is already in UTF-8, we don't have to do the roundtrip to
// wchar_t* and back:
// we must pass the real string length to SubstrBufFromMB ctor
if ( nLength == npos )
nLength = psz ? strlen(psz) : 0;
- return SubstrBufFromMB(wxCharBuffer::CreateNonOwned(psz), nLength);
+ return SubstrBufFromMB(wxScopedCharBuffer::CreateNonOwned(psz, nLength),
+ nLength);
}
// else: do the roundtrip through wchar_t*
}
// first convert to wide string:
size_t wcLen;
- wxWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
+ wxScopedWCharBuffer wcBuf(conv.cMB2WC(psz, nLength, &wcLen));
if ( !wcLen )
- return SubstrBufFromMB("", 0);
+ return SubstrBufFromMB(wxCharBuffer(""), 0);
// and then to UTF-8:
SubstrBufFromMB buf(ConvertStr(wcBuf, wcLen, wxMBConvStrictUTF8()));
{
// anything to do?
if ( !pwz || nLength == 0 )
- return SubstrBufFromWC("", 0);
+ return SubstrBufFromWC(wxCharBuffer(""), 0);
if ( nLength == npos )
nLength = wxNO_LEN;
size_t mbLen;
- wxCharBuffer mbBuf(conv.cWC2MB(pwz, nLength, &mbLen));
+ wxScopedCharBuffer mbBuf(conv.cWC2MB(pwz, nLength, &mbLen));
if ( !mbLen )
- return SubstrBufFromWC("", 0);
+ return SubstrBufFromWC(wxCharBuffer(""), 0);
else
return SubstrBufFromWC(mbBuf, mbLen);
}
#if wxUSE_UNICODE_WCHAR
//Convert wxString in Unicode mode to a multi-byte string
-const wxCharBuffer wxString::mb_str(const wxMBConv& conv) const
+const wxScopedCharBuffer wxString::mb_str(const wxMBConv& conv) const
{
- return conv.cWC2MB(wx_str(), length() + 1 /* size, not length */, NULL);
+ // NB: Length passed to cWC2MB() doesn't include terminating NUL, it's
+ // added by it automatically. If we passed length()+1 here, it would
+ // create a buffer with 2 trailing NULs of length one greater than
+ // expected.
+ return conv.cWC2MB(wx_str(), length(), NULL);
}
#elif wxUSE_UNICODE_UTF8
-const wxWCharBuffer wxString::wc_str() const
+const wxScopedWCharBuffer wxString::wc_str() const
{
+ // NB: Length passed to cMB2WC() doesn't include terminating NUL, it's
+ // added by it automatically. If we passed length()+1 here, it would
+ // create a buffer with 2 trailing NULs of length one greater than
+ // expected.
return wxMBConvStrictUTF8().cMB2WC
(
m_impl.c_str(),
- m_impl.length() + 1, // size, not length
+ m_impl.length(),
NULL
);
}
-const wxCharBuffer wxString::mb_str(const wxMBConv& conv) const
+const wxScopedCharBuffer wxString::mb_str(const wxMBConv& conv) const
{
if ( conv.IsUTF8() )
- return wxCharBuffer::CreateNonOwned(m_impl.c_str());
-
- // FIXME-UTF8: use wc_str() here once we have buffers with length
+ return wxScopedCharBuffer::CreateNonOwned(m_impl.c_str(), m_impl.length());
- size_t wcLen;
- wxWCharBuffer wcBuf(wxMBConvStrictUTF8().cMB2WC
- (
- m_impl.c_str(),
- m_impl.length() + 1, // size
- &wcLen
- ));
- if ( !wcLen )
+ wxScopedWCharBuffer wcBuf(wc_str());
+ if ( !wcBuf.length() )
return wxCharBuffer("");
- return conv.cWC2MB(wcBuf, wcLen+1, NULL);
+ return conv.cWC2MB(wcBuf.data(), wcBuf.length(), NULL);
}
#else // ANSI
//Converts this string to a wide character string if unicode
//mode is not enabled and wxUSE_WCHAR_T is enabled
-const wxWCharBuffer wxString::wc_str(const wxMBConv& conv) const
+const wxScopedWCharBuffer wxString::wc_str(const wxMBConv& conv) const
{
- return conv.cMB2WC(wx_str(), length() + 1 /* size, not length */, NULL);
+ // NB: Length passed to cMB2WC() doesn't include terminating NUL, it's
+ // added by it automatically. If we passed length()+1 here, it would
+ // create a buffer with 2 trailing NULs of length one greater than
+ // expected.
+ return conv.cMB2WC(wx_str(), length(), NULL);
}
#endif // Unicode/ANSI
int wxString::CmpNoCase(const wxString& s) const
{
-#if wxUSE_UNICODE_UTF8
- // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
+#if defined(__WXMSW__) && !wxUSE_UNICODE_UTF8
+ // prefer to use CompareString() if available as it's more efficient than
+ // doing it manual or even using wxStricmp() (see #10375)
+ switch ( ::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
+ m_impl.c_str(), m_impl.length(),
+ s.m_impl.c_str(), s.m_impl.length()) )
+ {
+ case CSTR_LESS_THAN:
+ return -1;
+ case CSTR_EQUAL:
+ return 0;
+
+ case CSTR_GREATER_THAN:
+ return 1;
+
+ default:
+ wxFAIL_MSG( "unexpected CompareString() return value" );
+ // fall through
+
+ case 0:
+ wxLogLastError("CompareString");
+ // use generic code below
+ }
+#endif // __WXMSW__ && !wxUSE_UNICODE_UTF8
+
+ // do the comparison manually: notice that we can't use wxStricmp() as it
+ // doesn't handle embedded NULs
+
+ // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
const_iterator i1 = begin();
const_iterator end1 = end();
const_iterator i2 = s.begin();
else if ( len1 > len2 )
return 1;
return 0;
-#else // wxUSE_UNICODE_WCHAR or ANSI
- return wxStricmp(m_impl.c_str(), s.m_impl.c_str());
-#endif
}
return wxString(wxUniChar((wchar_t)c));
}
-const wxCharBuffer wxString::ToAscii() const
+const wxScopedCharBuffer wxString::ToAscii() const
{
// this will allocate enough space for the terminating NUL too
wxCharBuffer buffer(length());
// FIXME-UTF8: implement using iterators, remove #if
#if wxUSE_UNICODE_UTF8
- wxWCharBuffer maskBuf = mask.wc_str();
- wxWCharBuffer txtBuf = wc_str();
+ const wxScopedWCharBuffer maskBuf = mask.wc_str();
+ const wxScopedWCharBuffer txtBuf = wc_str();
const wxChar *pszMask = maskBuf.data();
const wxChar *pszTxt = txtBuf.data();
#else