nwrfc 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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