bytes substring optimization

This commit is contained in:
Josh Baker 2016-09-08 08:34:01 -07:00
parent 124a25db9e
commit b39aa6075f
2 changed files with 28 additions and 4 deletions

View File

@ -2,6 +2,7 @@
package gjson
import (
"reflect"
"strconv"
"unsafe"
@ -1140,10 +1141,29 @@ func GetBytes(json []byte, path string) Result {
if json != nil {
// unsafe cast to string
result = Get(*(*string)(unsafe.Pointer(&json)), path)
// copy of string data for safety
// copy of string data for safety.
rawh := *(*reflect.SliceHeader)(unsafe.Pointer(&result.Raw))
strh := *(*reflect.SliceHeader)(unsafe.Pointer(&result.Str))
if strh.Data == 0 {
if rawh.Data == 0 {
result.Raw = ""
} else {
result.Raw = string(*(*[]byte)(unsafe.Pointer(&result.Raw)))
}
result.Str = ""
} else if rawh.Data == 0 {
result.Raw = ""
result.Str = string(*(*[]byte)(unsafe.Pointer(&result.Str)))
} else if strh.Data >= rawh.Data && strh.Len <= rawh.Len {
// Str is a substring of Raw.
result.Raw = string(*(*[]byte)(unsafe.Pointer(&result.Raw)))
start := int(strh.Data - rawh.Data)
result.Str = result.Raw[start : start+strh.Len]
} else {
result.Raw = string(*(*[]byte)(unsafe.Pointer(&result.Raw)))
result.Str = string(*(*[]byte)(unsafe.Pointer(&result.Str)))
}
}
return result
}

View File

@ -128,11 +128,15 @@ var basicJSON = `{"age":100, "name":{"here":"B\\\"R"},
var basicJSONB = []byte(basicJSON)
func TestByteSafety(t *testing.T) {
jsonb := []byte(`{"name":"Janet"}`)
jsonb := []byte(`{"name":"Janet","age":38}`)
mtok := GetBytes(jsonb, "name")
if mtok.String() != "Janet" {
t.Fatalf("expected %v, got %v", "Jason", mtok.String())
}
mtok2 := GetBytes(jsonb, "age")
if mtok2.Raw != "38" {
t.Fatalf("expected %v, got %v", "Jason", mtok2.Raw)
}
jsonb[9] = 'T'
jsonb[12] = 'd'
jsonb[13] = 'y'