forked from mirror/gjson
Add appengine support
This commit is contained in:
parent
afaeb95620
commit
f123b34087
55
gjson.go
55
gjson.go
|
@ -13,7 +13,6 @@ import (
|
|||
"time"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
|
||||
"github.com/tidwall/match"
|
||||
)
|
||||
|
@ -1385,64 +1384,14 @@ func Get(json, path string) Result {
|
|||
}
|
||||
}
|
||||
}
|
||||
if len(c.value.Raw) > 0 && !c.calcd {
|
||||
jhdr := *(*reflect.StringHeader)(unsafe.Pointer(&json))
|
||||
rhdr := *(*reflect.StringHeader)(unsafe.Pointer(&(c.value.Raw)))
|
||||
c.value.Index = int(rhdr.Data - jhdr.Data)
|
||||
if c.value.Index < 0 || c.value.Index >= len(json) {
|
||||
c.value.Index = 0
|
||||
}
|
||||
}
|
||||
fillIndex(json, c)
|
||||
return c.value
|
||||
}
|
||||
func fromBytesGet(result Result) Result {
|
||||
// safely get the string headers
|
||||
rawhi := *(*reflect.StringHeader)(unsafe.Pointer(&result.Raw))
|
||||
strhi := *(*reflect.StringHeader)(unsafe.Pointer(&result.Str))
|
||||
// create byte slice headers
|
||||
rawh := reflect.SliceHeader{Data: rawhi.Data, Len: rawhi.Len}
|
||||
strh := reflect.SliceHeader{Data: strhi.Data, Len: strhi.Len}
|
||||
if strh.Data == 0 {
|
||||
// str is nil
|
||||
if rawh.Data == 0 {
|
||||
// raw is nil
|
||||
result.Raw = ""
|
||||
} else {
|
||||
// raw has data, safely copy the slice header to a string
|
||||
result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
|
||||
}
|
||||
result.Str = ""
|
||||
} else if rawh.Data == 0 {
|
||||
// raw is nil
|
||||
result.Raw = ""
|
||||
// str has data, safely copy the slice header to a string
|
||||
result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
|
||||
} else if strh.Data >= rawh.Data &&
|
||||
int(strh.Data)+strh.Len <= int(rawh.Data)+rawh.Len {
|
||||
// Str is a substring of Raw.
|
||||
start := int(strh.Data - rawh.Data)
|
||||
// safely copy the raw slice header
|
||||
result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
|
||||
// substring the raw
|
||||
result.Str = result.Raw[start : start+strh.Len]
|
||||
} else {
|
||||
// safely copy both the raw and str slice headers to strings
|
||||
result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
|
||||
result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GetBytes searches json for the specified path.
|
||||
// If working with bytes, this method preferred over Get(string(data), path)
|
||||
func GetBytes(json []byte, path string) Result {
|
||||
var result Result
|
||||
if json != nil {
|
||||
// unsafe cast to string
|
||||
result = Get(*(*string)(unsafe.Pointer(&json)), path)
|
||||
result = fromBytesGet(result)
|
||||
}
|
||||
return result
|
||||
return getBytes(json, path)
|
||||
}
|
||||
|
||||
// runeit returns the rune from the the \uXXXX
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
//+build appengine
|
||||
|
||||
package gjson
|
||||
|
||||
func getBytes(json []byte, path string) Result {
|
||||
return Get(string(json), path)
|
||||
}
|
||||
func fillIndex(json string, c *parseContext) {
|
||||
// noop. Use zero for the Index value.
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
//+build !appengine
|
||||
|
||||
package gjson
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// getBytes casts the input json bytes to a string and safely returns the
|
||||
// results as uniquely allocated data. This operation is intended to minimize
|
||||
// copies and allocations for the large json string->[]byte.
|
||||
func getBytes(json []byte, path string) Result {
|
||||
var result Result
|
||||
if json != nil {
|
||||
// unsafe cast to string
|
||||
result = Get(*(*string)(unsafe.Pointer(&json)), path)
|
||||
result = fromBytesGet(result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func fromBytesGet(result Result) Result {
|
||||
// safely get the string headers
|
||||
rawhi := *(*reflect.StringHeader)(unsafe.Pointer(&result.Raw))
|
||||
strhi := *(*reflect.StringHeader)(unsafe.Pointer(&result.Str))
|
||||
// create byte slice headers
|
||||
rawh := reflect.SliceHeader{Data: rawhi.Data, Len: rawhi.Len}
|
||||
strh := reflect.SliceHeader{Data: strhi.Data, Len: strhi.Len}
|
||||
if strh.Data == 0 {
|
||||
// str is nil
|
||||
if rawh.Data == 0 {
|
||||
// raw is nil
|
||||
result.Raw = ""
|
||||
} else {
|
||||
// raw has data, safely copy the slice header to a string
|
||||
result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
|
||||
}
|
||||
result.Str = ""
|
||||
} else if rawh.Data == 0 {
|
||||
// raw is nil
|
||||
result.Raw = ""
|
||||
// str has data, safely copy the slice header to a string
|
||||
result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
|
||||
} else if strh.Data >= rawh.Data &&
|
||||
int(strh.Data)+strh.Len <= int(rawh.Data)+rawh.Len {
|
||||
// Str is a substring of Raw.
|
||||
start := int(strh.Data - rawh.Data)
|
||||
// safely copy the raw slice header
|
||||
result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
|
||||
// substring the raw
|
||||
result.Str = result.Raw[start : start+strh.Len]
|
||||
} else {
|
||||
// safely copy both the raw and str slice headers to strings
|
||||
result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
|
||||
result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// fillIndex finds the position of Raw data and assigns it to the Index field
|
||||
// of the resulting value. If the position cannot be found then Index zero is
|
||||
// used instead.
|
||||
func fillIndex(json string, c *parseContext) {
|
||||
if len(c.value.Raw) > 0 && !c.calcd {
|
||||
jhdr := *(*reflect.StringHeader)(unsafe.Pointer(&json))
|
||||
rhdr := *(*reflect.StringHeader)(unsafe.Pointer(&(c.value.Raw)))
|
||||
c.value.Index = int(rhdr.Data - jhdr.Data)
|
||||
if c.value.Index < 0 || c.value.Index >= len(json) {
|
||||
c.value.Index = 0
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue