1
0
mirror of https://github.com/json-iterator/go.git synced 2024-11-30 08:36:43 +02:00
json-iterator/feature_stream.go

276 lines
5.0 KiB
Go
Raw Normal View History

2017-01-07 06:28:16 +02:00
package jsoniter
import (
"io"
)
type Stream struct {
cfg *frozenConfig
2017-06-13 11:47:40 +02:00
out io.Writer
buf []byte
n int
Error error
indention int
2017-01-07 06:28:16 +02:00
}
func NewStream(cfg *frozenConfig, out io.Writer, bufSize int) *Stream {
2017-06-13 10:58:53 +02:00
return &Stream{
2017-06-13 11:47:40 +02:00
cfg: cfg,
out: out,
buf: make([]byte, bufSize),
n: 0,
Error: nil,
indention: 0,
2017-06-13 10:58:53 +02:00
}
2017-01-07 06:28:16 +02:00
}
2017-02-07 03:24:36 +02:00
func (b *Stream) Reset(out io.Writer) {
b.out = out
b.n = 0
}
2017-01-07 06:28:16 +02:00
// Available returns how many bytes are unused in the buffer.
func (b *Stream) Available() int {
return len(b.buf) - b.n
}
// Buffered returns the number of bytes that have been written into the current buffer.
func (b *Stream) Buffered() int {
return b.n
}
2017-06-06 03:44:56 +02:00
func (b *Stream) Buffer() []byte {
return b.buf[:b.n]
}
2017-01-07 06:28:16 +02:00
// Write writes the contents of p into the buffer.
// It returns the number of bytes written.
// If nn < len(p), it also returns an error explaining
// why the write is short.
func (b *Stream) Write(p []byte) (nn int, err error) {
for len(p) > b.Available() && b.Error == nil {
2017-06-06 03:44:56 +02:00
if b.out == nil {
b.growAtLeast(len(p))
2017-01-07 06:28:16 +02:00
} else {
2017-06-06 03:44:56 +02:00
var n int
if b.Buffered() == 0 {
// Large write, empty buffer.
// Write directly from p to avoid copy.
n, b.Error = b.out.Write(p)
} else {
n = copy(b.buf[b.n:], p)
b.n += n
b.Flush()
}
nn += n
p = p[n:]
2017-01-07 06:28:16 +02:00
}
}
if b.Error != nil {
return nn, b.Error
}
n := copy(b.buf[b.n:], p)
b.n += n
nn += n
return nn, nil
}
// WriteByte writes a single byte.
2017-01-22 13:28:14 +02:00
func (b *Stream) writeByte(c byte) {
2017-01-07 06:28:16 +02:00
if b.Error != nil {
2017-01-22 13:28:14 +02:00
return
2017-01-07 06:28:16 +02:00
}
2017-06-06 03:44:56 +02:00
if b.Available() < 1 {
b.growAtLeast(1)
2017-01-07 06:28:16 +02:00
}
b.buf[b.n] = c
b.n++
}
2017-01-22 13:28:14 +02:00
func (b *Stream) writeTwoBytes(c1 byte, c2 byte) {
2017-01-21 18:04:08 +02:00
if b.Error != nil {
2017-01-22 13:28:14 +02:00
return
2017-01-21 18:04:08 +02:00
}
2017-06-06 03:44:56 +02:00
if b.Available() < 2 {
b.growAtLeast(2)
2017-01-21 18:04:08 +02:00
}
b.buf[b.n] = c1
2017-06-06 03:44:56 +02:00
b.buf[b.n+1] = c2
2017-01-21 18:04:08 +02:00
b.n += 2
2017-01-22 13:28:14 +02:00
}
func (b *Stream) writeThreeBytes(c1 byte, c2 byte, c3 byte) {
if b.Error != nil {
return
}
2017-06-06 03:44:56 +02:00
if b.Available() < 3 {
b.growAtLeast(3)
2017-01-22 13:28:14 +02:00
}
b.buf[b.n] = c1
2017-06-06 03:44:56 +02:00
b.buf[b.n+1] = c2
b.buf[b.n+2] = c3
2017-01-22 13:28:14 +02:00
b.n += 3
}
func (b *Stream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) {
if b.Error != nil {
return
}
2017-06-06 03:44:56 +02:00
if b.Available() < 4 {
b.growAtLeast(4)
2017-01-22 13:28:14 +02:00
}
b.buf[b.n] = c1
2017-06-06 03:44:56 +02:00
b.buf[b.n+1] = c2
b.buf[b.n+2] = c3
b.buf[b.n+3] = c4
2017-01-22 13:28:14 +02:00
b.n += 4
}
func (b *Stream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) {
if b.Error != nil {
return
}
2017-06-06 03:44:56 +02:00
if b.Available() < 5 {
b.growAtLeast(5)
2017-01-22 13:28:14 +02:00
}
b.buf[b.n] = c1
2017-06-06 03:44:56 +02:00
b.buf[b.n+1] = c2
b.buf[b.n+2] = c3
b.buf[b.n+3] = c4
b.buf[b.n+4] = c5
2017-01-22 13:28:14 +02:00
b.n += 5
2017-01-21 18:04:08 +02:00
}
2017-01-07 06:28:16 +02:00
// Flush writes any buffered data to the underlying io.Writer.
func (b *Stream) Flush() error {
2017-06-06 03:44:56 +02:00
if b.out == nil {
return nil
}
2017-01-07 06:28:16 +02:00
if b.Error != nil {
return b.Error
}
if b.n == 0 {
return nil
}
n, err := b.out.Write(b.buf[0:b.n])
if n < b.n && err == nil {
err = io.ErrShortWrite
}
if err != nil {
if n > 0 && n < b.n {
2017-06-06 03:44:56 +02:00
copy(b.buf[0:b.n-n], b.buf[n:b.n])
2017-01-07 06:28:16 +02:00
}
b.n -= n
b.Error = err
return err
}
b.n = 0
return nil
}
2017-06-06 03:44:56 +02:00
func (b *Stream) ensure(minimal int) {
available := b.Available()
if available < minimal {
2017-06-06 08:16:54 +02:00
if b.n > 1024 {
2017-06-06 03:44:56 +02:00
b.Flush()
}
b.growAtLeast(minimal)
2017-01-07 17:06:48 +02:00
}
2017-06-06 03:44:56 +02:00
}
func (b *Stream) growAtLeast(minimal int) {
toGrow := len(b.buf)
if toGrow < minimal {
toGrow = minimal
}
newBuf := make([]byte, len(b.buf)+toGrow)
copy(newBuf, b.Buffer())
b.buf = newBuf
}
func (b *Stream) WriteRaw(s string) {
b.ensure(len(s))
2017-01-07 17:06:48 +02:00
if b.Error != nil {
return
}
n := copy(b.buf[b.n:], s)
b.n += n
}
2017-01-18 17:33:40 +02:00
func (stream *Stream) WriteNil() {
2017-01-22 13:28:14 +02:00
stream.writeFourBytes('n', 'u', 'l', 'l')
2017-01-07 06:28:16 +02:00
}
2017-01-07 16:08:45 +02:00
func (stream *Stream) WriteTrue() {
2017-01-22 13:28:14 +02:00
stream.writeFourBytes('t', 'r', 'u', 'e')
2017-01-07 16:08:45 +02:00
}
func (stream *Stream) WriteFalse() {
2017-01-22 13:28:14 +02:00
stream.writeFiveBytes('f', 'a', 'l', 's', 'e')
2017-01-07 16:08:45 +02:00
}
func (stream *Stream) WriteBool(val bool) {
if val {
2017-01-22 13:28:14 +02:00
stream.WriteTrue()
2017-01-07 16:08:45 +02:00
} else {
2017-01-22 13:28:14 +02:00
stream.WriteFalse()
2017-01-07 16:08:45 +02:00
}
}
func (stream *Stream) WriteObjectStart() {
stream.indention += stream.cfg.indentionStep
2017-01-07 16:08:45 +02:00
stream.writeByte('{')
stream.writeIndention(0)
}
func (stream *Stream) WriteObjectField(field string) {
stream.WriteString(field)
stream.writeByte(':')
}
func (stream *Stream) WriteObjectEnd() {
stream.writeIndention(stream.cfg.indentionStep)
stream.indention -= stream.cfg.indentionStep
2017-01-07 16:08:45 +02:00
stream.writeByte('}')
}
2017-01-09 13:48:57 +02:00
func (stream *Stream) WriteEmptyObject() {
stream.writeByte('{')
stream.writeByte('}')
}
2017-01-07 16:08:45 +02:00
func (stream *Stream) WriteMore() {
stream.writeByte(',')
stream.writeIndention(0)
}
2017-01-07 16:16:20 +02:00
func (stream *Stream) WriteArrayStart() {
stream.indention += stream.cfg.indentionStep
2017-01-07 16:16:20 +02:00
stream.writeByte('[')
stream.writeIndention(0)
}
2017-01-09 13:48:57 +02:00
func (stream *Stream) WriteEmptyArray() {
stream.writeByte('[')
stream.writeByte(']')
}
2017-01-07 16:16:20 +02:00
func (stream *Stream) WriteArrayEnd() {
stream.writeIndention(stream.cfg.indentionStep)
stream.indention -= stream.cfg.indentionStep
2017-01-07 16:16:20 +02:00
stream.writeByte(']')
}
2017-01-07 16:08:45 +02:00
func (stream *Stream) writeIndention(delta int) {
2017-06-06 03:44:56 +02:00
if stream.indention == 0 {
2017-01-07 16:08:45 +02:00
return
}
stream.writeByte('\n')
toWrite := stream.indention - delta
2017-06-06 03:44:56 +02:00
stream.ensure(toWrite)
2017-06-06 17:27:00 +02:00
for i := 0; i < toWrite && stream.n < len(stream.buf); i++ {
2017-06-06 03:44:56 +02:00
stream.buf[stream.n] = ' '
2017-06-06 17:27:00 +02:00
stream.n++
2017-01-07 16:08:45 +02:00
}
2017-06-06 03:44:56 +02:00
}