summaryrefslogtreecommitdiff
path: root/libgo/go/encoding/json/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/encoding/json/decode.go')
-rw-r--r--libgo/go/encoding/json/decode.go549
1 files changed, 272 insertions, 277 deletions
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index 730fb920ebd..0b29249218a 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -14,7 +14,6 @@ import (
"errors"
"fmt"
"reflect"
- "runtime"
"strconv"
"unicode"
"unicode/utf16"
@@ -168,25 +167,20 @@ func (e *InvalidUnmarshalError) Error() string {
return "json: Unmarshal(nil " + e.Type.String() + ")"
}
-func (d *decodeState) unmarshal(v interface{}) (err error) {
- defer func() {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- }
- err = r.(error)
- }
- }()
-
+func (d *decodeState) unmarshal(v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return &InvalidUnmarshalError{reflect.TypeOf(v)}
}
d.scan.reset()
+ d.scanWhile(scanSkipSpace)
// We decode rv not rv.Elem because the Unmarshaler interface
// test must be applied at the top level of the value.
- d.value(rv)
+ err := d.value(rv)
+ if err != nil {
+ return err
+ }
return d.savedError
}
@@ -210,7 +204,7 @@ func (n Number) Int64() (int64, error) {
func isValidNumber(s string) bool {
// This function implements the JSON numbers grammar.
// See https://tools.ietf.org/html/rfc7159#section-6
- // and http://json.org/number.gif
+ // and https://json.org/number.gif
if s == "" {
return false
@@ -269,9 +263,9 @@ func isValidNumber(s string) bool {
// decodeState represents the state while decoding a JSON value.
type decodeState struct {
data []byte
- off int // read offset in data
+ off int // next read offset in data
+ opcode int // last read result
scan scanner
- nextscan scanner // for calls to nextValue
errorContext struct { // provides context for type errors
Struct string
Field string
@@ -281,6 +275,11 @@ type decodeState struct {
disallowUnknownFields bool
}
+// readIndex returns the position of the last byte read.
+func (d *decodeState) readIndex() int {
+ return d.off - 1
+}
+
// errPhase is used for errors that should not happen unless
// there is a bug in the JSON decoder or something is editing
// the data slice while the decoder executes.
@@ -295,11 +294,6 @@ func (d *decodeState) init(data []byte) *decodeState {
return d
}
-// error aborts the decoding by panicking with err.
-func (d *decodeState) error(err error) {
- panic(d.addErrorContext(err))
-}
-
// saveError saves the first err it is called with,
// for reporting at the end of the unmarshal.
func (d *decodeState) saveError(err error) {
@@ -321,95 +315,91 @@ func (d *decodeState) addErrorContext(err error) error {
return err
}
-// next cuts off and returns the next full JSON value in d.data[d.off:].
-// The next value is known to be an object or array, not a literal.
-func (d *decodeState) next() []byte {
- c := d.data[d.off]
- item, rest, err := nextValue(d.data[d.off:], &d.nextscan)
- if err != nil {
- d.error(err)
+// skip scans to the end of what was started.
+func (d *decodeState) skip() {
+ s, data, i := &d.scan, d.data, d.off
+ depth := len(s.parseState)
+ for {
+ op := s.step(s, data[i])
+ i++
+ if len(s.parseState) < depth {
+ d.off = i
+ d.opcode = op
+ return
+ }
}
- d.off = len(d.data) - len(rest)
+}
- // Our scanner has seen the opening brace/bracket
- // and thinks we're still in the middle of the object.
- // invent a closing brace/bracket to get it out.
- if c == '{' {
- d.scan.step(&d.scan, '}')
+// scanNext processes the byte at d.data[d.off].
+func (d *decodeState) scanNext() {
+ s, data, i := &d.scan, d.data, d.off
+ if i < len(data) {
+ d.opcode = s.step(s, data[i])
+ d.off = i + 1
} else {
- d.scan.step(&d.scan, ']')
+ d.opcode = s.eof()
+ d.off = len(data) + 1 // mark processed EOF with len+1
}
-
- return item
}
// scanWhile processes bytes in d.data[d.off:] until it
// receives a scan code not equal to op.
-// It updates d.off and returns the new scan code.
-func (d *decodeState) scanWhile(op int) int {
- var newOp int
- for {
- if d.off >= len(d.data) {
- newOp = d.scan.eof()
- d.off = len(d.data) + 1 // mark processed EOF with len+1
- } else {
- c := d.data[d.off]
- d.off++
- newOp = d.scan.step(&d.scan, c)
- }
+func (d *decodeState) scanWhile(op int) {
+ s, data, i := &d.scan, d.data, d.off
+ for i < len(d.data) {
+ newOp := s.step(s, data[i])
+ i++
if newOp != op {
- break
+ d.opcode = newOp
+ d.off = i
+ return
}
}
- return newOp
-}
-
-// value decodes a JSON value from d.data[d.off:] into the value.
-// it updates d.off to point past the decoded value.
-func (d *decodeState) value(v reflect.Value) {
- if !v.IsValid() {
- _, rest, err := nextValue(d.data[d.off:], &d.nextscan)
- if err != nil {
- d.error(err)
- }
- d.off = len(d.data) - len(rest)
- // d.scan thinks we're still at the beginning of the item.
- // 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 {
- // rewind.
- d.scan.redo = false
- d.scan.step = stateBeginValue
- }
- d.scan.step(&d.scan, '"')
- d.scan.step(&d.scan, '"')
-
- n := len(d.scan.parseState)
- if n > 0 && d.scan.parseState[n-1] == parseObjectKey {
- // d.scan thinks we just read an object key; finish the object
- d.scan.step(&d.scan, ':')
- d.scan.step(&d.scan, '"')
- d.scan.step(&d.scan, '"')
- d.scan.step(&d.scan, '}')
- }
-
- return
- }
+ d.off = len(d.data) + 1 // mark processed EOF with len+1
+ d.opcode = d.scan.eof()
+}
- switch op := d.scanWhile(scanSkipSpace); op {
+// value consumes a JSON value from d.data[d.off-1:], decoding into v, and
+// reads the following byte ahead. If v is invalid, the value is discarded.
+// The first byte of the value has been read already.
+func (d *decodeState) value(v reflect.Value) error {
+ switch d.opcode {
default:
- d.error(errPhase)
+ return errPhase
case scanBeginArray:
- d.array(v)
+ if v.IsValid() {
+ if err := d.array(v); err != nil {
+ return err
+ }
+ } else {
+ d.skip()
+ }
+ d.scanNext()
case scanBeginObject:
- d.object(v)
+ if v.IsValid() {
+ if err := d.object(v); err != nil {
+ return err
+ }
+ } else {
+ d.skip()
+ }
+ d.scanNext()
case scanBeginLiteral:
- d.literal(v)
+ // All bytes inside literal return scanContinue op code.
+ start := d.readIndex()
+ d.scanWhile(scanContinue)
+
+ if v.IsValid() {
+ if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil {
+ return err
+ }
+ }
}
+ return nil
}
type unquotedValue struct{}
@@ -418,31 +408,37 @@ type unquotedValue struct{}
// quoted string literal or literal null into an interface value.
// If it finds anything other than a quoted string literal or null,
// valueQuoted returns unquotedValue{}.
-func (d *decodeState) valueQuoted() interface{} {
- switch op := d.scanWhile(scanSkipSpace); op {
+func (d *decodeState) valueQuoted() (interface{}, error) {
+ switch d.opcode {
default:
- d.error(errPhase)
+ return nil, errPhase
case scanBeginArray:
- d.array(reflect.Value{})
+ d.skip()
+ d.scanNext()
case scanBeginObject:
- d.object(reflect.Value{})
+ d.skip()
+ d.scanNext()
case scanBeginLiteral:
- switch v := d.literalInterface().(type) {
+ v, err := d.literalInterface()
+ if err != nil {
+ return nil, err
+ }
+ switch v.(type) {
case nil, string:
- return v
+ return v, nil
}
}
- return unquotedValue{}
+ return unquotedValue{}, nil
}
// 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 decodingNull is true, indirect stops at the last pointer so it can be set to nil.
-func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
+func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
// Issue #24153 indicates that it is generally not a guaranteed property
// that you may round-trip a reflect.Value by calling Value.Addr().Elem()
// and expect the value to still be settable for values derived from
@@ -507,26 +503,21 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
return nil, nil, v
}
-// array consumes an array from d.data[d.off-1:], decoding into the value v.
-// the first byte of the array ('[') has been read already.
-func (d *decodeState) array(v reflect.Value) {
+// array consumes an array from d.data[d.off-1:], decoding into v.
+// The first byte of the array ('[') has been read already.
+func (d *decodeState) array(v reflect.Value) error {
// Check for unmarshaler.
- u, ut, pv := d.indirect(v, false)
+ u, ut, pv := indirect(v, false)
if u != nil {
- d.off--
- err := u.UnmarshalJSON(d.next())
- if err != nil {
- d.error(err)
- }
- return
+ start := d.readIndex()
+ d.skip()
+ return u.UnmarshalJSON(d.data[start:d.off])
}
if ut != nil {
d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
- d.off--
- d.next()
- return
+ d.skip()
+ return nil
}
-
v = pv
// Check type of target.
@@ -534,16 +525,19 @@ func (d *decodeState) array(v reflect.Value) {
case reflect.Interface:
if v.NumMethod() == 0 {
// Decoding into nil interface? Switch to non-reflect code.
- v.Set(reflect.ValueOf(d.arrayInterface()))
- return
+ ai, err := d.arrayInterface()
+ if err != nil {
+ return err
+ }
+ v.Set(reflect.ValueOf(ai))
+ return nil
}
// Otherwise it's invalid.
fallthrough
default:
d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
- d.off--
- d.next()
- return
+ d.skip()
+ return nil
case reflect.Array:
case reflect.Slice:
break
@@ -552,15 +546,11 @@ func (d *decodeState) array(v reflect.Value) {
i := 0
for {
// Look ahead for ] - can only happen on first iteration.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndArray {
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndArray {
break
}
- // Back up so d.value can have the byte we just read.
- d.off--
- d.scan.undo(op)
-
// Get element of array, growing if necessary.
if v.Kind() == reflect.Slice {
// Grow slice if necessary
@@ -580,20 +570,26 @@ func (d *decodeState) array(v reflect.Value) {
if i < v.Len() {
// Decode into element.
- d.value(v.Index(i))
+ if err := d.value(v.Index(i)); err != nil {
+ return err
+ }
} else {
// Ran out of fixed array: skip.
- d.value(reflect.Value{})
+ if err := d.value(reflect.Value{}); err != nil {
+ return err
+ }
}
i++
// Next token must be , or ].
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndArray {
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndArray {
break
}
- if op != scanArrayValue {
- d.error(errPhase)
+ if d.opcode != scanArrayValue {
+ return errPhase
}
}
@@ -611,36 +607,37 @@ func (d *decodeState) array(v reflect.Value) {
if i == 0 && v.Kind() == reflect.Slice {
v.Set(reflect.MakeSlice(v.Type(), 0, 0))
}
+ return nil
}
var nullLiteral = []byte("null")
var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
-// object consumes an object from d.data[d.off-1:], decoding into the value v.
-// the first byte ('{') of the object has been read already.
-func (d *decodeState) object(v reflect.Value) {
+// object consumes an object from d.data[d.off-1:], decoding into v.
+// The first byte ('{') of the object has been read already.
+func (d *decodeState) object(v reflect.Value) error {
// Check for unmarshaler.
- u, ut, pv := d.indirect(v, false)
+ u, ut, pv := indirect(v, false)
if u != nil {
- d.off--
- err := u.UnmarshalJSON(d.next())
- if err != nil {
- d.error(err)
- }
- return
+ start := d.readIndex()
+ d.skip()
+ return u.UnmarshalJSON(d.data[start:d.off])
}
if ut != nil {
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
+ d.skip()
+ return nil
}
v = pv
// Decoding into nil interface? Switch to non-reflect code.
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
- v.Set(reflect.ValueOf(d.objectInterface()))
- return
+ oi, err := d.objectInterface()
+ if err != nil {
+ return err
+ }
+ v.Set(reflect.ValueOf(oi))
+ return nil
}
// Check type of target:
@@ -659,9 +656,8 @@ func (d *decodeState) object(v reflect.Value) {
default:
if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
+ d.skip()
+ return nil
}
}
if v.IsNil() {
@@ -671,31 +667,30 @@ func (d *decodeState) object(v reflect.Value) {
// ok
default:
d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
+ d.skip()
+ return nil
}
var mapElem reflect.Value
for {
// Read opening " of string key or closing }.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndObject {
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndObject {
// closing } - can only happen on first iteration.
break
}
- if op != scanBeginLiteral {
- d.error(errPhase)
+ if d.opcode != scanBeginLiteral {
+ return errPhase
}
// Read key.
- start := d.off - 1
- op = d.scanWhile(scanContinue)
- item := d.data[start : d.off-1]
+ start := d.readIndex()
+ d.scanWhile(scanContinue)
+ item := d.data[start:d.readIndex()]
key, ok := unquoteBytes(item)
if !ok {
- d.error(errPhase)
+ return errPhase
}
// Figure out field corresponding to key.
@@ -756,24 +751,35 @@ func (d *decodeState) object(v reflect.Value) {
}
// Read : before value.
- if op == scanSkipSpace {
- op = d.scanWhile(scanSkipSpace)
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
}
- if op != scanObjectKey {
- d.error(errPhase)
+ if d.opcode != scanObjectKey {
+ return errPhase
}
+ d.scanWhile(scanSkipSpace)
if destring {
- switch qv := d.valueQuoted().(type) {
+ q, err := d.valueQuoted()
+ if err != nil {
+ return err
+ }
+ switch qv := q.(type) {
case nil:
- d.literalStore(nullLiteral, subv, false)
+ if err := d.literalStore(nullLiteral, subv, false); err != nil {
+ return err
+ }
case string:
- d.literalStore([]byte(qv), subv, true)
+ if err := d.literalStore([]byte(qv), subv, true); err != nil {
+ return err
+ }
default:
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
}
} else {
- d.value(subv)
+ if err := d.value(subv); err != nil {
+ return err
+ }
}
// Write value back to map;
@@ -786,7 +792,9 @@ func (d *decodeState) object(v reflect.Value) {
kv = reflect.ValueOf(key).Convert(kt)
case reflect.PtrTo(kt).Implements(textUnmarshalerType):
kv = reflect.New(v.Type().Key())
- d.literalStore(item, kv, true)
+ if err := d.literalStore(item, kv, true); err != nil {
+ return err
+ }
kv = kv.Elem()
default:
switch kt.Kind() {
@@ -795,7 +803,7 @@ func (d *decodeState) object(v reflect.Value) {
n, err := strconv.ParseInt(s, 10, 64)
if err != nil || reflect.Zero(kt).OverflowInt(n) {
d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
- return
+ return nil
}
kv = reflect.ValueOf(n).Convert(kt)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
@@ -803,7 +811,7 @@ func (d *decodeState) object(v reflect.Value) {
n, err := strconv.ParseUint(s, 10, 64)
if err != nil || reflect.Zero(kt).OverflowUint(n) {
d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
- return
+ return nil
}
kv = reflect.ValueOf(n).Convert(kt)
default:
@@ -814,32 +822,20 @@ func (d *decodeState) object(v reflect.Value) {
}
// Next token must be , or }.
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndObject {
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndObject {
break
}
- if op != scanObjectValue {
- d.error(errPhase)
+ if d.opcode != scanObjectValue {
+ return errPhase
}
d.errorContext.Struct = ""
d.errorContext.Field = ""
}
-}
-
-// literal consumes a literal from d.data[d.off-1:], decoding into the value v.
-// The first byte of the literal has been read already
-// (that's how the caller knows it's a literal).
-func (d *decodeState) literal(v reflect.Value) {
- // All bytes inside literal return scanContinue op code.
- start := d.off - 1
- op := d.scanWhile(scanContinue)
-
- // Scan read one byte too far; back up.
- d.off--
- d.scan.undo(op)
-
- d.literalStore(d.data[start:d.off], v, false)
+ return nil
}
// convertNumber converts the number literal s to a float64 or a Number
@@ -862,21 +858,17 @@ var numberType = reflect.TypeOf(Number(""))
// fromQuoted indicates whether this literal came from unwrapping a
// string from the ",string" struct tag option. this is used only to
// produce more helpful error messages.
-func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) {
+func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error {
// Check for unmarshaler.
if len(item) == 0 {
//Empty string given
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- return
+ return nil
}
isNull := item[0] == 'n' // null
- u, ut, pv := d.indirect(v, isNull)
+ u, ut, pv := indirect(v, isNull)
if u != nil {
- err := u.UnmarshalJSON(item)
- if err != nil {
- d.error(err)
- }
- return
+ return u.UnmarshalJSON(item)
}
if ut != nil {
if item[0] != '"' {
@@ -892,23 +884,18 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
default:
val = "number"
}
- d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
}
- return
+ return nil
}
s, ok := unquoteBytes(item)
if !ok {
if fromQuoted {
- d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.error(errPhase)
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
+ return errPhase
}
- err := ut.UnmarshalText(s)
- if err != nil {
- d.error(err)
- }
- return
+ return ut.UnmarshalText(s)
}
v = pv
@@ -939,7 +926,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())})
}
case reflect.Bool:
v.SetBool(value)
@@ -947,7 +934,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(value))
} else {
- d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())})
}
}
@@ -955,17 +942,16 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
s, ok := unquoteBytes(item)
if !ok {
if fromQuoted {
- d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.error(errPhase)
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
+ return errPhase
}
switch v.Kind() {
default:
- d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
case reflect.Slice:
if v.Type().Elem().Kind() != reflect.Uint8 {
- d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
break
}
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
@@ -981,17 +967,16 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(string(s)))
} else {
- d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
}
}
default: // number
if c != '-' && (c < '0' || c > '9') {
if fromQuoted {
- d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.error(errPhase)
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
+ return errPhase
}
s := string(item)
switch v.Kind() {
@@ -999,15 +984,14 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if v.Kind() == reflect.String && v.Type() == numberType {
v.SetString(s)
if !isValidNumber(s) {
- d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item))
+ return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)
}
break
}
if fromQuoted {
- d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.error(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)})
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
+ return &UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}
case reflect.Interface:
n, err := d.convertNumber(s)
if err != nil {
@@ -1015,7 +999,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
break
}
if v.NumMethod() != 0 {
- d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
break
}
v.Set(reflect.ValueOf(n))
@@ -1023,7 +1007,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(s, 10, 64)
if err != nil || v.OverflowInt(n) {
- d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
break
}
v.SetInt(n)
@@ -1031,7 +1015,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(s, 10, 64)
if err != nil || v.OverflowUint(n) {
- d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
break
}
v.SetUint(n)
@@ -1039,12 +1023,13 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(s, v.Type().Bits())
if err != nil || v.OverflowFloat(n) {
- d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
break
}
v.SetFloat(n)
}
}
+ return nil
}
// The xxxInterface routines build up a value to be stored
@@ -1052,128 +1037,138 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
// but they avoid the weight of reflection in this common case.
// valueInterface is like value but returns interface{}
-func (d *decodeState) valueInterface() interface{} {
- switch d.scanWhile(scanSkipSpace) {
+func (d *decodeState) valueInterface() (val interface{}, err error) {
+ switch d.opcode {
default:
- d.error(errPhase)
- panic("unreachable")
+ err = errPhase
case scanBeginArray:
- return d.arrayInterface()
+ val, err = d.arrayInterface()
+ d.scanNext()
case scanBeginObject:
- return d.objectInterface()
+ val, err = d.objectInterface()
+ d.scanNext()
case scanBeginLiteral:
- return d.literalInterface()
+ val, err = d.literalInterface()
}
+ return
}
// arrayInterface is like array but returns []interface{}.
-func (d *decodeState) arrayInterface() []interface{} {
+func (d *decodeState) arrayInterface() ([]interface{}, error) {
var v = make([]interface{}, 0)
for {
// Look ahead for ] - can only happen on first iteration.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndArray {
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndArray {
break
}
- // Back up so d.value can have the byte we just read.
- d.off--
- d.scan.undo(op)
-
- v = append(v, d.valueInterface())
+ vi, err := d.valueInterface()
+ if err != nil {
+ return nil, err
+ }
+ v = append(v, vi)
// Next token must be , or ].
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndArray {
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndArray {
break
}
- if op != scanArrayValue {
- d.error(errPhase)
+ if d.opcode != scanArrayValue {
+ return nil, errPhase
}
}
- return v
+ return v, nil
}
// objectInterface is like object but returns map[string]interface{}.
-func (d *decodeState) objectInterface() map[string]interface{} {
+func (d *decodeState) objectInterface() (map[string]interface{}, error) {
m := make(map[string]interface{})
for {
// Read opening " of string key or closing }.
- op := d.scanWhile(scanSkipSpace)
- if op == scanEndObject {
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndObject {
// closing } - can only happen on first iteration.
break
}
- if op != scanBeginLiteral {
- d.error(errPhase)
+ if d.opcode != scanBeginLiteral {
+ return nil, errPhase
}
// Read string key.
- start := d.off - 1
- op = d.scanWhile(scanContinue)
- item := d.data[start : d.off-1]
+ start := d.readIndex()
+ d.scanWhile(scanContinue)
+ item := d.data[start:d.readIndex()]
key, ok := unquote(item)
if !ok {
- d.error(errPhase)
+ return nil, errPhase
}
// Read : before value.
- if op == scanSkipSpace {
- op = d.scanWhile(scanSkipSpace)
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
}
- if op != scanObjectKey {
- d.error(errPhase)
+ if d.opcode != scanObjectKey {
+ return nil, errPhase
}
+ d.scanWhile(scanSkipSpace)
// Read value.
- m[key] = d.valueInterface()
+ vi, err := d.valueInterface()
+ if err != nil {
+ return nil, err
+ }
+ m[key] = vi
// Next token must be , or }.
- op = d.scanWhile(scanSkipSpace)
- if op == scanEndObject {
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndObject {
break
}
- if op != scanObjectValue {
- d.error(errPhase)
+ if d.opcode != scanObjectValue {
+ return nil, errPhase
}
}
- return m
+ return m, nil
}
-// literalInterface is like literal but returns an interface value.
-func (d *decodeState) literalInterface() interface{} {
+// literalInterface consumes and returns a literal from d.data[d.off-1:] and
+// it reads the following byte ahead. The first byte of the literal has been
+// read already (that's how the caller knows it's a literal).
+func (d *decodeState) literalInterface() (interface{}, error) {
// All bytes inside literal return scanContinue op code.
- start := d.off - 1
- op := d.scanWhile(scanContinue)
+ start := d.readIndex()
+ d.scanWhile(scanContinue)
- // Scan read one byte too far; back up.
- d.off--
- d.scan.undo(op)
- item := d.data[start:d.off]
+ item := d.data[start:d.readIndex()]
switch c := item[0]; c {
case 'n': // null
- return nil
+ return nil, nil
case 't', 'f': // true, false
- return c == 't'
+ return c == 't', nil
case '"': // string
s, ok := unquote(item)
if !ok {
- d.error(errPhase)
+ return nil, errPhase
}
- return s
+ return s, nil
default: // number
if c != '-' && (c < '0' || c > '9') {
- d.error(errPhase)
+ return nil, errPhase
}
n, err := d.convertNumber(string(item))
if err != nil {
d.saveError(err)
}
- return n
+ return n, nil
}
}