You've already forked json-iterator
mirror of
https://github.com/json-iterator/go.git
synced 2025-06-15 22:50:24 +02:00
merge lexer with iterator
This commit is contained in:
606
jsoniter.go
606
jsoniter.go
@ -1,358 +1,294 @@
|
||||
package jsoniter
|
||||
|
||||
import (
|
||||
fflib "github.com/pquerna/ffjson/fflib/v1"
|
||||
"strconv"
|
||||
"io"
|
||||
"fmt"
|
||||
"unicode/utf16"
|
||||
)
|
||||
|
||||
type Token fflib.FFTok
|
||||
|
||||
const TokenInteger = Token(fflib.FFTok_integer)
|
||||
const TokenDouble = Token(fflib.FFTok_double)
|
||||
const TokenBool = Token(fflib.FFTok_bool)
|
||||
const TokenError = Token(fflib.FFTok_error)
|
||||
const TokenLeftBrace = Token(fflib.FFTok_left_brace)
|
||||
const TokenLeftBracket = Token(fflib.FFTok_left_bracket)
|
||||
const TokenRightBrace = Token(fflib.FFTok_right_brace)
|
||||
const TokenRightBracket = Token(fflib.FFTok_right_bracket)
|
||||
const TokenComma = Token(fflib.FFTok_comma)
|
||||
const TokenString = Token(fflib.FFTok_string)
|
||||
const TokenColon = Token(fflib.FFTok_colon)
|
||||
|
||||
func (tok Token) ToString() string {
|
||||
return fmt.Sprintf("%v", fflib.FFTok(tok))
|
||||
}
|
||||
|
||||
type Iterator struct {
|
||||
ErrorHandler func(error)
|
||||
lexer *fflib.FFLexer
|
||||
reader io.Reader
|
||||
buf []byte
|
||||
head int
|
||||
tail int
|
||||
Error error
|
||||
}
|
||||
|
||||
type UnexpectedToken struct {
|
||||
Expected Token
|
||||
Actual Token
|
||||
}
|
||||
|
||||
func (err *UnexpectedToken) Error() string {
|
||||
return fmt.Sprintf("unexpected token, expected %v, actual %v", fflib.FFTok(err.Expected), fflib.FFTok(err.Actual))
|
||||
}
|
||||
|
||||
func NewIterator(input []byte) Iterator {
|
||||
lexer := fflib.NewFFLexer(input)
|
||||
return Iterator{
|
||||
lexer: lexer,
|
||||
func Parse(reader io.Reader, bufSize int) *Iterator {
|
||||
return &Iterator{
|
||||
reader: reader,
|
||||
buf: make([]byte, bufSize),
|
||||
head: 0,
|
||||
tail: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadArray(callback func(Iterator, int)) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenLeftBrace) {
|
||||
return
|
||||
func ParseBytes(input []byte) *Iterator {
|
||||
return &Iterator{
|
||||
reader: nil,
|
||||
buf: input,
|
||||
head: 0,
|
||||
tail: len(input),
|
||||
}
|
||||
index := 0
|
||||
for {
|
||||
lexer.Scan()
|
||||
callback(iter, index)
|
||||
index += 1
|
||||
if iter.Token() != TokenComma {
|
||||
break
|
||||
}
|
||||
|
||||
func ParseString(input string) *Iterator {
|
||||
return ParseBytes([]byte(input))
|
||||
}
|
||||
|
||||
func (iter *Iterator) ReportError(operation string, msg string) {
|
||||
iter.Error = fmt.Errorf("%s: %s, parsing %v at %s", operation, msg, iter.head, string(iter.buf[0:iter.tail]))
|
||||
}
|
||||
|
||||
func (iter *Iterator) readByte() (ret byte) {
|
||||
if iter.head == iter.tail {
|
||||
if iter.reader == nil {
|
||||
iter.Error = io.EOF
|
||||
return
|
||||
}
|
||||
}
|
||||
iter.AssertToken(TokenRightBrace)
|
||||
lexer.Scan()
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadObject(callback func(Iterator, string)) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenLeftBracket) {
|
||||
return
|
||||
}
|
||||
for {
|
||||
lexer.Scan()
|
||||
field := iter.ReadString()
|
||||
iter.AssertToken(TokenColon)
|
||||
lexer.Scan()
|
||||
callback(iter, field)
|
||||
if iter.Token() != TokenComma {
|
||||
break
|
||||
n, err := iter.reader.Read(iter.buf)
|
||||
if err != nil {
|
||||
iter.Error = err
|
||||
return
|
||||
}
|
||||
}
|
||||
iter.AssertToken(TokenRightBracket)
|
||||
lexer.Scan()
|
||||
}
|
||||
|
||||
func (iter Iterator) Skip() {
|
||||
switch iter.Token() {
|
||||
case TokenLeftBracket:
|
||||
iter.ReadObject(func(iter Iterator, field string) {
|
||||
iter.Skip()
|
||||
})
|
||||
case TokenLeftBrace:
|
||||
iter.ReadArray(func(iter Iterator, index int) {
|
||||
iter.Skip()
|
||||
})
|
||||
default:
|
||||
iter.lexer.Scan()
|
||||
}
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadInt8() (rval int8) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseInt(string(field), 10, 8)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return int8(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadInt16() (rval int16) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseInt(string(field), 10, 16)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return int16(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadInt32() (rval int32) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseInt(string(field), 10, 32)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return int32(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadInt64() (rval int64) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseInt(string(field), 10, 64)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return number
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadInt() (rval int) {
|
||||
lexer := iter.lexer
|
||||
n, err := lexer.LexInt64()
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
return int(n)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadUint() (rval uint) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseUint(string(field), 10, 64)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return uint(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadUint8() (rval uint8) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseUint(string(field), 10, 8)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return uint8(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadUint16() (rval uint16) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseUint(string(field), 10, 16)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return uint16(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadUint32() (rval uint32) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseUint(string(field), 10, 32)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return uint32(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadUint64() (rval uint64) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenInteger) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseUint(string(field), 10, 64)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return uint64(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadFloat32() (rval float32) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenDouble) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseFloat(string(field), 32)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return float32(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadFloat64() (rval float64) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenDouble) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
number, err := strconv.ParseFloat(string(field), 64)
|
||||
if err != nil {
|
||||
iter.OnError(fmt.Errorf("failed to convert %v: %v", string(field), err.Error()))
|
||||
return
|
||||
}
|
||||
return float64(number)
|
||||
}
|
||||
|
||||
func (iter Iterator) ReadString() (rval string) {
|
||||
lexer := iter.lexer
|
||||
if !iter.AssertToken(TokenString) {
|
||||
return
|
||||
}
|
||||
field, err := lexer.CaptureField(lexer.Token)
|
||||
if err != nil {
|
||||
iter.OnError(err)
|
||||
return
|
||||
}
|
||||
lexer.Scan()
|
||||
return string(field[1:len(field) - 1])
|
||||
}
|
||||
|
||||
func (iter Iterator) AssertToken(expected Token) bool {
|
||||
actual := iter.Token()
|
||||
if expected != actual {
|
||||
if actual == TokenError {
|
||||
fmt.Println(iter.lexer.BigError.Error())
|
||||
if n == 0 {
|
||||
iter.Error = io.EOF
|
||||
return
|
||||
}
|
||||
iter.OnError(&UnexpectedToken{
|
||||
Expected: expected,
|
||||
Actual: actual,
|
||||
})
|
||||
return false
|
||||
iter.head = 0
|
||||
iter.tail = n
|
||||
}
|
||||
return true
|
||||
ret = iter.buf[iter.head]
|
||||
iter.head += 1
|
||||
return ret
|
||||
}
|
||||
|
||||
func (iter Iterator) Token() Token {
|
||||
return Token(iter.lexer.Token)
|
||||
func (iter *Iterator) unreadByte() {
|
||||
if iter.head == 0 {
|
||||
iter.ReportError("unreadByte", "unread too many bytes")
|
||||
return
|
||||
}
|
||||
iter.head -= 1
|
||||
return
|
||||
}
|
||||
|
||||
func (iter *Iterator) OnError(err error) {
|
||||
if iter.ErrorHandler == nil {
|
||||
panic(err.Error())
|
||||
const maxUint64 = (1 << 64 - 1)
|
||||
const cutoffUint64 = maxUint64 / 10 + 1
|
||||
const maxUint32 = (1 << 32 - 1)
|
||||
const cutoffUint32 = maxUint32 / 10 + 1
|
||||
|
||||
func (iter *Iterator) ReadUint64() (ret uint64) {
|
||||
c := iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
|
||||
/* a single zero, or a series of integers */
|
||||
if c == '0' {
|
||||
return 0
|
||||
} else if c >= '1' && c <= '9' {
|
||||
for c >= '0' && c <= '9' {
|
||||
var v byte
|
||||
v = c - '0'
|
||||
if ret >= cutoffUint64 {
|
||||
iter.ReportError("ReadUint64", "overflow")
|
||||
return
|
||||
}
|
||||
ret = ret * uint64(10) + uint64(v)
|
||||
c = iter.readByte()
|
||||
if iter.Error != nil {
|
||||
if iter.Error == io.EOF {
|
||||
break
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
if iter.Error != io.EOF {
|
||||
iter.unreadByte()
|
||||
}
|
||||
} else {
|
||||
iter.ErrorHandler(err)
|
||||
iter.ReportError("ReadUint64", "expects 0~9")
|
||||
return
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (iter *Iterator) ReadInt64() (ret int64) {
|
||||
c := iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
|
||||
/* optional leading minus */
|
||||
if c == '-' {
|
||||
n := iter.ReadUint64()
|
||||
return -int64(n)
|
||||
} else {
|
||||
iter.unreadByte()
|
||||
n := iter.ReadUint64()
|
||||
return int64(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) ReadString() (ret string) {
|
||||
str := make([]byte, 0, 10)
|
||||
c := iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
if c != '"' {
|
||||
iter.ReportError("ReadString", "expects quote")
|
||||
return
|
||||
}
|
||||
for {
|
||||
c = iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
switch c {
|
||||
case '\\':
|
||||
c = iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
switch c {
|
||||
case 'u':
|
||||
r := iter.readU4()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
if utf16.IsSurrogate(r) {
|
||||
c = iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
if c != '\\' {
|
||||
iter.ReportError("ReadString",
|
||||
`expects \u after utf16 surrogate, but \ not found`)
|
||||
return
|
||||
}
|
||||
c = iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
if c != 'u' {
|
||||
iter.ReportError("ReadString",
|
||||
`expects \u after utf16 surrogate, but \u not found`)
|
||||
return
|
||||
}
|
||||
r2 := iter.readU4()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
combined := utf16.DecodeRune(r, r2)
|
||||
str = appendRune(str, combined)
|
||||
} else {
|
||||
str = 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:
|
||||
iter.ReportError("ReadString",
|
||||
`invalid escape char after \`)
|
||||
return
|
||||
}
|
||||
case '"':
|
||||
return string(str)
|
||||
default:
|
||||
str = append(str, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) readU4() (ret rune) {
|
||||
for i := 0; i < 4; i++ {
|
||||
c := iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
if (c >= '0' && c <= '9') {
|
||||
if ret >= cutoffUint32 {
|
||||
iter.ReportError("readU4", "overflow")
|
||||
return
|
||||
}
|
||||
ret = ret * 16 + rune(c - '0')
|
||||
} else if ((c >= 'a' && c <= 'f') ) {
|
||||
if ret >= cutoffUint32 {
|
||||
iter.ReportError("readU4", "overflow")
|
||||
return
|
||||
}
|
||||
ret = ret * 16 + rune(c - 'a' + 10)
|
||||
} else {
|
||||
iter.ReportError("readU4", "expects 0~9 or a~f")
|
||||
return
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
const (
|
||||
t1 = 0x00 // 0000 0000
|
||||
tx = 0x80 // 1000 0000
|
||||
t2 = 0xC0 // 1100 0000
|
||||
t3 = 0xE0 // 1110 0000
|
||||
t4 = 0xF0 // 1111 0000
|
||||
t5 = 0xF8 // 1111 1000
|
||||
|
||||
maskx = 0x3F // 0011 1111
|
||||
mask2 = 0x1F // 0001 1111
|
||||
mask3 = 0x0F // 0000 1111
|
||||
mask4 = 0x07 // 0000 0111
|
||||
|
||||
rune1Max = 1 << 7 - 1
|
||||
rune2Max = 1 << 11 - 1
|
||||
rune3Max = 1 << 16 - 1
|
||||
|
||||
surrogateMin = 0xD800
|
||||
surrogateMax = 0xDFFF
|
||||
|
||||
MaxRune = '\U0010FFFF' // Maximum valid Unicode code point.
|
||||
RuneError = '\uFFFD' // the "error" Rune or "Unicode replacement character"
|
||||
)
|
||||
|
||||
func appendRune(p []byte, r rune) []byte {
|
||||
// Negative values are erroneous. Making it unsigned addresses the problem.
|
||||
switch i := uint32(r); {
|
||||
case i <= rune1Max:
|
||||
p = append(p, byte(r))
|
||||
return p
|
||||
case i <= rune2Max:
|
||||
p = append(p, t2 | byte(r >> 6))
|
||||
p = append(p, tx | byte(r) & maskx)
|
||||
return p
|
||||
case i > MaxRune, surrogateMin <= i && i <= surrogateMax:
|
||||
r = RuneError
|
||||
fallthrough
|
||||
case i <= rune3Max:
|
||||
p = append(p, t3 | byte(r >> 12))
|
||||
p = append(p, tx | byte(r >> 6) & maskx)
|
||||
p = append(p, tx | byte(r) & maskx)
|
||||
return p
|
||||
default:
|
||||
p = append(p, t4 | byte(r >> 18))
|
||||
p = append(p, tx | byte(r >> 12) & maskx)
|
||||
p = append(p, tx | byte(r >> 6) & maskx)
|
||||
p = append(p, tx | byte(r) & maskx)
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user