mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-04 13:05:31 +00:00
ICU-22303 Support parsing infinity/NaN when decimal pattern match is required
If a DecimalFormat pattern contains a decimal point and setDecimalPatternMatchRequired is true, then DecimalFormat parse() fails to parse infinity/NaN representations. This is because infinity/NaN parsing does not set the HAS_DECIMAL_SEPARATOR_FLAG and so the RequireDecimalSeparatorValidator fails. This modifies the RequireDecimalSeparatorValidator so that it does not fail if the INFINITY or NAN flags are set, making it so decimal separators are not required if the infinity/NaN representations are parsed.
This commit is contained in:
parent
255eb4ef3e
commit
3edd9c828a
5 changed files with 41 additions and 4 deletions
|
@ -46,8 +46,9 @@ RequireDecimalSeparatorValidator::RequireDecimalSeparatorValidator(bool patternH
|
|||
}
|
||||
|
||||
void RequireDecimalSeparatorValidator::postProcess(ParsedNumber& result) const {
|
||||
bool parseIsInfNaN = 0 != (result.flags & FLAG_INFINITY) || 0 != (result.flags & FLAG_NAN);
|
||||
bool parseHasDecimalSeparator = 0 != (result.flags & FLAG_HAS_DECIMAL_SEPARATOR);
|
||||
if (parseHasDecimalSeparator != fPatternHasDecimalSeparator) {
|
||||
if (!parseIsInfNaN && parseHasDecimalSeparator != fPatternHasDecimalSeparator) {
|
||||
result.flags |= FLAG_FAIL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,6 +227,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
|
|||
TESTCASE_AUTO(Test11649_DecFmtCurrencies);
|
||||
TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
|
||||
TESTCASE_AUTO(Test12753_PatternDecimalPoint);
|
||||
TESTCASE_AUTO(Test22303_PatternDecimalPoint_InfNaN);
|
||||
TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
|
||||
TESTCASE_AUTO(Test11913_BigDecimal);
|
||||
TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
|
||||
|
@ -9423,9 +9424,26 @@ void NumberFormatTest::Test12753_PatternDecimalPoint() {
|
|||
df.parse(u"123",result, status);
|
||||
assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
|
||||
U_INVALID_FORMAT_ERROR, status);
|
||||
}
|
||||
}
|
||||
|
||||
void NumberFormatTest::Test11647_PatternCurrencySymbols() {
|
||||
void NumberFormatTest::Test22303_PatternDecimalPoint_InfNaN() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
DecimalFormatSymbols symbols(Locale::getUS(), status);
|
||||
symbols.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"infinity", false);
|
||||
symbols.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"notanumber", false);
|
||||
DecimalFormat df(u"0.00", symbols, status);
|
||||
if (!assertSuccess("", status)) return;
|
||||
df.setDecimalPatternMatchRequired(true);
|
||||
Formattable result;
|
||||
df.parse(u"infinity", result, status);
|
||||
assertEquals("Should parse to +INF even though decimal is required", INFINITY, result.getDouble());
|
||||
df.parse(u"notanumber", result, status);
|
||||
assertEquals("Should parse to NaN even though decimal is required", NAN, result.getDouble());
|
||||
df.parse("-infinity", result, status);
|
||||
assertEquals("Should parse to -INF even though decimal is required", -INFINITY, result.getDouble());
|
||||
}
|
||||
|
||||
void NumberFormatTest::Test11647_PatternCurrencySymbols() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
DecimalFormat df(status);
|
||||
df.applyPattern(u"¤¤¤¤#", status);
|
||||
|
|
|
@ -283,6 +283,7 @@ class NumberFormatTest: public CalendarTimeZoneTest {
|
|||
void Test11649_DecFmtCurrencies();
|
||||
void Test13148_ParseGroupingSeparators();
|
||||
void Test12753_PatternDecimalPoint();
|
||||
void Test22303_PatternDecimalPoint_InfNaN();
|
||||
void Test11647_PatternCurrencySymbols();
|
||||
void Test11913_BigDecimal();
|
||||
void Test11020_RoundingInScientificNotation();
|
||||
|
|
|
@ -5511,6 +5511,22 @@ public class NumberFormatTest extends CoreTestFmwk {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Test22303() throws ParseException {
|
||||
ULocale locale = new ULocale("en-US");
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
symbols.setInfinity("infinity");
|
||||
symbols.setNaN("notanumber");
|
||||
DecimalFormat df = new DecimalFormat("0.00", symbols);
|
||||
df.setDecimalPatternMatchRequired(true);
|
||||
Number result = df.parse("infinity");
|
||||
assertEquals("Should parse to +INF even though decimal is required", Double.POSITIVE_INFINITY, result);
|
||||
result = df.parse("notanumber");
|
||||
assertEquals("Should parse to NaN even though decimal is required", Double.NaN, result);
|
||||
result = df.parse("-infinity");
|
||||
assertEquals("Should parse to -INF even though decimal is required", Double.NEGATIVE_INFINITY, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Test12962() {
|
||||
String pat = "**0.00";
|
||||
|
|
|
@ -23,8 +23,9 @@ public class RequireDecimalSeparatorValidator extends ValidationMatcher {
|
|||
|
||||
@Override
|
||||
public void postProcess(ParsedNumber result) {
|
||||
boolean parseIsInfNaN = 0 != (result.flags & ParsedNumber.FLAG_INFINITY) || 0 != (result.flags & ParsedNumber.FLAG_NAN);
|
||||
boolean parseHasDecimalSeparator = 0 != (result.flags & ParsedNumber.FLAG_HAS_DECIMAL_SEPARATOR);
|
||||
if (parseHasDecimalSeparator != patternHasDecimalSeparator) {
|
||||
if (!parseIsInfNaN && parseHasDecimalSeparator != patternHasDecimalSeparator) {
|
||||
result.flags |= ParsedNumber.FLAG_FAIL;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue