File Coverage

XS.xs
Criterion Covered Total %
statement 42 58 72.4
branch 33 60 55.0
condition n/a
subroutine n/a
pod n/a
total 75 118 63.5


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2              
3             #include "EXTERN.h"
4             #include "perl.h"
5             #include "XSUB.h"
6             #include "ppport.h"
7              
8             #ifndef CvISXSUB
9             # define CvISXSUB(cv) CvXSUB(cv)
10             #endif
11              
12             #include "multicall.h"
13              
14              
15             MODULE = Set::Product::XS PACKAGE = Set::Product::XS
16              
17             void
18             product (code, ...)
19             SV *code
20             PROTOTYPE: &@
21             PREINIT:
22             int i, j, *idx;
23             AV **in;
24             SV **out;
25             CV *cv;
26             HV *stash;
27             GV *gv;
28             PPCODE:
29 9           cv = sv_2cv(code, &stash, &gv, 0);
30 9 50         if (! cv)
31 0           croak("Not a subroutine reference");
32              
33 9 100         if (2 > items)
34 1           XSRETURN_UNDEF;
35              
36 24 100         for (i = items - 1; i > 0; i--) {
37 17 50         SvGETMAGIC(ST(i));
    0          
38 17 100         if (! SvROK(ST(i)) || SVt_PVAV != SvTYPE(SvRV(ST(i))))
    50          
39 1           croak("Not an array reference");
40             }
41 20 100         for (i = items - 1; i > 0; i--)
42 14 100         if (0 > av_len((AV *)SvRV(ST(i))))
43 1           XSRETURN_UNDEF;
44 6           items--;
45              
46 6 50         Newx(in, items, AV*);
47 19 100         for (i = items - 1; i >= 0; i--)
48 13           in[i] = (AV *)SvRV(ST(i+1));
49 6 50         Newx(out, items, SV*);
50 19 100         for (i = items - 1; i >= 0; i--)
51 13           out[i] = AvARRAY(in[i])[0];
52 6 50         Newxz(idx, items, int);
53              
54 6           SAVEFREEPV(in);
55 6           SAVEFREEPV(out);
56 6           SAVEFREEPV(idx);
57              
58 6 50         if (! CvISXSUB(cv)) {
59 6           I32 gimme = G_VOID;
60 6           AV *av = save_ary(PL_defgv);
61             /* @_ doesn't refcount it's contents. */
62 6           AvREAL_off(av);
63              
64             dMULTICALL;
65 6 50         PUSH_MULTICALL(cv);
    50          
66              
67 29 100         for (i = 0; i >= 0; ) {
68 23           av_extend(av, items - 1);
69 23           av_fill(av, items - 1);
70              
71 68 100         for (j = items - 1; j >= 0; j--)
72 45           AvARRAY(av)[j] = out[j];
73              
74 23           MULTICALL;
75              
76 39 100         for (i = items - 1; i >= 0; i--) {
77 33           idx[i]++;
78 33 100         if (idx[i] > av_len(in[i])) {
79 16           idx[i] = 0;
80 16           out[i] = AvARRAY(in[i])[0];
81             }
82             else {
83 17           out[i] = AvARRAY(in[i])[idx[i]];
84 17           break;
85             }
86             }
87             }
88              
89 6 50         POP_MULTICALL;
    50          
90             }
91             else {
92 0 0         for (i = 0; i >= 0; ) {
93             int j;
94              
95 0 0         PUSHMARK(SP);
96 0 0         EXTEND(SP, items);
    0          
97 0 0         for (j = 0; j < items; j++)
98 0           PUSHs(out[j]);
99 0           PUTBACK;
100              
101 0           call_sv((SV *)cv, G_VOID | G_DISCARD);
102              
103 0           SPAGAIN;
104              
105 0 0         for (i = items - 1; i >= 0; i--) {
106 0           idx[i]++;
107 0 0         if (idx[i] > av_len(in[i])) {
108 0           idx[i] = 0;
109 0           out[i] = AvARRAY(in[i])[0];
110             }
111             else {
112 0           out[i] = AvARRAY(in[i])[idx[i]];
113 0           break;
114             }
115             }
116             }
117             }
118              
119 8           XSRETURN_UNDEF;