2018-12-31 09:41:58 +00:00
|
|
|
/*
|
|
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
2020-01-01 00:09:18 +00:00
|
|
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
2018-12-31 09:41:58 +00:00
|
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
|
|
*/
|
2017-05-12 21:49:44 +00:00
|
|
|
package dan200.computercraft.core.apis.handles;
|
|
|
|
|
|
|
|
import dan200.computercraft.api.lua.LuaException;
|
Replace getMethodNames/callMethod with annotations (#447)
When creating a peripheral or custom Lua object, one must implement two
methods:
- getMethodNames(): String[] - Returns the name of the methods
- callMethod(int, ...): Object[] - Invokes the method using an index in
the above array.
This has a couple of problems:
- It's somewhat unwieldy to use - you need to keep track of array
indices, which leads to ugly code.
- Functions which yield (for instance, those which run on the main
thread) are blocking. This means we need to spawn new threads for
each CC-side yield.
We replace this system with a few changes:
- @LuaFunction annotation: One may annotate a public instance method
with this annotation. This then exposes a peripheral/lua object
method.
Furthermore, this method can accept and return a variety of types,
which often makes functions cleaner (e.g. can return an int rather
than an Object[], and specify and int argument rather than
Object[]).
- MethodResult: Instead of returning an Object[] and having blocking
yields, functions return a MethodResult. This either contains an
immediate return, or an instruction to yield with some continuation
to resume with.
MethodResult is then interpreted by the Lua runtime (i.e. Cobalt),
rather than our weird bodgey hacks before. This means we no longer
spawn new threads when yielding within CC.
- Methods accept IArguments instead of a raw Object array. This has a
few benefits:
- Consistent argument handling - people no longer need to use
ArgumentHelper (as it doesn't exist!), or even be aware of its
existence - you're rather forced into using it.
- More efficient code in some cases. We provide a Cobalt-specific
implementation of IArguments, which avoids the boxing/unboxing when
handling numbers and binary strings.
2020-05-15 12:21:16 +00:00
|
|
|
import dan200.computercraft.api.lua.LuaFunction;
|
2019-01-11 11:33:05 +00:00
|
|
|
import dan200.computercraft.shared.util.IoUtil;
|
2017-05-12 21:49:44 +00:00
|
|
|
|
2018-09-21 15:00:26 +00:00
|
|
|
import javax.annotation.Nonnull;
|
2017-05-12 21:49:44 +00:00
|
|
|
import java.io.Closeable;
|
|
|
|
import java.io.IOException;
|
2018-10-29 15:59:43 +00:00
|
|
|
import java.nio.channels.Channel;
|
2018-09-21 15:00:26 +00:00
|
|
|
import java.nio.channels.SeekableByteChannel;
|
2020-07-09 20:59:19 +00:00
|
|
|
import java.util.Optional;
|
2018-09-21 15:00:26 +00:00
|
|
|
|
Replace getMethodNames/callMethod with annotations (#447)
When creating a peripheral or custom Lua object, one must implement two
methods:
- getMethodNames(): String[] - Returns the name of the methods
- callMethod(int, ...): Object[] - Invokes the method using an index in
the above array.
This has a couple of problems:
- It's somewhat unwieldy to use - you need to keep track of array
indices, which leads to ugly code.
- Functions which yield (for instance, those which run on the main
thread) are blocking. This means we need to spawn new threads for
each CC-side yield.
We replace this system with a few changes:
- @LuaFunction annotation: One may annotate a public instance method
with this annotation. This then exposes a peripheral/lua object
method.
Furthermore, this method can accept and return a variety of types,
which often makes functions cleaner (e.g. can return an int rather
than an Object[], and specify and int argument rather than
Object[]).
- MethodResult: Instead of returning an Object[] and having blocking
yields, functions return a MethodResult. This either contains an
immediate return, or an instruction to yield with some continuation
to resume with.
MethodResult is then interpreted by the Lua runtime (i.e. Cobalt),
rather than our weird bodgey hacks before. This means we no longer
spawn new threads when yielding within CC.
- Methods accept IArguments instead of a raw Object array. This has a
few benefits:
- Consistent argument handling - people no longer need to use
ArgumentHelper (as it doesn't exist!), or even be aware of its
existence - you're rather forced into using it.
- More efficient code in some cases. We provide a Cobalt-specific
implementation of IArguments, which avoids the boxing/unboxing when
handling numbers and binary strings.
2020-05-15 12:21:16 +00:00
|
|
|
public abstract class HandleGeneric
|
2017-05-12 21:49:44 +00:00
|
|
|
{
|
Replace getMethodNames/callMethod with annotations (#447)
When creating a peripheral or custom Lua object, one must implement two
methods:
- getMethodNames(): String[] - Returns the name of the methods
- callMethod(int, ...): Object[] - Invokes the method using an index in
the above array.
This has a couple of problems:
- It's somewhat unwieldy to use - you need to keep track of array
indices, which leads to ugly code.
- Functions which yield (for instance, those which run on the main
thread) are blocking. This means we need to spawn new threads for
each CC-side yield.
We replace this system with a few changes:
- @LuaFunction annotation: One may annotate a public instance method
with this annotation. This then exposes a peripheral/lua object
method.
Furthermore, this method can accept and return a variety of types,
which often makes functions cleaner (e.g. can return an int rather
than an Object[], and specify and int argument rather than
Object[]).
- MethodResult: Instead of returning an Object[] and having blocking
yields, functions return a MethodResult. This either contains an
immediate return, or an instruction to yield with some continuation
to resume with.
MethodResult is then interpreted by the Lua runtime (i.e. Cobalt),
rather than our weird bodgey hacks before. This means we no longer
spawn new threads when yielding within CC.
- Methods accept IArguments instead of a raw Object array. This has a
few benefits:
- Consistent argument handling - people no longer need to use
ArgumentHelper (as it doesn't exist!), or even be aware of its
existence - you're rather forced into using it.
- More efficient code in some cases. We provide a Cobalt-specific
implementation of IArguments, which avoids the boxing/unboxing when
handling numbers and binary strings.
2020-05-15 12:21:16 +00:00
|
|
|
private Closeable closable;
|
|
|
|
private boolean open = true;
|
2017-05-12 21:49:44 +00:00
|
|
|
|
2018-09-21 15:00:26 +00:00
|
|
|
protected HandleGeneric( @Nonnull Closeable closable )
|
2017-05-12 21:49:44 +00:00
|
|
|
{
|
Replace getMethodNames/callMethod with annotations (#447)
When creating a peripheral or custom Lua object, one must implement two
methods:
- getMethodNames(): String[] - Returns the name of the methods
- callMethod(int, ...): Object[] - Invokes the method using an index in
the above array.
This has a couple of problems:
- It's somewhat unwieldy to use - you need to keep track of array
indices, which leads to ugly code.
- Functions which yield (for instance, those which run on the main
thread) are blocking. This means we need to spawn new threads for
each CC-side yield.
We replace this system with a few changes:
- @LuaFunction annotation: One may annotate a public instance method
with this annotation. This then exposes a peripheral/lua object
method.
Furthermore, this method can accept and return a variety of types,
which often makes functions cleaner (e.g. can return an int rather
than an Object[], and specify and int argument rather than
Object[]).
- MethodResult: Instead of returning an Object[] and having blocking
yields, functions return a MethodResult. This either contains an
immediate return, or an instruction to yield with some continuation
to resume with.
MethodResult is then interpreted by the Lua runtime (i.e. Cobalt),
rather than our weird bodgey hacks before. This means we no longer
spawn new threads when yielding within CC.
- Methods accept IArguments instead of a raw Object array. This has a
few benefits:
- Consistent argument handling - people no longer need to use
ArgumentHelper (as it doesn't exist!), or even be aware of its
existence - you're rather forced into using it.
- More efficient code in some cases. We provide a Cobalt-specific
implementation of IArguments, which avoids the boxing/unboxing when
handling numbers and binary strings.
2020-05-15 12:21:16 +00:00
|
|
|
this.closable = closable;
|
2017-05-12 21:49:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void checkOpen() throws LuaException
|
|
|
|
{
|
Replace getMethodNames/callMethod with annotations (#447)
When creating a peripheral or custom Lua object, one must implement two
methods:
- getMethodNames(): String[] - Returns the name of the methods
- callMethod(int, ...): Object[] - Invokes the method using an index in
the above array.
This has a couple of problems:
- It's somewhat unwieldy to use - you need to keep track of array
indices, which leads to ugly code.
- Functions which yield (for instance, those which run on the main
thread) are blocking. This means we need to spawn new threads for
each CC-side yield.
We replace this system with a few changes:
- @LuaFunction annotation: One may annotate a public instance method
with this annotation. This then exposes a peripheral/lua object
method.
Furthermore, this method can accept and return a variety of types,
which often makes functions cleaner (e.g. can return an int rather
than an Object[], and specify and int argument rather than
Object[]).
- MethodResult: Instead of returning an Object[] and having blocking
yields, functions return a MethodResult. This either contains an
immediate return, or an instruction to yield with some continuation
to resume with.
MethodResult is then interpreted by the Lua runtime (i.e. Cobalt),
rather than our weird bodgey hacks before. This means we no longer
spawn new threads when yielding within CC.
- Methods accept IArguments instead of a raw Object array. This has a
few benefits:
- Consistent argument handling - people no longer need to use
ArgumentHelper (as it doesn't exist!), or even be aware of its
existence - you're rather forced into using it.
- More efficient code in some cases. We provide a Cobalt-specific
implementation of IArguments, which avoids the boxing/unboxing when
handling numbers and binary strings.
2020-05-15 12:21:16 +00:00
|
|
|
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
2017-05-12 21:49:44 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 15:00:26 +00:00
|
|
|
protected final void close()
|
2017-05-12 21:49:44 +00:00
|
|
|
{
|
Replace getMethodNames/callMethod with annotations (#447)
When creating a peripheral or custom Lua object, one must implement two
methods:
- getMethodNames(): String[] - Returns the name of the methods
- callMethod(int, ...): Object[] - Invokes the method using an index in
the above array.
This has a couple of problems:
- It's somewhat unwieldy to use - you need to keep track of array
indices, which leads to ugly code.
- Functions which yield (for instance, those which run on the main
thread) are blocking. This means we need to spawn new threads for
each CC-side yield.
We replace this system with a few changes:
- @LuaFunction annotation: One may annotate a public instance method
with this annotation. This then exposes a peripheral/lua object
method.
Furthermore, this method can accept and return a variety of types,
which often makes functions cleaner (e.g. can return an int rather
than an Object[], and specify and int argument rather than
Object[]).
- MethodResult: Instead of returning an Object[] and having blocking
yields, functions return a MethodResult. This either contains an
immediate return, or an instruction to yield with some continuation
to resume with.
MethodResult is then interpreted by the Lua runtime (i.e. Cobalt),
rather than our weird bodgey hacks before. This means we no longer
spawn new threads when yielding within CC.
- Methods accept IArguments instead of a raw Object array. This has a
few benefits:
- Consistent argument handling - people no longer need to use
ArgumentHelper (as it doesn't exist!), or even be aware of its
existence - you're rather forced into using it.
- More efficient code in some cases. We provide a Cobalt-specific
implementation of IArguments, which avoids the boxing/unboxing when
handling numbers and binary strings.
2020-05-15 12:21:16 +00:00
|
|
|
open = false;
|
2019-06-04 20:34:19 +00:00
|
|
|
|
2020-06-16 08:24:14 +00:00
|
|
|
IoUtil.closeQuietly( closable );
|
|
|
|
closable = null;
|
2018-09-21 15:00:26 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 20:59:19 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
Replace getMethodNames/callMethod with annotations (#447)
When creating a peripheral or custom Lua object, one must implement two
methods:
- getMethodNames(): String[] - Returns the name of the methods
- callMethod(int, ...): Object[] - Invokes the method using an index in
the above array.
This has a couple of problems:
- It's somewhat unwieldy to use - you need to keep track of array
indices, which leads to ugly code.
- Functions which yield (for instance, those which run on the main
thread) are blocking. This means we need to spawn new threads for
each CC-side yield.
We replace this system with a few changes:
- @LuaFunction annotation: One may annotate a public instance method
with this annotation. This then exposes a peripheral/lua object
method.
Furthermore, this method can accept and return a variety of types,
which often makes functions cleaner (e.g. can return an int rather
than an Object[], and specify and int argument rather than
Object[]).
- MethodResult: Instead of returning an Object[] and having blocking
yields, functions return a MethodResult. This either contains an
immediate return, or an instruction to yield with some continuation
to resume with.
MethodResult is then interpreted by the Lua runtime (i.e. Cobalt),
rather than our weird bodgey hacks before. This means we no longer
spawn new threads when yielding within CC.
- Methods accept IArguments instead of a raw Object array. This has a
few benefits:
- Consistent argument handling - people no longer need to use
ArgumentHelper (as it doesn't exist!), or even be aware of its
existence - you're rather forced into using it.
- More efficient code in some cases. We provide a Cobalt-specific
implementation of IArguments, which avoids the boxing/unboxing when
handling numbers and binary strings.
2020-05-15 12:21:16 +00:00
|
|
|
@LuaFunction( "close" )
|
|
|
|
public final void doClose() throws LuaException
|
|
|
|
{
|
|
|
|
checkOpen();
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-21 15:00:26 +00:00
|
|
|
/**
|
2019-10-27 15:16:47 +00:00
|
|
|
* Shared implementation for various file handle types.
|
2018-09-21 15:00:26 +00:00
|
|
|
*
|
|
|
|
* @param channel The channel to seek in
|
2020-07-09 20:59:19 +00:00
|
|
|
* @param whence The seeking mode.
|
|
|
|
* @param offset The offset to seek to.
|
2019-03-29 21:21:39 +00:00
|
|
|
* @return The new position of the file, or null if some error occurred.
|
2018-09-21 15:00:26 +00:00
|
|
|
* @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>
|
|
|
|
*/
|
2020-07-09 20:59:19 +00:00
|
|
|
protected static Object[] handleSeek( SeekableByteChannel channel, Optional<String> whence, Optional<Long> offset ) throws LuaException
|
2018-09-21 15:00:26 +00:00
|
|
|
{
|
2020-07-09 20:59:19 +00:00
|
|
|
long actualOffset = offset.orElse( 0L );
|
2018-09-21 15:00:26 +00:00
|
|
|
try
|
|
|
|
{
|
2020-07-09 20:59:19 +00:00
|
|
|
switch( whence.orElse( "cur" ) )
|
2018-09-21 15:00:26 +00:00
|
|
|
{
|
|
|
|
case "set":
|
2020-07-09 20:59:19 +00:00
|
|
|
channel.position( actualOffset );
|
2018-09-21 15:00:26 +00:00
|
|
|
break;
|
|
|
|
case "cur":
|
2020-07-09 20:59:19 +00:00
|
|
|
channel.position( channel.position() + actualOffset );
|
2018-09-21 15:00:26 +00:00
|
|
|
break;
|
|
|
|
case "end":
|
2020-07-09 20:59:19 +00:00
|
|
|
channel.position( channel.size() + actualOffset );
|
2018-09-21 15:00:26 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new LuaException( "bad argument #1 to 'seek' (invalid option '" + whence + "'" );
|
|
|
|
}
|
|
|
|
|
2018-12-23 17:46:58 +00:00
|
|
|
return new Object[] { channel.position() };
|
2018-09-21 15:00:26 +00:00
|
|
|
}
|
|
|
|
catch( IllegalArgumentException e )
|
|
|
|
{
|
2020-07-09 20:59:19 +00:00
|
|
|
return new Object[] { null, "Position is negative" };
|
2018-09-21 15:00:26 +00:00
|
|
|
}
|
|
|
|
catch( IOException e )
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
2017-05-12 21:49:44 +00:00
|
|
|
}
|
2018-10-29 15:59:43 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-05-12 21:49:44 +00:00
|
|
|
}
|