1
0
mirror of https://github.com/json-iterator/go.git synced 2025-03-20 20:54:55 +02:00
This commit is contained in:
Tao Wen 2016-12-06 13:48:03 +08:00
parent 6a46bc9513
commit c457aeaac2
2 changed files with 92 additions and 27 deletions

View File

@ -26,7 +26,6 @@ func init() {
}
}
type Iterator struct {
reader io.Reader
buf []byte
@ -57,14 +56,30 @@ func ParseBytes(input []byte) *Iterator {
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 {
return ParseBytes([]byte(input))
}
func (iter *Iterator) skipWhitespaces() {
c := iter.readByte()
for c == ' ' || c == '\n' || c == '\t' {
c = iter.readByte()
for {
switch c {
case ' ', '\n', '\t', 'r':
c = iter.readByte()
continue
}
break
}
iter.unreadByte()
}
@ -258,29 +273,20 @@ func (iter *Iterator) ReadInt64() (ret int64) {
func (iter *Iterator) ReadString() (ret string) {
str := make([]byte, 0, 8)
c := iter.readByte()
if iter.Error != nil {
if c == 'n' {
iter.skipNull()
return
}
switch c {
case 'n':
iter.skipNull()
if iter.Error != nil {
return
}
return ""
case '"':
// nothing
default:
if c != '"' {
iter.ReportError("ReadString", `expects " or n`)
return
}
for {
for iter.Error == nil {
c = iter.readByte()
if iter.Error != nil {
return
if c == '"' {
return string(str)
}
switch c {
case '\\':
if c == '\\' {
c = iter.readByte()
if iter.Error != nil {
return
@ -340,12 +346,11 @@ func (iter *Iterator) ReadString() (ret string) {
`invalid escape char after \`)
return
}
case '"':
return *(*string)(unsafe.Pointer(&str))
default:
} else {
str = append(str, c)
}
}
return
}
func (iter *Iterator) readU4() (ret rune) {
@ -434,9 +439,6 @@ func (iter *Iterator) ReadArray() (ret bool) {
switch c {
case 'n': {
iter.skipNull()
if iter.Error != nil {
return
}
return false // null
}
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) {
iter.skipWhitespaces()
c := iter.readByte()

View File

@ -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) {
iter := ParseString(`[`)
iter.ReadArray()
@ -117,16 +128,32 @@ func Test_whitespace_before_comma(t *testing.T) {
}
}
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++ {
iter := ParseString(`[1,2,3]`)
iter.Reuse(input)
for iter.ReadArray() {
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) {
for n := 0; n < b.N; n++ {
result := []interface{}{}