mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[chore] Update gin to v1.9.0 (#1553)
This commit is contained in:
655
vendor/github.com/ugorji/go/codec/reader.go
generated
vendored
655
vendor/github.com/ugorji/go/codec/reader.go
generated
vendored
@ -3,7 +3,12 @@
|
||||
|
||||
package codec
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// decReader abstracts the reading source, allowing implementations that can
|
||||
// read from an io.Reader or directly off a byte slice with zero-copying.
|
||||
@ -17,8 +22,7 @@ type decReader interface {
|
||||
|
||||
readn1() byte
|
||||
readn2() [2]byte
|
||||
// readn3 will read 3 bytes into the top-most elements of a 4-byte array
|
||||
readn3() [4]byte
|
||||
readn3() [3]byte
|
||||
readn4() [4]byte
|
||||
readn8() [8]byte
|
||||
// readn1eof() (v uint8, eof bool)
|
||||
@ -62,55 +66,57 @@ const (
|
||||
unreadByteCanUnread
|
||||
)
|
||||
|
||||
// const defBufReaderSize = 4096
|
||||
|
||||
// --------------------
|
||||
|
||||
type ioDecReaderCommon struct {
|
||||
r io.Reader // the reader passed in
|
||||
// ioReaderByteScanner contains the io.Reader and io.ByteScanner interfaces
|
||||
type ioReaderByteScanner interface {
|
||||
io.Reader
|
||||
io.ByteScanner
|
||||
// ReadByte() (byte, error)
|
||||
// UnreadByte() error
|
||||
// Read(p []byte) (n int, err error)
|
||||
}
|
||||
|
||||
n uint // num read
|
||||
// ioReaderByteScannerT does a simple wrapper of a io.ByteScanner
|
||||
// over a io.Reader
|
||||
type ioReaderByteScannerT struct {
|
||||
r io.Reader
|
||||
|
||||
l byte // last byte
|
||||
ls unreadByteStatus // last byte status
|
||||
|
||||
b [6]byte // tiny buffer for reading single bytes
|
||||
|
||||
blist *bytesFreelist
|
||||
|
||||
bufr []byte // buffer for readTo/readUntil
|
||||
_ [2]byte // padding
|
||||
b [4]byte // tiny buffer for reading single bytes
|
||||
}
|
||||
|
||||
func (z *ioDecReaderCommon) reset(r io.Reader, blist *bytesFreelist) {
|
||||
z.blist = blist
|
||||
z.r = r
|
||||
z.ls = unreadByteUndefined
|
||||
z.l, z.n = 0, 0
|
||||
z.bufr = z.blist.check(z.bufr, 256)
|
||||
func (z *ioReaderByteScannerT) ReadByte() (c byte, err error) {
|
||||
if z.ls == unreadByteCanRead {
|
||||
z.ls = unreadByteCanUnread
|
||||
c = z.l
|
||||
} else {
|
||||
_, err = z.Read(z.b[:1])
|
||||
c = z.b[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReaderCommon) numread() uint {
|
||||
return z.n
|
||||
func (z *ioReaderByteScannerT) UnreadByte() (err error) {
|
||||
switch z.ls {
|
||||
case unreadByteCanUnread:
|
||||
z.ls = unreadByteCanRead
|
||||
case unreadByteCanRead:
|
||||
err = errDecUnreadByteLastByteNotRead
|
||||
case unreadByteUndefined:
|
||||
err = errDecUnreadByteNothingToRead
|
||||
default:
|
||||
err = errDecUnreadByteUnknown
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
|
||||
// ioDecReader is a decReader that reads off an io.Reader.
|
||||
//
|
||||
// It also has a fallback implementation of ByteScanner if needed.
|
||||
type ioDecReader struct {
|
||||
ioDecReaderCommon
|
||||
|
||||
br io.ByteScanner
|
||||
|
||||
x [64 + 48]byte // for: get struct field name, swallow valueTypeBytes, etc
|
||||
}
|
||||
|
||||
func (z *ioDecReader) reset(r io.Reader, blist *bytesFreelist) {
|
||||
z.ioDecReaderCommon.reset(r, blist)
|
||||
|
||||
z.br, _ = r.(io.ByteScanner)
|
||||
}
|
||||
|
||||
func (z *ioDecReader) Read(p []byte) (n int, err error) {
|
||||
func (z *ioReaderByteScannerT) Read(p []byte) (n int, err error) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
@ -139,45 +145,79 @@ func (z *ioDecReader) Read(p []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) ReadByte() (c byte, err error) {
|
||||
if z.br != nil {
|
||||
c, err = z.br.ReadByte()
|
||||
if err == nil {
|
||||
z.l = c
|
||||
z.ls = unreadByteCanUnread
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
n, err := z.Read(z.b[:1])
|
||||
if n == 1 {
|
||||
c = z.b[0]
|
||||
if err == io.EOF {
|
||||
err = nil // read was successful, so postpone EOF (till next time)
|
||||
}
|
||||
}
|
||||
return
|
||||
func (z *ioReaderByteScannerT) reset(r io.Reader) {
|
||||
z.r = r
|
||||
z.ls = unreadByteUndefined
|
||||
z.l = 0
|
||||
}
|
||||
|
||||
func (z *ioDecReader) UnreadByte() (err error) {
|
||||
if z.br != nil {
|
||||
err = z.br.UnreadByte()
|
||||
if err == nil {
|
||||
z.ls = unreadByteCanRead
|
||||
// ioDecReader is a decReader that reads off an io.Reader.
|
||||
type ioDecReader struct {
|
||||
rr ioReaderByteScannerT // the reader passed in, wrapped into a reader+bytescanner
|
||||
|
||||
n uint // num read
|
||||
|
||||
blist *bytesFreelist
|
||||
|
||||
bufr []byte // buffer for readTo/readUntil
|
||||
br ioReaderByteScanner // main reader used for Read|ReadByte|UnreadByte
|
||||
bb *bufio.Reader // created internally, and reused on reset if needed
|
||||
|
||||
x [64 + 40]byte // for: get struct field name, swallow valueTypeBytes, etc
|
||||
}
|
||||
|
||||
func (z *ioDecReader) reset(r io.Reader, bufsize int, blist *bytesFreelist) {
|
||||
z.blist = blist
|
||||
z.n = 0
|
||||
z.bufr = z.blist.check(z.bufr, 256)
|
||||
z.br = nil
|
||||
|
||||
var ok bool
|
||||
|
||||
if bufsize <= 0 {
|
||||
z.br, ok = r.(ioReaderByteScanner)
|
||||
if !ok {
|
||||
z.rr.reset(r)
|
||||
z.br = &z.rr
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch z.ls {
|
||||
case unreadByteCanUnread:
|
||||
z.ls = unreadByteCanRead
|
||||
case unreadByteCanRead:
|
||||
err = errDecUnreadByteLastByteNotRead
|
||||
case unreadByteUndefined:
|
||||
err = errDecUnreadByteNothingToRead
|
||||
default:
|
||||
err = errDecUnreadByteUnknown
|
||||
// bufsize > 0 ...
|
||||
|
||||
// if bytes.[Buffer|Reader], no value in adding extra buffer
|
||||
// if bufio.Reader, no value in extra buffer unless size changes
|
||||
switch bb := r.(type) {
|
||||
case *strings.Reader:
|
||||
z.br = bb
|
||||
case *bytes.Buffer:
|
||||
z.br = bb
|
||||
case *bytes.Reader:
|
||||
z.br = bb
|
||||
case *bufio.Reader:
|
||||
if bb.Size() == bufsize {
|
||||
z.br = bb
|
||||
}
|
||||
}
|
||||
|
||||
if z.br == nil {
|
||||
if z.bb != nil && z.bb.Size() == bufsize {
|
||||
z.bb.Reset(r)
|
||||
} else {
|
||||
z.bb = bufio.NewReaderSize(r, bufsize)
|
||||
}
|
||||
z.br = z.bb
|
||||
}
|
||||
}
|
||||
|
||||
func (z *ioDecReader) numread() uint {
|
||||
return z.n
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn1() (b uint8) {
|
||||
b, err := z.br.ReadByte()
|
||||
halt.onerror(err)
|
||||
z.n++
|
||||
return
|
||||
}
|
||||
|
||||
@ -186,8 +226,8 @@ func (z *ioDecReader) readn2() (bs [2]byte) {
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn3() (bs [4]byte) {
|
||||
z.readb(bs[1:])
|
||||
func (z *ioDecReader) readn3() (bs [3]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
@ -203,16 +243,16 @@ func (z *ioDecReader) readn8() (bs [8]byte) {
|
||||
|
||||
func (z *ioDecReader) readx(n uint) (bs []byte) {
|
||||
if n == 0 {
|
||||
return
|
||||
return zeroByteSlice
|
||||
}
|
||||
if n < uint(len(z.x)) {
|
||||
bs = z.x[:n]
|
||||
} else {
|
||||
bs = make([]byte, n)
|
||||
}
|
||||
_, err := readFull(z.r, bs)
|
||||
nn, err := readFull(z.br, bs)
|
||||
z.n += nn
|
||||
halt.onerror(err)
|
||||
z.n += uint(len(bs))
|
||||
return
|
||||
}
|
||||
|
||||
@ -220,38 +260,36 @@ func (z *ioDecReader) readb(bs []byte) {
|
||||
if len(bs) == 0 {
|
||||
return
|
||||
}
|
||||
_, err := readFull(z.r, bs)
|
||||
nn, err := readFull(z.br, bs)
|
||||
z.n += nn
|
||||
halt.onerror(err)
|
||||
z.n += uint(len(bs))
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn1() (b uint8) {
|
||||
b, err := z.ReadByte()
|
||||
halt.onerror(err)
|
||||
z.n++
|
||||
return
|
||||
}
|
||||
|
||||
func (z *ioDecReader) readn1eof() (b uint8, eof bool) {
|
||||
b, err := z.ReadByte()
|
||||
if err == nil {
|
||||
z.n++
|
||||
} else if err == io.EOF {
|
||||
eof = true
|
||||
} else {
|
||||
halt.onerror(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
// func (z *ioDecReader) readn1eof() (b uint8, eof bool) {
|
||||
// b, err := z.br.ReadByte()
|
||||
// if err == nil {
|
||||
// z.n++
|
||||
// } else if err == io.EOF {
|
||||
// eof = true
|
||||
// } else {
|
||||
// halt.onerror(err)
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
func (z *ioDecReader) jsonReadNum() (bs []byte) {
|
||||
z.unreadn1()
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
i, eof := z.readn1eof()
|
||||
if eof {
|
||||
// i, eof := z.readn1eof()
|
||||
i, err := z.br.ReadByte()
|
||||
if err == io.EOF {
|
||||
return z.bufr
|
||||
}
|
||||
if err != nil {
|
||||
halt.onerror(err)
|
||||
}
|
||||
z.n++
|
||||
if isNumberChar(i) {
|
||||
z.bufr = append(z.bufr, i)
|
||||
goto LOOP
|
||||
@ -280,307 +318,45 @@ LOOP:
|
||||
return
|
||||
}
|
||||
|
||||
// func (z *ioDecReader) readUntil(stop byte) []byte {
|
||||
// z.bufr = z.bufr[:0]
|
||||
// LOOP:
|
||||
// token := z.readn1()
|
||||
// z.bufr = append(z.bufr, token)
|
||||
// if token == stop {
|
||||
// return z.bufr[:len(z.bufr)-1]
|
||||
// }
|
||||
// goto LOOP
|
||||
// }
|
||||
|
||||
func (z *ioDecReader) readUntil(stop byte) []byte {
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
token := z.readn1()
|
||||
z.bufr = append(z.bufr, token)
|
||||
if token == stop {
|
||||
return z.bufr[:len(z.bufr)-1]
|
||||
return z.bufr
|
||||
}
|
||||
z.bufr = append(z.bufr, token)
|
||||
goto LOOP
|
||||
}
|
||||
|
||||
func (z *ioDecReader) unreadn1() {
|
||||
err := z.UnreadByte()
|
||||
err := z.br.UnreadByte()
|
||||
halt.onerror(err)
|
||||
z.n--
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
type bufioDecReader struct {
|
||||
ioDecReaderCommon
|
||||
|
||||
c uint // cursor
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) reset(r io.Reader, bufsize int, blist *bytesFreelist) {
|
||||
z.ioDecReaderCommon.reset(r, blist)
|
||||
z.c = 0
|
||||
if cap(z.buf) < bufsize {
|
||||
z.buf = blist.get(bufsize)
|
||||
} else {
|
||||
z.buf = z.buf[:0]
|
||||
}
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readb(p []byte) {
|
||||
var n = uint(copy(p, z.buf[z.c:]))
|
||||
z.n += n
|
||||
z.c += n
|
||||
if len(p) != int(n) {
|
||||
z.readbFill(p, n, true, false)
|
||||
}
|
||||
}
|
||||
|
||||
func readbFillHandleErr(err error, must, eof bool) (isEOF bool) {
|
||||
if err == io.EOF {
|
||||
isEOF = true
|
||||
}
|
||||
if must && !(eof && isEOF) {
|
||||
halt.onerror(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readbFill(p0 []byte, n uint, must, eof bool) (isEOF bool, err error) {
|
||||
// at this point, there's nothing in z.buf to read (z.buf is fully consumed)
|
||||
var p []byte
|
||||
if p0 != nil {
|
||||
p = p0[n:]
|
||||
}
|
||||
var n2 uint
|
||||
if len(p) > cap(z.buf) {
|
||||
n2, err = readFull(z.r, p)
|
||||
if err != nil {
|
||||
isEOF = readbFillHandleErr(err, must, eof)
|
||||
return
|
||||
}
|
||||
n += n2
|
||||
z.n += n2
|
||||
// always keep last byte in z.buf
|
||||
z.buf = z.buf[:1]
|
||||
z.buf[0] = p[len(p)-1]
|
||||
z.c = 1
|
||||
return
|
||||
}
|
||||
// z.c is now 0, and len(p) <= cap(z.buf)
|
||||
var n1 int
|
||||
LOOP:
|
||||
// for len(p) > 0 && z.err == nil {
|
||||
z.buf = z.buf[0:cap(z.buf)]
|
||||
n1, err = z.r.Read(z.buf)
|
||||
n2 = uint(n1)
|
||||
if n2 == 0 && err != nil {
|
||||
isEOF = readbFillHandleErr(err, must, eof)
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
z.buf = z.buf[:n2]
|
||||
z.c = 0
|
||||
if len(p) > 0 {
|
||||
n2 = uint(copy(p, z.buf))
|
||||
z.c = n2
|
||||
n += n2
|
||||
z.n += n2
|
||||
p = p[n2:]
|
||||
if len(p) > 0 {
|
||||
goto LOOP
|
||||
}
|
||||
if z.c == 0 {
|
||||
z.buf = z.buf[:1]
|
||||
z.buf[0] = p[len(p)-1]
|
||||
z.c = 1
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn1() (b byte) {
|
||||
if z.c >= uint(len(z.buf)) {
|
||||
z.readbFill(nil, 0, true, false)
|
||||
}
|
||||
b = z.buf[z.c]
|
||||
z.c++
|
||||
z.n++
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn1eof() (b byte, eof bool) {
|
||||
if z.c >= uint(len(z.buf)) {
|
||||
eof, _ = z.readbFill(nil, 0, true, true)
|
||||
if eof {
|
||||
return
|
||||
}
|
||||
}
|
||||
b = z.buf[z.c]
|
||||
z.c++
|
||||
z.n++
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) unreadn1() {
|
||||
if z.c == 0 {
|
||||
halt.onerror(errDecUnreadByteNothingToRead)
|
||||
}
|
||||
z.c--
|
||||
z.n--
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn2() (bs [2]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn3() (bs [4]byte) {
|
||||
z.readb(bs[1:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn4() (bs [4]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readn8() (bs [8]byte) {
|
||||
z.readb(bs[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readx(n uint) (bs []byte) {
|
||||
if n == 0 {
|
||||
// return
|
||||
} else if z.c+n <= uint(len(z.buf)) {
|
||||
bs = z.buf[z.c : z.c+n]
|
||||
z.n += n
|
||||
z.c += n
|
||||
} else {
|
||||
bs = make([]byte, n)
|
||||
// n no longer used - can reuse
|
||||
n = uint(copy(bs, z.buf[z.c:]))
|
||||
z.n += n
|
||||
z.c += n
|
||||
z.readbFill(bs, n, true, false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) jsonReadNum() (bs []byte) {
|
||||
z.unreadn1()
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
i, eof := z.readn1eof()
|
||||
if eof {
|
||||
return z.bufr
|
||||
}
|
||||
if isNumberChar(i) {
|
||||
z.bufr = append(z.bufr, i)
|
||||
goto LOOP
|
||||
}
|
||||
z.unreadn1()
|
||||
return z.bufr
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) jsonReadAsisChars() (bs []byte) {
|
||||
z.bufr = z.bufr[:0]
|
||||
LOOP:
|
||||
i := z.readn1()
|
||||
z.bufr = append(z.bufr, i)
|
||||
if i == '"' || i == '\\' {
|
||||
return z.bufr
|
||||
}
|
||||
goto LOOP
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) skipWhitespace() (token byte) {
|
||||
i := z.c
|
||||
LOOP:
|
||||
if i < uint(len(z.buf)) {
|
||||
// inline z.skipLoopFn(i) and refactor, so cost is within inline budget
|
||||
token = z.buf[i]
|
||||
i++
|
||||
if isWhitespaceChar(token) {
|
||||
goto LOOP
|
||||
}
|
||||
z.n += i - 2 - z.c
|
||||
z.c = i
|
||||
return
|
||||
}
|
||||
return z.skipFillWhitespace()
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) skipFillWhitespace() (token byte) {
|
||||
z.n += uint(len(z.buf)) - z.c
|
||||
var i, n2 int
|
||||
var err error
|
||||
for {
|
||||
z.c = 0
|
||||
z.buf = z.buf[0:cap(z.buf)]
|
||||
n2, err = z.r.Read(z.buf)
|
||||
if n2 == 0 {
|
||||
halt.onerror(err)
|
||||
}
|
||||
z.buf = z.buf[:n2]
|
||||
for i, token = range z.buf {
|
||||
if !isWhitespaceChar(token) {
|
||||
z.n += (uint(i) - z.c) - 1
|
||||
z.loopFn(uint(i + 1))
|
||||
return
|
||||
}
|
||||
}
|
||||
z.n += uint(n2)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) loopFn(i uint) {
|
||||
z.c = i
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readUntil(stop byte) (out []byte) {
|
||||
i := z.c
|
||||
LOOP:
|
||||
if i < uint(len(z.buf)) {
|
||||
if z.buf[i] == stop {
|
||||
z.n += (i - z.c) - 1
|
||||
i++
|
||||
out = z.buf[z.c:i]
|
||||
z.c = i
|
||||
goto FINISH
|
||||
}
|
||||
i++
|
||||
goto LOOP
|
||||
}
|
||||
out = z.readUntilFill(stop)
|
||||
FINISH:
|
||||
return out[:len(out)-1]
|
||||
}
|
||||
|
||||
func (z *bufioDecReader) readUntilFill(stop byte) []byte {
|
||||
z.bufr = z.bufr[:0]
|
||||
z.n += uint(len(z.buf)) - z.c
|
||||
z.bufr = append(z.bufr, z.buf[z.c:]...)
|
||||
for {
|
||||
z.c = 0
|
||||
z.buf = z.buf[0:cap(z.buf)]
|
||||
n1, err := z.r.Read(z.buf)
|
||||
if n1 == 0 {
|
||||
halt.onerror(err)
|
||||
}
|
||||
n2 := uint(n1)
|
||||
z.buf = z.buf[:n2]
|
||||
for i, token := range z.buf {
|
||||
if token == stop {
|
||||
z.n += (uint(i) - z.c) - 1
|
||||
z.bufr = append(z.bufr, z.buf[z.c:i+1]...)
|
||||
z.loopFn(uint(i + 1))
|
||||
return z.bufr
|
||||
}
|
||||
}
|
||||
z.bufr = append(z.bufr, z.buf...)
|
||||
z.n += n2
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
// bytesDecReader is a decReader that reads off a byte slice with zero copying
|
||||
//
|
||||
// Note: we do not try to convert index'ing out of bounds to an io.EOF.
|
||||
// instead, we let it bubble up to the exported Encode/Decode method
|
||||
// and recover it as an io.EOF.
|
||||
//
|
||||
// Every function here MUST defensively check bounds either explicitly
|
||||
// or via a bounds check.
|
||||
//
|
||||
// see panicValToErr(...) function in helper.go.
|
||||
type bytesDecReader struct {
|
||||
b []byte // data
|
||||
@ -601,9 +377,11 @@ func (z *bytesDecReader) numread() uint {
|
||||
// However, we do it only once, and it's better than reslicing both z.b and return value.
|
||||
|
||||
func (z *bytesDecReader) readx(n uint) (bs []byte) {
|
||||
x := z.c + n
|
||||
bs = z.b[z.c:x]
|
||||
z.c = x
|
||||
// x := z.c + n
|
||||
// bs = z.b[z.c:x]
|
||||
// z.c = x
|
||||
bs = z.b[z.c : z.c+n]
|
||||
z.c += n
|
||||
return
|
||||
}
|
||||
|
||||
@ -630,23 +408,26 @@ func (z *bytesDecReader) readb(bs []byte) {
|
||||
// return z.b[z.c-1]
|
||||
// }
|
||||
|
||||
// MARKER: readn{1,2,3,4,8} should throw an out of bounds error if past length.
|
||||
// MARKER: readn1: explicitly ensure bounds check is done
|
||||
// MARKER: readn{2,3,4,8}: ensure you slice z.b completely so we get bounds error if past end.
|
||||
|
||||
func (z *bytesDecReader) readn1() (v uint8) {
|
||||
v = z.b[z.c]
|
||||
z.c++
|
||||
return
|
||||
}
|
||||
|
||||
// MARKER: for readn{2,3,4,8}, ensure you slice z.b completely so we get bounds error if past end.
|
||||
|
||||
func (z *bytesDecReader) readn2() (bs [2]byte) {
|
||||
// copy(bs[:], z.b[z.c:z.c+2])
|
||||
bs[1] = z.b[z.c+1]
|
||||
bs[0] = z.b[z.c]
|
||||
// bs[1] = z.b[z.c+1]
|
||||
// bs[0] = z.b[z.c]
|
||||
bs = okBytes2(z.b[z.c : z.c+2])
|
||||
z.c += 2
|
||||
return
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) readn3() (bs [4]byte) {
|
||||
func (z *bytesDecReader) readn3() (bs [3]byte) {
|
||||
// copy(bs[1:], z.b[z.c:z.c+3])
|
||||
bs = okBytes3(z.b[z.c : z.c+3])
|
||||
z.c += 3
|
||||
@ -668,14 +449,17 @@ func (z *bytesDecReader) readn8() (bs [8]byte) {
|
||||
}
|
||||
|
||||
func (z *bytesDecReader) jsonReadNum() []byte {
|
||||
z.c--
|
||||
z.c-- // unread
|
||||
i := z.c
|
||||
LOOP:
|
||||
// gracefully handle end of slice, as end of stream is meaningful here
|
||||
if i < uint(len(z.b)) && isNumberChar(z.b[i]) {
|
||||
i++
|
||||
goto LOOP
|
||||
}
|
||||
z.c, i = i, z.c
|
||||
// MARKER: 20230103: byteSliceOf here prevents inlining of jsonReadNum
|
||||
// return byteSliceOf(z.b, i, z.c)
|
||||
return z.b[i:z.c]
|
||||
}
|
||||
|
||||
@ -686,7 +470,8 @@ LOOP:
|
||||
i++
|
||||
if token == '"' || token == '\\' {
|
||||
z.c, i = i, z.c
|
||||
return z.b[i:z.c]
|
||||
return byteSliceOf(z.b, i, z.c)
|
||||
// return z.b[i:z.c]
|
||||
}
|
||||
goto LOOP
|
||||
}
|
||||
@ -707,7 +492,8 @@ func (z *bytesDecReader) readUntil(stop byte) (out []byte) {
|
||||
i := z.c
|
||||
LOOP:
|
||||
if z.b[i] == stop {
|
||||
out = z.b[z.c:i]
|
||||
out = byteSliceOf(z.b, z.c, i)
|
||||
// out = z.b[z.c:i]
|
||||
z.c = i + 1
|
||||
return
|
||||
}
|
||||
@ -718,6 +504,16 @@ LOOP:
|
||||
// --------------
|
||||
|
||||
type decRd struct {
|
||||
rb bytesDecReader
|
||||
ri *ioDecReader
|
||||
|
||||
decReader
|
||||
|
||||
bytes bool // is bytes reader
|
||||
|
||||
// MARKER: these fields below should belong directly in Encoder.
|
||||
// we pack them here for space efficiency and cache-line optimization.
|
||||
|
||||
mtr bool // is maptype a known type?
|
||||
str bool // is slicetype a known type?
|
||||
|
||||
@ -726,73 +522,66 @@ type decRd struct {
|
||||
jsms bool // is json handle, and MapKeyAsString
|
||||
cbor bool // is cbor handle
|
||||
|
||||
bytes bool // is bytes reader
|
||||
bufio bool // is this a bufioDecReader?
|
||||
cbreak bool // is a check breaker
|
||||
|
||||
rb bytesDecReader
|
||||
ri *ioDecReader
|
||||
bi *bufioDecReader
|
||||
|
||||
decReader
|
||||
}
|
||||
|
||||
// From out benchmarking, we see the following in terms of performance:
|
||||
// From out benchmarking, we see the following impact performance:
|
||||
//
|
||||
// - interface calls
|
||||
// - branch that can inline what it calls
|
||||
//
|
||||
// the if/else-if/else block is expensive to inline.
|
||||
// Each node of this construct costs a lot and dominates the budget.
|
||||
// Best to only do an if fast-path else block (so fast-path is inlined).
|
||||
// This is irrespective of inlineExtraCallCost set in $GOROOT/src/cmd/compile/internal/gc/inl.go
|
||||
//
|
||||
// In decRd methods below, we delegate all IO functions into their own methods.
|
||||
// This allows for the inlining of the common path when z.bytes=true.
|
||||
// Go 1.12+ supports inlining methods with up to 1 inlined function (or 2 if no other constructs).
|
||||
//
|
||||
// However, up through Go 1.13, decRd's readXXX, skip and unreadXXX methods are not inlined.
|
||||
// Consequently, there is no benefit to do the xxxIO methods for decRd at this time.
|
||||
// Instead, we have a if/else-if/else block so that IO calls do not have to jump through
|
||||
// a second unnecessary function call.
|
||||
//
|
||||
// If golang inlining gets better and bytesDecReader methods can be inlined,
|
||||
// then we can revert to using these 2 functions so the bytesDecReader
|
||||
// methods are inlined and the IO paths call out to a function.
|
||||
// - functions that are too big to inline
|
||||
// - interface calls (as no inlining can occur)
|
||||
//
|
||||
// decRd is designed to embed a decReader, and then re-implement some of the decReader
|
||||
// methods using a conditional branch. We only override the ones that have a bytes version
|
||||
// that is small enough to be inlined. We use ./run.sh -z to check.
|
||||
// Right now, only numread and readn1 can be inlined.
|
||||
// methods using a conditional branch.
|
||||
//
|
||||
// We only override the ones where the bytes version is inlined AND the wrapper method
|
||||
// (containing the bytes version alongside a conditional branch) is also inlined.
|
||||
//
|
||||
// We use ./run.sh -z to check.
|
||||
//
|
||||
// Right now, only numread and "carefully crafted" readn1 can be inlined.
|
||||
|
||||
func (z *decRd) numread() uint {
|
||||
if z.bytes {
|
||||
return z.rb.numread()
|
||||
} else if z.bufio {
|
||||
return z.bi.numread()
|
||||
} else {
|
||||
return z.ri.numread()
|
||||
}
|
||||
return z.ri.numread()
|
||||
}
|
||||
|
||||
func (z *decRd) readn1() (v uint8) {
|
||||
if z.bytes {
|
||||
// MARKER: manually inline, else this function is not inlined.
|
||||
// Keep in sync with bytesDecReader.readn1
|
||||
// return z.rb.readn1()
|
||||
// MARKER: calling z.rb.readn1() prevents decRd.readn1 from being inlined.
|
||||
// copy code, to manually inline and explicitly return here.
|
||||
// Keep in sync with bytesDecReader.readn1
|
||||
v = z.rb.b[z.rb.c]
|
||||
z.rb.c++
|
||||
} else {
|
||||
v = z.readn1IO()
|
||||
}
|
||||
return
|
||||
}
|
||||
func (z *decRd) readn1IO() uint8 {
|
||||
if z.bufio {
|
||||
return z.bi.readn1()
|
||||
return
|
||||
}
|
||||
return z.ri.readn1()
|
||||
}
|
||||
|
||||
// func (z *decRd) readn4() [4]byte {
|
||||
// if z.bytes {
|
||||
// return z.rb.readn4()
|
||||
// }
|
||||
// return z.ri.readn4()
|
||||
// }
|
||||
|
||||
// func (z *decRd) readn3() [3]byte {
|
||||
// if z.bytes {
|
||||
// return z.rb.readn3()
|
||||
// }
|
||||
// return z.ri.readn3()
|
||||
// }
|
||||
|
||||
// func (z *decRd) skipWhitespace() byte {
|
||||
// if z.bytes {
|
||||
// return z.rb.skipWhitespace()
|
||||
// }
|
||||
// return z.ri.skipWhitespace()
|
||||
// }
|
||||
|
||||
type devNullReader struct{}
|
||||
|
||||
func (devNullReader) Read(p []byte) (int, error) { return 0, io.EOF }
|
||||
|
Reference in New Issue
Block a user