| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| #include "runtime.h" |
| |
| static int32 debug = 0; |
| |
| typedef struct Link Link; |
| typedef struct Hmap Hmap; |
| |
| struct Link |
| { |
| Link* link; |
| byte data[8]; |
| }; |
| |
| struct Hmap |
| { |
| uint32 len; // must be first |
| uint32 keysize; |
| uint32 valsize; |
| uint32 hint; |
| uint32 valoffset; |
| uint32 ko; |
| uint32 vo; |
| uint32 po; |
| Alg* keyalg; |
| Alg* valalg; |
| Link* link; |
| }; |
| |
| // newmap(keysize uint32, valsize uint32, |
| // keyalg uint32, valalg uint32, |
| // hint uint32) (hmap *map[any]any); |
| void |
| sys·newmap(uint32 keysize, uint32 valsize, |
| uint32 keyalg, uint32 valalg, uint32 hint, |
| Hmap* ret) |
| { |
| Hmap *m; |
| |
| if(keyalg >= 2 || |
| valalg >= 3) { |
| prints("0<="); |
| sys·printint(keyalg); |
| prints("<"); |
| sys·printint(nelem(algarray)); |
| prints("\n0<="); |
| sys·printint(valalg); |
| prints("<"); |
| sys·printint(nelem(algarray)); |
| prints("\n"); |
| |
| throw("sys·newmap: key/val algorithm out of range"); |
| } |
| |
| m = mal(sizeof(*m)); |
| |
| m->len = 0; |
| m->keysize = keysize; |
| m->valsize = valsize; |
| m->keyalg = &algarray[keyalg]; |
| m->valalg = &algarray[valalg]; |
| m->hint = hint; |
| |
| // these calculations are compiler dependent |
| m->valoffset = rnd(keysize, valsize); |
| m->ko = rnd(sizeof(m), keysize); |
| m->vo = rnd(m->ko+keysize, valsize); |
| m->po = rnd(m->vo+valsize, 1); |
| |
| ret = m; |
| FLUSH(&ret); |
| |
| if(debug) { |
| prints("newmap: map="); |
| sys·printpointer(m); |
| prints("; keysize="); |
| sys·printint(keysize); |
| prints("; valsize="); |
| sys·printint(valsize); |
| prints("; keyalg="); |
| sys·printint(keyalg); |
| prints("; valalg="); |
| sys·printint(valalg); |
| prints("; valoffset="); |
| sys·printint(m->valoffset); |
| prints("; ko="); |
| sys·printint(m->ko); |
| prints("; vo="); |
| sys·printint(m->vo); |
| prints("; po="); |
| sys·printint(m->po); |
| prints("\n"); |
| } |
| } |
| |
| // mapaccess1(hmap *map[any]any, key any) (val any); |
| void |
| sys·mapaccess1(Hmap *m, ...) |
| { |
| Link *l; |
| byte *ak, *av; |
| |
| ak = (byte*)&m + m->ko; |
| av = (byte*)&m + m->vo; |
| |
| for(l=m->link; l!=nil; l=l->link) { |
| if(m->keyalg->equal(m->keysize, ak, l->data)) { |
| m->valalg->copy(m->valsize, av, l->data+m->valoffset); |
| goto out; |
| } |
| } |
| |
| m->valalg->copy(m->valsize, av, 0); |
| |
| out: |
| if(debug) { |
| prints("sys·mapaccess1: map="); |
| sys·printpointer(m); |
| prints("; key="); |
| m->keyalg->print(m->keysize, ak); |
| prints("; val="); |
| m->valalg->print(m->valsize, av); |
| prints("\n"); |
| } |
| } |
| |
| // mapaccess2(hmap *map[any]any, key any) (val any, pres bool); |
| void |
| sys·mapaccess2(Hmap *m, ...) |
| { |
| Link *l; |
| byte *ak, *av, *ap; |
| |
| ak = (byte*)&m + m->ko; |
| av = (byte*)&m + m->vo; |
| ap = (byte*)&m + m->po; |
| |
| for(l=m->link; l!=nil; l=l->link) { |
| if(m->keyalg->equal(m->keysize, ak, l->data)) { |
| *ap = true; |
| m->valalg->copy(m->valsize, av, l->data+m->valoffset); |
| goto out; |
| } |
| } |
| |
| *ap = false; |
| m->valalg->copy(m->valsize, av, nil); |
| |
| out: |
| if(debug) { |
| prints("sys·mapaccess2: map="); |
| sys·printpointer(m); |
| prints("; key="); |
| m->keyalg->print(m->keysize, ak); |
| prints("; val="); |
| m->valalg->print(m->valsize, av); |
| prints("; pres="); |
| sys·printbool(*ap); |
| prints("\n"); |
| } |
| } |
| |
| static void |
| sys·mapassign(Hmap *m, byte *ak, byte *av) |
| { |
| Link *l; |
| |
| // mapassign(hmap *map[any]any, key any, val any); |
| |
| for(l=m->link; l!=nil; l=l->link) { |
| if(m->keyalg->equal(m->keysize, ak, l->data)) |
| goto out; |
| } |
| |
| l = mal((sizeof(*l)-8) + m->keysize + m->valsize); |
| l->link = m->link; |
| m->link = l; |
| m->keyalg->copy(m->keysize, l->data, ak); |
| m->len++; |
| |
| out: |
| m->valalg->copy(m->valsize, l->data+m->valoffset, av); |
| |
| if(debug) { |
| prints("mapassign: map="); |
| sys·printpointer(m); |
| prints("; key="); |
| m->keyalg->print(m->keysize, ak); |
| prints("; val="); |
| m->valalg->print(m->valsize, av); |
| prints("\n"); |
| } |
| } |
| |
| // mapassign1(hmap *map[any]any, key any, val any); |
| void |
| sys·mapassign1(Hmap *m, ...) |
| { |
| Link **ll; |
| byte *ak, *av; |
| |
| ak = (byte*)&m + m->ko; |
| av = (byte*)&m + m->vo; |
| |
| sys·mapassign(m, ak, av); |
| } |
| |
| // mapassign2(hmap *map[any]any, key any, val any, pres bool); |
| void |
| sys·mapassign2(Hmap *m, ...) |
| { |
| Link **ll; |
| byte *ak, *av, *ap; |
| |
| ak = (byte*)&m + m->ko; |
| av = (byte*)&m + m->vo; |
| ap = (byte*)&m + m->po; |
| |
| if(*ap == true) { |
| // assign |
| sys·mapassign(m, ak, av); |
| return; |
| } |
| |
| // delete |
| for(ll=&m->link; (*ll)!=nil; ll=&(*ll)->link) { |
| if(m->keyalg->equal(m->keysize, ak, (*ll)->data)) { |
| m->valalg->copy(m->valsize, (*ll)->data+m->valoffset, nil); |
| (*ll) = (*ll)->link; |
| m->len--; |
| if(debug) { |
| prints("mapdelete (found): map="); |
| sys·printpointer(m); |
| prints("; key="); |
| m->keyalg->print(m->keysize, ak); |
| prints("\n"); |
| } |
| return; |
| } |
| } |
| |
| if(debug) { |
| prints("mapdelete (not found): map="); |
| sys·printpointer(m); |
| prints("; key="); |
| m->keyalg->print(m->keysize, ak); |
| prints(" *** not found\n"); |
| } |
| } |