summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ktrans/hash.c
diff options
context:
space:
mode:
authorJacob Moody <moody@posixcafe.org>2022-07-17 14:52:11 +0000
committerJacob Moody <moody@posixcafe.org>2022-07-17 14:52:11 +0000
commitc147614656b9c1b4338099a69c35e42c1f4313a5 (patch)
tree7a74217a2dfc87b1896a7256d4a969227cd9f138 /sys/src/cmd/ktrans/hash.c
parentccbabf1c16caa4917c97b8d8f5cadfb8759610b3 (diff)
ktrans: 你好
This consolidates jisho and map lookups to use the same structure and removes the old jisho code.
Diffstat (limited to 'sys/src/cmd/ktrans/hash.c')
-rw-r--r--sys/src/cmd/ktrans/hash.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/sys/src/cmd/ktrans/hash.c b/sys/src/cmd/ktrans/hash.c
new file mode 100644
index 000000000..dcfa67cdd
--- /dev/null
+++ b/sys/src/cmd/ktrans/hash.c
@@ -0,0 +1,210 @@
+#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),
+};
+
+uvlong
+shash(char *s)
+{
+ uvlong hash;
+
+ hash = 7;
+ for(; *s; s++)
+ hash = hash*31 + *s;
+ return hash;
+}
+
+Hmap*
+hmapalloc(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->len = h->cap = nbuckets;
+
+ h->nodes = store;
+ h->nodes += sizeof(*h);
+ return store;
+}
+
+int
+hmapset(Hmap **store, char *key, void *new, void *old)
+{
+ Hnode *n;
+ uchar *v;
+ uchar *oldv;
+ Hmap *h;
+ int next;
+ vlong diff;
+
+ h = *store;
+ oldv = nil;
+ v = h->nodes + (shash(key)%h->nbs) * h->nsz;
+ for(;;){
+ n = (Hnode*)v;
+ next = n->next;
+
+ if(n->filled == 0)
+ goto replace;
+ if(strcmp(n->key, key) == 0){
+ oldv = v + Tagsize;
+ goto replace;
+ }
+ if(next == 0)
+ break;
+ v = h->nodes + next*h->nsz;
+ }
+
+ if(h->cap == h->len){
+ /* figure out way back from a relocation */
+ diff = v - h->nodes;
+
+ 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);
+
+ v = h->nodes + diff;
+ n = (Hnode*)v;
+ }
+ 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;
+ if(old != nil && oldv != nil){
+ memmove(old, oldv, h->nsz - Tagsize);
+ return 1;
+ }
+ return 0;
+}
+
+void*
+_hmapget(Hmap *h, char *key)
+{
+ Hnode *n;
+ uchar *v;
+
+ v = h->nodes + (shash(key)%h->nbs)*h->nsz;
+ for(;;){
+ n = (Hnode*)v;
+ if(n->filled != 0 && strcmp(n->key, key) == 0)
+ return v;
+ if(n->next == 0)
+ break;
+ v = h->nodes + n->next*h->nsz;
+ }
+ return nil;
+}
+
+int
+hmapget(Hmap *h, char *key, void *dst)
+{
+ uchar *v;
+
+ v = _hmapget(h, key);
+ if(v == nil)
+ return -1;
+ if(dst != nil)
+ memmove(dst, v + Tagsize, h->nsz - Tagsize);
+ return 0;
+}
+
+int
+hmapdel(Hmap *h, char *key, void *dst, int freekey)
+{
+ uchar *v;
+ Hnode *n;
+
+ v = _hmapget(h, key);
+ if(v == nil)
+ return -1;
+
+ n = (Hnode*)v;
+ n->filled = 0;
+ if(freekey)
+ free(n->key);
+ if(dst != nil)
+ memmove(dst, v + Tagsize, h->nsz - Tagsize);
+ return 0;
+}
+
+char*
+hmapkey(Hmap *h, char *key)
+{
+ uchar *v;
+ Hnode *n;
+
+ v = _hmapget(h, key);
+ if(v == nil)
+ return nil;
+
+ n = (Hnode*)v;
+ return n->key;
+}
+
+Hmap*
+hmaprehash(Hmap *old, int buckets)
+{
+ int i;
+ uchar *v;
+ Hnode *n;
+ Hmap *new;
+
+ if(buckets == 0)
+ buckets = old->len;
+
+ new = hmapalloc(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, nil);
+ }
+ free(old);
+ return new;
+}
+
+void
+hmapreset(Hmap *h, int freekeys)
+{
+ Hnode *n;
+ uchar *v;
+ int i;
+
+ for(i=0; i < h->len; i++){
+ v = h->nodes + i*h->nsz;
+ n = (Hnode*)v;
+ if(n->filled == 0)
+ continue;
+ if(freekeys)
+ free(n->key);
+ n->filled = 0;
+ }
+ h->len = 0;
+}