ref: 1edcce3e14962a3642ff07d95770128cee95c5b5
parent: d789157f513b2c3f324e00401f7e72e6010b6211
author: Jacob Moody <moody@posixcafe.org>
date: Sun May 22 00:03:05 EDT 2022
third pass
--- a/hash.c
+++ b/hash.c
@@ -2,19 +2,25 @@
#include <libc.h>
#include "hash.h"
+enum{
+ Tagsize = sizeof(Hnode),
+};
+
Hmap*
-allochmap(uvlong (*hash)(void*), int (*cmp)(void*,void*), int nbuckets, usize size)
+allochmap(uvlong (*hash)(void*), int (*cmp)(void*,void*), int nbuckets, int size)
{
void *store;
Hmap *h;
+ int nsz;
- store = mallocz(sizeof(*h) + (nbuckets * size), 1);
+ nsz = Tagsize + size;
+ store = mallocz(sizeof(*h) + (nbuckets * nsz), 1);
if(store == nil)
return nil;
h = store;
- h->size = nbuckets;
- h->nsize = size;
+ h->nbs = nbuckets;
+ h->nsz = nsz;
h->hash = hash;
h->cmp = cmp;
h->len = h->cap = nbuckets;
@@ -25,79 +31,80 @@
}
void
-hmapset(Hmap **store, Hnode *new)
+hmapset(Hmap **store, void *new)
{
Hnode *n;
+ uchar *v;
Hmap *h;
- int tmp;
+ int next;
- tmp = 0;
h = *store;
- n = (Hnode*)(h->nodes + (h->hash(new)%h->size)*h->nsize);
+ v = h->nodes + (h->hash(new)%h->nbs) * h->nsz;
for(;;){
+ n = (Hnode*)v;
+ next = n->next;
+
if(n->filled == 0)
goto replace;
- if(h->cmp(n, new) == 0){
- tmp = n->next;
+ if(h->cmp(v + Tagsize, new) == 0)
goto replace;
- }
- if(n->next == 0)
+ if(next == 0)
break;
- n = (Hnode*)(h->nodes + n->next*h->nsize);
+ v = h->nodes + next*h->nsz;
}
if(h->cap == h->len){
h->cap *= 2;
- *store = realloc(*store, sizeof(*h) + h->cap*h->nsize);
+ *store = realloc(*store, sizeof(*h) + h->cap*h->nsz);
h = *store;
h->nodes = (uchar*)*store + sizeof(*h);
- memset(h->nodes + h->len*h->nsize, 0, h->nsize);
+ memset(h->nodes + h->len*h->nsz, 0, h->nsz);
}
n->next = h->len;
h->len++;
assert(h->len <= h->cap);
- n = (Hnode*)(h->nodes + n->next*h->nsize);
+ v = h->nodes + n->next*h->nsz;
+ n = (Hnode*)v;
replace:
- memmove(n, new, h->nsize);
+ memmove(v + Tagsize, new, h->nsz - Tagsize);
n->filled++;
- n->next = tmp;
+ n->next = next;
}
void*
-hmapget(Hmap *h, Hnode *q)
+hmapget(Hmap *h, void *q)
{
Hnode *n;
+ uchar *v;
- n = (Hnode*)(h->nodes + (h->hash(q)%h->size)*h->nsize);
+ v = h->nodes + (h->hash(q)%h->nbs)*h->nsz;
for(;;){
- if(n->filled != 0 && h->cmp(n, q) == 0)
- return n;
+ n = (Hnode*)v;
+ if(n->filled != 0 && h->cmp(v + Tagsize, q) == 0)
+ return v + Tagsize;
if(n->next == 0)
break;
- n = (Hnode*)(h->nodes + n->next*h->nsize);
+ v = h->nodes + n->next*h->nsz;
}
return nil;
}
-void
-hmapmark(Hmap *h, Hnode *n)
-{
- n->filled = 0;
-}
void*
hmapdel(Hmap *h, Hnode *q)
{
+ uchar *v;
Hnode *n;
- n = hmapget(h, q);
+ v = hmapget(h, q);
if(n == nil)
return nil;
+ n = (Hnode*)(v - Tagsize);
n->filled = 0;
- return n;
+ return v;
}
Hmap*
@@ -104,16 +111,16 @@
hmaprehash(Hmap *old, int buckets)
{
int i;
- Hnode *n;
+ uchar *v;
Hmap *new;
if(buckets == 0)
buckets = old->len;
- new = allochmap(old->hash, old->cmp, buckets, old->nsize);
+ new = allochmap(old->hash, old->cmp, buckets, old->nsz);
for(i=0 ; i < old->len; i++){
- n = (Hnode*)(old->nodes + i*old->nsize);
- hmapset(&new, n);
+ v = old->nodes + i*old->nsz;
+ hmapset(&new, v + Tagsize);
}
free(old);
return new;
@@ -120,27 +127,23 @@
}
int
-hmapfmt(Fmt *f)
+hmapvals(Hmap *h, void *buf, int maxelem)
{
- Hmap *h;
- Hnode *n, *o;
- char fmt[16];
- int i, len;
+ Hnode *n;
+ uchar *v;
+ uchar *out;
+ int i, valsz;
- h = va_arg(f->args, Hmap*);
- fmt[0] = '%';
- memset(fmt+1, 0, UTFmax+1);
- runetochar(fmt+1, &h->nodeverb);
- for(i=len=0; i < h->size; i++){
- n = (Hnode*)(h->nodes + i*h->nsize);
- for(o=n;;){
- if(o->filled != 0)
- len += fmtprint(f, (char*)fmt, o);
- if(o->next == 0)
- break;
- o = (Hnode*)(h->nodes + o->next*h->nsize);
- }
+ 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 len;
+ return (out - (uchar*)buf)/valsz;
}
-
--- a/hash.h
+++ b/hash.h
@@ -1,17 +1,18 @@
typedef struct Hnode Hnode;
struct Hnode {
- int next;
int filled;
+ int next;
};
typedef struct Hmap Hmap;
struct Hmap {
+ int (*fmt)(Fmt*);
+ Rune fmtsep;
+
uvlong (*hash)(void*);
int (*cmp)(void*,void*);
- Rune nodeverb;
-
- int size;
- usize nsize;
+ int nbs;
+ int nsz;
int len;
int cap;
--- a/test.c
+++ b/test.c
@@ -1,20 +1,10 @@
#include "hash.c"
typedef struct Tnode {
- Hnode;
char *key;
char *value;
} Tnode;
-int
-tfmt(Fmt *f)
-{
- Tnode *t;
-
- t = va_arg(f->args, Tnode*);
- return fmtprint(f, "%s %s\n", t->key, t->value);
-}
-
uvlong
thash(void *n)
{
@@ -55,10 +45,7 @@
{.key "key6", .value "value6" },
};
- fmtinstall('T', tfmt);
- fmtinstall('H', hmapfmt);
h = allochmap(thash, tcmp, 2, sizeof(Tnode));
- h->nodeverb = 'T';
for(i=0; i < nelem(tab); i++)
hmapset(&h, &tab[i]);
@@ -72,8 +59,13 @@
assert(strcmp(r->value, tab[i].value) == 0);
}
- print("%H", h);
print("len, cap: %d %d\n", h->len, h->cap);
+ r = mallocz(sizeof tab, 1);
+ assert(hmapvals(h, r, nelem(tab)) == nelem(tab));
+ for(i=0; i < nelem(tab); i++){
+ print("%s %s\n", r[i].key, r[i].value);
+ }
+
h = hmaprehash(h, 0);
for(i=0; i < nelem(tab); i++){
t = tab[i];