github.com/michael-k/docker@v1.7.0-rc2/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  		if first == true {
    25  			first = false
    26  		} else {
    27  			buf.WriteString(`,`)
    28  		}
    29  		buf.WriteString(`"log":`)
    30  		ffjson_WriteJsonBytesAsString(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  		ffjson_WriteJsonString(buf, mj.Stream)
    40  	}
    41  	if first == true {
    42  		first = false
    43  	} else {
    44  		buf.WriteString(`,`)
    45  	}
    46  	buf.WriteString(`"time":`)
    47  	buf.WriteString(mj.Created)
    48  	buf.WriteString(`}`)
    49  	return nil
    50  }
    51  
    52  // This is based on ffjson_WriteJsonString. It has been changed
    53  // to accept a string passed as a slice of bytes.
    54  func ffjson_WriteJsonBytesAsString(buf *bytes.Buffer, s []byte) {
    55  	const hex = "0123456789abcdef"
    56  
    57  	buf.WriteByte('"')
    58  	start := 0
    59  	for i := 0; i < len(s); {
    60  		if b := s[i]; b < utf8.RuneSelf {
    61  			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
    62  				i++
    63  				continue
    64  			}
    65  			if start < i {
    66  				buf.Write(s[start:i])
    67  			}
    68  			switch b {
    69  			case '\\', '"':
    70  				buf.WriteByte('\\')
    71  				buf.WriteByte(b)
    72  			case '\n':
    73  				buf.WriteByte('\\')
    74  				buf.WriteByte('n')
    75  			case '\r':
    76  				buf.WriteByte('\\')
    77  				buf.WriteByte('r')
    78  			default:
    79  
    80  				buf.WriteString(`\u00`)
    81  				buf.WriteByte(hex[b>>4])
    82  				buf.WriteByte(hex[b&0xF])
    83  			}
    84  			i++
    85  			start = i
    86  			continue
    87  		}
    88  		c, size := utf8.DecodeRune(s[i:])
    89  		if c == utf8.RuneError && size == 1 {
    90  			if start < i {
    91  				buf.Write(s[start:i])
    92  			}
    93  			buf.WriteString(`\ufffd`)
    94  			i += size
    95  			start = i
    96  			continue
    97  		}
    98  
    99  		if c == '\u2028' || c == '\u2029' {
   100  			if start < i {
   101  				buf.Write(s[start:i])
   102  			}
   103  			buf.WriteString(`\u202`)
   104  			buf.WriteByte(hex[c&0xF])
   105  			i += size
   106  			start = i
   107  			continue
   108  		}
   109  		i += size
   110  	}
   111  	if start < len(s) {
   112  		buf.Write(s[start:])
   113  	}
   114  	buf.WriteByte('"')
   115  }