diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
index 7d0c1344f13..c34ba24fe17 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
@@ -2760,6 +2760,35 @@ public class DecimalFormat extends NumberFormat {
}
+ /**
+ * Check for bidi marks: LRM, RLM, ALM
+ */
+ private static boolean isBidiMark(int c) {
+ return (c==0x200E || c==0x200F || c==0x061C);
+ }
+
+ /**
+ * Remove bidi marks from affix
+ */
+ private static final int TRIM_BUFLEN = 32;
+ private static String trimMarksFromAffix(String affix) {
+ char[] trimBuf = new char[TRIM_BUFLEN];
+ int affixLen = affix.length();
+ int affixPos, trimLen = 0;
+ for (affixPos = 0; affixPos < affixLen; affixPos++) {
+ char c = affix.charAt(affixPos);
+ if (!isBidiMark(c)) {
+ if (trimLen < TRIM_BUFLEN) {
+ trimBuf[trimLen++] = c;
+ } else {
+ trimLen = 0;
+ break;
+ }
+ }
+ }
+ return (trimLen > 0)? new String(trimBuf, 0, trimLen): affix;
+ }
+
/**
* Return the length matched by the given affix, or -1 if none. Runs of white space in
* the affix, match runs of white space in the input. Pattern white space and input
@@ -2772,8 +2801,12 @@ public class DecimalFormat extends NumberFormat {
*/
private static int compareSimpleAffix(String affix, String input, int pos) {
int start = pos;
- for (int i = 0; i < affix.length();) {
- int c = UTF16.charAt(affix, i);
+ // Affixes here might consist of sign, currency symbol and related spacing, etc.
+ // For more efficiency we should keep lazily-created trimmed affixes around in
+ // instance variables instead of trimming each time they are used (the next step).
+ String trimmedAffix = trimMarksFromAffix(affix);
+ for (int i = 0; i < trimmedAffix.length();) {
+ int c = UTF16.charAt(trimmedAffix, i);
int len = UTF16.getCharCount(c);
if (PatternProps.isWhiteSpace(c)) {
// We may have a pattern like: \u200F and input text like: \u200F Note
@@ -2781,22 +2814,29 @@ public class DecimalFormat extends NumberFormat {
// UWhiteSpace. So we have to first do a direct match of the run of RULE
// whitespace in the pattern, then match any extra characters.
boolean literalMatch = false;
- while (pos < input.length() && UTF16.charAt(input, pos) == c) {
- literalMatch = true;
- i += len;
- pos += len;
- if (i == affix.length()) {
- break;
- }
- c = UTF16.charAt(affix, i);
- len = UTF16.getCharCount(c);
- if (!PatternProps.isWhiteSpace(c)) {
+ while (pos < input.length()) {
+ int ic = UTF16.charAt(input, pos);
+ if (ic == c) {
+ literalMatch = true;
+ i += len;
+ pos += len;
+ if (i == trimmedAffix.length()) {
+ break;
+ }
+ c = UTF16.charAt(trimmedAffix, i);
+ len = UTF16.getCharCount(c);
+ if (!PatternProps.isWhiteSpace(c)) {
+ break;
+ }
+ } else if (isBidiMark(ic)) {
+ pos++; // just skip over this input text
+ } else {
break;
}
}
- // Advance over run in affix
- i = skipPatternWhiteSpace(affix, i);
+ // Advance over run in trimmedAffix
+ i = skipPatternWhiteSpace(trimmedAffix, i);
// Advance over run in input text. Must see at least one white space char
// in input, unless we've already matched some characters literally.
@@ -2807,13 +2847,23 @@ public class DecimalFormat extends NumberFormat {
}
// If we skip UWhiteSpace in the input text, we need to skip it in the
// pattern. Otherwise, the previous lines may have skipped over text
- // (such as U+00A0) that is also in the affix.
- i = skipUWhiteSpace(affix, i);
+ // (such as U+00A0) that is also in the trimmedAffix.
+ i = skipUWhiteSpace(trimmedAffix, i);
} else {
- if (pos < input.length() && equalWithSignCompatibility(UTF16.charAt(input, pos), c)) {
- i += len;
- pos += len;
- } else {
+ boolean match = false;
+ while (pos < input.length()) {
+ int ic = UTF16.charAt(input, pos);
+ if (!match && equalWithSignCompatibility(ic, c)) {
+ i += len;
+ pos += len;
+ match = true;
+ } else if (isBidiMark(ic)) {
+ pos++; // just skip over this input text
+ } else {
+ break;
+ }
+ }
+ if (!match) {
return -1;
}
}
@@ -2855,7 +2905,21 @@ public class DecimalFormat extends NumberFormat {
return pos;
}
- /**
+ /**
+ * Skips over a run of zero or more bidi marks at pos in text.
+ */
+ private static int skipBidiMarks(String text, int pos) {
+ while (pos < text.length()) {
+ int c = UTF16.charAt(text, pos);
+ if (!isBidiMark(c)) {
+ break;
+ }
+ pos += UTF16.getCharCount(c);
+ }
+ return pos;
+ }
+
+ /**
* Returns the length matched by the given affix, or -1 if none.
*
* @param affixPat pattern string
@@ -2972,9 +3036,10 @@ public class DecimalFormat extends NumberFormat {
* white space in text.
*/
static final int match(String text, int pos, int ch) {
- if (pos >= text.length()) {
+ if (pos < 0 || pos >= text.length()) {
return -1;
}
+ pos = skipBidiMarks(text, pos);
if (PatternProps.isWhiteSpace(ch)) {
// Advance over run of white space in input text
// Must see at least one white space char in input
@@ -2985,7 +3050,11 @@ public class DecimalFormat extends NumberFormat {
}
return pos;
}
- return (pos >= 0 && UTF16.charAt(text, pos) == ch) ? (pos + UTF16.getCharCount(ch)) : -1;
+ if (pos >= text.length() || UTF16.charAt(text, pos) != ch) {
+ return -1;
+ }
+ pos = skipBidiMarks(text, pos + UTF16.getCharCount(ch));
+ return pos;
}
/**
@@ -4031,8 +4100,9 @@ public class DecimalFormat extends NumberFormat {
c = symbols.getPerMill();
break;
case PATTERN_MINUS:
- c = symbols.getMinusSign();
- break;
+ String minusString = symbols.getMinusString();
+ buffer.append(minusString);
+ continue;
}
buffer.append(c);
}
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java
index 6105898e85f..cc01e13b3ec 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java
@@ -1,6 +1,6 @@
/*
*******************************************************************************
- * Copyright (C) 1996-2012, International Business Machines Corporation and *
+ * Copyright (C) 1996-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@@ -403,6 +403,16 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
return minusSign;
}
+ /**
+ * Returns the string used to represent minus sign.
+ * @return the minus sign string
+ * @internal
+ * @deprecated This API is ICU internal only.
+ */
+ public String getMinusString() {
+ return minusString;
+ }
+
/**
* Sets the character used to represent minus sign. If no explicit
* negative format is specified, one is formed by prefixing
@@ -412,6 +422,9 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
*/
public void setMinusSign(char minusSign) {
this.minusSign = minusSign;
+ // Also updates minusString
+ char[] minusArray = { minusSign };
+ minusString = new String(minusArray);
}
/**
@@ -567,6 +580,16 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
return plusSign;
}
+ /**
+ * Returns the string used to represent plus sign.
+ * @return the plus sign string
+ * @internal
+ * @deprecated This API is ICU internal only.
+ */
+ public String getPlusString() {
+ return plusString;
+ }
+
/**
* {@icu} Sets the localized plus sign.
* @param plus the plus sign, used in localized patterns and formatted
@@ -578,6 +601,9 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
*/
public void setPlusSign(char plus) {
plusSign = plus;
+ // Also updates plusString
+ char[] plusArray = { plusSign };
+ plusString = new String(plusArray);
}
/**
@@ -763,6 +789,7 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
perMill == other.perMill &&
digit == other.digit &&
minusSign == other.minusSign &&
+ minusString.equals(other.minusString) &&
patternSeparator == other.patternSeparator &&
infinity.equals(other.infinity) &&
NaN.equals(other.NaN) &&
@@ -770,6 +797,7 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
intlCurrencySymbol.equals(other.intlCurrencySymbol) &&
padEscape == other.padEscape &&
plusSign == other.plusSign &&
+ plusString.equals(other.plusString) &&
exponentSeparator.equals(other.exponentSeparator) &&
monetarySeparator == other.monetarySeparator &&
monetaryGroupingSeparator == other.monetaryGroupingSeparator);
@@ -786,6 +814,13 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
return result;
}
+ /**
+ * Check for bidi marks: LRM, RLM, ALM
+ */
+ private static boolean isBidiMark(char c) {
+ return (c=='\u200E' || c=='\u200F' || c=='\u061C');
+ }
+
/**
* Initializes the symbols from the LocaleElements resource bundle.
* Note: The organization of LocaleElements badly needs to be
@@ -874,8 +909,10 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
groupingSeparator = numberElements[1].charAt(0);
patternSeparator = numberElements[2].charAt(0);
percent = numberElements[3].charAt(0);
- minusSign = numberElements[4].charAt(0);
- plusSign =numberElements[5].charAt(0);
+ minusString = numberElements[4];
+ minusSign = (minusString.length() > 1 && isBidiMark(minusString.charAt(0)))? minusString.charAt(1): minusString.charAt(0);
+ plusString = numberElements[5];
+ plusSign = (plusString.length() > 1 && isBidiMark(plusString.charAt(0)))? plusString.charAt(1): plusString.charAt(0);
exponentSeparator = numberElements[6];
perMill = numberElements[7].charAt(0);
infinity = numberElements[8];
@@ -1000,6 +1037,17 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
}
initSpacingInfo(CurrencyData.CurrencySpacingInfo.DEFAULT);
}
+ if (serialVersionOnStream < 7) {
+ // Set minusString,plusString from minusSign,plusSign
+ if (minusString == null) {
+ char[] minusArray = { minusSign };
+ minusString = new String(minusArray);
+ }
+ if (plusString == null) {
+ char[] plusArray = { plusSign };
+ plusString = new String(plusArray);
+ }
+ }
serialVersionOnStream = currentSerialVersion;
// recreate
@@ -1172,10 +1220,18 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
/**
* The requested ULocale. We keep the old locale for serialization compatibility.
- * @since IDU 3.2
+ * @since ICU 3.2
*/
private ULocale ulocale;
+ /**
+ * String versions of some number symbols.
+ * @serial
+ * @since ICU 52
+ */
+ private String minusString = null;
+ private String plusString = null;
+
// Proclaim JDK 1.1 FCS compatibility
private static final long serialVersionUID = 5772796243397350300L;
@@ -1189,7 +1245,8 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
// - 4 for ICU 3.2, which includes the ULocale field
// - 5 for ICU 3.6, which includes the monetaryGroupingSeparator field
// - 6 for ICU 4.2, which includes the currencySpc* fields
- private static final int currentSerialVersion = 6;
+ // - 7 for ICU 52, which includes the minusString and plusString fields
+ private static final int currentSerialVersion = 7;
/**
* Describes the version of DecimalFormatSymbols
present on the stream.
@@ -1205,7 +1262,8 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
*
DecimalFormatSymbols
, the most recent format
* (corresponding to the highest allowable serialVersionOnStream
)
diff --git a/icu4j/main/shared/data/icudata.jar b/icu4j/main/shared/data/icudata.jar
index 8c6f95b248d..90cb8dd88db 100755
--- a/icu4j/main/shared/data/icudata.jar
+++ b/icu4j/main/shared/data/icudata.jar
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0281eb436d3f76c50252cc66bbe357ba00aeb6db06839224cfefa18d386f3338
-size 10966706
+oid sha256:22577e214f576563ba1289192cb1d3d8684bb5273192958d1c0782cb4797b69b
+size 10966724
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 e454507688e..1a2d7f12bba 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
@@ -270,7 +270,7 @@ public class CompactDecimalFormatTest extends TestFmwk {
NumberFormat cdf =
CompactDecimalFormat.getInstance(
ULocale.forLanguageTag("ar"), CompactStyle.LONG);
- assertEquals("Arabic Long", "\u0665\u066B\u0663- \u0623\u0644\u0641", cdf.format(-5300));
+ assertEquals("Arabic Long", "\u200F-\u0665\u066B\u0663 \u0623\u0644\u0641", cdf.format(-5300));
}
public void TestCsShort() {
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 e366df65fed..010e182153f 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
@@ -510,7 +510,7 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
// test locale without currency information
{"root", "-1.23", "USD", "-US$ 1.23", "-USD 1.23", "-1.23 USD"},
{"root@numbers=latn", "-1.23", "USD", "-US$ 1.23", "-USD 1.23", "-1.23 USD"}, // ensure that the root locale is still used with modifiers
- {"root@numbers=arab", "-1.23", "USD", "-US$ ١٫٢٣", "-USD ١٫٢٣", "-١٫٢٣ USD"}, // ensure that the root locale is still used with modifiers
+ {"root@numbers=arab", "-1.23", "USD", "\u200F-US$ ١٫٢٣", "\u200F-USD ١٫٢٣", "\u200F-١٫٢٣ USD"}, // ensure that the root locale is still used with modifiers
// test choice format
{"es_AR", "1", "INR", "₹1,00", "INR1,00", "1,00 rupia india"},
{"ar_EG", "1", "USD", "US$ ١٫٠٠", "USD ١٫٠٠", "١٫٠٠ دولار أمريكي"},
@@ -1400,7 +1400,7 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
new TestNumberingSystemItem( "en_US@numbers=hebr", 5678.0, true, "\u05D4\u05F3\u05EA\u05E8\u05E2\u05F4\u05D7" ),
new TestNumberingSystemItem( "en_US@numbers=arabext", 1234.567, false, "\u06F1\u066c\u06F2\u06F3\u06F4\u066b\u06F5\u06F6\u06F7" ),
new TestNumberingSystemItem( "de_DE@numbers=foobar", 1234.567, false, "1.234,567" ),
- new TestNumberingSystemItem( "ar_EG", 1234.567, false, "\u0661\u0662\u0663\u0664\u066b\u0665\u0666\u0667" ),
+ new TestNumberingSystemItem( "ar_EG", 1234.567, false, "\u0661\u066C\u0662\u0663\u0664\u066b\u0665\u0666\u0667" ),
new TestNumberingSystemItem( "th_TH@numbers=traditional", 1234.567, false, "\u0E51,\u0E52\u0E53\u0E54.\u0E55\u0E56\u0E57" ), // fall back to native per TR35
new TestNumberingSystemItem( "ar_MA", 1234.567, false, "1.234,567" ),
new TestNumberingSystemItem( "en_US@numbers=hanidec", 1234.567, false, "\u4e00,\u4e8c\u4e09\u56db.\u4e94\u516d\u4e03" ),
@@ -3313,7 +3313,7 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
}
}
- public void TestCustomCurrecySignAndSeparator() {
+ public void TestCustomCurrencySignAndSeparator() {
DecimalFormatSymbols custom = new DecimalFormatSymbols(ULocale.US);
custom.setCurrencySymbol("*");
@@ -3325,4 +3325,121 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
final String numstr = "* 1^234:56";
expect2(fmt, 1234.56, numstr);
}
+
+ public void TestParseSignsAndMarks() {
+ class SignsAndMarksItem {
+ public String locale;
+ public boolean lenient;
+ public String numString;
+ public double value;
+ // Simple constructor
+ public SignsAndMarksItem(String loc, boolean lnt, String numStr, double val) {
+ locale = loc;
+ lenient = lnt;
+ numString = numStr;
+ value = val;
+ }
+ };
+ final SignsAndMarksItem[] items = {
+ // *** Note, ICU4J lenient number parsing does not handle arbitrary whitespace, but can
+ // treat some whitespace as a grouping separator. The cases marked *** below depend
+ // on isGroupingUsed() being set for the locale, which in turn depends on grouping
+ // separators being present in the decimalFormat pattern for the locale (& num sys).
+ //
+ // locale lenient numString value
+ new SignsAndMarksItem("en", false, "12", 12 ),
+ new SignsAndMarksItem("en", true, "12", 12 ),
+ new SignsAndMarksItem("en", false, "-23", -23 ),
+ new SignsAndMarksItem("en", true, "-23", -23 ),
+ new SignsAndMarksItem("en", true, "- 23", -23 ), // ***
+ new SignsAndMarksItem("en", false, "\u200E-23", -23 ),
+ new SignsAndMarksItem("en", true, "\u200E-23", -23 ),
+ new SignsAndMarksItem("en", true, "\u200E- 23", -23 ), // ***
+
+ new SignsAndMarksItem("en@numbers=arab", false, "\u0663\u0664", 34 ),
+ new SignsAndMarksItem("en@numbers=arab", true, "\u0663\u0664", 34 ),
+ new SignsAndMarksItem("en@numbers=arab", false, "-\u0664\u0665", -45 ),
+ new SignsAndMarksItem("en@numbers=arab", true, "-\u0664\u0665", -45 ),
+ new SignsAndMarksItem("en@numbers=arab", true, "- \u0664\u0665", -45 ), // ***
+ new SignsAndMarksItem("en@numbers=arab", false, "\u200F-\u0664\u0665", -45 ),
+ new SignsAndMarksItem("en@numbers=arab", true, "\u200F-\u0664\u0665", -45 ),
+ new SignsAndMarksItem("en@numbers=arab", true, "\u200F- \u0664\u0665", -45 ), // ***
+
+ new SignsAndMarksItem("en@numbers=arabext", false, "\u06F5\u06F6", 56 ),
+ new SignsAndMarksItem("en@numbers=arabext", true, "\u06F5\u06F6", 56 ),
+ new SignsAndMarksItem("en@numbers=arabext", false, "-\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("en@numbers=arabext", true, "-\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("en@numbers=arabext", true, "- \u06F6\u06F7", -67 ), // ***
+ new SignsAndMarksItem("en@numbers=arabext", false, "\u200E-\u200E\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("en@numbers=arabext", true, "\u200E-\u200E\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("en@numbers=arabext", true, "\u200E-\u200E \u06F6\u06F7", -67 ), // ***
+
+ new SignsAndMarksItem("he", false, "12", 12 ),
+ new SignsAndMarksItem("he", true, "12", 12 ),
+ new SignsAndMarksItem("he", false, "-23", -23 ),
+ new SignsAndMarksItem("he", true, "-23", -23 ),
+ new SignsAndMarksItem("he", true, "- 23", -23 ), // ***
+ new SignsAndMarksItem("he", false, "\u200E-23", -23 ),
+ new SignsAndMarksItem("he", true, "\u200E-23", -23 ),
+ new SignsAndMarksItem("he", true, "\u200E- 23", -23 ), // ***
+
+ new SignsAndMarksItem("ar", false, "\u0663\u0664", 34 ),
+ new SignsAndMarksItem("ar", true, "\u0663\u0664", 34 ),
+ new SignsAndMarksItem("ar", false, "-\u0664\u0665", -45 ),
+ new SignsAndMarksItem("ar", true, "-\u0664\u0665", -45 ),
+ new SignsAndMarksItem("ar", true, "- \u0664\u0665", -45 ), // ***
+ new SignsAndMarksItem("ar", false, "\u200F-\u0664\u0665", -45 ),
+ new SignsAndMarksItem("ar", true, "\u200F-\u0664\u0665", -45 ),
+ new SignsAndMarksItem("ar", true, "\u200F- \u0664\u0665", -45 ), // ***
+
+ new SignsAndMarksItem("ar_MA", false, "12", 12 ),
+ new SignsAndMarksItem("ar_MA", true, "12", 12 ),
+ new SignsAndMarksItem("ar_MA", false, "-23", -23 ),
+ new SignsAndMarksItem("ar_MA", true, "-23", -23 ),
+ new SignsAndMarksItem("ar_MA", true, "- 23", -23 ), // ***
+ new SignsAndMarksItem("ar_MA", false, "\u200E-23", -23 ),
+ new SignsAndMarksItem("ar_MA", true, "\u200E-23", -23 ),
+ new SignsAndMarksItem("ar_MA", true, "\u200E- 23", -23 ), // ***
+
+ new SignsAndMarksItem("fa", false, "\u06F5\u06F6", 56 ),
+ new SignsAndMarksItem("fa", true, "\u06F5\u06F6", 56 ),
+ new SignsAndMarksItem("fa", false, "\u2212\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("fa", true, "\u2212\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("fa", true, "\u2212 \u06F6\u06F7", -67 ), // ***
+ new SignsAndMarksItem("fa", false, "\u200E\u2212\u200E\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("fa", true, "\u200E\u2212\u200E\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("fa", true, "\u200E\u2212\u200E \u06F6\u06F7", -67 ), // ***
+
+ new SignsAndMarksItem("ps", false, "\u06F5\u06F6", 56 ),
+ new SignsAndMarksItem("ps", true, "\u06F5\u06F6", 56 ),
+ new SignsAndMarksItem("ps", false, "-\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("ps", true, "-\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("ps", true, "- \u06F6\u06F7", -67 ), // ***
+ new SignsAndMarksItem("ps", false, "\u200E-\u200E\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("ps", true, "\u200E-\u200E\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("ps", true, "\u200E-\u200E \u06F6\u06F7", -67 ), // ***
+ new SignsAndMarksItem("ps", false, "-\u200E\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("ps", true, "-\u200E\u06F6\u06F7", -67 ),
+ new SignsAndMarksItem("ps", true, "-\u200E \u06F6\u06F7", -67 ), // ***
+ };
+ for (SignsAndMarksItem item: items) {
+ ULocale locale = new ULocale(item.locale);
+ NumberFormat numfmt = NumberFormat.getInstance(locale);
+ if (numfmt != null) {
+ numfmt.setParseStrict(!item.lenient);
+ ParsePosition ppos = new ParsePosition(0);
+ Number num = numfmt.parse(item.numString, ppos);
+ if (num != null && ppos.getIndex() == item.numString.length()) {
+ double parsedValue = num.doubleValue();
+ if (parsedValue != item.value) {
+ errln("FAIL: locale " + item.locale + ", lenient " + item.lenient + ", parse of \"" + item.numString + "\" gives value " + parsedValue);
+ }
+ } else {
+ errln("FAIL: locale " + item.locale + ", lenient " + item.lenient + ", parse of \"" + item.numString + "\" gives position " + ppos.getIndex());
+ }
+ } else {
+ errln("FAIL: NumberFormat.getInstance for locale " + item.locale);
+ }
+ }
+ }
}