mirror of
https://github.com/golang/go
synced 2024-11-25 16:07:56 -07:00
allow any scalar type in xml.Unmarshal.
Fixes #574. R=rsc CC=golang-dev https://golang.org/cl/196056
This commit is contained in:
parent
60f27f0d6b
commit
5db5f68d96
@ -9,6 +9,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
@ -106,6 +107,10 @@ import (
|
|||||||
//
|
//
|
||||||
// Unmarshal maps an XML element to a bool by setting the bool to true.
|
// Unmarshal maps an XML element to a bool by setting the bool to true.
|
||||||
//
|
//
|
||||||
|
// Unmarshal maps an XML element to an integer or floating-point
|
||||||
|
// field by setting the field to the result of interpreting the string
|
||||||
|
// value in decimal. There is no check for overflow.
|
||||||
|
//
|
||||||
// Unmarshal maps an XML element to an xml.Name by recording the
|
// Unmarshal maps an XML element to an xml.Name by recording the
|
||||||
// element name.
|
// element name.
|
||||||
//
|
//
|
||||||
@ -200,6 +205,9 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
|
|||||||
styp *reflect.StructType
|
styp *reflect.StructType
|
||||||
)
|
)
|
||||||
switch v := val.(type) {
|
switch v := val.(type) {
|
||||||
|
default:
|
||||||
|
return os.ErrorString("unknown type " + v.Type().String())
|
||||||
|
|
||||||
case *reflect.BoolValue:
|
case *reflect.BoolValue:
|
||||||
v.Set(true)
|
v.Set(true)
|
||||||
|
|
||||||
@ -232,7 +240,11 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *reflect.StringValue:
|
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
|
saveData = v
|
||||||
|
|
||||||
case *reflect.StructValue:
|
case *reflect.StructValue:
|
||||||
@ -365,8 +377,103 @@ Loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save accumulated character data and comments
|
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) {
|
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:
|
case *reflect.StringValue:
|
||||||
t.Set(string(data))
|
t.Set(string(data))
|
||||||
case *reflect.SliceValue:
|
case *reflect.SliceValue:
|
||||||
|
@ -214,6 +214,76 @@ func TestSyntax(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type allScalars struct {
|
||||||
|
Bool bool
|
||||||
|
Int int
|
||||||
|
Int8 int8
|
||||||
|
Int16 int16
|
||||||
|
Int32 int32
|
||||||
|
Int64 int64
|
||||||
|
Uint int
|
||||||
|
Uint8 uint8
|
||||||
|
Uint16 uint16
|
||||||
|
Uint32 uint32
|
||||||
|
Uint64 uint64
|
||||||
|
Uintptr uintptr
|
||||||
|
Float float
|
||||||
|
Float32 float32
|
||||||
|
Float64 float64
|
||||||
|
String string
|
||||||
|
}
|
||||||
|
|
||||||
|
var all = allScalars{
|
||||||
|
Bool: true,
|
||||||
|
Int: 1,
|
||||||
|
Int8: -2,
|
||||||
|
Int16: 3,
|
||||||
|
Int32: -4,
|
||||||
|
Int64: 5,
|
||||||
|
Uint: 6,
|
||||||
|
Uint8: 7,
|
||||||
|
Uint16: 8,
|
||||||
|
Uint32: 9,
|
||||||
|
Uint64: 10,
|
||||||
|
Uintptr: 11,
|
||||||
|
Float: 12.0,
|
||||||
|
Float32: 13.0,
|
||||||
|
Float64: 14.0,
|
||||||
|
String: "15",
|
||||||
|
}
|
||||||
|
|
||||||
|
const testScalarsInput = `<allscalars>
|
||||||
|
<bool/>
|
||||||
|
<int>1</int>
|
||||||
|
<int8>-2</int8>
|
||||||
|
<int16>3</int16>
|
||||||
|
<int32>-4</int32>
|
||||||
|
<int64>5</int64>
|
||||||
|
<uint>6</uint>
|
||||||
|
<uint8>7</uint8>
|
||||||
|
<uint16>8</uint16>
|
||||||
|
<uint32>9</uint32>
|
||||||
|
<uint64>10</uint64>
|
||||||
|
<uintptr>11</uintptr>
|
||||||
|
<float>12.0</float>
|
||||||
|
<float32>13.0</float32>
|
||||||
|
<float64>14.0</float64>
|
||||||
|
<string>15</string>
|
||||||
|
</allscalars>`
|
||||||
|
|
||||||
|
func TestAllScalars(t *testing.T) {
|
||||||
|
var a allScalars
|
||||||
|
buf := bytes.NewBufferString(testScalarsInput)
|
||||||
|
err := Unmarshal(buf, &a)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(a, all) {
|
||||||
|
t.Errorf("expected %+v got %+v", a, all)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type item struct {
|
type item struct {
|
||||||
Field_a string
|
Field_a string
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user