コード例 #1
0
// decodeInterface receives the name of a concrete type followed by its value.
// If the name is empty, the value is nil and no value is sent.
func (dec *Decoder) decodeInterface(ityp *reflect.InterfaceType, state *decodeState, p uintptr, indir int) {
	// Create an interface reflect.Value.  We need one even for the nil case.
	ivalue := reflect.MakeZero(ityp).(*reflect.InterfaceValue)
	// Read the name of the concrete type.
	b := make([]byte, state.decodeUint())
	state.b.Read(b)
	name := string(b)
	if name == "" {
		// Copy the representation of the nil interface value to the target.
		// This is horribly unsafe and special.
		*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.Get()
		return
	}
	// The concrete type must be registered.
	typ, ok := nameToConcreteType[name]
	if !ok {
		errorf("gob: name not registered for interface: %q", name)
	}
	// Read the concrete value.
	value := reflect.MakeZero(typ)
	dec.decodeValueFromBuffer(value, false, true)
	if dec.err != nil {
		error(dec.err)
	}
	// Allocate the destination interface value.
	if indir > 0 {
		p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
	}
	// Assign the concrete value to the interface.
	// Tread carefully; it might not satisfy the interface.
	setInterfaceValue(ivalue, value)
	// Copy the representation of the interface value to the target.
	// This is horribly unsafe and special.
	*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.Get()
}
コード例 #2
0
ファイル: marshaler.go プロジェクト: niltonkummer/go-router
func (jm *jsonDemarshaler) Demarshal() (id Id, ctrlMsg interface{}, appMsg reflect.Value, err os.Error) {
	seedId := jm.proxy.router.seedId
	id, _ = seedId.Clone()
	if err = jm.Decode(id); err != nil {
		return
	}
	if id.Scope() == NumScope && id.Member() == NumMembership {
		return
	}
	switch id.SysIdIndex() {
	case ConnId, DisconnId, ErrorId:
		idc, _ := seedId.Clone()
		ctrlMsg = &ConnInfoMsg{Id: idc}
		err = jm.demarshalCtrlMsg(ctrlMsg)
	case ReadyId:
		idc, _ := seedId.Clone()
		ctrlMsg = &ConnReadyMsg{[]*ChanReadyInfo{&ChanReadyInfo{Id: idc}}}
		err = jm.demarshalCtrlMsg(ctrlMsg)
	case PubId, UnPubId, SubId, UnSubId:
		idc, _ := seedId.Clone()
		ctrlMsg = &IdChanInfoMsg{[]*IdChanInfo{&IdChanInfo{idc, nil, nil}}}
		err = jm.demarshalCtrlMsg(ctrlMsg)
	default: //appMsg
		chanType := jm.proxy.getExportRecvChanType(id)
		if chanType == nil {
			err = os.ErrorString(fmt.Sprintf("failed to find chanType for id %v", id))
			return
		}
		et := chanType.Elem()
		appMsg = reflect.MakeZero(et)
		var ptrT *reflect.PtrValue
		switch et := et.(type) {
		case *reflect.BoolType:
			ptrT = jm.ptrBool
			ptrT.PointTo(appMsg)
		case *reflect.IntType:
			ptrT = jm.ptrInt
			ptrT.PointTo(appMsg)
		case *reflect.FloatType:
			ptrT = jm.ptrFloat
			ptrT.PointTo(appMsg)
		case *reflect.StringType:
			ptrT = jm.ptrString
			ptrT.PointTo(appMsg)
		case *reflect.PtrType:
			sto := reflect.MakeZero(et.Elem())
			ptrT = appMsg.(*reflect.PtrValue)
			ptrT.PointTo(sto)
		default:
			err = os.ErrorString(fmt.Sprintf("invalid chanType for id %v", id))
			return
		}
		err = jm.Decode(ptrT.Interface())
	}
	return
}
コード例 #3
0
func TestUnmarshal(t *testing.T) {
	for i, test := range unmarshalTestData {
		pv := reflect.MakeZero(reflect.NewValue(test.out).Type())
		zv := reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem())
		pv.(*reflect.PtrValue).PointTo(zv)
		val := pv.Interface()
		err := Unmarshal(val, test.in)
		if err != nil {
			t.Errorf("Unmarshal failed at index %d %v", i, err)
		}
		if !reflect.DeepEqual(val, test.out) {
			t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out)
		}
	}
}
コード例 #4
0
ファイル: rewrite.go プロジェクト: ivanwyc/google-go
// subst returns a copy of pattern with values from m substituted in place
// of wildcards and pos used as the position of tokens from the pattern.
// if m == nil, subst returns a copy of pattern and doesn't change the line
// number information.
func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value {
	if pattern == nil {
		return nil
	}

	// Wildcard gets replaced with map value.
	if m != nil && pattern.Type() == identType {
		name := pattern.Interface().(*ast.Ident).Name()
		if isWildcard(name) {
			if old, ok := m[name]; ok {
				return subst(nil, old, nil)
			}
		}
	}

	if pos != nil && pattern.Type() == positionType {
		return pos
	}

	// Otherwise copy.
	switch p := pattern.(type) {
	case *reflect.SliceValue:
		v := reflect.MakeSlice(p.Type().(*reflect.SliceType), p.Len(), p.Len())
		for i := 0; i < p.Len(); i++ {
			v.Elem(i).SetValue(subst(m, p.Elem(i), pos))
		}
		return v

	case *reflect.StructValue:
		v := reflect.MakeZero(p.Type()).(*reflect.StructValue)
		for i := 0; i < p.NumField(); i++ {
			v.Field(i).SetValue(subst(m, p.Field(i), pos))
		}
		return v

	case *reflect.PtrValue:
		v := reflect.MakeZero(p.Type()).(*reflect.PtrValue)
		v.PointTo(subst(m, p.Elem(), pos))
		return v

	case *reflect.InterfaceValue:
		v := reflect.MakeZero(p.Type()).(*reflect.InterfaceValue)
		v.SetValue(subst(m, p.Elem(), pos))
		return v
	}

	return pattern
}
コード例 #5
0
ファイル: redis.go プロジェクト: mikelikespie/redis.go
func writeToContainer(data [][]byte, val reflect.Value) os.Error {
	switch v := val.(type) {
	case *reflect.PtrValue:
		return writeToContainer(data, reflect.Indirect(v))
	case *reflect.InterfaceValue:
		return writeToContainer(data, v.Elem())
	case *reflect.MapValue:
		if _, ok := v.Type().(*reflect.MapType).Key().(*reflect.StringType); !ok {
			return os.NewError("Invalid map type")
		}
		elemtype := v.Type().(*reflect.MapType).Elem()
		for i := 0; i < len(data)/2; i++ {
			mk := reflect.NewValue(string(data[i*2]))
			mv := reflect.MakeZero(elemtype)
			writeTo(data[i*2+1], mv)
			v.SetElem(mk, mv)
		}
	case *reflect.StructValue:
		for i := 0; i < len(data)/2; i++ {
			name := string(data[i*2])
			field := v.FieldByName(name)
			if field == nil {
				continue
			}
			writeTo(data[i*2+1], field)
		}
	default:
		return os.NewError("Invalid container type")
	}
	return nil
}
コード例 #6
0
ファイル: decode_test.go プロジェクト: rapgamer/golang-china
func TestUnmarshal(t *testing.T) {
	var scan scanner
	for i, tt := range unmarshalTests {
		in := []byte(tt.in)
		if err := checkValid(in, &scan); err != nil {
			t.Errorf("#%d: checkValid: %v", i, err)
			continue
		}
		// v = new(right-type)
		v := reflect.NewValue(tt.ptr).(*reflect.PtrValue)
		v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
		if err := Unmarshal([]byte(in), v.Interface()); err != nil {
			t.Errorf("#%d: %v", i, err)
			continue
		}
		if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
			t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
			data, _ := Marshal(v.Elem().Interface())
			println(string(data))
			data, _ = Marshal(tt.out)
			println(string(data))
			return
			continue
		}
	}
}
コード例 #7
0
ファイル: struct.go プロジェクト: ivanwyc/google-go
func (b *structBuilder) Key(k string) Builder {
	if b == nil {
		return nobuilder
	}
	switch v := reflect.Indirect(b.val).(type) {
	case *reflect.StructValue:
		t := v.Type().(*reflect.StructType)
		// Case-insensitive field lookup.
		k = strings.ToLower(k)
		for i := 0; i < t.NumField(); i++ {
			if strings.ToLower(t.Field(i).Name) == k {
				return &structBuilder{val: v.Field(i)}
			}
		}
	case *reflect.MapValue:
		t := v.Type().(*reflect.MapType)
		if t.Key() != reflect.Typeof(k) {
			break
		}
		key := reflect.NewValue(k)
		elem := v.Elem(key)
		if elem == nil {
			v.SetElem(key, reflect.MakeZero(t.Elem()))
			elem = v.Elem(key)
		}
		return &structBuilder{val: elem, map_: v, key: key}
	}
	return nobuilder
}
コード例 #8
0
ファイル: import.go プロジェクト: lougxing/golang-china
// ImportNValues imports a channel of the given type and specified direction
// and then receives or transmits up to n values on that channel.  A value of
// n==0 implies an unbounded number of values.  The channel to be bound to
// the remote site's channel is provided in the call and may be of arbitrary
// channel type.
// Despite the literal signature, the effective signature is
//	ImportNValues(name string, chT chan T, dir Dir, pT T)
// where T must be a struct, pointer to struct, etc.  pT may be more indirect
// than the value type of the channel (e.g.  chan T, pT *T) but it must be a
// pointer.
// Example usage:
//	imp, err := NewImporter("tcp", "netchanserver.mydomain.com:1234")
//	if err != nil { log.Exit(err) }
//	ch := make(chan myType)
//	err := imp.ImportNValues("name", ch, Recv, new(myType), 1)
//	if err != nil { log.Exit(err) }
//	fmt.Printf("%+v\n", <-ch)
// (TODO: Can we eliminate the need for pT?)
func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, pT interface{}, n int) os.Error {
	ch, err := checkChan(chT, dir)
	if err != nil {
		return err
	}
	// Make sure pT is a pointer (to a pointer...) to a struct.
	rt := reflect.Typeof(pT)
	if _, ok := rt.(*reflect.PtrType); !ok {
		return os.ErrorString("not a pointer:" + rt.String())
	}
	if _, ok := reflect.Indirect(reflect.NewValue(pT)).(*reflect.StructValue); !ok {
		return os.ErrorString("not a pointer to a struct:" + rt.String())
	}
	imp.chanLock.Lock()
	defer imp.chanLock.Unlock()
	_, present := imp.chans[name]
	if present {
		return os.ErrorString("channel name already being imported:" + name)
	}
	ptr := reflect.MakeZero(reflect.Typeof(pT)).(*reflect.PtrValue)
	imp.chans[name] = &importChan{ch, dir, ptr, n}
	// Tell the other side about this channel.
	req := new(request)
	req.name = name
	req.dir = dir
	req.count = n
	if err := imp.encode(req, nil); err != nil {
		log.Stderr("importer request encode:", err)
		return err
	}
	return nil
}
コード例 #9
0
ファイル: marshaler.go プロジェクト: niltonkummer/go-router
func (gm *gobDemarshaler) Demarshal() (id Id, ctrlMsg interface{}, appMsg reflect.Value, err os.Error) {
	seedId := gm.proxy.router.seedId
	id, _ = seedId.Clone()
	if err = gm.Decode(id); err != nil {
		return
	}
	if id.Scope() == NumScope && id.Member() == NumMembership {
		return
	}
	switch id.SysIdIndex() {
	case ConnId, DisconnId, ErrorId:
		idc, _ := seedId.Clone()
		ctrlMsg = &ConnInfoMsg{Id: idc}
		err = gm.demarshalCtrlMsg(ctrlMsg)
	case ReadyId:
		idc, _ := seedId.Clone()
		ctrlMsg = &ConnReadyMsg{[]*ChanReadyInfo{&ChanReadyInfo{Id: idc}}}
		err = gm.demarshalCtrlMsg(ctrlMsg)
	case PubId, UnPubId, SubId, UnSubId:
		idc, _ := seedId.Clone()
		ctrlMsg = &IdChanInfoMsg{[]*IdChanInfo{&IdChanInfo{idc, nil, nil}}}
		err = gm.demarshalCtrlMsg(ctrlMsg)
	default: //appMsg
		chanType := gm.proxy.getExportRecvChanType(id)
		if chanType == nil {
			err = os.ErrorString(fmt.Sprintf("failed to find chanType for id %v", id))
			return
		}
		appMsg = reflect.MakeZero(chanType.Elem())
		err = gm.DecodeValue(appMsg)
	}
	return
}
コード例 #10
0
ファイル: gorm.go プロジェクト: anandpowar/GoRM
func (c *Conn) GetAll(rowsSlicePtr interface{}, condition string, args ...interface{}) os.Error {
	sliceValue, ok := reflect.Indirect(reflect.NewValue(rowsSlicePtr)).(*reflect.SliceValue)
	if !ok {
		return os.NewError("needs a pointer to a slice")
	}

	sliceElementType := sliceValue.Type().(*reflect.SliceType).Elem()

	condition = strings.TrimSpace(condition)
	if len(condition) > 0 {
		condition = fmt.Sprintf("where %v", condition)
	}

	resultsSlice, err := c.getResultsForQuery(getTableName(rowsSlicePtr), condition, args)
	if err != nil {
		return err
	}

	for _, results := range resultsSlice {
		newValue := reflect.MakeZero(sliceElementType)
		scanMapIntoStruct(newValue.Addr().Interface(), results)
		sliceValue.SetValue(reflect.Append(sliceValue, newValue))
	}

	return nil
}
コード例 #11
0
ファイル: import.go プロジェクト: lougxing/golang-china
// Handle the data from a single imported data stream, which will
// have the form
//	(response, data)*
// The response identifies by name which channel is receiving data.
// TODO: allow an importer to send.
func (imp *Importer) run() {
	// Loop on responses; requests are sent by ImportNValues()
	resp := new(response)
	for {
		if err := imp.decode(resp); err != nil {
			log.Stderr("importer response decode:", err)
			break
		}
		if resp.error != "" {
			log.Stderr("importer response error:", resp.error)
			// TODO: tear down connection
			break
		}
		imp.chanLock.Lock()
		ich, ok := imp.chans[resp.name]
		imp.chanLock.Unlock()
		if !ok {
			log.Stderr("unknown name in request:", resp.name)
			break
		}
		if ich.dir != Recv {
			log.Stderr("TODO: import send unimplemented")
			break
		}
		// Create a new value for each received item.
		val := reflect.MakeZero(ich.ptr.Type().(*reflect.PtrType).Elem())
		ich.ptr.PointTo(val)
		if err := imp.decode(ich.ptr.Interface()); err != nil {
			log.Stderr("importer value decode:", err)
			return
		}
		ich.ch.Send(val)
	}
}
コード例 #12
0
ファイル: bson_test.go プロジェクト: hokapoka/go-mongo
func TestDecodeStruct(t *testing.T) {
	for i, bt := range bsonTests {
		if bt.psv == nil {
			continue
		}
		pt := reflect.NewValue(bt.psv).Type().(*reflect.PtrType)
		psv := reflect.MakeZero(pt).(*reflect.PtrValue)
		psv.PointTo(reflect.MakeZero(pt.Elem()))
		err := Decode(bt.data, psv.Interface())
		sv := psv.Elem().Interface()
		if err != nil {
			t.Errorf("%d: error decoding %q: %s", i, bt.data, err)
		} else if !reflect.DeepEqual(sv, bt.sv) {
			t.Errorf("%d: data=%q,\n\texpected %q\n\tactual  %q", i, bt.data, bt.sv, sv)
		}
	}
}
コード例 #13
0
func (dec *Decoder) decodeMap(mtyp *reflect.MapType, state *decodeState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl os.ErrorString) {
	if indir > 0 {
		p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
	}
	up := unsafe.Pointer(p)
	if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime
		// Allocate map.
		*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Get())
	}
	// Maps cannot be accessed by moving addresses around the way
	// that slices etc. can.  We must recover a full reflection value for
	// the iteration.
	v := reflect.NewValue(unsafe.Unreflect(mtyp, unsafe.Pointer((p)))).(*reflect.MapValue)
	n := int(state.decodeUint())
	for i := 0; i < n; i++ {
		key := decodeIntoValue(state, keyOp, keyIndir, reflect.MakeZero(mtyp.Key()), ovfl)
		elem := decodeIntoValue(state, elemOp, elemIndir, reflect.MakeZero(mtyp.Elem()), ovfl)
		v.SetElem(key, elem)
	}
}
コード例 #14
0
ファイル: export.go プロジェクト: GNA-SERVICES-INC/MoNGate
// Receive and deliver locally one item from a client asking for a Send
// The header is passed by value to avoid issues of overwriting.
func (client *expClient) serveSend(hdr header) {
	ech := client.getChan(&hdr, Recv)
	if ech == nil {
		return
	}
	// Create a new value for each received item.
	val := reflect.MakeZero(ech.ch.Type().(*reflect.ChanType).Elem())
	if err := client.decode(val); err != nil {
		expLog("value decode:", err)
		return
	}
	ech.ch.Send(val)
}
コード例 #15
0
ファイル: bson-struct.go プロジェクト: pbarrera/gomongo
func (self *structBuilder) Key(k string) Builder {
	if self == nil {
		return nobuilder
	}
	switch v := reflect.Indirect(self.val).(type) {
	case *reflect.StructValue:
		t := v.Type().(*reflect.StructType)
		// Case-insensitive field lookup.
		k = strings.ToLower(k)
		for i := 0; i < t.NumField(); i++ {
			if strings.ToLower(t.Field(i).Name) == k {
				return &structBuilder{val: v.Field(i)}
			}
		}

	case *reflect.MapValue:
		t := v.Type().(*reflect.MapType)
		if t.Key() != reflect.Typeof(k) {
			break
		}
		key := reflect.NewValue(k)
		elem := v.Elem(key)
		if elem == nil {
			v.SetElem(key, reflect.MakeZero(t.Elem()))
			elem = v.Elem(key)
		}
		return &structBuilder{val: elem, map_: v, key: key}

	case *reflect.SliceValue:
		index, err := strconv.Atoi(k)
		if err != nil {
			return nobuilder
		}
		if index < v.Len() {
			return &structBuilder{val: v.Elem(index)}
		}
		if index < v.Cap() {
			v.SetLen(index + 1)
			return &structBuilder{val: v.Elem(index)}
		}
		newCap := v.Cap() * 2
		if index >= newCap {
			newCap = index*2 + 1
		}
		temp := reflect.MakeSlice(v.Type().(*reflect.SliceType), index+1, newCap)
		reflect.ArrayCopy(temp, v)
		v.Set(temp)
		return &structBuilder{val: v.Elem(index)}
	}
	return nobuilder
}
コード例 #16
0
ファイル: bencode_test.go プロジェクト: royger/wgo
func checkUnmarshal(expected string, data any) (err os.Error) {
	if err = checkMarshal(expected, data); err != nil {
		return
	}
	dataValue := reflect.NewValue(data)
	newOne := reflect.MakeZero(dataValue.Type())
	buf := bytes.NewBufferString(expected)
	if err = UnmarshalValue(buf, newOne); err != nil {
		return
	}
	if err = checkFuzzyEqualValue(dataValue, newOne); err != nil {
		return
	}
	return
}
コード例 #17
0
ファイル: export.go プロジェクト: rapgamer/golang-china
// Export exports a channel of a given type and specified direction.  The
// channel to be exported is provided in the call and may be of arbitrary
// channel type.
// Despite the literal signature, the effective signature is
//	Export(name string, chT chan T, dir Dir)
// where T must be a struct, pointer to struct, etc.
// TODO: fix gob interface so we can eliminate the need for pT, and for structs.
func (exp *Exporter) Export(name string, chT interface{}, dir Dir, pT interface{}) os.Error {
	ch, err := checkChan(chT, dir)
	if err != nil {
		return err
	}
	exp.chanLock.Lock()
	defer exp.chanLock.Unlock()
	_, present := exp.chans[name]
	if present {
		return os.ErrorString("channel name already being exported:" + name)
	}
	ptr := reflect.MakeZero(reflect.Typeof(pT)).(*reflect.PtrValue)
	exp.chans[name] = &exportChan{ch, dir, ptr}
	return nil
}
コード例 #18
0
ファイル: export.go プロジェクト: rapgamer/golang-china
// Receive and deliver locally one item from a client asking for a Send
// The header is passed by value to avoid issues of overwriting.
func (client *expClient) serveSend(hdr header) {
	ech := client.getChan(&hdr, Recv)
	if ech == nil {
		return
	}
	// Create a new value for each received item.
	val := reflect.MakeZero(ech.ptr.Type().(*reflect.PtrType).Elem())
	ech.ptr.PointTo(val)
	if err := client.decode(ech.ptr.Interface()); err != nil {
		log.Stderr("exporter value decode:", err)
		return
	}
	ech.ch.Send(val)
	// TODO count
}
コード例 #19
0
ファイル: struct.go プロジェクト: ivanwyc/google-go
func (b *structBuilder) Map() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() {
		if v.IsNil() {
			v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
			b.Flush()
		}
		b.map_ = nil
		b.val = v.Elem()
	}
	if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() {
		v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
	}
}
コード例 #20
0
ファイル: bson-struct.go プロジェクト: welterde/gomongo
func (self *structBuilder) Object() {
	if self == nil {
		return
	}
	if v, ok := self.val.(*reflect.PtrValue); ok && v.IsNil() {
		if v.IsNil() {
			v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
			self.Flush()
		}
		self.map_ = nil
		self.val = v.Elem()
	}
	if v, ok := self.val.(*reflect.MapValue); ok && v.IsNil() {
		v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
	}
}
コード例 #21
0
ファイル: dm.go プロジェクト: tokuhirom/go_datamapper
func (m *Model) single_result(sql string) interface{} {
	res, err := Execute(sql);
	if err != 0 {
		defer res.Finalize()
	}
	o := reflect.MakeZero(m.Type);
	if err == 101 {	// not found
		f := o.(*reflect.StructValue).FieldByName("Null");
		f.(*reflect.BoolValue).Set(true);
		// return nil;
	} else {
		build_result(o, res)
	}

	return o.Interface();
}
コード例 #22
0
ファイル: import.go プロジェクト: rapgamer/golang-china
// Handle the data from a single imported data stream, which will
// have the form
//	(response, data)*
// The response identifies by name which channel is transmitting data.
func (imp *Importer) run() {
	// Loop on responses; requests are sent by ImportNValues()
	hdr := new(header)
	err := new(error)
	for {
		if e := imp.decode(hdr); e != nil {
			log.Stderr("importer header:", e)
			return
		}
		switch hdr.payloadType {
		case payData:
			// done lower in loop
		case payError:
			if e := imp.decode(err); e != nil {
				log.Stderr("importer error:", e)
				return
			}
			if err.error != "" {
				log.Stderr("importer response error:", err.error)
				// TODO: tear down connection
				return
			}
		default:
			log.Stderr("unexpected payload type:", hdr.payloadType)
			return
		}
		imp.chanLock.Lock()
		ich, ok := imp.chans[hdr.name]
		imp.chanLock.Unlock()
		if !ok {
			log.Stderr("unknown name in request:", hdr.name)
			return
		}
		if ich.dir != Recv {
			log.Stderr("cannot happen: receive from non-Recv channel")
			return
		}
		// Create a new value for each received item.
		val := reflect.MakeZero(ich.ptr.Type().(*reflect.PtrType).Elem())
		ich.ptr.PointTo(val)
		if e := imp.decode(ich.ptr.Interface()); e != nil {
			log.Stderr("importer value decode:", e)
			return
		}
		ich.ch.Send(val)
	}
}
コード例 #23
0
ファイル: import.go プロジェクト: rapgamer/golang-china
// ImportNValues imports a channel of the given type and specified direction
// and then receives or transmits up to n values on that channel.  A value of
// n==0 implies an unbounded number of values.  The channel to be bound to
// the remote site's channel is provided in the call and may be of arbitrary
// channel type.
// Despite the literal signature, the effective signature is
//	ImportNValues(name string, chT chan T, dir Dir, pT T, n int) os.Error
// where T must be a struct, pointer to struct, etc.  pT may be more indirect
// than the value type of the channel (e.g.  chan T, pT *T) but it must be a
// pointer.
// Example usage:
//	imp, err := NewImporter("tcp", "netchanserver.mydomain.com:1234")
//	if err != nil { log.Exit(err) }
//	ch := make(chan myType)
//	err := imp.ImportNValues("name", ch, Recv, new(myType), 1)
//	if err != nil { log.Exit(err) }
//	fmt.Printf("%+v\n", <-ch)
// TODO: fix gob interface so we can eliminate the need for pT, and for structs.
func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, pT interface{}, n int) os.Error {
	ch, err := checkChan(chT, dir)
	if err != nil {
		return err
	}
	// Make sure pT is a pointer (to a pointer...) to a struct.
	rt := reflect.Typeof(pT)
	if _, ok := rt.(*reflect.PtrType); !ok {
		return os.ErrorString("not a pointer:" + rt.String())
	}
	if _, ok := reflect.Indirect(reflect.NewValue(pT)).(*reflect.StructValue); !ok {
		return os.ErrorString("not a pointer to a struct:" + rt.String())
	}
	imp.chanLock.Lock()
	defer imp.chanLock.Unlock()
	_, present := imp.chans[name]
	if present {
		return os.ErrorString("channel name already being imported:" + name)
	}
	ptr := reflect.MakeZero(reflect.Typeof(pT)).(*reflect.PtrValue)
	imp.chans[name] = &importChan{ch, dir, ptr}
	// Tell the other side about this channel.
	hdr := new(header)
	hdr.name = name
	hdr.payloadType = payRequest
	req := new(request)
	req.dir = dir
	req.count = n
	if err := imp.encode(hdr, payRequest, req); err != nil {
		log.Stderr("importer request encode:", err)
		return err
	}
	if dir == Send {
		go func() {
			for i := 0; n == 0 || i < n; i++ {
				val := ch.Recv()
				if err := imp.encode(hdr, payData, val.Interface()); err != nil {
					log.Stderr("error encoding client response:", err)
					return
				}
			}
		}()
	}
	return nil
}
コード例 #24
0
ファイル: bson_decode.go プロジェクト: hokapoka/go-mongo
// indirect walks down v allocating pointers as needed, until it gets to a
// non-pointer.
func (d *decodeState) indirect(v reflect.Value) reflect.Value {
	for {
		/*
			if iv, ok := v.(*reflect.InterfaceValue); ok && !iv.IsNil() {
				v = iv.Elem()
				continue
			}
		*/
		pv, ok := v.(*reflect.PtrValue)
		if !ok {
			break
		}
		if pv.IsNil() {
			pv.PointTo(reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem()))
		}
		v = pv.Elem()
	}
	return v
}
コード例 #25
0
ファイル: decode.go プロジェクト: rapgamer/golang-china
// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
// if it encounters an Unmarshaler, indirect stops and returns that.
// if wantptr is true, indirect stops at the last pointer.
func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, reflect.Value) {
	for {
		var isUnmarshaler bool
		if v.Type().NumMethod() > 0 {
			// Remember that this is an unmarshaler,
			// but wait to return it until after allocating
			// the pointer (if necessary).
			_, isUnmarshaler = v.Interface().(Unmarshaler)
		}

		if iv, ok := v.(*reflect.InterfaceValue); ok && !iv.IsNil() {
			v = iv.Elem()
			continue
		}
		pv, ok := v.(*reflect.PtrValue)
		if !ok {
			break
		}
		_, isptrptr := pv.Elem().(*reflect.PtrValue)
		if !isptrptr && wantptr && !isUnmarshaler {
			return nil, pv
		}
		if pv.IsNil() {
			pv.PointTo(reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem()))
		}
		if isUnmarshaler {
			// Using v.Interface().(Unmarshaler)
			// here means that we have to use a pointer
			// as the struct field.  We cannot use a value inside
			// a pointer to a struct, because in that case
			// v.Interface() is the value (x.f) not the pointer (&x.f).
			// This is an unfortunate consequence of reflect.
			// An alternative would be to look up the
			// UnmarshalJSON method and return a FuncValue.
			return v.Interface().(Unmarshaler), nil
		}
		v = pv.Elem()
	}
	return nil, v
}
コード例 #26
0
ファイル: bson_decode.go プロジェクト: hokapoka/go-mongo
func decodeMap(d *decodeState, kind int, value reflect.Value) {
	t := value.Type().(*reflect.MapType)
	if t.Key().Kind() != reflect.String || kind != kindDocument {
		d.saveErrorAndSkip(kind, value.Type())
		return
	}
	v := value.(*reflect.MapValue)
	if v.IsNil() {
		v.SetValue(reflect.MakeMap(t))
	}
	offset := d.beginDoc()
	for {
		kind, name := d.scanKindName()
		if kind == 0 {
			break
		}
		subv := reflect.MakeZero(t.Elem())
		d.decodeValue(kind, subv)
		v.SetElem(reflect.NewValue(string(name)), subv)
	}
	d.endDoc(offset)
}
コード例 #27
0
ファイル: request.go プロジェクト: rsec/web.go
func (r *Request) writeToContainer(val reflect.Value) os.Error {
	switch v := val.(type) {
	case *reflect.PtrValue:
		return r.writeToContainer(reflect.Indirect(v))
	case *reflect.InterfaceValue:
		return r.writeToContainer(v.Elem())
	case *reflect.MapValue:
		if _, ok := v.Type().(*reflect.MapType).Key().(*reflect.StringType); !ok {
			return os.NewError("Invalid map type")
		}
		elemtype := v.Type().(*reflect.MapType).Elem()
		for pk, pv := range r.Params {
			mk := reflect.NewValue(pk)
			mv := reflect.MakeZero(elemtype)
			writeTo(pv, mv)
			v.SetElem(mk, mv)
		}
	case *reflect.StructValue:
		for pk, pv := range r.Params {
			//try case sensitive match
			field := v.FieldByName(pk)
			if field != nil {
				writeTo(pv, field)
			}

			//try case insensitive matching
			field = v.FieldByNameFunc(func(s string) bool { return matchName(pk, s) })
			if field != nil {
				writeTo(pv, field)
			}

		}
	default:
		return os.NewError("Invalid container type")
	}
	return nil
}
コード例 #28
0
ファイル: template.go プロジェクト: richlowe/gcc
// Evaluate interfaces and pointers looking for a value that can look up the name, via a
// struct field, method, or map key, and return the result of the lookup.
func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value {
	for v != nil {
		typ := v.Type()
		if n := v.Type().NumMethod(); n > 0 {
			for i := 0; i < n; i++ {
				m := typ.Method(i)
				mtyp := m.Type
				if m.Name == name && mtyp.NumIn() == 1 && mtyp.NumOut() == 1 {
					if !isExported(name) {
						t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
					}
					return v.Method(i).Call(nil)[0]
				}
			}
		}
		switch av := v.(type) {
		case *reflect.PtrValue:
			v = av.Elem()
		case *reflect.InterfaceValue:
			v = av.Elem()
		case *reflect.StructValue:
			if !isExported(name) {
				t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
			}
			return av.FieldByName(name)
		case *reflect.MapValue:
			if v := av.Elem(reflect.NewValue(name)); v != nil {
				return v
			}
			return reflect.MakeZero(typ.(*reflect.MapType).Elem())
		default:
			return nil
		}
	}
	return v
}
コード例 #29
0
ファイル: read.go プロジェクト: lougxing/golang-china
// Unmarshal a single XML element into val.
func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
	// Find start element if we need it.
	if start == nil {
		for {
			tok, err := p.Token()
			if err != nil {
				return err
			}
			if t, ok := tok.(StartElement); ok {
				start = &t
				break
			}
		}
	}

	if pv, ok := val.(*reflect.PtrValue); ok {
		if pv.Get() == 0 {
			zv := reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem())
			pv.PointTo(zv)
			val = zv
		} else {
			val = pv.Elem()
		}
	}

	var (
		data        []byte
		saveData    reflect.Value
		comment     []byte
		saveComment reflect.Value
		sv          *reflect.StructValue
		styp        *reflect.StructType
	)
	switch v := val.(type) {
	default:
		return os.ErrorString("unknown type " + v.Type().String())

	case *reflect.BoolValue:
		v.Set(true)

	case *reflect.SliceValue:
		typ := v.Type().(*reflect.SliceType)
		if _, ok := typ.Elem().(*reflect.Uint8Type); ok {
			// []byte
			saveData = v
			break
		}

		// Slice of element values.
		// Grow slice.
		n := v.Len()
		if n >= v.Cap() {
			ncap := 2 * n
			if ncap < 4 {
				ncap = 4
			}
			new := reflect.MakeSlice(typ, n, ncap)
			reflect.ArrayCopy(new, v)
			v.Set(new)
		}
		v.SetLen(n + 1)

		// Recur to read element into slice.
		if err := p.unmarshal(v.Elem(n), start); err != nil {
			v.SetLen(n)
			return err
		}
		return nil

	case *reflect.StringValue,
		*reflect.IntValue, *reflect.UintValue, *reflect.UintptrValue,
		*reflect.Int8Value, *reflect.Int16Value, *reflect.Int32Value, *reflect.Int64Value,
		*reflect.Uint8Value, *reflect.Uint16Value, *reflect.Uint32Value, *reflect.Uint64Value,
		*reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value:
		saveData = v

	case *reflect.StructValue:
		if _, ok := v.Interface().(Name); ok {
			v.Set(reflect.NewValue(start.Name).(*reflect.StructValue))
			break
		}

		sv = v
		typ := sv.Type().(*reflect.StructType)
		styp = typ
		// Assign name.
		if f, ok := typ.FieldByName("XMLName"); ok {
			// Validate element name.
			if f.Tag != "" {
				tag := f.Tag
				ns := ""
				i := strings.LastIndex(tag, " ")
				if i >= 0 {
					ns, tag = tag[0:i], tag[i+1:]
				}
				if tag != start.Name.Local {
					return UnmarshalError("expected element type <" + tag + "> but have <" + start.Name.Local + ">")
				}
				if ns != "" && ns != start.Name.Space {
					e := "expected element <" + tag + "> in name space " + ns + " but have "
					if start.Name.Space == "" {
						e += "no name space"
					} else {
						e += start.Name.Space
					}
					return UnmarshalError(e)
				}
			}

			// Save
			v := sv.FieldByIndex(f.Index)
			if _, ok := v.Interface().(Name); !ok {
				return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name")
			}
			v.(*reflect.StructValue).Set(reflect.NewValue(start.Name).(*reflect.StructValue))
		}

		// Assign attributes.
		// Also, determine whether we need to save character data or comments.
		for i, n := 0, typ.NumField(); i < n; i++ {
			f := typ.Field(i)
			switch f.Tag {
			case "attr":
				strv, ok := sv.FieldByIndex(f.Index).(*reflect.StringValue)
				if !ok {
					return UnmarshalError(sv.Type().String() + " field " + f.Name + " has attr tag but is not type string")
				}
				// Look for attribute.
				val := ""
				k := strings.ToLower(f.Name)
				for _, a := range start.Attr {
					if fieldName(a.Name.Local) == k {
						val = a.Value
						break
					}
				}
				strv.Set(val)

			case "comment":
				if saveComment == nil {
					saveComment = sv.FieldByIndex(f.Index)
				}

			case "chardata":
				if saveData == nil {
					saveData = sv.FieldByIndex(f.Index)
				}
			}
		}
	}

	// Find end element.
	// Process sub-elements along the way.
Loop:
	for {
		tok, err := p.Token()
		if err != nil {
			return err
		}
		switch t := tok.(type) {
		case StartElement:
			// Sub-element.
			// Look up by tag name.
			// If that fails, fall back to mop-up field named "Any".
			if sv != nil {
				k := fieldName(t.Name.Local)
				any := -1
				for i, n := 0, styp.NumField(); i < n; i++ {
					f := styp.Field(i)
					if strings.ToLower(f.Name) == k {
						if err := p.unmarshal(sv.FieldByIndex(f.Index), &t); err != nil {
							return err
						}
						continue Loop
					}
					if any < 0 && f.Name == "Any" {
						any = i
					}
				}
				if any >= 0 {
					if err := p.unmarshal(sv.FieldByIndex(styp.Field(any).Index), &t); err != nil {
						return err
					}
					continue Loop
				}
			}
			// Not saving sub-element but still have to skip over it.
			if err := p.Skip(); err != nil {
				return err
			}

		case EndElement:
			break Loop

		case CharData:
			if saveData != nil {
				data = bytes.Add(data, t)
			}

		case Comment:
			if saveComment != nil {
				comment = bytes.Add(comment, t)
			}
		}
	}

	var err os.Error
	// Helper functions for integer and unsigned integer conversions
	var itmp int64
	getInt64 := func() bool {
		itmp, err = strconv.Atoi64(string(data))
		// TODO: should check sizes
		return err == nil
	}
	var utmp uint64
	getUint64 := func() bool {
		utmp, err = strconv.Atoui64(string(data))
		// TODO: check for overflow?
		return err == nil
	}
	var ftmp float64
	getFloat64 := func() bool {
		ftmp, err = strconv.Atof64(string(data))
		// TODO: check for overflow?
		return err == nil
	}

	// Save accumulated data and comments
	switch t := saveData.(type) {
	case nil:
		// Probably a comment, handled below
	default:
		return os.ErrorString("cannot happen: unknown type " + t.Type().String())
	case *reflect.IntValue:
		if !getInt64() {
			return err
		}
		t.Set(int(itmp))
	case *reflect.Int8Value:
		if !getInt64() {
			return err
		}
		t.Set(int8(itmp))
	case *reflect.Int16Value:
		if !getInt64() {
			return err
		}
		t.Set(int16(itmp))
	case *reflect.Int32Value:
		if !getInt64() {
			return err
		}
		t.Set(int32(itmp))
	case *reflect.Int64Value:
		if !getInt64() {
			return err
		}
		t.Set(itmp)
	case *reflect.UintValue:
		if !getUint64() {
			return err
		}
		t.Set(uint(utmp))
	case *reflect.Uint8Value:
		if !getUint64() {
			return err
		}
		t.Set(uint8(utmp))
	case *reflect.Uint16Value:
		if !getUint64() {
			return err
		}
		t.Set(uint16(utmp))
	case *reflect.Uint32Value:
		if !getUint64() {
			return err
		}
		t.Set(uint32(utmp))
	case *reflect.Uint64Value:
		if !getUint64() {
			return err
		}
		t.Set(utmp)
	case *reflect.UintptrValue:
		if !getUint64() {
			return err
		}
		t.Set(uintptr(utmp))
	case *reflect.FloatValue:
		if !getFloat64() {
			return err
		}
		t.Set(float(ftmp))
	case *reflect.Float32Value:
		if !getFloat64() {
			return err
		}
		t.Set(float32(ftmp))
	case *reflect.Float64Value:
		if !getFloat64() {
			return err
		}
		t.Set(ftmp)
	case *reflect.StringValue:
		t.Set(string(data))
	case *reflect.SliceValue:
		t.Set(reflect.NewValue(data).(*reflect.SliceValue))
	}

	switch t := saveComment.(type) {
	case *reflect.StringValue:
		t.Set(string(comment))
	case *reflect.SliceValue:
		t.Set(reflect.NewValue(comment).(*reflect.SliceValue))
	}

	return nil
}
コード例 #30
0
ファイル: marshal.go プロジェクト: richlowe/gcc
func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err os.Error) {
	// If the field is an interface{} then recurse into it.
	if v, ok := v.(*reflect.InterfaceValue); ok && v.Type().(*reflect.InterfaceType).NumMethod() == 0 {
		return marshalField(out, v.Elem(), params)
	}

	if v.Type() == rawValueType {
		rv := v.Interface().(RawValue)
		err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
		if err != nil {
			return
		}
		_, err = out.Write(rv.Bytes)
		return
	}

	if params.optional && reflect.DeepEqual(v.Interface(), reflect.MakeZero(v.Type()).Interface()) {
		return
	}

	tag, isCompound, ok := getUniversalType(v.Type())
	if !ok {
		err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
		return
	}
	class := classUniversal

	if params.stringType != 0 {
		if tag != tagPrintableString {
			return StructuralError{"Explicit string type given to non-string member"}
		}
		tag = params.stringType
	}

	if params.set {
		if tag != tagSequence {
			return StructuralError{"Non sequence tagged as set"}
		}
		tag = tagSet
	}

	tags, body := out.fork()

	err = marshalBody(body, v, params)
	if err != nil {
		return
	}

	bodyLen := body.Len()

	var explicitTag *forkableWriter
	if params.explicit {
		explicitTag, tags = tags.fork()
	}

	if !params.explicit && params.tag != nil {
		// implicit tag.
		tag = *params.tag
		class = classContextSpecific
	}

	err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
	if err != nil {
		return
	}

	if params.explicit {
		err = marshalTagAndLength(explicitTag, tagAndLength{
			class:      classContextSpecific,
			tag:        *params.tag,
			length:     bodyLen + tags.Len(),
			isCompound: true,
		})
	}

	return nil
}