gir_ffi 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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