Mercurial > hg > xemacs-beta
comparison src/hash.c @ 173:8eaf7971accc r20-3b13
Import from CVS: tag r20-3b13
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:49:09 +0200 |
parents | 376386a54a3c |
children | 3d6bfa290dbd |
comparison
equal
deleted
inserted
replaced
172:a38aed19690b | 173:8eaf7971accc |
---|---|
30 | 30 |
31 #define NULL_ENTRY ((void *) 1) | 31 #define NULL_ENTRY ((void *) 1) |
32 | 32 |
33 #endif /* !emacs */ | 33 #endif /* !emacs */ |
34 | 34 |
35 #include <string.h> | |
36 #include "hash.h" | 35 #include "hash.h" |
37 #include "elhash.h" | 36 #include "elhash.h" |
38 | 37 |
39 static CONST int | 38 static CONST int |
40 primes []={ | 39 primes []={ |
41 13, | 40 13, |
42 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, | 41 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, |
43 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, | 42 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, |
44 8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, | 43 8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, |
45 62851, 75431, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, | 44 62851, 75431, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, |
46 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319, | 45 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319, |
47 2009191, 2411033, 2893249 | 46 2009191, 2411033, 2893249 |
48 }; | 47 }; |
49 | 48 |
50 /* strings code */ | 49 /* strings code */ |
51 | 50 |
52 /* from base/generic-hash.cc, and hence from Dragon book, p436 */ | 51 /* from base/generic-hash.cc, and hence from Dragon book, p436 */ |
53 unsigned long | 52 unsigned long |
54 string_hash (CONST void *xv) | 53 string_hash (CONST void *xv) |
55 { | 54 { |
56 unsigned int h = 0; | 55 unsigned int h = 0; |
57 unsigned int g; | 56 unsigned int g; |
58 unsigned CONST char *x = (unsigned CONST char *) xv; | 57 unsigned CONST char *x = (unsigned CONST char *) xv; |
59 | 58 |
60 if (!x) return 0; | 59 if (!x) return 0; |
69 return h; | 68 return h; |
70 } | 69 } |
71 | 70 |
72 unsigned long | 71 unsigned long |
73 memory_hash (CONST void *xv, int size) | 72 memory_hash (CONST void *xv, int size) |
74 { | 73 { |
75 unsigned int h = 0; | 74 unsigned int h = 0; |
76 unsigned int g; | 75 unsigned int g; |
77 unsigned CONST char *x = (unsigned CONST char *) xv; | 76 unsigned CONST char *x = (unsigned CONST char *) xv; |
78 | 77 |
79 if (!x) return 0; | 78 if (!x) return 0; |
87 } | 86 } |
88 | 87 |
89 return h; | 88 return h; |
90 } | 89 } |
91 | 90 |
92 static int | 91 static int |
93 string_eq (CONST void *st1v, CONST void *st2v) | 92 string_eq (CONST void *st1v, CONST void *st2v) |
94 { | 93 { |
95 CONST char *st1 = (CONST char *)st1v; | 94 CONST char *st1 = (CONST char *)st1v; |
96 CONST char *st2 = (CONST char *)st2v; | 95 CONST char *st2 = (CONST char *)st2v; |
97 | 96 |
102 else | 101 else |
103 return !strcmp (st1, st2); | 102 return !strcmp (st1, st2); |
104 } | 103 } |
105 | 104 |
106 | 105 |
107 static unsigned int | 106 static unsigned int |
108 prime_size (unsigned int size) | 107 prime_size (unsigned int size) |
109 { | 108 { |
110 unsigned int i; | 109 unsigned int i; |
111 CONST int lim = countof (primes); | 110 CONST int lim = countof (primes); |
112 for (i = 0; i < lim; i++) | 111 for (i = 0; i < lim; i++) |
123 gethash (CONST void *key, c_hashtable hash, CONST void **ret_value) | 122 gethash (CONST void *key, c_hashtable hash, CONST void **ret_value) |
124 { | 123 { |
125 hentry *harray = hash->harray; | 124 hentry *harray = hash->harray; |
126 int (*test_function) (CONST void *, CONST void *) = hash->test_function; | 125 int (*test_function) (CONST void *, CONST void *) = hash->test_function; |
127 unsigned int hsize = hash->size; | 126 unsigned int hsize = hash->size; |
128 unsigned int hcode_initial = | 127 unsigned int hcode_initial = |
129 (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key); | 128 (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key); |
130 unsigned int hcode = hcode_initial % hsize; | 129 unsigned int hcode = hcode_initial % hsize; |
131 hentry *e = &harray [hcode]; | 130 hentry *e = &harray [hcode]; |
132 CONST void *e_key = e->key; | 131 CONST void *e_key = e->key; |
133 | 132 |
134 if (!key) | 133 if (!key) |
135 { | 134 { |
136 *ret_value = hash->zero_entry; | 135 *ret_value = hash->zero_entry; |
137 return (void *) hash->zero_set; | 136 return (void *) hash->zero_set; |
138 } | |
139 | |
140 if ((e_key)? | |
141 (KEYS_DIFFER_P (e_key, key, test_function)): | |
142 (e->contents == NULL_ENTRY)) | |
143 { | |
144 unsigned int h2 = hsize - 2; | |
145 unsigned int incr = 1 + (hcode_initial % h2); | |
146 do | |
147 { | |
148 hcode = hcode + incr; | |
149 if (hcode >= hsize) hcode = hcode - hsize; | |
150 e = &harray [hcode]; | |
151 e_key = e->key; | |
152 } | |
153 while ((e_key)? | |
154 (KEYS_DIFFER_P (e_key, key, test_function)): | |
155 (e->contents == NULL_ENTRY)); | |
156 } | |
157 | |
158 *ret_value = e->contents; | |
159 return e->key; | |
160 } | |
161 | |
162 void | |
163 clrhash (c_hashtable hash) | |
164 { | |
165 memset (hash->harray, 0, sizeof (hentry) * hash->size); | |
166 hash->zero_entry = 0; | |
167 hash->zero_set = 0; | |
168 hash->fullness = 0; | |
169 } | |
170 | |
171 void | |
172 free_hashtable (c_hashtable hash) | |
173 { | |
174 #ifdef emacs | |
175 if (!NILP (hash->elisp_table)) | |
176 return; | |
177 #endif | |
178 xfree (hash->harray); | |
179 xfree (hash); | |
180 } | |
181 | |
182 c_hashtable | |
183 make_hashtable (unsigned int hsize) | |
184 { | |
185 c_hashtable res = (c_hashtable) xmalloc (sizeof (struct _C_hashtable)); | |
186 memset (res, 0, sizeof (struct _C_hashtable)); | |
187 res->size = prime_size ((13 * hsize) / 10); | |
188 res->harray = (hentry *) xmalloc (sizeof (hentry) * res->size); | |
189 #ifdef emacs | |
190 res->elisp_table = Qnil; | |
191 #endif | |
192 clrhash (res); | |
193 return res; | |
194 } | |
195 | |
196 c_hashtable | |
197 make_general_hashtable (unsigned int hsize, | |
198 unsigned long (*hash_function) (CONST void *), | |
199 int (*test_function) (CONST void *, CONST void *)) | |
200 { | |
201 c_hashtable res = (c_hashtable) xmalloc (sizeof (struct _C_hashtable)); | |
202 memset (res, 0, sizeof (struct _C_hashtable)); | |
203 res->size = prime_size ((13 * hsize) / 10); | |
204 res->harray = (hentry *) xmalloc (sizeof (hentry) * res->size); | |
205 res->hash_function = hash_function; | |
206 res->test_function = test_function; | |
207 #ifdef emacs | |
208 res->elisp_table = Qnil; | |
209 #endif | |
210 clrhash (res); | |
211 return res; | |
212 } | |
213 | |
214 c_hashtable | |
215 make_strings_hashtable (unsigned int hsize) | |
216 { | |
217 return make_general_hashtable (hsize, string_hash, string_eq); | |
218 } | |
219 | |
220 #ifdef emacs | |
221 unsigned int | |
222 compute_harray_size (unsigned int hsize) | |
223 { | |
224 return prime_size ((13 * hsize) / 10); | |
225 } | |
226 #endif | |
227 | |
228 void | |
229 copy_hash (c_hashtable dest, c_hashtable src) | |
230 { | |
231 #ifdef emacs | |
232 /* if these are not the same, then we are losing here */ | |
233 if ((NILP (dest->elisp_table)) != (NILP (src->elisp_table))) | |
234 { | |
235 error ("Incompatible hashtable types to copy_hash."); | |
236 return; | |
237 } | |
238 #endif | |
239 | |
240 if (dest->size != src->size) | |
241 { | |
242 #ifdef emacs | |
243 if (!NILP (dest->elisp_table)) | |
244 elisp_hvector_free (dest->harray, dest->elisp_table); | |
245 else | |
246 #endif | |
247 xfree (dest->harray); | |
248 | |
249 dest->size = src->size; | |
250 #ifdef emacs | |
251 if (!NILP (dest->elisp_table)) | |
252 dest->harray = | |
253 (hentry *) elisp_hvector_malloc | |
254 (sizeof (hentry) * dest->size, dest->elisp_table); | |
255 else | |
256 #endif | |
257 dest->harray = (hentry *) xmalloc (sizeof (hentry) * dest->size); | |
258 } | |
259 dest->fullness = src->fullness; | |
260 dest->zero_entry = src->zero_entry; | |
261 dest->zero_set = src->zero_set; | |
262 dest->hash_function = src->hash_function; | |
263 dest->test_function = src->test_function; | |
264 memcpy (dest->harray, src->harray, sizeof (hentry) * dest->size); | |
265 } | |
266 | |
267 static void | |
268 grow_hashtable (c_hashtable hash, unsigned int new_size) | |
269 { | |
270 unsigned int old_hsize = hash->size; | |
271 hentry *old_harray = hash->harray; | |
272 unsigned int new_hsize = prime_size (new_size); | |
273 hentry *new_harray; | |
274 | |
275 #ifdef emacs | |
276 /* We test for Qzero to facilitate free-hook.c. That module creates | |
277 a hashtable very very early, at which point Qnil has not yet | |
278 been set and is thus all zeroes. Qzero is "automatically" | |
279 initialized at startup because its correct value is also all | |
280 zeroes. */ | |
281 if (!NILP (hash->elisp_table) && !ZEROP (hash->elisp_table)) | |
282 new_harray = (hentry *) elisp_hvector_malloc (sizeof (hentry) * new_hsize, | |
283 hash->elisp_table); | |
284 else | |
285 #endif | |
286 new_harray = | |
287 (hentry *) xmalloc (sizeof (hentry) * new_hsize); | |
288 | |
289 hash->size = new_hsize; | |
290 hash->harray = new_harray; | |
291 | |
292 /* do the rehash on the "grown" table */ | |
293 { | |
294 long old_zero_set = hash->zero_set; | |
295 void *old_zero_entry = hash->zero_entry; | |
296 clrhash (hash); | |
297 hash->zero_set = old_zero_set; | |
298 hash->zero_entry = old_zero_entry; | |
299 rehash (old_harray, hash, old_hsize); | |
300 } | |
301 | |
302 #ifdef emacs | |
303 if (!NILP (hash->elisp_table) && !ZEROP (hash->elisp_table)) | |
304 elisp_hvector_free (old_harray, hash->elisp_table); | |
305 else | |
306 #endif | |
307 xfree (old_harray); | |
308 } | |
309 | |
310 void | |
311 expand_hashtable (c_hashtable hash, unsigned int needed_size) | |
312 { | |
313 unsigned int hsize = hash->size; | |
314 int comfortable_size = (13 * needed_size) / 10; | |
315 if (hsize < comfortable_size) | |
316 grow_hashtable (hash, comfortable_size + 1); | |
317 } | |
318 | |
319 void | |
320 puthash (CONST void *key, void *cont, c_hashtable hash) | |
321 { | |
322 unsigned int hsize = hash->size; | |
323 int (*test_function) (CONST void *, CONST void *) = hash->test_function; | |
324 unsigned int fullness = hash->fullness; | |
325 hentry *harray; | |
326 CONST void *e_key; | |
327 hentry *e; | |
328 unsigned int hcode_initial = | |
329 (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key); | |
330 unsigned int hcode; | |
331 unsigned int incr = 0; | |
332 unsigned int h2; | |
333 CONST void *oldcontents; | |
334 | |
335 if (!key) | |
336 { | |
337 hash->zero_entry = cont; | |
338 hash->zero_set = 1; | |
339 return; | |
340 } | |
341 | |
342 if (hsize < (1 + ((13 * fullness) / 10))) | |
343 { | |
344 grow_hashtable (hash, hsize + 1); | |
345 hsize = hash->size; | |
346 fullness = hash->fullness; | |
347 } | |
348 | |
349 harray= hash->harray; | |
350 h2 = hsize - 2; | |
351 | |
352 hcode = hcode_initial % hsize; | |
353 | |
354 e_key = harray [hcode].key; | |
355 if (e_key && (KEYS_DIFFER_P (e_key, key, test_function))) | |
356 { | |
357 h2 = hsize - 2; | |
358 incr = 1 + (hcode_initial % h2); | |
359 do | |
360 { | |
361 hcode = hcode + incr; | |
362 if (hcode >= hsize) hcode = hcode - hsize; | |
363 e_key = harray [hcode].key; | |
364 } | |
365 while (e_key && (KEYS_DIFFER_P (e_key, key, test_function))); | |
366 } | |
367 oldcontents = harray [hcode].contents; | |
368 harray [hcode].key = key; | |
369 harray [hcode].contents = cont; | |
370 /* if the entry that we used was a deleted entry, | |
371 check for a non deleted entry of the same key, | |
372 then delete it */ | |
373 if (!e_key && (oldcontents == NULL_ENTRY)) | |
374 { | |
375 if (!incr) incr = 1 + ((unsigned long) key % h2); | |
376 | |
377 do | |
378 { | |
379 hcode = hcode + incr; | |
380 if (hcode >= hsize) hcode = hcode - hsize; | |
381 e = &harray [hcode]; | |
382 e_key = e->key; | |
383 } | |
384 while ((e_key)? | |
385 (KEYS_DIFFER_P (e_key, key, test_function)): | |
386 (e->contents == NULL_ENTRY)); | |
387 | |
388 if (e_key) | |
389 { | |
390 e->key = 0; | |
391 e->contents = NULL_ENTRY; | |
392 } | |
393 } | |
394 | |
395 /* only increment the fullness when we used up a new hentry */ | |
396 if (!e_key || (KEYS_DIFFER_P (e_key, key, test_function))) | |
397 hash->fullness++; | |
398 } | |
399 | |
400 static void | |
401 rehash (hentry *harray, c_hashtable hash, unsigned int size) | |
402 { | |
403 hentry *limit = harray + size; | |
404 hentry *e; | |
405 for (e = harray; e < limit; e++) | |
406 { | |
407 if (e->key) | |
408 puthash (e->key, e->contents, hash); | |
409 } | |
410 } | |
411 | |
412 void | |
413 remhash (CONST void *key, c_hashtable hash) | |
414 { | |
415 hentry *harray = hash->harray; | |
416 int (*test_function) (CONST void*, CONST void*) = hash->test_function; | |
417 unsigned int hsize = hash->size; | |
418 unsigned int hcode_initial = | |
419 (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key); | |
420 unsigned int hcode = hcode_initial % hsize; | |
421 hentry *e = &harray [hcode]; | |
422 CONST void *e_key = e->key; | |
423 | |
424 if (!key) | |
425 { | |
426 hash->zero_entry = 0; | |
427 hash->zero_set = 0; | |
428 return; | |
429 } | 137 } |
430 | 138 |
431 if ((e_key)? | 139 if ((e_key)? |
432 (KEYS_DIFFER_P (e_key, key, test_function)): | 140 (KEYS_DIFFER_P (e_key, key, test_function)): |
433 (e->contents == NULL_ENTRY)) | 141 (e->contents == NULL_ENTRY)) |
443 } | 151 } |
444 while ((e_key)? | 152 while ((e_key)? |
445 (KEYS_DIFFER_P (e_key, key, test_function)): | 153 (KEYS_DIFFER_P (e_key, key, test_function)): |
446 (e->contents == NULL_ENTRY)); | 154 (e->contents == NULL_ENTRY)); |
447 } | 155 } |
156 | |
157 *ret_value = e->contents; | |
158 return e->key; | |
159 } | |
160 | |
161 void | |
162 clrhash (c_hashtable hash) | |
163 { | |
164 memset (hash->harray, 0, sizeof (hentry) * hash->size); | |
165 hash->zero_entry = 0; | |
166 hash->zero_set = 0; | |
167 hash->fullness = 0; | |
168 } | |
169 | |
170 void | |
171 free_hashtable (c_hashtable hash) | |
172 { | |
173 #ifdef emacs | |
174 if (!NILP (hash->elisp_table)) | |
175 return; | |
176 #endif | |
177 xfree (hash->harray); | |
178 xfree (hash); | |
179 } | |
180 | |
181 c_hashtable | |
182 make_hashtable (unsigned int hsize) | |
183 { | |
184 c_hashtable res = (c_hashtable) xmalloc (sizeof (struct _C_hashtable)); | |
185 memset (res, 0, sizeof (struct _C_hashtable)); | |
186 res->size = prime_size ((13 * hsize) / 10); | |
187 res->harray = (hentry *) xmalloc (sizeof (hentry) * res->size); | |
188 #ifdef emacs | |
189 res->elisp_table = Qnil; | |
190 #endif | |
191 clrhash (res); | |
192 return res; | |
193 } | |
194 | |
195 c_hashtable | |
196 make_general_hashtable (unsigned int hsize, | |
197 unsigned long (*hash_function) (CONST void *), | |
198 int (*test_function) (CONST void *, CONST void *)) | |
199 { | |
200 c_hashtable res = (c_hashtable) xmalloc (sizeof (struct _C_hashtable)); | |
201 memset (res, 0, sizeof (struct _C_hashtable)); | |
202 res->size = prime_size ((13 * hsize) / 10); | |
203 res->harray = (hentry *) xmalloc (sizeof (hentry) * res->size); | |
204 res->hash_function = hash_function; | |
205 res->test_function = test_function; | |
206 #ifdef emacs | |
207 res->elisp_table = Qnil; | |
208 #endif | |
209 clrhash (res); | |
210 return res; | |
211 } | |
212 | |
213 c_hashtable | |
214 make_strings_hashtable (unsigned int hsize) | |
215 { | |
216 return make_general_hashtable (hsize, string_hash, string_eq); | |
217 } | |
218 | |
219 #ifdef emacs | |
220 unsigned int | |
221 compute_harray_size (unsigned int hsize) | |
222 { | |
223 return prime_size ((13 * hsize) / 10); | |
224 } | |
225 #endif | |
226 | |
227 void | |
228 copy_hash (c_hashtable dest, c_hashtable src) | |
229 { | |
230 #ifdef emacs | |
231 /* if these are not the same, then we are losing here */ | |
232 if ((NILP (dest->elisp_table)) != (NILP (src->elisp_table))) | |
233 { | |
234 error ("Incompatible hashtable types to copy_hash."); | |
235 return; | |
236 } | |
237 #endif | |
238 | |
239 if (dest->size != src->size) | |
240 { | |
241 #ifdef emacs | |
242 if (!NILP (dest->elisp_table)) | |
243 elisp_hvector_free (dest->harray, dest->elisp_table); | |
244 else | |
245 #endif | |
246 xfree (dest->harray); | |
247 | |
248 dest->size = src->size; | |
249 #ifdef emacs | |
250 if (!NILP (dest->elisp_table)) | |
251 dest->harray = (hentry *) | |
252 elisp_hvector_malloc (sizeof (hentry) * dest->size, | |
253 dest->elisp_table); | |
254 else | |
255 #endif | |
256 dest->harray = (hentry *) xmalloc (sizeof (hentry) * dest->size); | |
257 } | |
258 dest->fullness = src->fullness; | |
259 dest->zero_entry = src->zero_entry; | |
260 dest->zero_set = src->zero_set; | |
261 dest->hash_function = src->hash_function; | |
262 dest->test_function = src->test_function; | |
263 memcpy (dest->harray, src->harray, sizeof (hentry) * dest->size); | |
264 } | |
265 | |
266 static void | |
267 grow_hashtable (c_hashtable hash, unsigned int new_size) | |
268 { | |
269 unsigned int old_hsize = hash->size; | |
270 hentry *old_harray = hash->harray; | |
271 unsigned int new_hsize = prime_size (new_size); | |
272 hentry *new_harray; | |
273 | |
274 #ifdef emacs | |
275 /* We test for Qzero to facilitate free-hook.c. That module creates | |
276 a hashtable very very early, at which point Qnil has not yet | |
277 been set and is thus all zeroes. Qzero is "automatically" | |
278 initialized at startup because its correct value is also all | |
279 zeroes. */ | |
280 if (!NILP (hash->elisp_table) && !ZEROP (hash->elisp_table)) | |
281 new_harray = (hentry *) elisp_hvector_malloc (sizeof (hentry) * new_hsize, | |
282 hash->elisp_table); | |
283 else | |
284 #endif | |
285 new_harray = (hentry *) xmalloc (sizeof (hentry) * new_hsize); | |
286 | |
287 hash->size = new_hsize; | |
288 hash->harray = new_harray; | |
289 | |
290 /* do the rehash on the "grown" table */ | |
291 { | |
292 long old_zero_set = hash->zero_set; | |
293 void *old_zero_entry = hash->zero_entry; | |
294 clrhash (hash); | |
295 hash->zero_set = old_zero_set; | |
296 hash->zero_entry = old_zero_entry; | |
297 rehash (old_harray, hash, old_hsize); | |
298 } | |
299 | |
300 #ifdef emacs | |
301 if (!NILP (hash->elisp_table) && !ZEROP (hash->elisp_table)) | |
302 elisp_hvector_free (old_harray, hash->elisp_table); | |
303 else | |
304 #endif | |
305 xfree (old_harray); | |
306 } | |
307 | |
308 void | |
309 expand_hashtable (c_hashtable hash, unsigned int needed_size) | |
310 { | |
311 unsigned int hsize = hash->size; | |
312 int comfortable_size = (13 * needed_size) / 10; | |
313 if (hsize < comfortable_size) | |
314 grow_hashtable (hash, comfortable_size + 1); | |
315 } | |
316 | |
317 void | |
318 puthash (CONST void *key, void *cont, c_hashtable hash) | |
319 { | |
320 unsigned int hsize = hash->size; | |
321 int (*test_function) (CONST void *, CONST void *) = hash->test_function; | |
322 unsigned int fullness = hash->fullness; | |
323 hentry *harray; | |
324 CONST void *e_key; | |
325 hentry *e; | |
326 unsigned int hcode_initial = | |
327 (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key); | |
328 unsigned int hcode; | |
329 unsigned int incr = 0; | |
330 unsigned int h2; | |
331 CONST void *oldcontents; | |
332 | |
333 if (!key) | |
334 { | |
335 hash->zero_entry = cont; | |
336 hash->zero_set = 1; | |
337 return; | |
338 } | |
339 | |
340 if (hsize < (1 + ((13 * fullness) / 10))) | |
341 { | |
342 grow_hashtable (hash, hsize + 1); | |
343 hsize = hash->size; | |
344 fullness = hash->fullness; | |
345 } | |
346 | |
347 harray= hash->harray; | |
348 h2 = hsize - 2; | |
349 | |
350 hcode = hcode_initial % hsize; | |
351 | |
352 e_key = harray [hcode].key; | |
353 if (e_key && (KEYS_DIFFER_P (e_key, key, test_function))) | |
354 { | |
355 h2 = hsize - 2; | |
356 incr = 1 + (hcode_initial % h2); | |
357 do | |
358 { | |
359 hcode = hcode + incr; | |
360 if (hcode >= hsize) hcode = hcode - hsize; | |
361 e_key = harray [hcode].key; | |
362 } | |
363 while (e_key && (KEYS_DIFFER_P (e_key, key, test_function))); | |
364 } | |
365 oldcontents = harray [hcode].contents; | |
366 harray [hcode].key = key; | |
367 harray [hcode].contents = cont; | |
368 /* if the entry that we used was a deleted entry, | |
369 check for a non deleted entry of the same key, | |
370 then delete it */ | |
371 if (!e_key && (oldcontents == NULL_ENTRY)) | |
372 { | |
373 if (!incr) incr = 1 + ((unsigned long) key % h2); | |
374 | |
375 do | |
376 { | |
377 hcode = hcode + incr; | |
378 if (hcode >= hsize) hcode = hcode - hsize; | |
379 e = &harray [hcode]; | |
380 e_key = e->key; | |
381 } | |
382 while ((e_key)? | |
383 (KEYS_DIFFER_P (e_key, key, test_function)): | |
384 (e->contents == NULL_ENTRY)); | |
385 | |
386 if (e_key) | |
387 { | |
388 e->key = 0; | |
389 e->contents = NULL_ENTRY; | |
390 } | |
391 } | |
392 | |
393 /* only increment the fullness when we used up a new hentry */ | |
394 if (!e_key || (KEYS_DIFFER_P (e_key, key, test_function))) | |
395 hash->fullness++; | |
396 } | |
397 | |
398 static void | |
399 rehash (hentry *harray, c_hashtable hash, unsigned int size) | |
400 { | |
401 hentry *limit = harray + size; | |
402 hentry *e; | |
403 for (e = harray; e < limit; e++) | |
404 { | |
405 if (e->key) | |
406 puthash (e->key, e->contents, hash); | |
407 } | |
408 } | |
409 | |
410 void | |
411 remhash (CONST void *key, c_hashtable hash) | |
412 { | |
413 hentry *harray = hash->harray; | |
414 int (*test_function) (CONST void*, CONST void*) = hash->test_function; | |
415 unsigned int hsize = hash->size; | |
416 unsigned int hcode_initial = | |
417 (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key); | |
418 unsigned int hcode = hcode_initial % hsize; | |
419 hentry *e = &harray [hcode]; | |
420 CONST void *e_key = e->key; | |
421 | |
422 if (!key) | |
423 { | |
424 hash->zero_entry = 0; | |
425 hash->zero_set = 0; | |
426 return; | |
427 } | |
428 | |
429 if ((e_key)? | |
430 (KEYS_DIFFER_P (e_key, key, test_function)): | |
431 (e->contents == NULL_ENTRY)) | |
432 { | |
433 unsigned int h2 = hsize - 2; | |
434 unsigned int incr = 1 + (hcode_initial % h2); | |
435 do | |
436 { | |
437 hcode = hcode + incr; | |
438 if (hcode >= hsize) hcode = hcode - hsize; | |
439 e = &harray [hcode]; | |
440 e_key = e->key; | |
441 } | |
442 while ((e_key)? | |
443 (KEYS_DIFFER_P (e_key, key, test_function)): | |
444 (e->contents == NULL_ENTRY)); | |
445 } | |
448 if (e_key) | 446 if (e_key) |
449 { | 447 { |
450 e->key = 0; | 448 e->key = 0; |
451 e->contents = NULL_ENTRY; | 449 e->contents = NULL_ENTRY; |
452 /* Note: you can't do fullness-- here, it breaks the world. */ | 450 /* Note: you can't do fullness-- here, it breaks the world. */ |
453 } | 451 } |
454 } | 452 } |
455 | 453 |
456 void | 454 void |
457 maphash (maphash_function mf, c_hashtable hash, void *arg) | 455 maphash (maphash_function mf, c_hashtable hash, void *arg) |
458 { | 456 { |
459 hentry *e; | 457 hentry *e; |
460 hentry *limit; | 458 hentry *limit; |
461 | 459 |
462 if (hash->zero_set) | 460 if (hash->zero_set) |
463 ((*mf) (0, hash->zero_entry, arg)); | 461 ((*mf) (0, hash->zero_entry, arg)); |
464 | 462 |
465 for (e = hash->harray, limit = e + hash->size; e < limit; e++) | 463 for (e = hash->harray, limit = e + hash->size; e < limit; e++) |
466 { | 464 { |
467 if (e->key) | 465 if (e->key) |
468 ((*mf) (e->key, e->contents, arg)); | 466 ((*mf) (e->key, e->contents, arg)); |
469 } | 467 } |
470 } | 468 } |
471 | 469 |
472 void | 470 void |
473 map_remhash (remhash_predicate predicate, c_hashtable hash, void *arg) | 471 map_remhash (remhash_predicate predicate, c_hashtable hash, void *arg) |
474 { | 472 { |
475 hentry *e; | 473 hentry *e; |
476 hentry *limit; | 474 hentry *limit; |
477 | 475 |
478 if (hash->zero_set && ((*predicate) (0, hash->zero_entry, arg))) | 476 if (hash->zero_set && ((*predicate) (0, hash->zero_entry, arg))) |
479 { | 477 { |
480 hash->zero_set = 0; | 478 hash->zero_set = 0; |
481 hash->zero_entry = 0; | 479 hash->zero_entry = 0; |
482 } | 480 } |