X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b331163bffd790ced0e88b73f44f86d49ccc48a5..4f1e1a09ce4daed860e35d359ce2fceccb0764e8:/icuSources/i18n/nfsubs.cpp?ds=sidebyside diff --git a/icuSources/i18n/nfsubs.cpp b/icuSources/i18n/nfsubs.cpp index 18c9b621..bf242059 100644 --- a/icuSources/i18n/nfsubs.cpp +++ b/icuSources/i18n/nfsubs.cpp @@ -1,10 +1,12 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ****************************************************************************** -* Copyright (C) 1997-2014, International Business Machines +* Copyright (C) 1997-2015, International Business Machines * Corporation and others. All Rights Reserved. ****************************************************************************** * file name: nfsubs.cpp -* encoding: US-ASCII +* encoding: UTF-8 * tab size: 8 (not used) * indentation:4 * @@ -18,6 +20,7 @@ #include "nfsubs.h" #include "digitlst.h" +#include "fmtableimp.h" #if U_HAVE_RBNF @@ -48,7 +51,6 @@ class SameValueSubstitution : public NFSubstitution { public: SameValueSubstitution(int32_t pos, const NFRuleSet* ruleset, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status); virtual ~SameValueSubstitution(); @@ -67,28 +69,24 @@ public: SameValueSubstitution::~SameValueSubstitution() {} class MultiplierSubstitution : public NFSubstitution { - double divisor; - int64_t ldivisor; + int64_t divisor; public: MultiplierSubstitution(int32_t _pos, - double _divisor, + const NFRule *rule, const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status) - : NFSubstitution(_pos, _ruleSet, formatter, description, status), divisor(_divisor) + : NFSubstitution(_pos, _ruleSet, description, status), divisor(rule->getDivisor()) { - ldivisor = util64_fromDouble(divisor); if (divisor == 0) { status = U_PARSE_ERROR; } } virtual ~MultiplierSubstitution(); - virtual void setDivisor(int32_t radix, int32_t exponent, UErrorCode& status) { - divisor = uprv_pow(radix, exponent); - ldivisor = util64_fromDouble(divisor); + virtual void setDivisor(int32_t radix, int16_t exponent, UErrorCode& status) { + divisor = util64_pow(radix, exponent); if(divisor == 0) { status = U_PARSE_ERROR; @@ -98,14 +96,14 @@ public: virtual UBool operator==(const NFSubstitution& rhs) const; virtual int64_t transformNumber(int64_t number) const { - return number / ldivisor; + return number / divisor; } virtual double transformNumber(double number) const { if (getRuleSet()) { return uprv_floor(number / divisor); } else { - return number/divisor; + return number / divisor; } } @@ -113,7 +111,7 @@ public: return newRuleValue * divisor; } - virtual double calcUpperBound(double /*oldUpperBound*/) const { return divisor; } + virtual double calcUpperBound(double /*oldUpperBound*/) const { return static_cast(divisor); } virtual UChar tokenChar() const { return (UChar)0x003c; } // '<' @@ -125,22 +123,19 @@ public: MultiplierSubstitution::~MultiplierSubstitution() {} class ModulusSubstitution : public NFSubstitution { - double divisor; - int64_t ldivisor; + int64_t divisor; const NFRule* ruleToUse; public: ModulusSubstitution(int32_t pos, - double _divisor, + const NFRule* rule, const NFRule* rulePredecessor, const NFRuleSet* ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status); virtual ~ModulusSubstitution(); - virtual void setDivisor(int32_t radix, int32_t exponent, UErrorCode& status) { - divisor = uprv_pow(radix, exponent); - ldivisor = util64_fromDouble(divisor); + virtual void setDivisor(int32_t radix, int16_t exponent, UErrorCode& status) { + divisor = util64_pow(radix, exponent); if (divisor == 0) { status = U_PARSE_ERROR; @@ -149,24 +144,25 @@ public: virtual UBool operator==(const NFSubstitution& rhs) const; - virtual void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos, UErrorCode& status) const; - virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, UErrorCode& status) const; + virtual void doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const; + virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const; - virtual int64_t transformNumber(int64_t number) const { return number % ldivisor; } - virtual double transformNumber(double number) const { return uprv_fmod(number, divisor); } + virtual int64_t transformNumber(int64_t number) const { return number % divisor; } + virtual double transformNumber(double number) const { return uprv_fmod(number, static_cast(divisor)); } virtual UBool doParse(const UnicodeString& text, ParsePosition& parsePosition, double baseValue, double upperBound, UBool lenientParse, + uint32_t nonNumericalExecutedRuleMask, Formattable& result) const; virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const { - return oldRuleValue - uprv_fmod(oldRuleValue, divisor) + newRuleValue; + return oldRuleValue - uprv_fmod(oldRuleValue, static_cast(divisor)) + newRuleValue; } - virtual double calcUpperBound(double /*oldUpperBound*/) const { return divisor; } + virtual double calcUpperBound(double /*oldUpperBound*/) const { return static_cast(divisor); } virtual UBool isModulusSubstitution() const { return TRUE; } @@ -185,10 +181,9 @@ class IntegralPartSubstitution : public NFSubstitution { public: IntegralPartSubstitution(int32_t _pos, const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status) - : NFSubstitution(_pos, _ruleSet, formatter, description, status) {} + : NFSubstitution(_pos, _ruleSet, description, status) {} virtual ~IntegralPartSubstitution(); virtual int64_t transformNumber(int64_t number) const { return number; } @@ -211,15 +206,14 @@ class FractionalPartSubstitution : public NFSubstitution { public: FractionalPartSubstitution(int32_t pos, const NFRuleSet* ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status); virtual ~FractionalPartSubstitution(); virtual UBool operator==(const NFSubstitution& rhs) const; - virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, UErrorCode& status) const; - virtual void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/, UErrorCode& /*status*/) const {} + virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const; + virtual void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/, int32_t /*recursionCount*/, UErrorCode& /*status*/) const {} virtual int64_t transformNumber(int64_t /*number*/) const { return 0; } virtual double transformNumber(double number) const { return number - uprv_floor(number); } @@ -228,6 +222,7 @@ public: double baseValue, double upperBound, UBool lenientParse, + uint32_t nonNumericalExecutedRuleMask, Formattable& result) const; virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue + oldRuleValue; } @@ -245,10 +240,9 @@ class AbsoluteValueSubstitution : public NFSubstitution { public: AbsoluteValueSubstitution(int32_t _pos, const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status) - : NFSubstitution(_pos, _ruleSet, formatter, description, status) {} + : NFSubstitution(_pos, _ruleSet, description, status) {} virtual ~AbsoluteValueSubstitution(); virtual int64_t transformNumber(int64_t number) const { return number >= 0 ? number : -number; } @@ -278,11 +272,10 @@ public: } NumeratorSubstitution(int32_t _pos, double _denominator, - const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, + NFRuleSet* _ruleSet, const UnicodeString& description, UErrorCode& status) - : NFSubstitution(_pos, _ruleSet, formatter, fixdesc(description), status), denominator(_denominator) + : NFSubstitution(_pos, _ruleSet, fixdesc(description), status), denominator(_denominator) { ldenominator = util64_fromDouble(denominator); withZeros = description.endsWith(LTLT, 2); @@ -294,13 +287,14 @@ public: virtual int64_t transformNumber(int64_t number) const { return number * ldenominator; } virtual double transformNumber(double number) const { return uprv_round(number * denominator); } - virtual void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/, UErrorCode& /*status*/) const {} - virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, UErrorCode& status) const; + virtual void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/, int32_t /*recursionCount*/, UErrorCode& /*status*/) const {} + virtual void doSubstitution(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const; virtual UBool doParse(const UnicodeString& text, ParsePosition& parsePosition, double baseValue, double upperBound, UBool /*lenientParse*/, + uint32_t nonNumericalExecutedRuleMask, Formattable& result) const; virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue / oldRuleValue; } @@ -316,40 +310,6 @@ public: NumeratorSubstitution::~NumeratorSubstitution() {} -class NullSubstitution : public NFSubstitution { -public: - NullSubstitution(int32_t _pos, - const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, - const UnicodeString& description, - UErrorCode& status) - : NFSubstitution(_pos, _ruleSet, formatter, description, status) {} - virtual ~NullSubstitution(); - - virtual void toString(UnicodeString& /*result*/) const {} - virtual void doSubstitution(double /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/, UErrorCode& /*status*/) const {} - virtual void doSubstitution(int64_t /*number*/, UnicodeString& /*toInsertInto*/, int32_t /*_pos*/, UErrorCode& /*status*/) const {} - virtual int64_t transformNumber(int64_t /*number*/) const { return 0; } - virtual double transformNumber(double /*number*/) const { return 0; } - virtual UBool doParse(const UnicodeString& /*text*/, - ParsePosition& /*parsePosition*/, - double baseValue, - double /*upperBound*/, - UBool /*lenientParse*/, - Formattable& result) const - { result.setDouble(baseValue); return TRUE; } - virtual double composeRuleValue(double /*newRuleValue*/, double /*oldRuleValue*/) const { return 0.0; } // never called - virtual double calcUpperBound(double /*oldUpperBound*/) const { return 0; } // never called - virtual UBool isNullSubstitution() const { return TRUE; } - virtual UChar tokenChar() const { return (UChar)0x0020; } // ' ' never called - -public: - static UClassID getStaticClassID(void); - virtual UClassID getDynamicClassID(void) const; -}; - -NullSubstitution::~NullSubstitution() {} - NFSubstitution* NFSubstitution::makeSubstitution(int32_t pos, const NFRule* rule, @@ -361,7 +321,7 @@ NFSubstitution::makeSubstitution(int32_t pos, { // if the description is empty, return a NullSubstitution if (description.length() == 0) { - return new NullSubstitution(pos, ruleSet, formatter, description, status); + return NULL; } switch (description.charAt(0)) { @@ -380,20 +340,20 @@ NFSubstitution::makeSubstitution(int32_t pos, else if (rule->getBaseValue() == NFRule::kImproperFractionRule || rule->getBaseValue() == NFRule::kProperFractionRule || rule->getBaseValue() == NFRule::kMasterRule) { - return new IntegralPartSubstitution(pos, ruleSet, formatter, description, status); + return new IntegralPartSubstitution(pos, ruleSet, description, status); } // if the rule set containing the rule is a fraction // rule set, return a NumeratorSubstitution else if (ruleSet->isFractionRuleSet()) { return new NumeratorSubstitution(pos, (double)rule->getBaseValue(), - formatter->getDefaultRuleSet(), formatter, description, status); + formatter->getDefaultRuleSet(), description, status); } // otherwise, return a MultiplierSubstitution else { - return new MultiplierSubstitution(pos, rule->getDivisor(), ruleSet, - formatter, description, status); + return new MultiplierSubstitution(pos, rule, ruleSet, + description, status); } // if the description begins with '>'... @@ -401,7 +361,7 @@ NFSubstitution::makeSubstitution(int32_t pos, // if the rule is a negative-number rule, return // an AbsoluteValueSubstitution if (rule->getBaseValue() == NFRule::kNegativeNumberRule) { - return new AbsoluteValueSubstitution(pos, ruleSet, formatter, description, status); + return new AbsoluteValueSubstitution(pos, ruleSet, description, status); } // if the rule is a fraction rule, return a @@ -409,7 +369,7 @@ NFSubstitution::makeSubstitution(int32_t pos, else if (rule->getBaseValue() == NFRule::kImproperFractionRule || rule->getBaseValue() == NFRule::kProperFractionRule || rule->getBaseValue() == NFRule::kMasterRule) { - return new FractionalPartSubstitution(pos, ruleSet, formatter, description, status); + return new FractionalPartSubstitution(pos, ruleSet, description, status); } // if the rule set owning the rule is a fraction rule set, @@ -422,14 +382,14 @@ NFSubstitution::makeSubstitution(int32_t pos, // otherwise, return a ModulusSubstitution else { - return new ModulusSubstitution(pos, rule->getDivisor(), predecessor, - ruleSet, formatter, description, status); + return new ModulusSubstitution(pos, rule, predecessor, + ruleSet, description, status); } // if the description begins with '=', always return a // SameValueSubstitution case gEquals: - return new SameValueSubstitution(pos, ruleSet, formatter, description, status); + return new SameValueSubstitution(pos, ruleSet, description, status); // and if it's anything else, throw an exception default: @@ -441,7 +401,6 @@ NFSubstitution::makeSubstitution(int32_t pos, NFSubstitution::NFSubstitution(int32_t _pos, const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status) : pos(_pos), ruleSet(NULL), numberFormat(NULL) @@ -463,54 +422,55 @@ NFSubstitution::NFSubstitution(int32_t _pos, return; } - // if the description was just two paired token characters - // (i.e., "<<" or ">>"), it uses the rule set it belongs to to - // format its result if (workingDescription.length() == 0) { + // if the description was just two paired token characters + // (i.e., "<<" or ">>"), it uses the rule set it belongs to to + // format its result this->ruleSet = _ruleSet; } - // if the description contains a rule set name, that's the rule - // set we use to format the result: get a reference to the - // names rule set else if (workingDescription.charAt(0) == gPercent) { - this->ruleSet = formatter->findRuleSet(workingDescription, status); + // if the description contains a rule set name, that's the rule + // set we use to format the result: get a reference to the + // names rule set + this->ruleSet = _ruleSet->getOwner()->findRuleSet(workingDescription, status); } - // if the description begins with 0 or #, treat it as a - // DecimalFormat pattern, and initialize a DecimalFormat with - // that pattern (then set it to use the DecimalFormatSymbols - // belonging to our formatter) else if (workingDescription.charAt(0) == gPound || workingDescription.charAt(0) ==gZero) { - DecimalFormatSymbols* sym = formatter->getDecimalFormatSymbols(); + // if the description begins with 0 or #, treat it as a + // DecimalFormat pattern, and initialize a DecimalFormat with + // that pattern (then set it to use the DecimalFormatSymbols + // belonging to our formatter) + const DecimalFormatSymbols* sym = _ruleSet->getOwner()->getDecimalFormatSymbols(); if (!sym) { status = U_MISSING_RESOURCE_ERROR; return; } - this->numberFormat = new DecimalFormat(workingDescription, *sym, status); + DecimalFormat *tempNumberFormat = new DecimalFormat(workingDescription, *sym, status); /* test for NULL */ - if (this->numberFormat == 0) { + if (!tempNumberFormat) { status = U_MEMORY_ALLOCATION_ERROR; return; } if (U_FAILURE(status)) { - delete (DecimalFormat*)this->numberFormat; - this->numberFormat = NULL; + delete tempNumberFormat; return; } - // this->numberFormat->setDecimalFormatSymbols(formatter->getDecimalFormatSymbols()); + this->numberFormat = tempNumberFormat; } - // if the description is ">>>", this substitution bypasses the - // usual rule-search process and always uses the rule that precedes - // it in its own rule set's rule list (this is used for place-value - // notations: formats where you want to see a particular part of - // a number even when it's 0) else if (workingDescription.charAt(0) == gGreaterThan) { + // if the description is ">>>", this substitution bypasses the + // usual rule-search process and always uses the rule that precedes + // it in its own rule set's rule list (this is used for place-value + // notations: formats where you want to see a particular part of + // a number even when it's 0) + // this causes problems when >>> is used in a frationalPartSubstitution // this->ruleSet = NULL; this->ruleSet = _ruleSet; this->numberFormat = NULL; } - // and of the description is none of these things, it's a syntax error else { + // and of the description is none of these things, it's a syntax error + // throw new IllegalArgumentException("Illegal substitution syntax"); status = U_PARSE_ERROR; } @@ -518,8 +478,8 @@ NFSubstitution::NFSubstitution(int32_t _pos, NFSubstitution::~NFSubstitution() { - // cast away const - delete (NumberFormat*)numberFormat; numberFormat = NULL; + delete numberFormat; + numberFormat = NULL; } /** @@ -530,10 +490,16 @@ NFSubstitution::~NFSubstitution() * @param exponent The exponent of the divisor */ void -NFSubstitution::setDivisor(int32_t /*radix*/, int32_t /*exponent*/, UErrorCode& /*status*/) { +NFSubstitution::setDivisor(int32_t /*radix*/, int16_t /*exponent*/, UErrorCode& /*status*/) { // a no-op for all substitutions except multiplier and modulus substitutions } +void +NFSubstitution::setDecimalFormatSymbols(const DecimalFormatSymbols &newSymbols, UErrorCode& /*status*/) { + if (numberFormat != NULL) { + numberFormat->setDecimalFormatSymbols(newSymbols); + } +} //----------------------------------------------------------------------- // boilerplate @@ -602,26 +568,41 @@ NFSubstitution::toString(UnicodeString& text) const * position to determine exactly where to insert the new text) */ void -NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, UErrorCode& status) const +NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const { if (ruleSet != NULL) { - // perform a transformation on the number that is dependent + // Perform a transformation on the number that is dependent // on the type of substitution this is, then just call its // rule set's format() method to format the result - ruleSet->format(transformNumber(number), toInsertInto, _pos + this->pos, status); + ruleSet->format(transformNumber(number), toInsertInto, _pos + this->pos, recursionCount, status); } else if (numberFormat != NULL) { - // or perform the transformation on the number (preserving - // the result's fractional part if the formatter it set - // to show it), then use that formatter's format() method - // to format the result - double numberToFormat = transformNumber((double)number); - if (numberFormat->getMaximumFractionDigits() == 0) { - numberToFormat = uprv_floor(numberToFormat); - } + if (number <= MAX_INT64_IN_DOUBLE) { + // or perform the transformation on the number (preserving + // the result's fractional part if the formatter it set + // to show it), then use that formatter's format() method + // to format the result + double numberToFormat = transformNumber((double)number); + if (numberFormat->getMaximumFractionDigits() == 0) { + numberToFormat = uprv_floor(numberToFormat); + } - UnicodeString temp; - numberFormat->format(numberToFormat, temp, status); - toInsertInto.insert(_pos + this->pos, temp); + UnicodeString temp; + numberFormat->format(numberToFormat, temp, status); + toInsertInto.insert(_pos + this->pos, temp); + } + else { + // We have gone beyond double precision. Something has to give. + // We're favoring accuracy of the large number over potential rules + // that round like a CompactDecimalFormat, which is not a common use case. + // + // Perform a transformation on the number that is dependent + // on the type of substitution this is, then just call its + // rule set's format() method to format the result + int64_t numberToFormat = transformNumber(number); + UnicodeString temp; + numberFormat->format(numberToFormat, temp, status); + toInsertInto.insert(_pos + this->pos, temp); + } } } @@ -636,24 +617,29 @@ NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int3 * position to determine exactly where to insert the new text) */ void -NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos, UErrorCode& status) const { +NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const { // perform a transformation on the number being formatted that // is dependent on the type of substitution this is double numberToFormat = transformNumber(number); - DigitList digits; - digits.set(numberToFormat); + + if (uprv_isInfinite(numberToFormat)) { + // This is probably a minus rule. Combine it with an infinite rule. + const NFRule *infiniteRule = ruleSet->findDoubleRule(uprv_getInfinity()); + infiniteRule->doFormat(numberToFormat, toInsertInto, _pos + this->pos, recursionCount, status); + return; + } // if the result is an integer, from here on out we work in integer // space (saving time and memory and preserving accuracy) - if (numberToFormat == uprv_floor(numberToFormat) && ruleSet != NULL && (!digits.isInfinite())) { - ruleSet->format(util64_fromDouble(numberToFormat), toInsertInto, _pos + this->pos, status); + if (numberToFormat == uprv_floor(numberToFormat) && ruleSet != NULL) { + ruleSet->format(util64_fromDouble(numberToFormat), toInsertInto, _pos + this->pos, recursionCount, status); // if the result isn't an integer, then call either our rule set's // format() method or our DecimalFormat's format() method to // format the result } else { if (ruleSet != NULL) { - ruleSet->format(numberToFormat, toInsertInto, _pos + this->pos, status); + ruleSet->format(numberToFormat, toInsertInto, _pos + this->pos, recursionCount, status); } else if (numberFormat != NULL) { UnicodeString temp; numberFormat->format(numberToFormat, temp); @@ -706,6 +692,7 @@ NFSubstitution::doParse(const UnicodeString& text, double baseValue, double upperBound, UBool lenientParse, + uint32_t nonNumericalExecutedRuleMask, Formattable& result) const { #ifdef RBNF_DEBUG @@ -726,7 +713,7 @@ NFSubstitution::doParse(const UnicodeString& text, // on), then also try parsing the text using a default- // constructed NumberFormat if (ruleSet != NULL) { - ruleSet->parse(text, parsePosition, upperBound, result); + ruleSet->parse(text, parsePosition, upperBound, nonNumericalExecutedRuleMask, result); if (lenientParse && !ruleSet->isFractionRuleSet() && parsePosition.getIndex() == 0) { UErrorCode status = U_ZERO_ERROR; NumberFormat* fmt = NumberFormat::createInstance(status); @@ -781,11 +768,6 @@ NFSubstitution::doParse(const UnicodeString& text, } } -UBool -NFSubstitution::isNullSubstitution() const { - return FALSE; -} - /** * Returns true if this is a modulus substitution. (We didn't do this * with instanceof partially because it causes source files to @@ -798,6 +780,7 @@ NFSubstitution::isModulusSubstitution() const { } /** + * Apple addition * @return true if this is a decimal format-only substitution */ UBool @@ -806,12 +789,13 @@ NFSubstitution::isDecimalFormatSubstitutionOnly() const { } /** + * Apple addition, not currently used * @return true if this substitution uses another ruleSet */ -UBool -NFSubstitution::isRuleSetSubstitutionOnly() const { - return (getNumberFormat() == NULL && ruleSet != NULL); -} +//UBool +//NFSubstitution::isRuleSetSubstitutionOnly() const { +// return (getNumberFormat() == NULL && ruleSet != NULL); +//} //=================================================================== // SameValueSubstitution @@ -823,10 +807,9 @@ NFSubstitution::isRuleSetSubstitutionOnly() const { */ SameValueSubstitution::SameValueSubstitution(int32_t _pos, const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status) -: NFSubstitution(_pos, _ruleSet, formatter, description, status) +: NFSubstitution(_pos, _ruleSet, description, status) { if (0 == description.compare(gEqualsEquals, 2)) { // throw new IllegalArgumentException("== is not a legal token"); @@ -859,23 +842,20 @@ UBool MultiplierSubstitution::operator==(const NFSubstitution& rhs) const * regular rule. */ ModulusSubstitution::ModulusSubstitution(int32_t _pos, - double _divisor, + const NFRule* rule, const NFRule* predecessor, const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status) - : NFSubstitution(_pos, _ruleSet, formatter, description, status) - , divisor(_divisor) + : NFSubstitution(_pos, _ruleSet, description, status) + , divisor(rule->getDivisor()) , ruleToUse(NULL) { - ldivisor = util64_fromDouble(_divisor); - // the owning rule's divisor controls the behavior of this // substitution: rather than keeping a backpointer to the rule, // we keep a copy of the divisor - if (ldivisor == 0) { + if (divisor == 0) { status = U_PARSE_ERROR; } @@ -912,19 +892,19 @@ UBool ModulusSubstitution::operator==(const NFSubstitution& rhs) const * @param pos The position of the rule text in toInsertInto */ void -ModulusSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, UErrorCode& status) const +ModulusSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const { // if this isn't a >>> substitution, just use the inherited version // of this function (which uses either a rule set or a DecimalFormat // to format its substitution value) if (ruleToUse == NULL) { - NFSubstitution::doSubstitution(number, toInsertInto, _pos, status); + NFSubstitution::doSubstitution(number, toInsertInto, _pos, recursionCount, status); // a >>> substitution goes straight to a particular rule to // format the substitution value } else { int64_t numberToFormat = transformNumber(number); - ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos(), status); + ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos(), recursionCount, status); } } @@ -937,20 +917,20 @@ ModulusSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, * @param pos The position of the rule text in toInsertInto */ void -ModulusSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos, UErrorCode& status) const +ModulusSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const { // if this isn't a >>> substitution, just use the inherited version // of this function (which uses either a rule set or a DecimalFormat // to format its substitution value) if (ruleToUse == NULL) { - NFSubstitution::doSubstitution(number, toInsertInto, _pos, status); + NFSubstitution::doSubstitution(number, toInsertInto, _pos, recursionCount, status); // a >>> substitution goes straight to a particular rule to // format the substitution value } else { double numberToFormat = transformNumber(number); - ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos(), status); + ruleToUse->doFormat(numberToFormat, toInsertInto, _pos + getPos(), recursionCount, status); } } @@ -973,18 +953,19 @@ ModulusSubstitution::doParse(const UnicodeString& text, double baseValue, double upperBound, UBool lenientParse, + uint32_t nonNumericalExecutedRuleMask, Formattable& result) const { // if this isn't a >>> substitution, we can just use the // inherited parse() routine to do the parsing if (ruleToUse == NULL) { - return NFSubstitution::doParse(text, parsePosition, baseValue, upperBound, lenientParse, result); + return NFSubstitution::doParse(text, parsePosition, baseValue, upperBound, lenientParse, nonNumericalExecutedRuleMask, result); // but if it IS a >>> substitution, we have to do it here: we // use the specific rule's doParse() method, and then we have to // do some of the other work of NFRuleSet.parse() } else { - ruleToUse->doParse(text, parsePosition, FALSE, upperBound, result); + ruleToUse->doParse(text, parsePosition, FALSE, upperBound, nonNumericalExecutedRuleMask, result); if (parsePosition.getIndex() != 0) { UErrorCode status = U_ZERO_ERROR; @@ -1038,10 +1019,9 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IntegralPartSubstitution) */ FractionalPartSubstitution::FractionalPartSubstitution(int32_t _pos, const NFRuleSet* _ruleSet, - const RuleBasedNumberFormat* formatter, const UnicodeString& description, UErrorCode& status) - : NFSubstitution(_pos, _ruleSet, formatter, description, status) + : NFSubstitution(_pos, _ruleSet, description, status) , byDigits(FALSE) , useSpaces(TRUE) @@ -1076,12 +1056,12 @@ FractionalPartSubstitution::FractionalPartSubstitution(int32_t _pos, */ void FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, - int32_t _pos, UErrorCode& status) const + int32_t _pos, int32_t recursionCount, UErrorCode& status) const { // if we're not in "byDigits" mode, just use the inherited // doSubstitution() routine if (!byDigits) { - NFSubstitution::doSubstitution(number, toInsertInto, _pos, status); + NFSubstitution::doSubstitution(number, toInsertInto, _pos, recursionCount, status); // if we're in "byDigits" mode, transform the value into an integer // by moving the decimal point eight places to the right and @@ -1123,13 +1103,13 @@ FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInser pad = TRUE; } int64_t digit = didx>=0 ? dl.getDigit(didx) - '0' : 0; - getRuleSet()->format(digit, toInsertInto, _pos + getPos(), status); + getRuleSet()->format(digit, toInsertInto, _pos + getPos(), recursionCount, status); } if (!pad) { // hack around lack of precision in digitlist. if we would end up with // "foo point" make sure we add a " zero" to the end. - getRuleSet()->format((int64_t)0, toInsertInto, _pos + getPos(), status); + getRuleSet()->format((int64_t)0, toInsertInto, _pos + getPos(), recursionCount, status); } } } @@ -1161,12 +1141,13 @@ FractionalPartSubstitution::doParse(const UnicodeString& text, double baseValue, double /*upperBound*/, UBool lenientParse, + uint32_t nonNumericalExecutedRuleMask, Formattable& resVal) const { // if we're not in byDigits mode, we can just use the inherited // doParse() if (!byDigits) { - return NFSubstitution::doParse(text, parsePosition, baseValue, 0, lenientParse, resVal); + return NFSubstitution::doParse(text, parsePosition, baseValue, 0, lenientParse, nonNumericalExecutedRuleMask, resVal); // if we ARE in byDigits mode, parse the text one digit at a time // using this substitution's owning rule set (we do this by setting @@ -1184,7 +1165,7 @@ FractionalPartSubstitution::doParse(const UnicodeString& text, while (workText.length() > 0 && workPos.getIndex() != 0) { workPos.setIndex(0); Formattable temp; - getRuleSet()->parse(workText, workPos, 10, temp); + getRuleSet()->parse(workText, workPos, 10, nonNumericalExecutedRuleMask, temp); UErrorCode status = U_ZERO_ERROR; digit = temp.getLong(status); // digit = temp.getType() == Formattable::kLong ? @@ -1248,7 +1229,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AbsoluteValueSubstitution) //=================================================================== void -NumeratorSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t apos, UErrorCode& status) const { +NumeratorSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t apos, int32_t recursionCount, UErrorCode& status) const { // perform a transformation on the number being formatted that // is dependent on the type of substitution this is @@ -1262,7 +1243,7 @@ NumeratorSubstitution::doSubstitution(double number, UnicodeString& toInsertInto int32_t len = toInsertInto.length(); while ((nf *= 10) < denominator) { toInsertInto.insert(apos + getPos(), gSpace); - aruleSet->format((int64_t)0, toInsertInto, apos + getPos(), status); + aruleSet->format((int64_t)0, toInsertInto, apos + getPos(), recursionCount, status); } apos += toInsertInto.length() - len; } @@ -1270,14 +1251,14 @@ NumeratorSubstitution::doSubstitution(double number, UnicodeString& toInsertInto // if the result is an integer, from here on out we work in integer // space (saving time and memory and preserving accuracy) if (numberToFormat == longNF && aruleSet != NULL) { - aruleSet->format(longNF, toInsertInto, apos + getPos(), status); + aruleSet->format(longNF, toInsertInto, apos + getPos(), recursionCount, status); // if the result isn't an integer, then call either our rule set's // format() method or our DecimalFormat's format() method to // format the result } else { if (aruleSet != NULL) { - aruleSet->format(numberToFormat, toInsertInto, apos + getPos(), status); + aruleSet->format(numberToFormat, toInsertInto, apos + getPos(), recursionCount, status); } else { UnicodeString temp; getNumberFormat()->format(numberToFormat, temp, status); @@ -1292,6 +1273,7 @@ NumeratorSubstitution::doParse(const UnicodeString& text, double baseValue, double upperBound, UBool /*lenientParse*/, + uint32_t nonNumericalExecutedRuleMask, Formattable& result) const { // we don't have to do anything special to do the parsing here, @@ -1310,7 +1292,7 @@ NumeratorSubstitution::doParse(const UnicodeString& text, while (workText.length() > 0 && workPos.getIndex() != 0) { workPos.setIndex(0); - getRuleSet()->parse(workText, workPos, 1, temp); // parse zero or nothing at all + getRuleSet()->parse(workText, workPos, 1, nonNumericalExecutedRuleMask, temp); // parse zero or nothing at all if (workPos.getIndex() == 0) { // we failed, either there were no more zeros, or the number was formatted with digits // either way, we're done @@ -1332,7 +1314,7 @@ NumeratorSubstitution::doParse(const UnicodeString& text, } // we've parsed off the zeros, now let's parse the rest from our current position - NFSubstitution::doParse(workText, parsePosition, withZeros ? 1 : baseValue, upperBound, FALSE, result); + NFSubstitution::doParse(workText, parsePosition, withZeros ? 1 : baseValue, upperBound, FALSE, nonNumericalExecutedRuleMask, result); if (withZeros) { // any base value will do in this case. is there a way to @@ -1369,12 +1351,6 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumeratorSubstitution) const UChar NumeratorSubstitution::LTLT[] = { 0x003c, 0x003c }; -//=================================================================== -// NullSubstitution -//=================================================================== - -UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NullSubstitution) - U_NAMESPACE_END /* U_HAVE_RBNF */