mirror of https://github.com/tidwall/gjson.git
unicode patterns
This commit is contained in:
parent
67e38154bd
commit
4fceff029c
86
gjson.go
86
gjson.go
|
@ -485,6 +485,7 @@ func Get(json string, path string) Result {
|
||||||
var alogok bool
|
var alogok bool
|
||||||
var alogkey string
|
var alogkey string
|
||||||
var alog []int
|
var alog []int
|
||||||
|
var uc bool
|
||||||
|
|
||||||
// parse the path into multiple parts.
|
// parse the path into multiple parts.
|
||||||
for i := 0; i < len(path); i++ {
|
for i := 0; i < len(path); i++ {
|
||||||
|
@ -521,6 +522,10 @@ func Get(json string, path string) Result {
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if path[i] > 0x7f {
|
||||||
|
uc = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
if path[i] == '\\' {
|
if path[i] == '\\' {
|
||||||
// go into escape mode. this is a slower path that
|
// go into escape mode. this is a slower path that
|
||||||
// strips off the escape character from the part.
|
// strips off the escape character from the part.
|
||||||
|
@ -530,6 +535,10 @@ func Get(json string, path string) Result {
|
||||||
epart = append(epart, path[i])
|
epart = append(epart, path[i])
|
||||||
i++
|
i++
|
||||||
for ; i < len(path); i++ {
|
for ; i < len(path); i++ {
|
||||||
|
if path[i] > 0x7f {
|
||||||
|
uc = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
if path[i] == '\\' {
|
if path[i] == '\\' {
|
||||||
i++
|
i++
|
||||||
if i < len(path) {
|
if i < len(path) {
|
||||||
|
@ -682,7 +691,7 @@ read_key:
|
||||||
if parts[depth-1].wild {
|
if parts[depth-1].wild {
|
||||||
// the path part contains a wildcard character. we must do a wildcard
|
// the path part contains a wildcard character. we must do a wildcard
|
||||||
// match to determine if it truly matches.
|
// match to determine if it truly matches.
|
||||||
matched = wildcardMatch(f.key, parts[depth-1].key)
|
matched = wildcardMatch(f.key, parts[depth-1].key, uc)
|
||||||
} else {
|
} else {
|
||||||
// just a straight up equality check
|
// just a straight up equality check
|
||||||
matched = parts[depth-1].key == f.key
|
matched = parts[depth-1].key == f.key
|
||||||
|
@ -1093,12 +1102,24 @@ func stringLessInsensitive(a, b string) bool {
|
||||||
// wilcardMatch returns true if str matches pattern. This is a very
|
// wilcardMatch returns true if str matches pattern. This is a very
|
||||||
// simple wildcard match where '*' matches on any number characters
|
// simple wildcard match where '*' matches on any number characters
|
||||||
// and '?' matches on any one character.
|
// and '?' matches on any one character.
|
||||||
func wildcardMatch(str, pattern string) bool {
|
func wildcardMatch(str, pattern string, uc bool) bool {
|
||||||
if pattern == "*" {
|
if pattern == "*" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if !uc {
|
||||||
return deepMatch(str, pattern)
|
return deepMatch(str, pattern)
|
||||||
|
}
|
||||||
|
rstr := make([]rune, 0, len(str))
|
||||||
|
rpattern := make([]rune, 0, len(pattern))
|
||||||
|
for _, r := range str {
|
||||||
|
rstr = append(rstr, r)
|
||||||
|
}
|
||||||
|
for _, r := range pattern {
|
||||||
|
rpattern = append(rpattern, r)
|
||||||
|
}
|
||||||
|
return deepMatchRune(rstr, rpattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deepMatch(str, pattern string) bool {
|
func deepMatch(str, pattern string) bool {
|
||||||
for len(pattern) > 0 {
|
for len(pattern) > 0 {
|
||||||
switch pattern[0] {
|
switch pattern[0] {
|
||||||
|
@ -1111,11 +1132,68 @@ func deepMatch(str, pattern string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case '*':
|
case '*':
|
||||||
return wildcardMatch(str, pattern[1:]) ||
|
return deepMatch(str, pattern[1:]) ||
|
||||||
(len(str) > 0 && wildcardMatch(str[1:], pattern))
|
(len(str) > 0 && deepMatch(str[1:], pattern))
|
||||||
}
|
}
|
||||||
str = str[1:]
|
str = str[1:]
|
||||||
pattern = pattern[1:]
|
pattern = pattern[1:]
|
||||||
}
|
}
|
||||||
return len(str) == 0 && len(pattern) == 0
|
return len(str) == 0 && len(pattern) == 0
|
||||||
}
|
}
|
||||||
|
func deepMatchRune(str, pattern []rune) bool {
|
||||||
|
for len(pattern) > 0 {
|
||||||
|
switch pattern[0] {
|
||||||
|
default:
|
||||||
|
if len(str) == 0 || str[0] != pattern[0] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case '?':
|
||||||
|
if len(str) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case '*':
|
||||||
|
return deepMatchRune(str, pattern[1:]) ||
|
||||||
|
(len(str) > 0 && deepMatchRune(str[1:], pattern))
|
||||||
|
}
|
||||||
|
str = str[1:]
|
||||||
|
pattern = pattern[1:]
|
||||||
|
}
|
||||||
|
return len(str) == 0 && len(pattern) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func wildcardMatch(str, pattern string) bool {
|
||||||
|
if pattern == "*" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
rstr := make([]rune, 0, len(str))
|
||||||
|
rpattern := make([]rune, 0, len(pattern))
|
||||||
|
for _, r := range str {
|
||||||
|
rstr = append(rstr, r)
|
||||||
|
}
|
||||||
|
for _, r := range pattern {
|
||||||
|
rpattern = append(rpattern, r)
|
||||||
|
}
|
||||||
|
return deepMatch(rstr, rpattern)
|
||||||
|
}
|
||||||
|
func deepMatch(str, pattern []rune) bool {
|
||||||
|
for len(pattern) > 0 {
|
||||||
|
switch pattern[0] {
|
||||||
|
default:
|
||||||
|
if len(str) == 0 || str[0] != pattern[0] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case '?':
|
||||||
|
if len(str) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case '*':
|
||||||
|
return deepMatch(str, pattern[1:]) ||
|
||||||
|
(len(str) > 0 && deepMatch(str[1:], pattern))
|
||||||
|
}
|
||||||
|
str = str[1:]
|
||||||
|
pattern = pattern[1:]
|
||||||
|
}
|
||||||
|
return len(str) == 0 && len(pattern) == 0
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -248,7 +248,71 @@ func TestBasic(t *testing.T) {
|
||||||
t.Fatalf("expecting %v, got %v", "Jason", fn)
|
t.Fatalf("expecting %v, got %v", "Jason", fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func TestMatch(t *testing.T) {
|
||||||
|
if !wildcardMatch("hello world", "hello world", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if wildcardMatch("hello world", "jello world", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("hello world", "hello*", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if wildcardMatch("hello world", "jello*", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("hello world", "hello?world", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if wildcardMatch("hello world", "jello?world", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("hello world", "he*o?world", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("hello world", "he*o?wor*", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("hello world", "he*o?*r*", false) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("的情况下解析一个", "*", true) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("的情况下解析一个", "*况下*", true) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("的情况下解析一个", "*况?*", true) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if !wildcardMatch("的情况下解析一个", "的情况?解析一个", true) {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestUnicode(t *testing.T) {
|
||||||
|
var json = `{"key":0,"的情况下解":{"key":1,"的情况":2}}`
|
||||||
|
if Get(json, "的情况下解.key").Num != 1 {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if Get(json, "的情况下解.的情况").Num != 2 {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if Get(json, "的情况下解.的?况").Num != 2 {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if Get(json, "的情况下解.的?*").Num != 2 {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if Get(json, "的情况下解.*?况").Num != 2 {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if Get(json, "的情?下解.*?况").Num != 2 {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
if Get(json, "的情下解.*?况").Num != 0 {
|
||||||
|
t.Fatal("fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
func TestUnescape(t *testing.T) {
|
func TestUnescape(t *testing.T) {
|
||||||
unescape(string([]byte{'\\', '\\', 0}))
|
unescape(string([]byte{'\\', '\\', 0}))
|
||||||
unescape(string([]byte{'\\', '/', '\\', 'b', '\\', 'f'}))
|
unescape(string([]byte{'\\', '/', '\\', 'b', '\\', 'f'}))
|
||||||
|
|
Loading…
Reference in New Issue