mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
More efficient filesystem implementation
This commit is contained in:
parent
f47644d890
commit
5b739238c2
|
@ -18,9 +18,15 @@ package org.teavm.classlib.fs;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface VirtualFileAccessor {
|
public interface VirtualFileAccessor {
|
||||||
int read(int pos, byte[] buffer, int offset, int limit) throws IOException;
|
int read(byte[] buffer, int offset, int limit) throws IOException;
|
||||||
|
|
||||||
void write(int pos, byte[] buffer, int offset, int limit) throws IOException;
|
void write(byte[] buffer, int offset, int limit) throws IOException;
|
||||||
|
|
||||||
|
int tell() throws IOException;
|
||||||
|
|
||||||
|
void seek(int target) throws IOException;
|
||||||
|
|
||||||
|
void skip(int amount) throws IOException;
|
||||||
|
|
||||||
int size() throws IOException;
|
int size() throws IOException;
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class CVirtualFile implements VirtualFile {
|
||||||
if (file == 0) {
|
if (file == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new CVirtualFileAccessor(file, append ? -1 : 0);
|
return new CVirtualFileAccessor(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,38 +20,50 @@ import org.teavm.classlib.fs.VirtualFileAccessor;
|
||||||
|
|
||||||
public class CVirtualFileAccessor implements VirtualFileAccessor {
|
public class CVirtualFileAccessor implements VirtualFileAccessor {
|
||||||
private long file;
|
private long file;
|
||||||
private int position;
|
|
||||||
|
|
||||||
public CVirtualFileAccessor(long file, int position) {
|
public CVirtualFileAccessor(long file) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.position = position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(int pos, byte[] buffer, int offset, int limit) throws IOException {
|
public int read(byte[] buffer, int offset, int limit) throws IOException {
|
||||||
ensurePosition(pos);
|
return CFileSystem.read(file, buffer, offset, limit);
|
||||||
int bytesRead = CFileSystem.read(file, buffer, offset, limit);
|
|
||||||
position += bytesRead;
|
|
||||||
return bytesRead;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(int pos, byte[] buffer, int offset, int limit) throws IOException {
|
public void write(byte[] buffer, int offset, int limit) throws IOException {
|
||||||
ensurePosition(pos);
|
|
||||||
int bytesWritten = CFileSystem.write(file, buffer, offset, limit);
|
int bytesWritten = CFileSystem.write(file, buffer, offset, limit);
|
||||||
if (bytesWritten < limit) {
|
if (bytesWritten < limit) {
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
}
|
}
|
||||||
position += bytesWritten;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int tell() throws IOException {
|
||||||
|
return CFileSystem.tell(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void skip(int amount) throws IOException {
|
||||||
|
CFileSystem.seek(file, 0, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void seek(int target) throws IOException {
|
||||||
|
CFileSystem.seek(file, 0, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() throws IOException {
|
public int size() throws IOException {
|
||||||
|
int current = CFileSystem.tell(file);
|
||||||
if (!CFileSystem.seek(file, 2, 0)) {
|
if (!CFileSystem.seek(file, 2, 0)) {
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
}
|
}
|
||||||
position = CFileSystem.tell(file);
|
int result = CFileSystem.tell(file);
|
||||||
return position;
|
if (!CFileSystem.seek(file, 0, current)) {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -59,11 +71,13 @@ public class CVirtualFileAccessor implements VirtualFileAccessor {
|
||||||
if (!CFileSystem.seek(file, 2, 0)) {
|
if (!CFileSystem.seek(file, 2, 0)) {
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
}
|
}
|
||||||
position = CFileSystem.tell(file);
|
int position = CFileSystem.tell(file);
|
||||||
if (position < size) {
|
if (position < size) {
|
||||||
byte[] zeros = new byte[4096];
|
byte[] zeros = new byte[4096];
|
||||||
while (position < size) {
|
while (position < size) {
|
||||||
write(position, zeros, 0, Math.min(zeros.length, size - position));
|
int bytesToWrite = Math.min(zeros.length, size - position);
|
||||||
|
write(zeros, 0, bytesToWrite);
|
||||||
|
position += bytesToWrite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,13 +97,4 @@ public class CVirtualFileAccessor implements VirtualFileAccessor {
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensurePosition(int pos) throws IOException {
|
|
||||||
if (position != pos) {
|
|
||||||
if (!CFileSystem.seek(file, 0, pos)) {
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
position = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,21 +58,50 @@ public class InMemoryVirtualFile extends AbstractInMemoryVirtualFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new VirtualFileAccessor() {
|
return new VirtualFileAccessor() {
|
||||||
|
private int pos;
|
||||||
|
|
||||||
|
{
|
||||||
|
if (append) {
|
||||||
|
pos = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(int pos, byte[] buffer, int offset, int limit) {
|
public int read(byte[] buffer, int offset, int limit) {
|
||||||
limit = Math.max(0, Math.min(size - pos, limit));
|
limit = Math.max(0, Math.min(size - pos, limit));
|
||||||
System.arraycopy(data, pos, buffer, offset, limit);
|
if (limit > 0) {
|
||||||
|
System.arraycopy(data, pos, buffer, offset, limit);
|
||||||
|
pos += limit;
|
||||||
|
}
|
||||||
return limit;
|
return limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(int pos, byte[] buffer, int offset, int limit) {
|
public void write(byte[] buffer, int offset, int limit) {
|
||||||
expandData(pos + limit);
|
expandData(pos + limit);
|
||||||
System.arraycopy(buffer, offset, data, pos, limit);
|
System.arraycopy(buffer, offset, data, pos, limit);
|
||||||
size = pos + limit;
|
pos += limit;
|
||||||
|
if (pos > size) {
|
||||||
|
size = pos;
|
||||||
|
}
|
||||||
modify();
|
modify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int tell() throws IOException {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void seek(int target) throws IOException {
|
||||||
|
pos = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void skip(int amount) throws IOException {
|
||||||
|
pos += amount;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return size;
|
return size;
|
||||||
|
|
|
@ -23,9 +23,8 @@ import org.teavm.classlib.fs.VirtualFile;
|
||||||
import org.teavm.classlib.fs.VirtualFileAccessor;
|
import org.teavm.classlib.fs.VirtualFileAccessor;
|
||||||
|
|
||||||
public class TFileInputStream extends InputStream {
|
public class TFileInputStream extends InputStream {
|
||||||
|
private static final byte[] ONE_BYTE_BUFFER = new byte[1];
|
||||||
private VirtualFileAccessor accessor;
|
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();
|
||||||
|
@ -52,16 +51,9 @@ public class TFileInputStream extends InputStream {
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (eof) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
int result = accessor.read(pos, b, off, len);
|
int result = accessor.read(b, off, len);
|
||||||
pos += result;
|
return result > 0 ? result : -1;
|
||||||
if (pos == accessor.size()) {
|
|
||||||
eof = true;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -70,25 +62,20 @@ public class TFileInputStream extends InputStream {
|
||||||
throw new IOException("Value must be positive: " + n);
|
throw new IOException("Value must be positive: " + n);
|
||||||
}
|
}
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
if (eof) {
|
int last = accessor.tell();
|
||||||
return 0;
|
accessor.skip((int) n - 1);
|
||||||
|
if (accessor.read(ONE_BYTE_BUFFER, 0, 1) < 1) {
|
||||||
|
int position = accessor.size();
|
||||||
|
accessor.seek(position);
|
||||||
|
return position - last;
|
||||||
}
|
}
|
||||||
int newPos = Math.max(pos, Math.min(accessor.size(), pos + (int) n));
|
return n;
|
||||||
int result = newPos - pos;
|
|
||||||
pos = newPos;
|
|
||||||
if (result == 0) {
|
|
||||||
eof = true;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int available() throws IOException {
|
public int available() throws IOException {
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
if (eof) {
|
return Math.max(0, accessor.size() - accessor.tell());
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return Math.max(0, accessor.size() - pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -102,17 +89,9 @@ public class TFileInputStream extends InputStream {
|
||||||
@Override
|
@Override
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
if (eof) {
|
byte[] buffer = ONE_BYTE_BUFFER;
|
||||||
return -1;
|
int read = accessor.read(buffer, 0, 1);
|
||||||
}
|
return read != 0 ? buffer[0] : -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 {
|
private void ensureOpened() throws IOException {
|
||||||
|
|
|
@ -24,8 +24,8 @@ import org.teavm.classlib.fs.VirtualFile;
|
||||||
import org.teavm.classlib.fs.VirtualFileAccessor;
|
import org.teavm.classlib.fs.VirtualFileAccessor;
|
||||||
|
|
||||||
public class TFileOutputStream extends OutputStream {
|
public class TFileOutputStream extends OutputStream {
|
||||||
|
private static byte[] ONE_BYTE_BUFER = new byte[1];
|
||||||
private VirtualFileAccessor accessor;
|
private VirtualFileAccessor accessor;
|
||||||
private int pos;
|
|
||||||
|
|
||||||
public TFileOutputStream(TFile file) throws FileNotFoundException {
|
public TFileOutputStream(TFile file) throws FileNotFoundException {
|
||||||
this(file, false);
|
this(file, false);
|
||||||
|
@ -57,10 +57,6 @@ public class TFileOutputStream extends OutputStream {
|
||||||
if (accessor == null) {
|
if (accessor == null) {
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (append) {
|
|
||||||
pos = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,9 +65,8 @@ public class TFileOutputStream extends OutputStream {
|
||||||
if (off < 0 || len < 0 || off > b.length - len) {
|
if (off < 0 || len < 0 || off > b.length - len) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
ensurePos();
|
ensureOpened();
|
||||||
accessor.write(pos, b, off, len);
|
accessor.write(b, off, len);
|
||||||
pos += len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -90,10 +85,10 @@ public class TFileOutputStream extends OutputStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
ensurePos();
|
ensureOpened();
|
||||||
byte[] buffer = { (byte) b };
|
byte[] buffer = ONE_BYTE_BUFER;
|
||||||
accessor.write(pos, buffer, 0, 1);
|
buffer[0] = (byte) b;
|
||||||
pos++;
|
accessor.write(buffer, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureOpened() throws IOException {
|
private void ensureOpened() throws IOException {
|
||||||
|
@ -101,11 +96,4 @@ public class TFileOutputStream extends OutputStream {
|
||||||
throw new IOException("This stream is already closed");
|
throw new IOException("This stream is already closed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensurePos() throws IOException {
|
|
||||||
ensureOpened();
|
|
||||||
if (pos < 0) {
|
|
||||||
pos = accessor.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,10 @@ import org.teavm.classlib.java.lang.TIndexOutOfBoundsException;
|
||||||
import org.teavm.classlib.java.lang.TNullPointerException;
|
import org.teavm.classlib.java.lang.TNullPointerException;
|
||||||
|
|
||||||
public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
||||||
|
private static final byte[] ONE_BYTE_BUFFER = new byte[1];
|
||||||
private boolean readOnly;
|
private boolean readOnly;
|
||||||
private boolean autoFlush;
|
private boolean autoFlush;
|
||||||
private VirtualFileAccessor accessor;
|
private VirtualFileAccessor accessor;
|
||||||
private int pos;
|
|
||||||
private byte[] buff;
|
private byte[] buff;
|
||||||
|
|
||||||
public TRandomAccessFile(String name, String mode) throws FileNotFoundException {
|
public TRandomAccessFile(String name, String mode) throws FileNotFoundException {
|
||||||
|
@ -76,13 +76,9 @@ public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
||||||
if (off < 0 || len < 0 || off + len > b.length) {
|
if (off < 0 || len < 0 || off + len > b.length) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
if (pos >= accessor.size()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
int result = accessor.read(pos, b, off, len);
|
int result = accessor.read(b, off, len);
|
||||||
pos += result;
|
return result > 0 ? result : -1;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(byte[] b) throws IOException {
|
public int read(byte[] b) throws IOException {
|
||||||
|
@ -92,8 +88,7 @@ public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
byte[] buffer = new byte[1];
|
byte[] buffer = new byte[1];
|
||||||
int read = accessor.read(pos, buffer, 0, 1);
|
int read = accessor.read(buffer, 0, 1);
|
||||||
pos += read;
|
|
||||||
return read > 0 ? buffer[0] : -1;
|
return read > 0 ? buffer[0] : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,20 +129,24 @@ public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
||||||
public int skipBytes(int n) throws IOException {
|
public int skipBytes(int n) throws IOException {
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
|
|
||||||
int newPos = Math.max(pos, Math.min(accessor.size(), pos));
|
int last = accessor.tell();
|
||||||
int result = newPos - pos;
|
accessor.skip(n - 1);
|
||||||
pos = newPos;
|
if (accessor.read(ONE_BYTE_BUFFER, 0, 1) < 1) {
|
||||||
return result;
|
int position = accessor.size();
|
||||||
|
accessor.seek(position);
|
||||||
|
return position - last;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getFilePointer() throws IOException {
|
public long getFilePointer() throws IOException {
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
return pos;
|
return accessor.tell();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void seek(long pos) throws IOException {
|
public void seek(long pos) throws IOException {
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
this.pos = (int) pos;
|
accessor.seek((int) pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long length() throws IOException {
|
public long length() throws IOException {
|
||||||
|
@ -287,11 +286,10 @@ public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
byte[] buffer = { (byte) b };
|
byte[] buffer = { (byte) b };
|
||||||
accessor.write(pos, buffer, 0, 1);
|
accessor.write(buffer, 0, 1);
|
||||||
if (autoFlush) {
|
if (autoFlush) {
|
||||||
accessor.flush();
|
accessor.flush();
|
||||||
}
|
}
|
||||||
pos++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -306,11 +304,10 @@ public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
ensureOpened();
|
ensureOpened();
|
||||||
accessor.write(pos, b, off, len);
|
accessor.write(b, off, len);
|
||||||
if (autoFlush) {
|
if (autoFlush) {
|
||||||
accessor.flush();
|
accessor.flush();
|
||||||
}
|
}
|
||||||
pos += len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -566,7 +566,7 @@ int32_t teavm_file_flush(int64_t file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t teavm_file_seek(int64_t file, int32_t where, int32_t offset) {
|
int32_t teavm_file_seek(int64_t file, int32_t where, int32_t offset) {
|
||||||
return SetFilePointer((HANDLE) file, offset, 0, where);
|
return SetFilePointer((HANDLE) file, offset, 0, where) != INVALID_SET_FILE_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t teavm_file_tell(int64_t file) {
|
int32_t teavm_file_tell(int64_t file) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user