| // 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 >= 3 || | |
| 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, ...) | |
| { | |
| 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"); | |
| } | |
| } |