// #define DEBUG_BINARY_READER // #define DEBUG_UNDUMP using System; using ULDebug = UniLua.Tools.ULDebug; namespace UniLua { public class BinaryBytesReader { private ILoadInfo LoadInfo; public int SizeOfSizeT; public BinaryBytesReader( ILoadInfo loadinfo ) { LoadInfo = loadinfo; SizeOfSizeT = 0; } public byte[] ReadBytes( int count ) { byte[] ret = new byte[count]; for( int i=0; i Int32.MaxValue ) throw new NotImplementedException(); return (int)ret; } public double ReadDouble() { var bytes = ReadBytes( 8 ); double ret = BitConverter.ToDouble( bytes, 0 ); #if DEBUG_BINARY_READER Console.WriteLine( "ReadDouble: " + ret ); #endif return ret; } public byte ReadByte() { var c = LoadInfo.ReadByte(); if( c == -1 ) throw new UndumpException("truncated"); #if DEBUG_BINARY_READER Console.WriteLine( "ReadBytes: " + c ); #endif return (byte)c; } public string ReadString() { var n = ReadSizeT(); if( n == 0 ) return null; var bytes = ReadBytes( n ); // n=1: removing trailing '\0' string ret = System.Text.Encoding.ASCII.GetString( bytes, 0, n-1 ); #if DEBUG_BINARY_READER Console.WriteLine( "ReadString n:" + n + " ret:" + ret ); #endif return ret; } } class UndumpException : Exception { public string Why; public UndumpException( string why ) { Why = why; } } public class Undump { private BinaryBytesReader Reader; public static LuaProto LoadBinary( ILuaState lua, ILoadInfo loadinfo, string name ) { try { var reader = new BinaryBytesReader( loadinfo ); var undump = new Undump( reader ); undump.LoadHeader(); return undump.LoadFunction(); } catch( UndumpException e ) { var Lua = (LuaState)lua; Lua.O_PushString( string.Format( "{0}: {1} precompiled chunk", name, e.Why ) ); Lua.D_Throw( ThreadStatus.LUA_ERRSYNTAX ); return null; } } private Undump( BinaryBytesReader reader ) { Reader = reader; } private int LoadInt() { return Reader.ReadInt(); } private byte LoadByte() { return Reader.ReadByte(); } private byte[] LoadBytes( int count ) { return Reader.ReadBytes( count ); } private string LoadString() { return Reader.ReadString(); } private bool LoadBoolean() { return LoadByte() != 0; } private double LoadNumber() { return Reader.ReadDouble(); } private void LoadHeader() { byte[] header = LoadBytes( 4 // Signature + 8 // version, format version, size of int ... etc + 6 // Tail ); byte v = header[ 4 /* skip signature */ + 4 /* offset of sizeof(size_t) */ ]; #if DEBUG_UNDUMP Console.WriteLine(string.Format("sizeof(size_t): {0}", v)); #endif Reader.SizeOfSizeT = v ; } private Instruction LoadInstruction() { return (Instruction)Reader.ReadUInt(); } private LuaProto LoadFunction() { #if DEBUG_UNDUMP Console.WriteLine( "LoadFunction enter" ); #endif LuaProto proto = new LuaProto(); proto.LineDefined = LoadInt(); proto.LastLineDefined = LoadInt(); proto.NumParams = LoadByte(); proto.IsVarArg = LoadBoolean(); proto.MaxStackSize = LoadByte(); LoadCode(proto); LoadConstants(proto); LoadUpvalues(proto); LoadDebug(proto); return proto; } private void LoadCode( LuaProto proto ) { var n = LoadInt(); #if DEBUG_UNDUMP Console.WriteLine( "LoadCode n:" + n ); #endif proto.Code.Clear(); for( int i=0; i