diff options
author | Jacob Moody <moody@posixcafe.org> | 2022-07-17 14:52:11 +0000 |
---|---|---|
committer | Jacob Moody <moody@posixcafe.org> | 2022-07-17 14:52:11 +0000 |
commit | c147614656b9c1b4338099a69c35e42c1f4313a5 (patch) | |
tree | 7a74217a2dfc87b1896a7256d4a969227cd9f138 /sys/src/cmd/ktrans/hash.c | |
parent | ccbabf1c16caa4917c97b8d8f5cadfb8759610b3 (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.c | 210 |
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; +} |