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 real_exception(INTERP, NULL, E_IndexError,
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 real_exception(INTERP, NULL, E_IndexError,
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 real_exception(INTERP, NULL, E_TypeError,
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 real_exception(INTERP, NULL, E_IndexError,
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 PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
650 PMC_struct_val(iter) = key;
654 real_exception(INTERP, NULL, E_IndexError, _("Array: Unknown slice type"));
657 VTABLE PMC *get_iter() {
658 PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
659 PMC * const key = pmc_new(INTERP, enum_class_Key);
660 PMC_struct_val(iter) = key;
661 PObj_get_FLAGS(key) |= KEY_integer_FLAG;
662 PMC_int_val(key) = 0;
664 if (PMC_int_val(SELF) == 0)
665 PMC_int_val(key) = -1;
672 =item C<INTVAL exists_keyed_int(INTVAL key)>
674 =item C<INTVAL exists_keyed_int(PMC *key)>
676 Returns TRUE is the element at C<key> exists; otherwise returns false.
681 VTABLE INTVAL exists_keyed_int(INTVAL key) {
683 if (key < 0 || key >= PMC_int_val(SELF))
684 real_exception(INTERP, NULL, E_IndexError,
685 _("FixedPMCArray: index out of bounds!"));
687 data = (PMC**)PMC_data(SELF);
688 return !PMC_IS_NULL(data[key]);
691 VTABLE INTVAL exists_keyed(PMC *key) {
692 const INTVAL ix = key_integer(INTERP, key);
693 return SELF.exists_keyed_int(ix);
698 =item C<void splice(PMC *value, INTVAL offset, INTVAL count)>
700 Replaces C<count> elements starting at C<offset> with the elements in C<value>.
702 If C<count> is 0 then the elements in C<value> will be inserted after
705 This throws an exception if any of the spliced in values are out of the range
710 void splice(PMC *value, INTVAL offset, INTVAL count) {
711 if (count + offset > PMC_int_val(SELF))
712 real_exception(INTERP, NULL, E_IndexError,
713 _("FixedPMCArray: index out of bounds!"));
715 for (count--; count >= 0; --count) {
716 VTABLE_set_pmc_keyed_int(INTERP, SELF, offset + count, value);
723 =item C<void visit(visit_info *info)>
725 This is used by freeze/thaw to visit the contents of the array.
727 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
729 =item C<void freeze(visit_info *info)>
731 Used to archive the array.
733 =item C<void thaw(visit_info *info)>
735 Used to unarchive the array.
741 VTABLE void visit(visit_info *info) {
743 const INTVAL n = VTABLE_elements(INTERP, SELF);
744 PMC **pos = (PMC **)PMC_data(SELF);
746 for (i = 0; i < n; ++i, ++pos) {
747 info->thaw_ptr = pos;
748 (info->visit_pmc_now)(INTERP, *pos, info);
754 VTABLE void freeze(visit_info *info) {
755 IMAGE_IO * const io = info->image_io;
757 VTABLE_push_integer(INTERP, io, VTABLE_elements(INTERP, SELF));
760 VTABLE void thaw(visit_info *info) {
761 IMAGE_IO * const io = info->image_io;
763 if (info->extra_flags == EXTRA_IS_NULL)
764 SELF.set_integer_native(VTABLE_shift_integer(INTERP, io));
769 =item C<INTVAL defined_keyed_int(INTVAL key)>
771 Returns TRUE is the element at C<key> is defined; otherwise returns false.
777 VTABLE INTVAL defined_keyed_int(INTVAL key) {
778 PMC * const val = SELF.get_pmc_keyed_int(key);
780 if (PMC_IS_NULL(val))
783 return VTABLE_defined(INTERP, val);
794 F<docs/pdds/pdd17_basic_types.pod>.
802 * c-file-style: "parrot"
804 * vim: expandtab shiftwidth=4: