X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/b93ad4221f3b60a851a9986f7d3841847075a2c8..fa59b86f7d1d4ee8dc71252100fbc9c0f93e37b7:/lib/hash.c diff --git a/lib/hash.c b/lib/hash.c index 18675c11..c0c19d8e 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -1,44 +1,57 @@ -/* $Header$ +/* $Id$ * * Generic hash table routines. Uses integer keys to store char * values. + * + * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * . */ -#include -#include "sms_app.h" -#define NULL 0 +#include +#include + +#include +#include +RCSID("$Header$"); + +#define hash_func(h, key) (key >= 0 ? (key % h->size) : (-key % h->size)) /* Create a hash table. The size is just a hint, not a maximum. */ -struct hash *create_hash(size) -int size; +struct hash *create_hash(int size) { - struct hash *h; - - h = (struct hash *) malloc(sizeof(struct hash)); - h->size = size; - h->data = (struct bucket **) malloc(size * sizeof(char *)); - bzero(h->data, size * sizeof(char *)); - return(h); + struct hash *h; + + h = malloc(sizeof(struct hash)); + if (!h) + return NULL; + h->size = size; + h->data = malloc(size * sizeof(void *)); + if (!h->data) + { + free(h); + return NULL; + } + memset(h->data, 0, size * sizeof(void *)); + return h; } /* Lookup an object in the hash table. Returns the value associated with * the key, or NULL (thus NULL is not a very good value to store...) */ -char *hash_lookup(h, key) -struct hash *h; -register int key; +void *hash_lookup(struct hash *h, int key) { - register struct bucket *b; - - b = h->data[key % h->size]; - while (b && b->key != key) - b = b->next; - if (b && b->key == key) - return(b->data); - else - return(NULL); + struct bucket *b; + + b = h->data[hash_func(h, key)]; + while (b && b->key != key) + b = b->next; + if (b && b->key == key) + return b->data; + else + return NULL; } @@ -46,55 +59,57 @@ register int key; * existed, or 0 if not. */ -int hash_update(h, key, value) -struct hash *h; -register int key; -char *value; +int hash_update(struct hash *h, int key, void *value) { - register struct bucket *b; - - b = h->data[key % h->size]; - while (b && b->key != key) - b = b->next; - if (b && b->key == key) { - b->data = value; - return(1); - } else - return(0); + struct bucket *b; + + b = h->data[hash_func(h, key)]; + while (b && b->key != key) + b = b->next; + if (b && b->key == key) + { + b->data = value; + return 1; + } + else + return 0; } /* Store an item in the hash table. Returns 0 if the key was not previously - * there, or 1 if it was. + * there, 1 if it was, or -1 if we ran out of memory. */ -int hash_store(h, key, value) -struct hash *h; -register int key; -char *value; +int hash_store(struct hash *h, int key, void *value) { - register struct bucket *b, **p; - - p = &(h->data[key % h->size]); - if (*p == NULL) { - b = *p = (struct bucket *) malloc(sizeof(struct bucket)); - b->next = NULL; - b->key = key; - b->data = value; - return(0); + struct bucket *b, **p; + + p = &(h->data[hash_func(h, key)]); + if (!*p) + { + b = *p = malloc(sizeof(struct bucket)); + if (!b) + return -1; + b->next = NULL; + b->key = key; + b->data = value; + return 0; } - for (b = *p; b && b->key != key; b = *p) - p = (struct bucket **) *p; - if (b && b->key == key) { - b->data = value; - return(1); + for (b = *p; b && b->key != key; b = *p) + p = (struct bucket **) *p; + if (b && b->key == key) + { + b->data = value; + return 1; } - b = *p = (struct bucket *) malloc(sizeof(struct bucket)); - b->next = NULL; - b->key = key; - b->data = value; - return(0); + b = *p = malloc(sizeof(struct bucket)); + if (!b) + return -1; + b->next = NULL; + b->key = key; + b->data = value; + return 0; } @@ -102,33 +117,49 @@ char *value; * data with that value, call the callback proc with the corresponding key. */ -hash_search(h, value, callback) -struct hash *h; -register char *value; -void (*callback)(); +void hash_search(struct hash *h, void *value, void (*callback)(int)) { - register struct bucket *b, **p; - - for (p = &(h->data[h->size - 1]); p >= h->data; p--) { - for (b = *p; b; b = b->next) { - if (b->data == value) - (*callback)(b->key); + struct bucket *b, **p; + + for (p = &(h->data[h->size - 1]); p >= h->data; p--) + { + for (b = *p; b; b = b->next) + { + if (b->data == value) + (*callback)(b->key); } } } -/* Deallocate all of the memory associated with a table */ +/* Step through the hash table, calling the callback proc with each key. + */ -hash_destroy(h) -struct hash *h; +void hash_step(struct hash *h, void (*callback)(int, void *, void *), + void *hint) { - register struct bucket *b, **p, *b1; + struct bucket *b, **p; + + for (p = &(h->data[h->size - 1]); p >= h->data; p--) + { + for (b = *p; b; b = b->next) + (*callback)(b->key, b->data, hint); + } +} - for (p = &(h->data[h->size - 1]); p >= h->data; p--) { - for (b = *p; b; b = b1) { - b1 = b->next; - free(b); + +/* Deallocate all of the memory associated with a table */ + +void hash_destroy(struct hash *h) +{ + struct bucket *b, **p, *b1; + + for (p = &(h->data[h->size - 1]); p >= h->data; p--) + { + for (b = *p; b; b = b1) + { + b1 = b->next; + free(b); } } }