Set-Product-XS
view release on metacpan or search on metacpan
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#ifndef CvISXSUB
# define CvISXSUB(cv) CvXSUB(cv)
#endif
#include "multicall.h"
MODULE = Set::Product::XS PACKAGE = Set::Product::XS
void
product (code, ...)
SV *code
PROTOTYPE: &@
PREINIT:
int i, j, *idx;
AV **in;
SV **out;
CV *cv;
HV *stash;
GV *gv;
PPCODE:
cv = sv_2cv(code, &stash, &gv, 0);
if (! cv)
croak("Not a subroutine reference");
if (2 > items)
XSRETURN_UNDEF;
items--;
for (i = items; i > 0; i--) {
SvGETMAGIC(ST(i));
if (! SvROK(ST(i)) || SVt_PVAV != SvTYPE(SvRV(ST(i))))
croak("Not an array reference");
}
for (i = items; i > 0; i--)
if (0 > av_len((AV *)SvRV(ST(i))))
XSRETURN_UNDEF;
Newx(in, items, AV*);
for (i = items - 1; i >= 0; i--)
in[i] = (AV *)SvRV(ST(i+1));
Newx(out, items, SV*);
for (i = items - 1; i >= 0; i--)
out[i] = AvARRAY(in[i])[0];
Newxz(idx, items, int);
SAVEFREEPV(in);
SAVEFREEPV(out);
SAVEFREEPV(idx);
if (! CvISXSUB(cv)) {
I32 gimme = G_VOID;
/* localize @_ */
AV *av = save_ary(PL_defgv);
/* @_ doesn't refcount it's contents. */
AvREAL_off(av);
dMULTICALL;
PUSH_MULTICALL(cv);
for (i = 0; i >= 0; ) {
av_fill(av, items - 1);
for (j = items - 1; j >= 0; j--)
AvARRAY(av)[j] = out[j];
ENTER;
SAVETMPS;
MULTICALL;
FREETMPS;
LEAVE;
for (i = items - 1; i >= 0; i--) {
idx[i]++;
if (idx[i] > av_len(in[i])) {
idx[i] = 0;
out[i] = AvARRAY(in[i])[0];
}
else {
out[i] = AvARRAY(in[i])[idx[i]];
break;
( run in 0.451 second using v1.01-cache-2.11-cpan-5511b514fd6 )