ICU-11276 ModifierStore wired up in LongNameHandler (C++).

This commit is contained in:
Shane Carr 2018-09-14 01:30:55 -07:00
parent 18431084c2
commit 0d4c8dad1f
No known key found for this signature in database
GPG key ID: FCED3B24AAB18B5C
7 changed files with 99 additions and 79 deletions

View 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

View 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});
}
}

View 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

View 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

View file

@ -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. */

View 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);
};
/**

View 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"15 meters",
u"~5 meters",
u"~5 meters",
u"03 meters", // Note: It collapses when the plurals are the same
u"03 meters",
u"~0 meters",
u"33,000 meters",
u"3,0005,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"33 000 degrés Fahrenheit",
u"3 0005 000 degrés Fahrenheit",