File Coverage

xs/closure.c
Criterion Covered Total %
statement 156 165 94.5
branch 92 180 51.1
condition n/a
subroutine n/a
pod n/a
total 248 345 71.8


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             #include "ffi_platypus_guts.h"
7             #include "perl_math_int64.h"
8              
9             void
10 89           ffi_pl_closure_add_data(SV *closure, ffi_pl_closure *closure_data)
11             {
12 89           dSP;
13 89           ENTER;
14 89           SAVETMPS;
15 89 50         PUSHMARK(SP);
16 89 50         XPUSHs(closure);
17 89 50         XPUSHs(sv_2mortal(newSViv(PTR2IV(closure_data))));
18 89 50         XPUSHs(sv_2mortal(newSViv(PTR2IV(closure_data->type))));
19 89           PUTBACK;
20 89           call_pv("FFI::Platypus::Closure::add_data", G_DISCARD);
21 89 50         FREETMPS;
22 89           LEAVE;
23 89           }
24              
25             ffi_pl_closure *
26 90           ffi_pl_closure_get_data(SV *closure, ffi_pl_type *type)
27             {
28 90           dSP;
29             int count;
30             ffi_pl_closure *ret;
31              
32 90           ENTER;
33 90           SAVETMPS;
34 90 50         PUSHMARK(SP);
35 90 50         XPUSHs(closure);
36 90 50         XPUSHs(sv_2mortal(newSViv(PTR2IV(type))));
37 90           PUTBACK;
38 90           count = call_pv("FFI::Platypus::Closure::get_data", G_SCALAR);
39 90           SPAGAIN;
40              
41 90 50         if (count != 1)
42 0           ret = NULL;
43             else
44 90 50         ret = INT2PTR(void*, POPi);
45              
46 90           PUTBACK;
47 90 50         FREETMPS;
48 90           LEAVE;
49              
50 90           return ret;
51             }
52              
53             void
54 103           ffi_pl_closure_call(ffi_cif *ffi_cif, void *result, void **arguments, void *user)
55             {
56 103           dSP;
57              
58 103           ffi_pl_closure *closure = (ffi_pl_closure*) user;
59 103           ffi_pl_type_extra_closure *extra = &closure->type->extra[0].closure;
60 103           int flags = extra->flags;
61             int i;
62             int count;
63             SV *sv,*ref;
64              
65 103 100         if(!(flags & G_NOARGS))
66             {
67 98           ENTER;
68 98           SAVETMPS;
69             }
70              
71 103 50         PUSHMARK(SP);
72              
73 103 100         if(!(flags & G_NOARGS))
74             {
75 205 100         for(i=0; i< ffi_cif->nargs; i++)
76             {
77 107           switch(extra->argument_types[i]->type_code)
78             {
79             case FFI_PL_TYPE_VOID:
80 0           break;
81             case FFI_PL_TYPE_SINT8:
82 6           sv = sv_newmortal();
83 6           sv_setiv(sv, *((int8_t*)arguments[i]));
84 6 50         XPUSHs(sv);
85 6           break;
86             case FFI_PL_TYPE_SINT16:
87 6           sv = sv_newmortal();
88 6           sv_setiv(sv, *((int16_t*)arguments[i]));
89 6 50         XPUSHs(sv);
90 6           break;
91             case FFI_PL_TYPE_SINT32:
92 10           sv = sv_newmortal();
93 10           sv_setiv(sv, *((int32_t*)arguments[i]));
94 10 50         XPUSHs(sv);
95 10           break;
96             case FFI_PL_TYPE_SINT64:
97 7           sv = sv_newmortal();
98 7           sv_seti64(sv, *((int64_t*)arguments[i]));
99 7 50         XPUSHs(sv);
100 7           break;
101             case FFI_PL_TYPE_UINT8:
102 6           sv = sv_newmortal();
103 6           sv_setuv(sv, *((uint8_t*)arguments[i]));
104 6 50         XPUSHs(sv);
105 6           break;
106             case FFI_PL_TYPE_UINT16:
107 6           sv = sv_newmortal();
108 6           sv_setuv(sv, *((uint16_t*)arguments[i]));
109 6 50         XPUSHs(sv);
110 6           break;
111             case FFI_PL_TYPE_UINT32:
112 6           sv = sv_newmortal();
113 6           sv_setuv(sv, *((uint32_t*)arguments[i]));
114 6 50         XPUSHs(sv);
115 6           break;
116             case FFI_PL_TYPE_UINT64:
117 7           sv = sv_newmortal();
118 7           sv_setu64(sv, *((uint64_t*)arguments[i]));
119 7 50         XPUSHs(sv);
120 7           break;
121             case FFI_PL_TYPE_FLOAT:
122 6           sv = sv_newmortal();
123 6           sv_setnv(sv, *((float*)arguments[i]));
124 6 50         XPUSHs(sv);
125 6           break;
126             case FFI_PL_TYPE_DOUBLE:
127 7           sv = sv_newmortal();
128 7           sv_setnv(sv, *((double*)arguments[i]));
129 7 50         XPUSHs(sv);
130 7           break;
131             case FFI_PL_TYPE_OPAQUE:
132 7           sv = sv_newmortal();
133 7 100         if( *((void**)arguments[i]) != NULL)
134 3           sv_setiv(sv, PTR2IV( *((void**)arguments[i]) ));
135 7 50         XPUSHs(sv);
136 7           break;
137             case FFI_PL_TYPE_STRING:
138 27           sv = sv_newmortal();
139 27 100         if( *((char**)arguments[i]) != NULL)
140             {
141 24           sv_setpv(sv, *((char**)arguments[i]));
142             }
143 27 50         XPUSHs(sv);
144 27           break;
145             case FFI_PL_TYPE_RECORD:
146 5           sv = sv_newmortal();
147 5 100         if( *((char**)arguments[i]) != NULL)
148             {
149 4           sv_setpvn(sv, *((char**)arguments[i]), extra->argument_types[i]->extra[0].record.size);
150 4 100         if(extra->argument_types[i]->extra[0].record.class != NULL)
151             {
152 1           ref = newRV_inc(sv);
153 1           sv_bless(ref, gv_stashpv(extra->argument_types[i]->extra[0].record.class, GV_ADD));
154 1           SvREADONLY_on(sv);
155 1           sv = ref;
156             }
157             else
158             {
159 3           SvREADONLY_on(sv);
160             }
161             }
162 5 50         XPUSHs(sv);
163 5           break;
164             case FFI_PL_TYPE_RECORD_VALUE:
165 1           sv = sv_newmortal();
166 1           sv_setpvn(sv, (char*)arguments[i], extra->argument_types[i]->extra[0].record.size);
167 1           ref = newRV_inc(sv);
168 1           sv_bless(ref, gv_stashpv(extra->argument_types[i]->extra[0].record.class, GV_ADD));
169 1           SvREADONLY_on(sv);
170 1 50         XPUSHs(ref);
171 1           break;
172             default:
173 0           warn("bad type");
174 0           break;
175             }
176             }
177 98           PUTBACK;
178             }
179              
180 103           count = call_sv(closure->coderef, flags | G_EVAL);
181              
182 103 50         if(SvTRUE(ERRSV))
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
183             {
184             #ifdef warn_sv
185 1 50         warn_sv(ERRSV);
186             #else
187             warn("%s", SvPV_nolen(ERRSV));
188             #endif
189             }
190              
191 103 100         if(!(flags & G_DISCARD))
192             {
193 73           SPAGAIN;
194              
195 73 50         if(count != 1)
196 0           sv = &PL_sv_undef;
197             else
198 73           sv = POPs;
199              
200 73           switch(extra->return_type->type_code)
201             {
202             case FFI_PL_TYPE_VOID:
203 0           break;
204             case FFI_PL_TYPE_UINT8:
205             #if defined FFI_PL_PROBE_BIGENDIAN
206             ((uint8_t*)result)[3] = SvUV(sv);
207             #elif defined FFI_PL_PROBE_BIGENDIAN64
208             ((uint8_t*)result)[7] = SvUV(sv);
209             #else
210 6 50         *((uint8_t*)result) = SvUV(sv);
211             #endif
212 6           break;
213             case FFI_PL_TYPE_SINT8:
214             #if defined FFI_PL_PROBE_BIGENDIAN
215             ((int8_t*)result)[3] = SvIV(sv);
216             #elif defined FFI_PL_PROBE_BIGENDIAN64
217             ((int8_t*)result)[7] = SvIV(sv);
218             #else
219 6 100         *((int8_t*)result) = SvIV(sv);
220             #endif
221 6           break;
222             case FFI_PL_TYPE_UINT16:
223             #if defined FFI_PL_PROBE_BIGENDIAN
224             ((uint16_t*)result)[1] = SvUV(sv);
225             #elif defined FFI_PL_PROBE_BIGENDIAN64
226             ((uint16_t*)result)[3] = SvUV(sv);
227             #else
228 6 50         *((uint16_t*)result) = SvUV(sv);
229             #endif
230 6           break;
231             case FFI_PL_TYPE_SINT16:
232             #if defined FFI_PL_PROBE_BIGENDIAN
233             ((int16_t*)result)[1] = SvIV(sv);
234             #elif defined FFI_PL_PROBE_BIGENDIAN64
235             ((int16_t*)result)[3] = SvIV(sv);
236             #else
237 6 100         *((int16_t*)result) = SvIV(sv);
238             #endif
239 6           break;
240             case FFI_PL_TYPE_UINT32:
241             #if defined FFI_PL_PROBE_BIGENDIAN64
242             ((uint32_t*)result)[1] = SvUV(sv);
243             #else
244 6 50         *((uint32_t*)result) = SvUV(sv);
245             #endif
246 6           break;
247             case FFI_PL_TYPE_SINT32:
248             #if defined FFI_PL_PROBE_BIGENDIAN64
249             ((int32_t*)result)[1] = SvIV(sv);
250             #else
251 9 100         *((int32_t*)result) = SvIV(sv);
252             #endif
253 9           break;
254             case FFI_PL_TYPE_UINT64:
255 6 50         *((uint64_t*)result) = SvU64(sv);
256 6           break;
257             case FFI_PL_TYPE_SINT64:
258 6 100         *((int64_t*)result) = SvI64(sv);
259 6           break;
260             case FFI_PL_TYPE_FLOAT:
261 6 100         *((float*)result) = SvNV(sv);
262 6           break;
263             case FFI_PL_TYPE_DOUBLE:
264 6 100         *((double*)result) = SvNV(sv);
265 6           break;
266             case FFI_PL_TYPE_OPAQUE:
267 7 100         *((void**)result) = SvOK(sv) ? INT2PTR(void*, SvIV(sv)) : NULL;
    50          
    50          
    50          
268 7           break;
269             case FFI_PL_TYPE_RECORD_VALUE:
270 3 100         if(sv_isobject(sv) && sv_derived_from(sv, extra->return_type->extra[0].record.class))
    50          
271             {
272             char *ptr;
273             STRLEN len;
274 2 50         ptr = SvPV(SvRV(sv), len);
275 2 50         if(len > extra->return_type->extra[0].record.size)
276 0           len = extra->return_type->extra[0].record.size;
277 2 100         else if(len < extra->return_type->extra[0].record.size)
278             {
279 1           warn("Return record from closure is wrong size!");
280 1           memset(result, 0, extra->return_type->extra[0].record.size);
281             }
282 2           memcpy(result, ptr, len);
283 2           break;
284             }
285 1           warn("Return record from closure is wrong type!");
286 1           memset(result, 0, extra->return_type->extra[0].record.size);
287 1           break;
288             default:
289 0           warn("bad type");
290 0           break;
291             }
292              
293 73           PUTBACK;
294             }
295              
296 103 100         if(!(flags & G_NOARGS))
297             {
298 98 50         FREETMPS;
299 98           LEAVE;
300             }
301 103           }
302