fbmuck-6.05/auto/
fbmuck-6.05/contrib/jresolver/
fbmuck-6.05/contrib/jresolver/org/
fbmuck-6.05/contrib/jresolver/org/fuzzball/
fbmuck-6.05/docs/devel/
fbmuck-6.05/game/
fbmuck-6.05/game/logs/
fbmuck-6.05/game/muf/
fbmuck-6.05/scripts/
fbmuck-6.05/src_docs/
/* $Header: /cvsroot/fbmuck/fbmuck/src/hashtab.c,v 1.3 2001/10/15 02:08:49 revar Exp $ */

/*
 *
 * $Log: hashtab.c,v $
 * Revision 1.3  2001/10/15 02:08:49  revar
 * Minor cleanups for possible Win32 port plans.
 *
 * Revision 1.2  2000/03/29 12:21:02  revar
 * Reformatted all code into consistent format.
 * 	Tabs are 4 spaces.
 * 	Indents are one tab.
 * 	Braces are generally K&R style.
 * Added ARRAY_DIFF, ARRAY_INTERSECT and ARRAY_UNION to man.txt.
 * Rewrote restart script as a bourne shell script.
 *
 * Revision 1.1.1.1  1999/12/16 03:23:29  revar
 * Initial Sourceforge checkin, fb6.00a29
 *
 * Revision 1.1.1.1  1999/12/12 07:27:43  foxen
 * Initial FB6 CVS checkin.
 *
 * Revision 1.1  1996/06/12 02:22:25  foxen
 * Initial revision
 *
 * Revision 5.4  1994/03/14  12:20:58  foxen
 * Fb5.20 release checkpoint.
 *
 * Revision 5.3  1994/03/14  12:08:46  foxen
 * Initial portability mods and bugfixes.
 *
 * Revision 5.2  1994/01/18  20:52:20  foxen
 * Version 5.15 release.
 *
 * Revision 5.1  1993/12/17  00:07:33  foxen
 * initial revision.
 *
 * Revision 1.3  90/09/28  12:21:59  rearl
 * Made some speed enhancements, fixed declarations of const char's.
 *
 * Revision 1.2  90/09/18  07:56:50  rearl
 * Incorporated hash routines into TinyMUCK.
 *
 * Revision 1.1  90/09/16  22:45:01  rearl
 * Initial revision
 *
 *
 * Baseline code 90/09/12  code donated by Gazer, (dbriggs@nrao.edu)
 *                         loosely based on hashing code in K&R II.
 *
 */

#include "config.h"
#include "db.h"
#include "props.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 int
hash(register const char *s, unsigned int hash_size)
{
	unsigned int 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 if not found, otherwise a pointer to the data union.
 */
hash_data *
find_hash(register const char *s, hash_tab * table, unsigned int 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 supercede 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 const char *name, hash_data data, hash_tab * table, unsigned int size)
{
	register hash_entry *hp;
	unsigned int 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(hash_entry));
		if (hp == NULL) {
			perror("add_hash: out of memory!");
			abort();			/* can't allocate new entry -- die */
		}
		hp->next = table[hashval];
		table[hashval] = hp;
		hp->name = (char *) string_dup(name);	/* This might be wasteful. */
		if (hp->name == NULL) {
			perror("add_hash: out of memory!");
			abort();			/* can't allocate new entry -- die */
		}
	}
	/* 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 const char *name, hash_tab * table, unsigned int 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 int size, int freeptrs)
{
	register hash_entry *hp, *np;
	unsigned 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;
	}
}