Adds support of java.io.BufferedReader and java.io.StringReader

This commit is contained in:
konsoletyper 2014-02-25 12:41:00 +04:00
parent 744033b118
commit 03bc2e2e07
17 changed files with 606 additions and 10 deletions

View File

@ -0,0 +1,185 @@
/*
* Copyright 2014 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.java.io;
import org.teavm.classlib.java.lang.TIllegalArgumentException;
import org.teavm.classlib.java.lang.TMath;
import org.teavm.classlib.java.lang.TString;
import org.teavm.classlib.java.lang.TStringBuilder;
import org.teavm.classlib.java.util.TArrays;
/**
*
* @author Alexey Andreev
*/
public class TBufferedReader extends TReader {
private TReader innerReader;
private char[] buffer;
private int index;
private int count;
private boolean eof;
private int mark = -1;
public TBufferedReader(TReader innerReader, int size) {
if (size < 0) {
throw new TIllegalArgumentException();
}
this.innerReader = innerReader;
this.buffer = new char[TMath.min(64, size)];
}
public TBufferedReader(TReader innerReader) {
this(innerReader, 1024);
}
@Override
public int read() throws TIOException {
requireOpened();
if (index >= count) {
if (!fillBuffer(0)) {
return -1;
}
}
return buffer[index++];
}
@Override
public void close() throws TIOException {
requireOpened();
innerReader.close();
innerReader = null;
}
@Override
public int read(char[] cbuf, int off, int len) throws TIOException {
requireOpened();
if (index == count && eof) {
return -1;
}
int charsRead = 0;
while (charsRead < len) {
int n = TMath.min(count - index, len - charsRead);
for (int i = 0; i < n; ++i) {
cbuf[off++] = buffer[index++];
}
charsRead += n;
if (!fillBuffer(0)) {
break;
}
}
return charsRead;
}
public TString readLine() throws TIOException {
requireOpened();
if (eof && index == count) {
return null;
}
TStringBuilder line = new TStringBuilder();
while (true) {
if (index >= count) {
if (!fillBuffer(0)) {
break;
}
}
char ch = buffer[index++];
if (ch == '\n') {
break;
} else if (ch == '\r') {
if (index >= count) {
if (!fillBuffer(0)) {
break;
}
}
if (buffer[index] == '\n') {
++index;
}
break;
} else {
line.append(ch);
}
}
return TString.wrap(line.toString());
}
@Override
public long skip(long n) throws TIOException {
requireOpened();
if (n < count - index) {
index += n;
} else {
n -= (count - index);
if (innerReader.skip(n) == n) {
fillBuffer(0);
}
}
return super.skip(n);
}
@Override
public boolean ready() {
return index < count;
}
@Override
public void mark(int readAheadLimit) throws TIOException {
if (readAheadLimit > buffer.length) {
buffer = TArrays.copyOf(buffer, readAheadLimit);
}
if (count - index < readAheadLimit) {
for (int i = index; i < count; ++i) {
buffer[i - index] = buffer[i];
}
fillBuffer(count - index);
}
mark = index;
}
@Override
public void reset() throws TIOException {
if (mark == -1) {
throw new TIOException();
}
index = mark;
}
private boolean fillBuffer(int offset) throws TIOException {
if (eof) {
return false;
}
while (true) {
int charsRead = innerReader.read(buffer, offset, buffer.length - 1);
if (charsRead == -1) {
eof = true;
break;
} else if (charsRead == 0) {
break;
} else {
offset += charsRead;
}
}
count = offset;
index = 0;
mark = -1;
return true;
}
private void requireOpened() {
if (innerReader == null) {
throw new TIOException();
}
}
}

View File

@ -23,5 +23,5 @@ import org.teavm.classlib.java.lang.TAutoCloseable;
*/
public interface TCloseable extends TAutoCloseable {
@Override
void close() throws TIOException;
public void close() throws TIOException;
}

View File

@ -0,0 +1,109 @@
/*
* Copyright 2014 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.java.io;
import org.teavm.classlib.java.lang.TIllegalArgumentException;
import org.teavm.classlib.java.lang.TMath;
import org.teavm.classlib.java.lang.TNullPointerException;
import org.teavm.classlib.java.lang.TString;
/**
*
* @author Alexey Andreev
*/
public class TStringReader extends TReader {
private TString string;
private int index;
private int mark = 0;
public TStringReader(TString string) {
if (string == null) {
throw new TNullPointerException();
}
this.string = string;
}
@Override
public int read() throws TIOException {
checkOpened();
if (index >= string.length()) {
return -1;
}
return string.charAt(index++);
}
@Override
public int read(char[] cbuf, int off, int len) throws TIOException {
checkOpened();
if (index >= string.length()) {
return -1;
}
int n = TMath.min(string.length() - index, len);
for (int i = 0; i < n; ++i) {
cbuf[off++] = string.charAt(index++);
}
return n;
}
@Override
public long skip(long n) throws TIOException {
checkOpened();
if (n < 0) {
n = TMath.max(n, -index);
} else {
n = TMath.min(string.length() - index, n);
}
index += n;
return n;
}
@Override
public boolean ready() throws TIOException {
checkOpened();
return true;
}
@Override
public boolean markSupported() {
return true;
}
@Override
public void mark(int readAheadLimit) throws TIOException {
checkOpened();
if (readAheadLimit < 0) {
throw new TIllegalArgumentException();
}
mark = index;
}
@Override
public void reset() throws TIOException {
checkOpened();
index = mark;
}
@Override
public void close() {
string = null;
}
private void checkOpened() throws TIOException {
if (string == null) {
throw new TIOException();
}
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2014 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.java.lang;
import org.teavm.javascript.ni.Rename;
/**
*
* @author Alexey Andreev
*/
public class TByte extends TNumber implements TComparable<TByte> {
private byte value;
public TByte(byte value) {
this.value = value;
}
@Override
public int intValue() {
return value;
}
@Override
public long longValue() {
return value;
}
@Override
public float floatValue() {
return value;
}
@Override
public double doubleValue() {
return value;
}
@Override
public byte byteValue() {
return value;
}
public static TByte valueOf(byte value) {
return new TByte(value);
}
public static TString toString(byte value) {
return TString.wrap(new StringBuilder().append(value).toString());
}
@Override
@Rename("toString")
public TString toString0() {
return toString(value);
}
@Override
public boolean equals(TObject other) {
return other instanceof TByte && ((TByte)other).value == value;
}
@Override
public int hashCode() {
return value;
}
public static int compare(byte a, byte b) {
return a - b;
}
@Override
public int compareTo(TByte other) {
return compare(value, other.value);
}
}

View File

@ -15,6 +15,7 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.classlib.impl.charset.UTF16Helper;
import org.teavm.classlib.impl.unicode.UnicodeHelper;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.ni.GeneratedBy;
@ -109,4 +110,23 @@ public class TCharacter extends TObject {
@GeneratedBy(CharacterNativeGenerator.class)
@PluggableDependency(CharacterNativeGenerator.class)
private static native String obtainDigitMapping();
public static int toChars(int codePoint, char[] dst, int dstIndex) {
if (codePoint >= UTF16Helper.SUPPLEMENTARY_PLANE) {
dst[dstIndex] = UTF16Helper.highSurrogate(codePoint);
dst[dstIndex + 1] = UTF16Helper.lowSurrogate(codePoint);
return 2;
} else {
dst[dstIndex] = (char)codePoint;
return 1;
}
}
public static char[] toChars(int codePoint) {
if (codePoint >= UTF16Helper.SUPPLEMENTARY_PLANE) {
return new char[] { UTF16Helper.highSurrogate(codePoint), UTF16Helper.lowSurrogate(codePoint) };
} else {
return new char[] { (char)codePoint };
}
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2014 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.java.lang;
import org.teavm.javascript.ni.Rename;
/**
*
* @author Alexey Andreev
*/
public class TShort extends TNumber implements TComparable<TShort> {
private short value;
public TShort(short value) {
this.value = value;
}
@Override
public int intValue() {
return value;
}
@Override
public long longValue() {
return value;
}
@Override
public float floatValue() {
return value;
}
@Override
public double doubleValue() {
return value;
}
@Override
public short shortValue() {
return value;
}
public static TShort valueOf(short value) {
return new TShort(value);
}
public static TString toString(short value) {
return TString.wrap(new StringBuilder().append(value).toString());
}
@Override
@Rename("toString")
public TString toString0() {
return toString(value);
}
@Override
public boolean equals(TObject other) {
return other instanceof TShort && ((TShort)other).value == value;
}
@Override
public int hashCode() {
return value;
}
public static int compare(short a, short b) {
return a - b;
}
@Override
public int compareTo(TShort other) {
return compare(value, other.value);
}
}

View File

@ -0,0 +1,98 @@
/*
* Copyright 2014 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.java.io;
import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import org.junit.Test;
/**
*
* @author Alexey Andreev
*/
public class BufferedReaderTest {
@Test
public void readsCharacters() throws IOException {
String str = "foo bar baz";
BufferedReader reader = new BufferedReader(new StringReader(str));
char[] chars = new char[100];
int charsRead = reader.read(chars);
assertEquals(str.length(), charsRead);
assertEquals(str.charAt(0), chars[0]);
assertEquals(str.charAt(charsRead - 1), chars[charsRead - 1]);
assertEquals(0, chars[charsRead]);
}
@Test
public void readsCharactersOneByOne() throws IOException {
String str = "foo";
BufferedReader reader = new BufferedReader(new StringReader(str));
assertEquals('f', reader.read());
assertEquals('o', reader.read());
assertEquals('o', reader.read());
assertEquals(-1, reader.read());
assertEquals(-1, reader.read());
}
@Test
public void readsLine() throws IOException {
String str = "foo\nbar\rbaz\r\nA\n\nB";
BufferedReader reader = new BufferedReader(new StringReader(str));
assertEquals("foo", reader.readLine());
assertEquals("bar", reader.readLine());
assertEquals("baz", reader.readLine());
assertEquals("A", reader.readLine());
assertEquals("", reader.readLine());
assertEquals("B", reader.readLine());
assertNull(reader.readLine());
assertNull(reader.readLine());
}
@Test
public void fillsBuffer() throws IOException {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; ++i) {
sb.append((char)i);
}
BufferedReader reader = new BufferedReader(new StringReader(sb.toString()), 101);
char[] buffer = new char[500];
reader.read(buffer);
assertEquals(0, buffer[0]);
assertEquals(1, buffer[1]);
assertEquals(499, buffer[499]);
}
@Test
public void leavesMark() throws IOException {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; ++i) {
sb.append((char)i);
}
BufferedReader reader = new BufferedReader(new StringReader(sb.toString()), 100);
reader.skip(50);
reader.mark(70);
reader.skip(60);
reader.reset();
char[] buffer = new char[150];
int charsRead = reader.read(buffer);
assertEquals(150, charsRead);
assertEquals(50, buffer[0]);
assertEquals(51, buffer[1]);
assertEquals(199, buffer[149]);
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang.io;
package org.teavm.classlib.java.io;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang.util;
package org.teavm.classlib.java.util;
import static org.junit.Assert.*;
import java.util.ArrayList;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang.util;
package org.teavm.classlib.java.util;
import static org.junit.Assert.*;
import java.util.Arrays;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang.util;
package org.teavm.classlib.java.util;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang.util;
package org.teavm.classlib.java.util;
import static org.junit.Assert.*;
import java.util.ServiceLoader;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang.util;
package org.teavm.classlib.java.util;
/**
*

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang.util;
package org.teavm.classlib.java.util;
/**
*

View File

@ -1 +0,0 @@
org.teavm.classlib.java.lang.util.TestServiceImpl

View File

@ -0,0 +1 @@
org.teavm.classlib.java.util.TestServiceImpl

View File

@ -411,7 +411,15 @@ class DependencyGraphBuilder {
}
@Override
public void isInstance(VariableReader receiver, VariableReader value, ValueType type) {
public void isInstance(VariableReader receiver, VariableReader value, final ValueType type) {
if (type instanceof ValueType.Object) {
final String className = ((ValueType.Object)type).getClassName();
useRunners.add(new Runnable() {
@Override public void run() {
dependencyChecker.initClass(className, callerStack);
}
});
}
}
@Override