mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
classlib: fix parse and other issues in Long and Integer
This commit is contained in:
parent
9c6f23d280
commit
bd80c2dfce
|
@ -95,11 +95,12 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
|||
break;
|
||||
}
|
||||
int value = 0;
|
||||
int maxValue = 1 + TInteger.MAX_VALUE / radix;
|
||||
if (index == endIndex) {
|
||||
throw new TNumberFormatException();
|
||||
}
|
||||
while (index < endIndex) {
|
||||
int digit = TCharacter.getNumericValue(s.charAt(index++));
|
||||
int digit = decodeDigit(s.charAt(index++));
|
||||
if (digit < 0) {
|
||||
throw new TNumberFormatException("String contains invalid digits: "
|
||||
+ s.subSequence(beginIndex, endIndex));
|
||||
|
@ -108,6 +109,9 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
|||
throw new TNumberFormatException("String contains digits out of radix " + radix + ": "
|
||||
+ s.subSequence(beginIndex, endIndex));
|
||||
}
|
||||
if (value > maxValue) {
|
||||
throw new TNumberFormatException("The value is too big for integer type");
|
||||
}
|
||||
value = radix * value + digit;
|
||||
if (value < 0) {
|
||||
if (index == endIndex && value == MIN_VALUE && negative) {
|
||||
|
@ -205,8 +209,8 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
|||
}
|
||||
|
||||
public static TInteger decode(String nm) throws TNumberFormatException {
|
||||
if (nm == null || nm.isEmpty()) {
|
||||
throw new TNumberFormatException("Can't parse empty or null string");
|
||||
if (nm.isEmpty()) {
|
||||
throw new TNumberFormatException("Can't parse empty string");
|
||||
}
|
||||
int index = 0;
|
||||
boolean negaive = false;
|
||||
|
@ -239,11 +243,15 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
|||
throw new TNumberFormatException("The string does not represent a number");
|
||||
}
|
||||
int value = 0;
|
||||
int maxValue = 1 + TInteger.MAX_VALUE / radix;
|
||||
while (index < nm.length()) {
|
||||
int digit = decodeDigit(nm.charAt(index++));
|
||||
if (digit >= radix) {
|
||||
if (digit < 0 || digit >= radix) {
|
||||
throw new TNumberFormatException("The string does not represent a number");
|
||||
}
|
||||
if (value > maxValue) {
|
||||
throw new TNumberFormatException("The value is too big for integer type");
|
||||
}
|
||||
value = value * radix + digit;
|
||||
if (value < 0) {
|
||||
if (negaive && value == MIN_VALUE && index == nm.length()) {
|
||||
|
@ -263,7 +271,7 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
|||
} else if (c >= 'A' && c <= 'Z') {
|
||||
return c - 'A' + 10;
|
||||
} else {
|
||||
return 255;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,12 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
|||
break;
|
||||
}
|
||||
long value = 0;
|
||||
long maxValue = 1 + TLong.MAX_VALUE / radix;
|
||||
if (index == endIndex) {
|
||||
throw new TNumberFormatException();
|
||||
}
|
||||
while (index < endIndex) {
|
||||
int digit = TCharacter.getNumericValue(s.charAt(index++));
|
||||
int digit = decodeDigit(s.charAt(index++));
|
||||
if (digit < 0) {
|
||||
throw new TNumberFormatException("String contains invalid digits: "
|
||||
+ s.subSequence(beginIndex, endIndex));
|
||||
|
@ -82,12 +86,15 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
|||
throw new TNumberFormatException("String contains digits out of radix " + radix + ": "
|
||||
+ s.subSequence(beginIndex, endIndex));
|
||||
}
|
||||
if (value > maxValue) {
|
||||
throw new TNumberFormatException("The value is too big for long type");
|
||||
}
|
||||
value = radix * value + digit;
|
||||
if (value < 0) {
|
||||
if (index == endIndex && value == MIN_VALUE && negative) {
|
||||
return MIN_VALUE;
|
||||
}
|
||||
throw new TNumberFormatException("The value is too big for int type: "
|
||||
throw new TNumberFormatException("The value is too big for long type: "
|
||||
+ s.subSequence(beginIndex, endIndex));
|
||||
}
|
||||
}
|
||||
|
@ -107,8 +114,8 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
|||
}
|
||||
|
||||
public static TLong decode(TString nm) throws TNumberFormatException {
|
||||
if (nm == null || nm.isEmpty()) {
|
||||
throw new TNumberFormatException("Can't parse empty or null string");
|
||||
if (nm.isEmpty()) {
|
||||
throw new TNumberFormatException("Can't parse empty string");
|
||||
}
|
||||
int index = 0;
|
||||
boolean negaive = false;
|
||||
|
@ -141,11 +148,15 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
|||
throw new TNumberFormatException("The string does not represent a number");
|
||||
}
|
||||
long value = 0;
|
||||
long maxValue = 1 + TLong.MAX_VALUE / radix;
|
||||
while (index < nm.length()) {
|
||||
int digit = decodeDigit(nm.charAt(index++));
|
||||
if (digit >= radix) {
|
||||
if (digit < 0 || digit >= radix) {
|
||||
throw new TNumberFormatException("The string does not represent a number");
|
||||
}
|
||||
if (value > maxValue) {
|
||||
throw new TNumberFormatException("The value is too big for long type");
|
||||
}
|
||||
value = value * radix + digit;
|
||||
if (value < 0) {
|
||||
if (negaive && value == MIN_VALUE && index == nm.length()) {
|
||||
|
@ -165,7 +176,7 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
|||
} else if (c >= 'A' && c <= 'Z') {
|
||||
return c - 'A' + 10;
|
||||
} else {
|
||||
return 255;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
|
@ -358,9 +369,9 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
|||
}
|
||||
|
||||
public static long reverseBytes(long i) {
|
||||
i = ((i & 0xFF00FF00FF00FF00L) >> 8) | ((i & 0x00FF00FF00FF00FFL) << 8);
|
||||
i = ((i & 0xFFFF0000FFFF0000L) >> 16) | ((i & 0x0000FFFF0000FFFFL) << 16);
|
||||
i = (i >> 32) | (i << 32);
|
||||
i = ((i & 0xFF00FF00FF00FF00L) >>> 8) | ((i & 0x00FF00FF00FF00FFL) << 8);
|
||||
i = ((i & 0xFFFF0000FFFF0000L) >>> 16) | ((i & 0x0000FFFF0000FFFFL) << 16);
|
||||
i = (i >>> 32) | (i << 32);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.classlib.java.lang;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
|
@ -48,12 +49,72 @@ public class IntegerTest {
|
|||
assertEquals(473, Integer.parseInt("[473]", 1, 4, 10));
|
||||
assertEquals(42, Integer.parseInt("[+42]", 1, 4, 10));
|
||||
assertEquals(-255, Integer.parseInt("[-FF]", 1, 4, 16));
|
||||
try {
|
||||
Integer.parseInt("[-FF]", 1, 5, 16);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.parseInt("[-FF]", 1, 6, 16);
|
||||
fail();
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.parseInt("[-FF]", 1, 2, 16);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.parseInt("[-FF]", 5, 4, 16);
|
||||
fail();
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parsesMinInteger() {
|
||||
public void parsesCornerCases() {
|
||||
assertEquals(-2147483648, Integer.parseInt("-2147483648", 10));
|
||||
assertEquals(-2147483648, Integer.parseInt("-80000000", 16));
|
||||
try {
|
||||
Integer.parseInt("FFFF", 10);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.parseInt("2147483648", 10);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.parseInt("-2147483649", 10);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.parseInt("80000000", 16);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.parseInt("-80000001", 16);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.parseInt("99999999999", 10);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = NumberFormatException.class)
|
||||
|
@ -86,6 +147,42 @@ public class IntegerTest {
|
|||
assertEquals(Integer.valueOf(65535), Integer.decode("+0xFFFF"));
|
||||
assertEquals(Integer.valueOf(-255), Integer.decode("-0xFF"));
|
||||
assertEquals(Integer.valueOf(2748), Integer.decode("+#ABC"));
|
||||
try {
|
||||
Integer.decode(null); // undocumented NPE
|
||||
fail();
|
||||
} catch (NullPointerException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.decode("2147483648");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.decode("-2147483649");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.decode("0x80000000");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.decode("-0x80000001");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Integer.decode("99999999999");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.classlib.java.lang;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.SkipJVM;
|
||||
|
@ -24,13 +25,36 @@ import org.teavm.junit.TeaVMTestRunner;
|
|||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
public class LongTest {
|
||||
|
||||
@Test
|
||||
public void parsesLongInSubstring() {
|
||||
assertEquals(0, Long.parseLong("[0]", 1, 2, 10));
|
||||
assertEquals(473, Long.parseLong("[473]", 1, 4, 10));
|
||||
assertEquals(42, Long.parseLong("[+42]", 1, 4, 10));
|
||||
assertEquals(-255, Long.parseLong("[-FF]", 1, 4, 16));
|
||||
try {
|
||||
Long.parseLong("[-FF]", 1, 5, 16);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.parseLong("[-FF]", 1, 6, 16);
|
||||
fail();
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.parseLong("[-FF]", 1, 2, 16);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.parseLong("[-FF]", 5, 4, 16);
|
||||
fail();
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -109,4 +133,133 @@ public class LongTest {
|
|||
assertEquals("-1000000000000000000000000000000000000000000000000000000000000000",
|
||||
Long.toString(Long.MIN_VALUE, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reverseBytes() {
|
||||
assertEquals(0xAABBCCDD00112233L, Long.reverseBytes(0x33221100DDCCBBAAL));
|
||||
assertEquals(0x1122334455667788L, Long.reverseBytes(0x8877665544332211L));
|
||||
assertEquals(0x0011223344556677L, Long.reverseBytes(0x7766554433221100L));
|
||||
assertEquals(0x2000000000000002L, Long.reverseBytes(0x0200000000000020L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decode() {
|
||||
assertEquals("Returned incorrect value for hex string", 255L,
|
||||
Long.decode("0xFF").longValue());
|
||||
assertEquals("Returned incorrect value for dec string", -89000L,
|
||||
Long.decode("-89000").longValue());
|
||||
assertEquals("Returned incorrect value for 0 decimal", 0,
|
||||
Long.decode("0").longValue());
|
||||
assertEquals("Returned incorrect value for 0 hex", 0,
|
||||
Long.decode("0x0").longValue());
|
||||
assertEquals("Returned incorrect value for most negative value decimal", 0x8000000000000000L,
|
||||
Long.decode("-9223372036854775808").longValue());
|
||||
assertEquals("Returned incorrect value for most negative value hex", 0x8000000000000000L,
|
||||
Long.decode("-0x8000000000000000").longValue());
|
||||
assertEquals("Returned incorrect value for most positive value decimal", 0x7fffffffffffffffL,
|
||||
Long.decode("9223372036854775807").longValue());
|
||||
assertEquals("Returned incorrect value for most positive value hex", 0x7fffffffffffffffL,
|
||||
Long.decode("0x7fffffffffffffff").longValue());
|
||||
assertEquals("Failed for 07654321765432", 07654321765432L,
|
||||
Long.decode("07654321765432").longValue());
|
||||
try {
|
||||
Long.decode(null); // undocumented NPE
|
||||
fail();
|
||||
} catch (NullPointerException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.decode("999999999999999999999999999999999999999999999999999999");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.decode("9223372036854775808");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.decode("-9223372036854775809");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.decode("0x8000000000000000");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.decode("-0x8000000000000001");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.decode("42325917317067571199");
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_parseLong() {
|
||||
assertEquals("Returned incorrect value",
|
||||
100000000L, Long.parseLong("100000000", 10));
|
||||
assertEquals("Returned incorrect value from hex string", 68719476735L,
|
||||
Long.parseLong("FFFFFFFFF", 16));
|
||||
assertEquals("Returned incorrect value from octal string: " + Long.parseLong("77777777777"),
|
||||
8589934591L, Long.parseLong("77777777777", 8));
|
||||
assertEquals("Returned incorrect value for 0 hex", 0, Long.parseLong("0", 16));
|
||||
assertEquals("Returned incorrect value for most negative value hex", 0x8000000000000000L,
|
||||
Long.parseLong("-8000000000000000", 16));
|
||||
assertEquals("Returned incorrect value for most positive value hex", 0x7fffffffffffffffL,
|
||||
Long.parseLong("7fffffffffffffff", 16));
|
||||
assertEquals("Returned incorrect value for 0 decimal", 0,
|
||||
Long.parseLong("0", 10));
|
||||
assertEquals("Returned incorrect value for most negative value decimal", 0x8000000000000000L,
|
||||
Long.parseLong("-9223372036854775808", 10));
|
||||
assertEquals("Returned incorrect value for most positive value decimal", 0x7fffffffffffffffL,
|
||||
Long.parseLong("9223372036854775807", 10));
|
||||
try {
|
||||
Long.parseLong("999999999999", 8);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.parseLong("9223372036854775808", 10);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.parseLong("-9223372036854775809", 10);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.parseLong("8000000000000000", 16);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.parseLong("-8000000000000001", 16);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
Long.parseLong("42325917317067571199", 10);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user