package lua.io; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import lua.VM; import lua.value.LBoolean; import lua.value.LDouble; import lua.value.LInteger; import lua.value.LNil; import lua.value.LNumber; import lua.value.LString; import lua.value.LValue; /* ** Function Prototypes */ public class LoadState { /** mark for precompiled code (`Lua') */ public static final String LUA_SIGNATURE = "\033Lua"; /** for header of binary files -- this is Lua 5.1 */ public static final int LUAC_VERSION = 0x51; /** for header of binary files -- this is the official format */ public static final int LUAC_FORMAT = 0; /** size of header of binary files */ public static final int LUAC_HEADERSIZE = 12; /** expected lua header bytes */ private static final int LUAC_HEADER_SIGNATURE = ('\033'<<24) | ('L'<<16) | ('u'<<8) | ('a'); // values read from the header private int luacVersion; private int luacFormat; private boolean luacLittleEndian; private int luacSizeofInt; private int luacSizeofSizeT; private int luacSizeofInstruction; private int luacSizeofLuaNumber; private boolean luacIsNumberIntegral; /** input stream from which we are loading */ private DataInputStream is; /** Name of what is being loaded? */ String name; /** The VM doing the loading */ VM L; private static final int LUA_TNONE = (-1); private static final int LUA_TNIL = 0; private static final int LUA_TBOOLEAN = 1; private static final int LUA_TLIGHTUSERDATA = 2; private static final int LUA_TNUMBER = 3; private static final int LUA_TSTRING = 4; private static final int LUA_TTABLE = 5; private static final int LUA_TFUNCTION = 6; private static final int LUA_TUSERDATA = 7; private static final int LUA_TTHREAD = 8; int loadByte() throws IOException { return is.readUnsignedByte(); } int loadInt() throws IOException { if ( this.luacLittleEndian ) { int a = is.readUnsignedByte(); int b = is.readUnsignedByte(); int c = is.readUnsignedByte(); int d = is.readUnsignedByte(); return (d << 24) | (c << 16) | (b << 8) | a; } else { return is.readInt(); } } long loadInt64() throws IOException { int a,b; if ( this.luacLittleEndian ) { a = loadInt(); b = loadInt(); } else { b = loadInt(); a = loadInt(); } return (((long)b)<<32) | (((long)a)&0xffffffffL); } LString loadString() throws IOException { int size = loadInt(); if ( size == 0 ) return null; byte[] bytes = new byte[size]; is.readFully( bytes ); String s = new String( bytes, 0, size-1 ); return new LString( s ); } static LNumber longBitsToLuaNumber( long bits ) { if ( ( bits & ( ( 1L << 63 ) - 1 ) ) == 0L ) { return new LInteger( 0 ); } int e = (int)((bits >> 52) & 0x7ffL) - 1023; if ( e >= 0 && e < 31 ) { long f = bits & 0xFFFFFFFFFFFFFL; int shift = 52 - e; long intPrecMask = ( 1L << shift ) - 1; if ( ( f & intPrecMask ) == 0 ) { int intValue = (int)( f >> shift ) | ( 1 << e ); return new LInteger( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue ); } } double value = Double.longBitsToDouble(bits); return new LDouble( value ); } LNumber loadNumber() throws IOException { if ( this.luacIsNumberIntegral ) { int value = loadInt(); return new LInteger( value ); } else { return longBitsToLuaNumber( loadInt64() ); } } public void loadCode( Proto f ) throws IOException { int n = loadInt(); int[] code = new int[n]; for ( int i=0; i