// 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
static UnicodeString getWithPlural(
const UnicodeString* strings,
- int32_t plural,
+ StandardPlural::Form plural,
UErrorCode& status) {
UnicodeString result = strings[plural];
if (result.isBogus()) {
} // 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) {
}
}
- 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; }
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});
}
}
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);
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
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;
}
-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
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) {
}
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,
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;
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
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] = {};
};
/**
* 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);
bool containsField(UNumberFormatFields field) const U_OVERRIDE;
+ void getParameters(Parameters& output) const U_OVERRIDE;
+
bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
/**
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,
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;
bool containsField(UNumberFormatFields field) const U_OVERRIDE;
+ void getParameters(Parameters& output) const U_OVERRIDE;
+
bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
protected:
NumberStringBuilder fSuffix;
bool fOverwrite;
bool fStrong;
+ Modifier::Parameters fParameters;
};
/** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */
int8_t signum;
StandardPlural::Form plural;
- static Parameters getBogus();
+ Parameters();
+ Parameters(const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural);
};
/**
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",
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",