mirror of
https://github.com/json-iterator/go.git
synced 2025-03-23 21:09:11 +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 {
|
type Iterator struct {
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
buf []byte
|
buf []byte
|
||||||
@ -57,14 +56,30 @@ func ParseBytes(input []byte) *Iterator {
|
|||||||
return iter
|
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 {
|
func ParseString(input string) *Iterator {
|
||||||
return ParseBytes([]byte(input))
|
return ParseBytes([]byte(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) skipWhitespaces() {
|
func (iter *Iterator) skipWhitespaces() {
|
||||||
c := iter.readByte()
|
c := iter.readByte()
|
||||||
for c == ' ' || c == '\n' || c == '\t' {
|
for {
|
||||||
c = iter.readByte()
|
switch c {
|
||||||
|
case ' ', '\n', '\t', 'r':
|
||||||
|
c = iter.readByte()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
iter.unreadByte()
|
iter.unreadByte()
|
||||||
}
|
}
|
||||||
@ -258,29 +273,20 @@ func (iter *Iterator) ReadInt64() (ret int64) {
|
|||||||
func (iter *Iterator) ReadString() (ret string) {
|
func (iter *Iterator) ReadString() (ret string) {
|
||||||
str := make([]byte, 0, 8)
|
str := make([]byte, 0, 8)
|
||||||
c := iter.readByte()
|
c := iter.readByte()
|
||||||
if iter.Error != nil {
|
if c == 'n' {
|
||||||
|
iter.skipNull()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch c {
|
if c != '"' {
|
||||||
case 'n':
|
|
||||||
iter.skipNull()
|
|
||||||
if iter.Error != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
case '"':
|
|
||||||
// nothing
|
|
||||||
default:
|
|
||||||
iter.ReportError("ReadString", `expects " or n`)
|
iter.ReportError("ReadString", `expects " or n`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for {
|
for iter.Error == nil {
|
||||||
c = iter.readByte()
|
c = iter.readByte()
|
||||||
if iter.Error != nil {
|
if c == '"' {
|
||||||
return
|
return string(str)
|
||||||
}
|
}
|
||||||
switch c {
|
if c == '\\' {
|
||||||
case '\\':
|
|
||||||
c = iter.readByte()
|
c = iter.readByte()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
@ -340,12 +346,11 @@ func (iter *Iterator) ReadString() (ret string) {
|
|||||||
`invalid escape char after \`)
|
`invalid escape char after \`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case '"':
|
} else {
|
||||||
return *(*string)(unsafe.Pointer(&str))
|
|
||||||
default:
|
|
||||||
str = append(str, c)
|
str = append(str, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readU4() (ret rune) {
|
func (iter *Iterator) readU4() (ret rune) {
|
||||||
@ -434,9 +439,6 @@ func (iter *Iterator) ReadArray() (ret bool) {
|
|||||||
switch c {
|
switch c {
|
||||||
case 'n': {
|
case 'n': {
|
||||||
iter.skipNull()
|
iter.skipNull()
|
||||||
if iter.Error != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return false // null
|
return false // null
|
||||||
}
|
}
|
||||||
case '[': {
|
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) {
|
func (iter *Iterator) ReadObject() (ret string) {
|
||||||
iter.skipWhitespaces()
|
iter.skipWhitespaces()
|
||||||
c := iter.readByte()
|
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) {
|
func Test_invalid_array(t *testing.T) {
|
||||||
iter := ParseString(`[`)
|
iter := ParseString(`[`)
|
||||||
iter.ReadArray()
|
iter.ReadArray()
|
||||||
@ -117,16 +128,32 @@ func Test_whitespace_before_comma(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func Benchmark_jsoniter_array(b *testing.B) {
|
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++ {
|
for n := 0; n < b.N; n++ {
|
||||||
iter := ParseString(`[1,2,3]`)
|
iter.Reuse(input)
|
||||||
for iter.ReadArray() {
|
for iter.ReadArray() {
|
||||||
iter.ReadUint64()
|
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) {
|
func Benchmark_json_array(b *testing.B) {
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := []interface{}{}
|
result := []interface{}{}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user