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

Reply via email to