|
|
|
|
@ -26,10 +26,10 @@ package pjson
|
|
|
|
|
import (
|
|
|
|
|
"activething.com/go/gogo/core/bins"
|
|
|
|
|
"activething.com/go/gogo/core/errs"
|
|
|
|
|
"activething.com/go/gogo/core/opts"
|
|
|
|
|
"activething.com/go/gogo/packets"
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"math"
|
|
|
|
|
"strconv"
|
|
|
|
|
"fmt"
|
|
|
|
|
"time"
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
)
|
|
|
|
|
@ -45,178 +45,273 @@ type (
|
|
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func NewPacker (options ...opts.OptionFnc[Packer]) *Packer {
|
|
|
|
|
return opts.Apply(&Packer{
|
|
|
|
|
options: Options{
|
|
|
|
|
Flags: JSONFlagQuote | JSONFlagEscapeHTML,
|
|
|
|
|
dateLayout: time.RFC822Z,
|
|
|
|
|
},
|
|
|
|
|
state : packets.NewState(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) Bytes () []byte {
|
|
|
|
|
defer p.reset()
|
|
|
|
|
return append([]byte(nil),p.state.Bytes()...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) Error () error {
|
|
|
|
|
return p.state.Error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) Pack (value any) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) PackRaw (value []byte) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if value == nil {
|
|
|
|
|
p.state.Write(G.nullValue)
|
|
|
|
|
_,_ = p.state.Write(G.nullValue)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
p.state.Write(value)
|
|
|
|
|
|
|
|
|
|
if p.options.Quote() {
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
_,_ = p.state.Write(value)
|
|
|
|
|
if p.options.Quote() {
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) PackBinary (value []byte) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if value == nil {
|
|
|
|
|
p.state.Write(G.nullValue)
|
|
|
|
|
_,_ = p.state.Write(G.nullValue)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if len(value) == 0 {
|
|
|
|
|
p.state.Write2Byte('"','"')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
ln := base64.StdEncoding.EncodedLen(len(value))
|
|
|
|
|
if ln <= len(p.state.Temp) {
|
|
|
|
|
dst := p.state.Temp[:ln]
|
|
|
|
|
base64.StdEncoding.Encode(dst, value)
|
|
|
|
|
p.state.Write(dst)
|
|
|
|
|
_,_= p.state.Write(dst)
|
|
|
|
|
} else if ln <= 1024 {
|
|
|
|
|
dst := make([]byte, ln)
|
|
|
|
|
base64.StdEncoding.Encode(dst, value)
|
|
|
|
|
p.state.Write(dst)
|
|
|
|
|
_,_ = p.state.Write(dst)
|
|
|
|
|
} else {
|
|
|
|
|
enc := base64.NewEncoder(base64.StdEncoding, p.state)
|
|
|
|
|
enc.Write(value)
|
|
|
|
|
enc.Close()
|
|
|
|
|
_,_ = enc.Write(value)
|
|
|
|
|
p.state.SetError(enc.Close())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Packer) PackString (value string) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(value) == 0 {
|
|
|
|
|
p.state.Write2Byte('"','"')
|
|
|
|
|
} else {
|
|
|
|
|
p.string(value,p.options.EscapeHTML())
|
|
|
|
|
p.packString(value,p.options.EscapeHTML())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Packer) packString(s string, scapeHTML bool) {
|
|
|
|
|
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
start := 0
|
|
|
|
|
for i := 0; i < len(s); {
|
|
|
|
|
if b := s[i]; b < utf8.RuneSelf {
|
|
|
|
|
if !G.jsonChars[b].isHtmlUnsafe() || (!scapeHTML && !G.jsonChars[b].isUnsafe()) {
|
|
|
|
|
i++
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if start < i {
|
|
|
|
|
_,_ = p.state.WriteString(s[start:i])
|
|
|
|
|
}
|
|
|
|
|
_ = p.state.WriteByte('\\')
|
|
|
|
|
switch b {
|
|
|
|
|
case '\\', '"': p.state.WriteByte(b)
|
|
|
|
|
case '\n': p.state.WriteByte('n')
|
|
|
|
|
case '\r': p.state.WriteByte('r')
|
|
|
|
|
case '\t': p.state.WriteByte('t')
|
|
|
|
|
default:
|
|
|
|
|
_,_ = p.state.WriteString(`u00`)
|
|
|
|
|
p.state.Write2Byte(G.hex[b>>4], G.hex[b&0xF])
|
|
|
|
|
}
|
|
|
|
|
i++
|
|
|
|
|
start = i
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
c, size := utf8.DecodeRuneInString(s[i:])
|
|
|
|
|
if c == utf8.RuneError && size == 1 {
|
|
|
|
|
if start < i {
|
|
|
|
|
_,_ = p.state.WriteString(s[start:i])
|
|
|
|
|
}
|
|
|
|
|
_,_ = p.state.WriteString(`\ufffd`)
|
|
|
|
|
i += size
|
|
|
|
|
start = i
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == '\u2028' || c == '\u2029' {
|
|
|
|
|
if start < i {
|
|
|
|
|
_,_ = p.state.WriteString(s[start:i])
|
|
|
|
|
}
|
|
|
|
|
_,_ = p.state.WriteString(`\u202`)
|
|
|
|
|
_ = p.state.WriteByte(G.hex[c&0xF])
|
|
|
|
|
i += size
|
|
|
|
|
start = i
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
i += size
|
|
|
|
|
}
|
|
|
|
|
if start < len(s) {
|
|
|
|
|
_,_ = p.state.WriteString(s[start:])
|
|
|
|
|
}
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) PackBool (value bool) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if p.options.QuoteNumbers() {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
if value {
|
|
|
|
|
p.state.Write(G.trueValue)
|
|
|
|
|
_,_ = p.state.Write(G.trueValue)
|
|
|
|
|
} else {
|
|
|
|
|
p.state.Write(G.falseValue)
|
|
|
|
|
_,_ = p.state.Write(G.falseValue)
|
|
|
|
|
}
|
|
|
|
|
if p.options.QuoteNumbers() {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Packer) PackInt8 (value int8) {}
|
|
|
|
|
func (p *Packer) PackInt16 (value int16) {}
|
|
|
|
|
func (p *Packer) PackInt32 (value int32) {}
|
|
|
|
|
func (p *Packer) PackInt8 (value int8) { p.PackInt64(int64(value)) }
|
|
|
|
|
func (p *Packer) PackInt16 (value int16) { p.PackInt64(int64(value)) }
|
|
|
|
|
func (p *Packer) PackInt32 (value int32) { p.PackInt64(int64(value)) }
|
|
|
|
|
func (p *Packer) PackInt64 (value int64) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if p.options.QuoteNumbers() {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
if value == 0 {
|
|
|
|
|
p.state.WriteByte('0')
|
|
|
|
|
_ = p.state.WriteByte('0')
|
|
|
|
|
} else {
|
|
|
|
|
p.state.WriteIntStr(value, 10)
|
|
|
|
|
}
|
|
|
|
|
if p.options.QuoteNumbers() {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Packer) PackUInt8 (value uint8) {}
|
|
|
|
|
func (p *Packer) PackUInt16 (value uint16) {}
|
|
|
|
|
func (p *Packer) PackUInt32 (value uint32) {}
|
|
|
|
|
func (p *Packer) PackUInt8 (value uint8 ) { p.PackUInt64(uint64(value)) }
|
|
|
|
|
func (p *Packer) PackUInt16 (value uint16) { p.PackUInt64(uint64(value)) }
|
|
|
|
|
func (p *Packer) PackUInt32 (value uint32) { p.PackUInt64(uint64(value)) }
|
|
|
|
|
func (p *Packer) PackUInt64 (value uint64) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if p.options.QuoteNumbers() {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
if value == 0 {
|
|
|
|
|
p.state.WriteByte('0')
|
|
|
|
|
_ = p.state.WriteByte('0')
|
|
|
|
|
} else {
|
|
|
|
|
p.state.WriteUIntStr(value, 10)
|
|
|
|
|
}
|
|
|
|
|
if p.options.QuoteNumbers() {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Packer) PackFloat32 (value float32) {}
|
|
|
|
|
func (p *Packer) PackFloat64 (value float64) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
func (p *Packer) PackFloat32 (value float32) { p.packFloat(float64(value),32) }
|
|
|
|
|
func (p *Packer) PackFloat64 (value float64) { p.packFloat(value,64) }
|
|
|
|
|
|
|
|
|
|
func (p *Packer) packFloat (value float64, bits int) {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
if math.IsInf(value,0) || math.IsNaN(value) {
|
|
|
|
|
p.state.SetError(packets.G.ErrInvalidValue)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if p.options.QuoteNumbers() {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
switch {
|
|
|
|
|
case value == 0 : p.state.Write(G.zeroValue)
|
|
|
|
|
case math.IsNaN(value) : p.state.Write(G.floatNaN)
|
|
|
|
|
case math.IsInf(value, 1) : p.state.Write(G.floatInfPos)
|
|
|
|
|
case math.IsInf(value, -1) : p.state.Write(G.floatInfNeg)
|
|
|
|
|
default:
|
|
|
|
|
fm := byte('f')
|
|
|
|
|
if ab := math.Abs(value); ab != 0 {
|
|
|
|
|
if ab < 1e-6 || ab >= 1e21 {
|
|
|
|
|
fm = 'e'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
b := p.state.Temp[:0]
|
|
|
|
|
|
|
|
|
|
b = strconv.AppendFloat(b, value, fm, -1, 64)
|
|
|
|
|
if fm == 'e' {
|
|
|
|
|
// clean up e-09 to e-9
|
|
|
|
|
n := len(b)
|
|
|
|
|
if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
|
|
|
|
|
b[n-2] = b[n-1]
|
|
|
|
|
b = b[:n-1]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p.state.Write(b)
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
b := stringifyFloat(p.state.Temp[:0], value,bits)
|
|
|
|
|
if b == nil {
|
|
|
|
|
p.state.SetError(packets.G.ErrInvalidValue)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if p.options.QuoteNumbers() {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) PackDate (value time.Time) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
p.state.AppendWith(bins.AppendFnc(func(d []byte) []byte {
|
|
|
|
|
return value.AppendFormat(d,p.options.dateLayout)
|
|
|
|
|
}))
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
_ = p.state.WriteByte('"')
|
|
|
|
|
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -236,10 +331,6 @@ func (p *Packer) PackObject(builder func(packer packets.ObjectPacker)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) packCompound(kind packets.NodeKind, opening, closing byte, buildFnc func(*Packer)) {
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dn := false
|
|
|
|
|
defer func(d *bool) {
|
|
|
|
|
if !(*d) {
|
|
|
|
|
@ -247,15 +338,22 @@ func (p *Packer) packCompound(kind packets.NodeKind, opening, closing byte, buil
|
|
|
|
|
}
|
|
|
|
|
}(&dn)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if p.state.Open(kind) {
|
|
|
|
|
p.addSep()
|
|
|
|
|
p.state.WriteByte(opening)
|
|
|
|
|
fmt.Printf("Node Count %d\n",p.state.Node.Count)
|
|
|
|
|
_ = p.state.WriteByte(opening)
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
if !p.state.SetValue() {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
buildFnc(p)
|
|
|
|
|
|
|
|
|
|
if p.state.Error == nil {
|
|
|
|
|
if p.state.Close() {
|
|
|
|
|
p.state.WriteByte(closing)
|
|
|
|
|
_ = p.state.WriteByte(closing)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -267,66 +365,62 @@ func (p *Packer) packCompound(kind packets.NodeKind, opening, closing byte, buil
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) string(s string, scapeHTML bool) {
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
start := 0
|
|
|
|
|
for i := 0; i < len(s); {
|
|
|
|
|
if b := s[i]; b < utf8.RuneSelf {
|
|
|
|
|
if !G.jsonChars[b].isHtmlUnsafe() || (!scapeHTML && !G.jsonChars[b].isUnsafe()) {
|
|
|
|
|
i++
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if start < i {
|
|
|
|
|
p.state.WriteString(s[start:i])
|
|
|
|
|
}
|
|
|
|
|
p.state.WriteByte('\\')
|
|
|
|
|
switch b {
|
|
|
|
|
case '\\', '"': p.state.WriteByte(b)
|
|
|
|
|
case '\n': p.state.WriteByte('n')
|
|
|
|
|
case '\r': p.state.WriteByte('r')
|
|
|
|
|
case '\t': p.state.WriteByte('t')
|
|
|
|
|
default:
|
|
|
|
|
p.state.WriteString(`u00`)
|
|
|
|
|
p.state.Write2Byte(G.hex[b>>4], G.hex[b&0xF])
|
|
|
|
|
}
|
|
|
|
|
i++
|
|
|
|
|
start = i
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
c, size := utf8.DecodeRuneInString(s[i:])
|
|
|
|
|
if c == utf8.RuneError && size == 1 {
|
|
|
|
|
if start < i {
|
|
|
|
|
p.state.WriteString(s[start:i])
|
|
|
|
|
}
|
|
|
|
|
p.state.WriteString(`\ufffd`)
|
|
|
|
|
i += size
|
|
|
|
|
start = i
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == '\u2028' || c == '\u2029' {
|
|
|
|
|
if start < i {
|
|
|
|
|
p.state.WriteString(s[start:i])
|
|
|
|
|
}
|
|
|
|
|
p.state.WriteString(`\u202`)
|
|
|
|
|
p.state.WriteByte(G.hex[c&0xF])
|
|
|
|
|
i += size
|
|
|
|
|
start = i
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
i += size
|
|
|
|
|
}
|
|
|
|
|
if start < len(s) {
|
|
|
|
|
p.state.WriteString(s[start:])
|
|
|
|
|
}
|
|
|
|
|
p.state.WriteByte('"')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) addSep () *Packer {
|
|
|
|
|
if p.state.Node.Count > 0 {
|
|
|
|
|
p.state.WriteByte(',')
|
|
|
|
|
_ = p.state.WriteByte(',')
|
|
|
|
|
}
|
|
|
|
|
return p
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) addKey (key any, call func(*Packer)) {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.addSep()
|
|
|
|
|
k := stringifyKey(p.state.Temp[0:],key)
|
|
|
|
|
if k == nil {
|
|
|
|
|
p.state.SetError(packets.G.ErrInvalidKey)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ks := string(k)
|
|
|
|
|
if !p.options.IgnoreKeys() && !p.state.SetKey(ks) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.packString(ks,p.options.EscapeHTML())
|
|
|
|
|
_ = p.state.WriteByte(':')
|
|
|
|
|
call(p)
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) addField (name string, call func(*Packer)) {
|
|
|
|
|
if p.state.Error != nil {
|
|
|
|
|
panic(p.state.Error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.addSep()
|
|
|
|
|
ks := string(name)
|
|
|
|
|
if !p.options.IgnoreKeys() && !p.state.SetKey(ks) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p.packString(name,p.options.EscapeHTML())
|
|
|
|
|
_ = p.state.WriteByte(':')
|
|
|
|
|
call(p)
|
|
|
|
|
p.state.Node.Count++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Packer) reset () {
|
|
|
|
|
p.state.Reset()
|
|
|
|
|
p.options.reset()
|
|
|
|
|
}
|