1 /* Fixed size hash table with internal linking.
2 Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
9 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
19 or both in parallel, as here.
21 elfutils is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
33 #include <sys/cdefs.h>
34 #include <sys/param.h>
38 #define CONCAT(t1,t2) __CONCAT (t1,t2)
40 /* Before including this file the following macros must be defined:
42 TYPE data type of the hash table entries
43 HASHFCT name of the hashing function to use
44 HASHTYPE type used for the hashing value
45 COMPARE comparison function taking two pointers to TYPE objects
46 CLASS can be defined to `static' to avoid exporting the functions
47 PREFIX prefix to be used for function and data type names
48 STORE_POINTER if defined the table stores a pointer and not an element
50 INSERT_HASH if defined alternate insert function which takes a hash
52 NO_FINI_FCT if defined the fini function is not defined
56 /* Defined separately. */
57 extern size_t next_prime (size_t seed);
60 /* Set default values. */
62 # define HASHTYPE size_t
74 /* The data structure. */
75 struct CONCAT(PREFIX,fshash)
78 struct CONCAT(PREFIX,fshashent)
82 # define ENTRYP(el) (el).entry
85 # define ENTRYP(el) &(el).entry
92 /* Constructor for the hashing table. */
93 CLASS struct CONCAT(PREFIX,fshash) *
94 CONCAT(PREFIX,fshash_init) (size_t nelems)
96 struct CONCAT(PREFIX,fshash) *result;
97 /* We choose a size for the hashing table 150% over the number of
98 entries. This will guarantee short medium search lengths. */
99 const size_t max_size_t = ~((size_t) 0);
101 if (nelems >= (max_size_t / 3) * 2)
107 /* Adjust the size to be used for the hashing table. */
108 nelems = next_prime (MAX ((nelems * 3) / 2, 10));
110 /* Allocate the data structure for the result. */
111 result = (struct CONCAT(PREFIX,fshash) *)
112 xcalloc (sizeof (struct CONCAT(PREFIX,fshash))
113 + (nelems + 1) * sizeof (struct CONCAT(PREFIX,fshashent)), 1);
117 result->nslots = nelems;
125 CONCAT(PREFIX,fshash_fini) (struct CONCAT(PREFIX,fshash) *htab)
132 static struct CONCAT(PREFIX,fshashent) *
133 CONCAT(PREFIX,fshash_lookup) (struct CONCAT(PREFIX,fshash) *htab,
134 HASHTYPE hval, TYPE *data)
136 size_t idx = 1 + hval % htab->nslots;
138 if (htab->table[idx].hval != 0)
142 /* See whether this is the same entry. */
143 if (htab->table[idx].hval == hval
144 && COMPARE (data, ENTRYP (htab->table[idx])) == 0)
145 return &htab->table[idx];
147 /* Second hash function as suggested in [Knuth]. */
148 hash = 1 + hval % (htab->nslots - 2);
153 idx = htab->nslots + idx - hash;
157 if (htab->table[idx].hval == hval
158 && COMPARE (data, ENTRYP(htab->table[idx])) == 0)
159 return &htab->table[idx];
161 while (htab->table[idx].hval != 0);
164 return &htab->table[idx];
169 __attribute__ ((unused))
170 CONCAT(PREFIX,fshash_insert) (struct CONCAT(PREFIX,fshash) *htab,
172 size_t len __attribute__ ((unused)), TYPE *data)
174 HASHTYPE hval = HASHFCT (str, len ?: strlen (str));
175 struct CONCAT(PREFIX,fshashent) *slot;
177 slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data);
179 /* We don't want to overwrite the old value. */
195 __attribute__ ((unused))
196 CONCAT(PREFIX,fshash_insert_hash) (struct CONCAT(PREFIX,fshash) *htab,
197 HASHTYPE hval, TYPE *data)
199 struct CONCAT(PREFIX,fshashent) *slot;
201 slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data);
203 /* We don't want to overwrite the old value. */
219 __attribute__ ((unused))
220 CONCAT(PREFIX,fshash_overwrite) (struct CONCAT(PREFIX,fshash) *htab,
222 size_t len __attribute__ ((unused)),
225 HASHTYPE hval = HASHFCT (str, len ?: strlen (str));
226 struct CONCAT(PREFIX,fshashent) *slot;
228 slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data);
241 CONCAT(PREFIX,fshash_find) (const struct CONCAT(PREFIX,fshash) *htab,
243 size_t len __attribute__ ((unused)), TYPE *data)
245 HASHTYPE hval = HASHFCT (str, len ?: strlen (str));
246 struct CONCAT(PREFIX,fshashent) *slot;
248 slot = CONCAT(PREFIX,fshash_lookup) ((struct CONCAT(PREFIX,fshash) *) htab,
254 return ENTRYP(*slot);
258 /* Unset the macros we expect. */