mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public class CVirtualFile implements VirtualFile {
|
|||
if (file == 0) {
|
||||
return null;
|
||||
}
|
||||
return new CVirtualFileAccessor(file, append ? -1 : 0);
|
||||
return new CVirtualFileAccessor(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,38 +20,50 @@ import org.teavm.classlib.fs.VirtualFileAccessor;
|
|||
|
||||
public class CVirtualFileAccessor implements VirtualFileAccessor {
|
||||
private long file;
|
||||
private int position;
|
||||
|
||||
public CVirtualFileAccessor(long file, int position) {
|
||||
public CVirtualFileAccessor(long file) {
|
||||
this.file = file;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(int pos, byte[] buffer, int offset, int limit) throws IOException {
|
||||
ensurePosition(pos);
|
||||
int bytesRead = CFileSystem.read(file, buffer, offset, limit);
|
||||
position += bytesRead;
|
||||
return bytesRead;
|
||||
public int read(byte[] buffer, int offset, int limit) throws IOException {
|
||||
return CFileSystem.read(file, buffer, offset, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int pos, byte[] buffer, int offset, int limit) throws IOException {
|
||||
ensurePosition(pos);
|
||||
public void write(byte[] buffer, int offset, int limit) throws IOException {
|
||||
int bytesWritten = CFileSystem.write(file, buffer, offset, limit);
|
||||
if (bytesWritten < limit) {
|
||||
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
|
||||
public int size() throws IOException {
|
||||
int current = CFileSystem.tell(file);
|
||||
if (!CFileSystem.seek(file, 2, 0)) {
|
||||
throw new IOException();
|
||||
}
|
||||
position = CFileSystem.tell(file);
|
||||
return position;
|
||||
int result = CFileSystem.tell(file);
|
||||
if (!CFileSystem.seek(file, 0, current)) {
|
||||
throw new IOException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -59,11 +71,13 @@ public class CVirtualFileAccessor implements VirtualFileAccessor {
|
|||
if (!CFileSystem.seek(file, 2, 0)) {
|
||||
throw new IOException();
|
||||
}
|
||||
position = CFileSystem.tell(file);
|
||||
int position = CFileSystem.tell(file);
|
||||
if (position < size) {
|
||||
byte[] zeros = new byte[4096];
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
private int pos;
|
||||
|
||||
{
|
||||
if (append) {
|
||||
pos = size;
|
||||
}
|
||||
}
|
||||
|
||||
@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));
|
||||
if (limit > 0) {
|
||||
System.arraycopy(data, pos, buffer, offset, limit);
|
||||
pos += limit;
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int pos, byte[] buffer, int offset, int limit) {
|
||||
public void write(byte[] buffer, int offset, int limit) {
|
||||
expandData(pos + limit);
|
||||
System.arraycopy(buffer, offset, data, pos, limit);
|
||||
size = pos + limit;
|
||||
pos += limit;
|
||||
if (pos > size) {
|
||||
size = pos;
|
||||
}
|
||||
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
|
||||
public int size() {
|
||||
return size;
|
||||
|
|
|
@ -23,9 +23,8 @@ import org.teavm.classlib.fs.VirtualFile;
|
|||
import org.teavm.classlib.fs.VirtualFileAccessor;
|
||||
|
||||
public class TFileInputStream extends InputStream {
|
||||
private static final byte[] ONE_BYTE_BUFFER = new byte[1];
|
||||
private VirtualFileAccessor accessor;
|
||||
private int pos;
|
||||
private boolean eof;
|
||||
|
||||
public TFileInputStream(TFile file) throws FileNotFoundException {
|
||||
VirtualFile virtualFile = file.findVirtualFile();
|
||||
|
@ -52,16 +51,9 @@ public class TFileInputStream extends InputStream {
|
|||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (eof) {
|
||||
return -1;
|
||||
}
|
||||
ensureOpened();
|
||||
int result = accessor.read(pos, b, off, len);
|
||||
pos += result;
|
||||
if (pos == accessor.size()) {
|
||||
eof = true;
|
||||
}
|
||||
return result;
|
||||
int result = accessor.read(b, off, len);
|
||||
return result > 0 ? result : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,25 +62,20 @@ public class TFileInputStream extends InputStream {
|
|||
throw new IOException("Value must be positive: " + n);
|
||||
}
|
||||
ensureOpened();
|
||||
if (eof) {
|
||||
return 0;
|
||||
int last = accessor.tell();
|
||||
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));
|
||||
int result = newPos - pos;
|
||||
pos = newPos;
|
||||
if (result == 0) {
|
||||
eof = true;
|
||||
}
|
||||
return result;
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
ensureOpened();
|
||||
if (eof) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(0, accessor.size() - pos);
|
||||
return Math.max(0, accessor.size() - accessor.tell());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,17 +89,9 @@ public class TFileInputStream extends InputStream {
|
|||
@Override
|
||||
public int read() throws IOException {
|
||||
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;
|
||||
byte[] buffer = ONE_BYTE_BUFFER;
|
||||
int read = accessor.read(buffer, 0, 1);
|
||||
return read != 0 ? buffer[0] : -1;
|
||||
}
|
||||
|
||||
private void ensureOpened() throws IOException {
|
||||
|
|
|
@ -24,8 +24,8 @@ import org.teavm.classlib.fs.VirtualFile;
|
|||
import org.teavm.classlib.fs.VirtualFileAccessor;
|
||||
|
||||
public class TFileOutputStream extends OutputStream {
|
||||
private static byte[] ONE_BYTE_BUFER = new byte[1];
|
||||
private VirtualFileAccessor accessor;
|
||||
private int pos;
|
||||
|
||||
public TFileOutputStream(TFile file) throws FileNotFoundException {
|
||||
this(file, false);
|
||||
|
@ -57,10 +57,6 @@ public class TFileOutputStream extends OutputStream {
|
|||
if (accessor == null) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
if (append) {
|
||||
pos = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,9 +65,8 @@ public class TFileOutputStream extends OutputStream {
|
|||
if (off < 0 || len < 0 || off > b.length - len) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
ensurePos();
|
||||
accessor.write(pos, b, off, len);
|
||||
pos += len;
|
||||
ensureOpened();
|
||||
accessor.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -90,10 +85,10 @@ public class TFileOutputStream extends OutputStream {
|
|||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
ensurePos();
|
||||
byte[] buffer = { (byte) b };
|
||||
accessor.write(pos, buffer, 0, 1);
|
||||
pos++;
|
||||
ensureOpened();
|
||||
byte[] buffer = ONE_BYTE_BUFER;
|
||||
buffer[0] = (byte) b;
|
||||
accessor.write(buffer, 0, 1);
|
||||
}
|
||||
|
||||
private void ensureOpened() throws IOException {
|
||||
|
@ -101,11 +96,4 @@ public class TFileOutputStream extends OutputStream {
|
|||
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;
|
||||
|
||||
public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
||||
private static final byte[] ONE_BYTE_BUFFER = new byte[1];
|
||||
private boolean readOnly;
|
||||
private boolean autoFlush;
|
||||
private VirtualFileAccessor accessor;
|
||||
private int pos;
|
||||
private byte[] buff;
|
||||
|
||||
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) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
if (pos >= accessor.size()) {
|
||||
return -1;
|
||||
}
|
||||
ensureOpened();
|
||||
int result = accessor.read(pos, b, off, len);
|
||||
pos += result;
|
||||
return result;
|
||||
int result = accessor.read(b, off, len);
|
||||
return result > 0 ? result : -1;
|
||||
}
|
||||
|
||||
public int read(byte[] b) throws IOException {
|
||||
|
@ -92,8 +88,7 @@ public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
|||
public int read() throws IOException {
|
||||
ensureOpened();
|
||||
byte[] buffer = new byte[1];
|
||||
int read = accessor.read(pos, buffer, 0, 1);
|
||||
pos += read;
|
||||
int read = accessor.read(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 {
|
||||
ensureOpened();
|
||||
|
||||
int newPos = Math.max(pos, Math.min(accessor.size(), pos));
|
||||
int result = newPos - pos;
|
||||
pos = newPos;
|
||||
return result;
|
||||
int last = accessor.tell();
|
||||
accessor.skip(n - 1);
|
||||
if (accessor.read(ONE_BYTE_BUFFER, 0, 1) < 1) {
|
||||
int position = accessor.size();
|
||||
accessor.seek(position);
|
||||
return position - last;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public long getFilePointer() throws IOException {
|
||||
ensureOpened();
|
||||
return pos;
|
||||
return accessor.tell();
|
||||
}
|
||||
|
||||
public void seek(long pos) throws IOException {
|
||||
ensureOpened();
|
||||
this.pos = (int) pos;
|
||||
accessor.seek((int) pos);
|
||||
}
|
||||
|
||||
public long length() throws IOException {
|
||||
|
@ -287,11 +286,10 @@ public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
|||
public void write(int b) throws IOException {
|
||||
ensureOpened();
|
||||
byte[] buffer = { (byte) b };
|
||||
accessor.write(pos, buffer, 0, 1);
|
||||
accessor.write(buffer, 0, 1);
|
||||
if (autoFlush) {
|
||||
accessor.flush();
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -306,11 +304,10 @@ public class TRandomAccessFile implements DataInput, DataOutput, Closeable {
|
|||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
ensureOpened();
|
||||
accessor.write(pos, b, off, len);
|
||||
accessor.write(b, off, len);
|
||||
if (autoFlush) {
|
||||
accessor.flush();
|
||||
}
|
||||
pos += len;
|
||||
}
|
||||
|
||||
@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) {
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user