-
Notifications
You must be signed in to change notification settings - Fork 196
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite file systems to use ByteChannels
This replaces the existing IMount openFor* method with openChannelFor* ones, which return an appropriate byte channel instead. As channels are not correctly closed when GCed, we introduce a FileSystemWrapper. We store a weak reference to this, and when it is GCed or the file closed, we will remove it from our "open file" set and ensure any underlying buffers are closed. While this change may seem a little odd, it does introduce some benefits: - We can replace JarMount with a more general FileSystemMount. This does assume a read-only file system, but could technically be used for other sources. - Add support for seekable (binary) handles. We can now look for instances of SeekableByteChannel and dynamically add it. This works for all binary filesystem and HTTP streams. - Rewrite the io library to more accurately emulate PUC Lua's implementation. We do not correctly implement some elements (most noticably "*n", but it's a definite improvement.
- Loading branch information
Showing
23 changed files
with
1,355 additions
and
924 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
src/main/java/dan200/computercraft/core/apis/handles/ArrayByteChannel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package dan200.computercraft.core.apis.handles; | ||
|
||
import com.google.common.base.Preconditions; | ||
|
||
import java.io.IOException; | ||
import java.nio.ByteBuffer; | ||
import java.nio.channels.ClosedChannelException; | ||
import java.nio.channels.NonWritableChannelException; | ||
import java.nio.channels.SeekableByteChannel; | ||
|
||
/** | ||
* A seekable, readable byte channel which is backed by a simple byte array. | ||
*/ | ||
public class ArrayByteChannel implements SeekableByteChannel | ||
{ | ||
private boolean closed = false; | ||
private int position = 0; | ||
|
||
private final byte[] backing; | ||
|
||
public ArrayByteChannel( byte[] backing ) | ||
{ | ||
this.backing = backing; | ||
} | ||
|
||
@Override | ||
public int read( ByteBuffer destination ) throws IOException | ||
{ | ||
if( closed ) throw new ClosedChannelException(); | ||
Preconditions.checkNotNull( destination, "destination" ); | ||
|
||
if( position >= backing.length ) return -1; | ||
|
||
int remaining = Math.min( backing.length - position, destination.remaining() ); | ||
destination.put( backing, position, remaining ); | ||
position += remaining; | ||
return remaining; | ||
} | ||
|
||
@Override | ||
public int write( ByteBuffer src ) throws IOException | ||
{ | ||
if( closed ) throw new ClosedChannelException(); | ||
throw new NonWritableChannelException(); | ||
} | ||
|
||
@Override | ||
public long position() throws IOException | ||
{ | ||
if( closed ) throw new ClosedChannelException(); | ||
return 0; | ||
} | ||
|
||
@Override | ||
public SeekableByteChannel position( long newPosition ) throws IOException | ||
{ | ||
if( closed ) throw new ClosedChannelException(); | ||
if( newPosition < 0 || newPosition > Integer.MAX_VALUE ) | ||
{ | ||
throw new IllegalArgumentException( "Position out of bounds" ); | ||
} | ||
position = (int) newPosition; | ||
return this; | ||
} | ||
|
||
@Override | ||
public long size() throws IOException | ||
{ | ||
if( closed ) throw new ClosedChannelException(); | ||
return backing.length; | ||
} | ||
|
||
@Override | ||
public SeekableByteChannel truncate( long size ) throws IOException | ||
{ | ||
if( closed ) throw new ClosedChannelException(); | ||
throw new NonWritableChannelException(); | ||
} | ||
|
||
@Override | ||
public boolean isOpen() | ||
{ | ||
return !closed; | ||
} | ||
|
||
@Override | ||
public void close() | ||
{ | ||
closed = true; | ||
} | ||
} |
Oops, something went wrong.