summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdlib/strhash.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdlib/strhash.c')
-rw-r--r--lib/libc/stdlib/strhash.c103
1 files changed, 55 insertions, 48 deletions
diff --git a/lib/libc/stdlib/strhash.c b/lib/libc/stdlib/strhash.c
index 77bc02e..0b50ce0 100644
--- a/lib/libc/stdlib/strhash.c
+++ b/lib/libc/stdlib/strhash.c
@@ -1,5 +1,5 @@
#ifndef lint
-static char *rcsid = "$Header: /home/ncvs/src/lib/libc/stdlib/strhash.c,v 1.2 1995/03/26 19:32:24 ache Exp $";
+static char *rcsid = "$Header: /home/ncvs/src/lib/libc/stdlib/strhash.c,v 1.3 1995/03/28 08:41:02 jkh Exp $";
#endif
/*
@@ -12,12 +12,12 @@ static char *rcsid = "$Header: /home/ncvs/src/lib/libc/stdlib/strhash.c,v 1.2 19
*
*
* All rights reserved.
- *
+ *
* This is unsupported software and is subject to change without notice.
* the author makes no representations about the suitability of this software
* for any purpose. It is supplied "as is" without express or implied
* warranty.
- *
+ *
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
@@ -32,11 +32,18 @@ static char *rcsid = "$Header: /home/ncvs/src/lib/libc/stdlib/strhash.c,v 1.2 19
* This is a fairly simple open addressing hash scheme.
* Terry did all the code, I just did the spec.
* Thanks again, you crazy Aussie..
- *
+ *
*/
/*
* $Log: strhash.c,v $
+ * Revision 1.3 1995/03/28 08:41:02 jkh
+ * Fix a missing _hash() to prevent namespace pollution with the db/hash routines.
+ * Grrr. If the dbhash routines weren't grossly overengineered I wouldn't
+ * even need to do this! :-(
+ *
+ * Also now export the hash_stats routine. Manpage coming RSN - I promise.
+ *
* Revision 1.2 1995/03/26 19:32:24 ache
* Hash 8bit chars without sign extension
*
@@ -53,35 +60,35 @@ static char *rcsid = "$Header: /home/ncvs/src/lib/libc/stdlib/strhash.c,v 1.2 19
*
* Revision 2.0 90/03/26 01:44:26 jkh
* pre-beta check-in
- *
+ *
* Revision 1.8 90/03/09 19:22:35 jkh
* Fixed bogus comment.
- *
+ *
* Revision 1.7 90/03/09 19:01:08 jkh
* Added comments, GPL.
- *
+ *
* Revision 1.6 90/03/08 17:55:58 terry
* Rearranged hash_purge to be a tiny bit more efficient.
* Added verbose option to hash_stats.
- *
+ *
* Revision 1.5 90/03/08 17:19:54 terry
* Added hash_purge. Added arg to hash_traverse. Changed all
* void * to Generic.
- *
+ *
* Revision 1.4 90/03/08 12:02:35 terry
* Fixed problems with allocation that I screwed up last night.
* Changed bucket lists to be singly linked. Thanks to JKH, my hero.
- *
+ *
* Revision 1.3 90/03/07 21:33:33 terry
* Cleaned up a few decls to keep gcc -Wall quiet.
- *
+ *
* Revision 1.2 90/03/07 21:14:53 terry
* Comments. Added HASH_STATS define. Removed hash_find()
* and new_node().
- *
+ *
* Revision 1.1 90/03/07 20:49:45 terry
* Initial revision
- *
+ *
*
*/
@@ -112,26 +119,26 @@ static hash_node *list_find(caddr_t key, hash_node *head);
hash_table *
hash_create(int size)
{
- register int i;
+ register int i;
hash_table *new = (hash_table *)malloc(sizeof(hash_table));
if (!new || size < 0){
return HASH_NULL;
}
-
+
if (size == 0){
size = HASH_SZ;
}
-
+
if (!(new->buckets = (hash_node **)malloc(size * sizeof(hash_node *)))){
return HASH_NULL;
}
for (i = 0; i < size; i++){
new->buckets[i] = NODE_NULL;
- }
+ }
new->size = size;
-
+
return new;
}
@@ -166,7 +173,7 @@ _hash(int size, char *key)
while (*key){
h = (h << 1) ^ (h ^ (unsigned char) *key++);
- }
+ }
h %= size;
return h;
@@ -179,17 +186,17 @@ _hash(int size, char *key)
* The function (*nukefunc)() is in charge of disposing
* of the storage help by the data associated with the node.
*/
-void
+void
hash_destroy(hash_table *table, char *key, void (*nukefunc)())
{
int bucket = _hash(table->size, key);
hash_node *found = table->buckets[bucket];
hash_node *to_free = NODE_NULL;
-
+
if (!found) {
return;
}
-
+
if (!strcmp(found->key, key)) {
/*
* It was the head of the list.
@@ -209,12 +216,12 @@ hash_destroy(hash_table *table, char *key, void (*nukefunc)())
}
found = found->next;
}
-
+
if (!to_free){
return;
}
}
-
+
if (nukefunc)
(*nukefunc)(to_free->key, to_free->data);
free(to_free);
@@ -227,8 +234,8 @@ hash_destroy(hash_table *table, char *key, void (*nukefunc)())
*
* Search the table for the given key. Then:
*
- * 1) If you find it and there is no replacement function, just
- * return what you found. (This is a simple search).
+ * 1) If you find it and there is no replacement function, just
+ * return what you found. (This is a simple search).
* 2) If you find it and there is a replacement function, run
* the function on the data you found, and replace the old
* data with whatever is passed in datum. Return 0.
@@ -256,11 +263,11 @@ hash_search(hash_table *table, caddr_t key, void *datum,
}
else{
if (datum){
-
+
static int assign_key();
-
+
hash_node *new = (hash_node *)malloc(sizeof(hash_node));
-
+
if (!new || !assign_key(key, new)){
return GENERIC_NULL;
}
@@ -276,7 +283,7 @@ hash_search(hash_table *table, caddr_t key, void *datum,
/*
* assign_key()
*
- * Set the key value of a node to be 'key'. Get some space from
+ * Set the key value of a node to be 'key'. Get some space from
* malloc and copy it in etc. Return 1 if all is well, 0 otherwise.
*/
static int
@@ -285,11 +292,11 @@ assign_key(char *key, hash_node *node)
if (!node || !key){
return 0;
}
-
+
if (!(node->key = (char *)malloc(strlen(key) + 1))){
return 0;
}
-
+
node->key[0] = '\0';
strcat(node->key, key);
return 1;
@@ -304,12 +311,12 @@ assign_key(char *key, hash_node *node)
void
hash_traverse(hash_table *table, int (*func)(), void *arg)
{
- register int i;
+ register int i;
register int size = table->size;
if (!func)
return;
-
+
for (i = 0; i < size; i++) {
hash_node *n = table->buckets[i];
while (n) {
@@ -317,7 +324,7 @@ hash_traverse(hash_table *table, int (*func)(), void *arg)
return;
n = n->next;
}
- }
+ }
return;
}
@@ -331,9 +338,9 @@ hash_traverse(hash_table *table, int (*func)(), void *arg)
void
hash_purge(hash_table *table, void (*purge_func)(char *p1, void *p2))
{
- register int i;
+ register int i;
register int size = table->size;
-
+
for (i = 0; i < size; i++) {
hash_node *n = table->buckets[i];
if (n) {
@@ -347,7 +354,7 @@ hash_purge(hash_table *table, void (*purge_func)(char *p1, void *p2))
} while (n);
table->buckets[i] = NODE_NULL;
}
- }
+ }
}
#undef min
@@ -361,19 +368,19 @@ hash_purge(hash_table *table, void (*purge_func)(char *p1, void *p2))
void
hash_stats(hash_table *table, int verbose)
{
- register int i;
+ register int i;
int total_elements = 0;
int non_empty_buckets = 0;
int max_count = 0;
int max_repeats = 0;
int *counts;
int size = table->size;
-
+
if (!(counts = (int *)malloc(size * sizeof(int)))){
fprintf(stderr, "malloc returns 0\n");
- exit(1);
+ exit(1);
}
-
+
for (i = 0; i < size; i++){
int x = 0;
hash_node *n = table->buckets[i];
@@ -392,7 +399,7 @@ hash_stats(hash_table *table, int verbose)
counts[i]++;
n = n->next;
}
-
+
total_elements += counts[i];
if (counts[i] > max_count){
max_count = counts[i];
@@ -401,17 +408,17 @@ hash_stats(hash_table *table, int verbose)
else if (counts[i] == max_count){
max_repeats++;
}
-
+
if (counts[i] && verbose){
printf(" (%d)\n", counts[i]);
}
- }
-
+ }
+
printf("\n");
printf("%d element%s in storage.\n", total_elements, total_elements == 1 ? "" : "s");
-
+
if (total_elements){
- printf("%d of %d (%.2f%%) buckets are in use\n", non_empty_buckets, size,
+ printf("%d of %d (%.2f%%) buckets are in use\n", non_empty_buckets, size,
(double)100 * (double)non_empty_buckets / (double)(size));
printf("the maximum number of elements in a bucket is %d (%d times)\n", max_count, max_repeats);
printf("average per bucket is %f\n", (double)total_elements / (double)non_empty_buckets);
OpenPOWER on IntegriCloud