// Hard case: the magnitude is 10^18.
// The largest int64 is: 9,223,372,036,854,775,807
for (int p = 0; p < precision; p++) {
- byte digit = getDigitPos(18 - p);
+ byte digit = getDigit(18 - p);
if (digit < INT64_BCD[p]) {
return true;
} else if (digit > INT64_BCD[p]) {
return AffixUtils.containsType(posPrefix, type) || AffixUtils.containsType(posSuffix, type)
|| AffixUtils.containsType(negPrefix, type) || AffixUtils.containsType(negSuffix, type);
}
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + " {"
+ + posPrefix
+ + "#"
+ + posSuffix
+ + ";"
+ + negPrefix
+ + "#"
+ + negSuffix
+ + "}";
+ }
}
\ No newline at end of file
&& AffixUtils.containsOnlySymbolsAndIgnorables(posPrefixString, ignorables.getSet())
&& AffixUtils.containsOnlySymbolsAndIgnorables(posSuffixString, ignorables.getSet())
&& AffixUtils.containsOnlySymbolsAndIgnorables(negPrefixString, ignorables.getSet())
- && AffixUtils.containsOnlySymbolsAndIgnorables(negSuffixString, ignorables.getSet())) {
+ && AffixUtils.containsOnlySymbolsAndIgnorables(negSuffixString, ignorables.getSet())
+ // HACK: Plus and minus sign are a special case: we accept them trailing only if they are
+ // trailing in the pattern string.
+ && !AffixUtils.containsType(posSuffixString, AffixUtils.TYPE_PLUS_SIGN)
+ && !AffixUtils.containsType(posSuffixString, AffixUtils.TYPE_MINUS_SIGN)
+ && !AffixUtils.containsType(negSuffixString, AffixUtils.TYPE_PLUS_SIGN)
+ && !AffixUtils.containsType(negSuffixString, AffixUtils.TYPE_MINUS_SIGN)) {
// The affixes contain only symbols and ignorables.
// No need to generate affix matchers.
return;
// Case 1: the token is a symbol.
switch (typeOrCp) {
case AffixUtils.TYPE_MINUS_SIGN:
- addMatcher(factory.minusSign());
+ addMatcher(factory.minusSign(true));
break;
case AffixUtils.TYPE_PLUS_SIGN:
- addMatcher(factory.plusSign());
+ addMatcher(factory.plusSign(true));
break;
case AffixUtils.TYPE_PERCENT:
addMatcher(factory.percent());
ULocale locale;
int parseFlags;
- public MinusSignMatcher minusSign() {
- return MinusSignMatcher.getInstance(symbols);
+ public MinusSignMatcher minusSign(boolean allowTrailing) {
+ return MinusSignMatcher.getInstance(symbols, allowTrailing);
}
- public PlusSignMatcher plusSign() {
- return PlusSignMatcher.getInstance(symbols);
+ public PlusSignMatcher plusSign(boolean allowTrailing) {
+ return PlusSignMatcher.getInstance(symbols, allowTrailing);
}
public PercentMatcher percent() {
*/
public class MinusSignMatcher extends SymbolMatcher {
- private static final MinusSignMatcher DEFAULT = new MinusSignMatcher();
+ private static final MinusSignMatcher DEFAULT = new MinusSignMatcher(false);
+ private static final MinusSignMatcher DEFAULT_ALLOW_TRAILING = new MinusSignMatcher(true);
- public static MinusSignMatcher getInstance(DecimalFormatSymbols symbols) {
+ public static MinusSignMatcher getInstance(DecimalFormatSymbols symbols, boolean allowTrailing) {
String symbolString = symbols.getMinusSignString();
if (DEFAULT.uniSet.contains(symbolString)) {
- return DEFAULT;
+ return allowTrailing ? DEFAULT_ALLOW_TRAILING : DEFAULT;
} else {
- return new MinusSignMatcher(symbolString);
+ return new MinusSignMatcher(symbolString, allowTrailing);
}
}
- private MinusSignMatcher(String symbolString) {
+ private final boolean allowTrailing;
+
+ private MinusSignMatcher(String symbolString, boolean allowTrailing) {
super(symbolString, DEFAULT.uniSet);
+ this.allowTrailing = allowTrailing;
}
- private MinusSignMatcher() {
+ private MinusSignMatcher(boolean allowTrailing) {
super(UnicodeSetStaticCache.Key.MINUS_SIGN);
+ this.allowTrailing = allowTrailing;
}
@Override
protected boolean isDisabled(ParsedNumber result) {
- return 0 != (result.flags & ParsedNumber.FLAG_NEGATIVE);
+ return 0 != (result.flags & ParsedNumber.FLAG_NEGATIVE)
+ || (allowTrailing ? false : result.seenNumber());
}
@Override
parser.addMatcher(ignorables);
parser.addMatcher(DecimalMatcher.getInstance(symbols, grouper, parseFlags));
- parser.addMatcher(MinusSignMatcher.getInstance(symbols));
+ parser.addMatcher(MinusSignMatcher.getInstance(symbols, false));
parser.addMatcher(NanMatcher.getInstance(symbols, parseFlags));
parser.addMatcher(ScientificMatcher.getInstance(symbols, grouper, parseFlags));
parser.addMatcher(CurrencyTrieMatcher.getInstance(locale));
ParsedNumber result = new ParsedNumber();
parser.parse(input, true, result);
if (result.success()) {
- ppos.setIndex(result.charsConsumed);
+ ppos.setIndex(result.charEnd);
return result.getNumber();
} else {
- ppos.setErrorIndex(result.charsConsumed);
+ ppos.setErrorIndex(result.charEnd);
return null;
}
}
ParsedNumber result = new ParsedNumber();
parser.parse(input, true, result);
if (result.success()) {
- ppos.setIndex(result.charsConsumed);
+ ppos.setIndex(result.charEnd);
// TODO: Clean this up
Currency currency;
if (result.currencyCode != null) {
}
return new CurrencyAmount(result.getNumber(), currency);
} else {
- ppos.setErrorIndex(result.charsConsumed);
+ ppos.setErrorIndex(result.charEnd);
return null;
}
}
} else {
parseFlags |= ParsingUtils.PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES;
}
- if (grouper.getPrimary() == -1) {
+ if (grouper.getPrimary() <= 0) {
parseFlags |= ParsingUtils.PARSE_FLAG_GROUPING_DISABLED;
}
if (parseCurrency || patternInfo.hasCurrencySign()) {
if (!isStrict
|| patternInfo.containsSymbolType(AffixUtils.TYPE_PLUS_SIGN)
|| properties.getSignAlwaysShown()) {
- parser.addMatcher(PlusSignMatcher.getInstance(symbols));
+ parser.addMatcher(PlusSignMatcher.getInstance(symbols, false));
}
- parser.addMatcher(MinusSignMatcher.getInstance(symbols));
+ parser.addMatcher(MinusSignMatcher.getInstance(symbols, false));
parser.addMatcher(NanMatcher.getInstance(symbols, parseFlags));
parser.addMatcher(PercentMatcher.getInstance(symbols));
parser.addMatcher(PermilleMatcher.getInstance(symbols));
*/
public void parse(String input, int start, boolean greedy, ParsedNumber result) {
assert frozen;
+ assert start >= 0 && start < input.length();
StringSegment segment = new StringSegment(ParsingUtils.maybeFold(input, parseFlags));
segment.adjustOffset(start);
if (greedy) {
public DecimalQuantity_DualStorageBCD quantity;
/**
- * The number of chars accepted during parsing. This is NOT necessarily the same as the StringSegment
- * offset; "weak" chars, like whitespace, change the offset, but the charsConsumed is not touched
- * until a "strong" char is encountered.
+ * The index of the last char consumed during parsing. If parsing started at index 0, this is equal
+ * to the number of chars consumed. This is NOT necessarily the same as the StringSegment offset;
+ * "weak" chars, like whitespace, change the offset, but the charsConsumed is not touched until a
+ * "strong" char is encountered.
*/
- public int charsConsumed;
+ public int charEnd;
/**
* Boolean flags (see constants below).
public static final Comparator<ParsedNumber> COMPARATOR = new Comparator<ParsedNumber>() {
@Override
public int compare(ParsedNumber o1, ParsedNumber o2) {
- return o1.charsConsumed - o2.charsConsumed;
+ return o1.charEnd - o2.charEnd;
}
};
*/
public void clear() {
quantity = null;
- charsConsumed = 0;
+ charEnd = 0;
flags = 0;
prefix = null;
suffix = null;
public void copyFrom(ParsedNumber other) {
quantity = other.quantity == null ? null
: (DecimalQuantity_DualStorageBCD) other.quantity.createCopy();
- charsConsumed = other.charsConsumed;
+ charEnd = other.charEnd;
flags = other.flags;
prefix = other.prefix;
suffix = other.suffix;
currencyCode = other.currencyCode;
}
+ /**
+ * Call this method to register that a "strong" char was consumed. This should be done after calling
+ * {@link StringSegment#setOffset} or {@link StringSegment#adjustOffset} except when the char is
+ * "weak", like whitespace.
+ *
+ * <p>
+ * <strong>What is a strong versus weak char?</strong> The behavior of number parsing is to "stop"
+ * after reading the number, even if there is other content following the number. For example, after
+ * parsing the string "123 " (123 followed by a space), the cursor should be set to 3, not 4, even
+ * though there are matchers that accept whitespace. In this example, the digits are strong, whereas
+ * the whitespace is weak. Grouping separators are weak, whereas decimal separators are strong. Most
+ * other chars are strong.
+ *
+ * @param segment
+ * The current StringSegment, usually immediately following a call to setOffset.
+ */
public void setCharsConsumed(StringSegment segment) {
- charsConsumed = segment.getOffset();
+ charEnd = segment.getOffset();
}
/**
* consumed, and the failure flag must not be set.
*/
public boolean success() {
- return charsConsumed > 0 && 0 == (flags & FLAG_FAIL);
+ return charEnd > 0 && 0 == (flags & FLAG_FAIL);
}
public boolean seenNumber() {
*/
public class PlusSignMatcher extends SymbolMatcher {
- private static final PlusSignMatcher DEFAULT = new PlusSignMatcher();
+ private static final PlusSignMatcher DEFAULT = new PlusSignMatcher(false);
+ private static final PlusSignMatcher DEFAULT_ALLOW_TRAILING = new PlusSignMatcher(true);
- public static PlusSignMatcher getInstance(DecimalFormatSymbols symbols) {
+ public static PlusSignMatcher getInstance(DecimalFormatSymbols symbols, boolean allowTrailing) {
String symbolString = symbols.getPlusSignString();
if (DEFAULT.uniSet.contains(symbolString)) {
- return DEFAULT;
+ return allowTrailing ? DEFAULT_ALLOW_TRAILING : DEFAULT;
} else {
- return new PlusSignMatcher(symbolString);
+ return new PlusSignMatcher(symbolString, allowTrailing);
}
}
- private PlusSignMatcher(String symbolString) {
+ private final boolean allowTrailing;
+
+ private PlusSignMatcher(String symbolString, boolean allowTrailing) {
super(symbolString, DEFAULT.uniSet);
+ this.allowTrailing = allowTrailing;
}
- private PlusSignMatcher() {
+ private PlusSignMatcher(boolean allowTrailing) {
super(UnicodeSetStaticCache.Key.PLUS_SIGN);
+ this.allowTrailing = allowTrailing;
}
@Override
protected boolean isDisabled(ParsedNumber result) {
- return false;
+ return allowTrailing ? false : result.seenNumber();
}
@Override
this.start = start;
}
+ /**
+ * Equivalent to <code>setOffset(getOffset()+delta)</code>.
+ *
+ * <p>
+ * This method is usually called by a Matcher to register that a char was consumed. If the char is
+ * strong (it usually is, except for things like whitespace), follow this with a call to
+ * {@link ParsedNumber#setCharsConsumed}. For more information on strong chars, see that method.
+ */
public void adjustOffset(int delta) {
assert start + delta >= 0;
assert start + delta <= end;
byte grouping1 = (byte) properties.getGroupingSize();
byte grouping2 = (byte) properties.getSecondaryGroupingSize();
int minGrouping = properties.getMinimumGroupingDigits();
- grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : -1;
+ grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : grouping1;
grouping2 = grouping2 > 0 ? grouping2 : grouping1;
// TODO: Is it important to handle minGrouping > 2?
return getInstance(grouping1, grouping2, minGrouping == 2);
if (parsePosition == null) {
parsePosition = new ParsePosition(0);
}
+ if (parsePosition.getIndex() < 0) {
+ throw new IllegalArgumentException("Cannot start parsing at a negative offset");
+ }
+ if (parsePosition.getIndex() >= text.length()) {
+ // For backwards compatibility, this is not an exception, just an empty result.
+ return null;
+ }
ParsedNumber result = new ParsedNumber();
// Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the
int startIndex = parsePosition.getIndex();
parser.parse(text, startIndex, true, result);
if (result.success()) {
- parsePosition.setIndex(startIndex + result.charsConsumed);
+ parsePosition.setIndex(result.charEnd);
// TODO: Accessing properties here is technically not thread-safe
Number number = result.getNumber(properties.getParseToBigDecimal());
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
}
return number;
} else {
- parsePosition.setErrorIndex(startIndex + result.charsConsumed);
+ parsePosition.setErrorIndex(startIndex + result.charEnd);
return null;
}
}
if (parsePosition == null) {
parsePosition = new ParsePosition(0);
}
+ if (parsePosition.getIndex() < 0) {
+ throw new IllegalArgumentException("Cannot start parsing at a negative offset");
+ }
+ if (parsePosition.getIndex() >= text.length()) {
+ // For backwards compatibility, this is not an exception, just an empty result.
+ return null;
+ }
ParsedNumber result = new ParsedNumber();
int startIndex = parsePosition.getIndex();
parserWithCurrency.parse(text.toString(), startIndex, true, result);
if (result.success()) {
- parsePosition.setIndex(startIndex + result.charsConsumed);
+ parsePosition.setIndex(result.charEnd);
// TODO: Accessing properties here is technically not thread-safe
Number number = result.getNumber(properties.getParseToBigDecimal());
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
Currency currency = Currency.getInstance(result.currencyCode);
return new CurrencyAmount(number, currency);
} else {
- parsePosition.setErrorIndex(startIndex + result.charsConsumed);
+ parsePosition.setErrorIndex(startIndex + result.charEnd);
return null;
}
}
en_US 0 123.456 123.456
it_IT 1 123,456 123.456
it_IT 0 123,456 123.456
-// JDK returns 123 here; not sure why.
-it_IT 1 123.456 123456 K
+it_IT 1 123.456 123456
it_IT 0 123.456 123
test no grouping in pattern with parsing
+1,234,567.8901 1234567.8901
+1,23,4567.8901 1234567.8901
// P supports grouping separators in the fraction; none of the others do.
-+1,23,4567.89,01 1234567.8901 CJK
++1,23,4567.89,01 1234567.8901 CJKS
+1,23,456.78.9 123456.78
-+12.34,56 12.3456 CJK
++12.34,56 12.3456 CJKS
+79,,20,3 79203
+79 20 3 79203 K
// Parsing stops at comma as it is different from other separators
+1,234.5 1234.5
// Comma after decimal means a fractional grouping separator
// P fails since it finds an invalid grouping size
-+1,23,456.78,9 123456.789 P
++1,23,456.78,9 123456.789 JKPS
// C and J fail upon seeing the second decimal point
+1,23,456.78.9 123456.78 CJ
+79 79
123.456 123456
123,456 123.456
// The separator after the comma can be inrepreted as a fractional grouping
-987,654.321 987.654321 CJK
-987,654 321 987.654321 CJK
+987,654.321 987.654321 CJKS
+987,654 321 987.654321 CJKS
987.654,321 987654.321
test select
set pattern \u00a4 0.00;\u00a4 -#
set locale fa_IR
begin
-parse output outputCurrency
+parse output outputCurrency breaks
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
// P fails here because this currency name is in the Trie only, but it has the same prefix as the non-Trie currency
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
IRR 1235 1235 IRR
\u0631\u06cc\u0627\u0644 1235 1235 IRR
-\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
+\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
test parse foreign currency ISO
set pattern \u00a4\u00a4 0.00;\u00a4\u00a4 -#
set locale fa_IR
begin
-parse output outputCurrency
+parse output outputCurrency breaks
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
-\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR
+\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
IRR 1235 1235 IRR
\u0631\u06cc\u0627\u0644 1235 1235 IRR
-\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
+\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
test parse foreign currency full
set pattern \u00a4\u00a4\u00a4 0.00;\u00a4\u00a4\u00a4 -#
set locale fa_IR
begin
-parse output outputCurrency
+parse output outputCurrency breaks
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
-\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR
+\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
IRR 1235 1235 IRR
\u0631\u06cc\u0627\u0644 1235 1235 IRR
-\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
+\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
test parse currency with foreign symbols symbol english
set pattern \u00a4 0.00;\u00a4 (#)
set locale en
set pattern #
begin
-parse output breaks
--123 -123
-- 123 -123 JK
- -123 -123 JK
- - 123 -123 JK
-123- -123 CJKS
-123 - -123 CJKS
+pattern parse output breaks
+# -123 -123
+# - 123 -123 JK
+# -123 -123 JK
+# - 123 -123 JK
+# 123- 123
+# 123 - 123
+#;#- 123- -123
+#;#- 123 - -123 JK
test parse case sensitive
set locale en
import java.text.ParseException;
import java.text.ParsePosition;
-import org.junit.Ignore;
import org.junit.Test;
import com.ibm.icu.dev.test.TestUtil;
};
@Test
- @Ignore
public void TestDataDrivenICU58() {
// Android can't access DecimalFormat_ICU58 for testing (ticket #13283).
if (TestUtil.getJavaVendor() == TestUtil.JavaVendor.Android) return;
// something may or may not work. However the test data assumes a specific
// Java runtime version. We should probably disable this test case - #13372
@Test
- @Ignore
public void TestDataDrivenJDK() {
// Android implements java.text.DecimalFormat with ICU4J (ticket #13322).
// Oracle/OpenJDK 9's behavior is not exactly same with Oracle/OpenJDK 8.
}
@Test
- @Ignore
public void TestDataDrivenICULatest_Format() {
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
"numberformattestspecification.txt", ICU60);
}
@Test
- @Ignore
public void TestDataDrivenICULatest_Other() {
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
"numberformattestspecification.txt", ICU59_Other);
// expect(currencyFormat, 0.08, "CA$0.1"); // ICU 58 and down
expect(currencyFormat, 0.08, "CA$0.10"); // ICU 59 and up
}
+
+ @Test
+ public void testParsePositionIncrease() {
+ String input = "123\n456\n$789";
+ ParsePosition ppos = new ParsePosition(0);
+ DecimalFormat df = new DecimalFormat();
+ df.parse(input, ppos);
+ assertEquals("Should stop after first entry", 3, ppos.getIndex());
+ ppos.setIndex(ppos.getIndex() + 1);
+ df.parse(input, ppos);
+ assertEquals("Should stop after second entry", 7, ppos.getIndex());
+ ppos.setIndex(ppos.getIndex() + 1);
+ df.parseCurrency(input, ppos); // test parseCurrency API as well
+ assertEquals("Should stop after third entry", 12, ppos.getIndex());
+ }
+
+ @Test
+ public void testTrailingMinusSign() {
+ String input = "52-";
+ DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(ULocale.ENGLISH);
+ ParsePosition ppos = new ParsePosition(0);
+ Number result = df.parse(input, ppos);
+ assertEquals("Trailing sign should NOT be accepted after the number in English by default",
+ 52.0,
+ result.doubleValue(),
+ 0.0);
+ df.applyPattern("#;#-");
+ ppos.setIndex(0);
+ result = df.parse(input, ppos);
+ assertEquals("Trailing sign SHOULD be accepted if there is one in the pattern",
+ -52.0,
+ result.doubleValue(),
+ 0.0);
+ }
}
DecimalFormatSymbols(java.util.Locale.US));
String text = "1.222,111";
Number num = df.parse(text,new ParsePosition(0));
- if (!num.toString().equals("1.222"))
+ if (!num.toString().equals("1.222111"))
errln("\"" + text + "\" is parsed as " + num);
text = "1.222x111";
num = df.parse(text,new ParsePosition(0));
assertTrue("10^19 should fit", quantity.fitsInLong());
quantity.setToLong(1234567890123456789L);
assertTrue("A number between 10^19 and max long should fit", quantity.fitsInLong());
+ quantity.setToLong(1234567890000000000L);
+ assertTrue("A number with trailing zeros less than max long should fit", quantity.fitsInLong());
quantity.setToLong(9223372026854775808L);
assertTrue("A number less than max long but with similar digits should fit",
quantity.fitsInLong());
assertFalse("One greater than max long long should not fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("9223372046854775806"));
assertFalse("A number between max long and 10^20 should not fit", quantity.fitsInLong());
+ quantity.setToBigInteger(new BigInteger("9223372046800000000"));
+ assertFalse("A large 10^19 number with trailing zeros should not fit", quantity.fitsInLong());
quantity.setToBigInteger(new BigInteger("10000000000000000000"));
assertFalse("10^20 should not fit", quantity.fitsInLong());
}
import org.junit.Test;
+import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.impl.number.parse.IgnorablesMatcher;
import com.ibm.icu.impl.number.parse.MinusSignMatcher;
import com.ibm.icu.impl.number.parse.NumberParserImpl;
assertNotNull("Greedy Parse failed: " + message, resultObject.quantity);
assertEquals("Greedy Parse failed: " + message,
expectedCharsConsumed,
- resultObject.charsConsumed);
+ resultObject.charEnd);
assertEquals("Greedy Parse failed: " + message,
resultDouble,
resultObject.getNumber().doubleValue(),
assertNotNull("Non-Greedy Parse failed: " + message, resultObject.quantity);
assertEquals("Non-Greedy Parse failed: " + message,
expectedCharsConsumed,
- resultObject.charsConsumed);
+ resultObject.charEnd);
assertEquals("Non-Greedy Parse failed: " + message,
resultDouble,
resultObject.getNumber().doubleValue(),
assertNotNull("Strict Parse failed: " + message, resultObject.quantity);
assertEquals("Strict Parse failed: " + message,
expectedCharsConsumed,
- resultObject.charsConsumed);
+ resultObject.charEnd);
assertEquals("Strict Parse failed: " + message,
resultDouble,
resultObject.getNumber().doubleValue(),
public void testSeriesMatcher() {
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
SeriesMatcher series = new SeriesMatcher();
- series.addMatcher(PlusSignMatcher.getInstance(symbols));
- series.addMatcher(MinusSignMatcher.getInstance(symbols));
+ series.addMatcher(PlusSignMatcher.getInstance(symbols, false));
+ series.addMatcher(MinusSignMatcher.getInstance(symbols, false));
series.addMatcher(IgnorablesMatcher.DEFAULT);
series.addMatcher(PercentMatcher.getInstance(symbols));
series.addMatcher(IgnorablesMatcher.DEFAULT);
assertEquals("'" + input + "'", expectedMaybeMore, actualMaybeMore);
}
}
+
+ @Test
+ public void testGroupingDisabled() {
+ DecimalFormatProperties properties = new DecimalFormatProperties();
+ properties.setGroupingSize(0);
+ DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
+ NumberParserImpl parser = NumberParserImpl
+ .createParserFromProperties(properties, symbols, false, true);
+ ParsedNumber result = new ParsedNumber();
+ parser.parse("12,345.678", true, result);
+ assertEquals("Should not parse with grouping separator",
+ 12.0,
+ result.getNumber().doubleValue(),
+ 0.0);
+ }
}
package com.ibm.icu.dev.test.number;
import static com.ibm.icu.impl.number.parse.UnicodeSetStaticCache.get;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import com.ibm.icu.impl.number.parse.UnicodeSetStaticCache;
import com.ibm.icu.impl.number.parse.UnicodeSetStaticCache.Key;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.DecimalFormatSymbols;
}
}
- @Test
- public void testUnions() {
- for (Key key1 : Key.values()) {
- for (Key key2 : Key.values()) {
- Key key3 = UnicodeSetStaticCache.unionOf(key1, key2);
- if (key3 != null) {
- UnicodeSet s1 = get(key1);
- UnicodeSet s2 = get(key2);
- UnicodeSet s3 = get(key3);
- UnicodeSet s1_s2 = s1.cloneAsThawed().addAll(s2);
- assertEquals(key1 + "/" + key2 + "/" + key3, s1_s2, s3);
- }
- }
- }
- }
-
static void assertInSet(ULocale locale, UnicodeSet set, String str) {
if (str.codePointCount(0, str.length()) != 1) {
// Ignore locale strings with more than one code point (usually a bidi mark)