mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-19 05:32:55 +00:00
Make Mount.openForRead always return a SeekableByteChannel
I want to make some further changes to Mount here, but this helps simplify BinaryReadableHandle a little.
This commit is contained in:
parent
c96172e78d
commit
fc5f296eeb
@ -8,7 +8,7 @@ package dan200.computercraft.api.filesystem;
|
|||||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -60,15 +60,13 @@ public interface Mount {
|
|||||||
long getSize(String path) throws IOException;
|
long getSize(String path) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
|
* Opens a file with a given path, and returns a {@link SeekableByteChannel} representing its contents.
|
||||||
*
|
*
|
||||||
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
|
||||||
* @return A channel representing the contents of the file. If the channel implements
|
* @return A channel representing the contents of the file.
|
||||||
* {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary positions when using binary
|
|
||||||
* mode.
|
|
||||||
* @throws IOException If the file does not exist, or could not be opened.
|
* @throws IOException If the file does not exist, or could not be opened.
|
||||||
*/
|
*/
|
||||||
ReadableByteChannel openForRead(String path) throws IOException;
|
SeekableByteChannel openForRead(String path) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get attributes about the given file.
|
* Get attributes about the given file.
|
||||||
|
@ -8,13 +8,11 @@ package dan200.computercraft.core.apis.handles;
|
|||||||
import dan200.computercraft.api.lua.LuaException;
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
import dan200.computercraft.api.lua.LuaFunction;
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
import dan200.computercraft.core.filesystem.TrackingCloseable;
|
import dan200.computercraft.core.filesystem.TrackingCloseable;
|
||||||
import dan200.computercraft.core.util.Nullability;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
|
||||||
import java.nio.channels.SeekableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -29,22 +27,19 @@ import java.util.Optional;
|
|||||||
public class BinaryReadableHandle extends HandleGeneric {
|
public class BinaryReadableHandle extends HandleGeneric {
|
||||||
private static final int BUFFER_SIZE = 8192;
|
private static final int BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
private final ReadableByteChannel reader;
|
private final SeekableByteChannel channel;
|
||||||
final @Nullable SeekableByteChannel seekable;
|
|
||||||
private final ByteBuffer single = ByteBuffer.allocate(1);
|
private final ByteBuffer single = ByteBuffer.allocate(1);
|
||||||
|
|
||||||
BinaryReadableHandle(ReadableByteChannel reader, @Nullable SeekableByteChannel seekable, TrackingCloseable closeable) {
|
BinaryReadableHandle(SeekableByteChannel channel, TrackingCloseable closeable) {
|
||||||
super(closeable);
|
super(closeable);
|
||||||
this.reader = reader;
|
this.channel = channel;
|
||||||
this.seekable = seekable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BinaryReadableHandle of(ReadableByteChannel channel, TrackingCloseable closeable) {
|
public static BinaryReadableHandle of(SeekableByteChannel channel, TrackingCloseable closeable) {
|
||||||
var seekable = asSeekable(channel);
|
return new BinaryReadableHandle(channel, closeable);
|
||||||
return seekable == null ? new BinaryReadableHandle(channel, null, closeable) : new Seekable(seekable, closeable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BinaryReadableHandle of(ReadableByteChannel channel) {
|
public static BinaryReadableHandle of(SeekableByteChannel channel) {
|
||||||
return of(channel, new TrackingCloseable.Impl(channel));
|
return of(channel, new TrackingCloseable.Impl(channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,21 +64,19 @@ public class BinaryReadableHandle extends HandleGeneric {
|
|||||||
if (countArg.isPresent()) {
|
if (countArg.isPresent()) {
|
||||||
int count = countArg.get();
|
int count = countArg.get();
|
||||||
if (count < 0) throw new LuaException("Cannot read a negative number of bytes");
|
if (count < 0) throw new LuaException("Cannot read a negative number of bytes");
|
||||||
if (count == 0 && seekable != null) {
|
if (count == 0) return channel.position() >= channel.size() ? null : new Object[]{ "" };
|
||||||
return seekable.position() >= seekable.size() ? null : new Object[]{ "" };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count <= BUFFER_SIZE) {
|
if (count <= BUFFER_SIZE) {
|
||||||
var buffer = ByteBuffer.allocate(count);
|
var buffer = ByteBuffer.allocate(count);
|
||||||
|
|
||||||
var read = reader.read(buffer);
|
var read = channel.read(buffer);
|
||||||
if (read < 0) return null;
|
if (read < 0) return null;
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
return new Object[]{ buffer };
|
return new Object[]{ buffer };
|
||||||
} else {
|
} else {
|
||||||
// Read the initial set of characters, failing if none are read.
|
// Read the initial set of characters, failing if none are read.
|
||||||
var buffer = ByteBuffer.allocate(BUFFER_SIZE);
|
var buffer = ByteBuffer.allocate(BUFFER_SIZE);
|
||||||
var read = reader.read(buffer);
|
var read = channel.read(buffer);
|
||||||
if (read < 0) return null;
|
if (read < 0) return null;
|
||||||
|
|
||||||
// If we failed to read "enough" here, let's just abort
|
// If we failed to read "enough" here, let's just abort
|
||||||
@ -99,7 +92,7 @@ public class BinaryReadableHandle extends HandleGeneric {
|
|||||||
parts.add(buffer);
|
parts.add(buffer);
|
||||||
while (read >= BUFFER_SIZE && totalRead < count) {
|
while (read >= BUFFER_SIZE && totalRead < count) {
|
||||||
buffer = ByteBuffer.allocate(Math.min(BUFFER_SIZE, count - totalRead));
|
buffer = ByteBuffer.allocate(Math.min(BUFFER_SIZE, count - totalRead));
|
||||||
read = reader.read(buffer);
|
read = channel.read(buffer);
|
||||||
if (read < 0) break;
|
if (read < 0) break;
|
||||||
|
|
||||||
totalRead += read;
|
totalRead += read;
|
||||||
@ -117,7 +110,7 @@ public class BinaryReadableHandle extends HandleGeneric {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
single.clear();
|
single.clear();
|
||||||
var b = reader.read(single);
|
var b = channel.read(single);
|
||||||
return b == -1 ? null : new Object[]{ single.get(0) & 0xFF };
|
return b == -1 ? null : new Object[]{ single.get(0) & 0xFF };
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -139,14 +132,14 @@ public class BinaryReadableHandle extends HandleGeneric {
|
|||||||
checkOpen();
|
checkOpen();
|
||||||
try {
|
try {
|
||||||
var expected = 32;
|
var expected = 32;
|
||||||
if (seekable != null) expected = Math.max(expected, (int) (seekable.size() - seekable.position()));
|
expected = Math.max(expected, (int) (channel.size() - channel.position()));
|
||||||
var stream = new ByteArrayOutputStream(expected);
|
var stream = new ByteArrayOutputStream(expected);
|
||||||
|
|
||||||
var buf = ByteBuffer.allocate(8192);
|
var buf = ByteBuffer.allocate(8192);
|
||||||
var readAnything = false;
|
var readAnything = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
buf.clear();
|
buf.clear();
|
||||||
var r = reader.read(buf);
|
var r = channel.read(buf);
|
||||||
if (r == -1) break;
|
if (r == -1) break;
|
||||||
|
|
||||||
readAnything = true;
|
readAnything = true;
|
||||||
@ -179,7 +172,7 @@ public class BinaryReadableHandle extends HandleGeneric {
|
|||||||
boolean readAnything = false, readRc = false;
|
boolean readAnything = false, readRc = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
single.clear();
|
single.clear();
|
||||||
var read = reader.read(single);
|
var read = channel.read(single);
|
||||||
if (read <= 0) {
|
if (read <= 0) {
|
||||||
// Nothing else to read, and we saw no \n. Return the array. If we saw a \r, then add it
|
// Nothing else to read, and we saw no \n. Return the array. If we saw a \r, then add it
|
||||||
// back.
|
// back.
|
||||||
@ -211,11 +204,6 @@ public class BinaryReadableHandle extends HandleGeneric {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Seekable extends BinaryReadableHandle {
|
|
||||||
Seekable(SeekableByteChannel seekable, TrackingCloseable closeable) {
|
|
||||||
super(seekable, seekable, closeable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seek to a new position within the file, changing where bytes are written to. The new position is an offset
|
* Seek to a new position within the file, changing where bytes are written to. The new position is an offset
|
||||||
* given by {@code offset}, relative to a start position determined by {@code whence}:
|
* given by {@code offset}, relative to a start position determined by {@code whence}:
|
||||||
@ -239,7 +227,6 @@ public class BinaryReadableHandle extends HandleGeneric {
|
|||||||
@LuaFunction
|
@LuaFunction
|
||||||
public final Object[] seek(Optional<String> whence, Optional<Long> offset) throws LuaException {
|
public final Object[] seek(Optional<String> whence, Optional<Long> offset) throws LuaException {
|
||||||
checkOpen();
|
checkOpen();
|
||||||
return handleSeek(Nullability.assertNonNull(seekable), whence, offset);
|
return handleSeek(channel, whence, offset);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import dan200.computercraft.core.apis.handles.ArrayByteChannel;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -110,7 +110,7 @@ public abstract class ArchiveMount<T extends ArchiveMount.FileEntry<T>> implemen
|
|||||||
protected abstract long getSize(T file) throws IOException;
|
protected abstract long getSize(T file) throws IOException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReadableByteChannel openForRead(String path) throws IOException {
|
public SeekableByteChannel openForRead(String path) throws IOException {
|
||||||
var file = get(path);
|
var file = get(path);
|
||||||
if (file == null || file.isDirectory()) throw new FileOperationException(path, NO_SUCH_FILE);
|
if (file == null || file.isDirectory()) throw new FileOperationException(path, NO_SUCH_FILE);
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ public class FileMount implements WritableMount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReadableByteChannel openForRead(String path) throws IOException {
|
public SeekableByteChannel openForRead(String path) throws IOException {
|
||||||
if (created()) {
|
if (created()) {
|
||||||
var file = getRealPath(path);
|
var file = getRealPath(path);
|
||||||
if (file.exists() && !file.isDirectory()) return FileChannel.open(file.toPath(), READ_OPTIONS);
|
if (file.exists() && !file.isDirectory()) return FileChannel.open(file.toPath(), READ_OPTIONS);
|
||||||
|
@ -18,7 +18,7 @@ import java.lang.ref.Reference;
|
|||||||
import java.lang.ref.ReferenceQueue;
|
import java.lang.ref.ReferenceQueue;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.nio.channels.Channel;
|
import java.nio.channels.Channel;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.nio.file.AccessDeniedException;
|
import java.nio.file.AccessDeniedException;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
@ -346,7 +346,7 @@ public class FileSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized <T extends Closeable> FileSystemWrapper<T> openForRead(String path, Function<ReadableByteChannel, T> open) throws FileSystemException {
|
public synchronized <T extends Closeable> FileSystemWrapper<T> openForRead(String path, Function<SeekableByteChannel, T> open) throws FileSystemException {
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
path = sanitizePath(path);
|
path = sanitizePath(path);
|
||||||
|
@ -11,7 +11,7 @@ import dan200.computercraft.api.filesystem.WritableMount;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.nio.file.AccessDeniedException;
|
import java.nio.file.AccessDeniedException;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
@ -120,7 +120,7 @@ class MountWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadableByteChannel openForRead(String path) throws FileSystemException {
|
public SeekableByteChannel openForRead(String path) throws FileSystemException {
|
||||||
path = toLocal(path);
|
path = toLocal(path);
|
||||||
try {
|
try {
|
||||||
if (mount.exists(path) && !mount.isDirectory(path)) {
|
if (mount.exists(path) && !mount.isDirectory(path)) {
|
||||||
|
@ -8,7 +8,7 @@ package dan200.computercraft.core.filesystem;
|
|||||||
import dan200.computercraft.api.filesystem.Mount;
|
import dan200.computercraft.api.filesystem.Mount;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ public class SubMount implements Mount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReadableByteChannel openForRead(String path) throws IOException {
|
public SeekableByteChannel openForRead(String path) throws IOException {
|
||||||
return parent.openForRead(getFullPath(path));
|
return parent.openForRead(getFullPath(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -111,7 +111,7 @@ public class MemoryMount implements WritableMount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReadableByteChannel openForRead(String path) throws FileOperationException {
|
public SeekableByteChannel openForRead(String path) throws FileOperationException {
|
||||||
var file = files.get(path);
|
var file = files.get(path);
|
||||||
if (file == null) throw new FileOperationException(path, "File not found");
|
if (file == null) throw new FileOperationException(path, "File not found");
|
||||||
return new ArrayByteChannel(file);
|
return new ArrayByteChannel(file);
|
||||||
|
Loading…
Reference in New Issue
Block a user