File tree Expand file tree Collapse file tree 2 files changed +43
-8
lines changed Expand file tree Collapse file tree 2 files changed +43
-8
lines changed Original file line number Diff line number Diff line change @@ -116,6 +116,8 @@ func searchKeys(data []byte, keys ...string) int {
116116 ln := len (data )
117117 lk := len (keys )
118118
119+ var stackbuf [unescapeStackBufSize ]byte // stack-allocated array for allocation-free unescaping of small strings
120+
119121 for i < ln {
120122 switch data [i ] {
121123 case '"' :
@@ -138,14 +140,22 @@ func searchKeys(data []byte, keys ...string) int {
138140
139141 // if string is a Key, and key level match
140142 if data [i ] == ':' {
141- key := unsafeBytesToString (data [keyBegin :keyEnd ])
142-
143- if keyLevel == level - 1 && // If key nesting level match current object nested level
144- keys [level - 1 ] == key {
145- keyLevel ++
146- // If we found all keys in path
147- if keyLevel == lk {
148- return i + 1
143+ key := data [keyBegin :keyEnd ]
144+
145+ // for unescape: if there are no escape sequences, this is cheap; if there are, it is a
146+ // bit more expensive, but causes no allocations unless len(key) > unescapeStackBufSize
147+ if keyUnesc , err := unescape (key , stackbuf [:]); err != nil {
148+ return - 1
149+ } else {
150+ keyUnescStr := unsafeBytesToString (keyUnesc )
151+
152+ if keyLevel == level - 1 && // If key nesting level match current object nested level
153+ keys [level - 1 ] == keyUnescStr {
154+ keyLevel ++
155+ // If we found all keys in path
156+ if keyLevel == lk {
157+ return i + 1
158+ }
149159 }
150160 }
151161 } else {
Original file line number Diff line number Diff line change @@ -158,6 +158,30 @@ var getTests = []Test{
158158 isFound : true ,
159159 data : `3` ,
160160 },
161+
162+ // Escaped key tests
163+ Test {
164+ desc : `key with simple escape` ,
165+ json : `{"a\\b":1}` ,
166+ path : []string {"a\\ b" },
167+ isFound : true ,
168+ data : `1` ,
169+ },
170+ Test {
171+ desc : `key with Unicode escape` ,
172+ json : `{"a\u00B0b":1}` ,
173+ path : []string {"a\u00B0 b" },
174+ isFound : true ,
175+ data : `1` ,
176+ },
177+ Test {
178+ desc : `key with complex escape` ,
179+ json : `{"a\uD83D\uDE03b":1}` ,
180+ path : []string {"a\U0001F603 b" },
181+ isFound : true ,
182+ data : `1` ,
183+ },
184+
161185 Test { // This test returns a match instead of a parse error, as checking for the malformed JSON would reduce performance
162186 desc : `malformed with trailing whitespace` ,
163187 json : `{"a":1 ` ,
@@ -268,6 +292,7 @@ var getTests = []Test{
268292 path : []string {"a" },
269293 isErr : true ,
270294 },
295+
271296 Test { // This test returns not found instead of a parse error, as checking for the malformed JSON would reduce performance
272297 desc : "malformed key (followed by comma followed by colon)" ,
273298 json : `{"a",:1}` ,
You can’t perform that action at this time.
0 commit comments