From d0d8535066a7b53ab307b84986e228b756b40303 Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Wed, 23 May 2018 04:03:19 +0000 Subject: [PATCH] ICU-13717 Adds fast path for RBNF, which is not affect by min/max integer digits. X-SVN-Rev: 41439 --- icu4c/source/i18n/smpdtfmt.cpp | 16 +++++++++++++--- icu4c/source/test/intltest/itrbnf.cpp | 16 ++++++++++++++++ icu4c/source/test/intltest/itrbnf.h | 1 + 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp index cc5da8b9d8..210e7db1a2 100644 --- a/icu4c/source/i18n/smpdtfmt.cpp +++ b/icu4c/source/i18n/smpdtfmt.cpp @@ -53,6 +53,7 @@ #include "unicode/vtzone.h" #include "unicode/udisplaycontext.h" #include "unicode/brkiter.h" +#include "unicode/rbnf.h" #include "uresimp.h" #include "olsontz.h" #include "patternprops.h" @@ -2069,7 +2070,6 @@ SimpleDateFormat::zeroPaddingNumber( } } } - if (fastFormatter != nullptr) { // Can use fast path number::impl::UFormattedNumberData result; @@ -2080,9 +2080,19 @@ SimpleDateFormat::zeroPaddingNumber( return; } appendTo.append(result.string.toTempUnicodeString()); + return; + } - } else if (currentNumberFormat != nullptr) { - // Fall back to slow path + // Check for RBNF (no clone necessary) + auto* rbnf = dynamic_cast(currentNumberFormat); + if (rbnf != nullptr) { + FieldPosition pos(FieldPosition::DONT_CARE); + rbnf->format(value, appendTo, pos); // 3rd arg is there to speed up processing + return; + } + + // Fall back to slow path (clone and mutate the NumberFormat) + if (currentNumberFormat != nullptr) { FieldPosition pos(FieldPosition::DONT_CARE); LocalPointer nf(dynamic_cast(currentNumberFormat->clone())); nf->setMinimumIntegerDigits(minDigits); diff --git a/icu4c/source/test/intltest/itrbnf.cpp b/icu4c/source/test/intltest/itrbnf.cpp index e6e9078014..c62715bb85 100644 --- a/icu4c/source/test/intltest/itrbnf.cpp +++ b/icu4c/source/test/intltest/itrbnf.cpp @@ -76,6 +76,7 @@ void IntlTestRBNF::runIndexedTest(int32_t index, UBool exec, const char* &name, TESTCASE(24, TestLargeNumbers); TESTCASE(25, TestCompactDecimalFormatStyle); TESTCASE(26, TestParseFailure); + TESTCASE(27, TestMinMaxIntegerDigitsIgnored); #else TESTCASE(0, TestRBNFDisabled); #endif @@ -2300,6 +2301,21 @@ void IntlTestRBNF::TestParseFailure() { } } +void IntlTestRBNF::TestMinMaxIntegerDigitsIgnored() { + IcuTestErrorCode status(*this, "TestMinMaxIntegerDigitsIgnored"); + + // NOTE: SimpleDateFormat has an optimization that depends on the fact that min/max integer digits + // do not affect RBNF (see SimpleDateFormat#zeroPaddingNumber). + RuleBasedNumberFormat rbnf(URBNF_SPELLOUT, "en", status); + rbnf.setMinimumIntegerDigits(2); + rbnf.setMaximumIntegerDigits(3); + UnicodeString result; + rbnf.format(3, result.remove(), status); + assertEquals("Min integer digits are ignored", u"three", result); + rbnf.format(1012, result.remove(), status); + assertEquals("Max integer digits are ignored", u"one thousand twelve", result); +} + void IntlTestRBNF::doTest(RuleBasedNumberFormat* formatter, const char* const testData[][2], UBool testParsing) { diff --git a/icu4c/source/test/intltest/itrbnf.h b/icu4c/source/test/intltest/itrbnf.h index e58d321362..c82b50d86f 100644 --- a/icu4c/source/test/intltest/itrbnf.h +++ b/icu4c/source/test/intltest/itrbnf.h @@ -148,6 +148,7 @@ class IntlTestRBNF : public IntlTest { void TestLargeNumbers(); void TestCompactDecimalFormatStyle(); void TestParseFailure(); + void TestMinMaxIntegerDigitsIgnored(); protected: virtual void doTest(RuleBasedNumberFormat* formatter, const char* const testData[][2], UBool testParsing);