ref: 9ae12fa984b9bc0eb0a33f9c0cf5b4ebd47ecd6d
dir: /hash.c/
#include <u.h> #include <libc.h> #include "hash.h" typedef struct Hnode Hnode; struct Hnode { int filled; int next; void *key; }; enum{ Tagsize = sizeof(Hnode), }; Hmap* allochmap(uvlong (*hash)(void*), int (*cmp)(void*,void*), int nbuckets, int size) { void *store; Hmap *h; int nsz; nsz = Tagsize + size; store = mallocz(sizeof(*h) + (nbuckets * nsz), 1); if(store == nil) return nil; h = store; h->nbs = nbuckets; h->nsz = nsz; h->hash = hash; h->cmp = cmp; h->len = h->cap = nbuckets; h->nodes = store; h->nodes += sizeof(*h); return store; } void hmapset(Hmap **store, void *key, void *new) { Hnode *n; uchar *v; Hmap *h; int next; h = *store; v = h->nodes + (h->hash(key)%h->nbs) * h->nsz; for(;;){ n = (Hnode*)v; next = n->next; if(n->filled == 0) goto replace; if(h->cmp(n->key, key) == 0) goto replace; if(next == 0) break; v = h->nodes + next*h->nsz; } if(h->cap == h->len){ h->cap *= 2; *store = realloc(*store, sizeof(*h) + h->cap*h->nsz); h = *store; h->nodes = (uchar*)*store + sizeof(*h); memset(h->nodes + h->len*h->nsz, 0, h->nsz); } n->next = h->len; h->len++; assert(h->len <= h->cap); v = h->nodes + n->next*h->nsz; n = (Hnode*)v; replace: memmove(v + Tagsize, new, h->nsz - Tagsize); n->filled++; n->key = key; n->next = next; } void* hmapget(Hmap *h, void *key) { Hnode *n; uchar *v; v = h->nodes + (h->hash(key)%h->nbs)*h->nsz; for(;;){ n = (Hnode*)v; if(n->filled != 0 && h->cmp(n->key, key) == 0) return v + Tagsize; if(n->next == 0) break; v = h->nodes + n->next*h->nsz; } return nil; } void* hmapdel(Hmap *h, void *key) { uchar *v; Hnode *n; v = hmapget(h, key); if(v == nil) return nil; n = (Hnode*)(v - Tagsize); n->filled = 0; return v; } Hmap* hmaprehash(Hmap *old, int buckets) { int i; uchar *v; Hnode *n; Hmap *new; if(buckets == 0) buckets = old->len; new = allochmap(old->hash, old->cmp, buckets, old->nsz - Tagsize); for(i=0 ; i < old->len; i++){ v = old->nodes + i*old->nsz; n = (Hnode*)v; hmapset(&new, n->key, v + Tagsize); } free(old); return new; } int hmapvals(Hmap *h, void *buf, int maxelem) { Hnode *n; uchar *v; uchar *out; int i, valsz; out = buf; valsz = h->nsz - Tagsize; for(i=0; i <= maxelem && i < h->len; i++){ v = h->nodes + i*h->nsz; n = (Hnode*)v; if(n->filled == 0) continue; v += Tagsize; memmove(out, v, valsz); out += valsz; } return (out - (uchar*)buf)/valsz; }