File Coverage

XS.xs
Criterion Covered Total %
statement 169 180 93.8
branch 93 168 55.3
condition n/a
subroutine n/a
pod n/a
total 262 348 75.2


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #ifndef CVf_HAS_SIGNATURES
6             # define CVf_HAS_SIGNATURES 0
7             #endif
8              
9             MODULE = Mojo::Collection::XS PACKAGE = Mojo::Collection::XS
10              
11             SV *
12             while_fast(self, cb)
13             SV *self
14             SV *cb
15             CODE:
16             {
17 5 50         if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVAV)
    50          
18 0           croak("while_fast: self is not an arrayref");
19 5 100         if (!SvROK(cb) || SvTYPE(SvRV(cb)) != SVt_PVCV)
    50          
20 1           croak("while_fast: callback must be a CODE ref");
21              
22 4           AV *av = (AV *)SvRV(self);
23 4 50         SSize_t max = AvFILL(av);
24              
25 4 50         if (max >= 0) {
26 4           dSP;
27              
28 4           CV *cv = (CV *)SvRV(cb); /* hoisted */
29 4           SV **items = AvARRAY(av);
30              
31 4           ENTER;
32 4           SAVETMPS;
33 4           SAVE_DEFSV; /* alias $_ */
34              
35 4           SV *idx_sv = sv_newmortal();
36              
37 17 100         for (SSize_t i = 0, num = 1; i <= max; i++, num++) {
38 13           SV *e = items[i];
39 13 50         if (!e) continue;
40              
41 13 50         DEFSV = e; /* $_ alias */
42 13           sv_setiv(idx_sv, num);
43              
44 13 50         PUSHMARK(SP);
45 13 50         XPUSHs(e);
46 13 50         XPUSHs(idx_sv);
47 13           PUTBACK;
48              
49 13           call_sv((SV *)cv, G_VOID | G_DISCARD);
50 13           SPAGAIN;
51             }
52              
53 4 50         FREETMPS;
54 4           LEAVE;
55             }
56              
57 4           RETVAL = SvREFCNT_inc(self);
58             }
59             OUTPUT: RETVAL
60              
61             SV *
62             while_ultra(self, cb)
63             SV *self
64             SV *cb
65             CODE:
66             {
67 2 50         if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVAV)
    50          
68 0           croak("while_ultra: self is not an arrayref");
69 2 50         if (!SvROK(cb) || SvTYPE(SvRV(cb)) != SVt_PVCV)
    50          
70 0           croak("while_ultra: callback must be a CODE ref");
71              
72 2           AV *av = (AV *)SvRV(self);
73 2 50         SSize_t max = AvFILL(av);
74              
75 2 50         if (max >= 0) {
76 2           dSP;
77              
78 2           CV *cv = (CV *)SvRV(cb); /* hoist */
79 2           SV **items = AvARRAY(av);
80              
81 2           ENTER;
82 2           SAVETMPS;
83              
84 2           SV *idx_sv = sv_newmortal();
85              
86 6 100         for (SSize_t i = 0, num = 1; i <= max; i++, num++) {
87 4           SV *e = items[i];
88 4 50         if (!e) continue;
89              
90 4           sv_setiv(idx_sv, num);
91              
92 4 50         PUSHMARK(SP);
93 4 50         XPUSHs(e);
94 4 50         XPUSHs(idx_sv);
95 4           PUTBACK;
96              
97 4           call_sv((SV *)cv, G_VOID | G_DISCARD);
98 4           SPAGAIN;
99             }
100              
101 2 50         FREETMPS;
102 2           LEAVE;
103             }
104              
105 2           RETVAL = SvREFCNT_inc(self);
106             }
107             OUTPUT: RETVAL
108              
109             SV *
110             each_fast(self, cb)
111             SV *self
112             SV *cb
113             CODE:
114             {
115 4 50         if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVAV)
    50          
116 0           croak("Mojo::Collection::XS->each_fast: self is not an arrayref");
117 4 50         if (!SvROK(cb) || SvTYPE(SvRV(cb)) != SVt_PVCV)
    50          
118 0           croak("Mojo::Collection::XS->each_fast: callback must be a CODE ref");
119              
120 4           AV *av = (AV *)SvRV(self);
121 4 50         SSize_t max = AvFILL(av);
122              
123 4 50         if (max >= 0) {
124 4           dSP;
125              
126 4           CV *cv = (CV *)SvRV(cb); /* hoist sekali */
127 4           SV **items = AvARRAY(av);
128              
129 4           ENTER;
130 4           SAVETMPS;
131 4           SAVE_DEFSV;
132              
133 4           SV *num_sv = sv_2mortal(newSViv(0)); /* reusable index SV */
134              
135 14 100         for (SSize_t idx = 0, num = 1; idx <= max; idx++, num++) {
136 10           SV *item = items[idx];
137 10 50         if (!item) continue;
138              
139 10 50         DEFSV = item; /* alias to element */
140 10           sv_setiv(num_sv, num);
141              
142 10 50         PUSHMARK(SP);
143 10 50         XPUSHs(item);
144 10 50         XPUSHs(num_sv);
145 10           PUTBACK;
146              
147 10           call_sv((SV *)cv, G_VOID | G_DISCARD);
148 10           SPAGAIN;
149             }
150              
151 4 50         FREETMPS;
152 4           LEAVE;
153             }
154              
155 4           RETVAL = SvREFCNT_inc(self);
156             }
157             OUTPUT:
158             RETVAL
159              
160             SV *
161             map_ultra(self, cb)
162             SV *self
163             SV *cb
164             CODE:
165             {
166 5 50         if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVAV)
    50          
167 0           croak("map_ultra: self is not an arrayref");
168 5 50         if (!SvROK(cb) || SvTYPE(SvRV(cb)) != SVt_PVCV)
    50          
169 0           croak("map_ultra: callback must be a CODE ref");
170              
171 5           AV *av = (AV *)SvRV(self);
172 5 50         SSize_t max = AvFILL(av);
173              
174 5           AV *out = newAV();
175 5           SV *out_rv = newRV_noinc((SV *)out);
176 5           sv_bless(out_rv, SvSTASH(SvRV(self)));
177              
178 5 50         if (max >= 0) {
179 5           dSP;
180              
181 5           CV *cv = (CV *)SvRV(cb);
182 5           SV **items = AvARRAY(av);
183              
184 5           ENTER;
185 5           SAVETMPS;
186 5           av_extend(out, max);
187              
188 19 100         for (SSize_t i = 0; i <= max; i++) {
189 14           SV *item = items[i];
190 14 50         if (!item) continue;
191              
192 14 50         PUSHMARK(SP);
193 14 50         XPUSHs(item);
194 14           PUTBACK;
195              
196 14           I32 count = call_sv((SV *)cv, G_SCALAR);
197 14           SPAGAIN;
198              
199 14 50         if (count > 0) {
200 14           SV *ret = POPs;
201 14 50         if (ret && ret != &PL_sv_undef) {
    50          
202 14 50         av_push(out, SvTEMP(ret) ? newSVsv(ret) : SvREFCNT_inc(ret));
203             }
204 14 50         if (count > 1) SP -= (count - 1);
205             }
206             }
207              
208 5 50         FREETMPS;
209 5           LEAVE;
210             }
211              
212 5           RETVAL = out_rv;
213             }
214             OUTPUT:
215             RETVAL
216              
217             SV *
218             map_fast(self, cb)
219             SV *self
220             SV *cb
221             CODE:
222             {
223 4 50         if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVAV)
    50          
224 0           croak("Mojo::Collection::XS->map_fast: self is not an arrayref");
225 4 50         if (!SvROK(cb) || SvTYPE(SvRV(cb)) != SVt_PVCV)
    50          
226 0           croak("Mojo::Collection::XS->map_fast: callback must be a CODE ref");
227              
228 4           AV *av = (AV *)SvRV(self);
229 4 50         SSize_t max = AvFILL(av);
230              
231 4           AV *out_av = newAV();
232 4           SV *ret_rv = newRV_noinc((SV *)out_av);
233 4           sv_bless(ret_rv, SvSTASH(SvRV(self)));
234              
235 4 50         if (max >= 0) {
236 4           dSP;
237              
238 4           CV *cv = (CV *)SvRV(cb); /* hoist sekali */
239 4           SV **items = AvARRAY(av);
240              
241 4           ENTER;
242 4           SAVETMPS;
243 4           SAVE_DEFSV;
244 4           av_extend(out_av, max);
245              
246 17 100         for (SSize_t idx = 0; idx <= max; idx++) {
247 13           SV *item = items[idx];
248 13 50         if (!item) continue;
249              
250 13 50         DEFSV = item; /* alias to element */
251              
252 13 50         PUSHMARK(SP);
253 13 50         XPUSHs(item);
254 13           PUTBACK;
255              
256 13           I32 count = call_sv((SV *)cv, G_ARRAY);
257 13           SPAGAIN;
258              
259 13 50         if (count > 0) {
260 13           SV **results = SP - count + 1; /* start of returned values */
261 30 100         for (I32 i = 0; i < count; i++) {
262 17           av_push(out_av, newSVsv(results[i]));
263             }
264 13           SP -= count;
265             }
266             }
267              
268 4 50         FREETMPS;
269 4           LEAVE;
270             }
271              
272 4           RETVAL = ret_rv;
273             }
274             OUTPUT:
275             RETVAL
276              
277             SV *
278             grep_fast(self, cb)
279             SV *self
280             SV *cb
281             CODE:
282             {
283 5 50         if (!SvROK(self) || SvTYPE(SvRV(self)) != SVt_PVAV)
    50          
284 0           croak("Mojo::Collection::XS->grep_fast: self is not an arrayref");
285 5 50         if (!SvROK(cb) || SvTYPE(SvRV(cb)) != SVt_PVCV)
    50          
286 0           croak("Mojo::Collection::XS->grep_fast: callback must be a CODE ref");
287              
288 5           AV *av = (AV *)SvRV(self);
289 5 50         SSize_t max = AvFILL(av);
290              
291 5           AV *out_av = newAV();
292 5           SV *ret_rv = newRV_noinc((SV *)out_av);
293 5           sv_bless(ret_rv, SvSTASH(SvRV(self)));
294              
295 5 50         if (max >= 0) {
296 5           dSP;
297              
298 5           CV *cv = (CV *)SvRV(cb);
299 5           SV **items = AvARRAY(av);
300              
301 5           ENTER;
302 5           SAVETMPS;
303 5           SAVE_DEFSV; /* karena kita set $_ */
304              
305 24 100         for (SSize_t idx = 0; idx <= max; idx++) {
306 19           SV *item = items[idx];
307 19 50         if (!item) continue;
308              
309 19 50         DEFSV = item; /* $_ = item */
310              
311 19 50         PUSHMARK(SP);
312 19 50         XPUSHs(item);
313 19           PUTBACK;
314              
315 19           I32 count = call_sv((SV *)cv, G_SCALAR);
316 19           SPAGAIN;
317              
318 19 50         SV *decision = count > 0 ? POPs : &PL_sv_undef;
319 19 50         if (count > 1) SP -= (count - 1);
320              
321 19 50         if (decision && SvTRUE(decision)) {
    100          
322             /* tidak clone: persis referensi aslinya */
323 11           av_push(out_av, SvREFCNT_inc(item));
324             }
325             }
326              
327 5 50         FREETMPS;
328 5           LEAVE;
329             }
330              
331 5           RETVAL = ret_rv;
332             }
333             OUTPUT:
334             RETVAL