/*
Copyright (C) 2001-2006, The Perl Foundation.
$Id: perlarray.pmc 16836 2007-01-30 04:30:52Z coke $

=head1 NAME

src/dynpmc/perlarray.pmc - Perl Array

=head1 DESCRIPTION

These are the vtable functions for the PerlArray PMC.

=head2 Functions

=over 4

=cut

*/

#include "parrot/parrot.h"

/*

=item C<static PMC *undef(Interp *interp)>

Returns the C<PerlUndef> PMC.

=cut

*/

static PMC* undef(Interp* interp) {
    INTVAL dynpmc_PerlUndef;

    dynpmc_PerlUndef = pmc_type(interp,
        string_from_const_cstring(interp, "PerlUndef", 0));

    return pmc_new(interp, dynpmc_PerlUndef);
}

/*

=item C<static PMC *
Parrot_PerlArray_set_pmc_ptr(Interp *interp, List *list, INTVAL key)>

Returns the PMC pointer for the element at index C<key>.

=cut

*/

static PMC *
Parrot_PerlArray_set_pmc_ptr(Interp *interp, List *list, INTVAL key)
{
    void * ret = list_get(interp, list, key, enum_type_PMC);
    PMC *value;

    /* assign into a sparse or past end */
    if (ret == 0 || ret == (void*) -1 || *(PMC**)ret == 0) {
        value = undef(interp);
        list_assign(interp, list, key, value, enum_type_PMC);
    }
    else
        value = *(PMC**) ret;
    return value;
}

pmclass PerlArray
    extends Array
    need_ext
    does array
    dynpmc
    group perl_group
    hll Perl
    maps ResizablePMCArray {

/*

=back

=head2 Methods

=over 4

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

Converts C<value> to a C<PerlInt> and assigns it to the array at index
C<key>.

=cut

*/

    void set_integer_keyed_int(INTVAL key, INTVAL value) {
        INTVAL  dynpmc_PerlInt;
        PMC    *src;

        dynpmc_PerlInt = pmc_type(interp,
            string_from_const_cstring(interp, "PerlInt", 0));
        src = pmc_new_noinit(INTERP, dynpmc_PerlInt);
        PMC_int_val(src) = value;
        list_assign(INTERP, (List *) PMC_data(SELF), key, src, enum_type_PMC);
    }

/*

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

Assigns C<value> to the array at index C<*key>.

=cut

*/

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

        ix = key_integer(INTERP, key);
        if (ix >= DYNSELF.elements() || ix < -DYNSELF.elements())
        list_set_length(INTERP, (List *) PMC_data(SELF), ix+1);
        SUPER(key, value);
    }

/*

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

Assigns C<value> to the array at index C<key>.

=cut

*/

    void set_number_keyed_int(INTVAL key, FLOATVAL value) {
        PMC * ptr = Parrot_PerlArray_set_pmc_ptr(INTERP,
            (List *) PMC_data(SELF), key);
        VTABLE_set_number_native(INTERP, ptr, value);
    }

/*

=item C<void set_number_keyed(PMC *key, FLOATVAL value)>

Assigns C<value> to the array at index C<*key>.

=cut

*/

    void set_number_keyed(PMC* key, FLOATVAL value) {
        INTVAL ix;

        ix = key_integer(INTERP, key);
        if (ix >= DYNSELF.elements() || ix < -DYNSELF.elements())
        list_set_length(INTERP, (List *) PMC_data(SELF), ix+1);
        SUPER(key, value);
    }

/*

=item C<void set_string_keyed_int(INTVAL key, STRING *value)>

Assigns C<*value> to the array at index C<key>.

=cut

*/

    void set_string_keyed_int(INTVAL key, STRING* value) {
        PMC * ptr = Parrot_PerlArray_set_pmc_ptr(INTERP,
            (List *) PMC_data(SELF), key);
        VTABLE_set_string_native(INTERP, ptr, value);
    }

/*

=item C<void set_string_keyed(PMC *key, STRING *value)>

Assigns C<*value> to the array at index C<*key>.

=cut

*/

    void set_string_keyed(PMC* key, STRING* value) {
        INTVAL ix;

        ix = key_integer(INTERP, key);
        if (ix >= DYNSELF.elements() || ix < -DYNSELF.elements())
        list_set_length(INTERP, (List *) PMC_data(SELF), ix+1);
        SUPER(key, value);
    }

/*

=item C<void set_pmc_keyed_int(INTVAL key, PMC *src)>

Assigns C<*src> to the array at index C<key>.

=cut

*/

    void set_pmc_keyed_int(INTVAL key, PMC* src) {
        list_assign(INTERP, (List *) PMC_data(SELF), key, src, enum_type_PMC);
    }

/*

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

Assigns C<*value> to the array at index C<*key>.

=cut

*/

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

        ix = key_integer(INTERP, key);
        if (ix >= DYNSELF.elements() || ix < -DYNSELF.elements())
        list_set_length(INTERP, (List *) PMC_data(SELF), ix+1);
        SUPER(key, value);
    }

/*

=item C<INTVAL get_integer_keyed_int(INTVAL key)>

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

=cut

*/

    INTVAL get_integer_keyed_int(INTVAL key) {
        if (key >= DYNSELF.elements() || key < -DYNSELF.elements()) {
            if (PARROT_WARNINGS_test(INTERP,
                                     PARROT_WARNINGS_UNDEF_FLAG)) {
                Parrot_warn(INTERP, PARROT_WARNINGS_UNDEF_FLAG,
                            "Use of uninitialized value");
            }
            return 0;
        }
        else
            return SUPER(key);
    }

/*

=item C<FLOATVAL get_number_keyed_int(INTVAL key)>

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

=cut

*/

    FLOATVAL get_number_keyed_int(INTVAL key) {
        if (key >= DYNSELF.elements() || key < -DYNSELF.elements()) {
            if (PARROT_WARNINGS_test(INTERP,
                                     PARROT_WARNINGS_UNDEF_FLAG)) {
                Parrot_warn(INTERP, PARROT_WARNINGS_UNDEF_FLAG,
                            "Use of uninitialized value");
            }
            return 0.0;
        }
        else
            return SUPER(key);
    }

/*

=item C<STRING *get_string()>

Returns the number of elements in the array as a Parrot string.

=cut

*/

    STRING* get_string() {
        return string_from_int(INTERP, DYNSELF.elements());
    }

/*

=item C<STRING *get_string_keyed_int(INTVAL key)>

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

=cut

*/

    STRING* get_string_keyed_int(INTVAL key) {
        if (key >= DYNSELF.elements() || key < -DYNSELF.elements()) {
            if (PARROT_WARNINGS_test(INTERP,
                                     PARROT_WARNINGS_UNDEF_FLAG)) {
                Parrot_warn(INTERP, PARROT_WARNINGS_UNDEF_FLAG,
                            "Use of uninitialized value");
            }
            return string_make_empty(INTERP, enum_stringrep_one, 0);
        }
        else
            return SUPER(key);
    }

/*

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

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

=cut

*/

    PMC* get_pmc_keyed_int(INTVAL key) {
        if (key >= DYNSELF.elements() || key < -DYNSELF.elements()) {
            if (PARROT_WARNINGS_test(INTERP,
                                     PARROT_WARNINGS_UNDEF_FLAG)) {
                Parrot_warn(INTERP, PARROT_WARNINGS_UNDEF_FLAG,
                            "Use of uninitialized value");
            }
            return undef(INTERP);
        }
        else
            return SUPER(key);
    }

}

/*

=back

=head1 TODO

Fix the arithmetic ops (right now they just corrupt the array length and
possibly seg fault).

=cut

*/

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