Graphviz 14.1.2~dev.20260118.1035
Loading...
Searching...
No Matches
dthash.c
Go to the documentation of this file.
1#include "config.h"
2
3#include <cdt/dthdr.h>
4#include <stdlib.h>
5
6/* Hash table.
7** dt: dictionary
8** obj: what to look for
9** type: type of search
10**
11** Written by Kiem-Phong Vo (05/25/96)
12*/
13
14/* resize the hash table */
15static void dthtab(Dt_t* dt)
16{
17 Dtlink_t *t, *r, *p, **s, **hs, **is, **olds;
18 int n;
19
20 /* compute new table size */
21 if ((n = dt->data.ntab) == 0)
22 n = HSLOT;
23 while (dt->data.size > HLOAD(n))
24 n = HRESIZE(n);
25 if (n == dt->data.ntab)
26 return;
27
28 /* allocate new table */
29 olds = dt->data.ntab == 0 ? NULL : dt->data.htab;
30 if (!(s = realloc(olds, n * sizeof(Dtlink_t*))))
31 return;
32 olds = s + dt->data.ntab;
33 dt->data.htab = s;
34 dt->data.ntab = n;
35
36 /* rehash elements */
37 for(hs = s+n-1; hs >= olds; --hs)
38 *hs = NULL;
39 for(hs = s; hs < olds; ++hs)
40 { for(p = NULL, t = *hs; t; t = r)
41 { r = t->right;
42 if((is = s + HINDEX(n,t->hash)) == hs)
43 p = t;
44 else /* move to a new chain */
45 { if(p)
46 p->right = r;
47 else *hs = r;
48 t->right = *is; *is = t;
49 }
50 }
51 }
52}
53
54static void* dthash(Dt_t* dt, void* obj, int type)
55{
56 Dtlink_t *t, *r = NULL, *p;
57 void *k, *key;
58 unsigned hsh;
59 int lk, sz, ky;
62 Dtlink_t **s = NULL, **ends;
63
64 UNFLATTEN(dt);
65
66 /* initialize discipline data */
67 disc = dt->disc; _DTDSC(disc,ky,sz,lk,cmpf);
68
69 if(!obj)
70 { if(type&(DT_NEXT|DT_PREV))
71 goto end_walk;
72
73 if (dt->data.size <= 0 || !(type & (DT_CLEAR|DT_FIRST|DT_LAST)) )
74 return NULL;
75
76 ends = (s = dt->data.htab) + dt->data.ntab;
77 if(type&DT_CLEAR)
78 { /* clean out all objects */
79 for(; s < ends; ++s)
80 { t = *s;
81 *s = NULL;
82 if(!disc->freef && disc->link >= 0)
83 continue;
84 while(t)
85 { r = t->right;
86 if(disc->freef)
87 disc->freef(_DTOBJ(t, lk));
88 if(disc->link < 0)
89 free(t);
90 t = r;
91 }
92 }
93 dt->data.here = NULL;
94 dt->data.size = 0;
95 dt->data.loop = 0;
96 return NULL;
97 }
98 else /* computing the first/last object */
99 { t = NULL;
100 while(s < ends && !t )
101 t = (type&DT_LAST) ? *--ends : *s++;
102 if(t && (type&DT_LAST))
103 for(; t->right; t = t->right)
104 ;
105
106 ++dt->data.loop;
107 dt->data.here = t;
108 return t ? _DTOBJ(t,lk) : NULL;
109 }
110 }
111
113 { key = (type&DT_MATCH) ? obj : _DTKEY(obj,ky,sz);
114 hsh = dtstrhash(key, sz);
115 goto do_search;
116 }
117 else if(type&(DT_RENEW|DT_VSEARCH) )
118 { r = obj;
119 obj = _DTOBJ(r,lk);
120 key = _DTKEY(obj,ky,sz);
121 hsh = r->hash;
122 goto do_search;
123 }
124 else /*if(type&(DT_DELETE|DT_DETACH|DT_NEXT|DT_PREV))*/
125 { if ((t = dt->data.here) && _DTOBJ(t, lk) == obj)
126 { hsh = t->hash;
127 s = dt->data.htab + HINDEX(dt->data.ntab, hsh);
128 p = NULL;
129 }
130 else
131 { key = _DTKEY(obj,ky,sz);
132 hsh = dtstrhash(key, sz);
133 do_search:
134 t = dt->data.ntab <= 0 ? NULL :
135 *(s = dt->data.htab + HINDEX(dt->data.ntab, hsh));
136 for(p = NULL; t; p = t, t = t->right)
137 { if(hsh == t->hash)
138 { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz);
139 if(_DTCMP(key, k, cmpf, sz) == 0)
140 break;
141 }
142 }
143 }
144 }
145
147 { if(!t)
148 return NULL;
149 if (p && (dt->data.type & DT_SET) && dt->data.loop <= 0)
150 { /* move-to-front heuristic */
151 p->right = t->right;
152 t->right = *s;
153 *s = t;
154 }
155 dt->data.here = t;
156 return _DTOBJ(t,lk);
157 }
158 else if(type&DT_INSERT)
159 { if (t && (dt->data.type & DT_SET))
160 { dt->data.here = t;
161 return _DTOBJ(t,lk);
162 }
163
164 if (disc->makef && (type&DT_INSERT) && !(obj = disc->makef(obj, disc)))
165 return NULL;
166 if(lk >= 0)
167 r = _DTLNK(obj,lk);
168 else
169 { r = malloc(sizeof(Dthold_t));
170 if(r)
171 ((Dthold_t*)r)->obj = obj;
172 else
173 { if(disc->makef && disc->freef && (type&DT_INSERT))
174 disc->freef(obj);
175 return NULL;
176 }
177 }
178 r->hash = hsh;
179
180 /* insert object */
181 do_insert:
182 if (++dt->data.size > HLOAD(dt->data.ntab) && dt->data.loop <= 0 )
183 dthtab(dt);
184 if (dt->data.ntab == 0)
185 { --dt->data.size;
186 if(disc->freef && (type&DT_INSERT))
187 disc->freef(obj);
188 if(disc->link < 0)
189 free(r);
190 return NULL;
191 }
192 s = dt->data.htab + HINDEX(dt->data.ntab, hsh);
193 if(t)
194 { r->right = t->right;
195 t->right = r;
196 }
197 else
198 { r->right = *s;
199 *s = r;
200 }
201 dt->data.here = r;
202 return obj;
203 }
204 else if(type&DT_NEXT)
205 { if(t && !(p = t->right) )
206 { for (ends = dt->data.htab + dt->data.ntab, s += 1; s < ends; ++s)
207 if((p = *s) )
208 break;
209 }
210 goto done_adj;
211 }
212 else if(type&DT_PREV)
213 { if(t && !p)
214 { if((p = *s) != t)
215 { while(p->right != t)
216 p = p->right;
217 }
218 else
219 { p = NULL;
220 for (s -= 1, ends = dt->data.htab; s >= ends; --s)
221 { if((p = *s) )
222 { while(p->right)
223 p = p->right;
224 break;
225 }
226 }
227 }
228 }
229 done_adj:
230 if (!(dt->data.here = p))
231 { end_walk:
232 if (--dt->data.loop < 0)
233 dt->data.loop = 0;
234 if (dt->data.size > HLOAD(dt->data.ntab) && dt->data.loop <= 0)
235 dthtab(dt);
236 return NULL;
237 }
238 else
239 { dt->data.type |= DT_WALK;
240 return _DTOBJ(p,lk);
241 }
242 }
243 else if(type&DT_RENEW)
244 { if(!t)
245 goto do_insert;
246 else
247 { if(disc->freef)
248 disc->freef(obj);
249 if(disc->link < 0)
250 free(r);
251 return t ? _DTOBJ(t,lk) : NULL;
252 }
253 }
254 else /*if(type&(DT_DELETE|DT_DETACH))*/
255 { /* take an element out of the dictionary */
256 if(!t)
257 return NULL;
258 else if(p)
259 p->right = t->right;
260 else if((p = *s) == t)
261 p = *s = t->right;
262 else
263 { while(p->right != t)
264 p = p->right;
265 p->right = t->right;
266 }
267 obj = _DTOBJ(t,lk);
268 --dt->data.size;
269 dt->data.here = p;
270 if(disc->freef && (type&DT_DELETE))
271 disc->freef(obj);
272 if(disc->link < 0)
273 free(t);
274 return obj;
275 }
276}
277
#define DT_MATCH
Definition cdt.h:134
#define _DTKEY(o, ky, sz)
Definition cdt.h:169
#define _DTDSC(dc, ky, sz, lk, cmpf)
Definition cdt.h:164
#define DT_LAST
Definition cdt.h:133
#define DT_PREV
Definition cdt.h:129
#define _DTLNK(o, lk)
Definition cdt.h:166
#define DT_NEXT
Definition cdt.h:128
#define DT_SET
Definition cdt.h:119
int(* Dtcompar_f)(void *, void *)
Definition cdt.h:48
#define DT_SEARCH
Definition cdt.h:127
#define DT_VSEARCH
Definition cdt.h:135
#define DT_DELETE
Definition cdt.h:126
#define DT_CLEAR
Definition cdt.h:131
CDT_API unsigned int dtstrhash(void *, int)
Definition dtstrhash.c:23
#define DT_INSERT
Definition cdt.h:125
#define DT_RENEW
Definition cdt.h:130
#define _DTCMP(k1, k2, cmpf, sz)
Definition cdt.h:172
#define _DTOBJ(e, lk)
Definition cdt.h:167
#define DT_FIRST
Definition cdt.h:132
static int cmpf(void *key1, void *key2)
Definition dijkstra.c:84
static Dtmethod_t _Dtset
Definition dthash.c:278
Dtmethod_t * Dtset
set with unique elements
Definition dthash.c:279
static void * dthash(Dt_t *dt, void *obj, int type)
Definition dthash.c:54
static void dthtab(Dt_t *dt)
Definition dthash.c:15
#define HSLOT
Definition dthdr.h:22
#define HINDEX(n, h)
Definition dthdr.h:25
#define HLOAD(s)
Definition dthdr.h:24
#define HRESIZE(n)
Definition dthdr.h:23
#define DT_WALK
Definition dthdr.h:19
#define UNFLATTEN(dt)
Definition dthdr.h:27
static Dtdisc_t disc
Definition exparse.y:209
expr procedure type
Definition exparse.y:208
void * malloc(YYSIZE_T)
void free(void *)
node NULL
Definition grammar.y:181
int size
Definition cdt.h:79
Dtlink_t * here
Definition cdt.h:73
int type
Definition cdt.h:72
int ntab
Definition cdt.h:78
int loop
Definition cdt.h:80
Definition cdt.h:59
Definition cdt.h:98
Dtdata_t data
sharable data
Definition cdt.h:101
Dtdisc_t * disc
Definition cdt.h:100
Dtfree_f freef
Definition cdt.h:89
int link
Definition cdt.h:87
Dtmake_f makef
Definition cdt.h:88
Definition grammar.c:90