Skip to content

Commit 9a71d90

Browse files
committed
Emulation for static methods in System, Objects, Double, Float, Integer
1 parent ec23cfa commit 9a71d90

14 files changed

Lines changed: 245 additions & 23 deletions

File tree

user/super/com/google/gwt/emul/java/lang/Double.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,23 @@ public static Double valueOf(String s) throws NumberFormatException {
121121
return new Double(s);
122122
}
123123

124+
public static String toHexString(double d) {
125+
if (!Double.isFinite(d)) {
126+
return Double.toString(d);
127+
}
128+
int exp = Math.abs(d) == 0 ? -1 : Math.getExponent(d);
129+
long allBits = Double.doubleToLongBits(d);
130+
String sign = allBits < 0 ? "-" : "";
131+
long significantBits = allBits & 0xfffffffffffffL;
132+
String unsignedPrefix = "0x1.";
133+
if (Math.abs(d) < Double.MIN_NORMAL) {
134+
unsignedPrefix = "0x0.";
135+
exp++;
136+
}
137+
return sign + unsignedPrefix + Long.toString(significantBits,16)
138+
.replaceFirst("(.)0+$", "$1") + "p" + exp;
139+
}
140+
124141
public Double(double value) {
125142
/*
126143
* Call to $create(value) must be here so that the method is referenced and not

user/super/com/google/gwt/emul/java/lang/Float.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,23 @@ public static Float valueOf(String s) throws NumberFormatException {
111111
return new Float(s);
112112
}
113113

114+
public static String toHexString(float f) {
115+
if (!Float.isFinite(f)) {
116+
return Float.toString(f);
117+
}
118+
int exp = Math.abs(f) == 0 ? -1 : Math.getExponent(f);
119+
int allBits = Float.floatToIntBits(f);
120+
String sign = allBits < 0 ? "-" : "";
121+
int significantBits = allBits << 1 & 0xffffff;
122+
String unsignedPrefix = "0x1.";
123+
if (Math.abs(f) < Float.MIN_NORMAL) {
124+
unsignedPrefix = "0x0.";
125+
exp++;
126+
}
127+
return sign + unsignedPrefix + Long.toString(significantBits,16)
128+
.replaceFirst("(.)0+$", "$1") + "p" + exp;
129+
}
130+
114131
private final transient float value;
115132

116133
public Float(double value) {

user/super/com/google/gwt/emul/java/lang/Integer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ public static int parseInt(String s, int radix) throws NumberFormatException {
170170
return __parseAndValidateInt(s, radix, MIN_VALUE, MAX_VALUE);
171171
}
172172

173+
public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
174+
throws NumberFormatException {
175+
return parseInt(s.subSequence(beginIndex, endIndex).toString(), radix);
176+
}
177+
173178
public static int reverse(int i) {
174179
int[] nibbles = ReverseNibbles.reverseNibbles;
175180
return (nibbles[i >>> 28]) | (nibbles[(i >> 24) & 0xf] << 4)

user/super/com/google/gwt/emul/java/lang/System.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ public static void setOut(PrintStream out) {
144144
System.out = out;
145145
}
146146

147+
public String lineSeparator() {
148+
return "\n";
149+
}
150+
147151
private static boolean arrayTypeMatch(Class<?> srcComp, Class<?> destComp) {
148152
if (srcComp.isPrimitive()) {
149153
return srcComp.equals(destComp);

user/super/com/google/gwt/emul/java/util/Objects.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,24 +139,44 @@ public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
139139

140140
public static int checkIndex(int index, int length) {
141141
if (index < 0 || index >= length) {
142-
throw new IndexOutOfBoundsException("Index " + index + " out of bounds for length " + length);
142+
throw getIndexError(index, length);
143143
}
144144
return index;
145145
}
146146

147147
public static int checkFromToIndex(int fromIndex, int toIndex, int length) {
148148
if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) {
149-
throw new IndexOutOfBoundsException("Range [" + fromIndex + ", " + toIndex
150-
+ ") out of bounds for length " + length);
149+
throw getFromIndexError(fromIndex, toIndex, length);
151150
}
152151
return fromIndex;
153152
}
154153

155154
public static int checkFromIndexSize(int fromIndex, int size, int length) {
156155
// in JS fromIndex + size cannot overflow because int is not limited to 32 bits
157156
if (fromIndex < 0 || size < 0 || fromIndex + size > length) {
158-
throw new IndexOutOfBoundsException("Range [" + fromIndex + ", " + (fromIndex + size)
159-
+ ") out of bounds for length " + length);
157+
throw getFromIndexError(fromIndex, fromIndex + size, length);
158+
}
159+
return fromIndex;
160+
}
161+
162+
public static long checkIndex(long index, long length) {
163+
if (index < 0 || index >= length) {
164+
throw getIndexError(index, length);
165+
}
166+
return index;
167+
}
168+
169+
public static long checkFromToIndex(long fromIndex, long toIndex, long length) {
170+
if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) {
171+
throw getFromIndexError(fromIndex, toIndex, length);
172+
}
173+
return fromIndex;
174+
}
175+
176+
public static long checkFromIndexSize(long fromIndex, long size, long length) {
177+
// in JS fromIndex + size cannot overflow because int is not limited to 64 bits
178+
if (fromIndex < 0 || size < 0 || fromIndex + size > length) {
179+
throw getFromIndexError(fromIndex, fromIndex + size, length);
160180
}
161181
return fromIndex;
162182
}
@@ -168,4 +188,14 @@ public static String toString(Object o) {
168188
public static String toString(Object o, String nullDefault) {
169189
return o != null ? o.toString() : nullDefault;
170190
}
191+
192+
private static IndexOutOfBoundsException getIndexError(long index, long length) {
193+
return new IndexOutOfBoundsException("Index " + index + " out of bounds for length " + length);
194+
}
195+
196+
private static IndexOutOfBoundsException getFromIndexError(long fromIndex,
197+
long toIndex, long length) {
198+
return new IndexOutOfBoundsException("Range [" + fromIndex + ", " + toIndex
199+
+ ") out of bounds for length " + length);
200+
}
171201
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2025 GWT Project Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.google.gwt.emultest.java17.util;
17+
18+
import com.google.gwt.emultest.java.util.EmulTestBase;
19+
20+
import java.util.Objects;
21+
22+
/**
23+
* Tests {@link Objects} additions up to Java 17 (checkIndex* is part of Java 16).
24+
*/
25+
public class ObjectsTest extends EmulTestBase {
26+
27+
public void testCheckIndex() {
28+
assertEquals(50000000000L, Objects.checkIndex(50000000000L, 100000000000L));
29+
assertThrows(IndexOutOfBoundsException.class,
30+
() -> Objects.checkIndex(-50000000000L, 50000000000L));
31+
assertThrows(IndexOutOfBoundsException.class,
32+
() -> Objects.checkIndex(100000000000L, 50000000000L));
33+
assertThrows(IndexOutOfBoundsException.class,
34+
() -> Objects.checkIndex(50000000000L, 50000000000L));
35+
}
36+
37+
public void testCheckFromToIndex() {
38+
assertEquals(50000000000L,
39+
Objects.checkFromToIndex(50000000000L, 70000000000L, 100000000000L));
40+
assertEquals(0L, Objects.checkFromToIndex(0, 100000000000L, 100000000000L));
41+
assertThrows(IndexOutOfBoundsException.class,
42+
() -> Objects.checkFromToIndex(-50000000000L, 10000000000L, 50000000000L));
43+
assertThrows(IndexOutOfBoundsException.class,
44+
() -> Objects.checkFromToIndex(100000000000L, 10000000000L, 50000000000L));
45+
assertThrows(IndexOutOfBoundsException.class,
46+
() -> Objects.checkFromToIndex(10000000000L, 100000000000L, 50000000000L));
47+
}
48+
49+
public void testCheckFromIndexSize() {
50+
assertEquals(50000000000L,
51+
Objects.checkFromIndexSize(50000000000L, 20000000000L, 100000000000L));
52+
assertEquals(0L, Objects.checkFromIndexSize(0, 100000000000L, 100000000000L));
53+
assertThrows(IndexOutOfBoundsException.class,
54+
() -> Objects.checkFromIndexSize(-50000000000L, 10000000000L, 50000000000L));
55+
assertThrows(IndexOutOfBoundsException.class,
56+
() -> Objects.checkFromIndexSize(100000000000L, 10000000000L, 50000000000L));
57+
assertThrows(IndexOutOfBoundsException.class,
58+
() -> Objects.checkFromIndexSize(10000000000L, 100000000000L, 50000000000L));
59+
assertThrows(IndexOutOfBoundsException.class,
60+
() -> Objects.checkFromIndexSize(10000000000L, -50000000000L, 50000000000L));
61+
}
62+
63+
}

user/test/com/google/gwt/emultest/EmulJava17Suite.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.google.gwt.emultest.java17.lang.MathTest;
2020
import com.google.gwt.emultest.java17.lang.StringTest;
2121
import com.google.gwt.emultest.java17.util.MapEntryTest;
22+
import com.google.gwt.emultest.java17.util.ObjectsTest;
2223
import com.google.gwt.emultest.java17.util.stream.CollectorsTest;
2324
import com.google.gwt.emultest.java17.util.stream.DoubleStreamTest;
2425
import com.google.gwt.emultest.java17.util.stream.IntStreamTest;
@@ -39,7 +40,8 @@
3940
DoubleStreamTest.class,
4041
IntStreamTest.class,
4142
LongStreamTest.class,
42-
MapEntryTest.class
43+
MapEntryTest.class,
44+
ObjectsTest.class
4345
})
4446
public class EmulJava17Suite {
4547
}

user/test/com/google/gwt/emultest/java/lang/DoubleTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,25 @@ public void testParse() {
256256
}
257257
}
258258

259+
public void testToHexString() {
260+
assertEquals("-0x1.0p0", Double.toHexString(-1.0));
261+
assertEquals("0x1.0p0", Double.toHexString(1.0));
262+
assertEquals("0x1.0p1", Double.toHexString(2.0));
263+
assertEquals("0x1.8p1", Double.toHexString(3.0));
264+
assertEquals("0x1.81c8p13", Double.toHexString(12345.0));
265+
assertEquals("0x1.0p-1022", Double.toHexString(Double.MIN_NORMAL));
266+
assertEquals("0x0.8p-1022", Double.toHexString(Double.MIN_NORMAL / 2));
267+
assertEquals("0x0.cp-1022", Double.toHexString(Double.MIN_NORMAL / 4 * 3));
268+
assertEquals("0x1.7e43c8800759cp996", Double.toHexString(1.0E300));
269+
assertEquals("-0x1.7e43c8800759cp996", Double.toHexString(-1.0E300));
270+
assertEquals("0x1.0p-1021", Double.toHexString(4.450147717014403E-308));
271+
assertEquals("0x0.0p0", Double.toHexString(0.0));
272+
assertEquals("-0x0.0p0", Double.toHexString(-0.0));
273+
assertEquals("Infinity", Double.toHexString(Double.POSITIVE_INFINITY));
274+
assertEquals("-Infinity", Double.toHexString(Double.NEGATIVE_INFINITY));
275+
assertEquals("NaN", Double.toHexString(Double.NaN));
276+
}
277+
259278
public void testDoubleBits() {
260279
// special values
261280
compareDoubleBits(0x0000000000000000L, 0.0);

user/test/com/google/gwt/emultest/java/lang/FloatTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,22 @@ public void testParse() {
162162
}
163163
}
164164

165+
public void testToHexString() {
166+
assertEquals("-0x1.0p0", Float.toHexString(-1.0f));
167+
assertEquals("0x1.0p0", Float.toHexString(1.0f));
168+
assertEquals("0x1.0p1", Float.toHexString(2.0f));
169+
assertEquals("0x1.8p1", Float.toHexString(3.0f));
170+
assertEquals("0x1.5p5", Float.toHexString(42.0f));
171+
assertEquals("0x1.81c8p13", Float.toHexString(12345.0f));
172+
assertEquals("0x0.0p0", Float.toHexString(0.0f));
173+
assertEquals("-0x0.0p0", Float.toHexString(-0.0f));
174+
assertEquals("Infinity", Float.toHexString(Float.POSITIVE_INFINITY));
175+
assertEquals("-Infinity", Float.toHexString(Float.NEGATIVE_INFINITY));
176+
assertEquals("NaN", Float.toHexString(Float.NaN));
177+
assertEquals("0x1.0p-126", Float.toHexString(Float.MIN_NORMAL));
178+
assertEquals("0x0.8p-126", Float.toHexString(Float.MIN_NORMAL / 2));
179+
}
180+
165181
public void testFloatBits() {
166182
compareFloatBits(0x1, 1.401298464324817E-45F);
167183
compareFloatBits(0x2, 1.401298464324817E-45F * 2.0F);

user/test/com/google/gwt/emultest/java/lang/IntegerTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package com.google.gwt.emultest.java.lang;
1717

18+
import static com.google.gwt.emultest.java.util.EmulTestBase.assertThrows;
19+
1820
import com.google.gwt.junit.client.GWTTestCase;
1921

2022
/**
@@ -100,6 +102,16 @@ public void testBadStrings() {
100102
}
101103
}
102104

105+
public void testParseIntWithIndex() {
106+
assertEquals(42, Integer.parseInt("a42", 1, 3, 10));
107+
assertThrows(NumberFormatException.class, () ->
108+
assertEquals(42, Integer.parseInt("bad", 1, 3, 10)));
109+
assertThrows(StringIndexOutOfBoundsException.class, () ->
110+
assertEquals(42, Integer.parseInt("bad", 1, 30, 10)));
111+
assertThrows(StringIndexOutOfBoundsException.class, () ->
112+
assertEquals(42, Integer.parseInt("bad", -1, 3, 10)));
113+
}
114+
103115
public void testBinaryString() {
104116
assertEquals("11000000111001", Integer.toBinaryString(12345));
105117
assertEquals("0", Integer.toBinaryString(0));

0 commit comments

Comments
 (0)