File Coverage

XS.xs
Criterion Covered Total %
statement 45 61 73.7
branch 35 62 56.4
condition n/a
subroutine n/a
pod n/a
total 80 123 65.0


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 10           cv = sv_2cv(code, &stash, &gv, 0);
30 10 50         if (! cv)
31 0           croak("Not a subroutine reference");
32              
33 10 100         if (2 > items)
34 1           XSRETURN_UNDEF;
35              
36 9           items--;
37 27 100         for (i = items; i > 0; i--) {
38 19 50         SvGETMAGIC(ST(i));
    0          
39 19 100         if (! SvROK(ST(i)) || SVt_PVAV != SvTYPE(SvRV(ST(i))))
    50          
40 1           croak("Not an array reference");
41             }
42 23 100         for (i = items; i > 0; i--)
43 16 100         if (0 > av_len((AV *)SvRV(ST(i))))
44 1           XSRETURN_UNDEF;
45              
46 7 50         Newx(in, items, AV*);
47 22 100         for (i = items - 1; i >= 0; i--)
48 15           in[i] = (AV *)SvRV(ST(i+1));
49 7 50         Newx(out, items, SV*);
50 22 100         for (i = items - 1; i >= 0; i--)
51 15           out[i] = AvARRAY(in[i])[0];
52 7 50         Newxz(idx, items, int);
53              
54 7           SAVEFREEPV(in);
55 7           SAVEFREEPV(out);
56 7           SAVEFREEPV(idx);
57              
58 7 50         if (! CvISXSUB(cv)) {
59 7           I32 gimme = G_VOID | G_NOARGS;
60             /* localize @_ */
61 7           AV *av = save_ary(PL_defgv);
62             /* @_ doesn't refcount it's contents. */
63 7           AvREAL_off(av);
64              
65             dMULTICALL;
66 7 50         PUSH_MULTICALL(cv);
    50          
67              
68 36 100         for (i = 0; i >= 0; ) {
69 29           av_fill(av, items - 1);
70              
71 86 100         for (j = items - 1; j >= 0; j--)
72 57           AvARRAY(av)[j] = out[j];
73              
74 29           ENTER;
75 29           SAVETMPS;
76 29           MULTICALL;
77 29 100         FREETMPS;
78 29           LEAVE;
79              
80 48 100         for (i = items - 1; i >= 0; i--) {
81 41           idx[i]++;
82 41 100         if (idx[i] > av_len(in[i])) {
83 19           idx[i] = 0;
84 19           out[i] = AvARRAY(in[i])[0];
85             }
86             else {
87 22           out[i] = AvARRAY(in[i])[idx[i]];
88 22           break;
89             }
90             }
91             }
92              
93 7 50         POP_MULTICALL;
    50          
94             }
95             else {
96 0 0         for (i = 0; i >= 0; ) {
97             int j;
98              
99 0 0         PUSHMARK(SP);
100 0 0         EXTEND(SP, items);
    0          
101 0 0         for (j = 0; j < items; j++)
102 0           PUSHs(out[j]);
103 0           PUTBACK;
104              
105 0           call_sv((SV *)cv, G_DISCARD | G_VOID | G_NOARGS);
106              
107 0           SPAGAIN;
108              
109 0 0         for (i = items - 1; i >= 0; i--) {
110 0           idx[i]++;
111 0 0         if (idx[i] > av_len(in[i])) {
112 0           idx[i] = 0;
113 0           out[i] = AvARRAY(in[i])[0];
114             }
115             else {
116 0           out[i] = AvARRAY(in[i])[idx[i]];
117 0           break;
118             }
119             }
120             }
121             }
122              
123 9           XSRETURN_UNDEF;