]> granicus.if.org Git - icu/commitdiff
ICU-11276 ModifierStore wired up in LongNameHandler (C++).
authorShane Carr <shane@unicode.org>
Fri, 14 Sep 2018 08:30:55 +0000 (01:30 -0700)
committerShane Carr <shane@unicode.org>
Thu, 27 Sep 2018 21:27:40 +0000 (14:27 -0700)
icu4c/source/i18n/number_formatimpl.cpp
icu4c/source/i18n/number_longnames.cpp
icu4c/source/i18n/number_longnames.h
icu4c/source/i18n/number_modifiers.cpp
icu4c/source/i18n/number_modifiers.h
icu4c/source/i18n/number_types.h
icu4c/source/test/intltest/numbertest_range.cpp

index a48f810a679b0c7709ff84efb16fb930353ce6c4..60c18ee284e238176593207bacd824b34fec392b 100644 (file)
@@ -366,25 +366,23 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
     // Outer modifier (CLDR units and currency long names)
     if (isCldrUnit) {
         fLongNameHandler.adoptInstead(
-                new LongNameHandler(
-                        LongNameHandler::forMeasureUnit(
-                                macros.locale,
-                                macros.unit,
-                                macros.perUnit,
-                                unitWidth,
-                                resolvePluralRules(macros.rules, macros.locale, status),
-                                chain,
-                                status)));
+                LongNameHandler::forMeasureUnit(
+                        macros.locale,
+                        macros.unit,
+                        macros.perUnit,
+                        unitWidth,
+                        resolvePluralRules(macros.rules, macros.locale, status),
+                        chain,
+                        status));
         chain = fLongNameHandler.getAlias();
     } else if (isCurrency && unitWidth == UNUM_UNIT_WIDTH_FULL_NAME) {
         fLongNameHandler.adoptInstead(
-                new LongNameHandler(
-                        LongNameHandler::forCurrencyLongNames(
-                                macros.locale,
-                                currency,
-                                resolvePluralRules(macros.rules, macros.locale, status),
-                                chain,
-                                status)));
+                LongNameHandler::forCurrencyLongNames(
+                        macros.locale,
+                        currency,
+                        resolvePluralRules(macros.rules, macros.locale, status),
+                        chain,
+                        status));
         chain = fLongNameHandler.getAlias();
     } else {
         // No outer modifier required
index f3ed5d117090300289746a8d7a98c6ca0d076565..fd8e8d381a1d76167504dc3d3254b6630e9d5621 100644 (file)
@@ -39,7 +39,7 @@ static int32_t getIndex(const char* pluralKeyword, UErrorCode& status) {
 
 static UnicodeString getWithPlural(
         const UnicodeString* strings,
-        int32_t plural,
+        StandardPlural::Form plural,
         UErrorCode& status) {
     UnicodeString result = strings[plural];
     if (result.isBogus()) {
@@ -156,7 +156,7 @@ UnicodeString getPerUnitFormat(const Locale& locale, const UNumberUnitWidth &wid
 
 } // namespace
 
-LongNameHandler
+LongNameHandler*
 LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, const MeasureUnit &perUnit,
                                 const UNumberUnitWidth &width, const PluralRules *rules,
                                 const MicroPropsGenerator *parent, UErrorCode &status) {
@@ -173,20 +173,28 @@ LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, c
         }
     }
 
-    LongNameHandler result(rules, parent);
+    auto* result = new LongNameHandler(rules, parent);
+    if (result == nullptr) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return nullptr;
+    }
     UnicodeString simpleFormats[ARRAY_LENGTH];
     getMeasureData(loc, unit, width, simpleFormats, status);
     if (U_FAILURE(status)) { return result; }
     // TODO: What field to use for units?
-    simpleFormatsToModifiers(simpleFormats, UNUM_FIELD_COUNT, result.fModifiers, status);
+    result->simpleFormatsToModifiers(simpleFormats, UNUM_FIELD_COUNT, status);
     return result;
 }
 
-LongNameHandler
+LongNameHandler*
 LongNameHandler::forCompoundUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit,
                                  const UNumberUnitWidth &width, const PluralRules *rules,
                                  const MicroPropsGenerator *parent, UErrorCode &status) {
-    LongNameHandler result(rules, parent);
+    auto* result = new LongNameHandler(rules, parent);
+    if (result == nullptr) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return nullptr;
+    }
     UnicodeString primaryData[ARRAY_LENGTH];
     getMeasureData(loc, unit, width, primaryData, status);
     if (U_FAILURE(status)) { return result; }
@@ -213,46 +221,52 @@ LongNameHandler::forCompoundUnit(const Locale &loc, const MeasureUnit &unit, con
         if (U_FAILURE(status)) { return result; }
     }
     // TODO: What field to use for units?
-    multiSimpleFormatsToModifiers(primaryData, perUnitFormat, UNUM_FIELD_COUNT, result.fModifiers, status);
+    result->multiSimpleFormatsToModifiers(primaryData, perUnitFormat, UNUM_FIELD_COUNT, status);
     return result;
 }
 
-LongNameHandler LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit &currency,
+LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit &currency,
                                                       const PluralRules *rules,
                                                       const MicroPropsGenerator *parent,
                                                       UErrorCode &status) {
-    LongNameHandler result(rules, parent);
+    auto* result = new LongNameHandler(rules, parent);
+    if (result == nullptr) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return nullptr;
+    }
     UnicodeString simpleFormats[ARRAY_LENGTH];
     getCurrencyLongNameData(loc, currency, simpleFormats, status);
-    if (U_FAILURE(status)) { return result; }
-    simpleFormatsToModifiers(simpleFormats, UNUM_CURRENCY_FIELD, result.fModifiers, status);
+    if (U_FAILURE(status)) { return nullptr; }
+    result->simpleFormatsToModifiers(simpleFormats, UNUM_CURRENCY_FIELD, status);
     return result;
 }
 
 void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field,
-                                               SimpleModifier *output, UErrorCode &status) {
+                                               UErrorCode &status) {
     for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
-        UnicodeString simpleFormat = getWithPlural(simpleFormats, i, status);
+        StandardPlural::Form plural = static_cast<StandardPlural::Form>(i);
+        UnicodeString simpleFormat = getWithPlural(simpleFormats, plural, status);
         if (U_FAILURE(status)) { return; }
         SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status);
         if (U_FAILURE(status)) { return; }
-        output[i] = SimpleModifier(compiledFormatter, field, false);
+        fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, 0, plural});
     }
 }
 
 void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat,
-                                                    Field field, SimpleModifier *output, UErrorCode &status) {
+                                                    Field field, UErrorCode &status) {
     SimpleFormatter trailCompiled(trailFormat, 1, 1, status);
     if (U_FAILURE(status)) { return; }
     for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
-        UnicodeString leadFormat = getWithPlural(leadFormats, i, status);
+        StandardPlural::Form plural = static_cast<StandardPlural::Form>(i);
+        UnicodeString leadFormat = getWithPlural(leadFormats, plural, status);
         if (U_FAILURE(status)) { return; }
         UnicodeString compoundFormat;
         trailCompiled.format(leadFormat, compoundFormat, status);
         if (U_FAILURE(status)) { return; }
         SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status);
         if (U_FAILURE(status)) { return; }
-        output[i] = SimpleModifier(compoundCompiled, field, false);
+        fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, 0, plural});
     }
 }
 
index a8804659135d622bc358415a6d8e7855120ea1e9..a71d0caadf125c8ce7db479cf52e995467a0ab6b 100644 (file)
@@ -16,11 +16,11 @@ namespace impl {
 
 class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public UMemory {
   public:
-    static LongNameHandler
+    static LongNameHandler*
     forCurrencyLongNames(const Locale &loc, const CurrencyUnit &currency, const PluralRules *rules,
                          const MicroPropsGenerator *parent, UErrorCode &status);
 
-    static LongNameHandler
+    static LongNameHandler*
     forMeasureUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit,
                    const UNumberUnitWidth &width, const PluralRules *rules,
                    const MicroPropsGenerator *parent, UErrorCode &status);
@@ -38,15 +38,14 @@ class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public
     LongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent)
             : rules(rules), parent(parent) {}
 
-    static LongNameHandler
+    static LongNameHandler*
     forCompoundUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit,
                     const UNumberUnitWidth &width, const PluralRules *rules,
                     const MicroPropsGenerator *parent, UErrorCode &status);
 
-    static void simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field,
-                                         SimpleModifier *output, UErrorCode &status);
-    static void multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat,
-                                         Field field, SimpleModifier *output, UErrorCode &status);
+    void simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field, UErrorCode &status);
+    void multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat,
+                                       Field field, UErrorCode &status);
 };
 
 }  // namespace impl
index dacac324efe4394f2ad57a468ca13430553a6bff..d92ec63b08da5881cf58ce90b99ac74633a752d4 100644 (file)
@@ -53,11 +53,12 @@ void U_CALLCONV initDefaultCurrencySpacing(UErrorCode &status) {
 
 Modifier::~Modifier() = default;
 
-Modifier::Parameters Modifier::Parameters::getBogus() {
-    Modifier::Parameters result;
-    result.obj = nullptr;
-    return result;
-}
+Modifier::Parameters::Parameters()
+        : obj(nullptr) {}
+
+Modifier::Parameters::Parameters(
+    const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural)
+        : obj(_obj), signum(_signum), plural(_plural) {}
 
 ModifierStore::~ModifierStore() = default;
 
@@ -68,14 +69,6 @@ AdoptingModifierStore::~AdoptingModifierStore()  {
 }
 
 
-ModifierWithParameters::ModifierWithParameters(const Modifier::Parameters& parameters)
-    : fParameters(parameters) {}
-
-void ModifierWithParameters::getParameters(Parameters& output) const {
-    output = fParameters;
-}
-
-
 int32_t ConstantAffixModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
                                      UErrorCode &status) const {
     // Insert the suffix first since inserting the prefix will change the rightIndex
@@ -122,12 +115,12 @@ bool ConstantAffixModifier::semanticallyEquivalent(const Modifier& other) const
 
 
 SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong)
-        : SimpleModifier(simpleFormatter, field, strong, Modifier::Parameters::getBogus()) {}
+        : SimpleModifier(simpleFormatter, field, strong, {}) {}
 
 SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong,
                                const Modifier::Parameters parameters)
-        : ModifierWithParameters(parameters),
-          fCompiledPattern(simpleFormatter.compiledPattern), fField(field), fStrong(strong) {
+        : fCompiledPattern(simpleFormatter.compiledPattern), fField(field), fStrong(strong),
+          fParameters(parameters) {
     int32_t argLimit = SimpleFormatter::getArgumentLimit(
             fCompiledPattern.getBuffer(), fCompiledPattern.length());
     if (argLimit == 0) {
@@ -159,8 +152,7 @@ SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field fie
 }
 
 SimpleModifier::SimpleModifier()
-        : ModifierWithParameters(Modifier::Parameters::getBogus()),
-          fField(UNUM_FIELD_COUNT), fStrong(false), fPrefixLength(0), fSuffixLength(0) {
+        : fField(UNUM_FIELD_COUNT), fStrong(false), fPrefixLength(0), fSuffixLength(0) {
 }
 
 int32_t SimpleModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
@@ -194,11 +186,18 @@ bool SimpleModifier::containsField(UNumberFormatFields field) const {
     return false;
 }
 
+void SimpleModifier::getParameters(Parameters& output) const {
+    output = fParameters;
+}
+
 bool SimpleModifier::semanticallyEquivalent(const Modifier& other) const {
     auto* _other = dynamic_cast<const SimpleModifier*>(&other);
     if (_other == nullptr) {
         return false;
     }
+    if (fParameters.obj != nullptr) {
+        return fParameters.obj == _other->fParameters.obj;
+    }
     return fCompiledPattern == _other->fCompiledPattern
         && fField == _other->fField
         && fStrong == _other->fStrong;
@@ -317,11 +316,18 @@ bool ConstantMultiFieldModifier::containsField(UNumberFormatFields field) const
     return fPrefix.containsField(field) || fSuffix.containsField(field);
 }
 
+void ConstantMultiFieldModifier::getParameters(Parameters& output) const {
+    output = fParameters;
+}
+
 bool ConstantMultiFieldModifier::semanticallyEquivalent(const Modifier& other) const {
     auto* _other = dynamic_cast<const ConstantMultiFieldModifier*>(&other);
     if (_other == nullptr) {
         return false;
     }
+    if (fParameters.obj != nullptr) {
+        return fParameters.obj == _other->fParameters.obj;
+    }
     return fPrefix.contentEquals(_other->fPrefix)
         && fSuffix.contentEquals(_other->fSuffix)
         && fOverwrite == _other->fOverwrite
index 1892ae554953ca9f6926608faea8007fe1605e17..9cc74b37974a15e1ebe1a735c7eebf9c84367ead 100644 (file)
 U_NAMESPACE_BEGIN namespace number {
 namespace impl {
 
-/**
- * A base class for modifiers that need to be able to keep a reference to a ModifierStore.
- */
-class U_I18N_API ModifierWithParameters : public Modifier, public UMemory {
+class ReferencingPluralsModifierStore : public ModifierStore {
   public:
-    ModifierWithParameters(const Modifier::Parameters& parameters);
-
-    void getParameters(Parameters& output) const U_OVERRIDE;
-
-  private:
-    Modifier::Parameters fParameters;
+    virtual const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const;
+    const Modifier* mods[StandardPlural::COUNT] = {};
 };
 
 /**
@@ -67,7 +60,7 @@ class U_I18N_API ConstantAffixModifier : public Modifier, public UObject {
  * The second primary implementation of {@link Modifier}, this one consuming a {@link SimpleFormatter}
  * pattern.
  */
-class U_I18N_API SimpleModifier : public ModifierWithParameters {
+class U_I18N_API SimpleModifier : public Modifier, public UMemory {
   public:
     SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong);
 
@@ -88,6 +81,8 @@ class U_I18N_API SimpleModifier : public ModifierWithParameters {
 
     bool containsField(UNumberFormatFields field) const U_OVERRIDE;
 
+    void getParameters(Parameters& output) const U_OVERRIDE;
+
     bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
 
     /**
@@ -137,13 +132,14 @@ class U_I18N_API SimpleModifier : public ModifierWithParameters {
     int32_t fPrefixLength = 0;
     int32_t fSuffixOffset = -1;
     int32_t fSuffixLength = 0;
+    Modifier::Parameters fParameters;
 };
 
 /**
  * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed
  * based on the contents of two {@link NumberStringBuilder} instances (one for the prefix, one for the suffix).
  */
-class U_I18N_API ConstantMultiFieldModifier :public ModifierWithParameters {
+class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
   public:
     ConstantMultiFieldModifier(
             const NumberStringBuilder &prefix,
@@ -151,18 +147,21 @@ class U_I18N_API ConstantMultiFieldModifier :public ModifierWithParameters {
             bool overwrite,
             bool strong,
             const Modifier::Parameters parameters)
-      : ModifierWithParameters(parameters),
-        fPrefix(prefix),
+      : fPrefix(prefix),
         fSuffix(suffix),
         fOverwrite(overwrite),
-        fStrong(strong) {}
+        fStrong(strong),
+        fParameters(parameters) {}
 
     ConstantMultiFieldModifier(
             const NumberStringBuilder &prefix,
             const NumberStringBuilder &suffix,
             bool overwrite,
             bool strong)
-      : ConstantMultiFieldModifier(prefix, suffix, overwrite, strong, Modifier::Parameters::getBogus()) {}
+      : fPrefix(prefix),
+        fSuffix(suffix),
+        fOverwrite(overwrite),
+        fStrong(strong) {}
 
     int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
                   UErrorCode &status) const U_OVERRIDE;
@@ -175,6 +174,8 @@ class U_I18N_API ConstantMultiFieldModifier :public ModifierWithParameters {
 
     bool containsField(UNumberFormatFields field) const U_OVERRIDE;
 
+    void getParameters(Parameters& output) const U_OVERRIDE;
+
     bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
 
   protected:
@@ -184,6 +185,7 @@ class U_I18N_API ConstantMultiFieldModifier :public ModifierWithParameters {
     NumberStringBuilder fSuffix;
     bool fOverwrite;
     bool fStrong;
+    Modifier::Parameters fParameters;
 };
 
 /** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */
index c20c8124f425eb59df0924ecee29d95dae17c216..45e641ddcbfef17d24802eafb54704bd8a4805c1 100644 (file)
@@ -195,7 +195,8 @@ class U_I18N_API Modifier {
         int8_t signum;
         StandardPlural::Form plural;
 
-        static Parameters getBogus();
+        Parameters();
+        Parameters(const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural);
     };
 
     /**
index e028be9a82aef7289a52fd798c28d2f84c5782e0..63bf5986079982011d26e1b62406db92824bda22 100644 (file)
@@ -113,10 +113,10 @@ void NumberRangeFormatterTest::testBasic() {
         NumberRangeFormatter::with()
             .numberFormatterBoth(NumberFormatter::with().unit(METER).unitWidth(UNUM_UNIT_WIDTH_FULL_NAME)),
         Locale("en-us"),
-        u"1 meter – 5 meters",  // TODO: This doesn't collapse because the plurals are different.  Fix?
+        u"1–5 meters",
         u"~5 meters",
         u"~5 meters",
-        u"0–3 meters",  // Note: It collapses when the plurals are the same
+        u"0–3 meters",
         u"~0 meters",
         u"3–3,000 meters",
         u"3,000–5,000 meters",
@@ -129,10 +129,10 @@ void NumberRangeFormatterTest::testBasic() {
         NumberRangeFormatter::with()
             .numberFormatterBoth(NumberFormatter::with().unit(FAHRENHEIT).unitWidth(UNUM_UNIT_WIDTH_FULL_NAME)),
         Locale("fr-FR"),
-        u"1 degré Fahrenheit – 5 degrés Fahrenheit",
+        u"15 degrés Fahrenheit",
         u"~5 degrés Fahrenheit",
         u"~5 degrés Fahrenheit",
-        u"0 degré Fahrenheit – 3 degrés Fahrenheit",
+        u"03 degrés Fahrenheit",
         u"~0 degré Fahrenheit",
         u"3–3 000 degrés Fahrenheit",
         u"3 000–5 000 degrés Fahrenheit",