Port to Java

This commit is contained in:
Shane F. Carr 2025-03-26 15:14:20 -07:00
parent f17e5c0e0e
commit 226cfe18e4
7 changed files with 99 additions and 2 deletions

View file

@ -3682,6 +3682,32 @@ public class NumberFormatTest extends CoreTestFmwk {
}
}
@Test
public void TestDecimalFormatParse7E() {
String testdata = "~";
DecimalFormat dfmt = new DecimalFormat(testdata);
try {
dfmt.parse(testdata);
errln("parsing ~ should fail with a handled exception");
} catch (ParseException e) {
}
// Test basic behavior
dfmt = new DecimalFormat("~0");
dfmt.setParseStrict(true);
try {
dfmt.parse("200");
errln("parsing 200 should fail");
} catch (ParseException e) {
}
try {
Number result = dfmt.parse("≈200");
assertEquals("parsing with approximately should succeed", result.longValue(), 200);
} catch (ParseException e) {
errln(e.toString());
}
}
/*
* Testing currency driven max/min fraction digits problem
* reported by ticket#7282
@ -6917,7 +6943,7 @@ public class NumberFormatTest extends CoreTestFmwk {
parsedStrictValue = ca_strict.getNumber().intValue();
}
assertEquals("Strict parse of " + inputString + " using " + patternString,
parsedStrictValue, expectedStrictParse);
expectedStrictParse, parsedStrictValue);
ppos.setIndex(0);
df.setParseStrict(false);
@ -6926,7 +6952,7 @@ public class NumberFormatTest extends CoreTestFmwk {
parsedLenientValue = ca_lenient.getNumber().intValue();
}
assertEquals("Strict parse of " + inputString + " using " + patternString,
parsedLenientValue, expectedLenientParse);
expectedLenientParse, parsedLenientValue);
}
}

View file

@ -128,6 +128,10 @@ public class NumberParserTest extends CoreTestFmwk {
{ 3, " 1,234", "a0", 35, 1234. }, // should not hang
{ 3, "NaN", "0", 3, Double.NaN },
{ 3, "NaN E5", "0", 6, Double.NaN },
{ 3, "~100", "~0", 4, 100.0 },
{ 3, " ~ 100", "~0", 6, 100.0 },
{ 3, "≈100", "~0", 4, 100.0 },
{ 3, "100≈", "~0", 3, 100.0 },
{ 3, "0", "0", 1, 0.0 } };
int parseFlags = ParsingUtils.PARSE_FLAG_IGNORE_CASE

View file

@ -49,6 +49,7 @@ public class StaticUnicodeSets {
PERCENT_SIGN,
PERMILLE_SIGN,
INFINITY_SIGN,
APPROXIMATELY_SIGN,
// Currency Symbols
DOLLAR_SIGN,
@ -263,7 +264,10 @@ public class StaticUnicodeSets {
assert unicodeSets.containsKey(Key.PERCENT_SIGN);
assert unicodeSets.containsKey(Key.PERMILLE_SIGN);
// The following don't currently have parseLenients in data.
unicodeSets.put(Key.INFINITY_SIGN, new UnicodeSet("[∞]").freeze());
// This set of characters was manually curated from the values of the approximatelySign element of CLDR common/main/*.xml files.
unicodeSets.put(Key.APPROXIMATELY_SIGN, new UnicodeSet("[~≈≃約]").freeze());
assert unicodeSets.containsKey(Key.DOLLAR_SIGN);
assert unicodeSets.containsKey(Key.POUND_SIGN);

View file

@ -76,6 +76,9 @@ public class AffixPatternMatcher extends SeriesMatcher implements AffixUtils.Tok
case AffixUtils.TYPE_PLUS_SIGN:
addMatcher(factory.plusSign());
break;
case AffixUtils.TYPE_APPROXIMATELY_SIGN:
addMatcher(factory.approximatelySign());
break;
case AffixUtils.TYPE_PERCENT:
addMatcher(factory.percent());
break;
@ -87,6 +90,7 @@ public class AffixPatternMatcher extends SeriesMatcher implements AffixUtils.Tok
case AffixUtils.TYPE_CURRENCY_TRIPLE:
case AffixUtils.TYPE_CURRENCY_QUAD:
case AffixUtils.TYPE_CURRENCY_QUINT:
case AffixUtils.TYPE_CURRENCY_OVERFLOW:
// All currency symbols use the same matcher
addMatcher(factory.currency());
break;

View file

@ -26,6 +26,10 @@ public class AffixTokenMatcherFactory {
return PlusSignMatcher.getInstance(symbols, true);
}
public ApproximatelySignMatcher approximatelySign() {
return ApproximatelySignMatcher.getInstance(symbols, true);
}
public PercentMatcher percent() {
return PercentMatcher.getInstance(symbols);
}

View file

@ -0,0 +1,54 @@
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package com.ibm.icu.impl.number.parse;
import com.ibm.icu.impl.StaticUnicodeSets;
import com.ibm.icu.impl.StringSegment;
import com.ibm.icu.text.DecimalFormatSymbols;
/**
* @author sffc
*
*/
public class ApproximatelySignMatcher extends SymbolMatcher {
private static final ApproximatelySignMatcher DEFAULT = new ApproximatelySignMatcher(false);
private static final ApproximatelySignMatcher DEFAULT_ALLOW_TRAILING = new ApproximatelySignMatcher(true);
public static ApproximatelySignMatcher getInstance(DecimalFormatSymbols symbols, boolean allowTrailing) {
String symbolString = symbols.getApproximatelySignString();
if (DEFAULT.uniSet.contains(symbolString)) {
return allowTrailing ? DEFAULT_ALLOW_TRAILING : DEFAULT;
} else {
return new ApproximatelySignMatcher(symbolString, allowTrailing);
}
}
private final boolean allowTrailing;
private ApproximatelySignMatcher(String symbolString, boolean allowTrailing) {
super(symbolString, DEFAULT.uniSet);
this.allowTrailing = allowTrailing;
}
private ApproximatelySignMatcher(boolean allowTrailing) {
super(StaticUnicodeSets.Key.APPROXIMATELY_SIGN);
this.allowTrailing = allowTrailing;
}
@Override
protected boolean isDisabled(ParsedNumber result) {
return !allowTrailing && result.seenNumber();
}
@Override
protected void accept(StringSegment segment, ParsedNumber result) {
result.setCharsConsumed(segment);
}
@Override
public String toString() {
return "<ApproximatelySignMatcher>";
}
}

View file

@ -59,6 +59,7 @@ public class NumberParserImpl {
parser.addMatcher(DecimalMatcher.getInstance(symbols, grouper, parseFlags));
parser.addMatcher(MinusSignMatcher.getInstance(symbols, false));
parser.addMatcher(PlusSignMatcher.getInstance(symbols, false));
parser.addMatcher(ApproximatelySignMatcher.getInstance(symbols, false));
parser.addMatcher(PercentMatcher.getInstance(symbols));
parser.addMatcher(PermilleMatcher.getInstance(symbols));
parser.addMatcher(NanMatcher.getInstance(symbols, parseFlags));