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 }