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