#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;
// 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*
}
//Convert wxString in Unicode mode to a multi-byte string
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 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 wxScopedCharBuffer wxString::mb_str(const wxMBConv& conv) const
{
if ( conv.IsUTF8() )
- return wxScopedCharBuffer::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;
- wxScopedWCharBuffer 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
//mode is not enabled and wxUSE_WCHAR_T is enabled
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
}