Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
obj.c
Go to the documentation of this file.
1
4
5/*************************************************************************
6 * Copyright (c) 2011 AT&T Intellectual Property
7 * All rights reserved. This program and the accompanying materials
8 * are made available under the terms of the Eclipse Public License v1.0
9 * which accompanies this distribution, and is available at
10 * https://www.eclipse.org/legal/epl-v10.html
11 *
12 * Contributors: Details at https://graphviz.org
13 *************************************************************************/
14
15#include <cgraph/cghdr.h>
16#include <stdlib.h>
17#include <util/alloc.h>
18#include <util/unreachable.h>
19
20int agdelete(Agraph_t * g, void *obj)
21{
22 if (AGTYPE(obj) == AGRAPH && g != agparent(obj)) {
23 agerrorf("agdelete on wrong graph");
24 return FAILURE;
25 }
26
27 switch (AGTYPE(obj)) {
28 case AGNODE:
29 return agdelnode(g, obj);
30 case AGINEDGE:
31 case AGOUTEDGE:
32 return agdeledge(g, obj);
33 case AGRAPH:
34 return agclose(obj);
35 default:
36 agerrorf("agdelete on bad object");
37 }
38 return SUCCESS; /* not reached */
39}
40
41int agrename(Agobj_t * obj, char *newname)
42{
43 Agraph_t *g;
44 IDTYPE old_id, new_id;
45
46 switch (AGTYPE(obj)) {
47 case AGRAPH:
48 old_id = AGID(obj);
49 g = agraphof(obj);
50 /* can we reserve the id corresponding to newname? */
51 if (agmapnametoid(agroot(g), AGTYPE(obj), newname, &new_id, false) == 0)
52 return FAILURE;
53 if (new_id == old_id)
54 return SUCCESS;
55 if (agmapnametoid(agroot(g), AGTYPE(obj), newname, &new_id, true) == 0)
56 return FAILURE;
57 /* obj* is unchanged, so no need to re agregister() */
58 if (agparent(g) && agidsubg(agparent(g), new_id, 0))
59 return FAILURE;
60 agfreeid(g, AGRAPH, old_id);
61 AGID(g) = new_id;
62 break;
63 case AGNODE:
64 return agrelabel_node((Agnode_t *) obj, newname);
65 case AGINEDGE:
66 case AGOUTEDGE:
67 return FAILURE;
68 default:
70 }
71 return SUCCESS;
72}
73
74/* perform initialization/update/finalization method invocation.
75 * skip over nil pointers to next method below.
76 */
77
78void agmethod_init(Agraph_t * g, void *obj)
79{
80 aginitcb(g, obj, g->clos->cb);
81}
82
83void aginitcb(Agraph_t * g, void *obj, Agcbstack_t * cbstack)
84{
85 agobjfn_t fn;
86
87 if (cbstack == NULL)
88 return;
89 aginitcb(g, obj, cbstack->prev);
90 fn = NULL;
91 switch (AGTYPE(obj)) {
92 case AGRAPH:
93 fn = cbstack->f->graph.ins;
94 break;
95 case AGNODE:
96 fn = cbstack->f->node.ins;
97 break;
98 case AGEDGE:
99 fn = cbstack->f->edge.ins;
100 break;
101 default: // ignore
102 break;
103 }
104 if (fn)
105 fn(g, obj, cbstack->state);
106}
107
108void agmethod_upd(Agraph_t * g, void *obj, Agsym_t * sym)
109{
110 agupdcb(g, obj, sym, g->clos->cb);
111}
112
113void agupdcb(Agraph_t * g, void *obj, Agsym_t * sym, Agcbstack_t * cbstack)
114{
115 agobjupdfn_t fn;
116
117 if (cbstack == NULL)
118 return;
119 agupdcb(g, obj, sym, cbstack->prev);
120 fn = NULL;
121 switch (AGTYPE(obj)) {
122 case AGRAPH:
123 fn = cbstack->f->graph.mod;
124 break;
125 case AGNODE:
126 fn = cbstack->f->node.mod;
127 break;
128 case AGEDGE:
129 fn = cbstack->f->edge.mod;
130 break;
131 default: // ignore
132 break;
133 }
134 if (fn)
135 fn(g, obj, cbstack->state, sym);
136}
137
138void agmethod_delete(Agraph_t * g, void *obj)
139{
140 agdelcb(g, obj, g->clos->cb);
141}
142
143void agdelcb(Agraph_t * g, void *obj, Agcbstack_t * cbstack)
144{
145 agobjfn_t fn;
146
147 if (cbstack == NULL)
148 return;
149 agdelcb(g, obj, cbstack->prev);
150 fn = NULL;
151 switch (AGTYPE(obj)) {
152 case AGRAPH:
153 fn = cbstack->f->graph.del;
154 break;
155 case AGNODE:
156 fn = cbstack->f->node.del;
157 break;
158 case AGEDGE:
159 fn = cbstack->f->edge.del;
160 break;
161 default: // ignore
162 break;
163 }
164 if (fn)
165 fn(g, obj, cbstack->state);
166}
167
168Agraph_t *agroot(void* obj)
169{
170 if (obj == 0) return NULL;
171 switch (AGTYPE(obj)) {
172 case AGINEDGE:
173 case AGOUTEDGE:
174 return ((Agedge_t *) obj)->node->root;
175 case AGNODE:
176 return ((Agnode_t *) obj)->root;
177 case AGRAPH:
178 return ((Agraph_t *) obj)->root;
179 default: /* actually can't occur if only 2 bit tags */
180 agerrorf("agroot of a bad object");
181 return NULL;
182 }
183}
184
186{
187 switch (AGTYPE(obj)) {
188 case AGINEDGE:
189 case AGOUTEDGE:
190 return ((Agedge_t *) obj)->node->root;
191 case AGNODE:
192 return ((Agnode_t *) obj)->root;
193 case AGRAPH:
194 return obj;
195 default: /* actually can't occur if only 2 bit tags */
196 agerrorf("agraphof a bad object");
197 return NULL;
198 }
199}
200
201/* to manage disciplines */
202void agpushdisc(Agraph_t * g, Agcbdisc_t * cbd, void *state)
203{
204 Agcbstack_t *stack_ent = gv_alloc(sizeof(Agcbstack_t));
205 stack_ent->f = cbd;
206 stack_ent->state = state;
207 stack_ent->prev = g->clos->cb;
208 g->clos->cb = stack_ent;
209}
210
212{
213 Agcbstack_t *stack_ent;
214
215 stack_ent = g->clos->cb;
216 if (stack_ent) {
217 if (stack_ent->f == cbd)
218 g->clos->cb = stack_ent->prev;
219 else {
220 while (stack_ent && stack_ent->prev->f != cbd)
221 stack_ent = stack_ent->prev;
222 if (stack_ent && stack_ent->prev)
223 stack_ent->prev = stack_ent->prev->prev;
224 }
225 if (stack_ent) {
226 free(stack_ent);
227 return SUCCESS;
228 }
229 }
230 return FAILURE;
231}
232
233int agcontains(Agraph_t* g, void* obj)
234{
235 Agraph_t* subg;
236
237 if (agroot (g) != agroot (obj)) return 0;
238 switch (AGTYPE(obj)) {
239 case AGRAPH:
240 subg = obj;
241 do {
242 if (subg == g) return 1;
243 } while ((subg = agparent (subg)));
244 return 0;
245 case AGNODE:
246 return agidnode(g, AGID(obj), 0) != 0;
247 default:
248 return agsubedge(g, obj, 0) != 0;
249 }
250}
251
252int agobjkind(void *arg)
253{
254 return AGTYPE(arg);
255}
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
cgraph.h additions
void agfreeid(Agraph_t *g, int objtype, IDTYPE id)
Definition id.c:146
int agmapnametoid(Agraph_t *g, int objtype, char *str, IDTYPE *result, bool createflag)
Definition id.c:112
#define FAILURE
Definition cghdr.h:45
#define SUCCESS
Definition cghdr.h:44
void free(void *)
node NULL
Definition grammar.y:163
void agupdcb(Agraph_t *g, void *obj, Agsym_t *sym, Agcbstack_t *cbstack)
Definition obj.c:113
void agdelcb(Agraph_t *g, void *obj, Agcbstack_t *cbstack)
Definition obj.c:143
void aginitcb(Agraph_t *g, void *obj, Agcbstack_t *cbstack)
Definition obj.c:83
int agpopdisc(Agraph_t *g, Agcbdisc_t *cbd)
Definition obj.c:211
void agmethod_delete(Agraph_t *g, void *obj)
Definition obj.c:138
void agpushdisc(Agraph_t *g, Agcbdisc_t *cbd, void *state)
Definition obj.c:202
void agmethod_init(Agraph_t *g, void *obj)
Definition obj.c:78
void agmethod_upd(Agraph_t *g, void *obj, Agsym_t *sym)
Definition obj.c:108
Agedge_t * agsubedge(Agraph_t *g, Agedge_t *e, int createflag)
Definition edge.c:355
int agdeledge(Agraph_t *g, Agedge_t *arg_e)
Definition edge.c:334
void agerrorf(const char *fmt,...)
Definition agerror.c:165
void(* agobjupdfn_t)(Agraph_t *g, Agobj_t *obj, void *arg, Agsym_t *sym)
Definition cgraph.h:370
void(* agobjfn_t)(Agraph_t *g, Agobj_t *obj, void *arg)
Definition cgraph.h:369
int agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
Definition graph.c:102
Agnode_t * agidnode(Agraph_t *g, IDTYPE id, int createflag)
Definition node.c:122
int agrelabel_node(Agnode_t *n, char *newname)
Definition node.c:237
int agdelnode(Agraph_t *g, Agnode_t *arg_n)
removes a node from a graph or subgraph.
Definition node.c:195
Agraph_t * agraphof(void *obj)
Definition obj.c:185
#define AGID(obj)
returns the unique integer ID associated with the object
Definition cgraph.h:221
uint64_t IDTYPE
unique per main graph ID
Definition cgraph.h:73
#define AGTYPE(obj)
returns AGRAPH, AGNODE, or AGEDGE depending on the type of the object
Definition cgraph.h:216
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
Definition obj.c:20
int agcontains(Agraph_t *g, void *obj)
returns non-zero if obj is a member of (sub)graph
Definition obj.c:233
int agobjkind(void *arg)
Definition obj.c:252
Agraph_t * agroot(void *obj)
Definition obj.c:168
@ AGOUTEDGE
Definition cgraph.h:207
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
@ AGINEDGE
Definition cgraph.h:207
@ AGRAPH
Definition cgraph.h:207
Agraph_t * agparent(Agraph_t *g)
Definition subg.c:91
Agraph_t * agidsubg(Agraph_t *g, IDTYPE id, int cflag)
Definition subg.c:49
int agrename(Agobj_t *obj, char *newname)
Definition obj.c:41
client event callbacks, used in Agcbstack_s
Definition cgraph.h:388
agobjupdfn_t mod
Definition cgraph.h:391
agobjfn_t ins
Definition cgraph.h:390
struct Agcbdisc_s::@63 edge
struct Agcbdisc_s::@63 graph
struct Agcbdisc_s::@63 node
agobjfn_t del
Definition cgraph.h:392
object event callbacks
Definition cgraph.h:399
void * state
Definition cgraph.h:401
Agcbdisc_t * f
Definition cgraph.h:400
Agcbstack_t * prev
Definition cgraph.h:402
Agcbstack_t * cb
Definition cgraph.h:416
a generic header of Agraph_s, Agnode_s and Agedge_s
Definition cgraph.h:210
graph or subgraph
Definition cgraph.h:425
Agraph_t * root
subgraphs - ancestors
Definition cgraph.h:434
Agclos_t * clos
shared resources
Definition cgraph.h:435
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:637
#define UNREACHABLE()
Definition unreachable.h:30