2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Synched up with: Not in FSF. */
27 #define NULL_ENTRY (LISP_TO_VOID (Qnil))
31 #define NULL_ENTRY ((void *) 1)
38 static CONST unsigned int
41 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631,
42 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013,
43 8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361,
44 62851, 75431, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449,
45 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319,
46 2009191, 2411033, 2893249
51 /* from base/generic-hash.cc, and hence from Dragon book, p436 */
53 string_hash (CONST void *xv)
56 unsigned CONST char *x = (unsigned CONST char *) xv;
64 if ((g = h & 0xf0000000) != 0)
65 h = (h ^ (g >> 24)) ^ g;
72 memory_hash (CONST void *xv, size_t size)
75 unsigned CONST char *x = (unsigned CONST char *) xv;
83 if ((g = h & 0xf0000000) != 0)
84 h = (h ^ (g >> 24)) ^ g;
92 string_eq (CONST void *st1, CONST void *st2)
99 return !strcmp ( (CONST char *) st1, (CONST char *) st2);
103 /* ### Ever heard of binary search? */
105 prime_size (unsigned int size)
108 for (i = 0; i < countof (primes); i++)
109 if (size <= primes [i])
111 return primes [countof (primes) - 1];
114 static void rehash (hentry *harray, c_hashtable ht, unsigned int size);
116 #define KEYS_DIFFER_P(old, new, testfun) \
117 ((testfun)?(((old) == (new))?0:(!(testfun ((old), new)))):((old) != (new)))
120 gethash (CONST void *key, c_hashtable hash, CONST void **ret_value)
122 hentry *harray = hash->harray;
123 int (*test_function) (CONST void *, CONST void *) = hash->test_function;
124 unsigned int hsize = hash->size;
125 unsigned int hcode_initial =
126 (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key);
127 unsigned int hcode = hcode_initial % hsize;
128 hentry *e = &harray [hcode];
129 CONST void *e_key = e->key;
133 *ret_value = hash->zero_entry;
134 return (void *) hash->zero_set;
138 (KEYS_DIFFER_P (e_key, key, test_function)):
139 (e->contents == NULL_ENTRY))
141 unsigned int h2 = hsize - 2;
142 unsigned int incr = 1 + (hcode_initial % h2);
145 hcode = hcode + incr;
146 if (hcode >= hsize) hcode = hcode - hsize;
151 (KEYS_DIFFER_P (e_key, key, test_function)):
152 (e->contents == NULL_ENTRY));
155 *ret_value = e->contents;
160 clrhash (c_hashtable hash)
162 memset (hash->harray, 0, sizeof (hentry) * hash->size);
163 hash->zero_entry = 0;
169 free_hashtable (c_hashtable hash)
172 if (!NILP (hash->elisp_table))
175 xfree (hash->harray);
180 make_hashtable (unsigned int hsize)
182 c_hashtable res = xnew_and_zero (struct _C_hashtable);
183 res->size = prime_size ((13 * hsize) / 10);
184 res->harray = xnew_array (hentry, res->size);
186 res->elisp_table = Qnil;
193 make_general_hashtable (unsigned int hsize,
194 unsigned long (*hash_function) (CONST void *),
195 int (*test_function) (CONST void *, CONST void *))
197 c_hashtable res = xnew_and_zero (struct _C_hashtable);
198 res->size = prime_size ((13 * hsize) / 10);
199 res->harray = xnew_array (hentry, res->size);
200 res->hash_function = hash_function;
201 res->test_function = test_function;
203 res->elisp_table = Qnil;
210 make_strings_hashtable (unsigned int hsize)
212 return make_general_hashtable (hsize, string_hash, string_eq);
217 compute_harray_size (unsigned int hsize)
219 return prime_size ((13 * hsize) / 10);
224 copy_hash (c_hashtable dest, c_hashtable src)
227 /* if these are not the same, then we are losing here */
228 if ((NILP (dest->elisp_table)) != (NILP (src->elisp_table)))
230 error ("Incompatible hashtable types to copy_hash.");
235 if (dest->size != src->size)
238 if (!NILP (dest->elisp_table))
239 elisp_hvector_free (dest->harray, dest->elisp_table);
242 xfree (dest->harray);
244 dest->size = src->size;
246 if (!NILP (dest->elisp_table))
247 dest->harray = (hentry *)
248 elisp_hvector_malloc (sizeof (hentry) * dest->size,
252 dest->harray = xnew_array (hentry, dest->size);
254 dest->fullness = src->fullness;
255 dest->zero_entry = src->zero_entry;
256 dest->zero_set = src->zero_set;
257 dest->hash_function = src->hash_function;
258 dest->test_function = src->test_function;
259 memcpy (dest->harray, src->harray, sizeof (hentry) * dest->size);
263 grow_hashtable (c_hashtable hash, unsigned int new_size)
265 unsigned int old_hsize = hash->size;
266 hentry *old_harray = hash->harray;
267 unsigned int new_hsize = prime_size (new_size);
271 /* We test for Qzero to facilitate free-hook.c. That module creates
272 a hashtable very very early, at which point Qnil has not yet
273 been set and is thus all zeroes. Qzero is "automatically"
274 initialized at startup because its correct value is also all
276 if (!EQ (hash->elisp_table, Qnull_pointer) &&
277 !NILP (hash->elisp_table) &&
278 !ZEROP (hash->elisp_table))
279 new_harray = (hentry *) elisp_hvector_malloc (sizeof (hentry) * new_hsize,
283 new_harray = (hentry *) xmalloc (sizeof (hentry) * new_hsize);
285 hash->size = new_hsize;
286 hash->harray = new_harray;
288 /* do the rehash on the "grown" table */
290 long old_zero_set = hash->zero_set;
291 void *old_zero_entry = hash->zero_entry;
293 hash->zero_set = old_zero_set;
294 hash->zero_entry = old_zero_entry;
295 rehash (old_harray, hash, old_hsize);
299 if (!EQ (hash->elisp_table, Qnull_pointer) &&
300 !NILP (hash->elisp_table) &&
301 !ZEROP (hash->elisp_table))
302 elisp_hvector_free (old_harray, hash->elisp_table);
309 expand_hashtable (c_hashtable hash, unsigned int needed_size)
311 size_t hsize = hash->size;
312 size_t comfortable_size = (13 * needed_size) / 10;
313 if (hsize < comfortable_size)
314 grow_hashtable (hash, comfortable_size + 1);
318 puthash (CONST void *key, void *cont, c_hashtable hash)
320 unsigned int hsize = hash->size;
321 int (*test_function) (CONST void *, CONST void *) = hash->test_function;
322 unsigned int fullness = hash->fullness;
326 unsigned int hcode_initial =
327 (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key);
329 unsigned int incr = 0;
331 CONST void *oldcontents;
335 hash->zero_entry = cont;
340 if (hsize < (1 + ((13 * fullness) / 10)))
342 grow_hashtable (hash, hsize + 1);
344 fullness = hash->fullness;
347 harray= hash->harray;
350 hcode = hcode_initial % hsize;
352 e_key = harray [hcode].key;
353 if (e_key && (KEYS_DIFFER_P (e_key, key, test_function)))
356 incr = 1 + (hcode_initial % h2);
359 hcode = hcode + incr;
360 if (hcode >= hsize) hcode = hcode - hsize;
361 e_key = harray [hcode].key;
363 while (e_key && (KEYS_DIFFER_P (e_key, key, test_function)));
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,
371 if (!e_key && (oldcontents == NULL_ENTRY))
373 if (!incr) incr = 1 + ((unsigned long) key % h2);
377 hcode = hcode + incr;
378 if (hcode >= hsize) hcode = hcode - hsize;
383 (KEYS_DIFFER_P (e_key, key, test_function)):
384 (e->contents == NULL_ENTRY));
389 e->contents = NULL_ENTRY;
393 /* only increment the fullness when we used up a new hentry */
394 if (!e_key || (KEYS_DIFFER_P (e_key, key, test_function)))
399 rehash (hentry *harray, c_hashtable hash, unsigned int size)
401 hentry *limit = harray + size;
403 for (e = harray; e < limit; e++)
406 puthash (e->key, e->contents, hash);
411 remhash (CONST void *key, c_hashtable hash)
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;
424 hash->zero_entry = 0;
430 (KEYS_DIFFER_P (e_key, key, test_function)):
431 (e->contents == NULL_ENTRY))
433 unsigned int h2 = hsize - 2;
434 unsigned int incr = 1 + (hcode_initial % h2);
437 hcode = hcode + incr;
438 if (hcode >= hsize) hcode = hcode - hsize;
443 (KEYS_DIFFER_P (e_key, key, test_function)):
444 (e->contents == NULL_ENTRY));
449 e->contents = NULL_ENTRY;
450 /* Note: you can't do fullness-- here, it breaks the world. */
455 maphash (maphash_function mf, c_hashtable hash, void *arg)
462 if (((*mf) (0, hash->zero_entry, arg)))
466 for (e = hash->harray, limit = e + hash->size; e < limit; e++)
470 if (((*mf) (e->key, e->contents, arg)))
477 map_remhash (remhash_predicate predicate, c_hashtable hash, void *arg)
482 if (hash->zero_set && ((*predicate) (0, hash->zero_entry, arg)))
485 hash->zero_entry = 0;
488 for (e = hash->harray, limit = e + hash->size; e < limit; e++)
489 if ((*predicate) (e->key, e->contents, arg))
492 e->contents = NULL_ENTRY;