Graphviz 12.0.1~dev.20240715.2254
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 <cgraph/unreachable.h>
17#include <stddef.h>
18
19int agdelete(Agraph_t * g, void *obj)
20{
21 if (AGTYPE(obj) == AGRAPH && g != agparent(obj)) {
22 agerrorf("agdelete on wrong graph");
23 return FAILURE;
24 }
25
26 switch (AGTYPE(obj)) {
27 case AGNODE:
28 return agdelnode(g, obj);
29 case AGINEDGE:
30 case AGOUTEDGE:
31 return agdeledge(g, obj);
32 case AGRAPH:
33 return agclose(obj);
34 default:
35 agerrorf("agdelete on bad object");
36 }
37 return SUCCESS; /* not reached */
38}
39
40int agrename(Agobj_t * obj, char *newname)
41{
42 Agraph_t *g;
43 IDTYPE old_id, new_id;
44
45 switch (AGTYPE(obj)) {
46 case AGRAPH:
47 old_id = AGID(obj);
48 g = agraphof(obj);
49 /* can we reserve the id corresponding to newname? */
50 if (agmapnametoid(agroot(g), AGTYPE(obj), newname, &new_id, false) == 0)
51 return FAILURE;
52 if (new_id == old_id)
53 return SUCCESS;
54 if (agmapnametoid(agroot(g), AGTYPE(obj), newname, &new_id, true) == 0)
55 return FAILURE;
56 /* obj* is unchanged, so no need to re agregister() */
57 if (agparent(g) && agidsubg(agparent(g), new_id, 0))
58 return FAILURE;
59 agfreeid(g, AGRAPH, old_id);
60 AGID(g) = new_id;
61 break;
62 case AGNODE:
63 return agrelabel_node((Agnode_t *) obj, newname);
64 case AGINEDGE:
65 case AGOUTEDGE:
66 return FAILURE;
67 default:
69 }
70 return SUCCESS;
71}
72
73/* perform initialization/update/finalization method invocation.
74 * skip over nil pointers to next method below.
75 */
76
77void agmethod_init(Agraph_t * g, void *obj)
78{
79 aginitcb(g, obj, g->clos->cb);
80}
81
82void aginitcb(Agraph_t * g, void *obj, Agcbstack_t * cbstack)
83{
84 agobjfn_t fn;
85
86 if (cbstack == NULL)
87 return;
88 aginitcb(g, obj, cbstack->prev);
89 fn = NULL;
90 switch (AGTYPE(obj)) {
91 case AGRAPH:
92 fn = cbstack->f->graph.ins;
93 break;
94 case AGNODE:
95 fn = cbstack->f->node.ins;
96 break;
97 case AGEDGE:
98 fn = cbstack->f->edge.ins;
99 break;
100 default: // ignore
101 break;
102 }
103 if (fn)
104 fn(g, obj, cbstack->state);
105}
106
107void agmethod_upd(Agraph_t * g, void *obj, Agsym_t * sym)
108{
109 agupdcb(g, obj, sym, g->clos->cb);
110}
111
112void agupdcb(Agraph_t * g, void *obj, Agsym_t * sym, Agcbstack_t * cbstack)
113{
114 agobjupdfn_t fn;
115
116 if (cbstack == NULL)
117 return;
118 agupdcb(g, obj, sym, cbstack->prev);
119 fn = NULL;
120 switch (AGTYPE(obj)) {
121 case AGRAPH:
122 fn = cbstack->f->graph.mod;
123 break;
124 case AGNODE:
125 fn = cbstack->f->node.mod;
126 break;
127 case AGEDGE:
128 fn = cbstack->f->edge.mod;
129 break;
130 default: // ignore
131 break;
132 }
133 if (fn)
134 fn(g, obj, cbstack->state, sym);
135}
136
137void agmethod_delete(Agraph_t * g, void *obj)
138{
139 agdelcb(g, obj, g->clos->cb);
140}
141
142void agdelcb(Agraph_t * g, void *obj, Agcbstack_t * cbstack)
143{
144 agobjfn_t fn;
145
146 if (cbstack == NULL)
147 return;
148 agdelcb(g, obj, cbstack->prev);
149 fn = NULL;
150 switch (AGTYPE(obj)) {
151 case AGRAPH:
152 fn = cbstack->f->graph.del;
153 break;
154 case AGNODE:
155 fn = cbstack->f->node.del;
156 break;
157 case AGEDGE:
158 fn = cbstack->f->edge.del;
159 break;
160 default: // ignore
161 break;
162 }
163 if (fn)
164 fn(g, obj, cbstack->state);
165}
166
167Agraph_t *agroot(void* obj)
168{
169 if (obj == 0) return NULL;
170 switch (AGTYPE(obj)) {
171 case AGINEDGE:
172 case AGOUTEDGE:
173 return ((Agedge_t *) obj)->node->root;
174 case AGNODE:
175 return ((Agnode_t *) obj)->root;
176 case AGRAPH:
177 return ((Agraph_t *) obj)->root;
178 default: /* actually can't occur if only 2 bit tags */
179 agerrorf("agroot of a bad object");
180 return NULL;
181 }
182}
183
185{
186 switch (AGTYPE(obj)) {
187 case AGINEDGE:
188 case AGOUTEDGE:
189 return ((Agedge_t *) obj)->node->root;
190 case AGNODE:
191 return ((Agnode_t *) obj)->root;
192 case AGRAPH:
193 return obj;
194 default: /* actually can't occur if only 2 bit tags */
195 agerrorf("agraphof a bad object");
196 return NULL;
197 }
198}
199
200/* to manage disciplines */
201void agpushdisc(Agraph_t * g, Agcbdisc_t * cbd, void *state)
202{
203 Agcbstack_t *stack_ent;
204
205 stack_ent = AGNEW(g, Agcbstack_t);
206 stack_ent->f = cbd;
207 stack_ent->state = state;
208 stack_ent->prev = g->clos->cb;
209 g->clos->cb = stack_ent;
210}
211
213{
214 Agcbstack_t *stack_ent;
215
216 stack_ent = g->clos->cb;
217 if (stack_ent) {
218 if (stack_ent->f == cbd)
219 g->clos->cb = stack_ent->prev;
220 else {
221 while (stack_ent && stack_ent->prev->f != cbd)
222 stack_ent = stack_ent->prev;
223 if (stack_ent && stack_ent->prev)
224 stack_ent->prev = stack_ent->prev->prev;
225 }
226 if (stack_ent) {
227 agfree(g, stack_ent);
228 return SUCCESS;
229 }
230 }
231 return FAILURE;
232}
233
234int agcontains(Agraph_t* g, void* obj)
235{
236 Agraph_t* subg;
237
238 if (agroot (g) != agroot (obj)) return 0;
239 switch (AGTYPE(obj)) {
240 case AGRAPH:
241 subg = obj;
242 do {
243 if (subg == g) return 1;
244 } while ((subg = agparent (subg)));
245 return 0;
246 case AGNODE:
247 return agidnode(g, AGID(obj), 0) != 0;
248 default:
249 return agsubedge(g, obj, 0) != 0;
250 }
251}
252
253int agobjkind(void *arg)
254{
255 return AGTYPE(arg);
256}
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:44
#define SUCCESS
Definition cghdr.h:43
#define AGNEW(g, t)
Definition cghdr.h:49
node NULL
Definition grammar.y:149
void agfree(Agraph_t *g, void *ptr)
Definition mem.c:49
void agupdcb(Agraph_t *g, void *obj, Agsym_t *sym, Agcbstack_t *cbstack)
Definition obj.c:112
void agdelcb(Agraph_t *g, void *obj, Agcbstack_t *cbstack)
Definition obj.c:142
void aginitcb(Agraph_t *g, void *obj, Agcbstack_t *cbstack)
Definition obj.c:82
int agpopdisc(Agraph_t *g, Agcbdisc_t *cbd)
Definition obj.c:212
void agmethod_delete(Agraph_t *g, void *obj)
Definition obj.c:137
void agpushdisc(Agraph_t *g, Agcbdisc_t *cbd, void *state)
Definition obj.c:201
void agmethod_init(Agraph_t *g, void *obj)
Definition obj.c:77
void agmethod_upd(Agraph_t *g, void *obj, Agsym_t *sym)
Definition obj.c:107
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:96
Agnode_t * agidnode(Agraph_t *g, IDTYPE id, int createflag)
Definition node.c:124
int agrelabel_node(Agnode_t *n, char *newname)
Definition node.c:239
int agdelnode(Agraph_t *g, Agnode_t *arg_n)
removes a node from a graph or subgraph.
Definition node.c:197
Agraph_t * agraphof(void *obj)
Definition obj.c:184
#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:19
int agcontains(Agraph_t *g, void *obj)
returns non-zero if obj is a member of (sub)graph
Definition obj.c:234
int agobjkind(void *arg)
Definition obj.c:253
Agraph_t * agroot(void *obj)
Definition obj.c:167
@ 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:90
Agraph_t * agidsubg(Agraph_t *g, IDTYPE id, int cflag)
Definition subg.c:48
static lexstate_t state
Definition htmllex.c:61
int agrename(Agobj_t *obj, char *newname)
Definition obj.c:40
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::@64 edge
struct Agcbdisc_s::@64 graph
struct Agcbdisc_s::@64 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:639
#define UNREACHABLE()
Definition unreachable.h:30