mirror of
https://github.com/json-iterator/go.git
synced 2025-04-20 11:28:49 +02:00
#61 read any reuse skip impl
This commit is contained in:
parent
54dbcda64d
commit
1ec246d16b
144
feature_any.go
144
feature_any.go
@ -167,137 +167,45 @@ func (iter *Iterator) readAny() Any {
|
|||||||
return iter.readObjectAny()
|
return iter.readObjectAny()
|
||||||
case '[':
|
case '[':
|
||||||
return iter.readArrayAny()
|
return iter.readArrayAny()
|
||||||
|
case '-':
|
||||||
|
return iter.readNumberAny(false)
|
||||||
default:
|
default:
|
||||||
return iter.readNumberAny(c)
|
return iter.readNumberAny(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readNumberAny(firstByte byte) Any {
|
func (iter *Iterator) readNumberAny(positive bool) Any {
|
||||||
dotFound := false
|
iter.startCapture(iter.head - 1)
|
||||||
lazyBuf := make([]byte, 1, 8)
|
dotFound := iter.skipNumberAndTellDotFoundOrNot()
|
||||||
lazyBuf[0] = firstByte
|
lazyBuf := iter.stopCapture()
|
||||||
for {
|
if dotFound {
|
||||||
for i := iter.head; i < iter.tail; i++ {
|
return &float64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
||||||
c := iter.buf[i]
|
} else {
|
||||||
if c == '.' {
|
if positive {
|
||||||
dotFound = true
|
return &uint64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
||||||
continue
|
} else {
|
||||||
}
|
return &int64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
||||||
switch c {
|
|
||||||
case ' ', '\n', '\r', '\t', ',', '}', ']':
|
|
||||||
lazyBuf = append(lazyBuf, iter.buf[iter.head:i]...)
|
|
||||||
iter.head = i
|
|
||||||
if dotFound {
|
|
||||||
return &float64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
|
||||||
} else {
|
|
||||||
if firstByte == '-' {
|
|
||||||
return &int64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
|
||||||
} else {
|
|
||||||
return &uint64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
|
|
||||||
if !iter.loadMore() {
|
|
||||||
iter.head = iter.tail
|
|
||||||
if dotFound {
|
|
||||||
return &float64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
|
||||||
} else {
|
|
||||||
if firstByte == '-' {
|
|
||||||
return &int64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
|
||||||
} else {
|
|
||||||
return &uint64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readStringAny() Any {
|
func (iter *Iterator) readStringAny() Any {
|
||||||
lazyBuf := make([]byte, 1, 8)
|
iter.startCapture(iter.head - 1)
|
||||||
lazyBuf[0] = '"'
|
iter.skipString()
|
||||||
for {
|
lazyBuf := iter.stopCapture()
|
||||||
end, escaped := iter.findStringEnd()
|
return &stringLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, ""}
|
||||||
if end == -1 {
|
|
||||||
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
|
|
||||||
if !iter.loadMore() {
|
|
||||||
iter.reportError("readStringAny", "incomplete string")
|
|
||||||
return &invalidAny{}
|
|
||||||
}
|
|
||||||
if escaped {
|
|
||||||
iter.head = 1 // skip the first char as last char read is \
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lazyBuf = append(lazyBuf, iter.buf[iter.head:end]...)
|
|
||||||
iter.head = end
|
|
||||||
return &stringLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, ""}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readObjectAny() Any {
|
func (iter *Iterator) readObjectAny() Any {
|
||||||
level := 1
|
iter.startCapture(iter.head - 1)
|
||||||
lazyBuf := make([]byte, 1, 32)
|
iter.skipObject()
|
||||||
lazyBuf[0] = '{'
|
lazyBuf := iter.stopCapture()
|
||||||
for {
|
return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
|
||||||
start := iter.head
|
|
||||||
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
|
|
||||||
lazyBuf = append(lazyBuf, iter.buf[start:iter.head]...)
|
|
||||||
return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
|
|
||||||
if !iter.loadMore() {
|
|
||||||
iter.reportError("skipObject", "incomplete object")
|
|
||||||
return &invalidAny{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readArrayAny() Any {
|
func (iter *Iterator) readArrayAny() Any {
|
||||||
level := 1
|
iter.startCapture(iter.head - 1)
|
||||||
lazyBuf := make([]byte, 1, 32)
|
iter.skipArray()
|
||||||
lazyBuf[0] = '['
|
lazyBuf := iter.stopCapture()
|
||||||
for {
|
return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
|
||||||
start := iter.head
|
|
||||||
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
|
|
||||||
lazyBuf = append(lazyBuf, iter.buf[start:iter.head]...)
|
|
||||||
return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
|
|
||||||
if !iter.loadMore() {
|
|
||||||
iter.reportError("skipArray", "incomplete array")
|
|
||||||
return &invalidAny{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,7 @@ func (iter *Iterator) readByte() (ret byte) {
|
|||||||
func (iter *Iterator) loadMore() bool {
|
func (iter *Iterator) loadMore() bool {
|
||||||
if iter.reader == nil {
|
if iter.reader == nil {
|
||||||
if iter.Error == nil {
|
if iter.Error == nil {
|
||||||
|
iter.head = iter.tail
|
||||||
iter.Error = io.EOF
|
iter.Error = io.EOF
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -30,7 +30,7 @@ func (iter *Iterator) ReadBool() (ret bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) SkipAndReturnBytes() []byte {
|
func (iter *Iterator) SkipAndReturnBytes() []byte {
|
||||||
iter.startCapture()
|
iter.startCapture(iter.head)
|
||||||
iter.Skip()
|
iter.Skip()
|
||||||
return iter.stopCapture()
|
return iter.stopCapture()
|
||||||
}
|
}
|
||||||
@ -40,11 +40,11 @@ type captureBuffer struct {
|
|||||||
captured []byte
|
captured []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) startCapture() {
|
func (iter *Iterator) startCapture(captureStartedAt int) {
|
||||||
if iter.captured != nil {
|
if iter.captured != nil {
|
||||||
panic("already in capture mode")
|
panic("already in capture mode")
|
||||||
}
|
}
|
||||||
iter.captureStartedAt = iter.head
|
iter.captureStartedAt = captureStartedAt
|
||||||
iter.captured = make([]byte, 0, 32)
|
iter.captured = make([]byte, 0, 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ func (iter *Iterator) Skip() {
|
|||||||
case 'f':
|
case 'f':
|
||||||
iter.skipFixedBytes(4) // false
|
iter.skipFixedBytes(4) // false
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
iter.skipUntilBreak()
|
iter.skipNumber()
|
||||||
case '[':
|
case '[':
|
||||||
iter.skipArray()
|
iter.skipArray()
|
||||||
case '{':
|
case '{':
|
||||||
@ -209,8 +209,7 @@ func (iter *Iterator) skipObject() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) skipUntilBreak() {
|
func (iter *Iterator) skipNumber() {
|
||||||
// true, false, null, number
|
|
||||||
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]
|
||||||
@ -226,6 +225,25 @@ func (iter *Iterator) skipUntilBreak() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (iter *Iterator) skipNumberAndTellDotFoundOrNot() bool {
|
||||||
|
dotFound := false
|
||||||
|
for {
|
||||||
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
|
c := iter.buf[i]
|
||||||
|
switch c {
|
||||||
|
case ' ', '\n', '\r', '\t', ',', '}', ']':
|
||||||
|
iter.head = i
|
||||||
|
return dotFound
|
||||||
|
case '.':
|
||||||
|
dotFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !iter.loadMore() {
|
||||||
|
return dotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (iter *Iterator) skipFixedBytes(n int) {
|
func (iter *Iterator) skipFixedBytes(n int) {
|
||||||
iter.head += n
|
iter.head += n
|
||||||
if iter.head >= iter.tail {
|
if iter.head >= iter.tail {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user