]> granicus.if.org Git - icu/commitdiff
ICU-9174 Fix CompactDecimalFormat to correctly handle suffixes that don't start at...
authorTravis Keep <keep94@gmail.com>
Wed, 29 Aug 2012 20:28:21 +0000 (20:28 +0000)
committerTravis Keep <keep94@gmail.com>
Wed, 29 Aug 2012 20:28:21 +0000 (20:28 +0000)
X-SVN-Rev: 32294

icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java

index 8a1e7f54a70f419ac18ea48ec543830ad4c48d47..70db3b8eec30eacb149b89c255e92ff2b136c856 100644 (file)
@@ -72,7 +72,7 @@ class CompactDecimalDataCache {
         for (int i = 0; i < size; i++) {
             populateData((ICUResourceBundle) r.get(i), result);
         }
-        fillInMissingAndFixRedundant(result);
+        fillInMissing(result);
         return result;
     }
 
@@ -87,7 +87,10 @@ class CompactDecimalDataCache {
             return;
         }
         ICUResourceBundle other = (ICUResourceBundle) divisorData.get("other");
-        populatePrefixSuffix(other.getString(), thisIndex, result);
+        int numZeros = populatePrefixSuffix(other.getString(), thisIndex, result);
+        for (int i = 1; i < numZeros; i++) {
+            divisor /= 10;
+        }
         result.divisors[thisIndex] = divisor;
     }
 
@@ -97,53 +100,35 @@ class CompactDecimalDataCache {
      * @param template the number template, e.g 000K
      * @param idx the index to store the extracted prefix and suffix
      * @param result Data object modified in-place here.
+     * @return number of zeros found before any decimal point in template.
      */
-    private static void populatePrefixSuffix(String template, int idx, Data result) {
+    private static int populatePrefixSuffix(String template, int idx, Data result) {
         int firstIdx = template.indexOf("0");
         int lastIdx = template.lastIndexOf("0");
         result.prefixes[idx] = template.substring(0, firstIdx);
         result.suffixes[idx] = template.substring(lastIdx + 1);
+        
+        // Calculate number of zeros before decimal point.
+        int i = firstIdx + 1;
+        while (i <= lastIdx && template.charAt(i) == '0') {
+            i++;
+        }
+        return i - firstIdx;
     }
 
     /**
      * After reading information from resource bundle into a Data object, there
-     * is no guarantee that every index of the arrays will be filled. Moreover,
-     * the resource bundle may contain redundant information. After reading
-     * the resource for english, we may end up with:
-     * <pre>
-     * index divisor prefix suffix
-     * 0     <none>  <none> <none>
-     * 1     <none>  <none> <none>
-     * 2     <none>  <none> <none>
-     * 3     1000           K
-     * 4     10000          K
-     * 5     100000         K
-     * 6     1000000        M
-     * ...
-     * </pre>
-     * The 10000 and 100000 are redundant. In fact, this data will cause CompactDecimalFormatter
-     * to format 12345 as 1.2K instead of 12K.  Moreover, no data was populated for
-     * indexes 0, 1, or 2. What we want is something like this:
-     * <pre>
-     * index divisor prefix suffix
-     * 0     1
-     * 1     1
-     * 2     1
-     * 3     1000           K
-     * 4     1000           K
-     * 5     1000           K
-     * 6     1000000        M
-     * ...
-     * </pre>
-     * This function walks through the arrays filling in missing data and replacing
-     * redundant data.  If prefix is missing for an index, we fill in that index
-     * with the values from the previous index. If prefix and suffix for an index
-     * are the same as the previous index, we consider that redundant data and we
-     * replace the divisor with the one from the previous index.
+     * is no guarantee that every index of the arrays will be filled. 
+     * 
+     * This function walks through the arrays filling in indexes with missing
+     * data from the previous index. If the first indexes are missing data,
+     * they are assumed to have no prefixes or suffixes and a divisor of 1.
+     * We assume an index has missing data if the corresponding element in the
+     * prefixes array is null.
      *
      * @param result this instance is fixed in-place.
      */
-    private static void fillInMissingAndFixRedundant(Data result) {
+    private static void fillInMissing(Data result) {
         // Initially we assume that previous divisor is 1 with no prefix or suffix.
         long lastDivisor = 1L;
         String lastPrefix = "";
@@ -153,8 +138,6 @@ class CompactDecimalDataCache {
                 result.divisors[i] = lastDivisor;
                 result.prefixes[i] = lastPrefix;
                 result.suffixes[i] = lastSuffix;
-            } else if (result.prefixes[i].equals(lastPrefix) && result.suffixes[i].equals(lastSuffix)) {
-                result.divisors[i] = lastDivisor;
             } else {
                 lastDivisor = result.divisors[i];
                 lastPrefix = result.prefixes[i];
index 07d9dadcc74f7781823387900d0fa931702060f2..4bc0d23ee03ad72ad386a3c7c9c41393a0a135b3 100644 (file)
@@ -37,6 +37,21 @@ public class CompactDecimalFormatTest extends TestFmwk {
             {123456789012345f, "120T"},
             {12345678901234567890f, "12000000T"},
     };
+    
+    Object[][] SerbianTestData = {
+            {1234, "1200"},
+            {12345, "12 хиљ"},
+            {123456, "120 хиљ"},
+            {1234567, "1,2 мил"},
+            {12345678, "12 мил"},
+            {123456789, "120 мил"},
+            {1234567890, "1,2 млрд"},
+            {12345678901f, "12 млрд"},
+            {123456789012f, "120 млрд"},
+            {1234567890123f, "1,2 бил"},
+            {12345678901234f, "12 бил"},
+            {123456789012345f, "120 бил"},
+    };
 
     Object[][] JapaneseTestData = {
             {1234, "1200"},
@@ -71,6 +86,10 @@ public class CompactDecimalFormatTest extends TestFmwk {
     public void TestEnglish() {
         checkLocale(ULocale.ENGLISH, EnglishTestData);
     }
+    
+    public void TestSerbian() {
+        checkLocale(ULocale.forLanguageTag("sr"), SerbianTestData);
+    }
 
     public void TestJapanese() {
 //         checkLocale(ULocale.JAPANESE, JapaneseTestData); Not decided yet by CLDR TC.