File Coverage

xs/TypeParser.xs
Criterion Covered Total %
statement 143 155 92.2
branch 38 54 70.3
condition n/a
subroutine n/a
pod n/a
total 181 209 86.6


line stmt bran cond sub pod time code
1             MODULE = FFI::Platypus PACKAGE = FFI::Platypus::TypeParser
2              
3             BOOT:
4             {
5 56           HV *bt = get_hv("FFI::Platypus::TypeParser::basic_type", GV_ADD);
6 56           hv_stores(bt, "void", newSViv(FFI_PL_TYPE_VOID));
7 56           hv_stores(bt, "sint8", newSViv(FFI_PL_TYPE_SINT8));
8 56           hv_stores(bt, "sint16", newSViv(FFI_PL_TYPE_SINT16));
9 56           hv_stores(bt, "sint32", newSViv(FFI_PL_TYPE_SINT32));
10 56           hv_stores(bt, "sint64", newSViv(FFI_PL_TYPE_SINT64));
11 56           hv_stores(bt, "uint8", newSViv(FFI_PL_TYPE_UINT8));
12 56           hv_stores(bt, "uint16", newSViv(FFI_PL_TYPE_UINT16));
13 56           hv_stores(bt, "uint32", newSViv(FFI_PL_TYPE_UINT32));
14 56           hv_stores(bt, "uint64", newSViv(FFI_PL_TYPE_UINT64));
15              
16 56           hv_stores(bt, "float", newSViv(FFI_PL_TYPE_FLOAT));
17 56           hv_stores(bt, "double", newSViv(FFI_PL_TYPE_DOUBLE));
18 56           hv_stores(bt, "string", newSViv(FFI_PL_TYPE_STRING));
19 56           hv_stores(bt, "opaque", newSViv(FFI_PL_TYPE_OPAQUE));
20             #ifdef FFI_PL_PROBE_LONGDOUBLE
21 56           hv_stores(bt, "longdouble", newSViv(FFI_PL_TYPE_LONG_DOUBLE));
22             #endif
23             #ifdef FFI_PL_PROBE_COMPLEX
24 56           hv_stores(bt, "complex_float", newSViv(FFI_PL_TYPE_COMPLEX_FLOAT));
25 56           hv_stores(bt, "complex_double", newSViv(FFI_PL_TYPE_COMPLEX_DOUBLE));
26             #endif
27             }
28              
29             ffi_pl_type *
30             create_type_basic(self, type_code)
31             SV *self
32             int type_code
33             PREINIT:
34             ffi_pl_type *type;
35             CODE:
36             (void)self;
37 834           type = ffi_pl_type_new(0);
38 834           type->type_code |= type_code;
39 834           RETVAL = type;
40             OUTPUT:
41             RETVAL
42              
43             ffi_pl_type *
44             create_type_record(self, is_by_value, size, record_class=NULL, meta=NULL)
45             SV *self
46             int is_by_value
47             size_t size
48             ffi_pl_string record_class
49             void *meta
50             PREINIT:
51             ffi_pl_type *type;
52             CODE:
53             (void)self;
54 72           type = ffi_pl_type_new(sizeof(ffi_pl_type_extra_record));
55 72 100         type->type_code |= is_by_value ? FFI_PL_TYPE_RECORD_VALUE : FFI_PL_TYPE_RECORD;
56 72           type->extra[0].record.size = size;
57 72 100         if(record_class != NULL)
58             {
59 28           size = strlen(record_class)+1;
60 28           type->extra[0].record.class = malloc(size);
61 28           memcpy(type->extra[0].record.class, record_class, size);
62             }
63             else
64             {
65 44           type->extra[0].record.class = NULL;
66             }
67 72           type->extra[0].record.meta = meta;
68 72           RETVAL = type;
69             OUTPUT:
70             RETVAL
71              
72             ffi_pl_type*
73             create_type_object(self, type_code, class)
74             SV *self
75             int type_code
76             ffi_pl_string class
77             PREINIT:
78             ffi_pl_type *type;
79             size_t size;
80             CODE:
81             (void)self;
82 24           type = ffi_pl_type_new(sizeof(ffi_pl_type_extra_object));
83 24           size = strlen(class)+1;
84 24           type->extra[0].object.class = malloc(size);
85 24           memcpy(type->extra[0].object.class, class, size);
86 24           type->type_code |= type_code;
87 24           type->type_code |= FFI_PL_SHAPE_OBJECT;
88 24           RETVAL = type;
89             OUTPUT:
90             RETVAL
91              
92             ffi_pl_type *
93             create_type_string(self, rw)
94             SV *self
95             int rw
96             PREINIT:
97             ffi_pl_type *type;
98             CODE:
99             (void)self;
100 72           type = ffi_pl_type_new(0);
101 72           type->type_code = FFI_PL_TYPE_STRING;
102 72 100         if(rw)
103 11           type->sub_type = FFI_PL_TYPE_STRING_RW;
104             else
105 61           type->sub_type = FFI_PL_TYPE_STRING_RO;
106 72           RETVAL = type;
107             OUTPUT:
108             RETVAL
109              
110             ffi_pl_type *
111             create_type_array(self, type_code, size)
112             SV *self
113             int type_code
114             size_t size
115             PREINIT:
116             ffi_pl_type *type;
117             CODE:
118             (void)self;
119 301           type = ffi_pl_type_new(sizeof(ffi_pl_type_extra_array));
120 301           type->type_code |= FFI_PL_SHAPE_ARRAY | type_code;
121 301           type->extra[0].array.element_count = size;
122 301           RETVAL = type;
123             OUTPUT:
124             RETVAL
125              
126             ffi_pl_type*
127             create_type_pointer(self, type_code)
128             SV *self
129             int type_code
130             PREINIT:
131             ffi_pl_type *type;
132             CODE:
133             (void)self;
134 833           type = ffi_pl_type_new(0);
135 833           type->type_code |= FFI_PL_SHAPE_POINTER | type_code;
136 833           RETVAL = type;
137             OUTPUT:
138             RETVAL
139              
140             ffi_pl_type *
141             _create_type_custom(self, basis, perl_to_native, native_to_perl, perl_to_native_post, argument_count)
142             SV *self
143             ffi_pl_type* basis
144             SV *perl_to_native
145             SV *native_to_perl
146             SV *perl_to_native_post
147             int argument_count
148             PREINIT:
149             ffi_pl_type *type;
150             int type_code;
151             ffi_pl_type_extra_custom_perl *custom;
152             ffi_pl_type_extra_record *record;
153             size_t size;
154             CODE:
155             (void)self;
156 209           type = ffi_pl_type_new(sizeof(ffi_pl_type_extra_custom_perl));
157 209           type->type_code = FFI_PL_SHAPE_CUSTOM_PERL | basis->type_code;
158              
159 209           type->extra[0].record.class = NULL;
160 209 100         if( (basis->type_code & FFI_PL_BASE_MASK) == (FFI_PL_TYPE_RECORD & FFI_PL_BASE_MASK)
161 206 100         || (basis->type_code & FFI_PL_BASE_MASK) == (FFI_PL_TYPE_RECORD_VALUE & FFI_PL_BASE_MASK))
162             {
163 5           type->extra[0].record.size = basis->extra[0].record.size;
164 5           type->extra[0].record.meta = basis->extra[0].record.meta;
165 5 100         if(basis->extra[0].record.class)
166             {
167 4           size = strlen(basis->extra[0].record.class) + 1;
168 4           type->extra[0].record.class = malloc(size);
169 4           memcpy(type->extra[0].record.class, basis->extra[0].record.class, size);
170             }
171             }
172              
173 209           custom = &type->extra[0].custom_perl;
174 209 100         custom->perl_to_native = SvOK(perl_to_native) ? SvREFCNT_inc_simple_NN(perl_to_native) : NULL;
    50          
    50          
175 209 100         custom->perl_to_native_post = SvOK(perl_to_native_post) ? SvREFCNT_inc_simple_NN(perl_to_native_post) : NULL;
    50          
    50          
176 209 100         custom->native_to_perl = SvOK(native_to_perl) ? SvREFCNT_inc_simple_NN(native_to_perl) : NULL;
    50          
    50          
177 209           custom->argument_count = argument_count-1;
178              
179 209           RETVAL = type;
180             OUTPUT:
181             RETVAL
182              
183              
184             ffi_pl_type *
185             create_type_closure(self, abi, return_type, ...)
186             SV *self
187             int abi
188             ffi_pl_type *return_type
189             PREINIT:
190             ffi_pl_type *type;
191             int i;
192             SV *arg;
193             ffi_type *ffi_return_type;
194             ffi_type **ffi_argument_types;
195             ffi_status ffi_status;
196             CODE:
197             (void)self;
198 95           switch(return_type->type_code)
199             {
200             case FFI_PL_TYPE_VOID:
201 47           ffi_return_type = &ffi_type_void;
202 47           break;
203             case FFI_PL_TYPE_SINT8:
204 3           ffi_return_type = &ffi_type_sint8;
205 3           break;
206             case FFI_PL_TYPE_SINT16:
207 3           ffi_return_type = &ffi_type_sint16;
208 3           break;
209             case FFI_PL_TYPE_SINT32:
210 13           ffi_return_type = &ffi_type_sint32;
211 13           break;
212             case FFI_PL_TYPE_SINT64:
213 3           ffi_return_type = &ffi_type_sint64;
214 3           break;
215             case FFI_PL_TYPE_UINT8:
216 3           ffi_return_type = &ffi_type_uint8;
217 3           break;
218             case FFI_PL_TYPE_UINT16:
219 3           ffi_return_type = &ffi_type_uint16;
220 3           break;
221             case FFI_PL_TYPE_UINT32:
222 3           ffi_return_type = &ffi_type_uint32;
223 3           break;
224             case FFI_PL_TYPE_UINT64:
225 3           ffi_return_type = &ffi_type_uint64;
226 3           break;
227             case FFI_PL_TYPE_FLOAT:
228 3           ffi_return_type = &ffi_type_float;
229 3           break;
230             case FFI_PL_TYPE_DOUBLE:
231 3           ffi_return_type = &ffi_type_double;
232 3           break;
233             case FFI_PL_TYPE_OPAQUE:
234 4           ffi_return_type = &ffi_type_pointer;
235 4           break;
236             case FFI_PL_TYPE_RECORD_VALUE:
237 2 50         if(return_type->extra[0].record.meta == NULL)
238 0           croak("Only native types are supported as closure return types (%d)", return_type->type_code);
239 2 100         if(!return_type->extra[0].record.meta->can_return_from_closure)
240 1           croak("Record return type contains types that cannot be returned from a closure");
241 1           ffi_return_type = &return_type->extra[0].record.meta->ffi_type;
242 1           break;
243             default:
244 2           croak("Only native types are supported as closure return types (%d)", return_type->type_code);
245             break;
246             }
247              
248 92 50         Newx(ffi_argument_types, items-3, ffi_type*);
249 92           type = ffi_pl_type_new(sizeof(ffi_pl_type_extra_closure) + sizeof(ffi_pl_type)*(items-3));
250 92           type->type_code = FFI_PL_TYPE_CLOSURE;
251              
252 92           type->extra[0].closure.return_type = return_type;
253 92           type->extra[0].closure.flags = 0;
254              
255 161 100         for(i=0; i<(items-3); i++)
256             {
257 72           arg = ST(3+i);
258 72 50         type->extra[0].closure.argument_types[i] = INT2PTR(ffi_pl_type*, SvIV((SV*)SvRV(arg)));
259 72           switch(type->extra[0].closure.argument_types[i]->type_code)
260             {
261             case FFI_PL_TYPE_VOID:
262 0           ffi_argument_types[i] = &ffi_type_void;
263 0           break;
264             case FFI_PL_TYPE_SINT8:
265 4           ffi_argument_types[i] = &ffi_type_sint8;
266 4           break;
267             case FFI_PL_TYPE_SINT16:
268 3           ffi_argument_types[i] = &ffi_type_sint16;
269 3           break;
270             case FFI_PL_TYPE_SINT32:
271 17           ffi_argument_types[i] = &ffi_type_sint32;
272 17           break;
273             case FFI_PL_TYPE_SINT64:
274 4           ffi_argument_types[i] = &ffi_type_sint64;
275 4           break;
276             case FFI_PL_TYPE_UINT8:
277 3           ffi_argument_types[i] = &ffi_type_uint8;
278 3           break;
279             case FFI_PL_TYPE_UINT16:
280 3           ffi_argument_types[i] = &ffi_type_uint16;
281 3           break;
282             case FFI_PL_TYPE_UINT32:
283 3           ffi_argument_types[i] = &ffi_type_uint32;
284 3           break;
285             case FFI_PL_TYPE_UINT64:
286 4           ffi_argument_types[i] = &ffi_type_uint64;
287 4           break;
288             case FFI_PL_TYPE_FLOAT:
289 3           ffi_argument_types[i] = &ffi_type_float;
290 3           break;
291             case FFI_PL_TYPE_DOUBLE:
292 4           ffi_argument_types[i] = &ffi_type_double;
293 4           break;
294             case FFI_PL_TYPE_OPAQUE:
295             case FFI_PL_TYPE_STRING:
296             case FFI_PL_TYPE_RECORD:
297 20           ffi_argument_types[i] = &ffi_type_pointer;
298 20           break;
299             case FFI_PL_TYPE_RECORD_VALUE:
300 1 50         if(type->extra[0].closure.argument_types[i]->extra[0].record.meta == NULL)
301             {
302 0           Safefree(ffi_argument_types);
303 0           croak("Only native types and strings are supported as closure argument types (%d)", type->extra[0].closure.argument_types[i]->type_code);
304             }
305 1           ffi_argument_types[i] = &type->extra[0].closure.argument_types[i]->extra[0].record.meta->ffi_type;
306 1           break;
307             default:
308 3           Safefree(ffi_argument_types);
309 3           croak("Only native types and strings are supported as closure argument types (%d)", type->extra[0].closure.argument_types[i]->type_code);
310             break;
311             }
312             }
313              
314 89 50         ffi_status = ffi_prep_cif(
315             &type->extra[0].closure.ffi_cif,
316             abi == -1 ? FFI_DEFAULT_ABI : abi,
317 89           items-3,
318             ffi_return_type,
319             ffi_argument_types
320             );
321              
322 89 50         if(ffi_status != FFI_OK)
323             {
324 0           Safefree(type);
325 0           Safefree(ffi_argument_types);
326 0 0         if(ffi_status == FFI_BAD_TYPEDEF)
327 0           croak("bad typedef");
328 0 0         else if(ffi_status == FFI_BAD_ABI)
329 0           croak("bad abi");
330             else
331 0           croak("unknown error with ffi_prep_cif");
332             }
333              
334 89 100         if( items-3 == 0 )
335             {
336 33           type->extra[0].closure.flags |= G_NOARGS;
337             }
338              
339 89 100         if(type->extra[0].closure.return_type->type_code == FFI_PL_TYPE_VOID)
340             {
341 47           type->extra[0].closure.flags |= G_DISCARD | G_VOID;
342             }
343             else
344             {
345 42           type->extra[0].closure.flags |= G_SCALAR;
346             }
347              
348 89           RETVAL = type;
349              
350             OUTPUT:
351             RETVAL
352              
353