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 4bd1666b6..153adaa5b 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 @@ -21,7 +21,6 @@ import java.text.DecimalFormatSymbols; import org.teavm.classlib.impl.unicode.CLDRHelper; import org.teavm.classlib.java.lang.TArithmeticException; import org.teavm.classlib.java.lang.TDouble; -import org.teavm.classlib.java.lang.TIndexOutOfBoundsException; import org.teavm.classlib.java.lang.TString; import org.teavm.classlib.java.util.TLocale; @@ -221,7 +220,7 @@ public class TDecimalFormat extends TNumberFormat { String posPrefix = getPositivePrefix(); if (string.regionMatches(index, negPrefix, 0, negPrefix.length())) { positive = false; - } else if (string.regionMatches(index, posPrefix, 0, posPrefix.length())) { + } else if (!string.regionMatches(index, posPrefix, 0, posPrefix.length())) { position.setErrorIndex(index); return null; } @@ -264,12 +263,38 @@ public class TDecimalFormat extends TNumberFormat { } allowGroupSeparator = false; ++index; - } else if (index + exponentSeparator.length() < string.length() && - string.substring(index, index + exponentSeparator.length()).equals(exponentSeparator)) { + } else if (string.regionMatches(index, exponentSeparator, 0, exponentSeparator.length())) { if (exponentDigits == 0) { break; } index += exponentSeparator.length(); + if (index == string.length()) { + position.setErrorIndex(index); + return null; + } + boolean positiveExponent = true; + if (string.charAt(index) == symbols.getMinusSign()) { + positiveExponent = false; + ++index; + } + int exponentLength = 0; + while (index < string.length()) { + digit = string.charAt(index) - symbols.getZeroDigit(); + if (digit < 0 || digit > 9) { + break; + } + exponent = exponent * 10 + digit; + ++exponentLength; + ++index; + } + if (exponentLength == 0) { + position.setErrorIndex(index); + return null; + } + if (!positiveExponent) { + exponent = -exponent; + } + break; } else { break; } @@ -280,18 +305,26 @@ public class TDecimalFormat extends TNumberFormat { return null; } - if (exponent < POW10_ARRAY.length) { + position.setIndex(index); + + exponent += shift - fracSize; + if (exponent > 0 && exponent < POW10_ARRAY.length) { if (mantissa < Long.MAX_VALUE / POW10_ARRAY[exponent]) { mantissa *= POW10_ARRAY[exponent]; exponent = 0; } + } else if (exponent < 0 && -exponent < POW10_ARRAY.length) { + if (mantissa % POW10_ARRAY[-exponent] == 0) { + mantissa /= POW10_ARRAY[-exponent]; + exponent = 0; + } } - if (shift == 0 && exponent == 0) { + if (exponent == 0) { return positive ? mantissa : -mantissa; } - double result = TDouble.decimalExponent(exponent + shift); + 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 new file mode 100644 index 000000000..1727a0b93 --- /dev/null +++ b/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatParseTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.text; + +import static org.junit.Assert.*; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.ParseException; +import java.util.Locale; +import org.junit.Test; + +/** + * + * @author Alexey Andreev + */ +public class DecimalFormatParseTest { + private static DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH); + + @Test + public void parsesNumber() throws ParseException { + DecimalFormat format = createFormat("#,#00.#"); + assertEquals(2L, format.parse("2")); + assertEquals(23L, format.parse("23")); + assertEquals(23L, format.parse("23.0")); + assertEquals(2300L, format.parse("2,3,0,0")); + assertEquals(23.1, format.parse("23.1")); + } + + @Test + public void parsesLargeValue() throws ParseException { + DecimalFormat format = createFormat("#,#00.#"); + assertEquals(9223372036854775807L, format.parse("9223372036854775807")); + assertEquals(99E18, format.parse("99000000000000000000")); + } + + @Test + public void parsesExponential() throws ParseException { + DecimalFormat format = createFormat("0.#E0"); + assertEquals(23L, format.parse("2.3E1")); + assertEquals(23L, format.parse("2300E-2")); + assertEquals(99E18, format.parse("99E18")); + } + + private DecimalFormat createFormat(String format) { + return new DecimalFormat(format, symbols); + } +} diff --git a/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatTest.java index e574576b1..496e54b3f 100644 --- a/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatTest.java +++ b/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.teavm.classlib.java.text; import static org.junit.Assert.*;