Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: source/i18n/nfrule.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « source/i18n/nfrule.h ('k') | source/i18n/nfsubs.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: source/i18n/nfrule.cpp
diff --git a/source/i18n/nfrule.cpp b/source/i18n/nfrule.cpp
index f8ed0b6c35fa68e57555f276b467363e576b9965..f0e0953d802e1aa1cdb730ced1901e97e871c7e7 100644
--- a/source/i18n/nfrule.cpp
+++ b/source/i18n/nfrule.cpp
@@ -1,6 +1,6 @@
/*
******************************************************************************
-* Copyright (C) 1997-2014, International Business Machines
+* Copyright (C) 1997-2015, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* file name: nfrule.cpp
@@ -31,25 +31,32 @@
U_NAMESPACE_BEGIN
-NFRule::NFRule(const RuleBasedNumberFormat* _rbnf)
+NFRule::NFRule(const RuleBasedNumberFormat* _rbnf, const UnicodeString &_ruleText, UErrorCode &status)
: baseValue((int32_t)0)
- , radix(0)
+ , radix(10)
, exponent(0)
- , ruleText()
+ , decimalPoint(0)
+ , ruleText(_ruleText)
, sub1(NULL)
, sub2(NULL)
, formatter(_rbnf)
, rulePatternFormat(NULL)
{
+ if (!ruleText.isEmpty()) {
+ parseRuleDescriptor(ruleText, status);
+ }
}
NFRule::~NFRule()
{
if (sub1 != sub2) {
delete sub2;
+ sub2 = NULL;
}
delete sub1;
+ sub1 = NULL;
delete rulePatternFormat;
+ rulePatternFormat = NULL;
}
static const UChar gLeftBracket = 0x005b;
@@ -66,11 +73,11 @@ static const UChar gDot = 0x002e;
static const UChar gTick = 0x0027;
//static const UChar gMinus = 0x002d;
static const UChar gSemicolon = 0x003b;
+static const UChar gX = 0x0078;
static const UChar gMinusX[] = {0x2D, 0x78, 0}; /* "-x" */
-static const UChar gXDotX[] = {0x78, 0x2E, 0x78, 0}; /* "x.x" */
-static const UChar gXDotZero[] = {0x78, 0x2E, 0x30, 0}; /* "x.0" */
-static const UChar gZeroDotX[] = {0x30, 0x2E, 0x78, 0}; /* "0.x" */
+static const UChar gInf[] = {0x49, 0x6E, 0x66, 0}; /* "Inf" */
+static const UChar gNaN[] = {0x4E, 0x61, 0x4E, 0}; /* "NaN" */
static const UChar gDollarOpenParenthesis[] = {0x24, 0x28, 0}; /* "$(" */
static const UChar gClosedParenthesisDollar[] = {0x29, 0x24, 0}; /* ")$" */
@@ -88,7 +95,7 @@ static const UChar gEqualHash[] = {0x3D, 0x23, 0}; /* "=#" */
static const UChar gEqualZero[] = {0x3D, 0x30, 0}; /* "=0" */
static const UChar gGreaterGreaterGreater[] = {0x3E, 0x3E, 0x3E, 0}; /* ">>>" */
-static const UChar * const tokenStrings[] = {
+static const UChar * const RULE_PREFIXES[] = {
gLessLess, gLessPercent, gLessHash, gLessZero,
gGreaterGreater, gGreaterPercent,gGreaterHash, gGreaterZero,
gEqualPercent, gEqualHash, gEqualZero, NULL
@@ -96,7 +103,7 @@ static const UChar * const tokenStrings[] = {
void
NFRule::makeRules(UnicodeString& description,
- const NFRuleSet *ruleSet,
+ NFRuleSet *owner,
const NFRule *predecessor,
const RuleBasedNumberFormat *rbnf,
NFRuleList& rules,
@@ -106,29 +113,32 @@ NFRule::makeRules(UnicodeString& description,
// new it up and initialize its basevalue and divisor
// (this also strips the rule descriptor, if any, off the
// descripton string)
- NFRule* rule1 = new NFRule(rbnf);
+ NFRule* rule1 = new NFRule(rbnf, description, status);
/* test for NULL */
if (rule1 == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
- rule1->parseRuleDescriptor(description, status);
+ description = rule1->ruleText;
// check the description to see whether there's text enclosed
// in brackets
int32_t brack1 = description.indexOf(gLeftBracket);
- int32_t brack2 = description.indexOf(gRightBracket);
+ int32_t brack2 = brack1 < 0 ? -1 : description.indexOf(gRightBracket);
// if the description doesn't contain a matched pair of brackets,
// or if it's of a type that doesn't recognize bracketed text,
// then leave the description alone, initialize the rule's
// rule text and substitutions, and return that rule
- if (brack1 == -1 || brack2 == -1 || brack1 > brack2
+ if (brack2 < 0 || brack1 > brack2
|| rule1->getType() == kProperFractionRule
- || rule1->getType() == kNegativeNumberRule) {
- rule1->extractSubstitutions(ruleSet, description, predecessor, status);
- rules.add(rule1);
- } else {
+ || rule1->getType() == kNegativeNumberRule
+ || rule1->getType() == kInfinityRule
+ || rule1->getType() == kNaNRule)
+ {
+ rule1->extractSubstitutions(owner, description, predecessor, status);
+ }
+ else {
// if the description does contain a matched pair of brackets,
// then it's really shorthand for two rules (with one exception)
NFRule* rule2 = NULL;
@@ -147,7 +157,7 @@ NFRule::makeRules(UnicodeString& description,
// set, they both have the same base value; otherwise,
// increment the original rule's base value ("rule1" actually
// goes SECOND in the rule set's rule list)
- rule2 = new NFRule(rbnf);
+ rule2 = new NFRule(rbnf, UnicodeString(), status);
/* test for NULL */
if (rule2 == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
@@ -155,7 +165,7 @@ NFRule::makeRules(UnicodeString& description,
}
if (rule1->baseValue >= 0) {
rule2->baseValue = rule1->baseValue;
- if (!ruleSet->isFractionRuleSet()) {
+ if (!owner->isFractionRuleSet()) {
++rule1->baseValue;
}
}
@@ -186,7 +196,7 @@ NFRule::makeRules(UnicodeString& description,
if (brack2 + 1 < description.length()) {
sbuf.append(description, brack2 + 1, description.length() - brack2 - 1);
}
- rule2->extractSubstitutions(ruleSet, sbuf, predecessor, status);
+ rule2->extractSubstitutions(owner, sbuf, predecessor, status);
}
// rule1's text includes the text in the brackets but omits
@@ -197,7 +207,7 @@ NFRule::makeRules(UnicodeString& description,
if (brack2 + 1 < description.length()) {
sbuf.append(description, brack2 + 1, description.length() - brack2 - 1);
}
- rule1->extractSubstitutions(ruleSet, sbuf, predecessor, status);
+ rule1->extractSubstitutions(owner, sbuf, predecessor, status);
// if we only have one rule, return it; if we have two, return
// a two-element array containing them (notice that rule2 goes
@@ -205,10 +215,20 @@ NFRule::makeRules(UnicodeString& description,
// material in the brackets and rule1 INCLUDES the material
// in the brackets)
if (rule2 != NULL) {
- rules.add(rule2);
+ if (rule2->baseValue >= kNoBase) {
+ rules.add(rule2);
+ }
+ else {
+ owner->setNonNumericalRule(rule2);
+ }
}
+ }
+ if (rule1->baseValue >= kNoBase) {
rules.add(rule1);
}
+ else {
+ owner->setNonNumericalRule(rule1);
+ }
}
/**
@@ -230,9 +250,7 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
// separated by a colon. The rule descriptor is optional. If
// it's omitted, just set the base value to 0.
int32_t p = description.indexOf(gColon);
- if (p == -1) {
- setBaseValue((int32_t)0, status);
- } else {
+ if (p != -1) {
// copy the descriptor out into its own string and strip it,
// along with any trailing whitespace, out of the original
// description
@@ -247,25 +265,15 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
// check first to see if the rule descriptor matches the token
// for one of the special rules. If it does, set the base
- // value to the correct identfier value
- if (0 == descriptor.compare(gMinusX, 2)) {
- setType(kNegativeNumberRule);
- }
- else if (0 == descriptor.compare(gXDotX, 3)) {
- setType(kImproperFractionRule);
- }
- else if (0 == descriptor.compare(gZeroDotX, 3)) {
- setType(kProperFractionRule);
- }
- else if (0 == descriptor.compare(gXDotZero, 3)) {
- setType(kMasterRule);
- }
-
- // if the rule descriptor begins with a digit, it's a descriptor
- // for a normal rule
- // since we don't have Long.parseLong, and this isn't much work anyway,
- // just build up the value as we encounter the digits.
- else if (descriptor.charAt(0) >= gZero && descriptor.charAt(0) <= gNine) {
+ // value to the correct identifier value
+ int descriptorLength = descriptor.length();
+ UChar firstChar = descriptor.charAt(0);
+ UChar lastChar = descriptor.charAt(descriptorLength - 1);
+ if (firstChar >= gZero && firstChar <= gNine && lastChar != gX) {
+ // if the rule descriptor begins with a digit, it's a descriptor
+ // for a normal rule
+ // since we don't have Long.parseLong, and this isn't much work anyway,
+ // just build up the value as we encounter the digits.
int64_t val = 0;
p = 0;
UChar c = gSpace;
@@ -275,7 +283,7 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
// stop on a slash or > sign (or at the end of the string),
// and throw an exception on any other character
int64_t ll_10 = 10;
- while (p < descriptor.length()) {
+ while (p < descriptorLength) {
c = descriptor.charAt(p);
if (c >= gZero && c <= gNine) {
val = val * ll_10 + (int32_t)(c - gZero);
@@ -304,7 +312,7 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
val = 0;
++p;
int64_t ll_10 = 10;
- while (p < descriptor.length()) {
+ while (p < descriptorLength) {
c = descriptor.charAt(p);
if (c >= gZero && c <= gNine) {
val = val * ll_10 + (int32_t)(c - gZero);
@@ -352,7 +360,31 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status)
}
}
}
+ else if (0 == descriptor.compare(gMinusX, 2)) {
+ setType(kNegativeNumberRule);
+ }
+ else if (descriptorLength == 3) {
+ if (firstChar == gZero && lastChar == gX) {
+ setBaseValue(kProperFractionRule, status);
+ decimalPoint = descriptor.charAt(1);
+ }
+ else if (firstChar == gX && lastChar == gX) {
+ setBaseValue(kImproperFractionRule, status);
+ decimalPoint = descriptor.charAt(1);
+ }
+ else if (firstChar == gX && lastChar == gZero) {
+ setBaseValue(kMasterRule, status);
+ decimalPoint = descriptor.charAt(1);
+ }
+ else if (descriptor.compare(gNaN, 3) == 0) {
+ setBaseValue(kNaNRule, status);
+ }
+ else if (descriptor.compare(gInf, 3) == 0) {
+ setBaseValue(kInfinityRule, status);
+ }
+ }
}
+ // else use the default base value for now.
// finally, if the rule body begins with an apostrophe, strip it off
// (this is generally used to put whitespace at the beginning of
@@ -384,11 +416,10 @@ NFRule::extractSubstitutions(const NFRuleSet* ruleSet,
return;
}
this->ruleText = ruleText;
- this->rulePatternFormat = NULL;
sub1 = extractSubstitution(ruleSet, predecessor, status);
- if (sub1 == NULL || sub1->isNullSubstitution()) {
+ if (sub1 == NULL) {
// Small optimization. There is no need to create a redundant NullSubstitution.
- sub2 = sub1;
+ sub2 = NULL;
}
else {
sub2 = extractSubstitution(ruleSet, predecessor, status);
@@ -439,14 +470,13 @@ NFRule::extractSubstitution(const NFRuleSet* ruleSet,
// search the rule's rule text for the first two characters of
// a substitution token
- int32_t subStart = indexOfAny(tokenStrings);
+ int32_t subStart = indexOfAnyRulePrefix();
int32_t subEnd = subStart;
// if we didn't find one, create a null substitution positioned
// at the end of the rule text
if (subStart == -1) {
- return NFSubstitution::makeSubstitution(ruleText.length(), this, predecessor,
- ruleSet, this->formatter, UnicodeString(), status);
+ return NULL;
}
// special-case the ">>>" token, since searching for the > at the
@@ -473,8 +503,7 @@ NFRule::extractSubstitution(const NFRuleSet* ruleSet,
// unmatched token character), create a null substitution positioned
// at the end of the rule
if (subEnd == -1) {
- return NFSubstitution::makeSubstitution(ruleText.length(), this, predecessor,
- ruleSet, this->formatter, UnicodeString(), status);
+ return NULL;
}
// if we get here, we have a real substitution token (or at least
@@ -503,6 +532,7 @@ NFRule::setBaseValue(int64_t newBaseValue, UErrorCode& status)
{
// set the base value
baseValue = newBaseValue;
+ radix = 10;
// if this isn't a special rule, recalculate the radix and exponent
// (the radix always defaults to 10; if it's supposed to be something
@@ -510,7 +540,6 @@ NFRule::setBaseValue(int64_t newBaseValue, UErrorCode& status)
// recalculated again-- the only function that does this is
// NFRule.parseRuleDescriptor() )
if (baseValue >= 1) {
- radix = 10;
exponent = expectedExponent();
// this function gets called on a fully-constructed rule whose
@@ -527,7 +556,6 @@ NFRule::setBaseValue(int64_t newBaseValue, UErrorCode& status)
// if this is a special rule, its radix and exponent are basically
// ignored. Set them to "safe" default values
} else {
- radix = 10;
exponent = 0;
}
}
@@ -560,19 +588,17 @@ NFRule::expectedExponent() const
/**
* Searches the rule's rule text for any of the specified strings.
- * @param strings An array of strings to search the rule's rule
- * text for
* @return The index of the first match in the rule's rule text
* (i.e., the first substring in the rule's rule text that matches
* _any_ of the strings in "strings"). If none of the strings in
* "strings" is found in the rule's rule text, returns -1.
*/
int32_t
-NFRule::indexOfAny(const UChar* const strings[]) const
+NFRule::indexOfAnyRulePrefix() const
{
int result = -1;
- for (int i = 0; strings[i]; i++) {
- int32_t pos = ruleText.indexOf(*strings[i]);
+ for (int i = 0; RULE_PREFIXES[i]; i++) {
+ int32_t pos = ruleText.indexOf(*RULE_PREFIXES[i]);
if (pos != -1 && (result == -1 || pos < result)) {
result = pos;
}
@@ -584,6 +610,19 @@ NFRule::indexOfAny(const UChar* const strings[]) const
// boilerplate
//-----------------------------------------------------------------------
+static UBool
+util_equalSubstitutions(const NFSubstitution* sub1, const NFSubstitution* sub2)
+{
+ if (sub1) {
+ if (sub2) {
+ return *sub1 == *sub2;
+ }
+ } else if (!sub2) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
/**
* Tests two rules for equality.
* @param that The rule to compare this one against
@@ -596,8 +635,8 @@ NFRule::operator==(const NFRule& rhs) const
&& radix == rhs.radix
&& exponent == rhs.exponent
&& ruleText == rhs.ruleText
- && *sub1 == *rhs.sub1
- && *sub2 == *rhs.sub2;
+ && util_equalSubstitutions(sub1, rhs.sub1)
+ && util_equalSubstitutions(sub2, rhs.sub2);
}
/**
@@ -619,9 +658,11 @@ NFRule::_appendRuleText(UnicodeString& result) const
{
switch (getType()) {
case kNegativeNumberRule: result.append(gMinusX, 2); break;
- case kImproperFractionRule: result.append(gXDotX, 3); break;
- case kProperFractionRule: result.append(gZeroDotX, 3); break;
- case kMasterRule: result.append(gXDotZero, 3); break;
+ case kImproperFractionRule: result.append(gX).append(decimalPoint == 0 ? gDot : decimalPoint).append(gX); break;
+ case kProperFractionRule: result.append(gZero).append(decimalPoint == 0 ? gDot : decimalPoint).append(gX); break;
+ case kMasterRule: result.append(gX).append(decimalPoint == 0 ? gDot : decimalPoint).append(gZero); break;
+ case kInfinityRule: result.append(gInf, 3); break;
+ case kNaNRule: result.append(gNaN, 3); break;
default:
// for a normal rule, write out its base value, and if the radix is
// something other than 10, write out the radix (with the preceding
@@ -646,7 +687,7 @@ NFRule::_appendRuleText(UnicodeString& result) const
// if the rule text begins with a space, write an apostrophe
// (whitespace after the rule descriptor is ignored; the
// apostrophe is used to make the whitespace significant)
- if (ruleText.charAt(0) == gSpace && sub1->getPos() != 0) {
+ if (ruleText.charAt(0) == gSpace && (sub1 == NULL || sub1->getPos() != 0)) {
result.append(gTick);
}
@@ -656,10 +697,14 @@ NFRule::_appendRuleText(UnicodeString& result) const
ruleTextCopy.setTo(ruleText);
UnicodeString temp;
- sub2->toString(temp);
- ruleTextCopy.insert(sub2->getPos(), temp);
- sub1->toString(temp);
- ruleTextCopy.insert(sub1->getPos(), temp);
+ if (sub2 != NULL) {
+ sub2->toString(temp);
+ ruleTextCopy.insert(sub2->getPos(), temp);
+ }
+ if (sub1 != NULL) {
+ sub1->toString(temp);
+ ruleTextCopy.insert(sub1->getPos(), temp);
+ }
result.append(ruleTextCopy);
@@ -682,7 +727,7 @@ NFRule::_appendRuleText(UnicodeString& result) const
* should be inserted
*/
void
-NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos, UErrorCode& status) const
+NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const
{
// first, insert the rule's rule text into toInsertInto at the
// specified position, then insert the results of the substitutions
@@ -709,11 +754,11 @@ NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos, UErro
lengthOffset = ruleText.length() - (toInsertInto.length() - initialLength);
}
- if (!sub2->isNullSubstitution()) {
- sub2->doSubstitution(number, toInsertInto, pos - (sub2->getPos() > pluralRuleStart ? lengthOffset : 0), status);
+ if (sub2 != NULL) {
+ sub2->doSubstitution(number, toInsertInto, pos - (sub2->getPos() > pluralRuleStart ? lengthOffset : 0), recursionCount, status);
}
- if (!sub1->isNullSubstitution()) {
- sub1->doSubstitution(number, toInsertInto, pos - (sub1->getPos() > pluralRuleStart ? lengthOffset : 0), status);
+ if (sub1 != NULL) {
+ sub1->doSubstitution(number, toInsertInto, pos - (sub1->getPos() > pluralRuleStart ? lengthOffset : 0), recursionCount, status);
}
}
@@ -727,7 +772,7 @@ NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos, UErro
* should be inserted
*/
void
-NFRule::doFormat(double number, UnicodeString& toInsertInto, int32_t pos, UErrorCode& status) const
+NFRule::doFormat(double number, UnicodeString& toInsertInto, int32_t pos, int32_t recursionCount, UErrorCode& status) const
{
// first, insert the rule's rule text into toInsertInto at the
// specified position, then insert the results of the substitutions
@@ -747,19 +792,27 @@ NFRule::doFormat(double number, UnicodeString& toInsertInto, int32_t pos, UError
if (pluralRuleEnd < ruleText.length() - 1) {
toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 2));
}
- toInsertInto.insert(pos,
- rulePatternFormat->format((int32_t)(number/uprv_pow(radix, exponent)), status));
+ double pluralVal = number;
+ if (0 <= pluralVal && pluralVal < 1) {
+ // We're in a fractional rule, and we have to match the NumeratorSubstitution behavior.
+ // 2.3 can become 0.2999999999999998 for the fraction due to rounding errors.
+ pluralVal = uprv_round(pluralVal * uprv_pow(radix, exponent));
+ }
+ else {
+ pluralVal = pluralVal / uprv_pow(radix, exponent);
+ }
+ toInsertInto.insert(pos, rulePatternFormat->format((int32_t)(pluralVal), status));
if (pluralRuleStart > 0) {
toInsertInto.insert(pos, ruleText.tempSubString(0, pluralRuleStart));
}
lengthOffset = ruleText.length() - (toInsertInto.length() - initialLength);
}
- if (!sub2->isNullSubstitution()) {
- sub2->doSubstitution(number, toInsertInto, pos - (sub2->getPos() > pluralRuleStart ? lengthOffset : 0), status);
+ if (sub2 != NULL) {
+ sub2->doSubstitution(number, toInsertInto, pos - (sub2->getPos() > pluralRuleStart ? lengthOffset : 0), recursionCount, status);
}
- if (!sub1->isNullSubstitution()) {
- sub1->doSubstitution(number, toInsertInto, pos - (sub1->getPos() > pluralRuleStart ? lengthOffset : 0), status);
+ if (sub1 != NULL) {
+ sub1->doSubstitution(number, toInsertInto, pos - (sub1->getPos() > pluralRuleStart ? lengthOffset : 0), recursionCount, status);
}
}
@@ -790,7 +843,7 @@ NFRule::shouldRollBack(double number) const
// a modulus substitution, its base value isn't an even multiple
// of 100, and the value we're trying to format _is_ an even
// multiple of 100. This is called the "rollback rule."
- if ((sub1->isModulusSubstitution()) || (sub2->isModulusSubstitution())) {
+ if ((sub1 != NULL && sub1->isModulusSubstitution()) || (sub2 != NULL && sub2->isModulusSubstitution())) {
int64_t re = util64_pow(radix, exponent);
return uprv_fmod(number, (double)re) == 0 && (baseValue % re) != 0;
}
@@ -833,7 +886,6 @@ static void dumpUS(FILE* f, const UnicodeString& us) {
}
}
#endif
-
UBool
NFRule::doParse(const UnicodeString& text,
ParsePosition& parsePosition,
@@ -846,22 +898,25 @@ NFRule::doParse(const UnicodeString& text,
ParsePosition pp;
UnicodeString workText(text);
+ int32_t sub1Pos = sub1 != NULL ? sub1->getPos() : ruleText.length();
+ int32_t sub2Pos = sub2 != NULL ? sub2->getPos() : ruleText.length();
+
// check to see whether the text before the first substitution
// matches the text at the beginning of the string being
// parsed. If it does, strip that off the front of workText;
// otherwise, dump out with a mismatch
UnicodeString prefix;
- prefix.setTo(ruleText, 0, sub1->getPos());
+ prefix.setTo(ruleText, 0, sub1Pos);
#ifdef RBNF_DEBUG
- fprintf(stderr, "doParse %x ", this);
+ fprintf(stderr, "doParse %p ", this);
{
UnicodeString rt;
_appendRuleText(rt);
dumpUS(stderr, rt);
}
- fprintf(stderr, " text: '", this);
+ fprintf(stderr, " text: '");
dumpUS(stderr, text);
fprintf(stderr, "' prefix: '");
dumpUS(stderr, prefix);
@@ -870,16 +925,28 @@ NFRule::doParse(const UnicodeString& text,
int32_t prefixLength = text.length() - workText.length();
#ifdef RBNF_DEBUG
- fprintf(stderr, "' pl: %d ppi: %d s1p: %d\n", prefixLength, pp.getIndex(), sub1->getPos());
+ fprintf(stderr, "' pl: %d ppi: %d s1p: %d\n", prefixLength, pp.getIndex(), sub1Pos);
#endif
- if (pp.getIndex() == 0 && sub1->getPos() != 0) {
+ if (pp.getIndex() == 0 && sub1Pos != 0) {
// commented out because ParsePosition doesn't have error index in 1.1.x
// restored for ICU4C port
parsePosition.setErrorIndex(pp.getErrorIndex());
resVal.setLong(0);
return TRUE;
}
+ if (baseValue == kInfinityRule) {
+ // If you match this, don't try to perform any calculations on it.
+ parsePosition.setIndex(pp.getIndex());
+ resVal.setDouble(uprv_getInfinity());
+ return TRUE;
+ }
+ if (baseValue == kNaNRule) {
+ // If you match this, don't try to perform any calculations on it.
+ parsePosition.setIndex(pp.getIndex());
+ resVal.setDouble(uprv_getNaN());
+ return TRUE;
+ }
// this is the fun part. The basic guts of the rule-matching
// logic is matchToDelimiter(), which is called twice. The first
@@ -923,7 +990,7 @@ NFRule::doParse(const UnicodeString& text,
// the substitution, giving us a new partial parse result
pp.setIndex(0);
- temp.setTo(ruleText, sub1->getPos(), sub2->getPos() - sub1->getPos());
+ temp.setTo(ruleText, sub1Pos, sub2Pos - sub1Pos);
double partialResult = matchToDelimiter(workText, start, tempBaseValue,
temp, pp, sub1,
upperBound);
@@ -932,7 +999,7 @@ NFRule::doParse(const UnicodeString& text,
// null substitution), pp is now pointing at the first unmatched
// character. Take note of that, and try matchToDelimiter()
// on the input text again
- if (pp.getIndex() != 0 || sub1->isNullSubstitution()) {
+ if (pp.getIndex() != 0 || sub1 == NULL) {
start = pp.getIndex();
UnicodeString workText2;
@@ -943,7 +1010,7 @@ NFRule::doParse(const UnicodeString& text,
// partial result with whatever it gets back from its
// substitution if there's a successful match, giving us
// a real result
- temp.setTo(ruleText, sub2->getPos(), ruleText.length() - sub2->getPos());
+ temp.setTo(ruleText, sub2Pos, ruleText.length() - sub2Pos);
partialResult = matchToDelimiter(workText2, 0, partialResult,
temp, pp2, sub2,
upperBound);
@@ -951,25 +1018,25 @@ NFRule::doParse(const UnicodeString& text,
// if we got a successful match on this second
// matchToDelimiter() call, update the high-water mark
// and result (if necessary)
- if (pp2.getIndex() != 0 || sub2->isNullSubstitution()) {
+ if (pp2.getIndex() != 0 || sub2 == NULL) {
if (prefixLength + pp.getIndex() + pp2.getIndex() > highWaterMark) {
highWaterMark = prefixLength + pp.getIndex() + pp2.getIndex();
result = partialResult;
}
}
- // commented out because ParsePosition doesn't have error index in 1.1.x
- // restored for ICU4C port
else {
- int32_t temp = pp2.getErrorIndex() + sub1->getPos() + pp.getIndex();
+ // commented out because ParsePosition doesn't have error index in 1.1.x
+ // restored for ICU4C port
+ int32_t temp = pp2.getErrorIndex() + sub1Pos + pp.getIndex();
if (temp> parsePosition.getErrorIndex()) {
parsePosition.setErrorIndex(temp);
}
}
}
- // commented out because ParsePosition doesn't have error index in 1.1.x
- // restored for ICU4C port
else {
- int32_t temp = sub1->getPos() + pp.getErrorIndex();
+ // commented out because ParsePosition doesn't have error index in 1.1.x
+ // restored for ICU4C port
+ int32_t temp = sub1Pos + pp.getErrorIndex();
if (temp > parsePosition.getErrorIndex()) {
parsePosition.setErrorIndex(temp);
}
@@ -977,7 +1044,7 @@ NFRule::doParse(const UnicodeString& text,
// keep trying to match things until the outer matchToDelimiter()
// call fails to make a match (each time, it picks up where it
// left off the previous time)
- } while (sub1->getPos() != sub2->getPos()
+ } while (sub1Pos != sub2Pos
&& pp.getIndex() > 0
&& pp.getIndex() < workText.length()
&& pp.getIndex() != start);
@@ -999,9 +1066,7 @@ NFRule::doParse(const UnicodeString& text,
// we have to account for it here. By definition, if the matching
// rule in a fraction rule set has no substitutions, its numerator
// is 1, and so the result is the reciprocal of its base value.
- if (isFractionRule &&
- highWaterMark > 0 &&
- sub1->isNullSubstitution()) {
+ if (isFractionRule && highWaterMark > 0 && sub1 == NULL) {
result = 1 / result;
}
@@ -1129,9 +1194,9 @@ NFRule::matchToDelimiter(const UnicodeString& text,
pp.setIndex(dPos + dLen);
return result.getDouble();
}
- // commented out because ParsePosition doesn't have error index in 1.1.x
- // restored for ICU4C port
else {
+ // commented out because ParsePosition doesn't have error index in 1.1.x
+ // restored for ICU4C port
if (tempPP.getErrorIndex() > 0) {
pp.setErrorIndex(tempPP.getErrorIndex());
} else {
@@ -1155,7 +1220,11 @@ NFRule::matchToDelimiter(const UnicodeString& text,
// (i.e., is semantically empty), thwe we obviously can't search
// for "delimiter". Instead, just use "sub" to parse as much of
// "text" as possible.
- } else {
+ }
+ else if (sub == NULL) {
+ return _baseValue;
+ }
+ else {
ParsePosition tempPP;
Formattable result;
@@ -1167,7 +1236,7 @@ NFRule::matchToDelimiter(const UnicodeString& text,
formatter->isLenient(),
#endif
result);
- if (success && (tempPP.getIndex() != 0 || sub->isNullSubstitution())) {
+ if (success && (tempPP.getIndex() != 0)) {
// if there's a successful match (or it's a null
// substitution), update pp to point to the first
// character we didn't match, and pass the result from
@@ -1175,9 +1244,9 @@ NFRule::matchToDelimiter(const UnicodeString& text,
pp.setIndex(tempPP.getIndex());
return result.getDouble();
}
- // commented out because ParsePosition doesn't have error index in 1.1.x
- // restored for ICU4C port
else {
+ // commented out because ParsePosition doesn't have error index in 1.1.x
+ // restored for ICU4C port
pp.setErrorIndex(tempPP.getErrorIndex());
}
@@ -1522,6 +1591,16 @@ NFRule::allIgnorable(const UnicodeString& str, UErrorCode& status) const
return FALSE;
}
+void
+NFRule::setDecimalFormatSymbols(const DecimalFormatSymbols& newSymbols, UErrorCode& status) {
+ if (sub1 != NULL) {
+ sub1->setDecimalFormatSymbols(newSymbols, status);
+ }
+ if (sub2 != NULL) {
+ sub2->setDecimalFormatSymbols(newSymbols, status);
+ }
+}
+
U_NAMESPACE_END
/* U_HAVE_RBNF */
« no previous file with comments | « source/i18n/nfrule.h ('k') | source/i18n/nfsubs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698