mirror of
https://github.com/json-iterator/go.git
synced 2025-06-12 22:47:42 +02:00
optimize skip
This commit is contained in:
parent
ea435e3473
commit
46d96fb105
114
jsoniter.go
114
jsoniter.go
@ -89,6 +89,7 @@ func (iter *Iterator) skipWhitespaces() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) nextToken() byte {
|
func (iter *Iterator) nextToken() byte {
|
||||||
|
// a variation of skip whitespaces, returning the next non-whitespace token
|
||||||
for {
|
for {
|
||||||
for i := iter.head; i < iter.tail; i++ {
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
c := iter.buf[i]
|
c := iter.buf[i]
|
||||||
@ -353,24 +354,6 @@ func (iter *Iterator) findStringEnd() (int, bool) {
|
|||||||
return -1, true // end with \
|
return -1, true // end with \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (iter *Iterator) skipUntilBreak() {
|
|
||||||
// true, false, null, number
|
|
||||||
for {
|
|
||||||
for i := iter.head; i < iter.tail; i++ {
|
|
||||||
c := iter.buf[i]
|
|
||||||
switch c {
|
|
||||||
case ' ', '\n', '\r', '\t', ',', '}', ']':
|
|
||||||
iter.head = i
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!iter.loadMore()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iter *Iterator) ReadStringAsBytes() (ret []byte) {
|
func (iter *Iterator) ReadStringAsBytes() (ret []byte) {
|
||||||
c := iter.readByte()
|
c := iter.readByte()
|
||||||
if c == 'n' {
|
if c == 'n' {
|
||||||
@ -804,64 +787,71 @@ func (iter *Iterator) skipString() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) skipArray() {
|
func (iter *Iterator) skipArray() {
|
||||||
c := iter.nextToken()
|
level := 1
|
||||||
if c == ']' {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
iter.unreadByte()
|
|
||||||
}
|
|
||||||
for {
|
for {
|
||||||
if iter.Error != nil {
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
|
switch iter.buf[i] {
|
||||||
|
case '"': // If inside string, skip it
|
||||||
|
iter.head = i + 1
|
||||||
|
iter.skipString()
|
||||||
|
i = iter.head - 1 // it will be i++ soon
|
||||||
|
case '[': // If open symbol, increase level
|
||||||
|
level++
|
||||||
|
case ']': // If close symbol, increase level
|
||||||
|
level--
|
||||||
|
|
||||||
|
// If we have returned to the original level, we're done
|
||||||
|
if level == 0 {
|
||||||
|
iter.head = i + 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
iter.Skip()
|
}
|
||||||
c = iter.nextToken()
|
}
|
||||||
switch c {
|
if (!iter.loadMore()) {
|
||||||
case ',':
|
|
||||||
iter.skipWhitespaces()
|
|
||||||
continue
|
|
||||||
case ']':
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
iter.ReportError("skipArray", "expects , or ]")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) skipObject() {
|
func (iter *Iterator) skipObject() {
|
||||||
c := iter.nextToken()
|
level := 1
|
||||||
if c == '}' {
|
|
||||||
return // end of object
|
|
||||||
} else {
|
|
||||||
iter.unreadByte()
|
|
||||||
}
|
|
||||||
for {
|
for {
|
||||||
c = iter.nextToken()
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
if c != '"' {
|
switch iter.buf[i] {
|
||||||
iter.ReportError("skipObject", `expects "`)
|
case '"': // If inside string, skip it
|
||||||
return
|
iter.head = i + 1
|
||||||
}
|
|
||||||
iter.skipString()
|
iter.skipString()
|
||||||
c = iter.nextToken()
|
i = iter.head - 1 // it will be i++ soon
|
||||||
if c != ':' {
|
case '{': // If open symbol, increase level
|
||||||
iter.ReportError("skipObject", `expects :`)
|
level++
|
||||||
|
case '}': // If close symbol, increase level
|
||||||
|
level--
|
||||||
|
|
||||||
|
// If we have returned to the original level, we're done
|
||||||
|
if level == 0 {
|
||||||
|
iter.head = i + 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
iter.skipWhitespaces()
|
|
||||||
if iter.Error != nil {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
iter.Skip()
|
}
|
||||||
c = iter.nextToken()
|
if (!iter.loadMore()) {
|
||||||
switch c {
|
return
|
||||||
case ',':
|
}
|
||||||
iter.skipWhitespaces()
|
}
|
||||||
continue
|
}
|
||||||
case '}':
|
|
||||||
return // end of object
|
func (iter *Iterator) skipUntilBreak() {
|
||||||
default:
|
// true, false, null, number
|
||||||
iter.ReportError("skipObject", "expects , or }")
|
for {
|
||||||
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
|
c := iter.buf[i]
|
||||||
|
switch c {
|
||||||
|
case ' ', '\n', '\r', '\t', ',', '}', ']':
|
||||||
|
iter.head = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!iter.loadMore()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,3 +136,35 @@ func Test_skip_string(t *testing.T) {
|
|||||||
t.Fatal(iter.head)
|
t.Fatal(iter.head)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_skip_object(t *testing.T) {
|
||||||
|
iter := ParseString(`}`)
|
||||||
|
iter.skipObject()
|
||||||
|
if iter.head != 1 {
|
||||||
|
t.Fatal(iter.head)
|
||||||
|
}
|
||||||
|
iter = ParseString(`a}`)
|
||||||
|
iter.skipObject()
|
||||||
|
if iter.head != 2 {
|
||||||
|
t.Fatal(iter.head)
|
||||||
|
}
|
||||||
|
iter = ParseString(`{}}a`)
|
||||||
|
iter.skipObject()
|
||||||
|
if iter.head != 3 {
|
||||||
|
t.Fatal(iter.head)
|
||||||
|
}
|
||||||
|
reader := &StagedReader{
|
||||||
|
r1: `{`,
|
||||||
|
r2: `}}a`,
|
||||||
|
}
|
||||||
|
iter = Parse(reader, 4096)
|
||||||
|
iter.skipObject()
|
||||||
|
if iter.head != 2 {
|
||||||
|
t.Fatal(iter.head)
|
||||||
|
}
|
||||||
|
iter = ParseString(`"}"}a`)
|
||||||
|
iter.skipObject()
|
||||||
|
if iter.head != 4 {
|
||||||
|
t.Fatal(iter.head)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -66,26 +66,6 @@ func Test_skip_empty_array(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_skip_object(t *testing.T) {
|
|
||||||
iter := ParseString(`[ {"a" : {"b": "c"}, "d": 102 }, "b"]`)
|
|
||||||
iter.ReadArray()
|
|
||||||
iter.Skip()
|
|
||||||
iter.ReadArray()
|
|
||||||
if iter.ReadString() != "b" {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_skip_empty_object(t *testing.T) {
|
|
||||||
iter := ParseString(`[ { }, "b"]`)
|
|
||||||
iter.ReadArray()
|
|
||||||
iter.Skip()
|
|
||||||
iter.ReadArray()
|
|
||||||
if iter.ReadString() != "b" {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_skip_nested(t *testing.T) {
|
func Test_skip_nested(t *testing.T) {
|
||||||
iter := ParseString(`[ {"a" : [{"b": "c"}], "d": 102 }, "b"]`)
|
iter := ParseString(`[ {"a" : [{"b": "c"}], "d": 102 }, "b"]`)
|
||||||
iter.ReadArray()
|
iter.ReadArray()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user