Graphviz  2.41.20171026.1811
refstr.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 #ifdef DMALLOC
17 #include "dmalloc.h"
18 #endif
19 
20 /*
21  * reference counted strings.
22  */
23 
24 static uint64_t HTML_BIT; /* msbit of uint64_t */
25 static uint64_t CNT_BITS; /* complement of HTML_BIT */
26 
27 typedef struct refstr_t {
29  uint64_t refcnt;
30  char *s;
31  char store[1]; /* this is actually a dynamic array */
32 } refstr_t;
33 
34 static Dtdisc_t Refstrdisc = {
35  offsetof(refstr_t, s), /* key */
36  -1, /* size */
37  0, /* link offset */
38  NIL(Dtmake_f),
40  NIL(Dtcompar_f),
41  NIL(Dthash_f),
43  NIL(Dtevent_f)
44 };
45 
46 static Dict_t *Refdict_default;
47 
48 /* refdict:
49  * Return the string dictionary associated with g.
50  * If necessary, create it.
51  * As a side-effect, set html masks. This assumes 8-bit bytes.
52  */
53 static Dict_t *refdict(Agraph_t * g)
54 {
55  Dict_t **dictref;
56 
57  if (g)
58  dictref = &(g->clos->strdict);
59  else
60  dictref = &Refdict_default;
61  if (*dictref == NIL(Dict_t *)) {
62  *dictref = agdtopen(g, &Refstrdisc, Dttree);
63  HTML_BIT = ((unsigned int) 1) << (sizeof(unsigned int) * 8 - 1);
64  CNT_BITS = ~HTML_BIT;
65  }
66  return *dictref;
67 }
68 
70 {
71  return agdtclose(g, refdict(g));
72 }
73 
74 static refstr_t *refsymbind(Dict_t * strdict, char *s)
75 {
76  refstr_t key, *r;
77  key.s = s;
78  r = (refstr_t *) dtsearch(strdict, &key);
79  return r;
80 }
81 
82 static char *refstrbind(Dict_t * strdict, char *s)
83 {
84  refstr_t *r;
85  r = refsymbind(strdict, s);
86  if (r)
87  return r->s;
88  else
89  return NIL(char *);
90 }
91 
92 char *agstrbind(Agraph_t * g, char *s)
93 {
94  return refstrbind(refdict(g), s);
95 }
96 
97 char *agstrdup(Agraph_t * g, char *s)
98 {
99  refstr_t *r;
100  Dict_t *strdict;
101  size_t sz;
102 
103  if (s == NIL(char *))
104  return NIL(char *);
105  strdict = refdict(g);
106  r = refsymbind(strdict, s);
107  if (r)
108  r->refcnt++;
109  else {
110  sz = sizeof(refstr_t) + strlen(s);
111  if (g)
112  r = (refstr_t *) agalloc(g, sz);
113  else
114  r = (refstr_t *) malloc(sz);
115  r->refcnt = 1;
116  strcpy(r->store, s);
117  r->s = r->store;
118  dtinsert(strdict, r);
119  }
120  return r->s;
121 }
122 
123 char *agstrdup_html(Agraph_t * g, char *s)
124 {
125  refstr_t *r;
126  Dict_t *strdict;
127  size_t sz;
128 
129  if (s == NIL(char *))
130  return NIL(char *);
131  strdict = refdict(g);
132  r = refsymbind(strdict, s);
133  if (r)
134  r->refcnt++;
135  else {
136  sz = sizeof(refstr_t) + strlen(s);
137  if (g)
138  r = (refstr_t *) agalloc(g, sz);
139  else
140  r = (refstr_t *) malloc(sz);
141  r->refcnt = 1 | HTML_BIT;
142  strcpy(r->store, s);
143  r->s = r->store;
144  dtinsert(strdict, r);
145  }
146  return r->s;
147 }
148 
149 int agstrfree(Agraph_t * g, char *s)
150 {
151  refstr_t *r;
152  Dict_t *strdict;
153 
154  if (s == NIL(char *))
155  return FAILURE;
156 
157  strdict = refdict(g);
158  r = refsymbind(strdict, s);
159  if (r && (r->s == s)) {
160  r->refcnt--;
161  if ((r->refcnt && CNT_BITS) == 0) {
162  agdtdelete(g, strdict, r);
163  /*
164  if (g) agfree(g,r);
165  else free(r);
166  */
167  }
168  }
169  if (r == NIL(refstr_t *))
170  return FAILURE;
171  return SUCCESS;
172 }
173 
174 /* aghtmlstr:
175  * Return true if s is an HTML string.
176  * We assume s points to the datafield store[0] of a refstr.
177  */
178 int aghtmlstr(char *s)
179 {
180  refstr_t *key;
181 
182  if (s == NULL)
183  return 0;
184  key = (refstr_t *) (s - offsetof(refstr_t, store[0]));
185  return (key->refcnt & HTML_BIT);
186 }
187 
188 void agmarkhtmlstr(char *s)
189 {
190  refstr_t *key;
191 
192  if (s == NULL)
193  return;
194  key = (refstr_t *) (s - offsetof(refstr_t, store[0]));
195  key->refcnt |= HTML_BIT;
196 }
197 
198 #ifdef DEBUG
199 static int refstrprint(Dict_t * dict, void *ptr, void *user)
200 {
201  refstr_t *r;
202 
203  NOTUSED(dict);
204  r = ptr;
205  NOTUSED(user);
206  write(2, r->s, strlen(r->s));
207  write(2, "\n", 1);
208  return 0;
209 }
210 
211 void agrefstrdump(Agraph_t * g)
212 {
213  dtwalk(Refdict_default, refstrprint, 0);
214 }
215 #endif
int(* Dtcompar_f)(Dt_t *, void *, void *, Dtdisc_t *)
Definition: cdt.h:40
unsigned int(* Dthash_f)(Dt_t *, void *, Dtdisc_t *)
Definition: cdt.h:41
void agmarkhtmlstr(char *s)
Definition: refstr.c:188
void *(* Dtmake_f)(Dt_t *, void *, Dtdisc_t *)
Definition: cdt.h:38
char store[1]
Definition: refstr.c:31
#define SUCCESS
Definition: cghdr.h:62
CGRAPH_API int aghtmlstr(char *)
Definition: refstr.c:178
int agdtclose(Agraph_t *g, Dict_t *dict)
Definition: utils.c:79
char * s
Definition: refstr.c:30
#define NOTUSED(var)
Definition: cghdr.h:54
Definition: cdt.h:80
int agstrclose(Agraph_t *g)
Definition: refstr.c:69
CGRAPH_API char * agstrdup_html(Agraph_t *, char *)
Definition: refstr.c:123
#define NIL(t)
Definition: dthdr.h:13
int
Definition: grammar.c:1264
#define dtsearch(d, o)
Definition: cdt.h:260
#define FAILURE
Definition: cghdr.h:63
long agdtdelete(Agraph_t *g, Dict_t *dict, void *obj)
Definition: utils.c:67
CGRAPH_API int agstrfree(Agraph_t *, char *)
Definition: refstr.c:149
CGRAPH_API char * agstrdup(Agraph_t *, char *)
Definition: refstr.c:97
Definition: grammar.c:79
struct refstr_t refstr_t
#define dtinsert(d, o)
Definition: cdt.h:262
Dtlink_t link
Definition: refstr.c:28
#define NULL
Definition: logic.h:39
Dict_t * agdtopen(Agraph_t *g, Dtdisc_t *disc, Dtmethod_t *method)
Definition: utils.c:53
bool write(Agraph_t *g, FILE *f)
Definition: gv.cpp:926
CDT_API Dtmethod_t * Dttree
Definition: cdt.h:176
CDT_API int dtwalk(Dt_t *, int(*)(Dt_t *, void *, void *), void *)
CGRAPH_API void * agalloc(Agraph_t *g, size_t size)
Definition: mem.c:62
void * agdictobjmem(Dict_t *dict, void *p, size_t size, Dtdisc_t *disc)
Definition: utils.c:19
int(* Dtevent_f)(Dt_t *, int, void *, Dtdisc_t *)
Definition: cdt.h:42
Definition: cdt.h:99
uint64_t refcnt
Definition: refstr.c:29
Dict_t * strdict
Definition: cgraph.h:231
Agclos_t * clos
Definition: cgraph.h:248
CGRAPH_API char * agstrbind(Agraph_t *g, char *)
Definition: refstr.c:92
void agdictobjfree(Dict_t *dict, void *p, Dtdisc_t *disc)
Definition: utils.c:40