package json
import (
)
type Decoder struct {
r io.Reader
buf []byte
d decodeState
scanp int
scanned int64
scan scanner
err error
tokenState int
tokenStack []int
}
func ( io.Reader) *Decoder {
return &Decoder{r: }
}
func ( *Decoder) () { .d.useNumber = true }
func ( *Decoder) () { .d.disallowUnknownFields = true }
func ( *Decoder) ( interface{}) error {
if .err != nil {
return .err
}
if := .tokenPrepareForDecode(); != nil {
return
}
if !.tokenValueAllowed() {
return &SyntaxError{msg: "not at beginning of value", Offset: .InputOffset()}
}
, := .readValue()
if != nil {
return
}
.d.init(.buf[.scanp : .scanp+])
.scanp +=
= .d.unmarshal()
.tokenValueEnd()
return
}
func ( *Decoder) () io.Reader {
return bytes.NewReader(.buf[.scanp:])
}
func ( *Decoder) () (int, error) {
.scan.reset()
:= .scanp
var error
:
for >= 0 {
for ; < len(.buf); ++ {
:= .buf[]
.scan.bytes++
switch .scan.step(&.scan, ) {
case scanEnd:
.scan.bytes--
break
case scanEndObject, scanEndArray:
if stateEndValue(&.scan, ' ') == scanEnd {
++
break
}
case scanError:
.err = .scan.err
return 0, .scan.err
}
}
if != nil {
if == io.EOF {
if .scan.step(&.scan, ' ') == scanEnd {
break
}
if nonSpace(.buf) {
= io.ErrUnexpectedEOF
}
}
.err =
return 0,
}
:= - .scanp
= .refill()
= .scanp +
}
return - .scanp, nil
}
func ( *Decoder) () error {
if .scanp > 0 {
.scanned += int64(.scanp)
:= copy(.buf, .buf[.scanp:])
.buf = .buf[:]
.scanp = 0
}
const = 512
if cap(.buf)-len(.buf) < {
:= make([]byte, len(.buf), 2*cap(.buf)+)
copy(, .buf)
.buf =
}
, := .r.Read(.buf[len(.buf):cap(.buf)])
.buf = .buf[0 : len(.buf)+]
return
}
func ( []byte) bool {
for , := range {
if !isSpace() {
return true
}
}
return false
}
type Encoder struct {
w io.Writer
err error
escapeHTML bool
indentBuf *bytes.Buffer
indentPrefix string
indentValue string
}
func ( io.Writer) *Encoder {
return &Encoder{w: , escapeHTML: true}
}
func ( *Encoder) ( interface{}) error {
if .err != nil {
return .err
}
:= newEncodeState()
:= .marshal(, encOpts{escapeHTML: .escapeHTML})
if != nil {
return
}
.WriteByte('\n')
:= .Bytes()
if .indentPrefix != "" || .indentValue != "" {
if .indentBuf == nil {
.indentBuf = new(bytes.Buffer)
}
.indentBuf.Reset()
= Indent(.indentBuf, , .indentPrefix, .indentValue)
if != nil {
return
}
= .indentBuf.Bytes()
}
if _, = .w.Write(); != nil {
.err =
}
encodeStatePool.Put()
return
}
func ( *Encoder) (, string) {
.indentPrefix =
.indentValue =
}
func ( *Encoder) ( bool) {
.escapeHTML =
}
type RawMessage []byte
func ( RawMessage) () ([]byte, error) {
if == nil {
return []byte("null"), nil
}
return , nil
}
func ( *RawMessage) ( []byte) error {
if == nil {
return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
}
* = append((*)[0:0], ...)
return nil
}
var _ Marshaler = (*RawMessage)(nil)
var _ Unmarshaler = (*RawMessage)(nil)
type Token interface{}
const (
tokenTopValue = iota
tokenArrayStart
tokenArrayValue
tokenArrayComma
tokenObjectStart
tokenObjectKey
tokenObjectColon
tokenObjectValue
tokenObjectComma
)
func ( *Decoder) () error {
switch .tokenState {
case tokenArrayComma:
, := .peek()
if != nil {
return
}
if != ',' {
return &SyntaxError{"expected comma after array element", .InputOffset()}
}
.scanp++
.tokenState = tokenArrayValue
case tokenObjectColon:
, := .peek()
if != nil {
return
}
if != ':' {
return &SyntaxError{"expected colon after object key", .InputOffset()}
}
.scanp++
.tokenState = tokenObjectValue
}
return nil
}
func ( *Decoder) () bool {
switch .tokenState {
case tokenTopValue, tokenArrayStart, tokenArrayValue, tokenObjectValue:
return true
}
return false
}
func ( *Decoder) () {
switch .tokenState {
case tokenArrayStart, tokenArrayValue:
.tokenState = tokenArrayComma
case tokenObjectValue:
.tokenState = tokenObjectComma
}
}
type Delim rune
func ( Delim) () string {
return string()
}
func ( *Decoder) () (Token, error) {
for {
, := .peek()
if != nil {
return nil,
}
switch {
case '[':
if !.tokenValueAllowed() {
return .tokenError()
}
.scanp++
.tokenStack = append(.tokenStack, .tokenState)
.tokenState = tokenArrayStart
return Delim('['), nil
case ']':
if .tokenState != tokenArrayStart && .tokenState != tokenArrayComma {
return .tokenError()
}
.scanp++
.tokenState = .tokenStack[len(.tokenStack)-1]
.tokenStack = .tokenStack[:len(.tokenStack)-1]
.tokenValueEnd()
return Delim(']'), nil
case '{':
if !.tokenValueAllowed() {
return .tokenError()
}
.scanp++
.tokenStack = append(.tokenStack, .tokenState)
.tokenState = tokenObjectStart
return Delim('{'), nil
case '}':
if .tokenState != tokenObjectStart && .tokenState != tokenObjectComma {
return .tokenError()
}
.scanp++
.tokenState = .tokenStack[len(.tokenStack)-1]
.tokenStack = .tokenStack[:len(.tokenStack)-1]
.tokenValueEnd()
return Delim('}'), nil
case ':':
if .tokenState != tokenObjectColon {
return .tokenError()
}
.scanp++
.tokenState = tokenObjectValue
continue
case ',':
if .tokenState == tokenArrayComma {
.scanp++
.tokenState = tokenArrayValue
continue
}
if .tokenState == tokenObjectComma {
.scanp++
.tokenState = tokenObjectKey
continue
}
return .tokenError()
case '"':
if .tokenState == tokenObjectStart || .tokenState == tokenObjectKey {
var string
:= .tokenState
.tokenState = tokenTopValue
:= .Decode(&)
.tokenState =
if != nil {
return nil,
}
.tokenState = tokenObjectColon
return , nil
}
fallthrough
default:
if !.tokenValueAllowed() {
return .tokenError()
}
var interface{}
if := .Decode(&); != nil {
return nil,
}
return , nil
}
}
}
func ( *Decoder) ( byte) (Token, error) {
var string
switch .tokenState {
case tokenTopValue:
= " looking for beginning of value"
case tokenArrayStart, tokenArrayValue, tokenObjectValue:
= " looking for beginning of value"
case tokenArrayComma:
= " after array element"
case tokenObjectKey:
= " looking for beginning of object key string"
case tokenObjectColon:
= " after object key"
case tokenObjectComma:
= " after object key:value pair"
}
return nil, &SyntaxError{"invalid character " + quoteChar() + , .InputOffset()}
}
func ( *Decoder) () bool {
, := .peek()
return == nil && != ']' && != '}'
}
func ( *Decoder) () (byte, error) {
var error
for {
for := .scanp; < len(.buf); ++ {
:= .buf[]
if isSpace() {
continue
}
.scanp =
return , nil
}
if != nil {
return 0,
}
= .refill()
}
}
func ( *Decoder) () int64 {
return .scanned + int64(.scanp)
}