/
field_builder.rb
103 lines (82 loc) · 2.81 KB
/
field_builder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
require 'gir_ffi/builders/argument_builder'
require 'gir_ffi/builders/return_value_builder'
require 'gir_ffi/variable_name_generator'
require 'gir_ffi/field_argument_info'
module GirFFI
module Builders
# Creates field getter and setter code for a given IFieldInfo.
class FieldBuilder
attr_reader :info
def initialize field_info
@info = field_info
end
def build
setup_getter
setup_setter
end
def setup_getter
container_class.class_eval getter_def unless container_defines_getter_method?
end
def container_defines_getter_method?
container_info.find_instance_method info.name
end
def setup_setter
container_class.class_eval setter_def if info.writable?
end
def getter_def
builder = return_value_builder
field_ptr = builder.new_variable
typed_ptr = builder.new_variable
<<-CODE.reset_indentation
def #{info.name}
#{field_ptr} = @struct.to_ptr + #{info.offset}
#{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag_or_class}, #{field_ptr})
#{builder.capture_variable_name} = #{typed_ptr}.to_value
#{builder.post_conversion.join("\n")}
#{builder.return_value_name}
end
CODE
end
def setter_def
builder = setter_builder
field_ptr = builder.new_variable
typed_ptr = builder.new_variable
<<-CODE.reset_indentation
def #{info.name}= #{builder.method_argument_name}
#{field_ptr} = @struct.to_ptr + #{info.offset}
#{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag_or_class}, #{field_ptr})
#{builder.pre_conversion.join("\n ")}
#{typed_ptr}.set_value #{builder.call_argument_name}
end
CODE
end
private
def field_type_tag_or_class
@field_type_tag_or_class ||= info.field_type.tag_or_class.inspect
end
def container_class
@container_class ||= container_module.const_get(container_info.safe_name)
end
def container_module
@container_module ||= Object.const_get(container_info.safe_namespace)
end
def container_info
@container_info ||= info.container
end
def field_type
@field_type ||= @info.field_type
end
def field_argument_info
@field_argument_info ||= FieldArgumentInfo.new 'value', field_type
end
def return_value_builder
@rv_builder ||= ReturnValueBuilder.new(VariableNameGenerator.new,
field_argument_info)
end
def setter_builder
@setter_builder ||= ArgumentBuilder.new(VariableNameGenerator.new,
field_argument_info)
end
end
end
end