Mercurial Hosting > luan
diff src/luan/lib/PickleCon.java @ 129:486a0641bca4
add pickle client/server;
fix parser bugs;
git-svn-id: https://luan-java.googlecode.com/svn/trunk@130 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Mon, 09 Jun 2014 09:16:16 +0000 |
parents | |
children | 0594c132888b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/lib/PickleCon.java Mon Jun 09 09:16:16 2014 +0000 @@ -0,0 +1,128 @@ +package luan.lib; + +import java.io.OutputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.Set; +import java.util.IdentityHashMap; +import java.util.Collections; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; +import luan.Luan; +import luan.LuanTable; +import luan.LuanState; +import luan.LuanFunction; +import luan.LuanJavaFunction; +import luan.LuanException; + + +public final class PickleCon { + final LuanState luan; + private final DataInputStream in; + private final LuanFunction _read_binary; + private final LuanTable ioModule; + private final DataOutputStream out; + private final List<byte[]> binaries = new ArrayList<byte[]>(); + String src; + + PickleCon(LuanState luan,DataInputStream in,DataOutputStream out) { + this.in = in; + this.luan = luan; + try { + this._read_binary = new LuanJavaFunction( + PickleCon.class.getMethod( "_read_binary", Integer.TYPE ), this + ); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + this.ioModule = (LuanTable)luan.loaded().get("Io"); + + this.out = out; + } + + public byte[] _read_binary(int size) throws IOException, LuanException { + byte[] a = new byte[size]; + int i = 0; + while( i < size ) { + int n = in.read(a,i,size-i); + if( n == -1 ) + throw luan.JAVA.exception( "end of stream" ); + i += n; + } + return a; + } + + public Object read() throws IOException, LuanException { + ioModule.put("_read_binary",_read_binary); + src = in.readUTF(); + LuanFunction fn = BasicLib.load(luan,src,"pickle-reader",true,false); + Object rtn = luan.JAVA.call(fn,null); + ioModule.put("_binaries",null); + return rtn; + } + + public String pickle(Object obj) throws LuanException { + if( obj == null ) + return "nil"; + if( obj instanceof Number ) + return Luan.toString((Number)obj); + if( obj instanceof String ) + return "\"" + Luan.stringEncode((String)obj) + "\""; + if( obj instanceof LuanTable ) + return pickle( (LuanTable)obj, Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) ); + if( obj instanceof byte[] ) { + byte[] a = (byte[])obj; + binaries.add(a); + return "Io._binaries[" + binaries.size() + "]"; + } + throw luan.JAVA.exception( "invalid type: " + obj.getClass() ); + } + + private String pickle(Object obj,Set<LuanTable> set) throws LuanException { + return obj instanceof LuanTable ? pickle((LuanTable)obj,set) : pickle(obj); + } + + private String pickle(LuanTable tbl,Set<LuanTable> set) throws LuanException { + if( !set.add(tbl) ) { + throw luan.JAVA.exception( "circular reference in table" ); + } + StringBuilder sb = new StringBuilder(); + sb.append( "{" ); + for( Map.Entry<Object,Object> entry : tbl ) { + sb.append( "[" ); + sb.append( pickle(entry.getKey(),set) ); + sb.append( "]=" ); + sb.append( pickle(entry.getValue(),set) ); + sb.append( ", " ); + } + sb.append( "}" ); + return sb.toString(); + } + + public void write(Object... args) throws LuanException, IOException { + StringBuilder sb = new StringBuilder(); + if( !binaries.isEmpty() ) { + sb.append( "Io._binaries = {}\n" ); + for( byte[] a : binaries ) { + sb.append( "Io._binaries[#Io._binaries+1] = Io._read_binary(" + a.length + ")\n" ); + } + } + for( Object obj : args ) { + sb.append( luan.JAVA.toString(obj) ); + } + out.writeUTF( sb.toString() ); + for( byte[] a : binaries ) { + out.write(a); + } + out.flush(); + binaries.clear(); + } + + public void close() throws IOException { + in.close(); + out.close(); + } +}