yakg 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/Gemfile.lock +1 -1
  2. data/VERSION +1 -1
  3. data/lib/yakg.rb +2 -1
  4. data/vendor/gems/installit.sh +9 -5
  5. data/vendor/gems/ruby/1.8/gems/ffi-1.8.1/lib/ffi_c.bundle +0 -0
  6. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/CHANGELOG +12 -0
  7. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/LICENSE +8 -0
  8. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/README.md +40 -0
  9. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/array.rb +123 -0
  10. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/base.rb +197 -0
  11. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/boolean.rb +25 -0
  12. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/data.rb +42 -0
  13. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/date.rb +32 -0
  14. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/dictionary.rb +114 -0
  15. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/extensions.rb +158 -0
  16. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/null.rb +11 -0
  17. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/number.rb +98 -0
  18. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/string.rb +91 -0
  19. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation/version.rb +4 -0
  20. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/lib/corefoundation.rb +13 -0
  21. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/array_spec.rb +92 -0
  22. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/boolean_spec.rb +24 -0
  23. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/data_spec.rb +30 -0
  24. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/date_spec.rb +25 -0
  25. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/dictionary_spec.rb +81 -0
  26. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/extensions_spec.rb +127 -0
  27. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/null_spec.rb +7 -0
  28. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/number_spec.rb +52 -0
  29. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/spec_helper.rb +10 -0
  30. data/vendor/gems/ruby/1.9.1/gems/corefoundation-0.2.0/spec/string_spec.rb +48 -0
  31. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/.require_paths +2 -0
  32. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/COPYING +674 -0
  33. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/COPYING.LESSER +165 -0
  34. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/History.txt +1 -0
  35. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/LICENSE +14 -0
  36. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/README.md +109 -0
  37. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/Rakefile +219 -0
  38. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/ffi.gemspec +22 -0
  39. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/gen/Rakefile +30 -0
  40. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/gen/log +1 -0
  41. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/autopointer.rb +184 -0
  42. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/buffer.rb +4 -0
  43. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/callback.rb +4 -0
  44. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/enum.rb +162 -0
  45. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/errno.rb +33 -0
  46. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/ffi.iml +11 -0
  47. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/ffi.rb +33 -0
  48. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/io.rb +52 -0
  49. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/library.rb +489 -0
  50. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/managedstruct.rb +55 -0
  51. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/memorypointer.rb +1 -0
  52. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/arm-linux/types.conf +104 -0
  53. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i386-cygwin/types.conf +3 -0
  54. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i386-darwin/types.conf +100 -0
  55. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  56. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i386-linux/types.conf +103 -0
  57. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  58. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i386-openbsd/types.conf +126 -0
  59. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i386-solaris/types.conf +122 -0
  60. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i386-windows/types.conf +105 -0
  61. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/i486-gnu/types.conf +107 -0
  62. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/ia64-linux/types.conf +104 -0
  63. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/mips-linux/types.conf +102 -0
  64. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  65. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/powerpc-aix/types.conf +180 -0
  66. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
  67. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/powerpc-linux/types.conf +100 -0
  68. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/s390-linux/types.conf +102 -0
  69. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/s390x-linux/types.conf +102 -0
  70. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/sparc-linux/types.conf +102 -0
  71. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/sparc-solaris/types.conf +128 -0
  72. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
  73. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/x86_64-darwin/types.conf +100 -0
  74. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
  75. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/x86_64-linux/types.conf +102 -0
  76. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/x86_64-netbsd/types.conf +126 -0
  77. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/x86_64-openbsd/types.conf +126 -0
  78. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
  79. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform/x86_64-windows/types.conf +27 -0
  80. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/platform.rb +139 -0
  81. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/pointer.rb +122 -0
  82. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/struct.rb +356 -0
  83. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/struct_layout_builder.rb +211 -0
  84. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/tools/const_generator.rb +229 -0
  85. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/tools/generator.rb +60 -0
  86. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/tools/generator_task.rb +36 -0
  87. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/tools/struct_generator.rb +194 -0
  88. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/tools/types_generator.rb +135 -0
  89. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/types.rb +177 -0
  90. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/union.rb +32 -0
  91. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/variadic.rb +65 -0
  92. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi/version.rb +4 -0
  93. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi.rb +28 -0
  94. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/lib/ffi_c.bundle +0 -0
  95. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/Benchmark.c +52 -0
  96. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/BoolTest.c +31 -0
  97. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/BufferTest.c +31 -0
  98. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/ClosureTest.c +190 -0
  99. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/EnumTest.c +34 -0
  100. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/FunctionTest.c +58 -0
  101. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/GNUmakefile +149 -0
  102. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/GlobalVariable.c +62 -0
  103. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/LastErrorTest.c +21 -0
  104. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/NumberTest.c +132 -0
  105. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/PointerTest.c +63 -0
  106. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/ReferenceTest.c +23 -0
  107. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/StringTest.c +34 -0
  108. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/StructTest.c +240 -0
  109. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/UnionTest.c +43 -0
  110. data/vendor/gems/ruby/1.9.1/gems/ffi-1.8.1/libtest/VariadicTest.c +62 -0
  111. data/vendor/gems/ruby/1.9.1/specifications/corefoundation-0.2.0.gemspec +44 -0
  112. data/vendor/gems/ruby/1.9.1/specifications/ffi-1.8.1.gemspec +43 -0
  113. metadata +172 -60
@@ -0,0 +1,356 @@
1
+ #
2
+ # Copyright (C) 2008-2010 Wayne Meissner
3
+ # Copyright (C) 2008, 2009 Andrea Fazzi
4
+ # Copyright (C) 2008, 2009 Luc Heinrich
5
+ #
6
+ # All rights reserved.
7
+ #
8
+ # This file is part of ruby-ffi.
9
+ #
10
+ # This code is free software: you can redistribute it and/or modify it under
11
+ # the terms of the GNU Lesser General Public License version 3 only, as
12
+ # published by the Free Software Foundation.
13
+ #
14
+ # This code is distributed in the hope that it will be useful, but WITHOUT
15
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
17
+ # version 3 for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public License
20
+ # version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
21
+ #
22
+
23
+ require 'ffi/platform'
24
+ require 'ffi/struct_layout_builder'
25
+
26
+ module FFI
27
+
28
+ class StructLayout
29
+
30
+ # @return [Array<Array(Symbol, Numeric)>
31
+ # Get an array of tuples (field name, offset of the field).
32
+ def offsets
33
+ members.map { |m| [ m, self[m].offset ] }
34
+ end
35
+
36
+ # @return [Numeric]
37
+ # Get the offset of a field.
38
+ def offset_of(field_name)
39
+ self[field_name].offset
40
+ end
41
+
42
+ # An enum {Field} in a {StructLayout}.
43
+ class Enum < Field
44
+
45
+ # @param [AbstractMemory] ptr pointer on a {Struct}
46
+ # @return [Object]
47
+ # Get an object of type {#type} from memory pointed by +ptr+.
48
+ def get(ptr)
49
+ type.find(ptr.get_int(offset))
50
+ end
51
+
52
+ # @param [AbstractMemory] ptr pointer on a {Struct}
53
+ # @param value
54
+ # @return [nil]
55
+ # Set +value+ into memory pointed by +ptr+.
56
+ def put(ptr, value)
57
+ ptr.put_int(offset, type.find(value))
58
+ end
59
+
60
+ end
61
+
62
+ class InnerStruct < Field
63
+ def get(ptr)
64
+ type.struct_class.new(ptr.slice(self.offset, self.size))
65
+ end
66
+
67
+ def put(ptr, value)
68
+ raise TypeError, "wrong value type (expected #{type.struct_class}" unless value.is_a?(type.struct_class)
69
+ ptr.slice(self.offset, self.size).__copy_from__(value.pointer, self.size)
70
+ end
71
+ end
72
+
73
+ class Mapped < Field
74
+ def initialize(name, offset, type, orig_field)
75
+ super(name, offset, type)
76
+ @orig_field = orig_field
77
+ end
78
+
79
+ def get(ptr)
80
+ type.from_native(@orig_field.get(ptr), nil)
81
+ end
82
+
83
+ def put(ptr, value)
84
+ @orig_field.put(ptr, type.to_native(value, nil))
85
+ end
86
+ end
87
+ end
88
+
89
+
90
+ class Struct
91
+
92
+ # Get struct size
93
+ # @return [Numeric]
94
+ def size
95
+ self.class.size
96
+ end
97
+
98
+ # @return [Fixnum] Struct alignment
99
+ def alignment
100
+ self.class.alignment
101
+ end
102
+ alias_method :align, :alignment
103
+
104
+ # (see FFI::StructLayout#offset_of)
105
+ def offset_of(name)
106
+ self.class.offset_of(name)
107
+ end
108
+
109
+ # (see FFI::StructLayout#members)
110
+ def members
111
+ self.class.members
112
+ end
113
+
114
+ # @return [Array]
115
+ # Get array of values from Struct fields.
116
+ def values
117
+ members.map { |m| self[m] }
118
+ end
119
+
120
+ # (see FFI::StructLayout#offsets)
121
+ def offsets
122
+ self.class.offsets
123
+ end
124
+
125
+ # Clear the struct content.
126
+ # @return [self]
127
+ def clear
128
+ pointer.clear
129
+ self
130
+ end
131
+
132
+ # Get {Pointer} to struct content.
133
+ # @return [AbstractMemory]
134
+ def to_ptr
135
+ pointer
136
+ end
137
+
138
+ # Get struct size
139
+ # @return [Numeric]
140
+ def self.size
141
+ defined?(@layout) ? @layout.size : defined?(@size) ? @size : 0
142
+ end
143
+
144
+ # set struct size
145
+ # @param [Numeric] size
146
+ # @return [size]
147
+ def self.size=(size)
148
+ raise ArgumentError, "Size already set" if defined?(@size) || defined?(@layout)
149
+ @size = size
150
+ end
151
+
152
+ # @return (see Struct#alignment)
153
+ def self.alignment
154
+ @layout.alignment
155
+ end
156
+
157
+ # (see FFI::Type#members)
158
+ def self.members
159
+ @layout.members
160
+ end
161
+
162
+ # (see FFI::StructLayout#offsets)
163
+ def self.offsets
164
+ @layout.offsets
165
+ end
166
+
167
+ # (see FFI::StructLayout#offset_of)
168
+ def self.offset_of(name)
169
+ @layout.offset_of(name)
170
+ end
171
+
172
+ def self.in
173
+ ptr(:in)
174
+ end
175
+
176
+ def self.out
177
+ ptr(:out)
178
+ end
179
+
180
+ def self.ptr(flags = :inout)
181
+ @ref_data_type ||= Type::Mapped.new(StructByReference.new(self))
182
+ end
183
+
184
+ def self.val
185
+ @val_data_type ||= StructByValue.new(self)
186
+ end
187
+
188
+ def self.by_value
189
+ self.val
190
+ end
191
+
192
+ def self.by_ref(flags = :inout)
193
+ self.ptr(flags)
194
+ end
195
+
196
+ class ManagedStructConverter < StructByReference
197
+
198
+ # @param [Struct] struct_class
199
+ def initialize(struct_class)
200
+ super(struct_class)
201
+
202
+ raise NoMethodError, "release() not implemented for class #{struct_class}" unless struct_class.respond_to? :release
203
+ @method = struct_class.method(:release)
204
+ end
205
+
206
+ # @param [Pointer] ptr
207
+ # @param [nil] ctx
208
+ # @return [Struct]
209
+ def from_native(ptr, ctx)
210
+ struct_class.new(AutoPointer.new(ptr, @method))
211
+ end
212
+ end
213
+
214
+ def self.auto_ptr
215
+ @managed_type ||= Type::Mapped.new(ManagedStructConverter.new(self))
216
+ end
217
+
218
+
219
+ class << self
220
+ public
221
+
222
+ # @return [StructLayout]
223
+ # @overload layout
224
+ # @return [StructLayout]
225
+ # Get struct layout.
226
+ # @overload layout(*spec)
227
+ # @param [Array<Symbol, Integer>,Array(Hash)] spec
228
+ # @return [StructLayout]
229
+ # Create struct layout from +spec+.
230
+ # @example Creating a layout from an array +spec+
231
+ # class MyStruct < Struct
232
+ # layout :field1, :int,
233
+ # :field2, :pointer,
234
+ # :field3, :string
235
+ # end
236
+ # @example Creating a layout from an array +spec+ with offset
237
+ # class MyStructWithOffset < Struct
238
+ # layout :field1, :int,
239
+ # :field2, :pointer, 6, # set offset to 6 for this field
240
+ # :field3, :string
241
+ # end
242
+ # @example Creating a layout from a hash +spec+ (Ruby 1.9 only)
243
+ # class MyStructFromHash < Struct
244
+ # layout :field1 => :int,
245
+ # :field2 => :pointer,
246
+ # :field3 => :string
247
+ # end
248
+ # @note Creating a layout from a hash +spec+ is supported only for Ruby 1.9.
249
+ def layout(*spec)
250
+ # raise RuntimeError, "struct layout already defined for #{self.inspect}" if defined?(@layout)
251
+ return @layout if spec.size == 0
252
+
253
+ builder = StructLayoutBuilder.new
254
+ builder.union = self < Union
255
+ builder.packed = @packed if defined?(@packed)
256
+ builder.alignment = @min_alignment if defined?(@min_alignment)
257
+
258
+ if spec[0].kind_of?(Hash)
259
+ hash_layout(builder, spec)
260
+ else
261
+ array_layout(builder, spec)
262
+ end
263
+ builder.size = @size if defined?(@size) && @size > builder.size
264
+ cspec = builder.build
265
+ @layout = cspec unless self == Struct
266
+ @size = cspec.size
267
+ return cspec
268
+ end
269
+
270
+
271
+ protected
272
+
273
+ def callback(params, ret)
274
+ mod = enclosing_module
275
+ FFI::CallbackInfo.new(find_type(ret, mod), params.map { |e| find_type(e, mod) })
276
+ end
277
+
278
+ def packed(packed = 1)
279
+ @packed = packed
280
+ end
281
+ alias :pack :packed
282
+
283
+ def aligned(alignment = 1)
284
+ @min_alignment = alignment
285
+ end
286
+ alias :align :aligned
287
+
288
+ def enclosing_module
289
+ begin
290
+ mod = self.name.split("::")[0..-2].inject(Object) { |obj, c| obj.const_get(c) }
291
+ (mod < FFI::Library || mod < FFI::Struct || mod.respond_to?(:find_type)) ? mod : nil
292
+ rescue Exception
293
+ nil
294
+ end
295
+ end
296
+
297
+
298
+ def find_field_type(type, mod = enclosing_module)
299
+ if type.kind_of?(Class) && type < Struct
300
+ FFI::Type::Struct.new(type)
301
+
302
+ elsif type.kind_of?(Class) && type < FFI::StructLayout::Field
303
+ type
304
+
305
+ elsif type.kind_of?(::Array)
306
+ FFI::Type::Array.new(find_field_type(type[0]), type[1])
307
+
308
+ else
309
+ find_type(type, mod)
310
+ end
311
+ end
312
+
313
+ def find_type(type, mod = enclosing_module)
314
+ if mod
315
+ mod.find_type(type)
316
+ end || FFI.find_type(type)
317
+ end
318
+
319
+ private
320
+
321
+ # @param [StructLayoutBuilder] builder
322
+ # @param [Hash] spec
323
+ # @return [builder]
324
+ # @raise if Ruby 1.8
325
+ # Add hash +spec+ to +builder+.
326
+ def hash_layout(builder, spec)
327
+ raise "Ruby version not supported" if RUBY_VERSION =~ /1.8.*/
328
+ spec[0].each do |name, type|
329
+ builder.add name, find_field_type(type), nil
330
+ end
331
+ end
332
+
333
+ # @param [StructLayoutBuilder] builder
334
+ # @param [Array<Symbol, Integer>] spec
335
+ # @return [builder]
336
+ # Add array +spec+ to +builder+.
337
+ def array_layout(builder, spec)
338
+ i = 0
339
+ while i < spec.size
340
+ name, type = spec[i, 2]
341
+ i += 2
342
+
343
+ # If the next param is a Integer, it specifies the offset
344
+ if spec[i].kind_of?(Integer)
345
+ offset = spec[i]
346
+ i += 1
347
+ else
348
+ offset = nil
349
+ end
350
+
351
+ builder.add name, find_field_type(type), offset
352
+ end
353
+ end
354
+ end
355
+ end
356
+ end
@@ -0,0 +1,211 @@
1
+ #
2
+ # Copyright (C) 2008-2010 Wayne Meissner
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # This file is part of ruby-ffi.
7
+ #
8
+ # This code is free software: you can redistribute it and/or modify it under
9
+ # the terms of the GNU Lesser General Public License version 3 only, as
10
+ # published by the Free Software Foundation.
11
+ #
12
+ # This code is distributed in the hope that it will be useful, but WITHOUT
13
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15
+ # version 3 for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ module FFI
22
+
23
+ # Build a {StructLayout struct layout}.
24
+ class StructLayoutBuilder
25
+ attr_reader :size
26
+ attr_reader :alignment
27
+
28
+ def initialize
29
+ @size = 0
30
+ @alignment = 1
31
+ @min_alignment = 1
32
+ @packed = false
33
+ @union = false
34
+ @fields = Array.new
35
+ end
36
+
37
+ # @param [Numeric] size
38
+ # Set size attribute with +size+ only if +size+ is greater than attribute value.
39
+ def size=(size)
40
+ @size = size if size > @size
41
+ end
42
+
43
+ # @param [Numeric] alignment
44
+ # Set alignment attribute with +alignment+ only if it is greater than attribute value.
45
+ def alignment=(align)
46
+ @alignment = align if align > @alignment
47
+ @min_alignment = align
48
+ end
49
+
50
+ # @param [Boolean] is_union
51
+ # @return [is_union]
52
+ # Set union attribute.
53
+ # Set to +true+ to build a {Union} instead of a {Struct}.
54
+ def union=(is_union)
55
+ @union = is_union
56
+ end
57
+
58
+ # @return [Boolean]
59
+ # Building a {Union} or a {Struct} ?
60
+ def union?
61
+ @union
62
+ end
63
+
64
+ # Set packed attribute
65
+ # @overload packed=(packed)
66
+ # @param [Fixnum] packed
67
+ # @return [packed]
68
+ # Set alignment and packed attributes to +packed+.
69
+ # @overload packed=(packed)
70
+ # @param packed
71
+ # @return [0,1]
72
+ # Set packed attribute.
73
+ def packed=(packed)
74
+ if packed.is_a?(Fixnum)
75
+ @alignment = packed
76
+ @packed = packed
77
+ else
78
+ @packed = packed ? 1 : 0
79
+ end
80
+ end
81
+
82
+
83
+ # List of number types
84
+ NUMBER_TYPES = [
85
+ Type::INT8,
86
+ Type::UINT8,
87
+ Type::INT16,
88
+ Type::UINT16,
89
+ Type::INT32,
90
+ Type::UINT32,
91
+ Type::LONG,
92
+ Type::ULONG,
93
+ Type::INT64,
94
+ Type::UINT64,
95
+ Type::FLOAT32,
96
+ Type::FLOAT64,
97
+ Type::LONGDOUBLE,
98
+ Type::BOOL,
99
+ ]
100
+
101
+ # @param [String, Symbol] name name of the field
102
+ # @param [Array, DataConverter, Struct, StructLayout::Field, Symbol, Type] type type of the field
103
+ # @param [Numeric, nil] offset
104
+ # @return [self]
105
+ # Add a field to the builder.
106
+ # @note Setting +offset+ to +nil+ or +-1+ is equivalent to +0+.
107
+ def add(name, type, offset = nil)
108
+
109
+ if offset.nil? || offset == -1
110
+ offset = @union ? 0 : align(@size, @packed ? [ @packed, type.alignment ].min : [ @min_alignment, type.alignment ].max)
111
+ end
112
+
113
+ #
114
+ # If a FFI::Type type was passed in as the field arg, try and convert to a StructLayout::Field instance
115
+ #
116
+ field = type.is_a?(StructLayout::Field) ? type : field_for_type(name, offset, type)
117
+ @fields << field
118
+ @alignment = [ @alignment, field.alignment ].max unless @packed
119
+ @size = [ @size, field.size + (@union ? 0 : field.offset) ].max
120
+
121
+ return self
122
+ end
123
+
124
+ # @param (see #add)
125
+ # @return (see #add)
126
+ # Same as {#add}.
127
+ # @see #add
128
+ def add_field(name, type, offset = nil)
129
+ add(name, type, offset)
130
+ end
131
+
132
+ # @param (see #add)
133
+ # @return (see #add)
134
+ # Add a struct as a field to the builder.
135
+ def add_struct(name, type, offset = nil)
136
+ add(name, Type::Struct.new(type), offset)
137
+ end
138
+
139
+ # @param name (see #add)
140
+ # @param type (see #add)
141
+ # @param [Numeric] count array length
142
+ # @param offset (see #add)
143
+ # @return (see #add)
144
+ # Add an array as a field to the builder.
145
+ def add_array(name, type, count, offset = nil)
146
+ add(name, Type::Array.new(type, count), offset)
147
+ end
148
+
149
+ # @return [StructLayout]
150
+ # Build and return the struct layout.
151
+ def build
152
+ # Add tail padding if the struct is not packed
153
+ size = @packed ? @size : align(@size, @alignment)
154
+
155
+ layout = StructLayout.new(@fields, size, @alignment)
156
+ layout.__union! if @union
157
+ layout
158
+ end
159
+
160
+ private
161
+
162
+ # @param [Numeric] offset
163
+ # @param [Numeric] align
164
+ # @return [Numeric]
165
+ def align(offset, align)
166
+ align + ((offset - 1) & ~(align - 1));
167
+ end
168
+
169
+ # @param (see #add)
170
+ # @return [StructLayout::Field]
171
+ def field_for_type(name, offset, type)
172
+ field_class = case
173
+ when type.is_a?(Type::Function)
174
+ StructLayout::Function
175
+
176
+ when type.is_a?(Type::Struct)
177
+ StructLayout::InnerStruct
178
+
179
+ when type.is_a?(Type::Array)
180
+ StructLayout::Array
181
+
182
+ when type.is_a?(FFI::Enum)
183
+ StructLayout::Enum
184
+
185
+ when NUMBER_TYPES.include?(type)
186
+ StructLayout::Number
187
+
188
+ when type == Type::POINTER
189
+ StructLayout::Pointer
190
+
191
+ when type == Type::STRING
192
+ StructLayout::String
193
+
194
+ when type.is_a?(Class) && type < StructLayout::Field
195
+ type
196
+
197
+ when type.is_a?(DataConverter)
198
+ return StructLayout::Mapped.new(name, offset, Type::Mapped.new(type), field_for_type(name, offset, type.native_type))
199
+
200
+ when type.is_a?(Type::Mapped)
201
+ return StructLayout::Mapped.new(name, offset, type, field_for_type(name, offset, type.native_type))
202
+
203
+ else
204
+ raise TypeError, "invalid struct field type #{type.inspect}"
205
+ end
206
+
207
+ field_class.new(name, offset, type)
208
+ end
209
+ end
210
+
211
+ end