Xavier Noria wrote:
I founded nothing about slices in perlguts, perlxs*, or perlapi (where
are they documented?), so I wrote this little utility to take a slice
from AV* data using the indices in AV* indices (integers), and put the
result in AV* out (indices and out are guaranteed to have the same
length):
void __slice(AV* indices, AV* data, AV* out) {
int i;
I32 last_index;
I32 index;
SV* val;
last_index = av_len(indices);
for (i = 0; i <= last_index; ++i) {
index = SvIVX(*av_fetch(indices, i, 0));
val = *av_fetch(data, index, 0);
av_store(out, i, newSVsv(val));
}
}
Hi Xavier, how are you doing?
to make a real splice, instead of cloning the SV with newSVsv(), just
increment the reference count of the original one and store it on the
target AV.
For instance:
void __slice(AV* indices, AV* data, AV* out) {
int i;
I32 last_index;
I32 index;
SV* val;
last_index = av_len(indices);
for (i = 0; i <= last_index; ++i) {
index = SvIVX(*av_fetch(indices, i, 0));
val = *av_fetch(data, index, 1); // <-- note the 1 here,
// to create a new SV if it
// doesn't exists yet on the
// original AV!
SvREFCNT_inc(val);
av_store(out, i, val);
// well, if out can be a tied array (and in the general
// case, it can), then you should replace the last line with
// this one:
// if (!av_store(out, i, val)) SvREFCNT_dec(val);
}
}
BTW, I can lend you my copy of "Extending and Embedding Perl" if you want.
Cheers,
- Salva