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); |
+ } |
} |
} |
} |