/* Iterator.pmc
 *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
 *  CVS Info
 *     $Id: iterator.pmc,v 1.13 2003/08/28 14:56:46 leo Exp $
 *  Overview:
 *     These are the vtable functions for the Iterator base class
 *  Data Structure and Algorithms:
 *  History:
 *  Notes:
 *  References:
 */

#include "parrot/parrot.h"

pmclass Iterator {

    void init () {
	internal_exception(1, "Iterator init without aggregate\n");
    }

    void init_pmc (PMC* initializer) {
	PMC_ptr2p(SELF) = initializer; /* the aggregate itself */
        SELF->cache.struct_val = NULL;
        PObj_custom_mark_SET(SELF);
    }

    void mark () {
	if (SELF->cache.struct_val) /* the KEY */
	     pobject_lives(INTERP, (PObj *) SELF->cache.struct_val);
	if (PMC_ptr2p(SELF))		/* the aggregate */
	     pobject_lives(INTERP, (PObj *) PMC_ptr2p(SELF));
    }

    void clone (PMC* dest) {
	/* XXX TODO */
    }

    INTVAL get_integer () {
        return VTABLE_get_integer(INTERP, (PMC *)PMC_ptr2p(SELF));
    }

    INTVAL get_integer_keyed (PMC* key) {
        return VTABLE_get_integer_keyed(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    INTVAL get_integer_keyed_int (INTVAL key) {
	/* XXX adjust index */
        return VTABLE_get_integer_keyed_int(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    FLOATVAL get_number_keyed (PMC* key) {
        return VTABLE_get_number_keyed(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    FLOATVAL get_number_keyed_int (INTVAL key) {
	/* XXX adjust index */
        return VTABLE_get_number_keyed_int(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    BIGNUM* get_bignum_keyed (PMC* key) {
        return VTABLE_get_bignum_keyed(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    BIGNUM* get_bignum_keyed_int (INTVAL key) {
        return VTABLE_get_bignum_keyed_int(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    STRING* get_string_keyed (PMC* key) {
        return VTABLE_get_string_keyed(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    STRING* get_string_keyed_int (INTVAL key) {
        return VTABLE_get_string_keyed_int(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    INTVAL get_bool () {
	PMC *key = SELF->cache.struct_val;
        return key && key->cache.int_val >= 0;
    }

    INTVAL elements () {
        return VTABLE_elements(INTERP, (PMC *)PMC_ptr2p(SELF));
    }

    PMC* get_pmc_keyed (PMC* key) {
        return VTABLE_get_pmc_keyed(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    PMC* get_pmc_keyed_int (INTVAL key) {
        return VTABLE_get_pmc_keyed_int(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    void set_integer_native (INTVAL value) {
	PMC *key;
	if (value < ITERATE_FROM_START || value > ITERATE_FROM_END)
	    internal_exception(1, "Illegal set_integer on iterator\n");
	/* reset iterator on aggregate */
	if (!SELF->cache.struct_val) {
	    SELF->cache.struct_val = key_new(INTERP);
	}
	key = SELF->cache.struct_val;
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, (PMC*) PMC_ptr2p(SELF), key, value);
    }

    INTVAL pop_integer () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	INTVAL ret = VTABLE_get_integer_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_PREV);
        return ret;
    }

    FLOATVAL pop_float () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	FLOATVAL ret = VTABLE_get_number_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_PREV);
        return ret;
    }

    BIGNUM* pop_bignum () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	BIGNUM *ret = VTABLE_get_bignum_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_PREV);
        return ret;
    }

    STRING* pop_string () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	STRING *ret = VTABLE_get_string_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_PREV);
        return ret;
    }

    PMC* pop_pmc () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	PMC *ret = VTABLE_get_pmc_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_PREV);
        return ret;
    }

    INTVAL shift_integer () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	INTVAL ret = VTABLE_get_integer_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_NEXT);
        return ret;
    }


    FLOATVAL shift_float () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	FLOATVAL ret = VTABLE_get_number_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_NEXT);
        return ret;
    }

    BIGNUM* shift_bignum () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	BIGNUM *ret = VTABLE_get_bignum_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_NEXT);
        return ret;
    }

    STRING* shift_string () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	STRING * ret = VTABLE_get_string_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_NEXT);
        return ret;
    }

    PMC* shift_pmc () {
	PMC *key = SELF->cache.struct_val;
	PMC *agg = PMC_ptr2p(SELF);
	PMC *ret = VTABLE_get_pmc_keyed(INTERP, agg, key);
	SELF->cache.struct_val =
	    VTABLE_nextkey_keyed(INTERP, agg, key, ITERATE_GET_NEXT);
        return ret;
    }

    INTVAL exists_keyed (PMC* key) {
	return VTABLE_exists_keyed(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    INTVAL exists_keyed_int (INTVAL key) {
	return VTABLE_exists_keyed_int(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    INTVAL defined () {
        return (INTVAL) (PMC_ptr2p(SELF) != 0);
    }

    INTVAL defined_keyed (PMC* key) {
	return VTABLE_defined_keyed(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    INTVAL defined_keyed_int (INTVAL key) {
	return VTABLE_defined_keyed_int(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }

    INTVAL type_keyed (PMC* key) {
	return VTABLE_type_keyed(INTERP, (PMC *)PMC_ptr2p(SELF), key);
    }
}
