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.
Files changed (46) hide show
  1. data.tar.gz.sig +1 -2
  2. data/.gitignore +1 -0
  3. data/History.txt +15 -2
  4. data/Manifest.txt +8 -0
  5. data/README.txt +41 -19
  6. data/lib/rserve.rb +1 -1
  7. data/lib/rserve/connection.rb +152 -69
  8. data/lib/rserve/engine.rb +9 -9
  9. data/lib/rserve/packet.rb +2 -2
  10. data/lib/rserve/protocol.rb +51 -46
  11. data/lib/rserve/protocol/rexpfactory.rb +659 -366
  12. data/lib/rserve/rexp.rb +175 -156
  13. data/lib/rserve/rexp/double.rb +45 -38
  14. data/lib/rserve/rexp/environment.rb +40 -0
  15. data/lib/rserve/rexp/expressionvector.rb +9 -0
  16. data/lib/rserve/rexp/genericvector.rb +5 -3
  17. data/lib/rserve/rexp/integer.rb +38 -38
  18. data/lib/rserve/rexp/language.rb +2 -2
  19. data/lib/rserve/rexp/list.rb +3 -0
  20. data/lib/rserve/rexp/logical.rb +17 -4
  21. data/lib/rserve/rexp/null.rb +20 -14
  22. data/lib/rserve/rexp/raw.rb +19 -0
  23. data/lib/rserve/rexp/reference.rb +42 -0
  24. data/lib/rserve/rexp/s4.rb +10 -0
  25. data/lib/rserve/rexp/string.rb +5 -3
  26. data/lib/rserve/rexp/symbol.rb +3 -0
  27. data/lib/rserve/rexp/vector.rb +30 -15
  28. data/lib/rserve/rexp/wrapper.rb +58 -0
  29. data/lib/rserve/rfactor.rb +10 -10
  30. data/lib/rserve/rlist.rb +129 -100
  31. data/lib/rserve/talk.rb +61 -61
  32. data/spec/rserve_connection_spec.rb +99 -33
  33. data/spec/rserve_double_spec.rb +28 -15
  34. data/spec/rserve_integer_spec.rb +24 -15
  35. data/spec/rserve_logical_spec.rb +21 -12
  36. data/spec/rserve_protocol_spec.rb +7 -7
  37. data/spec/rserve_rexp_spec.rb +3 -3
  38. data/spec/rserve_rexp_wrapper_spec.rb +36 -0
  39. data/spec/rserve_rexpfactory_spec.rb +86 -20
  40. data/spec/rserve_rfactor_spec.rb +2 -2
  41. data/spec/rserve_rlist_spec.rb +53 -0
  42. data/spec/rserve_spec.rb +8 -5
  43. data/spec/rserve_talk_spec.rb +7 -7
  44. data/spec/spec_helper.rb +1 -0
  45. metadata +13 -3
  46. metadata.gz.sig +0 -0
@@ -14,27 +14,27 @@ module Rserve
14
14
  evaluate(p,where,resolve)
15
15
  end
16
16
  def close;
17
- false
17
+ false
18
18
  end
19
19
  def supports_references?
20
- false
20
+ false
21
21
  end
22
22
  def supports_enviroments?
23
- false
23
+ false
24
24
  end
25
25
  def supports_REPL?
26
- false
26
+ false
27
27
  end
28
28
  def suuports_locking?
29
- false
29
+ false
30
30
  end
31
31
  def try_lock
32
- 0
32
+ 0
33
33
  end
34
34
  def lock
35
- 0
35
+ 0
36
36
  end
37
37
  def unlock;end;
38
-
38
+
39
39
  end
40
- end
40
+ end
@@ -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
@@ -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
- #server is free to choose any value - usually
46
- #it uses the size of its static buffer */
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("I")[0]
164
- #return ((buf[o]&255)|((buf[o+1]&255)<<8)|((buf[o+2]&255)<<16)|((buf[o+3]&255)<<24));
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
- s = ((bits >> 63) == 0) ? 1 : -1;
192
- e = ((bits >> 52) & 0x7ff)
193
- m = (e == 0) ?
194
- (bits & 0xfffffffffffff) << 1 :
195
- (bits & 0xfffffffffffff) | 0x10000000000000;
196
- s*m*2**(e-1075)
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
- 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
- attr_reader :type, :attr, :cont, :root_list
72
- def get_REXP
73
- @cont
74
- end
75
- def get_attr
76
- attr.nil? ? nil : attr.cont
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
- def sexp_mismatch(type)
79
- STDERR.puts("Warning: #{type} SEXP size mismatch")
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
- def initialize(*args)
82
- if args.size==0
83
-
84
- elsif
85
- r=args[0]
86
- r=Rserve::REXP::Null if r.nil?
87
- a=r.attr
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
- def parse_REXP(buf,o)
119
- xl=get_len(buf,o)
120
- #p "buffer:#{buf.to_s}"
121
- has_at = (buf[o]&128)!=0
122
- is_long = (buf[o]&64 )!=0
123
- xt = buf[o]&63
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
- if(o!=eox)
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 xt==XT_BOOL
166
- b=[buf[o]]
167
- if (b[0]!=0 && b[0]!=1)
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
- if xt==XT_ARRAY_BOOL_UA
175
- as=(eox-o)
176
- i=0
177
- d=Array.new(as)
178
- (eox-i).times {|i| d[i]=buf[o+i]}
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
- d.length.each {|j|
182
- if d[j]!=0 and d[j]!=1
183
- d[j]==REXP::Logical::NA
184
- end
185
- }
186
- @cont=REXP::Logical.new(d,get_attr)
187
- return o
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
- if xt==XT_ARRAY_BOOL
190
- as=get_int(buf, o)
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
- d=Array.new(as)
193
- as.times {|i| d[i]=buf[o+i]}
194
- d.collect! {|v|
195
- if v!=0 and v!=1
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
- if xt==XT_INT
206
- i=Array.new(get_int(buf,o))
207
- @cont=REXP::Integer.new(i,get_attr)
208
- o+=4
209
- if o!=eox
210
- $STDERR.puts "int SEXP size mismatch"
211
- o=eox
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
- if xt==XT_ARRAY_INT
217
- as=(eox-o).quo(4)
218
- i=0
219
- d=Array.new(as)
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
- # RAW not implemented yet
250
-
251
-
252
- if xt==XT_LIST_NOTAG or xt==XT_LIST_TAG or xt==XT_LANG_NOTAG or xt==XT_LANG_TAG
253
- lc=REXPFactory.new
254
- nf=REXPFactory.new
255
- l=Rlist.new
256
- while(o<eox)
257
- name=nil
258
- o=lc.parse_REXP(buf,o)
259
- if(xt==XT_LIST_TAG or xt==XT_LANG_TAG)
260
- o=nf.parse_REXP(buf,o)
261
-
262
- name=nf.cont.as_string if(nf.cont.symbol? or nf.cont.string?)
263
- end
264
- if name.nil?
265
-
266
- l.add(lc.cont)
267
- else
268
- l.put(name,lc.cont)
269
- end
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
- @cont=(xt==XT_LANG_NOTAG or xt==XT_LANG_TAG) ?
273
- REXP::Language.new(l,get_attr) : REXP::List.new(l, get_attr)
274
-
275
- if(o!=eox)
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
- # XT_LIST and XT_LANG not implemented yet
286
-
287
- if xt==XT_VECTOR or xt==XT_VECTOR_EXP
288
- v=Array.new
289
- while(o<eox)
290
- xx=REXPFactory.new()
291
- o = xx.parse_REXP(buf,o);
292
- v.push(xx.cont);
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
- if (o!=eox)
295
- sexp_mismatch("int")
296
- o=eox;
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
- # fixup for lists since they're stored as attributes of vectors
299
- if !get_attr.nil? and !get_attr.as_list['names'].nil?
300
- nam=get_attr.as_list['names']
301
- names=nil
302
- if nam.string?
303
- names=nam.as_strings
304
- elsif nam.vector?
305
- l=nam.to_a
306
- names=Array.new(aa.length)
307
- aa.length.times {|i| names[i]=aa[i].as_string}
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
- l=Rlist.new(v,names)
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
- return o
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
- if xt==XT_ARRAY_STR
318
- c=0
319
- i=o
320
- while(i<eox)
321
- c+=1 if buf[i]==0
322
- i+=1
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
- s=Array.new(c)
325
- if c>0
326
- c=0; i=o;
327
- while(o < eox)
328
- if buf[o]==0
329
- begin
330
- s[c]=buf[i,o-i].pack("C*")
331
- rescue
332
- s[c]=""
333
- end
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
- @cont=REXP::String.new(s, get_attr)
342
- return o
520
+ l+=1
343
521
  end
344
- if xt==XT_VECTOR_STR
345
- v=Array.new
346
- while(o<eox)
347
- xx=REXP::Factory.new
348
- o=xx.parse_REXP(buf,o)
349
- v.push(xx.cont.as_string)
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
- sa=Array.new(v.size)
352
- i=0
353
- while(i<sa.length)
354
- sa[i]=v.get(i)
355
- i+=1
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
- @cont=REXP::String.new(sa,get_attr)
358
- return o
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
- if (xt==XT_STR||xt==XT_SYMNAME)
362
- i = o;
363
- while (buf[i]!=0 && i<eox) do
364
- i+=1
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
- if (xt==XT_STR)
367
- @cont = REXP::String.new(buf[o,i-o].pack("C*"), get_attr);
368
-
369
- else
370
- @cont = REXP::Symbol.new(buf[o,i-o].pack("C*"))
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
- o = eox;
374
- return o;
375
- end
376
-
377
- #not implemented XT_SYM,
378
-
379
-
380
- if (xt==XT_CLOS)
381
- o=eox;
382
- return o;
383
- end
384
-
385
- if (xt==XT_UNKNOWN)
386
- @cont = REXP::Unknown.new(get_int(buf,o), get_attr)
387
- o=eox;
388
- return o;
389
- end
390
-
391
- if (xt==XT_S4)
392
- @cont = new REXP::S4(get_attr)
393
- o=eox
394
- return o;
395
- end
396
-
397
- @cont=nil
398
- o=eox
399
- raise "Unhandled type:#{xt}"
400
- return o
401
- end # def
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