mirror of
https://github.com/json-iterator/go.git
synced 2025-01-20 18:48:32 +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()
|
||||
case '[':
|
||||
return iter.readArrayAny()
|
||||
case '-':
|
||||
return iter.readNumberAny(false)
|
||||
default:
|
||||
return iter.readNumberAny(c)
|
||||
return iter.readNumberAny(true)
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) readNumberAny(firstByte byte) Any {
|
||||
dotFound := false
|
||||
lazyBuf := make([]byte, 1, 8)
|
||||
lazyBuf[0] = firstByte
|
||||
for {
|
||||
for i := iter.head; i < iter.tail; i++ {
|
||||
c := iter.buf[i]
|
||||
if c == '.' {
|
||||
dotFound = true
|
||||
continue
|
||||
}
|
||||
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) readNumberAny(positive bool) Any {
|
||||
iter.startCapture(iter.head - 1)
|
||||
dotFound := iter.skipNumberAndTellDotFoundOrNot()
|
||||
lazyBuf := iter.stopCapture()
|
||||
if dotFound {
|
||||
return &float64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
||||
} else {
|
||||
if positive {
|
||||
return &uint64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
||||
} else {
|
||||
return &int64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) readStringAny() Any {
|
||||
lazyBuf := make([]byte, 1, 8)
|
||||
lazyBuf[0] = '"'
|
||||
for {
|
||||
end, escaped := iter.findStringEnd()
|
||||
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, ""}
|
||||
}
|
||||
}
|
||||
iter.startCapture(iter.head - 1)
|
||||
iter.skipString()
|
||||
lazyBuf := iter.stopCapture()
|
||||
return &stringLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, ""}
|
||||
}
|
||||
|
||||
func (iter *Iterator) readObjectAny() Any {
|
||||
level := 1
|
||||
lazyBuf := make([]byte, 1, 32)
|
||||
lazyBuf[0] = '{'
|
||||
for {
|
||||
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{}
|
||||
}
|
||||
}
|
||||
iter.startCapture(iter.head - 1)
|
||||
iter.skipObject()
|
||||
lazyBuf := iter.stopCapture()
|
||||
return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
|
||||
}
|
||||
|
||||
func (iter *Iterator) readArrayAny() Any {
|
||||
level := 1
|
||||
lazyBuf := make([]byte, 1, 32)
|
||||
lazyBuf[0] = '['
|
||||
for {
|
||||
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{}
|
||||
}
|
||||
}
|
||||
iter.startCapture(iter.head - 1)
|
||||
iter.skipArray()
|
||||
lazyBuf := iter.stopCapture()
|
||||
return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
|
||||
}
|
||||
|
@ -210,6 +210,7 @@ func (iter *Iterator) readByte() (ret byte) {
|
||||
func (iter *Iterator) loadMore() bool {
|
||||
if iter.reader == nil {
|
||||
if iter.Error == nil {
|
||||
iter.head = iter.tail
|
||||
iter.Error = io.EOF
|
||||
}
|
||||
return false
|
||||
|
@ -30,7 +30,7 @@ func (iter *Iterator) ReadBool() (ret bool) {
|
||||
}
|
||||
|
||||
func (iter *Iterator) SkipAndReturnBytes() []byte {
|
||||
iter.startCapture()
|
||||
iter.startCapture(iter.head)
|
||||
iter.Skip()
|
||||
return iter.stopCapture()
|
||||
}
|
||||
@ -40,11 +40,11 @@ type captureBuffer struct {
|
||||
captured []byte
|
||||
}
|
||||
|
||||
func (iter *Iterator) startCapture() {
|
||||
func (iter *Iterator) startCapture(captureStartedAt int) {
|
||||
if iter.captured != nil {
|
||||
panic("already in capture mode")
|
||||
}
|
||||
iter.captureStartedAt = iter.head
|
||||
iter.captureStartedAt = captureStartedAt
|
||||
iter.captured = make([]byte, 0, 32)
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ func (iter *Iterator) Skip() {
|
||||
case 'f':
|
||||
iter.skipFixedBytes(4) // false
|
||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
iter.skipUntilBreak()
|
||||
iter.skipNumber()
|
||||
case '[':
|
||||
iter.skipArray()
|
||||
case '{':
|
||||
@ -209,8 +209,7 @@ func (iter *Iterator) skipObject() {
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *Iterator) skipUntilBreak() {
|
||||
// true, false, null, number
|
||||
func (iter *Iterator) skipNumber() {
|
||||
for {
|
||||
for i := iter.head; i < iter.tail; 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) {
|
||||
iter.head += n
|
||||
if iter.head >= iter.tail {
|
||||
|
Loading…
x
Reference in New Issue
Block a user