mirror of
https://github.com/json-iterator/go.git
synced 2024-11-27 08:30:57 +02:00
test read string and read string as slice
This commit is contained in:
parent
e7ff7339b2
commit
6efc6c44ac
@ -55,7 +55,7 @@ func (iter *Iterator) readObjectStart() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readObjectField() (ret string) {
|
func (iter *Iterator) readObjectField() (ret string) {
|
||||||
str := iter.readStringAsBytes()
|
str := iter.ReadStringAsSlice()
|
||||||
if iter.skipWhitespacesWithoutLoadMore() {
|
if iter.skipWhitespacesWithoutLoadMore() {
|
||||||
if ret == "" {
|
if ret == "" {
|
||||||
ret = string(str)
|
ret = string(str)
|
||||||
|
@ -27,6 +27,15 @@ func (iter *Iterator) ReadString() (ret string) {
|
|||||||
copied[j] = c
|
copied[j] = c
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
|
if i == iter.tail {
|
||||||
|
if iter.loadMore() {
|
||||||
|
i = iter.head
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
iter.reportError("ReadString", "incomplete string")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
iter.head = i
|
iter.head = i
|
||||||
if j == len(copied) {
|
if j == len(copied) {
|
||||||
newBuf := make([]byte, len(copied) * 2)
|
newBuf := make([]byte, len(copied) * 2)
|
||||||
@ -108,22 +117,23 @@ func (iter *Iterator) readStringSlowPath(str []byte) (ret string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterator) readStringAsBytes() (ret []byte) {
|
func (iter *Iterator) ReadStringAsSlice() (ret []byte) {
|
||||||
c := iter.nextToken()
|
c := iter.nextToken()
|
||||||
if c == '"' {
|
if c == '"' {
|
||||||
for i := iter.head; i < iter.tail; i++ {
|
for i := iter.head; i < iter.tail; i++ {
|
||||||
c := iter.buf[i]
|
// require ascii string and no escape
|
||||||
if c == '"' {
|
// for: field name, base64, number
|
||||||
|
if iter.buf[i] == '"' {
|
||||||
// fast path: reuse the underlying buffer
|
// fast path: reuse the underlying buffer
|
||||||
ret = iter.buf[iter.head : i]
|
ret = iter.buf[iter.head : i]
|
||||||
iter.head = i + 1
|
iter.head = i + 1
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iter.head = iter.tail
|
|
||||||
readLen := iter.tail - iter.head
|
readLen := iter.tail - iter.head
|
||||||
copied := make([]byte, readLen, readLen * 2)
|
copied := make([]byte, readLen, readLen * 2)
|
||||||
copy(copied, iter.buf[iter.head:iter.tail])
|
copy(copied, iter.buf[iter.head:iter.tail])
|
||||||
|
iter.head = iter.tail
|
||||||
for iter.Error == nil {
|
for iter.Error == nil {
|
||||||
c := iter.readByte()
|
c := iter.readByte()
|
||||||
if c == '"' {
|
if c == '"' {
|
||||||
@ -131,7 +141,7 @@ func (iter *Iterator) readStringAsBytes() (ret []byte) {
|
|||||||
}
|
}
|
||||||
copied = append(copied, c)
|
copied = append(copied, c)
|
||||||
}
|
}
|
||||||
return
|
return copied
|
||||||
}
|
}
|
||||||
if c == 'n' {
|
if c == 'n' {
|
||||||
iter.skipUntilBreak()
|
iter.skipUntilBreak()
|
||||||
|
@ -275,7 +275,7 @@ func (iter *Iterator) ReadBool() (ret bool) {
|
|||||||
|
|
||||||
// ReadBase64 reads a json object as Base64 in byte slice
|
// ReadBase64 reads a json object as Base64 in byte slice
|
||||||
func (iter *Iterator) ReadBase64() (ret []byte) {
|
func (iter *Iterator) ReadBase64() (ret []byte) {
|
||||||
src := iter.readStringAsBytes()
|
src := iter.ReadStringAsSlice()
|
||||||
if iter.Error != nil {
|
if iter.Error != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -5,89 +5,57 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
"github.com/json-iterator/go/require"
|
"github.com/json-iterator/go/require"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_read_large_string(t *testing.T) {
|
func Test_read_normal_string(t *testing.T) {
|
||||||
should := require.New(t)
|
cases := map[string]string{
|
||||||
iter := ParseString(`"0123456789012345678901234567890123456789"`)
|
`"0123456789012345678901234567890123456789"`: `0123456789012345678901234567890123456789`,
|
||||||
should.Equal("0123456789012345678901234567890123456789", iter.ReadString())
|
`""`: ``,
|
||||||
}
|
`"hello"`: `hello`,
|
||||||
|
|
||||||
func Test_decode_string_empty(t *testing.T) {
|
|
||||||
iter := Parse(bytes.NewBufferString(`""`), 4096)
|
|
||||||
val := iter.ReadString()
|
|
||||||
if iter.Error != nil {
|
|
||||||
t.Fatal(iter.Error)
|
|
||||||
}
|
}
|
||||||
if val != "" {
|
for input, output := range cases {
|
||||||
t.Fatal(val)
|
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
|
||||||
|
should := require.New(t)
|
||||||
|
iter := ParseString(input)
|
||||||
|
should.Equal(output, iter.ReadString())
|
||||||
|
})
|
||||||
|
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
|
||||||
|
should := require.New(t)
|
||||||
|
iter := Parse(bytes.NewBufferString(input), 2)
|
||||||
|
should.Equal(output, iter.ReadString())
|
||||||
|
})
|
||||||
|
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
|
||||||
|
should := require.New(t)
|
||||||
|
iter := ParseString(input)
|
||||||
|
should.Equal(output, string(iter.ReadStringAsSlice()))
|
||||||
|
})
|
||||||
|
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
|
||||||
|
should := require.New(t)
|
||||||
|
iter := Parse(bytes.NewBufferString(input), 2)
|
||||||
|
should.Equal(output, string(iter.ReadStringAsSlice()))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_decode_string_hello(t *testing.T) {
|
func Test_read_exotic_string(t *testing.T) {
|
||||||
iter := Parse(bytes.NewBufferString(`"hello"`), 4096)
|
cases := map[string]string{
|
||||||
val := iter.ReadString()
|
`"hel\"lo"`: `hel"lo`,
|
||||||
if iter.Error != nil {
|
`"hel\nlo"`: "hel\nlo",
|
||||||
t.Fatal(iter.Error)
|
`"\u4e2d\u6587"`: "中文",
|
||||||
|
`"\ud83d\udc4a"`: "\xf0\x9f\x91\x8a", // surrogate
|
||||||
}
|
}
|
||||||
if val != "hello" {
|
for input, output := range cases {
|
||||||
t.Fatal(val)
|
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
|
||||||
}
|
should := require.New(t)
|
||||||
}
|
iter := ParseString(input)
|
||||||
|
should.Equal(output, iter.ReadString())
|
||||||
func Test_decode_string_escape_quote(t *testing.T) {
|
})
|
||||||
iter := Parse(bytes.NewBufferString(`"hel\"lo"`), 4096)
|
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
|
||||||
val := iter.ReadString()
|
should := require.New(t)
|
||||||
if iter.Error != nil {
|
iter := Parse(bytes.NewBufferString(input), 2)
|
||||||
t.Fatal(iter.Error)
|
should.Equal(output, iter.ReadString())
|
||||||
}
|
})
|
||||||
if val != `hel"lo` {
|
|
||||||
t.Fatal(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_decode_string_escape_newline(t *testing.T) {
|
|
||||||
iter := Parse(bytes.NewBufferString(`"hel\nlo"`), 4096)
|
|
||||||
val := iter.ReadString()
|
|
||||||
if iter.Error != nil {
|
|
||||||
t.Fatal(iter.Error)
|
|
||||||
}
|
|
||||||
if val != "hel\nlo" {
|
|
||||||
t.Fatal(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_decode_string_escape_unicode(t *testing.T) {
|
|
||||||
iter := Parse(bytes.NewBufferString(`"\u4e2d\u6587"`), 4096)
|
|
||||||
val := iter.ReadString()
|
|
||||||
if iter.Error != nil {
|
|
||||||
t.Fatal(iter.Error)
|
|
||||||
}
|
|
||||||
if val != "中文" {
|
|
||||||
t.Fatal(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_decode_string_escape_unicode_with_surrogate(t *testing.T) {
|
|
||||||
iter := Parse(bytes.NewBufferString(`"\ud83d\udc4a"`), 4096)
|
|
||||||
val := iter.ReadString()
|
|
||||||
if iter.Error != nil {
|
|
||||||
t.Fatal(iter.Error)
|
|
||||||
}
|
|
||||||
if val != "\xf0\x9f\x91\x8a" {
|
|
||||||
t.Fatal(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_decode_string_as_bytes(t *testing.T) {
|
|
||||||
iter := Parse(bytes.NewBufferString(`"hello""world"`), 4096)
|
|
||||||
val := string(iter.readStringAsBytes())
|
|
||||||
if val != "hello" {
|
|
||||||
t.Fatal(val)
|
|
||||||
}
|
|
||||||
val = string(iter.readStringAsBytes())
|
|
||||||
if val != "world" {
|
|
||||||
t.Fatal(val)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +101,7 @@ func Benchmark_jsoniter_string_as_bytes(b *testing.B) {
|
|||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
iter.ResetBytes(iter.buf)
|
iter.ResetBytes(iter.buf)
|
||||||
iter.readStringAsBytes()
|
iter.ReadStringAsSlice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user