/* $Id: hash.c,v 1.3 1993/07/25 19:06:50 nils Exp $ */ /* generic hash table functions */ #include "externs.h" #include "hash.h" static struct hashtab *hashtabs=NULL; void free_hash() { struct hashtab *i; struct hashtab *next; for (i=hashtabs; i; i=next) { int j; next = i->next; for (j=0; j<i->nbuckets; j++) { /* int k; for (k=0; j->buckets[j][k].name; k++) free(i->buckets[j][k].name);*/ free(i->buckets[j]); } free(i->buckets); free(i->name); free(i); } } void do_showhash (player, arg1) dbref player; char *arg1; { struct hashtab *i; if (!*arg1) { for (i=hashtabs; i; i=i->next) notify(player,i->name); notify(player,"done."); } else { char buf[1024]; for (i=hashtabs; i; i=i->next) if (!string_compare(arg1, i->name)) { int j; notify(player,tprintf("%s (%d buckets):",i->name, i->nbuckets)); for (j=0; j<i->nbuckets; j++) { int k; notify(player,tprintf(" bucket %d:",j)); for (k=0; i->buckets[j][k].name; k++) { sprintf(buf," %s: %s",i->buckets[j][k].name, (*i->display)(i->buckets[j][k].value)); notify(player,buf); } } return; } notify(player,"couldn't find that."); return; } } struct hashtab *make_hashtab (nbuck, ents, entsize, name, displayfunc) int nbuck; void *ents; int entsize; char *name; char *(*displayfunc) P((void *)); { struct hashtab *op; int i; op = malloc (sizeof (struct hashtab)); op->nbuckets = nbuck; op->buckets = malloc (sizeof (hashbuck) * nbuck); op->name = malloc (strlen(name)+1); strcpy(op->name, name); op->display = displayfunc; op->next = hashtabs; hashtabs = op; for (i=0; i<nbuck; i++) { int numinbuck=1; struct hashdeclent *thisent; for (thisent=ents; thisent->name; thisent = ((void *)thisent)+entsize) { int val=hash_name (thisent->name); if ((val%nbuck) == i) numinbuck++; } op->buckets[i] = malloc (sizeof (struct hashent) * numinbuck); op->buckets[i][--numinbuck].name = NULL; /* end of list marker */ for (thisent=ents; thisent->name; thisent = ((void *)thisent)+entsize) { int val=hash_name (thisent->name); if ((val%nbuck) == i) { op->buckets[i][--numinbuck].name = thisent->name; op->buckets[i][numinbuck].hashnum = val; op->buckets[i][numinbuck].value = thisent; } } } return op; } void *lookup_hash (tab, hashvalue, name) struct hashtab *tab; int hashvalue; char *name; { hashbuck z = tab->buckets[hashvalue%tab->nbuckets]; int i; for (i=0; z[i].name; i++) if (z[i].hashnum == hashvalue) if (!string_compare (z[i].name, name)) return z[i].value; return NULL; } int hash_name (name) char *name; { unsigned short op=0; int i; int j; int shift=0; for (i=0; name[i]; i++) { j = to_lower(name[i]); /* case insensitive */ op ^= j<<(shift); op ^= j>>(16-shift); shift = (shift+11)%16; } return op; }