jsonstring.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package logfmt
  2. import (
  3. "bytes"
  4. "io"
  5. "strconv"
  6. "sync"
  7. "unicode"
  8. "unicode/utf16"
  9. "unicode/utf8"
  10. )
  11. // Taken from Go's encoding/json and modified for use here.
  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. var hex = "0123456789abcdef"
  16. var bufferPool = sync.Pool{
  17. New: func() interface{} {
  18. return &bytes.Buffer{}
  19. },
  20. }
  21. func getBuffer() *bytes.Buffer {
  22. return bufferPool.Get().(*bytes.Buffer)
  23. }
  24. func poolBuffer(buf *bytes.Buffer) {
  25. buf.Reset()
  26. bufferPool.Put(buf)
  27. }
  28. // NOTE: keep in sync with writeQuotedBytes below.
  29. func writeQuotedString(w io.Writer, s string) (int, error) {
  30. buf := getBuffer()
  31. buf.WriteByte('"')
  32. start := 0
  33. for i := 0; i < len(s); {
  34. if b := s[i]; b < utf8.RuneSelf {
  35. if 0x20 <= b && b != '\\' && b != '"' {
  36. i++
  37. continue
  38. }
  39. if start < i {
  40. buf.WriteString(s[start:i])
  41. }
  42. switch b {
  43. case '\\', '"':
  44. buf.WriteByte('\\')
  45. buf.WriteByte(b)
  46. case '\n':
  47. buf.WriteByte('\\')
  48. buf.WriteByte('n')
  49. case '\r':
  50. buf.WriteByte('\\')
  51. buf.WriteByte('r')
  52. case '\t':
  53. buf.WriteByte('\\')
  54. buf.WriteByte('t')
  55. default:
  56. // This encodes bytes < 0x20 except for \n, \r, and \t.
  57. buf.WriteString(`\u00`)
  58. buf.WriteByte(hex[b>>4])
  59. buf.WriteByte(hex[b&0xF])
  60. }
  61. i++
  62. start = i
  63. continue
  64. }
  65. c, size := utf8.DecodeRuneInString(s[i:])
  66. if c == utf8.RuneError {
  67. if start < i {
  68. buf.WriteString(s[start:i])
  69. }
  70. buf.WriteString(`\ufffd`)
  71. i += size
  72. start = i
  73. continue
  74. }
  75. i += size
  76. }
  77. if start < len(s) {
  78. buf.WriteString(s[start:])
  79. }
  80. buf.WriteByte('"')
  81. n, err := w.Write(buf.Bytes())
  82. poolBuffer(buf)
  83. return n, err
  84. }
  85. // NOTE: keep in sync with writeQuoteString above.
  86. func writeQuotedBytes(w io.Writer, s []byte) (int, error) {
  87. buf := getBuffer()
  88. buf.WriteByte('"')
  89. start := 0
  90. for i := 0; i < len(s); {
  91. if b := s[i]; b < utf8.RuneSelf {
  92. if 0x20 <= b && b != '\\' && b != '"' {
  93. i++
  94. continue
  95. }
  96. if start < i {
  97. buf.Write(s[start:i])
  98. }
  99. switch b {
  100. case '\\', '"':
  101. buf.WriteByte('\\')
  102. buf.WriteByte(b)
  103. case '\n':
  104. buf.WriteByte('\\')
  105. buf.WriteByte('n')
  106. case '\r':
  107. buf.WriteByte('\\')
  108. buf.WriteByte('r')
  109. case '\t':
  110. buf.WriteByte('\\')
  111. buf.WriteByte('t')
  112. default:
  113. // This encodes bytes < 0x20 except for \n, \r, and \t.
  114. buf.WriteString(`\u00`)
  115. buf.WriteByte(hex[b>>4])
  116. buf.WriteByte(hex[b&0xF])
  117. }
  118. i++
  119. start = i
  120. continue
  121. }
  122. c, size := utf8.DecodeRune(s[i:])
  123. if c == utf8.RuneError {
  124. if start < i {
  125. buf.Write(s[start:i])
  126. }
  127. buf.WriteString(`\ufffd`)
  128. i += size
  129. start = i
  130. continue
  131. }
  132. i += size
  133. }
  134. if start < len(s) {
  135. buf.Write(s[start:])
  136. }
  137. buf.WriteByte('"')
  138. n, err := w.Write(buf.Bytes())
  139. poolBuffer(buf)
  140. return n, err
  141. }
  142. // getu4 decodes \uXXXX from the beginning of s, returning the hex value,
  143. // or it returns -1.
  144. func getu4(s []byte) rune {
  145. if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
  146. return -1
  147. }
  148. r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
  149. if err != nil {
  150. return -1
  151. }
  152. return rune(r)
  153. }
  154. func unquoteBytes(s []byte) (t []byte, ok bool) {
  155. if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
  156. return
  157. }
  158. s = s[1 : len(s)-1]
  159. // Check for unusual characters. If there are none,
  160. // then no unquoting is needed, so return a slice of the
  161. // original bytes.
  162. r := 0
  163. for r < len(s) {
  164. c := s[r]
  165. if c == '\\' || c == '"' || c < ' ' {
  166. break
  167. }
  168. if c < utf8.RuneSelf {
  169. r++
  170. continue
  171. }
  172. rr, size := utf8.DecodeRune(s[r:])
  173. if rr == utf8.RuneError {
  174. break
  175. }
  176. r += size
  177. }
  178. if r == len(s) {
  179. return s, true
  180. }
  181. b := make([]byte, len(s)+2*utf8.UTFMax)
  182. w := copy(b, s[0:r])
  183. for r < len(s) {
  184. // Out of room? Can only happen if s is full of
  185. // malformed UTF-8 and we're replacing each
  186. // byte with RuneError.
  187. if w >= len(b)-2*utf8.UTFMax {
  188. nb := make([]byte, (len(b)+utf8.UTFMax)*2)
  189. copy(nb, b[0:w])
  190. b = nb
  191. }
  192. switch c := s[r]; {
  193. case c == '\\':
  194. r++
  195. if r >= len(s) {
  196. return
  197. }
  198. switch s[r] {
  199. default:
  200. return
  201. case '"', '\\', '/', '\'':
  202. b[w] = s[r]
  203. r++
  204. w++
  205. case 'b':
  206. b[w] = '\b'
  207. r++
  208. w++
  209. case 'f':
  210. b[w] = '\f'
  211. r++
  212. w++
  213. case 'n':
  214. b[w] = '\n'
  215. r++
  216. w++
  217. case 'r':
  218. b[w] = '\r'
  219. r++
  220. w++
  221. case 't':
  222. b[w] = '\t'
  223. r++
  224. w++
  225. case 'u':
  226. r--
  227. rr := getu4(s[r:])
  228. if rr < 0 {
  229. return
  230. }
  231. r += 6
  232. if utf16.IsSurrogate(rr) {
  233. rr1 := getu4(s[r:])
  234. if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
  235. // A valid pair; consume.
  236. r += 6
  237. w += utf8.EncodeRune(b[w:], dec)
  238. break
  239. }
  240. // Invalid surrogate; fall back to replacement rune.
  241. rr = unicode.ReplacementChar
  242. }
  243. w += utf8.EncodeRune(b[w:], rr)
  244. }
  245. // Quote, control characters are invalid.
  246. case c == '"', c < ' ':
  247. return
  248. // ASCII
  249. case c < utf8.RuneSelf:
  250. b[w] = c
  251. r++
  252. w++
  253. // Coerce to well-formed UTF-8.
  254. default:
  255. rr, size := utf8.DecodeRune(s[r:])
  256. r += size
  257. w += utf8.EncodeRune(b[w:], rr)
  258. }
  259. }
  260. return b[0:w], true
  261. }