mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-11276 ModifierStore wired up in LongNameHandler (C++).
This commit is contained in:
parent
18431084c2
commit
0d4c8dad1f
7 changed files with 99 additions and 79 deletions
|
@ -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
|
||||
|
|
|
@ -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<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});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Reference in a new issue