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 <stdio.h>
15 #include <cghdr.h>
16
17 /* a default ID allocator that works off the shared string lib */
18
idopen(Agraph_t * g,Agdisc_t * disc)19 static void *idopen(Agraph_t * g, Agdisc_t* disc)
20 {
21 return g;
22 }
23
idmap(void * state,int objtype,char * str,IDTYPE * id,int createflag)24 static long idmap(void *state, int objtype, char *str, IDTYPE *id,
25 int createflag)
26 {
27 char *s;
28 static IDTYPE ctr = 1;
29
30 NOTUSED(objtype);
31 if (str) {
32 Agraph_t *g;
33 g = state;
34 if (createflag)
35 s = agstrdup(g, str);
36 else
37 s = agstrbind(g, str);
38 *id = (IDTYPE) s;
39 } else {
40 *id = ctr;
41 ctr += 2;
42 }
43 return TRUE;
44 }
45
46 /* we don't allow users to explicitly set IDs, either */
idalloc(void * state,int objtype,IDTYPE request)47 static long idalloc(void *state, int objtype, IDTYPE request)
48 {
49 NOTUSED(state);
50 NOTUSED(objtype);
51 NOTUSED(request);
52 return FALSE;
53 }
54
idfree(void * state,int objtype,IDTYPE id)55 static void idfree(void *state, int objtype, IDTYPE id)
56 {
57 NOTUSED(objtype);
58 if (id % 2 == 0)
59 agstrfree((Agraph_t *) state, (char *) id);
60 }
61
idprint(void * state,int objtype,IDTYPE id)62 static char *idprint(void *state, int objtype, IDTYPE id)
63 {
64 NOTUSED(state);
65 NOTUSED(objtype);
66 if (id % 2 == 0)
67 return (char *) id;
68 else
69 return NILstr;
70 }
71
idclose(void * state)72 static void idclose(void *state)
73 {
74 NOTUSED(state);
75 }
76
idregister(void * state,int objtype,void * obj)77 static void idregister(void *state, int objtype, void *obj)
78 {
79 NOTUSED(state);
80 NOTUSED(objtype);
81 NOTUSED(obj);
82 }
83
84 Agiddisc_t AgIdDisc = {
85 idopen,
86 idmap,
87 idalloc,
88 idfree,
89 idprint,
90 idclose,
91 idregister
92 };
93
94 /* aux functions incl. support for disciplines with anonymous IDs */
95
agmapnametoid(Agraph_t * g,int objtype,char * str,IDTYPE * result,int createflag)96 int agmapnametoid(Agraph_t * g, int objtype, char *str,
97 IDTYPE *result, int createflag)
98 {
99 int rv;
100
101 if (str && (str[0] != LOCALNAMEPREFIX)) {
102 rv = AGDISC(g, id)->map(AGCLOS(g, id), objtype, str, result,
103 createflag);
104 if (rv)
105 return rv;
106 }
107
108 /* either an internal ID, or disc. can't map strings */
109 if (str) {
110 rv = aginternalmaplookup(g, objtype, str, result);
111 if (rv)
112 return rv;
113 } else
114 rv = 0;
115
116 if (createflag) {
117 /* get a new anonymous ID, and store in the internal map */
118 rv = AGDISC(g, id)->map(AGCLOS(g, id), objtype, NILstr, result,
119 createflag);
120 if (rv && str)
121 aginternalmapinsert(g, objtype, str, *result);
122 }
123 return rv;
124 }
125
agallocid(Agraph_t * g,int objtype,IDTYPE request)126 int agallocid(Agraph_t * g, int objtype, IDTYPE request)
127 {
128 return AGDISC(g, id)->alloc(AGCLOS(g, id), objtype, request);
129 }
130
agfreeid(Agraph_t * g,int objtype,IDTYPE id)131 void agfreeid(Agraph_t * g, int objtype, IDTYPE id)
132 {
133 (void) aginternalmapdelete(g, objtype, id);
134 (AGDISC(g, id)->free) (AGCLOS(g, id), objtype, id);
135 }
136
137 /* agnameof:
138 * Return string representation of object.
139 * In general, returns the name of node or graph,
140 * and the key of an edge. If edge is anonymous, returns NULL.
141 * Uses static buffer for anonymous graphs.
142 */
agnameof(void * obj)143 char *agnameof(void *obj)
144 {
145 Agraph_t *g;
146 char *rv;
147 static char buf[32];
148
149 /* perform internal lookup first */
150 g = agraphof(obj);
151 if ((rv = aginternalmapprint(g, AGTYPE(obj), AGID(obj))))
152 return rv;
153
154 if (AGDISC(g, id)->print) {
155 if ((rv =
156 AGDISC(g, id)->print(AGCLOS(g, id), AGTYPE(obj), AGID(obj))))
157 return rv;
158 }
159 if (AGTYPE(obj) != AGEDGE) {
160 sprintf(buf, "%c%ld", LOCALNAMEPREFIX, AGID(obj));
161 rv = buf;
162 }
163 else
164 rv = 0;
165 return rv;
166 }
167
168 /* register a graph object in an external namespace */
agregister(Agraph_t * g,int objtype,void * obj)169 void agregister(Agraph_t * g, int objtype, void *obj)
170 {
171 AGDISC(g, id)->idregister(AGCLOS(g, id), objtype, obj);
172 }
173