Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libvgraph/graph.c
1808 views
1
#include "grhdr.h"
2
3
/******************************************************************************
4
This defines a collection of basic operations on directed graphs.
5
Written by Kiem-Phong Vo (02/01/2006).
6
******************************************************************************/
7
8
/* CDT discipline for nodeset */
9
static int nodecmp(Dt_t* nodes, Void_t* one, Void_t* two, Dtdisc_t* disc)
10
{
11
Grnode_t *n1 = (Grnode_t*)one;
12
Grnode_t *n2 = (Grnode_t*)two;
13
14
if(n1->label != n2->label)
15
return n1->label < n2->label ? -1 : 1;
16
else return 0;
17
}
18
19
static void nodefree(Dt_t* nodes, Void_t* node, Dtdisc_t* disc)
20
{
21
Graph_t *gr = GRSTRUCTOF(Graph_t, nddc, disc);
22
Grdata_t *dt, *next;
23
24
if(node)
25
{ if(gr->disc && gr->disc->eventf)
26
(*gr->disc->eventf)(gr, GR_NODE|GR_CLOSING, node, gr->disc );
27
28
for(dt = ((Grnode_t*)node)->data; dt; dt = next)
29
{ next = dt->next;
30
(*dt->algo->dataf)(dt->algo, GR_NODE|GR_CLOSING, dt);
31
}
32
33
free(node);
34
}
35
}
36
37
/* CDT discipline for edgeset */
38
static int edgecmp(Dt_t* edges, Void_t* one, Void_t* two, Dtdisc_t* disc)
39
{
40
Gredge_t *e1 = (Gredge_t*)one;
41
Gredge_t *e2 = (Gredge_t*)two;
42
43
if(e1->tail != e2->tail)
44
return e1->tail < e2->tail ? -1 : 1;
45
else if(e1->head != e2->head)
46
return e1->head < e2->head ? -1 : 1;
47
else if(e1->label != e2->label )
48
return e1->label < e2->label ? -1 : 1;
49
else return 0;
50
}
51
52
static void edgefree(Dt_t* edges, Void_t* edge, Dtdisc_t* disc)
53
{
54
Graph_t *gr = GRSTRUCTOF(Graph_t, eddc, disc);
55
Grdata_t *dt, *next;
56
57
if(edge)
58
{ if(gr->disc && gr->disc->eventf)
59
(*gr->disc->eventf)(gr, GR_EDGE|GR_CLOSING, edge, gr->disc );
60
61
for(dt = ((Gredge_t*)edge)->data; dt; dt = next)
62
{ next = dt->next;
63
(*dt->algo->dataf)(dt->algo, GR_EDGE|GR_CLOSING, dt);
64
}
65
66
free(edge);
67
}
68
}
69
70
/* function to find/create/delete nodes */
71
Grnode_t* grnode(Graph_t* gr, Void_t* label, int type)
72
{
73
Grnode_t node, *nd;
74
Gredge_t *e, *enext;
75
ssize_t sz;
76
77
if(!gr)
78
return NIL(Grnode_t*);
79
80
/* see if the node already exists */
81
node.label = label;
82
nd = dtsearch(gr->nodes, &node);
83
84
if(type < 0) /* deleting a node */
85
{ if(nd)
86
{ for(e = nd->oedge; e; e = enext)
87
{ enext = e;
88
gredge(gr, e->tail, e->head, e->label, -1);
89
}
90
for(e = nd->iedge; e; e = enext)
91
{ enext = e;
92
gredge(gr, e->tail, e->head, e->label, -1);
93
}
94
dtdelete(gr->nodes, nd);
95
}
96
return NIL(Grnode_t*);
97
}
98
99
if(type == 0 || nd) /* finding only or inserting an existing node */
100
return nd;
101
102
/* making a new node */
103
if((sz = gr->disc ? gr->disc->nodesz : 0) < sizeof(Grnode_t) )
104
sz = sizeof(Grnode_t);
105
if(!(nd = (Grnode_t*)calloc(1, sz)) )
106
return NIL(Grnode_t*);
107
108
nd->label = label;
109
nd->fold = nd;
110
111
if(gr->disc && gr->disc->eventf)
112
(*gr->disc->eventf)(gr, GR_NODE|GR_OPENING, nd, gr->disc);
113
114
return (Grnode_t*)dtinsert(gr->nodes, nd);
115
}
116
117
/* function to find/create/delete edges */
118
Gredge_t* gredge(Graph_t* gr, Grnode_t* tail, Grnode_t* head, Void_t* label, int type)
119
{
120
Gredge_t edge, *ed, *e, *pe;
121
Grnode_t *nd;
122
ssize_t sz;
123
124
if(gr->type == GR_UNDIRECTED) /* enforce tail <= head */
125
if(tail > head)
126
{ nd = tail; tail = head; head = nd; }
127
128
if(!(edge.tail = tail) || !(edge.head = head) )
129
return NIL(Gredge_t*);
130
131
/* see if the edge exists */
132
edge.label = label;
133
ed = dtsearch(gr->edges, &edge);
134
135
if(type < 0) /* deleting */
136
{ if(ed)
137
{ for(pe = NIL(Gredge_t*), e = ed->tail->oedge; e; pe = e, e = e->onext)
138
{ if(e == ed)
139
{ if(pe)
140
pe->onext = e->onext;
141
else ed->tail->oedge->onext = e->onext;
142
break;
143
}
144
}
145
for(pe = NIL(Gredge_t*), e = ed->head->iedge; e; pe = e, e = e->inext)
146
{ if(e == ed)
147
{ if(pe)
148
pe->inext = e->inext;
149
else ed->head->iedge->inext = e->inext;
150
break;
151
}
152
}
153
154
dtdelete(gr->edges, ed);
155
}
156
return NIL(Gredge_t*);
157
}
158
159
if(type == 0 || ed) /* only searching or edge already exists */
160
return ed;
161
162
if((sz = gr->disc ? gr->disc->edgesz : 0) < sizeof(Gredge_t))
163
sz = sizeof(Gredge_t);
164
if(!(ed = (Gredge_t*)calloc(1, sz)) )
165
return NIL(Gredge_t*);
166
167
ed->label = label;
168
ed->tail = edge.tail;
169
ed->head = edge.head;
170
ed->inext = edge.head->iedge; edge.head->iedge = ed;
171
ed->onext = edge.tail->oedge; edge.tail->oedge = ed;
172
173
if(gr->disc && gr->disc->eventf)
174
(*gr->disc->eventf)(gr, GR_EDGE|GR_OPENING, ed, gr->disc);
175
176
return (Gredge_t*)dtinsert(gr->edges, ed);
177
}
178
179
/* contruct/return the data associated with an algorithm */
180
Grdata_t* _grdata(Grdata_t** data, Gralgo_t* algo, int type)
181
{
182
Grdata_t *dt, *pd;
183
184
if(type != GR_NODE && type != GR_EDGE && type != GR_GRAPH)
185
return NIL(Grdata_t*);
186
187
for(pd = NIL(Grdata_t*), dt = *data; dt; pd = dt, dt = dt->next)
188
if(dt->algo == algo)
189
break;
190
if(pd && dt) /* isolate from list */
191
pd->next = dt->next;
192
else if(dt)
193
*data = dt->next;
194
else if(!(dt = (*algo->dataf)(algo, type|GR_OPENING, 0)) )
195
return NIL(Grdata_t*);
196
else dt->algo = algo; /* set the algorithm that made this data */
197
198
/* put this at front of list for fast future accesses */
199
dt->next = *data; *data = dt;
200
201
return dt;
202
}
203
204
/* restore a graph after manipulation of nodes and edges */
205
int grrestore(Graph_t* gr)
206
{
207
Grnode_t *nd;
208
Gredge_t *ed;
209
210
for(nd = (Grnode_t*)dtflatten(gr->nodes); nd; nd = (Grnode_t*)dtlink(gr,nd))
211
{ nd->oedge = nd->iedge = NIL(Gredge_t*);
212
nd->fold = nd;
213
nd->link = NIL(Grnode_t*);
214
}
215
for(ed = (Gredge_t*)dtflatten(gr->edges); ed; ed = (Gredge_t*)dtlink(gr,ed))
216
{ ed->onext = ed->tail->oedge; ed->tail->oedge = ed;
217
ed->inext = ed->head->iedge; ed->head->iedge = ed;
218
ed->link = NIL(Gredge_t*);
219
}
220
221
return 0;
222
}
223
224
/* functions to open/close a graph structure */
225
int grclose(Graph_t* gr)
226
{
227
Grdata_t *dt, *next;
228
229
if(!gr)
230
return -1;
231
232
if(gr->disc && gr->disc->eventf )
233
if((*gr->disc->eventf)(gr, GR_GRAPH|GR_CLOSING, 0, gr->disc) < 0)
234
return -1;
235
236
if(gr->nodes)
237
dtclose(gr->nodes);
238
if(gr->edges)
239
dtclose(gr->edges);
240
241
for(dt = gr->data; dt; dt = next)
242
{ next = dt->next;
243
(*dt->algo->dataf)(dt->algo, GR_GRAPH|GR_CLOSING, dt);
244
}
245
246
free(gr);
247
return 0;
248
}
249
250
Graph_t* gropen(Grdisc_t* disc, int type)
251
{
252
Graph_t *gr;
253
ssize_t sz;
254
255
if((sz = disc ? disc->graphsz : 0) < sizeof(Graph_t) )
256
sz = sizeof(Graph_t);
257
if(!(gr = (Graph_t*)calloc(1,sz)) )
258
return NIL(Graph_t*);
259
260
gr->type = type;
261
262
DTDISC(&gr->nddc, 0, 0, 0, 0, nodefree, nodecmp, 0, 0, 0);
263
DTDISC(&gr->eddc, 0, 0, 0, 0, edgefree, edgecmp, 0, 0, 0);
264
265
if(!(gr->nodes = dtopen(&gr->nddc, Dtoset)) ||
266
!(gr->edges = dtopen(&gr->eddc, Dtoset)) )
267
{ grclose(gr);
268
return NIL(Graph_t*);
269
}
270
271
if((gr->disc = disc) && (*gr->disc->eventf)(gr, GR_GRAPH|GR_OPENING, 0, gr->disc) < 0)
272
{ grclose(gr);
273
return NIL(Graph_t*);
274
}
275
276
return gr;
277
}
278
279