2 Copyright (C) 2001-2010, Parrot Foundation.
7 src/pmc/fixedpmcarray.pmc - fixed size array for PMCs only
11 This class, FixedPMCArray, implements an array of fixed size which stores PMCs.
12 It puts things into Integer, Float, or String PMCs as appropriate
16 The flag C<PObj_private0_FLAG> is used in the C<NameSpace> PMC and should
17 never be set for user arrays.
27 #define PMC_size(x) ((Parrot_FixedPMCArray_attributes *)PMC_data(x))->size
28 #define PMC_array(x) ((Parrot_FixedPMCArray_attributes *)PMC_data(x))->pmc_array
30 pmclass FixedPMCArray auto_attrs provides array {
31 ATTR INTVAL size; /* number of elements in the array */
32 ATTR PMC **pmc_array; /* pointer to PMC array */
36 =item C<METHOD sort(PMC *cmp_func)>
38 Sort this array, optionally using the provided cmp_func
44 METHOD sort(PMC *cmp_func :optional) {
45 const INTVAL n = SELF.elements();
48 /* XXX Workaround for TT #218 */
49 if (PObj_is_object_TEST(SELF)) {
50 PMC *parent = SELF.get_attr_str(CONST_STRING(interp, "proxy"));
51 Parrot_pcc_invoke_method_from_c_args(interp, parent, CONST_STRING(interp, "sort"), "P->", cmp_func);
54 Parrot_quicksort(interp, (void **)PMC_array(SELF), n, cmp_func);
69 Initializes the array.
76 PObj_custom_mark_destroy_SETALL(SELF);
81 =item C<void init_int(INTVAL size)>
83 Initializes the array.
89 VTABLE void init_int(INTVAL size) {
94 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
95 _("FixedPMCArray: Cannot set array size to a negative number (%d)"),size);
97 SET_ATTR_size(INTERP, SELF, size);
98 data = mem_gc_allocate_n_typed(INTERP, size, PMC *);
100 for (i = 0; i < size; i++)
103 PObj_custom_destroy_SET(SELF);
108 =item C<void destroy()>
116 VTABLE void destroy() {
118 mem_gc_free(INTERP, PMC_array(SELF));
123 =item C<PMC *clone()>
125 Creates and returns a copy of the array.
131 VTABLE PMC *clone() {
132 PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
133 const INTVAL size = PMC_size(SELF);
136 PMC_size(dest) = size;
137 PMC_array(dest) = mem_gc_allocate_n_zeroed_typed(INTERP, size, PMC *);
138 mem_copy_n_typed(PMC_array(dest), PMC_array(SELF), size, PMC *);
139 PObj_custom_mark_destroy_SETALL(dest);
147 =item C<INTVAL get_bool()>
149 Returns whether the array has any elements (meaning been initialized, for a
155 VTABLE INTVAL get_bool() {
156 const INTVAL size = SELF.elements();
157 return (INTVAL)(size != 0);
162 =item C<INTVAL elements()>
168 VTABLE INTVAL elements() {
169 return PMC_size(SELF);
174 =item C<INTVAL get_integer()>
176 Returns the number of elements in the array.
182 VTABLE INTVAL get_integer() {
183 return SELF.elements();
188 =item C<FLOATVAL get_number()>
190 Returns the number of elements in the array.
196 VTABLE FLOATVAL get_number() {
197 const INTVAL e = SELF.elements();
203 =item C<STRING *get_string()>
205 Returns the number of elements in the array as a Parrot string. (??? -leo)
207 =item C<STRING *get_repr()>
209 Returns a string representation of the array contents.
210 TT #1229: implement freeze/thaw and use that instead.
216 VTABLE STRING *get_string() {
217 return Parrot_str_from_int(INTERP, SELF.elements());
220 VTABLE STRING *get_repr() {
221 STRING *res = CONST_STRING(INTERP, "(");
222 const INTVAL n = VTABLE_elements(INTERP, SELF);
225 for (i = 0; i < n; ++i) {
226 PMC * const val = SELF.get_pmc_keyed_int(i);
228 res = Parrot_str_append(INTERP, res, CONST_STRING(INTERP, ", "));
230 res = Parrot_str_append(INTERP, res, VTABLE_get_repr(INTERP, val));
233 res = Parrot_str_append(INTERP, res, CONST_STRING(INTERP, ")"));
240 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
242 Returns the integer value of the element at index C<key>.
248 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
249 PMC * const tempPMC = SELF.get_pmc_keyed_int(key);
250 if (PMC_IS_NULL(tempPMC))
252 return VTABLE_get_integer(INTERP, tempPMC);
257 =item C<INTVAL get_integer_keyed(PMC *key)>
259 Returns the integer value of the element at index C<*key>.
265 VTABLE INTVAL get_integer_keyed(PMC *key) {
266 PMC * const tempPMC = SELF.get_pmc_keyed(key);
267 return VTABLE_get_integer(INTERP, tempPMC);
272 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
274 Returns the floating-point value of the element at index C<key>.
280 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
281 PMC * const tempPMC = SELF.get_pmc_keyed_int(key);
282 return VTABLE_get_number(INTERP, tempPMC);
287 =item C<FLOATVAL get_number_keyed(PMC *key)>
289 Returns the floating-point value of the element at index C<*key>.
295 VTABLE FLOATVAL get_number_keyed(PMC *key) {
296 PMC * const tempPMC = SELF.get_pmc_keyed(key);
297 return VTABLE_get_number(INTERP, tempPMC);
302 =item C<STRING *get_string_keyed_int(INTVAL key)>
304 Returns the Parrot string value of the element at index C<key>.
310 VTABLE STRING *get_string_keyed_int(INTVAL key) {
311 PMC * const retval = SELF.get_pmc_keyed_int(key);
313 if (PMC_IS_NULL(retval))
314 return string_from_literal(interp, "");
316 return VTABLE_get_string(INTERP, retval);
321 =item C<STRING *get_string_keyed(PMC *key)>
323 Returns the Parrot string value of the element at index C<*key>.
329 VTABLE STRING *get_string_keyed(PMC *key) {
330 PMC * const tempPMC = SELF.get_pmc_keyed(key);
331 return VTABLE_get_string(INTERP, tempPMC);
336 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
338 Returns the PMC value of the element at index C<key>.
344 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
347 if (key < 0 || key >= PMC_size(SELF))
348 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
349 _("FixedPMCArray: index out of bounds!"));
351 data = PMC_array(SELF);
357 =item C<PMC *get_pmc_keyed(PMC *key)>
359 Returns the PMC value of the element at index C<*key>.
365 VTABLE PMC *get_pmc_keyed(PMC *key) {
366 const INTVAL k = VTABLE_get_integer(INTERP, key);
367 PMC * const nextkey = key_next(INTERP, key);
371 return SELF.get_pmc_keyed_int(k);
373 box = SELF.get_pmc_keyed_int(k);
376 box = Parrot_pmc_new(INTERP, enum_class_Undef);
378 return VTABLE_get_pmc_keyed(INTERP, box, nextkey);
383 =item C<void set_integer_native(INTVAL size)>
385 Sizes the array to C<size> elements. Can't be used to resize an
392 VTABLE void set_integer_native(INTVAL size) {
396 if (PMC_size(SELF) && size)
397 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
398 _("FixedPMCArray: Can't resize!"));
403 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
404 _("FixedPMCArray: Cannot set array size to a negative number"));
406 PMC_size(SELF) = size;
407 data = mem_gc_allocate_n_zeroed_typed(INTERP, size, PMC *);
409 for (i = 0; i < size; i++)
412 PMC_array(SELF) = data;
415 VTABLE void set_pmc(PMC *value) {
422 if (!VTABLE_does(interp, value, CONST_STRING(interp, "array")))
423 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
424 _("Can't set self from this type"));
427 mem_gc_free(INTERP, PMC_array(SELF));
429 size = PMC_size(SELF) = VTABLE_elements(INTERP, value);
430 PMC_array(SELF) = mem_gc_allocate_n_zeroed_typed(INTERP, size, PMC *);
432 for (i = 0; i < size; i++)
433 (PMC_array(SELF))[i] = VTABLE_get_pmc_keyed_int(INTERP, value, i);
435 PObj_custom_mark_destroy_SETALL(SELF);
439 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
441 Sets the integer value of the element at index C<key> to C<value>.
447 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
448 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
449 enum_class_Integer));
451 VTABLE_set_integer_native(INTERP, val, value);
452 SELF.set_pmc_keyed_int(key, val);
457 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
459 Sets the integer value of the element at index C<key> to C<value>.
465 VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
466 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
467 enum_class_Integer));
469 VTABLE_set_integer_native(INTERP, val, value);
471 /* Let set_pmc_keyed worry about multi keys */
472 SELF.set_pmc_keyed(key, val);
477 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
479 Sets the floating-point value of the element at index C<key> to
486 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
487 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
490 VTABLE_set_number_native(INTERP, val, value);
491 SELF.set_pmc_keyed_int(key, val);
496 =item C<void set_number_keyed(PMC *key, FLOATVAL value)>
498 Sets the floating-point value of the element at index C<key> to
505 VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
506 const INTVAL k = VTABLE_get_integer(INTERP, key);
507 PMC * const nextkey = key_next(INTERP, key);
509 if (nextkey == NULL) {
510 SELF.set_number_keyed_int(k, value);
513 PMC *box = SELF.get_pmc_keyed_int(k);
515 /* TT #1295: autovivify an Array and insert it in SELF */
517 box = Parrot_pmc_new(INTERP, SELF.type());
519 VTABLE_set_number_keyed(INTERP, box, nextkey, value);
525 =item C<void set_string_keyed_int(INTVAL key, STRING *value)>
527 Sets the Parrot string value of the element at index C<key> to C<value>.
533 VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
534 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
537 VTABLE_set_string_native(INTERP, val, value);
538 SELF.set_pmc_keyed_int(key, val);
543 =item C<void set_string_keyed(PMC *key, STRING *value)>
545 Sets the string value of the element at index C<key> to
552 VTABLE void set_string_keyed(PMC *key, STRING *value) {
553 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
556 VTABLE_set_string_native(INTERP, val, value);
558 /* Let set_pmc_keyed worry about multi keys */
559 SELF.set_pmc_keyed(key, val);
564 =item C<void set_pmc_keyed_int(INTVAL key, PMC *src)>
566 Sets the PMC value of the element at index C<key> to C<*src>.
572 VTABLE void set_pmc_keyed_int(INTVAL key, PMC *src) {
575 if (key < 0 || key >= PMC_size(SELF))
576 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
577 _("FixedPMCArray: index out of bounds!"));
579 data = PMC_array(SELF);
585 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
587 Sets the PMC at index C<key> to C<value>.
593 VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
594 const INTVAL k = VTABLE_get_integer(INTERP, key);
595 PMC *nextkey = key_next(INTERP, key);
598 SELF.set_pmc_keyed_int(k, value);
601 PMC *box = SELF.get_pmc_keyed_int(k);
603 /* TT #1295: autovivify an Array and insert it in SELF */
605 box = Parrot_pmc_new(INTERP, SELF.type());
607 VTABLE_set_pmc_keyed(INTERP, box, nextkey, value);
613 =item C<INTVAL is_equal(PMC *value)>
615 The C<==> operation. Compares two array to hold equal elements.
621 VTABLE INTVAL is_equal(PMC *value) {
624 if (value->vtable->base_type != SELF->vtable->base_type)
629 if (VTABLE_elements(INTERP, value) != n)
632 for (j = 0; j < n; ++j) {
633 PMC * const item1 = SELF.get_pmc_keyed_int(j);
634 PMC * const item2 = VTABLE_get_pmc_keyed_int(INTERP, value, j);
639 if (item1->vtable->base_type == enum_class_Null
640 || item2->vtable->base_type == enum_class_Null)
643 if (!VTABLE_is_equal(interp, item1, item2))
653 =item C<PMC *get_iter()>
655 Return a new iterator for SELF.
661 VTABLE PMC *get_iter() {
662 return Parrot_pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
667 =item C<INTVAL exists_keyed_int(INTVAL key)>
669 =item C<INTVAL exists_keyed_int(PMC *key)>
671 Returns TRUE is the element at C<key> exists; otherwise returns false.
676 VTABLE INTVAL exists_keyed_int(INTVAL key) {
678 if (key < 0 || key >= PMC_size(SELF))
679 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
680 _("FixedPMCArray: index out of bounds!"));
682 data = PMC_array(SELF);
683 return !PMC_IS_NULL(data[key]);
686 VTABLE INTVAL exists_keyed(PMC *key) {
687 const INTVAL ix = VTABLE_get_integer(INTERP, key);
688 return SELF.exists_keyed_int(ix);
693 =item C<void splice(PMC *value, INTVAL offset, INTVAL count)>
695 Replaces C<count> elements starting at C<offset> with the elements in C<value>.
697 If C<count> is 0 then the elements in C<value> will be inserted after
700 This throws an exception if any of the spliced in values are out of the range
707 VTABLE void splice(PMC *value, INTVAL offset, INTVAL count) {
708 if (count + offset > PMC_size(SELF))
709 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
710 _("FixedPMCArray: index out of bounds!"));
712 for (count--; count >= 0; --count) {
713 VTABLE_set_pmc_keyed_int(INTERP, SELF, offset + count, value);
720 =item C<void visit(PMC *info)>
722 This is used by freeze/thaw to visit the contents of the array.
724 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
726 =item C<void freeze(PMC *info)>
728 Used to archive the array.
730 =item C<void thaw(PMC *info)>
732 Used to unarchive the array.
738 VTABLE void visit(PMC *info) {
740 const INTVAL n = VTABLE_elements(INTERP, SELF);
741 PMC **pos = PMC_array(SELF);
743 for (i = 0; i < n; ++i, ++pos) {
744 VISIT_PMC(INTERP, info, *pos);
750 VTABLE void freeze(PMC *info) {
752 VTABLE_push_integer(INTERP, info, VTABLE_elements(INTERP, SELF));
755 VTABLE void thaw(PMC *info) {
757 SELF.set_integer_native(VTABLE_shift_integer(INTERP, info));
762 =item C<INTVAL defined_keyed_int(INTVAL key)>
764 Returns TRUE is the element at C<key> is defined; otherwise returns false.
770 VTABLE INTVAL defined_keyed_int(INTVAL key) {
771 PMC * const val = SELF.get_pmc_keyed_int(key);
773 if (PMC_IS_NULL(val))
776 return VTABLE_defined(INTERP, val);
781 =item C<void mark(void)>
790 PMC ** const data = PMC_array(SELF);
796 for (i = PMC_size(SELF) - 1; i >= 0; --i)
797 Parrot_gc_mark_PMC_alive(interp, data[i]);
810 F<docs/pdds/pdd17_basic_types.pod>.
818 * c-file-style: "parrot"
820 * vim: expandtab shiftwidth=4: