[GB.DATA]
* NEW: Graph and GraphMatrix work now. Graph implementations in Gambas are as powerful as native ones. git-svn-id: svn://localhost/gambas/trunk@6468 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
parent
6deb7f5ce6
commit
3a6db0ec55
@ -26,9 +26,9 @@ AvlTree:
|
||||
* NEW: Add a Copy() method to return a deep copy of an AvlTree.
|
||||
* NEW: Split() is a new method of AvlTree to return the left or right
|
||||
subtree of a given node or both.
|
||||
* NEW: Add Insert() to insert an AvlTree into another one.
|
||||
* NEW: Add PreOrder, PostOrder, Reverse and LevelOrder virtual properties to
|
||||
specify the enumeration flavour.
|
||||
* NEW: Add Insert() to insert an AvlTree into another one. (See a thread on
|
||||
stackoverflow about an O(log n) algorithm for that.)
|
||||
* NEW: Add the Reverse virtual property to traver in reverse in-order.
|
||||
|
||||
Trie:
|
||||
* BUG: Maintain lexicographical order in Trie.
|
||||
@ -37,3 +37,22 @@ Graph:
|
||||
* Write down the hidden methods and their signatures
|
||||
* Set down the relationships between methods; which default implementation
|
||||
calls what; what is minimum needed to implement a fully-functional Graph
|
||||
|
||||
RedBlackTree:
|
||||
* NEW: RedBlackTree class.
|
||||
|
||||
SearchTree:
|
||||
* NEW: SearchTree is the base class of all search trees.
|
||||
|
||||
PrioQueue:
|
||||
* NEW: Re-implement PrioQueue using a RedBlackTree.
|
||||
-> contain structures (key, time, value) where key is the key and time
|
||||
is a logical timestamp (rbtree->clock++). If key1 == key2, then compare
|
||||
the unique insertion timestamps.
|
||||
* OPT: Don't have Integer priority parameters. Consistently use
|
||||
GB.CompVariant() to compare elements. This is at least as mighty as
|
||||
integer priorities, but better encapsulated.
|
||||
|
||||
- First: Graph, PrioSet, Trie.
|
||||
- Use libtree to provide some trees (if possible).
|
||||
- General, navigatable tree class.
|
||||
|
@ -766,8 +766,7 @@ GB_DESC CAvlTree[] = {
|
||||
|
||||
#if 0
|
||||
GB_DESC CAvlTreeSplit[] = {
|
||||
GB_DECLARE(".AvlTree.Split", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
GB_DECLARE_VIRTUAL(".AvlTree.Split"),
|
||||
|
||||
GB_PROPERTY_READ("Left", "AvlTree", AvlTreeSplit_Left),
|
||||
GB_PROPERTY_READ("Right", "AvlTree", AvlTreeSplit_Right),
|
||||
|
@ -21,15 +21,30 @@
|
||||
|
||||
#define __C_GRAPH_C
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gambas.h"
|
||||
#include "c_graph.h"
|
||||
|
||||
typedef struct {
|
||||
GB_BASE ob;
|
||||
GB_VARIANT_VALUE tag;
|
||||
} CGRAPH;
|
||||
static GB_HASHTABLE interfaces;
|
||||
|
||||
BEGIN_METHOD_VOID(Graph_init)
|
||||
|
||||
GB.HashTable.New(&interfaces, GB_COMP_BINARY);
|
||||
|
||||
END_METHOD
|
||||
|
||||
static void enum_func(void *x)
|
||||
{
|
||||
GB.Free(&x);
|
||||
}
|
||||
|
||||
BEGIN_METHOD_VOID(Graph_exit)
|
||||
|
||||
GB.HashTable.Enum(interfaces, (GB_HASHTABLE_ENUM_FUNC) enum_func);
|
||||
GB.HashTable.Free(&interfaces);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(Graph_NoMethod)
|
||||
|
||||
@ -54,11 +69,73 @@ BEGIN_METHOD(Graph_call, GB_BOOLEAN d; GB_BOOLEAN w)
|
||||
|
||||
END_METHOD
|
||||
|
||||
#define get_func(func, arg, ret, need) \
|
||||
do { \
|
||||
GB_FUNCTION f; \
|
||||
\
|
||||
err = #func; \
|
||||
if (GB.GetFunction(&f, _object, #func, arg, ret)) { \
|
||||
if (need) \
|
||||
goto error; \
|
||||
else /* Clear error */ \
|
||||
GB.Error(NULL); \
|
||||
desc->func = NULL; \
|
||||
} else { \
|
||||
desc->func = f.desc; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
GRAPH_DESC *get_desc(void *_object)
|
||||
{
|
||||
GRAPH_DESC *desc;
|
||||
const char *err;
|
||||
|
||||
GB.Alloc((void **) &desc, sizeof(*desc));
|
||||
get_func(_getVertex, "s", NULL, 0);
|
||||
get_func(_getEdge, "ss", NULL, 0);
|
||||
get_func(_nextVertex, NULL, "s", 0);
|
||||
get_func(_nextEdge, NULL, "String[]", 0);
|
||||
get_func(_countVertices, NULL, "i", 0);
|
||||
get_func(_countEdges, NULL, "i", 0);
|
||||
get_func(_nextInEdge, NULL, "String[]", 0);
|
||||
get_func(_nextOutEdge, NULL, "String[]", 0);
|
||||
get_func(_nextAdjacent, NULL, "s", 0);
|
||||
get_func(_vertexProperty, ".", "b", 0);
|
||||
get_func(_edgeProperty, ".", "b", 0);
|
||||
get_func(_vertexUnknown, ".", "v", 0);
|
||||
get_func(_edgeUnknown, ".", "v", 0);
|
||||
return desc;
|
||||
|
||||
error:
|
||||
GB.Error("Method \"&1\" not found", err);
|
||||
GB.Free((void **) &desc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define THIS ((CGRAPH *) _object)
|
||||
|
||||
BEGIN_METHOD_VOID(Graph_new)
|
||||
|
||||
GRAPH_DESC *desc;
|
||||
char *name = GB.GetClassName(THIS);
|
||||
size_t len = GB.StringLength(name);
|
||||
|
||||
if (GB.HashTable.Get(interfaces, name, len, (void **) &desc)) {
|
||||
desc = get_desc(THIS);
|
||||
GB.HashTable.Add(interfaces, name, len, desc);
|
||||
}
|
||||
THIS->desc = desc;
|
||||
THIS->vertex = NULL;
|
||||
GB.Array.New(&THIS->edge, GB_T_STRING, 2);
|
||||
THIS->tag.type = GB_T_NULL;
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(Graph_free)
|
||||
|
||||
GB.StoreVariant(NULL, &THIS->tag);
|
||||
GB.Unref(&THIS->edge);
|
||||
GB.FreeString(&THIS->vertex);
|
||||
|
||||
END_METHOD
|
||||
|
||||
@ -72,15 +149,63 @@ BEGIN_PROPERTY(Graph_Tag)
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
#define SET_VERTEX() \
|
||||
do { \
|
||||
GB.FreeString(&THIS->vertex); \
|
||||
THIS->vertex = GB.NewString(STRING(vert), LENGTH(vert));\
|
||||
} while (0)
|
||||
|
||||
#define SET_VERTEX_P() \
|
||||
do { \
|
||||
GB.FreeString(&THIS->vertex); \
|
||||
THIS->vertex = GB.NewString(PSTRING(), PLENGTH()); \
|
||||
} while (0)
|
||||
|
||||
#define SET_EDGE() \
|
||||
do { \
|
||||
GB.StoreString(ARG(src), GB.Array.Get(THIS->edge, 0)); \
|
||||
GB.StoreString(ARG(dst), GB.Array.Get(THIS->edge, 1)); \
|
||||
} while (0)
|
||||
|
||||
#define SET_EDGE_P() \
|
||||
do { \
|
||||
GB.StoreObject(VPROP(GB_OBJECT), &THIS->edge); \
|
||||
} while (0)
|
||||
|
||||
BEGIN_PROPERTY(Graph_Vertex)
|
||||
|
||||
if (READ_PROPERTY) {
|
||||
GB.ReturnString(THIS->vertex);
|
||||
return;
|
||||
}
|
||||
SET_VERTEX_P();
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
BEGIN_PROPERTY(Graph_Edge)
|
||||
|
||||
if (READ_PROPERTY) {
|
||||
GB.ReturnObject(THIS->edge);
|
||||
return;
|
||||
}
|
||||
SET_EDGE_P();
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
GB_DESC CGraph[] = {
|
||||
GB_DECLARE("Graph", sizeof(CGRAPH)),
|
||||
GB_NOT_CREATABLE(),
|
||||
|
||||
GB_STATIC_METHOD("_init", NULL, Graph_init, NULL),
|
||||
GB_STATIC_METHOD("_exit", NULL, Graph_exit, NULL),
|
||||
|
||||
GB_STATIC_METHOD("_call", "Graph", Graph_call, "[(Directed)b(Weighted)b]"),
|
||||
GB_METHOD("_new", NULL, Graph_new, NULL),
|
||||
GB_METHOD("_free", NULL, Graph_free, NULL),
|
||||
|
||||
GB_METHOD("_getVertex", "_Graph_Vertex", Graph_NoMethod, "(Vertex)s"),
|
||||
GB_METHOD("_getEdge", "_Graph_Edge", Graph_NoMethod, "(Src)s(Dst)s"),
|
||||
/* Graph */
|
||||
GB_METHOD("_getVertex", ".Graph.Vertex", Graph_NoMethod, "(Vertex)s"),
|
||||
GB_METHOD("_getEdge", ".Graph.Edge", Graph_NoMethod, "(Src)s(Dst)s"),
|
||||
|
||||
GB_METHOD("_nextVertex", "s", Graph_NoMethod, NULL),
|
||||
GB_METHOD("_nextEdge", "String[]", Graph_NoMethod, NULL),
|
||||
@ -88,30 +213,40 @@ GB_DESC CGraph[] = {
|
||||
GB_METHOD("_countVertices", "i", Graph_NoMethod, NULL),
|
||||
GB_METHOD("_countEdges", "i", Graph_NoMethod, NULL),
|
||||
|
||||
GB_METHOD("Add", "_Graph_Vertex", Graph_NoMethod, "(Name)s"),
|
||||
/* Vertex */
|
||||
GB_METHOD("_nextInEdge", "String[]", Graph_NoMethod, NULL),
|
||||
GB_METHOD("_nextOutEdge", "String[]", Graph_NoMethod, NULL),
|
||||
|
||||
/* Public */
|
||||
GB_METHOD("Add", ".Graph.Vertex", Graph_NoMethod, "(Name)s"),
|
||||
GB_METHOD("Remove", NULL, Graph_NoMethod, "(Vertex)s"),
|
||||
GB_METHOD("Connect", "_Graph_Edge", Graph_NoMethod, "(Src)s(Dst)s"),
|
||||
GB_METHOD("Connect", ".Graph.Edge", Graph_NoMethod, "(Src)s(Dst)s"),
|
||||
GB_METHOD("Disconnect", NULL, Graph_NoMethod, "(Src)s(Dst)s"),
|
||||
|
||||
GB_PROPERTY("Tag", "v", Graph_Tag),
|
||||
|
||||
GB_PROPERTY("_Vertex", "s", Graph_Vertex),
|
||||
GB_PROPERTY("_Edge", "String[]", Graph_Edge),
|
||||
|
||||
GB_PROPERTY_SELF("Vertices", ".Graph.Vertices"),
|
||||
GB_PROPERTY_SELF("Edges", ".Graph.Edges"),
|
||||
|
||||
GB_PROPERTY_SELF("InEdges", ".Graph.InEdges"),
|
||||
GB_PROPERTY_SELF("OutEdges", ".Graph.OutEdges"),
|
||||
GB_PROPERTY_SELF("Adjacent", ".Graph.Adjacent"),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
/*
|
||||
* Call another method/property of this class and fail if not found.
|
||||
*/
|
||||
#define CALL_GRAPH(func, narg, arg, ret) \
|
||||
#define CALL_GRAPH(func, narg) \
|
||||
do { \
|
||||
GB_FUNCTION f; \
|
||||
\
|
||||
if (GB.GetFunction(&f, _object, func, arg, ret)) { \
|
||||
GB.Error("Method " func " not found"); \
|
||||
return; \
|
||||
} \
|
||||
f.desc = THIS->desc->func; \
|
||||
f.object = THIS; \
|
||||
GB.Call(&f, narg, 0); \
|
||||
} while (0)
|
||||
|
||||
@ -130,154 +265,72 @@ do { \
|
||||
* Try to call another method/property of this class. If found, return
|
||||
* afterwards. If not, continue.
|
||||
*/
|
||||
#define TRY_CALL_GRAPH(func, narg, arg, ret) \
|
||||
#define TRY_CALL_GRAPH(func, narg) \
|
||||
do { \
|
||||
GB_FUNCTION f; \
|
||||
\
|
||||
if (!GB.GetFunction(&f, _object, func, arg, ret)) { \
|
||||
GB.Call(&f, narg, 0); \
|
||||
if (THIS->desc->func) { \
|
||||
CALL_GRAPH(func, narg); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
BEGIN_METHOD_VOID(GraphVertices_next)
|
||||
|
||||
CALL_GRAPH("_nextVertex", 0, NULL, "s");
|
||||
CALL_GRAPH(_nextVertex, 0);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD(GraphVertices_get, GB_STRING vert)
|
||||
|
||||
GB.Push(1, GB_T_STRING, STRING(vert), LENGTH(vert));
|
||||
CALL_GRAPH("_getVertex", 1, "s", NULL);
|
||||
SET_VERTEX();
|
||||
GB.ReturnSelf(THIS);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_PROPERTY(GraphVertices_Count)
|
||||
|
||||
TRY_CALL_GRAPH("_countVertices", 0, NULL, "i");
|
||||
|
||||
/* Default: enumerate the vertices, counting */
|
||||
CALL_GRAPH(_countVertices, 0);
|
||||
/* Default: enumerate the vertices, counting. Then use
|
||||
* TRY_CALL_GRAPH. */
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
GB_DESC CGraphVertices[] = {
|
||||
GB_DECLARE(".Graph.Vertices", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
GB_DECLARE_VIRTUAL(".Graph.Vertices"),
|
||||
|
||||
GB_METHOD("_next", "s", GraphVertices_next, NULL),
|
||||
GB_METHOD("_get", "_Graph_Vertex", GraphVertices_get, "(Vertex)s"),
|
||||
GB_METHOD("_get", ".Graph.Vertex", GraphVertices_get, "(Vertex)s"),
|
||||
|
||||
GB_PROPERTY_READ("Count", "i", GraphVertices_Count),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_PROPERTY(GraphVertex_InDegree)
|
||||
|
||||
/* Default: enumerate */
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
BEGIN_PROPERTY(GraphVertex_OutDegree)
|
||||
|
||||
/* Default: enumerate */
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
GB_DESC CGraphVertex[] = {
|
||||
GB_DECLARE("_Graph_Vertex", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
|
||||
GB_METHOD("_nextInEdge", "String[]", Graph_NoMethod, NULL),
|
||||
GB_METHOD("_nextOutEdge", "String[]", Graph_NoMethod, NULL),
|
||||
GB_METHOD("_nextAdjacent", "s", Graph_NoMethod, NULL),
|
||||
|
||||
GB_PROPERTY_READ("InDegree", "i", GraphVertex_InDegree),
|
||||
GB_PROPERTY_READ("OutDegree", "i", GraphVertex_OutDegree),
|
||||
GB_PROPERTY("Name", "s", Graph_NoProperty),
|
||||
GB_PROPERTY("Value", "v", Graph_NoProperty),
|
||||
|
||||
GB_PROPERTY_SELF("InEdges", ".Vertex.InEdges"),
|
||||
GB_PROPERTY_SELF("OutEdges", ".Vertex.OutEdges"),
|
||||
GB_PROPERTY_SELF("Adjacent", ".Vertex.Adjacent"),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_METHOD_VOID(VertexInEdges_next)
|
||||
|
||||
CALL_GRAPH("_nextInEdge", 0, NULL, "String[]");
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CVertexInEdges[] = {
|
||||
GB_DECLARE(".Vertex.InEdges", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
|
||||
GB_METHOD("_next", "String[]", VertexInEdges_next, NULL),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_METHOD_VOID(VertexOutEdges_next)
|
||||
|
||||
CALL_GRAPH("_nextOutEdge", 0, NULL, "String[]");
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CVertexOutEdges[] = {
|
||||
GB_DECLARE(".Vertex.OutEdges", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
|
||||
GB_METHOD("_next", "String[]", VertexOutEdges_next, NULL),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_METHOD_VOID(VertexAdjacent_next)
|
||||
|
||||
CALL_GRAPH("_nextAdjacent", 0, NULL, "s");
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CVertexAdjacent[] = {
|
||||
GB_DECLARE(".Vertex.Adjacent", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
|
||||
GB_METHOD("_next", "s", VertexAdjacent_next, NULL),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_METHOD_VOID(GraphEdges_next)
|
||||
|
||||
CALL_GRAPH("_nextEdge", 0, NULL, "String[]");
|
||||
CALL_GRAPH(_nextEdge, 0);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD(GraphEdges_get, GB_STRING src; GB_STRING dst)
|
||||
|
||||
GB.Push(2, GB_T_STRING, STRING(src), LENGTH(src),
|
||||
GB_T_STRING, STRING(dst), LENGTH(dst));
|
||||
CALL_GRAPH("_getEdge", 2, "ss", NULL);
|
||||
SET_EDGE();
|
||||
GB.ReturnSelf(THIS);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_PROPERTY(GraphEdges_Count)
|
||||
|
||||
TRY_CALL_GRAPH("_countEdges", 0, NULL, "i");
|
||||
|
||||
/* Default: enumerate the edges, counting */
|
||||
CALL_GRAPH(_countEdges, 0);
|
||||
/* Default: enumerate the edges, counting. Then use
|
||||
* TRY_CALL_GRAPH. */
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
GB_DESC CGraphEdges[] = {
|
||||
GB_DECLARE(".Graph.Edges", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
GB_DECLARE_VIRTUAL(".Graph.Edges"),
|
||||
|
||||
GB_METHOD("_next", "String[]", GraphEdges_next, NULL),
|
||||
GB_METHOD("_get", "_Graph_Edge", GraphEdges_get, "(Src)s(Dst)s"),
|
||||
GB_METHOD("_get", ".Graph.Edge", GraphEdges_get, "(Src)s(Dst)s"),
|
||||
GB_METHOD("Exist", "b", Graph_NoMethod, "(Src)s(Dst)s"),
|
||||
|
||||
GB_PROPERTY_READ("Count", "i", GraphEdges_Count),
|
||||
@ -285,16 +338,147 @@ GB_DESC CGraphEdges[] = {
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
GB_DESC CGraphEdge[] = {
|
||||
GB_DECLARE("_Graph_Edge", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
BEGIN_METHOD(GraphInEdges_get, GB_STRING vert)
|
||||
|
||||
GB_PROPERTY_READ("Src", "s", Graph_NoProperty),
|
||||
GB_PROPERTY_READ("Dst", "s", Graph_NoProperty),
|
||||
GB_PROPERTY("Weight", "f", Graph_NoProperty),
|
||||
SET_VERTEX();
|
||||
GB.ReturnSelf(THIS);
|
||||
|
||||
GB_PROPERTY_READ("Source", "s", Graph_NoProperty),
|
||||
GB_PROPERTY_READ("Destination", "s", Graph_NoProperty),
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(GraphInEdges_next)
|
||||
|
||||
CALL_GRAPH(_nextInEdge, 0);
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CGraphInEdges[] = {
|
||||
GB_DECLARE_VIRTUAL(".Graph.InEdges"),
|
||||
|
||||
GB_METHOD("_get", ".Graph.InEdges", GraphInEdges_get, "(Vertex)s"),
|
||||
GB_METHOD("_next", "String[]", GraphInEdges_next, NULL),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_METHOD(GraphOutEdges_get, GB_STRING vert)
|
||||
|
||||
SET_VERTEX();
|
||||
GB.ReturnSelf(THIS);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(GraphOutEdges_next)
|
||||
|
||||
CALL_GRAPH(_nextOutEdge, 0);
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CGraphOutEdges[] = {
|
||||
GB_DECLARE_VIRTUAL(".Graph.OutEdges"),
|
||||
|
||||
GB_METHOD("_get", ".Graph.OutEdges", GraphOutEdges_get, "(Vertex)s"),
|
||||
GB_METHOD("_next", "String[]", GraphOutEdges_next, NULL),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_METHOD(GraphAdjacent_get, GB_STRING vert)
|
||||
|
||||
SET_VERTEX();
|
||||
GB.ReturnSelf(THIS);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(GraphAdjacent_next)
|
||||
|
||||
CALL_GRAPH(_nextAdjacent, 0);
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CGraphAdjacent[] = {
|
||||
GB_DECLARE_VIRTUAL(".Graph.Adjacent"),
|
||||
|
||||
GB_METHOD("_get", ".Graph.Adjacent", GraphAdjacent_get, "(Vertex)s"),
|
||||
GB_METHOD("_next", "s", GraphAdjacent_next, NULL),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_PROPERTY(GraphVertex_InDegree)
|
||||
|
||||
/* Call ??? */
|
||||
/* Default: enumerate */
|
||||
assert(0);
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
BEGIN_PROPERTY(GraphVertex_OutDegree)
|
||||
|
||||
/* Call ??? */
|
||||
/* Default: enumerate */
|
||||
assert(0);
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
BEGIN_METHOD_VOID(GraphVertex_property)
|
||||
|
||||
CALL_GRAPH(_vertexProperty, GB.NParam());
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(GraphVertex_unknown)
|
||||
|
||||
CALL_GRAPH(_vertexUnknown, GB.NParam());
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CGraphVertex[] = {
|
||||
GB_DECLARE_VIRTUAL(".Graph.Vertex"),
|
||||
|
||||
GB_PROPERTY_READ("InDegree", "i", GraphVertex_InDegree),
|
||||
GB_PROPERTY_READ("OutDegree", "i", GraphVertex_OutDegree),
|
||||
|
||||
GB_METHOD("_property", "b", GraphVertex_property, "."),
|
||||
GB_METHOD("_unknown", "v", GraphVertex_unknown, "."),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_PROPERTY(GraphEdge_Src)
|
||||
|
||||
GB.ReturnString(GB.Array.Get(THIS->edge, 0));
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
BEGIN_PROPERTY(GraphEdge_Dst)
|
||||
|
||||
GB.ReturnString(GB.Array.Get(THIS->edge, 1));
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
BEGIN_METHOD_VOID(GraphEdge_property)
|
||||
|
||||
CALL_GRAPH(_edgeProperty, GB.NParam());
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(GraphEdge_unknown)
|
||||
|
||||
CALL_GRAPH(_edgeUnknown, GB.NParam());
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CGraphEdge[] = {
|
||||
GB_DECLARE_VIRTUAL(".Graph.Edge"),
|
||||
|
||||
GB_PROPERTY_READ("Src", "s", GraphEdge_Src),
|
||||
GB_PROPERTY_READ("Dst", "s", GraphEdge_Dst),
|
||||
|
||||
GB_PROPERTY_READ("Source", "s", GraphEdge_Src),
|
||||
GB_PROPERTY_READ("Destination", "s", GraphEdge_Dst),
|
||||
|
||||
GB_METHOD("_property", "b", GraphEdge_property, "."),
|
||||
GB_METHOD("_unknown", "v", GraphEdge_unknown, "."),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
@ -26,9 +26,40 @@
|
||||
|
||||
extern GB_INTERFACE GB;
|
||||
|
||||
typedef struct {
|
||||
void *_getVertex;
|
||||
void *_getEdge;
|
||||
|
||||
void *_nextVertex;
|
||||
void *_nextEdge;
|
||||
|
||||
void *_countVertices;
|
||||
void *_countEdges;
|
||||
|
||||
void *_nextInEdge;
|
||||
void *_nextOutEdge;
|
||||
void *_nextAdjacent;
|
||||
|
||||
void *_vertexProperty;
|
||||
void *_edgeProperty;
|
||||
|
||||
void *_vertexUnknown;
|
||||
void *_edgeUnknown;
|
||||
} GRAPH_DESC;
|
||||
|
||||
typedef struct {
|
||||
GB_BASE ob;
|
||||
GRAPH_DESC *desc;
|
||||
char *vertex;
|
||||
GB_ARRAY edge;
|
||||
GB_VARIANT_VALUE tag;
|
||||
} CGRAPH;
|
||||
|
||||
extern GRAPH_DESC *get_desc(void *_object);
|
||||
|
||||
#ifndef __C_GRAPH_C
|
||||
extern GB_DESC CGraph[], CGraphVertices[], CGraphVertex[], CVertexInEdges[],
|
||||
CVertexOutEdges[], CVertexAdjacent[], CGraphEdges[],
|
||||
extern GB_DESC CGraph[], CGraphVertices[], CGraphEdges[], CGraphInEdges[],
|
||||
CGraphOutEdges[], CGraphAdjacent[], CGraphVertex[],
|
||||
CGraphEdge[];
|
||||
#endif
|
||||
|
||||
|
@ -21,10 +21,10 @@
|
||||
|
||||
#define __C_GRAPHMATRIX_C
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gambas.h"
|
||||
#include "c_graph.h"
|
||||
#include "c_graphmatrix.h"
|
||||
|
||||
#define E_NOVERTEX "Vertex does not exist"
|
||||
@ -45,22 +45,28 @@ typedef struct {
|
||||
char *name;
|
||||
} VERT;
|
||||
|
||||
/* Used as virtual object selector or in enumeration states */
|
||||
union vertex_edge {
|
||||
/* Virtual object selector or part of enumeration state */
|
||||
union virt {
|
||||
unsigned int vertex;
|
||||
struct {
|
||||
unsigned int src;
|
||||
unsigned int dst;
|
||||
} edge;
|
||||
unsigned int src, dst;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GB_BASE ob;
|
||||
CGRAPH base;
|
||||
int directed : 1;
|
||||
int weighted : 1;
|
||||
GB_HASHTABLE names;
|
||||
VERT *matrix;
|
||||
union vertex_edge v;
|
||||
/*
|
||||
* NOTE: This field is used by the "true" virtual object portions of
|
||||
* this class: GraphMatrix.Vertices[x] and GraphMatrix.Edges[x, y].
|
||||
*
|
||||
* In the enumerators (InEdges, OutEdges, Adjacent), we must use the
|
||||
* "current" vertex/edge which is stored within ->base.
|
||||
*/
|
||||
union virt v;
|
||||
void *gsl_matrix; /* Cache gb.gsl Matrix object of this */
|
||||
} CMATRIX;
|
||||
|
||||
@ -71,7 +77,7 @@ BEGIN_METHOD(Matrix_new, GB_BOOLEAN d; GB_BOOLEAN w)
|
||||
THIS->directed = VARGOPT(d, 0);
|
||||
THIS->weighted = VARGOPT(w, 0);
|
||||
THIS->v.vertex = -1;
|
||||
THIS->v.edge.src = THIS->v.edge.dst = -1;
|
||||
THIS->v.src = THIS->v.dst = -1;
|
||||
GB.HashTable.New(&THIS->names, GB_COMP_NOCASE);
|
||||
GB.NewArray(&THIS->matrix, sizeof(*THIS->matrix), 0);
|
||||
THIS->gsl_matrix = NULL;
|
||||
@ -105,6 +111,12 @@ static unsigned int get_vertex(CMATRIX *mat, const char *str, size_t len)
|
||||
return (unsigned int) vert;
|
||||
}
|
||||
|
||||
static unsigned int get_cur_vertex(CMATRIX *mat)
|
||||
{
|
||||
return get_vertex(mat, mat->base.vertex,
|
||||
GB.StringLength(mat->base.vertex));
|
||||
}
|
||||
|
||||
BEGIN_METHOD(Matrix_getVertex, GB_STRING vert)
|
||||
|
||||
unsigned int vert = get_vertex(THIS, STRING(vert), LENGTH(vert));
|
||||
@ -131,14 +143,13 @@ BEGIN_METHOD(Matrix_getEdge, GB_STRING src; GB_STRING dst)
|
||||
GB.Error(E_NOEDGE);
|
||||
return;
|
||||
}
|
||||
THIS->v.edge.src = src;
|
||||
THIS->v.edge.dst = dst;
|
||||
THIS->v.src = src; THIS->v.dst = dst;
|
||||
GB.ReturnSelf(THIS);
|
||||
|
||||
END_METHOD
|
||||
|
||||
struct enum_state {
|
||||
union vertex_edge cur;
|
||||
union virt v;
|
||||
GB_ARRAY e;
|
||||
};
|
||||
|
||||
@ -146,11 +157,11 @@ BEGIN_METHOD_VOID(Matrix_nextVertex)
|
||||
|
||||
struct enum_state *state = GB.GetEnum();
|
||||
|
||||
if (state->cur.vertex == GB.Count(THIS->matrix)) {
|
||||
if (state->v.vertex == GB.Count(THIS->matrix)) {
|
||||
GB.StopEnum();
|
||||
return;
|
||||
}
|
||||
GB.ReturnString(THIS->matrix[state->cur.vertex++].name);
|
||||
GB.ReturnString(THIS->matrix[state->v.vertex++].name);
|
||||
|
||||
END_METHOD
|
||||
|
||||
@ -182,7 +193,7 @@ static int next_edge(CMATRIX *mat, unsigned int *srcp, unsigned int *dstp)
|
||||
BEGIN_METHOD_VOID(Matrix_nextEdge)
|
||||
|
||||
struct enum_state *state = GB.GetEnum();
|
||||
unsigned int src = state->cur.edge.src, dst = state->cur.edge.dst;
|
||||
unsigned int src = state->v.src, dst = state->v.dst;
|
||||
|
||||
if (!state->e) {
|
||||
GB.Array.New(&state->e, GB_T_STRING, 2);
|
||||
@ -198,7 +209,7 @@ BEGIN_METHOD_VOID(Matrix_nextEdge)
|
||||
GB.Unref(&state->e);
|
||||
return;
|
||||
}
|
||||
state->cur.edge.src = src; state->cur.edge.dst = dst;
|
||||
state->v.src = src; state->v.dst = dst;
|
||||
found:;
|
||||
GB_STRING str;
|
||||
|
||||
@ -234,6 +245,115 @@ BEGIN_METHOD_VOID(Matrix_countEdges)
|
||||
|
||||
END_METHOD
|
||||
|
||||
static int next_edge_vertical(CMATRIX *mat, unsigned int *srcp,
|
||||
unsigned int *dstp)
|
||||
{
|
||||
unsigned int src = *srcp, dst = *dstp;
|
||||
unsigned int count = GB.Count(mat->matrix);
|
||||
|
||||
do {
|
||||
src = (src + 1) % count;
|
||||
if (!src)
|
||||
dst++;
|
||||
if (dst >= count)
|
||||
return -1;
|
||||
} while (!mat->matrix[src].edges[dst].set);
|
||||
*srcp = src;
|
||||
*dstp = dst;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BEGIN_METHOD_VOID(Matrix_nextInEdge)
|
||||
|
||||
struct enum_state *state = GB.GetEnum();
|
||||
unsigned int src = state->v.src, dst = THIS->v.vertex;
|
||||
|
||||
if (!state->e) {
|
||||
dst = THIS->v.vertex = get_cur_vertex(THIS);
|
||||
GB.Array.New(&state->e, GB_T_STRING, 2);
|
||||
GB.Ref(state->e);
|
||||
if (THIS->matrix[src].edges[dst].set)
|
||||
goto found;
|
||||
}
|
||||
if (next_edge_vertical(THIS, &src, &dst) || dst != THIS->v.vertex) {
|
||||
GB.StopEnum();
|
||||
GB.Unref(&state->e);
|
||||
return;
|
||||
}
|
||||
state->v.src = src;
|
||||
found:;
|
||||
GB_STRING str;
|
||||
|
||||
str.type = GB_T_STRING;
|
||||
|
||||
str.value.addr = THIS->matrix[src].name;
|
||||
str.value.start = 0;
|
||||
str.value.len = GB.StringLength(str.value.addr);
|
||||
GB.StoreString(&str, GB.Array.Get(state->e, 0));
|
||||
|
||||
str.value.addr = THIS->matrix[dst].name;
|
||||
str.value.len = GB.StringLength(str.value.addr);
|
||||
GB.StoreString(&str, GB.Array.Get(state->e, 1));
|
||||
GB.ReturnObject(state->e);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(Matrix_nextOutEdge)
|
||||
|
||||
struct enum_state *state = GB.GetEnum();
|
||||
unsigned int src = THIS->v.vertex, dst = state->v.dst;
|
||||
|
||||
if (!state->e) {
|
||||
src = THIS->v.vertex = get_cur_vertex(THIS);
|
||||
GB.Array.New(&state->e, GB_T_STRING, 2);
|
||||
GB.Ref(state->e);
|
||||
if (THIS->matrix[src].edges[dst].set)
|
||||
goto found;
|
||||
}
|
||||
if (next_edge(THIS, &src, &dst) || src != THIS->v.vertex) {
|
||||
GB.StopEnum();
|
||||
GB.Unref(&state->e);
|
||||
return;
|
||||
}
|
||||
state->v.dst = dst;
|
||||
found:;
|
||||
GB_STRING str;
|
||||
|
||||
str.type = GB_T_STRING;
|
||||
|
||||
str.value.addr = THIS->matrix[src].name;
|
||||
str.value.start = 0;
|
||||
str.value.len = GB.StringLength(str.value.addr);
|
||||
GB.StoreString(&str, GB.Array.Get(state->e, 0));
|
||||
|
||||
str.value.addr = THIS->matrix[dst].name;
|
||||
str.value.len = GB.StringLength(str.value.addr);
|
||||
GB.StoreString(&str, GB.Array.Get(state->e, 1));
|
||||
GB.ReturnObject(state->e);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(Matrix_nextAdjacent)
|
||||
|
||||
struct enum_state *state = GB.GetEnum();
|
||||
unsigned int src = THIS->v.vertex, dst = state->v.dst;
|
||||
|
||||
if (!state->e) {
|
||||
src = THIS->v.vertex = get_cur_vertex(THIS);
|
||||
state->e = (void *) 1;
|
||||
if (THIS->matrix[src].edges[dst].set)
|
||||
goto found;
|
||||
}
|
||||
if (next_edge(THIS, &src, &dst) || src != THIS->v.vertex) {
|
||||
GB.StopEnum();
|
||||
return;
|
||||
}
|
||||
state->v.dst = dst;
|
||||
found:
|
||||
GB.ReturnString(THIS->matrix[dst].name);
|
||||
|
||||
END_METHOD
|
||||
|
||||
/* TODO: This is used in Add() and Remove() to completely delete the gb.gsl
|
||||
* matrix. We could also enlarge/shrink it accordingly... */
|
||||
static void invalidate_gsl_matrix(CMATRIX *mat)
|
||||
@ -315,27 +435,24 @@ BEGIN_METHOD(Matrix_Remove, GB_STRING vert)
|
||||
|
||||
END_METHOD
|
||||
|
||||
/**G
|
||||
* A newly created edge has weight 1. You can use the return value of this
|
||||
* method to change it.
|
||||
*/
|
||||
BEGIN_METHOD(Matrix_Connect, GB_STRING src; GB_STRING dst)
|
||||
BEGIN_METHOD(Matrix_Connect, GB_STRING src; GB_STRING dst; GB_FLOAT w)
|
||||
|
||||
unsigned int src = get_vertex(THIS, STRING(src), LENGTH(src)),
|
||||
dst = get_vertex(THIS, STRING(dst), LENGTH(dst));
|
||||
float w = VARGOPT(w, 1);
|
||||
|
||||
if (src == -1 || dst == -1) {
|
||||
GB.Error(E_NOVERTEX);
|
||||
return;
|
||||
}
|
||||
THIS->matrix[src].edges[dst].set = 1;
|
||||
THIS->matrix[src].edges[dst].weight = 1;
|
||||
THIS->v.edge.src = src; THIS->v.edge.dst = dst;
|
||||
THIS->matrix[src].edges[dst].weight = w;
|
||||
THIS->v.src = src; THIS->v.dst = dst;
|
||||
update_gsl_matrix(THIS, src, dst);
|
||||
/* Duplicate if the graph is undirected */
|
||||
if (!THIS->directed && src != dst) {
|
||||
THIS->matrix[dst].edges[src].set = 1;
|
||||
THIS->matrix[dst].edges[src].weight = 1;
|
||||
THIS->matrix[dst].edges[src].weight = w;
|
||||
update_gsl_matrix(THIS, dst, src);
|
||||
}
|
||||
|
||||
@ -408,8 +525,8 @@ GB_DESC CGraphMatrix[] = {
|
||||
GB_METHOD("_new", NULL, Matrix_new, "[(Directed)b(Weighted)b]"),
|
||||
GB_METHOD("_free", NULL, Matrix_free, NULL),
|
||||
|
||||
GB_METHOD("_getVertex", "_Matrix_Vertex", Matrix_getVertex, "(Vertex)s"),
|
||||
GB_METHOD("_getEdge", "_Matrix_Edge", Matrix_getEdge, "(Src)s(Dst)s"),
|
||||
GB_METHOD("_getVertex", ".Matrix.Vertex", Matrix_getVertex, "(Vertex)s"),
|
||||
GB_METHOD("_getEdge", ".Matrix.Edge", Matrix_getEdge, "(Src)s(Dst)s"),
|
||||
|
||||
GB_METHOD("_nextVertex", "s", Matrix_nextVertex, NULL),
|
||||
GB_METHOD("_nextEdge", "String[]", Matrix_nextEdge, NULL),
|
||||
@ -417,11 +534,18 @@ GB_DESC CGraphMatrix[] = {
|
||||
GB_METHOD("_countVertices", "i", Matrix_countVertices, NULL),
|
||||
GB_METHOD("_countEdges", "i", Matrix_countEdges, NULL),
|
||||
|
||||
GB_METHOD("Add", "_Matrix_Vertex", Matrix_Add, "(Name)s"),
|
||||
GB_METHOD("_nextInEdge", "String[]", Matrix_nextInEdge, NULL),
|
||||
GB_METHOD("_nextOutEdge", "String[]", Matrix_nextOutEdge, NULL),
|
||||
GB_METHOD("_nextAdjacent", "s", Matrix_nextAdjacent, NULL),
|
||||
|
||||
GB_METHOD("Add", ".Matrix.Vertex", Matrix_Add, "(Name)s"),
|
||||
GB_METHOD("Remove", NULL, Matrix_Remove, "(Vertex)s"),
|
||||
GB_METHOD("Connect", "_Matrix_Edge", Matrix_Connect, "(Src)s(Dst)s"),
|
||||
GB_METHOD("Connect", ".Matrix.Edge", Matrix_Connect, "(Src)s(Dst)s[(Weight)f]"),
|
||||
GB_METHOD("Disconnect", NULL, Matrix_Disconnect, "(Src)s(Dst)s"),
|
||||
|
||||
GB_PROPERTY_SELF("Vertices", ".Matrix.Vertices"),
|
||||
GB_PROPERTY_SELF("Edges", ".Matrix.Edges"),
|
||||
|
||||
/*
|
||||
* Require gb.gsl.
|
||||
*/
|
||||
@ -431,97 +555,38 @@ GB_DESC CGraphMatrix[] = {
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
static int next_edge_vertical(CMATRIX *mat, unsigned int *srcp,
|
||||
unsigned int *dstp)
|
||||
{
|
||||
unsigned int src = *srcp, dst = *dstp;
|
||||
unsigned int count = GB.Count(mat->matrix);
|
||||
BEGIN_METHOD(MatrixVertices_get, GB_STRING vert)
|
||||
|
||||
do {
|
||||
src = (src + 1) % count;
|
||||
if (!src)
|
||||
dst++;
|
||||
if (dst >= count)
|
||||
return -1;
|
||||
} while (!mat->matrix[src].edges[dst].set);
|
||||
*srcp = src;
|
||||
*dstp = dst;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BEGIN_METHOD_VOID(MatrixVertex_nextInEdge)
|
||||
|
||||
struct enum_state *state = GB.GetEnum();
|
||||
unsigned int src = state->cur.edge.src, dst = THIS->v.vertex;
|
||||
|
||||
if (!state->e) {
|
||||
GB.Array.New(&state->e, GB_T_STRING, 2);
|
||||
GB.Ref(state->e);
|
||||
if (THIS->matrix[src].edges[dst].set)
|
||||
goto found;
|
||||
}
|
||||
if (next_edge_vertical(THIS, &src, &dst) || dst != THIS->v.vertex) {
|
||||
GB.StopEnum();
|
||||
GB.Unref(&state->e);
|
||||
return;
|
||||
}
|
||||
state->cur.edge.src = src;
|
||||
found:;
|
||||
GB_STRING str;
|
||||
|
||||
str.type = GB_T_STRING;
|
||||
|
||||
str.value.addr = THIS->matrix[src].name;
|
||||
str.value.start = 0;
|
||||
str.value.len = GB.StringLength(str.value.addr);
|
||||
GB.StoreString(&str, GB.Array.Get(state->e, 0));
|
||||
|
||||
str.value.addr = THIS->matrix[dst].name;
|
||||
str.value.len = GB.StringLength(str.value.addr);
|
||||
GB.StoreString(&str, GB.Array.Get(state->e, 1));
|
||||
GB.ReturnObject(state->e);
|
||||
THIS->v.vertex = get_vertex(THIS, STRING(vert), LENGTH(vert));
|
||||
GB.ReturnSelf(THIS);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(MatrixVertex_nextOutEdge)
|
||||
GB_DESC CMatrixVertices[] = {
|
||||
GB_DECLARE_VIRTUAL(".Matrix.Vertices"),
|
||||
GB_INHERITS(".Graph.Vertices"),
|
||||
|
||||
struct enum_state *state = GB.GetEnum();
|
||||
unsigned int src = THIS->v.vertex, dst = state->cur.edge.dst;
|
||||
GB_METHOD("_get", ".Matrix.Vertex", MatrixVertices_get, "(Vertex)s"),
|
||||
|
||||
if (!state->e) {
|
||||
GB.Array.New(&state->e, GB_T_STRING, 2);
|
||||
GB.Ref(state->e);
|
||||
if (THIS->matrix[src].edges[dst].set)
|
||||
goto found;
|
||||
}
|
||||
if (next_edge(THIS, &src, &dst) || src != THIS->v.vertex) {
|
||||
GB.StopEnum();
|
||||
GB.Unref(&state->e);
|
||||
return;
|
||||
}
|
||||
state->cur.edge.dst = dst;
|
||||
found:;
|
||||
GB_STRING str;
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
str.type = GB_T_STRING;
|
||||
BEGIN_METHOD(MatrixEdges_get, GB_STRING src; GB_STRING dst)
|
||||
|
||||
str.value.addr = THIS->matrix[src].name;
|
||||
str.value.start = 0;
|
||||
str.value.len = GB.StringLength(str.value.addr);
|
||||
GB.StoreString(&str, GB.Array.Get(state->e, 0));
|
||||
|
||||
str.value.addr = THIS->matrix[dst].name;
|
||||
str.value.len = GB.StringLength(str.value.addr);
|
||||
GB.StoreString(&str, GB.Array.Get(state->e, 1));
|
||||
GB.ReturnObject(state->e);
|
||||
THIS->v.src = get_vertex(THIS, STRING(src), LENGTH(src));
|
||||
THIS->v.dst = get_vertex(THIS, STRING(dst), LENGTH(dst));
|
||||
GB.ReturnSelf(THIS);
|
||||
|
||||
END_METHOD
|
||||
|
||||
BEGIN_METHOD_VOID(MatrixVertex_nextAdjacent)
|
||||
GB_DESC CMatrixEdges[] = {
|
||||
GB_DECLARE_VIRTUAL(".Matrix.Edges"),
|
||||
GB_INHERITS(".Graph.Edges"),
|
||||
|
||||
/* TODO */
|
||||
GB_METHOD("_get", ".Matrix.Edge", MatrixEdges_get, "(Src)s(Dst)s"),
|
||||
|
||||
END_METHOD
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
BEGIN_PROPERTY(MatrixVertex_InDegree)
|
||||
|
||||
@ -547,11 +612,18 @@ END_PROPERTY
|
||||
|
||||
BEGIN_PROPERTY(MatrixVertex_Name)
|
||||
|
||||
char *name = THIS->matrix[THIS->v.vertex].name;
|
||||
|
||||
if (READ_PROPERTY) {
|
||||
GB.ReturnString(THIS->matrix[THIS->v.vertex].name);
|
||||
GB.ReturnString(name);
|
||||
return;
|
||||
}
|
||||
/* delete old name from ->names, then register new one */
|
||||
GB.HashTable.Remove(THIS->names, name, GB.StringLength(name));
|
||||
GB.FreeString(&THIS->matrix[THIS->v.vertex].name);
|
||||
THIS->matrix[THIS->v.vertex].name =
|
||||
GB.NewString(PSTRING(), PLENGTH());
|
||||
GB.HashTable.Add(THIS->names, PSTRING(), PLENGTH(),
|
||||
(void *) (intptr_t) THIS->v.vertex);
|
||||
|
||||
END_PROPERTY
|
||||
|
||||
@ -566,13 +638,8 @@ BEGIN_PROPERTY(MatrixVertex_Value)
|
||||
END_METHOD
|
||||
|
||||
GB_DESC CMatrixVertex[] = {
|
||||
GB_DECLARE("_Matrix_Vertex", 0),
|
||||
GB_INHERITS("_Graph_Vertex"),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
|
||||
GB_METHOD("_nextInEdge", "String[]", MatrixVertex_nextInEdge, NULL),
|
||||
GB_METHOD("_nextOutEdge", "String[]", MatrixVertex_nextOutEdge, NULL),
|
||||
GB_METHOD("_nextAdjacent", "s", MatrixVertex_nextAdjacent, NULL),
|
||||
GB_DECLARE_VIRTUAL(".Matrix.Vertex"),
|
||||
GB_INHERITS(".Graph.Vertex"),
|
||||
|
||||
GB_PROPERTY_READ("InDegree", "i", MatrixVertex_InDegree),
|
||||
GB_PROPERTY_READ("OutDegree", "i", MatrixVertex_OutDegree),
|
||||
@ -584,7 +651,7 @@ GB_DESC CMatrixVertex[] = {
|
||||
|
||||
BEGIN_PROPERTY(MatrixEdge_Src)
|
||||
|
||||
int src = THIS->v.edge.src;
|
||||
int src = THIS->v.src;
|
||||
|
||||
GB.ReturnString(THIS->matrix[src].name);
|
||||
|
||||
@ -592,7 +659,7 @@ END_PROPERTY
|
||||
|
||||
BEGIN_PROPERTY(MatrixEdge_Dst)
|
||||
|
||||
int dst = THIS->v.edge.dst;
|
||||
int dst = THIS->v.dst;
|
||||
|
||||
GB.ReturnString(THIS->matrix[dst].name);
|
||||
|
||||
@ -600,7 +667,7 @@ END_PROPERTY
|
||||
|
||||
BEGIN_PROPERTY(MatrixEdge_Weight)
|
||||
|
||||
int src = THIS->v.edge.src, dst = THIS->v.edge.dst;
|
||||
int src = THIS->v.src, dst = THIS->v.dst;
|
||||
|
||||
if (READ_PROPERTY) {
|
||||
GB.ReturnFloat(THIS->matrix[src].edges[dst].weight);
|
||||
@ -613,9 +680,8 @@ BEGIN_PROPERTY(MatrixEdge_Weight)
|
||||
END_PROPERTY
|
||||
|
||||
GB_DESC CMatrixEdge[] = {
|
||||
GB_DECLARE("_Matrix_Edge", 0),
|
||||
GB_INHERITS("_Graph_Edge"),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
GB_DECLARE_VIRTUAL(".Matrix.Edge"),
|
||||
GB_INHERITS(".Graph.Edge"),
|
||||
|
||||
GB_PROPERTY_READ("Src", "s", MatrixEdge_Src),
|
||||
GB_PROPERTY_READ("Dst", "s", MatrixEdge_Dst),
|
||||
|
@ -27,7 +27,8 @@
|
||||
extern GB_INTERFACE GB;
|
||||
|
||||
#ifndef __C_GRAPHMATRIX_C
|
||||
extern GB_DESC CGraphMatrix[], CMatrixVertex[], CMatrixEdge[];
|
||||
extern GB_DESC CGraphMatrix[], CMatrixVertices[], CMatrixEdges[],
|
||||
CMatrixVertex[], CMatrixEdge[];
|
||||
#endif
|
||||
|
||||
#endif /* __C_GRAPHMATRIX_H */
|
||||
|
@ -1310,8 +1310,7 @@ GB_DESC CList[] = {
|
||||
};
|
||||
|
||||
GB_DESC CListBackwards[] = {
|
||||
GB_DECLARE(".List.Backwards", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
GB_DECLARE_VIRTUAL(".List.Backwards"),
|
||||
|
||||
GB_METHOD("_next", "v", ListBackwards_next, NULL),
|
||||
|
||||
@ -1349,8 +1348,7 @@ BEGIN_PROPERTY(ListItem_IsValid)
|
||||
END_PROPERTY
|
||||
|
||||
GB_DESC CListItem[] = {
|
||||
GB_DECLARE(".List.Item", 0),
|
||||
GB_VIRTUAL_CLASS(),
|
||||
GB_DECLARE_VIRTUAL(".List.Item"),
|
||||
|
||||
GB_METHOD("Append", NULL, ListItem_Append, "(Value)v"),
|
||||
GB_METHOD("Prepend", NULL, ListItem_Prepend, "(Value)v"),
|
||||
|
@ -51,14 +51,16 @@ GB_DESC *GB_CLASSES[] EXPORT = {
|
||||
|
||||
CGraph,
|
||||
CGraphVertices,
|
||||
CGraphVertex,
|
||||
CVertexInEdges,
|
||||
CVertexOutEdges,
|
||||
CVertexAdjacent,
|
||||
CGraphEdges,
|
||||
CGraphInEdges,
|
||||
CGraphOutEdges,
|
||||
CGraphAdjacent,
|
||||
CGraphVertex,
|
||||
CGraphEdge,
|
||||
|
||||
CGraphMatrix,
|
||||
CMatrixVertices,
|
||||
CMatrixEdges,
|
||||
CMatrixVertex,
|
||||
CMatrixEdge,
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user