using System; using System.Text; using System.Collections.Generic; namespace UniLua { public enum DumpStatus { OK, ERROR, } public delegate DumpStatus LuaWriter( byte[] bytes, int start, int length ); internal class DumpState { public static DumpStatus Dump( LuaProto proto, LuaWriter writer, bool strip ) { var d = new DumpState(); d.Writer = writer; d.Strip = strip; d.Status = DumpStatus.OK; d.DumpHeader(); d.DumpFunction( proto ); return d.Status; } private LuaWriter Writer; private bool Strip; private DumpStatus Status; private const string LUAC_TAIL = "\u0019\u0093\r\n\u001a\n"; private static int VERSION = (LuaDef.LUA_VERSION_MAJOR[0]-'0') * 16 + (LuaDef.LUA_VERSION_MINOR[0]-'0'); private static int LUAC_HEADERSIZE = LuaConf.LUA_SIGNATURE.Length + 2 + 6 + LUAC_TAIL.Length; private const int FORMAT = 0; private const int ENDIAN = 1; private DumpState() { } private byte[] BuildHeader() { var bytes = new byte[LUAC_HEADERSIZE]; int i = 0; for(var j=0; j { DumpBlock( BitConverter.GetBytes( (uint)ins ) ); }); } private void DumpConstants( LuaProto proto ) { DumpVector( proto.K, (k) => { var t = k.V.Tt; DumpByte( (byte)t ); switch( t ) { case (int)LuaType.LUA_TNIL: break; case (int)LuaType.LUA_TBOOLEAN: DumpBool(k.V.BValue()); break; case (int)LuaType.LUA_TNUMBER: DumpBlock( BitConverter.GetBytes(k.V.NValue) ); break; case (int)LuaType.LUA_TSTRING: DumpString(k.V.SValue()); break; default: Utl.Assert(false); break; } }); DumpVector( proto.P, (p) => { DumpFunction( p ); }); } private void DumpUpvalues( LuaProto proto ) { DumpVector( proto.Upvalues, (upval) => { DumpByte( upval.InStack ? (byte)1 : (byte)0 ); DumpByte( (byte)upval.Index ); }); } private void DumpDebug( LuaProto proto ) { DumpString( Strip ? null : proto.Source ); DumpVector( (Strip ? null : proto.LineInfo), (line) => { DumpInt(line); }); DumpVector( (Strip ? null : proto.LocVars), (locvar) => { DumpString( locvar.VarName ); DumpInt( locvar.StartPc ); DumpInt( locvar.EndPc ); }); DumpVector( (Strip ? null : proto.Upvalues), (upval) => { DumpString( upval.Name ); }); } private void DumpFunction( LuaProto proto ) { DumpInt( proto.LineDefined ); DumpInt( proto.LastLineDefined ); DumpByte( (byte)proto.NumParams ); DumpByte( proto.IsVarArg ? (byte)1 : (byte)0 ); DumpByte( (byte)proto.MaxStackSize ); DumpCode( proto ); DumpConstants( proto ); DumpUpvalues( proto ); DumpDebug( proto ); } private delegate void DumpItemDelegate( T item ); private void DumpVector( IList list, DumpItemDelegate dumpItem ) { if( list == null ) { DumpInt( 0 ); } else { DumpInt( list.Count ); for( var i=0; i