mirror of
https://github.com/golang/go
synced 2024-11-20 04:54:44 -07:00
212 lines
3.2 KiB
C
212 lines
3.2 KiB
C
|
// 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"
|
||
|
|
||
|
typedef struct Sigt Sigt;
|
||
|
typedef struct Sigi Sigi;
|
||
|
typedef struct Map Map;
|
||
|
|
||
|
struct Sigt
|
||
|
{
|
||
|
byte* name;
|
||
|
uint32 hash;
|
||
|
void (*fun)(void);
|
||
|
};
|
||
|
|
||
|
struct Sigi
|
||
|
{
|
||
|
byte* name;
|
||
|
uint32 hash;
|
||
|
uint32 offset;
|
||
|
};
|
||
|
|
||
|
struct Map
|
||
|
{
|
||
|
Sigi* sigi;
|
||
|
Sigt* sigt;
|
||
|
Map* link;
|
||
|
int32 bad;
|
||
|
int32 unused;
|
||
|
void (*fun[])(void);
|
||
|
};
|
||
|
|
||
|
static Map* hash[1009];
|
||
|
static int32 debug = 0;
|
||
|
|
||
|
static Map*
|
||
|
hashmap(Sigi *si, Sigt *ss)
|
||
|
{
|
||
|
int32 ns, ni;
|
||
|
uint32 ihash, h;
|
||
|
byte *sname, *iname;
|
||
|
Map *m;
|
||
|
|
||
|
h = ((uint32)(uint64)si + (uint32)(uint64)ss) % nelem(hash);
|
||
|
for(m=hash[h]; m!=nil; m=m->link) {
|
||
|
if(m->sigi == si && m->sigt == ss) {
|
||
|
if(m->bad) {
|
||
|
throw("bad hashmap");
|
||
|
m = nil;
|
||
|
}
|
||
|
// prints("old hashmap\n");
|
||
|
return m;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ni = si[0].offset; // first word has size
|
||
|
m = mal(sizeof(*m) + ni*sizeof(m->fun[0]));
|
||
|
m->sigi = si;
|
||
|
m->sigt = ss;
|
||
|
|
||
|
ni = 1; // skip first word
|
||
|
ns = 0;
|
||
|
|
||
|
loop1:
|
||
|
// pick up next name from
|
||
|
// interface signature
|
||
|
iname = si[ni].name;
|
||
|
if(iname == nil) {
|
||
|
m->link = hash[h];
|
||
|
hash[h] = m;
|
||
|
// prints("new hashmap\n");
|
||
|
return m;
|
||
|
}
|
||
|
ihash = si[ni].hash;
|
||
|
|
||
|
loop2:
|
||
|
// pick up and comapre next name
|
||
|
// from structure signature
|
||
|
sname = ss[ns].name;
|
||
|
if(sname == nil) {
|
||
|
prints((int8*)iname);
|
||
|
prints(": ");
|
||
|
throw("hashmap: failed to find method");
|
||
|
m->bad = 1;
|
||
|
m->link = hash[h];
|
||
|
hash[h] = m;
|
||
|
return nil;
|
||
|
}
|
||
|
|
||
|
if(ihash != ss[ns].hash ||
|
||
|
strcmp(sname, iname) != 0) {
|
||
|
ns++;
|
||
|
goto loop2;
|
||
|
}
|
||
|
|
||
|
m->fun[si[ni].offset] = ss[ns].fun;
|
||
|
ni++;
|
||
|
goto loop1;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
printsigi(Sigi *si)
|
||
|
{
|
||
|
sys·printpointer(si);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
printsigt(Sigt *st)
|
||
|
{
|
||
|
sys·printpointer(st);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
printiface(Map *im, void *it)
|
||
|
{
|
||
|
prints("(");
|
||
|
sys·printpointer(im);
|
||
|
prints(",");
|
||
|
sys·printpointer(it);
|
||
|
prints(")");
|
||
|
}
|
||
|
|
||
|
// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret interface{});
|
||
|
void
|
||
|
sys·ifaceT2I(Sigi *si, Sigt *st, void *elem, Map *retim, void *retit)
|
||
|
{
|
||
|
|
||
|
if(debug) {
|
||
|
prints("T2I sigi=");
|
||
|
printsigi(si);
|
||
|
prints(" sigt=");
|
||
|
printsigt(st);
|
||
|
prints(" elem=");
|
||
|
sys·printpointer(elem);
|
||
|
prints("\n");
|
||
|
}
|
||
|
|
||
|
retim = hashmap(si, st);
|
||
|
retit = elem;
|
||
|
|
||
|
if(debug) {
|
||
|
prints("T2I ret=");
|
||
|
printiface(retim, retit);
|
||
|
prints("\n");
|
||
|
}
|
||
|
|
||
|
FLUSH(&retim);
|
||
|
}
|
||
|
|
||
|
// ifaceI2T(sigt *byte, iface interface{}) (ret any);
|
||
|
void
|
||
|
sys·ifaceI2T(Sigt *st, Map *im, void *it, void *ret)
|
||
|
{
|
||
|
|
||
|
if(debug) {
|
||
|
prints("I2T sigt=");
|
||
|
printsigt(st);
|
||
|
prints(" iface=");
|
||
|
printiface(im, it);
|
||
|
prints("\n");
|
||
|
}
|
||
|
|
||
|
if(im == nil)
|
||
|
throw("ifaceI2T: nil map");
|
||
|
|
||
|
if(im->sigt != st)
|
||
|
throw("ifaceI2T: wrong type");
|
||
|
|
||
|
ret = it;
|
||
|
if(debug) {
|
||
|
prints("I2T ret=");
|
||
|
sys·printpointer(ret);
|
||
|
prints("\n");
|
||
|
}
|
||
|
|
||
|
FLUSH(&ret);
|
||
|
}
|
||
|
|
||
|
// ifaceI2I(sigi *byte, iface interface{}) (ret interface{});
|
||
|
void
|
||
|
sys·ifaceI2I(Sigi *si, Map *im, void *it, Map *retim, void *retit)
|
||
|
{
|
||
|
|
||
|
if(debug) {
|
||
|
prints("I2I sigi=");
|
||
|
sys·printpointer(si);
|
||
|
prints(" iface=");
|
||
|
printiface(im, it);
|
||
|
prints("\n");
|
||
|
}
|
||
|
|
||
|
if(im == nil) {
|
||
|
throw("ifaceI2I: nil map");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
retit = it;
|
||
|
retim = im;
|
||
|
if(im->sigi != si)
|
||
|
retim = hashmap(si, im->sigt);
|
||
|
|
||
|
if(debug) {
|
||
|
prints("I2I ret=");
|
||
|
printiface(retim, retit);
|
||
|
prints("\n");
|
||
|
}
|
||
|
|
||
|
FLUSH(&retim);
|
||
|
}
|