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

Unified Diff: source/i18n/nfrs.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/nfrs.h ('k') | source/i18n/nfrule.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: source/i18n/nfrs.cpp
diff --git a/source/i18n/nfrs.cpp b/source/i18n/nfrs.cpp
index 1a4bf493f3eb7ef83cd1ab8a601884a69c890044..85ebb06fabd4ed9ac7b6d91956d24d93bb7b85e9 100644
--- a/source/i18n/nfrs.cpp
+++ b/source/i18n/nfrs.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: nfrs.cpp
@@ -26,6 +26,22 @@
#include "cmemory.h"
#endif
+enum {
+ /** -x */
+ NEGATIVE_RULE_INDEX = 0,
+ /** x.x */
+ IMPROPER_FRACTION_RULE_INDEX = 1,
+ /** 0.x */
+ PROPER_FRACTION_RULE_INDEX = 2,
+ /** x.0 */
+ MASTER_RULE_INDEX = 3,
+ /** Inf */
+ INFINITY_RULE_INDEX = 4,
+ /** NaN */
+ NAN_RULE_INDEX = 5,
+ NON_NUMERICAL_RULE_LENGTH = 6
+};
+
U_NAMESPACE_BEGIN
#if 0
@@ -104,10 +120,6 @@ static const UChar gColon = 0x003a;
static const UChar gSemicolon = 0x003b;
static const UChar gLineFeed = 0x000a;
-static const UChar gFourSpaces[] =
-{
- 0x20, 0x20, 0x20, 0x20, 0
-}; /* " " */
static const UChar gPercentPercent[] =
{
0x25, 0x25, 0
@@ -118,17 +130,17 @@ static const UChar gNoparse[] =
0x40, 0x6E, 0x6F, 0x70, 0x61, 0x72, 0x73, 0x65, 0
}; /* "@noparse" */
-NFRuleSet::NFRuleSet(UnicodeString* descriptions, int32_t index, UErrorCode& status)
+NFRuleSet::NFRuleSet(RuleBasedNumberFormat *_owner, UnicodeString* descriptions, int32_t index, UErrorCode& status)
: name()
, rules(0)
- , negativeNumberRule(NULL)
+ , owner(_owner)
+ , fractionRules()
, fIsFractionRuleSet(FALSE)
, fIsPublic(FALSE)
, fIsParseable(TRUE)
- , fRecursionCount(0)
{
- for (int i = 0; i < 3; ++i) {
- fractionRules[i] = NULL;
+ for (int32_t i = 0; i < NON_NUMERICAL_RULE_LENGTH; ++i) {
+ nonNumericalRules[i] = NULL;
}
if (U_FAILURE(status)) {
@@ -179,7 +191,7 @@ NFRuleSet::NFRuleSet(UnicodeString* descriptions, int32_t index, UErrorCode& sta
}
void
-NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* owner, UErrorCode& status)
+NFRuleSet::parseRules(UnicodeString& description, UErrorCode& status)
{
// start by creating a Vector whose elements are Strings containing
// the descriptions of the rules (one rule per element). The rules
@@ -217,85 +229,103 @@ NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* o
// (this isn't a for loop because we might be deleting items from
// the vector-- we want to make sure we only increment i when
// we _didn't_ delete aything from the vector)
- uint32_t i = 0;
- while (i < rules.size()) {
+ int32_t rulesSize = rules.size();
+ for (int32_t i = 0; i < rulesSize; i++) {
NFRule* rule = rules[i];
+ int64_t baseValue = rule->getBaseValue();
- switch (rule->getType()) {
+ if (baseValue == 0) {
// if the rule's base value is 0, fill in a default
// base value (this will be 1 plus the preceding
// rule's base value for regular rule sets, and the
// same as the preceding rule's base value in fraction
// rule sets)
- case NFRule::kNoBase:
rule->setBaseValue(defaultBaseValue, status);
- if (!isFractionRuleSet()) {
- ++defaultBaseValue;
- }
- ++i;
- break;
-
- // if it's the negative-number rule, copy it into its own
- // data member and delete it from the list
- case NFRule::kNegativeNumberRule:
- if (negativeNumberRule) {
- delete negativeNumberRule;
- }
- negativeNumberRule = rules.remove(i);
- break;
-
- // if it's the improper fraction rule, copy it into the
- // correct element of fractionRules
- case NFRule::kImproperFractionRule:
- if (fractionRules[0]) {
- delete fractionRules[0];
- }
- fractionRules[0] = rules.remove(i);
- break;
-
- // if it's the proper fraction rule, copy it into the
- // correct element of fractionRules
- case NFRule::kProperFractionRule:
- if (fractionRules[1]) {
- delete fractionRules[1];
- }
- fractionRules[1] = rules.remove(i);
- break;
-
- // if it's the master rule, copy it into the
- // correct element of fractionRules
- case NFRule::kMasterRule:
- if (fractionRules[2]) {
- delete fractionRules[2];
- }
- fractionRules[2] = rules.remove(i);
- break;
-
+ }
+ else {
// if it's a regular rule that already knows its base value,
// check to make sure the rules are in order, and update
// the default base value for the next rule
- default:
- if (rule->getBaseValue() < defaultBaseValue) {
+ if (baseValue < defaultBaseValue) {
// throw new IllegalArgumentException("Rules are not in order");
status = U_PARSE_ERROR;
return;
}
- defaultBaseValue = rule->getBaseValue();
- if (!isFractionRuleSet()) {
- ++defaultBaseValue;
- }
- ++i;
- break;
+ defaultBaseValue = baseValue;
+ }
+ if (!fIsFractionRuleSet) {
+ ++defaultBaseValue;
}
}
}
+/**
+ * Set one of the non-numerical rules.
+ * @param rule The rule to set.
+ */
+void NFRuleSet::setNonNumericalRule(NFRule *rule) {
+ int64_t baseValue = rule->getBaseValue();
+ if (baseValue == NFRule::kNegativeNumberRule) {
+ delete nonNumericalRules[NEGATIVE_RULE_INDEX];
+ nonNumericalRules[NEGATIVE_RULE_INDEX] = rule;
+ }
+ else if (baseValue == NFRule::kImproperFractionRule) {
+ setBestFractionRule(IMPROPER_FRACTION_RULE_INDEX, rule, TRUE);
+ }
+ else if (baseValue == NFRule::kProperFractionRule) {
+ setBestFractionRule(PROPER_FRACTION_RULE_INDEX, rule, TRUE);
+ }
+ else if (baseValue == NFRule::kMasterRule) {
+ setBestFractionRule(MASTER_RULE_INDEX, rule, TRUE);
+ }
+ else if (baseValue == NFRule::kInfinityRule) {
+ delete nonNumericalRules[INFINITY_RULE_INDEX];
+ nonNumericalRules[INFINITY_RULE_INDEX] = rule;
+ }
+ else if (baseValue == NFRule::kNaNRule) {
+ delete nonNumericalRules[NAN_RULE_INDEX];
+ nonNumericalRules[NAN_RULE_INDEX] = rule;
+ }
+}
+
+/**
+ * Determine the best fraction rule to use. Rules matching the decimal point from
+ * DecimalFormatSymbols become the main set of rules to use.
+ * @param originalIndex The index into nonNumericalRules
+ * @param newRule The new rule to consider
+ * @param rememberRule Should the new rule be added to fractionRules.
+ */
+void NFRuleSet::setBestFractionRule(int32_t originalIndex, NFRule *newRule, UBool rememberRule) {
+ if (rememberRule) {
+ fractionRules.add(newRule);
+ }
+ NFRule *bestResult = nonNumericalRules[originalIndex];
+ if (bestResult == NULL) {
+ nonNumericalRules[originalIndex] = newRule;
+ }
+ else {
+ // We have more than one. Which one is better?
+ const DecimalFormatSymbols *decimalFormatSymbols = owner->getDecimalFormatSymbols();
+ if (decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol).charAt(0)
+ == newRule->getDecimalPoint())
+ {
+ nonNumericalRules[originalIndex] = newRule;
+ }
+ // else leave it alone
+ }
+}
+
NFRuleSet::~NFRuleSet()
{
- delete negativeNumberRule;
- delete fractionRules[0];
- delete fractionRules[1];
- delete fractionRules[2];
+ for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
+ if (i != IMPROPER_FRACTION_RULE_INDEX
+ && i != PROPER_FRACTION_RULE_INDEX
+ && i != MASTER_RULE_INDEX)
+ {
+ delete nonNumericalRules[i];
+ }
+ // else it will be deleted via NFRuleList fractionRules
+ }
}
static UBool
@@ -316,12 +346,16 @@ NFRuleSet::operator==(const NFRuleSet& rhs) const
{
if (rules.size() == rhs.rules.size() &&
fIsFractionRuleSet == rhs.fIsFractionRuleSet &&
- name == rhs.name &&
- util_equalRules(negativeNumberRule, rhs.negativeNumberRule) &&
- util_equalRules(fractionRules[0], rhs.fractionRules[0]) &&
- util_equalRules(fractionRules[1], rhs.fractionRules[1]) &&
- util_equalRules(fractionRules[2], rhs.fractionRules[2])) {
+ name == rhs.name) {
+ // ...then compare the non-numerical rule lists...
+ for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
+ if (!util_equalRules(nonNumericalRules[i], rhs.nonNumericalRules[i])) {
+ return FALSE;
+ }
+ }
+
+ // ...then compare the rule lists...
for (uint32_t i = 0; i < rules.size(); ++i) {
if (*rules[i] != *rhs.rules[i]) {
return FALSE;
@@ -332,41 +366,62 @@ NFRuleSet::operator==(const NFRuleSet& rhs) const
return FALSE;
}
-#define RECURSION_LIMIT 50
+void
+NFRuleSet::setDecimalFormatSymbols(const DecimalFormatSymbols &newSymbols, UErrorCode& status) {
+ for (uint32_t i = 0; i < rules.size(); ++i) {
+ rules[i]->setDecimalFormatSymbols(newSymbols, status);
+ }
+ // Switch the fraction rules to mirror the DecimalFormatSymbols.
+ for (int32_t nonNumericalIdx = IMPROPER_FRACTION_RULE_INDEX; nonNumericalIdx <= MASTER_RULE_INDEX; nonNumericalIdx++) {
+ if (nonNumericalRules[nonNumericalIdx]) {
+ for (uint32_t fIdx = 0; fIdx < fractionRules.size(); fIdx++) {
+ NFRule *fractionRule = fractionRules[fIdx];
+ if (nonNumericalRules[nonNumericalIdx]->getBaseValue() == fractionRule->getBaseValue()) {
+ setBestFractionRule(nonNumericalIdx, fractionRule, FALSE);
+ }
+ }
+ }
+ }
+
+ for (uint32_t nnrIdx = 0; nnrIdx < NON_NUMERICAL_RULE_LENGTH; nnrIdx++) {
+ NFRule *rule = nonNumericalRules[nnrIdx];
+ if (rule) {
+ rule->setDecimalFormatSymbols(newSymbols, status);
+ }
+ }
+}
+
+#define RECURSION_LIMIT 64
void
-NFRuleSet::format(int64_t number, UnicodeString& toAppendTo, int32_t pos, UErrorCode& status) const
+NFRuleSet::format(int64_t number, UnicodeString& toAppendTo, int32_t pos, int32_t recursionCount, UErrorCode& status) const
{
- NFRule *rule = findNormalRule(number);
+ if (recursionCount >= RECURSION_LIMIT) {
+ // stop recursion
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+ const NFRule *rule = findNormalRule(number);
if (rule) { // else error, but can't report it
- NFRuleSet* ncThis = (NFRuleSet*)this;
- if (ncThis->fRecursionCount++ >= RECURSION_LIMIT) {
- // stop recursion
- ncThis->fRecursionCount = 0;
- } else {
- rule->doFormat(number, toAppendTo, pos, status);
- ncThis->fRecursionCount--;
- }
+ rule->doFormat(number, toAppendTo, pos, ++recursionCount, status);
}
}
void
-NFRuleSet::format(double number, UnicodeString& toAppendTo, int32_t pos, UErrorCode& status) const
+NFRuleSet::format(double number, UnicodeString& toAppendTo, int32_t pos, int32_t recursionCount, UErrorCode& status) const
{
- NFRule *rule = findDoubleRule(number);
+ if (recursionCount >= RECURSION_LIMIT) {
+ // stop recursion
+ status = U_INVALID_STATE_ERROR;
+ return;
+ }
+ const NFRule *rule = findDoubleRule(number);
if (rule) { // else error, but can't report it
- NFRuleSet* ncThis = (NFRuleSet*)this;
- if (ncThis->fRecursionCount++ >= RECURSION_LIMIT) {
- // stop recursion
- ncThis->fRecursionCount = 0;
- } else {
- rule->doFormat(number, toAppendTo, pos, status);
- ncThis->fRecursionCount--;
- }
+ rule->doFormat(number, toAppendTo, pos, ++recursionCount, status);
}
}
-NFRule*
+const NFRule*
NFRuleSet::findDoubleRule(double number) const
{
// if this is a fraction rule set, use findFractionRuleSetRule()
@@ -374,33 +429,49 @@ NFRuleSet::findDoubleRule(double number) const
return findFractionRuleSetRule(number);
}
+ if (uprv_isNaN(number)) {
+ const NFRule *rule = nonNumericalRules[NAN_RULE_INDEX];
+ if (!rule) {
+ rule = owner->getDefaultNaNRule();
+ }
+ return rule;
+ }
+
// if the number is negative, return the negative number rule
// (if there isn't a negative-number rule, we pretend it's a
// positive number)
if (number < 0) {
- if (negativeNumberRule) {
- return negativeNumberRule;
+ if (nonNumericalRules[NEGATIVE_RULE_INDEX]) {
+ return nonNumericalRules[NEGATIVE_RULE_INDEX];
} else {
number = -number;
}
}
+ if (uprv_isInfinite(number)) {
+ const NFRule *rule = nonNumericalRules[INFINITY_RULE_INDEX];
+ if (!rule) {
+ rule = owner->getDefaultInfinityRule();
+ }
+ return rule;
+ }
+
// if the number isn't an integer, we use one of the fraction rules...
if (number != uprv_floor(number)) {
// if the number is between 0 and 1, return the proper
// fraction rule
- if (number < 1 && fractionRules[1]) {
- return fractionRules[1];
+ if (number < 1 && nonNumericalRules[PROPER_FRACTION_RULE_INDEX]) {
+ return nonNumericalRules[PROPER_FRACTION_RULE_INDEX];
}
// otherwise, return the improper fraction rule
- else if (fractionRules[0]) {
- return fractionRules[0];
+ else if (nonNumericalRules[IMPROPER_FRACTION_RULE_INDEX]) {
+ return nonNumericalRules[IMPROPER_FRACTION_RULE_INDEX];
}
}
// if there's a master rule, use it to format the number
- if (fractionRules[2]) {
- return fractionRules[2];
+ if (nonNumericalRules[MASTER_RULE_INDEX]) {
+ return nonNumericalRules[MASTER_RULE_INDEX];
}
// and if we haven't yet returned a rule, use findNormalRule()
@@ -409,7 +480,7 @@ NFRuleSet::findDoubleRule(double number) const
return findNormalRule(r);
}
-NFRule *
+const NFRule *
NFRuleSet::findNormalRule(int64_t number) const
{
// if this is a fraction rule set, use findFractionRuleSetRule()
@@ -422,8 +493,8 @@ NFRuleSet::findNormalRule(int64_t number) const
// if the number is negative, return the negative-number rule
// (if there isn't one, pretend the number is positive)
if (number < 0) {
- if (negativeNumberRule) {
- return negativeNumberRule;
+ if (nonNumericalRules[NEGATIVE_RULE_INDEX]) {
+ return nonNumericalRules[NEGATIVE_RULE_INDEX];
} else {
number = -number;
}
@@ -480,7 +551,7 @@ NFRuleSet::findNormalRule(int64_t number) const
return result;
}
// else use the master rule
- return fractionRules[2];
+ return nonNumericalRules[MASTER_RULE_INDEX];
}
/**
@@ -498,7 +569,7 @@ NFRuleSet::findNormalRule(int64_t number) const
* a number between 0 and 1)
* @return The rule to use to format this number
*/
-NFRule*
+const NFRule*
NFRuleSet::findFractionRuleSetRule(double number) const
{
// the obvious way to do this (multiply the value being formatted
@@ -631,40 +702,16 @@ NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBoun
fprintf(stderr, "'\n");
fprintf(stderr, " parse negative: %d\n", this, negativeNumberRule != 0);
#endif
-
- // start by trying the negative number rule (if there is one)
- if (negativeNumberRule) {
- Formattable tempResult;
-#ifdef RBNF_DEBUG
- fprintf(stderr, " <nfrs before negative> %x ub: %g\n", negativeNumberRule, upperBound);
-#endif
- UBool success = negativeNumberRule->doParse(text, workingPos, 0, upperBound, tempResult);
-#ifdef RBNF_DEBUG
- fprintf(stderr, " <nfrs after negative> success: %d wpi: %d\n", success, workingPos.getIndex());
-#endif
- if (success && workingPos.getIndex() > highWaterMark.getIndex()) {
- result = tempResult;
- highWaterMark = workingPos;
- }
- workingPos = pos;
- }
-#ifdef RBNF_DEBUG
- fprintf(stderr, "<nfrs> continue fractional with text '");
- dumpUS(stderr, text);
- fprintf(stderr, "' hwm: %d\n", highWaterMark.getIndex());
-#endif
- // then try each of the fraction rules
- {
- for (int i = 0; i < 3; i++) {
- if (fractionRules[i]) {
- Formattable tempResult;
- UBool success = fractionRules[i]->doParse(text, workingPos, 0, upperBound, tempResult);
- if (success && (workingPos.getIndex() > highWaterMark.getIndex())) {
- result = tempResult;
- highWaterMark = workingPos;
- }
- workingPos = pos;
+ // Try each of the negative rules, fraction rules, infinity rules and NaN rules
+ for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
+ if (nonNumericalRules[i]) {
+ Formattable tempResult;
+ UBool success = nonNumericalRules[i]->doParse(text, workingPos, 0, upperBound, tempResult);
+ if (success && (workingPos.getIndex() > highWaterMark.getIndex())) {
+ result = tempResult;
+ highWaterMark = workingPos;
}
+ workingPos = pos;
}
}
#ifdef RBNF_DEBUG
@@ -720,30 +767,37 @@ NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBoun
void
NFRuleSet::appendRules(UnicodeString& result) const
{
+ uint32_t i;
+
// the rule set name goes first...
result.append(name);
result.append(gColon);
result.append(gLineFeed);
// followed by the regular rules...
- for (uint32_t i = 0; i < rules.size(); i++) {
- result.append(gFourSpaces, 4);
+ for (i = 0; i < rules.size(); i++) {
rules[i]->_appendRuleText(result);
result.append(gLineFeed);
}
// followed by the special rules (if they exist)
- if (negativeNumberRule) {
- result.append(gFourSpaces, 4);
- negativeNumberRule->_appendRuleText(result);
- result.append(gLineFeed);
- }
-
- {
- for (uint32_t i = 0; i < 3; ++i) {
- if (fractionRules[i]) {
- result.append(gFourSpaces, 4);
- fractionRules[i]->_appendRuleText(result);
+ for (i = 0; i < NON_NUMERICAL_RULE_LENGTH; ++i) {
+ NFRule *rule = nonNumericalRules[i];
+ if (nonNumericalRules[i]) {
+ if (rule->getBaseValue() == NFRule::kImproperFractionRule
+ || rule->getBaseValue() == NFRule::kProperFractionRule
+ || rule->getBaseValue() == NFRule::kMasterRule)
+ {
+ for (uint32_t fIdx = 0; fIdx < fractionRules.size(); fIdx++) {
+ NFRule *fractionRule = fractionRules[fIdx];
+ if (fractionRule->getBaseValue() == rule->getBaseValue()) {
+ fractionRule->_appendRuleText(result);
+ result.append(gLineFeed);
+ }
+ }
+ }
+ else {
+ rule->_appendRuleText(result);
result.append(gLineFeed);
}
}
« no previous file with comments | « source/i18n/nfrs.h ('k') | source/i18n/nfrule.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698