//genMethods "-t" "Attribute<String>*" "-I" "LINK/graph/Attribute.h" "-d" "graph" "-y" "display_attribute_stringptr" 
#include <stk.h>
#include <LINK/stkWrapper/LINK_STk.h>

#include <LINK/graph/Attribute.h>

#include <LINK/stkWrapper/Wrapper.h>
#include <LINK/stkWrapper/Register.h>

void display_attribute_stringptr(SCM, SCM, int);

typedef Attribute<String>* _Attribute_String__;

#define _Attribute_String__DATA(x) ((Attribute<String>**) (EXTDATA(x)))
#define _Attribute_String__IS_DATA(x) (TYPEP(x, tc_CXXwrapper) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Attribute<String>* >::type))
#define _Attribute_String__ISNT_DATA(x) (!_Attribute_String__IS_DATA(x))

#define _Attribute_String__CXX_DATA(x) (*(Attribute<String>**) (EXTDATA(VAL(x))))
#define _Attribute_String__CXX_IS_DATA(x) (INSTANCEP(x) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Attribute<String>* >::type))
#define _Attribute_String__CXX_ISNT_DATA(x) (!_Attribute_String__CXX_IS_DATA(x))

#include <strstream.h>
#include <LINK/graph/GraphObject.h>

void display_attribute_stringptr(SCM c, SCM port, int mode)
{
        ostrstream oss;
	//ElementOps<String>::displayItem(oss,*_Attribute_String__DATA(c));
	if (*_Attribute_String__DATA(c))
        	oss << **_Attribute_String__DATA(c);
        oss << ends;
        char *buffer = oss.str();
        Puts(buffer, FILEPTR(port));
        delete buffer;
}

//#define STRING(s)    ((String) ((s)->storage_as.extension.data))

static SCM findStringAttributeCmd(SCM name, SCM go)
{
        GraphObject *gobj;

        if (!SYMBOLP(name))
                Err("find-string-attribute: bad arg 1, symbol expected", name);
        if (!(gobj = getGraphObject(go)))
                Err("find-string-attribute: bad arg 2, graph, vertex, or edge"
                    "expected", go);
        char *nm = PNAME(name);

        String val;
        if (getAttribute(gobj, nm, val) == LINK_GET_ATTR_FAIL)
                Err("find-string-attribute: error retrieving attribute", name);

        SCM str = STk_makestring(val);
        return str;
}

static SCM setStringAttributeCmd(SCM name, SCM val, SCM go)
{
        GraphObject *gobj;

        if (!SYMBOLP(name))
                Err("set-string-attribute!: bad arg 1, symbol expected", name);
        if (!STRINGP(val))
                Err("set-string-attribute!: bad arg 2, string expected", 
								val);
        if (!(gobj = getGraphObject(go)))
                Err("set-string-attribute!: bad arg 3, graph, vertex, or edge"
                    "expected", go);
        char *nm = PNAME(name);
       	String value = newString(STRING(val));  // LEAK!!!!!!!!!

        if (setAttribute(gobj, nm, value) == LINK_SET_ATTR_FAIL)
                Err("set-string-attribute: error setting attribute", name);

        return UNDEFINED;
}

static SCM newStringAttributeCmd(SCM name, SCM val, SCM go)
{
        Graph *g;

        if (!SYMBOLP(name))
                Err("new-string-attribute!: bad arg 1, symbol expected", name);
        if (!STRINGP(val))
                Err("new-string-attribute!: bad arg 2, string expected", val);
        if (!(g = getGraph(go)))
                Err("new-string-attribute!: bad arg 3, graph expected", go);
        char *nm = PNAME(name);
        String value = newString(STRING(val)); // LEAK!!!!!!!!!!

        if (newAttribute(g, nm, value) == LINK_NEW_ATTR_FAIL)
                Err("new-attribute: error creating attribute", name);

        return UNDEFINED;
}



// define your new methods above 
// and register them using STk_add_new_cpp_primitive() below

void genExtra_Attribute_String__Methods() 
{
        STk_add_new_cpp_primitive("find-string-attribute", tc_subr_2,
                                    (PRIMITIVE (*)(...))findStringAttributeCmd);
        STk_add_new_cpp_primitive("set-string-attribute!", tc_subr_3,
                                    (PRIMITIVE (*)(...))setStringAttributeCmd);
        STk_add_new_cpp_primitive("new-string-attribute!", tc_subr_3,
                                    (PRIMITIVE (*)(...))newStringAttributeCmd);
}
