rserve-client 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +1 -2
- data/.gitignore +1 -0
- data/History.txt +15 -2
- data/Manifest.txt +8 -0
- data/README.txt +41 -19
- data/lib/rserve.rb +1 -1
- data/lib/rserve/connection.rb +152 -69
- data/lib/rserve/engine.rb +9 -9
- data/lib/rserve/packet.rb +2 -2
- data/lib/rserve/protocol.rb +51 -46
- data/lib/rserve/protocol/rexpfactory.rb +659 -366
- data/lib/rserve/rexp.rb +175 -156
- data/lib/rserve/rexp/double.rb +45 -38
- data/lib/rserve/rexp/environment.rb +40 -0
- data/lib/rserve/rexp/expressionvector.rb +9 -0
- data/lib/rserve/rexp/genericvector.rb +5 -3
- data/lib/rserve/rexp/integer.rb +38 -38
- data/lib/rserve/rexp/language.rb +2 -2
- data/lib/rserve/rexp/list.rb +3 -0
- data/lib/rserve/rexp/logical.rb +17 -4
- data/lib/rserve/rexp/null.rb +20 -14
- data/lib/rserve/rexp/raw.rb +19 -0
- data/lib/rserve/rexp/reference.rb +42 -0
- data/lib/rserve/rexp/s4.rb +10 -0
- data/lib/rserve/rexp/string.rb +5 -3
- data/lib/rserve/rexp/symbol.rb +3 -0
- data/lib/rserve/rexp/vector.rb +30 -15
- data/lib/rserve/rexp/wrapper.rb +58 -0
- data/lib/rserve/rfactor.rb +10 -10
- data/lib/rserve/rlist.rb +129 -100
- data/lib/rserve/talk.rb +61 -61
- data/spec/rserve_connection_spec.rb +99 -33
- data/spec/rserve_double_spec.rb +28 -15
- data/spec/rserve_integer_spec.rb +24 -15
- data/spec/rserve_logical_spec.rb +21 -12
- data/spec/rserve_protocol_spec.rb +7 -7
- data/spec/rserve_rexp_spec.rb +3 -3
- data/spec/rserve_rexp_wrapper_spec.rb +36 -0
- data/spec/rserve_rexpfactory_spec.rb +86 -20
- data/spec/rserve_rfactor_spec.rb +2 -2
- data/spec/rserve_rlist_spec.rb +53 -0
- data/spec/rserve_spec.rb +8 -5
- data/spec/rserve_talk_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -0
- metadata +13 -3
- metadata.gz.sig +0 -0
data/lib/rserve/engine.rb
CHANGED
@@ -14,27 +14,27 @@ module Rserve
|
|
14
14
|
evaluate(p,where,resolve)
|
15
15
|
end
|
16
16
|
def close;
|
17
|
-
|
17
|
+
false
|
18
18
|
end
|
19
19
|
def supports_references?
|
20
|
-
|
20
|
+
false
|
21
21
|
end
|
22
22
|
def supports_enviroments?
|
23
|
-
|
23
|
+
false
|
24
24
|
end
|
25
25
|
def supports_REPL?
|
26
|
-
|
26
|
+
false
|
27
27
|
end
|
28
28
|
def suuports_locking?
|
29
|
-
|
29
|
+
false
|
30
30
|
end
|
31
31
|
def try_lock
|
32
|
-
|
32
|
+
0
|
33
33
|
end
|
34
34
|
def lock
|
35
|
-
|
35
|
+
0
|
36
36
|
end
|
37
37
|
def unlock;end;
|
38
|
-
|
38
|
+
|
39
39
|
end
|
40
|
-
end
|
40
|
+
end
|
data/lib/rserve/packet.rb
CHANGED
@@ -2,11 +2,11 @@ module Rserve
|
|
2
2
|
class Packet
|
3
3
|
attr_reader :cont
|
4
4
|
attr_reader :cmd
|
5
|
-
|
5
|
+
|
6
6
|
ERROR_DESCRIPTIONS={
|
7
7
|
2=>'Invalid expression',
|
8
8
|
127=>'Unknown variable/method'}
|
9
|
-
|
9
|
+
|
10
10
|
def initialize(cmd, cont)
|
11
11
|
raise "cont [#{cont.class} - #{cont.to_s}] should respond to :length" if !cont.nil? and !cont.respond_to? :length
|
12
12
|
@cmd=cmd
|
data/lib/rserve/protocol.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
module Rserve
|
2
2
|
#
|
3
|
-
# This module encapsulates methods and constants related to QAP1 protocol used by Rserv. Follows almost exactly the interface on RTalk class
|
3
|
+
# This module encapsulates methods and constants related to QAP1 protocol used by Rserv. Follows almost exactly the interface on RTalk class
|
4
4
|
# on Java version, except for use of undescores instead of CamelCase
|
5
5
|
# Implementation could differ if a cleaner/faster ruby version is available
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# Policy: No other class should know about the internal of protocol!
|
8
8
|
# See Rtalk class on Java version.
|
9
9
|
module Protocol
|
10
10
|
# Defines from Rsrv.h
|
11
11
|
CMD_RESP=0x010000 # all responses have this flag set
|
12
|
-
RESP_OK=(CMD_RESP|0x0001) # command succeeded; returned parameters depend on the command issued
|
12
|
+
RESP_OK=(CMD_RESP|0x0001) # command succeeded; returned parameters depend on the command issued
|
13
13
|
RESP_ERR=(CMD_RESP|0x0002) # command failed, check stats code attached string may describe the error
|
14
14
|
ERR_auth_failed=0x41 # auth.failed or auth.requested but no login came. in case of authentification failure due to name/pwd mismatch, server may send CMD_accessDenied instead
|
15
15
|
ERR_conn_broken=0x42 # connection closed or broken packet killed it */
|
@@ -21,41 +21,41 @@ module Rserve
|
|
21
21
|
|
22
22
|
|
23
23
|
ERR_notOpen=0x47 # attempt to perform fileRead/Write on closed file */
|
24
|
-
ERR_accessDenied=0x48 # this answer is also valid on CMD_login; otherwise it's sent if the server deosn;t allow the user to issue the specified command. (e.g. some server admins may block file I/O operations for some users)
|
24
|
+
ERR_accessDenied=0x48 # this answer is also valid on CMD_login; otherwise it's sent if the server deosn;t allow the user to issue the specified command. (e.g. some server admins may block file I/O operations for some users)
|
25
25
|
ERR_unsupportedCmd=0x49 # unsupported command */
|
26
26
|
ERR_unknownCmd=0x4a # unknown command - the difference between unsupported and unknown is that unsupported commands are known to the server but for some reasons (e.g. platform dependent) it's not supported. unknown commands are simply not recognized by the server at all. */
|
27
27
|
ERR_data_overflow=0x4b # incoming packet is too big. currently there is a limit as of the size of an incoming packet. */
|
28
|
-
ERR_object_too_big=0x4c # the requested object is too big to be transported in that way. If received after CMD_eval then the evaluation itself was successful. optional parameter is the size of the object
|
29
|
-
ERR_out_of_mem=0x4d # out of memory. the connection is usually closed after this error was sent
|
30
|
-
ERR_ctrl_closed=0x4e # control pipe to the master process is closed or broken
|
28
|
+
ERR_object_too_big=0x4c # the requested object is too big to be transported in that way. If received after CMD_eval then the evaluation itself was successful. optional parameter is the size of the object
|
29
|
+
ERR_out_of_mem=0x4d # out of memory. the connection is usually closed after this error was sent
|
30
|
+
ERR_ctrl_closed=0x4e # control pipe to the master process is closed or broken
|
31
31
|
ERR_session_busy=0x50 # session is still busy */
|
32
32
|
ERR_detach_failed=0x51 # unable to detach session (cannot determine peer IP or problems creating a listening socket for resume) */
|
33
|
-
|
34
|
-
|
33
|
+
|
34
|
+
|
35
35
|
CMD_login=0x001 # "name\npwd" : - */
|
36
36
|
CMD_voidEval=0x002 # string : - */
|
37
37
|
CMD_eval=0x003 # string : encoded SEXP */
|
38
38
|
CMD_shutdown=0x004 # [admin-pwd] : - */
|
39
|
-
|
39
|
+
|
40
40
|
#/* file I/O routines. server may answe */
|
41
41
|
CMD_openFile=0x010 # fn : - */
|
42
42
|
CMD_createFile=0x011 # fn : - */
|
43
43
|
CMD_closeFile=0x012 # - : - */
|
44
44
|
CMD_readFile=0x013 # [int size] : data... ; if size not present,
|
45
|
-
|
46
|
-
|
45
|
+
#server is free to choose any value - usually
|
46
|
+
#it uses the size of its static buffer */
|
47
47
|
CMD_writeFile=0x014 # data : - */
|
48
48
|
CMD_removeFile=0x015 # fn : - */
|
49
|
-
|
49
|
+
|
50
50
|
# /* object manipulation */
|
51
51
|
CMD_setSEXP=0x020 # string(name), REXP : - */
|
52
52
|
CMD_assignSEXP=0x021 # string(name), REXP : - ; same as setSEXP except that the name is parsed */
|
53
|
-
|
53
|
+
|
54
54
|
# /* session management (since 0.4-0) */
|
55
55
|
CMD_detachSession=0x030 # : session key */
|
56
56
|
CMD_detachedVoidEval=0x031 # string : session key; doesn't */
|
57
|
-
CMD_attachSession=0x032 # session key : - */
|
58
|
-
|
57
|
+
CMD_attachSession=0x032 # session key : - */
|
58
|
+
|
59
59
|
# control commands (since 0.6-0) - passed on to the master process */
|
60
60
|
# Note: currently all control commands are asychronous, i.e. RESP_OK
|
61
61
|
# indicates that the command was enqueued in the master pipe, but there
|
@@ -68,21 +68,21 @@ module Rserve
|
|
68
68
|
CMD_ctrlEval=0x42 # string : - */
|
69
69
|
CMD_ctrlSource=0x45 # string : - */
|
70
70
|
CMD_ctrlShutdown=0x44 # - : - */
|
71
|
-
|
71
|
+
|
72
72
|
# /* 'internal' commands (since 0.1-9) */
|
73
73
|
CMD_setBufferSize=0x081 # [int sendBufSize] this commad allow clients to request bigger buffer sizes if large data is to be transported from Rserve to the client. (incoming buffer is resized automatically) */
|
74
74
|
CMD_setEncoding=0x082 # string (one of "native","latin1","utf8") : -; since 0.5-3 */
|
75
|
-
|
75
|
+
|
76
76
|
# /* special commands - the payload of packages with this mask does not contain defined parameters */
|
77
|
-
|
77
|
+
|
78
78
|
CMD_SPECIAL_MASK=0xf0
|
79
|
-
|
79
|
+
|
80
80
|
CMD_serEval=0xf5 # serialized eval - the packets are raw serialized data without data header */
|
81
81
|
CMD_serAssign=0xf6 # serialized assign - serialized list with [[1]]=name, [[2]]=value */
|
82
82
|
CMD_serEEval=0xf7 # serialized expression eval - like serEval with one additional evaluation round */
|
83
|
-
|
84
|
-
# data types for the transport protocol (QAP1)do NOT confuse with XT_.. values.
|
85
|
-
|
83
|
+
|
84
|
+
# data types for the transport protocol (QAP1)do NOT confuse with XT_.. values.
|
85
|
+
|
86
86
|
DT_INT=1 # int */
|
87
87
|
DT_CHAR=2 # char */
|
88
88
|
DT_DOUBLE=3 # double */
|
@@ -110,8 +110,8 @@ module Rserve
|
|
110
110
|
ERR_session_busy=>"session still busy",
|
111
111
|
ERR_detach_failed=>"unable to detach seesion"
|
112
112
|
} # error descriptions
|
113
|
-
|
114
|
-
|
113
|
+
|
114
|
+
|
115
115
|
# writes bit-wise int to a byte buffer at specified position in Intel-endian form
|
116
116
|
# Internal: byte buffer will be the result of unpack("CCCC") an integer.
|
117
117
|
# @param v value to be written
|
@@ -123,7 +123,7 @@ module Rserve
|
|
123
123
|
buf[o]=((v&0xff0000)>>16); o+=1
|
124
124
|
buf[o]=((v&0xff000000)>>24);
|
125
125
|
end
|
126
|
-
|
126
|
+
|
127
127
|
# writes cmd/resp/type byte + 3/7 bytes len into a byte buffer at specified offset.
|
128
128
|
# @param ty type/cmd/resp byte
|
129
129
|
# @param len length
|
@@ -145,58 +145,63 @@ module Rserve
|
|
145
145
|
end
|
146
146
|
# creates a new header according to the type and length of the parameter
|
147
147
|
# @param ty type/cmd/resp byte
|
148
|
-
# @param len length
|
148
|
+
# @param len length
|
149
149
|
def new_hdr(ty, len)
|
150
150
|
hdr=Array.new( (len>0xfffff0)?8:4)
|
151
151
|
set_hdr(ty,len,hdr,0);
|
152
152
|
hdr
|
153
153
|
end
|
154
|
-
#
|
154
|
+
#
|
155
155
|
# converts bit-wise stored int in Intel-endian form into ruby int
|
156
156
|
#
|
157
157
|
# @param buf buffer containg the representation
|
158
158
|
# @param o offset where to start (4 bytes will be used)
|
159
159
|
# @return the int value. no bounds checking is done so you need to
|
160
|
-
# make sure that the buffer is big enough
|
161
|
-
|
162
|
-
def get_int(buf, o)
|
163
|
-
return buf.slice(o,4).pack("C*").unpack("
|
164
|
-
|
160
|
+
# make sure that the buffer is big enough
|
161
|
+
|
162
|
+
def get_int(buf, o)
|
163
|
+
#return buf.slice(o,4).pack("C*").unpack("i")[0]
|
164
|
+
return ((buf[o]&255)|((buf[o+1]&255)<<8)|((buf[o+2]&255)<<16)|((buf[o+3]&255)<<24));
|
165
165
|
end
|
166
|
-
|
166
|
+
|
167
167
|
# converts bit-wise stored length from a header. "long" format is supported up to 32-bit
|
168
168
|
# @param buf buffer
|
169
169
|
# @param o offset of the header (length is at o+1)
|
170
170
|
# @return length */
|
171
|
-
def get_len(buf, o)
|
172
|
-
# // "long" format; still - we support 32-bit only
|
171
|
+
def get_len(buf, o)
|
172
|
+
# // "long" format; still - we support 32-bit only
|
173
173
|
if ((buf[o]&64)>0)
|
174
|
+
#p "buf:#{buf} --- o: #{o} -- [#{buf[o+4]}]"
|
175
|
+
raise "Buffer without enough values" if buf[o+4].nil?
|
174
176
|
(buf[o+1]&255)|((buf[o+2]&255)<<8)|((buf[o+3]&255)<<16)|((buf[o+4]&255)<<24)
|
175
177
|
else
|
176
178
|
(buf[o+1]&255)|((buf[o+2]&255)<<8)|((buf[o+3]&255)<<16)
|
177
179
|
end
|
178
180
|
end
|
179
|
-
|
181
|
+
|
180
182
|
# converts bit-wise Intel-endian format into long
|
181
183
|
# @param buf buffer
|
182
184
|
# @param o offset (8 bytes will be used)
|
183
185
|
# @return long value */
|
184
|
-
def get_long(buf, o)
|
186
|
+
def get_long(buf, o)
|
185
187
|
low=(get_int(buf,o))&0xffffffff;
|
186
188
|
hi=(get_int(buf,o+4))&0xffffffff;
|
187
189
|
hi<<=32; hi|=low;
|
188
190
|
hi
|
189
191
|
end
|
190
192
|
def longBitsToDouble(bits)
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
193
|
+
s = ((bits >> 63) == 0) ? 1 : -1;
|
194
|
+
e = ((bits >> 52) & 0x7ff)
|
195
|
+
m = (e == 0) ?
|
196
|
+
(bits & 0xfffffffffffff) << 1 :
|
197
|
+
(bits & 0xfffffffffffff) | 0x10000000000000;
|
198
|
+
s*m*2**(e-1075)
|
199
|
+
end
|
200
|
+
def doubleToRawLongBits(double)
|
201
|
+
[double].pack("d").unpack("Q")[0]
|
197
202
|
end
|
198
|
-
def set_long(l, buf, o)
|
199
|
-
set_int((l&0xffffffff),buf,o)
|
203
|
+
def set_long(l, buf, o)
|
204
|
+
set_int((l&0xffffffff), buf, o)
|
200
205
|
set_int((l>>32),buf,o+4)
|
201
206
|
end
|
202
207
|
end
|
@@ -2,403 +2,696 @@ module Rserve
|
|
2
2
|
module Protocol
|
3
3
|
# representation of R-eXpressions in Ruby
|
4
4
|
class REXPFactory
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
5
|
+
include Rserve::Protocol
|
6
|
+
# xpression type: NULL
|
7
|
+
XT_NULL=0;
|
8
|
+
# xpression type: integer
|
9
|
+
XT_INT=1;
|
10
|
+
# xpression type: double
|
11
|
+
XT_DOUBLE=2;
|
12
|
+
# xpression type: String
|
13
|
+
XT_STR=3;
|
14
|
+
# xpression type: language construct (currently content is same as list)
|
15
|
+
XT_LANG=4;
|
16
|
+
# xpression type: symbol (content is symbol name: String)
|
17
|
+
XT_SYM=5;
|
18
|
+
# xpression type: RBool
|
19
|
+
XT_BOOL=6;
|
20
|
+
# xpression type: S4 object
|
21
|
+
#@since Rserve 0.5
|
22
|
+
XT_S4=7;
|
23
|
+
# xpression type: generic vector (RList)
|
24
|
+
XT_VECTOR=16;
|
25
|
+
# xpression type: dotted-pair list (RList)
|
26
|
+
XT_LIST=17;
|
27
|
+
# xpression type: closure (there is no java class for that type (yet?). currently the body of the closure is stored in the content part of the REXP. Please note that this may change in the future!)
|
28
|
+
XT_CLOS=18;
|
29
|
+
# xpression type: symbol name
|
30
|
+
# @since Rserve 0.5
|
31
|
+
XT_SYMNAME=19;
|
32
|
+
# xpression type: dotted-pair list (w/o tags)
|
33
|
+
# @since Rserve 0.5
|
34
|
+
XT_LIST_NOTAG=20;
|
35
|
+
# xpression type: dotted-pair list (w tags)
|
36
|
+
# @since Rserve 0.5
|
37
|
+
XT_LIST_TAG=21;
|
38
|
+
# xpression type: language list (w/o tags)
|
39
|
+
# @since Rserve 0.5
|
40
|
+
XT_LANG_NOTAG=22;
|
41
|
+
# xpression type: language list (w tags)
|
42
|
+
# @since Rserve 0.5
|
43
|
+
XT_LANG_TAG=23;
|
44
|
+
# xpression type: expression vector
|
45
|
+
XT_VECTOR_EXP=26;
|
46
|
+
# xpression type: string vector
|
47
|
+
XT_VECTOR_STR=27;
|
48
|
+
# xpression type: int[]
|
49
|
+
XT_ARRAY_INT=32;
|
50
|
+
# xpression type: double[]
|
51
|
+
XT_ARRAY_DOUBLE=33;
|
52
|
+
# xpression type: String[] (currently not used, Vector is used instead)
|
53
|
+
XT_ARRAY_STR=34;
|
54
|
+
# internal use only! this constant should never appear in a REXP
|
55
|
+
XT_ARRAY_BOOL_UA=35;
|
56
|
+
# xpression type: RBool[]
|
57
|
+
XT_ARRAY_BOOL=36;
|
58
|
+
# xpression type: raw (byte[])
|
59
|
+
# @since Rserve 0.4-?
|
60
|
+
XT_RAW=37;
|
61
|
+
# xpression type: Complex[]
|
62
|
+
# @since Rserve 0.5
|
63
|
+
XT_ARRAY_CPLX=38;
|
64
|
+
# xpression type: unknown; no assumptions can be made about the content
|
65
|
+
XT_UNKNOWN=48;
|
66
|
+
# xpression type: RFactor; this XT is internally generated (ergo is does not come from Rsrv.h) to support RFactor class which is built from XT_ARRAY_INT
|
67
|
+
XT_FACTOR=127;
|
68
|
+
# used for transport only - has attribute
|
69
|
+
XT_HAS_ATTR=128;
|
70
|
+
|
71
|
+
|
72
|
+
attr_reader :type, :attr, :cont, :root_list
|
73
|
+
def get_REXP
|
74
|
+
@cont
|
75
|
+
end
|
76
|
+
def get_attr
|
77
|
+
attr.nil? ? nil : attr.cont
|
78
|
+
end
|
79
|
+
def sexp_mismatch(type)
|
80
|
+
STDERR.puts("Warning: #{type} SEXP size mismatch")
|
81
|
+
end
|
82
|
+
def initialize(*args)
|
83
|
+
if args.size==0
|
84
|
+
|
85
|
+
elsif
|
86
|
+
r=args[0]
|
87
|
+
r=Rserve::REXP::Null if r.nil?
|
88
|
+
a=r.attr
|
89
|
+
@cont=r
|
90
|
+
@attr=REXPFactory.new(a) if !a.nil?
|
91
|
+
if r.is_a? REXP::Null
|
92
|
+
@type=XT_NULL
|
93
|
+
elsif r.is_a? REXP::List
|
94
|
+
l=r.as_list
|
95
|
+
@type=l.named? ? XT_LIST_TAG : XT_LIST_NOTAG
|
96
|
+
if r.is_a? REXP::Language
|
97
|
+
@type = (@type==XT_LIST_TAG) ? XT_LANG_TAG : XT_LANG_NOTAG;
|
98
|
+
end
|
99
|
+
elsif r.is_a? REXP::GenericVector
|
100
|
+
@type = XT_VECTOR; # FIXME: may have to adjust names attr
|
101
|
+
elsif r.is_a? REXP::S4
|
102
|
+
@type = XT_S4
|
103
|
+
elsif r.is_a? REXP::Integer
|
104
|
+
@type = XT_ARRAY_INT
|
105
|
+
elsif r.is_a? REXP::Double
|
106
|
+
@type = XT_ARRAY_DOUBLE
|
107
|
+
elsif r.is_a? REXP::String
|
108
|
+
@type = XT_ARRAY_STR
|
109
|
+
elsif r.is_a? REXP::Symbol
|
110
|
+
@type = XT_SYMNAME
|
111
|
+
elsif r.is_a? REXP::Raw
|
112
|
+
@type = XT_RAW
|
113
|
+
elsif r.is_a? REXP::Logical
|
114
|
+
@type = XT_ARRAY_BOOL
|
115
|
+
else
|
116
|
+
raise ArgumentError("***REXPFactory unable to interpret #{r}")
|
117
|
+
end
|
77
118
|
end
|
78
|
-
|
79
|
-
|
119
|
+
end
|
120
|
+
def parse_REXP(buf,o)
|
121
|
+
puts "buffer:#{buf.to_s} | o= #{o}" if $DEBUG
|
122
|
+
|
123
|
+
xl=get_len(buf,o)
|
124
|
+
has_at = (buf[o]&128)!=0
|
125
|
+
is_long = (buf[o]&64 )!=0
|
126
|
+
xt = buf[o]&63
|
127
|
+
o+=4 if is_long
|
128
|
+
o+=4
|
129
|
+
eox=o+xl
|
130
|
+
@type=xt
|
131
|
+
|
132
|
+
@attr=REXPFactory.new()
|
133
|
+
@cont=nil
|
134
|
+
o = attr.parse_REXP(buf,o) if has_at
|
135
|
+
|
136
|
+
puts "REXP: #{xt_name(@type)}(#{@type})[#{xl}], attr?:#{has_at}, attr=[#{get_attr}]" if $DEBUG
|
137
|
+
|
138
|
+
|
139
|
+
if xt==XT_NULL
|
140
|
+
@cont=REXP::Null.new(get_attr)
|
141
|
+
return o
|
80
142
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
@attr=Factory.new(a) if !a.nil?
|
89
|
-
if r.is_a? REXP::Null
|
90
|
-
@type=XT_NULL
|
91
|
-
elsif r.is_a? REXP::List
|
92
|
-
l=r.as_list
|
93
|
-
@type=l.named? ? XT_LIST_TAG : XT_LIST_NOTAG
|
94
|
-
if r.is_a? REXPLanguage
|
95
|
-
@type = (@type==XT_LIST_TAG) ? XT_LANG_TAG : XT_LANG_NOTAG;
|
96
|
-
end
|
97
|
-
elsif r.is_a? REXP::GenericVector
|
98
|
-
@type = XT_VECTOR; # FIXME: may have to adjust names attr
|
99
|
-
elsif r.is_a? REXP::S4
|
100
|
-
@type = XT_S4
|
101
|
-
elsif r.is_a? REXP::Integer
|
102
|
-
@type = XT_ARRAY_INT
|
103
|
-
elsif r.is_a? REXP::Double
|
104
|
-
@type = XT_ARRAY_DOUBLE
|
105
|
-
elsif r.is_a? REXP::String
|
106
|
-
@type = XT_ARRAY_STRING
|
107
|
-
elsif r.is_a? REXP::Symbol
|
108
|
-
@type = XT_SYMNAME
|
109
|
-
elsif r.is_a? REXP::Raw
|
110
|
-
@type = XT_RAW
|
111
|
-
elsif r.is_a? REXP::Logical
|
112
|
-
@type = XT_ARRAY_BOOL
|
113
|
-
else
|
114
|
-
raise ArgumentError("***REXPFactory unable to interpret #{r}")
|
115
|
-
end
|
143
|
+
if xt==XT_DOUBLE
|
144
|
+
lr=get_long(buf,o)
|
145
|
+
d=[longBitsToDouble(lr)]
|
146
|
+
o+=8
|
147
|
+
if(o!=eox)
|
148
|
+
sexp_mismatch("double")
|
149
|
+
o=eox
|
116
150
|
end
|
151
|
+
@cont=REXP::Double.new(d,get_attr)
|
152
|
+
return o
|
117
153
|
end
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
o+=4 if is_long
|
125
|
-
o+=4
|
126
|
-
eox=o+xl
|
127
|
-
@type=xt
|
128
|
-
|
129
|
-
@attr=REXPFactory.new()
|
130
|
-
@cont=nil
|
131
|
-
|
132
|
-
o=attr.parse_REXP(buf,o) if has_at
|
133
|
-
|
134
|
-
if xt==XT_NULL
|
135
|
-
@cont=REXP::Null.new(get_attr)
|
136
|
-
return o
|
137
|
-
end
|
138
|
-
if xt==XT_DOUBLE
|
139
|
-
lr=get_long(buf,o)
|
140
|
-
d=[longBitsToDouble(lr)]
|
154
|
+
if xt==XT_ARRAY_DOUBLE
|
155
|
+
as=(eox-o).quo(8)
|
156
|
+
i=0
|
157
|
+
d=Array.new(as)
|
158
|
+
while(o<eox)
|
159
|
+
d[i]=longBitsToDouble(get_long(buf,o))
|
141
160
|
o+=8
|
142
|
-
|
143
|
-
sexp_mismatch("double")
|
144
|
-
o=eox
|
145
|
-
end
|
146
|
-
@cont=REXP::Double.new(d,get_attr)
|
147
|
-
return o
|
148
|
-
end
|
149
|
-
if xt==XT_ARRAY_DOUBLE
|
150
|
-
as=(eox-o).quo(8)
|
151
|
-
i=0
|
152
|
-
d=Array.new(as)
|
153
|
-
while(o<eox)
|
154
|
-
d[i]=longBitsToDouble(get_long(buf,o))
|
155
|
-
o+=8
|
156
|
-
i+=1
|
157
|
-
end
|
158
|
-
if(o!=eox)
|
159
|
-
sexp_mismatch("double")
|
160
|
-
o=eox
|
161
|
-
end
|
162
|
-
@cont=REXP::Double.new(d,get_attr)
|
163
|
-
return o
|
161
|
+
i+=1
|
164
162
|
end
|
165
|
-
if
|
166
|
-
|
167
|
-
|
168
|
-
b[0]=REXP::Logical::NA
|
169
|
-
end
|
170
|
-
@cont=REXP::Logical.new(b,get_attr)
|
171
|
-
o+=1
|
172
|
-
return o
|
163
|
+
if(o!=eox)
|
164
|
+
sexp_mismatch("double")
|
165
|
+
o=eox
|
173
166
|
end
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
167
|
+
@cont=REXP::Double.new(d,get_attr)
|
168
|
+
return o
|
169
|
+
end
|
170
|
+
if xt==XT_BOOL
|
171
|
+
b=[buf[o]]
|
172
|
+
b[0]=REXP::Logical::NA if (b[0]!=0 && b[0]!=1)
|
173
|
+
@cont=REXP::Logical.new(b,get_attr)
|
174
|
+
o+=1
|
175
|
+
if(o!=eox)
|
176
|
+
sexp_mismatch("Warning: bool SEXP size mismatch\n") if (eox!=o+3) # o+3 could happen if the result was aligned (1 byte data + 3 bytes padding)
|
179
177
|
o=eox
|
178
|
+
end
|
179
|
+
return o
|
180
|
+
end
|
181
|
+
if xt==XT_ARRAY_BOOL_UA
|
182
|
+
as=(eox-o)
|
183
|
+
i=0
|
184
|
+
d=Array.new(as)
|
185
|
+
(eox-i).times {|i| d[i]=buf[o+i]}
|
186
|
+
o=eox
|
180
187
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
+
d.length.each {|j|
|
189
|
+
if d[j]!=0 and d[j]!=1
|
190
|
+
d[j]==REXP::Logical::NA
|
191
|
+
end
|
192
|
+
}
|
193
|
+
@cont=REXP::Logical.new(d,get_attr)
|
194
|
+
return o
|
195
|
+
end
|
196
|
+
if xt==XT_ARRAY_BOOL
|
197
|
+
as=get_int(buf, o)
|
198
|
+
o+=4
|
199
|
+
d=Array.new(as)
|
200
|
+
as.times {|i| d[i]=buf[o+i]}
|
201
|
+
d.collect! {|v|
|
202
|
+
if v!=0 and v!=1
|
203
|
+
REXP::Logical::NA
|
204
|
+
else
|
205
|
+
v
|
206
|
+
end
|
207
|
+
}
|
208
|
+
o=eox
|
209
|
+
@cont=REXP::Logical.new(d,get_attr)
|
210
|
+
return o
|
211
|
+
end
|
212
|
+
if xt==XT_INT
|
213
|
+
i=Array.new(get_int(buf,o))
|
214
|
+
@cont=REXP::Integer.new(i,get_attr)
|
215
|
+
o+=4
|
216
|
+
if o!=eox
|
217
|
+
$STDERR.puts "int SEXP size mismatch"
|
218
|
+
o=eox
|
188
219
|
end
|
189
|
-
|
190
|
-
|
220
|
+
return o
|
221
|
+
end
|
222
|
+
|
223
|
+
if xt==XT_ARRAY_INT
|
224
|
+
as=(eox-o).quo(4)
|
225
|
+
i=0
|
226
|
+
d=Array.new(as)
|
227
|
+
while(o<eox)
|
228
|
+
d[i]=get_int(buf,o)
|
191
229
|
o+=4
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
REXP::Logical::NA
|
197
|
-
else
|
198
|
-
v
|
199
|
-
end
|
200
|
-
}
|
230
|
+
i+=1
|
231
|
+
end
|
232
|
+
if o!=eox
|
233
|
+
$STDERR.puts "int SEXP size mismatch"
|
201
234
|
o=eox
|
202
|
-
@cont=REXP::Logical.new(d,get_attr)
|
203
|
-
return o
|
204
235
|
end
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
236
|
+
|
237
|
+
# hack for factors
|
238
|
+
if (!get_attr.nil?)
|
239
|
+
ca = get_attr().as_list().at("class");
|
240
|
+
ls = get_attr().as_list().at("levels");
|
241
|
+
if (!ca.nil? and !ls.nil? and ca.as_string=="factor")
|
242
|
+
# R uses 1-based index, Java (and Ruby) uses 0-based one
|
243
|
+
@cont = REXP::Factor.new(d, ls.as_strings(), get_attr)
|
244
|
+
xt = XT_FACTOR;
|
212
245
|
end
|
213
|
-
return o
|
214
246
|
end
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
while(o<eox)
|
221
|
-
d[i]=get_int(buf,o)
|
222
|
-
o+=4
|
223
|
-
i+=1
|
224
|
-
end
|
225
|
-
if o!=eox
|
226
|
-
$STDERR.puts "int SEXP size mismatch"
|
227
|
-
o=eox
|
228
|
-
end
|
229
|
-
|
230
|
-
# hack for factors
|
231
|
-
if (!get_attr.nil?)
|
232
|
-
ca = get_attr().as_list().at("class");
|
233
|
-
ls = get_attr().as_list().at("levels");
|
234
|
-
if (!ca.nil? and !ls.nil? and ca.as_string=="factor")
|
235
|
-
# R uses 1-based index, Java (and Ruby) uses 0-based one
|
236
|
-
@cont = REXP::Factor.new(d, ls.as_strings(), get_attr)
|
237
|
-
xt = XT_FACTOR;
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
if @cont.nil?
|
244
|
-
@cont=REXP::Integer.new(d,get_attr)
|
245
|
-
end
|
246
|
-
return o
|
247
|
+
|
248
|
+
|
249
|
+
|
250
|
+
if @cont.nil?
|
251
|
+
@cont=REXP::Integer.new(d,get_attr)
|
247
252
|
end
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
253
|
+
return o
|
254
|
+
end
|
255
|
+
|
256
|
+
if (xt==XT_RAW)
|
257
|
+
as=get_int(buf,o);
|
258
|
+
o+=4
|
259
|
+
d=buf[o,as]
|
260
|
+
o = eox;
|
261
|
+
@cont = new REXP::Raw.new(d, get_attr);
|
262
|
+
return o;
|
263
|
+
end
|
264
|
+
|
265
|
+
if xt==XT_LIST_NOTAG or xt==XT_LIST_TAG or xt==XT_LANG_NOTAG or xt==XT_LANG_TAG
|
266
|
+
lc=REXPFactory.new
|
267
|
+
nf=REXPFactory.new
|
268
|
+
l=Rlist.new
|
269
|
+
while(o<eox)
|
270
|
+
name=nil
|
271
|
+
o=lc.parse_REXP(buf,o)
|
272
|
+
if(xt==XT_LIST_TAG or xt==XT_LANG_TAG)
|
273
|
+
o=nf.parse_REXP(buf,o)
|
274
|
+
|
275
|
+
name=nf.cont.as_string if(nf.cont.symbol? or nf.cont.string?)
|
270
276
|
end
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
$STDERR.puts "Mismatch"
|
277
|
-
o=eox
|
277
|
+
if name.nil?
|
278
|
+
|
279
|
+
l.add(lc.cont)
|
280
|
+
else
|
281
|
+
l.put(name,lc.cont)
|
278
282
|
end
|
279
|
-
|
280
|
-
return o
|
281
|
-
|
282
283
|
end
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
if
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
284
|
+
|
285
|
+
@cont=(xt==XT_LANG_NOTAG or xt==XT_LANG_TAG) ?
|
286
|
+
REXP::Language.new(l,get_attr) : REXP::List.new(l, get_attr)
|
287
|
+
|
288
|
+
if(o!=eox)
|
289
|
+
$STDERR.puts "Mismatch"
|
290
|
+
o=eox
|
291
|
+
end
|
292
|
+
|
293
|
+
return o
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
|
298
|
+
# old-style lists, for comaptibility with older Rserve versions - rather inefficient since we have to convert the recusively stored structures into a flat structure
|
299
|
+
# NOT TESTED YET
|
300
|
+
if (xt==XT_LIST or xt==XT_LANG) #
|
301
|
+
is_root= false
|
302
|
+
if (root_list.nil?)
|
303
|
+
root_list = Rlist.new();
|
304
|
+
is_root= true;
|
305
|
+
end
|
306
|
+
headf = REXPFactory.new();
|
307
|
+
tagf = REXPFactory.new();
|
308
|
+
o = headf.parse_REXP(buf, o);
|
309
|
+
el_index = root_list.size();
|
310
|
+
root_list.add(headf.cont);
|
311
|
+
#System.out.println("HEAD="+headf.cont);
|
312
|
+
o = parse_REXP(buf, o); # we use ourselves recursively for the body
|
313
|
+
if (o < eox)
|
314
|
+
o = tagf.parseREXP(buf, o);
|
315
|
+
#//System.out.println("TAG="+tagf.cont);
|
316
|
+
if (!tagf.cont.nil? and (tagf.cont.string? or tagf.cont.symbol?))
|
317
|
+
|
318
|
+
root_list.set_key_at(el_index, tagf.cont.as_string);
|
293
319
|
end
|
294
|
-
|
295
|
-
|
296
|
-
|
320
|
+
end
|
321
|
+
if (is_root)
|
322
|
+
@cont = (xt==XT_LIST)?
|
323
|
+
REXP::List.new(root_list, get_attr):
|
324
|
+
REXP::Language.new(root_list, get_attr)
|
325
|
+
root_list = nil;
|
326
|
+
#System.out.println("result="+cont);
|
327
|
+
end
|
328
|
+
return o;
|
329
|
+
end
|
330
|
+
|
331
|
+
|
332
|
+
|
333
|
+
|
334
|
+
if xt==XT_VECTOR or xt==XT_VECTOR_EXP
|
335
|
+
v=Array.new
|
336
|
+
while(o<eox)
|
337
|
+
xx=REXPFactory.new()
|
338
|
+
o = xx.parse_REXP(buf,o);
|
339
|
+
v.push(xx.cont);
|
340
|
+
end
|
341
|
+
if (o!=eox)
|
342
|
+
sexp_mismatch("int")
|
343
|
+
o=eox;
|
344
|
+
end
|
345
|
+
# fixup for lists since they're stored as attributes of vectors
|
346
|
+
if !get_attr.nil? and !get_attr.as_list['names'].nil?
|
347
|
+
nam=get_attr.as_list['names']
|
348
|
+
names=nil
|
349
|
+
if nam.string?
|
350
|
+
names=nam.as_strings
|
351
|
+
elsif nam.vector?
|
352
|
+
l=nam.to_a
|
353
|
+
names=Array.new(aa.length)
|
354
|
+
aa.length.times {|i| names[i]=aa[i].as_string}
|
297
355
|
end
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
356
|
+
l=Rlist.new(v,names)
|
357
|
+
@cont=(xt==XT_VECTOR_EXP) ? REXP::ExpressionVector.new(l,get_attr) : REXP::GenericVector.new(l,get_attr)
|
358
|
+
else
|
359
|
+
|
360
|
+
@cont=(xt==XT_VECTOR_EXP) ? REXP::ExpressionVector.new(Rlist.new(v), get_attr) : REXP::GenericVector.new(Rlist.new(v), get_attr)
|
361
|
+
end
|
362
|
+
return o
|
363
|
+
end
|
364
|
+
if xt==XT_ARRAY_STR
|
365
|
+
c=0
|
366
|
+
i=o
|
367
|
+
while(i<eox)
|
368
|
+
c+=1 if buf[i]==0
|
369
|
+
i+=1
|
370
|
+
end
|
371
|
+
s=Array.new(c)
|
372
|
+
if c>0
|
373
|
+
c=0; i=o;
|
374
|
+
while(o < eox)
|
375
|
+
if buf[o]==0
|
376
|
+
begin
|
377
|
+
s[c]=buf[i,o-i].pack("C*")
|
378
|
+
rescue
|
379
|
+
s[c]=""
|
380
|
+
end
|
381
|
+
c+=1
|
382
|
+
i=o+1
|
308
383
|
end
|
309
|
-
|
310
|
-
@cont=(xt==XT_VECTOR_EXP) ? REXP::ExpressionVector.new(l,get_attr) : REXP::GenericVector.new(l,get_attr)
|
311
|
-
else
|
312
|
-
|
313
|
-
@cont=(xt==XT_VECTOR_EXP) ? REXP::ExpressionVector.new(Rlist.new(v), get_attr) : REXP::GenericVector.new(Rlist.new(v), get_attr)
|
384
|
+
o+=1
|
314
385
|
end
|
315
|
-
|
386
|
+
|
387
|
+
end
|
388
|
+
@cont=REXP::String.new(s, get_attr)
|
389
|
+
return o
|
390
|
+
end
|
391
|
+
if xt==XT_VECTOR_STR
|
392
|
+
v=Array.new
|
393
|
+
while(o<eox)
|
394
|
+
xx=REXPFactory.new
|
395
|
+
o=xx.parse_REXP(buf,o)
|
396
|
+
v.push(xx.cont.as_string)
|
397
|
+
end
|
398
|
+
sa=Array.new(v.size)
|
399
|
+
i=0
|
400
|
+
while(i<sa.length)
|
401
|
+
sa[i]=v.get(i)
|
402
|
+
i+=1
|
316
403
|
end
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
404
|
+
@cont=REXP::String.new(sa,get_attr)
|
405
|
+
return o
|
406
|
+
end
|
407
|
+
|
408
|
+
if (xt==XT_STR||xt==XT_SYMNAME)
|
409
|
+
i = o;
|
410
|
+
while (buf[i]!=0 && i<eox)
|
411
|
+
i+=1
|
412
|
+
end
|
413
|
+
if (xt==XT_STR)
|
414
|
+
@cont = REXP::String.new(buf[o,i-o].pack("C*"), get_attr);
|
415
|
+
else
|
416
|
+
@cont = REXP::Symbol.new(buf[o,i-o].pack("C*"))
|
417
|
+
end
|
418
|
+
o = eox;
|
419
|
+
return o;
|
420
|
+
end
|
421
|
+
|
422
|
+
if (xt==XT_SYM)
|
423
|
+
sym = REXPFactory.new
|
424
|
+
o = sym.parse_REXP(buf, o); # PRINTNAME that's all we will use
|
425
|
+
@cont = REXP::Symbol.new(sym.get__REXP().as_string) # content of a symbol is its printname string (so far)
|
426
|
+
o=eox;
|
427
|
+
return o;
|
428
|
+
end
|
429
|
+
|
430
|
+
if (xt==XT_CLOS)
|
431
|
+
o=eox;
|
432
|
+
return o;
|
433
|
+
end
|
434
|
+
|
435
|
+
if (xt==XT_UNKNOWN)
|
436
|
+
@cont = REXP::Unknown.new(get_int(buf,o), get_attr)
|
437
|
+
o=eox;
|
438
|
+
return o;
|
439
|
+
end
|
440
|
+
|
441
|
+
if (xt==XT_S4)
|
442
|
+
@cont = new REXP::S4.new(get_attr)
|
443
|
+
o=eox
|
444
|
+
return o;
|
445
|
+
end
|
446
|
+
@cont=nil
|
447
|
+
o=eox
|
448
|
+
raise "Unhandled type:#{xt}"
|
449
|
+
return o
|
450
|
+
end # def
|
451
|
+
|
452
|
+
|
453
|
+
|
454
|
+
# Calculates the length of the binary representation of the REXP including all headers.
|
455
|
+
# This is the amount of memory necessary to store the REXP via do@link #getBinaryRepresentationend.
|
456
|
+
# Please note that currently only XT_[ARRAY_]INT, XT_[ARRAY_]DOUBLE and XT_[ARRAY_]STR are supported! All other types will return 4
|
457
|
+
# which is the size of the header.
|
458
|
+
# @return length of the REXP including headers (4 or 8 bytes)*/
|
459
|
+
def get_binary_length
|
460
|
+
l=0
|
461
|
+
rxt = type
|
462
|
+
if (type==XT_LIST or type==XT_LIST_TAG or type==XT_LIST_NOTAG)
|
463
|
+
rxt=(!cont.as_list.nil? and cont.as_list.named?) ? XT_LIST_TAG : XT_LIST_NOTAG;
|
464
|
+
end
|
465
|
+
#System.out.print("len["+xtName(type)+"/"+xtName(rxt)+"] ");
|
466
|
+
rxt=XT_ARRAY_STR if (type==XT_VECTOR_STR) ; # VECTOR_STR is broken right now
|
467
|
+
|
468
|
+
|
469
|
+
has_attr= false;
|
470
|
+
a = get_attr;
|
471
|
+
al = nil;
|
472
|
+
al = a.as_list if (!a.nil?)
|
473
|
+
has_attr=true if (!al.nil? and al.size()>0)
|
474
|
+
l+=attr.get_binary_length if has_attr
|
475
|
+
|
476
|
+
if (rxt==XT_NULL or rxt==XT_S4)
|
477
|
+
elsif (rxt==XT_INT)
|
478
|
+
l+=4
|
479
|
+
elsif (rxt==XT_DOUBLE)
|
480
|
+
l+=8
|
481
|
+
elsif (rxt==XT_RAW)
|
482
|
+
l+=4 + cont.as_bytes.length
|
483
|
+
l=l-(l&3)+4 if ((l&3)>0)
|
484
|
+
elsif (rxt==XT_STR or rxt==XT_SYMNAME)
|
485
|
+
l+=(cont.nil?)?1:(cont.as_string.length()+1);
|
486
|
+
l=l-(l&3)+4 if ((l&3)>0)
|
487
|
+
elsif (rxt==XT_ARRAY_INT)
|
488
|
+
l+=cont.as_integers().length*4
|
489
|
+
elsif (rxt==XT_ARRAY_DOUBLE)
|
490
|
+
l+=cont.as_doubles().length*8
|
491
|
+
elsif (rxt==XT_ARRAY_CPLX)
|
492
|
+
l+=cont.as_doubles().length*8
|
493
|
+
elsif (rxt==XT_ARRAY_BOOL)
|
494
|
+
l += cont.as_bytes().length + 4
|
495
|
+
l = l - (l & 3) + 4 if ((l & 3) > 0)
|
496
|
+
elsif ([XT_LIST_TAG, XT_LIST_NOTAG, XT_LANG_TAG, XT_LANG_NOTAG, XT_LIST, XT_VECTOR].include? rxt)
|
497
|
+
lst = cont.as_list
|
498
|
+
i=0
|
499
|
+
while (i<lst.size)
|
500
|
+
x=lst.at(i)
|
501
|
+
l+=(x.nil?)?4:(REXPFactory.new(x).get_binary_length)
|
502
|
+
if(rxt==XT_LIST_TAG)
|
503
|
+
pl=l
|
504
|
+
s=lst.key_at(i)
|
505
|
+
l+=4
|
506
|
+
l+=(s.nil?) ? 1:(s.length+1)
|
507
|
+
l=l-(l&3)+4 if ((l&3)>0)
|
323
508
|
end
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
c+=1
|
335
|
-
i=o+1
|
336
|
-
end
|
337
|
-
o+=1
|
338
|
-
end
|
339
|
-
|
509
|
+
i+=1
|
510
|
+
end
|
511
|
+
l=l-(l&3)+4 if ((l&3)>0)
|
512
|
+
elsif rxt==XT_ARRAY_STR
|
513
|
+
sa=cont.as_strings
|
514
|
+
i=0
|
515
|
+
sa.each do |v|
|
516
|
+
if(!v.nil?)
|
517
|
+
b=v.unpack("C*")
|
518
|
+
l+=b.length
|
340
519
|
end
|
341
|
-
|
342
|
-
return o
|
520
|
+
l+=1
|
343
521
|
end
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
522
|
+
|
523
|
+
l=l-(l&3)+4 if ((l&3)>0)
|
524
|
+
else
|
525
|
+
raise "NOT IMPLEMENTED"
|
526
|
+
end
|
527
|
+
l+=4 if (l>0xfffff0)
|
528
|
+
l+4
|
529
|
+
end
|
530
|
+
def get_binary_representation(buf,off)
|
531
|
+
myl=get_binary_length;
|
532
|
+
is_large=(myl>0xfffff0);
|
533
|
+
a = get_attr;
|
534
|
+
al = nil;
|
535
|
+
al = a.as_list if (!a.nil?)
|
536
|
+
has_attr=(!al.nil? and al.size()>0)
|
537
|
+
rxt=type
|
538
|
+
ooff=off
|
539
|
+
rxt==XT_ARRAY_STR if(type==XT_VECTOR_STR) # VECTOR_STR is broken right now
|
540
|
+
if (type==XT_LIST || type==XT_LIST_TAG || type==XT_LIST_NOTAG)
|
541
|
+
rxt=(!cont.as_list.nil? and cont.as_list.named?) ? XT_LIST_TAG : XT_LIST_NOTAG
|
542
|
+
end
|
543
|
+
set_hdr(rxt|(has_attr ? XT_HAS_ATTR : 0), myl - (is_large ? 8 : 4 ),buf,off);
|
544
|
+
off+=(is_large ? 8 : 4);
|
545
|
+
if has_attr
|
546
|
+
puts "REXP BIN ATTR: #{attr.cont.inspect}" if $DEBUG
|
547
|
+
off=attr.get_binary_representation(buf, off)
|
548
|
+
end
|
549
|
+
|
550
|
+
|
551
|
+
puts "REXP BIN: #{xt_name(rxt)}(#{rxt})[#{myl}], '#{cont.inspect}' attr?:#{has_attr}" if $DEBUG
|
552
|
+
|
553
|
+
|
554
|
+
|
555
|
+
if(rxt==XT_S4 or rxt==XT_NULL)
|
556
|
+
elsif(rxt==XT_INT)
|
557
|
+
set_int(cont.as_integer, buf, off)
|
558
|
+
elsif(rxt==XT_DOUBLE)
|
559
|
+
set_long(doubleToRawLongBits(cont.as_double), buf, off)
|
560
|
+
elsif(rxt==XT_ARRAY_INT)
|
561
|
+
ia=cont.as_integers
|
562
|
+
io=off
|
563
|
+
ia.each{|v| set_int(v,buf,io); io+=4}
|
564
|
+
elsif(rxt==XT_ARRAY_BOOL)
|
565
|
+
ba=cont.as_bytes
|
566
|
+
io=off
|
567
|
+
set_int(ba.length,buf,io)
|
568
|
+
io+=4
|
569
|
+
if(ba.length>0)
|
570
|
+
ba.each {|v|
|
571
|
+
buf[io] = ( (v == REXP::Logical::NA) ? 2 : ((v == REXP::Logical::FALSE) ? 0 : 1) );
|
572
|
+
io+=1
|
573
|
+
}
|
574
|
+
while ((io & 3) != 0)
|
575
|
+
buf[io] = 3
|
576
|
+
io+=1
|
350
577
|
end
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
578
|
+
end
|
579
|
+
|
580
|
+
elsif(rxt==XT_ARRAY_DOUBLE)
|
581
|
+
da=cont.as_doubles
|
582
|
+
io=off
|
583
|
+
da.each do |v|
|
584
|
+
set_long(doubleToRawLongBits(v),buf,io)
|
585
|
+
io+=8
|
586
|
+
end
|
587
|
+
elsif(rxt==XT_RAW)
|
588
|
+
by=cont.as_bytes
|
589
|
+
set_int(by.length,buf,off);
|
590
|
+
off+=4
|
591
|
+
by.each_with_index {|v,i| buf[off+i]=v}
|
592
|
+
elsif(rxt==XT_ARRAY_STR)
|
593
|
+
sa=cont.as_strings
|
594
|
+
io=off
|
595
|
+
sa.each do |v|
|
596
|
+
if !v.nil?
|
597
|
+
b=v.unpack("C*")
|
598
|
+
b.each_with_index{|v,index| buf[io+index]=v}
|
599
|
+
io+=b.length
|
356
600
|
end
|
357
|
-
|
358
|
-
|
601
|
+
buf[io]=0
|
602
|
+
io+=1
|
603
|
+
end
|
604
|
+
i=io-off
|
605
|
+
while ((i&3)!=0)
|
606
|
+
buf[io]=1;
|
607
|
+
io+=1
|
608
|
+
i+=1 # padding if necessary..
|
359
609
|
end
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
610
|
+
|
611
|
+
elsif ([XT_LIST_TAG, XT_LIST_NOTAG, XT_LANG_TAG, XT_LANG_NOTAG, XT_LIST, XT_VECTOR,XT_VECTOR_EXP].include? rxt)
|
612
|
+
io=off
|
613
|
+
#puts "io:#{io}"
|
614
|
+
lst=cont.as_list
|
615
|
+
#p lst
|
616
|
+
if !lst.nil?
|
617
|
+
lst.size.times do |i|
|
618
|
+
x=lst.at(i)
|
619
|
+
#puts "#{x}"
|
620
|
+
x==REXP::Null if x.nil?
|
621
|
+
#p buf
|
622
|
+
io=REXPFactory.new(x).get_binary_representation(buf,io)
|
623
|
+
#p buf
|
624
|
+
#p io
|
625
|
+
if(rxt==XT_LIST_TAG or rxt==XT_LANG_TAG)
|
626
|
+
|
627
|
+
io=REXPFactory.new(REXP::Symbol.new(lst.key_at(i))).get_binary_representation(buf, io)
|
628
|
+
|
629
|
+
end
|
630
|
+
end #times
|
631
|
+
end #end if
|
632
|
+
|
633
|
+
elsif (rxt==XT_SYMNAME or rxt==XT_STR)
|
634
|
+
get_string_binary_representation(buf,off,cont.as_string)
|
635
|
+
else
|
636
|
+
raise "Can't represent on binary #{xt_name{rxt}}"
|
637
|
+
end
|
638
|
+
|
639
|
+
# end def
|
640
|
+
puts "END BUFFER:#{buf}" if $DEBUG
|
641
|
+
ooff+myl
|
365
642
|
end
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
643
|
+
def get_string_binary_representation(buf,off,s)
|
644
|
+
s||=""
|
645
|
+
io=off
|
646
|
+
b=s.unpack("C*")
|
647
|
+
puts "STRING REPRESENTATION: #{b}" if $DEBUG
|
648
|
+
b.each_with_index {|v,i| buf[io+i]=v}
|
649
|
+
io+=b.length
|
650
|
+
buf[io]=0
|
651
|
+
io+=1
|
652
|
+
while ((io&3)!=0)
|
653
|
+
buf[io]=0; # padding if necessary..
|
654
|
+
io+=1
|
371
655
|
end
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
656
|
+
io
|
657
|
+
end
|
658
|
+
def xt_name(xt)
|
659
|
+
case xt
|
660
|
+
when XT_NULL then "NULL";
|
661
|
+
when XT_INT then "INT";
|
662
|
+
when XT_STR then "STRING";
|
663
|
+
when XT_DOUBLE then "REAL";
|
664
|
+
when XT_BOOL then "BOOL";
|
665
|
+
when XT_ARRAY_INT then "INT*";
|
666
|
+
when XT_ARRAY_STR then "STRING*";
|
667
|
+
when XT_ARRAY_DOUBLE then "REAL*";
|
668
|
+
when XT_ARRAY_BOOL then "BOOL*";
|
669
|
+
when XT_ARRAY_CPLX then "COMPLEX*";
|
670
|
+
when XT_SYM then "SYMBOL";
|
671
|
+
when XT_SYMNAME then "SYMNAME";
|
672
|
+
when XT_LANG then "LANG";
|
673
|
+
when XT_LIST then "LIST";
|
674
|
+
when XT_LIST_TAG then "LIST+T";
|
675
|
+
when XT_LIST_NOTAG then "LIST/T";
|
676
|
+
when XT_LANG_TAG then "LANG+T";
|
677
|
+
when XT_LANG_NOTAG then "LANG/T";
|
678
|
+
when XT_CLOS then "CLOS";
|
679
|
+
when XT_RAW then "RAW";
|
680
|
+
when XT_S4 then "S4";
|
681
|
+
when XT_VECTOR then "VECTOR";
|
682
|
+
when XT_VECTOR_STR then "STRING[]";
|
683
|
+
when XT_VECTOR_EXP then "EXPR[]";
|
684
|
+
when XT_FACTOR then "FACTOR";
|
685
|
+
when XT_UNKNOWN then "UNKNOWN";
|
686
|
+
else
|
687
|
+
"<unknown #{xt}"
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
|
692
|
+
|
693
|
+
|
694
|
+
|
402
695
|
end # Factory
|
403
696
|
end # end Protocol
|
404
|
-
end # end Rserve
|
697
|
+
end # end Rserve
|