// 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() }
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 }
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) } } }
// 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 }
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 }
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 } } }
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 }
// 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 }
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 }
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 }
// 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) } }
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) } } }
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) } }
// 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) }
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 }
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 }
// 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 }
// 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 }
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))) } }
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))) } }
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(); }
// 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) } }
// 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 }
// 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 }
// 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 }
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) }
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 }
// 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 }
// 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 }
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 }