# New Ticket Created by Dino Morelli
# Please include the string: [perl #36244]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org/rt3/Ticket/Display.html?id=36244 >
As per discussions with Leo and Jerry, new allocation code for
resizablebooleanarray to support...
adding push_integer, pop_integer, shift_integer, unshift_integer
Some other things like freeze/thaw added as well because of this.
Removed push_integer from fixedbooleanarray
Files:
classes/fixedbooleanarray.pmc
classes/resizablebooleanarray.pmc
t/pmc/resizablebooleanarray.t
--
.~. Dino Morelli
/V\ email: [EMAIL PROTECTED]
/( )\ weblog: http://categorically.net/d/blog/
^^-^^ preferred distro: Debian GNU/Linux http://www.debian.org
Index: classes/fixedbooleanarray.pmc
===================================================================
--- classes/fixedbooleanarray.pmc (revision 8300)
+++ classes/fixedbooleanarray.pmc (working copy)
@@ -458,22 +458,6 @@
/*
-=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
-
-*/
-
- void push_integer (INTVAL value) {
- INTVAL nextix = DYNSELF.elements();
- DYNSELF.set_integer_keyed_int(nextix, value);
- }
-
-/*
-
=back
=head2 Freeze/thaw Interface
@@ -530,6 +514,8 @@
Initial version 2004.06.11 by Matt Fowles
+Removed push_integer - Dino Morelli 2004-06-10
+
=cut
*/
Index: classes/resizablebooleanarray.pmc
===================================================================
--- classes/resizablebooleanarray.pmc (revision 8300)
+++ classes/resizablebooleanarray.pmc (working copy)
@@ -25,6 +25,7 @@
#define BITS_PER_CHAR 8
+#define MIN_ALLOC 8 * BITS_PER_CHAR
pmclass ResizableBooleanArray extends FixedBooleanArray need_ext does array {
@@ -49,10 +50,13 @@
*/
INTVAL get_integer_keyed_int (INTVAL key) {
- Parrot_UInt1 *sd;
if (key < 0)
internal_exception(OUT_OF_BOUNDS,
"ResizableBooleanArray: index out of bounds!");
+
+ /* Adjust key for the current head position */
+ key += PMC_int_val2(SELF);
+
if(key >= PMC_int_val(SELF))
DYNSELF.set_integer_native(key+1);
@@ -70,6 +74,9 @@
*/
void set_integer_keyed_int (INTVAL key, INTVAL value) {
+ /* Adjust key for the current head position */
+ key += PMC_int_val2(SELF);
+
if (key < 0)
internal_exception(OUT_OF_BOUNDS,
"ResizableBooleanArray: index out of bounds!");
@@ -91,30 +98,223 @@
void set_integer_native (INTVAL size) {
Parrot_UInt1 *sd;
+ INTVAL newASize;
+ INTVAL currSize = PMC_int_val(SELF) - PMC_int_val2(SELF);
+
+ /* We are already at the requested size. Yay */
+ if(size == currSize) return;
+
if (size < 0)
internal_exception(OUT_OF_BOUNDS,
- "ResizableBooleanArray: Can't resize!");
+ "ResizableBooleanArray: Can't resize!");
+ newASize = (size / MIN_ALLOC + 1) * MIN_ALLOC;
+
+ /* Nothing allocated yet */
if ( ! PMC_data(SELF) ) {
- SUPER(size);
- } else if ( size > PMC_int_val2(SELF) ) {
- INTVAL old_size = PMC_int_val2(SELF);
- PMC_int_val2(SELF) = size < 2*old_size ? 2*old_size :
(size/BITS_PER_CHAR+1)*BITS_PER_CHAR;
+ PMC_data(SELF) = mem_sys_allocate_zeroed(newASize);
+ }
+ else {
sd = PMC_data(SELF);
- PMC_data(SELF) = mem_sys_realloc(sd,
PMC_int_val2(SELF)/BITS_PER_CHAR);
- PMC_int_val(SELF) = size;
- } else {
- PMC_int_val(SELF) = size;
- return;
+ PMC_data(SELF) = mem_sys_realloc(sd, newASize);
}
+
+ PMC_int_val2(SELF) = 0;
+ PMC_int_val(SELF) = size;
}
-}
+/*
+=item C<void push_integer(INTVAL size)>
+
+Extends the array by adding an element of value C<value> to the end.
+
+=cut
+
+*/
+
+ void push_integer (INTVAL value) {
+ INTVAL size = PMC_int_val(SELF) - PMC_int_val2(SELF);
+ DYNSELF.set_integer_native(size + 1);
+ DYNSELF.set_integer_keyed_int(size, value);
+ }
+
/*
+=item C<void pop_integer(INTVAL size)>
+
+Removes and returns the last element.
+
+=cut
+
+*/
+
+ INTVAL pop_integer () {
+ INTVAL size = PMC_int_val(SELF) - PMC_int_val2(SELF);
+ INTVAL value = DYNSELF.get_integer_keyed_int(size - 1);
+ DYNSELF.set_integer_native(size - 1);
+
+ return value;
+ }
+
+/*
+
+=item C<void unshift_integer(INTVAL size)>
+
+Extends the array by adding an element of value C<value> to the
+beginning.
+
+=cut
+
+*/
+
+ void unshift_integer (INTVAL value) {
+ Parrot_UInt1 *sdOld, *sdNew;
+
+ /* If int_val2 is smaller than 0, size this thing up */
+ if(PMC_int_val2(SELF) <= 0) {
+ sdOld = PMC_data(SELF);
+ sdNew = mem_sys_allocate_zeroed(
+ ((PMC_int_val2(SELF) / MIN_ALLOC) * MIN_ALLOC)
+ + PMC_int_val(SELF)
+ + ((PMC_int_val(SELF) / MIN_ALLOC + 1) * MIN_ALLOC)
+ );
+ mem_sys_memmove(sdNew, sdOld + PMC_int_val2(SELF),
+ PMC_int_val(SELF));
+ mem_sys_free(sdOld);
+ PMC_data(SELF) = sdNew;
+ PMC_int_val2(SELF) += MIN_ALLOC;
+ PMC_int_val(SELF) += MIN_ALLOC;
+ }
+
+ /* Move the head position */
+ PMC_int_val2(SELF)--;
+
+ /* Assign the new value as the first item */
+ DYNSELF.set_integer_keyed_int(0, value);
+ }
+
+/*
+
+=item C<void shift_integer(INTVAL size)>
+
+Removes and returns the first element.
+
+=cut
+
+*/
+
+ INTVAL shift_integer () {
+ INTVAL value;
+ Parrot_UInt1 *sdOld, *sdNew;
+
+
+ if (DYNSELF.elements() < 1)
+ internal_exception(OUT_OF_BOUNDS,
+ "ResizableBooleanArray: Can't shift from an empty array!");
+
+ /* Get head value */
+ value = DYNSELF.get_integer_keyed_int(0);
+
+ /* Move the head position */
+ PMC_int_val2(SELF)++;
+
+ /* If int_val2 is bigger than our allocation unit size, size
+ this thing down */
+ if(PMC_int_val2(SELF) >= MIN_ALLOC) {
+ sdOld = PMC_data(SELF);
+ sdNew = mem_sys_allocate_zeroed(
+ ((PMC_int_val2(SELF) / MIN_ALLOC) * MIN_ALLOC)
+ + PMC_int_val(SELF)
+ + ((PMC_int_val(SELF) / MIN_ALLOC + 1) * MIN_ALLOC)
+ );
+ mem_sys_memmove(sdNew, sdOld + PMC_int_val2(SELF),
+ PMC_int_val(SELF));
+ mem_sys_free(sdOld);
+ PMC_data(SELF) = sdNew;
+ }
+
+ return value;
+ }
+
+/*
+
+=item C<INTVAL elements()>
+
+=cut
+
+*/
+
+ INTVAL elements () {
+ return PMC_int_val(SELF) - PMC_int_val2(SELF);
+ }
+
+/*
+
+=item C<INTVAL get_integer()>
+
+Returns the number of elements in the array.
+
+=cut
+
+*/
+
+ INTVAL get_integer () {
+ return SELF.elements();
+ }
+
+/*
+
=back
+=head2 Freeze/thaw Interface
+
+=over 4
+
+=item C<void freeze(visit_info *info)>
+
+Used to archive the string.
+
+=cut
+
+*/
+ void freeze(visit_info *info) {
+ IMAGE_IO *io = info->image_io;
+ STRING *s;
+ INTVAL headPos = PMC_int_val2(SELF);
+ INTVAL size = PMC_int_val(SELF) - headPos;
+
+ io->vtable->push_integer(INTERP, io, size);
+ s = string_from_cstring(INTERP, PMC_data(SELF) + headPos,
+ size / MIN_ALLOC);
+ io->vtable->push_string(INTERP, io, s);
+ }
+
+/*
+
+=item C<void thaw(visit_info *info)>
+
+Used to unarchive the string.
+
+=cut
+
+*/
+ void thaw(visit_info *info) {
+ IMAGE_IO *io = info->image_io;
+ INTVAL size = io->vtable->shift_integer(INTERP, io);
+ STRING *s = io->vtable->shift_string(INTERP, io);
+
+ DYNSELF.set_integer_native(size);
+ mem_sys_memcopy(PMC_data(SELF) + PMC_int_val2(SELF),
+ s->strstart, s->bufused);
+ }
+
+} /* pmclass */
+
+/*
+
+=back
+
=head1 SEE ALSO
F<docs/pdds/pdd17_basic_types.pod>.
@@ -122,9 +322,15 @@
=head1 HISTORY
Initial version - Matt Fowles 2004-06-11
+
Changed allocator to double size - Matt Fowles 2004-06-15
+
Added push_integer - Bernhard Schmalhofer 2004-10-17
+Changed allocation code, added - Dino Morelli 2005-06-10
+ push_, pop_, shift_,
+ unshift_integer, freeze, thaw
+
=cut
*/
Index: t/pmc/resizablebooleanarray.t
===================================================================
--- t/pmc/resizablebooleanarray.t (revision 8300)
+++ t/pmc/resizablebooleanarray.t (working copy)
@@ -16,9 +16,12 @@
=cut
-use Parrot::Test tests => 9;
+use strict;
+use warnings;
+use Parrot::Test tests => 11;
use Test::More;
+
my $fp_equality_macro = <<'ENDOFMACRO';
.macro fp_eq ( J, K, L )
save N0
@@ -62,6 +65,7 @@
.endm
ENDOFMACRO
+
pasm_output_is(<<'CODE', <<'OUTPUT', "Setting array size");
new P0, .ResizableBooleanArray
@@ -102,6 +106,7 @@
ok 5
OUTPUT
+
pasm_output_is(<<'CODE', <<'OUTPUT', "Setting first element");
new P0, .ResizableBooleanArray
set P0, 1
@@ -160,6 +165,7 @@
ok 3
OUTPUT
+
# TODO: Rewrite these properly when we have exceptions
pasm_output_is(<<'CODE', <<'OUTPUT', "Setting out-of-bounds elements");
@@ -190,6 +196,7 @@
ok 3
OUTPUT
+
pasm_output_is(<<'CODE', <<'OUTPUT', "Getting out-of-bounds elements");
new P0, .ResizableBooleanArray
set P0, 1
@@ -238,6 +245,7 @@
ok 3
OUTPUT
+
pasm_output_is(<<"CODE", <<'OUTPUT', "Set via INTs, access via PMC Keys");
@{[ $fp_equality_macro ]}
new P0, .ResizableBooleanArray
@@ -284,6 +292,7 @@
ok 4
OUTPUT
+
pir_output_is(<< 'CODE', << 'OUTPUT', "check whether interface is done");
.sub _main
@@ -307,6 +316,7 @@
0
OUTPUT
+
pir_output_is(<< 'CODE', << 'OUTPUT', "push integer");
.sub _main
@@ -328,3 +338,149 @@
10001
1
OUTPUT
+
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "push and pop");
+
+.sub test @MAIN
+ .local int i, i_elem
+ .local pmc pmc_arr
+ .local int elements
+
+ i= 1
+ pmc_arr= new ResizableBooleanArray
+
+ print_num_elements( pmc_arr )
+
+ push pmc_arr, i
+ print i
+ print_num_elements( pmc_arr )
+
+ push pmc_arr, 0
+ print 0
+ print_num_elements( pmc_arr )
+
+ print_num_elements( pmc_arr )
+
+ i_elem= pop pmc_arr
+ print i_elem
+ print_num_elements( pmc_arr )
+
+ i_elem= pop pmc_arr
+ print i_elem
+ print_num_elements( pmc_arr )
+
+ pmc_arr = 62
+ push pmc_arr, 0
+ push pmc_arr, 1
+ push pmc_arr, 0
+ push pmc_arr, 1
+ i_elem = pop pmc_arr
+ i_elem = pop pmc_arr
+ i_elem = pop pmc_arr
+ print i_elem
+ print_num_elements(pmc_arr)
+
+ pmc_arr = 0
+ i_elem= pop pmc_arr
+ print i_elem
+ print_num_elements( pmc_arr )
+
+.end
+
+.sub print_num_elements
+ .param pmc pmc_arr
+ .local int elements
+ elements= pmc_arr
+ print '['
+ print elements
+ print "]\n"
+ .return()
+.end
+
+CODE
+[0]
+1[1]
+0[2]
+[2]
+0[1]
+1[0]
+1[63]
+ResizableBooleanArray: index out of bounds!
+OUTPUT
+
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "unshift and shift");
+
+.sub test @MAIN
+ .local int i, i_elem
+ .local pmc pmc_arr
+ .local int elements
+
+ i= 1
+ pmc_arr= new ResizableBooleanArray
+
+ print_num_elements( pmc_arr )
+
+ unshift pmc_arr, i
+ print i
+ print_num_elements( pmc_arr )
+
+ unshift pmc_arr, 0
+ print 0
+ print_num_elements( pmc_arr )
+
+ print_num_elements( pmc_arr )
+
+ i_elem= shift pmc_arr
+ print i_elem
+ print_num_elements( pmc_arr )
+
+ i_elem= shift pmc_arr
+ print i_elem
+ print_num_elements( pmc_arr )
+
+ pmc_arr = 62
+ unshift pmc_arr, 0
+ unshift pmc_arr, 1
+ unshift pmc_arr, 0
+ unshift pmc_arr, 1
+ i_elem = shift pmc_arr
+ i_elem = shift pmc_arr
+ i_elem = shift pmc_arr
+ print i_elem
+ print_num_elements(pmc_arr)
+
+ # Set same size array is currently
+ pmc_arr = 63
+ print_num_elements(pmc_arr)
+
+ pmc_arr = 0
+ i_elem= shift pmc_arr
+ print i_elem
+ print_num_elements( pmc_arr )
+
+ end
+.end
+
+.sub print_num_elements
+ .param pmc pmc_arr
+ .local int elements
+ elements= pmc_arr
+ print '['
+ print elements
+ print "]\n"
+ .return()
+.end
+
+CODE
+[0]
+1[1]
+0[2]
+[2]
+0[1]
+1[0]
+1[63]
+[63]
+ResizableBooleanArray: Can't shift from an empty array!
+OUTPUT