|  | /* | 
|  | * $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; | 
|  |  | 
|  | /** | 
|  | * The maximum amount of memory the may be used by the Lua state, in bytes. | 
|  | * This can be adjusted to limit the amount of memory a state may use. If | 
|  | * it is reduced while a VM is active this can very quickly lead to out of | 
|  | * memory errors. | 
|  | */ | 
|  | private int luaMemoryTotal; | 
|  |  | 
|  | /** | 
|  | * The amount of memory currently used by the Lua state, in bytes. This is | 
|  | * set from the JNI side and must not be modified from the Java side. | 
|  | */ | 
|  | private int luaMemoryUsed; | 
|  |  | 
|  | /** | 
|  | * 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. The Lua | 
|  | * state may allocate as much memory as it wants. | 
|  | * | 
|  | * @see #getClassLoader() | 
|  | * @see #setClassLoader(ClassLoader) | 
|  | * @see #getJavaReflector() | 
|  | * @see #setJavaReflector(JavaReflector) | 
|  | * @see #getConverter() | 
|  | * @see #setConverter(Converter) | 
|  | */ | 
|  | public LuaState() { | 
|  | this(0L, 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * 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. The Lua | 
|  | * state may allocate only as much memory as specified. This is enforced | 
|  | * by a custom allocator that is only used if a maximum memory is given. | 
|  | * | 
|  | * @param memory | 
|  | *            the maximum amount of memory this Lua state may use, in bytes | 
|  | * @see #getClassLoader() | 
|  | * @see #setClassLoader(ClassLoader) | 
|  | * @see #getJavaReflector() | 
|  | * @see #setJavaReflector(JavaReflector) | 
|  | * @see #getConverter() | 
|  | * @see #setConverter(Converter) | 
|  | */ | 
|  | public LuaState(int memory) { | 
|  | this(0L, validateMemory(memory)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Creates a new instance. | 
|  | */ | 
|  | private LuaState(long luaState, int memory) { | 
|  | ownState = luaState == 0L; | 
|  | luaMemoryTotal = memory; | 
|  | 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; | 
|  | } | 
|  |  | 
|  | // -- Memory | 
|  | /** | 
|  | * Returns the maximum memory consumption of this Lua state. This is the | 
|  | * maximum raw memory Lua may allocate for this state, in bytes. | 
|  | * | 
|  | * @return the maximum memory consumption | 
|  | */ | 
|  | public synchronized int getTotalMemory() { | 
|  | return luaMemoryTotal; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the maximum amount of memory this Lua state may allocate. This is | 
|  | * the size of the raw memory the Lua library may allocate for this tate, | 
|  | * in bytes. Note that you can only set the maximum memory consumption for | 
|  | * states that were created to enforce a maximum memory consumption. | 
|  | * | 
|  | * @param value | 
|  | *            the new maximum memory size this state may allocate | 
|  | */ | 
|  | public synchronized void setTotalMemory(int value) { | 
|  | if (luaMemoryTotal < 1) { | 
|  | throw new IllegalStateException("cannot set maximum memory for this state"); | 
|  | } | 
|  | luaMemoryTotal = validateMemory(value); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the current amount of unused memory by this Lua state. This is | 
|  | * the size of the total available memory minus the raw memory currently | 
|  | * allocated by this state, in bytes. | 
|  | * | 
|  | * This is guaranteed to be less or equal to {@link #getTotalMemory()} and | 
|  | * larger or equal to zero. | 
|  | * | 
|  | * This only returns something not zero if a maximum memory consumption is | 
|  | * enforced by this state. Otherwise it will always return zero. | 
|  | * | 
|  | * @return the current memory consumption | 
|  | */ | 
|  | public synchronized int getFreeMemory() { | 
|  | // This is the reason we use free amount instead of used amount: if we | 
|  | // lower the max memory we can get below used memory, which would be | 
|  | // weird; so we just say free memory is zero, which is more intuitive | 
|  | // and true at the same time. | 
|  | return Math.max(0, luaMemoryTotal - luaMemoryUsed); | 
|  | } | 
|  |  | 
|  | // -- 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(); | 
|  | converter.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 boolean. If | 
|  | * so, the argument value is returned as a boolean. Otherwise, the method | 
|  | * throws a Lua runtime exception with a descriptive error message. | 
|  | * | 
|  | * @param index | 
|  | *            the argument index | 
|  | * @return the integer value | 
|  | */ | 
|  | public synchronized boolean checkBoolean(int index) { | 
|  | check(); | 
|  | if (!isBoolean(index)) { | 
|  | throw getArgTypeException(index, LuaType.BOOLEAN); | 
|  | } | 
|  | return toBoolean(index); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * 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); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Validates a value specified as the new maximum allowed memory use. This | 
|  | * is used in particular to validate values passed to the constructor. | 
|  | * | 
|  | * @param value | 
|  | *            the value to validate | 
|  | * @return the value itself | 
|  | */ | 
|  | private static int validateMemory(int value) { | 
|  | if (value < 1) { | 
|  | throw new IllegalArgumentException("Maximum memory must be larger than zero."); | 
|  | } | 
|  | return value; | 
|  | } | 
|  |  | 
|  | // -- 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 persistence library. | 
|  | */ | 
|  | ERIS, | 
|  |  | 
|  | /** | 
|  | * 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(); | 
|  | } | 
|  | } |