diff --git a/src/util/numeric_conversion.hpp b/src/util/numeric_conversion.hpp index b0f53460..5cc15bf9 100644 --- a/src/util/numeric_conversion.hpp +++ b/src/util/numeric_conversion.hpp @@ -131,11 +131,13 @@ namespace boost { namespace locale { namespace util { template bool try_parse_icu(icu::Formattable& fmt, Integer& value) { + if(!fmt.isNumeric()) + return false; // Get value as a decimal number and parse that UErrorCode err = U_ZERO_ERROR; const auto decimals = fmt.getDecimalNumber(err); if(U_FAILURE(err)) - return false; // Not a number + return false; // Memory error LCOV_EXCL_LINE const core::string_view s(decimals.data(), decimals.length()); return try_scientific_to_int(s, value); } diff --git a/test/test_formatting.cpp b/test/test_formatting.cpp index c05ad6ea..96ee25f3 100644 --- a/test/test_formatting.cpp +++ b/test/test_formatting.cpp @@ -412,6 +412,7 @@ void test_manip(std::string e_charset = "UTF-8") TEST_PARSE_FAILS(as::percent, "1", double); TEST_FMT_PARSE_1(as::currency, 1345, "$1,345.00"); + TEST_FMT_PARSE_1(as::currency, uint64_t(1345), "$1,345.00"); TEST_FMT_PARSE_1(as::currency, 1345.34, "$1,345.34"); TEST_PARSE_FAILS(as::currency, "$", double); @@ -434,6 +435,7 @@ void test_manip(std::string e_charset = "UTF-8") TEST_FMT_PARSE_3_2(as::date, as::date_medium, as::gmt, a_datetime, "Feb 5, 1970", a_date); TEST_FMT_PARSE_3_2(as::date, as::date_long, as::gmt, a_datetime, "February 5, 1970", a_date); TEST_FMT_PARSE_3_2(as::date, as::date_full, as::gmt, a_datetime, "Thursday, February 5, 1970", a_date); + TEST_FMT_PARSE_2_2(as::date, as::gmt, uint64_t(a_datetime), "Feb 5, 1970", uint64_t(a_date)); TEST_PARSE_FAILS(as::date >> as::date_short, "aa/bb/cc", double); @@ -885,8 +887,8 @@ void test_uint64_format() std::unique_ptr fmt{icu::NumberFormat::createInstance(*cur_locale, err)}; icu::UnicodeString s; fmt->format(short_value, s, nullptr, err); - if(U_FAILURE(err)) - continue; + if(U_SUCCESS(err)) + continue; // LCOV_EXCL_LINE const std::string icu_value = boost::locale::conv::utf_to_utf(s.getBuffer(), s.getBuffer() + s.length()); std::stringstream ss; ss.imbue(g(cur_locale->getName() + utf8)); @@ -897,9 +899,10 @@ void test_uint64_format() // Assumption: Either both the int32 and uint64 values are in POSIX format, or neither are // This is the case if separators are used and/or numbers are not ASCII + // All languages likely use separators so not running into the POSIX case is OK. empty_stream(ss) << value; if(icu_value == posix_short_value) - TEST_EQ(ss.str(), posix_value); + TEST_EQ(ss.str(), posix_value); // LCOV_EXCL_LINE else TEST_NE(ss.str(), posix_value); diff --git a/test/test_util_numeric_convert.cpp b/test/test_util_numeric_convert.cpp index 309a68e7..f09ccb75 100644 --- a/test/test_util_numeric_convert.cpp +++ b/test/test_util_numeric_convert.cpp @@ -91,7 +91,7 @@ void test_try_scientific_to_int() // clang-format off "-1.1E1", // Too large - "256", "256E0", "2.56E2", "3.0E2", + "256", "256E0", "2.56E2", "3.0E2", "3.00E2", "300", "399", "3.99E2", "999", "9.99E2", "1000","1000E0", "100E1", "10E2", "1E3","1.0E3", // negative "-1", "-1.1E1", @@ -172,6 +172,11 @@ void test_try_parse_icu() TEST(!boost::locale::util::try_parse_icu(parsedByICU, parsedVal)); } } + { + icu::Formattable invalidNumber{"Str"}; + uint64_t parsedVal{}; + TEST(!boost::locale::util::try_parse_icu(invalidNumber, parsedVal)); + } // Test some numbers randomly to find missed cases std::mt19937_64 mt{std::random_device{}()}; std::uniform_int_distribution distr;