gir_ffi 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/History.txt +8 -0
  2. data/README.md +1 -1
  3. data/TODO.rdoc +12 -4
  4. data/lib/ffi-glib.rb +0 -5
  5. data/lib/ffi-glib/list.rb +1 -1
  6. data/lib/ffi-glib/s_list.rb +1 -1
  7. data/lib/ffi-gobject.rb +2 -3
  8. data/lib/ffi-gobject/closure.rb +4 -3
  9. data/lib/ffi-gobject_introspection/i_base_info.rb +11 -14
  10. data/lib/ffi-gobject_introspection/i_constant_info.rb +1 -1
  11. data/lib/ffi-gobject_introspection/i_function_info.rb +0 -6
  12. data/lib/ffi-gobject_introspection/lib.rb +8 -2
  13. data/lib/gir_ffi.rb +5 -0
  14. data/lib/gir_ffi/arg_helper.rb +1 -1
  15. data/lib/gir_ffi/argument_builder.rb +161 -0
  16. data/lib/gir_ffi/base_argument_builder.rb +146 -0
  17. data/lib/gir_ffi/builder/field.rb +7 -5
  18. data/lib/gir_ffi/builder/module.rb +3 -14
  19. data/lib/gir_ffi/builder/property.rb +0 -2
  20. data/lib/gir_ffi/builder/type/callback.rb +0 -8
  21. data/lib/gir_ffi/builder/type/constant.rb +0 -4
  22. data/lib/gir_ffi/builder/type/enum.rb +0 -4
  23. data/lib/gir_ffi/builder/type/interface.rb +0 -4
  24. data/lib/gir_ffi/builder/type/object.rb +0 -1
  25. data/lib/gir_ffi/builder/type/struct_based.rb +0 -6
  26. data/lib/gir_ffi/builder/type/union.rb +0 -4
  27. data/lib/gir_ffi/builder/type/with_layout.rb +0 -1
  28. data/lib/gir_ffi/builder/type/with_methods.rb +1 -7
  29. data/lib/gir_ffi/callback.rb +9 -0
  30. data/lib/gir_ffi/callback_helper.rb +8 -1
  31. data/lib/gir_ffi/class_base.rb +6 -26
  32. data/lib/gir_ffi/error_argument_builder.rb +17 -0
  33. data/lib/gir_ffi/{builder/function.rb → function_builder.rb} +14 -11
  34. data/lib/gir_ffi/in_out_pointer.rb +29 -36
  35. data/lib/gir_ffi/in_pointer.rb +1 -1
  36. data/lib/gir_ffi/info_ext.rb +6 -0
  37. data/lib/gir_ffi/info_ext/i_field_info.rb +0 -2
  38. data/lib/gir_ffi/info_ext/i_type_info.rb +29 -10
  39. data/lib/gir_ffi/info_ext/safe_constant_name.rb +21 -0
  40. data/lib/gir_ffi/info_ext/safe_function_name.rb +13 -0
  41. data/lib/gir_ffi/interface_base.rb +1 -11
  42. data/lib/gir_ffi/module_base.rb +0 -10
  43. data/lib/gir_ffi/null_argument_builder.rb +9 -0
  44. data/lib/gir_ffi/return_value_builder.rb +75 -0
  45. data/lib/gir_ffi/setter_argument_info.rb +16 -0
  46. data/lib/gir_ffi/type_map.rb +10 -1
  47. data/lib/gir_ffi/version.rb +1 -1
  48. data/tasks/test.rake +61 -0
  49. data/test/base_test_helper.rb +0 -2
  50. data/test/ffi-gobject/value_test.rb +15 -0
  51. data/test/ffi-gobject_introspection/i_base_info_test.rb +31 -6
  52. data/test/ffi-gobject_introspection/i_function_info_test.rb +0 -17
  53. data/test/ffi-gobject_introspection/lib_test.rb +0 -55
  54. data/test/ffi-gobject_test.rb +2 -1
  55. data/test/gir_ffi/argument_builder_test.rb +414 -0
  56. data/test/gir_ffi/base_argument_builder_test.rb +13 -0
  57. data/test/gir_ffi/builder/module_test.rb +4 -40
  58. data/test/gir_ffi/builder/type/callback_test.rb +0 -27
  59. data/test/gir_ffi/builder/type/constant_test.rb +0 -12
  60. data/test/gir_ffi/builder/type/enum_test.rb +0 -20
  61. data/test/gir_ffi/builder/type/interface_test.rb +0 -11
  62. data/test/gir_ffi/builder/type/object_test.rb +2 -2
  63. data/test/gir_ffi/builder/type/struct_test.rb +0 -39
  64. data/test/gir_ffi/builder/type/unintrospectable_test.rb +1 -1
  65. data/test/gir_ffi/builder/type/union_test.rb +0 -11
  66. data/test/gir_ffi/builder_test.rb +3 -11
  67. data/test/gir_ffi/callback_helper_test.rb +7 -0
  68. data/test/gir_ffi/{builder/function_test.rb → function_builder_test.rb} +16 -28
  69. data/test/gir_ffi/in_out_pointer_test.rb +0 -20
  70. data/test/gir_ffi/info_ext/i_type_info_test.rb +112 -26
  71. data/test/gir_ffi/info_ext/safe_constant_name_test.rb +16 -0
  72. data/test/gir_ffi/info_ext/safe_function_name_test.rb +22 -0
  73. data/test/gir_ffi/return_value_builder_test.rb +355 -0
  74. data/test/integration/generated_gimarshallingtests_test.rb +608 -296
  75. data/test/integration/generated_regress_test.rb +879 -494
  76. metadata +35 -24
  77. data/lib/gir_ffi/builder/argument.rb +0 -569
  78. data/lib/gir_ffi/builder/argument/base.rb +0 -151
  79. data/lib/gir_ffi/builder/argument/in_base.rb +0 -14
  80. data/lib/gir_ffi/builder/argument/in_out_base.rb +0 -18
  81. data/lib/gir_ffi/builder/argument/out_base.rb +0 -15
  82. data/test/gir_ffi/builder/argument/base_test.rb +0 -55
  83. data/test/integration/pretty_print_test.rb +0 -33
@@ -19,7 +19,7 @@ module GirFFI
19
19
  return nil if val.nil?
20
20
  case type
21
21
  when Array
22
- arr_t, sub_t = *type
22
+ _, sub_t = *type
23
23
  # TODO: Take array type into account (zero-terminated or not)
24
24
  self.from_array sub_t, val
25
25
  when :utf8, :filename
@@ -0,0 +1,6 @@
1
+ require 'gir_ffi/info_ext/safe_constant_name'
2
+ require 'gir_ffi/info_ext/safe_function_name'
3
+ require 'gir_ffi/info_ext/i_field_info'
4
+ require 'gir_ffi/info_ext/i_property_info'
5
+ require 'gir_ffi/info_ext/i_registered_type_info'
6
+ require 'gir_ffi/info_ext/i_type_info'
@@ -1,5 +1,3 @@
1
- require 'gir_ffi/info_ext/i_type_info'
2
-
3
1
  module GirFFI
4
2
  module InfoExt
5
3
  module IFieldInfo
@@ -40,9 +40,10 @@ module GirFFI
40
40
  end
41
41
 
42
42
  def type_specification
43
- tag = self.tag
44
- if tag == :array
45
- "[#{flattened_array_type.inspect}, #{element_type.inspect}]"
43
+ tag = self.flattened_tag
44
+ case tag
45
+ when :strv, :zero_terminated, :c
46
+ "[#{tag.inspect}, #{subtype_tag_or_class_name}]"
46
47
  else
47
48
  tag.inspect
48
49
  end
@@ -65,20 +66,38 @@ module GirFFI
65
66
 
66
67
  def flattened_array_type
67
68
  if zero_terminated?
68
- if element_type == :utf8
69
- :strv
70
- else
71
- # TODO: Check that array_type == :c
72
- # TODO: Perhaps distinguish :c from zero-terminated :c
73
- :c
74
- end
69
+ zero_terminated_array_type
75
70
  else
76
71
  array_type
77
72
  end
78
73
  end
79
74
 
75
+ def subtype_tag_or_class_name
76
+ type = self.param_type 0
77
+ tag = type.tag
78
+ base = if tag == :interface
79
+ type.interface_type_name
80
+ else
81
+ tag.inspect
82
+ end
83
+ if type.pointer? && tag != :utf8
84
+ "[:pointer, #{base}]"
85
+ else
86
+ base
87
+ end
88
+ end
89
+
80
90
  private
81
91
 
92
+ def zero_terminated_array_type
93
+ if element_type == :utf8
94
+ :strv
95
+ else
96
+ # TODO: Check that array_type == :c
97
+ :zero_terminated
98
+ end
99
+ end
100
+
82
101
  def subtype_tag index
83
102
  st = param_type(index)
84
103
  tag = st.tag
@@ -0,0 +1,21 @@
1
+ module GirFFI
2
+ module InfoExt
3
+ module SafeConstantName
4
+ def safe_name
5
+ name.gsub(/^./) do |char|
6
+ case char
7
+ when "_"
8
+ "Private___"
9
+ else
10
+ char.upcase
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ GObjectIntrospection::IRegisteredTypeInfo.send :include, GirFFI::InfoExt::SafeConstantName
19
+ GObjectIntrospection::ICallbackInfo.send :include, GirFFI::InfoExt::SafeConstantName
20
+ GObjectIntrospection::IConstantInfo.send :include, GirFFI::InfoExt::SafeConstantName
21
+
@@ -0,0 +1,13 @@
1
+ module GirFFI
2
+ module InfoExt
3
+ module SafeFunctionName
4
+ def safe_name
5
+ name = self.name
6
+ return "_" if name.empty?
7
+ name
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ GObjectIntrospection::IFunctionInfo.send :include, GirFFI::InfoExt::SafeFunctionName
@@ -1,21 +1,11 @@
1
1
  module GirFFI
2
2
  module InterfaceBase
3
- # @deprecated Compatibility function. Remove in version 0.5.0.
4
- def _builder
5
- gir_ffi_builder
6
- end
7
-
8
3
  def gir_ffi_builder
9
4
  self.const_get :GIR_FFI_BUILDER
10
5
  end
11
6
 
12
- # @deprecated Compatibility function. Remove in version 0.5.0.
13
- def _setup_instance_method name
14
- setup_instance_method name
15
- end
16
-
17
7
  def setup_instance_method name
18
- _builder.setup_instance_method name
8
+ gir_ffi_builder.setup_instance_method name
19
9
  end
20
10
 
21
11
  def wrap ptr
@@ -16,20 +16,10 @@ module GirFFI
16
16
  gir_ffi_builder.build_namespaced_class classname.to_s
17
17
  end
18
18
 
19
- # @deprecated Compatibility function. Remove in version 0.5.0.
20
- def _builder
21
- gir_ffi_builder
22
- end
23
-
24
19
  def gir_ffi_builder
25
20
  self.const_get :GIR_FFI_BUILDER
26
21
  end
27
22
 
28
- # @deprecated Compatibility function. Remove in version 0.5.0.
29
- def _setup_method name
30
- setup_method name
31
- end
32
-
33
23
  def setup_method name
34
24
  gir_ffi_builder.setup_method name
35
25
  end
@@ -0,0 +1,9 @@
1
+ module GirFFI
2
+ # Argument builder that does nothing. Implements the Null Object pattern.
3
+ class NullArgumentBuilder
4
+ def initialize *args; end
5
+ def pre; []; end
6
+ def post; []; end
7
+ def callarg; end
8
+ end
9
+ end
@@ -0,0 +1,75 @@
1
+ require 'gir_ffi/base_argument_builder'
2
+
3
+ module GirFFI
4
+ # Implements building post-processing statements for return values.
5
+ class ReturnValueBuilder < BaseArgumentBuilder
6
+ def initialize var_gen, type_info, is_constructor
7
+ super var_gen, nil, type_info, :return
8
+ @is_constructor = is_constructor
9
+ end
10
+
11
+ def post
12
+ if needs_wrapping?
13
+ if specialized_type_tag == :zero_terminated
14
+ # FIXME: This is almost certainly wrong.
15
+ [ "#{retname} = #{argument_class_name}.wrap(#{cvar})" ]
16
+ elsif [ :interface, :object ].include?(specialized_type_tag) && @is_constructor
17
+ [ "#{retname} = self.constructor_wrap(#{cvar})" ]
18
+ else
19
+ [ "#{retname} = #{argument_class_name}.wrap(#{return_value_conversion_arguments})" ]
20
+ end
21
+ elsif specialized_type_tag == :utf8
22
+ # TODO: Re-use methods in InOutPointer for this conversion
23
+ [ "#{retname} = GirFFI::ArgHelper.ptr_to_utf8(#{cvar})" ]
24
+ elsif specialized_type_tag == :c
25
+ size = array_size
26
+ [ "#{retname} = GirFFI::ArgHelper.ptr_to_typed_array #{subtype_tag_or_class_name}, #{cvar}, #{size}" ]
27
+ else
28
+ []
29
+ end
30
+ end
31
+
32
+ def inarg
33
+ nil
34
+ end
35
+
36
+ # TODO: Rename
37
+ def cvar
38
+ callarg unless is_void_return_value?
39
+ end
40
+
41
+ def retval
42
+ if has_conversion?
43
+ super
44
+ elsif is_void_return_value?
45
+ nil
46
+ else
47
+ callarg
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def retname
54
+ @retname ||= @var_gen.new_var
55
+ end
56
+
57
+ def has_conversion?
58
+ needs_wrapping? || [ :utf8, :c ].include?(specialized_type_tag)
59
+ end
60
+
61
+ def needs_wrapping?
62
+ [ :struct, :union, :interface, :object, :strv, :zero_terminated,
63
+ :byte_array, :ptr_array, :glist, :gslist, :ghash, :array
64
+ ].include?(specialized_type_tag)
65
+ end
66
+
67
+ def is_void_return_value?
68
+ specialized_type_tag == :void && !type_info.pointer?
69
+ end
70
+
71
+ def return_value_conversion_arguments
72
+ conversion_arguments cvar
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,16 @@
1
+ module GirFFI
2
+ # Class to represent argument info for the argument of a setter method.
3
+ # Implements the necessary parts of IArgumentInfo's interface.
4
+ class SetterArgumentInfo
5
+ attr_reader :name, :argument_type
6
+
7
+ def initialize name, type
8
+ @name = name
9
+ @argument_type = type
10
+ end
11
+
12
+ def direction
13
+ :in
14
+ end
15
+ end
16
+ end
@@ -4,6 +4,15 @@ module GirFFI
4
4
  gtype_type = "uint#{sz}".to_sym
5
5
 
6
6
  TAG_TYPE_MAP = {
7
+ :enum => :int32,
8
+ :flags => :int32,
9
+ :ghash => :pointer,
10
+ :glist => :pointer,
11
+ :gslist => :pointer,
12
+ :strv => :pointer,
13
+ :c => :pointer,
14
+ :object => :pointer,
15
+ :struct => :pointer,
7
16
  :GType => gtype_type,
8
17
  :gboolean => :bool,
9
18
  :gunichar => :uint32,
@@ -30,7 +39,7 @@ module GirFFI
30
39
  case type
31
40
  when :gboolean
32
41
  :int32
33
- when :utf8
42
+ when :utf8, :array
34
43
  :pointer
35
44
  else
36
45
  map_basic_type(type)
@@ -1,4 +1,4 @@
1
1
  module GirFFI
2
- VERSION = "0.4.3"
2
+ VERSION = "0.5.0"
3
3
  end
4
4
 
data/tasks/test.rake CHANGED
@@ -1,5 +1,52 @@
1
1
  require 'rake/testtask'
2
2
 
3
+ require 'rexml/document'
4
+ require 'rexml/streamlistener'
5
+
6
+ # Listener class used to process GIR xml data, for creating test stubs.
7
+ class Listener
8
+ include REXML::StreamListener
9
+
10
+ def initialize
11
+ @inside_class = false
12
+ end
13
+
14
+ attr_accessor :result
15
+ attr_accessor :namespace
16
+
17
+ def tag_start name, attrs
18
+ return if attrs['disguised'] == '1'
19
+ return if attrs['introspectable'] == '0'
20
+ return if attrs['glib:is-gtype-struct-for']
21
+
22
+ obj_name = attrs['name']
23
+ case name
24
+ when "constant"
25
+ result.puts " it \"has the constant #{obj_name}\" do"
26
+ when "record", "class", "enumeration", "bitfield", "interface", "union"
27
+ result.puts " describe \"#{namespace}::#{obj_name}\" do"
28
+ @inside_class = true
29
+ when "constructor"
30
+ result.puts " it \"creates an instance using ##{obj_name}\" do"
31
+ when "function", "method"
32
+ spaces = @inside_class ? " " : ""
33
+ result.puts " #{spaces}it \"has a working #{name} ##{obj_name}\" do"
34
+ when "member"
35
+ result.puts " it \"has the member :#{obj_name}\" do"
36
+ when "type", "return-value", "parameters", "parameter", "doc", "array"
37
+ else
38
+ puts "Skipping #{name}"
39
+ end
40
+ end
41
+
42
+ def tag_end name
43
+ case name
44
+ when "record", "class", "enumeration", "bitfield", "interface", "union"
45
+ @inside_class = false
46
+ end
47
+ end
48
+ end
49
+
3
50
  namespace :test do
4
51
  def define_test_task name
5
52
  Rake::TestTask.new(name) do |t|
@@ -54,6 +101,20 @@ namespace :test do
54
101
  :main,
55
102
  :overrides,
56
103
  :integration]
104
+
105
+ task :stub => :lib do
106
+ file = File.new 'test/lib/Regress-1.0.gir'
107
+ listener = Listener.new
108
+ listener.result = File.open('tmp/regress_lines.rb', 'w')
109
+ listener.namespace = "Regress"
110
+ REXML::Document.parse_stream file, listener
111
+
112
+ file = File.new 'test/lib/GIMarshallingTests-1.0.gir'
113
+ listener = Listener.new
114
+ listener.result = File.open('tmp/gimarshallingtests_lines.rb', 'w')
115
+ listener.namespace = "GIMarshallingTests"
116
+ REXML::Document.parse_stream file, listener
117
+ end
57
118
  end
58
119
 
59
120
  file "test/lib/Makefile" => "test/lib/configure" do
@@ -1,6 +1,4 @@
1
1
  if RUBY_PLATFORM == 'java'
2
- require 'java'
3
- JRuby.objectspace = true
4
2
  require 'rubygems'
5
3
  end
6
4
 
@@ -3,6 +3,21 @@ require 'gir_ffi_test_helper'
3
3
  require 'ffi-gobject'
4
4
 
5
5
  describe GObject::Value do
6
+ describe "::Struct" do
7
+ describe "layout" do
8
+ let(:layout) { GObject::Value::Struct.layout }
9
+
10
+ it "consists of :g_type and :data" do
11
+ layout.members.must_equal [:g_type, :data]
12
+ end
13
+
14
+ it "has an array as its second element" do
15
+ types = layout.fields.map(&:type)
16
+ types[1].class.must_equal FFI::Type::Array
17
+ end
18
+ end
19
+ end
20
+
6
21
  describe "::wrap_ruby_value" do
7
22
  it "wraps a boolean false" do
8
23
  gv = GObject::Value.wrap_ruby_value false
@@ -1,15 +1,40 @@
1
1
  require 'introspection_test_helper'
2
2
 
3
3
  describe GObjectIntrospection::IBaseInfo do
4
- describe "#safe_name" do
5
- it "makes names starting with an underscore safe" do
6
- stub(ptr = Object.new).null? { false }
4
+ let(:described_class) { GObjectIntrospection::IBaseInfo }
5
+ describe "#initialize" do
6
+ it "raises an error if nil is passed" do
7
+ proc { described_class.new nil }.must_raise ArgumentError
8
+ end
9
+
10
+ it "raises an error if a null pointer is passed" do
11
+ mock(ptr = Object.new).null? { true }
12
+ proc { described_class.new ptr }.must_raise ArgumentError
13
+ end
14
+
15
+ it "raises no error if a non-null pointer is passed" do
16
+ mock(ptr = Object.new).null? { false }
17
+ described_class.new ptr
18
+ pass
19
+ end
20
+ end
21
+
22
+ describe "upon garbage collection" do
23
+ it "calls g_base_info_unref" do
24
+ skip "cannot be reliably tested on JRuby" if RUBY_PLATFORM == 'java'
25
+ mock(ptr = Object.new).null? { false }
26
+ mock(lib = Object.new).g_base_info_unref(ptr) { nil }
27
+ described_class.new ptr, lib
7
28
 
8
- info = GObjectIntrospection::IBaseInfo.wrap ptr
29
+ GC.start
9
30
 
10
- stub(info).name { "_foo" }
31
+ # Yes, the next three lines are needed. https://gist.github.com/4277829
32
+ stub(ptr2 = Object.new).null? { false }
33
+ stub(lib).g_base_info_unref(ptr2) { nil }
34
+ described_class.new ptr2, lib
11
35
 
12
- assert_equal "Private___foo", info.safe_name
36
+ GC.start
37
+ GC.start
13
38
  end
14
39
  end
15
40
  end