#include "wx/msw/wrapwin.h"
#endif // __WXMSW__
+#if wxUSE_STD_IOSTREAM
+ #include <sstream>
+#endif
+
// string handling functions used by wxString:
#if wxUSE_UNICODE_UTF8
#define wxStringMemcpy memcpy
int wxString::CmpNoCase(const wxString& s) const
{
-#if defined(__WXMSW__) && !wxUSE_UNICODE_UTF8
- // Prefer to use CompareString() if available as it's more efficient than
- // doing it manually or even using wxStricmp() (see #10375)
- //
- // Also note that not using NORM_STRINGSORT may result in not having a
- // strict weak ordering (e.g. s1 < s2 and s2 < s3 but s3 < s1) and so break
- // algorithms such as std::sort that rely on it. It's also more consistent
- // with the fall back version below.
- switch ( ::CompareString(LOCALE_USER_DEFAULT,
- NORM_IGNORECASE | SORT_STRINGSORT,
- m_impl.c_str(), m_impl.length(),
- s.m_impl.c_str(), s.m_impl.length()) )
+#if !wxUSE_UNICODE_UTF8
+ // We compare NUL-delimited chunks of the strings inside the loop. We will
+ // do as many iterations as there are embedded NULs in the string, i.e.
+ // usually we will run it just once.
+
+ typedef const wxStringImpl::value_type *pchar_type;
+ const pchar_type thisBegin = m_impl.c_str();
+ const pchar_type thatBegin = s.m_impl.c_str();
+
+ const pchar_type thisEnd = thisBegin + m_impl.length();
+ const pchar_type thatEnd = thatBegin + s.m_impl.length();
+
+ pchar_type thisCur = thisBegin;
+ pchar_type thatCur = thatBegin;
+
+ int rc;
+ for ( ;; )
{
- case CSTR_LESS_THAN:
- return -1;
+ // Compare until the next NUL, if the strings differ this is the final
+ // result.
+ rc = wxStricmp(thisCur, thatCur);
+ if ( rc )
+ break;
- case CSTR_EQUAL:
- return 0;
+ const size_t lenChunk = wxStrlen(thisCur);
+ thisCur += lenChunk;
+ thatCur += lenChunk;
- case CSTR_GREATER_THAN:
- return 1;
+ // Skip all the NULs as wxStricmp() doesn't handle them.
+ for ( ; !*thisCur; thisCur++, thatCur++ )
+ {
+ // Check if we exhausted either of the strings.
+ if ( thisCur == thisEnd )
+ {
+ // This one is exhausted, is the other one too?
+ return thatCur == thatEnd ? 0 : -1;
+ }
- default:
- wxFAIL_MSG( "unexpected CompareString() return value" );
- // fall through
+ if ( thatCur == thatEnd )
+ {
+ // Because of the test above we know that this one is not
+ // exhausted yet so it's greater than the other one that is.
+ return 1;
+ }
- case 0:
- wxLogLastError("CompareString");
- // use generic code below
+ if ( *thatCur )
+ {
+ // Anything non-NUL is greater than NUL.
+ return -1;
+ }
+ }
}
-#endif // __WXMSW__ && !wxUSE_UNICODE_UTF8
- // do the comparison manually: notice that we can't use wxStricmp() as it
- // doesn't handle embedded NULs
+ return rc;
+#else // wxUSE_UNICODE_UTF8
+ // CRT functions can't be used for case-insensitive comparison of UTF-8
+ // strings so do it in the naive, simple and inefficient way.
// FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
const_iterator i1 = begin();
else if ( len1 > len2 )
return 1;
return 0;
+#endif // !wxUSE_UNICODE_UTF8/wxUSE_UNICODE_UTF8
}
#endif // wxUSE_XLOCALE/!wxUSE_XLOCALE
+// ----------------------------------------------------------------------------
+// number to string conversion
+// ----------------------------------------------------------------------------
+
+/* static */
+wxString wxString::FromCDouble(double val)
+{
+#if wxUSE_STD_IOSTREAM && wxUSE_STD_STRING
+ // We assume that we can use the ostream and not wstream for numbers.
+ wxSTD ostringstream os;
+ os << val;
+ return os.str();
+#else // wxUSE_STD_IOSTREAM
+ // Can't use iostream locale support, fall back to the manual method
+ // instead.
+ wxString s = FromDouble(val);
+#if wxUSE_INTL
+ wxString sep = wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT,
+ wxLOCALE_CAT_NUMBER);
+#else // !wxUSE_INTL
+ // As above, this is the most common alternative value. Notice that here it
+ // doesn't matter if we guess wrongly and the current separator is already
+ // ".": we'll just waste a call to Replace() in this case.
+ wxString sep(",");
+#endif // wxUSE_INTL/!wxUSE_INTL
+
+ s.Replace(sep, ".");
+ return s;
+#endif // wxUSE_STD_IOSTREAM/!wxUSE_STD_IOSTREAM
+}
+
// ---------------------------------------------------------------------------
// formatted output
// ---------------------------------------------------------------------------
if ( !buf )
{
// out of memory
-
- // in UTF-8 build, leaving uninitialized junk in the buffer
- // could result in invalid non-empty UTF-8 string, so just
- // reset the string to empty on failure:
- buf[0] = '\0';
return -1;
}