Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

326 lines (226 sloc) 7.35 kb
/*
Copyright (C) 2001-2014, Parrot Foundation.
=head1 NAME
src/pmc/resizableintegerarray.pmc - ResizableIntegerArray PMC
=head1 DESCRIPTION
This class, ResizableIntegerArray, implements an array of resizable
size, which stores INTVALs. It uses Integer PMCs for all of the
conversions.
=head2 Functions
=over 4
=cut
*/
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */
pmclass ResizableIntegerArray extends FixedIntegerArray auto_attrs provides array {
ATTR INTVAL resize_threshold; /* max size before array needs to be resized */
/*
=item C<void init_int(INTVAL size)>
Initializes the array.
=cut
*/
VTABLE void init_int(INTVAL size) :manual_wb {
SUPER(size);
if (size > 0) {
SET_ATTR_resize_threshold(INTERP, SELF, size);
PARROT_GC_WRITE_BARRIER(INTERP, SELF);
}
}
/*
=item C<INTVAL get_integer_keyed_int(INTVAL key)>
Returns the integer value of the element at index C<key>.
=cut
*/
VTABLE INTVAL get_integer_keyed_int(INTVAL key) :no_wb {
INTVAL *int_array;
INTVAL size;
GET_ATTR_size(INTERP, SELF, size);
if (key < 0)
key += size;
if (key < 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS,
"index out of bounds");
if (key >= size)
return 0;
GET_ATTR_int_array(INTERP, SELF, int_array);
return int_array[key];
}
/*
=item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
Sets the integer value of the element at index C<key> to C<value>.
=cut
*/
VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
INTVAL *int_array;
INTVAL size;
GET_ATTR_size(INTERP, SELF, size);
if (key < 0)
key += size;
if (key < 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS,
"index out of bounds");
if (key >= SELF.get_integer())
SELF.set_integer_native(key + 1);
GET_ATTR_int_array(INTERP, SELF, int_array);
int_array[key] = value;
}
/*
=item C<void set_integer_native(INTVAL size)>
Resizes the array to C<size> elements.
=cut
*/
VTABLE void set_integer_native(INTVAL size) {
INTVAL *int_array;
INTVAL resize_threshold;
if (size < 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS,
"illegal argument");
GET_ATTR_int_array(INTERP, SELF, int_array);
GET_ATTR_resize_threshold(INTERP, SELF, resize_threshold);
if (!int_array) {
/* empty - used fixed routine */
if (size < 8) {
SUPER(8);
SET_ATTR_size(INTERP, SELF, size);
SET_ATTR_resize_threshold(INTERP, SELF, 8);
}
else {
SUPER(size);
SET_ATTR_resize_threshold(INTERP, SELF, size);
}
}
else if (size <= resize_threshold) {
/* we could shrink here if necessary */
SET_ATTR_size(INTERP, SELF, size);
}
else {
INTVAL cur = resize_threshold;
INTVAL *i_array;
if (cur < 8192)
cur = size < 2 * cur ? 2 * cur : size;
else {
const INTVAL needed = size - cur;
cur += needed + 4096;
cur &= ~0xfff;
}
GET_ATTR_int_array(INTERP, SELF, i_array);
i_array = mem_gc_realloc_n_typed(INTERP, i_array, cur, INTVAL);
SET_ATTR_int_array(INTERP, SELF, i_array);
SET_ATTR_size(INTERP, SELF, size);
SET_ATTR_resize_threshold(INTERP, SELF, cur);
}
}
/*
=item C<void push_integer(INTVAL value)>
Extends the array by adding an element of value C<value> to the end
of the array.
=cut
*/
VTABLE void push_integer(INTVAL value) {
INTVAL *int_array;
INTVAL nextix;
INTVAL resize_threshold;
GET_ATTR_size(INTERP, SELF, nextix);
GET_ATTR_resize_threshold(INTERP, SELF, resize_threshold);
/* can't always avoid the resize, but don't duplicate the code */
if ((nextix && (nextix >= resize_threshold)) || !nextix)
SELF.set_integer_native(nextix + 1);
else
SET_ATTR_size(INTERP, SELF, nextix + 1);
/* fetch the array only after resize check; realloc may move it */
GET_ATTR_int_array(INTERP, SELF, int_array);
int_array[nextix] = value;
}
/*
=item C<INTVAL pop_integer()>
Removes and returns the last element in the array.
=cut
*/
VTABLE INTVAL pop_integer() :manual_wb {
INTVAL value;
INTVAL size;
GET_ATTR_size(INTERP, SELF, size);
if (size == 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS,
"Can't pop from an empty array");
value = SELF.get_integer_keyed_int(size-1);
SELF.set_integer_native(size - 1);
return value;
}
/*
=item C<INTVAL shift_integer()>
Removes and returns an item from the start of the array.
=cut
*/
VTABLE INTVAL shift_integer() :manual_wb {
INTVAL value, *int_array;
INTVAL size;
GET_ATTR_size(INTERP, SELF, size);
if (size == 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS,
"Can't shift from an empty array");
GET_ATTR_int_array(INTERP, SELF, int_array);
value = int_array[0];
--size;
memmove(int_array, int_array + 1, size * sizeof (INTVAL));
SELF.set_integer_native(size);
return value;
}
/*
=item C<void unshift_integer(INTVAL value)>
Add an integer to the start of the array.
=cut
*/
VTABLE void unshift_integer(INTVAL value) {
INTVAL *int_array;
INTVAL size;
GET_ATTR_size(INTERP, SELF, size);
SELF.set_integer_native(size + 1);
GET_ATTR_int_array(INTERP, SELF, int_array);
memmove(int_array + 1, int_array, size * sizeof (INTVAL));
int_array[0] = value;
}
/*
=item C<void delete_keyed_int(INTVAL key)>
Removes the element at C<key>.
=cut
*/
VTABLE void delete_keyed_int(INTVAL key) :manual_wb {
INTVAL *int_array;
INTVAL size;
GET_ATTR_size(INTERP, SELF, size);
if (size < 1 || key >= size)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS,
"index out of bounds");
GET_ATTR_int_array(INTERP, SELF, int_array);
--size;
memmove(int_array + key, int_array + key + 1, (size - key) * sizeof (INTVAL));
SELF.set_integer_native(size);
}
/*
=item C<PMC *clone()>
Creates and returns a copy of the array.
=cut
*/
VTABLE PMC *clone() :no_wb {
INTVAL size;
PMC * const copy = SUPER();
/* copy trimmed extra space */
GET_ATTR_size(INTERP, SELF, size);
SET_ATTR_resize_threshold(INTERP, copy, size);
return copy;
}
}
/*
=back
=head1 SEE ALSO
F<docs/pdds/pdd17_basic_types.pod>.
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/
Jump to Line
Something went wrong with that request. Please try again.