File Coverage

xs/meta.c
Criterion Covered Total %
statement 126 130 96.9
branch 34 42 80.9
condition n/a
subroutine n/a
pod n/a
total 160 172 93.0


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4             #include "ppport.h"
5             #include "ffi_platypus.h"
6              
7             /*
8             * - negative shift is undefined, so while it may work somewheree we make an explicit check for the
9             * 0 size.
10             * - We will eventually migrate fixed strings to be internally of record type, for now we have to
11             * check the platypus type when we have a type_code == FFI_PL_BASE_RECORD
12             */
13             #define unit_size(self) \
14             ((self->type_code & FFI_PL_BASE_MASK) == FFI_PL_BASE_RECORD \
15             ? (self->extra[0].record.size) \
16             : ((self->type_code & FFI_PL_SIZE_MASK) == FFI_PL_SIZE_0 \
17             ? 0 \
18             : 1 << ((self->type_code & FFI_PL_SIZE_MASK)-1) \
19             ) \
20             )
21              
22             size_t
23 719           ffi_pl_sizeof_new(ffi_pl_type *self)
24             {
25 719           switch( self->type_code & FFI_PL_SHAPE_MASK )
26             {
27             case FFI_PL_SHAPE_SCALAR:
28             case FFI_PL_SHAPE_CUSTOM_PERL:
29 459 50         return unit_size(self);
    100          
30             case FFI_PL_SHAPE_POINTER:
31 42           return sizeof(void*);
32             case FFI_PL_SHAPE_ARRAY:
33 218 50         return unit_size(self) * self->extra[0].array.element_count;
    50          
34             default:
35 0           return 0;
36             }
37             }
38              
39             size_t
40 817           ffi_pl_sizeof(ffi_pl_type *self)
41             {
42 817 100         if(self->type_code == FFI_PL_TYPE_RECORD
43 732 100         || self->type_code == FFI_PL_TYPE_RECORD_VALUE
44 725 100         || self->type_code == (FFI_PL_TYPE_RECORD | FFI_PL_SHAPE_CUSTOM_PERL)
45 721 100         || self->type_code == (FFI_PL_TYPE_RECORD_VALUE | FFI_PL_SHAPE_CUSTOM_PERL))
46             {
47 98           return self->extra[0].record.size;
48             }
49             else
50             {
51 719           return ffi_pl_sizeof_new(self);
52             }
53             }
54              
55             HV *
56 511           ffi_pl_get_type_meta(ffi_pl_type *self)
57             {
58             HV *meta;
59             const char *string;
60              
61 511           meta = newHV();
62              
63 511           hv_store(meta, "size", 4, newSViv(ffi_pl_sizeof(self)), 0);
64 511           hv_store(meta, "type_code", 9, newSViv(self->type_code), 0);
65              
66 511           switch(self->type_code & FFI_PL_SHAPE_MASK)
67             {
68             case FFI_PL_SHAPE_SCALAR:
69             {
70 310           switch(self->type_code)
71             {
72              
73             case FFI_PL_TYPE_STRING:
74 44           hv_store(meta, "element_size", 12, newSViv(sizeof(void*)), 0);
75 44           hv_store(meta, "type", 4, newSVpv("string",0),0);
76 44           switch(self->sub_type)
77             {
78             case FFI_PL_TYPE_STRING_RO:
79 22           hv_store(meta, "access", 6, newSVpv("ro",0), 0);
80 22           break;
81             case FFI_PL_TYPE_STRING_RW:
82 22           hv_store(meta, "access", 6, newSVpv("rw",0), 0);
83 22           break;
84             }
85 44           break;
86              
87             case FFI_PL_TYPE_CLOSURE:
88             {
89             AV *signature;
90             AV *argument_types;
91             HV *subtype;
92             int i;
93             int number_of_arguments;
94              
95 5           number_of_arguments = self->extra[0].closure.ffi_cif.nargs;
96              
97 5           signature = newAV();
98 5           argument_types = newAV();
99              
100 20 100         for(i=0; i < number_of_arguments; i++)
101             {
102 15           subtype = ffi_pl_get_type_meta(self->extra[0].closure.argument_types[i]);
103 15           av_store(argument_types, i, newRV_noinc((SV*)subtype));
104             }
105 5           av_store(signature, 0, newRV_noinc((SV*)argument_types));
106              
107 5           subtype = ffi_pl_get_type_meta(self->extra[0].closure.return_type);
108 5           av_store(signature, 1, newRV_noinc((SV*)subtype));
109              
110 5           hv_store(meta, "signature", 9, newRV_noinc((SV*)signature), 0);
111              
112 5           hv_store(meta, "element_size", 12, newSViv(sizeof(void*)), 0);
113 5           hv_store(meta, "type", 4, newSVpv("closure",0),0);
114             }
115 5           break;
116              
117             case FFI_PL_TYPE_RECORD:
118 72           hv_store(meta, "type", 4, newSVpv("record",0),0);
119 72           hv_store(meta, "ref", 3, newSViv(self->extra[0].record.class != NULL ? 1 : 0),0);
120 72 100         if(self->extra[0].record.class != NULL)
121 8           hv_store(meta, "class", 5, newSVpv(self->extra[0].record.class,0), 0);
122 72           break;
123              
124             case FFI_PL_TYPE_RECORD_VALUE:
125 6           hv_store(meta, "type", 4, newSVpv("record_value",0),0);
126 6           hv_store(meta, "ref", 3, newSViv(self->extra[0].record.class != NULL ? 1 : 0),0);
127 6           hv_store(meta, "class", 5, newSVpv(self->extra[0].record.class,0), 0);
128 6           break;
129              
130             default:
131 183 50         hv_store(meta, "element_size", 12, newSViv(unit_size(self)), 0);
    100          
132 183           hv_store(meta, "type", 4, newSVpv("scalar",0),0);
133 183           break;
134             }
135             }
136 310           break;
137              
138             case FFI_PL_SHAPE_POINTER:
139 30 50         hv_store(meta, "element_size", 12, newSViv(unit_size(self)), 0);
    50          
140 30           hv_store(meta, "type", 4, newSVpv("pointer",0),0);
141 30           break;
142              
143             case FFI_PL_SHAPE_ARRAY:
144 90 50         hv_store(meta, "element_size", 12, newSViv(unit_size(self)), 0);
    50          
145 90           hv_store(meta, "type", 4, newSVpv("array",0),0);
146 90           hv_store(meta, "element_count", 13, newSViv(self->extra[0].array.element_count), 0);
147 90           break;
148              
149             case FFI_PL_SHAPE_CUSTOM_PERL:
150 81           hv_store(meta, "type", 4, newSVpv("custom_perl",0),0);
151              
152 81 100         if(self->extra[0].custom_perl.perl_to_native != NULL)
153 48           hv_store(meta, "custom_perl_to_native", 18, newRV_inc((SV*)self->extra[0].custom_perl.perl_to_native), 0);
154              
155 81 100         if(self->extra[0].custom_perl.perl_to_native_post != NULL)
156 37           hv_store(meta, "custom_perl_to_native_post", 23, newRV_inc((SV*)self->extra[0].custom_perl.perl_to_native_post), 0);
157              
158 81 100         if(self->extra[0].custom_perl.native_to_perl != NULL)
159 59           hv_store(meta, "custom_native_to_perl", 18, newRV_inc((SV*)self->extra[0].custom_perl.native_to_perl), 0);
160              
161 81 100         if(self->type_code == (FFI_PL_TYPE_RECORD | FFI_PL_SHAPE_CUSTOM_PERL))
162             {
163 2           hv_store(meta, "sub_type", 8, newSVpv("record",0),0);
164 2           hv_store(meta, "ref", 3, newSViv(self->extra[0].record.class != NULL ? 1 : 0),0);
165 2 100         if(self->extra[0].record.class != NULL)
166 1           hv_store(meta, "class", 5, newSVpv(self->extra[0].record.class,0), 0);
167             }
168 81           break;
169             }
170              
171 511           switch(self->type_code & (FFI_PL_SIZE_MASK | FFI_PL_BASE_MASK))
172             {
173             case FFI_PL_TYPE_VOID:
174 3           hv_store(meta, "element_type", 12, newSVpv("void",0),0);
175 3           break;
176             case FFI_PL_TYPE_FLOAT:
177             case FFI_PL_TYPE_DOUBLE:
178             #ifdef FFI_PL_PROBE_LONGDOUBLE
179             case FFI_PL_TYPE_LONG_DOUBLE:
180             #endif
181             #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
182             case FFI_PL_TYPE_COMPLEX_FLOAT:
183             case FFI_PL_TYPE_COMPLEX_DOUBLE:
184             #endif
185 57           hv_store(meta, "element_type", 12, newSVpv("float",0),0);
186 57           break;
187             case FFI_PL_TYPE_UINT8:
188             case FFI_PL_TYPE_UINT16:
189             case FFI_PL_TYPE_UINT32:
190             case FFI_PL_TYPE_UINT64:
191 96           hv_store(meta, "element_type", 12, newSVpv("int",0),0);
192 96           hv_store(meta, "sign", 4, newSViv(0),0);
193 96           break;
194             case FFI_PL_TYPE_SINT8:
195             case FFI_PL_TYPE_SINT16:
196             case FFI_PL_TYPE_SINT32:
197             case FFI_PL_TYPE_SINT64:
198 191           hv_store(meta, "element_type", 12, newSVpv("int",0),0);
199 191           hv_store(meta, "sign", 4, newSViv(1),0);
200 191           break;
201             case FFI_PL_TYPE_OPAQUE:
202 30           hv_store(meta, "element_type", 12, newSVpv("opaque",0),0);
203 30           break;
204             }
205 511           switch(self->type_code & (FFI_PL_SIZE_MASK | FFI_PL_BASE_MASK))
206             {
207             case FFI_PL_TYPE_VOID:
208 3           string = "void";
209 3           break;
210             case FFI_PL_TYPE_FLOAT:
211 19           string = "float";
212 19           break;
213             case FFI_PL_TYPE_DOUBLE:
214 19           string = "double";
215 19           break;
216             #ifdef FFI_PL_PROBE_LONGDOUBLE
217             case FFI_PL_TYPE_LONG_DOUBLE:
218 7           string = "longdouble";
219 7           break;
220             #endif
221             case FFI_PL_TYPE_UINT8:
222 27           string = "uint8";
223 27           break;
224             case FFI_PL_TYPE_SINT8:
225 92           string = "sint8";
226 92           break;
227             case FFI_PL_TYPE_UINT16:
228 21           string = "uint16";
229 21           break;
230             case FFI_PL_TYPE_SINT16:
231 21           string = "sint16";
232 21           break;
233             case FFI_PL_TYPE_UINT32:
234 25           string = "uint32";
235 25           break;
236             case FFI_PL_TYPE_SINT32:
237 57           string = "sint32";
238 57           break;
239             case FFI_PL_TYPE_UINT64:
240 23           string = "uint64";
241 23           break;
242             case FFI_PL_TYPE_SINT64:
243 21           string = "sint64";
244 21           break;
245             case FFI_PL_TYPE_OPAQUE:
246             case FFI_PL_TYPE_STRING:
247             case FFI_PL_TYPE_CLOSURE:
248             case FFI_PL_TYPE_RECORD:
249 157           string = "pointer";
250 157           break;
251             case FFI_PL_TYPE_RECORD_VALUE:
252 7           string = "struct";
253 7           break;
254             #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
255             case FFI_PL_TYPE_COMPLEX_FLOAT:
256 6           string = "complex_float";
257 6           break;
258             case FFI_PL_TYPE_COMPLEX_DOUBLE:
259 6           string = "complex_double";
260 6           break;
261             #endif
262             default:
263 0           warn("bad type: %04x\n", self->type_code & (FFI_PL_SIZE_MASK | FFI_PL_BASE_MASK));
264 0           string = NULL;
265 0           break;
266             }
267 511           hv_store(meta, "ffi_type", 8, newSVpv(string,0),0);
268              
269 511           return meta;
270             }
271              
272 2437           ffi_pl_type *ffi_pl_type_new(size_t size)
273             {
274             char *buffer;
275             ffi_pl_type *self;
276              
277 2437           Newx(buffer, sizeof(ffi_pl_type) + size, char);
278 2437           self = (ffi_pl_type*) buffer;
279 2437           self->type_code = 0;
280 2437           self->sub_type = 0;
281              
282 2437           return self;
283             }