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 {
116
116
ln := len (data )
117
117
lk := len (keys )
118
118
119
+ var stackbuf [unescapeStackBufSize ]byte // stack-allocated array for allocation-free unescaping of small strings
120
+
119
121
for i < ln {
120
122
switch data [i ] {
121
123
case '"' :
@@ -138,14 +140,22 @@ func searchKeys(data []byte, keys ...string) int {
138
140
139
141
// if string is a Key, and key level match
140
142
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
+ }
149
159
}
150
160
}
151
161
} else {
Original file line number Diff line number Diff line change @@ -158,6 +158,30 @@ var getTests = []Test{
158
158
isFound : true ,
159
159
data : `3` ,
160
160
},
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
+
161
185
Test { // This test returns a match instead of a parse error, as checking for the malformed JSON would reduce performance
162
186
desc : `malformed with trailing whitespace` ,
163
187
json : `{"a":1 ` ,
@@ -268,6 +292,7 @@ var getTests = []Test{
268
292
path : []string {"a" },
269
293
isErr : true ,
270
294
},
295
+
271
296
Test { // This test returns not found instead of a parse error, as checking for the malformed JSON would reduce performance
272
297
desc : "malformed key (followed by comma followed by colon)" ,
273
298
json : `{"a",:1}` ,
You can’t perform that action at this time.
0 commit comments