From 773683046accb0d91c32080debe19aa7b09d15eb Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Fri, 31 Mar 2017 21:45:46 +0000 Subject: [PATCH] ICU-13088 Fixing number parsing when a minus sign is is preceded by ignorables in a pattern string. X-SVN-Rev: 39977 --- .../core/src/com/ibm/icu/impl/number/Parse.java | 11 ++++++++--- .../ibm/icu/dev/test/format/IntlTestNumberFormat.java | 4 +--- .../com/ibm/icu/dev/test/format/NumberFormatTest.java | 8 ++++++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Parse.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Parse.java index a1f8941f12b..7ca7d9fe608 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Parse.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Parse.java @@ -2214,7 +2214,9 @@ public class Parse { : AffixPatternUtils.nextToken(nextOffsetOrTag, str); if (firstOffsetOrTag == 0L) firstOffsetOrTag = nextOffsetOrTag; if (isString ? nextOffsetOrTag >= str.length() : nextOffsetOrTag < 0) { - nextTypeOrCp = -1; + // Integer.MIN_VALUE is an invalid value for either a type or a cp; + // use it to indicate the end of the string. + nextTypeOrCp = Integer.MIN_VALUE; break; } nextTypeOrCp = @@ -2224,7 +2226,7 @@ public class Parse { if (!isIgnorable(nextTypeOrCp, state)) break; } - if (nextTypeOrCp == -1) { + if (nextTypeOrCp == Integer.MIN_VALUE) { // Run at end or string that contains only ignorable characters. if (codePointEquals(cp, typeOrCp, state)) { // Step forward and also exit the string if not at very end. @@ -2251,6 +2253,9 @@ public class Parse { } else if (offsetOrTag == 0) { // Run at beginning. Go to nonignorable cp. // FALL THROUGH + // TODO: This branch doesn't work on affix patterns since offsetOrTag != 0 for the first + // element. This is harmless except for possible performance implications of evaluating + // the third case instead of the second. } else { // Run in middle. if (isIgnorable(cp, state)) { @@ -2267,7 +2272,7 @@ public class Parse { } // Fall through to the nonignorable code point found above. - assert nextTypeOrCp != -1; + assert nextTypeOrCp != Integer.MIN_VALUE; typeOrCp = nextTypeOrCp; offsetOrTag = nextOffsetOrTag; } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/IntlTestNumberFormat.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/IntlTestNumberFormat.java index f51c9f8c8b8..b106de70c73 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/IntlTestNumberFormat.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/IntlTestNumberFormat.java @@ -46,9 +46,7 @@ public class IntlTestNumberFormat extends com.ibm.icu.dev.test.TestFmwk { logln("Percent test " + localeName); fNumberFormat = NumberFormat.getPercentInstance(locale); - if (!locale.getLanguage().equals("fa") && !logKnownIssue("13088", "Negative number with percent cannot be parsed in Persian locale")) { - _testFormat(); - } + _testFormat(); if (locale.toString().compareTo("en_US_POSIX") != 0 ) { logln("Scientific test " + localeName); diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java index 8d3e72a1944..ee13913e2ed 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java @@ -4984,6 +4984,14 @@ public class NumberFormatTest extends TestFmwk { assertEquals("Locale 'bg' should not use monetary grouping", "987654,32 лв.", result); } + @Test + public void Test13088() { + ULocale loc = new ULocale("fa"); + double num = -12.34; + NumberFormat numfmt = NumberFormat.getPercentInstance(loc); + expect2(numfmt, num, "‎٪ ‎−۱٬۲۳۴"); + } + @Test public void testPercentZero() { DecimalFormat df = (DecimalFormat) NumberFormat.getPercentInstance(); -- 2.40.0