Add Reader and StringReader emulation. Change-Id: Ib382e5d1605e56a37b6dca6703016591f5a06c63 Review-Link: https://gwt-review.googlesource.com/#/c/20680/
diff --git a/user/super/com/google/gwt/emul/java/io/Reader.java b/user/super/com/google/gwt/emul/java/io/Reader.java new file mode 100644 index 0000000..5413799 --- /dev/null +++ b/user/super/com/google/gwt/emul/java/io/Reader.java
@@ -0,0 +1,102 @@ +/* + * Copyright 2018 Google Inc. + * + * 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 java.io; + +/** + * Reads a stream of characters. + */ +public abstract class Reader { + /** + * The maximum buffer size to incrementally read in {@link #skip}. + */ + private static final int MAX_SKIP_BUFFER_SIZE = 1024; + + /** + * Closes the reader, and releases any associated resources. + */ + public abstract void close() throws IOException; + + /** + * Marks the present position in the stream. Until {@code readAheadLimit} more + * characters have been read, the current point in the stream will be stored + * as the mark. Calls to {@link #reset} will reposition the point in the + * stream to the mark. + * + * @throws IOException If the stream does not support mark(). + */ + public void mark(int readAheadLimit) throws IOException { + throw new IOException("Not supported"); + } + + /** + * Returns whether {@link #mark} is implemented. + */ + public boolean markSupported() { + return false; + } + + /** + * Reads a single character, or -1 if we are at the end of the stream. + */ + public int read() throws IOException { + char chr[] = new char[1]; + return (read(chr) == -1) ? -1 : chr[0]; + } + + /** + * Attempts to fill {@code buf} with characters up to the size of the array. + */ + public int read(char[] buf) { + return read(buf, 0, buf.length); + } + + /** + * Attempts to fill {@code buf} with up to {@code len} characters. Characters + * will be stored in {@code buf} starting at index {@code off}. + */ + public abstract int read(char[] buf, int off, int len); + + /** + * Returns whether the stream is ready for reading characters. + */ + public boolean ready() throws IOException { + return false; + } + + /** + * Attempts to reset the stream to the previous mark. + */ + public void reset() throws IOException { + throw new IOException("Not supported"); + } + + /** + * Skips {@code n} characters, returning the number of characters that were actually skipped. + */ + public long skip(long n) throws IOException { + long remaining = n; + int bufferSize = Math.min((int) n, MAX_SKIP_BUFFER_SIZE); + char[] skipBuffer = new char[bufferSize]; + while (remaining > 0) { + long numRead = read(skipBuffer, 0, (int) remaining); + if (numRead < 0) { + break; + } + remaining -= numRead; + } + return n - remaining; + } +}
diff --git a/user/super/com/google/gwt/emul/java/io/StringReader.java b/user/super/com/google/gwt/emul/java/io/StringReader.java new file mode 100644 index 0000000..08d3241 --- /dev/null +++ b/user/super/com/google/gwt/emul/java/io/StringReader.java
@@ -0,0 +1,48 @@ +/* + * Copyright 2018 Google Inc. + * + * 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 java.io; + +/** + * Reads characters from a string. + */ +public class StringReader extends Reader { + private final String text; + private int position; + + /** + * Constructs a reader which will read from the given string. + */ + public StringReader(String text) { + this.text = text; + } + + @Override + public void close() throws IOException { } + + /** + * Reads up to the specified number of characters from the string. + */ + @Override + public int read(char[] buf, int off, int readLength) { + if (position >= text.length()) { + return -1; + } + int length = Math.min(text.length() - position, readLength); + text.getChars(position, position + length, buf, off); + position += length; + return length; + } +}
diff --git a/user/test/com/google/gwt/emultest/java/io/StringReaderTest.java b/user/test/com/google/gwt/emultest/java/io/StringReaderTest.java new file mode 100644 index 0000000..c9d79de --- /dev/null +++ b/user/test/com/google/gwt/emultest/java/io/StringReaderTest.java
@@ -0,0 +1,110 @@ +/* + * Copyright 2018 Google Inc. + * + * 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 com.google.gwt.emultest.java.io; + +import com.google.gwt.junit.client.GWTTestCase; + +import java.io.StringReader; +import java.util.Arrays; + +/** + * Unit test for the {@link java.io.StringReader} emulated class. + */ +public class StringReaderTest extends GWTTestCase { + @Override + public String getModuleName() { + return "com.google.gwt.emultest.EmulSuite"; + } + + public void testEmptyString() throws Exception { + StringReader reader = new StringReader(""); + assertEquals(-1, reader.read()); + char[] buf = new char[5]; + assertEquals(-1, reader.read(buf)); + assertEquals(-1, reader.read(buf, 2, 0)); + } + + public void testString() throws Exception { + StringReader reader = new StringReader("The q\u00DCuick brown fox jumped over the lazy dog"); + assertEquals('T', reader.read()); + + char[] buf = new char[10]; + assertEquals(6, reader.read(buf, 3, 6)); + assertEquals("\u0000\u0000\u0000he q\u00DCi\u0000", String.valueOf(buf)); + + assertEquals('k', reader.read()); + assertEquals(' ', reader.read()); + + assertEquals(2, reader.read(buf, 0, 2)); + // First 2 characters now filled. + assertEquals("br\u0000he q\u00DCi\u0000", String.valueOf(buf)); + + assertEquals(10, reader.read(buf)); + assertEquals("own fox ju", String.valueOf(buf)); + + char[] four = new char[4]; + assertEquals(4, reader.read(four)); + assertEquals("mped", String.valueOf(four)); + + char[] emptyBuf = new char[0]; + assertEquals(0, reader.read(emptyBuf)); + + assertEquals(10, reader.read(buf)); + assertEquals(" over the ", String.valueOf(buf)); + + char[] eight = new char[8]; + assertEquals(7, reader.read(eight)); + assertEquals("lazy dog\u0000", String.valueOf(eight)); + + assertEquals(-1, reader.read()); + assertEquals(-1, reader.read(eight)); + assertEquals(-1, reader.read(eight, 0, 0)); + assertEquals(-1, reader.read(eight, 0, 1)); + } + + public void testSkip_stringOverBufferSize() throws Exception { + StringReader reader = new StringReader(repeat('x', 1025)); + + assertEquals(1025, reader.skip(2000)); + + assertEquals(-1, reader.read()); + } + + public void testSkip_longString() throws Exception { + int n = 10000; + char[] arr = new char[n]; + for (char i = 0; i < n; i++) { + arr[i] = i; + } + + StringReader reader = new StringReader(String.valueOf(arr)); + assertEquals(5000, reader.skip(5000)); + assertEquals(5000, reader.read()); + assertEquals(5001, reader.read()); + + assertEquals(4000, reader.skip(4000)); + assertEquals(9002, reader.read()); + + assertEquals(997, reader.skip(4000)); + assertEquals(-1, reader.read()); + } + + private static String repeat(char c, int count) { + char[] arr = new char[count]; + Arrays.fill(arr, c); + return String.valueOf(arr); + } +}