summaryrefslogtreecommitdiff
path: root/vendor/github.com/ugorji/go/codec/writer.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/ugorji/go/codec/writer.go')
-rw-r--r--vendor/github.com/ugorji/go/codec/writer.go289
1 files changed, 289 insertions, 0 deletions
diff --git a/vendor/github.com/ugorji/go/codec/writer.go b/vendor/github.com/ugorji/go/codec/writer.go
new file mode 100644
index 000000000..4d2c9fe10
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/writer.go
@@ -0,0 +1,289 @@
+// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import "io"
+
+// encWriter abstracts writing to a byte array or to an io.Writer.
+type encWriter interface {
+ writeb([]byte)
+ writestr(string)
+ writeqstr(string) // write string wrapped in quotes ie "..."
+ writen1(byte)
+
+ // add convenience functions for writing 2,4
+ writen2(byte, byte)
+ writen4([4]byte)
+ writen8([8]byte)
+
+ end()
+}
+
+// ---------------------------------------------
+
+type bufioEncWriter struct {
+ w io.Writer
+
+ buf []byte
+
+ n int
+
+ b [16]byte // scratch buffer and padding (cache-aligned)
+}
+
+func (z *bufioEncWriter) reset(w io.Writer, bufsize int, blist *bytesFreelist) {
+ z.w = w
+ z.n = 0
+ if bufsize <= 0 {
+ bufsize = defEncByteBufSize
+ }
+ // bufsize must be >= 8, to accomodate writen methods (where n <= 8)
+ if bufsize <= 8 {
+ bufsize = 8
+ }
+ if cap(z.buf) < bufsize {
+ if len(z.buf) > 0 && &z.buf[0] != &z.b[0] {
+ blist.put(z.buf)
+ }
+ if len(z.b) > bufsize {
+ z.buf = z.b[:]
+ } else {
+ z.buf = blist.get(bufsize)
+ }
+ }
+ z.buf = z.buf[:cap(z.buf)]
+}
+
+func (z *bufioEncWriter) flushErr() (err error) {
+ n, err := z.w.Write(z.buf[:z.n])
+ z.n -= n
+ if z.n > 0 {
+ if err == nil {
+ err = io.ErrShortWrite
+ }
+ if n > 0 {
+ copy(z.buf, z.buf[n:z.n+n])
+ }
+ }
+ return err
+}
+
+func (z *bufioEncWriter) flush() {
+ halt.onerror(z.flushErr())
+}
+
+func (z *bufioEncWriter) writeb(s []byte) {
+LOOP:
+ a := len(z.buf) - z.n
+ if len(s) > a {
+ z.n += copy(z.buf[z.n:], s[:a])
+ s = s[a:]
+ z.flush()
+ goto LOOP
+ }
+ z.n += copy(z.buf[z.n:], s)
+}
+
+func (z *bufioEncWriter) writestr(s string) {
+ // z.writeb(bytesView(s)) // inlined below
+LOOP:
+ a := len(z.buf) - z.n
+ if len(s) > a {
+ z.n += copy(z.buf[z.n:], s[:a])
+ s = s[a:]
+ z.flush()
+ goto LOOP
+ }
+ z.n += copy(z.buf[z.n:], s)
+}
+
+func (z *bufioEncWriter) writeqstr(s string) {
+ // z.writen1('"')
+ // z.writestr(s)
+ // z.writen1('"')
+
+ if z.n+len(s)+2 > len(z.buf) {
+ z.flush()
+ }
+ z.buf[z.n] = '"'
+ z.n++
+LOOP:
+ a := len(z.buf) - z.n
+ if len(s)+1 > a {
+ z.n += copy(z.buf[z.n:], s[:a])
+ s = s[a:]
+ z.flush()
+ goto LOOP
+ }
+ z.n += copy(z.buf[z.n:], s)
+ z.buf[z.n] = '"'
+ z.n++
+}
+
+func (z *bufioEncWriter) writen1(b1 byte) {
+ if 1 > len(z.buf)-z.n {
+ z.flush()
+ }
+ z.buf[z.n] = b1
+ z.n++
+}
+func (z *bufioEncWriter) writen2(b1, b2 byte) {
+ if 2 > len(z.buf)-z.n {
+ z.flush()
+ }
+ z.buf[z.n+1] = b2
+ z.buf[z.n] = b1
+ z.n += 2
+}
+func (z *bufioEncWriter) writen4(b [4]byte) {
+ if 4 > len(z.buf)-z.n {
+ z.flush()
+ }
+ copy(z.buf[z.n:], b[:])
+ z.n += 4
+}
+
+func (z *bufioEncWriter) writen8(b [8]byte) {
+ if 8 > len(z.buf)-z.n {
+ z.flush()
+ }
+ copy(z.buf[z.n:], b[:])
+ z.n += 8
+}
+
+func (z *bufioEncWriter) endErr() (err error) {
+ if z.n > 0 {
+ err = z.flushErr()
+ }
+ return
+}
+
+// ---------------------------------------------
+
+// bytesEncAppender implements encWriter and can write to an byte slice.
+type bytesEncAppender struct {
+ b []byte
+ out *[]byte
+}
+
+func (z *bytesEncAppender) writeb(s []byte) {
+ z.b = append(z.b, s...)
+}
+func (z *bytesEncAppender) writestr(s string) {
+ z.b = append(z.b, s...)
+}
+func (z *bytesEncAppender) writeqstr(s string) {
+ z.b = append(append(append(z.b, '"'), s...), '"')
+ // z.b = append(z.b, '"')
+ // z.b = append(z.b, s...)
+ // z.b = append(z.b, '"')
+}
+func (z *bytesEncAppender) writen1(b1 byte) {
+ z.b = append(z.b, b1)
+}
+func (z *bytesEncAppender) writen2(b1, b2 byte) {
+ z.b = append(z.b, b1, b2)
+}
+func (z *bytesEncAppender) writen4(b [4]byte) {
+ z.b = append(z.b, b[:]...)
+ // z.b = append(z.b, b[0], b[1], b[2], b[3]) // prevents inlining encWr.writen4
+}
+func (z *bytesEncAppender) writen8(b [8]byte) {
+ z.b = append(z.b, b[:]...)
+ // z.b = append(z.b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]) // prevents inlining encWr.writen4
+}
+func (z *bytesEncAppender) endErr() error {
+ *(z.out) = z.b
+ return nil
+}
+func (z *bytesEncAppender) reset(in []byte, out *[]byte) {
+ z.b = in[:0]
+ z.out = out
+}
+
+// --------------------------------------------------
+
+type encWr struct {
+ bytes bool // encoding to []byte
+ js bool // is json encoder?
+ be bool // is binary encoder?
+
+ c containerState
+
+ calls uint16
+ seq uint16 // sequencer (e.g. used by binc for symbols, etc)
+ wb bytesEncAppender
+ wf *bufioEncWriter
+}
+
+// MARKER: manually inline bytesEncAppender.writenx/writeqstr methods,
+// as calling them causes encWr.writenx/writeqstr methods to not be inlined (cost > 80).
+//
+// i.e. e.g. instead of writing z.wb.writen2(b1, b2), use z.wb.b = append(z.wb.b, b1, b2)
+
+func (z *encWr) writeb(s []byte) {
+ if z.bytes {
+ z.wb.writeb(s)
+ } else {
+ z.wf.writeb(s)
+ }
+}
+func (z *encWr) writeqstr(s string) {
+ if z.bytes {
+ // MARKER: z.wb.writeqstr(s)
+ z.wb.b = append(append(append(z.wb.b, '"'), s...), '"')
+ } else {
+ z.wf.writeqstr(s)
+ }
+}
+func (z *encWr) writestr(s string) {
+ if z.bytes {
+ z.wb.writestr(s)
+ } else {
+ z.wf.writestr(s)
+ }
+}
+func (z *encWr) writen1(b1 byte) {
+ if z.bytes {
+ z.wb.writen1(b1)
+ } else {
+ z.wf.writen1(b1)
+ }
+}
+
+func (z *encWr) writen2(b1, b2 byte) {
+ if z.bytes {
+ // MARKER: z.wb.writen2(b1, b2)
+ z.wb.b = append(z.wb.b, b1, b2)
+ } else {
+ z.wf.writen2(b1, b2)
+ }
+}
+func (z *encWr) writen4(b [4]byte) {
+ if z.bytes {
+ z.wb.writen4(b)
+ } else {
+ z.wf.writen4(b)
+ }
+}
+func (z *encWr) writen8(b [8]byte) {
+ if z.bytes {
+ z.wb.writen8(b)
+ } else {
+ z.wf.writen8(b)
+ }
+}
+
+func (z *encWr) endErr() error {
+ if z.bytes {
+ return z.wb.endErr()
+ }
+ return z.wf.endErr()
+}
+
+func (z *encWr) end() {
+ halt.onerror(z.endErr())
+}
+
+var _ encWriter = (*encWr)(nil)