Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / go.uber.org / zap / zapcore / json_encoder.go
1 // Copyright (c) 2016 Uber Technologies, Inc.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20
21 package zapcore
22
23 import (
24         "encoding/base64"
25         "encoding/json"
26         "math"
27         "sync"
28         "time"
29         "unicode/utf8"
30
31         "go.uber.org/zap/buffer"
32         "go.uber.org/zap/internal/bufferpool"
33 )
34
35 // For JSON-escaping; see jsonEncoder.safeAddString below.
36 const _hex = "0123456789abcdef"
37
38 var _jsonPool = sync.Pool{New: func() interface{} {
39         return &jsonEncoder{}
40 }}
41
42 func getJSONEncoder() *jsonEncoder {
43         return _jsonPool.Get().(*jsonEncoder)
44 }
45
46 func putJSONEncoder(enc *jsonEncoder) {
47         if enc.reflectBuf != nil {
48                 enc.reflectBuf.Free()
49         }
50         enc.EncoderConfig = nil
51         enc.buf = nil
52         enc.spaced = false
53         enc.openNamespaces = 0
54         enc.reflectBuf = nil
55         enc.reflectEnc = nil
56         _jsonPool.Put(enc)
57 }
58
59 type jsonEncoder struct {
60         *EncoderConfig
61         buf            *buffer.Buffer
62         spaced         bool // include spaces after colons and commas
63         openNamespaces int
64
65         // for encoding generic values by reflection
66         reflectBuf *buffer.Buffer
67         reflectEnc *json.Encoder
68 }
69
70 // NewJSONEncoder creates a fast, low-allocation JSON encoder. The encoder
71 // appropriately escapes all field keys and values.
72 //
73 // Note that the encoder doesn't deduplicate keys, so it's possible to produce
74 // a message like
75 //   {"foo":"bar","foo":"baz"}
76 // This is permitted by the JSON specification, but not encouraged. Many
77 // libraries will ignore duplicate key-value pairs (typically keeping the last
78 // pair) when unmarshaling, but users should attempt to avoid adding duplicate
79 // keys.
80 func NewJSONEncoder(cfg EncoderConfig) Encoder {
81         return newJSONEncoder(cfg, false)
82 }
83
84 func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder {
85         return &jsonEncoder{
86                 EncoderConfig: &cfg,
87                 buf:           bufferpool.Get(),
88                 spaced:        spaced,
89         }
90 }
91
92 func (enc *jsonEncoder) AddArray(key string, arr ArrayMarshaler) error {
93         enc.addKey(key)
94         return enc.AppendArray(arr)
95 }
96
97 func (enc *jsonEncoder) AddObject(key string, obj ObjectMarshaler) error {
98         enc.addKey(key)
99         return enc.AppendObject(obj)
100 }
101
102 func (enc *jsonEncoder) AddBinary(key string, val []byte) {
103         enc.AddString(key, base64.StdEncoding.EncodeToString(val))
104 }
105
106 func (enc *jsonEncoder) AddByteString(key string, val []byte) {
107         enc.addKey(key)
108         enc.AppendByteString(val)
109 }
110
111 func (enc *jsonEncoder) AddBool(key string, val bool) {
112         enc.addKey(key)
113         enc.AppendBool(val)
114 }
115
116 func (enc *jsonEncoder) AddComplex128(key string, val complex128) {
117         enc.addKey(key)
118         enc.AppendComplex128(val)
119 }
120
121 func (enc *jsonEncoder) AddDuration(key string, val time.Duration) {
122         enc.addKey(key)
123         enc.AppendDuration(val)
124 }
125
126 func (enc *jsonEncoder) AddFloat64(key string, val float64) {
127         enc.addKey(key)
128         enc.AppendFloat64(val)
129 }
130
131 func (enc *jsonEncoder) AddInt64(key string, val int64) {
132         enc.addKey(key)
133         enc.AppendInt64(val)
134 }
135
136 func (enc *jsonEncoder) resetReflectBuf() {
137         if enc.reflectBuf == nil {
138                 enc.reflectBuf = bufferpool.Get()
139                 enc.reflectEnc = json.NewEncoder(enc.reflectBuf)
140         } else {
141                 enc.reflectBuf.Reset()
142         }
143 }
144
145 func (enc *jsonEncoder) AddReflected(key string, obj interface{}) error {
146         enc.resetReflectBuf()
147         err := enc.reflectEnc.Encode(obj)
148         if err != nil {
149                 return err
150         }
151         enc.reflectBuf.TrimNewline()
152         enc.addKey(key)
153         _, err = enc.buf.Write(enc.reflectBuf.Bytes())
154         return err
155 }
156
157 func (enc *jsonEncoder) OpenNamespace(key string) {
158         enc.addKey(key)
159         enc.buf.AppendByte('{')
160         enc.openNamespaces++
161 }
162
163 func (enc *jsonEncoder) AddString(key, val string) {
164         enc.addKey(key)
165         enc.AppendString(val)
166 }
167
168 func (enc *jsonEncoder) AddTime(key string, val time.Time) {
169         enc.addKey(key)
170         enc.AppendTime(val)
171 }
172
173 func (enc *jsonEncoder) AddUint64(key string, val uint64) {
174         enc.addKey(key)
175         enc.AppendUint64(val)
176 }
177
178 func (enc *jsonEncoder) AppendArray(arr ArrayMarshaler) error {
179         enc.addElementSeparator()
180         enc.buf.AppendByte('[')
181         err := arr.MarshalLogArray(enc)
182         enc.buf.AppendByte(']')
183         return err
184 }
185
186 func (enc *jsonEncoder) AppendObject(obj ObjectMarshaler) error {
187         enc.addElementSeparator()
188         enc.buf.AppendByte('{')
189         err := obj.MarshalLogObject(enc)
190         enc.buf.AppendByte('}')
191         return err
192 }
193
194 func (enc *jsonEncoder) AppendBool(val bool) {
195         enc.addElementSeparator()
196         enc.buf.AppendBool(val)
197 }
198
199 func (enc *jsonEncoder) AppendByteString(val []byte) {
200         enc.addElementSeparator()
201         enc.buf.AppendByte('"')
202         enc.safeAddByteString(val)
203         enc.buf.AppendByte('"')
204 }
205
206 func (enc *jsonEncoder) AppendComplex128(val complex128) {
207         enc.addElementSeparator()
208         // Cast to a platform-independent, fixed-size type.
209         r, i := float64(real(val)), float64(imag(val))
210         enc.buf.AppendByte('"')
211         // Because we're always in a quoted string, we can use strconv without
212         // special-casing NaN and +/-Inf.
213         enc.buf.AppendFloat(r, 64)
214         enc.buf.AppendByte('+')
215         enc.buf.AppendFloat(i, 64)
216         enc.buf.AppendByte('i')
217         enc.buf.AppendByte('"')
218 }
219
220 func (enc *jsonEncoder) AppendDuration(val time.Duration) {
221         cur := enc.buf.Len()
222         enc.EncodeDuration(val, enc)
223         if cur == enc.buf.Len() {
224                 // User-supplied EncodeDuration is a no-op. Fall back to nanoseconds to keep
225                 // JSON valid.
226                 enc.AppendInt64(int64(val))
227         }
228 }
229
230 func (enc *jsonEncoder) AppendInt64(val int64) {
231         enc.addElementSeparator()
232         enc.buf.AppendInt(val)
233 }
234
235 func (enc *jsonEncoder) AppendReflected(val interface{}) error {
236         enc.resetReflectBuf()
237         err := enc.reflectEnc.Encode(val)
238         if err != nil {
239                 return err
240         }
241         enc.reflectBuf.TrimNewline()
242         enc.addElementSeparator()
243         _, err = enc.buf.Write(enc.reflectBuf.Bytes())
244         return err
245 }
246
247 func (enc *jsonEncoder) AppendString(val string) {
248         enc.addElementSeparator()
249         enc.buf.AppendByte('"')
250         enc.safeAddString(val)
251         enc.buf.AppendByte('"')
252 }
253
254 func (enc *jsonEncoder) AppendTime(val time.Time) {
255         cur := enc.buf.Len()
256         enc.EncodeTime(val, enc)
257         if cur == enc.buf.Len() {
258                 // User-supplied EncodeTime is a no-op. Fall back to nanos since epoch to keep
259                 // output JSON valid.
260                 enc.AppendInt64(val.UnixNano())
261         }
262 }
263
264 func (enc *jsonEncoder) AppendUint64(val uint64) {
265         enc.addElementSeparator()
266         enc.buf.AppendUint(val)
267 }
268
269 func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
270 func (enc *jsonEncoder) AddFloat32(k string, v float32)     { enc.AddFloat64(k, float64(v)) }
271 func (enc *jsonEncoder) AddInt(k string, v int)             { enc.AddInt64(k, int64(v)) }
272 func (enc *jsonEncoder) AddInt32(k string, v int32)         { enc.AddInt64(k, int64(v)) }
273 func (enc *jsonEncoder) AddInt16(k string, v int16)         { enc.AddInt64(k, int64(v)) }
274 func (enc *jsonEncoder) AddInt8(k string, v int8)           { enc.AddInt64(k, int64(v)) }
275 func (enc *jsonEncoder) AddUint(k string, v uint)           { enc.AddUint64(k, uint64(v)) }
276 func (enc *jsonEncoder) AddUint32(k string, v uint32)       { enc.AddUint64(k, uint64(v)) }
277 func (enc *jsonEncoder) AddUint16(k string, v uint16)       { enc.AddUint64(k, uint64(v)) }
278 func (enc *jsonEncoder) AddUint8(k string, v uint8)         { enc.AddUint64(k, uint64(v)) }
279 func (enc *jsonEncoder) AddUintptr(k string, v uintptr)     { enc.AddUint64(k, uint64(v)) }
280 func (enc *jsonEncoder) AppendComplex64(v complex64)        { enc.AppendComplex128(complex128(v)) }
281 func (enc *jsonEncoder) AppendFloat64(v float64)            { enc.appendFloat(v, 64) }
282 func (enc *jsonEncoder) AppendFloat32(v float32)            { enc.appendFloat(float64(v), 32) }
283 func (enc *jsonEncoder) AppendInt(v int)                    { enc.AppendInt64(int64(v)) }
284 func (enc *jsonEncoder) AppendInt32(v int32)                { enc.AppendInt64(int64(v)) }
285 func (enc *jsonEncoder) AppendInt16(v int16)                { enc.AppendInt64(int64(v)) }
286 func (enc *jsonEncoder) AppendInt8(v int8)                  { enc.AppendInt64(int64(v)) }
287 func (enc *jsonEncoder) AppendUint(v uint)                  { enc.AppendUint64(uint64(v)) }
288 func (enc *jsonEncoder) AppendUint32(v uint32)              { enc.AppendUint64(uint64(v)) }
289 func (enc *jsonEncoder) AppendUint16(v uint16)              { enc.AppendUint64(uint64(v)) }
290 func (enc *jsonEncoder) AppendUint8(v uint8)                { enc.AppendUint64(uint64(v)) }
291 func (enc *jsonEncoder) AppendUintptr(v uintptr)            { enc.AppendUint64(uint64(v)) }
292
293 func (enc *jsonEncoder) Clone() Encoder {
294         clone := enc.clone()
295         clone.buf.Write(enc.buf.Bytes())
296         return clone
297 }
298
299 func (enc *jsonEncoder) clone() *jsonEncoder {
300         clone := getJSONEncoder()
301         clone.EncoderConfig = enc.EncoderConfig
302         clone.spaced = enc.spaced
303         clone.openNamespaces = enc.openNamespaces
304         clone.buf = bufferpool.Get()
305         return clone
306 }
307
308 func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) {
309         final := enc.clone()
310         final.buf.AppendByte('{')
311
312         if final.LevelKey != "" {
313                 final.addKey(final.LevelKey)
314                 cur := final.buf.Len()
315                 final.EncodeLevel(ent.Level, final)
316                 if cur == final.buf.Len() {
317                         // User-supplied EncodeLevel was a no-op. Fall back to strings to keep
318                         // output JSON valid.
319                         final.AppendString(ent.Level.String())
320                 }
321         }
322         if final.TimeKey != "" {
323                 final.AddTime(final.TimeKey, ent.Time)
324         }
325         if ent.LoggerName != "" && final.NameKey != "" {
326                 final.addKey(final.NameKey)
327                 cur := final.buf.Len()
328                 nameEncoder := final.EncodeName
329
330                 // if no name encoder provided, fall back to FullNameEncoder for backwards
331                 // compatibility
332                 if nameEncoder == nil {
333                         nameEncoder = FullNameEncoder
334                 }
335
336                 nameEncoder(ent.LoggerName, final)
337                 if cur == final.buf.Len() {
338                         // User-supplied EncodeName was a no-op. Fall back to strings to
339                         // keep output JSON valid.
340                         final.AppendString(ent.LoggerName)
341                 }
342         }
343         if ent.Caller.Defined && final.CallerKey != "" {
344                 final.addKey(final.CallerKey)
345                 cur := final.buf.Len()
346                 final.EncodeCaller(ent.Caller, final)
347                 if cur == final.buf.Len() {
348                         // User-supplied EncodeCaller was a no-op. Fall back to strings to
349                         // keep output JSON valid.
350                         final.AppendString(ent.Caller.String())
351                 }
352         }
353         if final.MessageKey != "" {
354                 final.addKey(enc.MessageKey)
355                 final.AppendString(ent.Message)
356         }
357         if enc.buf.Len() > 0 {
358                 final.addElementSeparator()
359                 final.buf.Write(enc.buf.Bytes())
360         }
361         addFields(final, fields)
362         final.closeOpenNamespaces()
363         if ent.Stack != "" && final.StacktraceKey != "" {
364                 final.AddString(final.StacktraceKey, ent.Stack)
365         }
366         final.buf.AppendByte('}')
367         if final.LineEnding != "" {
368                 final.buf.AppendString(final.LineEnding)
369         } else {
370                 final.buf.AppendString(DefaultLineEnding)
371         }
372
373         ret := final.buf
374         putJSONEncoder(final)
375         return ret, nil
376 }
377
378 func (enc *jsonEncoder) truncate() {
379         enc.buf.Reset()
380 }
381
382 func (enc *jsonEncoder) closeOpenNamespaces() {
383         for i := 0; i < enc.openNamespaces; i++ {
384                 enc.buf.AppendByte('}')
385         }
386 }
387
388 func (enc *jsonEncoder) addKey(key string) {
389         enc.addElementSeparator()
390         enc.buf.AppendByte('"')
391         enc.safeAddString(key)
392         enc.buf.AppendByte('"')
393         enc.buf.AppendByte(':')
394         if enc.spaced {
395                 enc.buf.AppendByte(' ')
396         }
397 }
398
399 func (enc *jsonEncoder) addElementSeparator() {
400         last := enc.buf.Len() - 1
401         if last < 0 {
402                 return
403         }
404         switch enc.buf.Bytes()[last] {
405         case '{', '[', ':', ',', ' ':
406                 return
407         default:
408                 enc.buf.AppendByte(',')
409                 if enc.spaced {
410                         enc.buf.AppendByte(' ')
411                 }
412         }
413 }
414
415 func (enc *jsonEncoder) appendFloat(val float64, bitSize int) {
416         enc.addElementSeparator()
417         switch {
418         case math.IsNaN(val):
419                 enc.buf.AppendString(`"NaN"`)
420         case math.IsInf(val, 1):
421                 enc.buf.AppendString(`"+Inf"`)
422         case math.IsInf(val, -1):
423                 enc.buf.AppendString(`"-Inf"`)
424         default:
425                 enc.buf.AppendFloat(val, bitSize)
426         }
427 }
428
429 // safeAddString JSON-escapes a string and appends it to the internal buffer.
430 // Unlike the standard library's encoder, it doesn't attempt to protect the
431 // user from browser vulnerabilities or JSONP-related problems.
432 func (enc *jsonEncoder) safeAddString(s string) {
433         for i := 0; i < len(s); {
434                 if enc.tryAddRuneSelf(s[i]) {
435                         i++
436                         continue
437                 }
438                 r, size := utf8.DecodeRuneInString(s[i:])
439                 if enc.tryAddRuneError(r, size) {
440                         i++
441                         continue
442                 }
443                 enc.buf.AppendString(s[i : i+size])
444                 i += size
445         }
446 }
447
448 // safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte.
449 func (enc *jsonEncoder) safeAddByteString(s []byte) {
450         for i := 0; i < len(s); {
451                 if enc.tryAddRuneSelf(s[i]) {
452                         i++
453                         continue
454                 }
455                 r, size := utf8.DecodeRune(s[i:])
456                 if enc.tryAddRuneError(r, size) {
457                         i++
458                         continue
459                 }
460                 enc.buf.Write(s[i : i+size])
461                 i += size
462         }
463 }
464
465 // tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte.
466 func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool {
467         if b >= utf8.RuneSelf {
468                 return false
469         }
470         if 0x20 <= b && b != '\\' && b != '"' {
471                 enc.buf.AppendByte(b)
472                 return true
473         }
474         switch b {
475         case '\\', '"':
476                 enc.buf.AppendByte('\\')
477                 enc.buf.AppendByte(b)
478         case '\n':
479                 enc.buf.AppendByte('\\')
480                 enc.buf.AppendByte('n')
481         case '\r':
482                 enc.buf.AppendByte('\\')
483                 enc.buf.AppendByte('r')
484         case '\t':
485                 enc.buf.AppendByte('\\')
486                 enc.buf.AppendByte('t')
487         default:
488                 // Encode bytes < 0x20, except for the escape sequences above.
489                 enc.buf.AppendString(`\u00`)
490                 enc.buf.AppendByte(_hex[b>>4])
491                 enc.buf.AppendByte(_hex[b&0xF])
492         }
493         return true
494 }
495
496 func (enc *jsonEncoder) tryAddRuneError(r rune, size int) bool {
497         if r == utf8.RuneError && size == 1 {
498                 enc.buf.AppendString(`\ufffd`)
499                 return true
500         }
501         return false
502 }