github.com/damirazo/docker@v1.9.0/pkg/jsonlog/jsonlogbytes.go (about) 1 package jsonlog 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "unicode/utf8" 7 ) 8 9 // JSONLogs is based on JSONLog. 10 // It allows marshalling JSONLog from Log as []byte 11 // and an already marshalled Created timestamp. 12 type JSONLogs struct { 13 Log []byte `json:"log,omitempty"` 14 Stream string `json:"stream,omitempty"` 15 Created string `json:"time"` 16 17 // json-encoded bytes 18 RawAttrs json.RawMessage `json:"attrs,omitempty"` 19 } 20 21 // MarshalJSONBuf is based on the same method from JSONLog 22 // It has been modified to take into account the necessary changes. 23 func (mj *JSONLogs) MarshalJSONBuf(buf *bytes.Buffer) error { 24 var first = true 25 26 buf.WriteString(`{`) 27 if len(mj.Log) != 0 { 28 first = false 29 buf.WriteString(`"log":`) 30 ffjsonWriteJSONBytesAsString(buf, mj.Log) 31 } 32 if len(mj.Stream) != 0 { 33 if first == true { 34 first = false 35 } else { 36 buf.WriteString(`,`) 37 } 38 buf.WriteString(`"stream":`) 39 ffjsonWriteJSONString(buf, mj.Stream) 40 } 41 if len(mj.RawAttrs) > 0 { 42 if first == true { 43 first = false 44 } else { 45 buf.WriteString(`,`) 46 } 47 buf.WriteString(`"attrs":`) 48 buf.Write(mj.RawAttrs) 49 } 50 if first == true { 51 first = false 52 } else { 53 buf.WriteString(`,`) 54 } 55 buf.WriteString(`"time":`) 56 buf.WriteString(mj.Created) 57 buf.WriteString(`}`) 58 return nil 59 } 60 61 // This is based on ffjsonWriteJSONBytesAsString. It has been changed 62 // to accept a string passed as a slice of bytes. 63 func ffjsonWriteJSONBytesAsString(buf *bytes.Buffer, s []byte) { 64 const hex = "0123456789abcdef" 65 66 buf.WriteByte('"') 67 start := 0 68 for i := 0; i < len(s); { 69 if b := s[i]; b < utf8.RuneSelf { 70 if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' { 71 i++ 72 continue 73 } 74 if start < i { 75 buf.Write(s[start:i]) 76 } 77 switch b { 78 case '\\', '"': 79 buf.WriteByte('\\') 80 buf.WriteByte(b) 81 case '\n': 82 buf.WriteByte('\\') 83 buf.WriteByte('n') 84 case '\r': 85 buf.WriteByte('\\') 86 buf.WriteByte('r') 87 default: 88 89 buf.WriteString(`\u00`) 90 buf.WriteByte(hex[b>>4]) 91 buf.WriteByte(hex[b&0xF]) 92 } 93 i++ 94 start = i 95 continue 96 } 97 c, size := utf8.DecodeRune(s[i:]) 98 if c == utf8.RuneError && size == 1 { 99 if start < i { 100 buf.Write(s[start:i]) 101 } 102 buf.WriteString(`\ufffd`) 103 i += size 104 start = i 105 continue 106 } 107 108 if c == '\u2028' || c == '\u2029' { 109 if start < i { 110 buf.Write(s[start:i]) 111 } 112 buf.WriteString(`\u202`) 113 buf.WriteByte(hex[c&0xF]) 114 i += size 115 start = i 116 continue 117 } 118 i += size 119 } 120 if start < len(s) { 121 buf.Write(s[start:]) 122 } 123 buf.WriteByte('"') 124 }