diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java index 50be2ff98..a91286a7a 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java @@ -219,6 +219,7 @@ public class TDecimalFormat extends TNumberFormat { boolean fractionalPart = false; boolean positive = true; + // Find prefix String negPrefix = getNegativePrefix(); String posPrefix = getPositivePrefix(); if (string.regionMatches(index, negPrefix, 0, negPrefix.length())) { @@ -231,6 +232,23 @@ public class TDecimalFormat extends TNumberFormat { return null; } + // Find suffix + String suffix = positive ? getPositiveSuffix() : getNegativeSuffix(); + if (suffix == null) { + suffix = getPositiveSuffix(); + } + + // Check for infinity + if (string.regionMatches(index, symbols.getInfinity(), 0, symbols.getInfinity().length())) { + index += symbols.getInfinity().length(); + if (suffix != null && !string.regionMatches(index, suffix, 0, suffix.length())) { + position.setErrorIndex(index); + return null; + } + return positive ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; + } + + // Parse mantissa and exponent while (index < string.length()) { char c = string.charAt(index); int digit = c - symbols.getZeroDigit(); @@ -309,22 +327,32 @@ public class TDecimalFormat extends TNumberFormat { } } + // If decimal separator without fractional part is not allowed, report error if (fracSize == 0 && fractionalPart && !isDecimalSeparatorAlwaysShown()) { position.setErrorIndex(index); return null; } - String suffix = positive ? getPositiveSuffix() : getNegativeSuffix(); - if (suffix == null) { - suffix = getPositiveSuffix(); - } + // Check suffix if (suffix != null && !string.regionMatches(index, suffix, 0, suffix.length())) { position.setErrorIndex(index); return null; } + // Advance parse position position.setIndex(index); + // Apply multiplier + if (multiplier != 1) { + int multiplierDigits = fastLn10(multiplier); + if (POW10_INT_ARRAY[multiplierDigits] != multiplier) { + mantissa /= multiplier; + } else { + exponent -= multiplierDigits; + } + } + + // Apply exponent exponent += shift - fracSize; if (exponent > 0 && exponent < POW10_ARRAY.length) { if (mantissa < Long.MAX_VALUE / POW10_ARRAY[exponent]) { @@ -338,10 +366,13 @@ public class TDecimalFormat extends TNumberFormat { } } + // Expose result + if (mantissa == 0 && !positive) { + return -0.0; + } if (exponent == 0) { return positive ? mantissa : -mantissa; } - double result = TDouble.decimalExponent(exponent) * mantissa; return positive ? result : -result; } diff --git a/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatParseTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatParseTest.java index e877e3b37..d47a827d2 100644 --- a/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatParseTest.java +++ b/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatParseTest.java @@ -76,6 +76,21 @@ public class DecimalFormatParseTest { } } + @Test + public void parsesPercent() throws ParseException { + DecimalFormat format = createFormat("0.#E0%"); + assertEquals(0.23, format.parse("23%").doubleValue(), 0.001); + assertEquals(23L, format.parse("2300%")); + } + + @Test + public void parsesSpecial() throws ParseException { + DecimalFormat format = createFormat("0.#E0"); + assertEquals(Double.POSITIVE_INFINITY, format.parse("∞")); + assertEquals(Double.NEGATIVE_INFINITY, format.parse("-∞")); + assertEquals(-0.0, format.parse("-0")); + } + private DecimalFormat createFormat(String format) { return new DecimalFormat(format, symbols); }