Merge remote-tracking branch 'src/master'
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,7 +1,6 @@
|
|||||||
bin/
|
bin/
|
||||||
target/
|
target/
|
||||||
build/
|
build/
|
||||||
lib/
|
|
||||||
jit/
|
jit/
|
||||||
*.ser
|
*.ser
|
||||||
*.gz
|
*.gz
|
||||||
|
|||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2007 LuaJ. 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
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -18,7 +18,7 @@ James Roseborough, Ian Farmer, Version 3.0.2
|
|||||||
<small>
|
<small>
|
||||||
Copyright © 2009-2014 Luaj.org.
|
Copyright © 2009-2014 Luaj.org.
|
||||||
Freely available under the terms of the
|
Freely available under the terms of the
|
||||||
<a href="http://sourceforge.net/dbimage.php?id=196142">Luaj license</a>.
|
<a href="LICENSE">Luaj license</a>.
|
||||||
</small>
|
</small>
|
||||||
<hr>
|
<hr>
|
||||||
<p>
|
<p>
|
||||||
@@ -412,7 +412,7 @@ and the math operations include all those supported by Java SE.
|
|||||||
Android applications should use the JsePlatform, and can include the <a href="#luajava">Luajava</a> library
|
Android applications should use the JsePlatform, and can include the <a href="#luajava">Luajava</a> library
|
||||||
to simplify access to underlying Android APIs.
|
to simplify access to underlying Android APIs.
|
||||||
A specialized Globals.finder should be provided to find scripts and data for loading.
|
A specialized Globals.finder should be provided to find scripts and data for loading.
|
||||||
See <a href="examples/android/src/android/LuajView">examples/android/src/android/LuajView</a>
|
See <a href="examples/android/src/android/LuajView.java">examples/android/src/android/LuajView.java</a>
|
||||||
for an example that loads from the "res" Android project directory.
|
for an example that loads from the "res" Android project directory.
|
||||||
The ant build script is <a href="examples/android/build.xml">examples/android/build.xml</a>.
|
The ant build script is <a href="examples/android/build.xml">examples/android/build.xml</a>.
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ import java.io.InputStream;
|
|||||||
* <p>
|
* <p>
|
||||||
* The {@link LoadState} class provides the default {@link Globals.Undumper}
|
* The {@link LoadState} class provides the default {@link Globals.Undumper}
|
||||||
* which is used to undump a string of bytes that represent a lua binary file
|
* which is used to undump a string of bytes that represent a lua binary file
|
||||||
* using either the C-based lua compiler, or luaj's
|
* using either the C-based lua compiler, or luaj's
|
||||||
* {@link org.luaj.vm2.compiler.LuaC} compiler.
|
* {@link org.luaj.vm2.compiler.LuaC} compiler.
|
||||||
* <p>
|
* <p>
|
||||||
* The canonical method to load and execute code is done
|
* The canonical method to load and execute code is done
|
||||||
* indirectly using the Globals:
|
* indirectly using the Globals:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
@@ -44,10 +44,10 @@ import java.io.InputStream;
|
|||||||
* This should work regardless of which {@link Globals.Compiler} or {@link Globals.Undumper}
|
* This should work regardless of which {@link Globals.Compiler} or {@link Globals.Undumper}
|
||||||
* have been installed.
|
* have been installed.
|
||||||
* <p>
|
* <p>
|
||||||
* By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
|
* By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform}
|
||||||
* to construct globals, the {@link LoadState} default undumper is installed
|
* to construct globals, the {@link LoadState} default undumper is installed
|
||||||
* as the default {@link Globals.Undumper}.
|
* as the default {@link Globals.Undumper}.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* A lua binary file is created via the {@link org.luaj.vm2.compiler.DumpState} class
|
* A lua binary file is created via the {@link org.luaj.vm2.compiler.DumpState} class
|
||||||
@@ -60,7 +60,7 @@ import java.io.InputStream;
|
|||||||
* byte[] lua_binary_file_bytes = o.toByteArray();
|
* byte[] lua_binary_file_bytes = o.toByteArray();
|
||||||
* } </pre>
|
* } </pre>
|
||||||
*
|
*
|
||||||
* The {@link LoadState}'s default undumper {@link #instance}
|
* The {@link LoadState}'s default undumper {@link #instance}
|
||||||
* may be used directly to undump these bytes:
|
* may be used directly to undump these bytes:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* Prototypep = LoadState.instance.undump(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua");
|
* Prototypep = LoadState.instance.undump(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua");
|
||||||
@@ -99,7 +99,7 @@ public class LoadState {
|
|||||||
/** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */
|
/** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */
|
||||||
public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
|
public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
|
||||||
|
|
||||||
// type constants
|
// type constants
|
||||||
public static final int LUA_TINT = (-2);
|
public static final int LUA_TINT = (-2);
|
||||||
public static final int LUA_TNONE = (-1);
|
public static final int LUA_TNONE = (-1);
|
||||||
public static final int LUA_TNIL = 0;
|
public static final int LUA_TNIL = 0;
|
||||||
@@ -155,7 +155,6 @@ public class LoadState {
|
|||||||
private static final LuaValue[] NOVALUES = {};
|
private static final LuaValue[] NOVALUES = {};
|
||||||
private static final Prototype[] NOPROTOS = {};
|
private static final Prototype[] NOPROTOS = {};
|
||||||
private static final LocVars[] NOLOCVARS = {};
|
private static final LocVars[] NOLOCVARS = {};
|
||||||
private static final LuaString[] NOSTRVALUES = {};
|
|
||||||
private static final Upvaldesc[] NOUPVALDESCS = {};
|
private static final Upvaldesc[] NOUPVALDESCS = {};
|
||||||
private static final int[] NOINTS = {};
|
private static final int[] NOINTS = {};
|
||||||
|
|
||||||
@@ -168,17 +167,17 @@ public class LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Load a 4-byte int value from the input stream
|
/** Load a 4-byte int value from the input stream
|
||||||
* @return the int value laoded.
|
* @return the int value laoded.
|
||||||
**/
|
**/
|
||||||
int loadInt() throws IOException {
|
int loadInt() throws IOException {
|
||||||
is.readFully(buf,0,4);
|
is.readFully(buf,0,4);
|
||||||
return luacLittleEndian?
|
return luacLittleEndian?
|
||||||
(buf[3] << 24) | ((0xff & buf[2]) << 16) | ((0xff & buf[1]) << 8) | (0xff & buf[0]):
|
(buf[3] << 24) | ((0xff & buf[2]) << 16) | ((0xff & buf[1]) << 8) | (0xff & buf[0]):
|
||||||
(buf[0] << 24) | ((0xff & buf[1]) << 16) | ((0xff & buf[2]) << 8) | (0xff & buf[3]);
|
(buf[0] << 24) | ((0xff & buf[1]) << 16) | ((0xff & buf[2]) << 8) | (0xff & buf[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Load an array of int values from the input stream
|
/** Load an array of int values from the input stream
|
||||||
* @return the array of int values laoded.
|
* @return the array of int values laoded.
|
||||||
**/
|
**/
|
||||||
int[] loadIntArray() throws IOException {
|
int[] loadIntArray() throws IOException {
|
||||||
int n = loadInt();
|
int n = loadInt();
|
||||||
@@ -192,7 +191,7 @@ public class LoadState {
|
|||||||
is.readFully(buf,0,m);
|
is.readFully(buf,0,m);
|
||||||
int[] array = new int[n];
|
int[] array = new int[n];
|
||||||
for ( int i=0, j=0; i<n; ++i, j+=4 )
|
for ( int i=0, j=0; i<n; ++i, j+=4 )
|
||||||
array[i] = luacLittleEndian?
|
array[i] = luacLittleEndian?
|
||||||
(buf[j+3] << 24) | ((0xff & buf[j+2]) << 16) | ((0xff & buf[j+1]) << 8) | (0xff & buf[j+0]):
|
(buf[j+3] << 24) | ((0xff & buf[j+2]) << 16) | ((0xff & buf[j+1]) << 8) | (0xff & buf[j+0]):
|
||||||
(buf[j+0] << 24) | ((0xff & buf[j+1]) << 16) | ((0xff & buf[j+2]) << 8) | (0xff & buf[j+3]);
|
(buf[j+0] << 24) | ((0xff & buf[j+1]) << 16) | ((0xff & buf[j+2]) << 8) | (0xff & buf[j+3]);
|
||||||
|
|
||||||
@@ -200,7 +199,7 @@ public class LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Load a long value from the input stream
|
/** Load a long value from the input stream
|
||||||
* @return the long value laoded.
|
* @return the long value laoded.
|
||||||
**/
|
**/
|
||||||
long loadInt64() throws IOException {
|
long loadInt64() throws IOException {
|
||||||
int a,b;
|
int a,b;
|
||||||
@@ -215,7 +214,7 @@ public class LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Load a lua strin gvalue from the input stream
|
/** Load a lua strin gvalue from the input stream
|
||||||
* @return the {@link LuaString} value laoded.
|
* @return the {@link LuaString} value laoded.
|
||||||
**/
|
**/
|
||||||
LuaString loadString() throws IOException {
|
LuaString loadString() throws IOException {
|
||||||
int size = this.luacSizeofSizeT == 8? (int) loadInt64(): loadInt();
|
int size = this.luacSizeofSizeT == 8? (int) loadInt64(): loadInt();
|
||||||
@@ -227,7 +226,7 @@ public class LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert bits in a long value to a {@link LuaValue}.
|
* Convert bits in a long value to a {@link LuaValue}.
|
||||||
* @param bits long value containing the bits
|
* @param bits long value containing the bits
|
||||||
* @return {@link LuaInteger} or {@link LuaDouble} whose value corresponds to the bits provided.
|
* @return {@link LuaInteger} or {@link LuaDouble} whose value corresponds to the bits provided.
|
||||||
*/
|
*/
|
||||||
@@ -251,7 +250,7 @@ public class LoadState {
|
|||||||
return LuaValue.valueOf( Double.longBitsToDouble(bits) );
|
return LuaValue.valueOf( Double.longBitsToDouble(bits) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a number from a binary chunk
|
* Load a number from a binary chunk
|
||||||
* @return the {@link LuaValue} loaded
|
* @return the {@link LuaValue} loaded
|
||||||
* @throws IOException if an i/o exception occurs
|
* @throws IOException if an i/o exception occurs
|
||||||
@@ -335,7 +334,7 @@ public class LoadState {
|
|||||||
f.upvalues[i].name = loadString();
|
f.upvalues[i].name = loadString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a function prototype from the input stream
|
* Load a function prototype from the input stream
|
||||||
* @param p name of the source
|
* @param p name of the source
|
||||||
* @return {@link Prototype} instance that was loaded
|
* @return {@link Prototype} instance that was loaded
|
||||||
@@ -366,8 +365,8 @@ public class LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the lua chunk header values.
|
* Load the lua chunk header values.
|
||||||
* @throws IOException if an i/o exception occurs.
|
* @throws IOException if an i/o exception occurs.
|
||||||
*/
|
*/
|
||||||
public void loadHeader() throws IOException {
|
public void loadHeader() throws IOException {
|
||||||
luacVersion = is.readByte();
|
luacVersion = is.readByte();
|
||||||
@@ -392,7 +391,7 @@ public class LoadState {
|
|||||||
*/
|
*/
|
||||||
public static Prototype undump(InputStream stream, String chunkname) throws IOException {
|
public static Prototype undump(InputStream stream, String chunkname) throws IOException {
|
||||||
// check rest of signature
|
// check rest of signature
|
||||||
if ( stream.read() != LUA_SIGNATURE[0]
|
if ( stream.read() != LUA_SIGNATURE[0]
|
||||||
|| stream.read() != LUA_SIGNATURE[1]
|
|| stream.read() != LUA_SIGNATURE[1]
|
||||||
|| stream.read() != LUA_SIGNATURE[2]
|
|| stream.read() != LUA_SIGNATURE[2]
|
||||||
|| stream.read() != LUA_SIGNATURE[3] )
|
|| stream.read() != LUA_SIGNATURE[3] )
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
|
import org.luaj.vm2.lib.DebugLib.CallFrame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension of {@link LuaFunction} which executes lua bytecode.
|
* Extension of {@link LuaFunction} which executes lua bytecode.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -415,7 +417,7 @@ public class LuaClosure extends LuaFunction {
|
|||||||
{
|
{
|
||||||
LuaValue limit = stack[a + 1];
|
LuaValue limit = stack[a + 1];
|
||||||
LuaValue step = stack[a + 2];
|
LuaValue step = stack[a + 2];
|
||||||
LuaValue idx = step.add(stack[a]);
|
LuaValue idx = stack[a].add(step);
|
||||||
if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) {
|
if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) {
|
||||||
stack[a] = idx;
|
stack[a] = idx;
|
||||||
stack[a + 3] = idx;
|
stack[a + 3] = idx;
|
||||||
@@ -547,8 +549,24 @@ public class LuaClosure extends LuaFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void processErrorHooks(LuaError le, Prototype p, int pc) {
|
private void processErrorHooks(LuaError le, Prototype p, int pc) {
|
||||||
le.fileline = (p.source != null? p.source.tojstring(): "?") + ":"
|
String file = "?";
|
||||||
+ (p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length? String.valueOf(p.lineinfo[pc]): "?") + ": ";
|
int line = -1;
|
||||||
|
{
|
||||||
|
CallFrame frame = null;
|
||||||
|
if (globals != null && globals.debuglib != null) {
|
||||||
|
frame = globals.debuglib.getCallFrame(le.level);
|
||||||
|
if (frame != null) {
|
||||||
|
String src = frame.shortsource();
|
||||||
|
file = src != null ? src : "?";
|
||||||
|
line = frame.currentline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (frame == null) {
|
||||||
|
file = p.source != null? p.source.tojstring(): "?";
|
||||||
|
line = p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length ? p.lineinfo[pc] : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
le.fileline = file + ": " + line;
|
||||||
le.traceback = errorHook(le.getMessage(), le.level);
|
le.traceback = errorHook(le.getMessage(), le.level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ import org.luaj.vm2.compat.JavaCompat;
|
|||||||
import org.luaj.vm2.lib.MathLib;
|
import org.luaj.vm2.lib.MathLib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension of {@link LuaNumber} which can hold a Java double as its value.
|
* Extension of {@link LuaNumber} which can hold a Java double as its value.
|
||||||
* <p>
|
* <p>
|
||||||
* These instance are not instantiated directly by clients, but indirectly
|
* These instance are not instantiated directly by clients, but indirectly
|
||||||
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
|
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
|
||||||
* functions. This ensures that values which can be represented as int
|
* functions. This ensures that values which can be represented as int
|
||||||
* are wrapped in {@link LuaInteger} instead of {@link LuaDouble}.
|
* are wrapped in {@link LuaInteger} instead of {@link LuaDouble}.
|
||||||
* <p>
|
* <p>
|
||||||
* Almost all API's implemented in LuaDouble are defined and documented in {@link LuaValue}.
|
* Almost all API's implemented in LuaDouble are defined and documented in {@link LuaValue}.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -44,7 +44,7 @@ import org.luaj.vm2.lib.MathLib;
|
|||||||
* <li>{@link #ddiv_d(double, double)}</li>
|
* <li>{@link #ddiv_d(double, double)}</li>
|
||||||
* <li>{@link #dmod(double, double)}</li>
|
* <li>{@link #dmod(double, double)}</li>
|
||||||
* <li>{@link #dmod_d(double, double)}</li>
|
* <li>{@link #dmod_d(double, double)}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
* @see LuaNumber
|
* @see LuaNumber
|
||||||
@@ -97,7 +97,7 @@ public class LuaDouble extends LuaNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean islong() {
|
public boolean islong() {
|
||||||
return v == (long) v;
|
return v == (long) v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte tobyte() { return (byte) (long) v; }
|
public byte tobyte() { return (byte) (long) v; }
|
||||||
@@ -158,12 +158,12 @@ public class LuaDouble extends LuaNumber {
|
|||||||
/** Divide two double numbers according to lua math, and return a {@link LuaValue} result.
|
/** Divide two double numbers according to lua math, and return a {@link LuaValue} result.
|
||||||
* @param lhs Left-hand-side of the division.
|
* @param lhs Left-hand-side of the division.
|
||||||
* @param rhs Right-hand-side of the division.
|
* @param rhs Right-hand-side of the division.
|
||||||
* @return {@link LuaValue} for the result of the division,
|
* @return {@link LuaValue} for the result of the division,
|
||||||
* taking into account positive and negiative infinity, and Nan
|
* taking into account positive and negiative infinity, and Nan
|
||||||
* @see #ddiv_d(double, double)
|
* @see #ddiv_d(double, double)
|
||||||
*/
|
*/
|
||||||
public static LuaValue ddiv(double lhs, double rhs) {
|
public static LuaValue ddiv(double lhs, double rhs) {
|
||||||
return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF;
|
return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Divide two double numbers according to lua math, and return a double result.
|
/** Divide two double numbers according to lua math, and return a double result.
|
||||||
@@ -173,15 +173,15 @@ public class LuaDouble extends LuaNumber {
|
|||||||
* @see #ddiv(double, double)
|
* @see #ddiv(double, double)
|
||||||
*/
|
*/
|
||||||
public static double ddiv_d(double lhs, double rhs) {
|
public static double ddiv_d(double lhs, double rhs) {
|
||||||
return rhs!=0? lhs / rhs: lhs>0? Double.POSITIVE_INFINITY: lhs==0? Double.NaN: Double.NEGATIVE_INFINITY;
|
return rhs!=0? lhs / rhs: lhs>0? Double.POSITIVE_INFINITY: lhs==0? Double.NaN: Double.NEGATIVE_INFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Take modulo double numbers according to lua math, and return a {@link LuaValue} result.
|
/** Take modulo double numbers according to lua math, and return a {@link LuaValue} result.
|
||||||
* @param lhs Left-hand-side of the modulo.
|
* @param lhs Left-hand-side of the modulo.
|
||||||
* @param rhs Right-hand-side of the modulo.
|
* @param rhs Right-hand-side of the modulo.
|
||||||
* @return {@link LuaValue} for the result of the modulo,
|
* @return {@link LuaValue} for the result of the modulo,
|
||||||
* using lua's rules for modulo
|
* using lua's rules for modulo
|
||||||
* @see #dmod_d(double, double)
|
* @see #dmod_d(double, double)
|
||||||
*/
|
*/
|
||||||
public static LuaValue dmod(double lhs, double rhs) {
|
public static LuaValue dmod(double lhs, double rhs) {
|
||||||
if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) return NAN;
|
if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) return NAN;
|
||||||
@@ -197,7 +197,7 @@ public class LuaDouble extends LuaNumber {
|
|||||||
/** Take modulo for double numbers according to lua math, and return a double result.
|
/** Take modulo for double numbers according to lua math, and return a double result.
|
||||||
* @param lhs Left-hand-side of the modulo.
|
* @param lhs Left-hand-side of the modulo.
|
||||||
* @param rhs Right-hand-side of the modulo.
|
* @param rhs Right-hand-side of the modulo.
|
||||||
* @return double value for the result of the modulo,
|
* @return double value for the result of the modulo,
|
||||||
* using lua's rules for modulo
|
* using lua's rules for modulo
|
||||||
* @see #dmod(double, double)
|
* @see #dmod(double, double)
|
||||||
*/
|
*/
|
||||||
@@ -213,28 +213,28 @@ public class LuaDouble extends LuaNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// relational operators
|
// relational operators
|
||||||
public LuaValue lt( LuaValue rhs ) { return rhs.gt_b(v)? LuaValue.TRUE: FALSE; }
|
public LuaValue lt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gt_b(v)? TRUE: FALSE) : super.lt(rhs); }
|
||||||
public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; }
|
||||||
public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; }
|
||||||
public boolean lt_b( LuaValue rhs ) { return rhs.gt_b(v); }
|
public boolean lt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gt_b(v) : super.lt_b(rhs); }
|
||||||
public boolean lt_b( int rhs ) { return v < rhs; }
|
public boolean lt_b( int rhs ) { return v < rhs; }
|
||||||
public boolean lt_b( double rhs ) { return v < rhs; }
|
public boolean lt_b( double rhs ) { return v < rhs; }
|
||||||
public LuaValue lteq( LuaValue rhs ) { return rhs.gteq_b(v)? LuaValue.TRUE: FALSE; }
|
public LuaValue lteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gteq_b(v)? TRUE: FALSE) : super.lteq(rhs); }
|
||||||
public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; }
|
||||||
public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; }
|
||||||
public boolean lteq_b( LuaValue rhs ) { return rhs.gteq_b(v); }
|
public boolean lteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gteq_b(v) : super.lteq_b(rhs); }
|
||||||
public boolean lteq_b( int rhs ) { return v <= rhs; }
|
public boolean lteq_b( int rhs ) { return v <= rhs; }
|
||||||
public boolean lteq_b( double rhs ) { return v <= rhs; }
|
public boolean lteq_b( double rhs ) { return v <= rhs; }
|
||||||
public LuaValue gt( LuaValue rhs ) { return rhs.lt_b(v)? LuaValue.TRUE: FALSE; }
|
public LuaValue gt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lt_b(v)? TRUE: FALSE) : super.gt(rhs); }
|
||||||
public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; }
|
||||||
public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; }
|
||||||
public boolean gt_b( LuaValue rhs ) { return rhs.lt_b(v); }
|
public boolean gt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lt_b(v) : super.gt_b(rhs); }
|
||||||
public boolean gt_b( int rhs ) { return v > rhs; }
|
public boolean gt_b( int rhs ) { return v > rhs; }
|
||||||
public boolean gt_b( double rhs ) { return v > rhs; }
|
public boolean gt_b( double rhs ) { return v > rhs; }
|
||||||
public LuaValue gteq( LuaValue rhs ) { return rhs.lteq_b(v)? LuaValue.TRUE: FALSE; }
|
public LuaValue gteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lteq_b(v)? TRUE: FALSE) : super.gteq(rhs); }
|
||||||
public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; }
|
||||||
public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; }
|
||||||
public boolean gteq_b( LuaValue rhs ) { return rhs.lteq_b(v); }
|
public boolean gteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lteq_b(v) : super.gteq_b(rhs); }
|
||||||
public boolean gteq_b( int rhs ) { return v >= rhs; }
|
public boolean gteq_b( int rhs ) { return v >= rhs; }
|
||||||
public boolean gteq_b( double rhs ) { return v >= rhs; }
|
public boolean gteq_b( double rhs ) { return v >= rhs; }
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ public class LuaDouble extends LuaNumber {
|
|||||||
if ( v == 0.0 ) // never occurs on J2ME
|
if ( v == 0.0 ) // never occurs on J2ME
|
||||||
return (JavaCompat.INSTANCE.doubleToRawLongBits(v)<0? "-0": "0");
|
return (JavaCompat.INSTANCE.doubleToRawLongBits(v)<0? "-0": "0");
|
||||||
long l = (long) v;
|
long l = (long) v;
|
||||||
if ( l == v )
|
if ( l == v )
|
||||||
return Long.toString(l);
|
return Long.toString(l);
|
||||||
if ( Double.isNaN(v) )
|
if ( Double.isNaN(v) )
|
||||||
return (JavaCompat.INSTANCE.doubleToRawLongBits(v)<0? JSTR_NEGNAN: JSTR_NAN);
|
return (JavaCompat.INSTANCE.doubleToRawLongBits(v)<0? JSTR_NEGNAN: JSTR_NAN);
|
||||||
@@ -271,11 +271,11 @@ public class LuaDouble extends LuaNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LuaNumber optnumber(LuaNumber defval) {
|
public LuaNumber optnumber(LuaNumber defval) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isnumber() {
|
public boolean isnumber() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isstring() {
|
public boolean isstring() {
|
||||||
@@ -290,14 +290,14 @@ public class LuaDouble extends LuaNumber {
|
|||||||
public LuaNumber checknumber() { return this; }
|
public LuaNumber checknumber() { return this; }
|
||||||
public double checkdouble() { return v; }
|
public double checkdouble() { return v; }
|
||||||
|
|
||||||
public String checkjstring() {
|
public String checkjstring() {
|
||||||
return tojstring();
|
return tojstring();
|
||||||
}
|
}
|
||||||
public LuaString checkstring() {
|
public LuaString checkstring() {
|
||||||
return LuaString.valueOf(tojstring());
|
return LuaString.valueOf(tojstring());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isvalidkey() {
|
public boolean isvalidkey() {
|
||||||
return !Double.isNaN(v);
|
return !Double.isNaN(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,14 +22,14 @@
|
|||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for functions implemented in Java.
|
* Base class for functions implemented in Java.
|
||||||
* <p>
|
* <p>
|
||||||
* Direct subclass include {@link org.luaj.vm2.lib.LibFunction}
|
* Direct subclass include {@link org.luaj.vm2.lib.LibFunction}
|
||||||
* which is the base class for
|
* which is the base class for
|
||||||
* all built-in library functions coded in Java,
|
* all built-in library functions coded in Java,
|
||||||
* and {@link LuaClosure}, which represents a lua closure
|
* and {@link LuaClosure}, which represents a lua closure
|
||||||
* whose bytecode is interpreted when the function is invoked.
|
* whose bytecode is interpreted when the function is invoked.
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
* @see LuaClosure
|
* @see LuaClosure
|
||||||
* @see org.luaj.vm2.lib.LibFunction
|
* @see org.luaj.vm2.lib.LibFunction
|
||||||
@@ -57,11 +57,11 @@ public class LuaFunction extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LuaFunction optfunction(LuaFunction defval) {
|
public LuaFunction optfunction(LuaFunction defval) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue getmetatable() {
|
public LuaValue getmetatable() {
|
||||||
return s_metatable;
|
return s_metatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
@@ -72,12 +72,15 @@ public class LuaFunction extends LuaValue {
|
|||||||
return valueOf(tojstring());
|
return valueOf(tojstring());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the last part of the class name, to be used as a function name in tojstring and elsewhere.
|
/** Return the last part of the class name, to be used as a function name in tojstring and elsewhere.
|
||||||
* @return String naming the last part of the class name after the last dot (.) or dollar sign ($).
|
* @return String naming the last part of the class name after the last dot (.) or dollar sign ($).
|
||||||
|
* If the first character is '_', it is skipped.
|
||||||
*/
|
*/
|
||||||
public String classnamestub() {
|
public String classnamestub() {
|
||||||
String s = getClass().getName();
|
String s = getClass().getName();
|
||||||
return s.substring(Math.max(s.lastIndexOf('.'),s.lastIndexOf('$'))+1);
|
int offset = Math.max(s.lastIndexOf('.'), s.lastIndexOf('$')) + 1;
|
||||||
|
if (s.charAt(offset) == '_') offset++;
|
||||||
|
return s.substring(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return a human-readable name for this function. Returns the last part of the class name by default.
|
/** Return a human-readable name for this function. Returns the last part of the class name by default.
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ package org.luaj.vm2;
|
|||||||
import org.luaj.vm2.lib.MathLib;
|
import org.luaj.vm2.lib.MathLib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension of {@link LuaNumber} which can hold a Java int as its value.
|
* Extension of {@link LuaNumber} which can hold a Java int as its value.
|
||||||
* <p>
|
* <p>
|
||||||
* These instance are not instantiated directly by clients, but indirectly
|
* These instance are not instantiated directly by clients, but indirectly
|
||||||
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
|
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
|
||||||
* functions. This ensures that policies regarding pooling of instances are
|
* functions. This ensures that policies regarding pooling of instances are
|
||||||
* encapsulated.
|
* encapsulated.
|
||||||
* <p>
|
* <p>
|
||||||
* There are no API's specific to LuaInteger that are useful beyond what is already
|
* There are no API's specific to LuaInteger that are useful beyond what is already
|
||||||
* exposed in {@link LuaValue}.
|
* exposed in {@link LuaValue}.
|
||||||
*
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
@@ -61,16 +61,16 @@ public class LuaInteger extends LuaNumber {
|
|||||||
*/
|
*/
|
||||||
public static LuaNumber valueOf(long l) {
|
public static LuaNumber valueOf(long l) {
|
||||||
int i = (int) l;
|
int i = (int) l;
|
||||||
return l==i? (i<=255 && i>=-256? intValues[i+256]:
|
return l==i? (i<=255 && i>=-256? intValues[i+256]:
|
||||||
(LuaNumber) new LuaInteger(i)):
|
(LuaNumber) new LuaInteger(i)):
|
||||||
(LuaNumber) LuaDouble.valueOf(l);
|
(LuaNumber) LuaDouble.valueOf(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The value being held by this instance. */
|
/** The value being held by this instance. */
|
||||||
public final int v;
|
public final int v;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package protected constructor.
|
* Package protected constructor.
|
||||||
* @see LuaValue#valueOf(int)
|
* @see LuaValue#valueOf(int)
|
||||||
**/
|
**/
|
||||||
LuaInteger(int i) {
|
LuaInteger(int i) {
|
||||||
@@ -103,15 +103,15 @@ public class LuaInteger extends LuaNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LuaString optstring(LuaString defval) {
|
public LuaString optstring(LuaString defval) {
|
||||||
return LuaString.valueOf(Integer.toString(v));
|
return LuaString.valueOf(Integer.toString(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue tostring() {
|
public LuaValue tostring() {
|
||||||
return LuaString.valueOf(Integer.toString(v));
|
return LuaString.valueOf(Integer.toString(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String optjstring(String defval) {
|
public String optjstring(String defval) {
|
||||||
return Integer.toString(v);
|
return Integer.toString(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaInteger checkinteger() {
|
public LuaInteger checkinteger() {
|
||||||
@@ -172,48 +172,48 @@ public class LuaInteger extends LuaNumber {
|
|||||||
public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); }
|
public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); }
|
||||||
|
|
||||||
// relational operators
|
// relational operators
|
||||||
public LuaValue lt( LuaValue rhs ) { return rhs.gt_b(v)? TRUE: FALSE; }
|
public LuaValue lt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gt_b(v)? TRUE: FALSE) : super.lt(rhs); }
|
||||||
public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; }
|
||||||
public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; }
|
||||||
public boolean lt_b( LuaValue rhs ) { return rhs.gt_b(v); }
|
public boolean lt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gt_b(v) : super.lt_b(rhs); }
|
||||||
public boolean lt_b( int rhs ) { return v < rhs; }
|
public boolean lt_b( int rhs ) { return v < rhs; }
|
||||||
public boolean lt_b( double rhs ) { return v < rhs; }
|
public boolean lt_b( double rhs ) { return v < rhs; }
|
||||||
public LuaValue lteq( LuaValue rhs ) { return rhs.gteq_b(v)? TRUE: FALSE; }
|
public LuaValue lteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gteq_b(v)? TRUE: FALSE) : super.lteq(rhs); }
|
||||||
public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; }
|
||||||
public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; }
|
||||||
public boolean lteq_b( LuaValue rhs ) { return rhs.gteq_b(v); }
|
public boolean lteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gteq_b(v) : super.lteq_b(rhs); }
|
||||||
public boolean lteq_b( int rhs ) { return v <= rhs; }
|
public boolean lteq_b( int rhs ) { return v <= rhs; }
|
||||||
public boolean lteq_b( double rhs ) { return v <= rhs; }
|
public boolean lteq_b( double rhs ) { return v <= rhs; }
|
||||||
public LuaValue gt( LuaValue rhs ) { return rhs.lt_b(v)? TRUE: FALSE; }
|
public LuaValue gt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lt_b(v)? TRUE: FALSE) : super.gt(rhs); }
|
||||||
public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; }
|
||||||
public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; }
|
||||||
public boolean gt_b( LuaValue rhs ) { return rhs.lt_b(v); }
|
public boolean gt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lt_b(v) : super.gt_b(rhs); }
|
||||||
public boolean gt_b( int rhs ) { return v > rhs; }
|
public boolean gt_b( int rhs ) { return v > rhs; }
|
||||||
public boolean gt_b( double rhs ) { return v > rhs; }
|
public boolean gt_b( double rhs ) { return v > rhs; }
|
||||||
public LuaValue gteq( LuaValue rhs ) { return rhs.lteq_b(v)? TRUE: FALSE; }
|
public LuaValue gteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lteq_b(v)? TRUE: FALSE) : super.gteq(rhs); }
|
||||||
public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; }
|
||||||
public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; }
|
||||||
public boolean gteq_b( LuaValue rhs ) { return rhs.lteq_b(v); }
|
public boolean gteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lteq_b(v) : super.gteq_b(rhs); }
|
||||||
public boolean gteq_b( int rhs ) { return v >= rhs; }
|
public boolean gteq_b( int rhs ) { return v >= rhs; }
|
||||||
public boolean gteq_b( double rhs ) { return v >= rhs; }
|
public boolean gteq_b( double rhs ) { return v >= rhs; }
|
||||||
|
|
||||||
// string comparison
|
// string comparison
|
||||||
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
|
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
|
||||||
|
|
||||||
public int checkint() {
|
public int checkint() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
public long checklong() {
|
public long checklong() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
public double checkdouble() {
|
public double checkdouble() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
public String checkjstring() {
|
public String checkjstring() {
|
||||||
return String.valueOf(v);
|
return String.valueOf(v);
|
||||||
}
|
}
|
||||||
public LuaString checkstring() {
|
public LuaString checkstring() {
|
||||||
return valueOf( String.valueOf(v) );
|
return valueOf( String.valueOf(v) );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,28 +31,28 @@ import java.io.PrintStream;
|
|||||||
import org.luaj.vm2.lib.MathLib;
|
import org.luaj.vm2.lib.MathLib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LuaValue} for representing lua strings.
|
* Subclass of {@link LuaValue} for representing lua strings.
|
||||||
* <p>
|
* <p>
|
||||||
* Because lua string values are more nearly sequences of bytes than
|
* Because lua string values are more nearly sequences of bytes than
|
||||||
* sequences of characters or unicode code points, the {@link LuaString}
|
* sequences of characters or unicode code points, the {@link LuaString}
|
||||||
* implementation holds the string value in an internal byte array.
|
* implementation holds the string value in an internal byte array.
|
||||||
* <p>
|
* <p>
|
||||||
* {@link LuaString} values are not considered mutable once constructed,
|
* {@link LuaString} values are not considered mutable once constructed,
|
||||||
* so multiple {@link LuaString} values can chare a single byte array.
|
* so multiple {@link LuaString} values can chare a single byte array.
|
||||||
* <p>
|
* <p>
|
||||||
* Currently {@link LuaString}s are pooled via a centrally managed weak table.
|
* 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,
|
* To ensure that as many string values as possible take advantage of this,
|
||||||
* Constructors are not exposed directly. As with number, booleans, and nil,
|
* Constructors are not exposed directly. As with number, booleans, and nil,
|
||||||
* instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API.
|
* instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API.
|
||||||
* <p>
|
* <p>
|
||||||
* Because of this pooling, users of LuaString <em>must not directly alter the
|
* Because of this pooling, users of LuaString <em>must not directly alter the
|
||||||
* bytes in a LuaString</em>, or undefined behavior will result.
|
* bytes in a LuaString</em>, or undefined behavior will result.
|
||||||
* <p>
|
* <p>
|
||||||
* When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed.
|
* When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed.
|
||||||
* The functions
|
* The functions
|
||||||
* {@link #lengthAsUtf8(char[])},
|
* {@link #lengthAsUtf8(char[])},
|
||||||
* {@link #encodeToUtf8(char[], int, byte[], int)}, and
|
* {@link #encodeToUtf8(char[], int, byte[], int)}, and
|
||||||
* {@link #decodeAsUtf8(byte[], int, int)}
|
* {@link #decodeAsUtf8(byte[], int, int)}
|
||||||
* are used to convert back and forth between UTF8 byte arrays and character arrays.
|
* are used to convert back and forth between UTF8 byte arrays and character arrays.
|
||||||
*
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
@@ -63,15 +63,15 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/** The singleton instance for string metatables that forwards to the string functions.
|
/** The singleton instance for string metatables that forwards to the string functions.
|
||||||
* Typically, this is set to the string metatable as a side effect of loading the string
|
* Typically, this is set to the string metatable as a side effect of loading the string
|
||||||
* library, and is read-write to provide flexible behavior by default. When used in a
|
* library, and is read-write to provide flexible behavior by default. When used in a
|
||||||
* server environment where there may be roge scripts, this should be replaced with a
|
* server environment where there may be roge scripts, this should be replaced with a
|
||||||
* read-only table since it is shared across all lua code in this Java VM.
|
* read-only table since it is shared across all lua code in this Java VM.
|
||||||
*/
|
*/
|
||||||
public static LuaValue s_metatable;
|
public static LuaValue s_metatable;
|
||||||
|
|
||||||
/** The bytes for the string. These <em><b>must not be mutated directly</b></em> because
|
/** The bytes for the string. These <em><b>must not be mutated directly</b></em> because
|
||||||
* the backing may be shared by multiple LuaStrings, and the hash code is
|
* the backing may be shared by multiple LuaStrings, and the hash code is
|
||||||
* computed only at construction time.
|
* computed only at construction time.
|
||||||
* It is exposed only for performance and legacy reasons. */
|
* It is exposed only for performance and legacy reasons. */
|
||||||
public final byte[] m_bytes;
|
public final byte[] m_bytes;
|
||||||
|
|
||||||
@@ -84,29 +84,29 @@ public class LuaString extends LuaValue {
|
|||||||
/** The hashcode for this string. Computed at construct time. */
|
/** The hashcode for this string. Computed at construct time. */
|
||||||
private final int m_hashcode;
|
private final int m_hashcode;
|
||||||
|
|
||||||
/** Size of cache of recent short strings. This is the maximum number of LuaStrings that
|
/** Size of cache of recent short strings. This is the maximum number of LuaStrings that
|
||||||
* will be retained in the cache of recent short strings. Exposed to package for testing. */
|
* will be retained in the cache of recent short strings. Exposed to package for testing. */
|
||||||
static final int RECENT_STRINGS_CACHE_SIZE = 128;
|
static final int RECENT_STRINGS_CACHE_SIZE = 128;
|
||||||
|
|
||||||
/** Maximum length of a string to be considered for recent short strings caching.
|
/** Maximum length of a string to be considered for recent short strings caching.
|
||||||
* This effectively limits the total memory that can be spent on the recent strings cache,
|
* This effectively limits the total memory that can be spent on the recent strings cache,
|
||||||
* because no LuaString whose backing exceeds this length will be put into the cache.
|
* because no LuaString whose backing exceeds this length will be put into the cache.
|
||||||
* Exposed to package for testing. */
|
* Exposed to package for testing. */
|
||||||
static final int RECENT_STRINGS_MAX_LENGTH = 32;
|
static final int RECENT_STRINGS_MAX_LENGTH = 32;
|
||||||
|
|
||||||
/** Simple cache of recently created strings that are short.
|
/** Simple cache of recently created strings that are short.
|
||||||
* This is simply a list of strings, indexed by their hash codes modulo the cache size
|
* This is simply a list of strings, indexed by their hash codes modulo the cache size
|
||||||
* that have been recently constructed. If a string is being constructed frequently
|
* that have been recently constructed. If a string is being constructed frequently
|
||||||
* from different contexts, it will generally show up as a cache hit and resolve
|
* from different contexts, it will generally show up as a cache hit and resolve
|
||||||
* to the same value. */
|
* to the same value. */
|
||||||
private static final class RecentShortStrings {
|
private static final class RecentShortStrings {
|
||||||
private static final LuaString recent_short_strings[] =
|
private static final LuaString recent_short_strings[] =
|
||||||
new LuaString[RECENT_STRINGS_CACHE_SIZE];
|
new LuaString[RECENT_STRINGS_CACHE_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a {@link LuaString} instance whose bytes match
|
* Get a {@link LuaString} instance whose bytes match
|
||||||
* the supplied Java String using the UTF8 encoding.
|
* the supplied Java String using the UTF8 encoding.
|
||||||
* @param string Java String containing characters to encode as UTF8
|
* @param string Java String containing characters to encode as UTF8
|
||||||
* @return {@link LuaString} with UTF8 bytes corresponding to the supplied String
|
* @return {@link LuaString} with UTF8 bytes corresponding to the supplied String
|
||||||
*/
|
*/
|
||||||
@@ -120,7 +120,7 @@ public class LuaString extends LuaValue {
|
|||||||
/** Construct a {@link LuaString} for a portion of a byte array.
|
/** Construct a {@link LuaString} for a portion of a byte array.
|
||||||
* <p>
|
* <p>
|
||||||
* The array is first be used as the backing for this object, so clients must not change contents.
|
* The array is first be used as the backing for this object, so clients must not change contents.
|
||||||
* If the supplied value for 'len' is more than half the length of the container, the
|
* If the supplied value for 'len' is more than half the length of the container, the
|
||||||
* supplied byte array will be used as the backing, otherwise the bytes will be copied to a
|
* supplied byte array will be used as the backing, otherwise the bytes will be copied to a
|
||||||
* new byte array, and cache lookup may be performed.
|
* new byte array, and cache lookup may be performed.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -172,11 +172,11 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/** Construct a {@link LuaString} using the supplied characters as byte values.
|
/** Construct a {@link LuaString} using the supplied characters as byte values.
|
||||||
* <p>
|
* <p>
|
||||||
* Only the low-order 8-bits of each character are used, the remainder is ignored.
|
* Only the low-order 8-bits of each character are used, the remainder is ignored.
|
||||||
* <p>
|
* <p>
|
||||||
* This is most useful for constructing byte sequences that do not conform to UTF8.
|
* 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.
|
* @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
|
* @return {@link LuaString} wrapping a copy of the byte buffer
|
||||||
*/
|
*/
|
||||||
public static LuaString valueOf(char[] bytes) {
|
public static LuaString valueOf(char[] bytes) {
|
||||||
return valueOf(bytes, 0, bytes.length);
|
return valueOf(bytes, 0, bytes.length);
|
||||||
@@ -184,11 +184,11 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/** Construct a {@link LuaString} using the supplied characters as byte values.
|
/** Construct a {@link LuaString} using the supplied characters as byte values.
|
||||||
* <p>
|
* <p>
|
||||||
* Only the low-order 8-bits of each character are used, the remainder is ignored.
|
* Only the low-order 8-bits of each character are used, the remainder is ignored.
|
||||||
* <p>
|
* <p>
|
||||||
* This is most useful for constructing byte sequences that do not conform to UTF8.
|
* 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.
|
* @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
|
* @return {@link LuaString} wrapping a copy of the byte buffer
|
||||||
*/
|
*/
|
||||||
public static LuaString valueOf(char[] bytes, int off, int len) {
|
public static LuaString valueOf(char[] bytes, int off, int len) {
|
||||||
byte[] b = new byte[len];
|
byte[] b = new byte[len];
|
||||||
@@ -215,7 +215,7 @@ public class LuaString extends LuaValue {
|
|||||||
* The LuaString returned will either be a new LuaString containing the byte array,
|
* The LuaString returned will either be a new LuaString containing the byte array,
|
||||||
* or be an existing LuaString used already having the same value.
|
* or be an existing LuaString used already having the same value.
|
||||||
* <p>
|
* <p>
|
||||||
* The caller must not mutate the contents of the byte array after this call, as
|
* The caller must not mutate the contents of the byte array after this call, as
|
||||||
* it may be used elsewhere due to recent short string caching.
|
* it may be used elsewhere due to recent short string caching.
|
||||||
* @param bytes byte buffer
|
* @param bytes byte buffer
|
||||||
* @return {@link LuaString} wrapping the byte buffer
|
* @return {@link LuaString} wrapping the byte buffer
|
||||||
@@ -241,11 +241,11 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isstring() {
|
public boolean isstring() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue getmetatable() {
|
public LuaValue getmetatable() {
|
||||||
return s_metatable;
|
return s_metatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int type() {
|
public int type() {
|
||||||
@@ -289,20 +289,20 @@ public class LuaString extends LuaValue {
|
|||||||
public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs, checkarith()); }
|
public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs, checkarith()); }
|
||||||
|
|
||||||
// relational operators, these only work with other strings
|
// relational operators, these only work with other strings
|
||||||
public LuaValue lt( LuaValue rhs ) { return rhs.strcmp(this)>0? LuaValue.TRUE: FALSE; }
|
public LuaValue lt( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)>0? LuaValue.TRUE: FALSE) : super.lt(rhs); }
|
||||||
public boolean lt_b( LuaValue rhs ) { return rhs.strcmp(this)>0; }
|
public boolean lt_b( LuaValue rhs ) { return rhs.isstring() ? rhs.strcmp(this)>0 : super.lt_b(rhs); }
|
||||||
public boolean lt_b( int rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean lt_b( int rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
public boolean lt_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean lt_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
public LuaValue lteq( LuaValue rhs ) { return rhs.strcmp(this)>=0? LuaValue.TRUE: FALSE; }
|
public LuaValue lteq( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)>=0? LuaValue.TRUE: FALSE) : super.lteq(rhs); }
|
||||||
public boolean lteq_b( LuaValue rhs ) { return rhs.strcmp(this)>=0; }
|
public boolean lteq_b( LuaValue rhs ) { return rhs.isstring() ? rhs.strcmp(this)>=0 : super.lteq_b(rhs); }
|
||||||
public boolean lteq_b( int rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean lteq_b( int rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
public boolean lteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean lteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
public LuaValue gt( LuaValue rhs ) { return rhs.strcmp(this)<0? LuaValue.TRUE: FALSE; }
|
public LuaValue gt( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)<0? LuaValue.TRUE: FALSE) : super.gt(rhs); }
|
||||||
public boolean gt_b( LuaValue rhs ) { return rhs.strcmp(this)<0; }
|
public boolean gt_b( LuaValue rhs ) { return rhs.isstring() ? rhs.strcmp(this)<0 : super.gt_b(rhs); }
|
||||||
public boolean gt_b( int rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean gt_b( int rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
public boolean gt_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean gt_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
public LuaValue gteq( LuaValue rhs ) { return rhs.strcmp(this)<=0? LuaValue.TRUE: FALSE; }
|
public LuaValue gteq( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)<=0? LuaValue.TRUE: FALSE) : super.gteq(rhs); }
|
||||||
public boolean gteq_b( LuaValue rhs ) { return rhs.strcmp(this)<=0; }
|
public boolean gteq_b( LuaValue rhs ) { return rhs.isstring() ? rhs.strcmp(this)<=0 : super.gteq_b(rhs); }
|
||||||
public boolean gteq_b( int rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean gteq_b( int rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
public boolean gteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean gteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
|
|
||||||
@@ -310,14 +310,14 @@ public class LuaString extends LuaValue {
|
|||||||
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
|
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
|
||||||
public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
|
public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
|
||||||
public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); }
|
public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); }
|
||||||
public LuaValue concatTo(LuaString lhs) {
|
public LuaValue concatTo(LuaString lhs) {
|
||||||
byte[] b = new byte[lhs.m_length+this.m_length];
|
byte[] b = new byte[lhs.m_length+this.m_length];
|
||||||
System.arraycopy(lhs.m_bytes, lhs.m_offset, b, 0, lhs.m_length);
|
System.arraycopy(lhs.m_bytes, lhs.m_offset, b, 0, lhs.m_length);
|
||||||
System.arraycopy(this.m_bytes, this.m_offset, b, lhs.m_length, this.m_length);
|
System.arraycopy(this.m_bytes, this.m_offset, b, lhs.m_length, this.m_length);
|
||||||
return valueUsing(b, 0, b.length);
|
return valueUsing(b, 0, b.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// string comparison
|
// string comparison
|
||||||
public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); }
|
public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); }
|
||||||
public int strcmp(LuaString rhs) {
|
public int strcmp(LuaString rhs) {
|
||||||
for ( int i=0, j=0; i<m_length && j<rhs.m_length; ++i, ++j ) {
|
for ( int i=0, j=0; i<m_length && j<rhs.m_length; ++i, ++j ) {
|
||||||
@@ -329,9 +329,9 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Check for number in arithmetic, or throw aritherror */
|
/** Check for number in arithmetic, or throw aritherror */
|
||||||
private double checkarith() {
|
private double checkarith() {
|
||||||
double d = scannumber();
|
double d = scannumber();
|
||||||
if ( Double.isNaN(d) )
|
if ( Double.isNaN(d) )
|
||||||
aritherror();
|
aritherror();
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@@ -368,15 +368,15 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
public boolean isint() {
|
public boolean isint() {
|
||||||
double d = scannumber();
|
double d = scannumber();
|
||||||
if ( Double.isNaN(d) )
|
if ( Double.isNaN(d) )
|
||||||
return false;
|
return false;
|
||||||
int i = (int) d;
|
int i = (int) d;
|
||||||
return i == d;
|
return i == d;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean islong() {
|
public boolean islong() {
|
||||||
double d = scannumber();
|
double d = scannumber();
|
||||||
if ( Double.isNaN(d) )
|
if ( Double.isNaN(d) )
|
||||||
return false;
|
return false;
|
||||||
long l = (long) d;
|
long l = (long) d;
|
||||||
return l == d;
|
return l == d;
|
||||||
@@ -398,7 +398,7 @@ public class LuaString extends LuaValue {
|
|||||||
return checkint();
|
return checkint();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaInteger optinteger(LuaInteger defval) {
|
public LuaInteger optinteger(LuaInteger defval) {
|
||||||
return checkinteger();
|
return checkinteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,15 +411,15 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LuaString optstring(LuaString defval) {
|
public LuaString optstring(LuaString defval) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue tostring() {
|
public LuaValue tostring() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String optjstring(String defval) {
|
public String optjstring(String defval) {
|
||||||
return tojstring();
|
return tojstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaString strvalue() {
|
public LuaString strvalue() {
|
||||||
@@ -429,7 +429,7 @@ public class LuaString extends LuaValue {
|
|||||||
/** Take a substring using Java zero-based indexes for begin and end or range.
|
/** Take a substring using Java zero-based indexes for begin and end or range.
|
||||||
* @param beginIndex The zero-based index of the first character to include.
|
* @param beginIndex The zero-based index of the first character to include.
|
||||||
* @param endIndex The zero-based index of position after the last character.
|
* @param endIndex The zero-based index of position after the last character.
|
||||||
* @return LuaString which is a substring whose first character is at offset
|
* @return LuaString which is a substring whose first character is at offset
|
||||||
* beginIndex and extending for (endIndex - beginIndex ) characters.
|
* beginIndex and extending for (endIndex - beginIndex ) characters.
|
||||||
*/
|
*/
|
||||||
public LuaString substring( int beginIndex, int endIndex ) {
|
public LuaString substring( int beginIndex, int endIndex ) {
|
||||||
@@ -476,7 +476,7 @@ public class LuaString extends LuaValue {
|
|||||||
return val.raweq(this);
|
return val.raweq(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean raweq( LuaString s ) {
|
public boolean raweq( LuaString s ) {
|
||||||
if ( this == s )
|
if ( this == s )
|
||||||
return true;
|
return true;
|
||||||
if ( s.m_length != m_length )
|
if ( s.m_length != m_length )
|
||||||
@@ -503,7 +503,7 @@ public class LuaString extends LuaValue {
|
|||||||
public static boolean equals( byte[] a, int i, byte[] b, int j, int n ) {
|
public static boolean equals( byte[] a, int i, byte[] b, int j, int n ) {
|
||||||
if ( a.length < i + n || b.length < j + n )
|
if ( a.length < i + n || b.length < j + n )
|
||||||
return false;
|
return false;
|
||||||
while ( --n>=0 )
|
while ( --n>=0 )
|
||||||
if ( a[i++]!=b[j++] )
|
if ( a[i++]!=b[j++] )
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
@@ -535,8 +535,8 @@ public class LuaString extends LuaValue {
|
|||||||
return luaByte( index );
|
return luaByte( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String checkjstring() {
|
public String checkjstring() {
|
||||||
return tojstring();
|
return tojstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaString checkstring() {
|
public LuaString checkstring() {
|
||||||
@@ -552,7 +552,7 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 strOffset offset from which to copy
|
||||||
* @param bytes destination byte array
|
* @param bytes destination byte array
|
||||||
* @param arrayOffset offset in destination
|
* @param arrayOffset offset in destination
|
||||||
@@ -626,12 +626,12 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 bytes byte array in UTF8 encoding to convert
|
||||||
* @param offset starting index in byte array
|
* @param offset starting index in byte array
|
||||||
* @param length number of bytes to convert
|
* @param length number of bytes to convert
|
||||||
* @return Java String corresponding to the value of bytes interpreted using UTF8
|
* @return Java String corresponding to the value of bytes interpreted using UTF8
|
||||||
* @see #lengthAsUtf8(char[])
|
* @see #lengthAsUtf8(char[])
|
||||||
* @see #encodeToUtf8(char[], int, byte[], int)
|
* @see #encodeToUtf8(char[], int, byte[], int)
|
||||||
* @see #isValidUtf8()
|
* @see #isValidUtf8()
|
||||||
@@ -692,7 +692,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the given Java string as UTF-8 bytes, writing the result to bytes
|
* Encode the given Java string as UTF-8 bytes, writing the result to bytes
|
||||||
* starting at offset.
|
* starting at offset.
|
||||||
* <p>
|
* <p>
|
||||||
* The string should be measured first with lengthAsUtf8
|
* The string should be measured first with lengthAsUtf8
|
||||||
* to make sure the given byte array is large enough.
|
* to make sure the given byte array is large enough.
|
||||||
@@ -759,22 +759,22 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
// --------------------- number conversion -----------------------
|
// --------------------- number conversion -----------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert to a number using baee 10 or base 16 if it starts with '0x',
|
* convert to a number using baee 10 or base 16 if it starts with '0x',
|
||||||
* or NIL if it can't be converted
|
* or NIL if it can't be converted
|
||||||
* @return IntValue, DoubleValue, or NIL depending on the content of the string.
|
* @return IntValue, DoubleValue, or NIL depending on the content of the string.
|
||||||
* @see LuaValue#tonumber()
|
* @see LuaValue#tonumber()
|
||||||
*/
|
*/
|
||||||
public LuaValue tonumber() {
|
public LuaValue tonumber() {
|
||||||
double d = scannumber();
|
double d = scannumber();
|
||||||
return Double.isNaN(d)? NIL: valueOf(d);
|
return Double.isNaN(d)? NIL: valueOf(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert to a number using a supplied base, or NIL if it can't be converted
|
* convert to a number using a supplied base, or NIL if it can't be converted
|
||||||
* @param base the base to use, such as 10
|
* @param base the base to use, such as 10
|
||||||
* @return IntValue, DoubleValue, or NIL depending on the content of the string.
|
* @return IntValue, DoubleValue, or NIL depending on the content of the string.
|
||||||
* @see LuaValue#tonumber()
|
* @see LuaValue#tonumber()
|
||||||
*/
|
*/
|
||||||
public LuaValue tonumber( int base ) {
|
public LuaValue tonumber( int base ) {
|
||||||
double d = scannumber( base );
|
double d = scannumber( base );
|
||||||
@@ -800,7 +800,7 @@ public class LuaString extends LuaValue {
|
|||||||
/**
|
/**
|
||||||
* Convert to a number in base 10, or base 16 if the string starts with '0x',
|
* Convert to a number in base 10, or base 16 if the string starts with '0x',
|
||||||
* or return Double.NaN if it cannot be converted to a number.
|
* or return Double.NaN if it cannot be converted to a number.
|
||||||
* @return double value if conversion is valid, or Double.NaN if not
|
* @return double value if conversion is valid, or Double.NaN if not
|
||||||
*/
|
*/
|
||||||
public double scannumber() {
|
public double scannumber() {
|
||||||
int i = m_offset, j = m_offset + m_length;
|
int i = m_offset, j = m_offset + m_length;
|
||||||
@@ -863,10 +863,10 @@ public class LuaString extends LuaValue {
|
|||||||
return sgn * m * MathLib.dpow_d(2.0, e);
|
return sgn * m * MathLib.dpow_d(2.0, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert to a number in a base, or return Double.NaN if not a number.
|
* Convert to a number in a base, or return Double.NaN if not a number.
|
||||||
* @param base the base to use between 2 and 36
|
* @param base the base to use between 2 and 36
|
||||||
* @return double value if conversion is valid, or Double.NaN if not
|
* @return double value if conversion is valid, or Double.NaN if not
|
||||||
*/
|
*/
|
||||||
public double scannumber(int base) {
|
public double scannumber(int base) {
|
||||||
if ( base < 2 || base > 36 )
|
if ( base < 2 || base > 36 )
|
||||||
@@ -884,7 +884,7 @@ public class LuaString extends LuaValue {
|
|||||||
* @param base the base to use, such as 10
|
* @param base the base to use, such as 10
|
||||||
* @param start the index to start searching from
|
* @param start the index to start searching from
|
||||||
* @param end the first index beyond the search range
|
* @param end the first index beyond the search range
|
||||||
* @return double value if conversion is valid,
|
* @return double value if conversion is valid,
|
||||||
* or Double.NaN if not
|
* or Double.NaN if not
|
||||||
*/
|
*/
|
||||||
private double scanlong( int base, int start, int end ) {
|
private double scanlong( int base, int start, int end ) {
|
||||||
@@ -895,7 +895,7 @@ public class LuaString extends LuaValue {
|
|||||||
int digit = m_bytes[i] - (base<=10||(m_bytes[i]>='0'&&m_bytes[i]<='9')? '0':
|
int digit = m_bytes[i] - (base<=10||(m_bytes[i]>='0'&&m_bytes[i]<='9')? '0':
|
||||||
m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10));
|
m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10));
|
||||||
if ( digit < 0 || digit >= base )
|
if ( digit < 0 || digit >= base )
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
x = x * base + digit;
|
x = x * base + digit;
|
||||||
if ( x < 0 )
|
if ( x < 0 )
|
||||||
return Double.NaN; // overflow
|
return Double.NaN; // overflow
|
||||||
@@ -907,7 +907,7 @@ public class LuaString extends LuaValue {
|
|||||||
* Scan and convert a double value, or return Double.NaN if not a double.
|
* Scan and convert a double value, or return Double.NaN if not a double.
|
||||||
* @param start the index to start searching from
|
* @param start the index to start searching from
|
||||||
* @param end the first index beyond the search range
|
* @param end the first index beyond the search range
|
||||||
* @return double value if conversion is valid,
|
* @return double value if conversion is valid,
|
||||||
* or Double.NaN if not
|
* or Double.NaN if not
|
||||||
*/
|
*/
|
||||||
private double scandouble(int start, int end) {
|
private double scandouble(int start, int end) {
|
||||||
@@ -930,7 +930,7 @@ public class LuaString extends LuaValue {
|
|||||||
c[i-start] = (char) m_bytes[i];
|
c[i-start] = (char) m_bytes[i];
|
||||||
try {
|
try {
|
||||||
return Double.parseDouble(new String(c));
|
return Double.parseDouble(new String(c));
|
||||||
} catch ( Exception e ) {
|
} catch ( Exception e ) {
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,23 +25,23 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LuaValue} for representing lua tables.
|
* Subclass of {@link LuaValue} for representing lua tables.
|
||||||
* <p>
|
* <p>
|
||||||
* Almost all API's implemented in {@link LuaTable} are defined and documented in {@link LuaValue}.
|
* Almost all API's implemented in {@link LuaTable} are defined and documented in {@link LuaValue}.
|
||||||
* <p>
|
* <p>
|
||||||
* If a table is needed, the one of the type-checking functions can be used such as
|
* If a table is needed, the one of the type-checking functions can be used such as
|
||||||
* {@link #istable()},
|
* {@link #istable()},
|
||||||
* {@link #checktable()}, or
|
* {@link #checktable()}, or
|
||||||
* {@link #opttable(LuaTable)}
|
* {@link #opttable(LuaTable)}
|
||||||
* <p>
|
* <p>
|
||||||
* The main table operations are defined on {@link LuaValue}
|
* The main table operations are defined on {@link LuaValue}
|
||||||
* for getting and setting values with and without metatag processing:
|
* for getting and setting values with and without metatag processing:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #get(LuaValue)}</li>
|
* <li>{@link #get(LuaValue)}</li>
|
||||||
* <li>{@link #set(LuaValue,LuaValue)}</li>
|
* <li>{@link #set(LuaValue,LuaValue)}</li>
|
||||||
* <li>{@link #rawget(LuaValue)}</li>
|
* <li>{@link #rawget(LuaValue)}</li>
|
||||||
* <li>{@link #rawset(LuaValue,LuaValue)}</li>
|
* <li>{@link #rawset(LuaValue,LuaValue)}</li>
|
||||||
* <li>plus overloads such as {@link #get(String)}, {@link #get(int)}, and so on</li>
|
* <li>plus overloads such as {@link #get(String)}, {@link #get(int)}, and so on</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* To iterate over key-value pairs from Java, use
|
* To iterate over key-value pairs from Java, use
|
||||||
@@ -56,7 +56,7 @@ import java.util.Vector;
|
|||||||
* }}</pre>
|
* }}</pre>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* As with other types, {@link LuaTable} instances should be constructed via one of the table constructor
|
* As with other types, {@link LuaTable} instances should be constructed via one of the table constructor
|
||||||
* methods on {@link LuaValue}:
|
* methods on {@link LuaValue}:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link LuaValue#tableOf()} empty table</li>
|
* <li>{@link LuaValue#tableOf()} empty table</li>
|
||||||
@@ -92,7 +92,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
hash = NOBUCKETS;
|
hash = NOBUCKETS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct table with preset capacity.
|
* Construct table with preset capacity.
|
||||||
* @param narray capacity of array part
|
* @param narray capacity of array part
|
||||||
* @param nhash capacity of hash part
|
* @param nhash capacity of hash part
|
||||||
@@ -102,9 +102,9 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct table with named and unnamed parts.
|
* Construct table with named and unnamed parts.
|
||||||
* @param named Named elements in order {@code key-a, value-a, key-b, value-b, ... }
|
* @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 unnamed Unnamed elements in order {@code value-1, value-2, ... }
|
||||||
* @param lastarg Additional unnamed values beyond {@code unnamed.length}
|
* @param lastarg Additional unnamed values beyond {@code unnamed.length}
|
||||||
*/
|
*/
|
||||||
public LuaTable(LuaValue[] named, LuaValue[] unnamed, Varargs lastarg) {
|
public LuaTable(LuaValue[] named, LuaValue[] unnamed, Varargs lastarg) {
|
||||||
@@ -123,17 +123,17 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct table of unnamed elements.
|
* Construct table of unnamed elements.
|
||||||
* @param varargs Unnamed elements in order {@code value-1, value-2, ... }
|
* @param varargs Unnamed elements in order {@code value-1, value-2, ... }
|
||||||
*/
|
*/
|
||||||
public LuaTable(Varargs varargs) {
|
public LuaTable(Varargs varargs) {
|
||||||
this(varargs,1);
|
this(varargs,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct table of unnamed elements.
|
* Construct table of unnamed elements.
|
||||||
* @param varargs Unnamed elements in order {@code value-1, value-2, ... }
|
* @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
|
* @param firstarg the index in varargs of the first argument to include in the table
|
||||||
*/
|
*/
|
||||||
public LuaTable(Varargs varargs, int firstarg) {
|
public LuaTable(Varargs varargs, int firstarg) {
|
||||||
int nskip = firstarg-1;
|
int nskip = firstarg-1;
|
||||||
@@ -152,8 +152,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
return "table";
|
return "table";
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean istable() {
|
public boolean istable() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaTable checktable() {
|
public LuaTable checktable() {
|
||||||
@@ -185,17 +185,17 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the length of the array part of the table.
|
* 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.
|
* @return length of the array part, does not relate to count of objects in the table.
|
||||||
*/
|
*/
|
||||||
protected int getArrayLength() {
|
protected int getArrayLength() {
|
||||||
return array.length;
|
return array.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the length of the hash part of the table.
|
* 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.
|
* @return length of the hash part, does not relate to count of objects in the table.
|
||||||
*/
|
*/
|
||||||
protected int getHashLength() {
|
protected int getHashLength() {
|
||||||
return hash.length;
|
return hash.length;
|
||||||
@@ -294,35 +294,35 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Remove the element at a position in a list-table
|
/** Remove the element at a position in a list-table
|
||||||
*
|
*
|
||||||
* @param pos the position to remove
|
* @param pos the position to remove
|
||||||
* @return The removed item, or {@link #NONE} if not removed
|
* @return The removed item, or {@link #NONE} if not removed
|
||||||
*/
|
*/
|
||||||
public LuaValue remove(int pos) {
|
public LuaValue remove(int pos) {
|
||||||
int n = rawlen();
|
int n = length();
|
||||||
if ( pos == 0 )
|
if ( pos == 0 )
|
||||||
pos = n;
|
pos = n;
|
||||||
else if (pos > n)
|
else if (pos > n)
|
||||||
return NONE;
|
return NONE;
|
||||||
LuaValue v = rawget(pos);
|
LuaValue v = get(pos);
|
||||||
for ( LuaValue r=v; !r.isnil(); ) {
|
for ( LuaValue r=v; !r.isnil(); ) {
|
||||||
r = rawget(pos+1);
|
r = get(pos+1);
|
||||||
rawset(pos++, r);
|
set(pos++, r);
|
||||||
}
|
}
|
||||||
return v.isnil()? NONE: v;
|
return v.isnil()? NONE: v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Insert an element at a position in a list-table
|
/** Insert an element at a position in a list-table
|
||||||
*
|
*
|
||||||
* @param pos the position to remove
|
* @param pos the position to remove
|
||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
public void insert(int pos, LuaValue value) {
|
public void insert(int pos, LuaValue value) {
|
||||||
if ( pos == 0 )
|
if ( pos == 0 )
|
||||||
pos = rawlen()+1;
|
pos = length()+1;
|
||||||
while ( ! value.isnil() ) {
|
while ( ! value.isnil() ) {
|
||||||
LuaValue v = rawget( pos );
|
LuaValue v = get( pos );
|
||||||
rawset(pos++, value);
|
set(pos++, value);
|
||||||
value = v;
|
value = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,14 +355,14 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
return rawlen();
|
return rawlen();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue len() {
|
public LuaValue len() {
|
||||||
final LuaValue h = metatag(LEN);
|
final LuaValue h = metatag(LEN);
|
||||||
if (h.toboolean())
|
if (h.toboolean())
|
||||||
return h.call(this);
|
return h.call(this);
|
||||||
return LuaInteger.valueOf(rawlen());
|
return LuaInteger.valueOf(rawlen());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int rawlen() {
|
public int rawlen() {
|
||||||
int a = getArrayLength();
|
int a = getArrayLength();
|
||||||
int n = a+1,m=0;
|
int n = a+1,m=0;
|
||||||
while ( !rawget(n).isnil() ) {
|
while ( !rawget(n).isnil() ) {
|
||||||
@@ -380,7 +380,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next element after a particular key in the table
|
* Get the next element after a particular key in the table
|
||||||
* @return key,value or nil
|
* @return key,value or nil
|
||||||
*/
|
*/
|
||||||
public Varargs next( LuaValue key ) {
|
public Varargs next( LuaValue key ) {
|
||||||
@@ -441,8 +441,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next element after a particular key in the
|
* Get the next element after a particular key in the
|
||||||
* contiguous array part of a table
|
* contiguous array part of a table
|
||||||
* @return key,value or none
|
* @return key,value or none
|
||||||
*/
|
*/
|
||||||
public Varargs inext(LuaValue key) {
|
public Varargs inext(LuaValue key) {
|
||||||
@@ -472,7 +472,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( checkLoadFactor() ) {
|
if ( checkLoadFactor() ) {
|
||||||
if ( key.isinttype() && key.toint() > 0 ) {
|
if ( (m_metatable == null || !m_metatable.useWeakValues())
|
||||||
|
&& key.isinttype() && key.toint() > 0 ) {
|
||||||
// a rehash might make room in the array portion for this key.
|
// a rehash might make room in the array portion for this key.
|
||||||
rehash( key.toint() );
|
rehash( key.toint() );
|
||||||
if ( arrayset(key.toint(), value) )
|
if ( arrayset(key.toint(), value) )
|
||||||
@@ -517,7 +518,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the hashtable slot to use
|
* Find the hashtable slot to use
|
||||||
* @param key key to look for
|
* @param key key to look for
|
||||||
* @return slot to use
|
* @return slot to use
|
||||||
@@ -719,7 +720,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
StrongSlot entry = slot.first();
|
StrongSlot entry = slot.first();
|
||||||
if (entry != null)
|
if (entry != null)
|
||||||
newArray[ k - 1 ] = entry.value();
|
newArray[ k - 1 ] = entry.value();
|
||||||
} else {
|
} else if ( !(slot instanceof DeadSlot) ) {
|
||||||
int j = slot.keyindex( newHashMask );
|
int j = slot.keyindex( newHashMask );
|
||||||
newHash[j] = slot.relink( newHash[j] );
|
newHash[j] = slot.relink( newHash[j] );
|
||||||
}
|
}
|
||||||
@@ -779,7 +780,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
//
|
//
|
||||||
// implemented heap sort from wikipedia
|
// implemented heap sort from wikipedia
|
||||||
//
|
//
|
||||||
// Only sorts the contiguous array part.
|
// Only sorts the contiguous array part.
|
||||||
//
|
//
|
||||||
/** Sort the table using a comparator.
|
/** Sort the table using a comparator.
|
||||||
* @param comparator {@link LuaValue} to be called to compare elements.
|
* @param comparator {@link LuaValue} to be called to compare elements.
|
||||||
@@ -789,33 +790,35 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
if (m_metatable != null && m_metatable.useWeakValues()) {
|
if (m_metatable != null && m_metatable.useWeakValues()) {
|
||||||
dropWeakArrayValues();
|
dropWeakArrayValues();
|
||||||
}
|
}
|
||||||
int n = array.length;
|
int n = length();
|
||||||
while ( n > 0 && array[n-1] == null )
|
if ( n > 1 )
|
||||||
--n;
|
heapSort(n, comparator.isnil() ? null : comparator);
|
||||||
if ( n > 1 )
|
|
||||||
heapSort(n, comparator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void heapSort(int count, LuaValue cmpfunc) {
|
private void heapSort(int count, LuaValue cmpfunc) {
|
||||||
heapify(count, cmpfunc);
|
heapify(count, cmpfunc);
|
||||||
for ( int end=count-1; end>0; ) {
|
for ( int end=count; end>1; ) {
|
||||||
swap(end, 0);
|
LuaValue a = get(end); // swap(end, 1)
|
||||||
siftDown(0, --end, cmpfunc);
|
set(end, get(1));
|
||||||
|
set(1, a);
|
||||||
|
siftDown(1, --end, cmpfunc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void heapify(int count, LuaValue cmpfunc) {
|
private void heapify(int count, LuaValue cmpfunc) {
|
||||||
for ( int start=count/2-1; start>=0; --start )
|
for ( int start=count/2; start>0; --start )
|
||||||
siftDown(start, count - 1, cmpfunc);
|
siftDown(start, count, cmpfunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void siftDown(int start, int end, LuaValue cmpfunc) {
|
private void siftDown(int start, int end, LuaValue cmpfunc) {
|
||||||
for ( int root=start; root*2+1 <= end; ) {
|
for ( int root=start; root*2 <= end; ) {
|
||||||
int child = root*2+1;
|
int child = root*2;
|
||||||
if (child < end && compare(child, child + 1, cmpfunc))
|
if (child < end && compare(child, child + 1, cmpfunc))
|
||||||
++child;
|
++child;
|
||||||
if (compare(root, child, cmpfunc)) {
|
if (compare(root, child, cmpfunc)) {
|
||||||
swap(root, child);
|
LuaValue a = get(root); // swap(root, child)
|
||||||
|
set(root, get(child));
|
||||||
|
set(child, a);
|
||||||
root = child;
|
root = child;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
@@ -823,32 +826,19 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean compare(int i, int j, LuaValue cmpfunc) {
|
private boolean compare(int i, int j, LuaValue cmpfunc) {
|
||||||
LuaValue a, b;
|
LuaValue a = get(i), b = get(j);
|
||||||
if (m_metatable == null) {
|
|
||||||
a = array[i];
|
|
||||||
b = array[j];
|
|
||||||
} else {
|
|
||||||
a = m_metatable.arrayget(array, i);
|
|
||||||
b = m_metatable.arrayget(array, j);
|
|
||||||
}
|
|
||||||
if ( a == null || b == null )
|
if ( a == null || b == null )
|
||||||
return false;
|
return false;
|
||||||
if ( ! cmpfunc.isnil() ) {
|
if ( cmpfunc != null ) {
|
||||||
return cmpfunc.call(a,b).toboolean();
|
return cmpfunc.call(a,b).toboolean();
|
||||||
} else {
|
} else {
|
||||||
return a.lt_b(b);
|
return a.lt_b(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void swap(int i, int j) {
|
/** This may be deprecated in a future release.
|
||||||
LuaValue a = array[i];
|
|
||||||
array[i] = array[j];
|
|
||||||
array[j] = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This may be deprecated in a future release.
|
|
||||||
* It is recommended to count via iteration over next() instead
|
* It is recommended to count via iteration over next() instead
|
||||||
* @return count of keys in the table
|
* @return count of keys in the table
|
||||||
* */
|
* */
|
||||||
public int keyCount() {
|
public int keyCount() {
|
||||||
LuaValue k = LuaValue.NIL;
|
LuaValue k = LuaValue.NIL;
|
||||||
@@ -859,9 +849,9 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This may be deprecated in a future release.
|
/** This may be deprecated in a future release.
|
||||||
* It is recommended to use next() instead
|
* It is recommended to use next() instead
|
||||||
* @return array of keys in the table
|
* @return array of keys in the table
|
||||||
* */
|
* */
|
||||||
public LuaValue[] keys() {
|
public LuaValue[] keys() {
|
||||||
Vector l = new Vector();
|
Vector l = new Vector();
|
||||||
|
|||||||
@@ -24,16 +24,16 @@ package org.luaj.vm2;
|
|||||||
/**
|
/**
|
||||||
* Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
|
* Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values.
|
||||||
* <p>
|
* <p>
|
||||||
* To construct varargs, use one of the static methods such as
|
* To construct varargs, use one of the static methods such as
|
||||||
* {@code LuaValue.varargsOf(LuaValue,LuaValue)}
|
* {@code LuaValue.varargsOf(LuaValue,LuaValue)}
|
||||||
* <p>
|
* <p>
|
||||||
* <p>
|
* <p>
|
||||||
* Any LuaValue can be used as a stand-in for Varargs, for both calls and return values.
|
* Any LuaValue can be used as a stand-in for Varargs, for both calls and return values.
|
||||||
* When doing so, nargs() will return 1 and arg1() or arg(1) will return this.
|
* When doing so, nargs() will return 1 and arg1() or arg(1) will return this.
|
||||||
* This simplifies the case when calling or implementing varargs functions with only
|
* This simplifies the case when calling or implementing varargs functions with only
|
||||||
* 1 argument or 1 return value.
|
* 1 argument or 1 return value.
|
||||||
* <p>
|
* <p>
|
||||||
* Varargs can also be derived from other varargs by appending to the front with a call
|
* Varargs can also be derived from other varargs by appending to the front with a call
|
||||||
* such as {@code LuaValue.varargsOf(LuaValue,Varargs)}
|
* such as {@code LuaValue.varargsOf(LuaValue,Varargs)}
|
||||||
* or by taking a portion of the args using {@code Varargs.subargs(int start)}
|
* or by taking a portion of the args using {@code Varargs.subargs(int start)}
|
||||||
* <p>
|
* <p>
|
||||||
@@ -57,22 +57,22 @@ public abstract class Varargs {
|
|||||||
abstract public LuaValue arg( int i );
|
abstract public LuaValue arg( int i );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of arguments, or 0 if there are none.
|
* Get the number of arguments, or 0 if there are none.
|
||||||
* @return number of arguments.
|
* @return number of arguments.
|
||||||
*/
|
*/
|
||||||
abstract public int narg();
|
abstract public int narg();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the first argument in the list.
|
* Get the first argument in the list.
|
||||||
* @return LuaValue which is first in the list, or LuaValue.NIL if there are no values.
|
* @return LuaValue which is first in the list, or LuaValue.NIL if there are no values.
|
||||||
* @see Varargs#arg(int)
|
* @see Varargs#arg(int)
|
||||||
* @see LuaValue#NIL
|
* @see LuaValue#NIL
|
||||||
*/
|
*/
|
||||||
abstract public LuaValue arg1();
|
abstract public LuaValue arg1();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate any pending tail call and return result.
|
* Evaluate any pending tail call and return result.
|
||||||
* @return the evaluated tail call result
|
* @return the evaluated tail call result
|
||||||
*/
|
*/
|
||||||
public Varargs eval() { return this; }
|
public Varargs eval() { return this; }
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ public abstract class Varargs {
|
|||||||
// utilities to get specific arguments and type-check them.
|
// utilities to get specific arguments and type-check them.
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
/** Gets the type of argument {@code i}
|
/** Gets the type of argument {@code i}
|
||||||
* @param i the index of the argument to convert, 1 is the first argument
|
* @param i the index of the argument to convert, 1 is the first argument
|
||||||
* @return int value corresponding to one of the LuaValue integer type values
|
* @return int value corresponding to one of the LuaValue integer type values
|
||||||
* @see LuaValue#TNIL
|
* @see LuaValue#TNIL
|
||||||
@@ -117,20 +117,20 @@ public abstract class Varargs {
|
|||||||
public boolean isfunction(int i) { return arg(i).isfunction(); }
|
public boolean isfunction(int i) { return arg(i).isfunction(); }
|
||||||
|
|
||||||
/** Tests if argument i is a number.
|
/** Tests if argument i is a number.
|
||||||
* Since anywhere a number is required, a string can be used that
|
* Since anywhere a number is required, a string can be used that
|
||||||
* is a number, this will return true for both numbers and
|
* is a number, this will return true for both numbers and
|
||||||
* strings that can be interpreted as numbers.
|
* strings that can be interpreted as numbers.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
* @return true if the argument exists and is a number or
|
* @return true if the argument exists and is a number or
|
||||||
* string that can be interpreted as a number, false otherwise
|
* string that can be interpreted as a number, false otherwise
|
||||||
* @see LuaValue#TNUMBER
|
* @see LuaValue#TNUMBER
|
||||||
* @see LuaValue#TSTRING
|
* @see LuaValue#TSTRING
|
||||||
* */
|
* */
|
||||||
public boolean isnumber(int i) { return arg(i).isnumber(); }
|
public boolean isnumber(int i) { return arg(i).isnumber(); }
|
||||||
|
|
||||||
/** Tests if argument i is a string.
|
/** Tests if argument i is a string.
|
||||||
* Since all lua numbers can be used where strings are used,
|
* Since all lua numbers can be used where strings are used,
|
||||||
* this will return true for both strings and numbers.
|
* this will return true for both strings and numbers.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
* @return true if the argument exists and is a string or number, false otherwise
|
* @return true if the argument exists and is a string or number, false otherwise
|
||||||
* @see LuaValue#TNUMBER
|
* @see LuaValue#TNUMBER
|
||||||
@@ -167,7 +167,7 @@ public abstract class Varargs {
|
|||||||
|
|
||||||
/** Return argument i as a boolean value, {@code defval} if nil, or throw a LuaError if any other type.
|
/** Return argument i as a boolean value, {@code defval} if nil, or throw a LuaError if any other type.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
* @return true if argument i is boolean true, false if it is false, or defval if not supplied or nil
|
* @return true if argument i is boolean true, false if it is false, or defval if not supplied or nil
|
||||||
* @exception LuaError if the argument is not a lua boolean
|
* @exception LuaError if the argument is not a lua boolean
|
||||||
* */
|
* */
|
||||||
public boolean optboolean(int i, boolean defval) { return arg(i).optboolean(defval); }
|
public boolean optboolean(int i, boolean defval) { return arg(i).optboolean(defval); }
|
||||||
@@ -256,7 +256,7 @@ public abstract class Varargs {
|
|||||||
* */
|
* */
|
||||||
public Object optuserdata(int i, Object defval) { return arg(i).optuserdata(defval); }
|
public Object optuserdata(int i, Object defval) { return arg(i).optuserdata(defval); }
|
||||||
|
|
||||||
/** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,
|
/** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,
|
||||||
* {@code defval} if nil, or throw a LuaError if any other type.
|
* {@code defval} if nil, or throw a LuaError if any other type.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
* @param c the class to which the userdata instance must be assignable
|
* @param c the class to which the userdata instance must be assignable
|
||||||
@@ -291,7 +291,7 @@ public abstract class Varargs {
|
|||||||
* @return java double value if argument i is a number or string that converts to a number
|
* @return java double value if argument i is a number or string that converts to a number
|
||||||
* @exception LuaError if the argument is not a number
|
* @exception LuaError if the argument is not a number
|
||||||
* */
|
* */
|
||||||
public double checkdouble(int i) { return arg(i).checknumber().todouble(); }
|
public double checkdouble(int i) { return arg(i).checkdouble(); }
|
||||||
|
|
||||||
/** Return argument i as a function, or throw an error if an incompatible type.
|
/** Return argument i as a function, or throw an error if an incompatible type.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
@@ -300,12 +300,12 @@ public abstract class Varargs {
|
|||||||
* */
|
* */
|
||||||
public LuaFunction checkfunction(int i) { return arg(i).checkfunction(); }
|
public LuaFunction checkfunction(int i) { return arg(i).checkfunction(); }
|
||||||
|
|
||||||
/** Return argument i as a java int value, discarding any fractional part, or throw an error if not a number.
|
/** Return argument i as a java int value, or throw an error if it cannot be converted to one.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
* @return int value with fraction discarded and truncated if necessary if argument i is number
|
* @return int value if argument i is a number or string that converts to a number
|
||||||
* @exception LuaError if the argument is not a number
|
* @exception LuaError if the argument cannot be represented by a java int value
|
||||||
* */
|
* */
|
||||||
public int checkint(int i) { return arg(i).checknumber().toint(); }
|
public int checkint(int i) { return arg(i).checkint(); }
|
||||||
|
|
||||||
/** Return argument i as a java int value, or throw an error if not a number or is not representable by a java int.
|
/** Return argument i as a java int value, or throw an error if not a number or is not representable by a java int.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
@@ -314,12 +314,12 @@ public abstract class Varargs {
|
|||||||
* */
|
* */
|
||||||
public LuaInteger checkinteger(int i) { return arg(i).checkinteger(); }
|
public LuaInteger checkinteger(int i) { return arg(i).checkinteger(); }
|
||||||
|
|
||||||
/** Return argument i as a java long value, discarding any fractional part, or throw an error if not a number.
|
/** Return argument i as a java long value, or throw an error if it cannot be converted to one.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
* @return long value with fraction discarded and truncated if necessary if argument i is number
|
* @return long value if argument i is a number or string that converts to a number
|
||||||
* @exception LuaError if the argument is not a number
|
* @exception LuaError if the argument cannot be represented by a java long value
|
||||||
* */
|
* */
|
||||||
public long checklong(int i) { return arg(i).checknumber().tolong(); }
|
public long checklong(int i) { return arg(i).checklong(); }
|
||||||
|
|
||||||
/** Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number.
|
/** Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
@@ -363,7 +363,7 @@ public abstract class Varargs {
|
|||||||
* */
|
* */
|
||||||
public Object checkuserdata(int i) { return arg(i).checkuserdata(); }
|
public Object checkuserdata(int i) { return arg(i).checkuserdata(); }
|
||||||
|
|
||||||
/** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,
|
/** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,
|
||||||
* or throw an error if any other type.
|
* or throw an error if any other type.
|
||||||
* @param i the index of the argument to test, 1 is the first argument
|
* @param i the index of the argument to test, 1 is the first argument
|
||||||
* @param c the class to which the userdata instance must be assignable
|
* @param c the class to which the userdata instance must be assignable
|
||||||
@@ -387,7 +387,7 @@ public abstract class Varargs {
|
|||||||
public LuaValue checknotnil(int i) { return arg(i).checknotnil(); }
|
public LuaValue checknotnil(int i) { return arg(i).checknotnil(); }
|
||||||
|
|
||||||
/** Performs test on argument i as a LuaValue when a user-supplied assertion passes, or throw an error.
|
/** Performs test on argument i as a LuaValue when a user-supplied assertion passes, or throw an error.
|
||||||
* Returns normally if the value of {@code test} is {@code true}, otherwise throws and argument error with
|
* Returns normally if the value of {@code test} is {@code true}, otherwise throws and argument error with
|
||||||
* the supplied message, {@code msg}.
|
* the supplied message, {@code msg}.
|
||||||
* @param test user supplied assertion to test against
|
* @param test user supplied assertion to test against
|
||||||
* @param i the index to report in any error message
|
* @param i the index to report in any error message
|
||||||
@@ -404,20 +404,20 @@ public abstract class Varargs {
|
|||||||
return i>narg() || arg(i).isnil();
|
return i>narg() || arg(i).isnil();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert argument {@code i} to java boolean based on lua rules for boolean evaluation.
|
/** Convert argument {@code i} to java boolean based on lua rules for boolean evaluation.
|
||||||
* @param i the index of the argument to convert, 1 is the first argument
|
* @param i the index of the argument to convert, 1 is the first argument
|
||||||
* @return {@code false} if argument i is nil or false, otherwise {@code true}
|
* @return {@code false} if argument i is nil or false, otherwise {@code true}
|
||||||
* */
|
* */
|
||||||
public boolean toboolean(int i) { return arg(i).toboolean(); }
|
public boolean toboolean(int i) { return arg(i).toboolean(); }
|
||||||
|
|
||||||
/** Return argument i as a java byte value, discarding any fractional part and truncating,
|
/** Return argument i as a java byte value, discarding any fractional part and truncating,
|
||||||
* or 0 if not a number.
|
* or 0 if not a number.
|
||||||
* @param i the index of the argument to convert, 1 is the first argument
|
* @param i the index of the argument to convert, 1 is the first argument
|
||||||
* @return byte value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
* @return byte value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
||||||
* */
|
* */
|
||||||
public byte tobyte(int i) { return arg(i).tobyte(); }
|
public byte tobyte(int i) { return arg(i).tobyte(); }
|
||||||
|
|
||||||
/** Return argument i as a java char value, discarding any fractional part and truncating,
|
/** Return argument i as a java char value, discarding any fractional part and truncating,
|
||||||
* or 0 if not a number.
|
* or 0 if not a number.
|
||||||
* @param i the index of the argument to convert, 1 is the first argument
|
* @param i the index of the argument to convert, 1 is the first argument
|
||||||
* @return char value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
* @return char value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
||||||
@@ -430,21 +430,21 @@ public abstract class Varargs {
|
|||||||
* */
|
* */
|
||||||
public double todouble(int i) { return arg(i).todouble(); }
|
public double todouble(int i) { return arg(i).todouble(); }
|
||||||
|
|
||||||
/** Return argument i as a java float value, discarding excess fractional part and truncating,
|
/** Return argument i as a java float value, discarding excess fractional part and truncating,
|
||||||
* or 0 if not a number.
|
* or 0 if not a number.
|
||||||
* @param i the index of the argument to convert, 1 is the first argument
|
* @param i the index of the argument to convert, 1 is the first argument
|
||||||
* @return float value with excess fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
* @return float value with excess fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
||||||
* */
|
* */
|
||||||
public float tofloat(int i) { return arg(i).tofloat(); }
|
public float tofloat(int i) { return arg(i).tofloat(); }
|
||||||
|
|
||||||
/** Return argument i as a java int value, discarding any fractional part and truncating,
|
/** Return argument i as a java int value, discarding any fractional part and truncating,
|
||||||
* or 0 if not a number.
|
* or 0 if not a number.
|
||||||
* @param i the index of the argument to convert, 1 is the first argument
|
* @param i the index of the argument to convert, 1 is the first argument
|
||||||
* @return int value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
* @return int value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
||||||
* */
|
* */
|
||||||
public int toint(int i) { return arg(i).toint(); }
|
public int toint(int i) { return arg(i).toint(); }
|
||||||
|
|
||||||
/** Return argument i as a java long value, discarding any fractional part and truncating,
|
/** Return argument i as a java long value, discarding any fractional part and truncating,
|
||||||
* or 0 if not a number.
|
* or 0 if not a number.
|
||||||
* @param i the index of the argument to convert, 1 is the first argument
|
* @param i the index of the argument to convert, 1 is the first argument
|
||||||
* @return long value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
* @return long value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
||||||
@@ -457,7 +457,7 @@ public abstract class Varargs {
|
|||||||
* */
|
* */
|
||||||
public String tojstring(int i) { return arg(i).tojstring(); }
|
public String tojstring(int i) { return arg(i).tojstring(); }
|
||||||
|
|
||||||
/** Return argument i as a java short value, discarding any fractional part and truncating,
|
/** Return argument i as a java short value, discarding any fractional part and truncating,
|
||||||
* or 0 if not a number.
|
* or 0 if not a number.
|
||||||
* @param i the index of the argument to convert, 1 is the first argument
|
* @param i the index of the argument to convert, 1 is the first argument
|
||||||
* @return short value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
* @return short value with fraction discarded and truncated if necessary if argument i is number, otherwise 0
|
||||||
@@ -477,8 +477,8 @@ public abstract class Varargs {
|
|||||||
* */
|
* */
|
||||||
public Object touserdata(int i,Class c) { return arg(i).touserdata(c); }
|
public Object touserdata(int i,Class c) { return arg(i).touserdata(c); }
|
||||||
|
|
||||||
/** Convert the list of varargs values to a human readable java String.
|
/** Convert the list of varargs values to a human readable java String.
|
||||||
* @return String value in human readable form such as {1,2}.
|
* @return String value in human readable form such as {1,2}.
|
||||||
*/
|
*/
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
Buffer sb = new Buffer();
|
Buffer sb = new Buffer();
|
||||||
@@ -491,8 +491,8 @@ public abstract class Varargs {
|
|||||||
return sb.tojstring();
|
return sb.tojstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert the value or values to a java String using Varargs.tojstring()
|
/** Convert the value or values to a java String using Varargs.tojstring()
|
||||||
* @return String value in human readable form.
|
* @return String value in human readable form.
|
||||||
* @see Varargs#tojstring()
|
* @see Varargs#tojstring()
|
||||||
*/
|
*/
|
||||||
public String toString() { return tojstring(); }
|
public String toString() { return tojstring(); }
|
||||||
@@ -544,21 +544,21 @@ public abstract class Varargs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Varargs implemenation backed by two values.
|
/** Varargs implemenation backed by two values.
|
||||||
* <p>
|
* <p>
|
||||||
* This is an internal class not intended to be used directly.
|
* This is an internal class not intended to be used directly.
|
||||||
* Instead use the corresponding static method on LuaValue.
|
* Instead use the corresponding static method on LuaValue.
|
||||||
*
|
*
|
||||||
* @see LuaValue#varargsOf(LuaValue, Varargs)
|
* @see LuaValue#varargsOf(LuaValue, Varargs)
|
||||||
*/
|
*/
|
||||||
static final class PairVarargs extends Varargs {
|
static final class PairVarargs extends Varargs {
|
||||||
private final LuaValue v1;
|
private final LuaValue v1;
|
||||||
private final Varargs v2;
|
private final Varargs v2;
|
||||||
/** Construct a Varargs from an two LuaValue.
|
/** Construct a Varargs from an two LuaValue.
|
||||||
* <p>
|
* <p>
|
||||||
* This is an internal class not intended to be used directly.
|
* This is an internal class not intended to be used directly.
|
||||||
* Instead use the corresponding static method on LuaValue.
|
* Instead use the corresponding static method on LuaValue.
|
||||||
*
|
*
|
||||||
* @see LuaValue#varargsOf(LuaValue, Varargs)
|
* @see LuaValue#varargsOf(LuaValue, Varargs)
|
||||||
*/
|
*/
|
||||||
PairVarargs(LuaValue v1, Varargs v2) {
|
PairVarargs(LuaValue v1, Varargs v2) {
|
||||||
@@ -571,8 +571,8 @@ public abstract class Varargs {
|
|||||||
public int narg() {
|
public int narg() {
|
||||||
return 1+v2.narg();
|
return 1+v2.narg();
|
||||||
}
|
}
|
||||||
public LuaValue arg1() {
|
public LuaValue arg1() {
|
||||||
return v1;
|
return v1;
|
||||||
}
|
}
|
||||||
public Varargs subargs(final int start) {
|
public Varargs subargs(final int start) {
|
||||||
if (start == 1)
|
if (start == 1)
|
||||||
@@ -585,22 +585,22 @@ public abstract class Varargs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Varargs implemenation backed by an array of LuaValues
|
/** Varargs implemenation backed by an array of LuaValues
|
||||||
* <p>
|
* <p>
|
||||||
* This is an internal class not intended to be used directly.
|
* This is an internal class not intended to be used directly.
|
||||||
* Instead use the corresponding static methods on LuaValue.
|
* Instead use the corresponding static methods on LuaValue.
|
||||||
*
|
*
|
||||||
* @see LuaValue#varargsOf(LuaValue[])
|
* @see LuaValue#varargsOf(LuaValue[])
|
||||||
* @see LuaValue#varargsOf(LuaValue[], Varargs)
|
* @see LuaValue#varargsOf(LuaValue[], Varargs)
|
||||||
*/
|
*/
|
||||||
static final class ArrayVarargs extends Varargs {
|
static final class ArrayVarargs extends Varargs {
|
||||||
private final LuaValue[] v;
|
private final LuaValue[] v;
|
||||||
private final Varargs r;
|
private final Varargs r;
|
||||||
/** Construct a Varargs from an array of LuaValue.
|
/** Construct a Varargs from an array of LuaValue.
|
||||||
* <p>
|
* <p>
|
||||||
* This is an internal class not intended to be used directly.
|
* This is an internal class not intended to be used directly.
|
||||||
* Instead use the corresponding static methods on LuaValue.
|
* Instead use the corresponding static methods on LuaValue.
|
||||||
*
|
*
|
||||||
* @see LuaValue#varargsOf(LuaValue[])
|
* @see LuaValue#varargsOf(LuaValue[])
|
||||||
* @see LuaValue#varargsOf(LuaValue[], Varargs)
|
* @see LuaValue#varargsOf(LuaValue[], Varargs)
|
||||||
*/
|
*/
|
||||||
@@ -631,11 +631,11 @@ public abstract class Varargs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Varargs implemenation backed by an array of LuaValues
|
/** Varargs implemenation backed by an array of LuaValues
|
||||||
* <p>
|
* <p>
|
||||||
* This is an internal class not intended to be used directly.
|
* This is an internal class not intended to be used directly.
|
||||||
* Instead use the corresponding static methods on LuaValue.
|
* Instead use the corresponding static methods on LuaValue.
|
||||||
*
|
*
|
||||||
* @see LuaValue#varargsOf(LuaValue[], int, int)
|
* @see LuaValue#varargsOf(LuaValue[], int, int)
|
||||||
* @see LuaValue#varargsOf(LuaValue[], int, int, Varargs)
|
* @see LuaValue#varargsOf(LuaValue[], int, int, Varargs)
|
||||||
*/
|
*/
|
||||||
@@ -644,11 +644,11 @@ public abstract class Varargs {
|
|||||||
private final LuaValue[] v;
|
private final LuaValue[] v;
|
||||||
private final int length;
|
private final int length;
|
||||||
private final Varargs more;
|
private final Varargs more;
|
||||||
/** Construct a Varargs from an array of LuaValue.
|
/** Construct a Varargs from an array of LuaValue.
|
||||||
* <p>
|
* <p>
|
||||||
* This is an internal class not intended to be used directly.
|
* This is an internal class not intended to be used directly.
|
||||||
* Instead use the corresponding static methods on LuaValue.
|
* Instead use the corresponding static methods on LuaValue.
|
||||||
*
|
*
|
||||||
* @see LuaValue#varargsOf(LuaValue[], int, int)
|
* @see LuaValue#varargsOf(LuaValue[], int, int)
|
||||||
*/
|
*/
|
||||||
ArrayPartVarargs(LuaValue[] v, int offset, int length) {
|
ArrayPartVarargs(LuaValue[] v, int offset, int length) {
|
||||||
@@ -657,11 +657,11 @@ public abstract class Varargs {
|
|||||||
this.length = length;
|
this.length = length;
|
||||||
this.more = LuaValue.NONE;
|
this.more = LuaValue.NONE;
|
||||||
}
|
}
|
||||||
/** Construct a Varargs from an array of LuaValue and additional arguments.
|
/** Construct a Varargs from an array of LuaValue and additional arguments.
|
||||||
* <p>
|
* <p>
|
||||||
* This is an internal class not intended to be used directly.
|
* This is an internal class not intended to be used directly.
|
||||||
* Instead use the corresponding static method on LuaValue.
|
* Instead use the corresponding static method on LuaValue.
|
||||||
*
|
*
|
||||||
* @see LuaValue#varargsOf(LuaValue[], int, int, Varargs)
|
* @see LuaValue#varargsOf(LuaValue[], int, int, Varargs)
|
||||||
*/
|
*/
|
||||||
public ArrayPartVarargs(LuaValue[] v, int offset, int length, Varargs more) {
|
public ArrayPartVarargs(LuaValue[] v, int offset, int length, Varargs more) {
|
||||||
@@ -676,8 +676,8 @@ public abstract class Varargs {
|
|||||||
public int narg() {
|
public int narg() {
|
||||||
return length + more.narg();
|
return length + more.narg();
|
||||||
}
|
}
|
||||||
public LuaValue arg1() {
|
public LuaValue arg1() {
|
||||||
return length>0? v[offset]: more.arg1();
|
return length>0? v[offset]: more.arg1();
|
||||||
}
|
}
|
||||||
public Varargs subargs(int start) {
|
public Varargs subargs(int start) {
|
||||||
if (start <= 0)
|
if (start <= 0)
|
||||||
@@ -707,8 +707,10 @@ public abstract class Varargs {
|
|||||||
/** Return Varargs that cannot be using a shared array for the storage, and is flattened.
|
/** Return Varargs that cannot be using a shared array for the storage, and is flattened.
|
||||||
* Internal utility method not intended to be called directly from user code.
|
* Internal utility method not intended to be called directly from user code.
|
||||||
* @return Varargs containing same values, but flattened and with a new array if needed.
|
* @return Varargs containing same values, but flattened and with a new array if needed.
|
||||||
|
* @exclude
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
Varargs dealias() {
|
public Varargs dealias() {
|
||||||
int n = narg();
|
int n = narg();
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 0: return LuaValue.NONE;
|
case 0: return LuaValue.NONE;
|
||||||
|
|||||||
@@ -28,14 +28,14 @@ import java.io.OutputStream;
|
|||||||
import org.luaj.vm2.Globals;
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.LoadState;
|
import org.luaj.vm2.LoadState;
|
||||||
import org.luaj.vm2.LocVars;
|
import org.luaj.vm2.LocVars;
|
||||||
import org.luaj.vm2.Prototype;
|
|
||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
|
import org.luaj.vm2.Prototype;
|
||||||
|
|
||||||
|
|
||||||
/** Class to dump a {@link Prototype} into an output stream, as part of compiling.
|
/** Class to dump a {@link Prototype} into an output stream, as part of compiling.
|
||||||
* <p>
|
* <p>
|
||||||
* Generally, this class is not used directly, but rather indirectly via a command
|
* Generally, this class is not used directly, but rather indirectly via a command
|
||||||
* line interface tool such as {@link luac}.
|
* line interface tool such as {@link luac}.
|
||||||
* <p>
|
* <p>
|
||||||
* A lua binary file is created via {@link DumpState#dump}:
|
* A lua binary file is created via {@link DumpState#dump}:
|
||||||
@@ -85,7 +85,7 @@ public class DumpState {
|
|||||||
public static final int NUMBER_FORMAT_DEFAULT = NUMBER_FORMAT_FLOATS_OR_DOUBLES;
|
public static final int NUMBER_FORMAT_DEFAULT = NUMBER_FORMAT_FLOATS_OR_DOUBLES;
|
||||||
|
|
||||||
// header fields
|
// header fields
|
||||||
private boolean IS_LITTLE_ENDIAN = false;
|
private boolean IS_LITTLE_ENDIAN = true;
|
||||||
private int NUMBER_FORMAT = NUMBER_FORMAT_DEFAULT;
|
private int NUMBER_FORMAT = NUMBER_FORMAT_DEFAULT;
|
||||||
private int SIZEOF_LUA_NUMBER = 8;
|
private int SIZEOF_LUA_NUMBER = 8;
|
||||||
private static final int SIZEOF_INT = 4;
|
private static final int SIZEOF_INT = 4;
|
||||||
@@ -190,7 +190,7 @@ public class DumpState {
|
|||||||
dumpString((LuaString)o);
|
dumpString((LuaString)o);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("bad type for " + o);
|
throw new IllegalArgumentException("bad type for " + o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
n = f.p.length;
|
n = f.p.length;
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isspace(int c) {
|
private boolean isspace(int c) {
|
||||||
return (c <= ' ');
|
return (c >= 0 && c <= ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -388,8 +388,13 @@ public class LexState extends Constants {
|
|||||||
seminfo.r = LuaValue.ZERO;
|
seminfo.r = LuaValue.ZERO;
|
||||||
else if (str.indexOf('x')>=0 || str.indexOf('X')>=0)
|
else if (str.indexOf('x')>=0 || str.indexOf('X')>=0)
|
||||||
seminfo.r = strx2number(str, seminfo);
|
seminfo.r = strx2number(str, seminfo);
|
||||||
else
|
else {
|
||||||
seminfo.r = LuaValue.valueOf(Double.parseDouble(str.trim()));
|
try {
|
||||||
|
seminfo.r = LuaValue.valueOf(Double.parseDouble(str.trim()));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
lexerror("malformed number (" + e.getMessage() + ")", TK_NUMBER);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,7 +413,6 @@ public class LexState extends Constants {
|
|||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
save('\0');
|
|
||||||
String str = new String(buff, 0, nbuff);
|
String str = new String(buff, 0, nbuff);
|
||||||
str2d(str, seminfo);
|
str2d(str, seminfo);
|
||||||
}
|
}
|
||||||
@@ -585,6 +589,13 @@ public class LexState extends Constants {
|
|||||||
inclinenumber();
|
inclinenumber();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
case ' ':
|
||||||
|
case '\f':
|
||||||
|
case '\t':
|
||||||
|
case 0x0B: /* \v */ {
|
||||||
|
nextChar();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
case '-': {
|
case '-': {
|
||||||
nextChar();
|
nextChar();
|
||||||
if (current != '-')
|
if (current != '-')
|
||||||
@@ -688,19 +699,12 @@ public class LexState extends Constants {
|
|||||||
return TK_EOF;
|
return TK_EOF;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
if (isspace(current)) {
|
if (isalpha(current) || current == '_') {
|
||||||
_assert (!currIsNewline());
|
|
||||||
nextChar();
|
|
||||||
continue;
|
|
||||||
} else if (isdigit(current)) {
|
|
||||||
read_numeral(seminfo);
|
|
||||||
return TK_NUMBER;
|
|
||||||
} else if (isalpha(current) || current == '_') {
|
|
||||||
/* identifier or reserved word */
|
/* identifier or reserved word */
|
||||||
LuaString ts;
|
LuaString ts;
|
||||||
do {
|
do {
|
||||||
save_and_next();
|
save_and_next();
|
||||||
} while (isalnum(current) || current == '_');
|
} while (isalnum(current));
|
||||||
ts = newstring(buff, 0, nbuff);
|
ts = newstring(buff, 0, nbuff);
|
||||||
if ( RESERVED.containsKey(ts) )
|
if ( RESERVED.containsKey(ts) )
|
||||||
return ((Integer)RESERVED.get(ts)).intValue();
|
return ((Integer)RESERVED.get(ts)).intValue();
|
||||||
@@ -1744,7 +1748,7 @@ public class LexState extends Constants {
|
|||||||
fs.checkrepeated(dyd.label, dyd.n_label, label); /* check for repeated labels */
|
fs.checkrepeated(dyd.label, dyd.n_label, label); /* check for repeated labels */
|
||||||
checknext(TK_DBCOLON); /* skip double colon */
|
checknext(TK_DBCOLON); /* skip double colon */
|
||||||
/* create new entry for this label */
|
/* create new entry for this label */
|
||||||
l = newlabelentry(dyd.label=grow(dyd.label, dyd.n_label+1), dyd.n_label++, label, line, fs.pc);
|
l = newlabelentry(dyd.label=grow(dyd.label, dyd.n_label+1), dyd.n_label++, label, line, fs.getlabel());
|
||||||
skipnoopstat(); /* skip other no-op statements */
|
skipnoopstat(); /* skip other no-op statements */
|
||||||
if (block_follow(false)) { /* label is last no-op statement in the block? */
|
if (block_follow(false)) { /* label is last no-op statement in the block? */
|
||||||
/* assume that locals are already out of scope */
|
/* assume that locals are already out of scope */
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
System.gc();
|
System.gc();
|
||||||
return LuaValue.TRUE;
|
return LuaValue.TRUE;
|
||||||
} else {
|
} else {
|
||||||
this.argerror("gc op");
|
argerror(1, "invalid option '" + s + "'");
|
||||||
}
|
}
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
@@ -172,16 +172,16 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
// "error", // ( message [,level] ) -> ERR
|
// "error", // ( message [,level] ) -> ERR
|
||||||
static final class error extends TwoArgFunction {
|
static final class error extends TwoArgFunction {
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
throw arg1.isnil()? new LuaError(null, arg2.optint(1)):
|
if (arg1.isnil()) throw new LuaError(NIL);
|
||||||
arg1.isstring()? new LuaError(arg1.tojstring(), arg2.optint(1)):
|
if (!arg1.isstring() || arg2.optint(1) == 0) throw new LuaError(arg1);
|
||||||
new LuaError(arg1);
|
throw new LuaError(arg1.tojstring(), arg2.optint(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "getmetatable", // ( object ) -> table
|
// "getmetatable", // ( object ) -> table
|
||||||
static final class getmetatable extends LibFunction {
|
static final class getmetatable extends LibFunction {
|
||||||
public LuaValue call() {
|
public LuaValue call() {
|
||||||
return argerror(1, "value");
|
return argerror(1, "value expected");
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
LuaValue mt = arg.getmetatable();
|
LuaValue mt = arg.getmetatable();
|
||||||
@@ -192,7 +192,9 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
final class load extends VarArgFunction {
|
final class load extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaValue ld = args.arg1();
|
LuaValue ld = args.arg1();
|
||||||
args.argcheck(ld.isstring() || ld.isfunction(), 1, "ld must be string or function");
|
if (!ld.isstring() && !ld.isfunction()) {
|
||||||
|
throw new LuaError("bad argument #1 to 'load' (string or function expected, got " + ld.typename() + ")");
|
||||||
|
}
|
||||||
String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
|
String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
|
||||||
String mode = args.optjstring(3, "bt");
|
String mode = args.optjstring(3, "bt");
|
||||||
LuaValue env = args.optvalue(4, globals);
|
LuaValue env = args.optvalue(4, globals);
|
||||||
@@ -257,10 +259,10 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
// "rawequal", // (v1, v2) -> boolean
|
// "rawequal", // (v1, v2) -> boolean
|
||||||
static final class rawequal extends LibFunction {
|
static final class rawequal extends LibFunction {
|
||||||
public LuaValue call() {
|
public LuaValue call() {
|
||||||
return argerror(1, "value");
|
return argerror(1, "value expected");
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
return argerror(2, "value");
|
return argerror(2, "value expected");
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
return valueOf(arg1.raweq(arg2));
|
return valueOf(arg1.raweq(arg2));
|
||||||
@@ -268,12 +270,12 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "rawget", // (table, index) -> value
|
// "rawget", // (table, index) -> value
|
||||||
static final class rawget extends LibFunction {
|
static final class rawget extends TableLibFunction {
|
||||||
public LuaValue call() {
|
public LuaValue call() {
|
||||||
return argerror(1, "value");
|
return argerror(1, "value expected");
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
return argerror(2, "value");
|
return argerror(2, "value expected");
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
return arg1.checktable().rawget(arg2);
|
return arg1.checktable().rawget(arg2);
|
||||||
@@ -289,16 +291,16 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "rawset", // (table, index, value) -> table
|
// "rawset", // (table, index, value) -> table
|
||||||
static final class rawset extends LibFunction {
|
static final class rawset extends TableLibFunction {
|
||||||
public LuaValue call(LuaValue table) {
|
public LuaValue call(LuaValue table) {
|
||||||
return argerror(2,"value");
|
return argerror(2,"value expected");
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue table, LuaValue index) {
|
public LuaValue call(LuaValue table, LuaValue index) {
|
||||||
return argerror(3,"value");
|
return argerror(3,"value expected");
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue table, LuaValue index, LuaValue value) {
|
public LuaValue call(LuaValue table, LuaValue index, LuaValue value) {
|
||||||
LuaTable t = table.checktable();
|
LuaTable t = table.checktable();
|
||||||
if (!index.isvalidkey()) argerror(2, "value");
|
if (!index.isvalidkey()) argerror(2, "table index is nil");
|
||||||
t.rawset(index, value);
|
t.rawset(index, value);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@@ -318,9 +320,9 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "setmetatable", // (table, metatable) -> table
|
// "setmetatable", // (table, metatable) -> table
|
||||||
static final class setmetatable extends LibFunction {
|
static final class setmetatable extends TableLibFunction {
|
||||||
public LuaValue call(LuaValue table) {
|
public LuaValue call(LuaValue table) {
|
||||||
return argerror(2,"value");
|
return argerror(2,"nil or table expected");
|
||||||
}
|
}
|
||||||
public LuaValue call(LuaValue table, LuaValue metatable) {
|
public LuaValue call(LuaValue table, LuaValue metatable) {
|
||||||
final LuaValue mt0 = table.checktable().getmetatable();
|
final LuaValue mt0 = table.checktable().getmetatable();
|
||||||
@@ -471,10 +473,12 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
this.func = func;
|
this.func = func;
|
||||||
}
|
}
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
if ( remaining <= 0 ) {
|
if ( remaining < 0 )
|
||||||
|
return -1;
|
||||||
|
if ( remaining == 0 ) {
|
||||||
LuaValue s = func.call();
|
LuaValue s = func.call();
|
||||||
if ( s.isnil() )
|
if ( s.isnil() )
|
||||||
return -1;
|
return remaining = -1;
|
||||||
LuaString ls = s.strvalue();
|
LuaString ls = s.strvalue();
|
||||||
bytes = ls.m_bytes;
|
bytes = ls.m_bytes;
|
||||||
offset = ls.m_offset;
|
offset = ls.m_offset;
|
||||||
|
|||||||
@@ -442,6 +442,10 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
return callstack().traceback(level);
|
return callstack().traceback(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CallFrame getCallFrame(int level) {
|
||||||
|
return callstack().getCallFrame(level);
|
||||||
|
}
|
||||||
|
|
||||||
void callHook(LuaThread.State s, LuaValue type, LuaValue arg) {
|
void callHook(LuaThread.State s, LuaValue type, LuaValue arg) {
|
||||||
if (s.inhook || s.hookfunc == null) return;
|
if (s.inhook || s.hookfunc == null) return;
|
||||||
s.inhook = true;
|
s.inhook = true;
|
||||||
@@ -645,7 +649,7 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class CallFrame {
|
public static class CallFrame {
|
||||||
LuaFunction f;
|
LuaFunction f;
|
||||||
int pc;
|
int pc;
|
||||||
int top;
|
int top;
|
||||||
@@ -691,7 +695,7 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int currentline() {
|
public int currentline() {
|
||||||
if ( !f.isclosure() ) return -1;
|
if ( !f.isclosure() ) return -1;
|
||||||
int[] li = f.checkclosure().p.lineinfo;
|
int[] li = f.checkclosure().p.lineinfo;
|
||||||
return li==null || pc<0 || pc>=li.length? -1: li[pc];
|
return li==null || pc<0 || pc>=li.length? -1: li[pc];
|
||||||
@@ -796,13 +800,13 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
LuaString vn = (Lua.GET_OPCODE(i) == Lua.OP_GETTABLE) /* name of indexed variable */
|
LuaString vn = (Lua.GET_OPCODE(i) == Lua.OP_GETTABLE) /* name of indexed variable */
|
||||||
? p.getlocalname(t + 1, pc)
|
? p.getlocalname(t + 1, pc)
|
||||||
: (t < p.upvalues.length ? p.upvalues[t].name : QMARK);
|
: (t < p.upvalues.length ? p.upvalues[t].name : QMARK);
|
||||||
name = kname(p, k);
|
String jname = kname(p, pc, k);
|
||||||
return new NameWhat( name.tojstring(), vn != null && vn.eq_b(ENV)? "global": "field" );
|
return new NameWhat( jname, vn != null && vn.eq_b(ENV)? "global": "field" );
|
||||||
}
|
}
|
||||||
case Lua.OP_GETUPVAL: {
|
case Lua.OP_GETUPVAL: {
|
||||||
int u = Lua.GETARG_B(i); /* upvalue index */
|
int u = Lua.GETARG_B(i); /* upvalue index */
|
||||||
name = u < p.upvalues.length ? p.upvalues[u].name : QMARK;
|
name = u < p.upvalues.length ? p.upvalues[u].name : QMARK;
|
||||||
return new NameWhat( name.tojstring(), "upvalue" );
|
return name == null ? null : new NameWhat( name.tojstring(), "upvalue" );
|
||||||
}
|
}
|
||||||
case Lua.OP_LOADK:
|
case Lua.OP_LOADK:
|
||||||
case Lua.OP_LOADKX: {
|
case Lua.OP_LOADKX: {
|
||||||
@@ -816,8 +820,8 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
case Lua.OP_SELF: {
|
case Lua.OP_SELF: {
|
||||||
int k = Lua.GETARG_C(i); /* key index */
|
int k = Lua.GETARG_C(i); /* key index */
|
||||||
name = kname(p, k);
|
String jname = kname(p, pc, k);
|
||||||
return new NameWhat( name.tojstring(), "method" );
|
return new NameWhat( jname, "method" );
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -826,11 +830,20 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
return null; /* no useful name found */
|
return null; /* no useful name found */
|
||||||
}
|
}
|
||||||
|
|
||||||
static LuaString kname(Prototype p, int c) {
|
static String kname(Prototype p, int pc, int c) {
|
||||||
if (Lua.ISK(c) && p.k[Lua.INDEXK(c)].isstring())
|
if (Lua.ISK(c)) { /* is 'c' a constant? */
|
||||||
return p.k[Lua.INDEXK(c)].strvalue();
|
LuaValue k = p.k[Lua.INDEXK(c)];
|
||||||
else
|
if (k.isstring()) { /* literal constant? */
|
||||||
return QMARK;
|
return k.tojstring(); /* it is its own name */
|
||||||
|
} /* else no reasonable name found */
|
||||||
|
} else { /* 'c' is a register */
|
||||||
|
NameWhat what = getobjname(p, pc, c); /* search for 'c' */
|
||||||
|
if (what != null && "constant".equals(what.namewhat)) { /* found a constant name? */
|
||||||
|
return what.name; /* 'name' already filled */
|
||||||
|
}
|
||||||
|
/* else no reasonable name found */
|
||||||
|
}
|
||||||
|
return "?"; /* no reasonable name found */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -95,6 +95,12 @@ public class IoLib extends TwoArgFunction {
|
|||||||
// return number of bytes read if positive, false if eof, throw IOException on other exception
|
// return number of bytes read if positive, false if eof, throw IOException on other exception
|
||||||
abstract public int read(byte[] bytes, int offset, int length) throws IOException;
|
abstract public int read(byte[] bytes, int offset, int length) throws IOException;
|
||||||
|
|
||||||
|
public boolean eof() throws IOException {
|
||||||
|
try {
|
||||||
|
return peek() < 0;
|
||||||
|
} catch (EOFException e) { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
// delegate method access to file methods table
|
// delegate method access to file methods table
|
||||||
public LuaValue get( LuaValue key ) {
|
public LuaValue get( LuaValue key ) {
|
||||||
return filemethods.get(key);
|
return filemethods.get(key);
|
||||||
@@ -112,6 +118,14 @@ public class IoLib extends TwoArgFunction {
|
|||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
return "file: " + Integer.toHexString(hashCode());
|
return "file: " + Integer.toHexString(hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void finalize() {
|
||||||
|
if (!isclosed()) {
|
||||||
|
try {
|
||||||
|
close();
|
||||||
|
} catch (IOException ignore) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Enumerated value representing stdin */
|
/** Enumerated value representing stdin */
|
||||||
@@ -269,8 +283,15 @@ public class IoLib extends TwoArgFunction {
|
|||||||
static final class IoLibV extends VarArgFunction {
|
static final class IoLibV extends VarArgFunction {
|
||||||
private File f;
|
private File f;
|
||||||
public IoLib iolib;
|
public IoLib iolib;
|
||||||
|
private boolean toclose;
|
||||||
|
private Varargs args;
|
||||||
public IoLibV() {
|
public IoLibV() {
|
||||||
}
|
}
|
||||||
|
public IoLibV(File f, String name, int opcode, IoLib iolib, boolean toclose, Varargs args) {
|
||||||
|
this(f, name, opcode, iolib);
|
||||||
|
this.toclose = toclose;
|
||||||
|
this.args = args.dealias();
|
||||||
|
}
|
||||||
public IoLibV(File f, String name, int opcode, IoLib iolib) {
|
public IoLibV(File f, String name, int opcode, IoLib iolib) {
|
||||||
super();
|
super();
|
||||||
this.f = f;
|
this.f = f;
|
||||||
@@ -290,22 +311,26 @@ public class IoLib extends TwoArgFunction {
|
|||||||
case IO_TYPE: return iolib._io_type(args.arg1());
|
case IO_TYPE: return iolib._io_type(args.arg1());
|
||||||
case IO_POPEN: return iolib._io_popen(args.checkjstring(1),args.optjstring(2,"r"));
|
case IO_POPEN: return iolib._io_popen(args.checkjstring(1),args.optjstring(2,"r"));
|
||||||
case IO_OPEN: return iolib._io_open(args.checkjstring(1), args.optjstring(2,"r"));
|
case IO_OPEN: return iolib._io_open(args.checkjstring(1), args.optjstring(2,"r"));
|
||||||
case IO_LINES: return iolib._io_lines(args.isvalue(1)? args.checkjstring(1): null);
|
case IO_LINES: return iolib._io_lines(args);
|
||||||
case IO_READ: return iolib._io_read(args);
|
case IO_READ: return iolib._io_read(args);
|
||||||
case IO_WRITE: return iolib._io_write(args);
|
case IO_WRITE: return iolib._io_write(args);
|
||||||
|
|
||||||
case FILE_CLOSE: return iolib._file_close(args.arg1());
|
case FILE_CLOSE: return iolib._file_close(args.arg1());
|
||||||
case FILE_FLUSH: return iolib._file_flush(args.arg1());
|
case FILE_FLUSH: return iolib._file_flush(args.arg1());
|
||||||
case FILE_SETVBUF: return iolib._file_setvbuf(args.arg1(),args.checkjstring(2),args.optint(3,1024));
|
case FILE_SETVBUF: return iolib._file_setvbuf(args.arg1(),args.checkjstring(2),args.optint(3,8192));
|
||||||
case FILE_LINES: return iolib._file_lines(args.arg1());
|
case FILE_LINES: return iolib._file_lines(args);
|
||||||
case FILE_READ: return iolib._file_read(args.arg1(),args.subargs(2));
|
case FILE_READ: return iolib._file_read(args.arg1(),args.subargs(2));
|
||||||
case FILE_SEEK: return iolib._file_seek(args.arg1(),args.optjstring(2,"cur"),args.optint(3,0));
|
case FILE_SEEK: return iolib._file_seek(args.arg1(),args.optjstring(2,"cur"),args.optint(3,0));
|
||||||
case FILE_WRITE: return iolib._file_write(args.arg1(),args.subargs(2));
|
case FILE_WRITE: return iolib._file_write(args.arg1(),args.subargs(2));
|
||||||
|
|
||||||
case IO_INDEX: return iolib._io_index(args.arg(2));
|
case IO_INDEX: return iolib._io_index(args.arg(2));
|
||||||
case LINES_ITER: return iolib._lines_iter(f);
|
case LINES_ITER: return iolib._lines_iter(f, toclose, this.args);
|
||||||
}
|
}
|
||||||
} catch ( IOException ioe ) {
|
} catch ( IOException ioe ) {
|
||||||
|
if (opcode == LINES_ITER) {
|
||||||
|
String s = ioe.getMessage();
|
||||||
|
error(s != null ? s : ioe.toString());
|
||||||
|
}
|
||||||
return errorresult(ioe);
|
return errorresult(ioe);
|
||||||
}
|
}
|
||||||
return NONE;
|
return NONE;
|
||||||
@@ -361,6 +386,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
// io.popen(prog, [mode]) -> file
|
// io.popen(prog, [mode]) -> file
|
||||||
public Varargs _io_popen(String prog, String mode) throws IOException {
|
public Varargs _io_popen(String prog, String mode) throws IOException {
|
||||||
|
if (!"r".equals(mode) && !"w".equals(mode)) argerror(2, "invalid value: '" + mode + "'; must be one of 'r' or 'w'");
|
||||||
return openProgram(prog, mode);
|
return openProgram(prog, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,11 +395,12 @@ public class IoLib extends TwoArgFunction {
|
|||||||
return rawopenfile(FTYPE_NAMED, filename, mode);
|
return rawopenfile(FTYPE_NAMED, filename, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// io.lines(filename) -> iterator
|
// io.lines(filename, ...) -> iterator
|
||||||
public Varargs _io_lines(String filename) {
|
public Varargs _io_lines(Varargs args) {
|
||||||
infile = filename==null? input(): ioopenfile(FTYPE_NAMED, filename,"r");
|
String filename = args.optjstring(1, null);
|
||||||
|
File infile = filename==null? input(): ioopenfile(FTYPE_NAMED, filename,"r");
|
||||||
checkopen(infile);
|
checkopen(infile);
|
||||||
return lines(infile);
|
return lines(infile, filename != null, args.subargs(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// io.read(...) -> (...)
|
// io.read(...) -> (...)
|
||||||
@@ -401,13 +428,19 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
// file:setvbuf(mode,[size]) -> void
|
// file:setvbuf(mode,[size]) -> void
|
||||||
public Varargs _file_setvbuf(LuaValue file, String mode, int size) {
|
public Varargs _file_setvbuf(LuaValue file, String mode, int size) {
|
||||||
|
if ("no".equals(mode)) {
|
||||||
|
} else if ("full".equals(mode)) {
|
||||||
|
} else if ("line".equals(mode)) {
|
||||||
|
} else {
|
||||||
|
argerror(1, "invalid value: '" + mode + "'; must be one of 'no', 'full' or 'line'");
|
||||||
|
}
|
||||||
checkfile(file).setvbuf(mode,size);
|
checkfile(file).setvbuf(mode,size);
|
||||||
return LuaValue.TRUE;
|
return LuaValue.TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// file:lines() -> iterator
|
// file:lines(...) -> iterator
|
||||||
public Varargs _file_lines(LuaValue file) {
|
public Varargs _file_lines(Varargs args) {
|
||||||
return lines(checkfile(file));
|
return lines(checkfile(args.arg1()), false, args.subargs(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// file:read(...) -> (...)
|
// file:read(...) -> (...)
|
||||||
@@ -417,6 +450,12 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
// file:seek([whence][,offset]) -> pos | nil,error
|
// file:seek([whence][,offset]) -> pos | nil,error
|
||||||
public Varargs _file_seek(LuaValue file, String whence, int offset) throws IOException {
|
public Varargs _file_seek(LuaValue file, String whence, int offset) throws IOException {
|
||||||
|
if ("set".equals(whence)) {
|
||||||
|
} else if ("end".equals(whence)) {
|
||||||
|
} else if ("cur".equals(whence)) {
|
||||||
|
} else {
|
||||||
|
argerror(1, "invalid value: '" + whence + "'; must be one of 'set', 'cur' or 'end'");
|
||||||
|
}
|
||||||
return valueOf( checkfile(file).seek(whence,offset) );
|
return valueOf( checkfile(file).seek(whence,offset) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,8 +472,13 @@ public class IoLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lines iterator(s,var) -> var'
|
// lines iterator(s,var) -> var'
|
||||||
public Varargs _lines_iter(LuaValue file) throws IOException {
|
public Varargs _lines_iter(LuaValue file, boolean toclose, Varargs args) throws IOException {
|
||||||
return freadline(checkfile(file));
|
File f = optfile(file);
|
||||||
|
if ( f == null ) argerror(1, "not a file: " + file);
|
||||||
|
if ( f.isclosed() ) error("file is already closed");
|
||||||
|
Varargs ret = ioread(f, args);
|
||||||
|
if (toclose && ret.isnil(1) && f.eof()) f.close();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private File output() {
|
private File output() {
|
||||||
@@ -476,9 +520,9 @@ public class IoLib extends TwoArgFunction {
|
|||||||
return varargsOf(NIL, valueOf(errortext));
|
return varargsOf(NIL, valueOf(errortext));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Varargs lines(final File f) {
|
private Varargs lines(final File f, boolean toclose, Varargs args) {
|
||||||
try {
|
try {
|
||||||
return new IoLibV(f,"lnext",LINES_ITER,this);
|
return new IoLibV(f,"lnext",LINES_ITER,this,toclose,args);
|
||||||
} catch ( Exception e ) {
|
} catch ( Exception e ) {
|
||||||
return error("lines: "+e);
|
return error("lines: "+e);
|
||||||
}
|
}
|
||||||
@@ -492,6 +536,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
private Varargs ioread(File f, Varargs args) throws IOException {
|
private Varargs ioread(File f, Varargs args) throws IOException {
|
||||||
int i,n=args.narg();
|
int i,n=args.narg();
|
||||||
|
if (n == 0) return freadline(f,false);
|
||||||
LuaValue[] v = new LuaValue[n];
|
LuaValue[] v = new LuaValue[n];
|
||||||
LuaValue ai,vi;
|
LuaValue ai,vi;
|
||||||
LuaString fmt;
|
LuaString fmt;
|
||||||
@@ -502,10 +547,11 @@ public class IoLib extends TwoArgFunction {
|
|||||||
break item;
|
break item;
|
||||||
case LuaValue.TSTRING:
|
case LuaValue.TSTRING:
|
||||||
fmt = ai.checkstring();
|
fmt = ai.checkstring();
|
||||||
if ( fmt.m_length == 2 && fmt.m_bytes[fmt.m_offset] == '*' ) {
|
if ( fmt.m_length >= 2 && fmt.m_bytes[fmt.m_offset] == '*' ) {
|
||||||
switch ( fmt.m_bytes[fmt.m_offset+1] ) {
|
switch ( fmt.m_bytes[fmt.m_offset+1] ) {
|
||||||
case 'n': vi = freadnumber(f); break item;
|
case 'n': vi = freadnumber(f); break item;
|
||||||
case 'l': vi = freadline(f); break item;
|
case 'l': vi = freadline(f,false); break item;
|
||||||
|
case 'L': vi = freadline(f,true); break item;
|
||||||
case 'a': vi = freadall(f); break item;
|
case 'a': vi = freadall(f); break item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -537,6 +583,17 @@ public class IoLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private File rawopenfile(int filetype, String filename, String mode) throws IOException {
|
private File rawopenfile(int filetype, String filename, String mode) throws IOException {
|
||||||
|
int len = mode.length();
|
||||||
|
for (int i = 0; i < len; i++) { // [rwa][+]?b*
|
||||||
|
char ch = mode.charAt(i);
|
||||||
|
if (i == 0 && "rwa".indexOf(ch) >= 0) continue;
|
||||||
|
if (i == 1 && ch == '+') continue;
|
||||||
|
if (i >= 1 && ch == 'b') continue;
|
||||||
|
len = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (len <= 0) argerror(2, "invalid mode: '" + mode + "'");
|
||||||
|
|
||||||
switch (filetype) {
|
switch (filetype) {
|
||||||
case FTYPE_STDIN: return wrapStdin();
|
case FTYPE_STDIN: return wrapStdin();
|
||||||
case FTYPE_STDOUT: return wrapStdout();
|
case FTYPE_STDOUT: return wrapStdout();
|
||||||
@@ -553,26 +610,27 @@ public class IoLib extends TwoArgFunction {
|
|||||||
// ------------- file reading utilitied ------------------
|
// ------------- file reading utilitied ------------------
|
||||||
|
|
||||||
public static LuaValue freadbytes(File f, int count) throws IOException {
|
public static LuaValue freadbytes(File f, int count) throws IOException {
|
||||||
|
if (count == 0) return f.eof() ? NIL : EMPTYSTRING;
|
||||||
byte[] b = new byte[count];
|
byte[] b = new byte[count];
|
||||||
int r;
|
int r;
|
||||||
if ( ( r = f.read(b,0,b.length) ) < 0 )
|
if ( ( r = f.read(b,0,b.length) ) < 0 )
|
||||||
return NIL;
|
return NIL;
|
||||||
return LuaString.valueUsing(b, 0, r);
|
return LuaString.valueUsing(b, 0, r);
|
||||||
}
|
}
|
||||||
public static LuaValue freaduntil(File f,boolean lineonly) throws IOException {
|
public static LuaValue freaduntil(File f,boolean lineonly,boolean withend) throws IOException {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
int c;
|
int c;
|
||||||
try {
|
try {
|
||||||
if ( lineonly ) {
|
if ( lineonly ) {
|
||||||
loop: while ( (c = f.read()) > 0 ) {
|
loop: while ( (c = f.read()) >= 0 ) {
|
||||||
switch ( c ) {
|
switch ( c ) {
|
||||||
case '\r': break;
|
case '\r': if (withend) baos.write(c); break;
|
||||||
case '\n': break loop;
|
case '\n': if (withend) baos.write(c); break loop;
|
||||||
default: baos.write(c); break;
|
default: baos.write(c); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while ( (c = f.read()) > 0 )
|
while ( (c = f.read()) >= 0 )
|
||||||
baos.write(c);
|
baos.write(c);
|
||||||
}
|
}
|
||||||
} catch ( EOFException e ) {
|
} catch ( EOFException e ) {
|
||||||
@@ -582,15 +640,15 @@ public class IoLib extends TwoArgFunction {
|
|||||||
(LuaValue) NIL:
|
(LuaValue) NIL:
|
||||||
(LuaValue) LuaString.valueUsing(baos.toByteArray());
|
(LuaValue) LuaString.valueUsing(baos.toByteArray());
|
||||||
}
|
}
|
||||||
public static LuaValue freadline(File f) throws IOException {
|
public static LuaValue freadline(File f,boolean withend) throws IOException {
|
||||||
return freaduntil(f,true);
|
return freaduntil(f,true,withend);
|
||||||
}
|
}
|
||||||
public static LuaValue freadall(File f) throws IOException {
|
public static LuaValue freadall(File f) throws IOException {
|
||||||
int n = f.remaining();
|
int n = f.remaining();
|
||||||
if ( n >= 0 ) {
|
if ( n >= 0 ) {
|
||||||
return freadbytes(f, n);
|
return n == 0 ? EMPTYSTRING : freadbytes(f, n);
|
||||||
} else {
|
} else {
|
||||||
return freaduntil(f,false);
|
return freaduntil(f,false,false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static LuaValue freadnumber(File f) throws IOException {
|
public static LuaValue freadnumber(File f) throws IOException {
|
||||||
|
|||||||
@@ -27,21 +27,21 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LuaFunction} common to Java functions exposed to lua.
|
* Subclass of {@link LuaFunction} common to Java functions exposed to lua.
|
||||||
* <p>
|
* <p>
|
||||||
* To provide for common implementations in JME and JSE,
|
* To provide for common implementations in JME and JSE,
|
||||||
* library functions are typically grouped on one or more library classes
|
* library functions are typically grouped on one or more library classes
|
||||||
* and an opcode per library function is defined and used to key the switch
|
* and an opcode per library function is defined and used to key the switch
|
||||||
* to the correct function within the library.
|
* to the correct function within the library.
|
||||||
* <p>
|
* <p>
|
||||||
* Since lua functions can be called with too few or too many arguments,
|
* Since lua functions can be called with too few or too many arguments,
|
||||||
* and there are overloaded {@link LuaValue#call()} functions with varying
|
* and there are overloaded {@link LuaValue#call()} functions with varying
|
||||||
* number of arguments, a Java function exposed in lua needs to handle the
|
* number of arguments, a Java function exposed in lua needs to handle the
|
||||||
* argument fixup when a function is called with a number of arguments
|
* argument fixup when a function is called with a number of arguments
|
||||||
* differs from that expected.
|
* differs from that expected.
|
||||||
* <p>
|
* <p>
|
||||||
* To simplify the creation of library functions,
|
* To simplify the creation of library functions,
|
||||||
* there are 5 direct subclasses to handle common cases based on number of
|
* there are 5 direct subclasses to handle common cases based on number of
|
||||||
* argument values and number of return return values.
|
* argument values and number of return return values.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link ZeroArgFunction}</li>
|
* <li>{@link ZeroArgFunction}</li>
|
||||||
@@ -51,13 +51,13 @@ import org.luaj.vm2.Varargs;
|
|||||||
* <li>{@link VarArgFunction}</li>
|
* <li>{@link VarArgFunction}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* To be a Java library that can be loaded via {@code require}, it should have
|
* To be a Java library that can be loaded via {@code require}, it should have
|
||||||
* a public constructor that returns a {@link LuaValue} that, when executed,
|
* a public constructor that returns a {@link LuaValue} that, when executed,
|
||||||
* initializes the library.
|
* initializes the library.
|
||||||
* <p>
|
* <p>
|
||||||
* For example, the following code will implement a library called "hyperbolic"
|
* For example, the following code will implement a library called "hyperbolic"
|
||||||
* with two functions, "sinh", and "cosh":
|
* with two functions, "sinh", and "cosh":
|
||||||
<pre> {@code
|
<pre> {@code
|
||||||
* import org.luaj.vm2.LuaValue;
|
* import org.luaj.vm2.LuaValue;
|
||||||
* import org.luaj.vm2.lib.*;
|
* import org.luaj.vm2.lib.*;
|
||||||
*
|
*
|
||||||
@@ -86,13 +86,13 @@ import org.luaj.vm2.Varargs;
|
|||||||
* }
|
* }
|
||||||
*}
|
*}
|
||||||
*}</pre>
|
*}</pre>
|
||||||
* The default constructor is used to instantiate the library
|
* The default constructor is used to instantiate the library
|
||||||
* in response to {@code require 'hyperbolic'} statement,
|
* in response to {@code require 'hyperbolic'} statement,
|
||||||
* provided it is on Java"s class path.
|
* provided it is on Java"s class path.
|
||||||
* This instance is then invoked with 2 arguments: the name supplied to require(),
|
* This instance is then invoked with 2 arguments: the name supplied to require(),
|
||||||
* and the environment for this function. The library may ignore these, or use
|
* and the environment for this function. The library may ignore these, or use
|
||||||
* them to leave side effects in the global environment, for example.
|
* them to leave side effects in the global environment, for example.
|
||||||
* In the previous example, two functions are created, 'sinh', and 'cosh', and placed
|
* In the previous example, two functions are created, 'sinh', and 'cosh', and placed
|
||||||
* into a global table called 'hyperbolic' using the supplied 'env' argument.
|
* into a global table called 'hyperbolic' using the supplied 'env' argument.
|
||||||
* <p>
|
* <p>
|
||||||
* To test it, a script such as this can be used:
|
* To test it, a script such as this can be used:
|
||||||
@@ -105,7 +105,7 @@ import org.luaj.vm2.Varargs;
|
|||||||
* end
|
* end
|
||||||
* print( 'sinh(.5)', hyperbolic.sinh(.5) )
|
* print( 'sinh(.5)', hyperbolic.sinh(.5) )
|
||||||
* print( 'cosh(.5)', hyperbolic.cosh(.5) )
|
* print( 'cosh(.5)', hyperbolic.cosh(.5) )
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* <p>
|
* <p>
|
||||||
* It should produce something like:
|
* It should produce something like:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
@@ -115,16 +115,16 @@ import org.luaj.vm2.Varargs;
|
|||||||
* k,v sinh function: 3dbbd242
|
* k,v sinh function: 3dbbd242
|
||||||
* sinh(.5) 0.5210953
|
* sinh(.5) 0.5210953
|
||||||
* cosh(.5) 1.127626
|
* cosh(.5) 1.127626
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* <p>
|
* <p>
|
||||||
* See the source code in any of the library functions
|
* See the source code in any of the library functions
|
||||||
* such as {@link BaseLib} or {@link TableLib} for other examples.
|
* such as {@link BaseLib} or {@link TableLib} for other examples.
|
||||||
*/
|
*/
|
||||||
abstract public class LibFunction extends LuaFunction {
|
abstract public class LibFunction extends LuaFunction {
|
||||||
|
|
||||||
/** User-defined opcode to differentiate between instances of the library function class.
|
/** User-defined opcode to differentiate between instances of the library function class.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclass will typicall switch on this value to provide the specific behavior for each function.
|
* Subclass will typicall switch on this value to provide the specific behavior for each function.
|
||||||
*/
|
*/
|
||||||
protected int opcode;
|
protected int opcode;
|
||||||
|
|
||||||
@@ -135,37 +135,37 @@ abstract public class LibFunction extends LuaFunction {
|
|||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
/** Default constructor for use by subclasses */
|
/** Default constructor for use by subclasses */
|
||||||
protected LibFunction() {
|
protected LibFunction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
return name != null ? "function: " + name : super.tojstring();
|
return name != null ? "function: " + name : super.tojstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind a set of library functions.
|
* Bind a set of library functions.
|
||||||
* <p>
|
* <p>
|
||||||
* An array of names is provided, and the first name is bound
|
* An array of names is provided, and the first name is bound
|
||||||
* with opcode = 0, second with 1, etc.
|
* with opcode = 0, second with 1, etc.
|
||||||
* @param env The environment to apply to each bound function
|
* @param env The environment to apply to each bound function
|
||||||
* @param factory the Class to instantiate for each bound function
|
* @param factory the Class to instantiate for each bound function
|
||||||
* @param names array of String names, one for each function.
|
* @param names array of String names, one for each function.
|
||||||
* @see #bind(LuaValue, Class, String[], int)
|
* @see #bind(LuaValue, Class, String[], int)
|
||||||
*/
|
*/
|
||||||
protected void bind(LuaValue env, Class factory, String[] names ) {
|
protected void bind(LuaValue env, Class factory, String[] names ) {
|
||||||
bind( env, factory, names, 0 );
|
bind( env, factory, names, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind a set of library functions, with an offset
|
* Bind a set of library functions, with an offset
|
||||||
* <p>
|
* <p>
|
||||||
* An array of names is provided, and the first name is bound
|
* An array of names is provided, and the first name is bound
|
||||||
* with opcode = {@code firstopcode}, second with {@code firstopcode+1}, etc.
|
* with opcode = {@code firstopcode}, second with {@code firstopcode+1}, etc.
|
||||||
* @param env The environment to apply to each bound function
|
* @param env The environment to apply to each bound function
|
||||||
* @param factory the Class to instantiate for each bound function
|
* @param factory the Class to instantiate for each bound function
|
||||||
* @param names array of String names, one for each function.
|
* @param names array of String names, one for each function.
|
||||||
* @param firstopcode the first opcode to use
|
* @param firstopcode the first opcode to use
|
||||||
* @see #bind(LuaValue, Class, String[])
|
* @see #bind(LuaValue, Class, String[])
|
||||||
*/
|
*/
|
||||||
protected void bind(LuaValue env, Class factory, String[] names, int firstopcode ) {
|
protected void bind(LuaValue env, Class factory, String[] names, int firstopcode ) {
|
||||||
try {
|
try {
|
||||||
@@ -178,7 +178,7 @@ abstract public class LibFunction extends LuaFunction {
|
|||||||
} catch ( Exception e ) {
|
} catch ( Exception e ) {
|
||||||
throw new LuaError( "bind failed: "+e );
|
throw new LuaError( "bind failed: "+e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Java code generation utility to allocate storage for upvalue, leave it empty */
|
/** Java code generation utility to allocate storage for upvalue, leave it empty */
|
||||||
protected static LuaValue[] newupe() {
|
protected static LuaValue[] newupe() {
|
||||||
@@ -219,4 +219,4 @@ abstract public class LibFunction extends LuaFunction {
|
|||||||
default: return call(args.arg1(),args.arg(2),args.arg(3),args.arg(4));
|
default: return call(args.arg1(),args.arg(2),args.arg(3),args.arg(4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ public class PackageLib extends TwoArgFunction {
|
|||||||
searchers.set(2, lua_searcher = new lua_searcher());
|
searchers.set(2, lua_searcher = new lua_searcher());
|
||||||
searchers.set(3, java_searcher = new java_searcher());
|
searchers.set(3, java_searcher = new java_searcher());
|
||||||
package_.set(_SEARCHERS, searchers);
|
package_.set(_SEARCHERS, searchers);
|
||||||
|
package_.set("config", FILE_SEP + "\n;\n?\n!\n-\n");
|
||||||
package_.get(_LOADED).set("package", package_);
|
package_.get(_LOADED).set("package", package_);
|
||||||
env.set("package", package_);
|
env.set("package", package_);
|
||||||
globals.package_ = this;
|
globals.package_ = this;
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
LuaTable string = new LuaTable();
|
LuaTable string = new LuaTable();
|
||||||
string.set("byte", new byte_());
|
string.set("byte", new _byte());
|
||||||
string.set("char", new char_());
|
string.set("char", new _char());
|
||||||
string.set("dump", new dump());
|
string.set("dump", new dump());
|
||||||
string.set("find", new find());
|
string.set("find", new find());
|
||||||
string.set("format", new format());
|
string.set("format", new format());
|
||||||
@@ -113,7 +113,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
*
|
*
|
||||||
* @param args the calling args
|
* @param args the calling args
|
||||||
*/
|
*/
|
||||||
static final class byte_ extends VarArgFunction {
|
static final class _byte extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaString s = args.checkstring(1);
|
LuaString s = args.checkstring(1);
|
||||||
int l = s.m_length;
|
int l = s.m_length;
|
||||||
@@ -144,7 +144,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
*
|
*
|
||||||
* @param args the calling VM
|
* @param args the calling VM
|
||||||
*/
|
*/
|
||||||
static final class char_ extends VarArgFunction {
|
static final class _char extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
int n = args.narg();
|
int n = args.narg();
|
||||||
byte[] bytes = new byte[n];
|
byte[] bytes = new byte[n];
|
||||||
@@ -624,19 +624,20 @@ public class StringLib extends TwoArgFunction {
|
|||||||
private final int srclen;
|
private final int srclen;
|
||||||
private final MatchState ms;
|
private final MatchState ms;
|
||||||
private int soffset;
|
private int soffset;
|
||||||
|
private int lastmatch;
|
||||||
public GMatchAux(Varargs args, LuaString src, LuaString pat) {
|
public GMatchAux(Varargs args, LuaString src, LuaString pat) {
|
||||||
this.srclen = src.length();
|
this.srclen = src.length();
|
||||||
this.ms = new MatchState(args, src, pat);
|
this.ms = new MatchState(args, src, pat);
|
||||||
this.soffset = 0;
|
this.soffset = 0;
|
||||||
|
this.lastmatch = -1;
|
||||||
}
|
}
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
for ( ; soffset<=srclen; soffset++ ) {
|
for ( ; soffset<=srclen; soffset++ ) {
|
||||||
ms.reset();
|
ms.reset();
|
||||||
int res = ms.match(soffset, 0);
|
int res = ms.match(soffset, 0);
|
||||||
if ( res >=0 ) {
|
if ( res >=0 && res != lastmatch ) {
|
||||||
int soff = soffset;
|
int soff = soffset;
|
||||||
soffset = res;
|
lastmatch = soffset = res;
|
||||||
if (soff == res) soffset++; /* empty match? go at least one position */
|
|
||||||
return ms.push_captures( true, soff, res );
|
return ms.push_captures( true, soff, res );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -695,6 +696,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
LuaString src = args.checkstring( 1 );
|
LuaString src = args.checkstring( 1 );
|
||||||
final int srclen = src.length();
|
final int srclen = src.length();
|
||||||
LuaString p = args.checkstring( 2 );
|
LuaString p = args.checkstring( 2 );
|
||||||
|
int lastmatch = -1; /* end of last match */
|
||||||
LuaValue repl = args.arg( 3 );
|
LuaValue repl = args.arg( 3 );
|
||||||
int max_s = args.optint( 4, srclen + 1 );
|
int max_s = args.optint( 4, srclen + 1 );
|
||||||
final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^';
|
final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^';
|
||||||
@@ -707,18 +709,15 @@ public class StringLib extends TwoArgFunction {
|
|||||||
while ( n < max_s ) {
|
while ( n < max_s ) {
|
||||||
ms.reset();
|
ms.reset();
|
||||||
int res = ms.match( soffset, anchor ? 1 : 0 );
|
int res = ms.match( soffset, anchor ? 1 : 0 );
|
||||||
if ( res != -1 ) {
|
if ( res != -1 && res != lastmatch ) { /* match? */
|
||||||
n++;
|
n++;
|
||||||
ms.add_value( lbuf, soffset, res, repl );
|
ms.add_value( lbuf, soffset, res, repl ); /* add replacement to buffer */
|
||||||
|
soffset = lastmatch = res;
|
||||||
}
|
}
|
||||||
if ( res != -1 && res > soffset )
|
else if ( soffset < srclen ) /* otherwise, skip one character */
|
||||||
soffset = res;
|
|
||||||
else if ( soffset < srclen )
|
|
||||||
lbuf.append( (byte) src.luaByte( soffset++ ) );
|
lbuf.append( (byte) src.luaByte( soffset++ ) );
|
||||||
else
|
else break; /* end of subject */
|
||||||
break;
|
if ( anchor ) break;
|
||||||
if ( anchor )
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
lbuf.append( src.substring( soffset, srclen ) );
|
lbuf.append( src.substring( soffset, srclen ) );
|
||||||
return varargsOf(lbuf.tostring(), valueOf(n));
|
return varargsOf(lbuf.tostring(), valueOf(n));
|
||||||
@@ -914,6 +913,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
private static final LuaString SPECIALS = valueOf("^$*+?.([%-");
|
private static final LuaString SPECIALS = valueOf("^$*+?.([%-");
|
||||||
private static final int MAX_CAPTURES = 32;
|
private static final int MAX_CAPTURES = 32;
|
||||||
|
|
||||||
|
private static final int MAXCCALLS = 200;
|
||||||
|
|
||||||
private static final int CAP_UNFINISHED = -1;
|
private static final int CAP_UNFINISHED = -1;
|
||||||
private static final int CAP_POSITION = -2;
|
private static final int CAP_POSITION = -2;
|
||||||
|
|
||||||
@@ -931,7 +932,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
static {
|
static {
|
||||||
CHAR_TABLE = new byte[256];
|
CHAR_TABLE = new byte[256];
|
||||||
|
|
||||||
for ( int i = 0; i < 256; ++i ) {
|
for ( int i = 0; i < 128; ++i ) {
|
||||||
final char c = (char) i;
|
final char c = (char) i;
|
||||||
CHAR_TABLE[i] = (byte)( ( Character.isDigit( c ) ? MASK_DIGIT : 0 ) |
|
CHAR_TABLE[i] = (byte)( ( Character.isDigit( c ) ? MASK_DIGIT : 0 ) |
|
||||||
( Character.isLowerCase( c ) ? MASK_LOWERCASE : 0 ) |
|
( Character.isLowerCase( c ) ? MASK_LOWERCASE : 0 ) |
|
||||||
@@ -940,7 +941,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
if ( ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) || ( c >= '0' && c <= '9' ) ) {
|
if ( ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) || ( c >= '0' && c <= '9' ) ) {
|
||||||
CHAR_TABLE[i] |= MASK_HEXDIGIT;
|
CHAR_TABLE[i] |= MASK_HEXDIGIT;
|
||||||
}
|
}
|
||||||
if ( ( c >= '!' && c <= '/' ) || ( c >= ':' && c <= '@' ) ) {
|
if ( ( c >= '!' && c <= '/' ) || ( c >= ':' && c <= '@' ) || ( c >= '[' && c <= '`' ) || ( c >= '{' && c <= '~' ) ) {
|
||||||
CHAR_TABLE[i] |= MASK_PUNCT;
|
CHAR_TABLE[i] |= MASK_PUNCT;
|
||||||
}
|
}
|
||||||
if ( ( CHAR_TABLE[i] & ( MASK_LOWERCASE | MASK_UPPERCASE ) ) != 0 ) {
|
if ( ( CHAR_TABLE[i] & ( MASK_LOWERCASE | MASK_UPPERCASE ) ) != 0 ) {
|
||||||
@@ -952,11 +953,12 @@ public class StringLib extends TwoArgFunction {
|
|||||||
CHAR_TABLE['\r'] |= MASK_SPACE;
|
CHAR_TABLE['\r'] |= MASK_SPACE;
|
||||||
CHAR_TABLE['\n'] |= MASK_SPACE;
|
CHAR_TABLE['\n'] |= MASK_SPACE;
|
||||||
CHAR_TABLE['\t'] |= MASK_SPACE;
|
CHAR_TABLE['\t'] |= MASK_SPACE;
|
||||||
CHAR_TABLE[0x0C /* '\v' */ ] |= MASK_SPACE;
|
CHAR_TABLE[0x0B /* '\v' */ ] |= MASK_SPACE;
|
||||||
CHAR_TABLE['\f'] |= MASK_SPACE;
|
CHAR_TABLE['\f'] |= MASK_SPACE;
|
||||||
};
|
};
|
||||||
|
|
||||||
static class MatchState {
|
static class MatchState {
|
||||||
|
int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
|
||||||
final LuaString s;
|
final LuaString s;
|
||||||
final LuaString p;
|
final LuaString p;
|
||||||
final Varargs args;
|
final Varargs args;
|
||||||
@@ -971,10 +973,12 @@ public class StringLib extends TwoArgFunction {
|
|||||||
this.level = 0;
|
this.level = 0;
|
||||||
this.cinit = new int[ MAX_CAPTURES ];
|
this.cinit = new int[ MAX_CAPTURES ];
|
||||||
this.clen = new int[ MAX_CAPTURES ];
|
this.clen = new int[ MAX_CAPTURES ];
|
||||||
|
this.matchdepth = MAXCCALLS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
level = 0;
|
level = 0;
|
||||||
|
this.matchdepth = MAXCCALLS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void add_s( Buffer lbuf, LuaString news, int soff, int e ) {
|
private void add_s( Buffer lbuf, LuaString news, int soff, int e ) {
|
||||||
@@ -1049,7 +1053,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
if ( i == 0 ) {
|
if ( i == 0 ) {
|
||||||
return s.substring( soff, end );
|
return s.substring( soff, end );
|
||||||
} else {
|
} else {
|
||||||
return error( "invalid capture index" );
|
return error( "invalid capture index %" + (i + 1) );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int l = clen[i];
|
int l = clen[i];
|
||||||
@@ -1068,7 +1072,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
private int check_capture( int l ) {
|
private int check_capture( int l ) {
|
||||||
l -= '1';
|
l -= '1';
|
||||||
if ( l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED ) {
|
if ( l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED ) {
|
||||||
error("invalid capture index");
|
error("invalid capture index %" + (l + 1));
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
@@ -1118,9 +1122,10 @@ public class StringLib extends TwoArgFunction {
|
|||||||
case 'c': res = ( cdata & MASK_CONTROL ) != 0; break;
|
case 'c': res = ( cdata & MASK_CONTROL ) != 0; break;
|
||||||
case 'p': res = ( cdata & MASK_PUNCT ) != 0; break;
|
case 'p': res = ( cdata & MASK_PUNCT ) != 0; break;
|
||||||
case 's': res = ( cdata & MASK_SPACE ) != 0; break;
|
case 's': res = ( cdata & MASK_SPACE ) != 0; break;
|
||||||
|
case 'g': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT | MASK_PUNCT ) ) != 0; break;
|
||||||
case 'w': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT ) ) != 0; break;
|
case 'w': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT ) ) != 0; break;
|
||||||
case 'x': res = ( cdata & MASK_HEXDIGIT ) != 0; break;
|
case 'x': res = ( cdata & MASK_HEXDIGIT ) != 0; break;
|
||||||
case 'z': res = ( c == 0 ); break;
|
case 'z': res = ( c == 0 ); break; /* deprecated option */
|
||||||
default: return cl == c;
|
default: return cl == c;
|
||||||
}
|
}
|
||||||
return ( lcl == cl ) ? res : !res;
|
return ( lcl == cl ) ? res : !res;
|
||||||
@@ -1162,81 +1167,86 @@ public class StringLib extends TwoArgFunction {
|
|||||||
* where match ends, otherwise returns -1.
|
* where match ends, otherwise returns -1.
|
||||||
*/
|
*/
|
||||||
int match( int soffset, int poffset ) {
|
int match( int soffset, int poffset ) {
|
||||||
while ( true ) {
|
if (matchdepth-- == 0) error("pattern too complex");
|
||||||
// Check if we are at the end of the pattern -
|
try {
|
||||||
// equivalent to the '\0' case in the C version, but our pattern
|
while ( true ) {
|
||||||
// string is not NUL-terminated.
|
// Check if we are at the end of the pattern -
|
||||||
if ( poffset == p.length() )
|
// equivalent to the '\0' case in the C version, but our pattern
|
||||||
return soffset;
|
// string is not NUL-terminated.
|
||||||
switch ( p.luaByte( poffset ) ) {
|
if ( poffset == p.length() )
|
||||||
case '(':
|
return soffset;
|
||||||
if ( ++poffset < p.length() && p.luaByte( poffset ) == ')' )
|
switch ( p.luaByte( poffset ) ) {
|
||||||
return start_capture( soffset, poffset + 1, CAP_POSITION );
|
case '(':
|
||||||
else
|
if ( ++poffset < p.length() && p.luaByte( poffset ) == ')' )
|
||||||
return start_capture( soffset, poffset, CAP_UNFINISHED );
|
return start_capture( soffset, poffset + 1, CAP_POSITION );
|
||||||
case ')':
|
else
|
||||||
return end_capture( soffset, poffset + 1 );
|
return start_capture( soffset, poffset, CAP_UNFINISHED );
|
||||||
case L_ESC:
|
case ')':
|
||||||
if ( poffset + 1 == p.length() )
|
return end_capture( soffset, poffset + 1 );
|
||||||
error("malformed pattern (ends with '%')");
|
case L_ESC:
|
||||||
switch ( p.luaByte( poffset + 1 ) ) {
|
if ( poffset + 1 == p.length() )
|
||||||
case 'b':
|
error("malformed pattern (ends with '%')");
|
||||||
soffset = matchbalance( soffset, poffset + 2 );
|
switch ( p.luaByte( poffset + 1 ) ) {
|
||||||
if ( soffset == -1 ) return -1;
|
case 'b':
|
||||||
poffset += 4;
|
soffset = matchbalance( soffset, poffset + 2 );
|
||||||
continue;
|
if ( soffset == -1 ) return -1;
|
||||||
case 'f': {
|
poffset += 4;
|
||||||
poffset += 2;
|
continue;
|
||||||
if ( poffset == p.length() || p.luaByte( poffset ) != '[' ) {
|
case 'f': {
|
||||||
error("Missing '[' after '%f' in pattern");
|
poffset += 2;
|
||||||
|
if ( poffset == p.length() || p.luaByte( poffset ) != '[' ) {
|
||||||
|
error("missing '[' after '%f' in pattern");
|
||||||
|
}
|
||||||
|
int ep = classend( poffset );
|
||||||
|
int previous = ( soffset == 0 ) ? '\0' : s.luaByte( soffset - 1 );
|
||||||
|
int next = ( soffset == s.length() ) ? '\0' : s.luaByte( soffset );
|
||||||
|
if ( matchbracketclass( previous, poffset, ep - 1 ) ||
|
||||||
|
!matchbracketclass( next, poffset, ep - 1 ) )
|
||||||
|
return -1;
|
||||||
|
poffset = ep;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
int ep = classend( poffset );
|
default: {
|
||||||
int previous = ( soffset == 0 ) ? '\0' : s.luaByte( soffset - 1 );
|
int c = p.luaByte( poffset + 1 );
|
||||||
int next = ( soffset == s.length() ) ? '\0' : s.luaByte( soffset );
|
if ( Character.isDigit( (char) c ) ) {
|
||||||
if ( matchbracketclass( previous, poffset, ep - 1 ) ||
|
soffset = match_capture( soffset, c );
|
||||||
!matchbracketclass( next, poffset, ep - 1 ) )
|
if ( soffset == -1 )
|
||||||
|
return -1;
|
||||||
|
return match( soffset, poffset + 2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case '$':
|
||||||
|
if ( poffset + 1 == p.length() )
|
||||||
|
return ( soffset == s.length() ) ? soffset : -1;
|
||||||
|
}
|
||||||
|
int ep = classend( poffset );
|
||||||
|
boolean m = soffset < s.length() && singlematch( s.luaByte( soffset ), poffset, ep );
|
||||||
|
int pc = ( ep < p.length() ) ? p.luaByte( ep ) : '\0';
|
||||||
|
|
||||||
|
switch ( pc ) {
|
||||||
|
case '?':
|
||||||
|
int res;
|
||||||
|
if ( m && ( ( res = match( soffset + 1, ep + 1 ) ) != -1 ) )
|
||||||
|
return res;
|
||||||
|
poffset = ep + 1;
|
||||||
|
continue;
|
||||||
|
case '*':
|
||||||
|
return max_expand( soffset, poffset, ep );
|
||||||
|
case '+':
|
||||||
|
return ( m ? max_expand( soffset + 1, poffset, ep ) : -1 );
|
||||||
|
case '-':
|
||||||
|
return min_expand( soffset, poffset, ep );
|
||||||
|
default:
|
||||||
|
if ( !m )
|
||||||
return -1;
|
return -1;
|
||||||
|
soffset++;
|
||||||
poffset = ep;
|
poffset = ep;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
default: {
|
|
||||||
int c = p.luaByte( poffset + 1 );
|
|
||||||
if ( Character.isDigit( (char) c ) ) {
|
|
||||||
soffset = match_capture( soffset, c );
|
|
||||||
if ( soffset == -1 )
|
|
||||||
return -1;
|
|
||||||
return match( soffset, poffset + 2 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case '$':
|
|
||||||
if ( poffset + 1 == p.length() )
|
|
||||||
return ( soffset == s.length() ) ? soffset : -1;
|
|
||||||
}
|
|
||||||
int ep = classend( poffset );
|
|
||||||
boolean m = soffset < s.length() && singlematch( s.luaByte( soffset ), poffset, ep );
|
|
||||||
int pc = ( ep < p.length() ) ? p.luaByte( ep ) : '\0';
|
|
||||||
|
|
||||||
switch ( pc ) {
|
|
||||||
case '?':
|
|
||||||
int res;
|
|
||||||
if ( m && ( ( res = match( soffset + 1, ep + 1 ) ) != -1 ) )
|
|
||||||
return res;
|
|
||||||
poffset = ep + 1;
|
|
||||||
continue;
|
|
||||||
case '*':
|
|
||||||
return max_expand( soffset, poffset, ep );
|
|
||||||
case '+':
|
|
||||||
return ( m ? max_expand( soffset + 1, poffset, ep ) : -1 );
|
|
||||||
case '-':
|
|
||||||
return min_expand( soffset, poffset, ep );
|
|
||||||
default:
|
|
||||||
if ( !m )
|
|
||||||
return -1;
|
|
||||||
soffset++;
|
|
||||||
poffset = ep;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
matchdepth++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1301,7 +1311,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
int matchbalance( int soff, int poff ) {
|
int matchbalance( int soff, int poff ) {
|
||||||
final int plen = p.length();
|
final int plen = p.length();
|
||||||
if ( poff == plen || poff + 1 == plen ) {
|
if ( poff == plen || poff + 1 == plen ) {
|
||||||
error( "unbalanced pattern" );
|
error( "malformed pattern (missing arguments to '%b')" );
|
||||||
}
|
}
|
||||||
final int slen = s.length();
|
final int slen = s.length();
|
||||||
if ( soff >= slen )
|
if ( soff >= slen )
|
||||||
|
|||||||
@@ -73,12 +73,6 @@ public class TableLib extends TwoArgFunction {
|
|||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("table", table);
|
if (!env.get("package").isnil()) env.get("package").get("loaded").set("table", table);
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TableLibFunction extends LibFunction {
|
|
||||||
public LuaValue call() {
|
|
||||||
return argerror(1, "table expected, got no value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "concat" (table [, sep [, i [, j]]]) -> string
|
// "concat" (table [, sep [, i [, j]]]) -> string
|
||||||
static class concat extends TableLibFunction {
|
static class concat extends TableLibFunction {
|
||||||
@@ -100,18 +94,22 @@ public class TableLib extends TwoArgFunction {
|
|||||||
static class insert extends VarArgFunction {
|
static class insert extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
switch (args.narg()) {
|
switch (args.narg()) {
|
||||||
case 0: case 1: {
|
|
||||||
return argerror(2, "value expected");
|
|
||||||
}
|
|
||||||
case 2: {
|
case 2: {
|
||||||
LuaTable table = args.arg1().checktable();
|
LuaTable table = args.checktable(1);
|
||||||
table.insert(table.length()+1,args.arg(2));
|
table.insert(table.length()+1,args.arg(2));
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
default: {
|
case 3: {
|
||||||
args.arg1().checktable().insert(args.checkint(2),args.arg(3));
|
LuaTable table = args.checktable(1);
|
||||||
|
int pos = args.checkint(2);
|
||||||
|
int max = table.length() + 1;
|
||||||
|
if (pos < 1 || pos > max) argerror(2, "position out of bounds: " + pos + " not between 1 and " + max);
|
||||||
|
table.insert(pos, args.arg(3));
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
|
default: {
|
||||||
|
return error("wrong number of arguments to 'table.insert': " + args.narg() + " (must be 2 or 3)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,15 +126,21 @@ public class TableLib extends TwoArgFunction {
|
|||||||
// "remove" (table [, pos]) -> removed-ele
|
// "remove" (table [, pos]) -> removed-ele
|
||||||
static class remove extends VarArgFunction {
|
static class remove extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
return args.arg1().checktable().remove(args.optint(2, 0));
|
LuaTable table = args.checktable(1);
|
||||||
|
int size = table.length();
|
||||||
|
int pos = args.optint(2, size);
|
||||||
|
if (pos != size && (pos < 1 || pos > size + 1)) {
|
||||||
|
argerror(2, "position out of bounds: " + pos + " not between 1 and " + (size + 1));
|
||||||
|
}
|
||||||
|
return table.remove(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "sort" (table [, comp])
|
// "sort" (table [, comp])
|
||||||
static class sort extends VarArgFunction {
|
static class sort extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
args.arg1().checktable().sort(
|
args.checktable(1).sort(
|
||||||
args.arg(2).isnil()? NIL: args.arg(2).checkfunction());
|
args.isnil(2)? NIL: args.checkfunction(2));
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,11 +150,9 @@ public class TableLib extends TwoArgFunction {
|
|||||||
static class unpack extends VarArgFunction {
|
static class unpack extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaTable t = args.checktable(1);
|
LuaTable t = args.checktable(1);
|
||||||
switch (args.narg()) {
|
// do not waste resource for calc rawlen if arg3 is not nil
|
||||||
case 1: return t.unpack();
|
int len = args.arg(3).isnil() ? t.length() : 0;
|
||||||
case 2: return t.unpack(args.checkint(2));
|
return t.unpack(args.optint(2, 1), args.optint(3, len));
|
||||||
default: return t.unpack(args.checkint(2), args.checkint(3));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/core/org/luaj/vm2/lib/TableLibFunction.java
Normal file
9
src/core/org/luaj/vm2/lib/TableLibFunction.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package org.luaj.vm2.lib;
|
||||||
|
|
||||||
|
import org.luaj.vm2.LuaValue;
|
||||||
|
|
||||||
|
class TableLibFunction extends LibFunction {
|
||||||
|
public LuaValue call() {
|
||||||
|
return argerror(1, "table expected, got no value");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,20 +36,20 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.lib.IoLib;
|
import org.luaj.vm2.lib.IoLib;
|
||||||
import org.luaj.vm2.lib.LibFunction;
|
import org.luaj.vm2.lib.LibFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io}
|
* Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io}
|
||||||
* library for the JSE platform.
|
* library for the JSE platform.
|
||||||
* <p>
|
|
||||||
* It uses RandomAccessFile to implement seek on files.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to
|
* It uses RandomAccessFile to implement seek on files.
|
||||||
|
* <p>
|
||||||
|
* Typically, this library is included as part of a call to
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
||||||
* } </pre>
|
* } </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* For special cases where the smallest possible footprint is desired,
|
* For special cases where the smallest possible footprint is desired,
|
||||||
* a minimal set of libraries could be loaded
|
* a minimal set of libraries could be loaded
|
||||||
* directly via {@link Globals#load(LuaValue)} using code such as:
|
* directly via {@link Globals#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
@@ -96,9 +96,9 @@ public class JseIoLib extends IoLib {
|
|||||||
|
|
||||||
protected File openProgram(String prog, String mode) throws IOException {
|
protected File openProgram(String prog, String mode) throws IOException {
|
||||||
final Process p = Runtime.getRuntime().exec(prog);
|
final Process p = Runtime.getRuntime().exec(prog);
|
||||||
return "w".equals(mode)?
|
return "w".equals(mode)?
|
||||||
new FileImpl( p.getOutputStream() ):
|
new FileImpl( p.getOutputStream() ):
|
||||||
new FileImpl( p.getInputStream() );
|
new FileImpl( p.getInputStream() );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File tmpFile() throws IOException {
|
protected File tmpFile() throws IOException {
|
||||||
@@ -133,7 +133,7 @@ public class JseIoLib extends IoLib {
|
|||||||
this( null, null, o );
|
this( null, null, o );
|
||||||
}
|
}
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
return "file ("+this.hashCode()+")";
|
return "file (" + (this.closed ? "closed" : String.valueOf(this.hashCode())) + ")";
|
||||||
}
|
}
|
||||||
public boolean isstdfile() {
|
public boolean isstdfile() {
|
||||||
return file == null;
|
return file == null;
|
||||||
@@ -199,11 +199,11 @@ public class JseIoLib extends IoLib {
|
|||||||
}
|
}
|
||||||
notimplemented();
|
notimplemented();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return char if read, -1 if eof, throw IOException on other exception
|
// return char if read, -1 if eof, throw IOException on other exception
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
if ( is != null )
|
if ( is != null )
|
||||||
return is.read();
|
return is.read();
|
||||||
else if ( file != null ) {
|
else if ( file != null ) {
|
||||||
return file.read();
|
return file.read();
|
||||||
@@ -321,7 +321,7 @@ public class JseIoLib extends IoLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int remaining() throws IOException {
|
public int remaining() throws IOException {
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int peek() throws IOException, EOFException {
|
public int peek() throws IOException, EOFException {
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ import org.luaj.vm2.lib.OsLib;
|
|||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the standard lua {@code os} library.
|
* Subclass of {@link LibFunction} which implements the standard lua {@code os} library.
|
||||||
* <p>
|
* <p>
|
||||||
* This contains more complete implementations of the following functions
|
* This contains more complete implementations of the following functions
|
||||||
* using features that are specific to JSE:
|
* using features that are specific to JSE:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@code execute()}</li>
|
* <li>{@code execute()}</li>
|
||||||
* <li>{@code remove()}</li>
|
* <li>{@code remove()}</li>
|
||||||
@@ -42,18 +42,18 @@ import org.luaj.vm2.lib.OsLib;
|
|||||||
* <li>{@code tmpname()}</li>
|
* <li>{@code tmpname()}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* Because the nature of the {@code os} library is to encapsulate
|
* Because the nature of the {@code os} library is to encapsulate
|
||||||
* os-specific features, the behavior of these functions varies considerably
|
* os-specific features, the behavior of these functions varies considerably
|
||||||
* from their counterparts in the C platform.
|
* from their counterparts in the C platform.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to
|
* Typically, this library is included as part of a call to
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println( globals.get("os").get("time").call() );
|
* System.out.println( globals.get("os").get("time").call() );
|
||||||
* } </pre>
|
* } </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* For special cases where the smallest possible footprint is desired,
|
* For special cases where the smallest possible footprint is desired,
|
||||||
* a minimal set of libraries could be loaded
|
* a minimal set of libraries could be loaded
|
||||||
* directly via {@link Globals#load(LuaValue)} using code such as:
|
* directly via {@link Globals#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
@@ -126,7 +126,7 @@ public class JseOsLib extends org.luaj.vm2.lib.OsLib {
|
|||||||
protected String tmpname() {
|
protected String tmpname() {
|
||||||
try {
|
try {
|
||||||
java.io.File f = java.io.File.createTempFile(TMP_PREFIX ,TMP_SUFFIX);
|
java.io.File f = java.io.File.createTempFile(TMP_PREFIX ,TMP_SUFFIX);
|
||||||
return f.getName();
|
return f.getAbsolutePath();
|
||||||
} catch ( IOException ioe ) {
|
} catch ( IOException ioe ) {
|
||||||
return super.tmpname();
|
return super.tmpname();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user