mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
rebased canonical/json off go 1.5.1
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
This commit is contained in:
parent
6563b7d2e8
commit
0d881349e8
7 changed files with 390 additions and 56 deletions
|
@ -44,7 +44,7 @@ clone git github.com/vbatts/tar-split v0.9.10
|
||||||
|
|
||||||
clone git github.com/docker/notary 089d8450d8928aa1c58fd03f09cabbde9bcb4590
|
clone git github.com/docker/notary 089d8450d8928aa1c58fd03f09cabbde9bcb4590
|
||||||
clone git github.com/endophage/gotuf 2df1c8e0a7b7e10ae2113bf37aaa1bf1c1de8cc5
|
clone git github.com/endophage/gotuf 2df1c8e0a7b7e10ae2113bf37aaa1bf1c1de8cc5
|
||||||
clone git github.com/jfrazelle/go 6e461eb70cb4187b41a84e9a567d7137bdbe0f16
|
clone git github.com/jfrazelle/go v1.5.1-1
|
||||||
clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
|
clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
|
||||||
|
|
||||||
clone git github.com/opencontainers/runc 6c198ae2d065c37f44316e0de3df7f3b88950923 # libcontainer
|
clone git github.com/opencontainers/runc 6c198ae2d065c37f44316e0de3df7f3b88950923 # libcontainer
|
||||||
|
|
27
vendor/src/github.com/jfrazelle/go/LICENSE
vendored
Normal file
27
vendor/src/github.com/jfrazelle/go/LICENSE
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -48,6 +48,13 @@ import (
|
||||||
// map[string]interface{}, for JSON objects
|
// map[string]interface{}, for JSON objects
|
||||||
// nil for JSON null
|
// nil for JSON null
|
||||||
//
|
//
|
||||||
|
// To unmarshal a JSON array into a slice, Unmarshal resets the slice to nil
|
||||||
|
// and then appends each element to the slice.
|
||||||
|
//
|
||||||
|
// To unmarshal a JSON object into a map, Unmarshal replaces the map
|
||||||
|
// with an empty map and then adds key-value pairs from the object to
|
||||||
|
// the map.
|
||||||
|
//
|
||||||
// If a JSON value is not appropriate for a given target type,
|
// If a JSON value is not appropriate for a given target type,
|
||||||
// or if a JSON number overflows the target type, Unmarshal
|
// or if a JSON number overflows the target type, Unmarshal
|
||||||
// skips that field and completes the unmarshalling as best it can.
|
// skips that field and completes the unmarshalling as best it can.
|
||||||
|
@ -90,8 +97,9 @@ type Unmarshaler interface {
|
||||||
// An UnmarshalTypeError describes a JSON value that was
|
// An UnmarshalTypeError describes a JSON value that was
|
||||||
// not appropriate for a value of a specific Go type.
|
// not appropriate for a value of a specific Go type.
|
||||||
type UnmarshalTypeError struct {
|
type UnmarshalTypeError struct {
|
||||||
Value string // description of JSON value - "bool", "array", "number -5"
|
Value string // description of JSON value - "bool", "array", "number -5"
|
||||||
Type reflect.Type // type of Go value it could not be assigned to
|
Type reflect.Type // type of Go value it could not be assigned to
|
||||||
|
Offset int64 // error occurred after reading Offset bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *UnmarshalTypeError) Error() string {
|
func (e *UnmarshalTypeError) Error() string {
|
||||||
|
@ -378,7 +386,7 @@ func (d *decodeState) array(v reflect.Value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ut != nil {
|
if ut != nil {
|
||||||
d.saveError(&UnmarshalTypeError{"array", v.Type()})
|
d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
|
||||||
d.off--
|
d.off--
|
||||||
d.next()
|
d.next()
|
||||||
return
|
return
|
||||||
|
@ -397,7 +405,7 @@ func (d *decodeState) array(v reflect.Value) {
|
||||||
// Otherwise it's invalid.
|
// Otherwise it's invalid.
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
d.saveError(&UnmarshalTypeError{"array", v.Type()})
|
d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
|
||||||
d.off--
|
d.off--
|
||||||
d.next()
|
d.next()
|
||||||
return
|
return
|
||||||
|
@ -486,7 +494,7 @@ func (d *decodeState) object(v reflect.Value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ut != nil {
|
if ut != nil {
|
||||||
d.saveError(&UnmarshalTypeError{"object", v.Type()})
|
d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
|
||||||
d.off--
|
d.off--
|
||||||
d.next() // skip over { } in input
|
d.next() // skip over { } in input
|
||||||
return
|
return
|
||||||
|
@ -505,7 +513,7 @@ func (d *decodeState) object(v reflect.Value) {
|
||||||
// map must have string kind
|
// map must have string kind
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
if t.Key().Kind() != reflect.String {
|
if t.Key().Kind() != reflect.String {
|
||||||
d.saveError(&UnmarshalTypeError{"object", v.Type()})
|
d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
|
||||||
d.off--
|
d.off--
|
||||||
d.next() // skip over { } in input
|
d.next() // skip over { } in input
|
||||||
return
|
return
|
||||||
|
@ -516,7 +524,7 @@ func (d *decodeState) object(v reflect.Value) {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
d.saveError(&UnmarshalTypeError{"object", v.Type()})
|
d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
|
||||||
d.off--
|
d.off--
|
||||||
d.next() // skip over { } in input
|
d.next() // skip over { } in input
|
||||||
return
|
return
|
||||||
|
@ -600,7 +608,7 @@ func (d *decodeState) object(v reflect.Value) {
|
||||||
case string:
|
case string:
|
||||||
d.literalStore([]byte(qv), subv, true)
|
d.literalStore([]byte(qv), subv, true)
|
||||||
default:
|
default:
|
||||||
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", item, v.Type()))
|
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
d.value(subv)
|
d.value(subv)
|
||||||
|
@ -647,7 +655,7 @@ func (d *decodeState) convertNumber(s string) (interface{}, error) {
|
||||||
}
|
}
|
||||||
f, err := strconv.ParseFloat(s, 64)
|
f, err := strconv.ParseFloat(s, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0)}
|
return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
|
||||||
}
|
}
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
@ -680,8 +688,9 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
if fromQuoted {
|
if fromQuoted {
|
||||||
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
||||||
} else {
|
} else {
|
||||||
d.saveError(&UnmarshalTypeError{"string", v.Type()})
|
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
s, ok := unquoteBytes(item)
|
s, ok := unquoteBytes(item)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -714,7 +723,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
if fromQuoted {
|
if fromQuoted {
|
||||||
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
||||||
} else {
|
} else {
|
||||||
d.saveError(&UnmarshalTypeError{"bool", v.Type()})
|
d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
|
||||||
}
|
}
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
v.SetBool(value)
|
v.SetBool(value)
|
||||||
|
@ -722,7 +731,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
if v.NumMethod() == 0 {
|
if v.NumMethod() == 0 {
|
||||||
v.Set(reflect.ValueOf(value))
|
v.Set(reflect.ValueOf(value))
|
||||||
} else {
|
} else {
|
||||||
d.saveError(&UnmarshalTypeError{"bool", v.Type()})
|
d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,10 +746,10 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
}
|
}
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
default:
|
default:
|
||||||
d.saveError(&UnmarshalTypeError{"string", v.Type()})
|
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
if v.Type() != byteSliceType {
|
if v.Type().Elem().Kind() != reflect.Uint8 {
|
||||||
d.saveError(&UnmarshalTypeError{"string", v.Type()})
|
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
||||||
|
@ -756,7 +765,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
if v.NumMethod() == 0 {
|
if v.NumMethod() == 0 {
|
||||||
v.Set(reflect.ValueOf(string(s)))
|
v.Set(reflect.ValueOf(string(s)))
|
||||||
} else {
|
} else {
|
||||||
d.saveError(&UnmarshalTypeError{"string", v.Type()})
|
d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,7 +787,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
if fromQuoted {
|
if fromQuoted {
|
||||||
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
|
||||||
} else {
|
} else {
|
||||||
d.error(&UnmarshalTypeError{"number", v.Type()})
|
d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
|
||||||
}
|
}
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
n, err := d.convertNumber(s)
|
n, err := d.convertNumber(s)
|
||||||
|
@ -787,7 +796,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if v.NumMethod() != 0 {
|
if v.NumMethod() != 0 {
|
||||||
d.saveError(&UnmarshalTypeError{"number", v.Type()})
|
d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.Set(reflect.ValueOf(n))
|
v.Set(reflect.ValueOf(n))
|
||||||
|
@ -795,7 +804,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
n, err := strconv.ParseInt(s, 10, 64)
|
n, err := strconv.ParseInt(s, 10, 64)
|
||||||
if err != nil || v.OverflowInt(n) {
|
if err != nil || v.OverflowInt(n) {
|
||||||
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
|
d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.SetInt(n)
|
v.SetInt(n)
|
||||||
|
@ -803,7 +812,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:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
n, err := strconv.ParseUint(s, 10, 64)
|
n, err := strconv.ParseUint(s, 10, 64)
|
||||||
if err != nil || v.OverflowUint(n) {
|
if err != nil || v.OverflowUint(n) {
|
||||||
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
|
d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.SetUint(n)
|
v.SetUint(n)
|
||||||
|
@ -811,7 +820,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
n, err := strconv.ParseFloat(s, v.Type().Bits())
|
n, err := strconv.ParseFloat(s, v.Type().Bits())
|
||||||
if err != nil || v.OverflowFloat(n) {
|
if err != nil || v.OverflowFloat(n) {
|
||||||
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
|
d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.SetFloat(n)
|
v.SetFloat(n)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
// in the documentation for the Marshal and Unmarshal functions.
|
// in the documentation for the Marshal and Unmarshal functions.
|
||||||
//
|
//
|
||||||
// See "JSON and Go" for an introduction to this package:
|
// See "JSON and Go" for an introduction to this package:
|
||||||
// http://golang.org/doc/articles/json_and_go.html
|
// https://golang.org/doc/articles/json_and_go.html
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -79,8 +79,8 @@ import (
|
||||||
//
|
//
|
||||||
// The "string" option signals that a field is stored as JSON inside a
|
// The "string" option signals that a field is stored as JSON inside a
|
||||||
// JSON-encoded string. It applies only to fields of string, floating point,
|
// JSON-encoded string. It applies only to fields of string, floating point,
|
||||||
// or integer types. This extra level of encoding is sometimes used when
|
// integer, or boolean types. This extra level of encoding is sometimes used
|
||||||
// communicating with JavaScript programs:
|
// when communicating with JavaScript programs:
|
||||||
//
|
//
|
||||||
// Int64String int64 `json:",string"`
|
// Int64String int64 `json:",string"`
|
||||||
//
|
//
|
||||||
|
@ -113,8 +113,8 @@ import (
|
||||||
// a JSON tag of "-".
|
// a JSON tag of "-".
|
||||||
//
|
//
|
||||||
// Map values encode as JSON objects.
|
// Map values encode as JSON objects.
|
||||||
// The map's key type must be string; the object keys are used directly
|
// The map's key type must be string; the map keys are used as JSON object
|
||||||
// as map keys.
|
// keys, subject to the UTF-8 coercion described for string values above.
|
||||||
//
|
//
|
||||||
// Pointer values encode as the value pointed to.
|
// Pointer values encode as the value pointed to.
|
||||||
// A nil pointer encodes as the null JSON object.
|
// A nil pointer encodes as the null JSON object.
|
||||||
|
@ -287,8 +287,6 @@ func (e *encodeState) error(err error) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var byteSliceType = reflect.TypeOf([]byte(nil))
|
|
||||||
|
|
||||||
func isEmptyValue(v reflect.Value) bool {
|
func isEmptyValue(v reflect.Value) bool {
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||||
|
@ -1075,6 +1073,19 @@ func typeFields(t reflect.Type) []field {
|
||||||
ft = ft.Elem()
|
ft = ft.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only strings, floats, integers, and booleans can be quoted.
|
||||||
|
quoted := false
|
||||||
|
if opts.Contains("string") {
|
||||||
|
switch ft.Kind() {
|
||||||
|
case reflect.Bool,
|
||||||
|
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||||
|
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||||
|
reflect.Float32, reflect.Float64,
|
||||||
|
reflect.String:
|
||||||
|
quoted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Record found field and index sequence.
|
// Record found field and index sequence.
|
||||||
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||||
tagged := name != ""
|
tagged := name != ""
|
||||||
|
@ -1087,7 +1098,7 @@ func typeFields(t reflect.Type) []field {
|
||||||
index: index,
|
index: index,
|
||||||
typ: ft,
|
typ: ft,
|
||||||
omitEmpty: opts.Contains("omitempty"),
|
omitEmpty: opts.Contains("omitempty"),
|
||||||
quoted: opts.Contains("string"),
|
quoted: quoted,
|
||||||
}))
|
}))
|
||||||
if count[f.typ] > 1 {
|
if count[f.typ] > 1 {
|
||||||
// If there were multiple instances, add a second,
|
// If there were multiple instances, add a second,
|
||||||
|
|
|
@ -26,7 +26,7 @@ const (
|
||||||
// The letters S and K are special because they map to 3 runes, not just 2:
|
// The letters S and K are special because they map to 3 runes, not just 2:
|
||||||
// * S maps to s and to U+017F 'ſ' Latin small letter long s
|
// * S maps to s and to U+017F 'ſ' Latin small letter long s
|
||||||
// * k maps to K and to U+212A 'K' Kelvin sign
|
// * k maps to K and to U+212A 'K' Kelvin sign
|
||||||
// See http://play.golang.org/p/tTxjOc0OGo
|
// See https://play.golang.org/p/tTxjOc0OGo
|
||||||
//
|
//
|
||||||
// The returned function is specialized for matching against s and
|
// The returned function is specialized for matching against s and
|
||||||
// should only be given s. It's not curried for performance reasons.
|
// should only be given s. It's not curried for performance reasons.
|
||||||
|
|
|
@ -38,8 +38,15 @@ func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) {
|
||||||
scan.reset()
|
scan.reset()
|
||||||
for i, c := range data {
|
for i, c := range data {
|
||||||
v := scan.step(scan, int(c))
|
v := scan.step(scan, int(c))
|
||||||
if v >= scanEnd {
|
if v >= scanEndObject {
|
||||||
switch v {
|
switch v {
|
||||||
|
// probe the scanner with a space to determine whether we will
|
||||||
|
// get scanEnd on the next character. Otherwise, if the next character
|
||||||
|
// is not a space, scanEndTop allocates a needless error.
|
||||||
|
case scanEndObject, scanEndArray:
|
||||||
|
if scan.step(scan, ' ') == scanEnd {
|
||||||
|
return data[:i+1], data[i+1:], nil
|
||||||
|
}
|
||||||
case scanError:
|
case scanError:
|
||||||
return nil, nil, scan.err
|
return nil, nil, scan.err
|
||||||
case scanEnd:
|
case scanEnd:
|
||||||
|
|
|
@ -12,11 +12,15 @@ import (
|
||||||
|
|
||||||
// A Decoder reads and decodes JSON objects from an input stream.
|
// A Decoder reads and decodes JSON objects from an input stream.
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
r io.Reader
|
r io.Reader
|
||||||
buf []byte
|
buf []byte
|
||||||
d decodeState
|
d decodeState
|
||||||
scan scanner
|
scanp int // start of unread data in buf
|
||||||
err error
|
scan scanner
|
||||||
|
err error
|
||||||
|
|
||||||
|
tokenState int
|
||||||
|
tokenStack []int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDecoder returns a new decoder that reads from r.
|
// NewDecoder returns a new decoder that reads from r.
|
||||||
|
@ -41,20 +45,29 @@ func (dec *Decoder) Decode(v interface{}) error {
|
||||||
return dec.err
|
return dec.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := dec.tokenPrepareForDecode(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !dec.tokenValueAllowed() {
|
||||||
|
return &SyntaxError{msg: "not at beginning of value"}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read whole value into buffer.
|
||||||
n, err := dec.readValue()
|
n, err := dec.readValue()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
|
||||||
|
dec.scanp += n
|
||||||
|
|
||||||
// Don't save err from unmarshal into dec.err:
|
// Don't save err from unmarshal into dec.err:
|
||||||
// the connection is still usable since we read a complete JSON
|
// the connection is still usable since we read a complete JSON
|
||||||
// object from it before the error happened.
|
// object from it before the error happened.
|
||||||
dec.d.init(dec.buf[0:n])
|
|
||||||
err = dec.d.unmarshal(v)
|
err = dec.d.unmarshal(v)
|
||||||
|
|
||||||
// Slide rest of data down.
|
// fixup token streaming state
|
||||||
rest := copy(dec.buf, dec.buf[n:])
|
dec.tokenValueEnd()
|
||||||
dec.buf = dec.buf[0:rest]
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -62,7 +75,7 @@ func (dec *Decoder) Decode(v interface{}) error {
|
||||||
// Buffered returns a reader of the data remaining in the Decoder's
|
// Buffered returns a reader of the data remaining in the Decoder's
|
||||||
// buffer. The reader is valid until the next call to Decode.
|
// buffer. The reader is valid until the next call to Decode.
|
||||||
func (dec *Decoder) Buffered() io.Reader {
|
func (dec *Decoder) Buffered() io.Reader {
|
||||||
return bytes.NewReader(dec.buf)
|
return bytes.NewReader(dec.buf[dec.scanp:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// readValue reads a JSON value into dec.buf.
|
// readValue reads a JSON value into dec.buf.
|
||||||
|
@ -70,7 +83,7 @@ func (dec *Decoder) Buffered() io.Reader {
|
||||||
func (dec *Decoder) readValue() (int, error) {
|
func (dec *Decoder) readValue() (int, error) {
|
||||||
dec.scan.reset()
|
dec.scan.reset()
|
||||||
|
|
||||||
scanp := 0
|
scanp := dec.scanp
|
||||||
var err error
|
var err error
|
||||||
Input:
|
Input:
|
||||||
for {
|
for {
|
||||||
|
@ -111,20 +124,35 @@ Input:
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make room to read more into the buffer.
|
n := scanp - dec.scanp
|
||||||
const minRead = 512
|
err = dec.refill()
|
||||||
if cap(dec.buf)-len(dec.buf) < minRead {
|
scanp = dec.scanp + n
|
||||||
newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
|
|
||||||
copy(newBuf, dec.buf)
|
|
||||||
dec.buf = newBuf
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read. Delay error for next iteration (after scan).
|
|
||||||
var n int
|
|
||||||
n, err = dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
|
|
||||||
dec.buf = dec.buf[0 : len(dec.buf)+n]
|
|
||||||
}
|
}
|
||||||
return scanp, nil
|
return scanp - dec.scanp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *Decoder) refill() error {
|
||||||
|
// Make room to read more into the buffer.
|
||||||
|
// First slide down data already consumed.
|
||||||
|
if dec.scanp > 0 {
|
||||||
|
n := copy(dec.buf, dec.buf[dec.scanp:])
|
||||||
|
dec.buf = dec.buf[:n]
|
||||||
|
dec.scanp = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grow buffer if not large enough.
|
||||||
|
const minRead = 512
|
||||||
|
if cap(dec.buf)-len(dec.buf) < minRead {
|
||||||
|
newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
|
||||||
|
copy(newBuf, dec.buf)
|
||||||
|
dec.buf = newBuf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read. Delay error for next iteration (after scan).
|
||||||
|
n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
|
||||||
|
dec.buf = dec.buf[0 : len(dec.buf)+n]
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func nonSpace(b []byte) bool {
|
func nonSpace(b []byte) bool {
|
||||||
|
@ -205,3 +233,255 @@ func (m *RawMessage) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
var _ Marshaler = (*RawMessage)(nil)
|
var _ Marshaler = (*RawMessage)(nil)
|
||||||
var _ Unmarshaler = (*RawMessage)(nil)
|
var _ Unmarshaler = (*RawMessage)(nil)
|
||||||
|
|
||||||
|
// A Token holds a value of one of these types:
|
||||||
|
//
|
||||||
|
// Delim, for the four JSON delimiters [ ] { }
|
||||||
|
// bool, for JSON booleans
|
||||||
|
// float64, for JSON numbers
|
||||||
|
// Number, for JSON numbers
|
||||||
|
// string, for JSON string literals
|
||||||
|
// nil, for JSON null
|
||||||
|
//
|
||||||
|
type Token interface{}
|
||||||
|
|
||||||
|
const (
|
||||||
|
tokenTopValue = iota
|
||||||
|
tokenArrayStart
|
||||||
|
tokenArrayValue
|
||||||
|
tokenArrayComma
|
||||||
|
tokenObjectStart
|
||||||
|
tokenObjectKey
|
||||||
|
tokenObjectColon
|
||||||
|
tokenObjectValue
|
||||||
|
tokenObjectComma
|
||||||
|
)
|
||||||
|
|
||||||
|
// advance tokenstate from a separator state to a value state
|
||||||
|
func (dec *Decoder) tokenPrepareForDecode() error {
|
||||||
|
// Note: Not calling peek before switch, to avoid
|
||||||
|
// putting peek into the standard Decode path.
|
||||||
|
// peek is only called when using the Token API.
|
||||||
|
switch dec.tokenState {
|
||||||
|
case tokenArrayComma:
|
||||||
|
c, err := dec.peek()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c != ',' {
|
||||||
|
return &SyntaxError{"expected comma after array element", 0}
|
||||||
|
}
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenState = tokenArrayValue
|
||||||
|
case tokenObjectColon:
|
||||||
|
c, err := dec.peek()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c != ':' {
|
||||||
|
return &SyntaxError{"expected colon after object key", 0}
|
||||||
|
}
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenState = tokenObjectValue
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *Decoder) tokenValueAllowed() bool {
|
||||||
|
switch dec.tokenState {
|
||||||
|
case tokenTopValue, tokenArrayStart, tokenArrayValue, tokenObjectValue:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *Decoder) tokenValueEnd() {
|
||||||
|
switch dec.tokenState {
|
||||||
|
case tokenArrayStart, tokenArrayValue:
|
||||||
|
dec.tokenState = tokenArrayComma
|
||||||
|
case tokenObjectValue:
|
||||||
|
dec.tokenState = tokenObjectComma
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Delim is a JSON array or object delimiter, one of [ ] { or }.
|
||||||
|
type Delim rune
|
||||||
|
|
||||||
|
func (d Delim) String() string {
|
||||||
|
return string(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Token returns the next JSON token in the input stream.
|
||||||
|
// At the end of the input stream, Token returns nil, io.EOF.
|
||||||
|
//
|
||||||
|
// Token guarantees that the delimiters [ ] { } it returns are
|
||||||
|
// properly nested and matched: if Token encounters an unexpected
|
||||||
|
// delimiter in the input, it will return an error.
|
||||||
|
//
|
||||||
|
// The input stream consists of basic JSON values—bool, string,
|
||||||
|
// number, and null—along with delimiters [ ] { } of type Delim
|
||||||
|
// to mark the start and end of arrays and objects.
|
||||||
|
// Commas and colons are elided.
|
||||||
|
func (dec *Decoder) Token() (Token, error) {
|
||||||
|
for {
|
||||||
|
c, err := dec.peek()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch c {
|
||||||
|
case '[':
|
||||||
|
if !dec.tokenValueAllowed() {
|
||||||
|
return dec.tokenError(c)
|
||||||
|
}
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenStack = append(dec.tokenStack, dec.tokenState)
|
||||||
|
dec.tokenState = tokenArrayStart
|
||||||
|
return Delim('['), nil
|
||||||
|
|
||||||
|
case ']':
|
||||||
|
if dec.tokenState != tokenArrayStart && dec.tokenState != tokenArrayComma {
|
||||||
|
return dec.tokenError(c)
|
||||||
|
}
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
|
||||||
|
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
|
||||||
|
dec.tokenValueEnd()
|
||||||
|
return Delim(']'), nil
|
||||||
|
|
||||||
|
case '{':
|
||||||
|
if !dec.tokenValueAllowed() {
|
||||||
|
return dec.tokenError(c)
|
||||||
|
}
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenStack = append(dec.tokenStack, dec.tokenState)
|
||||||
|
dec.tokenState = tokenObjectStart
|
||||||
|
return Delim('{'), nil
|
||||||
|
|
||||||
|
case '}':
|
||||||
|
if dec.tokenState != tokenObjectStart && dec.tokenState != tokenObjectComma {
|
||||||
|
return dec.tokenError(c)
|
||||||
|
}
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
|
||||||
|
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
|
||||||
|
dec.tokenValueEnd()
|
||||||
|
return Delim('}'), nil
|
||||||
|
|
||||||
|
case ':':
|
||||||
|
if dec.tokenState != tokenObjectColon {
|
||||||
|
return dec.tokenError(c)
|
||||||
|
}
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenState = tokenObjectValue
|
||||||
|
continue
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
if dec.tokenState == tokenArrayComma {
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenState = tokenArrayValue
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if dec.tokenState == tokenObjectComma {
|
||||||
|
dec.scanp++
|
||||||
|
dec.tokenState = tokenObjectKey
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return dec.tokenError(c)
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
if dec.tokenState == tokenObjectStart || dec.tokenState == tokenObjectKey {
|
||||||
|
var x string
|
||||||
|
old := dec.tokenState
|
||||||
|
dec.tokenState = tokenTopValue
|
||||||
|
err := dec.Decode(&x)
|
||||||
|
dec.tokenState = old
|
||||||
|
if err != nil {
|
||||||
|
clearOffset(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dec.tokenState = tokenObjectColon
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
|
||||||
|
default:
|
||||||
|
if !dec.tokenValueAllowed() {
|
||||||
|
return dec.tokenError(c)
|
||||||
|
}
|
||||||
|
var x interface{}
|
||||||
|
if err := dec.Decode(&x); err != nil {
|
||||||
|
clearOffset(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearOffset(err error) {
|
||||||
|
if s, ok := err.(*SyntaxError); ok {
|
||||||
|
s.Offset = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *Decoder) tokenError(c byte) (Token, error) {
|
||||||
|
var context string
|
||||||
|
switch dec.tokenState {
|
||||||
|
case tokenTopValue:
|
||||||
|
context = " looking for beginning of value"
|
||||||
|
case tokenArrayStart, tokenArrayValue, tokenObjectValue:
|
||||||
|
context = " looking for beginning of value"
|
||||||
|
case tokenArrayComma:
|
||||||
|
context = " after array element"
|
||||||
|
case tokenObjectKey:
|
||||||
|
context = " looking for beginning of object key string"
|
||||||
|
case tokenObjectColon:
|
||||||
|
context = " after object key"
|
||||||
|
case tokenObjectComma:
|
||||||
|
context = " after object key:value pair"
|
||||||
|
}
|
||||||
|
return nil, &SyntaxError{"invalid character " + quoteChar(int(c)) + " " + context, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// More reports whether there is another element in the
|
||||||
|
// current array or object being parsed.
|
||||||
|
func (dec *Decoder) More() bool {
|
||||||
|
c, err := dec.peek()
|
||||||
|
return err == nil && c != ']' && c != '}'
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *Decoder) peek() (byte, error) {
|
||||||
|
var err error
|
||||||
|
for {
|
||||||
|
for i := dec.scanp; i < len(dec.buf); i++ {
|
||||||
|
c := dec.buf[i]
|
||||||
|
if isSpace(rune(c)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dec.scanp = i
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
// buffer has been scanned, now report any error
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
err = dec.refill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO
|
||||||
|
|
||||||
|
// EncodeToken writes the given JSON token to the stream.
|
||||||
|
// It returns an error if the delimiters [ ] { } are not properly used.
|
||||||
|
//
|
||||||
|
// EncodeToken does not call Flush, because usually it is part of
|
||||||
|
// a larger operation such as Encode, and those will call Flush when finished.
|
||||||
|
// Callers that create an Encoder and then invoke EncodeToken directly,
|
||||||
|
// without using Encode, need to call Flush when finished to ensure that
|
||||||
|
// the JSON is written to the underlying writer.
|
||||||
|
func (e *Encoder) EncodeToken(t Token) error {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue