Module: Wrapture

Defined in:
lib/wrapture.rb,
lib/wrapture/version.rb,
lib/wrapture/wrapper.rb,
lib/wrapture/validator.rb,
lib/wrapture/class_spec.rb

Defined Under Namespace

Classes: ClassSpec

Constant Summary collapse

VERSION =
'0.1.0'

Class Method Summary collapse

Class Method Details

.normalize_spec(spec) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
# File 'lib/wrapture/validator.rb', line 3

def self.normalize_spec(spec)

  normalized_spec = Hash.new
  normalized_spec['classes'] = Array.new

  spec['classes'].each do |class_spec|
    normalized_spec['classes'] << ClassSpec.normalize_spec_hash(class_spec)
  end

  return normalized_spec

end

.wrap_class(class_spec) ⇒ Object



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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/wrapture/wrapper.rb', line 3

def self.wrap_class( class_spec )

  spec = ClassSpec.new class_spec
  spec.generate_wrappers

  class_name = class_spec['name']
  struct_name = class_spec['equivalent-struct']['name']

  # generating constructor signatures
  constructor_signatures = Array.new
  equivalent_name = 'equivalent'
  equivalent_struct = 'this->equivalent'
  equivalent_struct_pointer = '&this->equivalent'
  member_operator = '.'

  class_spec['constructors'].each do |constructor_spec|
    if constructor_spec['wrapped-function']['return']['type'] == 'equivalent-struct-pointer'
      equivalent_name = '*equivalent'
      equivalent_struct = '*(this->equivalent)'
      equivalent_struct_pointer = 'this->equivalent'
      member_operator = '->'
    end

    params = Array.new
    constructor_spec['wrapped-function']['params'].each do |param|
      params << "#{param['type']} #{param['name']}"
    end

    constructor_signatures << "#{class_name}( #{params.join ', '} )"
  end

  members = Array.new
  class_spec['equivalent-struct']['members'].each do |member|
    members << "#{member['type']} #{member['name']}"
  end

  member_constructor_signature = "#{class_name}( #{members.join ', '} )"
  struct_constructor_signature = "#{class_name}( struct #{struct_name} equivalent )"
  pointer_constructor_signature = "#{class_name}( const struct #{struct_name} *equivalent )"

  # get the list of includes for declarations
  declaration_includes = class_spec['equivalent-struct']['includes'].dup
  class_spec['functions'].each do |function_spec|
    declaration_includes.concat function_spec['return']['includes']
  end
  declaration_includes.uniq!

  # generate the header file
  File.open("#{class_name}.hpp", 'w') do |file|
    # header guard
    file.puts "#ifndef __#{class_name.upcase}_HPP"
    file.puts "#define __#{class_name.upcase}_HPP"

    file.puts

    declaration_includes.each do |include_file|
      file.puts "#include <#{include_file}>"
    end

    file.puts unless declaration_includes.empty?

    file.puts "namespace #{class_spec['namespace']} {"
    file.puts "  class #{class_name} {"
    file.puts '  public:'

    class_spec['constants'].each do |constant_spec|
      file.puts "    static const #{constant_spec['type']} #{constant_spec['name']};"
    end
    file.puts unless class_spec['constants'].empty?

    file.puts "    struct #{struct_name} #{equivalent_name};"
    file.puts

    constructor_signatures.each do |signature|
      file.puts "    #{signature};"
    end

    unless members.empty?
      file.puts "    #{member_constructor_signature};"
    end

    file.puts "    #{struct_constructor_signature};"
    file.puts "    #{pointer_constructor_signature};"

    class_spec['equivalent-struct']['members'].each do |member|
      file.puts "    #{member['type']} Get#{member['name'].capitalize}( void ) const;"
      file.puts "    void Set#{member['name'].capitalize}( #{member['type']} #{member['name']} );"
    end

    class_spec['functions'].each do |function_spec|
      static_modifier = if function_spec['static'] then 'static ' else '' end
      file.write "    #{static_modifier}#{function_spec['return']['type']} #{function_spec['name']}( "

      wrapped_params = Array.new
      function_spec['params'].each do |param|
        wrapped_params << "#{param['type']} #{param['name']}"
      end
      file.write(wrapped_params.join ', ')

      file.puts ' );'
    end

    # destructor
    unless class_spec['destructor'].nil?
      file.puts "    ~#{class_name}( void );"
    end

    file.puts '  };' # end of class
    file.puts '}' # end of namespace
    file.puts '#endif' # end of header guard
  end

  # get the complete list of includes for definitions
  definition_includes = Array.new
  definition_includes << "#{class_name}.hpp"
  class_spec['functions'].each do |function_spec|
    definition_includes.concat function_spec['return']['includes']
    definition_includes.concat function_spec['wrapped-function']['includes']
  end

  class_spec['constants'].each do |constant_spec|
    definition_includes.concat constant_spec['includes']
  end
  definition_includes.uniq!

  # generate the definition file
  File.open("#{class_name}.cpp", 'w') do |file|
    definition_includes.each do |include_file|
      file.puts "#include <#{include_file}>"
    end

    file.puts
    file.puts "namespace #{class_spec['namespace']} {"

    # constants
    class_spec['constants'].each do |constant_spec|
      file.puts
      file.puts "  const #{constant_spec['type']} #{class_name}::#{constant_spec['name']} = #{constant_spec['value']};"
    end

    # constructors
    class_spec['constructors'].each_index do |i|
      wrapped_function = class_spec['constructors'][i]['wrapped-function']
      function_params = Array.new
      wrapped_function['params'].each do |param|
        function_params << param['name']
      end

      file.puts
      file.puts "  #{class_name}::#{constructor_signatures[i]} {"
      file.write('    ')
      case wrapped_function['return']['type']
      when 'equivalent-struct'
        file.write(equivalent_struct)
      when 'equivalent-struct-pointer'
        file.write(equivalent_struct_pointer)
      end
      file.puts " = #{wrapped_function['name']}( #{function_params.join ', '} );"
      file.puts '  }'
    end

    unless members.empty?
      file.puts
      file.puts "  #{class_name}::#{member_constructor_signature} {"
      class_spec['equivalent-struct']['members'].each do |member|
        file.puts "    this->equivalent#{member_operator}#{member['name']} = #{member['name']};"
      end
      file.puts '  }' # end of the member constructor
    end

    file.puts
    file.puts "  #{class_name}::#{struct_constructor_signature} {"
    class_spec['equivalent-struct']['members'].each do |member|
      file.puts "    this->equivalent#{member_operator}#{member['name']} = equivalent.#{member['name']};"
    end
    file.puts '  }' # end of struct conversion

    file.puts
    file.puts "  #{class_name}::#{pointer_constructor_signature} {"
    class_spec['equivalent-struct']['members'].each do |member|
      file.puts "    this->equivalent#{member_operator}#{member['name']} = equivalent->#{member['name']};"
    end
    file.puts '  }' # end of pointer conversion

    class_spec['equivalent-struct']['members'].each do |member|
      file.puts # line to separate from previous functions
      file.puts "  #{member['type']} #{class_name}::Get#{member['name'].capitalize}( void ) const {"
      file.puts "    return this->equivalent#{member_operator}#{member['name']};"
      file.puts '  }'
      file.puts
      file.puts "  void #{class_name}::Set#{member['name'].capitalize}( #{member['type']} #{member['name']} ) {"
      file.puts "    this->equivalent#{member_operator}#{member['name']} = #{member['name']};"
      file.puts '  }'
    end

    class_spec['functions'].each do |function_spec|
      file.puts
      file.write "  #{function_spec['return']['type']} #{class_name}::#{function_spec['name']}( "

      wrapped_params = Array.new
      function_spec['params'].each do |param|
        wrapped_params << "#{param['type']} #{param['name']}"
      end
      file.write(wrapped_params.join ', ')

      file.puts ' ) {'

      # the function body
      if function_spec['return']['type'] == 'void'
        file.write "    #{function_spec['wrapped-function']['name']}( "
      else
        file.write "    return #{function_spec['return']['type']}( #{function_spec['wrapped-function']['name']}( "
      end

      # building the parameters
      wrapped_params = Array.new
      function_spec['wrapped-function']['params'].each do |param|
        case param['name']
        when 'equivalent-struct'
          wrapped_params << equivalent_struct
        when 'equivalent-struct-pointer'
          wrapped_params << equivalent_struct_pointer
        else
          wrapped_params << param['name']
        end
      end
      file.write(wrapped_params.join ', ')

      if function_spec['return']['type'] == 'void'
        file.puts ' );'
      else
        file.puts ' ) );'
      end
      file.puts '  }'
    end

    # destructor
    unless class_spec['destructor'].nil?
      file.puts
      file.puts "  #{class_name}::~#{class_name}( void ) {"
      file.write("    #{class_spec['destructor']['wrapped-function']['name']}( ")
      wrapped_params = Array.new
      class_spec['destructor']['wrapped-function']['params'].each do |param|
        case param['name']
        when 'equivalent-struct'
          wrapped_params << equivalent_struct
        when 'equivalent-struct-pointer'
          wrapped_params << equivalent_struct_pointer
        else
          wrapped_params << param['name']
        end
      end
      file.write(wrapped_params.join ', ')
      file.puts ' );'
      file.puts '  }'
    end

    file.puts # line after last function
    file.puts '}' # end of namespace
  end

end