/*
Copyright (C) 2001-2008, The Perl Foundation.
$Id: /mirror/trunk/src/pmc/intlist.pmc 29983 2008-08-02T22:45:13.271765Z allison  $

=head1 NAME

src/pmc/intlist.pmc - Array of integers

=head1 DESCRIPTION

C<IntList> provides an integer-only array.

=head2 Methods

=over 4

=cut

*/

#include "parrot/parrot.h"

pmclass IntList provides array {

/*

=item C<PMC *clone()>

Creates and returns a clone of the list.

=cut

*/

    VTABLE PMC *clone() {
        PMC * const dest     = pmc_new_noinit(INTERP, SELF->vtable->base_type);
        PObj_custom_mark_SET(dest);
        PMC_struct_val(dest) = intlist_clone(INTERP,
                                             (IntList *)PMC_struct_val(SELF));
        return dest;
    }

/*

=item C<void init()>

Initializes the list.

=cut

*/

    VTABLE void init() {
        PMC_struct_val(SELF) = intlist_new(INTERP);
        PObj_custom_mark_SET(SELF);
    }

/*

=item C<void mark()>

Marks the list as live.

=cut

*/

    VTABLE void mark() {
        intlist_mark(INTERP, (IntList *)PMC_struct_val(SELF));
    }

/*

=item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>

Sets C<value> at index C<key>.

=cut

*/

    VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
        intlist_assign(INTERP, (IntList *)PMC_struct_val(SELF), key, value);
    }

    VTABLE void set_integer_native(INTVAL len) {
        list_set_length(INTERP, (List *)PMC_struct_val(SELF), len);
    }
/*

=item C<void set_integer_keyed(PMC *key, INTVAL value)>

Sets C<value> at index C<*key>.

=cut

*/

    VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
        INTVAL ix;

        if (!key)
            return;

        ix = key_integer(INTERP, key);
        intlist_assign(INTERP, (IntList *)PMC_struct_val(SELF), ix, value);
    }

/*

=item C<INTVAL get_integer()>

Returns the number of elements in the list.

=cut

*/

    VTABLE INTVAL get_integer() {
        return intlist_length(INTERP, (IntList *)PMC_struct_val(SELF));
    }

    VTABLE INTVAL elements() {
        return intlist_length(INTERP, (IntList *)PMC_struct_val(SELF));
    }

/*

=item C<INTVAL get_integer_keyed_int(INTVAL key)>

Returns the value of the element at index C<key>.

=cut

*/

    VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
        return intlist_get(INTERP, (IntList *)PMC_struct_val(SELF), key);
    }

/*

=item C<INTVAL get_integer_keyed(PMC *key)>

Returns the value of the element at index C<*key>.

=cut

*/

    VTABLE INTVAL get_integer_keyed(PMC *key) {
        INTVAL ix;
        if (!key) return 0;
        ix = key_integer(INTERP, key);
        return intlist_get(INTERP, (IntList*) PMC_struct_val(SELF), ix);
    }

/*

=item C<void push_integer(INTVAL value)>

Adds C<value> to the end of the list.

=cut

*/

    VTABLE void push_integer(INTVAL value) {
        intlist_push(INTERP, (IntList *)PMC_struct_val(SELF), value);
    }

/*

=item C<INTVAL pop_integer()>

Removes and returns the last element in the list.

=cut

*/

    VTABLE INTVAL pop_integer() {
        return intlist_pop(INTERP, (IntList *)PMC_struct_val(SELF));
    }

/*

=item C<void unshift_integer(INTVAL value)>

Adds C<value> to the start of the list.

=cut

*/

    VTABLE void unshift_integer(INTVAL value) {
        IntList **list = (IntList **)PMC_struct_val(SELF);
        intlist_unshift(INTERP, list, value);
    }

/*

=item C<INTVAL shift_integer()>

Removes and returns the first element in the list.

=cut

*/

    VTABLE INTVAL shift_integer() {
        IntList **list = (IntList **)PMC_struct_val(SELF);
        return intlist_shift(INTERP, list);
    }

    void splice(PMC *value, INTVAL offset, INTVAL count) {
        if (SELF->vtable->base_type != value->vtable->base_type)
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
                "Type mismatch in splice");

        list_splice(INTERP, (List *)PMC_struct_val(SELF),
            (List *)PMC_struct_val(value), offset, count);
    }

    VTABLE PMC *slice(PMC *key, INTVAL f) {
        if (f)
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
                "IntList: Unknown slice type");
        else {
            PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
            PMC_struct_val(iter) = key;
            return iter;
        }
    }

    VTABLE PMC *get_iter() {
        PMC * const iter     = pmc_new_init(INTERP, enum_class_Iterator, SELF);
        PMC * const key      = pmc_new(INTERP, enum_class_Key);

        PMC_struct_val(iter) = key;
        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
        PMC_int_val(key)     = 0;

        if (!((List *)PMC_struct_val(SELF))->length)
            PMC_int_val(key) = -1;

        return iter;
    }
}

/*

=back

=cut

*/

/*
 * Local variables:
 *   c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4:
 */
