ICU-8940 Ensure the new DecimalFormatSymbols is propagated properly in ICU4C RBNF

X-SVN-Rev: 31417
This commit is contained in:
Michael Ow 2012-02-17 23:09:57 +00:00
parent bae575e95a
commit 1dfe6c4c8b
6 changed files with 114 additions and 10 deletions

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 1997-2011, International Business Machines
* Copyright (C) 1997-2012, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* file name: nfrlist.h
@ -82,6 +82,19 @@ public:
fCapacity = 0;
return result;
}
void deleteAll() {
NFRule** tmp = NULL;
int32_t size = fCount;
if (size > 0) {
tmp = release();
for (int32_t i = 0; i < size; i++) {
delete tmp[i];
}
if (tmp) {
uprv_free(tmp);
}
}
}
private:
NFRuleList(const NFRuleList &other); // forbid copying of this class

View file

@ -190,6 +190,9 @@ NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* o
return;
}
// ensure we are starting with an empty rule list
rules.deleteAll();
// dlf - the original code kept a separate description array for no reason,
// so I got rid of it. The loop was too complex so I simplified it.
@ -235,24 +238,36 @@ NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* o
// 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;

View file

@ -649,6 +649,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
const UnicodeString& locs,
const Locale& alocale, UParseError& perror, UErrorCode& status)
: ruleSets(NULL)
, ruleSetDescriptions(NULL)
, numRuleSets(0)
, defaultRuleSet(NULL)
, locale(alocale)
, collator(NULL)
@ -665,6 +667,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
const UnicodeString& locs,
UParseError& perror, UErrorCode& status)
: ruleSets(NULL)
, ruleSetDescriptions(NULL)
, numRuleSets(0)
, defaultRuleSet(NULL)
, locale(Locale::getDefault())
, collator(NULL)
@ -681,6 +685,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
LocalizationInfo* info,
const Locale& alocale, UParseError& perror, UErrorCode& status)
: ruleSets(NULL)
, ruleSetDescriptions(NULL)
, numRuleSets(0)
, defaultRuleSet(NULL)
, locale(alocale)
, collator(NULL)
@ -696,6 +702,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
UParseError& perror,
UErrorCode& status)
: ruleSets(NULL)
, ruleSetDescriptions(NULL)
, numRuleSets(0)
, defaultRuleSet(NULL)
, locale(Locale::getDefault())
, collator(NULL)
@ -712,6 +720,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
UParseError& perror,
UErrorCode& status)
: ruleSets(NULL)
, ruleSetDescriptions(NULL)
, numRuleSets(0)
, defaultRuleSet(NULL)
, locale(aLocale)
, collator(NULL)
@ -725,6 +735,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status)
: ruleSets(NULL)
, ruleSetDescriptions(NULL)
, numRuleSets(0)
, defaultRuleSet(NULL)
, locale(alocale)
, collator(NULL)
@ -783,6 +795,8 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale&
RuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs)
: NumberFormat(rhs)
, ruleSets(NULL)
, ruleSetDescriptions(NULL)
, numRuleSets(0)
, defaultRuleSet(NULL)
, locale(rhs.locale)
, collator(NULL)
@ -1324,7 +1338,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
// pre-flight parsing the description and count the number of
// rule sets (";%" marks the end of one rule set and the beginning
// of the next)
int numRuleSets = 0;
numRuleSets = 0;
for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, p)) {
++numRuleSets;
++p;
@ -1354,7 +1368,8 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
UnicodeString* ruleSetDescriptions = new UnicodeString[numRuleSets];
ruleSetDescriptions = new UnicodeString[numRuleSets];
if (ruleSetDescriptions == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
@ -1368,7 +1383,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
if (ruleSets[curRuleSet] == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
goto cleanup;
return;
}
++curRuleSet;
start = p + 1;
@ -1377,7 +1392,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
if (ruleSets[curRuleSet] == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
goto cleanup;
return;
}
}
@ -1424,9 +1439,6 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali
} else {
defaultRuleSet = getDefaultRuleSet();
}
cleanup:
delete[] ruleSetDescriptions;
}
void
@ -1481,6 +1493,10 @@ RuleBasedNumberFormat::dispose()
ruleSets = NULL;
}
if (ruleSetDescriptions) {
delete [] ruleSetDescriptions;
}
#if !UCONFIG_NO_COLLATION
delete collator;
#endif
@ -1594,6 +1610,15 @@ RuleBasedNumberFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsTo
}
decimalFormatSymbols = symbolsToAdopt;
{
// 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);
}
}
}
// Setting the symbols is equlivalent to adopting a newly created localized symbols.

View file

@ -1011,6 +1011,8 @@ private:
private:
NFRuleSet **ruleSets;
UnicodeString* ruleSetDescriptions;
int32_t numRuleSets;
NFRuleSet *defaultRuleSet;
Locale locale;
Collator* collator;

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2011, International Business Machines Corporation and *
* Copyright (C) 1996-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -66,6 +66,7 @@ void IntlTestRBNF::runIndexedTest(int32_t index, UBool exec, const char* &name,
TESTCASE(16, TestHebrewFraction);
TESTCASE(17, TestPortugueseSpellout);
TESTCASE(18, TestMultiplierSubstitution);
TESTCASE(19, TestSetDecimalFormatSymbols);
#else
TESTCASE(0, TestRBNFDisabled);
#endif
@ -1905,6 +1906,49 @@ IntlTestRBNF::TestMultiplierSubstitution(void) {
}
}
void
IntlTestRBNF::TestSetDecimalFormatSymbols() {
UErrorCode status = U_ZERO_ERROR;
RuleBasedNumberFormat rbnf(URBNF_ORDINAL, Locale::getEnglish(), status);
if (U_FAILURE(status)) {
errln("Unable to create RuleBasedNumberFormat - " + UnicodeString(u_errorName(status)));
return;
}
DecimalFormatSymbols dfs(Locale::getEnglish(), status);
if (U_FAILURE(status)) {
errln("Unable to create DecimalFormatSymbols - " + UnicodeString(u_errorName(status)));
return;
}
UnicodeString expected[] = {
UnicodeString("1,001st"),
UnicodeString("1&001st")
};
double number = 1001;
UnicodeString result;
rbnf.format(number, result);
if (result != expected[0]) {
errln("Format Error - Got: " + result + " Expected: " + expected[0]);
}
result.remove();
/* Set new symbol for testing */
dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, UnicodeString("&"), TRUE);
rbnf.setDecimalFormatSymbols(dfs);
rbnf.format(number, result);
if (result != expected[1]) {
errln("Format Error - Got: " + result + " Expected: " + expected[1]);
}
}
void
IntlTestRBNF::doTest(RuleBasedNumberFormat* formatter, const char* const testData[][2], UBool testParsing)
{

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2007, International Business Machines Corporation and *
* Copyright (C) 1996-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -128,6 +128,11 @@ class IntlTestRBNF : public IntlTest {
*/
virtual void TestMultiplierSubstitution();
/**
* Test the setDecimalFormatSymbols in RBNF
*/
virtual void TestSetDecimalFormatSymbols();
protected:
virtual void doTest(RuleBasedNumberFormat* formatter, const char* const testData[][2], UBool testParsing);
virtual void doLenientParseTest(RuleBasedNumberFormat* formatter, const char* testData[][2]);