Array-Splice
view release on metacpan or search on metacpan
lib/Array/Splice.xs view on Meta::CPAN
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
MODULE = Array::Splice PACKAGE = Array::Splice
void
_splice(array,offset,length,...)
SV* array;
I32 offset;
I32 length;
INIT:
AV* ary;
I32 i;
I32 newlen;
I32 after;
I32 diff;
SV **tmparyval = 0;
MAGIC *mg;
register SV **src;
register SV **dst;
PPCODE:
if ( !SvROK(array) || SvTYPE(SvRV(array)) != SVt_PVAV ) {
croak("first argument to Array::Splice::_splice() not an array");
}
ary = (AV*) SvRV(array);
if ((mg = SvTIED_mg((SV*)ary, 'P'))) {
croak("Array::Splice::_splice() not implemented for tied arrays");
}
i = offset;
if (offset < 0)
offset += AvFILLp(ary) + 1;
if (offset < 0)
croak(PL_no_aelem, i);
if (length < 0) {
length += AvFILLp(ary) - offset + 1;
if (length < 0)
length = 0;
}
if (offset > AvFILLp(ary) + 1) {
if (ckWARN(WARN_MISC))
warn("Array::Splice::_splice() offset past end of array" );
offset = AvFILLp(ary) + 1;
}
after = AvFILLp(ary) + 1 - (offset + length);
if (after < 0) { /* not that much array */
length += after; /* offset+length now in array */
after = 0;
if (!AvALLOC(ary))
av_extend(ary, 0);
}
newlen = items - 3;
diff = newlen - length;
/* inc refcounts now: avoid problems if they're from the array */
for (src = &ST(3), i = newlen; i; i--) {
SvREFCNT_inc(*src++);
}
if (diff < 0) { /* shrinking the area */
if (newlen) {
New(451, tmparyval, newlen, SV*); /* so remember insertion */
Copy(&ST(3), tmparyval, newlen, SV*);
}
if (GIMME == G_ARRAY) { /* copy return vals to stack */
MEXTEND(SP, length);
src = AvARRAY(ary)+offset;
i = length;
if (AvREAL(ary)) {
for ( ; i; i--) {
PUSHs(sv_2mortal(*src++)); /* free them eventualy */
}
} else {
for ( ; i; i--) {
PUSHs(*src++); /* don't free them eventualy */
}
}
( run in 1.271 second using v1.01-cache-2.11-cpan-71847e10f99 )