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 | |
19 | static void *idopen(Agraph_t * g, Agdisc_t* disc) |
20 | { |
21 | return g; |
22 | } |
23 | |
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 */ |
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 | |
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 | |
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 | |
72 | static void idclose(void *state) |
73 | { |
74 | NOTUSED(state); |
75 | } |
76 | |
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 | |
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 | |
126 | int agallocid(Agraph_t * g, int objtype, IDTYPE request) |
127 | { |
128 | return AGDISC(g, id)->alloc(AGCLOS(g, id), objtype, request); |
129 | } |
130 | |
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 | */ |
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 */ |
169 | void agregister(Agraph_t * g, int objtype, void *obj) |
170 | { |
171 | AGDISC(g, id)->idregister(AGCLOS(g, id), objtype, obj); |
172 | } |
173 | |