Refactor indent code

This commit is contained in:
Masaaki Goshima 2020-12-25 17:03:56 +09:00
parent 5de8891c0c
commit 5741c733a6
5 changed files with 37 additions and 180 deletions

View File

@ -200,26 +200,16 @@ func (e *Encoder) encode(v interface{}) ([]byte, error) {
// noescape trick for header.typ ( reflect.*rtype ) // noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**rtype)(unsafe.Pointer(&typeptr)) copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
codeIndent, err := e.compileHead(&encodeCompileContext{
typ: copiedType,
root: true,
withIndent: true,
structTypeToCompiledCode: map[uintptr]*compiledCode{},
})
if err != nil {
return nil, err
}
code, err := e.compileHead(&encodeCompileContext{ code, err := e.compileHead(&encodeCompileContext{
typ: copiedType, typ: copiedType,
root: true, root: true,
withIndent: false,
structTypeToCompiledCode: map[uintptr]*compiledCode{}, structTypeToCompiledCode: map[uintptr]*compiledCode{},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
codeIndent = copyOpcode(codeIndent)
code = copyOpcode(code) code = copyOpcode(code)
codeIndent := toIndent(code)
codeLength := code.totalLength() codeLength := code.totalLength()
codeSet := &opcodeSet{ codeSet := &opcodeSet{
codeIndent: codeIndent, codeIndent: codeIndent,

View File

@ -377,16 +377,6 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) {
end := newOpCode(ctx, opSliceEnd) end := newOpCode(ctx, opSliceEnd)
ctx.incIndex() ctx.incIndex()
if ctx.withIndent {
if ctx.root {
header.op = opRootSliceHeadIndent
elemCode.op = opRootSliceElemIndent
} else {
header.op = opSliceHeadIndent
elemCode.op = opSliceElemIndent
}
end.op = opSliceEndIndent
}
header.elem = elemCode header.elem = elemCode
header.end = end header.end = end
@ -421,12 +411,6 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) {
end := newOpCode(ctx, opArrayEnd) end := newOpCode(ctx, opArrayEnd)
ctx.incIndex() ctx.incIndex()
if ctx.withIndent {
header.op = opArrayHeadIndent
elemCode.op = opArrayElemIndent
end.op = opArrayEndIndent
}
header.elem = elemCode header.elem = elemCode
header.end = end header.end = end
header.next = code header.next = code
@ -487,13 +471,6 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode,
end := newMapEndCode(ctx, header) end := newMapEndCode(ctx, header)
ctx.incIndex() ctx.incIndex()
if ctx.withIndent {
header.op = header.op.toIndent()
key.op = key.op.toIndent()
value.op = value.op.toIndent()
end.op = end.op.toIndent()
}
header.next = keyCode header.next = keyCode
keyCode.beforeLastCode().next = (*opcode)(unsafe.Pointer(value)) keyCode.beforeLastCode().next = (*opcode)(unsafe.Pointer(value))
value.next = valueCode value.next = valueCode
@ -587,88 +564,46 @@ func (e *Encoder) typeToHeaderType(ctx *encodeCompileContext, code *opcode) opTy
} }
case opInt: case opInt:
return opStructFieldHeadInt return opStructFieldHeadInt
case opIntIndent:
return opStructFieldHeadIntIndent
case opInt8: case opInt8:
return opStructFieldHeadInt8 return opStructFieldHeadInt8
case opInt8Indent:
return opStructFieldHeadInt8Indent
case opInt16: case opInt16:
return opStructFieldHeadInt16 return opStructFieldHeadInt16
case opInt16Indent:
return opStructFieldHeadInt16Indent
case opInt32: case opInt32:
return opStructFieldHeadInt32 return opStructFieldHeadInt32
case opInt32Indent:
return opStructFieldHeadInt32Indent
case opInt64: case opInt64:
return opStructFieldHeadInt64 return opStructFieldHeadInt64
case opInt64Indent:
return opStructFieldHeadInt64Indent
case opUint: case opUint:
return opStructFieldHeadUint return opStructFieldHeadUint
case opUintIndent:
return opStructFieldHeadUintIndent
case opUint8: case opUint8:
return opStructFieldHeadUint8 return opStructFieldHeadUint8
case opUint8Indent:
return opStructFieldHeadUint8Indent
case opUint16: case opUint16:
return opStructFieldHeadUint16 return opStructFieldHeadUint16
case opUint16Indent:
return opStructFieldHeadUint16Indent
case opUint32: case opUint32:
return opStructFieldHeadUint32 return opStructFieldHeadUint32
case opUint32Indent:
return opStructFieldHeadUint32Indent
case opUint64: case opUint64:
return opStructFieldHeadUint64 return opStructFieldHeadUint64
case opUint64Indent:
return opStructFieldHeadUint64Indent
case opFloat32: case opFloat32:
return opStructFieldHeadFloat32 return opStructFieldHeadFloat32
case opFloat32Indent:
return opStructFieldHeadFloat32Indent
case opFloat64: case opFloat64:
return opStructFieldHeadFloat64 return opStructFieldHeadFloat64
case opFloat64Indent:
return opStructFieldHeadFloat64Indent
case opString: case opString:
return opStructFieldHeadString return opStructFieldHeadString
case opStringIndent:
return opStructFieldHeadStringIndent
case opBool: case opBool:
return opStructFieldHeadBool return opStructFieldHeadBool
case opBoolIndent:
return opStructFieldHeadBoolIndent
case opMapHead: case opMapHead:
return opStructFieldHeadMap return opStructFieldHeadMap
case opMapHeadLoad: case opMapHeadLoad:
return opStructFieldHeadMapLoad return opStructFieldHeadMapLoad
case opMapHeadIndent:
return opStructFieldHeadMapIndent
case opMapHeadLoadIndent:
return opStructFieldHeadMapLoadIndent
case opArrayHead: case opArrayHead:
return opStructFieldHeadArray return opStructFieldHeadArray
case opArrayHeadIndent:
return opStructFieldHeadArrayIndent
case opSliceHead: case opSliceHead:
return opStructFieldHeadSlice return opStructFieldHeadSlice
case opSliceHeadIndent:
return opStructFieldHeadSliceIndent
case opStructFieldHead: case opStructFieldHead:
return opStructFieldHeadStruct return opStructFieldHeadStruct
case opStructFieldHeadIndent:
return opStructFieldHeadStructIndent
case opMarshalJSON: case opMarshalJSON:
return opStructFieldHeadMarshalJSON return opStructFieldHeadMarshalJSON
case opMarshalJSONIndent:
return opStructFieldHeadMarshalJSONIndent
case opMarshalText: case opMarshalText:
return opStructFieldHeadMarshalText return opStructFieldHeadMarshalText
case opMarshalTextIndent:
return opStructFieldHeadMarshalTextIndent
} }
return opStructFieldHead return opStructFieldHead
} }
@ -753,93 +688,51 @@ func (e *Encoder) typeToFieldType(ctx *encodeCompileContext, code *opcode) opTyp
} }
case opInt: case opInt:
return opStructFieldInt return opStructFieldInt
case opIntIndent:
return opStructFieldIntIndent
case opInt8: case opInt8:
return opStructFieldInt8 return opStructFieldInt8
case opInt8Indent:
return opStructFieldInt8Indent
case opInt16: case opInt16:
return opStructFieldInt16 return opStructFieldInt16
case opInt16Indent:
return opStructFieldInt16Indent
case opInt32: case opInt32:
return opStructFieldInt32 return opStructFieldInt32
case opInt32Indent:
return opStructFieldInt32Indent
case opInt64: case opInt64:
return opStructFieldInt64 return opStructFieldInt64
case opInt64Indent:
return opStructFieldInt64Indent
case opUint: case opUint:
return opStructFieldUint return opStructFieldUint
case opUintIndent:
return opStructFieldUintIndent
case opUint8: case opUint8:
return opStructFieldUint8 return opStructFieldUint8
case opUint8Indent:
return opStructFieldUint8Indent
case opUint16: case opUint16:
return opStructFieldUint16 return opStructFieldUint16
case opUint16Indent:
return opStructFieldUint16Indent
case opUint32: case opUint32:
return opStructFieldUint32 return opStructFieldUint32
case opUint32Indent:
return opStructFieldUint32Indent
case opUint64: case opUint64:
return opStructFieldUint64 return opStructFieldUint64
case opUint64Indent:
return opStructFieldUint64Indent
case opFloat32: case opFloat32:
return opStructFieldFloat32 return opStructFieldFloat32
case opFloat32Indent:
return opStructFieldFloat32Indent
case opFloat64: case opFloat64:
return opStructFieldFloat64 return opStructFieldFloat64
case opFloat64Indent:
return opStructFieldFloat64Indent
case opString: case opString:
return opStructFieldString return opStructFieldString
case opStringIndent:
return opStructFieldStringIndent
case opBool: case opBool:
return opStructFieldBool return opStructFieldBool
case opBoolIndent:
return opStructFieldBoolIndent
case opMapHead: case opMapHead:
return opStructFieldMap return opStructFieldMap
case opMapHeadLoad: case opMapHeadLoad:
return opStructFieldMapLoad return opStructFieldMapLoad
case opMapHeadIndent:
return opStructFieldMapIndent
case opMapHeadLoadIndent:
return opStructFieldMapLoadIndent
case opArrayHead: case opArrayHead:
return opStructFieldArray return opStructFieldArray
case opArrayHeadIndent:
return opStructFieldArrayIndent
case opSliceHead: case opSliceHead:
return opStructFieldSlice return opStructFieldSlice
case opSliceHeadIndent:
return opStructFieldSliceIndent
case opStructFieldHead: case opStructFieldHead:
return opStructFieldStruct return opStructFieldStruct
case opStructFieldHeadIndent:
return opStructFieldStructIndent
case opMarshalJSON: case opMarshalJSON:
return opStructFieldMarshalJSON return opStructFieldMarshalJSON
case opMarshalJSONIndent:
return opStructFieldMarshalJSONIndent
case opMarshalText: case opMarshalText:
return opStructFieldMarshalText return opStructFieldMarshalText
case opMarshalTextIndent:
return opStructFieldMarshalTextIndent
} }
return opStructField return opStructField
} }
func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode, tag *structTag, withIndent bool) opType { func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode, tag *structTag) opType {
headType := e.typeToHeaderType(ctx, code) headType := e.typeToHeaderType(ctx, code)
switch { switch {
case tag.isOmitEmpty: case tag.isOmitEmpty:
@ -847,13 +740,10 @@ func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode,
case tag.isString: case tag.isString:
headType = headType.headToStringTagHead() headType = headType.headToStringTagHead()
} }
if withIndent {
return headType.toIndent()
}
return headType return headType
} }
func (e *Encoder) optimizeStructField(ctx *encodeCompileContext, code *opcode, tag *structTag, withIndent bool) opType { func (e *Encoder) optimizeStructField(ctx *encodeCompileContext, code *opcode, tag *structTag) opType {
fieldType := e.typeToFieldType(ctx, code) fieldType := e.typeToFieldType(ctx, code)
switch { switch {
case tag.isOmitEmpty: case tag.isOmitEmpty:
@ -861,9 +751,6 @@ func (e *Encoder) optimizeStructField(ctx *encodeCompileContext, code *opcode, t
case tag.isString: case tag.isString:
fieldType = fieldType.fieldToStringTagField() fieldType = fieldType.fieldToStringTagField()
} }
if withIndent {
return fieldType.toIndent()
}
return fieldType return fieldType
} }
@ -884,7 +771,7 @@ func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode {
func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag) *opcode { func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag) *opcode {
fieldCode.indent-- fieldCode.indent--
op := e.optimizeStructHeader(ctx, valueCode, tag, ctx.withIndent) op := e.optimizeStructHeader(ctx, valueCode, tag)
fieldCode.op = op fieldCode.op = op
fieldCode.ptrNum = valueCode.ptrNum fieldCode.ptrNum = valueCode.ptrNum
switch op { switch op {
@ -900,20 +787,7 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, val
opStructFieldHeadOmitEmptyMap, opStructFieldHeadOmitEmptyMap,
opStructFieldHeadOmitEmptyMapLoad, opStructFieldHeadOmitEmptyMapLoad,
opStructFieldHeadOmitEmptyStruct, opStructFieldHeadOmitEmptyStruct,
opStructFieldHeadStringTag, opStructFieldHeadStringTag:
opStructFieldHeadIndent,
opStructFieldHeadSliceIndent,
opStructFieldHeadArrayIndent,
opStructFieldHeadMapIndent,
opStructFieldHeadMapLoadIndent,
opStructFieldHeadStructIndent,
opStructFieldHeadOmitEmptyIndent,
opStructFieldHeadOmitEmptySliceIndent,
opStructFieldHeadOmitEmptyArrayIndent,
opStructFieldHeadOmitEmptyMapIndent,
opStructFieldHeadOmitEmptyMapLoadIndent,
opStructFieldHeadOmitEmptyStructIndent,
opStructFieldHeadStringTagIndent:
return valueCode.beforeLastCode() return valueCode.beforeLastCode()
} }
ctx.decOpcodeIndex() ctx.decOpcodeIndex()
@ -922,7 +796,7 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, val
func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag) *opcode { func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag) *opcode {
code := (*opcode)(unsafe.Pointer(fieldCode)) code := (*opcode)(unsafe.Pointer(fieldCode))
op := e.optimizeStructField(ctx, valueCode, tag, ctx.withIndent) op := e.optimizeStructField(ctx, valueCode, tag)
fieldCode.op = op fieldCode.op = op
fieldCode.ptrNum = valueCode.ptrNum fieldCode.ptrNum = valueCode.ptrNum
switch op { switch op {
@ -938,20 +812,7 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valu
opStructFieldOmitEmptyMap, opStructFieldOmitEmptyMap,
opStructFieldOmitEmptyMapLoad, opStructFieldOmitEmptyMapLoad,
opStructFieldOmitEmptyStruct, opStructFieldOmitEmptyStruct,
opStructFieldStringTag, opStructFieldStringTag:
opStructFieldIndent,
opStructFieldSliceIndent,
opStructFieldArrayIndent,
opStructFieldMapIndent,
opStructFieldMapLoadIndent,
opStructFieldStructIndent,
opStructFieldOmitEmptyIndent,
opStructFieldOmitEmptySliceIndent,
opStructFieldOmitEmptyArrayIndent,
opStructFieldOmitEmptyMapIndent,
opStructFieldOmitEmptyMapLoadIndent,
opStructFieldOmitEmptyStructIndent,
opStructFieldStringTagIndent:
return valueCode.beforeLastCode() return valueCode.beforeLastCode()
} }
ctx.decIndex() ctx.decIndex()
@ -988,10 +849,10 @@ func (e *Encoder) optimizeAnonymousFields(head *opcode) {
var prev *opcode var prev *opcode
removedFields := map[*opcode]struct{}{} removedFields := map[*opcode]struct{}{}
for { for {
if code.op == opStructEnd || code.op == opStructEndIndent { if code.op == opStructEnd {
break break
} }
if code.op == opStructField || code.op == opStructFieldIndent { if code.op == opStructField {
codeType := code.next.op.codeType() codeType := code.next.op.codeType()
if codeType == codeStructField { if codeType == codeStructField {
if e.isNotExistsField(code.next) { if e.isNotExistsField(code.next) {
@ -1252,9 +1113,6 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
} }
structEndCode.prevField = head structEndCode.prevField = head
ctx.incIndex() ctx.incIndex()
if ctx.withIndent {
head.op = opStructFieldHeadIndent
}
code = head code = head
} }
@ -1262,10 +1120,6 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
structEndCode.idx = opcodeOffset(ctx.ptrIndex) structEndCode.idx = opcodeOffset(ctx.ptrIndex)
ctx.incIndex() ctx.incIndex()
if ctx.withIndent {
structEndCode.op = opStructEndIndent
}
if prevField != nil && prevField.nextField == nil { if prevField != nil && prevField.nextField == nil {
prevField.nextField = structEndCode prevField.nextField = structEndCode
structEndCode.prevField = prevField structEndCode.prevField = prevField

View File

@ -6,7 +6,6 @@ import (
type encodeCompileContext struct { type encodeCompileContext struct {
typ *rtype typ *rtype
withIndent bool
root bool root bool
opcodeIndex int opcodeIndex int
ptrIndex int ptrIndex int
@ -19,7 +18,6 @@ type encodeCompileContext struct {
func (c *encodeCompileContext) context() *encodeCompileContext { func (c *encodeCompileContext) context() *encodeCompileContext {
return &encodeCompileContext{ return &encodeCompileContext{
typ: c.typ, typ: c.typ,
withIndent: c.withIndent,
root: c.root, root: c.root,
opcodeIndex: c.opcodeIndex, opcodeIndex: c.opcodeIndex,
ptrIndex: c.ptrIndex, ptrIndex: c.ptrIndex,

View File

@ -53,10 +53,21 @@ func copyOpcode(code *opcode) *opcode {
return code.copy(codeMap) return code.copy(codeMap)
} }
func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { func toIndent(c *opcode) *opcode {
if op != opEnd && ctx.withIndent { c = copyOpcode(c)
op = op.toIndent() for code := c; code.op != opEnd; {
code.op = code.op.toIndent()
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 {
return &opcode{ return &opcode{
op: op, op: op,
typ: ctx.typ, typ: ctx.typ,

View File

@ -319,13 +319,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
c, err := e.compileHead(&encodeCompileContext{ c, err := e.compileHead(&encodeCompileContext{
typ: header.typ, typ: header.typ,
root: code.root, root: code.root,
withIndent: e.enabledIndent,
indent: code.indent, indent: code.indent,
structTypeToCompiledCode: map[uintptr]*compiledCode{}, structTypeToCompiledCode: map[uintptr]*compiledCode{},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
if e.enabledIndent {
c = toIndent(c)
}
beforeLastCode := c.beforeLastCode() beforeLastCode := c.beforeLastCode()
lastCode := beforeLastCode.next lastCode := beforeLastCode.next
lastCode.idx = beforeLastCode.idx + uintptrSize lastCode.idx = beforeLastCode.idx + uintptrSize
@ -386,8 +388,8 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
code, err := e.compileMap(&encodeCompileContext{ code, err := e.compileMap(&encodeCompileContext{
typ: typ, typ: typ,
root: code.root, root: code.root,
withIndent: e.enabledIndent,
indent: code.indent, indent: code.indent,
structTypeToCompiledCode: map[uintptr]*compiledCode{},
}, false) }, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -397,15 +399,17 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
code, err := e.compile(&encodeCompileContext{ code, err := e.compile(&encodeCompileContext{
typ: typ, typ: typ,
root: code.root, root: code.root,
withIndent: e.enabledIndent,
indent: code.indent, indent: code.indent,
structTypeToCompiledCode: map[uintptr]*compiledCode{},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
c = code c = code
} }
if e.enabledIndent {
c = toIndent(c)
}
beforeLastCode := c.beforeLastCode() beforeLastCode := c.beforeLastCode()
lastCode := beforeLastCode.next lastCode := beforeLastCode.next
lastCode.idx = beforeLastCode.idx + uintptrSize lastCode.idx = beforeLastCode.idx + uintptrSize