stream.go (5287B)
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 }