Update Azure Go SDK to v55.0.0

This commit is contained in:
Pengfei Ni
2021-06-01 01:30:43 +00:00
parent f363322d4a
commit b98824c55d
88 changed files with 2313 additions and 944 deletions

View File

@@ -4,6 +4,7 @@ package buffer
import (
"io"
"net"
"sync"
)
@@ -52,14 +53,12 @@ func putBuf(buf []byte) {
// getBuf gets a chunk from reuse pool or creates a new one if reuse failed.
func getBuf(size int) []byte {
if size < config.PooledSize {
return make([]byte, 0, size)
}
if c := buffers[size]; c != nil {
v := c.Get()
if v != nil {
return v.([]byte)
if size >= config.PooledSize {
if c := buffers[size]; c != nil {
v := c.Get()
if v != nil {
return v.([]byte)
}
}
}
return make([]byte, 0, size)
@@ -78,9 +77,12 @@ type Buffer struct {
// EnsureSpace makes sure that the current chunk contains at least s free bytes,
// possibly creating a new chunk.
func (b *Buffer) EnsureSpace(s int) {
if cap(b.Buf)-len(b.Buf) >= s {
return
if cap(b.Buf)-len(b.Buf) < s {
b.ensureSpaceSlow(s)
}
}
func (b *Buffer) ensureSpaceSlow(s int) {
l := len(b.Buf)
if l > 0 {
if cap(b.toPool) != cap(b.Buf) {
@@ -105,18 +107,22 @@ func (b *Buffer) EnsureSpace(s int) {
// AppendByte appends a single byte to buffer.
func (b *Buffer) AppendByte(data byte) {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
}
b.EnsureSpace(1)
b.Buf = append(b.Buf, data)
}
// AppendBytes appends a byte slice to buffer.
func (b *Buffer) AppendBytes(data []byte) {
if len(data) <= cap(b.Buf)-len(b.Buf) {
b.Buf = append(b.Buf, data...) // fast path
} else {
b.appendBytesSlow(data)
}
}
func (b *Buffer) appendBytesSlow(data []byte) {
for len(data) > 0 {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
}
b.EnsureSpace(1)
sz := cap(b.Buf) - len(b.Buf)
if sz > len(data) {
@@ -128,12 +134,18 @@ func (b *Buffer) AppendBytes(data []byte) {
}
}
// AppendBytes appends a string to buffer.
// AppendString appends a string to buffer.
func (b *Buffer) AppendString(data string) {
if len(data) <= cap(b.Buf)-len(b.Buf) {
b.Buf = append(b.Buf, data...) // fast path
} else {
b.appendStringSlow(data)
}
}
func (b *Buffer) appendStringSlow(data string) {
for len(data) > 0 {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
}
b.EnsureSpace(1)
sz := cap(b.Buf) - len(b.Buf)
if sz > len(data) {
@@ -156,18 +168,14 @@ func (b *Buffer) Size() int {
// DumpTo outputs the contents of a buffer to a writer and resets the buffer.
func (b *Buffer) DumpTo(w io.Writer) (written int, err error) {
var n int
for _, buf := range b.bufs {
if err == nil {
n, err = w.Write(buf)
written += n
}
putBuf(buf)
bufs := net.Buffers(b.bufs)
if len(b.Buf) > 0 {
bufs = append(bufs, b.Buf)
}
n, err := bufs.WriteTo(w)
if err == nil {
n, err = w.Write(b.Buf)
written += n
for _, buf := range b.bufs {
putBuf(buf)
}
putBuf(b.toPool)
@@ -175,7 +183,7 @@ func (b *Buffer) DumpTo(w io.Writer) (written int, err error) {
b.Buf = nil
b.toPool = nil
return
return int(n), err
}
// BuildBytes creates a single byte slice with all the contents of the buffer. Data is
@@ -192,7 +200,7 @@ func (b *Buffer) BuildBytes(reuse ...[]byte) []byte {
var ret []byte
size := b.Size()
// If we got a buffer as argument and it is big enought, reuse it.
// If we got a buffer as argument and it is big enough, reuse it.
if len(reuse) == 1 && cap(reuse[0]) >= size {
ret = reuse[0][:0]
} else {

View File

@@ -5,6 +5,7 @@
package jlexer
import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
@@ -14,6 +15,8 @@ import (
"unicode"
"unicode/utf16"
"unicode/utf8"
"github.com/josharian/intern"
)
// tokenKind determines type of a token.
@@ -32,9 +35,10 @@ const (
type token struct {
kind tokenKind // Type of a token.
boolValue bool // Value if a boolean literal token.
byteValue []byte // Raw value of a token.
delimValue byte
boolValue bool // Value if a boolean literal token.
byteValueCloned bool // true if byteValue was allocated and does not refer to original json body
byteValue []byte // Raw value of a token.
delimValue byte
}
// Lexer is a JSON lexer: it iterates over JSON tokens in a byte slice.
@@ -240,23 +244,65 @@ func (r *Lexer) fetchNumber() {
// findStringLen tries to scan into the string literal for ending quote char to determine required size.
// The size will be exact if no escapes are present and may be inexact if there are escaped chars.
func findStringLen(data []byte) (isValid, hasEscapes bool, length int) {
delta := 0
for i := 0; i < len(data); i++ {
switch data[i] {
case '\\':
i++
delta++
if i < len(data) && data[i] == 'u' {
delta++
}
case '"':
return true, (delta > 0), (i - delta)
func findStringLen(data []byte) (isValid bool, length int) {
for {
idx := bytes.IndexByte(data, '"')
if idx == -1 {
return false, len(data)
}
if idx == 0 || (idx > 0 && data[idx-1] != '\\') {
return true, length + idx
}
// count \\\\\\\ sequences. even number of slashes means quote is not really escaped
cnt := 1
for idx-cnt-1 >= 0 && data[idx-cnt-1] == '\\' {
cnt++
}
if cnt%2 == 0 {
return true, length + idx
}
length += idx + 1
data = data[idx+1:]
}
}
// unescapeStringToken performs unescaping of string token.
// if no escaping is needed, original string is returned, otherwise - a new one allocated
func (r *Lexer) unescapeStringToken() (err error) {
data := r.token.byteValue
var unescapedData []byte
for {
i := bytes.IndexByte(data, '\\')
if i == -1 {
break
}
escapedRune, escapedBytes, err := decodeEscape(data[i:])
if err != nil {
r.errParse(err.Error())
return err
}
if unescapedData == nil {
unescapedData = make([]byte, 0, len(r.token.byteValue))
}
var d [4]byte
s := utf8.EncodeRune(d[:], escapedRune)
unescapedData = append(unescapedData, data[:i]...)
unescapedData = append(unescapedData, d[:s]...)
data = data[i+escapedBytes:]
}
return false, false, len(data)
if unescapedData != nil {
r.token.byteValue = append(unescapedData, data...)
r.token.byteValueCloned = true
}
return
}
// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
@@ -286,36 +332,30 @@ func getu4(s []byte) rune {
return val
}
// processEscape processes a single escape sequence and returns number of bytes processed.
func (r *Lexer) processEscape(data []byte) (int, error) {
// decodeEscape processes a single escape sequence and returns number of bytes processed.
func decodeEscape(data []byte) (decoded rune, bytesProcessed int, err error) {
if len(data) < 2 {
return 0, fmt.Errorf("syntax error at %v", string(data))
return 0, 0, errors.New("incorrect escape symbol \\ at the end of token")
}
c := data[1]
switch c {
case '"', '/', '\\':
r.token.byteValue = append(r.token.byteValue, c)
return 2, nil
return rune(c), 2, nil
case 'b':
r.token.byteValue = append(r.token.byteValue, '\b')
return 2, nil
return '\b', 2, nil
case 'f':
r.token.byteValue = append(r.token.byteValue, '\f')
return 2, nil
return '\f', 2, nil
case 'n':
r.token.byteValue = append(r.token.byteValue, '\n')
return 2, nil
return '\n', 2, nil
case 'r':
r.token.byteValue = append(r.token.byteValue, '\r')
return 2, nil
return '\r', 2, nil
case 't':
r.token.byteValue = append(r.token.byteValue, '\t')
return 2, nil
return '\t', 2, nil
case 'u':
rr := getu4(data)
if rr < 0 {
return 0, errors.New("syntax error")
return 0, 0, errors.New("incorrectly escaped \\uXXXX sequence")
}
read := 6
@@ -328,13 +368,10 @@ func (r *Lexer) processEscape(data []byte) (int, error) {
rr = unicode.ReplacementChar
}
}
var d [4]byte
s := utf8.EncodeRune(d[:], rr)
r.token.byteValue = append(r.token.byteValue, d[:s]...)
return read, nil
return rr, read, nil
}
return 0, errors.New("syntax error")
return 0, 0, errors.New("incorrectly escaped bytes")
}
// fetchString scans a string literal token.
@@ -342,43 +379,14 @@ func (r *Lexer) fetchString() {
r.pos++
data := r.Data[r.pos:]
isValid, hasEscapes, length := findStringLen(data)
isValid, length := findStringLen(data)
if !isValid {
r.pos += length
r.errParse("unterminated string literal")
return
}
if !hasEscapes {
r.token.byteValue = data[:length]
r.pos += length + 1
return
}
r.token.byteValue = make([]byte, 0, length)
p := 0
for i := 0; i < len(data); {
switch data[i] {
case '"':
r.pos += i + 1
r.token.byteValue = append(r.token.byteValue, data[p:i]...)
i++
return
case '\\':
r.token.byteValue = append(r.token.byteValue, data[p:i]...)
off, err := r.processEscape(data[i:])
if err != nil {
r.errParse(err.Error())
return
}
i += off
p = i
default:
i++
}
}
r.errParse("unterminated string literal")
r.token.byteValue = data[:length]
r.pos += length + 1 // skip closing '"' as well
}
// scanToken scans the next token if no token is currently available in the lexer.
@@ -602,7 +610,7 @@ func (r *Lexer) Consumed() {
}
}
func (r *Lexer) unsafeString() (string, []byte) {
func (r *Lexer) unsafeString(skipUnescape bool) (string, []byte) {
if r.token.kind == tokenUndef && r.Ok() {
r.FetchToken()
}
@@ -610,6 +618,13 @@ func (r *Lexer) unsafeString() (string, []byte) {
r.errInvalidToken("string")
return "", nil
}
if !skipUnescape {
if err := r.unescapeStringToken(); err != nil {
r.errInvalidToken("string")
return "", nil
}
}
bytes := r.token.byteValue
ret := bytesToStr(r.token.byteValue)
r.consume()
@@ -621,13 +636,19 @@ func (r *Lexer) unsafeString() (string, []byte) {
// Warning: returned string may point to the input buffer, so the string should not outlive
// the input buffer. Intended pattern of usage is as an argument to a switch statement.
func (r *Lexer) UnsafeString() string {
ret, _ := r.unsafeString()
ret, _ := r.unsafeString(false)
return ret
}
// UnsafeBytes returns the byte slice if the token is a string literal.
func (r *Lexer) UnsafeBytes() []byte {
_, ret := r.unsafeString()
_, ret := r.unsafeString(false)
return ret
}
// UnsafeFieldName returns current member name string token
func (r *Lexer) UnsafeFieldName(skipUnescape bool) string {
ret, _ := r.unsafeString(skipUnescape)
return ret
}
@@ -640,7 +661,34 @@ func (r *Lexer) String() string {
r.errInvalidToken("string")
return ""
}
ret := string(r.token.byteValue)
if err := r.unescapeStringToken(); err != nil {
r.errInvalidToken("string")
return ""
}
var ret string
if r.token.byteValueCloned {
ret = bytesToStr(r.token.byteValue)
} else {
ret = string(r.token.byteValue)
}
r.consume()
return ret
}
// StringIntern reads a string literal, and performs string interning on it.
func (r *Lexer) StringIntern() string {
if r.token.kind == tokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenString {
r.errInvalidToken("string")
return ""
}
if err := r.unescapeStringToken(); err != nil {
r.errInvalidToken("string")
return ""
}
ret := intern.Bytes(r.token.byteValue)
r.consume()
return ret
}
@@ -839,7 +887,7 @@ func (r *Lexer) Int() int {
}
func (r *Lexer) Uint8Str() uint8 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -856,7 +904,7 @@ func (r *Lexer) Uint8Str() uint8 {
}
func (r *Lexer) Uint16Str() uint16 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -873,7 +921,7 @@ func (r *Lexer) Uint16Str() uint16 {
}
func (r *Lexer) Uint32Str() uint32 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -890,7 +938,7 @@ func (r *Lexer) Uint32Str() uint32 {
}
func (r *Lexer) Uint64Str() uint64 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -915,7 +963,7 @@ func (r *Lexer) UintptrStr() uintptr {
}
func (r *Lexer) Int8Str() int8 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -932,7 +980,7 @@ func (r *Lexer) Int8Str() int8 {
}
func (r *Lexer) Int16Str() int16 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -949,7 +997,7 @@ func (r *Lexer) Int16Str() int16 {
}
func (r *Lexer) Int32Str() int32 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -966,7 +1014,7 @@ func (r *Lexer) Int32Str() int32 {
}
func (r *Lexer) Int64Str() int64 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -1004,7 +1052,7 @@ func (r *Lexer) Float32() float32 {
}
func (r *Lexer) Float32Str() float32 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@@ -1037,7 +1085,7 @@ func (r *Lexer) Float64() float64 {
}
func (r *Lexer) Float64Str() float64 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}

View File

@@ -270,16 +270,25 @@ func (w *Writer) Bool(v bool) {
const chars = "0123456789abcdef"
func isNotEscapedSingleChar(c byte, escapeHTML bool) bool {
// Note: might make sense to use a table if there are more chars to escape. With 4 chars
// it benchmarks the same.
if escapeHTML {
return c != '<' && c != '>' && c != '&' && c != '\\' && c != '"' && c >= 0x20 && c < utf8.RuneSelf
} else {
return c != '\\' && c != '"' && c >= 0x20 && c < utf8.RuneSelf
func getTable(falseValues ...int) [128]bool {
table := [128]bool{}
for i := 0; i < 128; i++ {
table[i] = true
}
for _, v := range falseValues {
table[v] = false
}
return table
}
var (
htmlEscapeTable = getTable(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '&', '<', '>', '\\')
htmlNoEscapeTable = getTable(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '\\')
)
func (w *Writer) String(s string) {
w.Buffer.AppendByte('"')
@@ -288,15 +297,21 @@ func (w *Writer) String(s string) {
p := 0 // last non-escape symbol
escapeTable := &htmlEscapeTable
if w.NoEscapeHTML {
escapeTable = &htmlNoEscapeTable
}
for i := 0; i < len(s); {
c := s[i]
if isNotEscapedSingleChar(c, !w.NoEscapeHTML) {
// single-width character, no escaping is required
i++
continue
} else if c < utf8.RuneSelf {
// single-with character, need to escape
if c < utf8.RuneSelf {
if escapeTable[c] {
// single-width character, no escaping is required
i++
continue
}
w.Buffer.AppendString(s[p:i])
switch c {
case '\t':