2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/pmc/sarray.pmc - Simple Array or Subroutine Parameter Array
11 Simple Array or Subroutine Parameter Array PMC.
12 SArray data are kept in an malloced array of C<HashEntry>s:
18 First index, for C<shift>.
22 Last index, for C<push>.
30 SArrays are fixed size, implying that the first operation on it must be
31 setting its size, and that only the most important vtable methods are
34 Currently SArrays are used for:
38 =item Global data per interpreter
40 =item Implementing lists, see F<src/list.c>.
42 =item Base class of the Exception PMC, see F<src/exception.pmc>
54 #include "parrot/parrot.h"
58 =item C<static PARROT_INLINE INTVAL
59 ret_int(PARROT_INTERP, const HashEntry *e)>
61 Processes C<*e>, returning the appropriate integer, or raising an
62 exception if necessary.
68 static PARROT_INLINE INTVAL
69 ret_int(PARROT_INTERP, const HashEntry *e)
73 return UVal_int(e->val);
75 return VTABLE_get_integer(interp, UVal_pmc(e->val));
80 real_exception(interp, NULL, E_IndexError, "SArray: Entry not an integer!");
85 =item C<static PARROT_INLINE FLOATVAL
86 ret_num(PARROT_INTERP, const HashEntry *e)>
88 Processes C<*e>, returning the appropriate floating-point number, or
89 raising an exception if necessary.
95 static PARROT_INLINE FLOATVAL
96 ret_num(PARROT_INTERP, const HashEntry *e)
100 return UVal_num(e->val);
102 return VTABLE_get_number(interp, UVal_pmc(e->val));
107 real_exception(interp, NULL, E_IndexError, "SArray: Entry not a number!");
112 =item C<static PARROT_INLINE STRING *
113 ret_string(PARROT_INTERP, HashEntry *e)>
115 Processes C<*e>, returning the appropriate Parrot string, or raising an
116 exception if necessary.
122 static PARROT_INLINE STRING*
123 ret_string(PARROT_INTERP, const HashEntry *e)
126 case enum_hash_string:
127 return UVal_str(e->val);
129 return VTABLE_get_string(interp, UVal_pmc(e->val));
134 real_exception(interp, NULL, E_IndexError, "SArray: Entry not a string!");
139 =item C<static PARROT_INLINE PMC *
140 ret_pmc(PARROT_INTERP, const HashEntry *e)>
142 Processes C<*e>, returning the appropriate PMC, or raising an exception
149 static PARROT_INLINE PMC*
150 ret_pmc(PARROT_INTERP, const HashEntry *e)
155 ret = pmc_new(interp, enum_class_Undef);
156 VTABLE_set_integer_native(interp, ret, UVal_int(e->val));
159 ret = pmc_new(interp, enum_class_Undef);
160 VTABLE_set_number_native(interp, ret, UVal_num(e->val));
162 case enum_hash_string:
163 ret = pmc_new(interp, enum_class_Undef);
164 VTABLE_set_string_native(interp, ret, UVal_str(e->val));
167 return UVal_pmc(e->val);
169 real_exception(interp, NULL, E_IndexError, "SArray: Unknown entry!");
175 =item C<static PARROT_INLINE HashEntry *
176 shift_entry(PARROT_INTERP, PMC *self)>
178 Removes and returns the first element from the array.
184 static PARROT_INLINE HashEntry *
185 shift_entry(PARROT_INTERP, PMC *self)
187 HashEntry * const e = (HashEntry *) PMC_data(self);
188 INTVAL start_index = UVal_int(e[0].val);
189 const INTVAL end_index = UVal_int(e[1].val);
192 if (start_index >= end_index)
193 real_exception(interp, NULL, OUT_OF_BOUNDS,
194 "SArray index out of bounds!");
196 ret = (HashEntry *) PMC_data(self) + (2 + start_index++);
198 /* Update the starting index */
199 UVal_int(e[0].val) = start_index;
205 =item C<static PARROT_INLINE HashEntry *
206 get_entry(PARROT_INTERP, PMC *self, INTVAL key)>
208 Returns the element for index C<key>.
214 static PARROT_INLINE HashEntry*
215 get_entry(PARROT_INTERP, PMC *self, INTVAL key)
217 HashEntry *e = (HashEntry *)PMC_data(self);
218 const INTVAL start_index = UVal_int(e[0].val);
219 const INTVAL end_index = UVal_int(e[1].val);
224 key += start_index; /* lower bound if already shifted */
226 if (key < start_index || key >= end_index)
227 real_exception(interp, NULL, OUT_OF_BOUNDS,
228 "SArray index out of bounds!");
230 return (HashEntry *)PMC_data(self) + (2 + key);
233 pmclass SArray need_ext provides array {
245 Initializes the array.
252 PMC_int_val(SELF) = 0;
253 PMC_data(SELF) = NULL;
261 Marks the array as live.
274 e = (HashEntry *)PMC_data(SELF);
275 start = UVal_int(e[0].val);
276 end = UVal_int(e[1].val);
277 e = (HashEntry *)PMC_data(SELF) + (2 + start);
279 for (i = start; i < end; i++, e++) {
281 case enum_hash_string:
282 if (UVal_str(e->val))
283 pobject_lives(INTERP, (PObj *)UVal_str(e->val));
286 if (UVal_pmc(e->val))
287 pobject_lives(INTERP, (PObj *)UVal_pmc(e->val));
297 =item C<void destroy()>
305 VTABLE void destroy() {
307 mem_sys_free(PMC_data(SELF));
308 PMC_data(SELF) = NULL;
313 =item C<PMC *clone()>
315 Creates and returns a copy of the array.
321 VTABLE PMC *clone() {
325 PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type);
330 size = PMC_int_val(SELF);
331 PMC_int_val(dest) = size;
332 PMC_data(dest) = mem_allocate_n_zeroed_typed(2 + size, HashEntry);
334 e = (HashEntry *)PMC_data(SELF);
335 d = (HashEntry *)PMC_data(dest);
336 start = UVal_int(e[0].val);
337 end = UVal_int(e[1].val);
339 UVal_int(d[0].val) = start;
340 UVal_int(d[1].val) = end;
342 e = (HashEntry *)PMC_data(SELF) + (2 + start);
343 d = (HashEntry *)PMC_data(dest) + (2 + start);
345 for (i = start; i < end; i++, e++, d++) {
349 UVal_int(d->val) = UVal_int(e->val);
352 UVal_num(d->val) = UVal_num(e->val);
354 case enum_hash_string:
356 string_copy(INTERP, UVal_str(e->val));
360 VTABLE_clone(INTERP, UVal_pmc(e->val));
367 PObj_custom_mark_destroy_SETALL(dest);
373 =item C<INTVAL get_bool()>
375 Returns whether the array has any elements.
381 VTABLE INTVAL get_bool() {
382 INTVAL size = SELF.elements();
383 return (INTVAL)(size != 0);
388 =item C<INTVAL elements()>
394 VTABLE INTVAL elements() {
400 e = (HashEntry *)PMC_data(SELF);
401 return UVal_int(e[1].val) - UVal_int(e[0].val);
406 =item C<INTVAL get_integer()>
408 Returns the number of elements in the array.
414 VTABLE INTVAL get_integer() {
415 return SELF.elements();
420 =item C<INTVAL type_keyed_int(INTVAL key)>
422 Returns the type of the element at index C<key>.
428 VTABLE INTVAL type_keyed_int(INTVAL key) {
429 HashEntry *e = get_entry(INTERP, SELF, key);
435 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
437 Returns the integer value of the element at index C<key>.
443 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
444 HashEntry *e = get_entry(INTERP, SELF, key);
445 return ret_int(INTERP, e);
450 =item C<INTVAL get_integer_keyed(PMC *key)>
452 Returns the integer value of the element at index C<*key>.
458 VTABLE INTVAL get_integer_keyed(PMC *key) {
459 /* simple int keys only */
460 INTVAL k = key_integer(INTERP, key);
461 return SELF.get_integer_keyed_int(k);
466 =item C<INTVAL shift_integer()>
468 Removes the first element from the array and returns its integer value.
474 VTABLE INTVAL shift_integer() {
475 HashEntry *ret = shift_entry(INTERP, SELF);
476 return ret_int(INTERP, ret);
481 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
483 Returns the floating-point value of the element at index C<key>.
489 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
490 HashEntry *e = get_entry(INTERP, SELF, key);
491 return ret_num(INTERP, e);
496 =item C<FLOATVAL get_number_keyed(PMC *key)>
498 Returns the floating-point value of the element at index C<*key>.
504 VTABLE FLOATVAL get_number_keyed(PMC *key) {
505 INTVAL k = key_integer(INTERP, key);
506 return SELF.get_number_keyed_int(k);
511 =item C<FLOATVAL shift_float()>
513 Removes the first element from the array and returns its floating-point
520 VTABLE FLOATVAL shift_float() {
521 HashEntry *ret = shift_entry(INTERP, SELF);
522 return ret_num(INTERP, ret);
527 =item C<STRING *get_string_keyed_int(INTVAL key)>
529 Returns the Parrot string value of the element at index C<key>.
535 VTABLE STRING *get_string_keyed_int(INTVAL key) {
536 HashEntry *e = get_entry(INTERP, SELF, key);
537 return ret_string(INTERP, e);
542 =item C<STRING *get_string_keyed(PMC *key)>
544 Returns the Parrot string value of the element at index C<*key>.
550 VTABLE STRING *get_string_keyed(PMC *key) {
551 INTVAL k = key_integer(INTERP, key);
552 return SELF.get_string_keyed_int(k);
557 =item C<STRING *shift_string()>
559 Removes the first element from the array and returns its Parrot string
566 VTABLE STRING *shift_string() {
567 HashEntry *ret = shift_entry(INTERP, SELF);
568 return ret_string(INTERP, ret);
573 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
575 Returns the PMC value of the element at index C<key>.
581 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
582 HashEntry *e = get_entry(INTERP, SELF, key);
583 return ret_pmc(INTERP, e);
588 =item C<PMC *get_pmc_keyed(PMC *key)>
590 Returns the PMC value of the element at index C<*key>.
596 VTABLE PMC *get_pmc_keyed(PMC *key) {
597 INTVAL k = key_integer(INTERP, key);
598 return SELF.get_pmc_keyed_int(k);
603 =item C<PMC *shift_pmc()>
605 Removes the first element from the array and returns its PMC value.
611 VTABLE PMC *shift_pmc() {
612 HashEntry *ret = shift_entry(INTERP, SELF);
613 return ret_pmc(INTERP, ret);
618 =item C<void set_integer_native(INTVAL size)>
620 Resizes the array to C<size> elements.
626 VTABLE void set_integer_native(INTVAL size) {
627 if (PMC_int_val(SELF))
628 real_exception(interp, NULL, E_IndexError, "SArray: Can't resize!");
630 PMC_int_val(SELF) = size;
632 /* Probably ought to actually copy this... */
635 mem_sys_free(PMC_data(SELF));
637 PMC_data(SELF) = mem_allocate_n_zeroed_typed(2 + size, HashEntry);
638 PObj_custom_mark_destroy_SETALL(SELF);
643 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
645 Sets the integer value of the element at index C<key> to C<value>.
651 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
654 if (key < 0 || key >= PMC_int_val(SELF))
655 real_exception(interp, NULL, E_IndexError, "SArray index out of bounds!");
657 e = (HashEntry *)PMC_data(SELF) + (2 + key);
658 e->type = enum_hash_int;
659 UVal_int(e->val) = value;
660 e = (HashEntry *)PMC_data(SELF) + 1;
662 if (key >= UVal_int(e->val))
663 UVal_int(e->val) = key + 1;
668 =item C<void push_integer(INTVAL value)>
670 Adds an element with integer value C<value> to the end of the array.
676 VTABLE void push_integer(INTVAL value) {
681 real_exception(interp, NULL, E_IndexError, "SArray index out of bounds!");
683 e = (HashEntry *)PMC_data(SELF) + 1;
684 nextix = UVal_int(e->val);
686 SELF.set_integer_keyed_int(nextix, value);
691 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
693 Sets the floating-point value of the element at index C<key> to
700 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
703 if (key < 0 || key >= PMC_int_val(SELF))
704 real_exception(interp, NULL, E_IndexError, "SArray index out of bounds!");
706 e = (HashEntry *)PMC_data(SELF) + (2 + key);
707 e->type = enum_hash_num;
708 UVal_num(e->val) = value;
709 e = (HashEntry *)PMC_data(SELF) + 1;
711 if (key >= UVal_int(e->val))
712 UVal_int(e->val) = key + 1;
717 =item C<void push_float(FLOATVAL value)>
719 Adds an element with floating-point value C<value> to the end of the array.
725 VTABLE void push_float(FLOATVAL value) {
730 real_exception(interp, NULL, E_IndexError, "SArray index out of bounds!");
732 e = (HashEntry *) PMC_data(SELF) + 1;
733 nextix = UVal_int(e->val);
735 SELF.set_number_keyed_int(nextix, value);
740 =item C<void set_string_keyed_int(INTVAL key, STRING *value)>
742 Sets the Parrot string value of the element at index C<key> to C<value>.
748 VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
751 if (key < 0 || key >= PMC_int_val(SELF))
752 real_exception(interp, NULL, E_IndexError, "SArray index out of bounds!");
754 e = (HashEntry *)PMC_data(SELF) + (2 + key);
755 e->type = enum_hash_string;
756 UVal_str(e->val) = value;
757 e = (HashEntry *)PMC_data(SELF) + 1;
759 if (key >= UVal_int(e->val))
760 UVal_int(e->val) = key + 1;
765 =item C<void push_string(STRING *value)>
767 Adds an element with Parrot string value C<*value> to the end of the
774 VTABLE void push_string(STRING *value) {
779 real_exception(interp, NULL, E_IndexError,
780 "SArray index out of bounds!");
782 e = (HashEntry *)PMC_data(SELF) + 1;
783 nextix = UVal_int(e->val);
785 SELF.set_string_keyed_int(nextix, value);
790 =item C<void set_pmc_keyed_int(INTVAL key, PMC *src)>
792 Sets the PMC value of the element at index C<key> to C<*src>.
798 VTABLE void set_pmc_keyed_int(INTVAL key, PMC *src) {
801 if (key < 0 || key >= PMC_int_val(SELF))
802 real_exception(interp, NULL, E_IndexError, "SArray index out of bounds!");
804 e = (HashEntry *) PMC_data(SELF) + (2 + key);
805 e->type = enum_hash_pmc;
807 DOD_WRITE_BARRIER(INTERP, SELF, UVal_pmc(e->val), src);
808 UVal_pmc(e->val) = src;
809 e = (HashEntry *) PMC_data(SELF) + 1;
811 if (key >= UVal_int(e->val))
812 UVal_int(e->val) = key + 1;
817 =item C<void push_pmc(PMC *value)>
819 Adds an element with PMC value C<*value> to the end of the array.
825 void push_pmc(PMC *value) {
830 real_exception(interp, NULL, E_IndexError,
831 "SArray index out of bounds!");
833 e = (HashEntry *)PMC_data(SELF) + 1;
834 nextix = UVal_int(e->val);
836 SELF.set_pmc_keyed_int(nextix, value);
846 F<docs/pdds/pdd03_calling_conventions.pod>.
850 Initial version 2003.07.04 by leo
852 2003.11.06 boemmels renamed HASH_ENTRY to HashEntry
860 * c-file-style: "parrot"
862 * vim: expandtab shiftwidth=4: