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