nwrfc 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,338 +1,338 @@
1
- module NWRFC
2
-
3
- # Representation of a data container (function, structure or table)
4
- # Implements common functions for data containers, such as setting and getting values, tables, structures and
5
- # takes care of type conversion and calling correct SDK functions to set or get values
6
- #
7
- # == Type Conversions
8
- # To ensure that data is passed correctly to the NW RFC SDK functions, certain conversions are applied to values
9
- # passed, depending on the type of the field. ABAP supports a number of elementary types, which are listed in the
10
- #
11
- # DECFLOAT16 and DECFLOAT34 types are not yet supported.
12
- #
13
- # === Inbound
14
- # For character and string
15
- class DataContainer
16
- attr_reader :handle, :desc
17
-
18
- def initialize(handle)
19
- @error = NWRFCLib::RFCError.new
20
- @handle = handle
21
- @desc = NWRFCLib.describe_type(@handle, @error)
22
- @member_metadata = {} #Cache of metadata for members
23
- NWRFC.check_error(@error)
24
- end
25
-
26
- #--
27
- # VALUE RETRIEVAL
28
- #++
29
-
30
- # Get value from a data container (structure, function instance or table)
31
- def [](element)
32
- member = element.to_s.upcase
33
- metadata = member_metadata(element)
34
- case metadata[:type]
35
-
36
- when :RFCTYPE_CHAR
37
- # TODO: Try use :string parameter in get_chars
38
- return read_chars(metadata)
39
-
40
- when :RFCTYPE_DATE
41
- return Date.parse(read_chars(metadata))
42
- #return Date.new(date[0..3].to_i, date[4..5].to_i, date[6..7].to_i)
43
-
44
- when :RFCTYPE_BCD
45
- size = metadata[:nucLength] + (metadata[:decimals] || 0)
46
- buf = FFI::MemoryPointer.new(:uchar, size*2)
47
- rc = NWRFCLib.get_chars(@handle, metadata[:name].cU, buf, size, @error.to_ptr)
48
- NWRFC.check_error(@error) if rc > 0
49
- return buf.get_bytes(0, size*2).uC.to_f
50
- #size = metadata[:ucLength]
51
- #cb = FFI::MemoryPointer.new :char, size * 2
52
- #rc = NWRFCLib.get_chars(@handle, metadata[:name].cU, cb, size * 2, @error.to_ptr)
53
- #NWRFC.check_error(@error) if rc > 0
54
- #cb.read_string(size).uC
55
-
56
- when :RFCTYPE_TIME
57
- # TODO: See whether we can optimize this
58
- timec = read_chars(metadata)
59
- return Time.parse("#{timec[0..1]}:#{timec[2..3]}:#{timec[4..5]}")
60
-
61
- when :RFCTYPE_BYTE
62
- size = metadata[:ucLength]
63
- buf = FFI::MemoryPointer.new(:uchar, size)
64
- rc = NWRFCLib.get_bytes(@handle, metadata[:name].cU, buf, size, @error.to_ptr)
65
- NWRFC.check_error(@error) if rc > 0
66
- return buf.get_bytes(0, size)
67
-
68
- when :RFCTYPE_TABLE
69
- # TODO Cache instances of table members and return those where available
70
- new_handle = NWRFCLib::RFCDataContainer.new
71
- rc = NWRFCLib.get_table(@handle, member.cU, new_handle.to_ptr, @error.to_ptr)
72
- NWRFC.check_error(@error) if rc > 0
73
- # CAVEAT: Other calls using the handle require "handle" field
74
- # of the RFC_DATA_CONTAINER struct for some reason.
75
- new_handle = new_handle[:handle]
76
- return Table.new(new_handle)
77
-
78
- when :RFCTYPE_NUM
79
- return read_chars(metadata)
80
-
81
- when :RFCTYPE_FLOAT
82
- double = FFI::MemoryPointer.new :double
83
- rc = NWRFCLib.get_float(@handle, member.cU, double, @error)
84
- NWRFC.check_error(@error) if rc > 0
85
- return double.get_double(0)
86
-
87
- when :RFCTYPE_INT
88
- int = FFI::MemoryPointer.new :int
89
- rc = NWRFCLib.get_int(@handle, member.cU, int, @error)
90
- NWRFC.check_error(@error) if rc > 0
91
- return int.get_int(0)
92
-
93
- when :RFCTYPE_INT2
94
- short = FFI::MemoryPointer.new :short
95
- rc = NWRFCLib.get_int2(@handle, member.cU, short, @error)
96
- NWRFC.check_error(@error) if rc > 0
97
- return short.get_short(0)
98
-
99
- when :RFCTYPE_INT1
100
- int1 = FFI::MemoryPointer.new :uint8
101
- rc = NWRFCLib.get_int1(@handle, member.cU, int1, @error)
102
- NWRFC.check_error(@error) if rc > 0
103
- return int1.get_uint8(0)
104
-
105
- when :RFCTYPE_NULL
106
- raise "Unsupported type RFCTYPE_NULL" #You should never run into this
107
-
108
- when :RFCTYPE_STRUCTURE
109
- # TODO Cache instances of structure members and return those where available
110
- new_handle = NWRFCLib::RFCDataContainer.new
111
- rc = NWRFCLib.get_structure(@handle, member.cU, new_handle.to_ptr, @error.to_ptr)
112
- NWRFC.check_error(@error) if rc > 0
113
- new_handle = new_handle[:handle]
114
- return Structure.new(new_handle)
115
-
116
- when :RFCTYPE_DECF16
117
- double = FFI::MemoryPointer.new :double
118
- rc = NWRFCLib.get_dec_f16(@handle, member.cU, double, @error)
119
- NWRFC.check_error(@error) if rc > 0
120
- return double.get_double(0)
121
-
122
- when :RFCTYPE_DECF34
123
- double = FFI::MemoryPointer.new :double, 2
124
- rc = NWRFCLib.get_dec_f34(@handle, member.cU, double, @error)
125
- NWRFC.check_error(@error) if rc > 0
126
- return double.get_double(0)
127
-
128
- when :RFCTYPE_XMLDATA
129
- raise "Unsupported type RFCTYPE_XMLDATA (no longer used)" #You should never run into this
130
-
131
- when :RFCTYPE_STRING
132
- return read_string(metadata)
133
-
134
- when :RFCTYPE_XSTRING
135
- size = FFI::MemoryPointer.new(:uint)
136
- rc = NWRFCLib.get_string_length(@handle, metadata[:name].cU, size, @error)
137
- NWRFC.check_error(@error) if rc > 0
138
- buf_len = size.read_uint
139
- sbuf = FFI::MemoryPointer.new :uchar, buf_len
140
- rc = NWRFCLib.get_x_string(@handle, metadata[:name].cU, sbuf, buf_len, size, @error)
141
- NWRFC.check_error(@error) if rc > 0
142
- return sbuf.read_string(sbuf.size)
143
-
144
- else
145
- raise "Illegal member type #{metadata[:type]}"
146
- end
147
-
148
- end
149
-
150
- #--
151
- # VALUE STORAGE
152
- #++
153
-
154
- # Set value on a data container (structure, function instance or table)
155
- def []=(element, value)
156
- member = element.to_s.upcase
157
- metadata = member_metadata(element)
158
- case metadata[:type]
159
-
160
- when :RFCTYPE_CHAR
161
- value = value.to_s
162
- NWRFCLib.set_chars(@handle, member.cU, value.cU, value.length, @error.to_ptr)
163
-
164
- when :RFCTYPE_DATE
165
- value = value_to_date(value)
166
- NWRFCLib.set_date(@handle, member.cU, value.cU, @error.to_ptr)
167
-
168
- when :RFCTYPE_BCD
169
- stval = value.to_s.cU
170
- m = FFI::MemoryPointer.from_string stval
171
- NWRFCLib.set_string(@handle, member.cU, m, value.to_s.size, @error)
172
-
173
- when :RFCTYPE_TIME
174
- value = value_to_time(value)
175
- NWRFCLib.set_time(@handle, member.cU, value.cU, @error.to_ptr)
176
-
177
- when :RFCTYPE_BYTE
178
- m = FFI::MemoryPointer.from_string value.to_s
179
- NWRFCLib.set_bytes(@handle, member.cU, m, value.to_s.size, @error.to_ptr)
180
-
181
- when :RFCTYPE_TABLE
182
- raise "Value must be of type table" unless value.class == NWRFC::Table
183
- NWRFCLib.set_table(@handle, member.cU, value.handle, @error)
184
-
185
- when :RFCTYPE_NUM
186
- value = value.to_s
187
- NWRFCLib.set_num(@handle, member.cU, value.cU, value.length, @error.to_ptr)
188
-
189
- when :RFCTYPE_FLOAT
190
- NWRFCLib.set_float(@handle, member.cU, value.to_f, @error.to_ptr)
191
-
192
- when :RFCTYPE_INT
193
- NWRFCLib.set_int(@handle, member.cU, value.to_i, @error.to_ptr)
194
-
195
- when :RFCTYPE_INT2
196
- NWRFCLib.set_int2(@handle, member.cU, value.to_i, @error.to_ptr)
197
-
198
- when :RFCTYPE_INT1
199
- NWRFCLib.set_int1(@handle, member.cU, value.to_i, @error.to_ptr)
200
-
201
- when :RFCTYPE_NULL
202
- raise "Unsupported type RFCTYPE_NULL" #You should never run into this
203
-
204
- when :RFCTYPE_STRUCTURE
205
- raise "Value must be of type table" unless value.class == NWRFC::Structure
206
- NWRFCLib.set_structure(@handle, member.cU, value.handle, @error)
207
-
208
- when :RFCTYPE_DECF16
209
- raise "#{@members[:type]}: decfloat16 not supported yet"
210
- double = NWRFCLib::RFC_DECF16.new #FFI::MemoryPointer.new :double
211
- double[:align] = value.to_f
212
- #double.put_double(0, value.to_f)
213
- #double = FFI::Pointer.new 4
214
- NWRFCLib.set_dec_f16(@handle, member.cU, double.pointer, @error)
215
-
216
- when :RFCTYPE_DECF34
217
- raise "#{@members[:type]}: decfloat34 not supported yet"
218
- # double = FFI::MemoryPointer.new :double, 2
219
- # double.put_double(0, value.to_f)
220
- double = NWRFCLib::RFC_DECF34.new #FFI::MemoryPointer.new :double
221
- double[:align] = value.to_f
222
- NWRFCLib.set_dec_f34(@handle, member.cU, double, @error)
223
-
224
- when :RFCTYPE_XMLDATA
225
- raise "Unsupported type RFCTYPE_XMLDATA (no longer used)" #You should never run into this
226
-
227
- when :RFCTYPE_STRING
228
- stval = value.cU
229
- m = FFI::MemoryPointer.from_string stval
230
- NWRFCLib.set_string(@handle, member.cU, m, value.size, @error)
231
-
232
- when :RFCTYPE_XSTRING
233
- m = FFI::MemoryPointer.new value.size
234
- m.put_bytes 0, value
235
- NWRFCLib.set_x_string(@handle, member.cU, m, value.size, @error)
236
-
237
- else
238
- raise "Illegal member type #{@members[:type]}"
239
- end
240
- NWRFC.check_error(@error)
241
- end
242
-
243
- # Return value as a SAP-formatted date ("YYYYMMDD"). Force value to fit into 8 chars by
244
- # truncating or padding with spaces
245
- def value_to_date(value)
246
- return value.strftime(NW_DATE_FORMAT) if value.respond_to? :strftime
247
- # Force the resulting string into 8 characters otherwise
248
- value = value.to_s
249
- value << ' ' until value.size == 8 if value.size < 8
250
- value = value[0..7] if value.size > 8
251
- value
252
- end
253
-
254
- # Return value as a SAP-formatted time ("HHMMSS"). Force value to fit into 6 chars by
255
- # truncating or padding with spaces
256
- def value_to_time(value)
257
- return value.strftime(NW_TIME_FORMAT) if value.respond_to? :strftime
258
- # Force the resulting string into 6 characters otherwise
259
- value = value.to_s
260
- value << ' ' until value.size == 6 if value.size < 6
261
- value = value[0..6] if value.size > 6
262
- value
263
- end
264
-
265
- # Return a list (array) of symbols representing the names of the fields (or parameters, in the case of a function)
266
- # of this data container
267
- def fields
268
- fc = FFI::MemoryPointer.new(:uint)
269
- rc = NWRFCLib.get_field_count(@desc, fc, @error)
270
- NWRFC.check_error(@error) if rc > 0
271
- fc = fc.read_uint
272
- fd = NWRFCLib::RFCFieldDesc.new
273
- # Make a list of field names
274
- fc.times.inject([]) {|array, index|
275
- rc = NWRFCLib.get_field_desc_by_index(@desc, index, fd.to_ptr, @error.to_ptr)
276
- NWRFC.check_error(@error) if rc > 0
277
- #@todo WARNING! our get_str method did not handle getting the name of the RESPTEXT parameter in STFC_DEEP_TABLE correctly
278
- # As a workaround, we use our read_string_dn method; do we need to use this elsewhere?
279
- #array << fd[:name].get_str.to_sym #<-The code with good intentions
280
- array << fd[:name].to_ptr.read_string_dn.uC.to_sym #<- Workaround; the way of the future?
281
- }
282
- end
283
-
284
- # Get the metadata of a member (function, structure or table)
285
- def member_metadata(member_name)
286
- # TODO: Cache metadata definitions; will it be quicker than making a hash of metadata for a given member each time?
287
- member = member_name.to_s.upcase
288
- if self.class == NWRFC::FunctionCall
289
- fpar = NWRFCLib::RFCFuncParam.new
290
- rc = NWRFCLib.get_parameter_desc_by_name(@desc, member.cU, fpar.to_ptr, @error.to_ptr)
291
- NWRFC.check_error(@error) if rc > 0
292
- member_to_hash(fpar)
293
- elsif self.class == NWRFC::Table || self.class == NWRFC::Structure
294
- fd = NWRFCLib::RFCFieldDesc.new
295
- rc = NWRFCLib.get_field_desc_by_name(@desc, member.cU, fd.to_ptr, @error.to_ptr)
296
- NWRFC.check_error(@error) if rc > 0
297
- member_to_hash(fd)
298
- end
299
- end
300
-
301
-
302
-
303
- private
304
- # Returns the subset of metadata values common to both a function parameter
305
- # and a type field
306
- def member_to_hash(member)
307
- {
308
- :name => member[:name].get_str,
309
- :type => NWRFCLib::RFC_TYPE[member[:type]],
310
- :nucLength => member[:nucLength],
311
- :ucLength => member[:ucLength],
312
- :decimals => member[:decimals],
313
- :typeDescHandle => member[:typeDescHandle]
314
- }
315
- end
316
-
317
- def read_chars(metadata)
318
- size = metadata[:ucLength]
319
- cb = FFI::MemoryPointer.new :char, size
320
- rc = NWRFCLib.get_chars(@handle, metadata[:name].cU, cb, metadata[:nucLength], @error.to_ptr)
321
- NWRFC.check_error(@error) if rc > 0
322
- cb.read_string(size).uC
323
- end
324
-
325
- def read_string(metadata)
326
- size = FFI::MemoryPointer.new(:uint)
327
- rc = NWRFCLib.get_string_length(@handle, metadata[:name].cU, size, @error)
328
- NWRFC.check_error(@error) if rc > 0
329
- buf_len = size.read_uint + 1
330
- sbuf = FFI::MemoryPointer.new :char, buf_len * NWRFCLib::B_SIZE
331
- rc = NWRFCLib.get_string(@handle, metadata[:name].cU, sbuf, buf_len, size, @error)
332
- NWRFC.check_error(@error) if rc > 0
333
- sbuf.read_string(sbuf.size).uC
334
- end
335
-
336
- end
337
-
1
+ module NWRFC
2
+
3
+ # Representation of a data container (function, structure or table)
4
+ # Implements common functions for data containers, such as setting and getting values, tables, structures and
5
+ # takes care of type conversion and calling correct SDK functions to set or get values
6
+ #
7
+ # == Type Conversions
8
+ # To ensure that data is passed correctly to the NW RFC SDK functions, certain conversions are applied to values
9
+ # passed, depending on the type of the field. ABAP supports a number of elementary types, which are listed in the
10
+ #
11
+ # DECFLOAT16 and DECFLOAT34 types are not yet supported.
12
+ #
13
+ # === Inbound
14
+ # For character and string
15
+ class DataContainer
16
+ attr_reader :handle, :desc
17
+
18
+ def initialize(handle)
19
+ @error = NWRFCLib::RFCError.new
20
+ @handle = handle
21
+ @desc = NWRFCLib.describe_type(@handle, @error)
22
+ @member_metadata = {} #Cache of metadata for members
23
+ NWRFC.check_error(@error)
24
+ end
25
+
26
+ #--
27
+ # VALUE RETRIEVAL
28
+ #++
29
+
30
+ # Get value from a data container (structure, function instance or table)
31
+ def [](element)
32
+ member = element.to_s.upcase
33
+ metadata = member_metadata(element)
34
+ case metadata[:type]
35
+
36
+ when :RFCTYPE_CHAR
37
+ # TODO: Try use :string parameter in get_chars
38
+ return read_chars(metadata)
39
+
40
+ when :RFCTYPE_DATE
41
+ return Date.parse(read_chars(metadata))
42
+ #return Date.new(date[0..3].to_i, date[4..5].to_i, date[6..7].to_i)
43
+
44
+ when :RFCTYPE_BCD
45
+ size = metadata[:nucLength] + (metadata[:decimals] || 0)
46
+ buf = FFI::MemoryPointer.new(:uchar, size*2)
47
+ rc = NWRFCLib.get_chars(@handle, metadata[:name].cU, buf, size, @error.to_ptr)
48
+ NWRFC.check_error(@error) if rc > 0
49
+ return buf.get_bytes(0, size*2).uC.to_f
50
+ #size = metadata[:ucLength]
51
+ #cb = FFI::MemoryPointer.new :char, size * 2
52
+ #rc = NWRFCLib.get_chars(@handle, metadata[:name].cU, cb, size * 2, @error.to_ptr)
53
+ #NWRFC.check_error(@error) if rc > 0
54
+ #cb.read_string(size).uC
55
+
56
+ when :RFCTYPE_TIME
57
+ # TODO: See whether we can optimize this
58
+ timec = read_chars(metadata)
59
+ return Time.parse("#{timec[0..1]}:#{timec[2..3]}:#{timec[4..5]}")
60
+
61
+ when :RFCTYPE_BYTE
62
+ size = metadata[:ucLength]
63
+ buf = FFI::MemoryPointer.new(:uchar, size)
64
+ rc = NWRFCLib.get_bytes(@handle, metadata[:name].cU, buf, size, @error.to_ptr)
65
+ NWRFC.check_error(@error) if rc > 0
66
+ return buf.get_bytes(0, size)
67
+
68
+ when :RFCTYPE_TABLE
69
+ # TODO Cache instances of table members and return those where available
70
+ new_handle = NWRFCLib::RFCDataContainer.new
71
+ rc = NWRFCLib.get_table(@handle, member.cU, new_handle.to_ptr, @error.to_ptr)
72
+ NWRFC.check_error(@error) if rc > 0
73
+ # CAVEAT: Other calls using the handle require "handle" field
74
+ # of the RFC_DATA_CONTAINER struct for some reason.
75
+ new_handle = new_handle[:handle]
76
+ return Table.new(new_handle)
77
+
78
+ when :RFCTYPE_NUM
79
+ return read_chars(metadata)
80
+
81
+ when :RFCTYPE_FLOAT
82
+ double = FFI::MemoryPointer.new :double
83
+ rc = NWRFCLib.get_float(@handle, member.cU, double, @error)
84
+ NWRFC.check_error(@error) if rc > 0
85
+ return double.get_double(0)
86
+
87
+ when :RFCTYPE_INT
88
+ int = FFI::MemoryPointer.new :int
89
+ rc = NWRFCLib.get_int(@handle, member.cU, int, @error)
90
+ NWRFC.check_error(@error) if rc > 0
91
+ return int.get_int(0)
92
+
93
+ when :RFCTYPE_INT2
94
+ short = FFI::MemoryPointer.new :short
95
+ rc = NWRFCLib.get_int2(@handle, member.cU, short, @error)
96
+ NWRFC.check_error(@error) if rc > 0
97
+ return short.get_short(0)
98
+
99
+ when :RFCTYPE_INT1
100
+ int1 = FFI::MemoryPointer.new :uint8
101
+ rc = NWRFCLib.get_int1(@handle, member.cU, int1, @error)
102
+ NWRFC.check_error(@error) if rc > 0
103
+ return int1.get_uint8(0)
104
+
105
+ when :RFCTYPE_NULL
106
+ raise "Unsupported type RFCTYPE_NULL" #You should never run into this
107
+
108
+ when :RFCTYPE_STRUCTURE
109
+ # TODO Cache instances of structure members and return those where available
110
+ new_handle = NWRFCLib::RFCDataContainer.new
111
+ rc = NWRFCLib.get_structure(@handle, member.cU, new_handle.to_ptr, @error.to_ptr)
112
+ NWRFC.check_error(@error) if rc > 0
113
+ new_handle = new_handle[:handle]
114
+ return Structure.new(new_handle)
115
+
116
+ when :RFCTYPE_DECF16
117
+ double = FFI::MemoryPointer.new :double
118
+ rc = NWRFCLib.get_dec_f16(@handle, member.cU, double, @error)
119
+ NWRFC.check_error(@error) if rc > 0
120
+ return double.get_double(0)
121
+
122
+ when :RFCTYPE_DECF34
123
+ double = FFI::MemoryPointer.new :double, 2
124
+ rc = NWRFCLib.get_dec_f34(@handle, member.cU, double, @error)
125
+ NWRFC.check_error(@error) if rc > 0
126
+ return double.get_double(0)
127
+
128
+ when :RFCTYPE_XMLDATA
129
+ raise "Unsupported type RFCTYPE_XMLDATA (no longer used)" #You should never run into this
130
+
131
+ when :RFCTYPE_STRING
132
+ return read_string(metadata)
133
+
134
+ when :RFCTYPE_XSTRING
135
+ size = FFI::MemoryPointer.new(:uint)
136
+ rc = NWRFCLib.get_string_length(@handle, metadata[:name].cU, size, @error)
137
+ NWRFC.check_error(@error) if rc > 0
138
+ buf_len = size.read_uint
139
+ sbuf = FFI::MemoryPointer.new :uchar, buf_len
140
+ rc = NWRFCLib.get_x_string(@handle, metadata[:name].cU, sbuf, buf_len, size, @error)
141
+ NWRFC.check_error(@error) if rc > 0
142
+ return sbuf.read_string(sbuf.size)
143
+
144
+ else
145
+ raise "Illegal member type #{metadata[:type]}"
146
+ end
147
+
148
+ end
149
+
150
+ #--
151
+ # VALUE STORAGE
152
+ #++
153
+
154
+ # Set value on a data container (structure, function instance or table)
155
+ def []=(element, value)
156
+ member = element.to_s.upcase
157
+ metadata = member_metadata(element)
158
+ case metadata[:type]
159
+
160
+ when :RFCTYPE_CHAR
161
+ value = value.to_s
162
+ NWRFCLib.set_chars(@handle, member.cU, value.cU, value.length, @error.to_ptr)
163
+
164
+ when :RFCTYPE_DATE
165
+ value = value_to_date(value)
166
+ NWRFCLib.set_date(@handle, member.cU, value.cU, @error.to_ptr)
167
+
168
+ when :RFCTYPE_BCD
169
+ stval = value.to_s.cU
170
+ m = FFI::MemoryPointer.from_string stval
171
+ NWRFCLib.set_string(@handle, member.cU, m, value.to_s.size, @error)
172
+
173
+ when :RFCTYPE_TIME
174
+ value = value_to_time(value)
175
+ NWRFCLib.set_time(@handle, member.cU, value.cU, @error.to_ptr)
176
+
177
+ when :RFCTYPE_BYTE
178
+ m = FFI::MemoryPointer.from_string value.to_s
179
+ NWRFCLib.set_bytes(@handle, member.cU, m, value.to_s.size, @error.to_ptr)
180
+
181
+ when :RFCTYPE_TABLE
182
+ raise "Value must be of type table" unless value.class == NWRFC::Table
183
+ NWRFCLib.set_table(@handle, member.cU, value.handle, @error)
184
+
185
+ when :RFCTYPE_NUM
186
+ value = value.to_s
187
+ NWRFCLib.set_num(@handle, member.cU, value.cU, value.length, @error.to_ptr)
188
+
189
+ when :RFCTYPE_FLOAT
190
+ NWRFCLib.set_float(@handle, member.cU, value.to_f, @error.to_ptr)
191
+
192
+ when :RFCTYPE_INT
193
+ NWRFCLib.set_int(@handle, member.cU, value.to_i, @error.to_ptr)
194
+
195
+ when :RFCTYPE_INT2
196
+ NWRFCLib.set_int2(@handle, member.cU, value.to_i, @error.to_ptr)
197
+
198
+ when :RFCTYPE_INT1
199
+ NWRFCLib.set_int1(@handle, member.cU, value.to_i, @error.to_ptr)
200
+
201
+ when :RFCTYPE_NULL
202
+ raise "Unsupported type RFCTYPE_NULL" #You should never run into this
203
+
204
+ when :RFCTYPE_STRUCTURE
205
+ raise "Value must be of type table" unless value.class == NWRFC::Structure
206
+ NWRFCLib.set_structure(@handle, member.cU, value.handle, @error)
207
+
208
+ when :RFCTYPE_DECF16
209
+ raise "#{@members[:type]}: decfloat16 not supported yet"
210
+ double = NWRFCLib::RFC_DECF16.new #FFI::MemoryPointer.new :double
211
+ double[:align] = value.to_f
212
+ #double.put_double(0, value.to_f)
213
+ #double = FFI::Pointer.new 4
214
+ NWRFCLib.set_dec_f16(@handle, member.cU, double.pointer, @error)
215
+
216
+ when :RFCTYPE_DECF34
217
+ raise "#{@members[:type]}: decfloat34 not supported yet"
218
+ # double = FFI::MemoryPointer.new :double, 2
219
+ # double.put_double(0, value.to_f)
220
+ double = NWRFCLib::RFC_DECF34.new #FFI::MemoryPointer.new :double
221
+ double[:align] = value.to_f
222
+ NWRFCLib.set_dec_f34(@handle, member.cU, double, @error)
223
+
224
+ when :RFCTYPE_XMLDATA
225
+ raise "Unsupported type RFCTYPE_XMLDATA (no longer used)" #You should never run into this
226
+
227
+ when :RFCTYPE_STRING
228
+ stval = value.cU
229
+ m = FFI::MemoryPointer.from_string stval
230
+ NWRFCLib.set_string(@handle, member.cU, m, value.size, @error)
231
+
232
+ when :RFCTYPE_XSTRING
233
+ m = FFI::MemoryPointer.new value.size
234
+ m.put_bytes 0, value
235
+ NWRFCLib.set_x_string(@handle, member.cU, m, value.size, @error)
236
+
237
+ else
238
+ raise "Illegal member type #{@members[:type]}"
239
+ end
240
+ NWRFC.check_error(@error)
241
+ end
242
+
243
+ # Return value as a SAP-formatted date ("YYYYMMDD"). Force value to fit into 8 chars by
244
+ # truncating or padding with spaces
245
+ def value_to_date(value)
246
+ return value.strftime(NW_DATE_FORMAT) if value.respond_to? :strftime
247
+ # Force the resulting string into 8 characters otherwise
248
+ value = value.to_s
249
+ value << ' ' until value.size == 8 if value.size < 8
250
+ value = value[0..7] if value.size > 8
251
+ value
252
+ end
253
+
254
+ # Return value as a SAP-formatted time ("HHMMSS"). Force value to fit into 6 chars by
255
+ # truncating or padding with spaces
256
+ def value_to_time(value)
257
+ return value.strftime(NW_TIME_FORMAT) if value.respond_to? :strftime
258
+ # Force the resulting string into 6 characters otherwise
259
+ value = value.to_s
260
+ value << ' ' until value.size == 6 if value.size < 6
261
+ value = value[0..6] if value.size > 6
262
+ value
263
+ end
264
+
265
+ # Return a list (array) of symbols representing the names of the fields (or parameters, in the case of a function)
266
+ # of this data container
267
+ def fields
268
+ fc = FFI::MemoryPointer.new(:uint)
269
+ rc = NWRFCLib.get_field_count(@desc, fc, @error)
270
+ NWRFC.check_error(@error) if rc > 0
271
+ fc = fc.read_uint
272
+ fd = NWRFCLib::RFCFieldDesc.new
273
+ # Make a list of field names
274
+ fc.times.inject([]) {|array, index|
275
+ rc = NWRFCLib.get_field_desc_by_index(@desc, index, fd.to_ptr, @error.to_ptr)
276
+ NWRFC.check_error(@error) if rc > 0
277
+ #@todo WARNING! our get_str method did not handle getting the name of the RESPTEXT parameter in STFC_DEEP_TABLE correctly
278
+ # As a workaround, we use our read_string_dn method; do we need to use this elsewhere?
279
+ #array << fd[:name].get_str.to_sym #<-The code with good intentions
280
+ array << fd[:name].to_ptr.read_string_dn.uC.to_sym #<- Workaround; the way of the future?
281
+ }
282
+ end
283
+
284
+ # Get the metadata of a member (function, structure or table)
285
+ def member_metadata(member_name)
286
+ # TODO: Cache metadata definitions; will it be quicker than making a hash of metadata for a given member each time?
287
+ member = member_name.to_s.upcase
288
+ if self.class == NWRFC::FunctionCall
289
+ fpar = NWRFCLib::RFCFuncParam.new
290
+ rc = NWRFCLib.get_parameter_desc_by_name(@desc, member.cU, fpar.to_ptr, @error.to_ptr)
291
+ NWRFC.check_error(@error) if rc > 0
292
+ member_to_hash(fpar)
293
+ elsif self.class == NWRFC::Table || self.class == NWRFC::Structure
294
+ fd = NWRFCLib::RFCFieldDesc.new
295
+ rc = NWRFCLib.get_field_desc_by_name(@desc, member.cU, fd.to_ptr, @error.to_ptr)
296
+ NWRFC.check_error(@error) if rc > 0
297
+ member_to_hash(fd)
298
+ end
299
+ end
300
+
301
+
302
+
303
+ private
304
+ # Returns the subset of metadata values common to both a function parameter
305
+ # and a type field
306
+ def member_to_hash(member)
307
+ {
308
+ :name => member[:name].get_str,
309
+ :type => NWRFCLib::RFC_TYPE[member[:type]],
310
+ :nucLength => member[:nucLength],
311
+ :ucLength => member[:ucLength],
312
+ :decimals => member[:decimals],
313
+ :typeDescHandle => member[:typeDescHandle]
314
+ }
315
+ end
316
+
317
+ def read_chars(metadata)
318
+ size = metadata[:ucLength]
319
+ cb = FFI::MemoryPointer.new :char, size
320
+ rc = NWRFCLib.get_chars(@handle, metadata[:name].cU, cb, metadata[:nucLength], @error.to_ptr)
321
+ NWRFC.check_error(@error) if rc > 0
322
+ cb.read_string(size).uC
323
+ end
324
+
325
+ def read_string(metadata)
326
+ size = FFI::MemoryPointer.new(:uint)
327
+ rc = NWRFCLib.get_string_length(@handle, metadata[:name].cU, size, @error)
328
+ NWRFC.check_error(@error) if rc > 0
329
+ buf_len = size.read_uint + 1
330
+ sbuf = FFI::MemoryPointer.new :char, buf_len * NWRFCLib::B_SIZE
331
+ rc = NWRFCLib.get_string(@handle, metadata[:name].cU, sbuf, buf_len, size, @error)
332
+ NWRFC.check_error(@error) if rc > 0
333
+ sbuf.read_string(sbuf.size).uC
334
+ end
335
+
336
+ end
337
+
338
338
  end