Graphviz  2.41.20170921.2350
obj.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #include <cghdr.h>
15 
16 int agdelete(Agraph_t * g, void *obj)
17 {
18  if ((AGTYPE((Agobj_t *) obj) == AGRAPH) && (g != agparent(obj))) {
19  agerr(AGERR, "agdelete on wrong graph");
20  return FAILURE;
21  }
22 
23  switch (AGTYPE((Agobj_t *) obj)) {
24  case AGNODE:
25  return agdelnode(g, obj);
26  case AGINEDGE:
27  case AGOUTEDGE:
28  return agdeledge(g, obj);
29  case AGRAPH:
30  return agclose(obj);
31  default:
32  agerr(AGERR, "agdelete on bad object");
33  }
34  return SUCCESS; /* not reached */
35 }
36 
37 int agrename(Agobj_t * obj, char *newname)
38 {
39  Agraph_t *g;
40  IDTYPE old_id, new_id;
41 
42  switch (AGTYPE(obj)) {
43  case AGRAPH:
44  old_id = AGID(obj);
45  g = agraphof(obj);
46  /* can we reserve the id corresponding to newname? */
47  if (agmapnametoid(agroot(g), AGTYPE(obj), newname,
48  &new_id, FALSE) == 0)
49  return FAILURE;
50  if (new_id == old_id)
51  return SUCCESS;
52  if (agmapnametoid(agroot(g), AGTYPE(obj), newname,
53  &new_id, TRUE) == 0)
54  return FAILURE;
55  /* obj* is unchanged, so no need to re agregister() */
56  if (agparent(g) && agidsubg(agparent(g), new_id, 0))
57  return FAILURE;
58  agfreeid(g, AGRAPH, old_id);
59  AGID(g) = new_id;
60  break;
61  case AGNODE:
62  return agrelabel_node((Agnode_t *) obj, newname);
63  agrename(obj, newname);
64  break;
65  case AGINEDGE:
66  case AGOUTEDGE:
67  return FAILURE;
68  }
69  return SUCCESS;
70 }
71 
72 /* perform initialization/update/finalization method invocation.
73  * skip over nil pointers to next method below.
74  */
75 
76 void agmethod_init(Agraph_t * g, void *obj)
77 {
78  if (g->clos->callbacks_enabled)
79  aginitcb(g, obj, g->clos->cb);
80  else
82 }
83 
84 void aginitcb(Agraph_t * g, void *obj, Agcbstack_t * cbstack)
85 {
86  agobjfn_t fn;
87 
88  if (cbstack == NIL(Agcbstack_t *))
89  return;
90  aginitcb(g, obj, cbstack->prev);
91  fn = NIL(agobjfn_t);
92  switch (AGTYPE(obj)) {
93  case AGRAPH:
94  fn = cbstack->f->graph.ins;
95  break;
96  case AGNODE:
97  fn = cbstack->f->node.ins;
98  break;
99  case AGEDGE:
100  fn = cbstack->f->edge.ins;
101  break;
102  }
103  if (fn)
104  fn(g, obj, cbstack->state);
105 }
106 
107 void agmethod_upd(Agraph_t * g, void *obj, Agsym_t * sym)
108 {
109  if (g->clos->callbacks_enabled)
110  agupdcb(g, obj, sym, g->clos->cb);
111  else
112  agrecord_callback(g, obj, CB_UPDATE, sym);
113 }
114 
115 void agupdcb(Agraph_t * g, void *obj, Agsym_t * sym, Agcbstack_t * cbstack)
116 {
117  agobjupdfn_t fn;
118 
119  if (cbstack == NIL(Agcbstack_t *))
120  return;
121  agupdcb(g, obj, sym, cbstack->prev);
122  fn = NIL(agobjupdfn_t);
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  }
134  if (fn)
135  fn(g, obj, cbstack->state, sym);
136 }
137 
138 void agmethod_delete(Agraph_t * g, void *obj)
139 {
140  if (g->clos->callbacks_enabled)
141  agdelcb(g, obj, g->clos->cb);
142  else
144 }
145 
146 void agdelcb(Agraph_t * g, void *obj, Agcbstack_t * cbstack)
147 {
148  agobjfn_t fn;
149 
150  if (cbstack == NIL(Agcbstack_t *))
151  return;
152  agdelcb(g, obj, cbstack->prev);
153  fn = NIL(agobjfn_t);
154  switch (AGTYPE(obj)) {
155  case AGRAPH:
156  fn = cbstack->f->graph.del;
157  break;
158  case AGNODE:
159  fn = cbstack->f->node.del;
160  break;
161  case AGEDGE:
162  fn = cbstack->f->edge.del;
163  break;
164  }
165  if (fn)
166  fn(g, obj, cbstack->state);
167 }
168 
169 Agraph_t *agroot(void* obj)
170 {
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  agerr(AGERR, "agroot of a bad object");
181  return NILgraph;
182  }
183 }
184 
185 Agraph_t *agraphof(void *obj)
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 (Agraph_t *) obj;
195  default: /* actually can't occur if only 2 bit tags */
196  agerr(AGERR, "agraphof a bad object");
197  return NILgraph;
198  }
199 }
200 
201 /* to manage disciplines */
202 void agpushdisc(Agraph_t * g, Agcbdisc_t * cbd, void *state)
203 {
204  Agcbstack_t *stack_ent;
205 
206  stack_ent = AGNEW(g, 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  agfree(g, stack_ent);
229  return SUCCESS;
230  }
231  }
232  return FAILURE;
233 }
234 
236 {
237  Agcbstack_t *stack_ent;
238 
239  for (stack_ent = g->clos->cb; stack_ent; stack_ent = stack_ent->prev)
240  if (stack_ent->f == cbd)
241  return stack_ent->state;
242  return NIL(void *);
243 }
244 
245 int agcontains(Agraph_t* g, void* obj)
246 {
247  Agraph_t* subg;
248 
249  if (agroot (g) != agroot (obj)) return 0;
250  switch (AGTYPE(obj)) {
251  case AGRAPH:
252  subg = (Agraph_t *) obj;
253  do {
254  if (subg == g) return 1;
255  } while ((subg = agparent (subg)));
256  return 0;
257  case AGNODE:
258  return (agidnode(g, AGID(obj), 0) != 0);
259  default:
260  return (agsubedge(g, (Agedge_t *) obj, 0) != 0);
261  }
262 }
263 
264 int agobjkind(void *arg)
265 {
266  return AGTYPE(arg);
267 }
CGRAPH_API int agdeledge(Agraph_t *g, Agedge_t *arg_e)
Definition: edge.c:357
void(* agobjupdfn_t)(Agraph_t *g, Agobj_t *obj, void *arg, Agsym_t *sym)
Definition: cgraph.h:211
CGRAPH_API int agobjkind(void *)
Definition: obj.c:264
Definition: cgraph.h:388
void agdelcb(Agraph_t *g, void *obj, Agcbstack_t *disc)
Definition: obj.c:146
#define SUCCESS
Definition: cghdr.h:62
CGRAPH_API int agdelnode(Agraph_t *g, Agnode_t *arg_n)
Definition: node.c:192
int agmapnametoid(Agraph_t *g, int objtype, char *str, IDTYPE *result, int allocflag)
Definition: id.c:96
void * state
Definition: cgraph.h:224
struct Agcbdisc_s::@2 edge
#define AGID(obj)
Definition: cgraph.h:114
agobjfn_t del
Definition: cgraph.h:218
CGRAPH_API Agraph_t * agidsubg(Agraph_t *g, IDTYPE id, int cflag)
Definition: subg.c:43
CGRAPH_API void agpushdisc(Agraph_t *g, Agcbdisc_t *disc, void *state)
Definition: obj.c:202
void * aggetuserptr(Agraph_t *g, Agcbdisc_t *cbd)
Definition: obj.c:235
CGRAPH_API int agdelete(Agraph_t *g, void *obj)
Definition: obj.c:16
int agerr(agerrlevel_t level, const char *fmt,...)
Definition: agerror.c:141
unsigned char callbacks_enabled
Definition: cgraph.h:234
CGRAPH_API int agcontains(Agraph_t *, void *)
Definition: obj.c:245
CGRAPH_API Agraph_t * agroot(void *obj)
Definition: obj.c:169
#define AGOUTEDGE
Definition: cgraph.h:102
#define NILsym
Definition: cghdr.h:59
CGRAPH_API void agfree(Agraph_t *g, void *ptr)
Definition: mem.c:89
Agcbdisc_t * f
Definition: cgraph.h:223
#define AGTYPE(obj)
Definition: cgraph.h:113
void agrecord_callback(Agraph_t *g, Agobj_t *obj, int kind, Agsym_t *optsym)
Definition: pend.c:193
agobjfn_t ins
Definition: cgraph.h:216
void aginitcb(Agraph_t *g, void *obj, Agcbstack_t *disc)
Definition: obj.c:84
#define AGNEW(g, t)
Definition: cghdr.h:68
CGRAPH_API Agraph_t * agraphof(void *obj)
Definition: obj.c:185
uint64_t IDTYPE
Definition: cgraph.h:51
#define NIL(t)
Definition: dthdr.h:13
#define CB_UPDATE
Definition: cghdr.h:161
#define NILgraph
Definition: cghdr.h:56
#define FAILURE
Definition: cghdr.h:63
CGRAPH_API int agclose(Agraph_t *g)
Definition: graph.c:93
CGRAPH_API Agraph_t * agparent(Agraph_t *g)
Definition: subg.c:85
void agupdcb(Agraph_t *g, void *obj, Agsym_t *sym, Agcbstack_t *disc)
Definition: obj.c:115
CGRAPH_API int agrelabel_node(Agnode_t *n, char *newname)
Definition: node.c:231
Agcbstack_t * prev
Definition: cgraph.h:225
void agmethod_delete(Agraph_t *g, void *obj)
Definition: obj.c:138
CGRAPH_API Agedge_t * agsubedge(Agraph_t *g, Agedge_t *e, int createflag)
Definition: edge.c:378
void agfreeid(Agraph_t *g, int objtype, IDTYPE id)
Definition: id.c:131
#define CB_INITIALIZE
Definition: cghdr.h:160
#define AGNODE
Definition: cgraph.h:101
void agmethod_init(Agraph_t *g, void *obj)
Definition: obj.c:76
struct Agcbdisc_s::@2 graph
agobjupdfn_t mod
Definition: cgraph.h:217
CGHDR_API int agrename(Agobj_t *obj, char *newname)
Definition: obj.c:37
CGRAPH_API int agpopdisc(Agraph_t *g, Agcbdisc_t *disc)
Definition: obj.c:213
struct Agcbdisc_s::@2 node
Agcbstack_t * cb
Definition: cgraph.h:233
void agmethod_upd(Agraph_t *g, void *obj, Agsym_t *sym)
Definition: obj.c:107
#define AGINEDGE
Definition: cgraph.h:103
Agclos_t * clos
Definition: cgraph.h:248
#define AGEDGE
Definition: cgraph.h:104
CGRAPH_API Agnode_t * agidnode(Agraph_t *g, IDTYPE id, int createflag)
Definition: node.c:119
#define FALSE
Definition: cgraph.h:35
#define CB_DELETION
Definition: cghdr.h:162
void(* agobjfn_t)(Agraph_t *g, Agobj_t *obj, void *arg)
Definition: cgraph.h:210
#define AGRAPH
Definition: cgraph.h:100
#define TRUE
Definition: cgraph.h:38