Skip to content

Instantly share code, notes, and snippets.

Created June 23, 2011 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/1042691 to your computer and use it in GitHub Desktop.
Save anonymous/1042691 to your computer and use it in GitHub Desktop.
diff --git a/src/pmc/resizablepmcarray.pmc b/src/pmc/resizablepmcarray.pmc
index 29c0294..ad83307 100644
--- a/src/pmc/resizablepmcarray.pmc
+++ b/src/pmc/resizablepmcarray.pmc
@@ -602,59 +602,59 @@ Returns the Parrot string representation C<ResizablePMCArray>.
/*
-=item C<void splice(PMC *value, INTVAL offset, INTVAL count)>
+=item C<void splice(PMC *from, INTVAL offset, INTVAL count)>
Replaces C<count> elements starting at C<offset> with the elements in
-C<value>.
+C<from>.
-Note that the C<value> PMC can be of any of the various array types.
-
-Note that this implementation can be *VERY *inefficient as it manipulates
-everything via the VTABLE api.
+Note that the C<from> PMC can be of any of the various array types.
=cut
*/
- VTABLE void splice(PMC *value, INTVAL offset, INTVAL count) {
-
- const INTVAL length = VTABLE_elements(INTERP, SELF);
- const INTVAL elems = VTABLE_elements(INTERP, value);
- const INTVAL shift = elems - count;
- INTVAL i;
+ VTABLE void splice(PMC *from, INTVAL offset, INTVAL count) {
+ const INTVAL elems0 = VTABLE_elements(INTERP, SELF);
+ const INTVAL elems1 = VTABLE_elements(INTERP, from);
+ PMC **item = 0;
+ INTVAL tail;
+ INTVAL i;
/* start from end? */
- if (offset < 0)
- offset += length;
+ if (offset < 0)
+ offset += elems0;
if (offset < 0)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"illegal splice offset\n");
- /* shrink the array */
- if (shift < 0) {
- /* start at offset so we don't overwrite values we'll need */
- for (i = offset + count; i < length; ++i)
- VTABLE_set_pmc_keyed_int(INTERP, SELF, i + shift,
- VTABLE_get_pmc_keyed_int(INTERP, SELF, i));
+ /* number of elements after the splice */
+ tail = elems0 - offset - count;
+ if (tail < 0) tail = 0;
- SELF.set_integer_native(length + shift);
+ item = PMC_array(SELF);
+ if (tail > 0 && count > elems1) {
+ /* we're shrinking the array, so first move the tail */
+ mem_sys_memmove(item + offset + elems1, item + offset + count,
+ tail * sizeof (PMC *));
}
- /* grow the array */
- else if (shift > 0) {
- SELF.set_integer_native(length + shift);
-
- /* move the existing values */
- /* start at length-1 so we don't overwrite values we'll need */
- for (i = length - 1; i >= offset; --i)
- VTABLE_set_pmc_keyed_int(INTERP, SELF, i + shift,
- VTABLE_get_pmc_keyed_int(INTERP, SELF, i));
+
+ /* now resize the array */
+ SELF.set_integer_native(offset + elems1 + tail);
+
+ item = PMC_array(SELF);
+ if (tail > 0 && count < elems1) {
+ /* the array grew, so move the tail to the right */
+ mem_sys_memmove(item + offset + elems1, item + offset + count,
+ tail * sizeof (PMC *));
}
- /* copy the new values */
- for (i = 0; i < elems; ++i)
- VTABLE_set_pmc_keyed_int(INTERP, SELF, i + offset,
- VTABLE_get_pmc_keyed_int(INTERP, value, i));
+ /* now copy C<from>'s elements into SELF */
+ if (elems1 > 0) {
+ PMC *iter = VTABLE_get_iter(INTERP, from);
+ for (i = 0; i < elems1; i++)
+ item[offset + i] = VTABLE_shift_pmc(INTERP, iter);
+ }
}
/*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment