]> granicus.if.org Git - icu/commitdiff
ICU-8940 Ensure the new DecimalFormatSymbols is propagated properly in ICU4C RBNF
authorMichael Ow <mow@svn.icu-project.org>
Fri, 17 Feb 2012 23:09:57 +0000 (23:09 +0000)
committerMichael Ow <mow@svn.icu-project.org>
Fri, 17 Feb 2012 23:09:57 +0000 (23:09 +0000)
X-SVN-Rev: 31417

icu4c/source/i18n/nfrlist.h
icu4c/source/i18n/nfrs.cpp
icu4c/source/i18n/rbnf.cpp
icu4c/source/i18n/unicode/rbnf.h
icu4c/source/test/intltest/itrbnf.cpp
icu4c/source/test/intltest/itrbnf.h

index 282051fb0d142a0a7b1e9d7f9401455da2b770ae..b5ab13ae9ab3ce4f1c64aa52178b69133f3beead 100644 (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
index 70f18a37c9ea0a20ad3600a957f6a0cc1f8fd041..6cc0c6381889a8fcca0a3924eed0efcabfdbc632 100644 (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;
 
index 816009de9d04c06d054118534c49d2c8c1bec4cb..bfd4f4a1bd5895c1dc976c0467ebe2d4930728b2 100644 (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.
index c595fd61ad03739e677b27f7669bfb1417ccf433..b235582b971f9e033fb548ce3c650b923b853cd5 100644 (file)
@@ -1011,6 +1011,8 @@ private:
 
 private:
     NFRuleSet **ruleSets;
+    UnicodeString* ruleSetDescriptions;
+    int32_t numRuleSets;
     NFRuleSet *defaultRuleSet;
     Locale locale;
     Collator* collator;
index 8bcfeabf63895dbc88debb186d1a7ba4eb285639..09c8aeaab521bd7437682e5c5b8de633494646e9 100644 (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) 
 {
index 939077b47524ba7d77f8a9e54b5ecc2a27b00f13..c1965249e2aa4cbd74b387bc2d1ba244c1df119c 100644 (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]);