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