List-MoreUtils-XS

 view release on metacpan or  search on metacpan

XS.xs  view on Meta::CPAN

    int exhausted = 1;

    /* 'cv' is the hidden argument with which XS_List__MoreUtils__array_iterator (this XSUB)
     * is called. The closure_arg struct is stored in this CV. */

    arrayeach_args *args = (arrayeach_args *)(CvXSUBANY(cv).any_ptr);

    if (strEQ(method, "index"))
    {
        EXTEND(SP, 1);
        ST(0) = args->curidx > 0 ? sv_2mortal(newSViv(args->curidx-1)) : &PL_sv_undef;
        XSRETURN(1);
    }

    EXTEND(SP, args->navs);

    for (i = 0; i < args->navs; i++)
    {
        AV *av = args->avs[i];
        if (args->curidx <= av_len(av))
        {
            ST(i) = sv_2mortal(newSVsv(*av_fetch(av, args->curidx, FALSE)));
            exhausted = 0;
            continue;
        }
        ST(i) = &PL_sv_undef;
    }

    if (exhausted)
        XSRETURN_EMPTY;

    args->curidx++;
    XSRETURN(args->navs);
}

SV *
each_array (...)
PROTOTYPE: \@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@
CODE:
{
    EACH_ARRAY_BODY;
}
OUTPUT:
    RETVAL

SV *
each_arrayref (...)
CODE:
{
    EACH_ARRAY_BODY;
}
OUTPUT:
    RETVAL

void
pairwise (code, list1, list2)
    SV *code;
    AV *list1;
    AV *list2;
PROTOTYPE: &\@\@
PPCODE:
{
    dMULTICALL;
    dMULTICALLSVCV;
    int i, maxitems;
    AV *rc = newAV();
    sv_2mortal(newRV_noinc((SV*)rc));

    if(!codelike(code))
       croak_xs_usage(cv, "code, list, list");

    if (in_pad(aTHX_ code)) {
        croak("Can't use lexical $a or $b in pairwise code block");
    }

    /* deref AV's for convenience and
     * get maximum items */
    maxitems = MAX(av_len(list1),av_len(list2))+1;
    av_extend(rc, maxitems);

    gimme = G_ARRAY;
    PUSH_MULTICALL(mc_cv);

    SAVEGENERICSV(PL_firstgv);
    SAVEGENERICSV(PL_secondgv);
    PL_firstgv = MUTABLE_GV(SvREFCNT_inc(
        gv_fetchpvs("a", GV_ADD|GV_NOTQUAL, SVt_PV)
    ));
    PL_secondgv = MUTABLE_GV(SvREFCNT_inc(
        gv_fetchpvs("b", GV_ADD|GV_NOTQUAL, SVt_PV)
    ));
    /* make sure the GP isn't removed out from under us for
     * the SAVESPTR() */
    save_gp(PL_firstgv, 0);
    save_gp(PL_secondgv, 0);
    /* we don't want modifications localized */
    GvINTRO_off(PL_firstgv);
    GvINTRO_off(PL_secondgv);
    SAVEGENERICSV(GvSV(PL_firstgv));
    SvREFCNT_inc(GvSV(PL_firstgv));
    SAVEGENERICSV(GvSV(PL_secondgv));
    SvREFCNT_inc(GvSV(PL_secondgv));

    for (i = 0; i < maxitems; ++i)
    {
        SV **j;
        SV *olda = GvSV(PL_firstgv), *oldb = GvSV(PL_secondgv);

        SV **svp = av_fetch(list1, i, FALSE);
        GvSV(PL_firstgv) = SvREFCNT_inc_simple_NN(svp ? *svp : &PL_sv_undef);
        svp = av_fetch(list2, i, FALSE);
        GvSV(PL_secondgv) = SvREFCNT_inc_simple_NN(svp ? *svp : &PL_sv_undef);
        SvREFCNT_dec(olda);
        SvREFCNT_dec(oldb);

        MULTICALL;

        for (j = PL_stack_base+1; j <= PL_stack_sp; ++j)
            av_push(rc, newSVsv(*j));
    }



( run in 0.530 second using v1.01-cache-2.11-cpan-5511b514fd6 )