ref: 9ae12fa984b9bc0eb0a33f9c0cf5b4ebd47ecd6d
parent: 1edcce3e14962a3642ff07d95770128cee95c5b5
author: Jacob Moody <moody@posixcafe.org>
date: Sun May 22 11:28:55 EDT 2022
fourth pass
--- a/hash.c
+++ b/hash.c
@@ -2,6 +2,13 @@
#include <libc.h>
#include "hash.h"
+typedef struct Hnode Hnode;
+struct Hnode {
+ int filled;
+ int next;
+ void *key;
+};
+
enum{
Tagsize = sizeof(Hnode),
};
@@ -31,7 +38,7 @@
}
void
-hmapset(Hmap **store, void *new)
+hmapset(Hmap **store, void *key, void *new)
{
Hnode *n;
uchar *v;
@@ -39,7 +46,7 @@
int next;
h = *store;
- v = h->nodes + (h->hash(new)%h->nbs) * h->nsz;
+ v = h->nodes + (h->hash(key)%h->nbs) * h->nsz;
for(;;){
n = (Hnode*)v;
@@ -47,7 +54,7 @@
if(n->filled == 0)
goto replace;
- if(h->cmp(v + Tagsize, new) == 0)
+ if(h->cmp(n->key, key) == 0)
goto replace;
if(next == 0)
break;
@@ -70,19 +77,20 @@
replace:
memmove(v + Tagsize, new, h->nsz - Tagsize);
n->filled++;
+ n->key = key;
n->next = next;
}
void*
-hmapget(Hmap *h, void *q)
+hmapget(Hmap *h, void *key)
{
Hnode *n;
uchar *v;
- v = h->nodes + (h->hash(q)%h->nbs)*h->nsz;
+ v = h->nodes + (h->hash(key)%h->nbs)*h->nsz;
for(;;){
n = (Hnode*)v;
- if(n->filled != 0 && h->cmp(v + Tagsize, q) == 0)
+ if(n->filled != 0 && h->cmp(n->key, key) == 0)
return v + Tagsize;
if(n->next == 0)
break;
@@ -93,13 +101,13 @@
void*
-hmapdel(Hmap *h, Hnode *q)
+hmapdel(Hmap *h, void *key)
{
uchar *v;
Hnode *n;
- v = hmapget(h, q);
- if(n == nil)
+ v = hmapget(h, key);
+ if(v == nil)
return nil;
n = (Hnode*)(v - Tagsize);
@@ -112,15 +120,17 @@
{
int i;
uchar *v;
+ Hnode *n;
Hmap *new;
if(buckets == 0)
buckets = old->len;
- new = allochmap(old->hash, old->cmp, buckets, old->nsz);
+ new = allochmap(old->hash, old->cmp, buckets, old->nsz - Tagsize);
for(i=0 ; i < old->len; i++){
v = old->nodes + i*old->nsz;
- hmapset(&new, v + Tagsize);
+ n = (Hnode*)v;
+ hmapset(&new, n->key, v + Tagsize);
}
free(old);
return new;
--- a/hash.h
+++ b/hash.h
@@ -1,14 +1,11 @@
-typedef struct Hnode Hnode;
-struct Hnode {
- int filled;
- int next;
+typedef union Hkey Hkey;
+union Hkey {
+ void *p;
+ int v;
};
typedef struct Hmap Hmap;
struct Hmap {
- int (*fmt)(Fmt*);
- Rune fmtsep;
-
uvlong (*hash)(void*);
int (*cmp)(void*,void*);
int nbs;
--- a/test.c
+++ b/test.c
@@ -1,42 +1,27 @@
#include "hash.c"
-typedef struct Tnode {
- char *key;
- char *value;
-} Tnode;
-
uvlong
-thash(void *n)
+thash(char *s)
{
- Tnode *t;
uvlong hash;
- char *s;
- t = n;
hash = 7;
- s = t->key;
for(; *s; s++)
hash = hash*31 + *s;
return hash;
}
-int
-tcmp(void *_a, void *_b)
-{
- Tnode *a, *b;
-
- a = _a;
- b = _b;
- return strcmp(a->key, b->key);
-}
-
void
-main(int argc, char **argv)
+testbasic(void)
{
int i;
Hmap *h;
- Tnode t, *r;
- Tnode tab[] = {
+ char **v;
+
+ struct {
+ char *key;
+ char *value;
+ } tab[] = {
{.key "key1", .value "value1" },
{.key "key2", .value "value2" },
{.key "key3", .value "value3" },
@@ -45,35 +30,76 @@
{.key "key6", .value "value6" },
};
- h = allochmap(thash, tcmp, 2, sizeof(Tnode));
+ h = allochmap(thash, strcmp, 1, sizeof(char*));
for(i=0; i < nelem(tab); i++)
- hmapset(&h, &tab[i]);
+ hmapset(&h, tab[i].key, &tab[i].value);
for(i=0; i < nelem(tab); i++){
- t = tab[i];
- t.value = "";
- r = hmapget(h, &t);
- assert(r);
- assert(strcmp(r->key, tab[i].key) == 0);
- assert(strcmp(r->value, tab[i].value) == 0);
+ v = hmapget(h, tab[i].key);
+ assert(v);
+ assert(strcmp(*v, tab[i].value) == 0);
}
print("len, cap: %d %d\n", h->len, h->cap);
- r = mallocz(sizeof tab, 1);
- assert(hmapvals(h, r, nelem(tab)) == nelem(tab));
+
+ v = mallocz(nelem(tab)*sizeof(char*), 1);
+ assert(hmapvals(h, v, nelem(tab)) == nelem(tab));
for(i=0; i < nelem(tab); i++){
- print("%s %s\n", r[i].key, r[i].value);
+ print("%s\n", v[i]);
}
h = hmaprehash(h, 0);
for(i=0; i < nelem(tab); i++){
- t = tab[i];
- t.value = "";
- r = hmapget(h, &t);
- assert(r);
- assert(strcmp(r->key, tab[i].key) == 0);
- assert(strcmp(r->value, tab[i].value) == 0);
+ v = hmapget(h, tab[i].key);
+ assert(v);
+ assert(strcmp(*v, tab[i].value) == 0);
}
print("len, cap: %d %d\n", h->len, h->cap);
+ free(h);
+}
+
+uvlong
+runehash(void *p)
+{
+ Hkey k;
+ k.p = p;
+ return k.v * 0xdeece66d + 0xb;
+}
+
+int
+runecmp(void *_a, void *_b)
+{
+ Hkey a, b;
+ a.p = _a, b.p = _b;
+ return !(a.v == b.v);
+}
+
+void
+testrunekey(void)
+{
+ Hkey k;
+ Hmap *h;
+ char *v;
+ char **p;
+
+ h = allochmap(runehash, runecmp, 16, sizeof(char*));
+
+ k.v = 'p';
+ v = "hello";
+ hmapset(&h, k.p, &v);
+ hmapset(&h, k.p, &v);
+
+ p = hmapget(h, k.p);
+ assert(p && *p);
+ assert(*p == v);
+}
+
+void
+main(int argc, char **argv)
+{
+ USED(argc);
+ USED(argv);
+ testbasic();
+ testrunekey();
}