mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Improve virtual FS API
This commit is contained in:
parent
99812d1bfa
commit
9ca09093a6
|
@ -15,8 +15,6 @@
|
|||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -48,12 +46,7 @@ public class InMemoryVirtualDirectory extends AbstractInMemoryVirtualFile {
|
|||
}
|
||||
|
||||
@Override
|
||||
public InputStream read() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream write(boolean append) {
|
||||
public VirtualFileAccessor createAccessor() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,7 @@
|
|||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class InMemoryVirtualFile extends AbstractInMemoryVirtualFile {
|
||||
|
@ -50,23 +47,37 @@ public class InMemoryVirtualFile extends AbstractInMemoryVirtualFile {
|
|||
}
|
||||
|
||||
@Override
|
||||
public InputStream read() {
|
||||
public VirtualFileAccessor createAccessor() {
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
return new ByteArrayInputStream(data, 0, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream write(boolean append) {
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
if (!append) {
|
||||
data = new byte[0];
|
||||
size = 0;
|
||||
}
|
||||
return new OutputStreamImpl(data, size);
|
||||
return new VirtualFileAccessor() {
|
||||
@Override
|
||||
public int read(int pos, byte[] buffer, int offset, int limit) throws IOException {
|
||||
limit = Math.max(0, Math.min(size - pos, limit));
|
||||
System.arraycopy(data, pos, buffer, offset, limit);
|
||||
return limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int pos, byte[] buffer, int offset, int limit) throws IOException {
|
||||
expandData(pos + limit);
|
||||
System.arraycopy(buffer, offset, data, pos, limit);
|
||||
size = pos + limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int size) throws IOException {
|
||||
expandData(size);
|
||||
InMemoryVirtualFile.this.size = size;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,73 +95,10 @@ public class InMemoryVirtualFile extends AbstractInMemoryVirtualFile {
|
|||
return size;
|
||||
}
|
||||
|
||||
class OutputStreamImpl extends OutputStream {
|
||||
byte[] data;
|
||||
int pos;
|
||||
|
||||
OutputStreamImpl(byte[] data, int pos) {
|
||||
this.data = data;
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
private void ensureIO() throws IOException {
|
||||
if (data == null) {
|
||||
throw new IOException("Stream was closed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
ensureIO();
|
||||
expandData(pos + 1);
|
||||
data[pos++] = (byte) b;
|
||||
sync();
|
||||
}
|
||||
|
||||
private void expandData(int newSize) {
|
||||
if (newSize > data.length) {
|
||||
int newCapacity = Math.max(newSize, data.length) * 3 / 2;
|
||||
boolean actual = data == InMemoryVirtualFile.this.data;
|
||||
data = Arrays.copyOf(data, newCapacity);
|
||||
if (actual) {
|
||||
InMemoryVirtualFile.this.data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sync() {
|
||||
if (data == InMemoryVirtualFile.this.data) {
|
||||
size = pos;
|
||||
modify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
ensureIO();
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (off < 0 || len < 0 || off + len >= b.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
expandData(pos + len);
|
||||
while (len-- > 0) {
|
||||
data[pos++] = b[off++];
|
||||
}
|
||||
|
||||
sync();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
data = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
private void expandData(int newSize) {
|
||||
if (newSize > data.length) {
|
||||
int newCapacity = Math.max(newSize, data.length) * 3 / 2;
|
||||
data = Arrays.copyOf(data, newCapacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface VirtualFile {
|
||||
String getName();
|
||||
|
||||
|
@ -29,9 +26,7 @@ public interface VirtualFile {
|
|||
|
||||
VirtualFile getChildFile(String fileName);
|
||||
|
||||
InputStream read();
|
||||
|
||||
OutputStream write(boolean append);
|
||||
VirtualFileAccessor createAccessor();
|
||||
|
||||
VirtualFile createFile(String fileName);
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2017 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.fs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface VirtualFileAccessor {
|
||||
int read(int pos, byte[] buffer, int offset, int limit) throws IOException;
|
||||
|
||||
void write(int pos, byte[] buffer, int offset, int limit) throws IOException;
|
||||
|
||||
int size();
|
||||
|
||||
void resize(int size) throws IOException;
|
||||
}
|
|
@ -366,6 +366,11 @@ public class TFile implements Serializable, Comparable<TFile> {
|
|||
return path.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return path;
|
||||
}
|
||||
|
||||
private static String fixSlashes(String origPath) {
|
||||
int uncIndex = 0;
|
||||
int length = origPath.length();
|
||||
|
|
|
@ -18,10 +18,14 @@ package org.teavm.classlib.java.io;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
import org.teavm.classlib.fs.VirtualFile;
|
||||
import org.teavm.classlib.fs.VirtualFileAccessor;
|
||||
|
||||
public class TFileInputStream extends InputStream {
|
||||
private InputStream underlyingStream;
|
||||
private VirtualFileAccessor accessor;
|
||||
private int pos;
|
||||
private boolean eof;
|
||||
|
||||
public TFileInputStream(TFile file) throws FileNotFoundException {
|
||||
VirtualFile virtualFile = file.findVirtualFile();
|
||||
|
@ -29,39 +33,78 @@ public class TFileInputStream extends InputStream {
|
|||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
underlyingStream = virtualFile.read();
|
||||
if (underlyingStream == null) {
|
||||
accessor = virtualFile.createAccessor();
|
||||
if (accessor == null) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return underlyingStream.read(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return underlyingStream.read(b, off, len);
|
||||
Objects.requireNonNull(b);
|
||||
if (off < 0 || len < 0 || off + len > b.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
if (eof) {
|
||||
return -1;
|
||||
}
|
||||
ensureOpened();
|
||||
int result = accessor.read(pos, b, off, len);
|
||||
pos += result;
|
||||
if (pos == accessor.size()) {
|
||||
eof = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
return underlyingStream.skip(n);
|
||||
ensureOpened();
|
||||
if (eof) {
|
||||
return 0;
|
||||
}
|
||||
int newPos = Math.max(pos, Math.min(accessor.size(), pos));
|
||||
int result = newPos - pos;
|
||||
pos = newPos;
|
||||
if (result == 0) {
|
||||
accessor = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return underlyingStream.available();
|
||||
ensureOpened();
|
||||
if (eof) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(0, accessor.size() - pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
underlyingStream.close();
|
||||
accessor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return underlyingStream.read();
|
||||
ensureOpened();
|
||||
if (eof) {
|
||||
return -1;
|
||||
}
|
||||
byte[] buffer = new byte[1];
|
||||
int read = accessor.read(pos, buffer, 0, 1);
|
||||
if (read == 0) {
|
||||
eof = true;
|
||||
} else {
|
||||
pos++;
|
||||
}
|
||||
return !eof ? buffer[0] : -1;
|
||||
}
|
||||
|
||||
private void ensureOpened() throws IOException {
|
||||
if (accessor == null) {
|
||||
throw new IOException("This stream is already closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,13 @@ package org.teavm.classlib.java.io;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Objects;
|
||||
import org.teavm.classlib.fs.VirtualFile;
|
||||
import org.teavm.classlib.fs.VirtualFileAccessor;
|
||||
|
||||
public class TFileOutputStream extends OutputStream {
|
||||
private OutputStream underlyingStream;
|
||||
private VirtualFileAccessor accessor;
|
||||
private int pos;
|
||||
|
||||
public TFileOutputStream(TFile file) throws FileNotFoundException {
|
||||
this(file, false);
|
||||
|
@ -40,34 +43,47 @@ public class TFileOutputStream extends OutputStream {
|
|||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
underlyingStream = virtualFile.write(append);
|
||||
if (underlyingStream == null) {
|
||||
accessor = virtualFile.createAccessor();
|
||||
if (accessor == null) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
if (append) {
|
||||
pos = accessor.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
underlyingStream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
underlyingStream.write(b, off, len);
|
||||
Objects.requireNonNull(b);
|
||||
if (off < 0 || len < 0 || off + len > b.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
ensureOpened();
|
||||
accessor.write(pos, b, off, len);
|
||||
pos += len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
underlyingStream.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
underlyingStream.close();
|
||||
accessor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
underlyingStream.write(b);
|
||||
ensureOpened();
|
||||
byte[] buffer = { (byte) b };
|
||||
accessor.write(pos, buffer, 0, 1);
|
||||
pos++;
|
||||
}
|
||||
|
||||
private void ensureOpened() throws IOException {
|
||||
if (accessor == null) {
|
||||
throw new IOException("This stream is already closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user