From 4153e49710f12f56e6efff0001a3713ec27334d3 Mon Sep 17 00:00:00 2001 From: Travis Keep Date: Wed, 29 Aug 2012 20:28:21 +0000 Subject: [PATCH] ICU-9174 Fix CompactDecimalFormat to correctly handle suffixes that don't start at 1. e.g for Serbian 9998, 9999, 10K. X-SVN-Rev: 32294 --- .../ibm/icu/text/CompactDecimalDataCache.java | 61 +++++++------------ .../test/format/CompactDecimalFormatTest.java | 19 ++++++ 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java index 8a1e7f54a70..70db3b8eec3 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java @@ -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: - *
-     * index divisor prefix suffix
-     * 0        
-     * 1        
-     * 2        
-     * 3     1000           K
-     * 4     10000          K
-     * 5     100000         K
-     * 6     1000000        M
-     * ...
-     * 
- * 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: - *
-     * index divisor prefix suffix
-     * 0     1
-     * 1     1
-     * 2     1
-     * 3     1000           K
-     * 4     1000           K
-     * 5     1000           K
-     * 6     1000000        M
-     * ...
-     * 
- * 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]; diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java index 07d9dadcc74..4bc0d23ee03 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java @@ -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. -- 2.40.0