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.go167
1 files changed, 41 insertions, 126 deletions
diff --git a/vendor/github.com/ugorji/go/codec/writer.go b/vendor/github.com/ugorji/go/codec/writer.go
index b6e4813f8..fcfce6109 100644
--- a/vendor/github.com/ugorji/go/codec/writer.go
+++ b/vendor/github.com/ugorji/go/codec/writer.go
@@ -3,10 +3,14 @@
package codec
-import "io"
+import (
+ "io"
+)
+
+const maxConsecutiveEmptyWrites = 16 // 2 is sufficient, 16 is enough, 64 is optimal
// encWriter abstracts writing to a byte array or to an io.Writer.
-type encWriter interface {
+type encWriterI interface {
writeb([]byte)
writestr(string)
writeqstr(string) // write string wrapped in quotes ie "..."
@@ -17,7 +21,11 @@ type encWriter interface {
writen4([4]byte)
writen8([8]byte)
+ // isBytes() bool
end()
+
+ resetIO(w io.Writer, bufsize int, blist *bytesFreeList)
+ resetBytes(in []byte, out *[]byte)
}
// ---------------------------------------------
@@ -32,16 +40,18 @@ type bufioEncWriter struct {
b [16]byte // scratch buffer and padding (cache-aligned)
}
-func (z *bufioEncWriter) reset(w io.Writer, bufsize int, blist *bytesFreelist) {
+// MARKER: use setByteAt/byteAt to elide the bounds-checks
+// when we are sure that we don't go beyond the bounds.
+
+func (z *bufioEncWriter) resetBytes(in []byte, out *[]byte) {
+ halt.errorStr("resetBytes is unsupported by bufioEncWriter")
+}
+
+func (z *bufioEncWriter) resetIO(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
- }
+ // use minimum bufsize of 16, matching the array z.b and accomodating writen methods (where n <= 8)
+ bufsize = max(16, bufsize) // max(byteBufSize, bufsize)
if cap(z.buf) < bufsize {
if len(z.buf) > 0 && &z.buf[0] != &z.b[0] {
blist.put(z.buf)
@@ -56,17 +66,19 @@ func (z *bufioEncWriter) reset(w io.Writer, bufsize int, blist *bytesFreelist) {
}
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
+ var n int
+ for i := maxConsecutiveEmptyReads; i > 0; i-- {
+ n, err = z.w.Write(z.buf[:z.n])
+ z.n -= n
+ if z.n == 0 || err != nil {
+ return
}
+ // at this point: z.n > 0 && err == nil
if n > 0 {
copy(z.buf, z.buf[n:z.n+n])
}
}
- return err
+ return io.ErrShortWrite // OR io.ErrNoProgress: not enough (or no) data written
}
func (z *bufioEncWriter) flush() {
@@ -131,6 +143,7 @@ func (z *bufioEncWriter) writen1(b1 byte) {
// z.buf[z.n] = b1
z.n++
}
+
func (z *bufioEncWriter) writen2(b1, b2 byte) {
if 2 > len(z.buf)-z.n {
z.flush()
@@ -169,8 +182,14 @@ func (z *bufioEncWriter) endErr() (err error) {
return
}
+func (z *bufioEncWriter) end() {
+ halt.onerror(z.endErr())
+}
+
// ---------------------------------------------
+var bytesEncAppenderDefOut = []byte{}
+
// bytesEncAppender implements encWriter and can write to an byte slice.
type bytesEncAppender struct {
b []byte
@@ -203,122 +222,18 @@ func (z *bytesEncAppender) writen4(b [4]byte) {
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
+ // z.b = append(z.b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7])
}
-func (z *bytesEncAppender) endErr() error {
+func (z *bytesEncAppender) end() {
*(z.out) = z.b
- return nil
}
-func (z *bytesEncAppender) reset(in []byte, out *[]byte) {
+
+func (z *bytesEncAppender) resetBytes(in []byte, out *[]byte) {
z.b = in[:0]
z.out = out
}
-// --------------------------------------------------
-
-type encWr struct {
- wb bytesEncAppender
- wf *bufioEncWriter
-
- bytes bool // encoding to []byte
-
- // MARKER: these fields below should belong directly in Encoder.
- // we pack them here for space efficiency and cache-line optimization.
-
- 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)
-}
-
-// 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) writestr(s string) {
- if z.bytes {
- z.wb.writestr(s)
- } else {
- z.wf.writestr(s)
- }
+func (z *bytesEncAppender) resetIO(w io.Writer, bufsize int, blist *bytesFreeList) {
+ halt.errorStr("resetIO is unsupported by bytesEncAppender")
}
-
-// MARKER: Add WriteStr to be called directly by generated code without a genHelper forwarding function.
-// Go's inlining model adds cost for forwarding functions, preventing inlining (cost goes above 80 budget).
-
-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 {
- // MARKER: z.wb.writen4(b1, b2, b3, b4)
- z.wb.b = append(z.wb.b, b[:]...)
- // z.wb.writen4(b)
- } else {
- z.wf.writen4(b)
- }
-}
-func (z *encWr) writen8(b [8]byte) {
- if z.bytes {
- // z.wb.b = append(z.wb.b, b[:]...)
- z.wb.writen8(b)
- } else {
- z.wf.writen8(b)
- }
-}
-
-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) 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)