forked from mirror/gjson
lessen frequency of assignments in path routine
This commit is contained in:
parent
81391efb66
commit
a6e9688393
122
gjson.go
122
gjson.go
|
@ -490,43 +490,64 @@ func parseLiteral(json string, i int) (int, string) {
|
||||||
return i, json[s:]
|
return i, json[s:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseArrayPath(path string) (
|
type arrayPathResult struct {
|
||||||
part string, npath string, more bool, alogok bool, arrch bool, alogkey string,
|
part string
|
||||||
) {
|
path string
|
||||||
|
more bool
|
||||||
|
alogok bool
|
||||||
|
arrch bool
|
||||||
|
alogkey string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseArrayPath(path string) (r arrayPathResult) {
|
||||||
for i := 0; i < len(path); i++ {
|
for i := 0; i < len(path); i++ {
|
||||||
if path[i] == '.' {
|
if path[i] == '.' {
|
||||||
return path[:i], path[i+1:], true, alogok, arrch, alogkey
|
r.part = path[:i]
|
||||||
|
r.path = path[i+1:]
|
||||||
|
r.more = true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if path[i] == '#' {
|
if path[i] == '#' {
|
||||||
arrch = true
|
r.arrch = true
|
||||||
if i == 0 && len(path) > 1 && path[1] == '.' {
|
if i == 0 && len(path) > 1 && path[1] == '.' {
|
||||||
alogok = true
|
r.alogok = true
|
||||||
alogkey = path[2:]
|
r.alogkey = path[2:]
|
||||||
path = path[:1]
|
r.path = path[:1]
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return path, "", false, alogok, arrch, alogkey
|
r.part = path
|
||||||
|
r.path = ""
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseObjectPath(path string) (
|
type objectPathResult struct {
|
||||||
part string, npath string, wild bool, uc bool, more bool,
|
part string
|
||||||
) {
|
path string
|
||||||
|
wild bool
|
||||||
|
uc bool
|
||||||
|
more bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseObjectPath(path string) (r objectPathResult) {
|
||||||
for i := 0; i < len(path); i++ {
|
for i := 0; i < len(path); i++ {
|
||||||
if path[i]&0x60 == 0x60 {
|
if path[i]&0x60 == 0x60 {
|
||||||
// alpha lowercase
|
// alpha lowercase
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if path[i] == '.' {
|
if path[i] == '.' {
|
||||||
return path[:i], path[i+1:], wild, uc, true
|
r.part = path[:i]
|
||||||
|
r.path = path[i+1:]
|
||||||
|
r.more = true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if path[i] == '*' || path[i] == '?' {
|
if path[i] == '*' || path[i] == '?' {
|
||||||
wild = true
|
r.wild = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if path[i] > 0x7f {
|
if path[i] > 0x7f {
|
||||||
uc = true
|
r.uc = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if path[i] == '\\' {
|
if path[i] == '\\' {
|
||||||
|
@ -539,7 +560,7 @@ func parseObjectPath(path string) (
|
||||||
i++
|
i++
|
||||||
for ; i < len(path); i++ {
|
for ; i < len(path); i++ {
|
||||||
if path[i] > 0x7f {
|
if path[i] > 0x7f {
|
||||||
uc = true
|
r.uc = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if path[i] == '\\' {
|
if path[i] == '\\' {
|
||||||
|
@ -549,18 +570,23 @@ func parseObjectPath(path string) (
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
} else if path[i] == '.' {
|
} else if path[i] == '.' {
|
||||||
return string(epart), path[i+1:], wild, uc, true
|
r.part = string(epart)
|
||||||
|
r.path = path[i+1:]
|
||||||
|
r.more = true
|
||||||
|
return
|
||||||
} else if path[i] == '*' || path[i] == '?' {
|
} else if path[i] == '*' || path[i] == '?' {
|
||||||
wild = true
|
r.wild = true
|
||||||
}
|
}
|
||||||
epart = append(epart, path[i])
|
epart = append(epart, path[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// append the last part
|
// append the last part
|
||||||
return string(epart), "", wild, uc, false
|
r.part = string(epart)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return path, "", wild, uc, false
|
r.part = path
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSquash(json string, i int) (int, string) {
|
func parseSquash(json string, i int) (int, string) {
|
||||||
|
@ -614,7 +640,7 @@ func parseSquash(json string, i int) (int, string) {
|
||||||
func parseObject(c *parseContext, i int, path string) (int, bool) {
|
func parseObject(c *parseContext, i int, path string) (int, bool) {
|
||||||
var match, kesc, vesc, ok, hit bool
|
var match, kesc, vesc, ok, hit bool
|
||||||
var key, val string
|
var key, val string
|
||||||
part, npath, wild, uc, more := parseObjectPath(path)
|
rp := parseObjectPath(path)
|
||||||
for i < len(c.json) {
|
for i < len(c.json) {
|
||||||
for ; i < len(c.json); i++ {
|
for ; i < len(c.json); i++ {
|
||||||
if c.json[i] == '"' {
|
if c.json[i] == '"' {
|
||||||
|
@ -669,20 +695,20 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return i, false
|
return i, false
|
||||||
}
|
}
|
||||||
if wild {
|
if rp.wild {
|
||||||
if kesc {
|
if kesc {
|
||||||
match = wildcardMatch(unescape(key), part, uc)
|
match = wildcardMatch(unescape(key), rp.part, rp.uc)
|
||||||
} else {
|
} else {
|
||||||
match = wildcardMatch(key, part, uc)
|
match = wildcardMatch(key, rp.part, rp.uc)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if kesc {
|
if kesc {
|
||||||
match = part == unescape(key)
|
match = rp.part == unescape(key)
|
||||||
} else {
|
} else {
|
||||||
match = part == key
|
match = rp.part == key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hit = match && !more
|
hit = match && !rp.more
|
||||||
for ; i < len(c.json); i++ {
|
for ; i < len(c.json); i++ {
|
||||||
switch c.json[i] {
|
switch c.json[i] {
|
||||||
default:
|
default:
|
||||||
|
@ -705,7 +731,7 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
case '{':
|
case '{':
|
||||||
if match && !hit {
|
if match && !hit {
|
||||||
i, hit = parseObject(c, i+1, npath)
|
i, hit = parseObject(c, i+1, rp.path)
|
||||||
if hit {
|
if hit {
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
|
@ -719,7 +745,7 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
case '[':
|
case '[':
|
||||||
if match && !hit {
|
if match && !hit {
|
||||||
i, hit = parseArray(c, i+1, npath)
|
i, hit = parseArray(c, i+1, rp.path)
|
||||||
if hit {
|
if hit {
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
|
@ -765,9 +791,9 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
var h int
|
var h int
|
||||||
var alog []int
|
var alog []int
|
||||||
var partidx int
|
var partidx int
|
||||||
part, npath, more, alogok, arrch, alogkey := parseArrayPath(path)
|
rp := parseArrayPath(path)
|
||||||
if !arrch {
|
if !rp.arrch {
|
||||||
n, err := strconv.ParseUint(part, 10, 64)
|
n, err := strconv.ParseUint(rp.part, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
partidx = -1
|
partidx = -1
|
||||||
} else {
|
} else {
|
||||||
|
@ -775,12 +801,12 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i < len(c.json) {
|
for i < len(c.json) {
|
||||||
if !arrch {
|
if !rp.arrch {
|
||||||
match = partidx == h
|
match = partidx == h
|
||||||
hit = match && !more
|
hit = match && !rp.more
|
||||||
}
|
}
|
||||||
h++
|
h++
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
alog = append(alog, i)
|
alog = append(alog, i)
|
||||||
}
|
}
|
||||||
for ; i < len(c.json); i++ {
|
for ; i < len(c.json); i++ {
|
||||||
|
@ -794,7 +820,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
return i, false
|
return i, false
|
||||||
}
|
}
|
||||||
if hit {
|
if hit {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if vesc {
|
if vesc {
|
||||||
|
@ -808,9 +834,9 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
case '{':
|
case '{':
|
||||||
if match && !hit {
|
if match && !hit {
|
||||||
i, hit = parseObject(c, i+1, npath)
|
i, hit = parseObject(c, i+1, rp.path)
|
||||||
if hit {
|
if hit {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return i, true
|
return i, true
|
||||||
|
@ -818,7 +844,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
} else {
|
} else {
|
||||||
i, val = parseSquash(c.json, i)
|
i, val = parseSquash(c.json, i)
|
||||||
if hit {
|
if hit {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c.value.Raw = val
|
c.value.Raw = val
|
||||||
|
@ -828,9 +854,9 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
case '[':
|
case '[':
|
||||||
if match && !hit {
|
if match && !hit {
|
||||||
i, hit = parseArray(c, i+1, npath)
|
i, hit = parseArray(c, i+1, rp.path)
|
||||||
if hit {
|
if hit {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return i, true
|
return i, true
|
||||||
|
@ -838,7 +864,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
} else {
|
} else {
|
||||||
i, val = parseSquash(c.json, i)
|
i, val = parseSquash(c.json, i)
|
||||||
if hit {
|
if hit {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c.value.Raw = val
|
c.value.Raw = val
|
||||||
|
@ -849,7 +875,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
i, val = parseNumber(c.json, i)
|
i, val = parseNumber(c.json, i)
|
||||||
if hit {
|
if hit {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c.value.Raw = val
|
c.value.Raw = val
|
||||||
|
@ -861,7 +887,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
vc := c.json[i]
|
vc := c.json[i]
|
||||||
i, val = parseLiteral(c.json, i)
|
i, val = parseLiteral(c.json, i)
|
||||||
if hit {
|
if hit {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c.value.Raw = val
|
c.value.Raw = val
|
||||||
|
@ -874,12 +900,12 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
case ']':
|
case ']':
|
||||||
if arrch && part == "#" {
|
if rp.arrch && rp.part == "#" {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
var jsons = make([]byte, 0, 64)
|
var jsons = make([]byte, 0, 64)
|
||||||
jsons = append(jsons, '[')
|
jsons = append(jsons, '[')
|
||||||
for j := 0; j < len(alog); j++ {
|
for j := 0; j < len(alog); j++ {
|
||||||
res := Get(c.json[alog[j]:], alogkey)
|
res := Get(c.json[alog[j]:], rp.alogkey)
|
||||||
if res.Exists() {
|
if res.Exists() {
|
||||||
if j > 0 {
|
if j > 0 {
|
||||||
jsons = append(jsons, ',')
|
jsons = append(jsons, ',')
|
||||||
|
@ -892,7 +918,7 @@ func parseArray(c *parseContext, i int, path string) (int, bool) {
|
||||||
c.value.Raw = string(jsons)
|
c.value.Raw = string(jsons)
|
||||||
return i + 1, true
|
return i + 1, true
|
||||||
} else {
|
} else {
|
||||||
if alogok {
|
if rp.alogok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c.value.Raw = val
|
c.value.Raw = val
|
||||||
|
|
Loading…
Reference in New Issue