forked from mirror/gjson
bytes substring optimization
This commit is contained in:
parent
124a25db9e
commit
b39aa6075f
26
gjson.go
26
gjson.go
|
@ -2,6 +2,7 @@
|
||||||
package gjson
|
package gjson
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
@ -1140,9 +1141,28 @@ func GetBytes(json []byte, path string) Result {
|
||||||
if json != nil {
|
if json != nil {
|
||||||
// unsafe cast to string
|
// unsafe cast to string
|
||||||
result = Get(*(*string)(unsafe.Pointer(&json)), path)
|
result = Get(*(*string)(unsafe.Pointer(&json)), path)
|
||||||
// copy of string data for safety
|
// copy of string data for safety.
|
||||||
result.Raw = string(*(*[]byte)(unsafe.Pointer(&result.Raw)))
|
rawh := *(*reflect.SliceHeader)(unsafe.Pointer(&result.Raw))
|
||||||
result.Str = string(*(*[]byte)(unsafe.Pointer(&result.Str)))
|
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
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,11 +128,15 @@ var basicJSON = `{"age":100, "name":{"here":"B\\\"R"},
|
||||||
var basicJSONB = []byte(basicJSON)
|
var basicJSONB = []byte(basicJSON)
|
||||||
|
|
||||||
func TestByteSafety(t *testing.T) {
|
func TestByteSafety(t *testing.T) {
|
||||||
jsonb := []byte(`{"name":"Janet"}`)
|
jsonb := []byte(`{"name":"Janet","age":38}`)
|
||||||
mtok := GetBytes(jsonb, "name")
|
mtok := GetBytes(jsonb, "name")
|
||||||
if mtok.String() != "Janet" {
|
if mtok.String() != "Janet" {
|
||||||
t.Fatalf("expected %v, got %v", "Jason", mtok.String())
|
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[9] = 'T'
|
||||||
jsonb[12] = 'd'
|
jsonb[12] = 'd'
|
||||||
jsonb[13] = 'y'
|
jsonb[13] = 'y'
|
||||||
|
|
Loading…
Reference in New Issue