package jsontext
import (
"bytes"
"errors"
"io"
"encoding/json/internal/jsonflags"
"encoding/json/internal/jsonopts"
"encoding/json/internal/jsonwire"
)
type Decoder struct {
s decoderState
}
type decoderState struct {
state
decodeBuffer
jsonopts .Struct
StringCache *[256 ]string
}
type decodeBuffer struct {
peekPos int
peekErr error
buf []byte
prevStart int
prevEnd int
baseOffset int64
rd io .Reader
}
func NewDecoder (r io .Reader , opts ...Options ) *Decoder {
d := new (Decoder )
d .Reset (r , opts ...)
return d
}
func (d *Decoder ) Reset (r io .Reader , opts ...Options ) {
switch {
case d == nil :
panic ("jsontext: invalid nil Decoder" )
case r == nil :
panic ("jsontext: invalid nil io.Reader" )
case d .s .Flags .Get (jsonflags .WithinArshalCall ):
panic ("jsontext: cannot reset Decoder passed to json.UnmarshalerFrom" )
}
d .s .reset (nil , r , opts ...)
}
func (d *decoderState ) reset (b []byte , r io .Reader , opts ...Options ) {
d .state .reset ()
d .decodeBuffer = decodeBuffer {buf : b , rd : r }
opts2 := jsonopts .Struct {}
opts2 .Join (opts ...)
d .Struct = opts2
}
func (d *Decoder ) Options () Options {
return &d .s .Struct
}
var errBufferWriteAfterNext = errors .New ("invalid bytes.Buffer.Write call after calling bytes.Buffer.Next" )
func (d *decoderState ) fetch () error {
if d .rd == nil {
return io .ErrUnexpectedEOF
}
d .Names .copyQuotedBuffer (d .buf )
if bb , ok := d .rd .(*bytes .Buffer ); ok {
switch {
case bb .Len () == 0 :
return io .ErrUnexpectedEOF
case len (d .buf ) == 0 :
d .buf = bb .Next (bb .Len ())
return nil
default :
return &ioError {action : "read" , err : errBufferWriteAfterNext }
}
}
if cap (d .buf ) == 0 {
d .buf = make ([]byte , 0 , 64 )
}
const maxBufferSize = 4 << 10
const growthSizeFactor = 2
const growthRateFactor = 2
grow := cap (d .buf ) <= maxBufferSize /growthSizeFactor
grow = grow && int64 (cap (d .buf )) < d .previousOffsetEnd ()/growthRateFactor
grow = grow || (d .prevStart == 0 && len (d .buf ) >= 3 *cap (d .buf )/4 )
if grow {
buf := make ([]byte , 0 , cap (d .buf )*growthSizeFactor )
d .buf = append (buf , d .buf [d .prevStart :]...)
} else {
n := copy (d .buf [:cap (d .buf )], d .buf [d .prevStart :])
d .buf = d .buf [:n ]
}
d .baseOffset += int64 (d .prevStart )
d .prevEnd -= d .prevStart
d .prevStart = 0
for {
n , err := d .rd .Read (d .buf [len (d .buf ):cap (d .buf )])
switch {
case n > 0 :
d .buf = d .buf [:len (d .buf )+n ]
return nil
case err == io .EOF :
return io .ErrUnexpectedEOF
case err != nil :
return &ioError {action : "read" , err : err }
default :
continue
}
}
}
const invalidateBufferByte = '#'
func (d *decodeBuffer ) invalidatePreviousRead () {
isBytesBuffer := func (r io .Reader ) bool {
_ , ok := r .(*bytes .Buffer )
return ok
}
if d .rd != nil && !isBytesBuffer (d .rd ) && d .prevStart < d .prevEnd && uint (d .prevStart ) < uint (len (d .buf )) {
d .buf [d .prevStart ] = invalidateBufferByte
d .prevStart = d .prevEnd
}
}
func (d *decodeBuffer ) needMore (pos int ) bool {
return pos == len (d .buf )
}
func (d *decodeBuffer ) offsetAt (pos int ) int64 { return d .baseOffset + int64 (pos ) }
func (d *decodeBuffer ) previousOffsetStart () int64 { return d .baseOffset + int64 (d .prevStart ) }
func (d *decodeBuffer ) previousOffsetEnd () int64 { return d .baseOffset + int64 (d .prevEnd ) }
func (d *decodeBuffer ) previousBuffer () []byte { return d .buf [d .prevStart :d .prevEnd ] }
func (d *decodeBuffer ) unreadBuffer () []byte { return d .buf [d .prevEnd :len (d .buf )] }
func (d *decodeBuffer ) PreviousTokenOrValue () []byte {
b := d .previousBuffer ()
if d .peekPos > 0 || len (b ) > 0 && b [0 ] == invalidateBufferByte {
return nil
}
if len (b ) == 0 {
b = d .buf [:d .prevEnd ]
for _ , tok := range []string {"null" , "false" , "true" , "{" , "}" , "[" , "]" } {
if len (b ) >= len (tok ) && string (b [len (b )-len (tok ):]) == tok {
return b [len (b )-len (tok ):]
}
}
}
return b
}
func (d *Decoder ) PeekKind () Kind {
return d .s .PeekKind ()
}
func (d *decoderState ) PeekKind () Kind {
if d .peekPos > 0 {
return Kind (d .buf [d .peekPos ]).normalize ()
}
var err error
d .invalidatePreviousRead ()
pos := d .prevEnd
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
if err == io .ErrUnexpectedEOF && d .Tokens .Depth () == 1 {
err = io .EOF
}
d .peekPos , d .peekErr = -1 , wrapSyntacticError (d , err , pos , 0 )
return invalidKind
}
}
var delim byte
if c := d .buf [pos ]; c == ':' || c == ',' {
delim = c
pos += 1
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
err = wrapSyntacticError (d , err , pos , 0 )
d .peekPos , d .peekErr = -1 , d .checkDelimBeforeIOError (delim , err )
return invalidKind
}
}
}
next := Kind (d .buf [pos ]).normalize ()
if d .Tokens .needDelim (next ) != delim {
d .peekPos , d .peekErr = -1 , d .checkDelim (delim , next )
return invalidKind
}
d .peekPos , d .peekErr = pos , nil
return next
}
func (d *decoderState ) checkDelimBeforeIOError (delim byte , err error ) error {
const next = Kind ('"' )
if d .Tokens .needDelim (next ) != delim {
err = d .checkDelim (delim , next )
}
return err
}
func (d *decoderState ) CountNextDelimWhitespace () int {
d .PeekKind ()
return len (d .unreadBuffer ()) - len (bytes .TrimLeft (d .unreadBuffer (), ",: \n\r\t" ))
}
func (d *decoderState ) checkDelim (delim byte , next Kind ) error {
where := "at start of value"
switch d .Tokens .needDelim (next ) {
case delim :
return nil
case ':' :
where = "after object name (expecting ':')"
case ',' :
if d .Tokens .Last .isObject () {
where = "after object value (expecting ',' or '}')"
} else {
where = "after array element (expecting ',' or ']')"
}
}
pos := d .prevEnd
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
err := jsonwire .NewInvalidCharacterError (d .buf [pos :], where )
return wrapSyntacticError (d , err , pos , 0 )
}
func (d *Decoder ) SkipValue () error {
return d .s .SkipValue ()
}
func (d *decoderState ) SkipValue () error {
switch d .PeekKind () {
case '{' , '[' :
depth := d .Tokens .Depth ()
for {
if _ , err := d .ReadToken (); err != nil {
return err
}
if depth >= d .Tokens .Depth () {
return nil
}
}
default :
var flags jsonwire .ValueFlags
if _ , err := d .ReadValue (&flags ); err != nil {
return err
}
return nil
}
}
func (d *decoderState ) SkipValueRemainder () error {
if d .Tokens .Depth ()-1 > 0 && d .Tokens .Last .Length () == 0 {
for n := d .Tokens .Depth (); d .Tokens .Depth () >= n ; {
if _ , err := d .ReadToken (); err != nil {
return err
}
}
}
return nil
}
func (d *decoderState ) SkipUntil (depth int , length int64 ) error {
for d .Tokens .Depth () > depth || (d .Tokens .Depth () == depth && d .Tokens .Last .Length () < length ) {
if _ , err := d .ReadToken (); err != nil {
return err
}
}
return nil
}
func (d *Decoder ) ReadToken () (Token , error ) {
return d .s .ReadToken ()
}
func (d *decoderState ) ReadToken () (Token , error ) {
var err error
var next Kind
pos := d .peekPos
if pos != 0 {
if d .peekErr != nil {
err := d .peekErr
d .peekPos , d .peekErr = 0 , nil
return Token {}, err
}
next = Kind (d .buf [pos ]).normalize ()
d .peekPos = 0
} else {
d .invalidatePreviousRead ()
pos = d .prevEnd
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
if err == io .ErrUnexpectedEOF && d .Tokens .Depth () == 1 {
err = io .EOF
}
return Token {}, wrapSyntacticError (d , err , pos , 0 )
}
}
var delim byte
if c := d .buf [pos ]; c == ':' || c == ',' {
delim = c
pos += 1
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
err = wrapSyntacticError (d , err , pos , 0 )
return Token {}, d .checkDelimBeforeIOError (delim , err )
}
}
}
next = Kind (d .buf [pos ]).normalize ()
if d .Tokens .needDelim (next ) != delim {
return Token {}, d .checkDelim (delim , next )
}
}
var n int
switch next {
case 'n' :
if jsonwire .ConsumeNull (d .buf [pos :]) == 0 {
pos , err = d .consumeLiteral (pos , "null" )
if err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
} else {
pos += len ("null" )
}
if err = d .Tokens .appendLiteral (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos -len ("null" ), +1 )
}
d .prevStart , d .prevEnd = pos , pos
return Null , nil
case 'f' :
if jsonwire .ConsumeFalse (d .buf [pos :]) == 0 {
pos , err = d .consumeLiteral (pos , "false" )
if err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
} else {
pos += len ("false" )
}
if err = d .Tokens .appendLiteral (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos -len ("false" ), +1 )
}
d .prevStart , d .prevEnd = pos , pos
return False , nil
case 't' :
if jsonwire .ConsumeTrue (d .buf [pos :]) == 0 {
pos , err = d .consumeLiteral (pos , "true" )
if err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
} else {
pos += len ("true" )
}
if err = d .Tokens .appendLiteral (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos -len ("true" ), +1 )
}
d .prevStart , d .prevEnd = pos , pos
return True , nil
case '"' :
var flags jsonwire .ValueFlags
if n = jsonwire .ConsumeSimpleString (d .buf [pos :]); n == 0 {
oldAbsPos := d .baseOffset + int64 (pos )
pos , err = d .consumeString (&flags , pos )
newAbsPos := d .baseOffset + int64 (pos )
n = int (newAbsPos - oldAbsPos )
if err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
} else {
pos += n
}
if d .Tokens .Last .NeedObjectName () {
if !d .Flags .Get (jsonflags .AllowDuplicateNames ) {
if !d .Tokens .Last .isValidNamespace () {
return Token {}, wrapSyntacticError (d , errInvalidNamespace , pos -n , +1 )
}
if d .Tokens .Last .isActiveNamespace () && !d .Namespaces .Last ().insertQuoted (d .buf [pos -n :pos ], flags .IsVerbatim ()) {
err = wrapWithObjectName (ErrDuplicateName , d .buf [pos -n :pos ])
return Token {}, wrapSyntacticError (d , err , pos -n , +1 )
}
}
d .Names .ReplaceLastQuotedOffset (pos - n )
}
if err = d .Tokens .appendString (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos -n , +1 )
}
d .prevStart , d .prevEnd = pos -n , pos
return Token {raw : &d .decodeBuffer , num : uint64 (d .previousOffsetStart ())}, nil
case '0' :
if n = jsonwire .ConsumeSimpleNumber (d .buf [pos :]); n == 0 || d .needMore (pos +n ) {
oldAbsPos := d .baseOffset + int64 (pos )
pos , err = d .consumeNumber (pos )
newAbsPos := d .baseOffset + int64 (pos )
n = int (newAbsPos - oldAbsPos )
if err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
} else {
pos += n
}
if err = d .Tokens .appendNumber (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos -n , +1 )
}
d .prevStart , d .prevEnd = pos -n , pos
return Token {raw : &d .decodeBuffer , num : uint64 (d .previousOffsetStart ())}, nil
case '{' :
if err = d .Tokens .pushObject (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
d .Names .push ()
if !d .Flags .Get (jsonflags .AllowDuplicateNames ) {
d .Namespaces .push ()
}
pos += 1
d .prevStart , d .prevEnd = pos , pos
return BeginObject , nil
case '}' :
if err = d .Tokens .popObject (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
d .Names .pop ()
if !d .Flags .Get (jsonflags .AllowDuplicateNames ) {
d .Namespaces .pop ()
}
pos += 1
d .prevStart , d .prevEnd = pos , pos
return EndObject , nil
case '[' :
if err = d .Tokens .pushArray (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
pos += 1
d .prevStart , d .prevEnd = pos , pos
return BeginArray , nil
case ']' :
if err = d .Tokens .popArray (); err != nil {
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
pos += 1
d .prevStart , d .prevEnd = pos , pos
return EndArray , nil
default :
err = jsonwire .NewInvalidCharacterError (d .buf [pos :], "at start of value" )
return Token {}, wrapSyntacticError (d , err , pos , +1 )
}
}
func (d *Decoder ) ReadValue () (Value , error ) {
var flags jsonwire .ValueFlags
return d .s .ReadValue (&flags )
}
func (d *decoderState ) ReadValue (flags *jsonwire .ValueFlags ) (Value , error ) {
var err error
var next Kind
pos := d .peekPos
if pos != 0 {
if d .peekErr != nil {
err := d .peekErr
d .peekPos , d .peekErr = 0 , nil
return nil , err
}
next = Kind (d .buf [pos ]).normalize ()
d .peekPos = 0
} else {
d .invalidatePreviousRead ()
pos = d .prevEnd
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
if err == io .ErrUnexpectedEOF && d .Tokens .Depth () == 1 {
err = io .EOF
}
return nil , wrapSyntacticError (d , err , pos , 0 )
}
}
var delim byte
if c := d .buf [pos ]; c == ':' || c == ',' {
delim = c
pos += 1
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
err = wrapSyntacticError (d , err , pos , 0 )
return nil , d .checkDelimBeforeIOError (delim , err )
}
}
}
next = Kind (d .buf [pos ]).normalize ()
if d .Tokens .needDelim (next ) != delim {
return nil , d .checkDelim (delim , next )
}
}
oldAbsPos := d .baseOffset + int64 (pos )
pos , err = d .consumeValue (flags , pos , d .Tokens .Depth ())
newAbsPos := d .baseOffset + int64 (pos )
n := int (newAbsPos - oldAbsPos )
if err != nil {
return nil , wrapSyntacticError (d , err , pos , +1 )
}
switch next {
case 'n' , 't' , 'f' :
err = d .Tokens .appendLiteral ()
case '"' :
if d .Tokens .Last .NeedObjectName () {
if !d .Flags .Get (jsonflags .AllowDuplicateNames ) {
if !d .Tokens .Last .isValidNamespace () {
err = errInvalidNamespace
break
}
if d .Tokens .Last .isActiveNamespace () && !d .Namespaces .Last ().insertQuoted (d .buf [pos -n :pos ], flags .IsVerbatim ()) {
err = wrapWithObjectName (ErrDuplicateName , d .buf [pos -n :pos ])
break
}
}
d .Names .ReplaceLastQuotedOffset (pos - n )
}
err = d .Tokens .appendString ()
case '0' :
err = d .Tokens .appendNumber ()
case '{' :
if err = d .Tokens .pushObject (); err != nil {
break
}
if err = d .Tokens .popObject (); err != nil {
panic ("BUG: popObject should never fail immediately after pushObject: " + err .Error())
}
case '[' :
if err = d .Tokens .pushArray (); err != nil {
break
}
if err = d .Tokens .popArray (); err != nil {
panic ("BUG: popArray should never fail immediately after pushArray: " + err .Error())
}
}
if err != nil {
return nil , wrapSyntacticError (d , err , pos -n , +1 )
}
d .prevEnd = pos
d .prevStart = pos - n
return d .buf [pos -n : pos : pos ], nil
}
func (d *decoderState ) CheckNextValue () error {
d .PeekKind ()
pos , err := d .peekPos , d .peekErr
d .peekPos , d .peekErr = 0 , nil
if err != nil {
return err
}
var flags jsonwire .ValueFlags
if pos , err := d .consumeValue (&flags , pos , d .Tokens .Depth ()); err != nil {
return wrapSyntacticError (d , err , pos , +1 )
}
return nil
}
func (d *decoderState ) CheckEOF () error {
switch pos , err := d .consumeWhitespace (d .prevEnd ); err {
case nil :
err := jsonwire .NewInvalidCharacterError (d .buf [pos :], "after top-level value" )
return wrapSyntacticError (d , err , pos , 0 )
case io .ErrUnexpectedEOF :
return nil
default :
return err
}
}
func (d *decoderState ) consumeWhitespace (pos int ) (newPos int , err error ) {
for {
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
absPos := d .baseOffset + int64 (pos )
err = d .fetch ()
pos = int (absPos - d .baseOffset )
if err != nil {
return pos , err
}
continue
}
return pos , nil
}
}
func (d *decoderState ) consumeValue (flags *jsonwire .ValueFlags , pos , depth int ) (newPos int , err error ) {
for {
var n int
var err error
switch next := Kind (d .buf [pos ]).normalize (); next {
case 'n' :
if n = jsonwire .ConsumeNull (d .buf [pos :]); n == 0 {
n , err = jsonwire .ConsumeLiteral (d .buf [pos :], "null" )
}
case 'f' :
if n = jsonwire .ConsumeFalse (d .buf [pos :]); n == 0 {
n , err = jsonwire .ConsumeLiteral (d .buf [pos :], "false" )
}
case 't' :
if n = jsonwire .ConsumeTrue (d .buf [pos :]); n == 0 {
n , err = jsonwire .ConsumeLiteral (d .buf [pos :], "true" )
}
case '"' :
if n = jsonwire .ConsumeSimpleString (d .buf [pos :]); n == 0 {
return d .consumeString (flags , pos )
}
case '0' :
if n = jsonwire .ConsumeSimpleNumber (d .buf [pos :]); n == 0 || d .needMore (pos +n ) {
return d .consumeNumber (pos )
}
case '{' :
return d .consumeObject (flags , pos , depth )
case '[' :
return d .consumeArray (flags , pos , depth )
default :
if (d .Tokens .Last .isObject () && next == ']' ) || (d .Tokens .Last .isArray () && next == '}' ) {
return pos , errMismatchDelim
}
return pos , jsonwire .NewInvalidCharacterError (d .buf [pos :], "at start of value" )
}
if err == io .ErrUnexpectedEOF {
absPos := d .baseOffset + int64 (pos )
err = d .fetch ()
pos = int (absPos - d .baseOffset )
if err != nil {
return pos + n , err
}
continue
}
return pos + n , err
}
}
func (d *decoderState ) consumeLiteral (pos int , lit string ) (newPos int , err error ) {
for {
n , err := jsonwire .ConsumeLiteral (d .buf [pos :], lit )
if err == io .ErrUnexpectedEOF {
absPos := d .baseOffset + int64 (pos )
err = d .fetch ()
pos = int (absPos - d .baseOffset )
if err != nil {
return pos + n , err
}
continue
}
return pos + n , err
}
}
func (d *decoderState ) consumeString (flags *jsonwire .ValueFlags , pos int ) (newPos int , err error ) {
var n int
for {
n , err = jsonwire .ConsumeStringResumable (flags , d .buf [pos :], n , !d .Flags .Get (jsonflags .AllowInvalidUTF8 ))
if err == io .ErrUnexpectedEOF {
absPos := d .baseOffset + int64 (pos )
err = d .fetch ()
pos = int (absPos - d .baseOffset )
if err != nil {
return pos + n , err
}
continue
}
return pos + n , err
}
}
func (d *decoderState ) consumeNumber (pos int ) (newPos int , err error ) {
var n int
var state jsonwire .ConsumeNumberState
for {
n , state , err = jsonwire .ConsumeNumberResumable (d .buf [pos :], n , state )
if err == io .ErrUnexpectedEOF || d .needMore (pos +n ) {
mayTerminate := err == nil
absPos := d .baseOffset + int64 (pos )
err = d .fetch ()
pos = int (absPos - d .baseOffset )
if err != nil {
if mayTerminate && err == io .ErrUnexpectedEOF {
return pos + n , nil
}
return pos , err
}
continue
}
return pos + n , err
}
}
func (d *decoderState ) consumeObject (flags *jsonwire .ValueFlags , pos , depth int ) (newPos int , err error ) {
var n int
var names *objectNamespace
if !d .Flags .Get (jsonflags .AllowDuplicateNames ) {
d .Namespaces .push ()
defer d .Namespaces .pop ()
names = d .Namespaces .Last ()
}
if uint (pos ) >= uint (len (d .buf )) || d .buf [pos ] != '{' {
panic ("BUG: consumeObject must be called with a buffer that starts with '{'" )
} else if depth == maxNestingDepth +1 {
return pos , errMaxDepth
}
pos ++
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
return pos , err
}
}
if d .buf [pos ] == '}' {
pos ++
return pos , nil
}
depth ++
for {
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
return pos , err
}
}
var flags2 jsonwire .ValueFlags
if n = jsonwire .ConsumeSimpleString (d .buf [pos :]); n == 0 {
oldAbsPos := d .baseOffset + int64 (pos )
pos , err = d .consumeString (&flags2 , pos )
newAbsPos := d .baseOffset + int64 (pos )
n = int (newAbsPos - oldAbsPos )
flags .Join (flags2 )
if err != nil {
return pos , err
}
} else {
pos += n
}
quotedName := d .buf [pos -n : pos ]
if !d .Flags .Get (jsonflags .AllowDuplicateNames ) && !names .insertQuoted (quotedName , flags2 .IsVerbatim ()) {
return pos - n , wrapWithObjectName (ErrDuplicateName , quotedName )
}
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
return pos , wrapWithObjectName (err , quotedName )
}
}
if d .buf [pos ] != ':' {
err := jsonwire .NewInvalidCharacterError (d .buf [pos :], "after object name (expecting ':')" )
return pos , wrapWithObjectName (err , quotedName )
}
pos ++
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
return pos , wrapWithObjectName (err , quotedName )
}
}
pos , err = d .consumeValue (flags , pos , depth )
if err != nil {
return pos , wrapWithObjectName (err , quotedName )
}
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
return pos , err
}
}
switch d .buf [pos ] {
case ',' :
pos ++
continue
case '}' :
pos ++
return pos , nil
default :
return pos , jsonwire .NewInvalidCharacterError (d .buf [pos :], "after object value (expecting ',' or '}')" )
}
}
}
func (d *decoderState ) consumeArray (flags *jsonwire .ValueFlags , pos , depth int ) (newPos int , err error ) {
if uint (pos ) >= uint (len (d .buf )) || d .buf [pos ] != '[' {
panic ("BUG: consumeArray must be called with a buffer that starts with '['" )
} else if depth == maxNestingDepth +1 {
return pos , errMaxDepth
}
pos ++
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
return pos , err
}
}
if d .buf [pos ] == ']' {
pos ++
return pos , nil
}
var idx int64
depth ++
for {
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
return pos , err
}
}
pos , err = d .consumeValue (flags , pos , depth )
if err != nil {
return pos , wrapWithArrayIndex (err , idx )
}
pos += jsonwire .ConsumeWhitespace (d .buf [pos :])
if d .needMore (pos ) {
if pos , err = d .consumeWhitespace (pos ); err != nil {
return pos , err
}
}
switch d .buf [pos ] {
case ',' :
pos ++
idx ++
continue
case ']' :
pos ++
return pos , nil
default :
return pos , jsonwire .NewInvalidCharacterError (d .buf [pos :], "after array element (expecting ',' or ']')" )
}
}
}
func (d *Decoder ) InputOffset () int64 {
return d .s .previousOffsetEnd ()
}
func (d *Decoder ) UnreadBuffer () []byte {
return d .s .unreadBuffer ()
}
func (d *Decoder ) StackDepth () int {
return d .s .Tokens .Depth () - 1
}
func (d *Decoder ) StackIndex (i int ) (Kind , int64 ) {
switch s := d .s .Tokens .index (i ); {
case i > 0 && s .isObject ():
return '{' , s .Length ()
case i > 0 && s .isArray ():
return '[' , s .Length ()
default :
return 0 , s .Length ()
}
}
func (d *Decoder ) StackPointer () Pointer {
return Pointer (d .s .AppendStackPointer (nil , -1 ))
}
func (d *decoderState ) AppendStackPointer (b []byte , where int ) []byte {
d .Names .copyQuotedBuffer (d .buf )
return d .state .appendStackPointer (b , where )
}
The pages are generated with Golds v0.7.7-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .