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