Skip to content

Commit 0257e71

Browse files
committed
More emulation
1 parent b780d3f commit 0257e71

File tree

33 files changed

+945
-102
lines changed

33 files changed

+945
-102
lines changed

dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public class JavaResourceBase {
8282
"public interface CharSequence {",
8383
" char charAt(int index);",
8484
" int length();",
85+
" default boolean isEmpty() { return length() == 0; }",
8586
" String toString();",
8687
"}");
8788

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,38 @@ public boolean hasNext() {
5858
}, Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED, false);
5959
}
6060

61+
default IntStream codePoints() {
62+
return StreamSupport.intStream(() -> {
63+
PrimitiveIterator.OfInt it = new PrimitiveIterator.OfInt() {
64+
int cursor;
65+
66+
@Override
67+
public int nextInt() {
68+
checkElement(hasNext());
69+
int codePoint = CharSequence.this.toString().codePointAt(cursor++);
70+
if (codePoint >= 1 << 16) {
71+
cursor++;
72+
}
73+
return codePoint;
74+
}
75+
76+
@Override
77+
public boolean hasNext() {
78+
return cursor < length();
79+
}
80+
};
81+
return Spliterators.spliterator(it, length(), Spliterator.ORDERED);
82+
}, Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED, false);
83+
}
84+
85+
default boolean isEmpty() {
86+
return length() == 0;
87+
}
88+
89+
static int compare(CharSequence cs1, CharSequence cs2) {
90+
return cs1.toString().compareTo(cs2.toString());
91+
}
92+
6193
// CHECKSTYLE_OFF: Utility methods.
6294
@JsMethod
6395
static boolean $isInstance(HasCharSequenceTypeMarker instance) {

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

Lines changed: 121 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@
2727
import java.nio.charset.Charset;
2828
import java.nio.charset.UnsupportedCharsetException;
2929
import java.util.Comparator;
30+
import java.util.List;
3031
import java.util.Locale;
3132
import java.util.Spliterator;
3233
import java.util.Spliterators;
3334
import java.util.StringJoiner;
3435
import java.util.function.Consumer;
36+
import java.util.function.Function;
37+
import java.util.stream.Collectors;
3538
import java.util.stream.Stream;
3639
import java.util.stream.StreamSupport;
3740
import javaemul.internal.ArrayHelper;
@@ -488,6 +491,7 @@ public String intern() {
488491
return checkNotNull(this);
489492
}
490493

494+
@Override
491495
public boolean isEmpty() {
492496
return length() == 0;
493497
}
@@ -815,6 +819,117 @@ private int getTrailingWhitespaceLength() {
815819
return length;
816820
}
817821

822+
public String indent(int spaces) {
823+
if (spaces == 0) {
824+
return this;
825+
}
826+
Stream<String> indentedLines;
827+
if (spaces > 0) {
828+
String spaceString = " ".repeat(spaces);
829+
indentedLines = lines().map(line -> spaceString + line);
830+
} else {
831+
indentedLines = lines().map(
832+
line -> line.substring(Math.min(-spaces, line.getLeadingWhitespaceLength())));
833+
}
834+
return indentedLines.collect(Collectors.joining("\n", "", "\n"));
835+
}
836+
837+
public String stripIndent() {
838+
if (isEmpty()) {
839+
return "";
840+
}
841+
List<String> lines = lines().collect(Collectors.toList());
842+
int minIndent;
843+
char lastChar = charAt(length() - 1);
844+
String suffix = "";
845+
if (lastChar != '\r' && lastChar != '\n') {
846+
minIndent = Integer.MAX_VALUE;
847+
for (int i = 0; i < lines.size() - 1; i++) {
848+
String line = lines.get(i);
849+
int leadingWhitespace = line.getLeadingWhitespaceLength();
850+
// only update minIndent if not blank
851+
if (leadingWhitespace < line.length()) {
852+
minIndent = Math.min(minIndent, leadingWhitespace);
853+
}
854+
}
855+
// the last line affects minIndent even if blank
856+
minIndent = Math.min(minIndent, lines.get(lines.size() - 1).getLeadingWhitespaceLength());
857+
suffix = "\n";
858+
} else {
859+
minIndent = 0;
860+
}
861+
final int outdent = minIndent;
862+
return lines.stream().map(line -> {
863+
if (line.isBlank()) {
864+
return "";
865+
}
866+
return line.substring(outdent).stripTrailing();
867+
})
868+
.collect(Collectors.joining("\n", "", suffix));
869+
}
870+
871+
public String translateEscapes() {
872+
StringBuilder result = new StringBuilder();
873+
int translated = 0;
874+
while (translated < length()) {
875+
int nextBackslash = indexOf("\\", translated);
876+
result.append(substring(translated, nextBackslash));
877+
char currentChar = charAt(nextBackslash + 1);
878+
translated = nextBackslash + 1;
879+
switch (currentChar) {
880+
case 'b':
881+
result.append('\t');
882+
break;
883+
case 's':
884+
result.append(' ');
885+
break;
886+
case 't':
887+
result.append('\t');
888+
break;
889+
case 'n':
890+
result.append('\n');
891+
break;
892+
case 'f':
893+
result.append('\f');
894+
break;
895+
case 'r':
896+
result.append('\r');
897+
break;
898+
case '\n':
899+
case '\r':
900+
// discard
901+
break;
902+
case '"':
903+
result.append('"');
904+
break;
905+
case '\'':
906+
result.append('\'');
907+
break;
908+
case '\\':
909+
result.append('\\');
910+
break;
911+
case '0':
912+
case '1':
913+
case '2':
914+
case '3':
915+
case '4':
916+
case '5':
917+
case '6':
918+
case '7':
919+
int unicode = currentChar - '0';
920+
translated++;
921+
char nextChar = charAt(translated);
922+
while (nextChar >= '0' && nextChar < '8' && unicode < 32 && translated < length()) {
923+
unicode = (unicode << 3) + nextChar;
924+
translated++;
925+
nextChar = charAt(translated);
926+
}
927+
result.append((char) unicode);
928+
}
929+
}
930+
return result.toString();
931+
}
932+
818933
private class LinesSpliterator extends Spliterators.AbstractSpliterator<String> {
819934
private int nextIndex = 0;
820935
private int rPosition = -1;
@@ -830,10 +945,10 @@ public boolean tryAdvance(Consumer<? super String> action) {
830945
return false;
831946
}
832947
if (rPosition < nextIndex) {
833-
rPosition = cappedIndexOf('\r');
948+
rPosition = cappedIndexOf('\r', nextIndex);
834949
}
835950
if (nPosition < nextIndex) {
836-
nPosition = cappedIndexOf('\n');
951+
nPosition = cappedIndexOf('\n', nextIndex);
837952
}
838953
int lineEnd = Math.min(nPosition, rPosition);
839954
action.accept(substring(nextIndex, lineEnd));
@@ -843,11 +958,11 @@ public boolean tryAdvance(Consumer<? super String> action) {
843958
}
844959
return nextIndex < length();
845960
}
961+
}
846962

847-
private int cappedIndexOf(char c) {
848-
int index = indexOf(c, nextIndex);
849-
return index == -1 ? length() : index;
850-
}
963+
private int cappedIndexOf(char c, int nextIndex) {
964+
int index = indexOf(c, nextIndex);
965+
return index == -1 ? length() : index;
851966
}
852967

853968
@JsType(isNative = true, name = "String", namespace = "<window>")

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
import javaemul.internal.ArrayHelper;
2222
import javaemul.internal.LongUtils;
2323

24+
import java.util.function.Consumer;
25+
import java.util.function.IntConsumer;
26+
import java.util.stream.IntStream;
27+
import java.util.stream.StreamSupport;
28+
2429
/**
2530
* This implementation uses a dense array holding bit groups of size 31 to keep track of when bits
2631
* are set to true or false. Using 31 bits keeps our implementation within the range of V8's
@@ -37,6 +42,36 @@ public class BitSet {
3742

3843
private final int[] array;
3944

45+
private class BitSetSpliterator implements Spliterator.OfInt {
46+
int nextBitIndex = 0;
47+
48+
@Override
49+
public boolean tryAdvance(IntConsumer action) {
50+
int nextBit = nextSetBit(nextBitIndex);
51+
if (nextBit >= 0) {
52+
nextBitIndex = nextBit + 1;
53+
action.accept(nextBit);
54+
return true;
55+
}
56+
return false;
57+
}
58+
59+
@Override
60+
public Spliterator.OfInt trySplit() {
61+
return null;
62+
}
63+
64+
@Override
65+
public long estimateSize() {
66+
return size();
67+
}
68+
69+
@Override
70+
public int characteristics() {
71+
return Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED;
72+
}
73+
}
74+
4075
public BitSet() {
4176
array = new int[0];
4277
}
@@ -604,6 +639,11 @@ public int nextSetBit(int fromIndex) {
604639
return bitIndex(index) + Integer.numberOfTrailingZeros(word);
605640
}
606641

642+
public IntStream stream() {
643+
Spliterator.OfInt spliterator = new BitSetSpliterator();
644+
return StreamSupport.intStream(spliterator, false);
645+
}
646+
607647
public int previousClearBit(int fromIndex) {
608648
if (fromIndex == -1) {
609649
return -1;

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,13 @@ static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V>
276276
return (Comparator<Map.Entry<K, V>> & Serializable)
277277
(a, b) -> cmp.compare(a.getValue(), b.getValue());
278278
}
279+
280+
static <K,V> Map.Entry<K,V> copyOf(Map.Entry<? extends K,? extends V> e) {
281+
if (e instanceof AbstractMap.SimpleImmutableEntry) {
282+
return (Entry<K, V>) e;
283+
}
284+
return entry(e.getKey(), e.getValue());
285+
}
279286
}
280287

281288
void clear();

user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
import static javaemul.internal.InternalPreconditions.checkState;
1919

20+
import java.util.ArrayList;
2021
import java.util.Arrays;
2122
import java.util.DoubleSummaryStatistics;
23+
import java.util.List;
2224
import java.util.OptionalDouble;
2325
import java.util.PrimitiveIterator;
2426
import java.util.Spliterator;
@@ -58,6 +60,15 @@ default DoubleStream.Builder add(double t) {
5860
DoubleStream build();
5961
}
6062

63+
/**
64+
* See <a
65+
* href="https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/DoubleStream.DoubleMapMultiConsumer.html">
66+
* the official Java API doc</a> for details.
67+
*/
68+
interface DoubleMapMultiConsumer {
69+
void accept(double value, DoubleConsumer consumer);
70+
}
71+
6172
static Builder builder() {
6273
return new Builder() {
6374
private double[] items = new double[0];
@@ -317,5 +328,13 @@ public boolean tryAdvance(DoubleConsumer action) {
317328
return StreamSupport.doubleStream(spliterator, false);
318329
}
319330

331+
default DoubleStream mapMulti(DoubleStream.DoubleMapMultiConsumer mapper) {
332+
return flatMap(element -> {
333+
List<Double> buffer = new ArrayList<>();
334+
mapper.accept(element, (DoubleConsumer) buffer::add);
335+
return buffer.stream().mapToDouble(n -> n);
336+
});
337+
}
338+
320339
double[] toArray();
321340
}

user/super/com/google/gwt/emul/java/util/stream/IntStream.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717

1818
import static javaemul.internal.InternalPreconditions.checkState;
1919

20+
import java.util.ArrayList;
2021
import java.util.Arrays;
2122
import java.util.Comparator;
2223
import java.util.IntSummaryStatistics;
24+
import java.util.List;
2325
import java.util.OptionalDouble;
2426
import java.util.OptionalInt;
2527
import java.util.PrimitiveIterator;
@@ -61,6 +63,15 @@ default IntStream.Builder add(int t) {
6163
IntStream build();
6264
}
6365

66+
/**
67+
* See <a
68+
* href="https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/stream/IntStream.IntMapMultiConsumer.html">
69+
* the official Java API doc</a> for details.
70+
*/
71+
interface IntMapMultiConsumer {
72+
void accept(int value, IntConsumer consumer);
73+
}
74+
6475
static Builder builder() {
6576
return new Builder() {
6677
private int[] items = new int[0];
@@ -366,5 +377,13 @@ public boolean tryAdvance(IntConsumer action) {
366377
return StreamSupport.intStream(spliterator, false);
367378
}
368379

380+
default IntStream mapMulti(IntMapMultiConsumer mapper) {
381+
return flatMap(element -> {
382+
List<Integer> buffer = new ArrayList<>();
383+
mapper.accept(element, (IntConsumer) buffer::add);
384+
return buffer.stream().mapToInt(n -> n);
385+
});
386+
}
387+
369388
int[] toArray();
370389
}

0 commit comments

Comments
 (0)