comparison 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
comparison
equal deleted inserted replaced
128:f0a4abe58593 129:486a0641bca4
1 package luan.lib;
2
3 import java.io.OutputStream;
4 import java.io.BufferedOutputStream;
5 import java.io.DataInputStream;
6 import java.io.DataOutputStream;
7 import java.io.IOException;
8 import java.util.Set;
9 import java.util.IdentityHashMap;
10 import java.util.Collections;
11 import java.util.Map;
12 import java.util.List;
13 import java.util.ArrayList;
14 import luan.Luan;
15 import luan.LuanTable;
16 import luan.LuanState;
17 import luan.LuanFunction;
18 import luan.LuanJavaFunction;
19 import luan.LuanException;
20
21
22 public final class PickleCon {
23 final LuanState luan;
24 private final DataInputStream in;
25 private final LuanFunction _read_binary;
26 private final LuanTable ioModule;
27 private final DataOutputStream out;
28 private final List<byte[]> binaries = new ArrayList<byte[]>();
29 String src;
30
31 PickleCon(LuanState luan,DataInputStream in,DataOutputStream out) {
32 this.in = in;
33 this.luan = luan;
34 try {
35 this._read_binary = new LuanJavaFunction(
36 PickleCon.class.getMethod( "_read_binary", Integer.TYPE ), this
37 );
38 } catch(NoSuchMethodException e) {
39 throw new RuntimeException(e);
40 }
41 this.ioModule = (LuanTable)luan.loaded().get("Io");
42
43 this.out = out;
44 }
45
46 public byte[] _read_binary(int size) throws IOException, LuanException {
47 byte[] a = new byte[size];
48 int i = 0;
49 while( i < size ) {
50 int n = in.read(a,i,size-i);
51 if( n == -1 )
52 throw luan.JAVA.exception( "end of stream" );
53 i += n;
54 }
55 return a;
56 }
57
58 public Object read() throws IOException, LuanException {
59 ioModule.put("_read_binary",_read_binary);
60 src = in.readUTF();
61 LuanFunction fn = BasicLib.load(luan,src,"pickle-reader",true,false);
62 Object rtn = luan.JAVA.call(fn,null);
63 ioModule.put("_binaries",null);
64 return rtn;
65 }
66
67 public String pickle(Object obj) throws LuanException {
68 if( obj == null )
69 return "nil";
70 if( obj instanceof Number )
71 return Luan.toString((Number)obj);
72 if( obj instanceof String )
73 return "\"" + Luan.stringEncode((String)obj) + "\"";
74 if( obj instanceof LuanTable )
75 return pickle( (LuanTable)obj, Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) );
76 if( obj instanceof byte[] ) {
77 byte[] a = (byte[])obj;
78 binaries.add(a);
79 return "Io._binaries[" + binaries.size() + "]";
80 }
81 throw luan.JAVA.exception( "invalid type: " + obj.getClass() );
82 }
83
84 private String pickle(Object obj,Set<LuanTable> set) throws LuanException {
85 return obj instanceof LuanTable ? pickle((LuanTable)obj,set) : pickle(obj);
86 }
87
88 private String pickle(LuanTable tbl,Set<LuanTable> set) throws LuanException {
89 if( !set.add(tbl) ) {
90 throw luan.JAVA.exception( "circular reference in table" );
91 }
92 StringBuilder sb = new StringBuilder();
93 sb.append( "{" );
94 for( Map.Entry<Object,Object> entry : tbl ) {
95 sb.append( "[" );
96 sb.append( pickle(entry.getKey(),set) );
97 sb.append( "]=" );
98 sb.append( pickle(entry.getValue(),set) );
99 sb.append( ", " );
100 }
101 sb.append( "}" );
102 return sb.toString();
103 }
104
105 public void write(Object... args) throws LuanException, IOException {
106 StringBuilder sb = new StringBuilder();
107 if( !binaries.isEmpty() ) {
108 sb.append( "Io._binaries = {}\n" );
109 for( byte[] a : binaries ) {
110 sb.append( "Io._binaries[#Io._binaries+1] = Io._read_binary(" + a.length + ")\n" );
111 }
112 }
113 for( Object obj : args ) {
114 sb.append( luan.JAVA.toString(obj) );
115 }
116 out.writeUTF( sb.toString() );
117 for( byte[] a : binaries ) {
118 out.write(a);
119 }
120 out.flush();
121 binaries.clear();
122 }
123
124 public void close() throws IOException {
125 in.close();
126 out.close();
127 }
128 }