forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/github.com/mailru/easyjson/jwriter/writer.go

659 lines
10 KiB
Go
Raw Normal View History

2024-05-14 13:07:09 +00:00
// Package jwriter contains a JSON writer.
2024-05-14 13:07:09 +00:00
package jwriter
import (
"io"
"strconv"
"unicode/utf8"
"github.com/mailru/easyjson/buffer"
)
// Flags describe various encoding options. The behavior may be actually implemented in the encoder, but
2024-05-14 13:07:09 +00:00
// Flags field in Writer is used to set and pass them around.
2024-05-14 13:07:09 +00:00
type Flags int
const (
NilMapAsEmpty Flags = 1 << iota // Encode nil map as '{}' rather than 'null'.
NilSliceAsEmpty // Encode nil slice as '[]' rather than 'null'.
2024-05-14 13:07:09 +00:00
)
// Writer is a JSON writer.
2024-05-14 13:07:09 +00:00
type Writer struct {
Flags Flags
Error error
Buffer buffer.Buffer
2024-05-14 13:07:09 +00:00
NoEscapeHTML bool
}
// Size returns the size of the data that was written out.
2024-05-14 13:07:09 +00:00
func (w *Writer) Size() int {
2024-05-14 13:07:09 +00:00
return w.Buffer.Size()
2024-05-14 13:07:09 +00:00
}
// DumpTo outputs the data to given io.Writer, resetting the buffer.
2024-05-14 13:07:09 +00:00
func (w *Writer) DumpTo(out io.Writer) (written int, err error) {
2024-05-14 13:07:09 +00:00
return w.Buffer.DumpTo(out)
2024-05-14 13:07:09 +00:00
}
// BuildBytes returns writer data as a single byte slice. You can optionally provide one byte slice
2024-05-14 13:07:09 +00:00
// as argument that it will try to reuse.
2024-05-14 13:07:09 +00:00
func (w *Writer) BuildBytes(reuse ...[]byte) ([]byte, error) {
2024-05-14 13:07:09 +00:00
if w.Error != nil {
2024-05-14 13:07:09 +00:00
return nil, w.Error
2024-05-14 13:07:09 +00:00
}
return w.Buffer.BuildBytes(reuse...), nil
2024-05-14 13:07:09 +00:00
}
// ReadCloser returns an io.ReadCloser that can be used to read the data.
2024-05-14 13:07:09 +00:00
// ReadCloser also resets the buffer.
2024-05-14 13:07:09 +00:00
func (w *Writer) ReadCloser() (io.ReadCloser, error) {
2024-05-14 13:07:09 +00:00
if w.Error != nil {
2024-05-14 13:07:09 +00:00
return nil, w.Error
2024-05-14 13:07:09 +00:00
}
return w.Buffer.ReadCloser(), nil
2024-05-14 13:07:09 +00:00
}
// RawByte appends raw binary data to the buffer.
2024-05-14 13:07:09 +00:00
func (w *Writer) RawByte(c byte) {
2024-05-14 13:07:09 +00:00
w.Buffer.AppendByte(c)
2024-05-14 13:07:09 +00:00
}
// RawByte appends raw binary data to the buffer.
2024-05-14 13:07:09 +00:00
func (w *Writer) RawString(s string) {
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(s)
2024-05-14 13:07:09 +00:00
}
// Raw appends raw binary data to the buffer or sets the error if it is given. Useful for
2024-05-14 13:07:09 +00:00
// calling with results of MarshalJSON-like functions.
2024-05-14 13:07:09 +00:00
func (w *Writer) Raw(data []byte, err error) {
2024-05-14 13:07:09 +00:00
switch {
2024-05-14 13:07:09 +00:00
case w.Error != nil:
2024-05-14 13:07:09 +00:00
return
2024-05-14 13:07:09 +00:00
case err != nil:
2024-05-14 13:07:09 +00:00
w.Error = err
2024-05-14 13:07:09 +00:00
case len(data) > 0:
2024-05-14 13:07:09 +00:00
w.Buffer.AppendBytes(data)
2024-05-14 13:07:09 +00:00
default:
2024-05-14 13:07:09 +00:00
w.RawString("null")
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
}
// RawText encloses raw binary data in quotes and appends in to the buffer.
2024-05-14 13:07:09 +00:00
// Useful for calling with results of MarshalText-like functions.
2024-05-14 13:07:09 +00:00
func (w *Writer) RawText(data []byte, err error) {
2024-05-14 13:07:09 +00:00
switch {
2024-05-14 13:07:09 +00:00
case w.Error != nil:
2024-05-14 13:07:09 +00:00
return
2024-05-14 13:07:09 +00:00
case err != nil:
2024-05-14 13:07:09 +00:00
w.Error = err
2024-05-14 13:07:09 +00:00
case len(data) > 0:
2024-05-14 13:07:09 +00:00
w.String(string(data))
2024-05-14 13:07:09 +00:00
default:
2024-05-14 13:07:09 +00:00
w.RawString("null")
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
}
// Base64Bytes appends data to the buffer after base64 encoding it
2024-05-14 13:07:09 +00:00
func (w *Writer) Base64Bytes(data []byte) {
2024-05-14 13:07:09 +00:00
if data == nil {
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString("null")
2024-05-14 13:07:09 +00:00
return
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
w.Buffer.AppendByte('"')
2024-05-14 13:07:09 +00:00
w.base64(data)
2024-05-14 13:07:09 +00:00
w.Buffer.AppendByte('"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint8(n uint8) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(3)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint16(n uint16) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(5)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint32(n uint32) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint(n uint) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint64(n uint64) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int8(n int8) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(4)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int16(n int16) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(6)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int32(n int32) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(11)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int(n int) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(21)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int64(n int64) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(21)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint8Str(n uint8) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(3)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint16Str(n uint16) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(5)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint32Str(n uint32) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) UintStr(n uint) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Uint64Str(n uint64) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) UintptrStr(n uintptr) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int8Str(n int8) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(4)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int16Str(n int16) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(6)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int32Str(n int32) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(11)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) IntStr(n int) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(21)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Int64Str(n int64) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(21)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Float32(n float32) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Float32Str(n float32) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Float64(n float64) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, n, 'g', -1, 64)
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Float64Str(n float64) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(20)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 64)
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, '"')
2024-05-14 13:07:09 +00:00
}
func (w *Writer) Bool(v bool) {
2024-05-14 13:07:09 +00:00
w.Buffer.EnsureSpace(5)
2024-05-14 13:07:09 +00:00
if v {
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, "true"...)
2024-05-14 13:07:09 +00:00
} else {
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, "false"...)
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
}
const chars = "0123456789abcdef"
func getTable(falseValues ...int) [128]bool {
2024-05-14 13:07:09 +00:00
table := [128]bool{}
for i := 0; i < 128; i++ {
2024-05-14 13:07:09 +00:00
table[i] = true
2024-05-14 13:07:09 +00:00
}
for _, v := range falseValues {
2024-05-14 13:07:09 +00:00
table[v] = false
2024-05-14 13:07:09 +00:00
}
return table
2024-05-14 13:07:09 +00:00
}
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, '"', '&', '<', '>', '\\')
2024-05-14 13:07:09 +00:00
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) {
2024-05-14 13:07:09 +00:00
w.Buffer.AppendByte('"')
// Portions of the string that contain no escapes are appended as
2024-05-14 13:07:09 +00:00
// byte slices.
p := 0 // last non-escape symbol
escapeTable := &htmlEscapeTable
2024-05-14 13:07:09 +00:00
if w.NoEscapeHTML {
2024-05-14 13:07:09 +00:00
escapeTable = &htmlNoEscapeTable
2024-05-14 13:07:09 +00:00
}
for i := 0; i < len(s); {
2024-05-14 13:07:09 +00:00
c := s[i]
if c < utf8.RuneSelf {
2024-05-14 13:07:09 +00:00
if escapeTable[c] {
2024-05-14 13:07:09 +00:00
// single-width character, no escaping is required
2024-05-14 13:07:09 +00:00
i++
2024-05-14 13:07:09 +00:00
continue
2024-05-14 13:07:09 +00:00
}
w.Buffer.AppendString(s[p:i])
2024-05-14 13:07:09 +00:00
switch c {
2024-05-14 13:07:09 +00:00
case '\t':
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(`\t`)
2024-05-14 13:07:09 +00:00
case '\r':
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(`\r`)
2024-05-14 13:07:09 +00:00
case '\n':
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(`\n`)
2024-05-14 13:07:09 +00:00
case '\\':
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(`\\`)
2024-05-14 13:07:09 +00:00
case '"':
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(`\"`)
2024-05-14 13:07:09 +00:00
default:
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(`\u00`)
2024-05-14 13:07:09 +00:00
w.Buffer.AppendByte(chars[c>>4])
2024-05-14 13:07:09 +00:00
w.Buffer.AppendByte(chars[c&0xf])
2024-05-14 13:07:09 +00:00
}
i++
2024-05-14 13:07:09 +00:00
p = i
2024-05-14 13:07:09 +00:00
continue
2024-05-14 13:07:09 +00:00
}
// broken utf
2024-05-14 13:07:09 +00:00
runeValue, runeWidth := utf8.DecodeRuneInString(s[i:])
2024-05-14 13:07:09 +00:00
if runeValue == utf8.RuneError && runeWidth == 1 {
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(s[p:i])
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(`\ufffd`)
2024-05-14 13:07:09 +00:00
i++
2024-05-14 13:07:09 +00:00
p = i
2024-05-14 13:07:09 +00:00
continue
2024-05-14 13:07:09 +00:00
}
// jsonp stuff - tab separator and line separator
2024-05-14 13:07:09 +00:00
if runeValue == '\u2028' || runeValue == '\u2029' {
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(s[p:i])
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(`\u202`)
2024-05-14 13:07:09 +00:00
w.Buffer.AppendByte(chars[runeValue&0xf])
2024-05-14 13:07:09 +00:00
i += runeWidth
2024-05-14 13:07:09 +00:00
p = i
2024-05-14 13:07:09 +00:00
continue
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
i += runeWidth
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
w.Buffer.AppendString(s[p:])
2024-05-14 13:07:09 +00:00
w.Buffer.AppendByte('"')
2024-05-14 13:07:09 +00:00
}
const encode = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
2024-05-14 13:07:09 +00:00
const padChar = '='
func (w *Writer) base64(in []byte) {
if len(in) == 0 {
2024-05-14 13:07:09 +00:00
return
2024-05-14 13:07:09 +00:00
}
w.Buffer.EnsureSpace(((len(in)-1)/3 + 1) * 4)
si := 0
2024-05-14 13:07:09 +00:00
n := (len(in) / 3) * 3
for si < n {
2024-05-14 13:07:09 +00:00
// Convert 3x 8bit source bytes into 4 bytes
2024-05-14 13:07:09 +00:00
val := uint(in[si+0])<<16 | uint(in[si+1])<<8 | uint(in[si+2])
w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>18&0x3F], encode[val>>12&0x3F], encode[val>>6&0x3F], encode[val&0x3F])
si += 3
2024-05-14 13:07:09 +00:00
}
remain := len(in) - si
2024-05-14 13:07:09 +00:00
if remain == 0 {
2024-05-14 13:07:09 +00:00
return
2024-05-14 13:07:09 +00:00
}
// Add the remaining small block
2024-05-14 13:07:09 +00:00
val := uint(in[si+0]) << 16
2024-05-14 13:07:09 +00:00
if remain == 2 {
2024-05-14 13:07:09 +00:00
val |= uint(in[si+1]) << 8
2024-05-14 13:07:09 +00:00
}
w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>18&0x3F], encode[val>>12&0x3F])
switch remain {
2024-05-14 13:07:09 +00:00
case 2:
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>6&0x3F], byte(padChar))
2024-05-14 13:07:09 +00:00
case 1:
2024-05-14 13:07:09 +00:00
w.Buffer.Buf = append(w.Buffer.Buf, byte(padChar), byte(padChar))
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
}