ref: d3298a0f73f8d45249df6b45b167ae17bea22167
dir: /hash.c/
#include <u.h>
#include <libc.h>
#include "hash.h"
Hmap*
allochmap(uvlong (*hash)(Hnode*), int (*cmp)(Hnode*,Hnode*), int nbuckets, usize size)
{
Hmap *h = mallocz(sizeof(Hmap), 1);
if(h == nil)
return nil;
h->size = nbuckets;
h->nsize = size;
h->hash = hash;
h->cmp = cmp;
h->len = h->cap = nbuckets;
h->nodes = mallocz(h->cap*h->nsize, 1);
if(h->nodes == nil)
return nil;
return h;
}
void
hmapset(Hmap *h, Hnode *new)
{
Hnode *n, *tmp;
tmp = nil;
wlock(h);
n = (Hnode*)(h->nodes + (h->hash(new)%h->size)*h->nsize);
for(;;){
if(n->filled == 0)
goto replace;
if(h->cmp(n, new) == 0){
tmp = n->next;
goto replace;
}
if(n->next == nil)
break;
n = n->next;
}
if(h->cap == h->len){
h->cap *= 2;
h->nodes = realloc(h->nodes, h->cap*h->nsize);
memset(h->nodes + h->len*h->nsize, 0, h->nsize);
}
n->next = (Hnode*)(h->nodes + h->len*h->nsize);
h->len++;
assert(h->len < h->cap);
n = n->next;
replace:
memmove(n, new, h->nsize);
n->filled++;
n->next = tmp;
wunlock(h);
}
Hnode*
hmapget(Hmap *h, Hnode *q)
{
Hnode *n;
rlock(h);
n = (Hnode*)(h->nodes + (h->hash(q)%h->size)*h->nsize);
for(; n!=nil; n=n->next)
if(n->filled != 0 && h->cmp(n, q) == 0){
runlock(h);
return n;
}
runlock(h);
return nil;
}
void
hmapmark(Hmap *h, Hnode *n)
{
wlock(h);
n->filled = 0;
wunlock(h);
}
Hnode*
hmapdel(Hmap *h, Hnode *q)
{
Hnode *n;
n = hmapget(h, q);
if(n == nil)
return nil;
hmapmark(h, n);
return n;
}
void
hmapfree(Hmap *h)
{
free(h->nodes);
free(h);
}
int
hmapfmt(Fmt *f)
{
Hmap *h;
Hnode *n, *o;
Rune r[3] = {0, 0, 0};
char fmt[16];
int i, len;
h = va_arg(f->args, Hmap*);
rlock(h);
r[0] = '%';
r[1] = h->nodeverb;
snprint(fmt, sizeof fmt - 1, "%S", r);
for(i=len=0; i < h->size; i++){
n = (Hnode*)(h->nodes + i*h->nsize);
for(o=n; o != nil; o = o->next)
if(n->filled != 0)
len += fmtprint(f, (char*)fmt, o);
}
runlock(h);
return len;
}