2 Copyright (C) 2001-2008, The Perl 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 #include "parrot/parrot.h"
29 pmclass FixedPMCArray need_ext provides array {
33 =item C<METHOD sort(PMC *cmp_func)>
35 Sort this array, optionally using the provided cmp_func
41 METHOD sort(PMC *cmp_func :optional) {
42 const UINTVAL n = (UINTVAL) PMC_int_val(SELF);
45 Parrot_quicksort(interp, PMC_data_typed(SELF, void **), n, cmp_func);
58 Initializes the array.
65 PMC_int_val(SELF) = 0;
66 PMC_data(SELF) = NULL;
67 PObj_active_destroy_SET(SELF);
68 PObj_data_is_PMC_array_SET(SELF);
73 =item C<void destroy()>
81 VTABLE void destroy() {
83 mem_sys_free(PMC_data(SELF));
84 PMC_data(SELF) = NULL;
86 PMC_int_val(SELF) = 0;
93 Creates and returns a copy of the array.
100 PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type);
101 const INTVAL size = PMC_int_val(SELF);
104 PMC_int_val(dest) = size;
105 PMC_data(dest) = mem_allocate_n_typed(size, PMC *);
106 mem_copy_n_typed(PMC_data(dest), PMC_data(SELF), size, PMC *);
107 PObj_data_is_PMC_array_SET(dest);
115 =item C<INTVAL get_bool()>
117 Returns whether the array has any elements (meaning been initialized, for a
123 VTABLE INTVAL get_bool() {
124 const INTVAL size = SELF.elements();
125 return (INTVAL)(size != 0);
130 =item C<INTVAL elements()>
136 VTABLE INTVAL elements() {
137 return PMC_int_val(SELF);
142 =item C<INTVAL get_integer()>
144 Returns the number of elements in the array.
150 VTABLE INTVAL get_integer() {
151 return SELF.elements();
156 =item C<FLOATVAL get_number()>
158 Returns the number of elements in the array.
164 VTABLE FLOATVAL get_number() {
165 const INTVAL e = SELF.elements();
171 =item C<STRING *get_string()>
173 Returns the number of elements in the array as a Parrot string. (??? -leo)
175 =item C<STRING *get_repr()>
177 Returns a string representation of the array contents.
178 RT#46673 implement freeze/thaw and use that instead.
184 VTABLE STRING *get_string() {
185 return string_from_int(INTERP, SELF.elements());
188 VTABLE STRING *get_repr() {
189 STRING *res = CONST_STRING(INTERP, "(");
190 const INTVAL n = VTABLE_elements(INTERP, SELF);
193 for (i = 0; i < n; ++i) {
194 PMC * const val = SELF.get_pmc_keyed_int(i);
196 res = string_append(INTERP, res, VTABLE_get_repr(INTERP, val));
198 res = string_append(INTERP, res, CONST_STRING(INTERP, ","));
200 res = string_append(INTERP, res, CONST_STRING(INTERP, ", "));
203 res = string_append(INTERP, res, CONST_STRING(INTERP, ")"));
210 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
212 Returns the integer value of the element at index C<key>.
218 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
219 PMC * const tempPMC = SELF.get_pmc_keyed_int(key);
220 if (PMC_IS_NULL(tempPMC))
222 return VTABLE_get_integer(INTERP, tempPMC);
227 =item C<INTVAL get_integer_keyed(PMC *key)>
229 Returns the integer value of the element at index C<*key>.
235 VTABLE INTVAL get_integer_keyed(PMC *key) {
236 PMC * const tempPMC = SELF.get_pmc_keyed(key);
237 return VTABLE_get_integer(INTERP, tempPMC);
242 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
244 Returns the floating-point value of the element at index C<key>.
250 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
251 PMC * const tempPMC = SELF.get_pmc_keyed_int(key);
252 return VTABLE_get_number(INTERP, tempPMC);
257 =item C<FLOATVAL get_number_keyed(PMC *key)>
259 Returns the floating-point value of the element at index C<*key>.
265 VTABLE FLOATVAL get_number_keyed(PMC *key) {
266 PMC * const tempPMC = SELF.get_pmc_keyed(key);
267 return VTABLE_get_number(INTERP, tempPMC);
272 =item C<STRING *get_string_keyed_int(INTVAL key)>
274 Returns the Parrot string value of the element at index C<key>.
280 VTABLE STRING *get_string_keyed_int(INTVAL key) {
281 PMC * const tempPMC = SELF.get_pmc_keyed_int(key);
283 if (PMC_IS_NULL(tempPMC))
284 return CONST_STRING(interp, "");
286 return VTABLE_get_string(INTERP, tempPMC);
291 =item C<STRING *get_string_keyed(PMC *key)>
293 Returns the Parrot string value of the element at index C<*key>.
299 VTABLE STRING *get_string_keyed(PMC *key) {
300 PMC * const tempPMC = SELF.get_pmc_keyed(key);
301 return VTABLE_get_string(INTERP, tempPMC);
306 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
308 Returns the PMC value of the element at index C<key>.
314 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
317 if (key < 0 || key >= PMC_int_val(SELF))
318 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
319 _("FixedPMCArray: index out of bounds!"));
321 data = (PMC **)PMC_data(SELF);
327 =item C<PMC *get_pmc_keyed(PMC *key)>
329 Returns the PMC value of the element at index C<*key>.
335 VTABLE PMC *get_pmc_keyed(PMC *key) {
336 const INTVAL k = key_integer(INTERP, key);
337 PMC * const nextkey = key_next(INTERP, key);
341 return SELF.get_pmc_keyed_int(k);
343 box = SELF.get_pmc_keyed_int(k);
346 box = pmc_new(INTERP, enum_class_Undef);
348 return VTABLE_get_pmc_keyed(INTERP, box, nextkey);
353 =item C<void set_integer_native(INTVAL size)>
355 Sizes the array to C<size> elements. Can't be used to resize an
362 VTABLE void set_integer_native(INTVAL size) {
366 if (PMC_int_val(SELF) && size)
367 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
368 _("FixedPMCArray: Can't resize!"));
372 PMC_int_val(SELF) = size;
373 data = mem_allocate_n_zeroed_typed(size, PMC *);
375 for (i = 0; i < size; i++)
378 PMC_data(SELF) = data;
381 VTABLE void set_pmc(PMC *value) {
388 if (!VTABLE_does(interp, value, CONST_STRING(interp, "array")))
389 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
390 _("Can't set self from this type"));
393 mem_sys_free(PMC_data(SELF));
395 /* If the value is a FixedPMCArray or a ResizablePMCArray itself, we
396 * can just copy the data directly. Otherwise, must use interface. */
397 is_set_same = value->vtable->base_type == enum_class_FixedPMCArray ||
398 value->vtable->base_type == enum_class_ResizablePMCArray;
400 size = PMC_int_val(SELF) = is_set_same ?
402 VTABLE_elements(INTERP, value);
403 PMC_data(SELF) = mem_allocate_n_zeroed_typed(size, PMC *);
406 mem_sys_memcopy(PMC_data(SELF), PMC_data(value), size * sizeof (PMC *));
410 for (i = 0; i < size; i++)
411 ((PMC**)PMC_data(SELF))[i] = VTABLE_get_pmc_keyed_int(INTERP, value, i);
414 PMC_int_val2(SELF) = size;
415 PObj_data_is_PMC_array_SET(SELF);
419 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
421 Sets the integer value of the element at index C<key> to C<value>.
427 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
428 PMC * const val = pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
429 enum_class_Integer));
431 VTABLE_set_integer_native(INTERP, val, value);
432 SELF.set_pmc_keyed_int(key, val);
437 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
439 Sets the integer value of the element at index C<key> to C<value>.
445 VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
446 PMC * const val = pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
447 enum_class_Integer));
449 VTABLE_set_integer_native(INTERP, val, value);
451 /* Let set_pmc_keyed worry about multi keys */
452 SELF.set_pmc_keyed(key, val);
457 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
459 Sets the floating-point value of the element at index C<key> to
466 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
467 PMC * const val = pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
470 VTABLE_set_number_native(INTERP, val, value);
471 SELF.set_pmc_keyed_int(key, val);
476 =item C<void set_number_keyed(PMC *key, FLOATVAL value)>
478 Sets the floating-point value of the element at index C<key> to
485 VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
486 const INTVAL k = key_integer(INTERP, key);
487 PMC * const nextkey = key_next(INTERP, key);
489 if (nextkey == NULL) {
490 SELF.set_number_keyed_int(k, value);
493 PMC *box = SELF.get_pmc_keyed_int(k);
495 /* RT#46675: autovivify an Array and insert it in SELF */
497 box = pmc_new(INTERP, SELF.type());
499 VTABLE_set_number_keyed(INTERP, box, nextkey, value);
505 =item C<void set_string_keyed_int(INTVAL key, STRING *value)>
507 Sets the Parrot string value of the element at index C<key> to C<value>.
513 VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
514 PMC * const val = pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
517 VTABLE_set_string_native(INTERP, val, value);
518 SELF.set_pmc_keyed_int(key, val);
523 =item C<void set_string_keyed(PMC *key, STRING *value)>
525 Sets the string value of the element at index C<key> to
532 VTABLE void set_string_keyed(PMC *key, STRING *value) {
533 PMC * const val = pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
536 VTABLE_set_string_native(INTERP, val, value);
538 /* Let set_pmc_keyed worry about multi keys */
539 SELF.set_pmc_keyed(key, val);
544 =item C<void set_pmc_keyed_int(INTVAL key, PMC *src)>
546 Sets the PMC value of the element at index C<key> to C<*src>.
552 VTABLE void set_pmc_keyed_int(INTVAL key, PMC *src) {
555 if (key < 0 || key >= PMC_int_val(SELF))
556 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
557 _("FixedPMCArray: index out of bounds!"));
559 data = (PMC**)PMC_data(SELF);
560 GC_WRITE_BARRIER(INTERP, SELF, data[key], src);
566 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
568 Sets the PMC at index C<key> to C<value>.
574 VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
575 const INTVAL k = key_integer(INTERP, key);
576 PMC *nextkey = key_next(INTERP, key);
579 SELF.set_pmc_keyed_int(k, value);
582 PMC *box = SELF.get_pmc_keyed_int(k);
584 /* RT#46675: autovivify an Array and insert it in SELF */
586 box = pmc_new(INTERP, SELF.type());
588 VTABLE_set_pmc_keyed(INTERP, box, nextkey, value);
594 =item C<INTVAL is_equal(PMC *value)>
596 The C<==> operation. Compares two array to hold equal elements.
602 VTABLE INTVAL is_equal(PMC *value) {
605 if (value->vtable->base_type != enum_class_FixedPMCArray)
610 if (VTABLE_elements(INTERP, value) != n)
613 for (j = 0; j < n; ++j) {
614 PMC * const item1 = SELF.get_pmc_keyed_int(j);
615 PMC * const item2 = VTABLE_get_pmc_keyed_int(INTERP, value, j);
620 if (item1->vtable->base_type == enum_class_Null
621 || item2->vtable->base_type == enum_class_Null)
624 if (!mmd_dispatch_i_pp(INTERP, item1, item2, MMD_EQ))
633 =item C<PMC *slice(PMC *key, INTVAL f)>
635 Return a new iterator for the slice PMC C<key> if f == 0.
637 Return a new pythonic array slice if f == 1.
639 =item C<PMC *get_iter()>
641 Return a new iterator for SELF.
647 VTABLE PMC *slice(PMC *key, INTVAL f) {
649 STRING *name = CONST_STRING(interp, "set_key");
650 PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
651 Parrot_PCCINVOKE(interp, iter, name, "P->", key);
655 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
656 _("Array: Unknown slice type"));
659 VTABLE PMC *get_iter() {
660 STRING *name = CONST_STRING(interp, "set_key");
661 PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
662 PMC * const key = pmc_new(INTERP, enum_class_Key);
664 Parrot_PCCINVOKE(interp, iter, name, "P->", key);
665 PObj_get_FLAGS(key) |= KEY_integer_FLAG;
666 PMC_int_val(key) = 0;
668 if (PMC_int_val(SELF) == 0)
669 PMC_int_val(key) = -1;
676 =item C<INTVAL exists_keyed_int(INTVAL key)>
678 =item C<INTVAL exists_keyed_int(PMC *key)>
680 Returns TRUE is the element at C<key> exists; otherwise returns false.
685 VTABLE INTVAL exists_keyed_int(INTVAL key) {
687 if (key < 0 || key >= PMC_int_val(SELF))
688 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
689 _("FixedPMCArray: index out of bounds!"));
691 data = (PMC**)PMC_data(SELF);
692 return !PMC_IS_NULL(data[key]);
695 VTABLE INTVAL exists_keyed(PMC *key) {
696 const INTVAL ix = key_integer(INTERP, key);
697 return SELF.exists_keyed_int(ix);
702 =item C<void splice(PMC *value, INTVAL offset, INTVAL count)>
704 Replaces C<count> elements starting at C<offset> with the elements in C<value>.
706 If C<count> is 0 then the elements in C<value> will be inserted after
709 This throws an exception if any of the spliced in values are out of the range
714 void splice(PMC *value, INTVAL offset, INTVAL count) {
715 if (count + offset > PMC_int_val(SELF))
716 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
717 _("FixedPMCArray: index out of bounds!"));
719 for (count--; count >= 0; --count) {
720 VTABLE_set_pmc_keyed_int(INTERP, SELF, offset + count, value);
727 =item C<void visit(visit_info *info)>
729 This is used by freeze/thaw to visit the contents of the array.
731 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
733 =item C<void freeze(visit_info *info)>
735 Used to archive the array.
737 =item C<void thaw(visit_info *info)>
739 Used to unarchive the array.
745 VTABLE void visit(visit_info *info) {
747 const INTVAL n = VTABLE_elements(INTERP, SELF);
748 PMC **pos = (PMC **)PMC_data(SELF);
750 for (i = 0; i < n; ++i, ++pos) {
751 info->thaw_ptr = pos;
752 (info->visit_pmc_now)(INTERP, *pos, info);
758 VTABLE void freeze(visit_info *info) {
759 IMAGE_IO * const io = info->image_io;
761 VTABLE_push_integer(INTERP, io, VTABLE_elements(INTERP, SELF));
764 VTABLE void thaw(visit_info *info) {
765 IMAGE_IO * const io = info->image_io;
767 if (info->extra_flags == EXTRA_IS_NULL)
768 SELF.set_integer_native(VTABLE_shift_integer(INTERP, io));
773 =item C<INTVAL defined_keyed_int(INTVAL key)>
775 Returns TRUE is the element at C<key> is defined; otherwise returns false.
781 VTABLE INTVAL defined_keyed_int(INTVAL key) {
782 PMC * const val = SELF.get_pmc_keyed_int(key);
784 if (PMC_IS_NULL(val))
787 return VTABLE_defined(INTERP, val);
798 F<docs/pdds/pdd17_basic_types.pod>.
806 * c-file-style: "parrot"
808 * vim: expandtab shiftwidth=4: