comparison core/src/luan/modules/PickleCon.java @ 171:3dcb0f9bee82

add core component git-svn-id: https://luan-java.googlecode.com/svn/trunk@172 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Sun, 22 Jun 2014 05:41:22 +0000
parents src/luan/modules/PickleCon.java@ebe9db183eb7
children fb3993431f76
comparison
equal deleted inserted replaced
170:7c792a328a83 171:3dcb0f9bee82
1 package luan.modules;
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 final LuanTable ioModule;
27 private final DataOutputStream out;
28 private final List<byte[]> binaries = new ArrayList<byte[]>();
29 String src;
30 private final LuanTable env = new LuanTable();
31
32 PickleCon(LuanState luan,DataInputStream in,DataOutputStream out) {
33 this.in = in;
34 this.luan = luan;
35 try {
36 this._read_binary = new LuanJavaFunction(
37 PickleCon.class.getMethod( "_read_binary", Integer.TYPE ), this
38 );
39 } catch(NoSuchMethodException e) {
40 throw new RuntimeException(e);
41 }
42 this.ioModule = (LuanTable)luan.loaded().get("Io");
43
44 this.out = out;
45 }
46
47 public byte[] _read_binary(int size) throws IOException, LuanException {
48 byte[] a = new byte[size];
49 int i = 0;
50 while( i < size ) {
51 int n = in.read(a,i,size-i);
52 if( n == -1 )
53 throw luan.exception( "end of stream" );
54 i += n;
55 }
56 return a;
57 }
58
59 public Object read() throws IOException, LuanException {
60 ioModule.put("_read_binary",_read_binary);
61 try {
62 src = in.readUTF();
63 LuanFunction fn = BasicLuan.load(luan,src,"pickle-reader",env,false);
64 return luan.call(fn);
65 } finally {
66 ioModule.put("_binaries",null);
67 ioModule.put("_read_binary",null);
68 }
69 }
70
71 public String pickle(Object obj) throws LuanException {
72 if( obj == null )
73 return "nil";
74 if( obj instanceof Boolean )
75 return Luan.toString((Boolean)obj);
76 if( obj instanceof Number )
77 return Luan.toString((Number)obj);
78 if( obj instanceof String )
79 return "\"" + Luan.stringEncode((String)obj) + "\"";
80 if( obj instanceof LuanTable )
81 return pickle( (LuanTable)obj, Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) );
82 if( obj instanceof byte[] ) {
83 byte[] a = (byte[])obj;
84 binaries.add(a);
85 return "Io._binaries[" + binaries.size() + "]";
86 }
87 throw luan.exception( "invalid type: " + obj.getClass() );
88 }
89
90 private String pickle(Object obj,Set<LuanTable> set) throws LuanException {
91 return obj instanceof LuanTable ? pickle((LuanTable)obj,set) : pickle(obj);
92 }
93
94 private String pickle(LuanTable tbl,Set<LuanTable> set) throws LuanException {
95 if( !set.add(tbl) ) {
96 throw luan.exception( "circular reference in table" );
97 }
98 StringBuilder sb = new StringBuilder();
99 sb.append( "{" );
100 for( Map.Entry<Object,Object> entry : tbl ) {
101 sb.append( "[" );
102 sb.append( pickle(entry.getKey(),set) );
103 sb.append( "]=" );
104 sb.append( pickle(entry.getValue(),set) );
105 sb.append( ", " );
106 }
107 sb.append( "}" );
108 return sb.toString();
109 }
110
111 public void write(Object... args) throws LuanException, IOException {
112 StringBuilder sb = new StringBuilder();
113 if( !binaries.isEmpty() ) {
114 sb.append( "Io._binaries = {}\n" );
115 for( byte[] a : binaries ) {
116 sb.append( "Io._binaries[#Io._binaries+1] = Io._read_binary(" + a.length + ")\n" );
117 }
118 }
119 for( Object obj : args ) {
120 sb.append( luan.toString(obj) );
121 }
122 out.writeUTF( sb.toString() );
123 for( byte[] a : binaries ) {
124 out.write(a);
125 }
126 out.flush();
127 binaries.clear();
128 }
129
130 public void close() throws IOException {
131 in.close();
132 out.close();
133 }
134 }