writer.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // Package jwriter contains a JSON writer.
  2. package jwriter
  3. import (
  4. "io"
  5. "strconv"
  6. "unicode/utf8"
  7. "github.com/mailru/easyjson/buffer"
  8. )
  9. // Flags describe various encoding options. The behavior may be actually implemented in the encoder, but
  10. // Flags field in Writer is used to set and pass them around.
  11. type Flags int
  12. const (
  13. NilMapAsEmpty Flags = 1 << iota // Encode nil map as '{}' rather than 'null'.
  14. NilSliceAsEmpty // Encode nil slice as '[]' rather than 'null'.
  15. )
  16. // Writer is a JSON writer.
  17. type Writer struct {
  18. Flags Flags
  19. Error error
  20. Buffer buffer.Buffer
  21. NoEscapeHTML bool
  22. }
  23. // Size returns the size of the data that was written out.
  24. func (w *Writer) Size() int {
  25. return w.Buffer.Size()
  26. }
  27. // DumpTo outputs the data to given io.Writer, resetting the buffer.
  28. func (w *Writer) DumpTo(out io.Writer) (written int, err error) {
  29. return w.Buffer.DumpTo(out)
  30. }
  31. // BuildBytes returns writer data as a single byte slice. You can optionally provide one byte slice
  32. // as argument that it will try to reuse.
  33. func (w *Writer) BuildBytes(reuse ...[]byte) ([]byte, error) {
  34. if w.Error != nil {
  35. return nil, w.Error
  36. }
  37. return w.Buffer.BuildBytes(reuse...), nil
  38. }
  39. // ReadCloser returns an io.ReadCloser that can be used to read the data.
  40. // ReadCloser also resets the buffer.
  41. func (w *Writer) ReadCloser() (io.ReadCloser, error) {
  42. if w.Error != nil {
  43. return nil, w.Error
  44. }
  45. return w.Buffer.ReadCloser(), nil
  46. }
  47. // RawByte appends raw binary data to the buffer.
  48. func (w *Writer) RawByte(c byte) {
  49. w.Buffer.AppendByte(c)
  50. }
  51. // RawByte appends raw binary data to the buffer.
  52. func (w *Writer) RawString(s string) {
  53. w.Buffer.AppendString(s)
  54. }
  55. // Raw appends raw binary data to the buffer or sets the error if it is given. Useful for
  56. // calling with results of MarshalJSON-like functions.
  57. func (w *Writer) Raw(data []byte, err error) {
  58. switch {
  59. case w.Error != nil:
  60. return
  61. case err != nil:
  62. w.Error = err
  63. case len(data) > 0:
  64. w.Buffer.AppendBytes(data)
  65. default:
  66. w.RawString("null")
  67. }
  68. }
  69. // RawText encloses raw binary data in quotes and appends in to the buffer.
  70. // Useful for calling with results of MarshalText-like functions.
  71. func (w *Writer) RawText(data []byte, err error) {
  72. switch {
  73. case w.Error != nil:
  74. return
  75. case err != nil:
  76. w.Error = err
  77. case len(data) > 0:
  78. w.String(string(data))
  79. default:
  80. w.RawString("null")
  81. }
  82. }
  83. // Base64Bytes appends data to the buffer after base64 encoding it
  84. func (w *Writer) Base64Bytes(data []byte) {
  85. if data == nil {
  86. w.Buffer.AppendString("null")
  87. return
  88. }
  89. w.Buffer.AppendByte('"')
  90. w.base64(data)
  91. w.Buffer.AppendByte('"')
  92. }
  93. func (w *Writer) Uint8(n uint8) {
  94. w.Buffer.EnsureSpace(3)
  95. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  96. }
  97. func (w *Writer) Uint16(n uint16) {
  98. w.Buffer.EnsureSpace(5)
  99. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  100. }
  101. func (w *Writer) Uint32(n uint32) {
  102. w.Buffer.EnsureSpace(10)
  103. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  104. }
  105. func (w *Writer) Uint(n uint) {
  106. w.Buffer.EnsureSpace(20)
  107. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  108. }
  109. func (w *Writer) Uint64(n uint64) {
  110. w.Buffer.EnsureSpace(20)
  111. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
  112. }
  113. func (w *Writer) Int8(n int8) {
  114. w.Buffer.EnsureSpace(4)
  115. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
  116. }
  117. func (w *Writer) Int16(n int16) {
  118. w.Buffer.EnsureSpace(6)
  119. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
  120. }
  121. func (w *Writer) Int32(n int32) {
  122. w.Buffer.EnsureSpace(11)
  123. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
  124. }
  125. func (w *Writer) Int(n int) {
  126. w.Buffer.EnsureSpace(21)
  127. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
  128. }
  129. func (w *Writer) Int64(n int64) {
  130. w.Buffer.EnsureSpace(21)
  131. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
  132. }
  133. func (w *Writer) Uint8Str(n uint8) {
  134. w.Buffer.EnsureSpace(3)
  135. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  136. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  137. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  138. }
  139. func (w *Writer) Uint16Str(n uint16) {
  140. w.Buffer.EnsureSpace(5)
  141. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  142. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  143. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  144. }
  145. func (w *Writer) Uint32Str(n uint32) {
  146. w.Buffer.EnsureSpace(10)
  147. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  148. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  149. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  150. }
  151. func (w *Writer) UintStr(n uint) {
  152. w.Buffer.EnsureSpace(20)
  153. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  154. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  155. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  156. }
  157. func (w *Writer) Uint64Str(n uint64) {
  158. w.Buffer.EnsureSpace(20)
  159. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  160. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
  161. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  162. }
  163. func (w *Writer) UintptrStr(n uintptr) {
  164. w.Buffer.EnsureSpace(20)
  165. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  166. w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
  167. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  168. }
  169. func (w *Writer) Int8Str(n int8) {
  170. w.Buffer.EnsureSpace(4)
  171. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  172. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
  173. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  174. }
  175. func (w *Writer) Int16Str(n int16) {
  176. w.Buffer.EnsureSpace(6)
  177. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  178. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
  179. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  180. }
  181. func (w *Writer) Int32Str(n int32) {
  182. w.Buffer.EnsureSpace(11)
  183. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  184. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
  185. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  186. }
  187. func (w *Writer) IntStr(n int) {
  188. w.Buffer.EnsureSpace(21)
  189. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  190. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
  191. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  192. }
  193. func (w *Writer) Int64Str(n int64) {
  194. w.Buffer.EnsureSpace(21)
  195. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  196. w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
  197. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  198. }
  199. func (w *Writer) Float32(n float32) {
  200. w.Buffer.EnsureSpace(20)
  201. w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32)
  202. }
  203. func (w *Writer) Float32Str(n float32) {
  204. w.Buffer.EnsureSpace(20)
  205. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  206. w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32)
  207. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  208. }
  209. func (w *Writer) Float64(n float64) {
  210. w.Buffer.EnsureSpace(20)
  211. w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, n, 'g', -1, 64)
  212. }
  213. func (w *Writer) Float64Str(n float64) {
  214. w.Buffer.EnsureSpace(20)
  215. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  216. w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 64)
  217. w.Buffer.Buf = append(w.Buffer.Buf, '"')
  218. }
  219. func (w *Writer) Bool(v bool) {
  220. w.Buffer.EnsureSpace(5)
  221. if v {
  222. w.Buffer.Buf = append(w.Buffer.Buf, "true"...)
  223. } else {
  224. w.Buffer.Buf = append(w.Buffer.Buf, "false"...)
  225. }
  226. }
  227. const chars = "0123456789abcdef"
  228. func getTable(falseValues ...int) [128]bool {
  229. table := [128]bool{}
  230. for i := 0; i < 128; i++ {
  231. table[i] = true
  232. }
  233. for _, v := range falseValues {
  234. table[v] = false
  235. }
  236. return table
  237. }
  238. var (
  239. htmlEscapeTable = getTable(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '&', '<', '>', '\\')
  240. htmlNoEscapeTable = getTable(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '\\')
  241. )
  242. func (w *Writer) String(s string) {
  243. w.Buffer.AppendByte('"')
  244. // Portions of the string that contain no escapes are appended as
  245. // byte slices.
  246. p := 0 // last non-escape symbol
  247. escapeTable := &htmlEscapeTable
  248. if w.NoEscapeHTML {
  249. escapeTable = &htmlNoEscapeTable
  250. }
  251. for i := 0; i < len(s); {
  252. c := s[i]
  253. if c < utf8.RuneSelf {
  254. if escapeTable[c] {
  255. // single-width character, no escaping is required
  256. i++
  257. continue
  258. }
  259. w.Buffer.AppendString(s[p:i])
  260. switch c {
  261. case '\t':
  262. w.Buffer.AppendString(`\t`)
  263. case '\r':
  264. w.Buffer.AppendString(`\r`)
  265. case '\n':
  266. w.Buffer.AppendString(`\n`)
  267. case '\\':
  268. w.Buffer.AppendString(`\\`)
  269. case '"':
  270. w.Buffer.AppendString(`\"`)
  271. default:
  272. w.Buffer.AppendString(`\u00`)
  273. w.Buffer.AppendByte(chars[c>>4])
  274. w.Buffer.AppendByte(chars[c&0xf])
  275. }
  276. i++
  277. p = i
  278. continue
  279. }
  280. // broken utf
  281. runeValue, runeWidth := utf8.DecodeRuneInString(s[i:])
  282. if runeValue == utf8.RuneError && runeWidth == 1 {
  283. w.Buffer.AppendString(s[p:i])
  284. w.Buffer.AppendString(`\ufffd`)
  285. i++
  286. p = i
  287. continue
  288. }
  289. // jsonp stuff - tab separator and line separator
  290. if runeValue == '\u2028' || runeValue == '\u2029' {
  291. w.Buffer.AppendString(s[p:i])
  292. w.Buffer.AppendString(`\u202`)
  293. w.Buffer.AppendByte(chars[runeValue&0xf])
  294. i += runeWidth
  295. p = i
  296. continue
  297. }
  298. i += runeWidth
  299. }
  300. w.Buffer.AppendString(s[p:])
  301. w.Buffer.AppendByte('"')
  302. }
  303. const encode = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  304. const padChar = '='
  305. func (w *Writer) base64(in []byte) {
  306. if len(in) == 0 {
  307. return
  308. }
  309. w.Buffer.EnsureSpace(((len(in)-1)/3 + 1) * 4)
  310. si := 0
  311. n := (len(in) / 3) * 3
  312. for si < n {
  313. // Convert 3x 8bit source bytes into 4 bytes
  314. val := uint(in[si+0])<<16 | uint(in[si+1])<<8 | uint(in[si+2])
  315. w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>18&0x3F], encode[val>>12&0x3F], encode[val>>6&0x3F], encode[val&0x3F])
  316. si += 3
  317. }
  318. remain := len(in) - si
  319. if remain == 0 {
  320. return
  321. }
  322. // Add the remaining small block
  323. val := uint(in[si+0]) << 16
  324. if remain == 2 {
  325. val |= uint(in[si+1]) << 8
  326. }
  327. w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>18&0x3F], encode[val>>12&0x3F])
  328. switch remain {
  329. case 2:
  330. w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>6&0x3F], byte(padChar))
  331. case 1:
  332. w.Buffer.Buf = append(w.Buffer.Buf, byte(padChar), byte(padChar))
  333. }
  334. }