/* * 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 {@code file:seek} in the Lua manual. */ protected static Object[] handleSeek( SeekableByteChannel channel, Optional whence, Optional 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; } } }