From ff04436fe542a0e74f4b5e9b9e3d69b6f49d4a3d Mon Sep 17 00:00:00 2001 From: Peter Edberg Date: Tue, 5 Feb 2019 11:34:29 -0800 Subject: [PATCH] ICU-20374 Formattable::internalGetCharString should produce int string for types kLong or kInt64 --- icu4c/source/i18n/fmtable.cpp | 3 +- icu4c/source/test/cintltst/cnumtst.c | 87 +++++++++++++++++++++++++ icu4c/source/test/intltest/numfmtst.cpp | 2 +- 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/icu4c/source/i18n/fmtable.cpp b/icu4c/source/i18n/fmtable.cpp index 8601d95f4a6..546abd6e133 100644 --- a/icu4c/source/i18n/fmtable.cpp +++ b/icu4c/source/i18n/fmtable.cpp @@ -734,7 +734,8 @@ CharString *Formattable::internalGetCharString(UErrorCode &status) { // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?). if (fDecimalQuantity->isZero()) { fDecimalStr->append("0", -1, status); - } else if (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5) { + } else if (fType==kLong || fType==kInt64 || // use toPlainString for integer types + fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5) { fDecimalStr->appendInvariantChars(fDecimalQuantity->toPlainString(), status); } else { fDecimalStr->appendInvariantChars(fDecimalQuantity->toScientificString(), status); diff --git a/icu4c/source/test/cintltst/cnumtst.c b/icu4c/source/test/cintltst/cnumtst.c index bc1ee209503..8ecab85324b 100644 --- a/icu4c/source/test/cintltst/cnumtst.c +++ b/icu4c/source/test/cintltst/cnumtst.c @@ -67,6 +67,7 @@ static void TestParseCurrPatternWithDecStyle(void); static void TestFormatForFields(void); static void TestRBNFRounding(void); static void Test12052_NullPointer(void); +static void TestParseCases(void); #define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x) @@ -100,6 +101,7 @@ void addNumForTest(TestNode** root) TESTCASE(TestParseCurrPatternWithDecStyle); TESTCASE(TestFormatForFields); TESTCASE(Test12052_NullPointer); + TESTCASE(TestParseCases); } /* test Parse int 64 */ @@ -3082,4 +3084,89 @@ static void Test12052_NullPointer() { unum_close(theFormatter); } +typedef struct { + const char* locale; + const UChar* text; // text to parse + UBool lenient; // leniency to use + UBool intOnly; // whether to set PARSE_INT_ONLY + UErrorCode intStatus; // expected status from parse + int32_t intPos; // expected final pos from parse + int32_t intValue; // expected value from parse + UErrorCode doubStatus; // expected status from parseDouble + int32_t doubPos; // expected final pos from parseDouble + double doubValue; // expected value from parseDouble + UErrorCode decStatus; // expected status from parseDecimal + int32_t decPos; // expected final pos from parseDecimal + const char* decString; // expected output string from parseDecimal + +} ParseCaseItem; + +static const ParseCaseItem parseCaseItems[] = { + { "en", u"0,000", FALSE, FALSE, U_ZERO_ERROR, 5, 0, U_ZERO_ERROR, 5, 0.0, U_ZERO_ERROR, 5, "0" }, + { "en", u"0,000", TRUE, FALSE, U_ZERO_ERROR, 5, 0, U_ZERO_ERROR, 5, 0.0, U_ZERO_ERROR, 5, "0" }, + { "en", u"1000,000", FALSE, FALSE, U_PARSE_ERROR, 0, 0, U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, "" }, + { "en", u"1000,000", TRUE, FALSE, U_ZERO_ERROR, 8, 1000000, U_ZERO_ERROR, 8, 1000000.0, U_ZERO_ERROR, 8, "1000000" }, + { "en", u"9999990000503021", FALSE, FALSE, U_INVALID_FORMAT_ERROR, 16, 2147483647, U_ZERO_ERROR, 16, 9999990000503020.0, U_ZERO_ERROR, 16, "9999990000503021" }, + { "en", u"9999990000503021", FALSE, TRUE, U_INVALID_FORMAT_ERROR, 16, 2147483647, U_ZERO_ERROR, 16, 9999990000503020.0, U_ZERO_ERROR, 16, "9999990000503021" }, + { "en", u"1000000.5", FALSE, FALSE, U_ZERO_ERROR, 9, 1000000, U_ZERO_ERROR, 9, 1000000.5, U_ZERO_ERROR, 9, "1.0000005E+6"}, + { "en", u"1000000.5", FALSE, TRUE, U_ZERO_ERROR, 7, 1000000, U_ZERO_ERROR, 7, 1000000.0, U_ZERO_ERROR, 7, "1000000" }, + { "en", u"123.5", FALSE, FALSE, U_ZERO_ERROR, 5, 123, U_ZERO_ERROR, 5, 123.5, U_ZERO_ERROR, 5, "123.5" }, + { "en", u"123.5", FALSE, TRUE, U_ZERO_ERROR, 3, 123, U_ZERO_ERROR, 3, 123.0, U_ZERO_ERROR, 3, "123" }, + { NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0, NULL } +}; + +static void TestParseCases(void) { + const ParseCaseItem* itemPtr; + for (itemPtr = parseCaseItems; itemPtr->locale != NULL; itemPtr++) { + UErrorCode status = U_ZERO_ERROR; + UNumberFormat* unumDec = unum_open(UNUM_DECIMAL, NULL, 0, itemPtr->locale, NULL, &status); + if (U_FAILURE(status)) { + log_data_err("unum_open UNUM_DECIMAL fails for locale %s: %s\n", itemPtr->locale, u_errorName(status)); + continue; + } + int32_t intValue, parsePos, dclen; + double doubValue; + char decstr[32]; + unum_setAttribute(unumDec, UNUM_LENIENT_PARSE, itemPtr->lenient); + unum_setAttribute(unumDec, UNUM_PARSE_INT_ONLY, itemPtr->intOnly); + + parsePos = 0; + status = U_ZERO_ERROR; + intValue = unum_parse(unumDec, itemPtr->text, -1, &parsePos, &status); + if (status != itemPtr->intStatus || parsePos != itemPtr->intPos || intValue != itemPtr->intValue) { + char btext[32]; + u_austrcpy(btext, itemPtr->text); + log_err("locale %s, text \"%s\", lenient %d, intOnly %d;\n parse expected status %s, pos %d, value %d;\n got %s, %d, %d\n", + itemPtr->locale, btext, itemPtr->lenient, itemPtr->intOnly, + u_errorName(itemPtr->intStatus), itemPtr->intPos, itemPtr->intValue, + u_errorName(status), parsePos, intValue); + } + + parsePos = 0; + status = U_ZERO_ERROR; + doubValue = unum_parseDouble(unumDec, itemPtr->text, -1, &parsePos, &status); + if (status != itemPtr->doubStatus || parsePos != itemPtr->doubPos || doubValue != itemPtr->doubValue) { + char btext[32]; + u_austrcpy(btext, itemPtr->text); + log_err("locale %s, text \"%s\", lenient %d, intOnly %d;\n parseDouble expected status %s, pos %d, value %.1f;\n got %s, %d, %.1f\n", + itemPtr->locale, btext, itemPtr->lenient, itemPtr->intOnly, + u_errorName(itemPtr->doubStatus), itemPtr->doubPos, itemPtr->doubValue, + u_errorName(status), parsePos, doubValue); + } + + parsePos = 0; + status = U_ZERO_ERROR; + decstr[0] = 0; + dclen = unum_parseDecimal(unumDec, itemPtr->text, -1, &parsePos, decstr, 32, &status); + if (status != itemPtr->decStatus || parsePos != itemPtr->decPos || uprv_strcmp(decstr,itemPtr->decString) != 0) { + char btext[32]; + u_austrcpy(btext, itemPtr->text); + log_err("locale %s, text \"%s\", lenient %d, intOnly %d;\n parseDecimal expected status %s, pos %d, str \"%s\";\n got %s, %d, \"%s\"\n", + itemPtr->locale, btext, itemPtr->lenient, itemPtr->intOnly, + u_errorName(itemPtr->decStatus), itemPtr->decPos, itemPtr->decString, + u_errorName(status), parsePos, decstr); + } + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/test/intltest/numfmtst.cpp b/icu4c/source/test/intltest/numfmtst.cpp index a6e225372f9..3babb314c19 100644 --- a/icu4c/source/test/intltest/numfmtst.cpp +++ b/icu4c/source/test/intltest/numfmtst.cpp @@ -6770,7 +6770,7 @@ void NumberFormatTest::TestDecimal() { ASSERT_EQUALS(1234567890123LL, f.getInt64()); ASSERT_EQUALS(1234567890123LL, f.getInt64(status)); ASSERT_SUCCESS(status); - ASSERT_EQUALS("1.234567890123E+12", f.getDecimalNumber(status).data()); + ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data()); ASSERT_SUCCESS(status); }