ffi 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (203) hide show
  1. data/LICENSE +1 -27
  2. data/Rakefile +2 -11
  3. data/ext/ffi_c/AbstractMemory.c +6 -8
  4. data/ext/ffi_c/AbstractMemory.h +23 -21
  5. data/ext/ffi_c/AutoPointer.c +0 -1
  6. data/ext/ffi_c/Buffer.c +23 -8
  7. data/ext/ffi_c/Call.c +28 -0
  8. data/ext/ffi_c/Call.h +5 -1
  9. data/ext/ffi_c/DynamicLibrary.c +0 -1
  10. data/ext/ffi_c/Function.c +19 -2
  11. data/ext/ffi_c/MemoryPointer.c +2 -3
  12. data/ext/ffi_c/Pointer.c +23 -9
  13. data/ext/ffi_c/Struct.c +142 -69
  14. data/ext/ffi_c/Struct.h +16 -7
  15. data/ext/ffi_c/StructLayout.c +92 -55
  16. data/ext/ffi_c/Type.c +5 -22
  17. data/ext/ffi_c/Type.h +1 -1
  18. data/ext/ffi_c/Types.c +8 -2
  19. data/ext/ffi_c/Types.h +2 -0
  20. data/ext/ffi_c/extconf.rb +11 -7
  21. data/ext/ffi_c/libffi/ChangeLog +900 -84
  22. data/ext/ffi_c/libffi/ChangeLog.libffi +311 -0
  23. data/ext/ffi_c/libffi/LICENSE +1 -1
  24. data/ext/ffi_c/libffi/Makefile.am +14 -4
  25. data/ext/ffi_c/libffi/Makefile.in +362 -211
  26. data/ext/ffi_c/libffi/README +70 -92
  27. data/ext/ffi_c/libffi/aclocal.m4 +6068 -4586
  28. data/ext/ffi_c/libffi/config.guess +125 -143
  29. data/ext/ffi_c/libffi/config.sub +103 -27
  30. data/ext/ffi_c/libffi/configure +11364 -18497
  31. data/ext/ffi_c/libffi/configure.ac +43 -4
  32. data/ext/ffi_c/libffi/doc/libffi.info +15 -15
  33. data/ext/ffi_c/libffi/doc/libffi.texi +1 -1
  34. data/ext/ffi_c/libffi/doc/stamp-vti +4 -4
  35. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  36. data/ext/ffi_c/libffi/fficonfig.h.in +24 -3
  37. data/ext/ffi_c/libffi/include/Makefile.am +1 -1
  38. data/ext/ffi_c/libffi/include/Makefile.in +97 -50
  39. data/ext/ffi_c/libffi/include/ffi.h.in +8 -2
  40. data/ext/ffi_c/libffi/include/ffi_common.h +24 -0
  41. data/ext/ffi_c/libffi/libtool-version +1 -1
  42. data/ext/ffi_c/libffi/ltmain.sh +7346 -5870
  43. data/ext/ffi_c/libffi/m4/libtool.m4 +7360 -0
  44. data/ext/ffi_c/libffi/m4/ltoptions.m4 +368 -0
  45. data/ext/ffi_c/libffi/m4/ltsugar.m4 +123 -0
  46. data/ext/ffi_c/libffi/m4/ltversion.m4 +23 -0
  47. data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +92 -0
  48. data/ext/ffi_c/libffi/man/Makefile.in +115 -62
  49. data/ext/ffi_c/libffi/man/ffi_call.3 +3 -3
  50. data/ext/ffi_c/libffi/missing +15 -8
  51. data/ext/ffi_c/libffi/src/arm/sysv.S +15 -8
  52. data/ext/ffi_c/libffi/src/avr32/ffi.c +421 -0
  53. data/ext/ffi_c/libffi/src/avr32/ffitarget.h +50 -0
  54. data/ext/ffi_c/libffi/src/avr32/sysv.S +208 -0
  55. data/ext/ffi_c/libffi/src/closures.c +47 -10
  56. data/ext/ffi_c/libffi/src/frv/ffi.c +1 -1
  57. data/ext/ffi_c/libffi/src/java_raw_api.c +0 -3
  58. data/ext/ffi_c/libffi/src/mips/ffi.c +135 -32
  59. data/ext/ffi_c/libffi/src/mips/ffitarget.h +37 -4
  60. data/ext/ffi_c/libffi/src/mips/n32.S +67 -10
  61. data/ext/ffi_c/libffi/src/mips/o32.S +8 -8
  62. data/ext/ffi_c/libffi/src/pa/ffi.c +7 -0
  63. data/ext/ffi_c/libffi/src/powerpc/aix.S +163 -64
  64. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +308 -112
  65. data/ext/ffi_c/libffi/src/powerpc/ffi.c +20 -7
  66. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +208 -80
  67. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +11 -3
  68. data/ext/ffi_c/libffi/src/powerpc/sysv.S +12 -23
  69. data/ext/ffi_c/libffi/src/s390/sysv.S +1 -1
  70. data/ext/ffi_c/libffi/src/sh/sysv.S +9 -9
  71. data/ext/ffi_c/libffi/src/sh64/ffi.c +37 -22
  72. data/ext/ffi_c/libffi/src/sh64/sysv.S +23 -14
  73. data/ext/ffi_c/libffi/src/sparc/ffi.c +21 -6
  74. data/ext/ffi_c/libffi/src/sparc/v8.S +55 -14
  75. data/ext/ffi_c/libffi/src/x86/darwin.S +10 -9
  76. data/ext/ffi_c/libffi/src/x86/ffi.c +293 -86
  77. data/ext/ffi_c/libffi/src/x86/ffi64.c +73 -19
  78. data/ext/ffi_c/libffi/src/x86/ffitarget.h +30 -0
  79. data/ext/ffi_c/libffi/src/x86/sysv.S +21 -4
  80. data/ext/ffi_c/libffi/src/x86/unix64.S +8 -4
  81. data/ext/ffi_c/libffi/src/x86/win32.S +633 -147
  82. data/ext/ffi_c/libffi/src/x86/win64.S +460 -0
  83. data/ext/ffi_c/libffi/testsuite/Makefile.am +63 -54
  84. data/ext/ffi_c/libffi/testsuite/Makefile.in +112 -77
  85. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +12 -1
  86. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +4 -4
  87. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +7 -15
  88. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +7 -15
  89. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +7 -15
  90. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +7 -15
  91. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +7 -15
  92. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +7 -14
  93. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +7 -15
  94. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_loc_fn0.c +95 -0
  95. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +6 -14
  96. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +4 -12
  97. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +4 -12
  98. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +4 -12
  99. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +4 -12
  100. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +4 -12
  101. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +4 -12
  102. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +4 -12
  103. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +4 -12
  104. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +4 -12
  105. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +4 -12
  106. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +4 -12
  107. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +4 -12
  108. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +4 -12
  109. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +4 -12
  110. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +4 -12
  111. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +4 -12
  112. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +4 -12
  113. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +4 -12
  114. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +4 -12
  115. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +4 -12
  116. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +4 -12
  117. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +4 -12
  118. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +4 -12
  119. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +4 -12
  120. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +4 -12
  121. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +4 -12
  122. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +4 -12
  123. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +134 -0
  124. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +117 -0
  125. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +11 -17
  126. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +4 -12
  127. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +4 -12
  128. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +7 -15
  129. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +4 -12
  130. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +4 -12
  131. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +7 -15
  132. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_dbls_struct.c +66 -0
  133. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +4 -12
  134. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +57 -0
  135. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +4 -13
  136. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +105 -0
  137. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +57 -0
  138. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +4 -12
  139. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +4 -12
  140. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +4 -12
  141. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +4 -12
  142. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +4 -12
  143. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +4 -12
  144. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +74 -0
  145. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +140 -0
  146. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +4 -12
  147. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +4 -12
  148. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +4 -12
  149. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +4 -12
  150. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +4 -12
  151. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +8 -16
  152. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +4 -12
  153. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +37 -0
  154. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +25 -0
  155. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +31 -0
  156. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +2 -1
  157. data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +342 -0
  158. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +4 -12
  159. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +4 -12
  160. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +4 -12
  161. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +4 -12
  162. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +4 -12
  163. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +4 -12
  164. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +4 -12
  165. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +4 -12
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +4 -12
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +4 -12
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +4 -12
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +4 -12
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +1 -1
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +1 -1
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large.c +145 -0
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large2.c +148 -0
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium.c +124 -0
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +124 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/testclosure.c +70 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +10 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +4 -5
  179. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +17 -16
  180. data/ext/ffi_c/libffi/texinfo.tex +155 -427
  181. data/lib/ffi/autopointer.rb +79 -20
  182. data/lib/ffi/callback.rb +4 -10
  183. data/lib/ffi/enum.rb +28 -0
  184. data/lib/ffi/io.rb +28 -0
  185. data/lib/ffi/library.rb +237 -182
  186. data/lib/ffi/memorypointer.rb +28 -62
  187. data/lib/ffi/platform.rb +27 -0
  188. data/lib/ffi/pointer.rb +28 -0
  189. data/lib/ffi/struct.rb +55 -1
  190. data/lib/ffi/types.rb +29 -0
  191. data/lib/ffi/variadic.rb +29 -0
  192. data/spec/ffi/library_spec.rb +31 -5
  193. data/spec/ffi/rbx/attach_function_spec.rb +2 -1
  194. data/spec/ffi/rbx/memory_pointer_spec.rb +2 -1
  195. data/spec/ffi/spec_helper.rb +5 -1
  196. data/spec/ffi/struct_spec.rb +64 -0
  197. metadata +28 -8
  198. data/ext/ffi_c/libffi/TODO +0 -1
  199. data/ext/ffi_c/libffi/ltcf-c.sh +0 -861
  200. data/ext/ffi_c/libffi/ltcf-cxx.sh +0 -1069
  201. data/ext/ffi_c/libffi/ltcf-gcj.sh +0 -700
  202. data/ext/ffi_c/libffi/ltconfig +0 -2862
  203. data/ext/ffi_c/libffi/mkinstalldirs +0 -158
@@ -59,7 +59,6 @@ rbffi_Pointer_NewInstance(void* addr)
59
59
  obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
60
60
  p->memory.address = addr;
61
61
  p->memory.size = LONG_MAX;
62
- p->memory.ops = &rbffi_AbstractMemoryOps;
63
62
  p->memory.access = (addr == NULL) ? 0 : (MEM_RD | MEM_WR);
64
63
  p->memory.typeSize = 1;
65
64
  p->parent = Qnil;
@@ -75,7 +74,6 @@ ptr_allocate(VALUE klass)
75
74
 
76
75
  obj = Data_Make_Struct(klass, Pointer, NULL, -1, p);
77
76
  p->parent = Qnil;
78
- p->memory.ops = &rbffi_AbstractMemoryOps;
79
77
  p->memory.access = MEM_RD | MEM_WR;
80
78
 
81
79
  return obj;
@@ -132,21 +130,19 @@ ptr_initialize(int argc, VALUE* argv, VALUE self)
132
130
 
133
131
 
134
132
  static VALUE
135
- ptr_plus(VALUE self, VALUE offset)
133
+ slice(VALUE self, long offset, long size)
136
134
  {
137
135
  AbstractMemory* ptr;
138
136
  Pointer* p;
139
137
  VALUE retval;
140
- long off = NUM2LONG(offset);
141
-
138
+
142
139
  Data_Get_Struct(self, AbstractMemory, ptr);
143
- checkBounds(ptr, off, 1);
140
+ checkBounds(ptr, offset, 1);
144
141
 
145
142
  retval = Data_Make_Struct(rbffi_PointerClass, Pointer, ptr_mark, -1, p);
146
143
 
147
- p->memory.address = ptr->address + off;
148
- p->memory.size = ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off;
149
- p->memory.ops = &rbffi_AbstractMemoryOps;
144
+ p->memory.address = ptr->address + offset;
145
+ p->memory.size = size;
150
146
  p->memory.access = ptr->access;
151
147
  p->memory.typeSize = ptr->typeSize;
152
148
  p->parent = self;
@@ -154,6 +150,23 @@ ptr_plus(VALUE self, VALUE offset)
154
150
  return retval;
155
151
  }
156
152
 
153
+ static VALUE
154
+ ptr_plus(VALUE self, VALUE offset)
155
+ {
156
+ AbstractMemory* ptr;
157
+ long off = NUM2LONG(offset);
158
+
159
+ Data_Get_Struct(self, AbstractMemory, ptr);
160
+
161
+ return slice(self, off, ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off);
162
+ }
163
+
164
+ static VALUE
165
+ ptr_slice(VALUE self, VALUE rbOffset, VALUE rbLength)
166
+ {
167
+ return slice(self, NUM2LONG(rbOffset), NUM2LONG(rbLength));
168
+ }
169
+
157
170
  static VALUE
158
171
  ptr_inspect(VALUE self)
159
172
  {
@@ -214,6 +227,7 @@ rbffi_Pointer_Init(VALUE moduleFFI)
214
227
  rb_define_method(rbffi_PointerClass, "initialize", ptr_initialize, -1);
215
228
  rb_define_method(rbffi_PointerClass, "inspect", ptr_inspect, 0);
216
229
  rb_define_method(rbffi_PointerClass, "+", ptr_plus, 1);
230
+ rb_define_method(rbffi_PointerClass, "slice", ptr_slice, 2);
217
231
  rb_define_method(rbffi_PointerClass, "null?", ptr_null_p, 0);
218
232
  rb_define_method(rbffi_PointerClass, "address", ptr_address, 0);
219
233
  rb_define_alias(rbffi_PointerClass, "to_i", "address");
@@ -63,6 +63,8 @@ typedef struct InlineArray_ {
63
63
  StructField* field;
64
64
  MemoryOp *op;
65
65
  Type* componentType;
66
+ ArrayType* arrayType;
67
+ unsigned int length;
66
68
  } InlineArray;
67
69
 
68
70
 
@@ -77,6 +79,8 @@ VALUE rbffi_StructClass = Qnil;
77
79
  static VALUE StructLayoutBuilderClass = Qnil;
78
80
 
79
81
  VALUE rbffi_StructInlineArrayClass = Qnil;
82
+ VALUE rbffi_StructLayoutCharArrayClass = Qnil;
83
+
80
84
  static ID id_pointer_ivar = 0, id_layout_ivar = 0;
81
85
  static ID id_get = 0, id_put = 0, id_to_ptr = 0, id_to_s = 0, id_layout = 0;
82
86
 
@@ -132,11 +136,6 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
132
136
  s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
133
137
  }
134
138
 
135
- if (s->pointer->ops == NULL) {
136
- VALUE name = rb_class_name(CLASS_OF(s->rbPointer));
137
- rb_raise(rb_eRuntimeError, "No memory ops set for %s", StringValueCStr(name));
138
- }
139
-
140
139
  return self;
141
140
  }
142
141
 
@@ -171,19 +170,22 @@ struct_aref(VALUE self, VALUE fieldName)
171
170
  Struct* s;
172
171
  VALUE rbField;
173
172
  StructField* f;
174
- MemoryOp* op;
175
-
173
+
176
174
  Data_Get_Struct(self, Struct, s);
177
175
  rbField = struct_field(s, fieldName);
178
176
  f = (StructField *) DATA_PTR(rbField);
179
177
 
180
- op = memory_get_op(s->pointer, f->type);
181
- if (op != NULL) {
182
- return (*op->get)(s->pointer, f->offset);
183
- }
178
+ if (f->get != NULL) {
179
+ return (*f->get)(f, s);
180
+
181
+ } else if (f->memoryOp != NULL) {
182
+ return (*f->memoryOp->get)(s->pointer, f->offset);
183
+
184
+ } else {
184
185
 
185
- /* call up to the ruby code to fetch the value */
186
- return rb_funcall2(rbField, id_get, 1, &s->rbPointer);
186
+ /* call up to the ruby code to fetch the value */
187
+ return rb_funcall2(rbField, id_get, 1, &s->rbPointer);
188
+ }
187
189
  }
188
190
 
189
191
  static VALUE
@@ -192,25 +194,27 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value)
192
194
  Struct* s;
193
195
  VALUE rbField;
194
196
  StructField* f;
195
- MemoryOp* op;
196
- VALUE argv[2];
197
+
197
198
 
198
199
  Data_Get_Struct(self, Struct, s);
199
200
  rbField = struct_field(s, fieldName);
200
201
  f = (StructField *) DATA_PTR(rbField);
202
+ if (f->put != NULL) {
203
+ (*f->put)(f, s, value);
201
204
 
202
- op = memory_get_op(s->pointer, f->type);
203
- if (op != NULL) {
204
- (*op->put)(s->pointer, f->offset, value);
205
- return self;
206
- }
205
+ } else if (f->memoryOp != NULL) {
206
+
207
+ (*f->memoryOp->put)(s->pointer, f->offset, value);
207
208
 
208
- /* call up to the ruby code to set the value */
209
- argv[0] = s->rbPointer;
210
- argv[1] = value;
211
- rb_funcall2(rbField, id_put, 2, argv);
209
+ } else {
210
+ /* call up to the ruby code to set the value */
211
+ VALUE argv[2];
212
+ argv[0] = s->rbPointer;
213
+ argv[1] = value;
214
+ rb_funcall2(rbField, id_put, 2, argv);
215
+ }
212
216
 
213
- return self;
217
+ return value;
214
218
  }
215
219
 
216
220
  static VALUE
@@ -425,16 +429,32 @@ struct_layout_builder_add_field(int argc, VALUE* argv, VALUE self)
425
429
  fargv[0] = rbName;
426
430
  fargv[1] = UINT2NUM(offset);
427
431
  fargv[2] = rbType;
432
+
428
433
  if (rb_obj_is_kind_of(rbType, rbffi_FunctionTypeClass)) {
434
+
429
435
  rbFieldClass = rbffi_StructLayoutFunctionFieldClass;
436
+
430
437
  } else if (rb_obj_is_kind_of(rbType, rbffi_StructByValueClass)) {
431
- rbFieldClass = rbffi_StructLayoutStructFieldClass;
438
+
439
+ rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("InlineStruct"));
440
+
432
441
  } else if (rb_obj_is_kind_of(rbType, rbffi_ArrayTypeClass)) {
442
+
433
443
  rbFieldClass = rbffi_StructLayoutArrayFieldClass;
444
+
445
+ } else if (rb_obj_is_kind_of(rbType, rbffi_EnumTypeClass)) {
446
+
447
+ rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("Enum"));
448
+
434
449
  } else {
435
450
  rbFieldClass = rbffi_StructLayoutFieldClass;
436
451
  }
437
452
 
453
+ if (!RTEST(rbFieldClass)) {
454
+ rb_raise(rb_eTypeError, "invalid struct field type (%s)", rb_obj_classname(rbType));
455
+ return Qnil;
456
+ }
457
+
438
458
  rbField = rb_class_new_instance(3, fargv, rbFieldClass);
439
459
  } else {
440
460
  rbField = rbType;
@@ -449,7 +469,8 @@ static VALUE
449
469
  struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
450
470
  {
451
471
  StructLayoutBuilder* builder;
452
- VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil, rbStructClass = Qnil;
472
+ VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
473
+ VALUE rbFieldClass = Qnil, rbStructClass = Qnil;
453
474
  VALUE fargv[3];
454
475
  unsigned int size, alignment, offset;
455
476
  int nargs;
@@ -472,7 +493,14 @@ struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
472
493
  fargv[0] = rbName;
473
494
  fargv[1] = UINT2NUM(offset);
474
495
  fargv[2] = rbType;
475
- rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutStructFieldClass);
496
+ rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("InlineStruct"));
497
+ if (!RTEST(rbFieldClass)) {
498
+ rb_raise(rb_eRuntimeError, "could not locate StructLayout::InlineStruct");
499
+ return Qnil;
500
+ }
501
+
502
+ rbField = rb_class_new_instance(3, fargv, rbFieldClass);
503
+
476
504
  store_field(builder, rbName, rbField, offset, size, alignment);
477
505
 
478
506
  return self;
@@ -554,21 +582,18 @@ static VALUE
554
582
  inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
555
583
  {
556
584
  InlineArray* array;
557
- ArrayType* arrayType;
558
-
585
+
559
586
  Data_Get_Struct(self, InlineArray, array);
560
587
  array->rbMemory = rbMemory;
561
588
  array->rbField = rbField;
562
589
 
563
590
  Data_Get_Struct(rbMemory, AbstractMemory, array->memory);
564
591
  Data_Get_Struct(rbField, StructField, array->field);
565
- Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
566
- Data_Get_Struct(arrayType->rbComponentType, Type, array->componentType);
592
+ Data_Get_Struct(array->field->rbType, ArrayType, array->arrayType);
593
+ Data_Get_Struct(array->arrayType->rbComponentType, Type, array->componentType);
567
594
 
568
- array->op = memory_get_op(array->memory, array->componentType);
569
- if (array->op == NULL) {
570
- rb_raise(rb_eRuntimeError, "invalid memory ops");
571
- }
595
+ array->op = get_memory_op(array->componentType);
596
+ array->length = array->arrayType->length;
572
597
 
573
598
  return self;
574
599
  }
@@ -584,8 +609,12 @@ inline_array_size(VALUE self)
584
609
  }
585
610
 
586
611
  static int
587
- inline_array_offset(InlineArray* array, unsigned int index)
612
+ inline_array_offset(InlineArray* array, int index)
588
613
  {
614
+ if (index < 0 || index >= array->length) {
615
+ rb_raise(rb_eIndexError, "index %d out of bounds", index);
616
+ }
617
+
589
618
  return array->field->offset + (index * array->componentType->ffiType->size);
590
619
  }
591
620
 
@@ -596,7 +625,19 @@ inline_array_aref(VALUE self, VALUE rbIndex)
596
625
 
597
626
  Data_Get_Struct(self, InlineArray, array);
598
627
 
599
- return array->op->get(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)));
628
+ if (array->op != NULL) {
629
+ return array->op->get(array->memory, inline_array_offset(array, NUM2INT(rbIndex)));
630
+ } else if (array->componentType->nativeType == NATIVE_STRUCT) {
631
+ VALUE rbOffset = INT2NUM(inline_array_offset(array, NUM2INT(rbIndex)));
632
+ VALUE rbLength = INT2NUM(array->componentType->ffiType->size);
633
+ VALUE rbPointer = rb_funcall(array->rbMemory, rb_intern("slice"), 2, rbOffset, rbLength);
634
+
635
+ return rb_class_new_instance(1, &rbPointer, ((StructByValue *) array->componentType)->rbStructClass);
636
+ } else {
637
+
638
+ rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(array->arrayType->rbComponentType));
639
+ return Qnil;
640
+ }
600
641
  }
601
642
 
602
643
  static VALUE
@@ -606,8 +647,34 @@ inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue)
606
647
 
607
648
  Data_Get_Struct(self, InlineArray, array);
608
649
 
609
- array->op->put(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)),
610
- rbValue);
650
+ if (array->op != NULL) {
651
+ array->op->put(array->memory, inline_array_offset(array, NUM2INT(rbIndex)),
652
+ rbValue);
653
+ } else if (array->componentType->nativeType == NATIVE_STRUCT) {
654
+ int offset = inline_array_offset(array, NUM2INT(rbIndex));
655
+ Struct* s;
656
+
657
+ if (!rb_obj_is_kind_of(rbValue, rbffi_StructClass)) {
658
+ rb_raise(rb_eTypeError, "argument not an instance of struct");
659
+ return Qnil;
660
+ }
661
+
662
+ checkWrite(array->memory);
663
+ checkBounds(array->memory, offset, array->componentType->ffiType->size);
664
+
665
+ Data_Get_Struct(rbValue, Struct, s);
666
+ checkRead(s->pointer);
667
+ checkBounds(s->pointer, 0, array->componentType->ffiType->size);
668
+
669
+ memcpy(array->memory->address + offset, s->pointer->address, array->componentType->ffiType->size);
670
+
671
+ } else {
672
+ ArrayType* arrayType;
673
+ Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
674
+
675
+ rb_raise(rb_eArgError, "set not supported for %s", rb_obj_classname(arrayType->rbComponentType));
676
+ return Qnil;
677
+ }
611
678
 
612
679
  return rbValue;
613
680
  }
@@ -616,16 +683,30 @@ static VALUE
616
683
  inline_array_each(VALUE self)
617
684
  {
618
685
  InlineArray* array;
619
- ArrayType* arrayType;
620
686
 
621
687
  int i;
622
688
 
623
689
  Data_Get_Struct(self, InlineArray, array);
624
- Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
690
+
691
+ if (array->op != NULL) {
692
+ for (i = 0; i < array->length; ++i) {
693
+ int offset = inline_array_offset(array, i);
694
+ rb_yield(array->op->get(array->memory, offset));
695
+ }
696
+ } else if (array->componentType->nativeType == NATIVE_STRUCT) {
697
+ for (i = 0; i < array->length; ++i) {
698
+ VALUE rbOffset = UINT2NUM(inline_array_offset(array, i));
699
+ VALUE rbLength = UINT2NUM(array->componentType->ffiType->size);
700
+ VALUE rbPointer = rb_funcall(array->rbMemory, rb_intern("slice"), 2, rbOffset, rbLength);
625
701
 
626
- for (i = 0; i < arrayType->length; ++i) {
627
- int offset = inline_array_offset(array, i);
628
- rb_yield(array->op->get(array->memory, offset));
702
+ rb_yield(rb_class_new_instance(1, &rbPointer, ((StructByValue *) array->componentType)->rbStructClass));
703
+ }
704
+ } else {
705
+ ArrayType* arrayType;
706
+ Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
707
+
708
+ rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(arrayType->rbComponentType));
709
+ return Qnil;
629
710
  }
630
711
 
631
712
  return self;
@@ -635,16 +716,14 @@ static VALUE
635
716
  inline_array_to_a(VALUE self)
636
717
  {
637
718
  InlineArray* array;
638
- ArrayType* arrayType;
639
719
  VALUE obj;
640
720
  int i;
641
721
 
642
722
  Data_Get_Struct(self, InlineArray, array);
643
- Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
644
- obj = rb_ary_new2(arrayType->length);
723
+ obj = rb_ary_new2(array->length);
645
724
 
646
725
 
647
- for (i = 0; i < arrayType->length; ++i) {
726
+ for (i = 0; i < array->length; ++i) {
648
727
  int offset = inline_array_offset(array, i);
649
728
  rb_ary_push(obj, array->op->get(array->memory, offset));
650
729
  }
@@ -656,19 +735,17 @@ static VALUE
656
735
  inline_array_to_s(VALUE self)
657
736
  {
658
737
  InlineArray* array;
659
- ArrayType* arrayType;
660
738
  VALUE argv[2];
661
739
 
662
740
  Data_Get_Struct(self, InlineArray, array);
663
- Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
664
-
665
- if (arrayType->componentType->nativeType != NATIVE_INT8 && arrayType->componentType->nativeType != NATIVE_UINT8) {
666
- rb_raise(rb_eNoMethodError, "to_s not defined for this array type");
667
- return Qnil;
741
+
742
+ if (array->componentType->nativeType != NATIVE_INT8 && array->componentType->nativeType != NATIVE_UINT8) {
743
+ VALUE dummy = Qnil;
744
+ return rb_call_super(0, &dummy);
668
745
  }
669
746
 
670
747
  argv[0] = UINT2NUM(array->field->offset);
671
- argv[1] = UINT2NUM(arrayType->length);
748
+ argv[1] = UINT2NUM(array->length);
672
749
 
673
750
  return rb_funcall2(array->rbMemory, rb_intern("get_string"), 2, argv);
674
751
  }
@@ -678,19 +755,11 @@ static VALUE
678
755
  inline_array_to_ptr(VALUE self)
679
756
  {
680
757
  InlineArray* array;
681
- AbstractMemory* ptr;
682
- VALUE rbOffset, rbPointer;
683
-
684
- Data_Get_Struct(self, InlineArray, array);
685
-
686
- rbOffset = UINT2NUM(array->field->offset);
687
- rbPointer = rb_funcall2(array->rbMemory, rb_intern("+"), 1, &rbOffset);
688
- Data_Get_Struct(rbPointer, AbstractMemory, ptr);
689
758
 
690
- // Restrict the size of the pointer so ops like ptr.get_string(0) are bounds checked
691
- ptr->size = MIN(ptr->size, array->field->type->ffiType->size);
759
+ Data_Get_Struct(self, InlineArray, array);
692
760
 
693
- return rbPointer;
761
+ return rb_funcall(array->rbMemory, rb_intern("slice"), 2,
762
+ UINT2NUM(array->field->offset), UINT2NUM(array->arrayType->base.ffiType->size));
694
763
  }
695
764
 
696
765
 
@@ -711,6 +780,9 @@ rbffi_Struct_Init(VALUE moduleFFI)
711
780
  rbffi_StructInlineArrayClass = rb_define_class_under(rbffi_StructClass, "InlineArray", rb_cObject);
712
781
  rb_global_variable(&rbffi_StructInlineArrayClass);
713
782
 
783
+ rbffi_StructLayoutCharArrayClass = rb_define_class_under(rbffi_StructLayoutClass,
784
+ "CharArray", rbffi_StructInlineArrayClass);
785
+ rb_global_variable(&rbffi_StructLayoutCharArrayClass);
714
786
 
715
787
 
716
788
  rb_define_alloc_func(StructClass, struct_allocate);
@@ -756,10 +828,11 @@ rbffi_Struct_Init(VALUE moduleFFI)
756
828
  rb_define_method(rbffi_StructInlineArrayClass, "each", inline_array_each, 0);
757
829
  rb_define_method(rbffi_StructInlineArrayClass, "size", inline_array_size, 0);
758
830
  rb_define_method(rbffi_StructInlineArrayClass, "to_a", inline_array_to_a, 0);
759
- rb_define_method(rbffi_StructInlineArrayClass, "to_s", inline_array_to_s, 0);
760
- rb_define_alias(rbffi_StructInlineArrayClass, "to_str", "to_s");
761
831
  rb_define_method(rbffi_StructInlineArrayClass, "to_ptr", inline_array_to_ptr, 0);
762
832
 
833
+ rb_define_method(rbffi_StructLayoutCharArrayClass, "to_s", inline_array_to_s, 0);
834
+ rb_define_alias(rbffi_StructLayoutCharArrayClass, "to_str", "to_s");
835
+
763
836
  id_pointer_ivar = rb_intern("@pointer");
764
837
  id_layout_ivar = rb_intern("@layout");
765
838
  id_layout = rb_intern("layout");