/* hash.c */ #include #include #include "hash.h" #include "mem.h" /* * Declare hash as: * struct hashentry hash[HASHSIZE]; * * Initialise with hash_init(hash); * free all hash items with hash_clear(hash); */ /* * Based on Jenkins one-at-a-time hash, from * http://en.wikipedia.org/wiki/Hash_table */ int hashfn(char *key) { uint32_t hash = 0; size_t i; size_t len = strlen(key); for (i = 0; i < len; i++) { hash += key[i]; hash += (hash << 10); hash ^= (hash >> 6); } hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15); return hash & HASHMASK; } void hash_iterate(struct hashentry **hash, void (*fn)(struct hashentry *)) { int i; struct hashentry *hashptr; for (i = 0; i < HASHSIZE; i++) if (hash[i]) { hashptr = hash[i]; while (hashptr) { fn(hashptr); hashptr = hashptr->next; } } } void hash_clear(struct hashentry **hash) { int i; struct hashentry *hashptr; struct hashentry *last; for (i = 0; i < HASHSIZE; i++) if (hash[i]) { hashptr = hash[i]; while (hashptr) { last = hashptr; hashptr = hashptr->next; free(last); } } } void hash_init(struct hashentry **hash) { bzero(hash, sizeof(struct hashentry *) * HASHSIZE); } struct hashentry *hash_lookup(struct hashentry **base, char *key, int create) { struct hashentry *hashptr; int hash; int found; hash = hashfn(key); hashptr = base[hash]; found = 0; while (hashptr) { if (strcmp(key, hashptr->name) == 0) return hashptr; hashptr = hashptr->next; } if (!create) return NULL; hashptr = safe_malloc(sizeof(struct hashentry)); hashptr->next = base[hash]; hashptr->name = NULL; /* Signal that this is new */ base[hash] = hashptr; return hashptr; }