X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/249c4c5ea9376c24572daf9c2effa7484a282f14..3d1f044b704633e2e541231cd17ae9ecf9ad5c7a:/icuSources/i18n/number_patternmodifier.cpp diff --git a/icuSources/i18n/number_patternmodifier.cpp b/icuSources/i18n/number_patternmodifier.cpp index 6417e143..75de439f 100644 --- a/icuSources/i18n/number_patternmodifier.cpp +++ b/icuSources/i18n/number_patternmodifier.cpp @@ -23,33 +23,34 @@ AffixPatternProvider::~AffixPatternProvider() = default; MutablePatternModifier::MutablePatternModifier(bool isStrong) : fStrong(isStrong) {} -void MutablePatternModifier::setPatternInfo(const AffixPatternProvider* patternInfo) { - this->patternInfo = patternInfo; +void MutablePatternModifier::setPatternInfo(const AffixPatternProvider* patternInfo, Field field) { + fPatternInfo = patternInfo; + fField = field; } void MutablePatternModifier::setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille) { - this->signDisplay = signDisplay; - this->perMilleReplacesPercent = perMille; + fSignDisplay = signDisplay; + fPerMilleReplacesPercent = perMille; } void MutablePatternModifier::setSymbols(const DecimalFormatSymbols* symbols, const CurrencySymbols* currencySymbols, const UNumberUnitWidth unitWidth, const PluralRules* rules) { U_ASSERT((rules != nullptr) == needsPlurals()); - this->symbols = symbols; - this->currencySymbols = currencySymbols; - this->unitWidth = unitWidth; - this->rules = rules; + fSymbols = symbols; + fCurrencySymbols = currencySymbols; + fUnitWidth = unitWidth; + fRules = rules; } void MutablePatternModifier::setNumberProperties(int8_t signum, StandardPlural::Form plural) { - this->signum = signum; - this->plural = plural; + fSignum = signum; + fPlural = plural; } bool MutablePatternModifier::needsPlurals() const { UErrorCode statusLocal = U_ZERO_ERROR; - return patternInfo->containsSymbolType(AffixPatternType::TYPE_CURRENCY_TRIPLE, statusLocal); + return fPatternInfo->containsSymbolType(AffixPatternType::TYPE_CURRENCY_TRIPLE, statusLocal); // Silently ignore any error codes. } @@ -69,7 +70,7 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren StandardPlural::Form::MANY, StandardPlural::Form::OTHER}; - auto pm = new ParameterizedModifier(); + auto pm = new AdoptingModifierStore(); if (pm == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -79,26 +80,25 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren // Slower path when we require the plural keyword. for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) { setNumberProperties(1, plural); - pm->adoptSignPluralModifier(1, plural, createConstantModifier(status)); + pm->adoptModifier(1, plural, createConstantModifier(status)); setNumberProperties(0, plural); - pm->adoptSignPluralModifier(0, plural, createConstantModifier(status)); + pm->adoptModifier(0, plural, createConstantModifier(status)); setNumberProperties(-1, plural); - pm->adoptSignPluralModifier(-1, plural, createConstantModifier(status)); + pm->adoptModifier(-1, plural, createConstantModifier(status)); } if (U_FAILURE(status)) { delete pm; return nullptr; } - return new ImmutablePatternModifier(pm, rules, parent); // adopts pm + return new ImmutablePatternModifier(pm, fRules, parent); // adopts pm } else { // Faster path when plural keyword is not needed. setNumberProperties(1, StandardPlural::Form::COUNT); - Modifier* positive = createConstantModifier(status); + pm->adoptModifierWithoutPlural(1, createConstantModifier(status)); setNumberProperties(0, StandardPlural::Form::COUNT); - Modifier* zero = createConstantModifier(status); + pm->adoptModifierWithoutPlural(0, createConstantModifier(status)); setNumberProperties(-1, StandardPlural::Form::COUNT); - Modifier* negative = createConstantModifier(status); - pm->adoptPositiveNegativeModifiers(positive, zero, negative); + pm->adoptModifierWithoutPlural(-1, createConstantModifier(status)); if (U_FAILURE(status)) { delete pm; return nullptr; @@ -112,39 +112,37 @@ ConstantMultiFieldModifier* MutablePatternModifier::createConstantModifier(UErro NumberStringBuilder b; insertPrefix(a, 0, status); insertSuffix(b, 0, status); - if (patternInfo->hasCurrencySign()) { + if (fPatternInfo->hasCurrencySign()) { return new CurrencySpacingEnabledModifier( - a, b, !patternInfo->hasBody(), fStrong, *symbols, status); + a, b, !fPatternInfo->hasBody(), fStrong, *fSymbols, status); } else { - return new ConstantMultiFieldModifier(a, b, !patternInfo->hasBody(), fStrong); + return new ConstantMultiFieldModifier(a, b, !fPatternInfo->hasBody(), fStrong); } } -ImmutablePatternModifier::ImmutablePatternModifier(ParameterizedModifier* pm, const PluralRules* rules, +ImmutablePatternModifier::ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules, const MicroPropsGenerator* parent) : pm(pm), rules(rules), parent(parent) {} void ImmutablePatternModifier::processQuantity(DecimalQuantity& quantity, MicroProps& micros, UErrorCode& status) const { parent->processQuantity(quantity, micros, status); - applyToMicros(micros, quantity); + applyToMicros(micros, quantity, status); } -void ImmutablePatternModifier::applyToMicros(MicroProps& micros, DecimalQuantity& quantity) const { +void ImmutablePatternModifier::applyToMicros( + MicroProps& micros, const DecimalQuantity& quantity, UErrorCode& status) const { if (rules == nullptr) { - micros.modMiddle = pm->getModifier(quantity.signum()); + micros.modMiddle = pm->getModifierWithoutPlural(quantity.signum()); } else { - // TODO: Fix this. Avoid the copy. - DecimalQuantity copy(quantity); - copy.roundToInfinity(); - StandardPlural::Form plural = utils::getStandardPlural(rules, copy); - micros.modMiddle = pm->getModifier(quantity.signum(), plural); + StandardPlural::Form pluralForm = utils::getPluralSafe(micros.rounder, rules, quantity, status); + micros.modMiddle = pm->getModifier(quantity.signum(), pluralForm); } } const Modifier* ImmutablePatternModifier::getModifier(int8_t signum, StandardPlural::Form plural) const { if (rules == nullptr) { - return pm->getModifier(signum); + return pm->getModifierWithoutPlural(signum); } else { return pm->getModifier(signum, plural); } @@ -153,21 +151,19 @@ const Modifier* ImmutablePatternModifier::getModifier(int8_t signum, StandardPlu /** Used by the unsafe code path. */ MicroPropsGenerator& MutablePatternModifier::addToChain(const MicroPropsGenerator* parent) { - this->parent = parent; + fParent = parent; return *this; } void MutablePatternModifier::processQuantity(DecimalQuantity& fq, MicroProps& micros, UErrorCode& status) const { - parent->processQuantity(fq, micros, status); + fParent->processQuantity(fq, micros, status); // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. auto nonConstThis = const_cast(this); if (needsPlurals()) { - // TODO: Fix this. Avoid the copy. - DecimalQuantity copy(fq); - micros.rounder.apply(copy, status); - nonConstThis->setNumberProperties(fq.signum(), utils::getStandardPlural(rules, copy)); + StandardPlural::Form pluralForm = utils::getPluralSafe(micros.rounder, fRules, fq, status); + nonConstThis->setNumberProperties(fq.signum(), pluralForm); } else { nonConstThis->setNumberProperties(fq.signum(), StandardPlural::Form::COUNT); } @@ -183,7 +179,7 @@ int32_t MutablePatternModifier::apply(NumberStringBuilder& output, int32_t leftI int32_t suffixLen = nonConstThis->insertSuffix(output, rightIndex + prefixLen, status); // If the pattern had no decimal stem body (like #,##0.00), overwrite the value. int32_t overwriteLen = 0; - if (!patternInfo->hasBody()) { + if (!fPatternInfo->hasBody()) { overwriteLen = output.splice( leftIndex + prefixLen, rightIndex + prefixLen, @@ -199,28 +195,30 @@ int32_t MutablePatternModifier::apply(NumberStringBuilder& output, int32_t leftI prefixLen, rightIndex + overwriteLen + prefixLen, suffixLen, - *symbols, + *fSymbols, status); return prefixLen + overwriteLen + suffixLen; } -int32_t MutablePatternModifier::getPrefixLength(UErrorCode& status) const { +int32_t MutablePatternModifier::getPrefixLength() const { // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. auto nonConstThis = const_cast(this); // Enter and exit CharSequence Mode to get the length. + UErrorCode status = U_ZERO_ERROR; // status fails only with an iilegal argument exception nonConstThis->prepareAffix(true); int result = AffixUtils::unescapedCodePointCount(currentAffix, *this, status); // prefix length return result; } -int32_t MutablePatternModifier::getCodePointCount(UErrorCode& status) const { +int32_t MutablePatternModifier::getCodePointCount() const { // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. auto nonConstThis = const_cast(this); // Render the affixes to get the length + UErrorCode status = U_ZERO_ERROR; // status fails only with an iilegal argument exception nonConstThis->prepareAffix(true); int result = AffixUtils::unescapedCodePointCount(currentAffix, *this, status); // prefix length nonConstThis->prepareAffix(false); @@ -232,69 +230,85 @@ bool MutablePatternModifier::isStrong() const { return fStrong; } +bool MutablePatternModifier::containsField(UNumberFormatFields field) const { + (void)field; + // This method is not currently used. + UPRV_UNREACHABLE; +} + +void MutablePatternModifier::getParameters(Parameters& output) const { + (void)output; + // This method is not currently used. + UPRV_UNREACHABLE; +} + +bool MutablePatternModifier::semanticallyEquivalent(const Modifier& other) const { + (void)other; + // This method is not currently used. + UPRV_UNREACHABLE; +} + int32_t MutablePatternModifier::insertPrefix(NumberStringBuilder& sb, int position, UErrorCode& status) { prepareAffix(true); - int length = AffixUtils::unescape(currentAffix, sb, position, *this, status); + int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status); return length; } int32_t MutablePatternModifier::insertSuffix(NumberStringBuilder& sb, int position, UErrorCode& status) { prepareAffix(false); - int length = AffixUtils::unescape(currentAffix, sb, position, *this, status); + int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status); return length; } /** This method contains the heart of the logic for rendering LDML affix strings. */ void MutablePatternModifier::prepareAffix(bool isPrefix) { PatternStringUtils::patternInfoToStringBuilder( - *patternInfo, isPrefix, signum, signDisplay, plural, perMilleReplacesPercent, currentAffix); + *fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, fPerMilleReplacesPercent, currentAffix); } UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { UErrorCode localStatus = U_ZERO_ERROR; switch (type) { case AffixPatternType::TYPE_MINUS_SIGN: - return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kMinusSignSymbol); + return fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kMinusSignSymbol); case AffixPatternType::TYPE_PLUS_SIGN: - return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPlusSignSymbol); + return fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPlusSignSymbol); case AffixPatternType::TYPE_PERCENT: - return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPercentSymbol); + return fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPercentSymbol); case AffixPatternType::TYPE_PERMILLE: - return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPerMillSymbol); + return fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPerMillSymbol); case AffixPatternType::TYPE_CURRENCY_SINGLE: { // UnitWidth ISO and HIDDEN overrides the singular currency symbol. - if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE) { - return currencySymbols->getIntlCurrencySymbol(localStatus); - } else if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN) { + if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE) { + return fCurrencySymbols->getIntlCurrencySymbol(localStatus); + } else if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN) { return UnicodeString(); - } else if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW) { - return currencySymbols->getNarrowCurrencySymbol(localStatus); + } else if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW) { + return fCurrencySymbols->getNarrowCurrencySymbol(localStatus); } else { - return currencySymbols->getCurrencySymbol(localStatus); + return fCurrencySymbols->getCurrencySymbol(localStatus); } } case AffixPatternType::TYPE_CURRENCY_DOUBLE: - return currencySymbols->getIntlCurrencySymbol(localStatus); + return fCurrencySymbols->getIntlCurrencySymbol(localStatus); case AffixPatternType::TYPE_CURRENCY_TRIPLE: // NOTE: This is the code path only for patterns containing "¤¤¤". // Plural currencies set via the API are formatted in LongNameHandler. // This code path is used by DecimalFormat via CurrencyPluralInfo. - U_ASSERT(plural != StandardPlural::Form::COUNT); - return currencySymbols->getPluralName(plural, localStatus); + U_ASSERT(fPlural != StandardPlural::Form::COUNT); + return fCurrencySymbols->getPluralName(fPlural, localStatus); case AffixPatternType::TYPE_CURRENCY_QUAD: return UnicodeString(u"\uFFFD"); case AffixPatternType::TYPE_CURRENCY_QUINT: return UnicodeString(u"\uFFFD"); default: - U_ASSERT(false); - return UnicodeString(); + UPRV_UNREACHABLE; } } UnicodeString MutablePatternModifier::toUnicodeString() const { // Never called by AffixUtils - U_ASSERT(false); - return UnicodeString(); + UPRV_UNREACHABLE; } #endif /* #if !UCONFIG_NO_FORMATTING */