diff --git a/include/wx/numformatter.h b/include/wx/numformatter.h index 13b47b210b..24ab702ab7 100644 --- a/include/wx/numformatter.h +++ b/include/wx/numformatter.h @@ -34,6 +34,8 @@ public: static wxString ToString(wxLongLong_t val, int style = Style_WithThousandsSep); #endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + static wxString ToString(wxULongLong_t val, + int style = Style_WithThousandsSep); static wxString ToString(double val, int precision, int style = Style_WithThousandsSep); @@ -46,6 +48,7 @@ public: #ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG static bool FromString(wxString s, wxLongLong_t *val); #endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + static bool FromString(wxString s, wxULongLong_t *val); static bool FromString(wxString s, double *val); diff --git a/interface/wx/numformatter.h b/interface/wx/numformatter.h index c6e0eaffe2..1479bae1c4 100644 --- a/interface/wx/numformatter.h +++ b/interface/wx/numformatter.h @@ -73,6 +73,7 @@ public: //@{ static wxString ToString(long val, int flags = Style_WithThousandsSep); static wxString ToString(long long val, int flags = Style_WithThousandsSep); + static wxString ToString(unsigned long long val, int flags = Style_WithThousandsSep); //@} /** @@ -97,11 +98,18 @@ public: success they return @true and store the result at the location pointed to by @a val (which can't be @NULL), otherwise @false is returned. + Note that the overload taking unsigned long long value is only + available since wxWidgets 3.1.5. Also, unlike wxString::ToULongLong() + and the standard functions such as @c strtoul(), this overload does + @em not accept, i.e. returns @false, for the strings starting with the + minus sign. + @see wxString::ToLong(), wxString::ToDouble() */ //@{ static bool FromString(wxString s, long *val); static bool FromString(wxString s, long long *val); + static bool FromString(wxString s, unsigned long long *val); static bool FromString(wxString s, double *val); //@} diff --git a/src/common/numformatter.cpp b/src/common/numformatter.cpp index 1bf8497712..e57ab02335 100644 --- a/src/common/numformatter.cpp +++ b/src/common/numformatter.cpp @@ -198,6 +198,12 @@ wxString wxNumberFormatter::ToString(wxLongLong_t val, int style) #endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG +wxString wxNumberFormatter::ToString(wxULongLong_t val, int style) +{ + return PostProcessIntString(wxString::Format("%" wxLongLongFmtSpec "u", val), + style); +} + wxString wxNumberFormatter::ToString(double val, int precision, int style) { wxString s = wxString::FromDouble(val,precision); @@ -300,6 +306,27 @@ bool wxNumberFormatter::FromString(wxString s, wxLongLong_t *val) #endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG +bool wxNumberFormatter::FromString(wxString s, wxULongLong_t *val) +{ + RemoveThousandsSeparators(s); + + // wxString::ToULongLong() does accept minus sign for unsigned integers, + // consistently with the standard functions behaviour, e.g. strtoul() does + // the same thing, but here we really want to accept the "true" unsigned + // numbers only, so check for leading minus, possibly preceded by some + // whitespace. + for ( wxString::const_iterator it = s.begin(); it != s.end(); ++it ) + { + if ( *it == '-' ) + return false; + + if ( *it != ' ' && *it != '\t' ) + break; + } + + return s.ToULongLong(val); +} + bool wxNumberFormatter::FromString(wxString s, double *val) { RemoveThousandsSeparators(s); diff --git a/tests/strings/numformatter.cpp b/tests/strings/numformatter.cpp index d93f6c3244..b9445190dc 100644 --- a/tests/strings/numformatter.cpp +++ b/tests/strings/numformatter.cpp @@ -206,6 +206,10 @@ TEST_CASE_METHOD(NumFormatterTestCase, "NumFormatter::LongLongFromString", "[num CHECK( !wxNumberFormatter::FromString("", &l) ); CHECK( !wxNumberFormatter::FromString("foo", &l) ); CHECK( !wxNumberFormatter::FromString("1.234", &l) ); + CHECK( !wxNumberFormatter::FromString("-", &l) ); + + CHECK( wxNumberFormatter::FromString("0", &l) ); + CHECK( l == 0 ); CHECK( wxNumberFormatter::FromString("123", &l) ); CHECK( l == 123 ); @@ -224,10 +228,63 @@ TEST_CASE_METHOD(NumFormatterTestCase, "NumFormatter::LongLongFromString", "[num CHECK( wxNumberFormatter::FromString("1,234,567", &l) ); CHECK( l == 1234567 ); + + CHECK( wxNumberFormatter::FromString("-123", &l) ); + CHECK( l == -123 ); + + CHECK( wxNumberFormatter::FromString("9223372036854775807", &l) ); + CHECK( l == wxINT64_MAX ); + + CHECK( !wxNumberFormatter::FromString("9223372036854775808", &l) ); } #endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG +TEST_CASE_METHOD(NumFormatterTestCase, "NumFormatter::ULongLongFromString", "[numformatter]") +{ + if ( !CanRunTest() ) + return; + + wxULongLong_t u; + CHECK( !wxNumberFormatter::FromString("", &u) ); + CHECK( !wxNumberFormatter::FromString("bar", &u) ); + CHECK( !wxNumberFormatter::FromString("1.234", &u) ); + CHECK( !wxNumberFormatter::FromString("-2", &u) ); + CHECK( !wxNumberFormatter::FromString("-", &u) ); + + CHECK( wxNumberFormatter::FromString("0", &u) ); + CHECK( u == 0 ); + + CHECK( wxNumberFormatter::FromString("123", &u) ); + CHECK( u == 123 ); + + CHECK( wxNumberFormatter::FromString("1234", &u) ); + CHECK( u == 1234 ); + + CHECK( wxNumberFormatter::FromString("1,234", &u) ); + CHECK( u == 1234 ); + + CHECK( wxNumberFormatter::FromString("12,345", &u) ); + CHECK( u == 12345 ); + + CHECK( wxNumberFormatter::FromString("123,456", &u) ); + CHECK( u == 123456 ); + + CHECK( wxNumberFormatter::FromString("1,234,567", &u) ); + CHECK( u == 1234567 ); + + CHECK( wxNumberFormatter::FromString("9223372036854775807", &u) ); + CHECK( u == static_cast(wxINT64_MAX) ); + + CHECK( wxNumberFormatter::FromString("9223372036854775808", &u) ); + CHECK( u == static_cast(wxINT64_MAX) + 1 ); + + CHECK( wxNumberFormatter::FromString("18446744073709551615", &u) ); + CHECK( u == wxUINT64_MAX ); + + CHECK( !wxNumberFormatter::FromString("18446744073709551616", &u) ); +} + TEST_CASE_METHOD(NumFormatterTestCase, "NumFormatter::DoubleFromString", "[numformatter]") { if ( !CanRunTest() )