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