/*
** HASH: Simple hash table implementation.
** Copyright (C) 2002 Michael W. Shaffer <mwshaffer@angrypot.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program (see the file COPYING). If not, write to:
**
** The Free Software Foundation, Inc.
** 59 Temple Place, Suite 330,
** Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#include "primes.h"
#include "list.h"
#include "hash.h"
/* Peter J. Wienberger's hash */
static unsigned long hash_pjw (char *value)
{
unsigned long h = 0;
unsigned long g = 0;
while (*value) {
h = (h << 4) + *(value++);
if ((g = h & 0xF0000000))
h ^= g >> 24;
h &= ~g;
}
return h;
}
void hash_table_init (struct hash_table *h)
{
int i = 0;
if (!h)
return;
if (h->size < 1)
h->size = 100;
h->size = find_prime (h->size);
h->tbl = (struct list *) malloc (h->size * (sizeof (struct list)));
if (!h->tbl)
return;
memset (h->tbl, 0, (h->size * sizeof (struct list)));
for (i = 0 ; i < h->size ; i++) {
list_init (&(h->tbl[i]));
}
return;
}
void hash_table_free (struct hash_table *h)
{
int i = 0;
struct datum *d = NULL;
struct list_item *curr = NULL;
if (!h)
return;
for (i = 0 ; i < h->size ; i++) {
for (curr = h->tbl[i].head ; curr ; curr = curr->next) {
if (curr->data) {
d = (struct datum *) curr->data;
if (d->key)
free (d->key);
if (d->val)
free (d->val);
}
}
list_free (&(h->tbl[i]));
}
if (h->tbl)
free (h->tbl);
h->size = 0;
h->tbl = NULL;
return;
}
struct datum *hash_table_insert (struct hash_table *h, struct datum *d)
{
int slot = 0;
struct datum *new = NULL;
struct list_item *item = NULL;
if (!(d && h && (h->size > 0) && h->tbl))
return NULL;
new = (struct datum *) malloc (sizeof (struct datum));
if (!new)
goto ERROR;
memset (new, 0, (sizeof (struct datum)));
new->ksize = d->ksize;
new->key = (void *) malloc (new->ksize + 1);
if (!new->key)
goto ERROR;
memset (new->key, 0, (new->ksize + 1));
memcpy (new->key, d->key, new->ksize);
new->vsize = d->vsize;
new->val = (void *) malloc (new->vsize + 1);
if (!new->val)
goto ERROR;
memset (new->val, 0, (new->vsize + 1));
memcpy (new->val, d->val, new->vsize);
slot = (int) (hash_pjw (d->key) % h->size);
item = list_insert (&(h->tbl[slot]), (void *) new, sizeof (struct datum));
goto EXIT;
ERROR:
if (new && (new->key))
free (new->key);
if (new && (new->val))
free (new->val);
EXIT:
if (new)
free (new);
return (struct datum *) item->data;
}
struct datum *hash_table_search (struct hash_table *h, struct datum *k)
{
int slot = 0;
struct list_item *curr = NULL;
struct datum *d = NULL;
if (!(k && h && (h->size > 0) && h->tbl))
goto EXIT;
slot = (int) (hash_pjw (k->key) % h->size);
for (curr = h->tbl[slot].head ; curr ; curr = curr->next) {
d = (struct datum *) curr->data;
if (d->ksize == k->ksize){
if (!memcmp (d->key, k->key, d->ksize))
goto EXIT;
}
}
d = NULL;
EXIT:
return d;
}
static struct list_item *hash_table_search2 (struct hash_table *h, struct datum *k)
{
int slot = 0;
struct list_item *curr = NULL;
struct datum *d = NULL;
if (!(k && h && (h->size > 0) && h->tbl))
goto EXIT;
slot = (int) (hash_pjw (k->key) % h->size);
for (curr = h->tbl[slot].head ; curr ; curr = curr->next) {
d = (struct datum *) curr->data;
if (d->ksize == k->ksize){
if (!memcmp (d->key, k->key, d->ksize))
goto EXIT;
}
}
curr = NULL;
EXIT:
return curr;
}
void hash_table_delete (struct hash_table *h, struct datum *k)
{
struct datum *d = NULL;
struct list_item *l = NULL;
if (!(k && h && (h->size > 0) && h->tbl))
return;
if ((l = hash_table_search2 (h, k))) {
d = (struct datum *) l->data;
if (d->key)
free (d->key);
if (d->val)
free (d->val);
list_delete ((struct list_item *) l);
}
return;
}
syntax highlighted by Code2HTML, v. 0.9.1