The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
/*
Copyright (C) 2001-2009, Parrot Foundation.

=head1 NAME

src/pmc/fixedfloatarray.pmc - fixed size array for floating point numbers only

=head1 DESCRIPTION

This class, FixedFloatArray, implements an array of fixed size which
stored FLOATVALs.  It uses Float PMCs to do all necessary conversions.

=head2 Functions

=over 4

=cut

*/

/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */

pmclass FixedFloatArray auto_attrs provides array {
    ATTR INTVAL    size;
    ATTR FLOATVAL *float_array;

/*

=back

=head2 Methods

=over 4

=item C<void destroy()>

Destroys the array.

=cut

*/

    VTABLE void destroy() {
        FLOATVAL *float_array;
        GET_ATTR_float_array(INTERP, SELF, float_array);
        if (float_array)
            mem_gc_free(INTERP, float_array);
    }

/*

=item C<void init_int(INTVAL size)>

Initializes the array.

=cut

*/

    VTABLE void init_int(INTVAL size) {
        if (size < 0)
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
                _("FixedFloatArray: Cannot set array size to a negative number (%d)"), size);
        SET_ATTR_size(INTERP, SELF, size);
        SET_ATTR_float_array(INTERP, SELF, mem_gc_allocate_n_typed(INTERP, size, FLOATVAL));
        PObj_custom_destroy_SET(SELF);
    }

/*

=item C<PMC *clone()>

Creates and returns a copy of the array.

=cut

*/

    VTABLE PMC *clone() {
        FLOATVAL *self_float_array;
        PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
        GET_ATTR_float_array(INTERP, SELF, self_float_array);
        if (self_float_array) {
            INTVAL size;
            GET_ATTR_size(INTERP, SELF, size);
            {
                FLOATVAL * const dest_float_array = mem_gc_allocate_n_typed(INTERP,
                        size, FLOATVAL);
                mem_copy_n_typed(dest_float_array, self_float_array,
                        size, FLOATVAL);
                SET_ATTR_float_array(INTERP, dest, dest_float_array);
            }
            SET_ATTR_size(INTERP, dest, size);
            PObj_custom_destroy_SET(dest);
        }
        return dest;
    }

/*

=item C<PMC *get_iter()>

Return an Iterator for this PMC.

=cut

*/

    VTABLE PMC *get_iter() {
        return Parrot_pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
    }

/*

=item C<INTVAL get_bool()>

Returns whether the array has any elements (meaning been initialized, for a
fixed sized array).

=cut

*/
    VTABLE INTVAL get_bool() {
        const INTVAL size = SELF.elements();
        return (INTVAL)(size != 0);
    }

/*

=item C<INTVAL elements()>

=cut

*/

    VTABLE INTVAL elements() {
        INTVAL size;
        GET_ATTR_size(INTERP, SELF, size);
        return size;
    }

/*

=item C<INTVAL get_integer()>

Returns the number of elements in the array.

=cut

*/

    VTABLE INTVAL get_integer() {
        return SELF.elements();
    }


/*

=item C<INTVAL get_integer_keyed_int(INTVAL key)>

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

=cut

*/

    VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
        const FLOATVAL f = SELF.get_number_keyed_int(key);
        return (INTVAL)f;
    }

/*

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

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

=cut

*/

    VTABLE INTVAL get_integer_keyed(PMC *key) {
        /* simple int keys only */
        const INTVAL k = VTABLE_get_integer(INTERP, key);
        return SELF.get_integer_keyed_int(k);
    }


/*

=item C<FLOATVAL get_number_keyed_int(INTVAL key)>

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

=cut

*/

    VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
        FLOATVAL *float_array;
        INTVAL    size;

        GET_ATTR_size(INTERP, SELF, size);
        if (key < 0 || key >= size)
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
                "FixedFloatArray: index out of bounds!");

        GET_ATTR_float_array(INTERP, SELF, float_array);
        return float_array[key];
    }

/*

=item C<FLOATVAL get_number_keyed(PMC *key)>

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

=cut

*/

    VTABLE FLOATVAL get_number_keyed(PMC *key) {
        const INTVAL k = VTABLE_get_integer(INTERP, key);
        return SELF.get_number_keyed_int(k);
    }

/*

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

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

=cut

*/

    VTABLE STRING *get_string_keyed_int(INTVAL key) {
        PMC * const e = SELF.get_pmc_keyed_int(key);
        return VTABLE_get_string(INTERP, e);
    }

/*

=item C<STRING *get_string_keyed(PMC *key)>

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

=cut

*/

    VTABLE STRING *get_string_keyed(PMC *key) {
        const INTVAL k = VTABLE_get_integer(INTERP, key);
        return SELF.get_string_keyed_int(k);
    }


/*

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

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

=cut

*/

    VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
        PMC    * const ret = Parrot_pmc_new(INTERP, enum_class_Float);
        const FLOATVAL val = SELF.get_number_keyed_int(key);

        VTABLE_set_number_native(INTERP, ret, val);
        return ret;
    }

/*

=item C<PMC *get_pmc_keyed(PMC *key)>

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

=cut

*/

    VTABLE PMC *get_pmc_keyed(PMC *key) {
        const INTVAL k = VTABLE_get_integer(INTERP, key);
        return SELF.get_pmc_keyed_int(k);
    }

/*

=item C<void * get_pointer()>

Return a pointer to the underlying data buffer. This is a C C<FLOATVAL*> array
and can be treated like any other array. This array should not be resized or
freed.

=cut

*/

    VTABLE void * get_pointer() {
        FLOATVAL *float_array;
        GET_ATTR_float_array(INTERP, SELF, float_array);
        return float_array;
    }

/*

=item C<void set_integer_native(INTVAL size)>

Resizes the array to C<size> elements.

=cut

*/

    VTABLE void set_integer_native(INTVAL new_size) {
        INTVAL old_size;
        GET_ATTR_size(INTERP, SELF, old_size);
        if (old_size || new_size < 1)
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
                    "FixedFloatArray: Can't resize!");

        SET_ATTR_size(INTERP, SELF, new_size);
        SET_ATTR_float_array(INTERP, SELF,
                mem_gc_allocate_n_typed(INTERP, new_size, FLOATVAL));
        PObj_custom_destroy_SET(SELF);
    }

/*

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

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

=cut

*/

    VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
        SELF.set_number_keyed_int(key, (FLOATVAL)value);
    }

/*

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

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

=cut

*/

    VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
        const INTVAL k = VTABLE_get_integer(INTERP, key);
        SELF.set_integer_keyed_int(k, value);
    }

/*

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

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

=cut

*/

    VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
        FLOATVAL *float_array;
        INTVAL size;

        GET_ATTR_size(INTERP, SELF, size);
        if (key < 0 || key >= size)
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
                "FixedFloatArray: index out of bounds!");

        GET_ATTR_float_array(INTERP, SELF, float_array);
        float_array[key] = value;
    }

/*

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

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

=cut

*/

    VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
        const INTVAL k = VTABLE_get_integer(INTERP, key);
        SELF.set_number_keyed_int(k, value);
    }

/*

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

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

=cut

*/

    VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
        FLOATVAL tempNum;
        PMC * const tempPMC = Parrot_pmc_new(INTERP, enum_class_Float);

        VTABLE_set_string_native(INTERP, tempPMC, value);
        tempNum = VTABLE_get_number(INTERP, tempPMC);
        SELF.set_number_keyed_int(key, tempNum);
    }

/*

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

Sets the string value of the element at index C<key> to
C<value>.

=cut

*/

    VTABLE void set_string_keyed(PMC *key, STRING *value) {
        const INTVAL k = VTABLE_get_integer(INTERP, key);
        SELF.set_string_keyed_int(k, value);
    }

/*

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

Sets the PMC value of the element at index C<key> to C<*src>.

=cut

*/

    VTABLE void set_pmc_keyed_int(INTVAL key, PMC *src) {
        const FLOATVAL tempNum = VTABLE_get_number(INTERP, src);
        SELF.set_number_keyed_int(key, tempNum);
    }

/*

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

Sets the string value of the element at index C<key> to
C<value>.

=cut

*/

    VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
        const INTVAL k = VTABLE_get_integer(INTERP, key);
        SELF.set_pmc_keyed_int(k, value);
    }

/*

=item C<STRING *get_string()>

=item C<STRING *get_repo()>

Returns the Parrot string representation C<key>

=cut

*/

    VTABLE STRING *get_string() {
        return STATICSELF.get_repr();
    }

    VTABLE STRING *get_repr() {
        STRING *str = CONST_STRING(INTERP, "[ ");
        STRING *comma = CONST_STRING(INTERP, ", ");
        UINTVAL i;
        const UINTVAL elems = SELF.elements();

        if (elems > 0)
            str = Parrot_str_concat(INTERP, str,
                SELF.get_string_keyed_int(0));

        for (i = 1; i < elems; ++i) {
            str = Parrot_str_concat(INTERP, str, comma);
            str = Parrot_str_concat(INTERP, str,
                SELF.get_string_keyed_int((INTVAL)i));
        }

        str = Parrot_str_concat(INTERP, str, CONST_STRING(INTERP, " ]"));
        return str;
    }

/*

=item C<METHOD reverse()>

Reverse the contents of the array.

=cut

*/

    METHOD reverse() {
        INTVAL n;
        GET_ATTR_size(INTERP, SELF, n);
        if (n > 1) {
            FLOATVAL val;
            FLOATVAL *data;
            INTVAL i;

            GET_ATTR_float_array(INTERP, SELF, data);
            for (i = 0; i <= --n; i++) {
                val = data[i];
                data[i] = data[n];
                data[n] = val;
            }
        }
    }

}

/*

=back

=head1 SEE ALSO

F<docs/pdds/pdd17_basic_types.pod>.

=cut

*/

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