rbind 0.0.26 → 0.0.27

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46980738979a4fdad06df4d7e4b0c7575c78fc4e
4
- data.tar.gz: 8d9c115d8f4796b04e2454129c0d843c1362f727
3
+ metadata.gz: 35c0ae5064a1ce8f8300cd4c05a55023ea335709
4
+ data.tar.gz: 199b59b9b1276492efc6c8dc1ae647f1767948f5
5
5
  SHA512:
6
- metadata.gz: 1e1f14419e0c7671ba60aecdc2f6b908c07e6f6dd52599e67594cb82021f724e0de826bbda44e48caa15b0f028f62923590aee55d82f4b182d6fe88e788a4c4f
7
- data.tar.gz: 6f09249e83aa24141ab16847c4961825f3d3731386e9d69e46ee27326ca7ae298d316d33d65490aaa9aa6466a26c0b7e1815e1ad0cb81232ec6788d15b88d916
6
+ metadata.gz: 1cdc8e6a92bf75d18c22b51e2bb8f109eba3d40e7ea098ec06ecef746cb42266c6b6fe9970f4287d16ea567eb3770b3909c0103473aca774e386436ed9d66602
7
+ data.tar.gz: 9a7da3274763ca86e8d898b8f941d58a802daa7b3c6a6dda3fdded7bbe307c8fea0dc423f130f303cfb996e26653d3f2df1c4fd5cf1ca84ff77d7d3cc7a32fb3
@@ -0,0 +1,57 @@
1
+ require 'set'
2
+
3
+ module Hooks
4
+ module ClassMethods
5
+ def define_hook(name)
6
+ name = name.to_sym
7
+ @hook_names << name
8
+ instance_eval %Q{
9
+ def #{name}(&block)
10
+ @hook_callbacks[:#{name}] << block
11
+ end
12
+ }
13
+ end
14
+
15
+ def __initialize
16
+ @hook_names ||= Set.new
17
+ @hook_callbacks ||= Hash.new do |h,k|
18
+ h[k] = Array.new
19
+ end
20
+ end
21
+
22
+ def callbacks_for_hook(name)
23
+ name = name.to_sym
24
+ raise ArgumentError,"hook #{name} is not known" unless hook?(name)
25
+ if @hook_callbacks.has_key?(name)
26
+ @hook_callbacks[name]
27
+ else
28
+ []
29
+ end
30
+ end
31
+
32
+ def hook?(name)
33
+ name = name.to_sym
34
+ if @hook_names.include?(name)
35
+ true
36
+ else
37
+ false
38
+ end
39
+ end
40
+
41
+ def callback?(name)
42
+ !callbacks_for_hook(name).empty?
43
+ end
44
+
45
+ def run_hook(name,*args)
46
+ callbacks = callbacks_for_hook(name)
47
+ callbacks.map do |c|
48
+ c.call(*args)
49
+ end
50
+ end
51
+ end
52
+
53
+ def self.included(base)
54
+ base.extend ClassMethods
55
+ base.__initialize
56
+ end
57
+ end
@@ -0,0 +1,14 @@
1
+
2
+ module Rbind
3
+ class RCastOperation < ROperation
4
+ extend ::Rbind::Logger
5
+ def initialize(name,to_class,from_class=nil)
6
+ para = []
7
+ if(from_class)
8
+ @static = true
9
+ para << RParameter.new("ptr",from_class.to_ptr)
10
+ end
11
+ super(name,to_class.to_ptr,para)
12
+ end
13
+ end
14
+ end
@@ -3,21 +3,28 @@ module Rbind
3
3
  class RClass < RNamespace
4
4
  attr_reader :parent_classes
5
5
  attr_reader :attributes
6
+ attr_accessor :polymorphic
6
7
  ParentClass = Struct.new(:type,:accessor)
8
+ ChildClass = Struct.new(:type,:accessor)
7
9
 
8
10
  def initialize(name,*parent_classes)
11
+ super(name)
9
12
  @parent_classes = Hash.new
13
+ @child_classes = Hash.new
10
14
  @attributes = Hash.new
11
15
  parent_classes.flatten!
12
16
  parent_classes.each do |p|
13
17
  add_parent(p)
14
18
  end
15
- super(name)
16
19
  # we have to disable the type check for classes
17
20
  # otherwise derived types cannot be parsed
18
21
  @check_type = false
19
22
  end
20
23
 
24
+ def polymorphic?
25
+ !!@polymorphic
26
+ end
27
+
21
28
  def basic_type?
22
29
  false
23
30
  end
@@ -50,7 +57,7 @@ module Rbind
50
57
  def attributes
51
58
  attribs = @attributes.values
52
59
  parent_classes.each do |k|
53
- others = k.type.attributes
60
+ others = k.attributes
54
61
  others.delete_if do |other|
55
62
  attribs.inclue? other
56
63
  end
@@ -67,7 +74,7 @@ module Rbind
67
74
  attrib = @attributes[name]
68
75
  attrib ||= begin
69
76
  p = parent_classes.find do |k|
70
- k.type.attribute(name)
77
+ k.attribute(name)
71
78
  end
72
79
  a = p.attribute(name).dup if p
73
80
  a.owner = self if a
@@ -79,7 +86,11 @@ module Rbind
79
86
  # temporarily add all base class operations
80
87
  own_ops = @operations.dup
81
88
  parent_classes.each do |k|
82
- k.type.operations.each do |other_ops|
89
+ add_operation RCastOperation.new("castTo#{k.name}",k)
90
+ if k.polymorphic?
91
+ add_operation RCastOperation.new("castFrom#{k.name}",self,k)
92
+ end
93
+ k.operations.each do |other_ops|
83
94
  next if other_ops.empty?
84
95
  ops = if @operations.has_key?(other_ops.first.name)
85
96
  @operations[other_ops.first.name]
@@ -116,7 +127,7 @@ module Rbind
116
127
  def used_namespaces
117
128
  namespaces = super.clone
118
129
  parent_classes.each do |k|
119
- namespaces += k.type.used_namespaces
130
+ namespaces += k.used_namespaces
120
131
  end
121
132
  namespaces
122
133
  end
@@ -128,7 +139,7 @@ module Rbind
128
139
  []
129
140
  end
130
141
  parent_classes.each do |k|
131
- other_ops = Array(k.type.operation(name,false))
142
+ other_ops = Array(k.operation(name,false))
132
143
  other_ops.delete_if do |other_op|
133
144
  ops.include? other_op
134
145
  end
@@ -163,10 +174,17 @@ module Rbind
163
174
  str = "#{"template " if template?}class #{full_name}"
164
175
  unless parent_classes.empty?
165
176
  parents = parent_classes.map do |p|
166
- p.type.full_name
177
+ p.full_name
167
178
  end
168
179
  str += " : " + parents.join(", ")
169
180
  end
181
+ unless child_classes.empty?
182
+ childs = child_classes.map do |c|
183
+ c.full_name
184
+ end
185
+ str += " Childs: " + childs.join(", ")
186
+ end
187
+
170
188
  str
171
189
  end
172
190
 
@@ -192,24 +210,89 @@ module Rbind
192
210
  else
193
211
  [klass,accessor]
194
212
  end
195
- if @parent_classes.has_key? klass.name
213
+ if !klass.name || klass.name.empty?
214
+ raise ArgumentError, "klass name is empty"
215
+ end
216
+ if parent? klass
196
217
  raise ArgumentError,"#A parent class with the name #{klass.name} already exists"
197
218
  end
198
219
  if klass.full_name == full_name || klass == self
199
220
  raise ArgumentError,"class #{klass.full_name} cannot be parent of its self"
200
221
  end
201
222
  @parent_classes[klass.name] = ParentClass.new(klass,accessor)
223
+ klass.add_child(self,accessor) unless klass.child?(self)
202
224
  self
203
225
  end
204
226
 
227
+ def parent?(name)
228
+ name = if name.respond_to?(:name)
229
+ name.name
230
+ else
231
+ name
232
+ end
233
+ @parent_classes.key?(name)
234
+ end
235
+
205
236
  def parent_class(name)
237
+ name = if name.respond_to?(:name)
238
+ name.name
239
+ else
240
+ name
241
+ end
206
242
  @parent_class[name].type
207
243
  end
208
244
 
209
245
  def parent_classes(accessor = :public)
210
- @parent_classes.values.find_all do |k|
211
- k.accessor = accessor
246
+ parents = @parent_classes.values.find_all do |k|
247
+ k.accessor == accessor
248
+ end
249
+ parents.map(&:type)
250
+ end
251
+
252
+ def add_child(klass,accessor=:public)
253
+ klass,accessor = if klass.is_a?(ChildClass)
254
+ [klass.type,klass.accessor]
255
+ else
256
+ [klass,accessor]
257
+ end
258
+ if !klass.name || klass.name.empty?
259
+ raise ArgumentError, "klass name is empty"
260
+ end
261
+ if child? klass
262
+ raise ArgumentError,"#A child class with the name #{klass.name} already exists"
263
+ end
264
+ if klass.full_name == full_name || klass == self
265
+ raise ArgumentError,"class #{klass.full_name} cannot be child of its self"
266
+ end
267
+ @polymorphic ||= true
268
+ @child_classes[klass.name] = ChildClass.new(klass,accessor)
269
+ klass.add_parent(self,accessor) unless klass.parent?(self)
270
+ self
271
+ end
272
+
273
+ def child?(name)
274
+ name = if name.respond_to?(:name)
275
+ name.name
276
+ else
277
+ name
278
+ end
279
+ @child_classes.key?(name)
280
+ end
281
+
282
+ def child_class(name)
283
+ name = if name.respond_to?(:name)
284
+ name.name
285
+ else
286
+ name
287
+ end
288
+ @child_classes[name].type
289
+ end
290
+
291
+ def child_classes(accessor = :public)
292
+ childs = @child_classes.values.find_all do |k|
293
+ k.accessor == accessor
212
294
  end
295
+ childs.map(&:type)
213
296
  end
214
297
  end
215
298
  end
@@ -203,6 +203,20 @@ module Rbind
203
203
  end
204
204
  end
205
205
 
206
+ def used_extern_types
207
+ extern = Set.new
208
+ each_operation do |op|
209
+ extern << op.return_type.to_raw if op.return_type && op.return_type.extern?
210
+ op.parameters.each do |arg|
211
+ extern << arg.type.to_raw if arg.type.extern?
212
+ end
213
+ end
214
+ each_container do |type|
215
+ extern += type.used_extern_types
216
+ end
217
+ extern
218
+ end
219
+
206
220
  def operations
207
221
  @operations.values
208
222
  end
@@ -341,6 +355,10 @@ module Rbind
341
355
  type
342
356
  end
343
357
 
358
+ def type?(name,search_owner = true)
359
+ !type(name,false,search_owner).nil?
360
+ end
361
+
344
362
  def type(name,raise_ = true,search_owner = true)
345
363
  name = name.to_s
346
364
  constant = if name =~ /const /
@@ -428,8 +446,8 @@ module Rbind
428
446
  end
429
447
  end
430
448
  if !t && raise_
431
- if self.class.callbacks_for_hook(:on_type_not_found)
432
- results = self.run_hook(:on_type_not_found,self,name)
449
+ if RNamespace.callbacks_for_hook(:on_type_not_found)
450
+ results = RNamespace.run_hook(:on_type_not_found,self,name)
433
451
  t = results.find do |t|
434
452
  t.respond_to?(:type)
435
453
  end
data/lib/rbind/core.rb CHANGED
@@ -1,11 +1,12 @@
1
- require 'hooks'
2
1
  require 'rbind/logger.rb'
2
+ require 'rbind/core/hooks.rb'
3
3
  require 'rbind/core/rbase.rb'
4
4
  require 'rbind/core/rdata_type.rb'
5
5
  require 'rbind/core/renum.rb'
6
6
  require 'rbind/core/rattribute.rb'
7
7
  require 'rbind/core/rparameter.rb'
8
8
  require 'rbind/core/roperation.rb'
9
+ require 'rbind/core/rcast_operation.rb'
9
10
  require 'rbind/core/rgetter.rb'
10
11
  require 'rbind/core/rsetter.rb'
11
12
  require 'rbind/core/rnamespace.rb'
@@ -61,7 +61,7 @@ module Rbind
61
61
  end
62
62
  end
63
63
 
64
- def find_type(owner,type_name)
64
+ def find_type(owner,type_name,braise=true)
65
65
  type_name = unmask_template(type_name)
66
66
  t = owner.type(type_name,false)
67
67
  return t if t
@@ -81,7 +81,7 @@ module Rbind
81
81
  return t if t
82
82
 
83
83
  #search again even if we know the type is not there to create a proper error message
84
- owner.type(type_name,true)
84
+ owner.type(type_name,true) if braise
85
85
  end
86
86
 
87
87
  def parameter(line_number,string,owner = self)
@@ -113,7 +113,13 @@ module Rbind
113
113
  array = flags.shift.split(" ")
114
114
  type_name = array[0]
115
115
  name = array[1]
116
- type = find_type(owner,type_name)
116
+ type = find_type(owner,type_name,false)
117
+ # auto embedded types
118
+ type ||= begin
119
+ t = owner.add_type(RClass.new(RBase.normalize(type_name)))
120
+ t.extern_package_name = @extern_package_name
121
+ t
122
+ end
117
123
  flags = normalize_flags(line_number,flags,:RW,:R)
118
124
  a = RAttribute.new(name,type)
119
125
  a.writeable!(true) if flags.include? :RW
@@ -156,25 +162,11 @@ module Rbind
156
162
  end
157
163
  end
158
164
  flags = if flags
159
- normalize_flags(line_number,flags.gsub(" ","").split("/").compact,:Simple)
165
+ normalize_flags(line_number,flags.gsub(" ","").split("/").compact,:Simple,:Map)
160
166
  end
161
167
  t = RClass.new(name,*parent_classes)
162
168
  t.extern_package_name = @extern_package_name
163
- t = if t2 = type(t.full_name,false)
164
- if !t2.is_a?(RClass) || (!t2.parent_classes.empty? && t2.parent_classes != t.parent_classes)
165
- raise "Cannot add class #{t.full_name}. A different type #{t2} is already registered"
166
- else
167
- t.parent_classes.each do |p|
168
- t2.add_parent p
169
- end
170
- t2.extern_package_name = t.extern_package_name
171
- t2
172
- end
173
- else
174
- t.name = t.name.gsub(">>","> >")
175
- add_type(t)
176
- t
177
- end
169
+ t = add_type(t)
178
170
  line_counter = 1
179
171
  lines.each do |line|
180
172
  a = attribute(line_counter+line_number,line,t)
@@ -186,6 +178,24 @@ module Rbind
186
178
  raise "input line #{line_number}: #{e}"
187
179
  end
188
180
 
181
+ def add_type(klass)
182
+ if klass2 = type(klass.full_name,false)
183
+ if !klass2.is_a?(RClass) || (!klass2.parent_classes.empty? && klass2.parent_classes != klass.parent_classes)
184
+ raise "Cannot add class #{klass.full_name}. A different type #{klass2} is already registered"
185
+ else
186
+ klass.parent_classes.each do |p|
187
+ klass2.add_parent p
188
+ end
189
+ klass2.extern_package_name = klass.extern_package_name
190
+ klass2
191
+ end
192
+ else
193
+ klass.name = klass.name.gsub(">>","> >")
194
+ super(klass)
195
+ klass
196
+ end
197
+ end
198
+
189
199
  def parse_struct(line_number,string)
190
200
  a = string.split("\n")
191
201
  first_line = a.shift
@@ -193,7 +203,7 @@ module Rbind
193
203
  name = flags.shift.split(" ")[1]
194
204
  flags = normalize_flags(line_number,flags)
195
205
  klass = RClass.new(name)
196
- add_type(klass)
206
+ klass = add_type(klass)
197
207
  line_counter = 1
198
208
  a.each do |line|
199
209
  a = attribute(line_counter+line_number,line,klass)
@@ -280,7 +290,9 @@ module Rbind
280
290
  @extern_package_name = extern_package_name
281
291
 
282
292
  a = split(string)
283
- a.pop #remove number at the end of the file
293
+ #remove number at the end of the file
294
+ a.pop if a.last.to_i != 0
295
+
284
296
  line_number = 1
285
297
  a.each do |block|
286
298
  begin
@@ -305,15 +317,20 @@ module Rbind
305
317
  break
306
318
  end
307
319
  end
320
+ a.size
308
321
  end
309
322
 
310
323
  def split(string)
311
324
  array = []
312
- string.each_line do |line|
313
- if !line.empty? && line[0] != " "
314
- array << line
315
- else
316
- array[array.size-1] = array.last + line
325
+ if string
326
+ string.each_line do |line|
327
+ if line == "\n" || line.empty?
328
+ next
329
+ elsif line[0] != " "
330
+ array << line
331
+ elsif !array.empty?
332
+ array[array.size-1] = array.last + line
333
+ end
317
334
  end
318
335
  end
319
336
  array