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 *);
61 hash_def_hash(int nbuckets
, uintptr_t data
)
63 return (data
% nbuckets
);
67 hash_def_cmp(uintptr_t d1
, uintptr_t d2
)
74 hash_name(int nbuckets
, const char *name
)
80 for (c
= name
; *c
; c
++) {
82 if ((g
= (h
& 0xf0000000)) != 0) {
88 return (h
% nbuckets
);
92 hash_new(int nbuckets
, int (*hashfn
)(int, void *), int (*cmp
)(void *, void *))
96 hash
= xmalloc(sizeof (hash_t
));
97 hash
->h_buckets
= xcalloc(sizeof (list_t
*) * nbuckets
);
98 hash
->h_nbuckets
= nbuckets
;
99 hash
->h_hashfn
= hashfn
? hashfn
: (int (*)())hash_def_hash
;
100 hash
->h_cmp
= cmp
? cmp
: (int (*)())hash_def_cmp
;
106 hash_add(hash_t
*hash
, void *key
)
108 int bucket
= hash
->h_hashfn(hash
->h_nbuckets
, key
);
110 list_add(&hash
->h_buckets
[bucket
], key
);
114 hash_add_cb(void *node
, void *private)
116 hash_add((hash_t
*)private, node
);
121 hash_merge(hash_t
*to
, hash_t
*from
)
123 (void) hash_iter(from
, hash_add_cb
, to
);
127 hash_remove_cb(void *key1
, void *key2
, hash_t
*hash
)
129 return (hash
->h_cmp(key1
, key2
));
133 hash_remove(hash_t
*hash
, void *key
)
135 int bucket
= hash
->h_hashfn(hash
->h_nbuckets
, key
);
137 (void) list_remove(&hash
->h_buckets
[bucket
], key
,
138 (int (*)())hash_remove_cb
, hash
);
142 hash_match(hash_t
*hash
, void *key
, int (*fun
)(void *, void *),
145 int bucket
= hash
->h_hashfn(hash
->h_nbuckets
, key
);
147 return (list_iter(hash
->h_buckets
[bucket
], fun
, private) < 0);
151 hash_find_list_cb(void *node
, struct hash_data
*hd
)
156 if (hd
->hd_hash
->h_cmp(hd
->hd_key
, node
) == 0) {
157 if ((cbrc
= hd
->hd_fun(node
, hd
->hd_private
)) < 0)
166 hash_find_iter(hash_t
*hash
, void *key
, int (*fun
)(void *, void *),
169 int bucket
= hash
->h_hashfn(hash
->h_nbuckets
, key
);
175 hd
.hd_private
= private;
177 return (list_iter(hash
->h_buckets
[bucket
], (int (*)())hash_find_list_cb
,
181 /* stop on first match */
183 hash_find_first_cb(void *node
, struct hash_data
*hd
)
185 if (hd
->hd_hash
->h_cmp(hd
->hd_key
, node
) == 0) {
194 hash_find(hash_t
*hash
, void *key
, void **value
)
200 hd
.hd_fun
= hash_find_first_cb
;
203 ret
= hash_match(hash
, key
, (int (*)())hash_find_first_cb
, &hd
);
211 hash_iter(hash_t
*hash
, int (*fun
)(void *, void *), void *private)
217 for (i
= 0; i
< hash
->h_nbuckets
; i
++) {
218 if (hash
->h_buckets
[i
] != NULL
) {
219 if ((cbrc
= list_iter(hash
->h_buckets
[i
], fun
,
230 hash_count(hash_t
*hash
)
234 for (num
= 0, i
= 0; i
< hash
->h_nbuckets
; i
++)
235 num
+= list_count(hash
->h_buckets
[i
]);
241 hash_free(hash_t
*hash
, void (*datafree
)(void *, void *), void *private)
248 for (i
= 0; i
< hash
->h_nbuckets
; i
++)
249 list_free(hash
->h_buckets
[i
], datafree
, private);
250 free(hash
->h_buckets
);
255 hash_stats(hash_t
*hash
, int verbose
)
257 int min
= list_count(hash
->h_buckets
[0]);
266 printf("%3d: %d\n", 0, min
);
267 for (i
= 1; i
< hash
->h_nbuckets
; i
++) {
268 count
= list_count(hash
->h_buckets
[i
]);
277 if (count
&& verbose
)
278 printf("%3d: %d\n", i
, count
);
282 printf("Hash statistics:\n");
283 printf(" Buckets: %d\n", hash
->h_nbuckets
);
284 printf(" Items : %d\n", tot
);
285 printf(" Min/Max: %d in #%d, %d in #%d\n", min
, minidx
, max
, maxidx
);
286 printf(" Average: %5.2f\n", (float)tot
/ (float)hash
->h_nbuckets
);