diff options
Diffstat (limited to 'src/pkg/encoding/xml/read.go')
-rw-r--r-- | src/pkg/encoding/xml/read.go | 74 |
1 files changed, 32 insertions, 42 deletions
diff --git a/src/pkg/encoding/xml/read.go b/src/pkg/encoding/xml/read.go index c21682420..344ab514e 100644 --- a/src/pkg/encoding/xml/read.go +++ b/src/pkg/encoding/xml/read.go @@ -81,8 +81,8 @@ import ( // of the above rules and the struct has a field with tag ",any", // unmarshal maps the sub-element to that struct field. // -// * A non-pointer anonymous struct field is handled as if the -// fields of its value were part of the outer struct. +// * An anonymous struct field is handled as if the fields of its +// value were part of the outer struct. // // * A struct field with tag "-" is never unmarshalled into. // @@ -248,7 +248,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error { } return UnmarshalError(e) } - fv := sv.FieldByIndex(finfo.idx) + fv := finfo.value(sv) if _, ok := fv.Interface().(Name); ok { fv.Set(reflect.ValueOf(start.Name)) } @@ -260,7 +260,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error { finfo := &tinfo.fields[i] switch finfo.flags & fMode { case fAttr: - strv := sv.FieldByIndex(finfo.idx) + strv := finfo.value(sv) // Look for attribute. for _, a := range start.Attr { if a.Name.Local == finfo.name { @@ -271,22 +271,22 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error { case fCharData: if !saveData.IsValid() { - saveData = sv.FieldByIndex(finfo.idx) + saveData = finfo.value(sv) } case fComment: if !saveComment.IsValid() { - saveComment = sv.FieldByIndex(finfo.idx) + saveComment = finfo.value(sv) } - case fAny: + case fAny, fAny | fElement: if !saveAny.IsValid() { - saveAny = sv.FieldByIndex(finfo.idx) + saveAny = finfo.value(sv) } case fInnerXml: if !saveXML.IsValid() { - saveXML = sv.FieldByIndex(finfo.idx) + saveXML = finfo.value(sv) if p.saved == nil { saveXMLIndex = 0 p.saved = new(bytes.Buffer) @@ -374,68 +374,58 @@ Loop: } func copyValue(dst reflect.Value, src []byte) (err error) { - // Helper functions for integer and unsigned integer conversions - var itmp int64 - getInt64 := func() bool { - itmp, err = strconv.ParseInt(string(src), 10, 64) - // TODO: should check sizes - return err == nil - } - var utmp uint64 - getUint64 := func() bool { - utmp, err = strconv.ParseUint(string(src), 10, 64) - // TODO: check for overflow? - return err == nil - } - var ftmp float64 - getFloat64 := func() bool { - ftmp, err = strconv.ParseFloat(string(src), 64) - // TODO: check for overflow? - return err == nil + if dst.Kind() == reflect.Ptr { + if dst.IsNil() { + dst.Set(reflect.New(dst.Type().Elem())) + } + dst = dst.Elem() } // Save accumulated data. - switch t := dst; t.Kind() { + switch dst.Kind() { case reflect.Invalid: - // Probably a comment. + // Probably a commendst. default: - return errors.New("cannot happen: unknown type " + t.Type().String()) + return errors.New("cannot happen: unknown type " + dst.Type().String()) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - if !getInt64() { + itmp, err := strconv.ParseInt(string(src), 10, dst.Type().Bits()) + if err != nil { return err } - t.SetInt(itmp) + dst.SetInt(itmp) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - if !getUint64() { + utmp, err := strconv.ParseUint(string(src), 10, dst.Type().Bits()) + if err != nil { return err } - t.SetUint(utmp) + dst.SetUint(utmp) case reflect.Float32, reflect.Float64: - if !getFloat64() { + ftmp, err := strconv.ParseFloat(string(src), dst.Type().Bits()) + if err != nil { return err } - t.SetFloat(ftmp) + dst.SetFloat(ftmp) case reflect.Bool: value, err := strconv.ParseBool(strings.TrimSpace(string(src))) if err != nil { return err } - t.SetBool(value) + dst.SetBool(value) case reflect.String: - t.SetString(string(src)) + dst.SetString(string(src)) case reflect.Slice: if len(src) == 0 { // non-nil to flag presence src = []byte{} } - t.SetBytes(src) + dst.SetBytes(src) case reflect.Struct: - if t.Type() == timeType { + if dst.Type() == timeType { tv, err := time.Parse(time.RFC3339, string(src)) if err != nil { return err } - t.Set(reflect.ValueOf(tv)) + dst.Set(reflect.ValueOf(tv)) } } return nil @@ -461,7 +451,7 @@ Loop: } if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local { // It's a perfect match, unmarshal the field. - return true, p.unmarshal(sv.FieldByIndex(finfo.idx), start) + return true, p.unmarshal(finfo.value(sv), start) } if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local { // It's a prefix for the field. Break and recurse |