muse1.7b4/
muse1.7b4/config/
muse1.7b4/doc/
muse1.7b4/run/
muse1.7b4/run/db/
muse1.7b4/src/
muse1.7b4/src/db/
muse1.7b4/src/files/
muse1.7b4/src/io/
muse1.7b4/src/prog/
muse1.7b4/src/util/
/* $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;
}