/*
 * hash.c
 *	A hashed lookup mechanism
 */

#include <memory.h>
#include <string.h>
/* #include <malloc.h> */
#include <stdlib.h>

#include "hash.h"

static unsigned int
hashidstr(register const char* key, unsigned int size)
{
	register unsigned int h;

	for (h = 0; *key; key++) {
		h = ( (64 * h) + *key) % size;
	}

	return h;
}


struct hash *
hash_alloc(int hashsize)
{
	struct hash *h;

	if (hashsize <= 0) {
		return NULL;
	}

	h = (struct hash *)malloc(sizeof(struct hash) + hashsize*sizeof(struct hash *));
	if (h) {
		h->h_hashsize = hashsize;
   		memset(&h->h_hash, 0, hashsize*sizeof(struct hash *));
	}
	return(h);
}

int
hash_insert_str(struct hash *h, const char *key, void *val)
{
	struct hash_node *hn;
	unsigned int idx;

	if (!h) {
		return(1);
	}
	idx = hashidstr(key, h->h_hashsize);
	hn = (struct hash_node *)malloc(sizeof(struct hash_node));
	if (!hn) {
		return(1);
	}
	hn->h_key = (long)key;
	hn->h_data = val;
	hn->h_next = h->h_hash[idx];
	h->h_hash[idx] = hn;

	return(0);
}

int hash_delete_str(struct hash *h, const char *key)
{
	struct hash_node **hnp, *hn;
	unsigned int idx;

	if (!h) {
		return(1);
	}

	idx = hashidstr(key, h->h_hashsize);
	hnp = &h->h_hash[idx];
	hn = *hnp;
	while (hn) {
		if (strcmp((char *)hn->h_key, key) == 0 ) {
			*hnp = hn->h_next;
			free(hn);
			return(0);
		}
		hnp = &hn->h_next;
		hn = *hnp;
	}
	return(1);
}

void
hash_dealloc(struct hash *h)
{
	unsigned int x;
	struct hash_node *hn, *hnn;

	for (x = 0; x < h->h_hashsize; ++x) {
		for (hn = h->h_hash[x]; hn; hn = hnn) {
			hnn = hn->h_next;
			free(hn);
		}
	}
	free(h);
}

void *
hash_lookup_str(struct hash *h, const char *key)
{
	struct hash_node *hn;
	unsigned int idx;

	if (!h) {
		return(0);
	}
	idx = hashidstr(key, h->h_hashsize);
	for (hn = h->h_hash[idx]; hn; hn = hn->h_next) {
		if (strcmp((char *)hn->h_key, key) == 0) {
			return(hn->h_data);
		}
	}
	return(0);
}

void *
hash_lookup_str2(struct hash *h, const char *key, unsigned int *found, struct hash_node **hn2)
{
	struct hash_node *hn;
	unsigned int idx;

	if (!h) {
		return(0);
	}
	idx = hashidstr(key, h->h_hashsize);

	if (*hn2) {
		hn = *hn2;
	} else {
		if (*found) {
			return 0;
		}
		hn = h->h_hash[idx];
	}

	for (; hn; hn = hn->h_next) {
		if (strcmp((char *)hn->h_key, key) == 0) {
			*hn2 = hn->h_next;
			(*found)++;
			return (hn->h_data);
		}
	}

	return(0);
}



syntax highlighted by Code2HTML, v. 0.9.1