Optimize HTML escape operation

This commit is contained in:
Masaaki Goshima 2020-12-25 22:26:59 +09:00
parent 5741c733a6
commit b8f43ca445
3 changed files with 5718 additions and 513 deletions

View File

@ -34,10 +34,19 @@ const (
bufSize = 1024 bufSize = 1024
) )
const (
opCodeEscapedType = iota
opCodeEscapedIndentType
opCodeNoEscapeType
opCodeNoEscapeIndentType
)
type opcodeSet struct { type opcodeSet struct {
codeIndent *opcode escapedCode *opcode
code *opcode escapedCodeIndent *opcode
codeLength int code *opcode
codeIndent *opcode
codeLength int
} }
func loadOpcodeMap() map[uintptr]*opcodeSet { func loadOpcodeMap() map[uintptr]*opcodeSet {
@ -187,9 +196,17 @@ func (e *Encoder) encode(v interface{}) ([]byte, error) {
if codeSet, exists := opcodeMap[typeptr]; exists { if codeSet, exists := opcodeMap[typeptr]; exists {
var code *opcode var code *opcode
if e.enabledIndent { if e.enabledIndent {
code = codeSet.codeIndent if e.enabledHTMLEscape {
code = codeSet.escapedCodeIndent
} else {
code = codeSet.codeIndent
}
} else { } else {
code = codeSet.code if e.enabledHTMLEscape {
code = codeSet.escapedCode
} else {
code = codeSet.code
}
} }
ctx := e.ctx ctx := e.ctx
p := uintptr(header.ptr) p := uintptr(header.ptr)
@ -212,9 +229,11 @@ func (e *Encoder) encode(v interface{}) ([]byte, error) {
codeIndent := toIndent(code) codeIndent := toIndent(code)
codeLength := code.totalLength() codeLength := code.totalLength()
codeSet := &opcodeSet{ codeSet := &opcodeSet{
codeIndent: codeIndent, escapedCode: toEscaped(code),
code: code, escapedCodeIndent: toEscaped(codeIndent),
codeLength: codeLength, code: code,
codeIndent: codeIndent,
codeLength: codeLength,
} }
storeOpcodeSet(typeptr, codeSet, opcodeMap) storeOpcodeSet(typeptr, codeSet, opcodeMap)
@ -224,9 +243,17 @@ func (e *Encoder) encode(v interface{}) ([]byte, error) {
var c *opcode var c *opcode
if e.enabledIndent { if e.enabledIndent {
c = codeIndent if e.enabledHTMLEscape {
c = codeSet.escapedCodeIndent
} else {
c = codeSet.codeIndent
}
} else { } else {
c = code if e.enabledHTMLEscape {
c = codeSet.escapedCode
} else {
c = codeSet.code
}
} }
b, err = e.run(ctx, b, c) b, err = e.run(ctx, b, c)
@ -285,20 +312,6 @@ func encodeIndentComma(b []byte) []byte {
return append(b, ',', '\n') return append(b, ',', '\n')
} }
func (e *Encoder) encodeKey(b []byte, code *opcode) []byte {
if e.enabledHTMLEscape {
return append(b, code.escapedKey...)
}
return append(b, code.key...)
}
func (e *Encoder) encodeString(b []byte, s string) []byte {
if e.enabledHTMLEscape {
return encodeEscapedString(b, s)
}
return encodeNoEscapedString(b, s)
}
func encodeByteSlice(b []byte, src []byte) []byte { func encodeByteSlice(b []byte, src []byte) []byte {
encodedLen := base64.StdEncoding.EncodedLen(len(src)) encodedLen := base64.StdEncoding.EncodedLen(len(src))
b = append(b, '"') b = append(b, '"')

View File

@ -67,6 +67,20 @@ func toIndent(c *opcode) *opcode {
return c return c
} }
func toEscaped(c *opcode) *opcode {
c = copyOpcode(c)
for code := c; code.op != opEnd; {
code.op = code.op.toEscaped()
switch code.op.codeType() {
case codeArrayElem, codeSliceElem, codeMapKey:
code = code.end
default:
code = code.next
}
}
return c
}
func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode {
return &opcode{ return &opcode{
op: op, op: op,

File diff suppressed because it is too large Load Diff