1
0
mirror of https://github.com/json-iterator/go.git synced 2025-03-26 21:12:40 +02:00

optimize read string

This commit is contained in:
Tao Wen 2016-12-07 14:21:25 +08:00
parent 71cdbd249c
commit 3e376c671c

View File

@ -304,55 +304,6 @@ func (iter *Iterator) ReadString() (ret string) {
return string(iter.ReadStringAsBytes()) return string(iter.ReadStringAsBytes())
} }
// adapted from: https://github.com/buger/jsonparser/blob/master/parser.go
// Tries to find the end of string
// Support if string contains escaped quote symbols.
func (iter *Iterator) findStringEnd() (int, bool) {
escaped := false
for i := iter.head; i < iter.tail; i++ {
c := iter.buf[i]
if c == '"' {
if !escaped {
return i + 1, false
} else {
j := i - 1
for {
if j < iter.head || iter.buf[j] != '\\' {
// even number of backslashes
// either end of buffer, or " found
return i + 1, true
}
j--
if j < iter.head || iter.buf[j] != '\\' {
// odd number of backslashes
// it is \" or \\\"
break
}
j--
}
}
} else if c == '\\' {
escaped = true
}
}
j := iter.tail - 1
for {
if j < iter.head || iter.buf[j] != '\\' {
// even number of backslashes
// either end of buffer, or " found
return -1, false // do not end with \
}
j--
if j < iter.head || iter.buf[j] != '\\' {
// odd number of backslashes
// it is \" or \\\"
break
}
j--
}
return -1, true // end with \
}
func (iter *Iterator) ReadStringAsBytes() (ret []byte) { func (iter *Iterator) ReadStringAsBytes() (ret []byte) {
c := iter.readByte() c := iter.readByte()
@ -364,8 +315,8 @@ func (iter *Iterator) ReadStringAsBytes() (ret []byte) {
iter.ReportError("ReadString", `expects " or n`) iter.ReportError("ReadString", `expects " or n`)
return return
} }
end, escaped := iter.findStringEnd() end := iter.findStringEndWithoutEscape()
if end != -1 && !escaped { if end != -1 {
// fast path: reuse the underlying buffer // fast path: reuse the underlying buffer
ret = iter.buf[iter.head:end-1] ret = iter.buf[iter.head:end-1]
iter.head = end iter.head = end
@ -726,15 +677,9 @@ func (iter *Iterator) ReadBool() (ret bool) {
switch c { switch c {
case 't': case 't':
iter.skipUntilBreak() iter.skipUntilBreak()
if iter.Error != nil {
return
}
return true return true
case 'f': case 'f':
iter.skipUntilBreak() iter.skipUntilBreak()
if iter.Error != nil {
return
}
return false return false
default: default:
iter.ReportError("ReadBool", "expect t or f") iter.ReportError("ReadBool", "expect t or f")
@ -786,6 +731,70 @@ func (iter *Iterator) skipString() {
} }
} }
// adapted from: https://github.com/buger/jsonparser/blob/master/parser.go
// Tries to find the end of string
// Support if string contains escaped quote symbols.
func (iter *Iterator) findStringEnd() (int, bool) {
escaped := false
for i := iter.head; i < iter.tail; i++ {
c := iter.buf[i]
if c == '"' {
if !escaped {
return i + 1, false
} else {
j := i - 1
for {
if j < iter.head || iter.buf[j] != '\\' {
// even number of backslashes
// either end of buffer, or " found
return i + 1, true
}
j--
if j < iter.head || iter.buf[j] != '\\' {
// odd number of backslashes
// it is \" or \\\"
break
}
j--
}
}
} else if c == '\\' {
escaped = true
}
}
j := iter.tail - 1
for {
if j < iter.head || iter.buf[j] != '\\' {
// even number of backslashes
// either end of buffer, or " found
return -1, false // do not end with \
}
j--
if j < iter.head || iter.buf[j] != '\\' {
// odd number of backslashes
// it is \" or \\\"
break
}
j--
}
return -1, true // end with \
}
func (iter *Iterator) findStringEndWithoutEscape() int {
for i := iter.head; i < iter.tail; i++ {
c := iter.buf[i]
if c == '"' {
return i + 1
} else if c == '\\' {
return -1
}
}
return -1
}
func (iter *Iterator) skipArray() { func (iter *Iterator) skipArray() {
level := 1 level := 1
for { for {