Array-Slice
view release on metacpan or search on metacpan
static MAGIC *
get_magic( pTHX_ SV *sv)
{
MAGIC *mg;
mg = get_existing_magic( aTHX_ sv);
if (mg)
return mg;
/* didn't find any iterator magic, so create some */
return sv_magicext(sv, sv_2mortal( newSViv( 0)), PERL_MAGIC_ext, 0, &private_data, 0);
}
static int
advance_iterator( pTHX_ SV *sv, int howmany)
{
MAGIC *mg;
int i;
mg = get_magic( aTHX_ sv);
i = SvIVX( mg-> mg_obj);
sv_setiv( mg-> mg_obj, i + howmany);
return i;
}
static int
set_iterator( pTHX_ SV *sv, int val)
{
MAGIC *mg;
int i;
mg = get_magic( aTHX_ sv);
i = SvIVX( mg-> mg_obj);
sv_setiv( mg-> mg_obj, val);
return i;
}
static void
clear_iterator( pTHX_ SV *sv)
{
MAGIC *mg;
if ((mg = get_existing_magic( aTHX_ sv)))
sv_setiv(mg-> mg_obj, 0);
}
MODULE = Array::Slice PACKAGE = Array::Slice
PROTOTYPES: ENABLE
void
array_slice(sv,howmany)
SV *sv
int howmany
PREINIT:
int i, j, len;
AV *av;
PPCODE:
if (howmany == 0)
XSRETURN_EMPTY;
if (howmany < 0)
croak("Second argument must be a positive integer");
if (!SvROK(sv))
croak("Argument to Array::Slice::slice must be a reference");
sv = SvRV(sv);
if (SvTYPE(sv) != SVt_PVAV)
croak("Argument to Array::Slice::slice must be an array reference");
av = (AV *) sv;
i = advance_iterator( aTHX_ sv, howmany);
len = av_len( av);
if (i > len) {
clear_iterator( aTHX_ sv);
XSRETURN_EMPTY;
}
if (GIMME_V != G_VOID) {
EXTEND(SP, howmany);
for ( j = 0; j < howmany; j++) {
PUSHs(( i + j <= len) ?
*av_fetch( av, i + j, 0) :
&PL_sv_undef
);
}
XSRETURN( howmany);
}
XSRETURN_EMPTY;
void
reset(sv,...)
SV *sv
PROTOTYPE: \@;$
PPCODE:
if (!SvROK(sv))
croak("Argument to Array::Slice::reset must be a reference");
sv = SvRV(sv);
if (SvTYPE(sv) != SVt_PVAV)
croak("Argument to Array::Slice::reset must be an array reference");
if ( items == 1 || SvTYPE( ST(1)) == SVt_NULL) {
clear_iterator( aTHX_ sv);
} else {
int i = SvIV( ST( 1));
AV *av = (AV *) sv;
int len = av_len( av);
if ( i < 0) {
i = len + i + 1;
if ( i < 0) {
warn("Array::Slice::reset past beginning of array");
i = 0;
}
} else if ( i > len) {
warn("Array::Slice::reset past end of array");
i = len;
}
set_iterator( aTHX_ sv, i);
}
XSRETURN_EMPTY;
( run in 1.478 second using v1.01-cache-2.11-cpan-71847e10f99 )