Graphviz 12.0.1~dev.20240715.2254
Loading...
Searching...
No Matches
id.c
Go to the documentation of this file.
1
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 <assert.h>
16#include <stdbool.h>
17#include <stdio.h>
18#include <cgraph/alloc.h>
19#include <cgraph/cghdr.h>
20#include <inttypes.h>
21#include <stdint.h>
22#include <stdlib.h>
23
24/* a default ID allocator that works off the shared string lib */
25
27typedef struct {
30} state_t;
31
32static void *idopen(Agraph_t * g, Agdisc_t* disc)
33{
34 (void)disc;
35
36 state_t *s = gv_alloc(sizeof(state_t));
37 *s = (state_t){.g = g};
38 return s;
39}
40
41static long idmap(void *state, int objtype, char *str, IDTYPE *id,
42 int createflag)
43{
44 char *s;
45 state_t *st = state;
46
47 (void)objtype;
48 if (str) {
49 if (createflag)
50 s = agstrdup(st->g, str);
51 else
52 s = agstrbind(st->g, str);
53 // The scheme of using pointers as the IDs of named objects and odd
54 // numbers as the IDs of unnamed objects relies on heap pointers being
55 // even, to avoid collisions. So the low bit had better be unset.
56 assert((uintptr_t)s % 2 == 0 &&
57 "heap pointer with low bit set will collide with anonymous IDs");
58 *id = (IDTYPE)(uintptr_t)s;
59 } else {
60 *id = st->counter * 2 + 1;
61 ++st->counter;
62 }
63 return 1;
64}
65
66 /* we don't allow users to explicitly set IDs, either */
67static long idalloc(void *state, int objtype, IDTYPE request)
68{
69 (void)state;
70 (void)objtype;
71 (void)request;
72 return 0;
73}
74
75static void idfree(void *state, int objtype, IDTYPE id)
76{
77 (void)objtype;
78 state_t *st = state;
79 if (id % 2 == 0)
80 agstrfree(st->g, (char *)(uintptr_t)id);
81}
82
83static char *idprint(void *state, int objtype, IDTYPE id)
84{
85 (void)state;
86 (void)objtype;
87 if (id % 2 == 0)
88 return (char *)(uintptr_t)id;
89 else
90 return NULL;
91}
92
93static void idregister(void *state, int objtype, void *obj)
94{
95 (void)state;
96 (void)objtype;
97 (void)obj;
98}
99
101 idopen,
102 idmap,
103 idalloc,
104 idfree,
105 idprint,
106 free,
108};
109
110/* aux functions incl. support for disciplines with anonymous IDs */
111
112int agmapnametoid(Agraph_t * g, int objtype, char *str,
113 IDTYPE *result, bool createflag) {
114 int rv;
115
116 if (str && str[0] != LOCALNAMEPREFIX) {
117 rv = (int) AGDISC(g, id)->map(AGCLOS(g, id), objtype, str, result,
118 createflag);
119 if (rv)
120 return rv;
121 }
122
123 /* either an internal ID, or disc. can't map strings */
124 if (str) {
125 rv = aginternalmaplookup(g, objtype, str, result);
126 if (rv)
127 return rv;
128 } else
129 rv = 0;
130
131 if (createflag) {
132 /* get a new anonymous ID, and store in the internal map */
133 rv = (int) AGDISC(g, id)->map(AGCLOS(g, id), objtype, NULL, result,
134 createflag);
135 if (rv && str)
136 aginternalmapinsert(g, objtype, str, *result);
137 }
138 return rv;
139}
140
141int agallocid(Agraph_t * g, int objtype, IDTYPE request)
142{
143 return (int) AGDISC(g, id)->alloc(AGCLOS(g, id), objtype, request);
144}
145
146void agfreeid(Agraph_t * g, int objtype, IDTYPE id)
147{
148 (void) aginternalmapdelete(g, objtype, id);
149 (AGDISC(g, id)->free) (AGCLOS(g, id), objtype, id);
150}
151
158char *agnameof(void *obj)
159{
160 Agraph_t *g;
161 char *rv;
162
163 /* perform internal lookup first */
164 g = agraphof(obj);
165 rv = aginternalmapprint(g, AGTYPE(obj), AGID(obj));
166 if (rv != NULL)
167 return rv;
168
169 if (AGDISC(g, id)->print) {
170 rv = AGDISC(g, id)->print(AGCLOS(g, id), AGTYPE(obj), AGID(obj));
171 if (rv != NULL)
172 return rv;
173 }
174 if (AGTYPE(obj) != AGEDGE) {
175 static char buf[32];
176 snprintf(buf, sizeof(buf), "%c%" PRIu64, LOCALNAMEPREFIX, AGID(obj));
177 rv = buf;
178 }
179 else
180 rv = 0;
181 return rv;
182}
183
184/* register a graph object in an external namespace */
185void agregister(Agraph_t * g, int objtype, void *obj)
186{
187 AGDISC(g, id)->idregister(AGCLOS(g, id), objtype, obj);
188}
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
cgraph.h additions
int aginternalmapdelete(Agraph_t *g, int objtype, IDTYPE id)
Definition imap.c:151
void aginternalmapinsert(Agraph_t *g, int objtype, char *str, IDTYPE result)
Definition imap.c:104
int aginternalmaplookup(Agraph_t *g, int objtype, char *str, IDTYPE *result)
Definition imap.c:81
char * aginternalmapprint(Agraph_t *g, int objtype, IDTYPE id)
Definition imap.c:141
#define AGDISC(g, d)
Definition cghdr.h:47
#define LOCALNAMEPREFIX
Definition cghdr.h:45
#define AGCLOS(g, d)
Definition cghdr.h:48
static void print(Excc_t *cc, Exnode_t *exnode)
Definition excc.c:125
void free(void *)
node NULL
Definition grammar.y:149
Agiddisc_t AgIdDisc
Definition id.c:100
Agraph_t * agraphof(void *obj)
Definition obj.c:184
char * agnameof(void *obj)
returns a string descriptor for the object.
Definition id.c:158
#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
@ AGEDGE
Definition cgraph.h:207
int agstrfree(Agraph_t *, const char *)
Definition refstr.c:138
char * agstrdup(Agraph_t *, const char *)
returns a pointer to a reference-counted copy of the argument string, creating one if necessary
Definition refstr.c:130
char * agstrbind(Agraph_t *g, const char *)
Definition refstr.c:95
static uint64_t id
Definition gv2gml.c:42
static lexstate_t state
Definition htmllex.c:61
agxbuf * str
Definition htmlparse.c:97
void agfreeid(Agraph_t *g, int objtype, IDTYPE id)
Definition id.c:146
static void * idopen(Agraph_t *g, Agdisc_t *disc)
Definition id.c:32
int agmapnametoid(Agraph_t *g, int objtype, char *str, IDTYPE *result, bool createflag)
Definition id.c:112
int agallocid(Agraph_t *g, int objtype, IDTYPE request)
Definition id.c:141
static long idalloc(void *state, int objtype, IDTYPE request)
Definition id.c:67
void agregister(Agraph_t *g, int objtype, void *obj)
Definition id.c:185
static char * idprint(void *state, int objtype, IDTYPE id)
Definition id.c:83
static void idfree(void *state, int objtype, IDTYPE id)
Definition id.c:75
static void idregister(void *state, int objtype, void *obj)
Definition id.c:93
static long idmap(void *state, int objtype, char *str, IDTYPE *id, int createflag)
Definition id.c:41
user's discipline
Definition cgraph.h:337
object ID allocator discipline
Definition cgraph.h:316
long(* map)(void *state, int objtype, char *str, IDTYPE *id, int createflag)
Definition cgraph.h:318
graph or subgraph
Definition cgraph.h:425
information the ID allocator needs to do its job
Definition id.c:27
Agraph_t * g
graph in use
Definition id.c:29
IDTYPE counter
base to derive next identifier from
Definition id.c:28
Definition grammar.c:93