From 951201d81c463d55edb4b316002c7fa5c8291603 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin <vadim@wxwidgets.org> Date: Mon, 31 May 2010 11:55:48 +0000 Subject: [PATCH] Add wxString::FromDouble() and FromCDouble(). wxString::FromCDouble() is needed inside wxWidgets itself to format numbers independently of the current locale. FromDouble() was added for symmetry with ToDouble/ToCDouble() functions. Use std::locale for the implementation if available and manual wxLocale-based fallback otherwise. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64449 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/string.h | 7 +++++++ interface/wx/string.h | 30 ++++++++++++++++++++++++++++++ src/common/string.cpp | 35 +++++++++++++++++++++++++++++++++++ tests/strings/strings.cpp | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) diff --git a/include/wx/string.h b/include/wx/string.h index 369d30c505..58a6ed7cd8 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -2288,6 +2288,13 @@ public: // convert to a double bool ToCDouble(double *val) const; + // create a string representing the given floating point number + // in the current locale + static wxString FromDouble(double val) + { return wxString::Format(wxS("%g"), val); } + // in C locale + static wxString FromCDouble(double val); + #ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN // formatted input/output // as sprintf(), returns the number of characters written or < 0 on error diff --git a/interface/wx/string.h b/interface/wx/string.h index 90ee7d718f..74f34ad6da 100644 --- a/interface/wx/string.h +++ b/interface/wx/string.h @@ -1507,6 +1507,36 @@ public: static wxString FromAscii(char c); //@} + /** + Returns a string with the textual representation of the number in C + locale. + + Unlike FromDouble() the string returned by this function always uses + the period character as decimal separator, independently of the current + locale. + + @since 2.9.1 + + @see ToCDouble() + */ + static wxString FromCDouble(double val); + + /** + Returns a string with the textual representation of the number. + + This is a simple wrapper for @code wxString::Format("%g", val) + @endcode. + + Notice that the string returned by this function uses the decimal + separator appropriate for the current locale, e.g. @c "," and not a + period in French locale. Use FromCDouble() if this is unwanted. + + @since 2.9.1 + + @see ToDouble() + */ + static wxString FromDouble(double val); + //@{ /** Converts C string encoded in UTF-8 to wxString. diff --git a/src/common/string.cpp b/src/common/string.cpp index 952727ec62..a0d42cb42f 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -45,6 +45,10 @@ #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 @@ -1785,6 +1789,37 @@ bool wxString::ToCDouble(double *pVal) const #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 // --------------------------------------------------------------------------- diff --git a/tests/strings/strings.cpp b/tests/strings/strings.cpp index d27644b565..0bfa1be370 100644 --- a/tests/strings/strings.cpp +++ b/tests/strings/strings.cpp @@ -53,6 +53,7 @@ private: CPPUNIT_TEST( ToULongLong ); #endif // wxLongLong_t CPPUNIT_TEST( ToDouble ); + CPPUNIT_TEST( FromDouble ); CPPUNIT_TEST( StringBuf ); CPPUNIT_TEST( UTF8Buf ); CPPUNIT_TEST( CStrDataTernaryOperator ); @@ -85,6 +86,7 @@ private: void ToULongLong(); #endif // wxLongLong_t void ToDouble(); + void FromDouble(); void StringBuf(); void UTF8Buf(); void CStrDataTernaryOperator(); @@ -747,6 +749,41 @@ void StringTestCase::ToDouble() } } +void StringTestCase::FromDouble() +{ + static const struct FromDoubleTestData + { + double value; + const char *str; + } testData[] = + { + { 1.23, "1.23" }, + { -3e-10, "-3e-10" }, + { -0.45678, "-0.45678" }, + }; + + for ( unsigned n = 0; n < WXSIZEOF(testData); n++ ) + { + const FromDoubleTestData& td = testData[n]; + CPPUNIT_ASSERT_EQUAL( td.str, wxString::FromCDouble(td.value) ); + } + + if ( !wxLocale::IsAvailable(wxLANGUAGE_FRENCH) ) + return; + + wxLocale locale; + CPPUNIT_ASSERT( locale.Init(wxLANGUAGE_FRENCH, wxLOCALE_DONT_LOAD_DEFAULT) ); + + for ( unsigned m = 0; m < WXSIZEOF(testData); m++ ) + { + const FromDoubleTestData& td = testData[m]; + + wxString str(td.str); + str.Replace(".", ","); + CPPUNIT_ASSERT_EQUAL( str, wxString::FromDouble(td.value) ); + } +} + void StringTestCase::StringBuf() { // check that buffer can be used to write into the string -- 2.47.2