From caacec21bdacfde0f6c97b35b3d08f61d05ee8a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 7 Jul 2014 04:37:19 +0200 Subject: [PATCH] LuaJ 3 Final. I'm not sure this is a good idea, but nothing seems to break (immediately). --- src/main/java/org/luaj/vm3/Globals.java | 122 +++++++++++++----- src/main/java/org/luaj/vm3/LuaClosure.java | 8 +- .../org/luaj/vm3/lib/jse/CoerceJavaToLua.java | 24 +++- 3 files changed, 118 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/luaj/vm3/Globals.java b/src/main/java/org/luaj/vm3/Globals.java index c5161aa84..f10556888 100644 --- a/src/main/java/org/luaj/vm3/Globals.java +++ b/src/main/java/org/luaj/vm3/Globals.java @@ -231,7 +231,7 @@ public class Globals extends LuaTable { if (undumper == null) error("No undumper."); if (!is.markSupported()) - is = new MarkStream(is); + is = new BufferedStream(is); is.mark(4); final Prototype p = undumper.undump(is, chunkname); if (p != null) @@ -277,7 +277,8 @@ public class Globals extends LuaTable { /** Reader implementation to read chars from a String in JME or JSE. */ static class StrReader extends Reader { final String s; - int i = 0, n; + int i = 0; + final int n; StrReader(String s) { this.s = s; n = s.length(); @@ -285,6 +286,9 @@ public class Globals extends LuaTable { public void close() throws IOException { i = n; } + public int read() throws IOException { + return i < n ? s.charAt(i++) : -1; + } public int read(char[] cbuf, int off, int len) throws IOException { int j = 0; for (; j < len && i < n; ++j, ++i) @@ -293,54 +297,115 @@ public class Globals extends LuaTable { } } + /* Abstract base class to provide basic buffered input storage and delivery. + * This class may be moved to its own package in the future. + */ + abstract static class AbstractBufferedStream extends InputStream { + protected byte[] b; + protected int i = 0, j = 0; + protected AbstractBufferedStream(int buflen) { + this.b = new byte[buflen]; + } + abstract protected int avail() throws IOException; + public int read() throws IOException { + int a = avail(); + return (a <= 0 ? -1 : 0xff & b[i++]); + } + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + public int read(byte[] b, int i0, int n) throws IOException { + int a = avail(); + if (a <= 0) return -1; + final int n_read = Math.min(a, n); + System.arraycopy(this.b, i, b, i0, n_read); + i += n_read; + return n_read; + } + public long skip(long n) throws IOException { + final long k = Math.min(n, j - i); + i += k; + return k; + } + public int available() throws IOException { + return j - i; + } + } + /** Simple converter from Reader to InputStream using UTF8 encoding that will work * on both JME and JSE. + * This class may be moved to its own package in the future. */ - static class UTF8Stream extends InputStream { - final char[] c = new char[32]; - final byte[] b = new byte[96]; - int i = 0, j = 0; - final Reader r; + static class UTF8Stream extends AbstractBufferedStream { + private final char[] c = new char[32]; + private final Reader r; UTF8Stream(Reader r) { + super(96); this.r = r; } - public int read() throws IOException { - if (i < j) - return c[i++]; + protected int avail() throws IOException { + if (i < j) return j - i; int n = r.read(c); if (n < 0) return -1; + if (n == 0) { + int u = r.read(); + if (u < 0) + return -1; + c[0] = (char) u; + n = 1; + } j = LuaString.encodeToUtf8(c, n, b, i = 0); - return b[i++]; + return j; + } + public void close() throws IOException { + r.close(); } } - /** Simple InputStream that supports mark. + /** Simple buffered InputStream that supports mark. * Used to examine an InputStream for a 4-byte binary lua signature, - * and fall back to text input when the signature is not found. + * and fall back to text input when the signature is not found, + * as well as speed up normal compilation and reading of lua scripts. + * This class may be moved to its own package in the future. */ - static class MarkStream extends InputStream { - private int[] b; - private int i = 0, j = 0; + static class BufferedStream extends AbstractBufferedStream { private final InputStream s; - MarkStream(InputStream s) { + public BufferedStream(InputStream s) { + this(128, s); + } + BufferedStream(int buflen, InputStream s) { + super(buflen); this.s = s; } - public int read() throws IOException { - if (i < j) - return b[i++]; - final int c = s.read(); - if (c < 0) + protected int avail() throws IOException { + if (i < j) return j - i; + if (j >= b.length) i = j = 0; + // leave previous bytes in place to implement mark()/reset(). + int n = s.read(b, j, b.length - j); + if (n < 0) return -1; - if (j < b.length) { - b[j++] = c; - i = j; + if (n == 0) { + int u = s.read(); + if (u < 0) + return -1; + b[j] = (byte) u; + n = 1; } - return c; + j += n; + return n; + } + public void close() throws IOException { + s.close(); } public synchronized void mark(int n) { - b = new int[n]; - i = j = 0; + if (i > 0 || n > b.length) { + byte[] dest = n > b.length ? new byte[n] : b; + System.arraycopy(b, i, dest, 0, j - i); + j -= i; + i = 0; + b = dest; + } } public boolean markSupported() { return true; @@ -349,5 +414,4 @@ public class Globals extends LuaTable { i = 0; } } - } diff --git a/src/main/java/org/luaj/vm3/LuaClosure.java b/src/main/java/org/luaj/vm3/LuaClosure.java index 8efd35b63..a1193b9a4 100644 --- a/src/main/java/org/luaj/vm3/LuaClosure.java +++ b/src/main/java/org/luaj/vm3/LuaClosure.java @@ -195,12 +195,12 @@ public class LuaClosure extends LuaFunction { // process instructions try { - while ( true ) { + for (; true; ++pc) { if (globals != null && globals.debuglib != null) globals.debuglib.onInstruction( pc, v, top ); // pull out instruction - i = code[pc++]; + i = code[pc]; a = ((i>>6) & 0xff); // process the op code @@ -217,7 +217,7 @@ public class LuaClosure extends LuaFunction { case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */ stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE; if ((i&(0x1ff<<14)) != 0) - pc++; /* skip next instruction (if C) */ + ++pc; /* skip next instruction (if C) */ continue; case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(A+B):= nil */ @@ -444,7 +444,7 @@ public class LuaClosure extends LuaFunction { case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */ { if ( (c=(i>>14)&0x1ff) == 0 ) - c = code[pc++]; + c = code[++pc]; int offset = (c-1) * Lua.LFIELDS_PER_FLUSH; o = stack[a]; if ( (b=i>>>23) == 0 ) { diff --git a/src/main/java/org/luaj/vm3/lib/jse/CoerceJavaToLua.java b/src/main/java/org/luaj/vm3/lib/jse/CoerceJavaToLua.java index e4f083bbd..218b813e3 100644 --- a/src/main/java/org/luaj/vm3/lib/jse/CoerceJavaToLua.java +++ b/src/main/java/org/luaj/vm3/lib/jse/CoerceJavaToLua.java @@ -99,6 +99,16 @@ public class CoerceJavaToLua { return LuaString.valueOf( javaValue.toString() ); } } ; + Coercion bytesCoercion = new Coercion() { + public LuaValue coerce( Object javaValue ) { + return LuaValue.valueOf((byte[]) javaValue); + } + } ; + Coercion classCoercion = new Coercion() { + public LuaValue coerce( Object javaValue ) { + return JavaClass.forClass((Class) javaValue); + } + } ; COERCIONS.put( Boolean.class, boolCoercion ); COERCIONS.put( Byte.class, intCoercion ); COERCIONS.put( Character.class, charCoercion ); @@ -108,6 +118,8 @@ public class CoerceJavaToLua { COERCIONS.put( Float.class, doubleCoercion ); COERCIONS.put( Double.class, doubleCoercion ); COERCIONS.put( String.class, stringCoercion ); + COERCIONS.put( byte[].class, bytesCoercion ); + COERCIONS.put( Class.class, classCoercion ); } /** @@ -117,6 +129,7 @@ public class CoerceJavaToLua { * will become {@link LuaInteger}; * {@code long}, {@code float}, and {@code double} will become {@link LuaDouble}; * {@code String} and {@code byte[]} will become {@link LuaString}; + * types inheriting from {@link LuaValue} will be returned without coercion; * other types will become {@link LuaUserdata}. * @param o Java object needing conversion * @return {@link LuaValue} corresponding to the supplied Java value. @@ -129,13 +142,12 @@ public class CoerceJavaToLua { public static LuaValue coerce(Object o) { if ( o == null ) return LuaValue.NIL; - if (o instanceof Class) - return JavaClass.forClass((Class) o); Class clazz = o.getClass(); Coercion c = (Coercion) COERCIONS.get( clazz ); if ( c == null ) { c = clazz.isArray()? arrayCoercion: - instanceCoercion; + o instanceof LuaValue ? luaCoercion: + instanceCoercion; COERCIONS.put( clazz, c ); } return c.coerce(o); @@ -153,4 +165,10 @@ public class CoerceJavaToLua { return new JavaArray(javaValue); } }; + + static final Coercion luaCoercion = new Coercion() { + public LuaValue coerce( Object javaValue ) { + return (LuaValue) javaValue; + } + } ; }