fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / pmc / fixedpmcarray.pmc
blobeac3fa6d3e06ba7c5b5bfb402b33c07f3e651fb3
1 /*
2 Copyright (C) 2001-2010, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/fixedpmcarray.pmc - fixed size array for PMCs only
9 =head1 DESCRIPTION
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
14 =head2 Note
16 The flag C<PObj_private0_FLAG> is used in the C<NameSpace> PMC and should
17 never be set for user arrays.
19 =head2 Functions
21 =over 4
23 =cut
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
44 =cut
48     METHOD sort(PMC *cmp_func :optional) {
49         const INTVAL n = SELF.elements();
51         if (n > 1) {
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);
56             }
57             else
58                 Parrot_quicksort(INTERP, (void **)PMC_array(SELF), n, cmp_func);
59         }
60         RETURN(PMC *SELF);
61     }
65 =back
67 =head2 Methods
69 =over 4
71 =item C<void init_int(INTVAL size)>
73 Initializes the array.
75 =cut
79     VTABLE void init_int(INTVAL size) {
80         if (size < 0)
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);
85     }
89 =item C<void destroy()>
91 Destroys the array.
93 =cut
97     VTABLE void destroy() {
98         if (PMC_array(SELF))
99             mem_gc_free(INTERP, PMC_array(SELF));
100     }
104 =item C<PMC *clone()>
106 Creates and returns a copy of the array.
108 =cut
112     VTABLE PMC *clone() {
113         PMC * const dest  = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
114         const INTVAL size = PMC_size(SELF);
116         if (size) {
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);
121         }
123         return dest;
124     }
128 =item C<INTVAL get_bool()>
130 Returns whether the array has any elements (meaning been initialized, for a
131 fixed sized array).
133 =cut
136     VTABLE INTVAL get_bool() {
137         const INTVAL size = SELF.elements();
138         return (INTVAL)(size != 0);
139     }
143 =item C<INTVAL elements()>
145 =cut
149     VTABLE INTVAL elements() {
150         return PMC_size(SELF);
151     }
155 =item C<INTVAL get_integer()>
157 Returns the number of elements in the array.
159 =cut
163     VTABLE INTVAL get_integer() {
164         return SELF.elements();
165     }
169 =item C<FLOATVAL get_number()>
171 Returns the number of elements in the array.
173 =cut
177     VTABLE FLOATVAL get_number() {
178         const INTVAL e = SELF.elements();
179         return (FLOATVAL)e;
180     }
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.
193 =cut
197     VTABLE STRING *get_string() {
198         return Parrot_str_from_int(INTERP, SELF.elements());
199     }
201     VTABLE STRING *get_repr() {
202         STRING *res    = CONST_STRING(INTERP, "(");
203         const INTVAL n = VTABLE_elements(INTERP, SELF);
204         INTVAL  i;
206         for (i = 0; i < n; ++i) {
207             PMC * const val = SELF.get_pmc_keyed_int(i);
208             if (i > 0)
209                 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, ", "));
211             res = Parrot_str_concat(INTERP, res, VTABLE_get_repr(INTERP, val));
212         }
214         res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, ")"));
216         return res;
217     }
221 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
223 Returns the integer value of the element at index C<key>.
225 =cut
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))
232             return 0;
233         return VTABLE_get_integer(INTERP, tempPMC);
234     }
238 =item C<INTVAL get_integer_keyed(PMC *key)>
240 Returns the integer value of the element at index C<*key>.
242 =cut
246     VTABLE INTVAL get_integer_keyed(PMC *key) {
247         PMC * const tempPMC = SELF.get_pmc_keyed(key);
248         return VTABLE_get_integer(INTERP, tempPMC);
249     }
253 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
255 Returns the floating-point value of the element at index C<key>.
257 =cut
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);
264     }
268 =item C<FLOATVAL get_number_keyed(PMC *key)>
270 Returns the floating-point value of the element at index C<*key>.
272 =cut
276     VTABLE FLOATVAL get_number_keyed(PMC *key) {
277         PMC * const tempPMC = SELF.get_pmc_keyed(key);
278         return VTABLE_get_number(INTERP, tempPMC);
279     }
283 =item C<STRING *get_string_keyed_int(INTVAL key)>
285 Returns the Parrot string value of the element at index C<key>.
287 =cut
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);
298     }
302 =item C<STRING *get_string_keyed(PMC *key)>
304 Returns the Parrot string value of the element at index C<*key>.
306 =cut
310     VTABLE STRING *get_string_keyed(PMC *key) {
311         PMC * const tempPMC = SELF.get_pmc_keyed(key);
312         return VTABLE_get_string(INTERP, tempPMC);
313     }
317 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
319 Returns the PMC value of the element at index C<key>.
321 =cut
325     VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
326         PMC **data;
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);
333         return data[key];
334     }
338 =item C<PMC *get_pmc_keyed(PMC *key)>
340 Returns the PMC value of the element at index C<*key>.
342 =cut
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);
349         PMC   *box;
351         if (!nextkey)
352             return SELF.get_pmc_keyed_int(k);
354         box = SELF.get_pmc_keyed_int(k);
356         if (box == NULL)
357             box = Parrot_pmc_new(INTERP, enum_class_Undef);
359         return VTABLE_get_pmc_keyed(INTERP, box, nextkey);
360     }
364 =item C<void set_integer_native(INTVAL size)>
366 Sizes the array to C<size> elements. Can't be used to resize an
367 array.
369 =cut
373     VTABLE void set_integer_native(INTVAL size) {
374         int i;
375         PMC **data;
377         if (PMC_size(SELF) && size)
378             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
379                     _("FixedPMCArray: Can't resize!"));
380         if (!size)
381             return;
383         if (size < 0)
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)
391             data[i] = PMCNULL;
393         PObj_custom_mark_destroy_SETALL(SELF);
394         PMC_array(SELF) = data;
395     }
397     VTABLE void set_pmc(PMC *value) {
398         INTVAL size;
399         INTVAL i;
401         if (SELF == value)
402             return;
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"));
408         if (PMC_array(SELF))
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);
418     }
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>.
425 =cut
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);
435     }
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>.
443 =cut
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);
455     }
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
462 C<value>.
464 =cut
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,
470                     enum_class_Float));
472         VTABLE_set_number_native(INTERP, val, value);
473         SELF.set_pmc_keyed_int(key, val);
474     }
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
481 C<value>.
483 =cut
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);
493         }
494         else {
495             PMC *box = SELF.get_pmc_keyed_int(k);
497             /* TT #1295: autovivify an Array and insert it in SELF */
498             if (!box)
499                 box = Parrot_pmc_new(INTERP, SELF.type());
501             VTABLE_set_number_keyed(INTERP, box, nextkey, value);
502         }
503     }
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>.
511 =cut
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,
517                     enum_class_String));
519         VTABLE_set_string_native(INTERP, val, value);
520         SELF.set_pmc_keyed_int(key, val);
521     }
525 =item C<void set_string_keyed(PMC *key, STRING *value)>
527 Sets the string value of the element at index C<key> to
528 C<value>.
530 =cut
534     VTABLE void set_string_keyed(PMC *key, STRING *value) {
535         PMC * const val = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP,
536                     enum_class_String));
538         VTABLE_set_string_native(INTERP, val, value);
540         /* Let set_pmc_keyed worry about multi keys */
541         SELF.set_pmc_keyed(key, val);
542     }
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>.
550 =cut
554     VTABLE void set_pmc_keyed_int(INTVAL key, PMC *src) {
555         PMC **data;
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);
562         data[key] = src;
563     }
567 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
569 Sets the PMC at index C<key> to C<value>.
571 =cut
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);
579         if (!nextkey) {
580             SELF.set_pmc_keyed_int(k, value);
581         }
582         else {
583             PMC *box = SELF.get_pmc_keyed_int(k);
585             /* TT #1295: autovivify an Array and insert it in SELF */
586             if (!box)
587                 box = Parrot_pmc_new(INTERP, SELF.type());
589             VTABLE_set_pmc_keyed(INTERP, box, nextkey, value);
590         }
591     }
595 =item C<INTVAL is_equal(PMC *value)>
597 The C<==> operation. Compares two array to hold equal elements.
599 =cut
603     VTABLE INTVAL is_equal(PMC *value) {
604         INTVAL j, n;
606         if (value->vtable->base_type != SELF->vtable->base_type)
607             return 0;
609         n = SELF.elements();
611         if (VTABLE_elements(INTERP, value) != n)
612             return 0;
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);
618             if (item1 == item2)
619                 continue;
621             if (item1->vtable->base_type == enum_class_Null
622             ||  item2->vtable->base_type == enum_class_Null)
623                 return 0;
625             if (!VTABLE_is_equal(INTERP, item1, item2))
626                 return 0;
627         }
629         return 1;
630     }
635 =item C<PMC *get_iter()>
637 Return a new iterator for SELF.
639 =cut
643     VTABLE PMC *get_iter() {
644         return Parrot_pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
645     }
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.
655 =cut
658     VTABLE INTVAL exists_keyed_int(INTVAL key) {
659         PMC **data;
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]);
666     }
668     VTABLE INTVAL exists_keyed(PMC *key) {
669         const INTVAL ix = VTABLE_get_integer(INTERP, key);
670         return SELF.exists_keyed_int(ix);
671     }
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
680 C<offset>.
682 This throws an exception if any of the spliced in values are out of the range
683 of this array.
685 =cut
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);
696         }
697     }
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.
716 =cut
720     VTABLE void visit(PMC *info) {
721         INTVAL  i;
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);
727         }
729         SUPER(info);
730     }
732     VTABLE void freeze(PMC *info) {
733         SUPER(info);
734         VTABLE_push_integer(INTERP, info, VTABLE_elements(INTERP, SELF));
735     }
737     VTABLE void thaw(PMC *info) {
738         SUPER(info);
739         SELF.set_integer_native(VTABLE_shift_integer(INTERP, info));
740     }
744 =item C<INTVAL defined_keyed_int(INTVAL key)>
746 Returns TRUE is the element at C<key> is defined; otherwise returns false.
748 =cut
752     VTABLE INTVAL defined_keyed_int(INTVAL key) {
753         PMC * const val = SELF.get_pmc_keyed_int(key);
755         if (PMC_IS_NULL(val))
756             return 0;
758         return VTABLE_defined(INTERP, val);
759     }
763 =item C<void mark(void)>
765 Mark the array.
767 =cut
771     VTABLE void mark() {
772         PMC ** const data = PMC_array(SELF);
773         INTVAL i;
775         if (!data)
776             return;
778         for (i = PMC_size(SELF) - 1; i >= 0; --i)
779             Parrot_gc_mark_PMC_alive(INTERP, data[i]);
780     }
788 =back
790 =head1 SEE ALSO
792 F<docs/pdds/pdd17_basic_types.pod>.
794 =cut
799  * Local variables:
800  *   c-file-style: "parrot"
801  * End:
802  * vim: expandtab shiftwidth=4:
803  */