alinta-ffi 1.9.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +49 -0
  3. data/LICENSE +24 -0
  4. data/README.md +112 -0
  5. data/Rakefile +243 -0
  6. data/ext/ffi_c/AbstractMemory.c +1109 -0
  7. data/ext/ffi_c/AbstractMemory.h +175 -0
  8. data/ext/ffi_c/ArrayType.c +162 -0
  9. data/ext/ffi_c/ArrayType.h +59 -0
  10. data/ext/ffi_c/Buffer.c +365 -0
  11. data/ext/ffi_c/Call.c +517 -0
  12. data/ext/ffi_c/Call.h +110 -0
  13. data/ext/ffi_c/ClosurePool.c +283 -0
  14. data/ext/ffi_c/ClosurePool.h +57 -0
  15. data/ext/ffi_c/DataConverter.c +91 -0
  16. data/ext/ffi_c/DynamicLibrary.c +339 -0
  17. data/ext/ffi_c/DynamicLibrary.h +98 -0
  18. data/ext/ffi_c/Function.c +998 -0
  19. data/ext/ffi_c/Function.h +87 -0
  20. data/ext/ffi_c/FunctionInfo.c +271 -0
  21. data/ext/ffi_c/LastError.c +184 -0
  22. data/ext/ffi_c/LastError.h +47 -0
  23. data/ext/ffi_c/LongDouble.c +63 -0
  24. data/ext/ffi_c/LongDouble.h +51 -0
  25. data/ext/ffi_c/MappedType.c +168 -0
  26. data/ext/ffi_c/MappedType.h +59 -0
  27. data/ext/ffi_c/MemoryPointer.c +197 -0
  28. data/ext/ffi_c/MemoryPointer.h +53 -0
  29. data/ext/ffi_c/MethodHandle.c +358 -0
  30. data/ext/ffi_c/MethodHandle.h +55 -0
  31. data/ext/ffi_c/Platform.c +129 -0
  32. data/ext/ffi_c/Platform.h +45 -0
  33. data/ext/ffi_c/Pointer.c +508 -0
  34. data/ext/ffi_c/Pointer.h +63 -0
  35. data/ext/ffi_c/Struct.c +829 -0
  36. data/ext/ffi_c/Struct.h +106 -0
  37. data/ext/ffi_c/StructByReference.c +190 -0
  38. data/ext/ffi_c/StructByReference.h +50 -0
  39. data/ext/ffi_c/StructByValue.c +150 -0
  40. data/ext/ffi_c/StructByValue.h +55 -0
  41. data/ext/ffi_c/StructLayout.c +698 -0
  42. data/ext/ffi_c/Thread.c +352 -0
  43. data/ext/ffi_c/Thread.h +95 -0
  44. data/ext/ffi_c/Type.c +397 -0
  45. data/ext/ffi_c/Type.h +62 -0
  46. data/ext/ffi_c/Types.c +139 -0
  47. data/ext/ffi_c/Types.h +89 -0
  48. data/ext/ffi_c/Variadic.c +304 -0
  49. data/ext/ffi_c/compat.h +78 -0
  50. data/ext/ffi_c/extconf.rb +71 -0
  51. data/ext/ffi_c/ffi.c +98 -0
  52. data/ext/ffi_c/libffi.bsd.mk +40 -0
  53. data/ext/ffi_c/libffi.darwin.mk +105 -0
  54. data/ext/ffi_c/libffi.gnu.mk +32 -0
  55. data/ext/ffi_c/libffi.mk +18 -0
  56. data/ext/ffi_c/libffi.vc.mk +26 -0
  57. data/ext/ffi_c/libffi.vc64.mk +26 -0
  58. data/ext/ffi_c/rbffi.h +57 -0
  59. data/ext/ffi_c/rbffi_endian.h +59 -0
  60. data/ext/ffi_c/win32/stdbool.h +8 -0
  61. data/ext/ffi_c/win32/stdint.h +201 -0
  62. data/ffi.gemspec +23 -0
  63. data/gen/Rakefile +30 -0
  64. data/lib/ffi.rb +20 -0
  65. data/lib/ffi/autopointer.rb +203 -0
  66. data/lib/ffi/buffer.rb +4 -0
  67. data/lib/ffi/callback.rb +4 -0
  68. data/lib/ffi/enum.rb +296 -0
  69. data/lib/ffi/errno.rb +43 -0
  70. data/lib/ffi/ffi.rb +44 -0
  71. data/lib/ffi/io.rb +62 -0
  72. data/lib/ffi/library.rb +590 -0
  73. data/lib/ffi/managedstruct.rb +84 -0
  74. data/lib/ffi/memorypointer.rb +1 -0
  75. data/lib/ffi/platform.rb +164 -0
  76. data/lib/ffi/platform/aarch64-linux/types.conf +104 -0
  77. data/lib/ffi/platform/arm-linux/types.conf +104 -0
  78. data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
  79. data/lib/ffi/platform/i386-darwin/types.conf +100 -0
  80. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  81. data/lib/ffi/platform/i386-gnu/types.conf +107 -0
  82. data/lib/ffi/platform/i386-linux/types.conf +103 -0
  83. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  84. data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
  85. data/lib/ffi/platform/i386-solaris/types.conf +122 -0
  86. data/lib/ffi/platform/i386-windows/types.conf +105 -0
  87. data/lib/ffi/platform/ia64-linux/types.conf +104 -0
  88. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  89. data/lib/ffi/platform/mips64el-linux/types.conf +104 -0
  90. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  91. data/lib/ffi/platform/powerpc-aix/types.conf +180 -0
  92. data/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
  93. data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
  94. data/lib/ffi/platform/powerpc64-linux/types.conf +104 -0
  95. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  96. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  97. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  98. data/lib/ffi/platform/sparc-solaris/types.conf +128 -0
  99. data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
  100. data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
  101. data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
  102. data/lib/ffi/platform/x86_64-darwin/types.conf +126 -0
  103. data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
  104. data/lib/ffi/platform/x86_64-linux/types.conf +102 -0
  105. data/lib/ffi/platform/x86_64-netbsd/types.conf +128 -0
  106. data/lib/ffi/platform/x86_64-openbsd/types.conf +134 -0
  107. data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
  108. data/lib/ffi/platform/x86_64-windows/types.conf +120 -0
  109. data/lib/ffi/pointer.rb +161 -0
  110. data/lib/ffi/struct.rb +371 -0
  111. data/lib/ffi/struct_layout_builder.rb +227 -0
  112. data/lib/ffi/tools/const_generator.rb +229 -0
  113. data/lib/ffi/tools/generator.rb +60 -0
  114. data/lib/ffi/tools/generator_task.rb +36 -0
  115. data/lib/ffi/tools/struct_generator.rb +194 -0
  116. data/lib/ffi/tools/types_generator.rb +134 -0
  117. data/lib/ffi/types.rb +194 -0
  118. data/lib/ffi/union.rb +43 -0
  119. data/lib/ffi/variadic.rb +78 -0
  120. data/lib/ffi/version.rb +4 -0
  121. data/libtest/Benchmark.c +52 -0
  122. data/libtest/BoolTest.c +34 -0
  123. data/libtest/BufferTest.c +31 -0
  124. data/libtest/ClosureTest.c +205 -0
  125. data/libtest/EnumTest.c +51 -0
  126. data/libtest/FunctionTest.c +70 -0
  127. data/libtest/GNUmakefile +149 -0
  128. data/libtest/GlobalVariable.c +62 -0
  129. data/libtest/LastErrorTest.c +21 -0
  130. data/libtest/NumberTest.c +132 -0
  131. data/libtest/PointerTest.c +63 -0
  132. data/libtest/ReferenceTest.c +23 -0
  133. data/libtest/StringTest.c +34 -0
  134. data/libtest/StructTest.c +243 -0
  135. data/libtest/UnionTest.c +43 -0
  136. data/libtest/VariadicTest.c +99 -0
  137. data/spec/ffi/LICENSE.SPECS +22 -0
  138. data/spec/ffi/async_callback_spec.rb +35 -0
  139. data/spec/ffi/bitmask_spec.rb +575 -0
  140. data/spec/ffi/bool_spec.rb +32 -0
  141. data/spec/ffi/buffer_spec.rb +279 -0
  142. data/spec/ffi/callback_spec.rb +773 -0
  143. data/spec/ffi/custom_param_type.rb +37 -0
  144. data/spec/ffi/custom_type_spec.rb +74 -0
  145. data/spec/ffi/dup_spec.rb +52 -0
  146. data/spec/ffi/enum_spec.rb +423 -0
  147. data/spec/ffi/errno_spec.rb +20 -0
  148. data/spec/ffi/ffi_spec.rb +28 -0
  149. data/spec/ffi/fixtures/Benchmark.c +52 -0
  150. data/spec/ffi/fixtures/BitmaskTest.c +51 -0
  151. data/spec/ffi/fixtures/BoolTest.c +34 -0
  152. data/spec/ffi/fixtures/BufferTest.c +31 -0
  153. data/spec/ffi/fixtures/ClosureTest.c +205 -0
  154. data/spec/ffi/fixtures/EnumTest.c +51 -0
  155. data/spec/ffi/fixtures/FunctionTest.c +142 -0
  156. data/spec/ffi/fixtures/GNUmakefile +149 -0
  157. data/spec/ffi/fixtures/GlobalVariable.c +62 -0
  158. data/spec/ffi/fixtures/LastErrorTest.c +21 -0
  159. data/spec/ffi/fixtures/NumberTest.c +132 -0
  160. data/spec/ffi/fixtures/PipeHelper.h +21 -0
  161. data/spec/ffi/fixtures/PipeHelperPosix.c +41 -0
  162. data/spec/ffi/fixtures/PipeHelperWindows.c +72 -0
  163. data/spec/ffi/fixtures/PointerTest.c +63 -0
  164. data/spec/ffi/fixtures/ReferenceTest.c +23 -0
  165. data/spec/ffi/fixtures/StringTest.c +34 -0
  166. data/spec/ffi/fixtures/StructTest.c +243 -0
  167. data/spec/ffi/fixtures/UnionTest.c +43 -0
  168. data/spec/ffi/fixtures/VariadicTest.c +99 -0
  169. data/spec/ffi/fixtures/classes.rb +438 -0
  170. data/spec/ffi/function_spec.rb +97 -0
  171. data/spec/ffi/io_spec.rb +16 -0
  172. data/spec/ffi/library_spec.rb +286 -0
  173. data/spec/ffi/long_double.rb +30 -0
  174. data/spec/ffi/managed_struct_spec.rb +68 -0
  175. data/spec/ffi/memorypointer_spec.rb +78 -0
  176. data/spec/ffi/number_spec.rb +247 -0
  177. data/spec/ffi/platform_spec.rb +114 -0
  178. data/spec/ffi/pointer_spec.rb +285 -0
  179. data/spec/ffi/rbx/attach_function_spec.rb +34 -0
  180. data/spec/ffi/rbx/memory_pointer_spec.rb +198 -0
  181. data/spec/ffi/rbx/spec_helper.rb +6 -0
  182. data/spec/ffi/rbx/struct_spec.rb +18 -0
  183. data/spec/ffi/spec_helper.rb +93 -0
  184. data/spec/ffi/string_spec.rb +118 -0
  185. data/spec/ffi/strptr_spec.rb +50 -0
  186. data/spec/ffi/struct_by_ref_spec.rb +43 -0
  187. data/spec/ffi/struct_callback_spec.rb +69 -0
  188. data/spec/ffi/struct_initialize_spec.rb +35 -0
  189. data/spec/ffi/struct_packed_spec.rb +50 -0
  190. data/spec/ffi/struct_spec.rb +882 -0
  191. data/spec/ffi/typedef_spec.rb +91 -0
  192. data/spec/ffi/union_spec.rb +67 -0
  193. data/spec/ffi/variadic_spec.rb +132 -0
  194. data/spec/spec.opts +4 -0
  195. metadata +309 -0
@@ -0,0 +1,175 @@
1
+ /*
2
+ * Copyright (c) 2008, 2009, Wayne Meissner
3
+ *
4
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of the Ruby FFI project nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifndef RBFFI_ABSTRACTMEMORY_H
31
+ #define RBFFI_ABSTRACTMEMORY_H
32
+
33
+ #ifndef _MSC_VER
34
+ #include <sys/param.h>
35
+ #endif
36
+ #include <sys/types.h>
37
+ #ifndef _MSC_VER
38
+ #include <stdint.h>
39
+ #endif
40
+
41
+ #include "compat.h"
42
+ #include "Types.h"
43
+
44
+ #ifdef __cplusplus
45
+ extern "C" {
46
+ #endif
47
+
48
+
49
+ #define MEM_RD 0x01
50
+ #define MEM_WR 0x02
51
+ #define MEM_CODE 0x04
52
+ #define MEM_SWAP 0x08
53
+ #define MEM_EMBED 0x10
54
+
55
+ typedef struct AbstractMemory_ AbstractMemory;
56
+
57
+ typedef struct {
58
+ VALUE (*get)(AbstractMemory* ptr, long offset);
59
+ void (*put)(AbstractMemory* ptr, long offset, VALUE value);
60
+ } MemoryOp;
61
+
62
+ typedef struct {
63
+ MemoryOp* int8;
64
+ MemoryOp* uint8;
65
+ MemoryOp* int16;
66
+ MemoryOp* uint16;
67
+ MemoryOp* int32;
68
+ MemoryOp* uint32;
69
+ MemoryOp* int64;
70
+ MemoryOp* uint64;
71
+ MemoryOp* slong;
72
+ MemoryOp* uslong;
73
+ MemoryOp* float32;
74
+ MemoryOp* float64;
75
+ MemoryOp* longdouble;
76
+ MemoryOp* pointer;
77
+ MemoryOp* strptr;
78
+ MemoryOp* boolOp;
79
+ } MemoryOps;
80
+
81
+ struct AbstractMemory_ {
82
+ char* address; /* Use char* instead of void* to ensure adding to it works correctly */
83
+ long size;
84
+ int flags;
85
+ int typeSize;
86
+ };
87
+
88
+
89
+ extern VALUE rbffi_AbstractMemoryClass;
90
+ extern MemoryOps rbffi_AbstractMemoryOps;
91
+
92
+ extern void rbffi_AbstractMemory_Init(VALUE ffiModule);
93
+
94
+ extern AbstractMemory* rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass);
95
+
96
+ extern void rbffi_AbstractMemory_Error(AbstractMemory *, int op);
97
+
98
+ static inline void
99
+ checkBounds(AbstractMemory* mem, long off, long len)
100
+ {
101
+ if (unlikely((off | len | (off + len) | (mem->size - (off + len))) < 0)) {
102
+ rb_raise(rb_eIndexError, "Memory access offset=%ld size=%ld is out of bounds",
103
+ off, len);
104
+ }
105
+ }
106
+
107
+ static inline void
108
+ checkRead(AbstractMemory* mem)
109
+ {
110
+ if (unlikely((mem->flags & MEM_RD) == 0)) {
111
+ rbffi_AbstractMemory_Error(mem, MEM_RD);
112
+ }
113
+ }
114
+
115
+ static inline void
116
+ checkWrite(AbstractMemory* mem)
117
+ {
118
+ if (unlikely((mem->flags & MEM_WR) == 0)) {
119
+ rbffi_AbstractMemory_Error(mem, MEM_WR);
120
+ }
121
+ }
122
+
123
+ static inline MemoryOp*
124
+ get_memory_op(Type* type)
125
+ {
126
+ switch (type->nativeType) {
127
+ case NATIVE_INT8:
128
+ return rbffi_AbstractMemoryOps.int8;
129
+ case NATIVE_UINT8:
130
+ return rbffi_AbstractMemoryOps.uint8;
131
+ case NATIVE_INT16:
132
+ return rbffi_AbstractMemoryOps.int16;
133
+ case NATIVE_UINT16:
134
+ return rbffi_AbstractMemoryOps.uint16;
135
+ case NATIVE_INT32:
136
+ return rbffi_AbstractMemoryOps.int32;
137
+ case NATIVE_UINT32:
138
+ return rbffi_AbstractMemoryOps.uint32;
139
+ case NATIVE_INT64:
140
+ return rbffi_AbstractMemoryOps.int64;
141
+ case NATIVE_UINT64:
142
+ return rbffi_AbstractMemoryOps.uint64;
143
+ case NATIVE_LONG:
144
+ return rbffi_AbstractMemoryOps.slong;
145
+ case NATIVE_ULONG:
146
+ return rbffi_AbstractMemoryOps.uslong;
147
+ case NATIVE_FLOAT32:
148
+ return rbffi_AbstractMemoryOps.float32;
149
+ case NATIVE_FLOAT64:
150
+ return rbffi_AbstractMemoryOps.float64;
151
+ case NATIVE_LONGDOUBLE:
152
+ return rbffi_AbstractMemoryOps.longdouble;
153
+ case NATIVE_POINTER:
154
+ return rbffi_AbstractMemoryOps.pointer;
155
+ case NATIVE_STRING:
156
+ return rbffi_AbstractMemoryOps.strptr;
157
+ case NATIVE_BOOL:
158
+ return rbffi_AbstractMemoryOps.boolOp;
159
+ default:
160
+ return NULL;
161
+ }
162
+ }
163
+
164
+ #define MEMORY(obj) rbffi_AbstractMemory_Cast((obj), rbffi_AbstractMemoryClass)
165
+ #define MEMORY_PTR(obj) MEMORY((obj))->address
166
+ #define MEMORY_LEN(obj) MEMORY((obj))->size
167
+
168
+
169
+
170
+ #ifdef __cplusplus
171
+ }
172
+ #endif
173
+
174
+ #endif /* RBFFI_ABSTRACTMEMORY_H */
175
+
@@ -0,0 +1,162 @@
1
+ /*
2
+ * Copyright (c) 2009, Wayne Meissner
3
+ *
4
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of the Ruby FFI project nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #include <ruby.h>
31
+ #include <ffi.h>
32
+ #include "ArrayType.h"
33
+
34
+ static VALUE array_type_s_allocate(VALUE klass);
35
+ static VALUE array_type_initialize(VALUE self, VALUE rbComponentType, VALUE rbLength);
36
+ static void array_type_mark(ArrayType *);
37
+ static void array_type_free(ArrayType *);
38
+
39
+ VALUE rbffi_ArrayTypeClass = Qnil;
40
+
41
+ static VALUE
42
+ array_type_s_allocate(VALUE klass)
43
+ {
44
+ ArrayType* array;
45
+ VALUE obj;
46
+
47
+ obj = Data_Make_Struct(klass, ArrayType, array_type_mark, array_type_free, array);
48
+
49
+ array->base.nativeType = NATIVE_ARRAY;
50
+ array->base.ffiType = xcalloc(1, sizeof(*array->base.ffiType));
51
+ array->base.ffiType->type = FFI_TYPE_STRUCT;
52
+ array->base.ffiType->size = 0;
53
+ array->base.ffiType->alignment = 0;
54
+ array->rbComponentType = Qnil;
55
+
56
+ return obj;
57
+ }
58
+
59
+ static void
60
+ array_type_mark(ArrayType *array)
61
+ {
62
+ rb_gc_mark(array->rbComponentType);
63
+ }
64
+
65
+ static void
66
+ array_type_free(ArrayType *array)
67
+ {
68
+ xfree(array->base.ffiType);
69
+ xfree(array->ffiTypes);
70
+ xfree(array);
71
+ }
72
+
73
+
74
+ /*
75
+ * call-seq: initialize(component_type, length)
76
+ * @param [Type] component_type
77
+ * @param [Numeric] length
78
+ * @return [self]
79
+ * A new instance of ArrayType.
80
+ */
81
+ static VALUE
82
+ array_type_initialize(VALUE self, VALUE rbComponentType, VALUE rbLength)
83
+ {
84
+ ArrayType* array;
85
+ int i;
86
+
87
+ Data_Get_Struct(self, ArrayType, array);
88
+
89
+ array->length = NUM2UINT(rbLength);
90
+ array->rbComponentType = rbComponentType;
91
+ Data_Get_Struct(rbComponentType, Type, array->componentType);
92
+
93
+ array->ffiTypes = xcalloc(array->length + 1, sizeof(*array->ffiTypes));
94
+ array->base.ffiType->elements = array->ffiTypes;
95
+ array->base.ffiType->size = array->componentType->ffiType->size * array->length;
96
+ array->base.ffiType->alignment = array->componentType->ffiType->alignment;
97
+
98
+ for (i = 0; i < array->length; ++i) {
99
+ array->ffiTypes[i] = array->componentType->ffiType;
100
+ }
101
+
102
+ return self;
103
+ }
104
+
105
+ /*
106
+ * call-seq: length
107
+ * @return [Numeric]
108
+ * Get array's length
109
+ */
110
+ static VALUE
111
+ array_type_length(VALUE self)
112
+ {
113
+ ArrayType* array;
114
+
115
+ Data_Get_Struct(self, ArrayType, array);
116
+
117
+ return UINT2NUM(array->length);
118
+ }
119
+
120
+ /*
121
+ * call-seq: element_type
122
+ * @return [Type]
123
+ * Get element type.
124
+ */
125
+ static VALUE
126
+ array_type_element_type(VALUE self)
127
+ {
128
+ ArrayType* array;
129
+
130
+ Data_Get_Struct(self, ArrayType, array);
131
+
132
+ return array->rbComponentType;
133
+ }
134
+
135
+ void
136
+ rbffi_ArrayType_Init(VALUE moduleFFI)
137
+ {
138
+ VALUE ffi_Type;
139
+
140
+ ffi_Type = rbffi_TypeClass;
141
+
142
+ /*
143
+ * Document-class: FFI::ArrayType < FFI::Type
144
+ *
145
+ * This is a typed array. The type is a {NativeType native type}.
146
+ */
147
+ rbffi_ArrayTypeClass = rb_define_class_under(moduleFFI, "ArrayType", ffi_Type);
148
+ /*
149
+ * Document-variable: FFI::ArrayType
150
+ */
151
+ rb_global_variable(&rbffi_ArrayTypeClass);
152
+ /*
153
+ * Document-constant: FFI::Type::Array
154
+ */
155
+ rb_define_const(ffi_Type, "Array", rbffi_ArrayTypeClass);
156
+
157
+ rb_define_alloc_func(rbffi_ArrayTypeClass, array_type_s_allocate);
158
+ rb_define_method(rbffi_ArrayTypeClass, "initialize", array_type_initialize, 2);
159
+ rb_define_method(rbffi_ArrayTypeClass, "length", array_type_length, 0);
160
+ rb_define_method(rbffi_ArrayTypeClass, "elem_type", array_type_element_type, 0);
161
+ }
162
+
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Copyright (c) 2009, Wayne Meissner
3
+ *
4
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of the Ruby FFI project nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifndef RBFFI_ARRAYTYPE_H
31
+ #define RBFFI_ARRAYTYPE_H
32
+
33
+ #include <ruby.h>
34
+ #include <ffi.h>
35
+ #include "Type.h"
36
+
37
+ #ifdef __cplusplus
38
+ extern "C" {
39
+ #endif
40
+
41
+
42
+ typedef struct ArrayType_ {
43
+ Type base;
44
+ int length;
45
+ ffi_type** ffiTypes;
46
+ Type* componentType;
47
+ VALUE rbComponentType;
48
+ } ArrayType;
49
+
50
+ extern void rbffi_ArrayType_Init(VALUE moduleFFI);
51
+ extern VALUE rbffi_ArrayTypeClass;
52
+
53
+
54
+ #ifdef __cplusplus
55
+ }
56
+ #endif
57
+
58
+ #endif /* RBFFI_ARRAYTYPE_H */
59
+
@@ -0,0 +1,365 @@
1
+ /*
2
+ * Copyright (c) 2008-2010 Wayne Meissner
3
+ * Copyright (C) 2009 Aman Gupta <aman@tmm1.net>
4
+ *
5
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ * * Neither the name of the Ruby FFI project nor the
16
+ * names of its contributors may be used to endorse or promote products
17
+ * derived from this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #ifndef _MSC_VER
32
+ # include <stdint.h>
33
+ # include <stdbool.h>
34
+ #else
35
+ # include "win32/stdbool.h"
36
+ # include "win32/stdint.h"
37
+ #endif
38
+ #include <limits.h>
39
+ #include <ruby.h>
40
+ #include "rbffi.h"
41
+ #include "rbffi_endian.h"
42
+ #include "AbstractMemory.h"
43
+
44
+ #define BUFFER_EMBED_MAXLEN (8)
45
+ typedef struct Buffer {
46
+ AbstractMemory memory;
47
+
48
+ union {
49
+ VALUE rbParent; /* link to parent buffer */
50
+ char* storage; /* start of malloc area */
51
+ long embed[BUFFER_EMBED_MAXLEN / sizeof(long)]; /* storage for tiny allocations */
52
+ } data;
53
+ } Buffer;
54
+
55
+ static VALUE buffer_allocate(VALUE klass);
56
+ static VALUE buffer_initialize(int argc, VALUE* argv, VALUE self);
57
+ static void buffer_release(Buffer* ptr);
58
+ static void buffer_mark(Buffer* ptr);
59
+ static VALUE buffer_free(VALUE self);
60
+
61
+ static VALUE BufferClass = Qnil;
62
+
63
+ static VALUE
64
+ buffer_allocate(VALUE klass)
65
+ {
66
+ Buffer* buffer;
67
+ VALUE obj;
68
+
69
+ obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer);
70
+ buffer->data.rbParent = Qnil;
71
+ buffer->memory.flags = MEM_RD | MEM_WR;
72
+
73
+ return obj;
74
+ }
75
+
76
+ static void
77
+ buffer_release(Buffer* ptr)
78
+ {
79
+ if ((ptr->memory.flags & MEM_EMBED) == 0 && ptr->data.storage != NULL) {
80
+ xfree(ptr->data.storage);
81
+ ptr->data.storage = NULL;
82
+ }
83
+
84
+ xfree(ptr);
85
+ }
86
+
87
+ /*
88
+ * call-seq: initialize(size, count=1, clear=false)
89
+ * @param [Integer, Symbol, #size] Type or size in bytes of a buffer cell
90
+ * @param [Fixnum] count number of cell in the Buffer
91
+ * @param [Boolean] clear if true, set the buffer to all-zero
92
+ * @return [self]
93
+ * @raise {NoMemoryError} if failed to allocate memory for Buffer
94
+ * A new instance of Buffer.
95
+ */
96
+ static VALUE
97
+ buffer_initialize(int argc, VALUE* argv, VALUE self)
98
+ {
99
+ VALUE rbSize = Qnil, rbCount = Qnil, rbClear = Qnil;
100
+ Buffer* p;
101
+ int nargs;
102
+
103
+ Data_Get_Struct(self, Buffer, p);
104
+
105
+ nargs = rb_scan_args(argc, argv, "12", &rbSize, &rbCount, &rbClear);
106
+ p->memory.typeSize = rbffi_type_size(rbSize);
107
+ p->memory.size = p->memory.typeSize * (nargs > 1 ? NUM2LONG(rbCount) : 1);
108
+
109
+ if (p->memory.size > BUFFER_EMBED_MAXLEN) {
110
+ p->data.storage = xmalloc(p->memory.size + 7);
111
+ if (p->data.storage == NULL) {
112
+ rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", p->memory.size);
113
+ return Qnil;
114
+ }
115
+
116
+ /* ensure the memory is aligned on at least a 8 byte boundary */
117
+ p->memory.address = (void *) (((uintptr_t) p->data.storage + 0x7) & (uintptr_t) ~0x7UL);
118
+
119
+ if (p->memory.size > 0 && (nargs < 3 || RTEST(rbClear))) {
120
+ memset(p->memory.address, 0, p->memory.size);
121
+ }
122
+
123
+ } else {
124
+ p->memory.flags |= MEM_EMBED;
125
+ p->memory.address = (void *) &p->data.embed[0];
126
+ }
127
+
128
+ if (rb_block_given_p()) {
129
+ return rb_ensure(rb_yield, self, buffer_free, self);
130
+ }
131
+
132
+ return self;
133
+ }
134
+
135
+ /*
136
+ * call-seq: initialize_copy(other)
137
+ * @return [self]
138
+ * DO NOT CALL THIS METHOD.
139
+ */
140
+ static VALUE
141
+ buffer_initialize_copy(VALUE self, VALUE other)
142
+ {
143
+ AbstractMemory* src;
144
+ Buffer* dst;
145
+
146
+ Data_Get_Struct(self, Buffer, dst);
147
+ src = rbffi_AbstractMemory_Cast(other, BufferClass);
148
+ if ((dst->memory.flags & MEM_EMBED) == 0 && dst->data.storage != NULL) {
149
+ xfree(dst->data.storage);
150
+ }
151
+ dst->data.storage = xmalloc(src->size + 7);
152
+ if (dst->data.storage == NULL) {
153
+ rb_raise(rb_eNoMemError, "failed to allocate memory size=%lu bytes", src->size);
154
+ return Qnil;
155
+ }
156
+
157
+ dst->memory.address = (void *) (((uintptr_t) dst->data.storage + 0x7) & (uintptr_t) ~0x7UL);
158
+ dst->memory.size = src->size;
159
+ dst->memory.typeSize = src->typeSize;
160
+
161
+ /* finally, copy the actual buffer contents */
162
+ memcpy(dst->memory.address, src->address, src->size);
163
+
164
+ return self;
165
+ }
166
+
167
+ static VALUE
168
+ buffer_alloc_inout(int argc, VALUE* argv, VALUE klass)
169
+ {
170
+ return buffer_initialize(argc, argv, buffer_allocate(klass));
171
+ }
172
+
173
+ static VALUE
174
+ slice(VALUE self, long offset, long len)
175
+ {
176
+ Buffer* ptr;
177
+ Buffer* result;
178
+ VALUE obj = Qnil;
179
+
180
+ Data_Get_Struct(self, Buffer, ptr);
181
+ checkBounds(&ptr->memory, offset, len);
182
+
183
+ obj = Data_Make_Struct(BufferClass, Buffer, buffer_mark, -1, result);
184
+ result->memory.address = ptr->memory.address + offset;
185
+ result->memory.size = len;
186
+ result->memory.flags = ptr->memory.flags;
187
+ result->memory.typeSize = ptr->memory.typeSize;
188
+ result->data.rbParent = self;
189
+
190
+ return obj;
191
+ }
192
+
193
+ /*
194
+ * call-seq: + offset
195
+ * @param [Numeric] offset
196
+ * @return [Buffer] a new instance of Buffer pointing from offset until end of previous buffer.
197
+ * Add a Buffer with an offset
198
+ */
199
+ static VALUE
200
+ buffer_plus(VALUE self, VALUE rbOffset)
201
+ {
202
+ Buffer* ptr;
203
+ long offset = NUM2LONG(rbOffset);
204
+
205
+ Data_Get_Struct(self, Buffer, ptr);
206
+
207
+ return slice(self, offset, ptr->memory.size - offset);
208
+ }
209
+
210
+ /*
211
+ * call-seq: slice(offset, length)
212
+ * @param [Numeric] offset
213
+ * @param [Numeric] length
214
+ * @return [Buffer] a new instance of Buffer
215
+ * Slice an existing Buffer.
216
+ */
217
+ static VALUE
218
+ buffer_slice(VALUE self, VALUE rbOffset, VALUE rbLength)
219
+ {
220
+ return slice(self, NUM2LONG(rbOffset), NUM2LONG(rbLength));
221
+ }
222
+
223
+ /*
224
+ * call-seq: inspect
225
+ * @return [String]
226
+ * Inspect a Buffer.
227
+ */
228
+ static VALUE
229
+ buffer_inspect(VALUE self)
230
+ {
231
+ char tmp[100];
232
+ Buffer* ptr;
233
+
234
+ Data_Get_Struct(self, Buffer, ptr);
235
+
236
+ snprintf(tmp, sizeof(tmp), "#<FFI:Buffer:%p address=%p size=%ld>", ptr, ptr->memory.address, ptr->memory.size);
237
+
238
+ return rb_str_new2(tmp);
239
+ }
240
+
241
+
242
+ #if BYTE_ORDER == LITTLE_ENDIAN
243
+ # define SWAPPED_ORDER BIG_ENDIAN
244
+ #else
245
+ # define SWAPPED_ORDER LITTLE_ENDIAN
246
+ #endif
247
+
248
+ /*
249
+ * Set or get endianness of Buffer.
250
+ * @overload order
251
+ * @return [:big, :little]
252
+ * Get endianness of Buffer.
253
+ * @overload order(order)
254
+ * @param [:big, :little, :network] order
255
+ * @return [self]
256
+ * Set endianness of Buffer (+:network+ is an alias for +:big+).
257
+ */
258
+ static VALUE
259
+ buffer_order(int argc, VALUE* argv, VALUE self)
260
+ {
261
+ Buffer* ptr;
262
+
263
+ Data_Get_Struct(self, Buffer, ptr);
264
+ if (argc == 0) {
265
+ int order = (ptr->memory.flags & MEM_SWAP) == 0 ? BYTE_ORDER : SWAPPED_ORDER;
266
+ return order == BIG_ENDIAN ? ID2SYM(rb_intern("big")) : ID2SYM(rb_intern("little"));
267
+ } else {
268
+ VALUE rbOrder = Qnil;
269
+ int order = BYTE_ORDER;
270
+
271
+ if (rb_scan_args(argc, argv, "1", &rbOrder) < 1) {
272
+ rb_raise(rb_eArgError, "need byte order");
273
+ }
274
+ if (SYMBOL_P(rbOrder)) {
275
+ ID id = SYM2ID(rbOrder);
276
+ if (id == rb_intern("little")) {
277
+ order = LITTLE_ENDIAN;
278
+
279
+ } else if (id == rb_intern("big") || id == rb_intern("network")) {
280
+ order = BIG_ENDIAN;
281
+ }
282
+ }
283
+ if (order != BYTE_ORDER) {
284
+ Buffer* p2;
285
+ VALUE retval = slice(self, 0, ptr->memory.size);
286
+
287
+ Data_Get_Struct(retval, Buffer, p2);
288
+ p2->memory.flags |= MEM_SWAP;
289
+ return retval;
290
+ }
291
+
292
+ return self;
293
+ }
294
+ }
295
+
296
+ /* Only used to free the buffer if the yield in the initializer throws an exception */
297
+ static VALUE
298
+ buffer_free(VALUE self)
299
+ {
300
+ Buffer* ptr;
301
+
302
+ Data_Get_Struct(self, Buffer, ptr);
303
+ if ((ptr->memory.flags & MEM_EMBED) == 0 && ptr->data.storage != NULL) {
304
+ xfree(ptr->data.storage);
305
+ ptr->data.storage = NULL;
306
+ }
307
+
308
+ return self;
309
+ }
310
+
311
+ static void
312
+ buffer_mark(Buffer* ptr)
313
+ {
314
+ rb_gc_mark(ptr->data.rbParent);
315
+ }
316
+
317
+ void
318
+ rbffi_Buffer_Init(VALUE moduleFFI)
319
+ {
320
+ VALUE ffi_AbstractMemory = rbffi_AbstractMemoryClass;
321
+
322
+ /*
323
+ * Document-class: FFI::Buffer < FFI::AbstractMemory
324
+ *
325
+ * A Buffer is a function argument type. It should be use with functions playing with C arrays.
326
+ */
327
+ BufferClass = rb_define_class_under(moduleFFI, "Buffer", ffi_AbstractMemory);
328
+
329
+ /*
330
+ * Document-variable: FFI::Buffer
331
+ */
332
+ rb_global_variable(&BufferClass);
333
+ rb_define_alloc_func(BufferClass, buffer_allocate);
334
+
335
+ /*
336
+ * Document-method: alloc_inout
337
+ * call-seq: alloc_inout(*args)
338
+ * Create a new Buffer for in and out arguments (alias : <i>new_inout</i>).
339
+ */
340
+ rb_define_singleton_method(BufferClass, "alloc_inout", buffer_alloc_inout, -1);
341
+ /*
342
+ * Document-method: alloc_out
343
+ * call-seq: alloc_out(*args)
344
+ * Create a new Buffer for out arguments (alias : <i>new_out</i>).
345
+ */
346
+ rb_define_singleton_method(BufferClass, "alloc_out", buffer_alloc_inout, -1);
347
+ /*
348
+ * Document-method: alloc_in
349
+ * call-seq: alloc_in(*args)
350
+ * Create a new Buffer for in arguments (alias : <i>new_in</i>).
351
+ */
352
+ rb_define_singleton_method(BufferClass, "alloc_in", buffer_alloc_inout, -1);
353
+ rb_define_alias(rb_singleton_class(BufferClass), "new_in", "alloc_in");
354
+ rb_define_alias(rb_singleton_class(BufferClass), "new_out", "alloc_out");
355
+ rb_define_alias(rb_singleton_class(BufferClass), "new_inout", "alloc_inout");
356
+
357
+ rb_define_method(BufferClass, "initialize", buffer_initialize, -1);
358
+ rb_define_method(BufferClass, "initialize_copy", buffer_initialize_copy, 1);
359
+ rb_define_method(BufferClass, "order", buffer_order, -1);
360
+ rb_define_method(BufferClass, "inspect", buffer_inspect, 0);
361
+ rb_define_alias(BufferClass, "length", "total");
362
+ rb_define_method(BufferClass, "+", buffer_plus, 1);
363
+ rb_define_method(BufferClass, "slice", buffer_slice, 2);
364
+ }
365
+