github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/logql/log/logfmt/jsonstring.go (about) 1 package logfmt 2 3 import ( 4 "strconv" 5 "unicode" 6 "unicode/utf16" 7 "unicode/utf8" 8 ) 9 10 // Taken from Go's encoding/json and modified for use here. 11 12 // Copyright 2010 The Go Authors. All rights reserved. 13 // Use of this source code is governed by a BSD-style 14 // license that can be found in the LICENSE file. 15 16 func getu4(s []byte) rune { 17 if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { 18 return -1 19 } 20 r, err := strconv.ParseUint(string(s[2:6]), 16, 64) 21 if err != nil { 22 return -1 23 } 24 return rune(r) 25 } 26 27 func unquoteBytes(s []byte) (t []byte, ok bool) { 28 if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { 29 return 30 } 31 s = s[1 : len(s)-1] 32 33 // Check for unusual characters. If there are none, 34 // then no unquoting is needed, so return a slice of the 35 // original bytes. 36 r := 0 37 for r < len(s) { 38 c := s[r] 39 if c == '\\' || c == '"' { 40 break 41 } 42 if c < utf8.RuneSelf { 43 r++ 44 continue 45 } 46 rr, size := utf8.DecodeRune(s[r:]) 47 if rr == utf8.RuneError { 48 break 49 } 50 r += size 51 } 52 if r == len(s) { 53 return s, true 54 } 55 56 b := make([]byte, len(s)+2*utf8.UTFMax) 57 w := copy(b, s[0:r]) 58 for r < len(s) { 59 // Out of room? Can only happen if s is full of 60 // malformed UTF-8 and we're replacing each 61 // byte with RuneError. 62 if w >= len(b)-2*utf8.UTFMax { 63 nb := make([]byte, (len(b)+utf8.UTFMax)*2) 64 copy(nb, b[0:w]) 65 b = nb 66 } 67 switch c := s[r]; { 68 case c == '\\': 69 r++ 70 if r >= len(s) { 71 return 72 } 73 switch s[r] { 74 default: 75 return 76 case '"', '\\', '/', '\'': 77 b[w] = s[r] 78 r++ 79 w++ 80 case 'b': 81 b[w] = '\b' 82 r++ 83 w++ 84 case 'f': 85 b[w] = '\f' 86 r++ 87 w++ 88 case 'n': 89 b[w] = '\n' 90 r++ 91 w++ 92 case 'r': 93 b[w] = '\r' 94 r++ 95 w++ 96 case 't': 97 b[w] = '\t' 98 r++ 99 w++ 100 case 'u': 101 r-- 102 rr := getu4(s[r:]) 103 if rr < 0 { 104 return 105 } 106 r += 6 107 if utf16.IsSurrogate(rr) { 108 rr1 := getu4(s[r:]) 109 if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { 110 // A valid pair; consume. 111 r += 6 112 w += utf8.EncodeRune(b[w:], dec) 113 break 114 } 115 // Invalid surrogate; fall back to replacement rune. 116 rr = unicode.ReplacementChar 117 } 118 w += utf8.EncodeRune(b[w:], rr) 119 } 120 121 // Unescaped quote is invalid. 122 case c == '"': 123 return 124 125 // ASCII 126 case c < utf8.RuneSelf: 127 b[w] = c 128 r++ 129 w++ 130 131 // Coerce to well-formed UTF-8. 132 default: 133 rr, size := utf8.DecodeRune(s[r:]) 134 r += size 135 w += utf8.EncodeRune(b[w:], rr) 136 } 137 } 138 return b[0:w], true 139 }