1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00
CC-Tweaked/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java
SquidDev 518eefbe10 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.
2018-09-26 10:00:17 +01:00

84 lines
2.5 KiB
Java

package dan200.computercraft.core.apis.handles;
import dan200.computercraft.api.lua.ILuaObject;
import dan200.computercraft.api.lua.LuaException;
import javax.annotation.Nonnull;
import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.SeekableByteChannel;
import static dan200.computercraft.core.apis.ArgumentHelper.optInt;
import static dan200.computercraft.core.apis.ArgumentHelper.optString;
public abstract class HandleGeneric implements ILuaObject
{
private Closeable m_closable;
private boolean m_open = true;
protected HandleGeneric( @Nonnull Closeable closable )
{
this.m_closable = closable;
}
protected void checkOpen() throws LuaException
{
if( !m_open ) throw new LuaException( "attempt to use a closed file" );
}
protected final void close()
{
try
{
m_closable.close();
m_open = false;
}
catch( IOException ignored )
{
}
m_closable = null;
}
/**
* Shared implementation for various file handle types
*
* @param channel The channel to seek in
* @param args The Lua arguments to process, like Lua's {@code file:seek}.
* @return The new position of the file, or null if some error occured.
* @throws LuaException If the arguments were invalid
* @see <a href="https://www.lua.org/manual/5.1/manual.html#pdf-file:seek">{@code file:seek} in the Lua manual.</a>
*/
protected static Object[] handleSeek( SeekableByteChannel channel, Object[] args ) throws LuaException
{
try
{
String whence = optString( args, 0, "cur" );
long offset = optInt( args, 1, 0 );
switch( whence )
{
case "set":
channel.position( offset );
break;
case "cur":
channel.position( channel.position() + offset );
break;
case "end":
channel.position( channel.size() + offset );
break;
default:
throw new LuaException( "bad argument #1 to 'seek' (invalid option '" + whence + "'" );
}
return new Object[] { channel.position() };
}
catch( IllegalArgumentException e )
{
return new Object[] { false, "Position is negative" };
}
catch( IOException e )
{
return null;
}
}
}