]> granicus.if.org Git - icu/commitdiff
ICU-9042 in time unit format, ignore those plural counts that are not defined in...
authorXiaomei Ji <xji@google.com>
Fri, 8 Jun 2012 19:02:03 +0000 (19:02 +0000)
committerXiaomei Ji <xji@google.com>
Fri, 8 Jun 2012 19:02:03 +0000 (19:02 +0000)
X-SVN-Rev: 31924

icu4c/source/i18n/tmutfmt.cpp
icu4c/source/i18n/unicode/tmutfmt.h
icu4c/source/test/intltest/tufmtts.cpp
icu4c/source/test/intltest/tufmtts.h

index dc355a0365e3dbd6c04396e808564b70a5e1733e..e2394ed3ab9919e0e99f450bb7feb869e72c2c59 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2008-2011, Google, International Business Machines Corporation
+ * Copyright (C) 2008-2012, Google, International Business Machines Corporation
  * and others. All Rights Reserved.
  *******************************************************************************
  */
@@ -386,9 +386,19 @@ TimeUnitFormat::create(const Locale& locale, UTimeUnitFormatStyle style, UErrorC
 void 
 TimeUnitFormat::setup(UErrorCode& err) {
     initDataMembers(err);
-    readFromCurrentLocale(UTMUTFMT_FULL_STYLE, gUnitsTag, err);
+
+    UVector pluralCounts(0, uhash_compareUnicodeString, 6, err);
+    StringEnumeration* keywords = fPluralRules->getKeywords(err);
+    if (U_FAILURE(err)) {
+        return;
+    }
+    UnicodeString* pluralCount;
+    while ((pluralCount = const_cast<UnicodeString*>(keywords->snext(err))) != NULL) {
+      pluralCounts.addElement(pluralCount, err);
+    }
+    readFromCurrentLocale(UTMUTFMT_FULL_STYLE, gUnitsTag, pluralCounts, err);
     checkConsistency(UTMUTFMT_FULL_STYLE, gUnitsTag, err);
-    readFromCurrentLocale(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, err);
+    readFromCurrentLocale(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, pluralCounts, err);
     checkConsistency(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, err);
 }
 
@@ -415,7 +425,8 @@ TimeUnitFormat::initDataMembers(UErrorCode& err){
 
 
 void
-TimeUnitFormat::readFromCurrentLocale(UTimeUnitFormatStyle style, const char* key, UErrorCode& err) {
+TimeUnitFormat::readFromCurrentLocale(UTimeUnitFormatStyle style, const char* key,
+                                      const UVector& pluralCounts, UErrorCode& err) {
     if (U_FAILURE(err)) {
         return;
     }
@@ -490,12 +501,15 @@ TimeUnitFormat::readFromCurrentLocale(UTimeUnitFormatStyle style, const char* ke
                 if (U_FAILURE(status)) {
                     continue;
                 }
+                UnicodeString pluralCountUniStr(pluralCount, -1, US_INV);
+                if (!pluralCounts.contains(&pluralCountUniStr)) {
+                  continue;
+                }
                 MessageFormat* messageFormat = new MessageFormat(pattern, fLocale, err);
                 if ( U_SUCCESS(err) ) {
                   if (fNumberFormat != NULL) {
                     messageFormat->setFormat(0, *fNumberFormat);
                   }
-                  UnicodeString pluralCountUniStr(pluralCount, -1, US_INV);
                   MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCountUniStr);
                   if (formatters == NULL) {
                     formatters = (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*));
@@ -763,6 +777,7 @@ TimeUnitFormat::setNumberFormat(const NumberFormat& format, UErrorCode& status){
         while ((elem = fTimeUnitToCountToPatterns[i]->nextElement(pos)) != NULL){
             const UHashTok keyTok = elem->value;
             MessageFormat** pattern = (MessageFormat**)keyTok.pointer;
+
             pattern[UTMUTFMT_FULL_STYLE]->setFormat(0, format);
             pattern[UTMUTFMT_ABBREVIATED_STYLE]->setFormat(0, format);
         }
index a2acc7a6bfa41a3b432bda5bd8712d4dd418a06b..dd9aa36f45f85dfa5861b6de76a60cc616ca02bb 100644 (file)
@@ -24,6 +24,7 @@
 #include "unicode/measfmt.h"
 #include "unicode/numfmt.h"
 #include "unicode/plurrule.h"
+#include "uvector.h"
 
 /**
  * Constants for various styles.
@@ -229,7 +230,8 @@ private:
     void initDataMembers(UErrorCode& status);
 
     // initialize fTimeUnitToCountToPatterns from current locale's resource.
-    void readFromCurrentLocale(UTimeUnitFormatStyle style, const char* key, UErrorCode& status);
+    void readFromCurrentLocale(UTimeUnitFormatStyle style, const char* key, const UVector& pluralCounts,
+                               UErrorCode& status);
 
     // check completeness of fTimeUnitToCountToPatterns against all time units,
     // and all plural rules, fill in fallback as necessary.
index 90efa96fcf291295c5edb4213c07ddc8712ff6ff..e4268d04e16e4ae2d3958d1c9635699f01803d7c 100644 (file)
@@ -1,5 +1,5 @@
 /********************************************************************
- * Copyright (c) 2008-2011, International Business Machines Corporation and
+ * Copyright (c) 2008-2012, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 
@@ -25,7 +25,8 @@ void TimeUnitTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
     switch (index) {
         TESTCASE(0, testBasic);
         TESTCASE(1, testAPI);
-        TESTCASE(2, testGreek);
+        TESTCASE(2, testGreekWithFallback);
+        TESTCASE(3, testGreekWithSanitization);
         default: name = ""; break;
     }
 }
@@ -208,7 +209,7 @@ void TimeUnitTest::testAPI() {
  * to long unit names for a locale where the locale data does not 
  * provide short unit names. As of CLDR 1.9, Greek is one such language.
  */
-void TimeUnitTest::testGreek() {
+void TimeUnitTest::testGreekWithFallback() {
     UErrorCode status = U_ZERO_ERROR;
 
     const char* locales[] = {"el-GR", "el"};
@@ -323,4 +324,23 @@ void TimeUnitTest::testGreek() {
     }
 }
 
+// Test bug9042
+void TimeUnitTest::testGreekWithSanitization() {
+    
+    UErrorCode status = U_ZERO_ERROR;
+    Locale elLoc("el");
+    NumberFormat* numberFmt = NumberFormat::createInstance(Locale("el"), status);
+    if (!assertSuccess("NumberFormat::createInstance for el locale", status)) return;
+    numberFmt->setMaximumFractionDigits(1);
+
+    TimeUnitFormat* timeUnitFormat = new TimeUnitFormat(elLoc, status);
+    if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status)) return;
+
+    timeUnitFormat->setNumberFormat(*numberFmt, status);
+
+    delete numberFmt;
+    delete timeUnitFormat;
+}
+
+
 #endif
index 3910f4a2db838edb4470e79394680ad52c107605..45e841cb8063b203aed94c5231da00ce173b3bdd 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 2008-2010, International Business Machines Corporation
+ * Copyright (c) 2008-2012, International Business Machines Corporation
  * and others. All Rights Reserved.
  ********************************************************************/
 
@@ -37,7 +37,18 @@ public:
      * to long unit names for a locale where the locale data does not 
      * provide short unit names. As of CLDR 1.9, Greek is one such language.
      **/
-    void testGreek();
+    void testGreekWithFallback();
+
+    /**
+     * Performs tests for Greek
+     * This tests that if the plural count listed in time unit format does not
+     * match those in the plural rules for the locale, those plural count in
+     * time unit format will be ingored and subsequently, fall back will kick in
+     * which is tested above.
+     * Without data sanitization, setNumberFormat() would crash.
+     * As of CLDR shiped in ICU4.8, Greek is one such language.
+     */
+    void testGreekWithSanitization();
 };
 
 #endif /* #if !UCONFIG_NO_FORMATTING */