#include "config.h" #include "db.h" #include "externs.h" /* hash: compute hash value for a string * * this particular hash function is fairly simple. Note that it * throws away the information from the 0x20 bit in the character. * This means that upper and lower case letters will hash to the * same value. */ unsigned hash(register char *s, unsigned hash_size) { unsigned hashval; for (hashval = 0; *s != '\0'; s++) hashval = (*s | 0x20) + 31 * hashval; return hashval % hash_size; } /* find_hash: lookup a name in a hash table * * returns NULL is not found, otherwise a pointer to the data union. */ hash_data *find_hash(register char *s, hash_tab * table, unsigned size) { register hash_entry *hp; for (hp = table[hash(s, size)]; hp != NULL; hp = hp->next) if (string_compare(s, hp->name) == 0) return &(hp->dat); /* found */ return NULL; /* not found */ } /* add_hash: add a string to a hash table * * will superceede old values in the table, returns pointer to * the hash entry, or NULL on failure. * * NB: These hash routines assume that the names are static entities. * The hash entries store only a pointer to the names. Be sure to * make a static copy of the name before adding it to the table. */ hash_entry * add_hash(register char *name, hash_data data, hash_tab * table, unsigned size) { register hash_entry *hp; unsigned hashval; hashval = hash(name, size); /* an inline find_hash */ for (hp = table[hashval]; hp != NULL; hp = hp->next) if (string_compare(name, hp->name) == 0) break; /* If not found, set up a new entry */ if (hp == NULL) { hp = (hash_entry *) malloc(sizeof(*hp)); if (hp == NULL) /* can't allocate new entry -- die */ return NULL; hp->next = table[hashval]; table[hashval] = hp; hp->name = (char *) strdup(name); } /* One way or another, the pointer is now valid */ hp->dat = data; return hp; } /* free_hash: free a hash table entry * * frees the dynamically allocated hash table entry associated with * a name. Returns 0 on success, or -1 if the name cannot be found. */ int free_hash(register char *name, hash_tab * table, unsigned size) { register hash_entry **lp, *hp; lp = &table[hash(name, size)]; for (hp = *lp; hp != NULL; lp = &hp->next, hp = hp->next) if (string_compare(name, hp->name) == 0) { *lp = hp->next; /* got it. fix the pointers */ free((void *) hp->name); free((void *) hp); return 0; } return -1; /* not found */ } /* kill_hash: kill an entire hash table, by freeing every entry */ void kill_hash(hash_tab * table, unsigned size, int freeptrs) { register hash_entry *hp, *np; int i; for (i = 0; i < size; i++) { for (hp = table[i]; hp != NULL; hp = np) { np = hp->next; /* Don't dereference the pointer after */ free((void *) hp->name); if (freeptrs) free((void *) hp->dat.pval); free((void *) hp); /* we've freed it! */ } table[i] = NULL; } }