//genMethods "-g" "-t" "Vertex*" "-I" "LINK/graph/Vertex.h" "-d" "graph" "-y" "display_vertexptr" "-m" "mark_vertexptr" "-w" "free_vertexptr" 

#include <stk.h>
#include <LINK/stkWrapper/LINK_STk.h>

#include <LINK/graph/Vertex.h>

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

void display_vertexptr(SCM, SCM, int);
void mark_vertexptr(SCM);
void free_vertexptr(SCM);

typedef Vertex* _Vertex_;

#define _Vertex_DATA(x) ((Vertex**) (EXTDATA(x)))
#define _Vertex_IS_DATA(x) (TYPEP(x, tc_CXXwrapper) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Vertex* >::type))
#define _Vertex_ISNT_DATA(x) (!IS_DATA(x))

#define _Vertex_CXX_DATA(x) (*(Vertex**) (EXTDATA(VAL(x))))
#define _Vertex_CXX_IS_DATA(x) (INSTANCEP(x) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Vertex* >::type))
#define _Vertex_CXX_ISNT_DATA(x) (!CXX_IS_DATA(x))

#include <strstream.h>
void display_vertexptr(SCM c, SCM port, int mode)
{
        ostrstream oss;
        if (*_Vertex_DATA(c))
        	oss << **_Vertex_DATA(c);
        oss << ends;
        char *buffer = oss.str();
        Puts(buffer, FILEPTR(port));
        delete buffer;
}

void mark_vertexptr(SCM p)
{
        Register<Vertex>::markEntry(*_Vertex_DATA(p));
}

void free_vertexptr(SCM p)
{
        if (!EXTSTATICP(p)) {
                delete _Vertex_DATA(p);
        }
}


static PRIMITIVE InNeighborsVertexCmd(SCM v)
{
        Vertex *vert;
        int& vtype = Wrapper<Vertex*>::type;
        if (!CXX_TYPEP(v, vtype))
                Err("in-neighbors: bad arg 1, <vertex*> expected", v);
	vert = *(Vertex**) CLASSDATA(v);
        Set<Vertex*>* s = new Set<Vertex*>(vert->inNeighbors());

        //Set<Vertex*>* s = new Set<Vertex*>(gr->vertices());  SEGFAULT (WHY?)

        return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
                Wrapper<Set<Vertex*> >::name, (void *) s, LINK_DYNAMIC);
}

static PRIMITIVE OutNeighborsVertexCmd(SCM v)
{
        Vertex *vert;
        int& vtype = Wrapper<Vertex*>::type;
        if (!CXX_TYPEP(v, vtype))
                Err("out-neighbors: bad arg 1, <vertex*> expected", v);
	vert = *(Vertex**) CLASSDATA(v);
        Set<Vertex*>* s = new Set<Vertex*>(vert->outNeighbors());

        //Set<Vertex*>* s = new Set<Vertex*>(gr->vertices());  SEGFAULT (WHY?)

        return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
                Wrapper<Set<Vertex*> >::name, (void *) s, LINK_DYNAMIC);
}

static PRIMITIVE NeighborsVertexCmd(SCM v)
{
        Vertex *vert;
        int& vtype = Wrapper<Vertex*>::type;
        if (!CXX_TYPEP(v, vtype))
                Err("neighbors: bad arg 1, <vertex*> expected", v);
	vert = *(Vertex**) CLASSDATA(v);
        Set<Vertex*>* s = new Set<Vertex*>(vert->neighbors());

        //Set<Vertex*>* s = new Set<Vertex*>(gr->vertices());  SEGFAULT (WHY?)

        return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
                Wrapper<Set<Vertex*> >::name, (void *) s, LINK_DYNAMIC);
}


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

void genExtra_Vertex_Methods() 
{
        STk_add_new_cpp_primitive("neighbors", tc_subr_1,
                                    (PRIMITIVE (*)(...))NeighborsVertexCmd);
        STk_add_new_cpp_primitive("in-neighbors", tc_subr_1,
                                    (PRIMITIVE (*)(...))InNeighborsVertexCmd);
        STk_add_new_cpp_primitive("out-neighbors", tc_subr_1,
                                    (PRIMITIVE (*)(...))OutNeighborsVertexCmd);
}
