mirror of
https://github.com/json-iterator/go.git
synced 2025-03-20 20:54:55 +02:00
optimize
This commit is contained in:
parent
6a46bc9513
commit
c457aeaac2
88
jsoniter.go
88
jsoniter.go
@ -26,7 +26,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type Iterator struct {
|
||||
reader io.Reader
|
||||
buf []byte
|
||||
@ -57,14 +56,30 @@ func ParseBytes(input []byte) *Iterator {
|
||||
return iter
|
||||
}
|
||||
|
||||
func (iter *Iterator) Reuse(input []byte) *Iterator {
|
||||
// only for benchmarking
|
||||
iter.reader = nil
|
||||
iter.Error = nil
|
||||
iter.buf = input
|
||||
iter.head = 0
|
||||
iter.tail = len(input)
|
||||
iter.skipWhitespaces()
|
||||
return iter
|
||||
}
|
||||
|
||||
func ParseString(input string) *Iterator {
|
||||
return ParseBytes([]byte(input))
|
||||
}
|
||||
|
||||
func (iter *Iterator) skipWhitespaces() {
|
||||
c := iter.readByte()
|
||||
for c == ' ' || c == '\n' || c == '\t' {
|
||||
c = iter.readByte()
|
||||
for {
|
||||
switch c {
|
||||
case ' ', '\n', '\t', 'r':
|
||||
c = iter.readByte()
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
iter.unreadByte()
|
||||
}
|
||||
@ -258,29 +273,20 @@ func (iter *Iterator) ReadInt64() (ret int64) {
|
||||
func (iter *Iterator) ReadString() (ret string) {
|
||||
str := make([]byte, 0, 8)
|
||||
c := iter.readByte()
|
||||
if iter.Error != nil {
|
||||
if c == 'n' {
|
||||
iter.skipNull()
|
||||
return
|
||||
}
|
||||
switch c {
|
||||
case 'n':
|
||||
iter.skipNull()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
return ""
|
||||
case '"':
|
||||
// nothing
|
||||
default:
|
||||
if c != '"' {
|
||||
iter.ReportError("ReadString", `expects " or n`)
|
||||
return
|
||||
}
|
||||
for {
|
||||
for iter.Error == nil {
|
||||
c = iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
if c == '"' {
|
||||
return string(str)
|
||||
}
|
||||
switch c {
|
||||
case '\\':
|
||||
if c == '\\' {
|
||||
c = iter.readByte()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
@ -340,12 +346,11 @@ func (iter *Iterator) ReadString() (ret string) {
|
||||
`invalid escape char after \`)
|
||||
return
|
||||
}
|
||||
case '"':
|
||||
return *(*string)(unsafe.Pointer(&str))
|
||||
default:
|
||||
} else {
|
||||
str = append(str, c)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (iter *Iterator) readU4() (ret rune) {
|
||||
@ -434,9 +439,6 @@ func (iter *Iterator) ReadArray() (ret bool) {
|
||||
switch c {
|
||||
case 'n': {
|
||||
iter.skipNull()
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
return false // null
|
||||
}
|
||||
case '[': {
|
||||
@ -462,6 +464,42 @@ func (iter *Iterator) ReadArray() (ret bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) ReadArrayCB(cb func()) {
|
||||
iter.skipWhitespaces()
|
||||
c := iter.readByte()
|
||||
if c == 'n' {
|
||||
iter.skipNull()
|
||||
return // null
|
||||
}
|
||||
if c != '[' {
|
||||
iter.ReportError("ReadArray", "expect [ or n")
|
||||
return
|
||||
}
|
||||
iter.skipWhitespaces()
|
||||
c = iter.readByte()
|
||||
if c == ']' {
|
||||
return // []
|
||||
} else {
|
||||
iter.unreadByte()
|
||||
}
|
||||
for {
|
||||
if iter.Error != nil {
|
||||
return
|
||||
}
|
||||
cb()
|
||||
iter.skipWhitespaces()
|
||||
c = iter.readByte()
|
||||
if c == ']' {
|
||||
return
|
||||
}
|
||||
if c != ',' {
|
||||
iter.ReportError("ReadArray", "expect , or ]")
|
||||
return
|
||||
}
|
||||
iter.skipWhitespaces()
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) ReadObject() (ret string) {
|
||||
iter.skipWhitespaces()
|
||||
c := iter.readByte()
|
||||
|
@ -50,6 +50,17 @@ func Test_two_elements(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_two_elements_cb(t *testing.T) {
|
||||
iter := ParseString(`[1,2]`)
|
||||
total := int64(0)
|
||||
iter.ReadArrayCB(func() {
|
||||
total += iter.ReadInt64()
|
||||
})
|
||||
if total != 3 {
|
||||
t.Fatal(total)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_invalid_array(t *testing.T) {
|
||||
iter := ParseString(`[`)
|
||||
iter.ReadArray()
|
||||
@ -117,16 +128,32 @@ func Test_whitespace_before_comma(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func Benchmark_jsoniter_array(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
input := []byte(`[1,2,3,4,5,6,7,8,9]`)
|
||||
iter := ParseBytes(input)
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
iter := ParseString(`[1,2,3]`)
|
||||
iter.Reuse(input)
|
||||
for iter.ReadArray() {
|
||||
iter.ReadUint64()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_jsoniter_array_cb(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
input := []byte(`[1,2,3,4,5,6,7,8,9]`)
|
||||
iter := ParseBytes(input)
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
iter.Reuse(input)
|
||||
iter.ReadArrayCB(func() {
|
||||
iter.ReadUint64()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_json_array(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
result := []interface{}{}
|
||||
|
Loading…
x
Reference in New Issue
Block a user