diff --git a/src/core/org/luaj/vm2/Buffer.java b/src/core/org/luaj/vm2/Buffer.java index 58650783..7083ca8b 100644 --- a/src/core/org/luaj/vm2/Buffer.java +++ b/src/core/org/luaj/vm2/Buffer.java @@ -24,21 +24,49 @@ package org.luaj.vm2; /** * String buffer for use in string library methods, optimized for production - * of StrValue instances. + * of StrValue instances. + *
+ * The buffer can begin initially as a wrapped {@link LuaValue} + * and only when concatenation actually occurs are the bytes first copied. + *
+ * To convert back to a {@link LuaValue} again, + * the function {@link Buffer#value()} is used. + * @see LuaValue + * @see LuaValue#buffer() + * @see LuaString */ public final class Buffer { + + /** Default capacity for a buffer: 64 */ private static final int DEFAULT_CAPACITY = 64; + + /** Shared static array with no bytes */ private static final byte[] NOBYTES = {}; + /** Bytes in this buffer */ private byte[] bytes; + + /** Length of this buffer */ private int length; + + /** Offset into the byte array */ private int offset; + + /** Value of this buffer, when not represented in bytes */ private LuaValue value; + /** + * Create buffer with default capacity + * @see #DEFAULT_CAPACITY + */ public Buffer() { this(DEFAULT_CAPACITY); } + /** + * Create buffer with specified initial capacity + * @param initialCapacity the initial capacity + */ public Buffer( int initialCapacity ) { bytes = new byte[ initialCapacity ]; length = 0; @@ -46,16 +74,28 @@ public final class Buffer { value = null; } + /** + * Create buffer with specified initial value + * @param value the initial value + */ public Buffer(LuaValue value) { bytes = NOBYTES; length = offset = 0; this.value = value; } - + + /** + * Get buffer contents as a {@link LuaValue} + * @return value as a {@link LuaValue}, converting as necessary + */ public LuaValue value() { return value != null? value: this.tostring(); } + /** + * Set buffer contents as a {@link LuaValue} + * @param value value to set + */ public Buffer setvalue(LuaValue value) { bytes = NOBYTES; offset = length = 0; @@ -63,30 +103,54 @@ public final class Buffer { return this; } + /** + * Convert the buffer to a {@link LuaString} + * @return the value as a {@link LuaString} + */ public final LuaString tostring() { realloc( length, 0 ); return LuaString.valueOf( bytes, offset, length ); } + /** + * Convert the buffer to a Java String + * @return the value as a Java String + */ public String tojstring() { return value().tojstring(); } + /** + * Convert the buffer to a Java String + * @return the value as a Java String + */ public String toString() { return tojstring(); } + /** + * Append a single byte to the buffer. + * @return {@code this} to allow call chaining + */ public final Buffer append( byte b ) { makeroom( 0, 1 ); bytes[ offset + length++ ] = b; return this; } + /** + * Append a {@link LuaValue} to the buffer. + * @return {@code this} to allow call chaining + */ public final Buffer append( LuaValue val ) { append( val.strvalue() ); return this; } + /** + * Append a {@link LuaString} to the buffer. + * @return {@code this} to allow call chaining + */ public final Buffer append( LuaString str ) { final int n = str.m_length; makeroom( 0, n ); @@ -95,6 +159,12 @@ public final class Buffer { return this; } + /** + * Append a Java String to the buffer. + * The Java string will be converted to bytes using the UTF8 encoding. + * @return {@code this} to allow call chaining + * @see LuaString#encodeToUtf8(char[], byte[], int) + */ public final Buffer append( String str ) { char[] chars = str.toCharArray(); final int n = LuaString.lengthAsUtf8( chars ); @@ -104,18 +174,36 @@ public final class Buffer { return this; } + /** Concatenate this buffer onto a {@link LuaValue} + * @param lhs the left-hand-side value onto which we are concatenating {@code this} + * @return {@link Buffer} for use in call chaining. + */ public Buffer concatTo(LuaValue lhs) { return setvalue(lhs.concat(value())); } + /** Concatenate this buffer onto a {@link LuaString} + * @param lhs the left-hand-side value onto which we are concatenating {@code this} + * @return {@link Buffer} for use in call chaining. + */ public Buffer concatTo(LuaString lhs) { return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs); } + /** Concatenate this buffer onto a {@link LuaNumber} + *
+ * The {@link LuaNumber} will be converted to a string before concatenating. + * @param lhs the left-hand-side value onto which we are concatenating {@code this} + * @return {@link Buffer} for use in call chaining. + */ public Buffer concatTo(LuaNumber lhs) { return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs.strvalue()); } + /** Concatenate bytes from a {@link LuaString} onto the front of this buffer + * @param s the left-hand-side value which we will concatenate onto the front of {@code this} + * @return {@link Buffer} for use in call chaining. + */ public Buffer prepend(LuaString s) { int n = s.m_length; makeroom( n, 0 ); @@ -126,6 +214,10 @@ public final class Buffer { return this; } + /** Ensure there is enough room before and after the bytes. + * @param nbefore number of unused bytes which must precede the data after this completes + * @param nafter number of unused bytes which must follow the data after this completes + */ public final void makeroom( int nbefore, int nafter ) { if ( value != null ) { LuaString s = value.strvalue(); @@ -141,6 +233,10 @@ public final class Buffer { } } + /** Reallocate the internal storage for the buffer + * @param newSize the size of the buffer to use + * @param newOffset the offset to use + */ private final void realloc( int newSize, int newOffset ) { if ( newSize != bytes.length ) { byte[] newBytes = new byte[ newSize ]; diff --git a/src/core/org/luaj/vm2/LoadState.java b/src/core/org/luaj/vm2/LoadState.java index c74ac435..60bfe7a6 100644 --- a/src/core/org/luaj/vm2/LoadState.java +++ b/src/core/org/luaj/vm2/LoadState.java @@ -25,8 +25,14 @@ import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; -/* -** Loader to load compiled function prototypes +/** +* Class to manage loading of {@link Prototype} instances. +*
+* @see LuaCompiler +* @see LuaClosure +* @see LuaFunction +* @see LoadState#compiler +* @see LoadState#load(InputStream, String, LuaValue) */ public class LoadState { @@ -53,7 +59,12 @@ public class LoadState { public static final int LUA_TTHREAD = 8; public static final int LUA_TVALUE = 9; - /** Interface for the compiler, if it is installed. */ + /** Interface for the compiler, if it is installed. + *
+ * See the {@link LuaClosure} documentation for examples of how to use the compiler. + * @see LuaClosure + * @see #load(InputStream, String, LuaValue) + * */ public interface LuaCompiler { /** Load into a Closure or LuaFunction from a Stream and initializes the environment @@ -106,6 +117,9 @@ public class LoadState { private byte[] buf = new byte[512]; + /** Load a 4-byte int value from the input stream + * @return the int value laoded. + **/ int loadInt() throws IOException { is.readFully(buf,0,4); return luacLittleEndian? @@ -113,6 +127,9 @@ public class LoadState { (buf[0] << 24) | ((0xff & buf[1]) << 16) | ((0xff & buf[2]) << 8) | (0xff & buf[3]); } + /** Load an array of int values from the input stream + * @return the array of int values laoded. + **/ int[] loadIntArray() throws IOException { int n = loadInt(); if ( n == 0 ) @@ -132,7 +149,9 @@ public class LoadState { return array; } - + /** Load a long value from the input stream + * @return the long value laoded. + **/ long loadInt64() throws IOException { int a,b; if ( this.luacLittleEndian ) { @@ -145,6 +164,9 @@ public class LoadState { return (((long)b)<<32) | (((long)a)&0xffffffffL); } + /** Load a lua strin gvalue from the input stream + * @return the {@link LuaString} value laoded. + **/ LuaString loadString() throws IOException { int size = loadInt(); if ( size == 0 ) @@ -154,6 +176,11 @@ public class LoadState { return LuaString.valueOf( bytes, 0, bytes.length - 1 ); } + /** + * Convert bits in a long value to a {@link LuaValue}. + * @param bits long value containing the bits + * @return {@link LuaInteger} or {@link LuaDouble} whose value corresponds to the bits provided. + */ public static LuaValue longBitsToLuaNumber( long bits ) { if ( ( bits & ( ( 1L << 63 ) - 1 ) ) == 0L ) { return LuaValue.ZERO; @@ -174,6 +201,11 @@ public class LoadState { return LuaValue.valueOf( Double.longBitsToDouble(bits) ); } + /** + * Load a number from a binary chunk + * @return the {@link LuaValue} loaded + * @throws IOException if an i/o exception occurs + */ LuaValue loadNumber() throws IOException { if ( luacNumberFormat == NUMBER_FORMAT_INTS_ONLY ) { return LuaInteger.valueOf( loadInt() ); @@ -182,6 +214,11 @@ public class LoadState { } } + /** + * Load a list of constants from a binary chunk + * @param f the function prototype + * @throws IOException if an i/o exception occurs + */ void loadConstants(Prototype f) throws IOException { int n = loadInt(); LuaValue[] values = n>0? new LuaValue[n]: NOVALUES; @@ -215,6 +252,11 @@ public class LoadState { f.p = protos; } + /** + * Load the debug infor for a function prototype + * @param f the function Prototype + * @throws IOException if there is an i/o exception + */ void loadDebug( Prototype f ) throws IOException { f.lineinfo = loadIntArray(); int n = loadInt(); @@ -233,6 +275,12 @@ public class LoadState { } } + /** + * Load a function prototype from the input stream + * @param p name of the source + * @return {@link Prototype} instance that was loaded + * @throws IOException + */ public Prototype loadFunction(LuaString p) throws IOException { Prototype f = new Prototype(); // this.L.push(f); @@ -257,6 +305,10 @@ public class LoadState { return f; } + /** + * Load the lua chunk header values. + * @throws IOException if an i/o exception occurs. + */ public void loadHeader() throws IOException { luacVersion = is.readByte(); luacFormat = is.readByte(); @@ -268,6 +320,15 @@ public class LoadState { luacNumberFormat = is.readByte(); } + /** + * Load lua in either binary or text form from an input stream. + * @param firstByte the first byte of the input stream + * @param stream InputStream to read, after having read the first byte already + * @param name Name to apply to the loaded chunk + * @return {@link Prototype} that was loaded + * @throws IllegalArgumentException if the signature is bac + * @throws IOException if an IOException occurs + */ public static LuaFunction load( InputStream stream, String name, LuaValue env ) throws IOException { if ( compiler != null ) return compiler.load(stream, name, env); @@ -280,6 +341,15 @@ public class LoadState { } } + /** + * Load lua thought to be a binary chunk from its first byte from an input stream. + * @param firstByte the first byte of the input stream + * @param stream InputStream to read, after having read the first byte already + * @param name Name to apply to the loaded chunk + * @return {@link Prototype} that was loaded + * @throws IllegalArgumentException if the signature is bac + * @throws IOException if an IOException occurs + */ public static Prototype loadBinaryChunk( int firstByte, InputStream stream, String name ) throws IOException { // check rest of signature @@ -306,6 +376,11 @@ public class LoadState { return s.loadFunction( LuaString.valueOf(sname) ); } + /** + * Construct a source name from a supplied chunk name + * @param name String name that appears in the chunk + * @return source file name + */ public static String getSourceName(String name) { String sname = name; if ( name.startsWith("@") || name.startsWith("=") ) diff --git a/src/core/org/luaj/vm2/LocVars.java b/src/core/org/luaj/vm2/LocVars.java index 5cb2d003..73e23b16 100644 --- a/src/core/org/luaj/vm2/LocVars.java +++ b/src/core/org/luaj/vm2/LocVars.java @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. +* Copyright (c) 2009-2011 Luaj.org. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,11 +21,25 @@ ******************************************************************************/ package org.luaj.vm2; +/** + * Data class to hold debug information relatign to local variables for a {@link Prototype} + */ public class LocVars { + /** The local variable name */ public LuaString varname; + + /** The instruction offset when the variable comes into scope */ public int startpc; + + /** The instruction offset when the variable goes out of scope */ public int endpc; + /** + * Construct a LocVars instance. + * @param varname The local variable name + * @param startpc The instruction offset when the variable comes into scope + * @param endpc The instruction offset when the variable goes out of scope + */ public LocVars(LuaString varname, int startpc, int endpc) { this.varname = varname; this.startpc = startpc; diff --git a/src/core/org/luaj/vm2/Lua.java b/src/core/org/luaj/vm2/Lua.java index 3f987864..93af012a 100644 --- a/src/core/org/luaj/vm2/Lua.java +++ b/src/core/org/luaj/vm2/Lua.java @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. +* Copyright (c) 2009-2011 Luaj.org. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,10 @@ package org.luaj.vm2; /** - * Constants for lua limits and opcodes + * Constants for lua limits and opcodes. + *
+ * This is a direct translation of C lua distribution header file constants + * for bytecode creation and processing. */ public class Lua { /** version is supplied by ant build task */ diff --git a/src/core/org/luaj/vm2/LuaBoolean.java b/src/core/org/luaj/vm2/LuaBoolean.java index 1dfe9113..41921741 100644 --- a/src/core/org/luaj/vm2/LuaBoolean.java +++ b/src/core/org/luaj/vm2/LuaBoolean.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Luaj.org. All rights reserved. + * Copyright (c) 2009-2011 Luaj.org. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,13 +21,36 @@ ******************************************************************************/ package org.luaj.vm2; +/** + * Extension of {@link LuaValue} which can hold a Java boolean as its value. + *
+ * These instance are not instantiated directly by clients. + * Instead, there are exactly twon instances of this class, + * {@link LuaValue#TRUE} and {@link LuaValue#FALSE} + * representing the lua values {@code true} and {@link false}. + * The function {@link LuaValue#valueOf(boolean)} will always + * return one of these two values. + *
+ * Any {@link LuaValue} can be converted to its equivalent + * boolean representation using {@link LuaValue#toboolean()} + *
+ * @see LuaValue + * @see LuaValue#valueOf(boolean) + * @see LuaValue#TRUE + * @see LuaValue#FALSE + */ public final class LuaBoolean extends LuaValue { + /** The singleton instance representing lua {@code true} */ static final LuaBoolean _TRUE = new LuaBoolean(true); + + /** The singleton instance representing lua {@code false} */ static final LuaBoolean _FALSE = new LuaBoolean(false); + /** Shared static metatable for boolean values represented in lua. */ public static LuaValue s_metatable; - + + /** The value of the boolean */ public final boolean v; LuaBoolean(boolean b) { @@ -50,6 +73,10 @@ public final class LuaBoolean extends LuaValue { return v ? FALSE : LuaValue.TRUE; } + /** + * Return the boolean value for this boolean + * @return value as a Java boolean + */ public boolean booleanValue() { return v; } diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/src/core/org/luaj/vm2/LuaClosure.java index df59c8e0..7b9cdc63 100644 --- a/src/core/org/luaj/vm2/LuaClosure.java +++ b/src/core/org/luaj/vm2/LuaClosure.java @@ -21,8 +21,74 @@ ******************************************************************************/ package org.luaj.vm2; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.luaj.vm2.LoadState.LuaCompiler; +import org.luaj.vm2.compiler.LuaC; import org.luaj.vm2.lib.DebugLib; +/** + * Extension of {@link LuaFunction} which executes lua bytecode. + *
+ * A {@link LuaClosure} is a combination of a {@link Prototype} + * and a {@link LuaValue} to use as an environment for execution. + *
+ * There are three main ways {@link LuaClosure} instances are created: + *
+ * To construct it directly, the {@link Prototype} is typically created via a compiler such as {@link LuaC}: + *
{@code
+ * InputStream is = new ByteArrayInputStream("print('hello,world').getBytes());
+ * Prototype p = LuaC.instance.compile(is, "script");
+ * LuaValue _G = JsePlatform.standardGlobals()
+ * LuaClosure f = new LuaClosure(p, _G);
+ * }
+ * + * To construct it indirectly, the {@link LuaC} compiler may be used, + * which implements the {@link LuaCompiler} interface: + *
{@code
+ * LuaFunction f = LuaC.instance.load(is, "script", _G);
+ * }
+ * + * Typically, a closure that has just been loaded needs to be initialized by executing it, + * and its return value can be saved if needed: + *
{@code
+ * LuaValue r = f.call();
+ * _G.set( "mypkg", r )
+ * }
+ * + * In the preceding, the loaded value is typed as {@link LuaFunction} + * to allow for the possibility of other compilers such as {@link LuaJC} + * producing {@link LuaFunction} directly without + * creating a {@link Prototype} or {@link LuaClosure}. + *
+ * Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue}, + * all the value operations can be used directly such as: + *
+ * {@link LuaError} is used wherever a lua call to {@code error()} + * would be used within a script. + *
+ * Since it is an unchecked exception inheriting from {@link RuntimeException}, + * Java method signatures do notdeclare this exception, althoug it can + * be thrown on almost any luaj Java operation. + * This is analagous to the fact that any lua script can throw a lua error at any time. + *
*/ public class LuaError extends RuntimeException { private static final long serialVersionUID = 1L; private String traceback; - /** Run the error hook if there is one */ + /** + * Run the error hook if there is one + * @param msg the message to use in error hook processing. + * */ private static String errorHook(String msg) { LuaThread thread = LuaThread.getRunning(); if ( thread.err != null ) { @@ -54,11 +62,10 @@ public class LuaError extends RuntimeException { private Throwable cause; - /** - * Construct a LuaErrorException in response to a Throwable that was caught - * indicating a problem with the VM rather than the lua code. - * - * All errors generated from lua code should throw LuaError(String) instead. + /** Construct LuaError when a program exception occurs. + *
+ * All errors generated from lua code should throw LuaError(String) instead. + * @param cause the Throwable that caused the error, if known. */ public LuaError(Throwable cause) { super( errorHook( addFileLine( "vm error: "+cause ) ) ); @@ -67,8 +74,7 @@ public class LuaError extends RuntimeException { } /** - * Construct a LuaError with a specific message indicating a problem - * within the lua code itself such as an argument type error. + * Construct a LuaError with a specific message. * * @param message message to supply */ @@ -78,6 +84,7 @@ public class LuaError extends RuntimeException { } /** + * Construct a LuaError with a message, and level to draw line number information from. * @param message message to supply * @param level where to supply line info from in call stack */ @@ -86,7 +93,11 @@ public class LuaError extends RuntimeException { this.traceback = DebugLib.traceback(1); } - /** Add file and line info to a message at a particular level */ + /** + * Add file and line info to a message at a particular level + * @param message the String message to use + * @param level where to supply line info from in call stack + * */ private static String addFileLine( String message, int level ) { if ( message == null ) return null; if ( level == 0 ) return message; @@ -94,19 +105,15 @@ public class LuaError extends RuntimeException { return fileline!=null? fileline+": "+message: message; } - /** Add file and line info for the nearest enclosing closure */ + /** Add file and line info for the nearest enclosing closure + * @param message the String message to use + * */ private static String addFileLine( String message ) { if ( message == null ) return null; String fileline = DebugLib.fileline(); return fileline!=null? fileline+": "+message: message; } -// /** Get the message, including source line info if there is any */ -// public String getMessage() { -// String msg = super.getMessage(); -// return msg!=null && traceback!=null? traceback+": "+msg: msg; -// } - /** Print the message and stack trace */ public void printStackTrace() { System.out.println( toString() ); diff --git a/src/core/org/luaj/vm2/LuaNil.java b/src/core/org/luaj/vm2/LuaNil.java index 78d147b3..f492ebdf 100644 --- a/src/core/org/luaj/vm2/LuaNil.java +++ b/src/core/org/luaj/vm2/LuaNil.java @@ -21,6 +21,21 @@ ******************************************************************************/ package org.luaj.vm2; +/** + * Class to encapsulate behavior of the singleton instance {@code nil} + *
+ * There will be one instance of this class, {@link LuaValue#NIL}, + * per Java virtual machine. + * However, the {@link Varargs} instance {@link LuaValue#NONE} + * which is the empty list, + * is also considered treated as a nil value by default. + *
+ * Although it is possible to test for nil using Java == operator, + * the recommended approach is to use the method {@link LuaValue#isnil()} + * instead. By using that any ambiguities between + * {@link LuaValue#NIL} and {@link LuaValue#NONE} are avoided. + * + */ public class LuaNil extends LuaValue { static final LuaNil _NIL = new LuaNil(); diff --git a/src/core/org/luaj/vm2/LuaString.java b/src/core/org/luaj/vm2/LuaString.java index eab8c0d4..50326eed 100644 --- a/src/core/org/luaj/vm2/LuaString.java +++ b/src/core/org/luaj/vm2/LuaString.java @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. +* Copyright (c) 2009-2011 Luaj.org. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,6 +21,7 @@ ******************************************************************************/ package org.luaj.vm2; + import java.io.ByteArrayInputStream; import java.io.DataOutputStream; import java.io.IOException; @@ -31,12 +32,44 @@ import java.util.Hashtable; import org.luaj.vm2.lib.MathLib; import org.luaj.vm2.lib.StringLib; +/** + * Subclass of {@link LuaValue} for representing lua strings. + *
+ * Because lua string values are more nearly sequences of bytes than + * sequences of characters or unicode code points, the {@link LuaString} + * implementation holds the string value in an internal byte array. + *
+ * {@link LuaString} values are generally not mutable once constructed, + * so multiple {@link LuaString} values can chare a single byte array. + *
+ * Currently {@link LuaString}s are pooled via a centrally managed weak table. + * To ensure that as many string values as possible take advantage of this, + * Constructors are not exposed directly. As with number, booleans, and nil, + * instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API. + *
+ * When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed. + * The functions + * {@link LuaString#lengthAsUtf8(char[]), + * {@link LuaString#encodeToUtf8(char[], byte[], int)}, and + * {@link LuaString#decodeAsUtf8(byte[], int, int) + * are used to convert back and forth between UTF8 byte arrays and character arrays. + * + * @see LuaValue + * @see LuaValue#valueOf(String) + * @see LuaValue#valueOf(byte[]) + */ public class LuaString extends LuaValue { + /** The singleton instance representing lua {@code true} */ public static LuaValue s_metatable; + /** The bytes for the string */ public final byte[] m_bytes; + + /** The offset into the byte array, 0 means start at the first byte */ public final int m_offset; + + /** The number of bytes that comprise this string */ public final int m_length; private static final Hashtable index_java = new Hashtable(); @@ -49,7 +82,13 @@ public class LuaString extends LuaValue { private final static void index_set(Hashtable indextable, Object key, LuaString value) { indextable.put(key, new WeakReference(value)); } - + + /** + * Get a {@link LuaString} instance whose bytes match + * the supplied Java String using the UTF8 encoding. + * @param string Java String containing characters to encode as UTF8 + * @return {@link LuaString} with UTF8 bytes corresponding to the supplied String + */ public static LuaString valueOf(String string) { LuaString s = index_get( index_java, string ); if ( s != null ) return s; @@ -60,11 +99,29 @@ public class LuaString extends LuaValue { index_set( index_java, string, s ); return s; } - + + // TODO: should this be deprecated or made private? + /** Construct a {@link LuaString} around a byte array without copying the contents. + *
+ * The array is used directly after this is called, so clients must not change contents. + *
+ * @param bytes byte buffer + * @param off offset into the byte buffer + * @param len length of the byte buffer + * @return {@link LuaString} wrapping the byte buffer + */ public static LuaString valueOf(byte[] bytes, int off, int len) { return new LuaString(bytes, off, len); } + /** Construct a {@link LuaString} using the supplied characters as byte values. + *
+ * Only th elow-order 8-bits of each character are used, the remainder is ignored. + *
+ * This is most useful for constructing byte sequences that do not conform to UTF8. + * @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array. + * @return {@link LuaString} wrapping a copy of the byte buffer + */ public static LuaString valueOf(char[] bytes) { int n = bytes.length; byte[] b = new byte[n]; @@ -73,10 +130,27 @@ public class LuaString extends LuaValue { return valueOf(b, 0, n); } + + /** Construct a {@link LuaString} around a byte array without copying the contents. + *
+ * The array is used directly after this is called, so clients must not change contents. + *
+ * @param bytes byte buffer + * @return {@link LuaString} wrapping the byte buffer + */ public static LuaString valueOf(byte[] bytes) { return valueOf(bytes, 0, bytes.length); } + /** Construct a {@link LuaString} around a byte array without copying the contents. + *
+ * The array is used directly after this is called, so clients must not change contents. + *
+ * @param bytes byte buffer + * @param offset offset into the byte buffer + * @param length length of the byte buffer + * @return {@link LuaString} wrapping the byte buffer + */ private LuaString(byte[] bytes, int offset, int length) { this.m_bytes = bytes; this.m_offset = offset; @@ -364,18 +438,29 @@ public class LuaString extends LuaValue { return this; } + /** Convert value to an input stream. + * + * @return {@link InputStream} whose data matches the bytes in this {@link LuaString} + */ public InputStream toInputStream() { return new ByteArrayInputStream(m_bytes, m_offset, m_length); } /** - * Copy the bytes of the string into the given byte array. + * Copy the bytes of the string into the given byte array. + * @param strOffset offset from which to copy + * @param bytes destination byte array + * @param arrayOffset offset in destination + * @param len number of bytes to copy */ public void copyInto( int strOffset, byte[] bytes, int arrayOffset, int len ) { System.arraycopy( m_bytes, m_offset+strOffset, bytes, arrayOffset, len ); } - /** Java version of strpbrk, which is a terribly named C function. */ + /** Java version of strpbrk - find index of any byte that in an accept string. + * @param accept {@link LuaString} containing characters to look for. + * @return index of first match in the {@code accept} string, or -1 if not found. + */ public int indexOfAny( LuaString accept ) { final int ilimit = m_offset + m_length; final int jlimit = accept.m_offset + accept.m_length; @@ -389,6 +474,12 @@ public class LuaString extends LuaValue { return -1; } + /** + * Find the index of a byte starting at a point in this string + * @param b the byte to look for + * @param start the first index in the string + * @return index of first match found, or -1 if not found. + */ public int indexOf( byte b, int start ) { for ( int i=0, j=m_offset+start; i < m_length; ++i ) { if ( m_bytes[j++] == b ) @@ -397,6 +488,12 @@ public class LuaString extends LuaValue { return -1; } + /** + * Find the index of a string starting at a point in this string + * @param s the string to search for + * @param start the first index in the string + * @return index of first match found, or -1 if not found. + */ public int indexOf( LuaString s, int start ) { final int slen = s.length(); final int limit = m_offset + m_length - slen; @@ -408,6 +505,11 @@ public class LuaString extends LuaValue { return -1; } + /** + * Find the last index of a string in this string + * @param s the string to search for + * @return index of last match found, or -1 if not found. + */ public int lastIndexOf( LuaString s ) { final int slen = s.length(); final int limit = m_offset + m_length - slen; @@ -419,10 +521,17 @@ public class LuaString extends LuaValue { return -1; } - // --------------------- utf8 conversion ------------------------- - + /** - * Convert to Java String interpreting as utf8 characters + * Convert to Java String interpreting as utf8 characters. + * + * @param bytes byte array in UTF8 encoding to convert + * @param offset starting index in byte array + * @param length number of bytes to convert + * @return Java String corresponding to the value of bytes interpreted using UTF8 + * @see #lengthAsUtf8(char[]) + * @see #encodeToUtf8(char[], byte[], int) + * @see #isValidUtf8() */ public static String decodeAsUtf8(byte[] bytes, int offset, int length) { int i,j,n,b; @@ -444,6 +553,11 @@ public class LuaString extends LuaValue { /** * Count the number of bytes required to encode the string as UTF-8. + * @param chars Array of unicode characters to be encoded as UTF-8 + * @return count of bytes needed to encode using UTF-8 + * @see #encodeToUtf8(char[], byte[], int) + * @see #decodeAsUtf8(byte[], int, int) + * @see #isValidUtf8() */ public static int lengthAsUtf8(char[] chars) { int i,b; @@ -456,8 +570,16 @@ public class LuaString extends LuaValue { /** * Encode the given Java string as UTF-8 bytes, writing the result to bytes - * starting at offset. The string should be measured first with lengthAsUtf8 + * starting at offset. + *
+ * The string should be measured first with lengthAsUtf8
* to make sure the given byte array is large enough.
+ * @param chars Array of unicode characters to be encoded as UTF-8
+ * @param bytes byte array to hold the result
+ * @param off offset into the byte array to start writing
+ * @see #lengthAsUtf8(char[])
+ * @see #decodeAsUtf8(byte[], int, int)
+ * @see #isValidUtf8()
*/
public static void encodeToUtf8(char[] chars, byte[] bytes, int off) {
final int n = chars.length;
@@ -476,6 +598,12 @@ public class LuaString extends LuaValue {
}
}
+ /** Check that a byte sequence is valid UTF-8
+ * @return true if it is valid UTF-8, otherwise false
+ * @see #lengthAsUtf8(char[])
+ * @see #encodeToUtf8(char[], byte[], int)
+ * @see #decodeAsUtf8(byte[], int, int)
+ */
public boolean isValidUtf8() {
int i,j,n,b,e=0;
for ( i=m_offset,j=m_offset+m_length,n=0; i
+ * Almost all API's implemented in {@link LuaTable} are defined and documented in {@link LuaValue}.
+ *
+ * If a table is needed, the one of the type-checking functions can be used such as
+ * {@link #istable()},
+ * {@link #checktable()}, or
+ * {@link #opttable(LuaTable)}
+ *
+ * The main table operations are defined on {@link LuaValue}
+ * for getting and setting values with and without metatag processing:
+ *
+ * To iterate over key-value pairs from Java, use
+ *
+ * As with other types, {@link LuaTable} instances should be constructed via one of the table constructor
+ * methods on {@link LuaValue}:
+ *
+ * Provided for compatibility, not a scalable operation.
+ * @return value for maxn
+ */
public int maxn() {
int n = 0;
for ( int i=0; i
+ * This is both a straight translation of the corresponding C type,
+ * and the main data structure for execution of compiled lua bytecode.
+ *
+ * See documentatation on {@link LuaClosure} for information on how to load
+ * and execute a {@link Prototype}.
+ * @see LuaClosure
+ */
public class Prototype {
/* constants used by the function */
diff --git a/src/core/org/luaj/vm2/TailcallVarargs.java b/src/core/org/luaj/vm2/TailcallVarargs.java
index 083de10d..5cffed4a 100644
--- a/src/core/org/luaj/vm2/TailcallVarargs.java
+++ b/src/core/org/luaj/vm2/TailcallVarargs.java
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2010 Luaj.org. All rights reserved.
+* Copyright (c) 2010-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -21,6 +21,25 @@
******************************************************************************/
package org.luaj.vm2;
+/**
+ * Subclass of {@link Varargs} that represents a lua tail call
+ * in a Java library function execution environment.
+ *
+ * Since Java doesn't have direct support for tail calls,
+ * any lua function whose {@link Prototype} contains the
+ * {@link Lua#OP_TAILCALL} bytecode needs a mechanism
+ * for tail calls when converting lua-bytecode to java-bytecode.
+ *
+ * The tail call holds the next function and arguments,
+ * and the client a call to {@link #eval()} executes the function
+ * repeatedly until the tail calls are completed.
+ *
+ * Normally, users of luaj need not concern themselves with the
+ * details of this mechanism, as it is built into the core
+ * execution framework.
+ * @see Prototype
+ * @see LuaJC
+ */
public class TailcallVarargs extends Varargs {
private LuaValue func;
diff --git a/src/core/org/luaj/vm2/UpValue.java b/src/core/org/luaj/vm2/UpValue.java
index 004540b6..072dd348 100644
--- a/src/core/org/luaj/vm2/UpValue.java
+++ b/src/core/org/luaj/vm2/UpValue.java
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2009 Luaj.org. All rights reserved.
+* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,29 +22,54 @@
package org.luaj.vm2;
-/** Upvalue used with Closure formulation */
+/** Upvalue used with Closure formulation
+ *
+ * @see LuaClosure
+ * @see Prototype
+ */
public final class UpValue {
LuaValue[] array; // initially the stack, becomes a holder
int index;
-
+
+ /**
+ * Create an upvalue relative to a stack
+ * @param stack the stack
+ * @param index the index on the stack for the upvalue
+ */
public UpValue( LuaValue[] stack, int index) {
this.array = stack;
this.index = index;
}
+ /**
+ * Convert this upvalue to a Java String
+ * @return the Java String for this upvalue.
+ * @see LuaValue#tojstring()
+ */
public String tojstring() {
return array[index].tojstring();
}
+ /**
+ * Get the value of the upvalue
+ * @return the {@link LuaValue} for this upvalue
+ */
public final LuaValue getValue() {
return array[index];
}
+ /**
+ * Set the value of the upvalue
+ * @param the {@link LuaValue} to set it to
+ */
public final void setValue( LuaValue value ) {
array[index] = value;
}
+ /**
+ * Close this upvalue so it is no longer on the stack
+ */
public final void close() {
array = new LuaValue[] { array[index] };
index = 0;
diff --git a/src/core/org/luaj/vm2/WeakTable.java b/src/core/org/luaj/vm2/WeakTable.java
index beef71fd..6afa4505 100644
--- a/src/core/org/luaj/vm2/WeakTable.java
+++ b/src/core/org/luaj/vm2/WeakTable.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Luaj.org. All rights reserved.
+ * Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,17 +25,46 @@ import java.lang.ref.WeakReference;
import org.luaj.vm2.lib.TwoArgFunction;
+/**
+ * Subclass of {@link LuaTable} that provides weak key and weak value semantics.
+ *
+ * Normally these are not created directly, but indirectly when changing the mode
+ * of a {@link LuaTable} as lua script executes.
+ *
+ * However, calling the constructors directly when weak tables are required from
+ * Java will reduce overhead.
+ */
public class WeakTable extends LuaTable {
private boolean weakkeys,weakvalues;
+ /**
+ * Construct a table with weak keys, weak values, or both
+ * @param weakkeys true to let the table have weak keys
+ * @param weakvalues true to let the table have weak values
+ */
public WeakTable(boolean weakkeys, boolean weakvalues) {
this(weakkeys, weakvalues, 0, 0);
}
+
+ /**
+ * Construct a table with weak keys, weak values, or both, and an initial capacity
+ * @param weakkeys true to let the table have weak keys
+ * @param weakvalues true to let the table have weak values
+ * @param narray capacity of array part
+ * @param nhash capacity of hash part
+ */
protected WeakTable(boolean weakkeys, boolean weakvalues, int narray, int nhash) {
super(narray, nhash);
this.weakkeys = weakkeys;
this.weakvalues = weakvalues;
}
+
+ /**
+ * Construct a table with weak keys, weak values, or both, and a source of initial data
+ * @param weakkeys true to let the table have weak keys
+ * @param weakvalues true to let the table have weak values
+ * @param source {@link LuaTable} containing the initial elements
+ */
protected WeakTable(boolean weakkeys, boolean weakvalues, LuaTable source) {
this(weakkeys, weakvalues, source.getArrayLength(), source.getHashLength());
Varargs n;
@@ -49,6 +78,11 @@ public class WeakTable extends LuaTable {
super.presize(narray);
}
+ /**
+ * Presize capacity of both array and hash parts.
+ * @param narray capacity of array part
+ * @param nhash capacity of hash part
+ */
public void presize(int narray, int nhash) {
super.presize(narray, nhash);
}
@@ -67,6 +101,11 @@ public class WeakTable extends LuaTable {
return this;
}
+ /**
+ * Self-sent message to convert a value to its weak counterpart
+ * @param value value to convert
+ * @return {@link LuaValue} that is a strong or weak reference, depending on type of {@code value}
+ */
LuaValue weaken( LuaValue value ) {
switch ( value.type() ) {
case LuaValue.TFUNCTION:
@@ -85,8 +124,7 @@ public class WeakTable extends LuaTable {
value = weaken( value );
super.rawset(key, value);
}
-
- /** caller must ensure key is not nil */
+
public void rawset( LuaValue key, LuaValue value ) {
if ( weakvalues )
value = weaken( value );
@@ -114,6 +152,9 @@ public class WeakTable extends LuaTable {
return super.rawget(key).strongvalue();
}
+ /** Get the hash value for a key
+ * key the key to look up
+ * */
protected LuaValue hashget(LuaValue key) {
if ( hashEntries > 0 ) {
int i = hashFindSlot(key);
@@ -179,6 +220,9 @@ public class WeakTable extends LuaTable {
} );
}
+ /** Internal class to implement weak values.
+ * @see WeakTable
+ */
static class WeakValue extends LuaValue {
final WeakReference ref;
@@ -215,6 +259,9 @@ public class WeakTable extends LuaTable {
}
}
+ /** Internal class to implement weak userdata values.
+ * @see WeakTable
+ */
static final class WeakUserdata extends WeakValue {
private final WeakReference ob;
private final LuaValue mt;
@@ -247,6 +294,9 @@ public class WeakTable extends LuaTable {
}
}
+ /** Internal class to implement weak table entries.
+ * @see WeakTable
+ */
static final class WeakEntry extends LuaValue {
final LuaValue weakkey;
LuaValue weakvalue;
diff --git a/src/core/org/luaj/vm2/compiler/LuaC.java b/src/core/org/luaj/vm2/compiler/LuaC.java
index f3345bb6..9a32818f 100644
--- a/src/core/org/luaj/vm2/compiler/LuaC.java
+++ b/src/core/org/luaj/vm2/compiler/LuaC.java
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2009 Luaj.org. All rights reserved.
+* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -38,7 +38,19 @@ import org.luaj.vm2.LoadState.LuaCompiler;
/**
- * Compiler for Lua
+ * Compiler for Lua.
+ *
+ * Compiles lua source files into lua bytecode within a {@link Prototype},
+ * loads lua binary files directly into a{@link Prototype},
+ * and optionaly instantiates a {@link LuaClosure} around the result
+ * using a user-supplied environment.
+ *
+ * Implements the {@link LuaCompiler} interface for loading
+ * initialized chunks, which is an interface common to
+ * lua bytecode compiling and java bytecode compiling.
+ *
+ * @see LuaCompiler
+ * @see Prototype
*/
public class LuaC extends Lua implements LuaCompiler {
+ *
+ * {@code
+ * LuaValue k = LuaValue.NIL;
+ * while ( true ) {
+ * Varargs n = table.next(k);
+ * if ( (k = n.arg1()).isnil() )
+ * break;
+ * LuaValue v = n.arg(2)
+ * process( k, v )
+ * }
+ *
+ *
+ *
+ */
public class LuaTable extends LuaValue {
private static final int MIN_HASH_CAPACITY = 2;
private static final LuaString N = valueOf("n");
+ /** the array values */
protected LuaValue[] array;
+
+ /** the hash keys */
protected LuaValue[] hashKeys;
+
+ /** the hash values */
protected LuaValue[] hashValues;
+
+ /** the number of hash entries */
protected int hashEntries;
+
+ /** metatable for this table, or null */
protected LuaValue m_metatable;
+ /** Construct empty table */
public LuaTable() {
array = NOVALS;
hashKeys = NOVALS;
hashValues = NOVALS;
}
+ /**
+ * Construct table with preset capacity.
+ * @param narray capacity of array part
+ * @param nhash capacity of hash part
+ */
public LuaTable(int narray, int nhash) {
presize(narray, nhash);
}
-
+
+ /**
+ * Construct table with named and unnamed parts.
+ * @param named Named elements in order {@code key-a, value-a, key-b, value-b, ... }
+ * @param unnamed Unnamed elements in order {@code value-1, value-2, ... }
+ * @param lastarg Additional unnamed values beyond {@code unnamed.length}
+ */
public LuaTable(LuaValue[] named, LuaValue[] unnamed, Varargs lastarg) {
int nn = (named!=null? named.length: 0);
int nu = (unnamed!=null? unnamed.length: 0);
@@ -58,10 +122,19 @@ public class LuaTable extends LuaValue {
rawset(named[i], named[i+1]);
}
+ /**
+ * Construct table of unnamed elements.
+ * @param varargs Unnamed elements in order {@code value-1, value-2, ... }
+ */
public LuaTable(Varargs varargs) {
this(varargs,1);
}
+ /**
+ * Construct table of unnamed elements.
+ * @param varargs Unnamed elements in order {@code value-1, value-2, ... }
+ * @param firstarg the index in varargs of the first argument to include in the table
+ */
public LuaTable(Varargs varargs, int firstarg) {
int nskip = firstarg-1;
int n = Math.max(varargs.narg()-nskip,0);
@@ -105,16 +178,25 @@ public class LuaTable extends LuaValue {
hashEntries = 0;
}
+ /** Resize the table */
private static LuaValue[] resize( LuaValue[] old, int n ) {
LuaValue[] v = new LuaValue[n];
System.arraycopy(old, 0, v, 0, old.length);
return v;
}
+ /**
+ * Get the length of the array part of the table.
+ * @return length of the array part, does not relate to count of objects in the table.
+ */
protected int getArrayLength() {
return array.length;
}
+ /**
+ * Get the length of the hash part of the table.
+ * @return length of the hash part, does not relate to count of objects in the table.
+ */
protected int getHashLength() {
return hashValues.length;
}
@@ -135,6 +217,12 @@ public class LuaTable extends LuaValue {
return this;
}
+ /**
+ * Change the mode of a table
+ * @param weakkeys true to make the table have weak keys going forward
+ * @param weakvalues true to make the table have weak values going forward
+ * @return {@code this} or a new {@link WeakTable} if the mode change requires copying.
+ */
protected LuaTable changemode(boolean weakkeys, boolean weakvalues) {
if ( weakkeys || weakvalues )
return new WeakTable(weakkeys, weakvalues, this);
@@ -197,6 +285,7 @@ public class LuaTable extends LuaValue {
hashset( key, value );
}
+ /** Set an array element */
private boolean arrayset( int key, LuaValue value ) {
if ( key>0 && key<=array.length ) {
array[key-1] = (value.isnil()? null: value);
@@ -208,7 +297,8 @@ public class LuaTable extends LuaValue {
}
return false;
}
-
+
+ /** Expand the array part */
private void expandarray() {
int n = array.length;
int m = Math.max(2,n*2);
@@ -223,6 +313,11 @@ public class LuaTable extends LuaValue {
}
}
+ /** Remove the element at a position in a list-table
+ *
+ * @param pos the position to remove
+ * @return The removed item, or {@link #NONE} if not removed
+ */
public LuaValue remove(int pos) {
if ( pos == 0 )
pos = length();
@@ -234,6 +329,11 @@ public class LuaTable extends LuaValue {
return v.isnil()? NONE: v;
}
+ /** Insert an element at a position in a list-table
+ *
+ * @param pos the position to remove
+ * @param value The value to insert
+ */
public void insert(int pos, LuaValue value) {
if ( pos == 0 )
pos = length()+1;
@@ -244,6 +344,13 @@ public class LuaTable extends LuaValue {
}
}
+ /** Concatenate the contents of a table efficiently, using {@link Buffer}
+ *
+ * @param sep {@link LuaString} separater to apply between elements
+ * @param i the first element index
+ * @param j the last element index, inclusive
+ * @return {@link LuaString} value of the concatenation
+ */
public LuaValue concat(LuaString sep, int i, int j) {
Buffer sb = new Buffer ();
if ( i<=j ) {
@@ -263,9 +370,6 @@ public class LuaTable extends LuaValue {
return ZERO;
}
- /**
- * Get the length of this table, as lua defines it.
- */
public int length() {
int a = getArrayLength();
int n = a+1,m=0;
@@ -287,6 +391,11 @@ public class LuaTable extends LuaValue {
return LuaInteger.valueOf(length());
}
+ /** Return table.maxn() as defined by lua 5.0.
+ *