stream.go raw

   1  package jsoniter
   2  
   3  import (
   4  	"io"
   5  )
   6  
   7  // stream is a io.Writer like object, with JSON specific write functions.
   8  // Error is not returned as return value, but stored as Error member on this stream instance.
   9  type Stream struct {
  10  	cfg        *frozenConfig
  11  	out        io.Writer
  12  	buf        []byte
  13  	Error      error
  14  	indention  int
  15  	Attachment interface{} // open for customized encoder
  16  }
  17  
  18  // NewStream create new stream instance.
  19  // cfg can be jsoniter.ConfigDefault.
  20  // out can be nil if write to internal buffer.
  21  // bufSize is the initial size for the internal buffer in bytes.
  22  func NewStream(cfg API, out io.Writer, bufSize int) *Stream {
  23  	return &Stream{
  24  		cfg:       cfg.(*frozenConfig),
  25  		out:       out,
  26  		buf:       make([]byte, 0, bufSize),
  27  		Error:     nil,
  28  		indention: 0,
  29  	}
  30  }
  31  
  32  // Pool returns a pool can provide more stream with same configuration
  33  func (stream *Stream) Pool() StreamPool {
  34  	return stream.cfg
  35  }
  36  
  37  // Reset reuse this stream instance by assign a new writer
  38  func (stream *Stream) Reset(out io.Writer) {
  39  	stream.out = out
  40  	stream.buf = stream.buf[:0]
  41  }
  42  
  43  // Available returns how many bytes are unused in the buffer.
  44  func (stream *Stream) Available() int {
  45  	return cap(stream.buf) - len(stream.buf)
  46  }
  47  
  48  // Buffered returns the number of bytes that have been written into the current buffer.
  49  func (stream *Stream) Buffered() int {
  50  	return len(stream.buf)
  51  }
  52  
  53  // Buffer if writer is nil, use this method to take the result
  54  func (stream *Stream) Buffer() []byte {
  55  	return stream.buf
  56  }
  57  
  58  // SetBuffer allows to append to the internal buffer directly
  59  func (stream *Stream) SetBuffer(buf []byte) {
  60  	stream.buf = buf
  61  }
  62  
  63  // Write writes the contents of p into the buffer.
  64  // It returns the number of bytes written.
  65  // If nn < len(p), it also returns an error explaining
  66  // why the write is short.
  67  func (stream *Stream) Write(p []byte) (nn int, err error) {
  68  	stream.buf = append(stream.buf, p...)
  69  	if stream.out != nil {
  70  		nn, err = stream.out.Write(stream.buf)
  71  		stream.buf = stream.buf[nn:]
  72  		return
  73  	}
  74  	return len(p), nil
  75  }
  76  
  77  // WriteByte writes a single byte.
  78  func (stream *Stream) writeByte(c byte) {
  79  	stream.buf = append(stream.buf, c)
  80  }
  81  
  82  func (stream *Stream) writeTwoBytes(c1 byte, c2 byte) {
  83  	stream.buf = append(stream.buf, c1, c2)
  84  }
  85  
  86  func (stream *Stream) writeThreeBytes(c1 byte, c2 byte, c3 byte) {
  87  	stream.buf = append(stream.buf, c1, c2, c3)
  88  }
  89  
  90  func (stream *Stream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) {
  91  	stream.buf = append(stream.buf, c1, c2, c3, c4)
  92  }
  93  
  94  func (stream *Stream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) {
  95  	stream.buf = append(stream.buf, c1, c2, c3, c4, c5)
  96  }
  97  
  98  // Flush writes any buffered data to the underlying io.Writer.
  99  func (stream *Stream) Flush() error {
 100  	if stream.out == nil {
 101  		return nil
 102  	}
 103  	if stream.Error != nil {
 104  		return stream.Error
 105  	}
 106  	_, err := stream.out.Write(stream.buf)
 107  	if err != nil {
 108  		if stream.Error == nil {
 109  			stream.Error = err
 110  		}
 111  		return err
 112  	}
 113  	stream.buf = stream.buf[:0]
 114  	return nil
 115  }
 116  
 117  // WriteRaw write string out without quotes, just like []byte
 118  func (stream *Stream) WriteRaw(s string) {
 119  	stream.buf = append(stream.buf, s...)
 120  }
 121  
 122  // WriteNil write null to stream
 123  func (stream *Stream) WriteNil() {
 124  	stream.writeFourBytes('n', 'u', 'l', 'l')
 125  }
 126  
 127  // WriteTrue write true to stream
 128  func (stream *Stream) WriteTrue() {
 129  	stream.writeFourBytes('t', 'r', 'u', 'e')
 130  }
 131  
 132  // WriteFalse write false to stream
 133  func (stream *Stream) WriteFalse() {
 134  	stream.writeFiveBytes('f', 'a', 'l', 's', 'e')
 135  }
 136  
 137  // WriteBool write true or false into stream
 138  func (stream *Stream) WriteBool(val bool) {
 139  	if val {
 140  		stream.WriteTrue()
 141  	} else {
 142  		stream.WriteFalse()
 143  	}
 144  }
 145  
 146  // WriteObjectStart write { with possible indention
 147  func (stream *Stream) WriteObjectStart() {
 148  	stream.indention += stream.cfg.indentionStep
 149  	stream.writeByte('{')
 150  	stream.writeIndention(0)
 151  }
 152  
 153  // WriteObjectField write "field": with possible indention
 154  func (stream *Stream) WriteObjectField(field string) {
 155  	stream.WriteString(field)
 156  	if stream.indention > 0 {
 157  		stream.writeTwoBytes(':', ' ')
 158  	} else {
 159  		stream.writeByte(':')
 160  	}
 161  }
 162  
 163  // WriteObjectEnd write } with possible indention
 164  func (stream *Stream) WriteObjectEnd() {
 165  	stream.writeIndention(stream.cfg.indentionStep)
 166  	stream.indention -= stream.cfg.indentionStep
 167  	stream.writeByte('}')
 168  }
 169  
 170  // WriteEmptyObject write {}
 171  func (stream *Stream) WriteEmptyObject() {
 172  	stream.writeByte('{')
 173  	stream.writeByte('}')
 174  }
 175  
 176  // WriteMore write , with possible indention
 177  func (stream *Stream) WriteMore() {
 178  	stream.writeByte(',')
 179  	stream.writeIndention(0)
 180  }
 181  
 182  // WriteArrayStart write [ with possible indention
 183  func (stream *Stream) WriteArrayStart() {
 184  	stream.indention += stream.cfg.indentionStep
 185  	stream.writeByte('[')
 186  	stream.writeIndention(0)
 187  }
 188  
 189  // WriteEmptyArray write []
 190  func (stream *Stream) WriteEmptyArray() {
 191  	stream.writeTwoBytes('[', ']')
 192  }
 193  
 194  // WriteArrayEnd write ] with possible indention
 195  func (stream *Stream) WriteArrayEnd() {
 196  	stream.writeIndention(stream.cfg.indentionStep)
 197  	stream.indention -= stream.cfg.indentionStep
 198  	stream.writeByte(']')
 199  }
 200  
 201  func (stream *Stream) writeIndention(delta int) {
 202  	if stream.indention == 0 {
 203  		return
 204  	}
 205  	stream.writeByte('\n')
 206  	toWrite := stream.indention - delta
 207  	for i := 0; i < toWrite; i++ {
 208  		stream.buf = append(stream.buf, ' ')
 209  	}
 210  }
 211