#define _NIMLIB_
#include<perfstat.h>
#include<hashtable.h>
#include<stdlib.h>
KHMEXP hashtable * KHMAPI hash_new_hashtable(khm_int32 n,
hash_function_t hash,
comp_function_t comp,
add_ref_function_t addr,
del_ref_function_t delr)
{
hashtable * h;
h = PMALLOC(sizeof(hashtable));
h->n = n;
h->addr = addr;
h->comp = comp;
h->delr = delr;
h->hash = hash;
h->bins = PCALLOC(sizeof(hash_bin *), n);
return h;
}
KHMEXP void KHMAPI hash_del_hashtable(hashtable * h) {
hash_bin * b;
int i;
for(i=0;i<h->n;i++) {
LPOP(&h->bins[i], &b);
while(b) {
if(h->delr)
h->delr(b->key, b->data);
PFREE(b);
LPOP(&h->bins[i], &b);
}
}
if (h->bins)
PFREE(h->bins);
PFREE(h);
}
KHMEXP void KHMAPI hash_add(hashtable * h, const void * key, void * data) {
int hv;
hash_bin * b;
hv = h->hash(key) % h->n;
b = h->bins[hv];
while(b) {
if(!h->comp(b->key, key)) {
if(h->delr)
h->delr(b->key, b->data);
b->key = key;
b->data = data;
if(h->addr)
h->addr(b->key, b->data);
break;
}
b = LNEXT(b);
}
if(!b) {
b = PMALLOC(sizeof(hash_bin));
b->data = data;
b->key = key;
LINIT(b);
LPUSH(&h->bins[hv], b);
if(h->addr)
h->addr(b->key, b->data);
}
}
KHMEXP void KHMAPI hash_del(hashtable * h, const void * key) {
hash_bin * b;
int hv;
hv = h->hash(key) % h->n;
b = h->bins[hv];
while(b) {
if(!h->comp(b->key, key)) {
LDELETE(&h->bins[hv], b);
if(h->delr)
h->delr(b->key, b->data);
PFREE(b);
break;
}
b = LNEXT(b);
}
}
KHMEXP void * KHMAPI hash_lookup(hashtable * h, const void * key) {
hash_bin * b;
int hv;
hv = h->hash(key) % h->n;
b = h->bins[hv];
while(b) {
if(!h->comp(b->key, key)) {
return b->data;
}
b = LNEXT(b);
}
return NULL;
}
KHMEXP khm_boolean KHMAPI hash_exist(hashtable * h, const void * key) {
hash_bin * b;
int hv;
hv = h->hash(key) % h->n;
b = h->bins[hv];
while(b) {
if(!h->comp(b->key, key))
return 1;
b = LNEXT(b);
}
return 0;
}
KHMEXP khm_int32 hash_string(const void *vs) {
khm_int32 hv = 13331;
wchar_t * c;
for(c = (wchar_t *) vs; *c; c++) {
hv = ((hv<<5) + hv) + (khm_int32) *c;
}
return (hv & KHM_INT32_MAX);
}
KHMEXP khm_int32 hash_string_comp(const void *vs1, const void *vs2) {
return wcscmp((const wchar_t *) vs1, (const wchar_t *) vs2);
}