diff --git a/classlib/src/main/java/org/teavm/classlib/impl/IntegerUtil.java b/classlib/src/main/java/org/teavm/classlib/impl/IntegerUtil.java new file mode 100644 index 000000000..ad4329e2f --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/impl/IntegerUtil.java @@ -0,0 +1,43 @@ +/* + * Copyright 2018 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.impl; + +import org.teavm.classlib.java.lang.TCharacter; + +public final class IntegerUtil { + private IntegerUtil() { + } + + public static String toUnsignedLogRadixString(int value, int radixLog2, int size) { + if (value == 0) { + return "0"; + } + + int radix = 1 << radixLog2; + int mask = radix - 1; + int sz = (size - Integer.numberOfLeadingZeros(value) + radixLog2 - 1) / radixLog2; + char[] chars = new char[sz]; + + int pos = (sz - 1) * radixLog2; + int target = 0; + while (pos >= 0) { + chars[target++] = TCharacter.forDigit((value >>> pos) & mask, radix); + pos -= radixLog2; + } + + return new String(chars); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TInteger.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TInteger.java index 42ac0f1dd..ab8f82b1f 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TInteger.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TInteger.java @@ -15,6 +15,8 @@ */ package org.teavm.classlib.java.lang; +import static org.teavm.classlib.impl.IntegerUtil.toUnsignedLogRadixString; + public class TInteger extends TNumber implements TComparable { public static final int SIZE = 32; public static final int MIN_VALUE = 0x80000000; @@ -39,15 +41,15 @@ public class TInteger extends TNumber implements TComparable { } public static String toHexString(int i) { - return toString(i, 16); + return toUnsignedLogRadixString(i, 4, SIZE); } public static String toOctalString(int i) { - return toString(i, 8); + return toUnsignedLogRadixString(i, 3, SIZE); } public static String toBinaryString(int i) { - return toString(i, 2); + return toUnsignedLogRadixString(i, 1, SIZE); } public static String toString(int i) { diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java index fd92e87bc..72225116c 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java @@ -172,15 +172,35 @@ public class TLong extends TNumber implements TComparable { } public static String toHexString(long i) { - return toString(i, 16); + return toUnsignedLogRadixString(i, 4); } public static String toOctalString(long i) { - return toString(i, 8); + return toUnsignedLogRadixString(i, 3); } public static String toBinaryString(long i) { - return toString(i, 2); + return toUnsignedLogRadixString(i, 1); + } + + private static String toUnsignedLogRadixString(long value, int radixLog2) { + if (value == 0) { + return "0"; + } + + int radix = 1 << radixLog2; + int mask = radix - 1; + int sz = (SIZE - numberOfLeadingZeros(value) + radixLog2 - 1) / radixLog2; + char[] chars = new char[sz]; + + long pos = (sz - 1) * radixLog2; + int target = 0; + while (pos >= 0) { + chars[target++] = TCharacter.forDigit((int) (value >>> pos) & mask, radix); + pos -= radixLog2; + } + + return new String(chars); } public static String toString(long value) { diff --git a/tests/src/test/java/org/teavm/classlib/java/lang/IntegerTest.java b/tests/src/test/java/org/teavm/classlib/java/lang/IntegerTest.java index 5f92545b6..58accc4f6 100644 --- a/tests/src/test/java/org/teavm/classlib/java/lang/IntegerTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/lang/IntegerTest.java @@ -150,4 +150,14 @@ public class IntegerTest { assertNull(Integer.getInteger("test.baz")); assertNull(Integer.getInteger(null)); } + + @Test + public void toHex() { + assertEquals("0", Integer.toHexString(0)); + assertEquals("1", Integer.toHexString(1)); + assertEquals("a", Integer.toHexString(10)); + assertEquals("11", Integer.toHexString(17)); + assertEquals("ff", Integer.toHexString(255)); + assertEquals("ffffffff", Integer.toHexString(-1)); + } }