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 /* HEADERIZER HFILE: none */
31 /* HEADERIZER BEGIN: static */
32 /* HEADERIZER END: static */
34 pmclass FixedPMCArray auto_attrs provides array {
35 ATTR INTVAL size; /* number of elements in the array */
36 ATTR PMC **pmc_array; /* pointer to PMC array */
40 =item C<METHOD sort(PMC *cmp_func)>
42 Sort this array, optionally using the provided cmp_func
48 METHOD sort(PMC *cmp_func :optional) {
49 const INTVAL n = SELF.elements();
52 /* XXX Workaround for TT #218 */
53 if (PObj_is_object_TEST(SELF)) {
54 PMC *parent = SELF.get_attr_str(CONST_STRING(INTERP, "proxy"));
55 Parrot_pcc_invoke_method_from_c_args(INTERP, parent, CONST_STRING(INTERP, "sort"), "P->", cmp_func);
58 Parrot_quicksort(INTERP, (void **)PMC_array(SELF), n, cmp_func);
71 =item C<void init_int(INTVAL size)>
73 Initializes the array.
79 VTABLE void init_int(INTVAL size) {
81 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
82 _("FixedPMCArray: Cannot set array size to a negative number (%d)"), size);
84 SELF.set_integer_native(size);
89 =item C<void destroy()>
97 VTABLE void destroy() {
99 mem_gc_free(INTERP, PMC_array(SELF));
104 =item C<PMC *clone()>
106 Creates and returns a copy of the array.
112 VTABLE PMC *clone() {
113 PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
114 const INTVAL size = PMC_size(SELF);
117 PMC_size(dest) = size;
118 PMC_array(dest) = mem_gc_allocate_n_typed(INTERP, size, PMC *);
119 mem_copy_n_typed(PMC_array(dest), PMC_array(SELF), size, PMC *);
120 PObj_custom_mark_destroy_SETALL(dest);
128 =item C<INTVAL get_bool()>
130 Returns whether the array has any elements (meaning been initialized, for a
136 VTABLE INTVAL get_bool() {
137 const INTVAL size = SELF.elements();
138 return (INTVAL)(size != 0);
143 =item C<INTVAL elements()>
149 VTABLE INTVAL elements() {
150 return PMC_size(SELF);
155 =item C<INTVAL get_integer()>
157 Returns the number of elements in the array.
163 VTABLE INTVAL get_integer() {
164 return SELF.elements();
169 =item C<FLOATVAL get_number()>
171 Returns the number of elements in the array.
177 VTABLE FLOATVAL get_number() {
178 const INTVAL e = SELF.elements();
184 =item C<STRING *get_string()>
186 Returns the number of elements in the array as a Parrot string. (??? -leo)
188 =item C<STRING *get_repr()>
190 Returns a string representation of the array contents.
191 TT #1229: implement freeze/thaw and use that instead.
197 VTABLE STRING *get_string() {
198 return Parrot_str_from_int(INTERP, SELF.elements());
201 VTABLE STRING *get_repr() {
202 STRING *res = CONST_STRING(INTERP, "(");
203 const INTVAL n = VTABLE_elements(INTERP, SELF);
206 for (i = 0; i < n; ++i) {
207 PMC * const val = SELF.get_pmc_keyed_int(i);
209 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, ", "));
211 res = Parrot_str_concat(INTERP, res, VTABLE_get_repr(INTERP, val));
214 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, ")"));
221 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
223 Returns the integer value of the element at index C<key>.
229 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
230 PMC * const tempPMC = SELF.get_pmc_keyed_int(key);
231 if (PMC_IS_NULL(tempPMC))
233 return VTABLE_get_integer(INTERP, tempPMC);
238 =item C<INTVAL get_integer_keyed(PMC *key)>
240 Returns the integer value of the element at index C<*key>.
246 VTABLE INTVAL get_integer_keyed(PMC *key) {
247 PMC * const tempPMC = SELF.get_pmc_keyed(key);
248 return VTABLE_get_integer(INTERP, tempPMC);
253 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
255 Returns the floating-point value of the element at index C<key>.
261 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
262 PMC * const tempPMC = SELF.get_pmc_keyed_int(key);
263 return VTABLE_get_number(INTERP, tempPMC);
268 =item C<FLOATVAL get_number_keyed(PMC *key)>
270 Returns the floating-point value of the element at index C<*key>.
276 VTABLE FLOATVAL get_number_keyed(PMC *key) {
277 PMC * const tempPMC = SELF.get_pmc_keyed(key);
278 return VTABLE_get_number(INTERP, tempPMC);
283 =item C<STRING *get_string_keyed_int(INTVAL key)>
285 Returns the Parrot string value of the element at index C<key>.
291 VTABLE STRING *get_string_keyed_int(INTVAL key) {
292 PMC * const retval = SELF.get_pmc_keyed_int(key);
294 if (PMC_IS_NULL(retval))
295 return CONST_STRING(INTERP, "");
297 return VTABLE_get_string(INTERP, retval);
302 =item C<STRING *get_string_keyed(PMC *key)>
304 Returns the Parrot string value of the element at index C<*key>.
310 VTABLE STRING *get_string_keyed(PMC *key) {
311 PMC * const tempPMC = SELF.get_pmc_keyed(key);
312 return VTABLE_get_string(INTERP, tempPMC);
317 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
319 Returns the PMC value of the element at index C<key>.
325 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
328 if (key < 0 || key >= PMC_size(SELF))
329 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
330 _("FixedPMCArray: index out of bounds!"));
332 data = PMC_array(SELF);
338 =item C<PMC *get_pmc_keyed(PMC *key)>
340 Returns the PMC value of the element at index C<*key>.
346 VTABLE PMC *get_pmc_keyed(PMC *key) {
347 const INTVAL k = VTABLE_get_integer(INTERP, key);
348 PMC * const nextkey = key_next(INTERP, key);
352 return SELF.get_pmc_keyed_int(k);
354 box = SELF.get_pmc_keyed_int(k);
357 box = Parrot_pmc_new(INTERP, enum_class_Undef);
359 return VTABLE_get_pmc_keyed(INTERP, box, nextkey);
364 =item C<void set_integer_native(INTVAL size)>
366 Sizes the array to C<size> elements. Can't be used to resize an
373 VTABLE void set_integer_native(INTVAL size) {
377 if (PMC_size(SELF) && size)
378 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
379 _("FixedPMCArray: Can't resize!"));
384 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
385 _("FixedPMCArray: Cannot set array size to a negative number"));
387 PMC_size(SELF) = size;
388 data = mem_gc_allocate_n_typed(INTERP, size, PMC *);
390 for (i = 0; i < size; ++i)
393 PObj_custom_mark_destroy_SETALL(SELF);
394 PMC_array(SELF) = data;
397 VTABLE void set_pmc(PMC *value) {
404 if (!VTABLE_does(INTERP, value, CONST_STRING(INTERP, "array")))
405 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
406 _("Can't set self from this type"));
409 mem_gc_free(INTERP, PMC_array(SELF));
411 size = PMC_size(SELF) = VTABLE_elements(INTERP, value);
412 PMC_array(SELF) = mem_gc_allocate_n_typed(INTERP, size, PMC *);
414 for (i = 0; i < size; ++i)
415 (PMC_array(SELF))[i] = VTABLE_get_pmc_keyed_int(INTERP, value, i);
417 PObj_custom_mark_destroy_SETALL(SELF);
421 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
423 Sets the integer value of the element at index C<key> to C<value>.
429 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
430 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
431 enum_class_Integer));
433 VTABLE_set_integer_native(INTERP, val, value);
434 SELF.set_pmc_keyed_int(key, val);
439 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
441 Sets the integer value of the element at index C<key> to C<value>.
447 VTABLE void set_integer_keyed(PMC *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);
453 /* Let set_pmc_keyed worry about multi keys */
454 SELF.set_pmc_keyed(key, val);
459 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
461 Sets the floating-point value of the element at index C<key> to
468 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
469 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
472 VTABLE_set_number_native(INTERP, val, value);
473 SELF.set_pmc_keyed_int(key, val);
478 =item C<void set_number_keyed(PMC *key, FLOATVAL value)>
480 Sets the floating-point value of the element at index C<key> to
487 VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
488 const INTVAL k = VTABLE_get_integer(INTERP, key);
489 PMC * const nextkey = key_next(INTERP, key);
491 if (nextkey == NULL) {
492 SELF.set_number_keyed_int(k, value);
495 PMC *box = SELF.get_pmc_keyed_int(k);
497 /* TT #1295: autovivify an Array and insert it in SELF */
499 box = Parrot_pmc_new(INTERP, SELF.type());
501 VTABLE_set_number_keyed(INTERP, box, nextkey, value);
507 =item C<void set_string_keyed_int(INTVAL key, STRING *value)>
509 Sets the Parrot string value of the element at index C<key> to C<value>.
515 VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
516 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
519 VTABLE_set_string_native(INTERP, val, value);
520 SELF.set_pmc_keyed_int(key, val);
525 =item C<void set_string_keyed(PMC *key, STRING *value)>
527 Sets the string value of the element at index C<key> to
534 VTABLE void set_string_keyed(PMC *key, STRING *value) {
535 PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
538 VTABLE_set_string_native(INTERP, val, value);
540 /* Let set_pmc_keyed worry about multi keys */
541 SELF.set_pmc_keyed(key, val);
546 =item C<void set_pmc_keyed_int(INTVAL key, PMC *src)>
548 Sets the PMC value of the element at index C<key> to C<*src>.
554 VTABLE void set_pmc_keyed_int(INTVAL key, PMC *src) {
557 if (key < 0 || key >= PMC_size(SELF))
558 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
559 _("FixedPMCArray: index out of bounds!"));
561 data = PMC_array(SELF);
567 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
569 Sets the PMC at index C<key> to C<value>.
575 VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
576 const INTVAL k = VTABLE_get_integer(INTERP, key);
577 PMC *nextkey = key_next(INTERP, key);
580 SELF.set_pmc_keyed_int(k, value);
583 PMC *box = SELF.get_pmc_keyed_int(k);
585 /* TT #1295: autovivify an Array and insert it in SELF */
587 box = Parrot_pmc_new(INTERP, SELF.type());
589 VTABLE_set_pmc_keyed(INTERP, box, nextkey, value);
595 =item C<INTVAL is_equal(PMC *value)>
597 The C<==> operation. Compares two array to hold equal elements.
603 VTABLE INTVAL is_equal(PMC *value) {
606 if (value->vtable->base_type != SELF->vtable->base_type)
611 if (VTABLE_elements(INTERP, value) != n)
614 for (j = 0; j < n; ++j) {
615 PMC * const item1 = SELF.get_pmc_keyed_int(j);
616 PMC * const item2 = VTABLE_get_pmc_keyed_int(INTERP, value, j);
621 if (item1->vtable->base_type == enum_class_Null
622 || item2->vtable->base_type == enum_class_Null)
625 if (!VTABLE_is_equal(INTERP, item1, item2))
635 =item C<PMC *get_iter()>
637 Return a new iterator for SELF.
643 VTABLE PMC *get_iter() {
644 return Parrot_pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
649 =item C<INTVAL exists_keyed_int(INTVAL key)>
651 =item C<INTVAL exists_keyed_int(PMC *key)>
653 Returns TRUE is the element at C<key> exists; otherwise returns false.
658 VTABLE INTVAL exists_keyed_int(INTVAL key) {
660 if (key < 0 || key >= PMC_size(SELF))
661 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
662 _("FixedPMCArray: index out of bounds!"));
664 data = PMC_array(SELF);
665 return !PMC_IS_NULL(data[key]);
668 VTABLE INTVAL exists_keyed(PMC *key) {
669 const INTVAL ix = VTABLE_get_integer(INTERP, key);
670 return SELF.exists_keyed_int(ix);
675 =item C<void splice(PMC *value, INTVAL offset, INTVAL count)>
677 Replaces C<count> elements starting at C<offset> with the elements in C<value>.
679 If C<count> is 0 then the elements in C<value> will be inserted after
682 This throws an exception if any of the spliced in values are out of the range
689 VTABLE void splice(PMC *value, INTVAL offset, INTVAL count) {
690 if (count + offset > PMC_size(SELF))
691 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
692 _("FixedPMCArray: index out of bounds!"));
694 for (count--; count >= 0; --count) {
695 VTABLE_set_pmc_keyed_int(INTERP, SELF, offset + count, value);
702 =item C<void visit(PMC *info)>
704 This is used by freeze/thaw to visit the contents of the array.
706 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
708 =item C<void freeze(PMC *info)>
710 Used to archive the array.
712 =item C<void thaw(PMC *info)>
714 Used to unarchive the array.
720 VTABLE void visit(PMC *info) {
722 const INTVAL n = VTABLE_elements(INTERP, SELF);
723 PMC **pos = PMC_array(SELF);
725 for (i = 0; i < n; ++i, ++pos) {
726 VISIT_PMC(INTERP, info, *pos);
732 VTABLE void freeze(PMC *info) {
734 VTABLE_push_integer(INTERP, info, VTABLE_elements(INTERP, SELF));
737 VTABLE void thaw(PMC *info) {
739 SELF.set_integer_native(VTABLE_shift_integer(INTERP, info));
744 =item C<INTVAL defined_keyed_int(INTVAL key)>
746 Returns TRUE is the element at C<key> is defined; otherwise returns false.
752 VTABLE INTVAL defined_keyed_int(INTVAL key) {
753 PMC * const val = SELF.get_pmc_keyed_int(key);
755 if (PMC_IS_NULL(val))
758 return VTABLE_defined(INTERP, val);
763 =item C<void mark(void)>
772 PMC ** const data = PMC_array(SELF);
778 for (i = PMC_size(SELF) - 1; i >= 0; --i)
779 Parrot_gc_mark_PMC_alive(INTERP, data[i]);
792 F<docs/pdds/pdd17_basic_types.pod>.
800 * c-file-style: "parrot"
802 * vim: expandtab shiftwidth=4: