827 lines
19 KiB
Go
827 lines
19 KiB
Go
package json
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"io"
|
|
"math/big"
|
|
"reflect"
|
|
"unicode/utf16"
|
|
|
|
"go_dreamfactory/lego/utils/codec"
|
|
"go_dreamfactory/lego/utils/codec/codecore"
|
|
"go_dreamfactory/lego/utils/codec/utils"
|
|
|
|
"github.com/modern-go/reflect2"
|
|
)
|
|
|
|
type JsonReader struct {
|
|
buf []byte
|
|
head int
|
|
tail int
|
|
depth int
|
|
err error
|
|
}
|
|
|
|
func (this *JsonReader) GetReader(buf []byte) codecore.IReader {
|
|
return GetReader(buf)
|
|
}
|
|
func (this *JsonReader) PutReader(r codecore.IReader) {
|
|
PutReader(r)
|
|
}
|
|
func (this *JsonReader) GetWriter() codecore.IWriter {
|
|
return GetWriter()
|
|
}
|
|
func (this *JsonReader) PutWriter(w codecore.IWriter) {
|
|
PutWriter(w)
|
|
}
|
|
func (this *JsonReader) ReadVal(obj interface{}) {
|
|
depth := this.depth
|
|
cacheKey := reflect2.RTypeOf(obj)
|
|
decoder := codec.GetDecoder(cacheKey)
|
|
if decoder == nil {
|
|
typ := reflect2.TypeOf(obj)
|
|
if typ == nil || typ.Kind() != reflect.Ptr {
|
|
this.reportError("ReadVal", "can only unmarshal into pointer")
|
|
return
|
|
}
|
|
decoder = codec.DecoderOf(typ, defconf)
|
|
}
|
|
ptr := reflect2.PtrOf(obj)
|
|
if ptr == nil {
|
|
this.reportError("ReadVal", "can not read into nil pointer")
|
|
return
|
|
}
|
|
decoder.Decode(ptr, this)
|
|
if this.depth != depth {
|
|
this.reportError("ReadVal", "unexpected mismatched nesting")
|
|
return
|
|
}
|
|
}
|
|
func (this *JsonReader) WhatIsNext() codecore.ValueType {
|
|
valueType := valueTypes[this.nextToken()]
|
|
this.unreadByte()
|
|
return valueType
|
|
}
|
|
func (this *JsonReader) Read() interface{} {
|
|
valueType := this.WhatIsNext()
|
|
switch valueType {
|
|
case codecore.StringValue:
|
|
return this.ReadString()
|
|
case codecore.NumberValue:
|
|
return this.ReadFloat64()
|
|
case codecore.NilValue:
|
|
this.skipFourBytes('n', 'u', 'l', 'l')
|
|
return nil
|
|
case codecore.BoolValue:
|
|
return this.ReadBool()
|
|
case codecore.ArrayValue:
|
|
arr := []interface{}{}
|
|
this.ReadArrayCB(func(extra codecore.IReader) bool {
|
|
var elem interface{}
|
|
extra.ReadVal(&elem)
|
|
arr = append(arr, elem)
|
|
return true
|
|
})
|
|
return arr
|
|
case codecore.ObjectValue:
|
|
obj := map[string]interface{}{}
|
|
this.ReadMapCB(func(extra codecore.IReader, field string) bool {
|
|
var elem interface{}
|
|
this.ReadVal(&elem)
|
|
obj[field] = elem
|
|
return true
|
|
})
|
|
return obj
|
|
default:
|
|
this.reportError("Read", fmt.Sprintf("unexpected value type: %v", valueType))
|
|
return nil
|
|
}
|
|
}
|
|
func (this *JsonReader) ReadNil() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == 'n' {
|
|
this.skipThreeBytes('u', 'l', 'l') // null
|
|
return true
|
|
}
|
|
this.unreadByte()
|
|
return false
|
|
}
|
|
func (this *JsonReader) ReadArrayStart() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == '[' {
|
|
return true
|
|
}
|
|
this.reportError("ReadArrayStart", `expect [ but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) CheckNextIsArrayEnd() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == ']' {
|
|
return true
|
|
}
|
|
this.unreadByte()
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadArrayEnd() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == ']' {
|
|
return true
|
|
}
|
|
this.reportError("ReadArrayEnd", `expect ] but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadObjectStart() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == '{' {
|
|
return this.incrementDepth()
|
|
}
|
|
this.reportError("ReadObjectStart", `expect { but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) CheckNextIsObjectEnd() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == '}' {
|
|
return this.decrementDepth()
|
|
}
|
|
this.unreadByte()
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadObjectEnd() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == '}' {
|
|
return this.decrementDepth()
|
|
}
|
|
this.reportError("ReadObjectEnd", `expect } but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadMemberSplit() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == ',' {
|
|
return true
|
|
}
|
|
this.unreadByte()
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadKVSplit() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == ':' {
|
|
return true
|
|
}
|
|
this.reportError("ReadKVSplit", `expect : but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadKeyStart() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == '"' {
|
|
return true
|
|
}
|
|
this.reportError("ReadKeyStart", `expect " but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadKeyEnd() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == '"' {
|
|
return true
|
|
}
|
|
this.reportError("ReadKeyEnd", `expect " but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) Skip() {
|
|
c := this.nextToken()
|
|
switch c {
|
|
case '"':
|
|
this.skipString()
|
|
case 'n':
|
|
this.skipThreeBytes('u', 'l', 'l') // null
|
|
case 't':
|
|
this.skipThreeBytes('r', 'u', 'e') // true
|
|
case 'f':
|
|
this.skipFourBytes('a', 'l', 's', 'e') // false
|
|
case '0':
|
|
this.unreadByte()
|
|
this.ReadFloat32()
|
|
case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
|
this.skipNumber()
|
|
case '[':
|
|
this.skipArray()
|
|
case '{':
|
|
this.skipObject()
|
|
default:
|
|
this.reportError("Skip", fmt.Sprintf("do not know how to skip: %v", c))
|
|
return
|
|
}
|
|
}
|
|
func (this *JsonReader) ReadBool() (ret bool) {
|
|
c := this.nextToken()
|
|
if c == 't' {
|
|
this.skipThreeBytes('r', 'u', 'e')
|
|
return true
|
|
}
|
|
if c == 'f' {
|
|
this.skipFourBytes('a', 'l', 's', 'e')
|
|
return false
|
|
}
|
|
this.reportError("ReadBool", "expect t or f, but found "+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadInt8() (ret int8) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadInt8ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadInt8", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadInt16() (ret int16) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadInt16ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadInt32", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadInt32() (ret int32) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadInt32ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadInt32", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadInt64() (ret int64) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadInt64ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadInt64", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadUint8() (ret uint8) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadUint8ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadUint8", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadUint16() (ret uint16) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadUint16ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadUint16", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadUint32() (ret uint32) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadUint32ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadUint32", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadUint64() (ret uint64) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadUint64ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadUint64", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadFloat32() (ret float32) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadFloat32ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadFloat32", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadFloat64() (ret float64) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadFloat64ForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadFloat64", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (this *JsonReader) ReadString() (ret string) {
|
|
c := this.nextToken()
|
|
if c == '"' {
|
|
for i := this.head; i < this.tail; i++ {
|
|
c := this.buf[i]
|
|
if c == '"' {
|
|
ret = string(this.buf[this.head:i])
|
|
this.head = i + 1
|
|
return ret
|
|
} else if c == '\\' {
|
|
break
|
|
} else if c < ' ' {
|
|
this.reportError("ReadString",
|
|
fmt.Sprintf(`invalid control character found: %d`, c))
|
|
return
|
|
}
|
|
}
|
|
return this.readStringSlowPath()
|
|
} else if c == 'n' {
|
|
this.skipThreeBytes('u', 'l', 'l')
|
|
return ""
|
|
}
|
|
this.reportError("ReadString", `expects " or n, but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
func (this *JsonReader) ResetBytes(d []byte) {
|
|
this.buf = d
|
|
this.head = 0
|
|
this.tail = len(d)
|
|
}
|
|
func (this *JsonReader) Error() error {
|
|
return this.err
|
|
}
|
|
func (this *JsonReader) SetErr(err error) {
|
|
this.err = err
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------------------------------------------------------------
|
|
func (this *JsonReader) readByte() (ret byte) {
|
|
if this.head == this.tail {
|
|
return 0
|
|
}
|
|
ret = this.buf[this.head]
|
|
this.head++
|
|
return ret
|
|
}
|
|
func (this *JsonReader) readStringSlowPath() (ret string) {
|
|
var str []byte
|
|
var c byte
|
|
for this.err == nil {
|
|
c = this.readByte()
|
|
if c == '"' {
|
|
return string(str)
|
|
}
|
|
if c == '\\' {
|
|
c = this.readByte()
|
|
str = this.readEscapedChar(c, str)
|
|
} else {
|
|
str = append(str, c)
|
|
}
|
|
}
|
|
this.reportError("readStringSlowPath", "unexpected end of input")
|
|
return
|
|
}
|
|
func (this *JsonReader) readEscapedChar(c byte, str []byte) []byte {
|
|
switch c {
|
|
case 'u':
|
|
r := this.readU4()
|
|
if utf16.IsSurrogate(r) {
|
|
c = this.readByte()
|
|
if this.err != nil {
|
|
return nil
|
|
}
|
|
if c != '\\' {
|
|
this.unreadByte()
|
|
str = utils.AppendRune(str, r)
|
|
return str
|
|
}
|
|
c = this.readByte()
|
|
if this.err != nil {
|
|
return nil
|
|
}
|
|
if c != 'u' {
|
|
str = utils.AppendRune(str, r)
|
|
return this.readEscapedChar(c, str)
|
|
}
|
|
r2 := this.readU4()
|
|
if this.err != nil {
|
|
return nil
|
|
}
|
|
combined := utf16.DecodeRune(r, r2)
|
|
if combined == '\uFFFD' {
|
|
str = utils.AppendRune(str, r)
|
|
str = utils.AppendRune(str, r2)
|
|
} else {
|
|
str = utils.AppendRune(str, combined)
|
|
}
|
|
} else {
|
|
str = utils.AppendRune(str, r)
|
|
}
|
|
case '"':
|
|
str = append(str, '"')
|
|
case '\\':
|
|
str = append(str, '\\')
|
|
case '/':
|
|
str = append(str, '/')
|
|
case 'b':
|
|
str = append(str, '\b')
|
|
case 'f':
|
|
str = append(str, '\f')
|
|
case 'n':
|
|
str = append(str, '\n')
|
|
case 'r':
|
|
str = append(str, '\r')
|
|
case 't':
|
|
str = append(str, '\t')
|
|
default:
|
|
this.reportError("readEscapedChar",
|
|
`invalid escape char after \`)
|
|
return nil
|
|
}
|
|
return str
|
|
}
|
|
func (this *JsonReader) readU4() (ret rune) {
|
|
for i := 0; i < 4; i++ {
|
|
c := this.readByte()
|
|
if this.err != nil {
|
|
return
|
|
}
|
|
if c >= '0' && c <= '9' {
|
|
ret = ret*16 + rune(c-'0')
|
|
} else if c >= 'a' && c <= 'f' {
|
|
ret = ret*16 + rune(c-'a'+10)
|
|
} else if c >= 'A' && c <= 'F' {
|
|
ret = ret*16 + rune(c-'A'+10)
|
|
} else {
|
|
this.reportError("readU4", "expects 0~9 or a~f, but found "+string([]byte{c}))
|
|
return
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
func (this *JsonReader) nextToken() byte {
|
|
for i := this.head; i < this.tail; i++ {
|
|
c := this.buf[i]
|
|
switch c {
|
|
case ' ', '\n', '\t', '\r':
|
|
continue
|
|
}
|
|
this.head = i + 1
|
|
return c
|
|
}
|
|
return 0
|
|
}
|
|
func (this *JsonReader) unreadByte() {
|
|
if this.err != nil {
|
|
return
|
|
}
|
|
this.head--
|
|
return
|
|
}
|
|
func (this *JsonReader) skipNumber() {
|
|
if !this.trySkipNumber() {
|
|
this.unreadByte()
|
|
if this.err != nil && this.err != io.EOF {
|
|
return
|
|
}
|
|
this.ReadFloat64()
|
|
if this.err != nil && this.err != io.EOF {
|
|
this.err = nil
|
|
this.ReadBigFloat()
|
|
}
|
|
}
|
|
}
|
|
func (this *JsonReader) ReadBigFloat() (ret *big.Float) {
|
|
var (
|
|
n int
|
|
err error
|
|
)
|
|
if ret, n, err = utils.ReadBigFloatForString(this.buf[this.head:]); err != nil {
|
|
this.reportError("ReadBigFloat", err.Error())
|
|
return
|
|
}
|
|
this.head += n
|
|
return
|
|
}
|
|
func (iter *JsonReader) trySkipNumber() bool {
|
|
dotFound := false
|
|
for i := iter.head; i < iter.tail; i++ {
|
|
c := iter.buf[i]
|
|
switch c {
|
|
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
|
case '.':
|
|
if dotFound {
|
|
iter.reportError("validateNumber", `more than one dot found in number`)
|
|
return true // already failed
|
|
}
|
|
if i+1 == iter.tail {
|
|
return false
|
|
}
|
|
c = iter.buf[i+1]
|
|
switch c {
|
|
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
|
default:
|
|
iter.reportError("validateNumber", `missing digit after dot`)
|
|
return true // already failed
|
|
}
|
|
dotFound = true
|
|
default:
|
|
switch c {
|
|
case ',', ']', '}', ' ', '\t', '\n', '\r':
|
|
if iter.head == i {
|
|
return false // if - without following digits
|
|
}
|
|
iter.head = i
|
|
return true // must be valid
|
|
}
|
|
return false // may be invalid
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
func (this *JsonReader) skipString() {
|
|
if !this.trySkipString() {
|
|
this.unreadByte()
|
|
this.ReadString()
|
|
}
|
|
}
|
|
func (this *JsonReader) trySkipString() bool {
|
|
for i := this.head; i < this.tail; i++ {
|
|
c := this.buf[i]
|
|
if c == '"' {
|
|
this.head = i + 1
|
|
return true // valid
|
|
} else if c == '\\' {
|
|
return false
|
|
} else if c < ' ' {
|
|
this.reportError("trySkipString",
|
|
fmt.Sprintf(`invalid control character found: %d`, c))
|
|
return true // already failed
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
func (this *JsonReader) skipObject() {
|
|
this.unreadByte()
|
|
this.ReadObjectCB(func(extra codecore.IReader, field string) bool {
|
|
extra.Skip()
|
|
return true
|
|
})
|
|
}
|
|
func (this *JsonReader) skipArray() {
|
|
this.unreadByte()
|
|
this.ReadArrayCB(func(extra codecore.IReader) bool {
|
|
extra.Skip()
|
|
return true
|
|
})
|
|
}
|
|
func (this *JsonReader) skipThreeBytes(b1, b2, b3 byte) {
|
|
if this.readByte() != b1 {
|
|
this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3})))
|
|
return
|
|
}
|
|
if this.readByte() != b2 {
|
|
this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3})))
|
|
return
|
|
}
|
|
if this.readByte() != b3 {
|
|
this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3})))
|
|
return
|
|
}
|
|
}
|
|
func (this *JsonReader) skipFourBytes(b1, b2, b3, b4 byte) {
|
|
if this.readByte() != b1 {
|
|
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
|
|
return
|
|
}
|
|
if this.readByte() != b2 {
|
|
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
|
|
return
|
|
}
|
|
if this.readByte() != b3 {
|
|
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
|
|
return
|
|
}
|
|
if this.readByte() != b4 {
|
|
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
|
|
return
|
|
}
|
|
}
|
|
func (this *JsonReader) reportError(operation string, msg string) {
|
|
if this.err != nil {
|
|
if this.err != io.EOF {
|
|
return
|
|
}
|
|
}
|
|
peekStart := this.head - 10
|
|
if peekStart < 0 {
|
|
peekStart = 0
|
|
}
|
|
peekEnd := this.head + 10
|
|
if peekEnd > this.tail {
|
|
peekEnd = this.tail
|
|
}
|
|
parsing := string(this.buf[peekStart:peekEnd])
|
|
contextStart := this.head - 50
|
|
if contextStart < 0 {
|
|
contextStart = 0
|
|
}
|
|
contextEnd := this.head + 50
|
|
if contextEnd > this.tail {
|
|
contextEnd = this.tail
|
|
}
|
|
context := string(this.buf[contextStart:contextEnd])
|
|
this.err = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...",
|
|
operation, msg, this.head-peekStart, parsing, context)
|
|
}
|
|
func (this *JsonReader) incrementDepth() (success bool) {
|
|
this.depth++
|
|
if this.depth <= maxDepth {
|
|
return true
|
|
}
|
|
this.reportError("incrementDepth", "exceeded max depth")
|
|
return false
|
|
}
|
|
func (this *JsonReader) decrementDepth() (success bool) {
|
|
this.depth--
|
|
if this.depth >= 0 {
|
|
return true
|
|
}
|
|
this.reportError("decrementDepth", "unexpected negative nesting")
|
|
return false
|
|
}
|
|
func (iter *JsonReader) ReadObjectCB(callback func(codecore.IReader, string) bool) bool {
|
|
c := iter.nextToken()
|
|
var field string
|
|
if c == '{' {
|
|
if !iter.incrementDepth() {
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
if c == '"' {
|
|
iter.unreadByte()
|
|
field = iter.ReadString()
|
|
c = iter.nextToken()
|
|
if c != ':' {
|
|
iter.reportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
|
|
}
|
|
if !callback(iter, field) {
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
for c == ',' {
|
|
field = iter.ReadString()
|
|
c = iter.nextToken()
|
|
if c != ':' {
|
|
iter.reportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
|
|
}
|
|
if !callback(iter, field) {
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
}
|
|
if c != '}' {
|
|
iter.reportError("ReadObjectCB", `object not ended with }`)
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
return iter.decrementDepth()
|
|
}
|
|
if c == '}' {
|
|
return iter.decrementDepth()
|
|
}
|
|
iter.reportError("ReadObjectCB", `expect " after {, but found `+string([]byte{c}))
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
if c == 'n' {
|
|
iter.skipThreeBytes('u', 'l', 'l')
|
|
return true // null
|
|
}
|
|
iter.reportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c}))
|
|
return false
|
|
}
|
|
|
|
func (iter *JsonReader) ReadMapCB(callback func(codecore.IReader, string) bool) bool {
|
|
c := iter.nextToken()
|
|
if c == '{' {
|
|
if !iter.incrementDepth() {
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
if c == '"' {
|
|
iter.unreadByte()
|
|
field := iter.ReadString()
|
|
if iter.nextToken() != ':' {
|
|
iter.reportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
if !callback(iter, field) {
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
for c == ',' {
|
|
field = iter.ReadString()
|
|
if iter.nextToken() != ':' {
|
|
iter.reportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
if !callback(iter, field) {
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
}
|
|
if c != '}' {
|
|
iter.reportError("ReadMapCB", `object not ended with }`)
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
return iter.decrementDepth()
|
|
}
|
|
if c == '}' {
|
|
return iter.decrementDepth()
|
|
}
|
|
iter.reportError("ReadMapCB", `expect " after {, but found `+string([]byte{c}))
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
if c == 'n' {
|
|
iter.skipThreeBytes('u', 'l', 'l')
|
|
return true // null
|
|
}
|
|
iter.reportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
|
|
return false
|
|
}
|
|
|
|
func (iter *JsonReader) ReadArrayCB(callback func(codecore.IReader) bool) (ret bool) {
|
|
c := iter.nextToken()
|
|
if c == '[' {
|
|
if !iter.incrementDepth() {
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
if c != ']' {
|
|
iter.unreadByte()
|
|
if !callback(iter) {
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
for c == ',' {
|
|
if !callback(iter) {
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
c = iter.nextToken()
|
|
}
|
|
if c != ']' {
|
|
iter.reportError("ReadArrayCB", "expect ] in the end, but found "+string([]byte{c}))
|
|
iter.decrementDepth()
|
|
return false
|
|
}
|
|
return iter.decrementDepth()
|
|
}
|
|
return iter.decrementDepth()
|
|
}
|
|
if c == 'n' {
|
|
iter.skipThreeBytes('u', 'l', 'l')
|
|
return true // null
|
|
}
|
|
iter.reportError("ReadArrayCB", "expect [ or n, but found "+string([]byte{c}))
|
|
return false
|
|
}
|