Commit 4a4c39e7 authored by Rémy Oudompheng's avatar Rémy Oudompheng Committed by Russ Cox

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
parent 3a2dec02
...@@ -228,7 +228,9 @@ func (d *decodeState) value(v reflect.Value) { ...@@ -228,7 +228,9 @@ func (d *decodeState) value(v reflect.Value) {
// Feed in an empty string - the shortest, simplest value - // Feed in an empty string - the shortest, simplest value -
// so that it knows we got to the end of the value. // so that it knows we got to the end of the value.
if d.scan.redo { 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, '"')
d.scan.step(&d.scan, '"') d.scan.step(&d.scan, '"')
...@@ -317,25 +319,22 @@ func (d *decodeState) array(v reflect.Value) { ...@@ -317,25 +319,22 @@ func (d *decodeState) array(v reflect.Value) {
} }
v = pv 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. // Check type of target.
av := v switch v.Kind() {
if av.Kind() != reflect.Array && av.Kind() != reflect.Slice { default:
d.saveError(&UnmarshalTypeError{"array", v.Type()}) d.saveError(&UnmarshalTypeError{"array", v.Type()})
d.off-- d.off--
d.next() d.next()
return 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 i := 0
for { for {
// Look ahead for ] - can only happen on first iteration. // Look ahead for ] - can only happen on first iteration.
...@@ -349,23 +348,25 @@ func (d *decodeState) array(v reflect.Value) { ...@@ -349,23 +348,25 @@ func (d *decodeState) array(v reflect.Value) {
d.scan.undo(op) d.scan.undo(op)
// Get element of array, growing if necessary. // Get element of array, growing if necessary.
if i >= av.Cap() && sv.IsValid() { if v.Kind() == reflect.Slice {
newcap := sv.Cap() + sv.Cap()/2 // Grow slice if necessary
if newcap < 4 { if i >= v.Cap() {
newcap = 4 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 < v.Len() {
if i < av.Len() { // Decode into element.
d.value(av.Index(i)) d.value(v.Index(i))
} else { } else {
// Ran out of fixed array: skip. // Ran out of fixed array: skip.
d.value(reflect.Value{}) d.value(reflect.Value{})
...@@ -382,19 +383,19 @@ func (d *decodeState) array(v reflect.Value) { ...@@ -382,19 +383,19 @@ func (d *decodeState) array(v reflect.Value) {
} }
} }
if i < av.Len() { if i < v.Len() {
if !sv.IsValid() { if v.Kind() == reflect.Array {
// Array. Zero the rest. // Array. Zero the rest.
z := reflect.Zero(av.Type().Elem()) z := reflect.Zero(v.Type().Elem())
for ; i < av.Len(); i++ { for ; i < v.Len(); i++ {
av.Index(i).Set(z) v.Index(i).Set(z)
} }
} else { } else {
sv.SetLen(i) v.SetLen(i)
} }
} }
if i == 0 && av.Kind() == reflect.Slice && sv.IsNil() { if i == 0 && v.Kind() == reflect.Slice {
sv.Set(reflect.MakeSlice(sv.Type(), 0, 0)) v.Set(reflect.MakeSlice(v.Type(), 0, 0))
} }
} }
......
...@@ -74,6 +74,12 @@ var unmarshalTests = []unmarshalTest{ ...@@ -74,6 +74,12 @@ var unmarshalTests = []unmarshalTest{
// syntax errors // syntax errors
{`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}}, {`{"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 // composite tests
{allValueIndent, new(All), allValue, nil}, {allValueIndent, new(All), allValue, nil},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment