package decoder
import (
"fmt"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type arrayDecoder struct {
elemType *runtime .Type
size uintptr
valueDecoder Decoder
alen int
structName string
fieldName string
zeroValue unsafe .Pointer
}
func newArrayDecoder(dec Decoder , elemType *runtime .Type , alen int , structName , fieldName string ) *arrayDecoder {
zeroValuePtr := unsafe_New (elemType )
zeroValue := **(**unsafe .Pointer )(unsafe .Pointer (&zeroValuePtr ))
return &arrayDecoder {
valueDecoder : dec ,
elemType : elemType ,
size : elemType .Size (),
alen : alen ,
structName : structName ,
fieldName : fieldName ,
zeroValue : zeroValue ,
}
}
func (d *arrayDecoder ) DecodeStream (s *Stream , depth int64 , p unsafe .Pointer ) error {
depth ++
if depth > maxDecodeNestingDepth {
return errors .ErrExceededMaxDepth (s .char (), s .cursor )
}
for {
switch s .char () {
case ' ' , '\n' , '\t' , '\r' :
case 'n' :
if err := nullBytes (s ); err != nil {
return err
}
return nil
case '[' :
idx := 0
s .cursor ++
if s .skipWhiteSpace () == ']' {
for idx < d .alen {
*(*unsafe .Pointer )(unsafe .Pointer (uintptr (p ) + uintptr (idx )*d .size )) = d .zeroValue
idx ++
}
s .cursor ++
return nil
}
for {
if idx < d .alen {
if err := d .valueDecoder .DecodeStream (s , depth , unsafe .Pointer (uintptr (p )+uintptr (idx )*d .size )); err != nil {
return err
}
} else {
if err := s .skipValue (depth ); err != nil {
return err
}
}
idx ++
switch s .skipWhiteSpace () {
case ']' :
for idx < d .alen {
*(*unsafe .Pointer )(unsafe .Pointer (uintptr (p ) + uintptr (idx )*d .size )) = d .zeroValue
idx ++
}
s .cursor ++
return nil
case ',' :
s .cursor ++
continue
case nul :
if s .read () {
s .cursor ++
continue
}
goto ERROR
default :
goto ERROR
}
}
case nul :
if s .read () {
continue
}
goto ERROR
default :
goto ERROR
}
s .cursor ++
}
ERROR :
return errors .ErrUnexpectedEndOfJSON ("array" , s .totalOffset ())
}
func (d *arrayDecoder ) Decode (ctx *RuntimeContext , cursor , depth int64 , p unsafe .Pointer ) (int64 , error ) {
buf := ctx .Buf
depth ++
if depth > maxDecodeNestingDepth {
return 0 , errors .ErrExceededMaxDepth (buf [cursor ], cursor )
}
for {
switch buf [cursor ] {
case ' ' , '\n' , '\t' , '\r' :
cursor ++
continue
case 'n' :
if err := validateNull (buf , cursor ); err != nil {
return 0 , err
}
cursor += 4
return cursor , nil
case '[' :
idx := 0
cursor ++
cursor = skipWhiteSpace (buf , cursor )
if buf [cursor ] == ']' {
for idx < d .alen {
*(*unsafe .Pointer )(unsafe .Pointer (uintptr (p ) + uintptr (idx )*d .size )) = d .zeroValue
idx ++
}
cursor ++
return cursor , nil
}
for {
if idx < d .alen {
c , err := d .valueDecoder .Decode (ctx , cursor , depth , unsafe .Pointer (uintptr (p )+uintptr (idx )*d .size ))
if err != nil {
return 0 , err
}
cursor = c
} else {
c , err := skipValue (buf , cursor , depth )
if err != nil {
return 0 , err
}
cursor = c
}
idx ++
cursor = skipWhiteSpace (buf , cursor )
switch buf [cursor ] {
case ']' :
for idx < d .alen {
*(*unsafe .Pointer )(unsafe .Pointer (uintptr (p ) + uintptr (idx )*d .size )) = d .zeroValue
idx ++
}
cursor ++
return cursor , nil
case ',' :
cursor ++
continue
default :
return 0 , errors .ErrInvalidCharacter (buf [cursor ], "array" , cursor )
}
}
default :
return 0 , errors .ErrUnexpectedEndOfJSON ("array" , cursor )
}
}
}
func (d *arrayDecoder ) DecodePath (ctx *RuntimeContext , cursor , depth int64 ) ([][]byte , int64 , error ) {
return nil , 0 , fmt .Errorf ("json: array decoder does not support decode path" )
}
The pages are generated with Golds v0.8.2 . (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 .