/* key.pmc
 *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
 *  CVS Info $Id: key.pmc,v 1.13 2003/10/08 13:40:12 leo Exp $
 *  Overview:
 *     These are the vtable functions for the default PMC class
 *  Data Structure and Algorithms:
 *  History:
 *  Notes:
 *  References:
 */

#include "parrot/parrot.h"

pmclass Key need_ext {

    void init () {
        PObj_custom_mark_SET(SELF);
    }

    void clone(PMC *dest) {
	PMC *dkey = dest;
	PMC *key = SELF;
	PMC *p, *c;

        PObj_custom_mark_SET(dest);
	for (; key ; ) {

	    switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
		case KEY_integer_FLAG:
		case KEY_integer_FLAG|KEY_register_FLAG:
		    key_set_integer(INTERP, dkey, key_integer(INTERP, key));
		    break;
		case KEY_number_FLAG:
		case KEY_number_FLAG|KEY_register_FLAG:
		    key_set_number(INTERP, dkey, key_number(INTERP, key));
		    break;
		case KEY_string_FLAG:
		case KEY_string_FLAG|KEY_register_FLAG:
		    key_set_string(INTERP, dkey,
			    string_copy(INTERP, key_string(INTERP, key)));
		    break;
		case KEY_pmc_FLAG:
		case KEY_pmc_FLAG|KEY_register_FLAG:
		    p = key_pmc(INTERP, key);
		    c = pmc_new_noinit(INTERP, VTABLE_type(INTERP, p));
		    key_set_pmc(INTERP, dkey, c);
		    VTABLE_clone(INTERP, p, c);
		    break;
	    }
	    key = key_next(INTERP, key);
	    if (key) {
		p = key_new(INTERP);
		key_append(INTERP, dkey, p);
		dkey = p;
	    }
	}
    }

    void mark () {
        key_mark(INTERP, SELF);
    }

    INTVAL get_integer () {
        return key_integer(INTERP, SELF);
    }

    FLOATVAL get_number () {
        return key_number(INTERP, SELF);
    }

    STRING* get_string () {
        return key_string(INTERP, SELF);
    }

    PMC* get_pmc () {
        return key_pmc(INTERP, SELF);
    }

    void set_integer (PMC* value) {
        key_set_integer(INTERP, SELF, VTABLE_get_integer(INTERP, value));
    }

    void set_integer_native (INTVAL value) {
        key_set_integer(INTERP, SELF, value);
    }

    void set_number (PMC* value) {
        key_set_number(INTERP, SELF, VTABLE_get_number(INTERP, value));
    }

    void set_number_native (FLOATVAL value) {
        key_set_number(INTERP, SELF, value);
    }

    void set_string (PMC* value) {
        key_set_string(INTERP, SELF, VTABLE_get_string(INTERP, value));
    }

    void set_string_native (STRING* value) {
        key_set_string(INTERP, SELF, value);
    }

    void set_pmc (PMC* value) {
        key_set_pmc(INTERP, SELF, value);
    }

    void push_pmc (PMC * value) {
	key_append(INTERP, SELF, value);
    }

    /* actually doesn't remove the entry but might be useful
     * to traverse a key chain
     */
    PMC* shift_pmc() {
	return key_next(INTERP, SELF);
    }

    /* iterator interface */
    PMC* get_pmc_keyed (PMC* key) {
	return key;
    }

    PMC* nextkey_keyed (PMC* key, INTVAL what) {
	PMC *ret = SELF;

	switch (what) {
	    case ITERATE_FROM_START:	/* reset key */
		break;
	    case ITERATE_GET_NEXT:
		if (PMC_data(key))
		    ret = key_next(interpreter, key);
		else
		    ret->cache.int_val = -1;
		break;
	    default:
		internal_exception(1, "Key can't iterate backwards");
		break;
	}
	return ret;
    }
}
