gir_ffi 0.0.6 → 0.0.7

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,382 +0,0 @@
1
- module GirFFI
2
- # Abstract parent class of the argument building classes. These classes
3
- # are used by FunctionDefinitionBuilder to create the code that processes
4
- # each argument before and after the actual function call.
5
- class ArgumentBuilder
6
- KEYWORDS = [
7
- "alias", "and", "begin", "break", "case", "class", "def", "do",
8
- "else", "elsif", "end", "ensure", "false", "for", "if", "in",
9
- "module", "next", "nil", "not", "or", "redo", "rescue", "retry",
10
- "return", "self", "super", "then", "true", "undef", "unless",
11
- "until", "when", "while", "yield"
12
- ]
13
-
14
- attr_reader :arginfo, :callarg, :pre, :post, :postpost
15
-
16
- attr_accessor :length_arg, :inarg, :retval
17
-
18
- def initialize function_builder, arginfo=nil, libmodule=nil
19
- @arginfo = arginfo
20
- @inarg = nil
21
- @callarg = nil
22
- @retval = nil
23
- @retname = nil
24
- @name = nil
25
- @pre = []
26
- @post = []
27
- @postpost = []
28
- @function_builder = function_builder
29
- @libmodule = libmodule
30
- end
31
-
32
- def self.build function_builder, arginfo, libmodule
33
- klass = case arginfo.direction
34
- when :inout
35
- InOutArgumentBuilder
36
- when :in
37
- InArgumentBuilder
38
- when :out
39
- OutArgumentBuilder
40
- else
41
- raise ArgumentError
42
- end
43
- klass.new function_builder, arginfo, libmodule
44
- end
45
-
46
- def type
47
- @arginfo.type
48
- end
49
-
50
- private
51
-
52
- def safe name
53
- if KEYWORDS.include? name
54
- "#{name}_"
55
- else
56
- name
57
- end
58
- end
59
- end
60
-
61
- # Implements argument processing for arguments with direction :in
62
- class InArgumentBuilder < ArgumentBuilder
63
- def prepare
64
- @name = safe(@arginfo.name)
65
- @callarg = @function_builder.new_var
66
- @inarg = @name
67
- end
68
-
69
- def process
70
- case @arginfo.type.tag
71
- when :interface
72
- process_interface_in_arg
73
- when :void
74
- process_void_in_arg
75
- when :array
76
- process_array_in_arg
77
- when :utf8
78
- process_utf8_in_arg
79
- else
80
- process_other_in_arg
81
- end
82
- end
83
-
84
- private
85
-
86
-
87
- def process_interface_in_arg
88
- arg = @arginfo
89
- type = arg.type
90
-
91
- iface = type.interface
92
- if iface.type == :callback
93
- @pre << "#{@callarg} = GirFFI::ArgHelper.wrap_in_callback_args_mapper \"#{iface.namespace}\", \"#{iface.name}\", #{@inarg}"
94
- @pre << "::#{@libmodule}::CALLBACKS << #{@callarg}"
95
- else
96
- @pre << "#{@callarg} = #{@inarg}"
97
- end
98
- end
99
-
100
- def process_void_in_arg
101
- @pre << "#{@callarg} = GirFFI::ArgHelper.object_to_inptr #{@inarg}"
102
- end
103
-
104
- def process_utf8_in_arg
105
- @pre << "#{@callarg} = GirFFI::ArgHelper.utf8_to_inptr #{@name}"
106
- # TODO:
107
- #@post << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
108
- end
109
-
110
- def process_array_in_arg
111
- arg = @arginfo
112
- type = arg.type
113
-
114
- if type.array_fixed_size > 0
115
- @pre << "GirFFI::ArgHelper.check_fixed_array_size #{type.array_fixed_size}, #{@inarg}, \"#{@inarg}\""
116
- elsif type.array_length > -1
117
- idx = type.array_length
118
- lenvar = @length_arg.inarg
119
- @length_arg.inarg = nil
120
- @length_arg.pre.unshift "#{lenvar} = #{@inarg}.nil? ? 0 : #{@inarg}.length"
121
- end
122
-
123
- tag = arg.type.param_type(0).tag.to_s.downcase
124
- @pre << "#{@callarg} = GirFFI::ArgHelper.#{tag}_array_to_inptr #{@inarg}"
125
- unless arg.ownership_transfer == :everything
126
- if tag == :utf8
127
- @post << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
128
- else
129
- @post << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
130
- end
131
- end
132
- end
133
-
134
- def process_other_in_arg
135
- @pre << "#{@callarg} = #{@name}"
136
- end
137
- end
138
-
139
- # Implements argument processing for arguments with direction :out
140
- class OutArgumentBuilder < ArgumentBuilder
141
- def prepare
142
- @name = safe(@arginfo.name)
143
- @callarg = @function_builder.new_var
144
- @retname = @retval = @function_builder.new_var
145
- end
146
-
147
- def process
148
- case @arginfo.type.tag
149
- when :interface
150
- process_interface_out_arg
151
- when :array
152
- process_array_out_arg
153
- else
154
- process_other_out_arg
155
- end
156
- end
157
-
158
- private
159
-
160
- def process_interface_out_arg
161
- iface = @arginfo.type.interface
162
- klass = "#{iface.namespace}::#{iface.name}"
163
-
164
- if @arginfo.caller_allocates?
165
- @pre << "#{@callarg} = #{klass}.allocate"
166
- @post << "#{@retval} = #{@callarg}"
167
- else
168
- @pre << "#{@callarg} = GirFFI::ArgHelper.pointer_outptr"
169
- @post << "#{@retval} = #{klass}.wrap GirFFI::ArgHelper.outptr_to_pointer(#{@callarg})"
170
- end
171
- end
172
-
173
- def process_array_out_arg
174
- @pre << "#{@callarg} = GirFFI::ArgHelper.pointer_outptr"
175
-
176
- arg = @arginfo
177
- type = arg.type
178
- tag = type.param_type(0).tag
179
- size = type.array_fixed_size
180
- idx = type.array_length
181
-
182
- if size <= 0
183
- if idx > -1
184
- size = @length_arg.retval
185
- @length_arg.retval = nil
186
- else
187
- raise NotImplementedError
188
- end
189
- end
190
-
191
- @postpost << "#{@retval} = GirFFI::ArgHelper.outptr_to_#{tag}_array #{@callarg}, #{size}"
192
-
193
- if arg.ownership_transfer == :everything
194
- if tag == :utf8
195
- @postpost << "GirFFI::ArgHelper.cleanup_ptr_array_ptr #{@callarg}, #{rv}"
196
- else
197
- @postpost << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
198
- end
199
- end
200
- end
201
-
202
- def process_other_out_arg
203
- tag = @arginfo.type.tag
204
- @pre << "#{@callarg} = GirFFI::ArgHelper.#{tag}_outptr"
205
- @post << "#{@retname} = GirFFI::ArgHelper.outptr_to_#{tag} #{@callarg}"
206
- if @arginfo.ownership_transfer == :everything
207
- @post << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
208
- end
209
- end
210
-
211
- end
212
-
213
- # Implements argument processing for arguments with direction :inout
214
- class InOutArgumentBuilder < ArgumentBuilder
215
- def prepare
216
- @name = safe(@arginfo.name)
217
- @callarg = @function_builder.new_var
218
- @inarg = @name
219
- @retname = @retval = @function_builder.new_var
220
- end
221
-
222
- def process
223
- raise NotImplementedError unless @arginfo.ownership_transfer == :everything
224
-
225
- case @arginfo.type.tag
226
- when :interface
227
- process_interface_inout_arg
228
- when :array
229
- process_array_inout_arg
230
- else
231
- process_other_inout_arg
232
- end
233
- end
234
-
235
- private
236
-
237
- def process_interface_inout_arg
238
- raise NotImplementedError
239
- end
240
-
241
- def process_array_inout_arg
242
- arg = @arginfo
243
- tag = arg.type.param_type(0).tag
244
- @pre << "#{@callarg} = GirFFI::ArgHelper.#{tag}_array_to_inoutptr #{@inarg}"
245
- if arg.type.array_length > -1
246
- idx = arg.type.array_length
247
- rv = @length_arg.retval
248
- @length_arg.retval = nil
249
- lname = @length_arg.inarg
250
- @length_arg.inarg = nil
251
- @length_arg.pre.unshift "#{lname} = #{@inarg}.length"
252
- @post << "#{@retval} = GirFFI::ArgHelper.outptr_to_#{tag}_array #{@callarg}, #{rv}"
253
- if tag == :utf8
254
- @post << "GirFFI::ArgHelper.cleanup_ptr_array_ptr #{@callarg}, #{rv}"
255
- else
256
- @post << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
257
- end
258
- else
259
- raise NotImplementedError
260
- end
261
- end
262
-
263
- def process_other_inout_arg
264
- tag = @arginfo.type.tag
265
- @pre << "#{@callarg} = GirFFI::ArgHelper.#{tag}_to_inoutptr #{@inarg}"
266
- @post << "#{@retval} = GirFFI::ArgHelper.outptr_to_#{tag} #{@callarg}"
267
- @post << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
268
- end
269
- end
270
-
271
- # Implements argument processing for return values.
272
- class ReturnValueBuilder < ArgumentBuilder
273
- attr_reader :cvar
274
-
275
- def prepare
276
- return if tag == :void
277
- @cvar = @function_builder.new_var
278
- @retval = @function_builder.new_var
279
- end
280
-
281
- def process
282
- return if tag == :void
283
-
284
- type = @arginfo.return_type
285
-
286
- case tag
287
- when :interface
288
- process_interface_return_value type, @cvar
289
- when :array
290
- process_array_return_value type, @cvar
291
- else
292
- process_other_return_value
293
- end
294
- end
295
-
296
- def type
297
- @arginfo.return_type
298
- end
299
-
300
- private
301
-
302
- def process_interface_return_value type, cvar
303
- interface = type.interface
304
- namespace = interface.namespace
305
- name = interface.name
306
-
307
- case interface.type
308
- when :interface
309
- GirFFI::Builder.build_class namespace, name
310
- @post << "#{@retval} = ::#{namespace}::#{name}.wrap(#{cvar})"
311
- when :object
312
- if @arginfo.constructor?
313
- GirFFI::Builder.build_class namespace, name
314
- @post << "#{@retval} = ::#{namespace}::#{name}.wrap(#{cvar})"
315
- if is_subclass_of_initially_unowned interface
316
- @post << "GirFFI::GObject.object_ref_sink(#{@retval})"
317
- end
318
- else
319
- @post << "#{@retval} = GirFFI::ArgHelper.object_pointer_to_object(#{cvar})"
320
- end
321
- when :struct
322
- GirFFI::Builder.build_class namespace, name
323
- @post << "#{@retval} = ::#{namespace}::#{name}.wrap(#{cvar})"
324
- else
325
- @post << "#{@retval} = #{cvar}"
326
- end
327
- end
328
-
329
- def process_array_return_value type, cvar
330
- tag = type.param_type(0).tag
331
- size = type.array_fixed_size
332
- idx = type.array_length
333
-
334
- if size > 0
335
- @post << "#{@retval} = GirFFI::ArgHelper.ptr_to_#{tag}_array #{cvar}, #{size}"
336
- elsif idx > -1
337
- lendata = @length_arg #@data[idx]
338
- rv = lendata.retval
339
- lendata.retval = nil
340
- @post << "#{@retval} = GirFFI::ArgHelper.ptr_to_#{tag}_array #{cvar}, #{rv}"
341
- end
342
- end
343
-
344
- def process_other_return_value
345
- @retval = @cvar
346
- end
347
-
348
- def tag
349
- type.tag
350
- end
351
-
352
- def is_subclass_of_initially_unowned interface
353
- if interface.namespace == "GObject" and interface.name == "InitiallyUnowned"
354
- true
355
- elsif interface.parent
356
- is_subclass_of_initially_unowned interface.parent
357
- else
358
- false
359
- end
360
- end
361
- end
362
-
363
- # Implements argument processing for error handling arguments. These
364
- # arguments are not part of the introspected signature, but their
365
- # presence is indicated by the 'throws' attribute of the function.
366
- class ErrorHandlerBuilder < ArgumentBuilder
367
- def prepare
368
- @callarg = @function_builder.new_var
369
- end
370
-
371
- def process
372
- @pre << "#{@callarg} = FFI::MemoryPointer.new(:pointer).write_pointer nil"
373
- @post << "GirFFI::ArgHelper.check_error(#{@callarg})"
374
- end
375
- end
376
-
377
- # Argument builder that does nothing. Implements Null Object pattern.
378
- class NullArgumentBuilder < ArgumentBuilder
379
- def prepare; end
380
- def process; end
381
- end
382
- end