#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hash.h"
hash_table *
hash_create(int (*cmp_func) (const void *, const void *),
uint32_t (*hash_func) (const void *, int), int hsz)
{
hash_table *htbl;
htbl = malloc(sizeof(hash_table));
if (htbl == NULL)
return NULL;
if (hsz < 1)
htbl->size = HASH_SIZE;
else
htbl->size = hsz;
htbl->bucket = calloc(htbl->size, sizeof(hash_link *));
htbl->cmp = cmp_func;
htbl->hash = hash_func;
htbl->cur = 0;
htbl->bucket_cur = NULL;
return htbl;
}
hash_link *
hash_first(hash_table *htbl)
{
htbl->cur = 0;
htbl->bucket_cur = NULL;
return hash_next(htbl);
}
hash_link *
hash_next(hash_table *htbl)
{
hash_link *hlink;
if (htbl->bucket_cur != NULL) {
hlink = htbl->bucket_cur;
htbl->bucket_cur = hlink->next;
return hlink;
}
while (htbl->cur < htbl->size) {
if (htbl->bucket[htbl->cur] != NULL) {
hlink = htbl->bucket[htbl->cur++];
htbl->bucket_cur = hlink->next;
return hlink;
}
htbl->cur++;
}
return NULL;
}
hash_link *
hash_lookup(hash_table *htbl, const void *k)
{
int c;
hash_link *w;
if (htbl == NULL || k == NULL)
return NULL;
c = (htbl->hash) (k, (int)htbl->size);
for (w = htbl->bucket[c]; w != NULL; w = w->next)
if (htbl->cmp(w->key, k) == 0)
return w;
return NULL;
}
int
hash_insert(hash_table *htbl, const void *k, void *i)
{
int c;
hash_link *n;
if (htbl == NULL || k == NULL)
return -1;
if ((n = malloc(sizeof(hash_link))) == NULL) {
return -1;
}
c = (htbl->hash) (k, (int)htbl->size);
n->item = i;
n->key = k;
n->next = htbl->bucket[c];
htbl->bucket[c] = n;
return 0;
}
int
hash_delete(hash_table *htbl, const void *k, int memfree)
{
int i;
hash_link *b, *w;
if (htbl == NULL || k == NULL)
return -1;
i = (htbl->hash) (k, (int)htbl->size);
for (w = htbl->bucket[i], b = NULL; w != NULL; w = w->next) {
if (htbl->cmp(w->key, k) == 0) {
if (b != NULL)
b->next = w->next;
else
htbl->bucket[i] = w->next;
if (htbl->bucket_cur == w)
htbl->bucket_cur = w->next;
if (w->item != NULL && memfree) {
free(w->item);
}
free(w);
return 0;
}
b = w;
}
return -1;
}
void
hash_delete_all(hash_table *htbl, int memfree)
{
int i;
hash_link *w, *hl;
for (i = 0; i < htbl->size; i++) {
hl = htbl->bucket[i];
htbl->bucket[i] = NULL;
while (hl != NULL) {
w = hl;
hl = hl->next;
if (memfree && w->item != NULL)
free(w->item);
free(w);
}
}
}
void
hash_free(hash_table *htbl)
{
if (htbl != NULL) {
free(htbl->bucket);
free(htbl);
}
}