| Index: source/i18n/rbnf.cpp
|
| diff --git a/source/i18n/rbnf.cpp b/source/i18n/rbnf.cpp
|
| index bdfd71a4dc387fca1d7b3a6412b88d6d6ced1b79..de260118fa8f81649daabbe40ea25d9de29509d7 100644
|
| --- a/source/i18n/rbnf.cpp
|
| +++ b/source/i18n/rbnf.cpp
|
| @@ -1,6 +1,6 @@
|
| /*
|
| *******************************************************************************
|
| -* Copyright (C) 1997-2014, International Business Machines Corporation
|
| +* Copyright (C) 1997-2015, International Business Machines Corporation
|
| * and others. All Rights Reserved.
|
| *******************************************************************************
|
| */
|
| @@ -36,7 +36,7 @@
|
| // #define RBNF_DEBUG
|
|
|
| #ifdef RBNF_DEBUG
|
| -#include "stdio.h"
|
| +#include <stdio.h>
|
| #endif
|
|
|
| #define U_ICUDATA_RBNF U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "rbnf"
|
| @@ -661,6 +661,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
| , locale(alocale)
|
| , collator(NULL)
|
| , decimalFormatSymbols(NULL)
|
| + , defaultInfinityRule(NULL)
|
| + , defaultNaNRule(NULL)
|
| , lenient(FALSE)
|
| , lenientParseRules(NULL)
|
| , localizations(NULL)
|
| @@ -683,6 +685,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
| , locale(Locale::getDefault())
|
| , collator(NULL)
|
| , decimalFormatSymbols(NULL)
|
| + , defaultInfinityRule(NULL)
|
| + , defaultNaNRule(NULL)
|
| , lenient(FALSE)
|
| , lenientParseRules(NULL)
|
| , localizations(NULL)
|
| @@ -705,6 +709,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
| , locale(alocale)
|
| , collator(NULL)
|
| , decimalFormatSymbols(NULL)
|
| + , defaultInfinityRule(NULL)
|
| + , defaultNaNRule(NULL)
|
| , lenient(FALSE)
|
| , lenientParseRules(NULL)
|
| , localizations(NULL)
|
| @@ -726,6 +732,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
| , locale(Locale::getDefault())
|
| , collator(NULL)
|
| , decimalFormatSymbols(NULL)
|
| + , defaultInfinityRule(NULL)
|
| + , defaultNaNRule(NULL)
|
| , lenient(FALSE)
|
| , lenientParseRules(NULL)
|
| , localizations(NULL)
|
| @@ -748,6 +756,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
|
| , locale(aLocale)
|
| , collator(NULL)
|
| , decimalFormatSymbols(NULL)
|
| + , defaultInfinityRule(NULL)
|
| + , defaultNaNRule(NULL)
|
| , lenient(FALSE)
|
| , lenientParseRules(NULL)
|
| , localizations(NULL)
|
| @@ -767,6 +777,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale&
|
| , locale(alocale)
|
| , collator(NULL)
|
| , decimalFormatSymbols(NULL)
|
| + , defaultInfinityRule(NULL)
|
| + , defaultNaNRule(NULL)
|
| , lenient(FALSE)
|
| , lenientParseRules(NULL)
|
| , localizations(NULL)
|
| @@ -814,7 +826,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale&
|
| }
|
| UParseError perror;
|
|
|
| - init (desc, locinfo, perror, status);
|
| + init(desc, locinfo, perror, status);
|
|
|
| ures_close(ruleSets);
|
| ures_close(rbnfRules);
|
| @@ -831,6 +843,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs)
|
| , locale(rhs.locale)
|
| , collator(NULL)
|
| , decimalFormatSymbols(NULL)
|
| + , defaultInfinityRule(NULL)
|
| + , defaultNaNRule(NULL)
|
| , lenient(FALSE)
|
| , lenientParseRules(NULL)
|
| , localizations(NULL)
|
| @@ -857,8 +871,8 @@ RuleBasedNumberFormat::operator=(const RuleBasedNumberFormat& rhs)
|
| lenient = rhs.lenient;
|
|
|
| UParseError perror;
|
| - init(rhs.originalDescription, rhs.localizations ? rhs.localizations->ref() : NULL, perror, status);
|
| setDecimalFormatSymbols(*rhs.getDecimalFormatSymbols());
|
| + init(rhs.originalDescription, rhs.localizations ? rhs.localizations->ref() : NULL, perror, status);
|
| setDefaultRuleSet(rhs.getDefaultRuleSetName(), status);
|
|
|
| capitalizationInfoSet = rhs.capitalizationInfoSet;
|
| @@ -936,9 +950,10 @@ UnicodeString
|
| RuleBasedNumberFormat::getRuleSetName(int32_t index) const
|
| {
|
| if (localizations) {
|
| - UnicodeString string(TRUE, localizations->getRuleSetName(index), (int32_t)-1);
|
| - return string;
|
| - } else if (ruleSets) {
|
| + UnicodeString string(TRUE, localizations->getRuleSetName(index), (int32_t)-1);
|
| + return string;
|
| + }
|
| + else if (ruleSets) {
|
| UnicodeString result;
|
| for (NFRuleSet** p = ruleSets; *p; ++p) {
|
| NFRuleSet* rs = *p;
|
| @@ -959,8 +974,9 @@ RuleBasedNumberFormat::getNumberOfRuleSetNames() const
|
| {
|
| int32_t result = 0;
|
| if (localizations) {
|
| - result = localizations->getNumberOfRuleSets();
|
| - } else if (ruleSets) {
|
| + result = localizations->getNumberOfRuleSets();
|
| + }
|
| + else if (ruleSets) {
|
| for (NFRuleSet** p = ruleSets; *p; ++p) {
|
| if ((**p).isPublic()) {
|
| ++result;
|
| @@ -1068,7 +1084,7 @@ RuleBasedNumberFormat::format(int32_t number,
|
| if (defaultRuleSet) {
|
| UErrorCode status = U_ZERO_ERROR;
|
| int32_t startPos = toAppendTo.length();
|
| - defaultRuleSet->format((int64_t)number, toAppendTo, toAppendTo.length(), status);
|
| + defaultRuleSet->format((int64_t)number, toAppendTo, toAppendTo.length(), 0, status);
|
| adjustForCapitalizationContext(startPos, toAppendTo);
|
| }
|
| return toAppendTo;
|
| @@ -1083,7 +1099,7 @@ RuleBasedNumberFormat::format(int64_t number,
|
| if (defaultRuleSet) {
|
| UErrorCode status = U_ZERO_ERROR;
|
| int32_t startPos = toAppendTo.length();
|
| - defaultRuleSet->format(number, toAppendTo, toAppendTo.length(), status);
|
| + defaultRuleSet->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
| adjustForCapitalizationContext(startPos, toAppendTo);
|
| }
|
| return toAppendTo;
|
| @@ -1096,15 +1112,9 @@ RuleBasedNumberFormat::format(double number,
|
| FieldPosition& /* pos */) const
|
| {
|
| int32_t startPos = toAppendTo.length();
|
| - // Special case for NaN; adapted from what DecimalFormat::_format( double number,...) does.
|
| - if (uprv_isNaN(number)) {
|
| - DecimalFormatSymbols* decFmtSyms = getDecimalFormatSymbols(); // RuleBasedNumberFormat internal
|
| - if (decFmtSyms) {
|
| - toAppendTo += decFmtSyms->getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
|
| - }
|
| - } else if (defaultRuleSet) {
|
| + if (defaultRuleSet) {
|
| UErrorCode status = U_ZERO_ERROR;
|
| - defaultRuleSet->format(number, toAppendTo, toAppendTo.length(), status);
|
| + defaultRuleSet->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
| }
|
| return adjustForCapitalizationContext(startPos, toAppendTo);
|
| }
|
| @@ -1126,7 +1136,7 @@ RuleBasedNumberFormat::format(int32_t number,
|
| NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
| if (rs) {
|
| int32_t startPos = toAppendTo.length();
|
| - rs->format((int64_t)number, toAppendTo, toAppendTo.length(), status);
|
| + rs->format((int64_t)number, toAppendTo, toAppendTo.length(), 0, status);
|
| adjustForCapitalizationContext(startPos, toAppendTo);
|
| }
|
| }
|
| @@ -1150,7 +1160,7 @@ RuleBasedNumberFormat::format(int64_t number,
|
| NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
| if (rs) {
|
| int32_t startPos = toAppendTo.length();
|
| - rs->format(number, toAppendTo, toAppendTo.length(), status);
|
| + rs->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
| adjustForCapitalizationContext(startPos, toAppendTo);
|
| }
|
| }
|
| @@ -1174,7 +1184,7 @@ RuleBasedNumberFormat::format(double number,
|
| NFRuleSet *rs = findRuleSet(ruleSetName, status);
|
| if (rs) {
|
| int32_t startPos = toAppendTo.length();
|
| - rs->format(number, toAppendTo, toAppendTo.length(), status);
|
| + rs->format(number, toAppendTo, toAppendTo.length(), 0, status);
|
| adjustForCapitalizationContext(startPos, toAppendTo);
|
| }
|
| }
|
| @@ -1294,13 +1304,13 @@ RuleBasedNumberFormat::setDefaultRuleSet(const UnicodeString& ruleSetName, UErro
|
|
|
| UnicodeString
|
| RuleBasedNumberFormat::getDefaultRuleSetName() const {
|
| - UnicodeString result;
|
| - if (defaultRuleSet && defaultRuleSet->isPublic()) {
|
| - defaultRuleSet->getName(result);
|
| - } else {
|
| - result.setToBogus();
|
| - }
|
| - return result;
|
| + UnicodeString result;
|
| + if (defaultRuleSet && defaultRuleSet->isPublic()) {
|
| + defaultRuleSet->getName(result);
|
| + } else {
|
| + result.setToBogus();
|
| + }
|
| + return result;
|
| }
|
|
|
| void
|
| @@ -1308,12 +1318,12 @@ RuleBasedNumberFormat::initDefaultRuleSet()
|
| {
|
| defaultRuleSet = NULL;
|
| if (!ruleSets) {
|
| - return;
|
| + return;
|
| }
|
|
|
| - const UnicodeString spellout = UNICODE_STRING_SIMPLE("%spellout-numbering");
|
| - const UnicodeString ordinal = UNICODE_STRING_SIMPLE("%digits-ordinal");
|
| - const UnicodeString duration = UNICODE_STRING_SIMPLE("%duration");
|
| + const UnicodeString spellout(UNICODE_STRING_SIMPLE("%spellout-numbering"));
|
| + const UnicodeString ordinal(UNICODE_STRING_SIMPLE("%digits-ordinal"));
|
| + const UnicodeString duration(UNICODE_STRING_SIMPLE("%duration"));
|
|
|
| NFRuleSet**p = &ruleSets[0];
|
| while (*p) {
|
| @@ -1348,6 +1358,13 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
| return;
|
| }
|
|
|
| + initializeDecimalFormatSymbols(status);
|
| + initializeDefaultInfinityRule(status);
|
| + initializeDefaultNaNRule(status);
|
| + if (U_FAILURE(status)) {
|
| + return;
|
| + }
|
| +
|
| this->localizations = localizationInfos == NULL ? NULL : localizationInfos->ref();
|
|
|
| UnicodeString description(rules);
|
| @@ -1445,7 +1462,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
| int32_t start = 0;
|
| for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, start)) {
|
| ruleSetDescriptions[curRuleSet].setTo(description, start, p + 1 - start);
|
| - ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
|
| + ruleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status);
|
| if (ruleSets[curRuleSet] == 0) {
|
| status = U_MEMORY_ALLOCATION_ERROR;
|
| return;
|
| @@ -1454,7 +1471,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
| start = p + 1;
|
| }
|
| ruleSetDescriptions[curRuleSet].setTo(description, start, description.length() - start);
|
| - ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
|
| + ruleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status);
|
| if (ruleSets[curRuleSet] == 0) {
|
| status = U_MEMORY_ALLOCATION_ERROR;
|
| return;
|
| @@ -1477,7 +1494,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
|
| // away the temporary descriptions as we go)
|
| {
|
| for (int i = 0; i < numRuleSets; i++) {
|
| - ruleSets[i]->parseRules(ruleSetDescriptions[i], this, status);
|
| + ruleSets[i]->parseRules(ruleSetDescriptions[i], status);
|
| }
|
| }
|
|
|
| @@ -1609,6 +1626,7 @@ RuleBasedNumberFormat::dispose()
|
|
|
| if (ruleSetDescriptions) {
|
| delete [] ruleSetDescriptions;
|
| + ruleSetDescriptions = NULL;
|
| }
|
|
|
| #if !UCONFIG_NO_COLLATION
|
| @@ -1619,15 +1637,23 @@ RuleBasedNumberFormat::dispose()
|
| delete decimalFormatSymbols;
|
| decimalFormatSymbols = NULL;
|
|
|
| + delete defaultInfinityRule;
|
| + defaultInfinityRule = NULL;
|
| +
|
| + delete defaultNaNRule;
|
| + defaultNaNRule = NULL;
|
| +
|
| delete lenientParseRules;
|
| lenientParseRules = NULL;
|
|
|
| #if !UCONFIG_NO_BREAK_ITERATION
|
| - delete capitalizationBrkIter;
|
| - capitalizationBrkIter = NULL;
|
| + delete capitalizationBrkIter;
|
| + capitalizationBrkIter = NULL;
|
| #endif
|
|
|
| - if (localizations) localizations = localizations->unref();
|
| + if (localizations) {
|
| + localizations = localizations->unref();
|
| + }
|
| }
|
|
|
|
|
| @@ -1691,31 +1717,86 @@ RuleBasedNumberFormat::getCollator() const
|
| }
|
|
|
|
|
| -/**
|
| - * Returns the DecimalFormatSymbols object that should be used by all DecimalFormat
|
| - * instances owned by this formatter. This object is lazily created: this function
|
| - * creates it the first time it's called.
|
| - * @return The DecimalFormatSymbols object that should be used by all DecimalFormat
|
| - * instances owned by this formatter.
|
| -*/
|
| DecimalFormatSymbols*
|
| -RuleBasedNumberFormat::getDecimalFormatSymbols() const
|
| +RuleBasedNumberFormat::initializeDecimalFormatSymbols(UErrorCode &status)
|
| {
|
| // lazy-evaluate the DecimalFormatSymbols object. This object
|
| // is shared by all DecimalFormat instances belonging to this
|
| // formatter
|
| if (decimalFormatSymbols == NULL) {
|
| - UErrorCode status = U_ZERO_ERROR;
|
| DecimalFormatSymbols* temp = new DecimalFormatSymbols(locale, status);
|
| if (U_SUCCESS(status)) {
|
| - ((RuleBasedNumberFormat*)this)->decimalFormatSymbols = temp;
|
| - } else {
|
| + decimalFormatSymbols = temp;
|
| + }
|
| + else {
|
| delete temp;
|
| }
|
| }
|
| return decimalFormatSymbols;
|
| }
|
|
|
| +/**
|
| + * Returns the DecimalFormatSymbols object that should be used by all DecimalFormat
|
| + * instances owned by this formatter.
|
| +*/
|
| +const DecimalFormatSymbols*
|
| +RuleBasedNumberFormat::getDecimalFormatSymbols() const
|
| +{
|
| + return decimalFormatSymbols;
|
| +}
|
| +
|
| +NFRule*
|
| +RuleBasedNumberFormat::initializeDefaultInfinityRule(UErrorCode &status)
|
| +{
|
| + if (U_FAILURE(status)) {
|
| + return NULL;
|
| + }
|
| + if (defaultInfinityRule == NULL) {
|
| + UnicodeString rule(UNICODE_STRING_SIMPLE("Inf: "));
|
| + rule.append(getDecimalFormatSymbols()->getSymbol(DecimalFormatSymbols::kInfinitySymbol));
|
| + NFRule* temp = new NFRule(this, rule, status);
|
| + if (U_SUCCESS(status)) {
|
| + defaultInfinityRule = temp;
|
| + }
|
| + else {
|
| + delete temp;
|
| + }
|
| + }
|
| + return defaultInfinityRule;
|
| +}
|
| +
|
| +const NFRule*
|
| +RuleBasedNumberFormat::getDefaultInfinityRule() const
|
| +{
|
| + return defaultInfinityRule;
|
| +}
|
| +
|
| +NFRule*
|
| +RuleBasedNumberFormat::initializeDefaultNaNRule(UErrorCode &status)
|
| +{
|
| + if (U_FAILURE(status)) {
|
| + return NULL;
|
| + }
|
| + if (defaultNaNRule == NULL) {
|
| + UnicodeString rule(UNICODE_STRING_SIMPLE("NaN: "));
|
| + rule.append(getDecimalFormatSymbols()->getSymbol(DecimalFormatSymbols::kNaNSymbol));
|
| + NFRule* temp = new NFRule(this, rule, status);
|
| + if (U_SUCCESS(status)) {
|
| + defaultNaNRule = temp;
|
| + }
|
| + else {
|
| + delete temp;
|
| + }
|
| + }
|
| + return defaultNaNRule;
|
| +}
|
| +
|
| +const NFRule*
|
| +RuleBasedNumberFormat::getDefaultNaNRule() const
|
| +{
|
| + return defaultNaNRule;
|
| +}
|
| +
|
| // De-owning the current localized symbols and adopt the new symbols.
|
| void
|
| RuleBasedNumberFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
|
| @@ -1734,8 +1815,18 @@ RuleBasedNumberFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsTo
|
| // Apply the new decimalFormatSymbols by reparsing the rulesets
|
| UErrorCode status = U_ZERO_ERROR;
|
|
|
| - for (int32_t i = 0; i < numRuleSets; i++) {
|
| - ruleSets[i]->parseRules(ruleSetDescriptions[i], this, status);
|
| + delete defaultInfinityRule;
|
| + defaultInfinityRule = NULL;
|
| + initializeDefaultInfinityRule(status); // Reset with the new DecimalFormatSymbols
|
| +
|
| + delete defaultNaNRule;
|
| + defaultNaNRule = NULL;
|
| + initializeDefaultNaNRule(status); // Reset with the new DecimalFormatSymbols
|
| +
|
| + if (ruleSets) {
|
| + for (int32_t i = 0; i < numRuleSets; i++) {
|
| + ruleSets[i]->setDecimalFormatSymbols(*symbolsToAdopt, status);
|
| + }
|
| }
|
| }
|
| }
|
|
|