| /* | |
| * $Id: LuaState.java 157 2012-10-05 23:00:17Z andre@naef.com $ | |
| * See LICENSE.txt for license terms. | |
| */ | |
| package com.naef.jnlua; | |
| import java.io.ByteArrayInputStream; | |
| import java.io.IOException; | |
| import java.io.InputStream; | |
| import java.io.OutputStream; | |
| import java.lang.ref.PhantomReference; | |
| import java.lang.ref.ReferenceQueue; | |
| import java.lang.reflect.InvocationHandler; | |
| import java.lang.reflect.Method; | |
| import java.lang.reflect.Proxy; | |
| import java.util.HashSet; | |
| import java.util.Set; | |
| import com.naef.jnlua.JavaReflector.Metamethod; | |
| /** | |
| * JNLua core class representing a Lua instance. | |
| * | |
| * <p> | |
| * The class performs extensive checking on all arguments and its state. | |
| * Specifically, the following exceptions are thrown under the indicated | |
| * conditions: | |
| * </p> | |
| * | |
| * <table class="doc"> | |
| * <tr> | |
| * <th>Exception</th> | |
| * <th>When</th> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link java.lang.NullPointerException}</td> | |
| * <td>if an argument is <code>null</code> and the API does not explicitly | |
| * specify that the argument may be <code>null</code></td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link java.lang.IllegalStateException}</td> | |
| * <td>if the Lua state is closed and the API does not explicitly specify that | |
| * the method may be invoked on a closed Lua state</td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link java.lang.IllegalArgumentException}</td> | |
| * <td>if a stack index refers to a non-valid stack location and the API does | |
| * not explicitly specify that the stack index may be non-valid</td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link java.lang.IllegalArgumentException}</td> | |
| * <td>if a stack index refers to an stack location with value type that is | |
| * different from the value type explicitly specified in the API</td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link java.lang.IllegalArgumentException}</td> | |
| * <td>if a count is negative or out of range and the API does not explicitly | |
| * specify that the count may be negative or out of range</td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link com.naef.jnlua.LuaRuntimeException}</td> | |
| * <td>if a Lua runtime error occurs</td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link com.naef.jnlua.LuaSyntaxException}</td> | |
| * <td>if the syntax of a Lua chunk is incorrect</td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link com.naef.jnlua.LuaMemoryAllocationException}</td> | |
| * <td>if the Lua memory allocator runs out of memory or if a JNI allocation | |
| * fails</td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link com.naef.jnlua.LuaGcMetamethodException}</td> | |
| * <td>if an error occurs running a <code>__gc</code> metamethod during garbage | |
| * collection</td> | |
| * </tr> | |
| * <tr> | |
| * <td>{@link com.naef.jnlua.LuaMessageHandlerException}</td> | |
| * <td>if an error occurs running the message handler of a protected call</td> | |
| * </tr> | |
| * </table> | |
| */ | |
| public class LuaState { | |
| // -- Static | |
| /** | |
| * Multiple returns pseudo return value count. | |
| */ | |
| public static final int MULTRET = -1; | |
| /** | |
| * Registry pseudo-index. | |
| */ | |
| public static final int REGISTRYINDEX; | |
| /** | |
| * OK status. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| public static final int OK = 0; | |
| /** | |
| * Status indicating that a thread is suspended. | |
| */ | |
| public static final int YIELD = 1; | |
| /** | |
| * Registry index of the main thread. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| public static final int RIDX_MAINTHREAD = 1; | |
| /** | |
| * Registry index of the global environment. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| public static final int RIDX_GLOBALS = 2; | |
| /** | |
| * The JNLua version. The format is <major>.<minor>. | |
| */ | |
| public static final String VERSION = "1.0"; | |
| /** | |
| * The Lua version. The format is <major>.<minor>. | |
| */ | |
| public static final String LUA_VERSION; | |
| static { | |
| NativeSupport.getInstance().getLoader().load(); | |
| REGISTRYINDEX = lua_registryindex(); | |
| LUA_VERSION = lua_version(); | |
| } | |
| /** | |
| * The API version. | |
| */ | |
| private static final int APIVERSION = 3; | |
| // -- State | |
| /** | |
| * Whether the <code>lua_State</code> on the JNI side is owned by the Java | |
| * state and must be closed when the Java state closes. | |
| */ | |
| private boolean ownState; | |
| /** | |
| * The <code>lua_State</code> pointer on the JNI side. <code>0</code> | |
| * implies that this Lua state is closed. The field is modified exclusively | |
| * on the JNI side and must not be touched on the Java side. | |
| */ | |
| private long luaState; | |
| /** | |
| * The <code>lua_State</code> pointer on the JNI side for the running | |
| * coroutine. This field is modified exclusively on the JNI side and must | |
| * not be touched on the Java side. | |
| */ | |
| private long luaThread; | |
| /** | |
| * The yield flag. This field is modified from both the JNI side and Java | |
| * side and signals a pending yield. | |
| */ | |
| private boolean yield; | |
| /** | |
| * Ensures proper finalization of this Lua state. | |
| */ | |
| private Object finalizeGuardian; | |
| /** | |
| * The class loader for dynamically loading classes. | |
| */ | |
| private ClassLoader classLoader; | |
| /** | |
| * Reflects Java objects. | |
| */ | |
| private JavaReflector javaReflector; | |
| /** | |
| * Converts between Lua types and Java types. | |
| */ | |
| private Converter converter; | |
| /** | |
| * Set of Lua proxy phantom references for pre-mortem cleanup. | |
| */ | |
| private Set<LuaValueProxyRef> proxySet = new HashSet<LuaValueProxyRef>(); | |
| /** | |
| * Reference queue for pre-mortem cleanup. | |
| */ | |
| private ReferenceQueue<LuaValueProxyImpl> proxyQueue = new ReferenceQueue<LuaValueProxyImpl>(); | |
| // -- Construction | |
| /** | |
| * Creates a new instance. The class loader of this Lua state is set to the | |
| * context class loader of the calling thread. The Java reflector and the | |
| * converter are initialized with the default implementations. | |
| * | |
| * @see #getClassLoader() | |
| * @see #setClassLoader(ClassLoader) | |
| * @see #getJavaReflector() | |
| * @see #setJavaReflector(JavaReflector) | |
| * @see #getConverter() | |
| * @see #setConverter(Converter) | |
| */ | |
| public LuaState() { | |
| this(0L); | |
| } | |
| /** | |
| * Creates a new instance. | |
| */ | |
| private LuaState(long luaState) { | |
| ownState = luaState == 0L; | |
| lua_newstate(APIVERSION, luaState); | |
| check(); | |
| // Create a finalize guardian | |
| finalizeGuardian = new Object() { | |
| @Override | |
| public void finalize() { | |
| synchronized (LuaState.this) { | |
| closeInternal(); | |
| } | |
| } | |
| }; | |
| // Add metamethods | |
| for (int i = 0; i < JavaReflector.Metamethod.values().length; i++) { | |
| final JavaReflector.Metamethod metamethod = JavaReflector.Metamethod | |
| .values()[i]; | |
| lua_pushjavafunction(new JavaFunction() { | |
| @Override | |
| public int invoke(LuaState luaState) { | |
| JavaFunction javaFunction = getMetamethod( | |
| luaState.toJavaObjectRaw(1), metamethod); | |
| if (javaFunction != null) { | |
| return javaFunction.invoke(LuaState.this); | |
| } else { | |
| throw new UnsupportedOperationException( | |
| metamethod.getMetamethodName()); | |
| } | |
| } | |
| }); | |
| lua_setfield(-2, metamethod.getMetamethodName()); | |
| } | |
| lua_pop(1); | |
| // Set fields | |
| classLoader = Thread.currentThread().getContextClassLoader(); | |
| javaReflector = DefaultJavaReflector.getInstance(); | |
| converter = DefaultConverter.getInstance(); | |
| } | |
| // -- Properties | |
| /** | |
| * Returns the class loader of this Lua state. The class loader is used for | |
| * dynamically loading classes. | |
| * | |
| * <p> | |
| * The method may be invoked on a closed Lua state. | |
| * </p> | |
| * | |
| * @return the class loader | |
| */ | |
| public synchronized ClassLoader getClassLoader() { | |
| return classLoader; | |
| } | |
| /** | |
| * Sets the class loader of this Lua state. The class loader is used for | |
| * dynamically loading classes. | |
| * | |
| * <p> | |
| * The method may be invoked on a closed Lua state. | |
| * </p> | |
| * | |
| * @param classLoader | |
| * the class loader to set | |
| */ | |
| public synchronized void setClassLoader(ClassLoader classLoader) { | |
| if (classLoader == null) { | |
| throw new NullPointerException(); | |
| } | |
| this.classLoader = classLoader; | |
| } | |
| /** | |
| * Returns the Java reflector of this Lua state. | |
| * | |
| * <p> | |
| * The method may be invoked on a closed Lua state. | |
| * </p> | |
| * | |
| * @return the Java reflector converter | |
| */ | |
| public synchronized JavaReflector getJavaReflector() { | |
| return javaReflector; | |
| } | |
| /** | |
| * Sets the Java reflector of this Lua state. | |
| * | |
| * <p> | |
| * The method may be invoked on a closed Lua state. | |
| * </p> | |
| * | |
| * @param javaReflector | |
| * the Java reflector | |
| */ | |
| public synchronized void setJavaReflector(JavaReflector javaReflector) { | |
| if (javaReflector == null) { | |
| throw new NullPointerException(); | |
| } | |
| this.javaReflector = javaReflector; | |
| } | |
| /** | |
| * Returns a metamethod for a specified object. If the object implements the | |
| * {@link com.naef.jnlua.JavaReflector} interface, the metamethod is first | |
| * queried from the object. If the object provides the requested metamethod, | |
| * that metamethod is returned. Otherwise, the method returns the metamethod | |
| * provided by the Java reflector configured in this Lua state. | |
| * | |
| * <p> | |
| * Clients requiring access to metamethods should go by this method to | |
| * ensure consistent class-by-class overriding of the Java reflector. | |
| * </p> | |
| * | |
| * @param obj | |
| * the object, or <code>null</code> | |
| * @return the Java reflector | |
| */ | |
| public synchronized JavaFunction getMetamethod(Object obj, | |
| Metamethod metamethod) { | |
| if (obj != null && obj instanceof JavaReflector) { | |
| JavaFunction javaFunction = ((JavaReflector) obj) | |
| .getMetamethod(metamethod); | |
| if (javaFunction != null) { | |
| return javaFunction; | |
| } | |
| } | |
| return javaReflector.getMetamethod(metamethod); | |
| } | |
| /** | |
| * Returns the converter of this Lua state. | |
| * | |
| * <p> | |
| * The method may be invoked on a closed Lua state. | |
| * </p> | |
| * | |
| * @return the converter | |
| */ | |
| public synchronized Converter getConverter() { | |
| return converter; | |
| } | |
| /** | |
| * Sets the converter of this Lua state. | |
| * | |
| * <p> | |
| * The method may be invoked on a closed Lua state. | |
| * </p> | |
| * | |
| * @param converter | |
| * the converter | |
| */ | |
| public synchronized void setConverter(Converter converter) { | |
| if (converter == null) { | |
| throw new NullPointerException(); | |
| } | |
| this.converter = converter; | |
| } | |
| // -- Life cycle | |
| /** | |
| * Returns whether this Lua state is open. | |
| * | |
| * <p> | |
| * The method may be invoked on a closed Lua state. | |
| * </p> | |
| * | |
| * @return whether this Lua state is open | |
| */ | |
| public final synchronized boolean isOpen() { | |
| return isOpenInternal(); | |
| } | |
| /** | |
| * Closes this Lua state and releases all resources. | |
| * | |
| * <p> | |
| * The method may be invoked on a closed Lua state and has no effect in that | |
| * case. | |
| * </p> | |
| */ | |
| public synchronized void close() { | |
| closeInternal(); | |
| } | |
| /** | |
| * Performs a garbage collection operation. Please see the Lua Reference | |
| * Manual for an explanation of the actions, arguments and return values. | |
| * | |
| * @param what | |
| * the operation to perform | |
| * @param data | |
| * the argument required by some operations | |
| * @return a return value depending on the GC operation performed | |
| */ | |
| public synchronized int gc(GcAction what, int data) { | |
| check(); | |
| return lua_gc(what.ordinal(), data); | |
| } | |
| // -- Registration | |
| /** | |
| * Opens the specified library in this Lua state. The library is pushed onto | |
| * the stack. | |
| * | |
| * @param library | |
| * the library | |
| */ | |
| public synchronized void openLib(Library library) { | |
| check(); | |
| library.open(this); | |
| } | |
| /** | |
| * Opens the Lua standard libraries and the JNLua Java module in this Lua | |
| * state. | |
| * | |
| * <p> | |
| * The method opens all libraries defined by the {@link Library} | |
| * enumeration. | |
| * </p> | |
| */ | |
| public synchronized void openLibs() { | |
| check(); | |
| for (Library library : Library.values()) { | |
| library.open(this); | |
| pop(1); | |
| } | |
| } | |
| /** | |
| * Registers a named Java function as a global variable. | |
| * | |
| * @param namedJavaFunction | |
| * the Java function to register | |
| */ | |
| public synchronized void register(NamedJavaFunction namedJavaFunction) { | |
| check(); | |
| String name = namedJavaFunction.getName(); | |
| if (name == null) { | |
| throw new IllegalArgumentException("anonymous function"); | |
| } | |
| pushJavaFunction(namedJavaFunction); | |
| setGlobal(name); | |
| } | |
| /** | |
| * Registers a module and pushes the module on the stack. Optionally, a | |
| * module can be registered globally. As of Lua 5.2, modules are <i>not</i> | |
| * expected to set global variables anymore. | |
| * | |
| * @param moduleName | |
| * the module name | |
| * @param namedJavaFunctions | |
| * the Java functions of the module | |
| * @param global | |
| * whether to register the module globally | |
| */ | |
| public synchronized void register(String moduleName, | |
| NamedJavaFunction[] namedJavaFunctions, boolean global) { | |
| check(); | |
| /* | |
| * The following code corresponds to luaL_requiref() and must be kept in | |
| * sync. The original code cannot be called due to the necessity of | |
| * pushing each C function with an individual closure. | |
| */ | |
| newTable(0, namedJavaFunctions.length); | |
| for (int i = 0; i < namedJavaFunctions.length; i++) { | |
| String name = namedJavaFunctions[i].getName(); | |
| if (name == null) { | |
| throw new IllegalArgumentException(String.format( | |
| "anonymous function at index %d", i)); | |
| } | |
| pushJavaFunction(namedJavaFunctions[i]); | |
| setField(-2, name); | |
| } | |
| lua_getsubtable(REGISTRYINDEX, "_LOADED"); | |
| pushValue(-2); | |
| setField(-2, moduleName); | |
| pop(1); | |
| if (global) { | |
| rawGet(REGISTRYINDEX, RIDX_GLOBALS); | |
| pushValue(-2); | |
| setField(-2, moduleName); | |
| pop(1); | |
| } | |
| } | |
| // -- Load and dump | |
| /** | |
| * Loads a Lua chunk from an input stream and pushes it on the stack as a | |
| * function. Depending on the value of mode, the the Lua chunk can either be | |
| * a pre-compiled binary chunk or a UTF-8 encoded text chunk. | |
| * | |
| * @param inputStream | |
| * the input stream | |
| * @param chunkName | |
| * the name of the chunk for use in error messages | |
| * @param mode | |
| * <code>"b"</code> to accept binary, <code>"t"</code> to accept | |
| * text, or <code>"bt"</code> to accept both | |
| * @throws IOException | |
| * if an IO error occurs | |
| */ | |
| public synchronized void load(InputStream inputStream, String chunkName, | |
| String mode) throws IOException { | |
| check(); | |
| lua_load(inputStream, chunkName, mode); | |
| } | |
| /** | |
| * Loads a Lua chunk from a string and pushes it on the stack as a function. | |
| * The string must contain a source chunk. | |
| * | |
| * @param chunk | |
| * the Lua source chunk | |
| * @param chunkName | |
| * the name of the chunk for use in error messages | |
| */ | |
| public synchronized void load(String chunk, String chunkName) { | |
| check(); | |
| try { | |
| load(new ByteArrayInputStream(chunk.getBytes("UTF-8")), chunkName, | |
| "t"); | |
| } catch (IOException e) { | |
| throw new LuaMemoryAllocationException(e.getMessage(), e); | |
| } | |
| } | |
| /** | |
| * Dumps the function on top of the stack as a pre-compiled binary chunk | |
| * into an output stream. | |
| * | |
| * @param outputStream | |
| * the output stream | |
| * @throws IOException | |
| * if an IO error occurs | |
| */ | |
| public synchronized void dump(OutputStream outputStream) throws IOException { | |
| check(); | |
| lua_dump(outputStream); | |
| } | |
| // -- Call | |
| /** | |
| * Calls a Lua function. The function to call and the specified number of | |
| * arguments are on the stack. After the call, the specified number of | |
| * returns values are on stack. If the number of return values has been | |
| * specified as {@link #MULTRET}, the number of values on the stack | |
| * corresponds the to number of values actually returned by the called | |
| * function. | |
| * | |
| * @param argCount | |
| * the number of arguments | |
| * @param returnCount | |
| * the number of return values, or {@link #MULTRET} to accept all | |
| * values returned by the function | |
| */ | |
| public synchronized void call(int argCount, int returnCount) { | |
| check(); | |
| lua_pcall(argCount, returnCount); | |
| } | |
| // -- Globals | |
| /** | |
| * Pushes the value of a global variable on the stack. | |
| * | |
| * @param name | |
| * the global variable name | |
| */ | |
| public synchronized void getGlobal(String name) { | |
| check(); | |
| lua_getglobal(name); | |
| } | |
| /** | |
| * Sets the value on top of the stack as a global variable and pops the | |
| * value from the stack. | |
| * | |
| * @param name | |
| * the global variable name | |
| */ | |
| public synchronized void setGlobal(String name) | |
| throws LuaMemoryAllocationException, LuaRuntimeException { | |
| check(); | |
| lua_setglobal(name); | |
| } | |
| // -- Stack push | |
| /** | |
| * Pushes a boolean value on the stack. | |
| * | |
| * @param b | |
| * the boolean value to push | |
| */ | |
| public synchronized void pushBoolean(boolean b) { | |
| check(); | |
| lua_pushboolean(b ? 1 : 0); | |
| } | |
| /** | |
| * Pushes a byte array value as a string value on the stack. | |
| * | |
| * @param b | |
| * the byte array to push | |
| */ | |
| public synchronized void pushByteArray(byte[] b) { | |
| check(); | |
| lua_pushbytearray(b); | |
| } | |
| /** | |
| * Pushes an integer value as a number value on the stack. | |
| * | |
| * @param n | |
| * the integer value to push | |
| */ | |
| public synchronized void pushInteger(int n) { | |
| check(); | |
| lua_pushinteger(n); | |
| } | |
| /** | |
| * Pushes a Java function on the stack. | |
| * | |
| * @param javaFunction | |
| * the function to push | |
| */ | |
| public synchronized void pushJavaFunction(JavaFunction javaFunction) { | |
| check(); | |
| lua_pushjavafunction(javaFunction); | |
| } | |
| /** | |
| * Pushes a Java object on the stack with conversion. The object is | |
| * processed the by the configured converter. | |
| * | |
| * @param object | |
| * the Java object | |
| * @see #getConverter() | |
| * @see #setConverter(Converter) | |
| */ | |
| public synchronized void pushJavaObject(Object object) { | |
| check(); | |
| getConverter().convertJavaObject(this, object); | |
| } | |
| /** | |
| * Pushes a Java object on the stack. The object is pushed "as is", i.e. | |
| * without conversion. | |
| * | |
| * <p> | |
| * If you require to push a Lua value that represents the Java object, then | |
| * invoke <code>pushJavaObject(object)</code>. | |
| * </p> | |
| * | |
| * <p> | |
| * You cannot push <code>null</code> without conversion since | |
| * <code>null</code> is not a Java object. The converter converts | |
| * <code>null</code> to <code>nil</code>. | |
| * </p> | |
| * | |
| * @param object | |
| * the Java object | |
| * @see #pushJavaObject(Object) | |
| */ | |
| public synchronized void pushJavaObjectRaw(Object object) { | |
| check(); | |
| lua_pushjavaobject(object); | |
| } | |
| /** | |
| * Pushes a nil value on the stack. | |
| */ | |
| public synchronized void pushNil() { | |
| check(); | |
| lua_pushnil(); | |
| } | |
| /** | |
| * Pushes a number value on the stack. | |
| * | |
| * @param n | |
| * the number to push | |
| */ | |
| public synchronized void pushNumber(double n) { | |
| check(); | |
| lua_pushnumber(n); | |
| } | |
| /** | |
| * Pushes a string value on the stack. | |
| * | |
| * @param s | |
| * the string value to push | |
| */ | |
| public synchronized void pushString(String s) { | |
| check(); | |
| lua_pushstring(s); | |
| } | |
| // -- Stack type test | |
| /** | |
| * Returns whether the value at the specified stack index is a boolean. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a boolean | |
| */ | |
| public synchronized boolean isBoolean(int index) { | |
| check(); | |
| return lua_isboolean(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is a C function. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a function | |
| */ | |
| public synchronized boolean isCFunction(int index) { | |
| check(); | |
| return lua_iscfunction(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is a function | |
| * (either a C function, a Java function or a Lua function.) | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a function | |
| */ | |
| public synchronized boolean isFunction(int index) { | |
| check(); | |
| return lua_isfunction(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is a Java | |
| * function. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a function | |
| */ | |
| public synchronized boolean isJavaFunction(int index) { | |
| check(); | |
| return lua_isjavafunction(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is convertible to | |
| * a Java object of the specified type. The conversion is checked by the | |
| * configured converter. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is convertible to a Java object of the | |
| * specified type | |
| * @see #setConverter(Converter) | |
| * @see #getConverter() | |
| */ | |
| public synchronized boolean isJavaObject(int index, Class<?> type) { | |
| check(); | |
| return converter.getTypeDistance(this, index, type) != Integer.MAX_VALUE; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is a Java object. | |
| * | |
| * <p> | |
| * Note that the method does not perform conversion. If you want to check if | |
| * a value <i>is convertible to</i> a Java object, then invoke <code> | |
| * isJavaObject(index, Object.class)</code>. | |
| * </p> | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a Java object | |
| * @see #isJavaObject(int, Class) | |
| */ | |
| public synchronized boolean isJavaObjectRaw(int index) { | |
| check(); | |
| return lua_isjavaobject(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is | |
| * <code>nil</code>. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is <code>nil</code> | |
| */ | |
| public synchronized boolean isNil(int index) { | |
| check(); | |
| return lua_isnil(index) != 0; | |
| } | |
| /** | |
| * Returns whether the specified stack index is non-valid. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the stack index is non-valid | |
| */ | |
| public synchronized boolean isNone(int index) { | |
| check(); | |
| return lua_isnone(index) != 0; | |
| } | |
| /** | |
| * Returns whether the specified stack index is non-valid or its value is | |
| * <code>nil</code>. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the stack index is non-valid or its value is | |
| * <code>nil</code> | |
| */ | |
| public synchronized boolean isNoneOrNil(int index) { | |
| check(); | |
| return lua_isnoneornil(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is a number or a | |
| * string convertible to a number. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a number or a string convertible to a number | |
| */ | |
| public synchronized boolean isNumber(int index) { | |
| check(); | |
| return lua_isnumber(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is a string or a | |
| * number (which is always convertible to a string.) | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a string or a number | |
| */ | |
| public synchronized boolean isString(int index) { | |
| check(); | |
| return lua_isstring(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is a table. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a table | |
| */ | |
| public synchronized boolean isTable(int index) { | |
| check(); | |
| return lua_istable(index) != 0; | |
| } | |
| /** | |
| * Returns whether the value at the specified stack index is a thread. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return whether the value is a thread | |
| */ | |
| public synchronized boolean isThread(int index) { | |
| check(); | |
| return lua_isthread(index) != 0; | |
| } | |
| // -- Stack query | |
| /** | |
| * Compares the values at two specified stack indexes for the specified | |
| * operator according to Lua semantics. | |
| * | |
| * <p> | |
| * Any stack index may be non-valid in which case the method returns | |
| * <code>false</code>. | |
| * </p> | |
| * | |
| * @param index1 | |
| * the first stack index | |
| * @param index2 | |
| * the second stack index | |
| * @param operator | |
| * the operator | |
| * @return the result of the comparison | |
| * @since JNLua 1.0.0 | |
| */ | |
| public synchronized boolean compare(int index1, int index2, | |
| RelOperator operator) { | |
| check(); | |
| return lua_compare(index1, index2, operator.ordinal()) != 0; | |
| } | |
| /** | |
| * Returns whether the values at two specified stack indexes are equal | |
| * according to Lua semantics. | |
| * | |
| * @param index1 | |
| * the first stack index | |
| * @param index2 | |
| * the second stack index | |
| * @return whether the values are equal | |
| * @deprecated instead use {@link #compare(int, int, RelOperator)} | |
| */ | |
| public synchronized boolean equal(int index1, int index2) { | |
| return compare(index1, index2, RelOperator.EQ); | |
| } | |
| /** | |
| * Returns the length of the value at the specified stack index. Please see | |
| * the Lua Reference Manual for the definition of the raw length of a value. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the length | |
| * @deprecated instead use {@link #rawLen(int)} | |
| */ | |
| public synchronized int length(int index) { | |
| return rawLen(index); | |
| } | |
| /** | |
| * Returns whether a value at a first stack index is less than the value at | |
| * a second stack index according to Lua semantics. | |
| * | |
| * @param index1 | |
| * the first stack index | |
| * @param index2 | |
| * the second stack index | |
| * @return whether the value at the first index is less than the value at | |
| * the second index | |
| * @deprecated instead use {@link #compare(int, int, RelOperator)} | |
| */ | |
| public synchronized boolean lessThan(int index1, int index2) | |
| throws LuaMemoryAllocationException, LuaRuntimeException { | |
| return compare(index1, index2, RelOperator.LT); | |
| } | |
| /** | |
| * Bypassing metatable logic, returns whether the values at two specified | |
| * stack indexes are equal according to Lua semantics. | |
| * | |
| * <p> | |
| * Any stack index may be non-valid in which case the method returns | |
| * <code>false</code>. | |
| * </p> | |
| * | |
| * @param index1 | |
| * the first stack index | |
| * @param index2 | |
| * the second stack index | |
| * @return whether the values are equal | |
| */ | |
| public synchronized boolean rawEqual(int index1, int index2) { | |
| check(); | |
| return lua_rawequal(index1, index2) != 0; | |
| } | |
| /** | |
| * Bypassing metatable logic, returns the length of the value at the | |
| * specified stack index. Please see the Lua Reference Manual for the | |
| * definition of the raw length of a value. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the length | |
| * @since JNLua 1.0.0 | |
| */ | |
| public synchronized int rawLen(int index) { | |
| check(); | |
| return lua_rawlen(index); | |
| } | |
| /** | |
| * Returns the boolean representation of the value at the specified stack | |
| * index. The boolean representation is <code>true</code> for all values | |
| * except <code>false</code> and <code>nil</code>. The method also returns | |
| * <code>false</code> if the index is non-valid. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the boolean representation of the value | |
| */ | |
| public synchronized boolean toBoolean(int index) { | |
| check(); | |
| return lua_toboolean(index) != 0; | |
| } | |
| /** | |
| * Returns the byte array representation of the value at the specified stack | |
| * index. The value must be a string or a number. If the value is a number, | |
| * it is in place converted to a string. Otherwise, the method returns | |
| * <code>null</code>. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the byte array representation of the value | |
| */ | |
| public synchronized byte[] toByteArray(int index) { | |
| check(); | |
| return lua_tobytearray(index); | |
| } | |
| /** | |
| * Returns the integer representation of the value at the specified stack | |
| * index. The value must be a number or a string convertible to a number. | |
| * Otherwise, the method returns <code>0</code>. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the integer representation, or <code>0</code> | |
| */ | |
| public synchronized int toInteger(int index) { | |
| check(); | |
| return lua_tointeger(index); | |
| } | |
| /** | |
| * Returns the integer representation of the value at the specified stack | |
| * index. The value must be a number or a string convertible to a number. | |
| * Otherwise, the method returns <code>null</code>. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the integer representation, or <code>null</code> | |
| * @since JNLua 1.0.2 | |
| */ | |
| public synchronized Integer toIntegerX(int index) { | |
| check(); | |
| return lua_tointegerx(index); | |
| } | |
| /** | |
| * Returns the Java function of the value at the specified stack index. If | |
| * the value is not a Java function, the method returns <code>null</code>. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the Java function, or <code>null</code> | |
| */ | |
| public synchronized JavaFunction toJavaFunction(int index) { | |
| check(); | |
| return lua_tojavafunction(index); | |
| } | |
| /** | |
| * Returns a Java object of the specified type representing the value at the | |
| * specified stack index. The value must be convertible to a Java object of | |
| * the specified type. The conversion is executed by the configured | |
| * converter. | |
| * | |
| * @param index | |
| * the stack index | |
| * @param type | |
| * the Java type to convert to | |
| * @return the object | |
| * @throws ClassCastException | |
| * if the conversion is not supported by the converter | |
| * @see #getConverter() | |
| * @see #setConverter(Converter) | |
| */ | |
| public synchronized <T> T toJavaObject(int index, Class<T> type) { | |
| check(); | |
| return converter.convertLuaValue(this, index, type); | |
| } | |
| /** | |
| * Returns the Java object of the value at the specified stack index. If the | |
| * value is not a Java object, the method returns <code>null</code>. | |
| * | |
| * <p> | |
| * Note that the method does not convert values to Java objects. If you | |
| * require <i>any</i> Java object that represents the value at the specified | |
| * index, then invoke <code>toJavaObject(index, Object.class)</code>. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the Java object, or <code>null</code> | |
| * @see #toJavaObject(int, Class) | |
| */ | |
| public synchronized Object toJavaObjectRaw(int index) { | |
| check(); | |
| return lua_tojavaobject(index); | |
| } | |
| /** | |
| * Returns the number representation of the value at the specified stack | |
| * index. The value must be a number or a string convertible to a number. | |
| * Otherwise, the method returns <code>0.0</code>. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the number representation, or <code>0.0</code> | |
| */ | |
| public synchronized double toNumber(int index) { | |
| check(); | |
| return lua_tonumber(index); | |
| } | |
| /** | |
| * Returns the number representation of the value at the specified stack | |
| * index. The value must be a number or a string convertible to a number. | |
| * Otherwise, the method returns <code>null</code>. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the number representation, or <code>null</code> | |
| * @since JNLua 1.0.2 | |
| */ | |
| public synchronized Double toNumberX(int index) { | |
| check(); | |
| return lua_tonumberx(index); | |
| } | |
| /** | |
| * Returns the pointer representation of the value at the specified stack | |
| * index. The value must be a table, thread, function or userdata (such as a | |
| * Java object.) Otherwise, the method returns <code>0L</code>. Different | |
| * values return different pointers. Other than that, the returned value has | |
| * no portable significance. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the pointer representation, or <code>0L</code> if none | |
| */ | |
| public synchronized long toPointer(int index) { | |
| check(); | |
| return lua_topointer(index); | |
| } | |
| /** | |
| * Returns the string representation of the value at the specified stack | |
| * index. The value must be a string or a number. If the value is a number, | |
| * it is in place converted to a string. Otherwise, the method returns | |
| * <code>null</code>. | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the string representation, or <code>null</code> | |
| */ | |
| public synchronized String toString(int index) { | |
| check(); | |
| return lua_tostring(index); | |
| } | |
| /** | |
| * Returns the type of the value at the specified stack index. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the type, or <code>null</code> if the stack index is non-valid | |
| */ | |
| public synchronized LuaType type(int index) { | |
| check(); | |
| int type = lua_type(index); | |
| return type >= 0 ? LuaType.values()[type] : null; | |
| } | |
| /** | |
| * Returns the name of the type at the specified stack index. The type name | |
| * is the display text for the Lua type except for Java objects where the | |
| * type name is the canonical class name. | |
| * | |
| * <p> | |
| * The stack index may be non-valid in which case the method returns the | |
| * string <code>"none"</code>. | |
| * </p> | |
| * | |
| * @param index | |
| * the index | |
| * @return the type name | |
| * @see LuaType#displayText() | |
| * @see Class#getCanonicalName() | |
| */ | |
| public synchronized String typeName(int index) { | |
| check(); | |
| LuaType type = type(index); | |
| if (type == null) { | |
| return "none"; | |
| } | |
| switch (type) { | |
| case USERDATA: | |
| if (isJavaObjectRaw(index)) { | |
| Object object = toJavaObjectRaw(index); | |
| Class<?> clazz; | |
| if (object instanceof Class<?>) { | |
| clazz = (Class<?>) object; | |
| } else { | |
| clazz = object.getClass(); | |
| } | |
| return clazz.getCanonicalName(); | |
| } | |
| break; | |
| } | |
| return type.displayText(); | |
| } | |
| // -- Stack operation | |
| /** | |
| * Returns the absolute stack index of the specified index. | |
| * | |
| * <p> | |
| * The stack index may be non-valid. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index | |
| * @return the absolute stack index | |
| * @since JNLua 1.0.0 | |
| */ | |
| public synchronized int absIndex(int index) { | |
| check(); | |
| return lua_absindex(index); | |
| } | |
| /** | |
| * Performs an arithmetic operation with values on top of the stack using | |
| * Lua semantics. | |
| * | |
| * @param operator | |
| * the operator to apply | |
| * @since JNLua 1.0.0 | |
| */ | |
| public synchronized void arith(ArithOperator operator) { | |
| check(); | |
| lua_arith(operator.ordinal()); | |
| } | |
| /** | |
| * Concatenates the specified number values on top of the stack and replaces | |
| * them with the concatenated value. | |
| * | |
| * @param n | |
| * the number of values to concatenate | |
| */ | |
| public synchronized void concat(int n) { | |
| check(); | |
| lua_concat(n); | |
| } | |
| /** | |
| * Copies a value at a specified index to another index, replacing the value | |
| * at that index. | |
| * | |
| * @param fromIndex | |
| * the index to copy from | |
| * @param toIndex | |
| * the index to copy to | |
| * @since JNLua 1.0.0 | |
| */ | |
| public synchronized void copy(int fromIndex, int toIndex) { | |
| check(); | |
| lua_copy(fromIndex, toIndex); | |
| } | |
| /** | |
| * Returns the number of values on the stack. | |
| * | |
| * @return the number of values on the tack | |
| */ | |
| public synchronized int getTop() { | |
| check(); | |
| return lua_gettop(); | |
| } | |
| /** | |
| * Pushes the length of the value at the specified stack index on the stack. | |
| * The value pushed by the method corresponds to the Lua <code>#</code> | |
| * operator. | |
| * | |
| * @param index | |
| * the index for which to push the length | |
| * @since JNLua 1.0.0 | |
| */ | |
| public synchronized void len(int index) { | |
| check(); | |
| lua_len(index); | |
| } | |
| /** | |
| * Pops the value on top of the stack inserting it at the specified index | |
| * and moving up elements above that index. | |
| * | |
| * @param index | |
| * the stack index | |
| */ | |
| public synchronized void insert(int index) { | |
| check(); | |
| lua_insert(index); | |
| } | |
| /** | |
| * Pops values from the stack. | |
| * | |
| * @param count | |
| * the number of values to pop | |
| */ | |
| public synchronized void pop(int count) { | |
| check(); | |
| lua_pop(count); | |
| } | |
| /** | |
| * Pushes the value at the specified index on top of the stack. | |
| * | |
| * @param index | |
| * the stack index | |
| */ | |
| public synchronized void pushValue(int index) { | |
| check(); | |
| lua_pushvalue(index); | |
| } | |
| /** | |
| * Removes the value at the specified stack index moving down elements above | |
| * that index. | |
| * | |
| * @param index | |
| * the stack index | |
| */ | |
| public synchronized void remove(int index) { | |
| check(); | |
| lua_remove(index); | |
| } | |
| /** | |
| * Replaces the value at the specified index with the value popped from the | |
| * top of the stack. | |
| * | |
| * @param index | |
| * the stack index | |
| */ | |
| public synchronized void replace(int index) { | |
| check(); | |
| lua_replace(index); | |
| } | |
| /** | |
| * Sets the specified index as the new top of the stack. | |
| * | |
| * <p> | |
| * The new top of the stack may be above the current top of the stack. In | |
| * this case, new values are set to <code>nil</code>. | |
| * </p> | |
| * | |
| * @param index | |
| * the index of the new top of the stack | |
| */ | |
| public synchronized void setTop(int index) { | |
| check(); | |
| lua_settop(index); | |
| } | |
| // -- Table | |
| /** | |
| * Pushes on the stack the value indexed by the key on top of the stack in | |
| * the table at the specified index. The key is replaced by the value from | |
| * the table. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| */ | |
| public synchronized void getTable(int index) { | |
| check(); | |
| lua_gettable(index); | |
| } | |
| /** | |
| * Pushes on the stack the value indexed by the specified string key in the | |
| * table at the specified index. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @param key | |
| * the string key | |
| */ | |
| public synchronized void getField(int index, String key) { | |
| check(); | |
| lua_getfield(index, key); | |
| } | |
| /** | |
| * Creates a new table and pushes it on the stack. | |
| */ | |
| public synchronized void newTable() { | |
| check(); | |
| lua_newtable(); | |
| } | |
| /** | |
| * Creates a new table with pre-allocated space for a number of array | |
| * elements and record elements and pushes it on the stack. | |
| * | |
| * @param arrayCount | |
| * the number of array elements | |
| * @param recordCount | |
| * the number of record elements | |
| */ | |
| public synchronized void newTable(int arrayCount, int recordCount) { | |
| check(); | |
| lua_createtable(arrayCount, recordCount); | |
| } | |
| /** | |
| * Pops a key from the stack and pushes on the stack the next key and its | |
| * value in the table at the specified index. If there is no next key, the | |
| * key is popped but nothing is pushed. The method returns whether there is | |
| * a next key. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @return whether there is a next key | |
| */ | |
| public synchronized boolean next(int index) { | |
| check(); | |
| return lua_next(index) != 0; | |
| } | |
| /** | |
| * Bypassing metatable logic, pushes on the stack the value indexed by the | |
| * key on top of the stack in the table at the specified index. The key is | |
| * replaced by the value from the table. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| */ | |
| public synchronized void rawGet(int index) { | |
| check(); | |
| lua_rawget(index); | |
| } | |
| /** | |
| * Bypassing metatable logic, pushes on the stack the value indexed by the | |
| * specified integer key in the table at the specified index. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @param key | |
| * the integer key | |
| */ | |
| public synchronized void rawGet(int index, int key) { | |
| check(); | |
| lua_rawgeti(index, key); | |
| } | |
| /** | |
| * Bypassing metatable logic, sets the value on top of the stack in the | |
| * table at the specified index using the value on the second highest stack | |
| * position as the key. Both the value and the key are popped from the | |
| * stack. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| */ | |
| public synchronized void rawSet(int index) { | |
| check(); | |
| lua_rawset(index); | |
| } | |
| /** | |
| * Bypassing metatable logic, sets the value on top of the stack in the | |
| * table at the specified index using the specified integer key. The value | |
| * is popped from the stack. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @param key | |
| * the integer key | |
| */ | |
| public synchronized void rawSet(int index, int key) { | |
| check(); | |
| lua_rawseti(index, key); | |
| } | |
| /** | |
| * Sets the value on top of the stack in the table at the specified index | |
| * using the value on the second highest stack position as the key. Both the | |
| * value and the key are popped from the stack. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| */ | |
| public synchronized void setTable(int index) { | |
| check(); | |
| lua_settable(index); | |
| } | |
| /** | |
| * Sets the value on top of the stack in the table at the specified index | |
| * using the specified string key. The value is popped from the stack. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @param key | |
| * the string key | |
| */ | |
| public synchronized void setField(int index, String key) { | |
| check(); | |
| lua_setfield(index, key); | |
| } | |
| // -- Metatable | |
| /** | |
| * Pushes on the stack the value of the named field in the metatable of the | |
| * value at the specified index and returns <code>true</code>. If the value | |
| * does not have a metatable or if the metatable does not contain the named | |
| * field, nothing is pushed and the method returns <code>false</code>. | |
| * | |
| * @param index | |
| * the stack index containing the value to get the metafield from | |
| * @param key | |
| * the string key | |
| * @return whether the metafield was pushed on the stack | |
| */ | |
| public synchronized boolean getMetafield(int index, String key) { | |
| check(); | |
| return lua_getmetafield(index, key) != 0; | |
| } | |
| /** | |
| * Pushes on the stack the metatable of the value at the specified index. If | |
| * the value does not have a metatable, the method returns | |
| * <code>false</code> and nothing is pushed. | |
| * | |
| * @param index | |
| * the stack index containing the value to get the metatable from | |
| * @return whether the metatable was pushed on the stack | |
| */ | |
| public synchronized boolean getMetatable(int index) { | |
| check(); | |
| return lua_getmetatable(index) != 0; | |
| } | |
| /** | |
| * Sets the value on top of the stack as the metatable of the value at the | |
| * specified index. The metatable to be set is popped from the stack | |
| * regardless whether it can be set or not. | |
| * | |
| * @param index | |
| * the stack index containing the value to set the metatable for | |
| */ | |
| public synchronized void setMetatable(int index) { | |
| check(); | |
| lua_setmetatable(index); | |
| } | |
| // -- Thread | |
| /** | |
| * Pops the start function of a new Lua thread from the stack and creates | |
| * the new thread with that start function. The new thread is pushed on the | |
| * stack. | |
| */ | |
| public synchronized void newThread() { | |
| check(); | |
| lua_newthread(); | |
| } | |
| /** | |
| * Resumes the thread at the specified stack index, popping the specified | |
| * number of arguments from the top of the stack and passing them to the | |
| * resumed thread. The method returns the number of values pushed on the | |
| * stack as the return values of the resumed thread. | |
| * | |
| * @param index | |
| * the stack index containing the thread | |
| * @param argCount | |
| * the number of arguments to pass | |
| * @return the number of values returned by the thread | |
| */ | |
| public synchronized int resume(int index, int argCount) { | |
| check(); | |
| return lua_resume(index, argCount); | |
| } | |
| /** | |
| * Returns the status of the thread at the specified stack index. If the | |
| * thread is in initial state of has finished its execution, the method | |
| * returns <code>0</code>. If the thread has yielded, the method returns | |
| * {@link #YIELD}. Other return values indicate errors for which an | |
| * exception has been thrown. | |
| * | |
| * @param index | |
| * the index | |
| * @return the status | |
| */ | |
| public synchronized int status(int index) { | |
| check(); | |
| return lua_status(index); | |
| } | |
| /** | |
| * Yields the running thread, popping the specified number of values from | |
| * the top of the stack and passing them as return values to the thread | |
| * which has resumed the running thread. The method must be used exclusively | |
| * at the exit point of Java functions, i.e. | |
| * <code>return luaState.yield(n)</code>. | |
| * | |
| * @param returnCount | |
| * the number of results to pass | |
| * @return the return value of the Java function | |
| */ | |
| public synchronized int yield(int returnCount) { | |
| check(); | |
| yield = true; | |
| return returnCount; | |
| } | |
| // -- Reference | |
| /** | |
| * Stores the value on top of the stack in the table at the specified index | |
| * and returns the integer key of the value in that table as a reference. | |
| * The value is popped from the stack. | |
| * | |
| * @param index | |
| * the stack index containing the table where to store the value | |
| * @return the reference integer key | |
| * @see #unref(int, int) | |
| */ | |
| public synchronized int ref(int index) { | |
| check(); | |
| return lua_ref(index); | |
| } | |
| /** | |
| * Removes a previously created reference from the table at the specified | |
| * index. The value is removed from the table and its integer key of the | |
| * reference is freed for reuse. | |
| * | |
| * @param index | |
| * the stack index containing the table where the value was | |
| * stored | |
| * @param reference | |
| * the reference integer key | |
| * @see #ref(int) | |
| */ | |
| public synchronized void unref(int index, int reference) { | |
| check(); | |
| lua_unref(index, reference); | |
| } | |
| // -- Optimization | |
| /** | |
| * Counts the number of entries in a table. | |
| * | |
| * <p> | |
| * The method provides optimized performance over a Java implementation of | |
| * the same functionality due to the reduced number of JNI transitions. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @return the number of entries in the table | |
| */ | |
| public synchronized int tableSize(int index) { | |
| check(); | |
| return lua_tablesize(index); | |
| } | |
| /** | |
| * Moves the specified number of sequential elements in a table used as an | |
| * array from one index to another. | |
| * | |
| * <p> | |
| * The method provides optimized performance over a Java implementation of | |
| * the same functionality due to the reduced number of JNI transitions. | |
| * </p> | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @param from | |
| * the index to move from | |
| * @param to | |
| * the index to move to | |
| * @param count | |
| * the number of elements to move | |
| */ | |
| public synchronized void tableMove(int index, int from, int to, int count) { | |
| check(); | |
| lua_tablemove(index, from, to, count); | |
| } | |
| // -- Argument checking | |
| /** | |
| * Checks if a condition is true for the specified function argument. If | |
| * not, the method throws a Lua runtime exception with the specified error | |
| * message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param condition | |
| * the condition | |
| * @param msg | |
| * the error message | |
| */ | |
| public synchronized void checkArg(int index, boolean condition, String msg) { | |
| check(); | |
| if (!condition) { | |
| throw getArgException(index, msg); | |
| } | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a string or a | |
| * number. If so, the argument value is returned as a byte array. Otherwise, | |
| * the method throws a Lua runtime exception with a descriptive error | |
| * message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @return the byte array value | |
| */ | |
| public synchronized byte[] checkByteArray(int index) { | |
| check(); | |
| if (!isString(index)) { | |
| throw getArgTypeException(index, LuaType.STRING); | |
| } | |
| return toByteArray(index); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a string or a | |
| * number. If so, the argument value is returned as a byte array. If the | |
| * value of the specified argument is undefined or <code>nil</code>, the | |
| * method returns the specified default value. Otherwise, the method throws | |
| * a Lua runtime exception with a descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param d | |
| * the default value | |
| * @return the string value, or the default value | |
| */ | |
| public synchronized byte[] checkByteArray(int index, byte[] d) { | |
| check(); | |
| if (isNoneOrNil(index)) { | |
| return d; | |
| } | |
| return checkByteArray(index); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a string or a | |
| * number matching the name of one of the specified enum values. If so, the | |
| * argument value is returned as an enum value. Otherwise, the method throws | |
| * a Lua runtime exception with a descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param values | |
| * the enum values | |
| * @return the string value | |
| * @since JNLua 1.0.0 | |
| */ | |
| public synchronized <T extends Enum<T>> T checkEnum(int index, T[] values) { | |
| check(); | |
| return checkEnum(index, values, null); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a string or a | |
| * number matching one of the specified enum values. If so, the argument | |
| * value is returned as an enum value. If the specified stack index is | |
| * non-valid or if its value is <code>nil</code>, the method returns the | |
| * specified default value. Otherwise, the method throws a Lua runtime | |
| * exception with a descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param values | |
| * the enum values | |
| * @param d | |
| * the default value | |
| * @return the string value, or the default value | |
| * @since JNLua 1.0.0 | |
| */ | |
| public synchronized <T extends Enum<T>> T checkEnum(int index, T[] values, | |
| T d) { | |
| check(); | |
| String s = d != null ? checkString(index, d.name()) | |
| : checkString(index); | |
| for (int i = 0; i < values.length; i++) { | |
| if (values[i].name().equals(s)) { | |
| return values[i]; | |
| } | |
| } | |
| throw getArgException(index, String.format("invalid option '%s'", s)); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a number or a | |
| * string convertible to a number. If so, the argument value is returned as | |
| * an integer. Otherwise, the method throws a Lua runtime exception with a | |
| * descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @return the integer value | |
| */ | |
| public synchronized int checkInteger(int index) { | |
| check(); | |
| Integer integer = toIntegerX(index); | |
| if (integer == null) { | |
| throw getArgTypeException(index, LuaType.NUMBER); | |
| } | |
| return integer.intValue(); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a number or a | |
| * string convertible to a number. If so, the argument value is returned as | |
| * an integer. If the specified stack index is non-valid or if its value is | |
| * <code>nil</code>, the method returns the specified default value. | |
| * Otherwise, the method throws a Lua runtime exception with a descriptive | |
| * error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param d | |
| * the default value | |
| * @return the integer value, or the default value | |
| */ | |
| public synchronized int checkInteger(int index, int d) { | |
| check(); | |
| if (isNoneOrNil(index)) { | |
| return d; | |
| } | |
| return checkInteger(index); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is convertible to | |
| * a Java object of the specified type. If so, the argument value is | |
| * returned as a Java object of the specified type. Otherwise, the method | |
| * throws a Lua runtime exception with a descriptive error message. | |
| * | |
| * <p> | |
| * Note that the converter converts <code>nil</code> to <code>null</code>. | |
| * Therefore, the method may return <code>null</code> if the value is | |
| * <code>nil</code>. | |
| * </p> | |
| * | |
| * @param index | |
| * the argument index | |
| * @param clazz | |
| * the expected type | |
| * @return the Java object, or <code>null</code> | |
| */ | |
| public synchronized <T> T checkJavaObject(int index, Class<T> clazz) { | |
| check(); | |
| if (!isJavaObject(index, clazz)) { | |
| checkArg( | |
| index, | |
| false, | |
| String.format("%s expected, got %s", | |
| clazz.getCanonicalName(), typeName(index))); | |
| } | |
| return toJavaObject(index, clazz); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is convertible to | |
| * a Java object of the specified type. If so, the argument value is | |
| * returned as a Java object of the specified type. If the specified stack | |
| * index is non-valid or if its value is <code>nil</code>, the method | |
| * returns the specified default value. Otherwise, the method throws a Lua | |
| * runtime exception with a descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param clazz | |
| * the expected class | |
| * @param d | |
| * the default value | |
| * @return the Java object, or the default value | |
| */ | |
| public synchronized <T> T checkJavaObject(int index, Class<T> clazz, T d) { | |
| check(); | |
| if (isNoneOrNil(index)) { | |
| return d; | |
| } | |
| return checkJavaObject(index, clazz); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a number or a | |
| * string convertible to a number. If so, the argument value is returned as | |
| * a number. Otherwise, the method throws a Lua runtime exception with a | |
| * descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @return the number value | |
| */ | |
| public synchronized double checkNumber(int index) { | |
| check(); | |
| Double number = toNumberX(index); | |
| if (number == null) { | |
| throw getArgTypeException(index, LuaType.NUMBER); | |
| } | |
| return number.doubleValue(); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a number or a | |
| * string convertible to a number. If so, the argument value is returned as | |
| * a number. If the specified stack index is non-valid or if its value is | |
| * <code>nil</code>, the method returns the specified default value. | |
| * Otherwise, the method throws a Lua runtime exception with a descriptive | |
| * error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param d | |
| * the default value | |
| * @return the number value, or the default value | |
| */ | |
| public synchronized double checkNumber(int index, double d) { | |
| check(); | |
| if (isNoneOrNil(index)) { | |
| return d; | |
| } | |
| return checkNumber(index); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a string or a | |
| * number matching one of the specified options. If so, the index position | |
| * of the matched option is returned. Otherwise, the method throws a Lua | |
| * runtime exception with a descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param options | |
| * the options | |
| * @return the index position of the matched option | |
| */ | |
| public synchronized int checkOption(int index, String[] options) { | |
| check(); | |
| return checkOption(index, options, null); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a string or a | |
| * number matching one of the specified options. If so, the index position | |
| * of the matched option is returned. If the specified stack index is | |
| * non-valid or if its value is <code>nil</code>, the method matches the | |
| * specified default value. If no match is found, the method throws a Lua | |
| * runtime exception with a descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param options | |
| * the options | |
| * @param d | |
| * the default value | |
| * @return the index position of the matched option | |
| */ | |
| public synchronized int checkOption(int index, String[] options, String d) { | |
| check(); | |
| String s = d != null ? checkString(index, d) : checkString(index); | |
| for (int i = 0; i < options.length; i++) { | |
| if (options[i].equals(s)) { | |
| return i; | |
| } | |
| } | |
| throw getArgException(index, String.format("invalid option '%s'", s)); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a string or a | |
| * number. If so, the argument value is returned as a string. Otherwise, the | |
| * method throws a Lua runtime exception with a descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @return the string value | |
| */ | |
| public synchronized String checkString(int index) { | |
| check(); | |
| if (!isString(index)) { | |
| throw getArgTypeException(index, LuaType.STRING); | |
| } | |
| return toString(index); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is a string or a | |
| * number. If so, the argument value is returned as a string. If the | |
| * specified stack index is non-valid or if its value is <code>nil</code>, | |
| * the method returns the specified default value. Otherwise, the method | |
| * throws a Lua runtime exception with a descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param d | |
| * the default value | |
| * @return the string value, or the default value | |
| */ | |
| public synchronized String checkString(int index, String d) { | |
| check(); | |
| if (isNoneOrNil(index)) { | |
| return d; | |
| } | |
| return checkString(index); | |
| } | |
| /** | |
| * Checks if the value of the specified function argument is of the | |
| * specified type. If not, the method throws a Lua runtime exception with a | |
| * descriptive error message. | |
| * | |
| * @param index | |
| * the argument index | |
| * @param type | |
| * the type | |
| */ | |
| public synchronized void checkType(int index, LuaType type) { | |
| check(); | |
| if (type(index) != type) { | |
| throw getArgTypeException(index, type); | |
| } | |
| } | |
| // -- Proxy | |
| /** | |
| * Returns a proxy object for the Lua value at the specified index. | |
| * | |
| * @param index | |
| * the stack index containing the Lua value | |
| * @return the Lua value proxy | |
| */ | |
| public synchronized LuaValueProxy getProxy(int index) { | |
| check(); | |
| pushValue(index); | |
| return new LuaValueProxyImpl(ref(REGISTRYINDEX)); | |
| } | |
| /** | |
| * Returns a proxy object implementing the specified interface in Lua. The | |
| * table at the specified stack index contains the method names from the | |
| * interface as keys and the Lua functions implementing the interface | |
| * methods as values. The returned object always implements the | |
| * {@link LuaValueProxy} interface in addition to the specified interface. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @param interfaze | |
| * the interface | |
| * @return the proxy object | |
| */ | |
| @SuppressWarnings("unchecked") | |
| public synchronized <T> T getProxy(int index, Class<T> interfaze) { | |
| check(); | |
| return (T) getProxy(index, new Class<?>[] { interfaze }); | |
| } | |
| /** | |
| * Returns a proxy object implementing the specified list of interfaces in | |
| * Lua. The table at the specified stack index contains the method names | |
| * from the interfaces as keys and the Lua functions implementing the | |
| * interface methods as values. The returned object always implements the | |
| * {@link LuaValueProxy} interface in addition to the specified interfaces. | |
| * | |
| * @param index | |
| * the stack index containing the table | |
| * @param interfaces | |
| * the interfaces | |
| * @return the proxy object | |
| */ | |
| public synchronized LuaValueProxy getProxy(int index, Class<?>[] interfaces) { | |
| check(); | |
| pushValue(index); | |
| if (!isTable(index)) { | |
| throw new IllegalArgumentException(String.format( | |
| "index %d is not a table", index)); | |
| } | |
| Class<?>[] allInterfaces = new Class<?>[interfaces.length + 1]; | |
| System.arraycopy(interfaces, 0, allInterfaces, 0, interfaces.length); | |
| allInterfaces[allInterfaces.length - 1] = LuaValueProxy.class; | |
| int reference = ref(REGISTRYINDEX); | |
| try { | |
| Object proxy = Proxy.newProxyInstance(classLoader, allInterfaces, | |
| new LuaInvocationHandler(reference)); | |
| reference = -1; | |
| return (LuaValueProxy) proxy; | |
| } finally { | |
| if (reference >= 0) { | |
| unref(REGISTRYINDEX, reference); | |
| } | |
| } | |
| } | |
| // -- Private methods | |
| /** | |
| * Returns whether this Lua state is open. | |
| */ | |
| private boolean isOpenInternal() { | |
| return luaState != 0L; | |
| } | |
| /** | |
| * Closes this Lua state. | |
| */ | |
| private void closeInternal() { | |
| if (isOpenInternal()) { | |
| lua_close(ownState); | |
| if (isOpenInternal()) { | |
| throw new IllegalStateException("cannot close"); | |
| } | |
| } | |
| } | |
| /** | |
| * Checks this Lua state. | |
| */ | |
| private void check() { | |
| // Check open | |
| if (!isOpenInternal()) { | |
| throw new IllegalStateException("Lua state is closed"); | |
| } | |
| // Check proxy queue | |
| LuaValueProxyRef luaValueProxyRef; | |
| while ((luaValueProxyRef = (LuaValueProxyRef) proxyQueue.poll()) != null) { | |
| proxySet.remove(luaValueProxyRef); | |
| lua_unref(REGISTRYINDEX, luaValueProxyRef.getReference()); | |
| } | |
| } | |
| /** | |
| * Creates a Lua runtime exception to indicate an argument type error. | |
| */ | |
| private LuaRuntimeException getArgTypeException(int index, LuaType type) { | |
| return getArgException(index, | |
| String.format("%s expected, got %s", type.toString() | |
| .toLowerCase(), type(index).toString().toLowerCase())); | |
| } | |
| /** | |
| * Creates a Lua runtime exception to indicate an argument error. | |
| * | |
| * @param extraMsg | |
| * @return | |
| */ | |
| private LuaRuntimeException getArgException(int index, String extraMsg) { | |
| check(); | |
| // Get execution point | |
| String name = null, nameWhat = null; | |
| LuaDebug luaDebug = lua_getstack(0); | |
| if (luaDebug != null) { | |
| lua_getinfo("n", luaDebug); | |
| name = luaDebug.getName(); | |
| nameWhat = luaDebug.getNameWhat(); | |
| } | |
| // Adjust for methods | |
| if ("method".equals(nameWhat)) { | |
| index--; | |
| } | |
| // Format message | |
| String msg; | |
| String argument = index > 0 ? String.format("argument #%d", index) | |
| : "self argument"; | |
| if (name != null) { | |
| msg = String | |
| .format("bad %s to '%s' (%s)", argument, name, extraMsg); | |
| } else { | |
| msg = String.format("bad %s (%s)", argument, extraMsg); | |
| } | |
| return new LuaRuntimeException(msg); | |
| } | |
| // -- Native methods | |
| private static native int lua_registryindex(); | |
| private static native String lua_version(); | |
| private native void lua_newstate(int apiversion, long luaState); | |
| private native void lua_close(boolean ownState); | |
| private native int lua_gc(int what, int data); | |
| private native void lua_openlib(int lib); | |
| private native void lua_load(InputStream inputStream, String chunkname, | |
| String mode) throws IOException; | |
| private native void lua_dump(OutputStream outputStream) throws IOException; | |
| private native void lua_pcall(int nargs, int nresults); | |
| private native void lua_getglobal(String name); | |
| private native void lua_setglobal(String name); | |
| private native void lua_pushboolean(int b); | |
| private native void lua_pushbytearray(byte[] b); | |
| private native void lua_pushinteger(int n); | |
| private native void lua_pushjavafunction(JavaFunction f); | |
| private native void lua_pushjavaobject(Object object); | |
| private native void lua_pushnil(); | |
| private native void lua_pushnumber(double n); | |
| private native void lua_pushstring(String s); | |
| private native int lua_isboolean(int index); | |
| private native int lua_iscfunction(int index); | |
| private native int lua_isfunction(int index); | |
| private native int lua_isjavafunction(int index); | |
| private native int lua_isjavaobject(int index); | |
| private native int lua_isnil(int index); | |
| private native int lua_isnone(int index); | |
| private native int lua_isnoneornil(int index); | |
| private native int lua_isnumber(int index); | |
| private native int lua_isstring(int index); | |
| private native int lua_istable(int index); | |
| private native int lua_isthread(int index); | |
| private native int lua_compare(int index1, int index2, int operator); | |
| private native int lua_rawequal(int index1, int index2); | |
| private native int lua_rawlen(int index); | |
| private native int lua_toboolean(int index); | |
| private native byte[] lua_tobytearray(int index); | |
| private native int lua_tointeger(int index); | |
| private native Integer lua_tointegerx(int index); | |
| private native JavaFunction lua_tojavafunction(int index); | |
| private native Object lua_tojavaobject(int index); | |
| private native double lua_tonumber(int index); | |
| private native Double lua_tonumberx(int index); | |
| private native long lua_topointer(int index); | |
| private native String lua_tostring(int index); | |
| private native int lua_type(int index); | |
| private native int lua_absindex(int index); | |
| private native int lua_arith(int operator); | |
| private native void lua_concat(int n); | |
| private native int lua_copy(int fromIndex, int toIndex); | |
| private native int lua_gettop(); | |
| private native void lua_len(int index); | |
| private native void lua_insert(int index); | |
| private native void lua_pop(int n); | |
| private native void lua_pushvalue(int index); | |
| private native void lua_remove(int index); | |
| private native void lua_replace(int index); | |
| private native void lua_settop(int index); | |
| private native void lua_createtable(int narr, int nrec); | |
| private native int lua_getsubtable(int idx, String fname); | |
| private native void lua_gettable(int index); | |
| private native void lua_getfield(int index, String k); | |
| private native void lua_newtable(); | |
| private native int lua_next(int index); | |
| private native void lua_rawget(int index); | |
| private native void lua_rawgeti(int index, int n); | |
| private native void lua_rawset(int index); | |
| private native void lua_rawseti(int index, int n); | |
| private native void lua_settable(int index); | |
| private native void lua_setfield(int index, String k); | |
| private native int lua_getmetatable(int index); | |
| private native void lua_setmetatable(int index); | |
| private native int lua_getmetafield(int index, String k); | |
| private native void lua_newthread(); | |
| private native int lua_resume(int index, int nargs); | |
| private native int lua_status(int index); | |
| private native int lua_ref(int index); | |
| private native void lua_unref(int index, int ref); | |
| private native LuaDebug lua_getstack(int level); | |
| private native int lua_getinfo(String what, LuaDebug ar); | |
| private native int lua_tablesize(int index); | |
| private native void lua_tablemove(int index, int from, int to, int count); | |
| // -- Enumerated types | |
| /** | |
| * Represents a Lua library. | |
| */ | |
| public enum Library { | |
| /* | |
| * The order of the libraries follows the definition in linit.c. | |
| */ | |
| /** | |
| * The base library. | |
| */ | |
| BASE, | |
| /** | |
| * The package library. | |
| */ | |
| PACKAGE, | |
| /** | |
| * The coroutine library. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| COROUTINE, | |
| /** | |
| * The table library. | |
| */ | |
| TABLE, | |
| /** | |
| * The IO library. | |
| */ | |
| IO, | |
| /** | |
| * The OS library. | |
| */ | |
| OS, | |
| /** | |
| * The string library. | |
| */ | |
| STRING, | |
| /** | |
| * The bit32 library. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| BIT32, | |
| /** | |
| * The math library. | |
| */ | |
| MATH, | |
| /** | |
| * The debug library. | |
| */ | |
| DEBUG, | |
| /** | |
| * The Java library. | |
| */ | |
| JAVA { | |
| @Override | |
| void open(LuaState luaState) { | |
| JavaModule.getInstance().open(luaState); | |
| } | |
| }; | |
| // -- Methods | |
| /** | |
| * Opens this library. | |
| */ | |
| void open(LuaState luaState) { | |
| luaState.lua_openlib(ordinal()); | |
| } | |
| } | |
| /** | |
| * Represents a Lua garbage collector action. Please see the Lua Reference | |
| * Manual for an explanation of these actions. | |
| */ | |
| public enum GcAction { | |
| /** | |
| * Stop. | |
| */ | |
| STOP, | |
| /** | |
| * Restart. | |
| */ | |
| RESTART, | |
| /** | |
| * Collect. | |
| */ | |
| COLLECT, | |
| /** | |
| * Count memory in kilobytes. | |
| */ | |
| COUNT, | |
| /** | |
| * Count reminder in bytes. | |
| */ | |
| COUNTB, | |
| /** | |
| * Step. | |
| */ | |
| STEP, | |
| /** | |
| * Set pause. | |
| */ | |
| SETPAUSE, | |
| /** | |
| * Set step multiplier. | |
| */ | |
| SETSTEPMUL, | |
| /** | |
| * Undocumented. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| SETMAJORINC, | |
| /** | |
| * Returns whether the collector is running (i.e. not stopped). | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| ISRUNNING, | |
| /** | |
| * Changes the collector to the generational mode. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| GEN, | |
| /** | |
| * Changes the collector to the incremental mode. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| INC | |
| } | |
| /** | |
| * Represents a Lua arithmetic operator. Please see the Lua Reference Manual | |
| * for an explanation of these operators. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| public enum ArithOperator { | |
| /** | |
| * Addition operator. | |
| */ | |
| ADD, | |
| /** | |
| * Subtraction operator. | |
| */ | |
| SUB, | |
| /** | |
| * Multiplication operator. | |
| */ | |
| MUL, | |
| /** | |
| * Division operator. | |
| */ | |
| DIV, | |
| /** | |
| * Modulo operator. | |
| */ | |
| MOD, | |
| /** | |
| * Exponentiation operator. | |
| */ | |
| POW, | |
| /** | |
| * Mathematical negation operator. | |
| */ | |
| UNM | |
| } | |
| /** | |
| * Represents a Lua relational operator. Please see the Lua Reference Manual | |
| * for an explanation of these operators. | |
| * | |
| * @since JNLua 1.0.0 | |
| */ | |
| public enum RelOperator { | |
| /** | |
| * Equality operator. | |
| */ | |
| EQ, | |
| /** | |
| * Less than operator. | |
| */ | |
| LT, | |
| /** | |
| * Less or equal operator. | |
| */ | |
| LE | |
| } | |
| // -- Nested types | |
| /** | |
| * Phantom reference to a Lua value proxy for pre-mortem cleanup. | |
| */ | |
| private static class LuaValueProxyRef extends | |
| PhantomReference<LuaValueProxyImpl> { | |
| // -- State | |
| private int reference; | |
| // --Construction | |
| /** | |
| * Creates a new instance. | |
| */ | |
| public LuaValueProxyRef(LuaValueProxyImpl luaProxyImpl, int reference) { | |
| super(luaProxyImpl, luaProxyImpl.getLuaState().proxyQueue); | |
| this.reference = reference; | |
| } | |
| // -- Properties | |
| /** | |
| * Returns the reference. | |
| */ | |
| public int getReference() { | |
| return reference; | |
| } | |
| } | |
| /** | |
| * Lua value proxy implementation. | |
| */ | |
| private class LuaValueProxyImpl implements LuaValueProxy { | |
| // -- State | |
| private int reference; | |
| // -- Construction | |
| /** | |
| * Creates a new instance. | |
| */ | |
| public LuaValueProxyImpl(int reference) { | |
| this.reference = reference; | |
| proxySet.add(new LuaValueProxyRef(this, reference)); | |
| } | |
| // -- LuaProxy methods | |
| @Override | |
| public LuaState getLuaState() { | |
| return LuaState.this; | |
| } | |
| @Override | |
| public void pushValue() { | |
| synchronized (LuaState.this) { | |
| rawGet(REGISTRYINDEX, reference); | |
| } | |
| } | |
| } | |
| /** | |
| * Invocation handler for implementing Java interfaces in Lua. | |
| */ | |
| private class LuaInvocationHandler extends LuaValueProxyImpl implements | |
| InvocationHandler { | |
| // -- Construction | |
| /** | |
| * Creates a new instance. | |
| */ | |
| public LuaInvocationHandler(int reference) { | |
| super(reference); | |
| } | |
| // -- InvocationHandler methods | |
| @Override | |
| public Object invoke(Object proxy, Method method, Object[] args) | |
| throws Throwable { | |
| // Handle LuaProxy methods | |
| if (method.getDeclaringClass() == LuaValueProxy.class) { | |
| return method.invoke(this, args); | |
| } | |
| // Handle Lua calls | |
| synchronized (LuaState.this) { | |
| pushValue(); | |
| getField(-1, method.getName()); | |
| if (!isFunction(-1)) { | |
| pop(2); | |
| throw new UnsupportedOperationException(method.getName()); | |
| } | |
| insert(-2); | |
| int argCount = args != null ? args.length : 0; | |
| for (int i = 0; i < argCount; i++) { | |
| pushJavaObject(args[i]); | |
| } | |
| int retCount = method.getReturnType() != Void.TYPE ? 1 : 0; | |
| call(argCount + 1, retCount); | |
| try { | |
| return retCount == 1 ? LuaState.this.toJavaObject(-1, | |
| method.getReturnType()) : null; | |
| } finally { | |
| if (retCount == 1) { | |
| pop(1); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Lua debug structure. | |
| */ | |
| private static class LuaDebug { | |
| /** | |
| * The <code>lua_Debug</code> pointer on the JNI side. <code>0</code> | |
| * implies that the activation record has been freed. The field is | |
| * modified exclusively on the JNI side and must not be touched on the | |
| * Java side. | |
| */ | |
| private long luaDebug; | |
| /** | |
| * Ensures proper finalization of this Lua debug structure. | |
| */ | |
| private Object finalizeGuardian; | |
| /** | |
| * Creates a new instance. | |
| */ | |
| private LuaDebug(long luaDebug, boolean ownDebug) { | |
| this.luaDebug = luaDebug; | |
| if (ownDebug) { | |
| finalizeGuardian = new Object() { | |
| @Override | |
| public void finalize() { | |
| synchronized (LuaDebug.this) { | |
| lua_debugfree(); | |
| } | |
| } | |
| }; | |
| } | |
| } | |
| // -- Properties | |
| /** | |
| * Returns a reasonable name for the function given by this activation | |
| * record, or <code>null</code> if none is found. | |
| */ | |
| public String getName() { | |
| return lua_debugname(); | |
| } | |
| /** | |
| * Explains the name of the function given by this activation record. | |
| */ | |
| public String getNameWhat() { | |
| return lua_debugnamewhat(); | |
| } | |
| // -- Native methods | |
| private native void lua_debugfree(); | |
| private native String lua_debugname(); | |
| private native String lua_debugnamewhat(); | |
| } | |
| } |