From: Shane Carr Date: Fri, 14 Sep 2018 08:30:55 +0000 (-0700) Subject: ICU-11276 ModifierStore wired up in LongNameHandler (C++). X-Git-Tag: release-63-rc~63^2~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0d4c8dad1fc4d1ef9b39c1b993471a7708daf312;p=icu ICU-11276 ModifierStore wired up in LongNameHandler (C++). --- diff --git a/icu4c/source/i18n/number_formatimpl.cpp b/icu4c/source/i18n/number_formatimpl.cpp index a48f810a679..60c18ee284e 100644 --- a/icu4c/source/i18n/number_formatimpl.cpp +++ b/icu4c/source/i18n/number_formatimpl.cpp @@ -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 diff --git a/icu4c/source/i18n/number_longnames.cpp b/icu4c/source/i18n/number_longnames.cpp index f3ed5d11709..fd8e8d381a1 100644 --- a/icu4c/source/i18n/number_longnames.cpp +++ b/icu4c/source/i18n/number_longnames.cpp @@ -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 ¤cy, +LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, 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(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(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}); } } diff --git a/icu4c/source/i18n/number_longnames.h b/icu4c/source/i18n/number_longnames.h index a8804659135..a71d0caadf1 100644 --- a/icu4c/source/i18n/number_longnames.h +++ b/icu4c/source/i18n/number_longnames.h @@ -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 ¤cy, 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 diff --git a/icu4c/source/i18n/number_modifiers.cpp b/icu4c/source/i18n/number_modifiers.cpp index dacac324efe..d92ec63b08d 100644 --- a/icu4c/source/i18n/number_modifiers.cpp +++ b/icu4c/source/i18n/number_modifiers.cpp @@ -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(&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(&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 diff --git a/icu4c/source/i18n/number_modifiers.h b/icu4c/source/i18n/number_modifiers.h index 1892ae55495..9cc74b37974 100644 --- a/icu4c/source/i18n/number_modifiers.h +++ b/icu4c/source/i18n/number_modifiers.h @@ -18,17 +18,10 @@ 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. */ diff --git a/icu4c/source/i18n/number_types.h b/icu4c/source/i18n/number_types.h index c20c8124f42..45e641ddcbf 100644 --- a/icu4c/source/i18n/number_types.h +++ b/icu4c/source/i18n/number_types.h @@ -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); }; /** diff --git a/icu4c/source/test/intltest/numbertest_range.cpp b/icu4c/source/test/intltest/numbertest_range.cpp index e028be9a82a..63bf5986079 100644 --- a/icu4c/source/test/intltest/numbertest_range.cpp +++ b/icu4c/source/test/intltest/numbertest_range.cpp @@ -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"1–5 degrés Fahrenheit", u"~5 degrés Fahrenheit", u"~5 degrés Fahrenheit", - u"0 degré Fahrenheit – 3 degrés Fahrenheit", + u"0–3 degrés Fahrenheit", u"~0 degré Fahrenheit", u"3–3 000 degrés Fahrenheit", u"3 000–5 000 degrés Fahrenheit",