package jsoniter
import (
"encoding/json"
"fmt"
"io"
)
type ValueType int
const (
InvalidValue ValueType = iota
StringValue
NumberValue
NilValue
BoolValue
ArrayValue
ObjectValue
)
var hexDigits []byte
var valueTypes []ValueType
func init() {
hexDigits = make ([]byte , 256 )
for i := 0 ; i < len (hexDigits ); i ++ {
hexDigits [i ] = 255
}
for i := '0' ; i <= '9' ; i ++ {
hexDigits [i ] = byte (i - '0' )
}
for i := 'a' ; i <= 'f' ; i ++ {
hexDigits [i ] = byte ((i - 'a' ) + 10 )
}
for i := 'A' ; i <= 'F' ; i ++ {
hexDigits [i ] = byte ((i - 'A' ) + 10 )
}
valueTypes = make ([]ValueType , 256 )
for i := 0 ; i < len (valueTypes ); i ++ {
valueTypes [i ] = InvalidValue
}
valueTypes ['"' ] = StringValue
valueTypes ['-' ] = NumberValue
valueTypes ['0' ] = NumberValue
valueTypes ['1' ] = NumberValue
valueTypes ['2' ] = NumberValue
valueTypes ['3' ] = NumberValue
valueTypes ['4' ] = NumberValue
valueTypes ['5' ] = NumberValue
valueTypes ['6' ] = NumberValue
valueTypes ['7' ] = NumberValue
valueTypes ['8' ] = NumberValue
valueTypes ['9' ] = NumberValue
valueTypes ['t' ] = BoolValue
valueTypes ['f' ] = BoolValue
valueTypes ['n' ] = NilValue
valueTypes ['[' ] = ArrayValue
valueTypes ['{' ] = ObjectValue
}
type Iterator struct {
cfg *frozenConfig
reader io .Reader
buf []byte
head int
tail int
depth int
captureStartedAt int
captured []byte
Error error
Attachment interface {}
}
func NewIterator (cfg API ) *Iterator {
return &Iterator {
cfg : cfg .(*frozenConfig ),
reader : nil ,
buf : nil ,
head : 0 ,
tail : 0 ,
depth : 0 ,
}
}
func Parse (cfg API , reader io .Reader , bufSize int ) *Iterator {
return &Iterator {
cfg : cfg .(*frozenConfig ),
reader : reader ,
buf : make ([]byte , bufSize ),
head : 0 ,
tail : 0 ,
depth : 0 ,
}
}
func ParseBytes (cfg API , input []byte ) *Iterator {
return &Iterator {
cfg : cfg .(*frozenConfig ),
reader : nil ,
buf : input ,
head : 0 ,
tail : len (input ),
depth : 0 ,
}
}
func ParseString (cfg API , input string ) *Iterator {
return ParseBytes (cfg , []byte (input ))
}
func (iter *Iterator ) Pool () IteratorPool {
return iter .cfg
}
func (iter *Iterator ) Reset (reader io .Reader ) *Iterator {
iter .reader = reader
iter .head = 0
iter .tail = 0
iter .depth = 0
return iter
}
func (iter *Iterator ) ResetBytes (input []byte ) *Iterator {
iter .reader = nil
iter .buf = input
iter .head = 0
iter .tail = len (input )
iter .depth = 0
return iter
}
func (iter *Iterator ) WhatIsNext () ValueType {
valueType := valueTypes [iter .nextToken ()]
iter .unreadByte ()
return valueType
}
func (iter *Iterator ) skipWhitespacesWithoutLoadMore () bool {
for i := iter .head ; i < iter .tail ; i ++ {
c := iter .buf [i ]
switch c {
case ' ' , '\n' , '\t' , '\r' :
continue
}
iter .head = i
return false
}
return true
}
func (iter *Iterator ) isObjectEnd () bool {
c := iter .nextToken ()
if c == ',' {
return false
}
if c == '}' {
return true
}
iter .ReportError ("isObjectEnd" , "object ended prematurely, unexpected char " +string ([]byte {c }))
return true
}
func (iter *Iterator ) nextToken () byte {
for {
for i := iter .head ; i < iter .tail ; i ++ {
c := iter .buf [i ]
switch c {
case ' ' , '\n' , '\t' , '\r' :
continue
}
iter .head = i + 1
return c
}
if !iter .loadMore () {
return 0
}
}
}
func (iter *Iterator ) ReportError (operation string , msg string ) {
if iter .Error != nil {
if iter .Error != io .EOF {
return
}
}
peekStart := iter .head - 10
if peekStart < 0 {
peekStart = 0
}
peekEnd := iter .head + 10
if peekEnd > iter .tail {
peekEnd = iter .tail
}
parsing := string (iter .buf [peekStart :peekEnd ])
contextStart := iter .head - 50
if contextStart < 0 {
contextStart = 0
}
contextEnd := iter .head + 50
if contextEnd > iter .tail {
contextEnd = iter .tail
}
context := string (iter .buf [contextStart :contextEnd ])
iter .Error = fmt .Errorf ("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|..." ,
operation , msg , iter .head -peekStart , parsing , context )
}
func (iter *Iterator ) CurrentBuffer () string {
peekStart := iter .head - 10
if peekStart < 0 {
peekStart = 0
}
return fmt .Sprintf ("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|..." , iter .head ,
string (iter .buf [peekStart :iter .head ]), string (iter .buf [0 :iter .tail ]))
}
func (iter *Iterator ) readByte () (ret byte ) {
if iter .head == iter .tail {
if iter .loadMore () {
ret = iter .buf [iter .head ]
iter .head ++
return ret
}
return 0
}
ret = iter .buf [iter .head ]
iter .head ++
return ret
}
func (iter *Iterator ) loadMore () bool {
if iter .reader == nil {
if iter .Error == nil {
iter .head = iter .tail
iter .Error = io .EOF
}
return false
}
if iter .captured != nil {
iter .captured = append (iter .captured ,
iter .buf [iter .captureStartedAt :iter .tail ]...)
iter .captureStartedAt = 0
}
for {
n , err := iter .reader .Read (iter .buf )
if n == 0 {
if err != nil {
if iter .Error == nil {
iter .Error = err
}
return false
}
} else {
iter .head = 0
iter .tail = n
return true
}
}
}
func (iter *Iterator ) unreadByte () {
if iter .Error != nil {
return
}
iter .head --
return
}
func (iter *Iterator ) Read () interface {} {
valueType := iter .WhatIsNext ()
switch valueType {
case StringValue :
return iter .ReadString ()
case NumberValue :
if iter .cfg .configBeforeFrozen .UseNumber {
return json .Number (iter .readNumberAsString ())
}
return iter .ReadFloat64 ()
case NilValue :
iter .skipFourBytes ('n' , 'u' , 'l' , 'l' )
return nil
case BoolValue :
return iter .ReadBool ()
case ArrayValue :
arr := []interface {}{}
iter .ReadArrayCB (func (iter *Iterator ) bool {
var elem interface {}
iter .ReadVal (&elem )
arr = append (arr , elem )
return true
})
return arr
case ObjectValue :
obj := map [string ]interface {}{}
iter .ReadMapCB (func (Iter *Iterator , field string ) bool {
var elem interface {}
iter .ReadVal (&elem )
obj [field ] = elem
return true
})
return obj
default :
iter .ReportError ("Read" , fmt .Sprintf ("unexpected value type: %v" , valueType ))
return nil
}
}
const maxDepth = 10000
func (iter *Iterator ) incrementDepth () (success bool ) {
iter .depth ++
if iter .depth <= maxDepth {
return true
}
iter .ReportError ("incrementDepth" , "exceeded max depth" )
return false
}
func (iter *Iterator ) decrementDepth () (success bool ) {
iter .depth --
if iter .depth >= 0 {
return true
}
iter .ReportError ("decrementDepth" , "unexpected negative nesting" )
return false
}
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 .