github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/jsoni/stream.go (about) 1 package jsoni 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 jsoni.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 (s *Stream) Pool() StreamPool { return s.cfg } 34 35 // Reset reuse this stream instance by assign a new writer 36 func (s *Stream) Reset(out io.Writer) { 37 s.out = out 38 s.buf = s.buf[:0] 39 } 40 41 // Available returns how many bytes are unused in the buffer. 42 func (s *Stream) Available() int { return cap(s.buf) - len(s.buf) } 43 44 // Buffered returns the number of bytes that have been written into the current buffer. 45 func (s *Stream) Buffered() int { return len(s.buf) } 46 47 // Buffer if writer is nil, use this method to take the result 48 func (s *Stream) Buffer() []byte { return s.buf } 49 50 // SetBuffer allows appending to the internal buffer directly 51 func (s *Stream) SetBuffer(buf []byte) { s.buf = buf } 52 53 // Write writes the contents of p into the buffer. 54 // It returns the number of bytes written. 55 // If nn < len(p), it also returns an error explaining 56 // why the write is short. 57 func (s *Stream) Write(p []byte) (nn int, err error) { 58 s.buf = append(s.buf, p...) 59 if s.out != nil { 60 nn, err = s.out.Write(s.buf) 61 s.buf = s.buf[nn:] 62 return 63 } 64 return len(p), nil 65 } 66 67 // WriteByte writes a single byte. 68 func (s *Stream) writeByte(c byte) { s.buf = append(s.buf, c) } 69 func (s *Stream) write2Bytes(c1, c2 byte) { s.buf = append(s.buf, c1, c2) } 70 func (s *Stream) write3Bytes(c1, c2, c3 byte) { s.buf = append(s.buf, c1, c2, c3) } 71 func (s *Stream) write4Bytes(c1, c2, c3, c4 byte) { s.buf = append(s.buf, c1, c2, c3, c4) } 72 func (s *Stream) write5Bytes(c1, c2, c3, c4, c5 byte) { s.buf = append(s.buf, c1, c2, c3, c4, c5) } 73 74 // Flush writes any buffered data to the underlying io.Writer. 75 func (s *Stream) Flush() error { 76 if s.out == nil { 77 return nil 78 } 79 if s.Error != nil { 80 return s.Error 81 } 82 _, err := s.out.Write(s.buf) 83 if err != nil { 84 if s.Error == nil { 85 s.Error = err 86 } 87 return err 88 } 89 s.buf = s.buf[:0] 90 return nil 91 } 92 93 // WriteRawBytes write string out without quotes, just like []byte 94 func (s *Stream) WriteRawBytes(a []byte) { s.buf = append(s.buf, a...) } 95 96 // WriteRaw write string out without quotes, just like []byte 97 func (s *Stream) WriteRaw(a string) { s.buf = append(s.buf, a...) } 98 99 // WriteNil write null to stream 100 func (s *Stream) WriteNil() { s.write4Bytes('n', 'u', 'l', 'l') } 101 102 // WriteTrue write true to stream 103 func (s *Stream) WriteTrue() { s.write4Bytes('t', 'r', 'u', 'e') } 104 105 // WriteFalse write false to stream 106 func (s *Stream) WriteFalse() { s.write5Bytes('f', 'a', 'l', 's', 'e') } 107 108 // WriteBool write true or false into stream 109 func (s *Stream) WriteBool(val bool) { 110 if val { 111 s.WriteTrue() 112 } else { 113 s.WriteFalse() 114 } 115 } 116 117 // WriteObjectStart write { with possible indention 118 func (s *Stream) WriteObjectStart() { 119 s.indention += s.cfg.indentionStep 120 s.writeByte('{') 121 s.writeIndention(0) 122 } 123 124 // WriteObjectField write "field": with possible indention 125 func (s *Stream) WriteObjectField(field string) { 126 s.WriteString(field) 127 if s.indention > 0 { 128 s.write2Bytes(':', ' ') 129 } else { 130 s.writeByte(':') 131 } 132 } 133 134 // WriteObjectEnd write } with possible indention 135 func (s *Stream) WriteObjectEnd() { 136 s.writeIndention(s.cfg.indentionStep) 137 s.indention -= s.cfg.indentionStep 138 s.writeByte('}') 139 } 140 141 // WriteEmptyObject write {} 142 func (s *Stream) WriteEmptyObject() { 143 s.writeByte('{') 144 s.writeByte('}') 145 } 146 147 // WriteMore write , with possible indention 148 func (s *Stream) WriteMore() { 149 s.writeByte(',') 150 s.writeIndention(0) 151 } 152 153 // WriteArrayStart write [ with possible indention 154 func (s *Stream) WriteArrayStart() { 155 s.indention += s.cfg.indentionStep 156 s.writeByte('[') 157 s.writeIndention(0) 158 } 159 160 // WriteEmptyArray write [] 161 func (s *Stream) WriteEmptyArray() { 162 s.write2Bytes('[', ']') 163 } 164 165 // WriteArrayEnd write ] with possible indention 166 func (s *Stream) WriteArrayEnd() { 167 s.writeIndention(s.cfg.indentionStep) 168 s.indention -= s.cfg.indentionStep 169 s.writeByte(']') 170 } 171 172 func (s *Stream) writeIndention(delta int) { 173 if s.indention == 0 { 174 return 175 } 176 s.writeByte('\n') 177 toWrite := s.indention - delta 178 for i := 0; i < toWrite; i++ { 179 s.buf = append(s.buf, ' ') 180 } 181 }