]> jfr.im git - irc/evilnet/x3.git/blob - rx/rxhash.c
Couple of srvx updates.
[irc/evilnet/x3.git] / rx / rxhash.c
1 /* Copyright (C) 1995, 1996 Tom Lord
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU Library General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Library General Public License for more details.
12 *
13 * You should have received a copy of the GNU Library General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, 59 Temple Place - Suite 330,
16 * Boston, MA 02111-1307, USA.
17 */
18
19 \f
20 /*
21 * Tom Lord (lord@cygnus.com, lord@gnu.ai.mit.edu)
22 */
23 \f
24
25 #include "rxall.h"
26 #include "rxhash.h"
27
28 \f
29
30 #ifdef __STDC__
31 static struct rx_hash *
32 default_hash_alloc (struct rx_hash_rules * rules)
33 #else
34 static struct rx_hash *
35 default_hash_alloc (rules)
36 struct rx_hash_rules * rules;
37 #endif
38 {
39 return (struct rx_hash *)malloc (sizeof (struct rx_hash));
40 }
41
42
43 #ifdef __STDC__
44 static struct rx_hash_item *
45 default_hash_item_alloc (struct rx_hash_rules * rules, void * value)
46 #else
47 static struct rx_hash_item *
48 default_hash_item_alloc (rules, value)
49 struct rx_hash_rules * rules;
50 void * value;
51 #endif
52 {
53 struct rx_hash_item * it;
54 it = (struct rx_hash_item *)malloc (sizeof (*it));
55 if (it)
56 {
57 it->data = value;
58 it->binding = 0;
59 }
60 return it;
61 }
62
63
64 #ifdef __STDC__
65 static void
66 default_free_hash (struct rx_hash * tab,
67 struct rx_hash_rules * rules)
68 #else
69 static void
70 default_free_hash (tab, rules)
71 struct rx_hash * tab;
72 struct rx_hash_rules * rules;
73 #endif
74 {
75 free ((char *)tab);
76 }
77
78
79 #ifdef __STDC__
80 static void
81 default_free_hash_item (struct rx_hash_item * item,
82 struct rx_hash_rules * rules)
83 #else
84 static void
85 default_free_hash_item (item, rules)
86 struct rx_hash_item * item;
87 struct rx_hash_rules * rules;
88 #endif
89 {
90 free ((char *)item);
91 }
92
93 #ifdef __STDC__
94 static int
95 default_eq (void * va, void * vb)
96 #else
97 static int
98 default_eq (va, vb)
99 void * va;
100 void * vb;
101 #endif
102 {
103 return va == vb;
104 }
105
106 \f
107
108 #define EQ(rules) ((rules && rules->eq) ? rules->eq : default_eq)
109 #define HASH_ALLOC(rules) ((rules && rules->hash_alloc) ? rules->hash_alloc : default_hash_alloc)
110 #define FREE_HASH(rules) ((rules && rules->free_hash) ? rules->free_hash : default_free_hash)
111 #define ITEM_ALLOC(rules) ((rules && rules->hash_item_alloc) ? rules->hash_item_alloc : default_hash_item_alloc)
112 #define FREE_HASH_ITEM(rules) ((rules && rules->free_hash_item) ? rules->free_hash_item : default_free_hash_item)
113
114 \f
115 static unsigned long rx_hash_masks[4] =
116 {
117 0x12488421,
118 0x96699669,
119 0xbe7dd7eb,
120 0xffffffff
121 };
122
123 /* hash to bucket */
124 #define JOIN_BYTE(H, B) (((H) + ((H) << 3) + (B)) & 0xf)
125
126 #define H2B(X) JOIN_BYTE (JOIN_BYTE (JOIN_BYTE ((X & 0xf), ((X>>8) & 0xf)), ((X>>16) & 0xf)), ((X>>24) & 0xf))
127
128 #define BKTS 16
129
130 /* Hash tables */
131 #ifdef __STDC__
132 struct rx_hash_item *
133 rx_hash_find (struct rx_hash * table,
134 unsigned long hash,
135 void * value,
136 struct rx_hash_rules * rules)
137 #else
138 struct rx_hash_item *
139 rx_hash_find (table, hash, value, rules)
140 struct rx_hash * table;
141 unsigned long hash;
142 void * value;
143 struct rx_hash_rules * rules;
144 #endif
145 {
146 rx_hash_eq eq = EQ (rules);
147 int maskc = 0;
148 long mask = rx_hash_masks [0];
149 int bucket = H2B(hash & mask);
150
151 while (RX_bitset_member (&table->nested_p, bucket))
152 {
153 table = (struct rx_hash *)(table->children [bucket]);
154 ++maskc;
155 mask = rx_hash_masks[maskc];
156 bucket = H2B (hash & mask);
157 }
158
159 {
160 struct rx_hash_item * it;
161 it = (struct rx_hash_item *)(table->children[bucket]);
162 while (it)
163 if (eq (it->data, value))
164 return it;
165 else
166 it = it->next_same_hash;
167 }
168
169 return 0;
170 }
171
172
173 #ifdef __STDC__
174 static int
175 listlen (struct rx_hash_item * bucket)
176 #else
177 static int
178 listlen (bucket)
179 struct rx_hash_item * bucket;
180 #endif
181 {
182 int i;
183 for (i = 0; bucket; ++i, bucket = bucket->next_same_hash)
184 ;
185 return i;
186 }
187
188 #ifdef __STDC__
189 static int
190 overflows (struct rx_hash_item * bucket)
191 #else
192 static int
193 overflows (bucket)
194 struct rx_hash_item * bucket;
195 #endif
196 {
197 return !( bucket
198 && bucket->next_same_hash
199 && bucket->next_same_hash->next_same_hash
200 && bucket->next_same_hash->next_same_hash->next_same_hash);
201 }
202
203
204 #ifdef __STDC__
205 struct rx_hash_item *
206 rx_hash_store (struct rx_hash * table,
207 unsigned long hash,
208 void * value,
209 struct rx_hash_rules * rules)
210 #else
211 struct rx_hash_item *
212 rx_hash_store (table, hash, value, rules)
213 struct rx_hash * table;
214 unsigned long hash;
215 void * value;
216 struct rx_hash_rules * rules;
217 #endif
218 {
219 rx_hash_eq eq = EQ (rules);
220 int maskc = 0;
221 long mask = rx_hash_masks [0];
222 int bucket = H2B(hash & mask);
223 int depth = 0;
224
225 while (RX_bitset_member (&table->nested_p, bucket))
226 {
227 table = (struct rx_hash *)(table->children [bucket]);
228 ++maskc;
229 mask = rx_hash_masks[maskc];
230 bucket = H2B(hash & mask);
231 ++depth;
232 }
233
234 {
235 struct rx_hash_item * it;
236 it = (struct rx_hash_item *)(table->children[bucket]);
237 while (it)
238 if (eq (it->data, value))
239 return it;
240 else
241 it = it->next_same_hash;
242 }
243
244 {
245 if ( (depth < 3)
246 && (overflows ((struct rx_hash_item *)table->children [bucket])))
247 {
248 struct rx_hash * newtab;
249 newtab = (struct rx_hash *) HASH_ALLOC(rules) (rules);
250 if (!newtab)
251 goto add_to_bucket;
252 rx_bzero ((char *)newtab, sizeof (*newtab));
253 newtab->parent = table;
254 {
255 struct rx_hash_item * them;
256 unsigned long newmask;
257 them = (struct rx_hash_item *)table->children[bucket];
258 newmask = rx_hash_masks[maskc + 1];
259 while (them)
260 {
261 struct rx_hash_item * save = them->next_same_hash;
262 int new_buck = H2B(them->hash & newmask);
263 them->next_same_hash = ((struct rx_hash_item *)
264 newtab->children[new_buck]);
265 ((struct rx_hash_item **)newtab->children)[new_buck] = them;
266 them->table = newtab;
267 them = save;
268 ++newtab->refs;
269 --table->refs;
270 }
271 ((struct rx_hash **)table->children)[bucket] = newtab;
272 RX_bitset_enjoin (&table->nested_p, bucket);
273 ++table->refs;
274 table = newtab;
275 bucket = H2B(hash & newmask);
276 }
277 }
278 }
279 add_to_bucket:
280 {
281 struct rx_hash_item * it = ((struct rx_hash_item *)
282 ITEM_ALLOC(rules) (rules, value));
283 if (!it)
284 return 0;
285 it->hash = hash;
286 it->table = table;
287 /* DATA and BINDING are to be set in hash_item_alloc */
288 it->next_same_hash = (struct rx_hash_item *)table->children [bucket];
289 ((struct rx_hash_item **)table->children)[bucket] = it;
290 ++table->refs;
291 return it;
292 }
293 }
294
295
296 #ifdef __STDC__
297 void
298 rx_hash_free (struct rx_hash_item * it, struct rx_hash_rules * rules)
299 #else
300 void
301 rx_hash_free (it, rules)
302 struct rx_hash_item * it;
303 struct rx_hash_rules * rules;
304 #endif
305 {
306 if (it)
307 {
308 struct rx_hash * table = it->table;
309 unsigned long hash = it->hash;
310 int depth = (table->parent
311 ? (table->parent->parent
312 ? (table->parent->parent->parent
313 ? 3
314 : 2)
315 : 1)
316 : 0);
317 int bucket = H2B (hash & rx_hash_masks [depth]);
318 struct rx_hash_item ** pos
319 = (struct rx_hash_item **)&table->children [bucket];
320
321 while (*pos != it)
322 pos = &(*pos)->next_same_hash;
323 *pos = it->next_same_hash;
324 FREE_HASH_ITEM(rules) (it, rules);
325 --table->refs;
326 while (!table->refs && depth)
327 {
328 struct rx_hash * save = table;
329 table = table->parent;
330 --depth;
331 bucket = H2B(hash & rx_hash_masks [depth]);
332 --table->refs;
333 table->children[bucket] = 0;
334 RX_bitset_remove (&table->nested_p, bucket);
335 FREE_HASH (rules) (save, rules);
336 }
337 }
338 }
339
340 #ifdef __STDC__
341 void
342 rx_free_hash_table (struct rx_hash * tab, rx_hash_freefn freefn,
343 struct rx_hash_rules * rules)
344 #else
345 void
346 rx_free_hash_table (tab, freefn, rules)
347 struct rx_hash * tab;
348 rx_hash_freefn freefn;
349 struct rx_hash_rules * rules;
350 #endif
351 {
352 int x;
353
354 for (x = 0; x < BKTS; ++x)
355 if (RX_bitset_member (&tab->nested_p, x))
356 {
357 rx_free_hash_table ((struct rx_hash *)tab->children[x],
358 freefn, rules);
359 FREE_HASH (rules) ((struct rx_hash *)tab->children[x], rules);
360 }
361 else
362 {
363 struct rx_hash_item * them = (struct rx_hash_item *)tab->children[x];
364 while (them)
365 {
366 struct rx_hash_item * that = them;
367 them = that->next_same_hash;
368 freefn (that);
369 FREE_HASH_ITEM (rules) (that, rules);
370 }
371 }
372 }
373
374
375
376 #ifdef __STDC__
377 int
378 rx_count_hash_nodes (struct rx_hash * st)
379 #else
380 int
381 rx_count_hash_nodes (st)
382 struct rx_hash * st;
383 #endif
384 {
385 int x;
386 int count = 0;
387 for (x = 0; x < BKTS; ++x)
388 count += ((RX_bitset_member (&st->nested_p, x))
389 ? rx_count_hash_nodes ((struct rx_hash *)st->children[x])
390 : listlen ((struct rx_hash_item *)(st->children[x])));
391
392 return count;
393 }
394