btmux-0.6-rc4/doc/
btmux-0.6-rc4/event/
btmux-0.6-rc4/game/
btmux-0.6-rc4/game/maps/
btmux-0.6-rc4/game/mechs/
btmux-0.6-rc4/game/text/help/
btmux-0.6-rc4/game/text/help/cat_faction/
btmux-0.6-rc4/game/text/help/cat_inform/
btmux-0.6-rc4/game/text/help/cat_misc/
btmux-0.6-rc4/game/text/help/cat_mux/
btmux-0.6-rc4/game/text/help/cat_mux/cat_commands/
btmux-0.6-rc4/game/text/help/cat_mux/cat_functions/
btmux-0.6-rc4/game/text/help/cat_templates/
btmux-0.6-rc4/game/text/wizhelp/
btmux-0.6-rc4/include/
btmux-0.6-rc4/misc/
btmux-0.6-rc4/python/
btmux-0.6-rc4/src/hcode/btech/
btmux-0.6-rc4/tree/
/*
 * htab.c - table hashing routines 
 */

#include "copyright.h"
#include "config.h"

#include "db.h"
#include "externs.h"
#include "htab.h"
#include "alloc.h"

#include "mudconf.h"

struct string_dict_entry {
	char *key;
	void *data;
};

static int hrbtab_compare(char *left, char *right, void *arg)
{
	return strcmp(left, right);
}

void hashinit(RBTAB * htab, int size)
{
	memset(htab, 0, sizeof(RBTAB));
	htab->tree = rb_init((void *)hrbtab_compare, NULL);
	htab->last = NULL;
}

/*
 * ---------------------------------------------------------------------------
 * * hashreset: Reset hash table stats.
 */

void hashreset(RBTAB * htab)
{
	htab->checks = 0;
	htab->scans = 0;
	htab->hits = 0;
}

/*
 * ---------------------------------------------------------------------------
 * * hashfind: Look up an entry in a hash table and return a pointer to its
 * * hash data.
 */

void *hashfind(char *str, RBTAB * htab)
{
	int hval, numchecks;
	struct string_dict_entry *ent;

	htab->checks++;
	ent = rb_find(htab->tree, str);
	if(ent) {
		return ent->data;
	} else
		return (void *)ent;
}

/*
 * ---------------------------------------------------------------------------
 * * hashadd: Add a new entry to a hash table.
 */

int hashadd(char *str, void *hashdata, RBTAB * htab)
{
	struct string_dict_entry *ent = malloc(sizeof(struct string_dict_entry));

	if(rb_exists(htab->tree, str))
		return (-1);

	ent->key = strdup(str);
	ent->data = hashdata;

	rb_insert(htab->tree, ent->key, ent);
	return 0;

}

/*
 * ---------------------------------------------------------------------------
 * * hashdelete: Remove an entry from a hash table.
 */

void hashdelete(char *str, RBTAB * htab)
{
	struct string_dict_entry *ent = NULL;

	if(!rb_exists(htab->tree, str)) {
		return;
	}
	ent = rb_delete(htab->tree, str);

	if(ent) {
		if(ent->key)
			free(ent->key);
		free(ent);
	}

	return;
}

/*
 * ---------------------------------------------------------------------------
 * * hashflush: free all the entries in a hashtable.
 */

static int nuke_hash_ent(void *key, void *data, int depth, void *arg)
{
	struct string_dict_entry *ent = (struct string_dict_entry *) data;
	free(ent->key);
	free(ent);
	return 1;
}

void hashflush(RBTAB * htab, int size)
{
	rb_walk(htab->tree, WALK_POSTORDER, nuke_hash_ent, NULL);
	rb_destroy(htab->tree);
	htab->tree = rb_init((void *)hrbtab_compare, NULL);
	if(htab->last)
		free(htab->last);
	htab->last = NULL;
}

/*
 * ---------------------------------------------------------------------------
 * * hashrepl: replace the data part of a hash entry.
 */

int hashrepl(char *str, void *hashdata, RBTAB * htab)
{
	struct string_dict_entry *ent;

	ent = rb_find(htab->tree, str);
	if(!ent)
		return 0;

	ent->data = hashdata;
	return 1;
}

struct hashreplstat {
	void *old;
	void *new;
};

static int hashreplall_cb(void *key, void *data, int depth, void *arg)
{
	struct string_dict_entry *ent = (struct string_dict_entry *) data;
	struct hashreplstat *repl = (struct hashreplstat *) arg;

	if(ent->data == repl->old) {
		ent->data = repl->new;
	}
	return 1;
}

void hashreplall(void *old, void *new, RBTAB * htab)
{
	struct hashreplstat repl = { old, new };

	rb_walk(htab->tree, WALK_INORDER, hashreplall_cb, &repl);
}

/*
 * ---------------------------------------------------------------------------
 * * hashinfo: return an mbuf with hashing stats
 */

char *hashinfo(const char *tab_name, RBTAB * htab)
{
	char *buff;

	buff = alloc_mbuf("hashinfo");
	sprintf(buff, "%-15s %8d", tab_name, rb_size(htab->tree));
	return buff;
}

/*
 * Returns the key for the first hash entry in 'htab'. 
 */

void *hash_firstentry(RBTAB * htab)
{
	struct string_dict_entry *ent;

	if(htab->last)
		free(htab->last);

	ent = rb_search(htab->tree, SEARCH_FIRST, NULL);
	if(ent) {
		htab->last = strdup(ent->key);
		return ent->data;
	}
	htab->last = NULL;

	return NULL;
}

void *hash_nextentry(RBTAB * htab)
{
	struct string_dict_entry *ent;

	if(!htab->last) {
		return hash_firstentry(htab);
	}

	ent = rb_search(htab->tree, SEARCH_GT, htab->last);
	free(htab->last);

	if(ent) {
		htab->last = strdup(ent->key);
		return ent->data;
	} else {
		htab->last = NULL;
		return NULL;
	}
}

char *hash_firstkey(RBTAB * htab)
{
	struct string_dict_entry *ent;
	if(htab->last)
		free(htab->last);

	ent = rb_search(htab->tree, SEARCH_FIRST, NULL);
	if(ent) {
		htab->last = strdup(ent->key);
		return ent->key;
	}
	htab->last = NULL;

	return NULL;
}

char *hash_nextkey(RBTAB * htab)
{
	struct string_dict_entry *ent;

	if(!htab->last) {
		return hash_firstkey(htab);
	}

	ent = rb_search(htab->tree, SEARCH_NEXT, htab->last);
	free(htab->last);

	if(ent) {
		htab->last = strdup(ent->key);
		return ent->key;
	} else {
		htab->last = NULL;
		return NULL;
	}
}