go-json/decode.go

263 lines
5.2 KiB
Go
Raw Permalink Normal View History

2020-04-22 07:06:52 +03:00
package json
import (
2020-05-08 14:22:57 +03:00
"encoding"
2020-04-22 07:06:52 +03:00
"io"
"reflect"
2020-07-30 16:41:53 +03:00
"strconv"
2020-04-22 07:06:52 +03:00
"sync"
"unsafe"
)
type Delim rune
2020-05-24 15:31:10 +03:00
func (d Delim) String() string {
return string(d)
}
2020-04-23 19:39:20 +03:00
type decoder interface {
2020-05-23 06:51:09 +03:00
decode([]byte, int64, uintptr) (int64, error)
2020-07-30 16:41:53 +03:00
decodeStream(*stream, uintptr) error
2020-04-23 19:39:20 +03:00
}
2020-04-22 07:06:52 +03:00
type Decoder struct {
2020-05-24 15:31:10 +03:00
s *stream
2020-04-22 07:06:52 +03:00
}
2020-04-28 12:35:08 +03:00
type decoderMap struct {
sync.Map
}
2020-05-06 16:22:13 +03:00
func (m *decoderMap) get(k uintptr) decoder {
2020-04-28 12:35:08 +03:00
if v, ok := m.Load(k); ok {
return v.(decoder)
}
return nil
}
2020-05-06 16:22:13 +03:00
func (m *decoderMap) set(k uintptr, dec decoder) {
2020-04-28 12:35:08 +03:00
m.Store(k, dec)
}
2020-04-22 07:06:52 +03:00
var (
2020-05-08 14:22:57 +03:00
cachedDecoder decoderMap
unmarshalJSONType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
2020-04-22 07:06:52 +03:00
)
func init() {
2020-04-28 12:35:08 +03:00
cachedDecoder = decoderMap{}
2020-04-22 07:06:52 +03:00
}
2020-07-31 11:10:03 +03:00
const (
nul = '\000'
)
2020-04-25 13:55:05 +03:00
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may
// read data from r beyond the JSON values requested.
2020-04-22 07:06:52 +03:00
func NewDecoder(r io.Reader) *Decoder {
2020-07-30 16:41:53 +03:00
s := &stream{r: r}
s.read()
return &Decoder{s: s}
2020-04-22 07:06:52 +03:00
}
2020-04-25 13:55:05 +03:00
// Buffered returns a reader of the data remaining in the Decoder's
// buffer. The reader is valid until the next call to Decode.
2020-04-22 07:06:52 +03:00
func (d *Decoder) Buffered() io.Reader {
2020-05-24 15:31:10 +03:00
return d.s.buffered()
2020-04-22 07:06:52 +03:00
}
func (d *Decoder) validateType(typ *rtype, p uintptr) error {
if typ.Kind() != reflect.Ptr || p == 0 {
return &InvalidUnmarshalError{Type: rtype2type(typ)}
}
return nil
}
2020-04-24 15:57:11 +03:00
func (d *Decoder) decode(src []byte, header *interfaceHeader) error {
2020-04-24 14:23:26 +03:00
typ := header.typ
2020-05-06 16:22:13 +03:00
typeptr := uintptr(unsafe.Pointer(typ))
// noescape trick for header.typ ( reflect.*rtype )
copiedType := (*rtype)(unsafe.Pointer(typeptr))
ptr := uintptr(header.ptr)
if err := d.validateType(copiedType, ptr); err != nil {
return err
}
2020-05-06 16:22:13 +03:00
dec := cachedDecoder.get(typeptr)
2020-04-28 12:35:08 +03:00
if dec == nil {
2020-05-08 17:59:49 +03:00
compiledDec, err := d.compileHead(copiedType)
2020-04-22 07:06:52 +03:00
if err != nil {
return err
}
2020-05-06 16:22:13 +03:00
cachedDecoder.set(typeptr, compiledDec)
2020-04-23 19:39:20 +03:00
dec = compiledDec
2020-04-22 07:06:52 +03:00
}
2020-05-06 20:37:29 +03:00
if _, err := dec.decode(src, 0, ptr); err != nil {
2020-04-22 07:06:52 +03:00
return err
}
return nil
}
2020-04-24 15:57:11 +03:00
func (d *Decoder) decodeForUnmarshal(src []byte, v interface{}) error {
header := (*interfaceHeader)(unsafe.Pointer(&v))
header.typ.escape()
return d.decode(src, header)
}
func (d *Decoder) decodeForUnmarshalNoEscape(src []byte, v interface{}) error {
header := (*interfaceHeader)(unsafe.Pointer(&v))
return d.decode(src, header)
}
2020-05-24 15:31:10 +03:00
func (d *Decoder) prepareForDecode() error {
s := d.s
2020-07-30 16:41:53 +03:00
for {
2020-05-24 15:31:10 +03:00
switch s.char() {
case ' ', '\t', '\r', '\n':
2020-07-31 11:10:03 +03:00
s.cursor++
2020-05-24 15:31:10 +03:00
continue
case ',', ':':
2020-07-31 11:10:03 +03:00
s.cursor++
2020-05-24 15:31:10 +03:00
return nil
2020-07-31 11:10:03 +03:00
case nul:
if s.read() {
continue
}
return io.EOF
2020-05-24 15:31:10 +03:00
}
break
}
return nil
}
2020-04-25 13:55:05 +03:00
// Decode reads the next JSON-encoded value from its
// input and stores it in the value pointed to by v.
//
// See the documentation for Unmarshal for details about
// the conversion of JSON into a Go value.
2020-04-22 07:06:52 +03:00
func (d *Decoder) Decode(v interface{}) error {
2020-04-24 14:23:26 +03:00
header := (*interfaceHeader)(unsafe.Pointer(&v))
typ := header.typ
ptr := uintptr(header.ptr)
2020-05-06 16:22:13 +03:00
typeptr := uintptr(unsafe.Pointer(typ))
// noescape trick for header.typ ( reflect.*rtype )
copiedType := (*rtype)(unsafe.Pointer(typeptr))
if err := d.validateType(copiedType, ptr); err != nil {
return err
}
2020-05-06 16:22:13 +03:00
dec := cachedDecoder.get(typeptr)
2020-04-28 12:35:08 +03:00
if dec == nil {
2020-05-08 14:22:57 +03:00
compiledDec, err := d.compileHead(typ)
2020-04-22 07:06:52 +03:00
if err != nil {
return err
}
2020-05-06 16:22:13 +03:00
cachedDecoder.set(typeptr, compiledDec)
2020-04-23 19:39:20 +03:00
dec = compiledDec
2020-04-22 07:06:52 +03:00
}
2020-05-24 15:31:10 +03:00
if err := d.prepareForDecode(); err != nil {
return err
2020-04-25 16:48:16 +03:00
}
2020-05-24 15:31:10 +03:00
s := d.s
2020-07-30 16:41:53 +03:00
if err := dec.decodeStream(s, ptr); err != nil {
2020-05-24 15:31:10 +03:00
return err
2020-04-25 16:48:16 +03:00
}
2020-05-24 15:31:10 +03:00
return nil
2020-04-22 07:06:52 +03:00
}
2020-05-24 15:31:10 +03:00
func (d *Decoder) More() bool {
s := d.s
2020-07-30 16:41:53 +03:00
for {
2020-05-24 15:31:10 +03:00
switch s.char() {
case ' ', '\n', '\r', '\t':
2020-07-31 11:10:03 +03:00
s.cursor++
continue
case '}', ']':
return false
case nul:
if s.read() {
2020-07-30 16:41:53 +03:00
continue
}
2020-05-24 15:31:10 +03:00
return false
}
break
2020-04-22 07:06:52 +03:00
}
2020-05-24 15:31:10 +03:00
return true
2020-04-22 07:06:52 +03:00
}
2020-05-24 15:31:10 +03:00
func (d *Decoder) Token() (Token, error) {
s := d.s
2020-07-30 16:41:53 +03:00
for {
c := s.char()
switch c {
2020-05-24 15:31:10 +03:00
case ' ', '\n', '\r', '\t':
2020-07-31 11:10:03 +03:00
s.cursor++
2020-07-30 16:41:53 +03:00
case '{', '[', ']', '}':
2020-07-31 11:10:03 +03:00
s.cursor++
2020-07-30 16:41:53 +03:00
return Delim(c), nil
case ',', ':':
2020-07-31 11:10:03 +03:00
s.cursor++
2020-05-24 15:31:10 +03:00
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
2020-07-30 16:41:53 +03:00
bytes := floatBytes(s)
s := *(*string)(unsafe.Pointer(&bytes))
f64, err := strconv.ParseFloat(s, 64)
if err != nil {
return nil, err
}
return f64, nil
2020-05-24 15:31:10 +03:00
case '"':
2020-07-30 16:41:53 +03:00
bytes, err := stringBytes(s)
if err != nil {
return nil, err
}
return string(bytes), nil
2020-05-24 15:31:10 +03:00
case 't':
2020-07-30 16:41:53 +03:00
if err := trueBytes(s); err != nil {
return nil, err
}
return true, nil
2020-05-24 15:31:10 +03:00
case 'f':
2020-07-30 16:41:53 +03:00
if err := falseBytes(s); err != nil {
return nil, err
}
return false, nil
2020-05-24 15:31:10 +03:00
case 'n':
2020-07-30 16:41:53 +03:00
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
2020-07-31 11:10:03 +03:00
case nul:
if s.read() {
continue
}
2020-07-30 16:41:53 +03:00
return nil, io.EOF
2020-05-24 15:31:10 +03:00
default:
return nil, errInvalidCharacter(s.char(), "token", s.totalOffset())
2020-04-22 07:06:52 +03:00
}
}
2020-05-24 15:31:10 +03:00
return nil, io.EOF
2020-04-22 07:06:52 +03:00
}
2020-04-25 13:55:05 +03:00
// DisallowUnknownFields causes the Decoder to return an error when the destination
// is a struct and the input contains object keys which do not match any
// non-ignored, exported fields in the destination.
2020-04-22 07:06:52 +03:00
func (d *Decoder) DisallowUnknownFields() {
}
func (d *Decoder) InputOffset() int64 {
2020-07-31 14:31:14 +03:00
return d.s.totalOffset()
2020-04-22 07:06:52 +03:00
}
2020-04-25 13:55:05 +03:00
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
// Number instead of as a float64.
2020-04-22 07:06:52 +03:00
func (d *Decoder) UseNumber() {
}