diff options
Diffstat (limited to 'libgo/go/encoding/json/decode.go')
-rw-r--r-- | libgo/go/encoding/json/decode.go | 549 |
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 } } |