4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Routines for manipulating hash tables
36 #include <sys/types.h>
37 #include <sys/sysmacros.h>
47 int (*h_hashfn)(int, void *);
48 int (*h_cmp)(void *, void *);
53 int (*hd_fun)(void *, void *);
61 hash_def_hash(int nbuckets, void *arg)
63 uintptr_t data = (uintptr_t) arg;
64 return (data % nbuckets);
68 hash_def_cmp(void *d1, void *d2)
75 hash_name(int nbuckets, const char *name)
81 for (c = name; *c; c++) {
83 if ((g = (h & 0xf0000000)) != 0) {
89 return (h % nbuckets);
93 hash_new(int nbuckets, int (*hashfn)(int, void *), int (*cmp)(void *, void *))
97 hash = xmalloc(sizeof (hash_t));
98 hash->h_buckets = xcalloc(sizeof (list_t *) * nbuckets);
99 hash->h_nbuckets = nbuckets;
100 hash->h_hashfn = hashfn ? hashfn : hash_def_hash;
101 hash->h_cmp = cmp ? cmp : hash_def_cmp;
107 hash_add(hash_t *hash, void *key)
109 int bucket = hash->h_hashfn(hash->h_nbuckets, key);
111 list_add(&hash->h_buckets[bucket], key);
115 hash_add_cb(void *node, void *private)
117 hash_add((hash_t *)private, node);
122 hash_merge(hash_t *to, hash_t *from)
124 (void) hash_iter(from, hash_add_cb, to);
128 hash_remove_cb(void *key1, void *key2, void *arg)
131 return (hash->h_cmp(key1, key2));
135 hash_remove(hash_t *hash, void *key)
137 int bucket = hash->h_hashfn(hash->h_nbuckets, key);
139 (void) list_remove(&hash->h_buckets[bucket], key,
140 hash_remove_cb, hash);
144 hash_match(hash_t *hash, void *key, int (*fun)(void *, void *),
147 int bucket = hash->h_hashfn(hash->h_nbuckets, key);
149 return (list_iter(hash->h_buckets[bucket], fun, private) < 0);
153 hash_find_list_cb(void *node, void *arg)
155 struct hash_data *hd = arg;
159 if (hd->hd_hash->h_cmp(hd->hd_key, node) == 0) {
160 if ((cbrc = hd->hd_fun(node, hd->hd_private)) < 0)
169 hash_find_iter(hash_t *hash, void *key, int (*fun)(void *, void *),
172 int bucket = hash->h_hashfn(hash->h_nbuckets, key);
178 hd.hd_private = private;
180 return (list_iter(hash->h_buckets[bucket], hash_find_list_cb,
184 /* stop on first match */
186 hash_find_first_cb(void *node, void *arg)
188 struct hash_data *hd = arg;
189 if (hd->hd_hash->h_cmp(hd->hd_key, node) == 0) {
198 hash_find(hash_t *hash, void *key, void **value)
204 hd.hd_fun = hash_find_first_cb;
207 ret = hash_match(hash, key, hash_find_first_cb, &hd);
215 hash_iter(hash_t *hash, int (*fun)(void *, void *), void *private)
221 for (i = 0; i < hash->h_nbuckets; i++) {
222 if (hash->h_buckets[i] != NULL) {
223 if ((cbrc = list_iter(hash->h_buckets[i], fun,
234 hash_count(hash_t *hash)
238 for (num = 0, i = 0; i < hash->h_nbuckets; i++)
239 num += list_count(hash->h_buckets[i]);
245 hash_free(hash_t *hash, void (*datafree)(void *, void *), void *private)
252 for (i = 0; i < hash->h_nbuckets; i++)
253 list_free(hash->h_buckets[i], datafree, private);
254 free(hash->h_buckets);
259 hash_stats(hash_t *hash, int verbose)
261 int min = list_count(hash->h_buckets[0]);
270 printf("%3d: %d\n", 0, min);
271 for (i = 1; i < hash->h_nbuckets; i++) {
272 count = list_count(hash->h_buckets[i]);
281 if (count && verbose)
282 printf("%3d: %d\n", i, count);
286 printf("Hash statistics:\n");
287 printf(" Buckets: %d\n", hash->h_nbuckets);
288 printf(" Items : %d\n", tot);
289 printf(" Min/Max: %d in #%d, %d in #%d\n", min, minidx, max, maxidx);
290 printf(" Average: %5.2f\n", (float)tot / (float)hash->h_nbuckets);