@@ -327,28 +327,41 @@ func parseObject(s string, c *cache, depth int) (*Value, string, error) {
327
327
}
328
328
329
329
func escapeString (dst []byte , s string ) []byte {
330
- if ! hasSpecialChars (s ) {
331
- // Fast path - nothing to escape.
332
- dst = append (dst , '"' )
333
- dst = append (dst , s ... )
334
- dst = append (dst , '"' )
335
- return dst
336
- }
337
-
338
- // Slow path.
339
- return strconv .AppendQuote (dst , s )
340
- }
341
-
342
- func hasSpecialChars (s string ) bool {
343
- if strings .IndexByte (s , '"' ) >= 0 || strings .IndexByte (s , '\\' ) >= 0 {
344
- return true
345
- }
330
+ dst = append (dst , '"' )
346
331
for i := 0 ; i < len (s ); i ++ {
347
- if s [i ] < 0x20 {
348
- return true
332
+ c := s [i ]
333
+ switch {
334
+ case c == '"' :
335
+ // quotation mark
336
+ dst = append (dst , []byte {'\\' , '"' }... )
337
+ case c == '\\' :
338
+ // reverse solidus
339
+ dst = append (dst , []byte {'\\' , '\\' }... )
340
+ case c >= 0x20 :
341
+ // default, rest below are control chars
342
+ dst = append (dst , c )
343
+ case c == 0x08 :
344
+ dst = append (dst , []byte {'\\' , 'b' }... )
345
+ case c < 0x09 :
346
+ dst = append (dst , []byte {'\\' , 'u' , '0' , '0' , '0' , '0' + c }... )
347
+ case c == 0x09 :
348
+ dst = append (dst , []byte {'\\' , 't' }... )
349
+ case c == 0x0a :
350
+ dst = append (dst , []byte {'\\' , 'n' }... )
351
+ case c == 0x0c :
352
+ dst = append (dst , []byte {'\\' , 'f' }... )
353
+ case c == 0x0d :
354
+ dst = append (dst , []byte {'\\' , 'r' }... )
355
+ case c < 0x10 :
356
+ dst = append (dst , []byte {'\\' , 'u' , '0' , '0' , '0' , 0x57 + c }... )
357
+ case c < 0x1a :
358
+ dst = append (dst , []byte {'\\' , 'u' , '0' , '0' , '1' , 0x20 + c }... )
359
+ case c < 0x20 :
360
+ dst = append (dst , []byte {'\\' , 'u' , '0' , '0' , '1' , 0x47 + c }... )
349
361
}
350
362
}
351
- return false
363
+ dst = append (dst , '"' )
364
+ return dst
352
365
}
353
366
354
367
func unescapeStringBestEffort (s string ) string {
0 commit comments