mirror of
https://github.com/golang/go
synced 2024-11-25 01:57:56 -07:00
encoding/json: cleanup leftover variables in array decoding.
An old update for API changes in reflect package left several helper variables that do not have a meaning anymore, and the type checking of arrays vs slices was broken. Fixes #2513. R=ultrotter, rsc CC=golang-dev, remy https://golang.org/cl/5488094
This commit is contained in:
parent
3a2dec0246
commit
4a4c39e7d4
@ -228,7 +228,9 @@ func (d *decodeState) value(v reflect.Value) {
|
||||
// Feed in an empty string - the shortest, simplest value -
|
||||
// so that it knows we got to the end of the value.
|
||||
if d.scan.redo {
|
||||
panic("redo")
|
||||
// rewind.
|
||||
d.scan.redo = false
|
||||
d.scan.step = stateBeginValue
|
||||
}
|
||||
d.scan.step(&d.scan, '"')
|
||||
d.scan.step(&d.scan, '"')
|
||||
@ -317,25 +319,22 @@ func (d *decodeState) array(v reflect.Value) {
|
||||
}
|
||||
v = pv
|
||||
|
||||
// Decoding into nil interface? Switch to non-reflect code.
|
||||
iv := v
|
||||
ok := iv.Kind() == reflect.Interface
|
||||
if ok {
|
||||
iv.Set(reflect.ValueOf(d.arrayInterface()))
|
||||
return
|
||||
}
|
||||
|
||||
// Check type of target.
|
||||
av := v
|
||||
if av.Kind() != reflect.Array && av.Kind() != reflect.Slice {
|
||||
switch v.Kind() {
|
||||
default:
|
||||
d.saveError(&UnmarshalTypeError{"array", v.Type()})
|
||||
d.off--
|
||||
d.next()
|
||||
return
|
||||
case reflect.Interface:
|
||||
// Decoding into nil interface? Switch to non-reflect code.
|
||||
v.Set(reflect.ValueOf(d.arrayInterface()))
|
||||
return
|
||||
case reflect.Array:
|
||||
case reflect.Slice:
|
||||
break
|
||||
}
|
||||
|
||||
sv := v
|
||||
|
||||
i := 0
|
||||
for {
|
||||
// Look ahead for ] - can only happen on first iteration.
|
||||
@ -349,23 +348,25 @@ func (d *decodeState) array(v reflect.Value) {
|
||||
d.scan.undo(op)
|
||||
|
||||
// Get element of array, growing if necessary.
|
||||
if i >= av.Cap() && sv.IsValid() {
|
||||
newcap := sv.Cap() + sv.Cap()/2
|
||||
if newcap < 4 {
|
||||
newcap = 4
|
||||
if v.Kind() == reflect.Slice {
|
||||
// Grow slice if necessary
|
||||
if i >= v.Cap() {
|
||||
newcap := v.Cap() + v.Cap()/2
|
||||
if newcap < 4 {
|
||||
newcap = 4
|
||||
}
|
||||
newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
|
||||
reflect.Copy(newv, v)
|
||||
v.Set(newv)
|
||||
}
|
||||
if i >= v.Len() {
|
||||
v.SetLen(i + 1)
|
||||
}
|
||||
newv := reflect.MakeSlice(sv.Type(), sv.Len(), newcap)
|
||||
reflect.Copy(newv, sv)
|
||||
sv.Set(newv)
|
||||
}
|
||||
if i >= av.Len() && sv.IsValid() {
|
||||
// Must be slice; gave up on array during i >= av.Cap().
|
||||
sv.SetLen(i + 1)
|
||||
}
|
||||
|
||||
// Decode into element.
|
||||
if i < av.Len() {
|
||||
d.value(av.Index(i))
|
||||
if i < v.Len() {
|
||||
// Decode into element.
|
||||
d.value(v.Index(i))
|
||||
} else {
|
||||
// Ran out of fixed array: skip.
|
||||
d.value(reflect.Value{})
|
||||
@ -382,19 +383,19 @@ func (d *decodeState) array(v reflect.Value) {
|
||||
}
|
||||
}
|
||||
|
||||
if i < av.Len() {
|
||||
if !sv.IsValid() {
|
||||
if i < v.Len() {
|
||||
if v.Kind() == reflect.Array {
|
||||
// Array. Zero the rest.
|
||||
z := reflect.Zero(av.Type().Elem())
|
||||
for ; i < av.Len(); i++ {
|
||||
av.Index(i).Set(z)
|
||||
z := reflect.Zero(v.Type().Elem())
|
||||
for ; i < v.Len(); i++ {
|
||||
v.Index(i).Set(z)
|
||||
}
|
||||
} else {
|
||||
sv.SetLen(i)
|
||||
v.SetLen(i)
|
||||
}
|
||||
}
|
||||
if i == 0 && av.Kind() == reflect.Slice && sv.IsNil() {
|
||||
sv.Set(reflect.MakeSlice(sv.Type(), 0, 0))
|
||||
if i == 0 && v.Kind() == reflect.Slice {
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,12 @@ var unmarshalTests = []unmarshalTest{
|
||||
|
||||
// syntax errors
|
||||
{`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
|
||||
{`[1, 2, 3+]`, nil, nil, &SyntaxError{"invalid character '+' after array element", 9}},
|
||||
|
||||
// array tests
|
||||
{`[1, 2, 3]`, new([3]int), [3]int{1, 2, 3}, nil},
|
||||
{`[1, 2, 3]`, new([1]int), [1]int{1}, nil},
|
||||
{`[1, 2, 3]`, new([5]int), [5]int{1, 2, 3, 0, 0}, nil},
|
||||
|
||||
// composite tests
|
||||
{allValueIndent, new(All), allValue, nil},
|
||||
|
Loading…
Reference in New Issue
Block a user