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