]> granicus.if.org Git - icu/commitdiff
ICU-13717 Adds fast path for RBNF, which is not affect by min/max integer digits.
authorShane Carr <shane@unicode.org>
Wed, 23 May 2018 04:03:19 +0000 (04:03 +0000)
committerShane Carr <shane@unicode.org>
Wed, 23 May 2018 04:03:19 +0000 (04:03 +0000)
X-SVN-Rev: 41439

icu4c/source/i18n/smpdtfmt.cpp
icu4c/source/test/intltest/itrbnf.cpp
icu4c/source/test/intltest/itrbnf.h

index cc5da8b9d8f453c601d7ce0e33ead146774abd6d..210e7db1a29a0a2b4ef7e4dd0bd4c581c4453032 100644 (file)
@@ -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;
+    }
+
+    // Check for RBNF (no clone necessary)
+    auto* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(currentNumberFormat);
+    if (rbnf != nullptr) {
+        FieldPosition pos(FieldPosition::DONT_CARE);
+        rbnf->format(value, appendTo, pos);  // 3rd arg is there to speed up processing
+        return;
+    }
 
-    } else if (currentNumberFormat != nullptr) {
-        // Fall back to slow path
+    // Fall back to slow path (clone and mutate the NumberFormat)
+    if (currentNumberFormat != nullptr) {
         FieldPosition pos(FieldPosition::DONT_CARE);
         LocalPointer<NumberFormat> nf(dynamic_cast<NumberFormat*>(currentNumberFormat->clone()));
         nf->setMinimumIntegerDigits(minDigits);
index e6e9078014506d12bc14d4fc9a4c1186defbceb5..c62715bb85b5dd543404b3b9d773235b1a66d4e0 100644 (file)
@@ -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) 
 {
index e58d321362cba303a1de9656d1b8a66863c8656c..c82b50d86fe0a7d67bdad85d200b70f98e2e8fff 100644 (file)
@@ -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);