CC-Tweaked/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java

115 lines
3.3 KiB
Java

/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core.apis.handles;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.shared.util.IoUtil;
import javax.annotation.Nonnull;
import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.Channel;
import java.nio.channels.SeekableByteChannel;
import java.util.Optional;
public abstract class HandleGeneric
{
private Closeable closable;
private boolean open = true;
protected HandleGeneric( @Nonnull Closeable closable )
{
this.closable = closable;
}
protected void checkOpen() throws LuaException
{
if( !open ) throw new LuaException( "attempt to use a closed file" );
}
protected final void close()
{
open = false;
IoUtil.closeQuietly( closable );
closable = null;
}
/**
* Close this file, freeing any resources it uses.
*
* Once a file is closed it may no longer be read or written to.
*
* @throws LuaException If the file has already been closed.
*/
@LuaFunction( "close" )
public final void doClose() throws LuaException
{
checkOpen();
close();
}
/**
* Shared implementation for various file handle types.
*
* @param channel The channel to seek in
* @param whence The seeking mode.
* @param offset The offset to seek to.
* @return The new position of the file, or null if some error occurred.
* @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, Optional<String> whence, Optional<Long> offset ) throws LuaException
{
long actualOffset = offset.orElse( 0L );
try
{
switch( whence.orElse( "cur" ) )
{
case "set":
channel.position( actualOffset );
break;
case "cur":
channel.position( channel.position() + actualOffset );
break;
case "end":
channel.position( channel.size() + actualOffset );
break;
default:
throw new LuaException( "bad argument #1 to 'seek' (invalid option '" + whence + "'" );
}
return new Object[] { channel.position() };
}
catch( IllegalArgumentException e )
{
return new Object[] { null, "Position is negative" };
}
catch( IOException e )
{
return null;
}
}
protected static SeekableByteChannel asSeekable( Channel channel )
{
if( !(channel instanceof SeekableByteChannel) ) return null;
SeekableByteChannel seekable = (SeekableByteChannel) channel;
try
{
seekable.position( seekable.position() );
return seekable;
}
catch( IOException | UnsupportedOperationException e )
{
return null;
}
}
}