home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / hash.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-13  |  11.0 KB  |  465 lines

  1. /* Hash tables.
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <string.h>
  21. #include "hash.h"
  22.  
  23. #ifdef emacs
  24. #include "config.h"
  25. #include "lisp.h"
  26. extern Lisp_Object Qnil;
  27. extern char *elisp_hvector_malloc();
  28. extern void elisp_hvector_free();
  29. #define NULL_ENTRY ((void *) Qnil)
  30. #else
  31. #define NULL_ENTRY ((void *) 1)
  32. #endif
  33.  
  34. #define MAXPRIME 62
  35.  
  36. static int 
  37. primes []={
  38.   29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 
  39.   761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 
  40.   8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 
  41.   62851, 75431, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, 
  42.   389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319,
  43.   2009191, 2411033, 2893249
  44. };
  45.  
  46. /* strings code */
  47.  
  48. /* from base/generic-hash.cc, and hence from Dragon book, p436 */
  49. static unsigned long
  50. string_hash (x)
  51.      char *x;
  52.   unsigned int h = 0;
  53.   unsigned int g;
  54.  
  55.   if (!x) return 0;
  56.  
  57.   while (*x != 0)
  58.   {
  59.     h = (h << 4) + *x++;
  60.     if ((g = h & 0xf0000000) != 0)
  61.       h = (h ^ (g >> 24)) ^ g;
  62.   }
  63.  
  64.   return h;
  65. }
  66.  
  67. static int 
  68. string_eq (st1, st2)
  69.      char *st1, *st2;
  70. {
  71.   if (!st1)
  72.     return (st2)?0:1;
  73.   else if (!st2)
  74.     return 0;
  75.   else
  76.     return !strcmp (st1, st2);
  77. }
  78.  
  79.  
  80. static unsigned int 
  81. prime_size (size)
  82.      unsigned int size;
  83. {
  84.   unsigned int i;
  85.   for (i = 0; i < MAXPRIME; i++)
  86.     if (size <= primes [i]) return primes [i];
  87.   return primes [MAXPRIME - 1];
  88. }
  89.  
  90. static void 
  91. rehash (/* hentry *harray, c_hashtable ht, unsigned int size */);
  92.  
  93. #define KEYS_DIFFER_P(old, new, testfun) \
  94.   ((testfun)?(((old) == (new))?0:(!(testfun ((old), new)))):((old) != (new)))
  95.  
  96. void *
  97. gethash (key, hash, ret_value)
  98.      void *key; c_hashtable hash; void **ret_value;
  99. {
  100.   hentry *harray = hash->harray;
  101.   int (*test_function)() = hash->test_function;
  102.   unsigned int hsize = hash->size;
  103.   unsigned int hcode_initial = 
  104.     (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key);
  105.   unsigned int hcode = hcode_initial % hsize;
  106.   hentry *e = &harray [hcode];
  107.   void *e_key = e->key;
  108.  
  109.   if (!key) 
  110.     {
  111.       *ret_value = hash->zero_entry;
  112.       return (void *) hash->zero_set;
  113.     }
  114.     
  115.   if ((e_key)?
  116.       (KEYS_DIFFER_P (e_key, key, test_function)):
  117.       (e->contents == NULL_ENTRY))
  118.     {
  119.       unsigned int h2 = hsize - 2;
  120.       unsigned int incr = 1 + (hcode_initial % h2);
  121.       do
  122.         {
  123.           hcode = hcode + incr;
  124.           if (hcode >= hsize) hcode = hcode - hsize;
  125.           e = &harray [hcode];
  126.           e_key = e->key;
  127.         } 
  128.       while ((e_key)?
  129.              (KEYS_DIFFER_P (e_key, key, test_function)):
  130.              (e->contents == NULL_ENTRY));
  131.     }
  132.  
  133.   *ret_value = e->contents;
  134.   return e->key;
  135. }
  136.  
  137. void 
  138. clrhash (hash)
  139.      c_hashtable hash;
  140. {
  141.   memset (hash->harray, 0, sizeof (hentry) * hash->size);
  142.   hash->zero_entry = 0;
  143.   hash->zero_set = 0;
  144.   hash->fullness = 0;
  145. }
  146.  
  147. void
  148. free_hashtable (hash)
  149.      c_hashtable hash;
  150. {
  151. #ifdef emacs
  152.   if (hash->elisp_table) return;
  153. #endif
  154.   xfree (hash->harray);
  155.   xfree (hash);
  156. }
  157.  
  158. c_hashtable
  159. make_hashtable (hsize)
  160.      unsigned int hsize;
  161. {
  162.   c_hashtable res = (c_hashtable) xmalloc (sizeof (struct _C_hashtable));
  163.   memset (res, 0, sizeof (struct _C_hashtable));
  164.   res->size = prime_size ((13 * hsize) / 10);
  165.   res->harray = (hentry *) xmalloc (sizeof (hentry) * res->size);
  166.   clrhash (res);
  167.   return res;
  168. }
  169.  
  170. c_hashtable
  171. make_general_hashtable (unsigned int hsize,
  172.             unsigned long (*hash_function)(),
  173.             int (*test_function)())
  174. {
  175.   c_hashtable res = (c_hashtable) xmalloc (sizeof (struct _C_hashtable));
  176.   memset (res, 0, sizeof (struct _C_hashtable));
  177.   res->size = prime_size ((13 * hsize) / 10);
  178.   res->harray = (hentry *) xmalloc (sizeof (hentry) * res->size);
  179.   res->hash_function = hash_function;
  180.   res->test_function = test_function;
  181.   clrhash (res);
  182.   return res;
  183. }
  184.  
  185. c_hashtable 
  186. make_strings_hashtable (hsize)
  187.      unsigned int hsize;
  188. {
  189.   return make_general_hashtable (hsize, string_hash, string_eq);
  190. }
  191.  
  192. #ifdef emacs
  193. unsigned int
  194. compute_harray_size (hsize)
  195.      unsigned int hsize;
  196. {
  197.   return prime_size ((13 * hsize) / 10);
  198. }
  199. #endif
  200.  
  201. void
  202. copy_hash (dest, src)
  203.      c_hashtable dest; c_hashtable src;
  204. {
  205. #ifdef emacs
  206.   /* if these are not the same, then we are losing here */
  207.   if ( ((dest->elisp_table)?1:0) != ((src->elisp_table)?1:0) )
  208.     {
  209.       extern void error ();
  210.       error ("Incompatible hashtable types to copy_hash.");
  211.       return;
  212.     }
  213. #endif
  214.  
  215.   if (dest->size != src->size)
  216.     {
  217. #ifdef emacs
  218.       if (dest->elisp_table) 
  219.         elisp_hvector_free (dest->harray, dest->elisp_table);
  220.       else
  221. #endif
  222.         xfree (dest->harray);
  223.  
  224.       dest->size = src->size;
  225. #ifdef emacs
  226.       if (dest->elisp_table)
  227.         dest->harray = 
  228.           (hentry *) elisp_hvector_malloc
  229.             (sizeof (hentry) * dest->size, dest->elisp_table);
  230.       else
  231. #endif
  232.         dest->harray = 
  233.           (hentry *) 
  234.             xmalloc (sizeof (hentry) * dest->size);
  235.     }
  236.   dest->fullness = src->fullness;
  237.   dest->zero_entry = src->zero_entry;
  238.   dest->zero_set = src->zero_set;
  239.   dest->hash_function = src->hash_function;
  240.   dest->test_function = src->test_function;
  241.   memcpy (dest->harray, src->harray, sizeof (hentry) * dest->size);
  242. }
  243.   
  244. static void
  245. grow_hashtable (hash, new_size)
  246.      c_hashtable hash; unsigned int new_size;
  247. {
  248.   unsigned int old_hsize = hash->size;
  249.   hentry *old_harray = hash->harray;
  250.   unsigned int new_hsize = prime_size (new_size);
  251.   hentry *new_harray;
  252.  
  253. #ifdef emacs
  254.   if (hash->elisp_table)
  255.     new_harray = 
  256.       (hentry *) elisp_hvector_malloc
  257.         (sizeof (hentry) * new_hsize, hash->elisp_table);
  258.   else
  259. #endif
  260.     new_harray =
  261.       (hentry *) xmalloc (sizeof (hentry) * new_hsize);
  262.  
  263.   hash->size = new_hsize;
  264.   hash->harray = new_harray;
  265.  
  266.   /* do the rehash on the "grown" table */
  267.   {
  268.     int old_zero_set = hash->zero_set;
  269.     void *old_zero_entry = hash->zero_entry;
  270.     clrhash (hash);
  271.     hash->zero_set = old_zero_set;
  272.     hash->zero_entry = old_zero_entry;
  273.     rehash (old_harray, hash, old_hsize);
  274.   }
  275.  
  276. #ifdef emacs
  277.   if (hash->elisp_table) 
  278.     elisp_hvector_free (old_harray, hash->elisp_table);
  279.   else
  280. #endif
  281.     xfree (old_harray);
  282. }
  283.  
  284. void 
  285. puthash (key, cont, hash)
  286.      void *key; void *cont; c_hashtable hash;
  287. {
  288.   unsigned int hsize = hash->size;
  289.   int (*test_function)() = hash->test_function;
  290.   unsigned int fullness = hash->fullness;
  291.   hentry *harray;
  292.   void *e_key;
  293.   hentry *e;
  294.   unsigned int hcode_initial = 
  295.     (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key);
  296.   unsigned int hcode;
  297.   unsigned int incr = 0;
  298.   unsigned int h2;
  299.   void *oldcontents;
  300.  
  301.   if (!key) 
  302.     {
  303.       hash->zero_entry = cont;      
  304.       hash->zero_set = 1;
  305.       return;
  306.     }
  307.  
  308.   if (hsize < (1 + ((13 * fullness) / 10)))
  309.     {
  310.       grow_hashtable (hash, hsize + 1);
  311.       hsize = hash->size;
  312.       fullness = hash->fullness;
  313.     }
  314.  
  315.   harray= hash->harray;
  316.   h2 = hsize - 2;
  317.  
  318.   hcode = hcode_initial % hsize;
  319.   
  320.   e_key = harray [hcode].key;
  321.   if (e_key && (KEYS_DIFFER_P (e_key, key, test_function)))
  322.     {
  323.       h2 = hsize - 2;
  324.       incr = 1 + (hcode_initial % h2);
  325.       do
  326.         {
  327.           hcode = hcode + incr;
  328.           if (hcode >= hsize) hcode = hcode - hsize;
  329.           e_key = harray [hcode].key;
  330.         } 
  331.       while (e_key && (KEYS_DIFFER_P (e_key, key, test_function)));
  332.     }
  333.   oldcontents = harray [hcode].contents;
  334.   harray [hcode].key = (void *) key;
  335.   harray [hcode].contents = (void *) cont;
  336.   /* if the entry that we used was a deleted entry,
  337.      check for a non deleted entry of the same key,
  338.      then delete it */
  339.   if (!e_key && (oldcontents == NULL_ENTRY))
  340.     {
  341.       if (!incr) incr = 1 + ((unsigned long) key % h2);
  342.  
  343.       do
  344.         {
  345.           hcode = hcode + incr;
  346.           if (hcode >= hsize) hcode = hcode - hsize;
  347.           e = &harray [hcode];
  348.           e_key = e->key;
  349.         }
  350.       while ((e_key)?
  351.              (KEYS_DIFFER_P (e_key, key, test_function)):
  352.              (e->contents == NULL_ENTRY));
  353.  
  354.       if (e_key)
  355.         {
  356.           e->key = 0;
  357.           e->contents = NULL_ENTRY;
  358.         }
  359.     }
  360.  
  361.   /* only increment the fullness when we used up a new hentry */
  362.   if (!e_key || (KEYS_DIFFER_P (e_key, key, test_function)))
  363.     hash->fullness++;
  364. }
  365.  
  366. static void
  367. rehash (harray, hash, size)
  368.      hentry *harray; c_hashtable hash; unsigned int size;
  369. {
  370.   hentry *limit = harray + size;
  371.   hentry *e;
  372.   for (e = harray; e < limit; e++) 
  373.     if (e->key) puthash (e->key, e->contents, hash);
  374. }
  375.  
  376. void 
  377. remhash (key, hash)
  378.      void *key; c_hashtable hash;
  379. {
  380.   hentry *harray = hash->harray;
  381.   int (*test_function)() = hash->test_function;
  382.   unsigned int hsize = hash->size;
  383.   unsigned int hcode_initial = 
  384.     (hash->hash_function)?(hash->hash_function(key)):((unsigned long) key);
  385.   unsigned int hcode = hcode_initial % hsize;
  386.   hentry *e = &harray [hcode];
  387.   void *e_key = e->key;
  388.  
  389.   if (!key) 
  390.     {
  391.       hash->zero_entry = 0;
  392.       hash->zero_set = 0;
  393.       return;
  394.     }
  395.  
  396.   if ((e_key)?
  397.       (KEYS_DIFFER_P (e_key, key, test_function)):
  398.       (e->contents == NULL_ENTRY))
  399.     {
  400.       unsigned int h2 = hsize - 2;
  401.       unsigned int incr = 1 + (hcode_initial % h2);
  402.       do
  403.         {
  404.           hcode = hcode + incr;
  405.           if (hcode >= hsize) hcode = hcode - hsize;
  406.           e = &harray [hcode];
  407.           e_key = e->key;
  408.         }
  409.       while ((e_key)?
  410.              (KEYS_DIFFER_P (e_key, key, test_function)):
  411.              (e->contents == NULL_ENTRY));
  412.     }
  413.   if (e_key)
  414.     {
  415.       e->key = 0;
  416.       e->contents = NULL_ENTRY;
  417. /* This seems to break the world and I don't understand why. 
  418.    Keymaps need a correct count of how many items are really in
  419.    the table, taking remhash into account, but it looks like I
  420.    have to do it by hand in the keymap code.  -jwz
  421.  
  422.       hash->fullness--;
  423.  */
  424.     }
  425. }
  426.  
  427. void 
  428. maphash (mf, hash, arg)
  429.      maphash_function mf; c_hashtable hash; void *arg;
  430. {
  431.   hentry *e;
  432.   hentry *limit;
  433.   
  434.   if (hash->zero_set) (*mf) (0, hash->zero_entry, arg);
  435.  
  436.   for (e = hash->harray, limit = e + hash->size; e < limit; e++)
  437.     if (e->key) (*mf) (e->key, e->contents, arg);
  438. }
  439.  
  440.  
  441. void 
  442. map_remhash (predicate, hash, arg)
  443.      remhash_predicate predicate; 
  444.      c_hashtable hash; 
  445.      void *arg;
  446. {
  447.   hentry *e;
  448.   hentry *limit;
  449.   
  450.   if (hash->zero_set && ((*predicate) (0, hash->zero_entry, arg)))
  451.     {
  452.       hash->zero_set = 0;
  453.       hash->zero_entry = 0;
  454.     }
  455.  
  456.   for (e = hash->harray, limit = e + hash->size; e < limit; e++)
  457.     if ((*predicate) (e->key, e->contents, arg))
  458.       {
  459.         e->key = 0;
  460.         e->contents = NULL_ENTRY;
  461.       }
  462. }
  463.  
  464.