diff options
| author | Ken Thompson <ken@golang.org> | 2008-06-22 21:02:06 -0700 |
|---|---|---|
| committer | Ken Thompson <ken@golang.org> | 2008-06-22 21:02:06 -0700 |
| commit | dee07c884e190c14caf1f82288455d37707da6bf (patch) | |
| tree | b72c7d3023068dab56530441babb8e05a18f3fc6 /src/runtime/runtime.c | |
| parent | 12c2864e4f02d9d5ab452eb70e296fa6c715443b (diff) | |
| download | go-dee07c884e190c14caf1f82288455d37707da6bf.tar.xz | |
maps
SVN=124030
Diffstat (limited to 'src/runtime/runtime.c')
| -rw-r--r-- | src/runtime/runtime.c | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index e8c1838592..2c1acadec6 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -764,3 +764,362 @@ check(void) // prints(1"check ok\n"); initsig(); } + +typedef struct Link Link; +typedef struct Hmap Hmap; +typedef struct Alg Alg; + +struct Alg +{ + uint64 (*hash)(uint32, void*); + uint32 (*equal)(uint32, void*, void*); + void (*print)(uint32, void*); + void (*copy)(uint32, void*, void*); +}; + +struct Link +{ + Link* link; + byte data[8]; +}; + +struct Hmap +{ + uint32 keysize; + uint32 valsize; + uint32 hint; + Alg* keyalg; + Alg* valalg; + uint32 valoffset; + uint32 ko; + uint32 vo; + uint32 po; + Link* link; +}; + +static uint64 +memhash(uint32 s, void *a) +{ + prints("memhash\n"); + return 0x12345; +} + +static uint32 +memequal(uint32 s, void *a, void *b) +{ + byte *ba, *bb; + uint32 i; + + ba = a; + bb = b; + for(i=0; i<s; i++) + if(ba[i] != bb[i]) + return 0; + return 1; +} + +static void +memprint(uint32 s, void *a) +{ + uint64 v; + + v = 0xbadb00b; + switch(s) { + case 1: + v = *(uint8*)a; + break; + case 2: + v = *(uint16*)a; + break; + case 4: + v = *(uint32*)a; + break; + case 8: + v = *(uint64*)a; + break; + } + sys_printint(v); +} + +static void +memcopy(uint32 s, void *a, void *b) +{ + byte *ba, *bb; + uint32 i; + + ba = a; + bb = b; + if(bb == nil) { + for(i=0; i<s; i++) + ba[i] = 0; + return; + } + for(i=0; i<s; i++) + ba[i] = bb[i]; +} + +static uint64 +stringhash(uint32 s, string *a) +{ + prints("stringhash\n"); + return 0x12345; +} + +static uint32 +stringequal(uint32 s, string *a, string *b) +{ + return cmpstring(*a, *b) == 0; +} + +static void +stringprint(uint32 s, string *a) +{ + sys_printstring(*a); +} + +static void +stringcopy(uint32 s, string *a, string *b) +{ + if(b == nil) { + *b = nil; + return; + } + *a = *b; +} + +static uint32 +rnd(uint32 n, uint32 m) +{ + uint32 r; + + r = n % m; + if(r) + n += m-r; + return n; +} + +static Alg +algarray[] = +{ + { &memhash, &memequal, &memprint, &memcopy }, + { &stringhash, &stringequal, &stringprint, &stringcopy }, +}; + +// 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 >= nelem(algarray) || + valalg >= nelem(algarray)) { + 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->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(1) { + 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); + +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; + 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"); + } +} |
