From 5741c733a691a80d222847ea1932cbd62e75a8f9 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 25 Dec 2020 17:03:56 +0900 Subject: [PATCH] Refactor indent code --- encode.go | 12 +--- encode_compile.go | 162 +++------------------------------------------- encode_context.go | 2 - encode_opcode.go | 17 ++++- encode_vm.go | 24 ++++--- 5 files changed, 37 insertions(+), 180 deletions(-) diff --git a/encode.go b/encode.go index 8618fb7..05c6b4a 100644 --- a/encode.go +++ b/encode.go @@ -200,26 +200,16 @@ func (e *Encoder) encode(v interface{}) ([]byte, error) { // noescape trick for header.typ ( reflect.*rtype ) 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{ typ: copiedType, root: true, - withIndent: false, structTypeToCompiledCode: map[uintptr]*compiledCode{}, }) if err != nil { return nil, err } - codeIndent = copyOpcode(codeIndent) code = copyOpcode(code) + codeIndent := toIndent(code) codeLength := code.totalLength() codeSet := &opcodeSet{ codeIndent: codeIndent, diff --git a/encode_compile.go b/encode_compile.go index fe70c08..4d3127f 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -377,16 +377,6 @@ func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) { end := newOpCode(ctx, opSliceEnd) 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.end = end @@ -421,12 +411,6 @@ func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) { end := newOpCode(ctx, opArrayEnd) ctx.incIndex() - if ctx.withIndent { - header.op = opArrayHeadIndent - elemCode.op = opArrayElemIndent - end.op = opArrayEndIndent - } - header.elem = elemCode header.end = end header.next = code @@ -487,13 +471,6 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, end := newMapEndCode(ctx, header) 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 keyCode.beforeLastCode().next = (*opcode)(unsafe.Pointer(value)) value.next = valueCode @@ -587,88 +564,46 @@ func (e *Encoder) typeToHeaderType(ctx *encodeCompileContext, code *opcode) opTy } case opInt: return opStructFieldHeadInt - case opIntIndent: - return opStructFieldHeadIntIndent case opInt8: return opStructFieldHeadInt8 - case opInt8Indent: - return opStructFieldHeadInt8Indent case opInt16: return opStructFieldHeadInt16 - case opInt16Indent: - return opStructFieldHeadInt16Indent case opInt32: return opStructFieldHeadInt32 - case opInt32Indent: - return opStructFieldHeadInt32Indent case opInt64: return opStructFieldHeadInt64 - case opInt64Indent: - return opStructFieldHeadInt64Indent case opUint: return opStructFieldHeadUint - case opUintIndent: - return opStructFieldHeadUintIndent case opUint8: return opStructFieldHeadUint8 - case opUint8Indent: - return opStructFieldHeadUint8Indent case opUint16: return opStructFieldHeadUint16 - case opUint16Indent: - return opStructFieldHeadUint16Indent case opUint32: return opStructFieldHeadUint32 - case opUint32Indent: - return opStructFieldHeadUint32Indent case opUint64: return opStructFieldHeadUint64 - case opUint64Indent: - return opStructFieldHeadUint64Indent case opFloat32: return opStructFieldHeadFloat32 - case opFloat32Indent: - return opStructFieldHeadFloat32Indent case opFloat64: return opStructFieldHeadFloat64 - case opFloat64Indent: - return opStructFieldHeadFloat64Indent case opString: return opStructFieldHeadString - case opStringIndent: - return opStructFieldHeadStringIndent case opBool: return opStructFieldHeadBool - case opBoolIndent: - return opStructFieldHeadBoolIndent case opMapHead: return opStructFieldHeadMap case opMapHeadLoad: return opStructFieldHeadMapLoad - case opMapHeadIndent: - return opStructFieldHeadMapIndent - case opMapHeadLoadIndent: - return opStructFieldHeadMapLoadIndent case opArrayHead: return opStructFieldHeadArray - case opArrayHeadIndent: - return opStructFieldHeadArrayIndent case opSliceHead: return opStructFieldHeadSlice - case opSliceHeadIndent: - return opStructFieldHeadSliceIndent case opStructFieldHead: return opStructFieldHeadStruct - case opStructFieldHeadIndent: - return opStructFieldHeadStructIndent case opMarshalJSON: return opStructFieldHeadMarshalJSON - case opMarshalJSONIndent: - return opStructFieldHeadMarshalJSONIndent case opMarshalText: return opStructFieldHeadMarshalText - case opMarshalTextIndent: - return opStructFieldHeadMarshalTextIndent } return opStructFieldHead } @@ -753,93 +688,51 @@ func (e *Encoder) typeToFieldType(ctx *encodeCompileContext, code *opcode) opTyp } case opInt: return opStructFieldInt - case opIntIndent: - return opStructFieldIntIndent case opInt8: return opStructFieldInt8 - case opInt8Indent: - return opStructFieldInt8Indent case opInt16: return opStructFieldInt16 - case opInt16Indent: - return opStructFieldInt16Indent case opInt32: return opStructFieldInt32 - case opInt32Indent: - return opStructFieldInt32Indent case opInt64: return opStructFieldInt64 - case opInt64Indent: - return opStructFieldInt64Indent case opUint: return opStructFieldUint - case opUintIndent: - return opStructFieldUintIndent case opUint8: return opStructFieldUint8 - case opUint8Indent: - return opStructFieldUint8Indent case opUint16: return opStructFieldUint16 - case opUint16Indent: - return opStructFieldUint16Indent case opUint32: return opStructFieldUint32 - case opUint32Indent: - return opStructFieldUint32Indent case opUint64: return opStructFieldUint64 - case opUint64Indent: - return opStructFieldUint64Indent case opFloat32: return opStructFieldFloat32 - case opFloat32Indent: - return opStructFieldFloat32Indent case opFloat64: return opStructFieldFloat64 - case opFloat64Indent: - return opStructFieldFloat64Indent case opString: return opStructFieldString - case opStringIndent: - return opStructFieldStringIndent case opBool: return opStructFieldBool - case opBoolIndent: - return opStructFieldBoolIndent case opMapHead: return opStructFieldMap case opMapHeadLoad: return opStructFieldMapLoad - case opMapHeadIndent: - return opStructFieldMapIndent - case opMapHeadLoadIndent: - return opStructFieldMapLoadIndent case opArrayHead: return opStructFieldArray - case opArrayHeadIndent: - return opStructFieldArrayIndent case opSliceHead: return opStructFieldSlice - case opSliceHeadIndent: - return opStructFieldSliceIndent case opStructFieldHead: return opStructFieldStruct - case opStructFieldHeadIndent: - return opStructFieldStructIndent case opMarshalJSON: return opStructFieldMarshalJSON - case opMarshalJSONIndent: - return opStructFieldMarshalJSONIndent case opMarshalText: return opStructFieldMarshalText - case opMarshalTextIndent: - return opStructFieldMarshalTextIndent } 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) switch { case tag.isOmitEmpty: @@ -847,13 +740,10 @@ func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode, case tag.isString: headType = headType.headToStringTagHead() } - if withIndent { - return headType.toIndent() - } 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) switch { case tag.isOmitEmpty: @@ -861,9 +751,6 @@ func (e *Encoder) optimizeStructField(ctx *encodeCompileContext, code *opcode, t case tag.isString: fieldType = fieldType.fieldToStringTagField() } - if withIndent { - return fieldType.toIndent() - } 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 { fieldCode.indent-- - op := e.optimizeStructHeader(ctx, valueCode, tag, ctx.withIndent) + op := e.optimizeStructHeader(ctx, valueCode, tag) fieldCode.op = op fieldCode.ptrNum = valueCode.ptrNum switch op { @@ -900,20 +787,7 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, val opStructFieldHeadOmitEmptyMap, opStructFieldHeadOmitEmptyMapLoad, opStructFieldHeadOmitEmptyStruct, - opStructFieldHeadStringTag, - opStructFieldHeadIndent, - opStructFieldHeadSliceIndent, - opStructFieldHeadArrayIndent, - opStructFieldHeadMapIndent, - opStructFieldHeadMapLoadIndent, - opStructFieldHeadStructIndent, - opStructFieldHeadOmitEmptyIndent, - opStructFieldHeadOmitEmptySliceIndent, - opStructFieldHeadOmitEmptyArrayIndent, - opStructFieldHeadOmitEmptyMapIndent, - opStructFieldHeadOmitEmptyMapLoadIndent, - opStructFieldHeadOmitEmptyStructIndent, - opStructFieldHeadStringTagIndent: + opStructFieldHeadStringTag: return valueCode.beforeLastCode() } 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 { code := (*opcode)(unsafe.Pointer(fieldCode)) - op := e.optimizeStructField(ctx, valueCode, tag, ctx.withIndent) + op := e.optimizeStructField(ctx, valueCode, tag) fieldCode.op = op fieldCode.ptrNum = valueCode.ptrNum switch op { @@ -938,20 +812,7 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valu opStructFieldOmitEmptyMap, opStructFieldOmitEmptyMapLoad, opStructFieldOmitEmptyStruct, - opStructFieldStringTag, - opStructFieldIndent, - opStructFieldSliceIndent, - opStructFieldArrayIndent, - opStructFieldMapIndent, - opStructFieldMapLoadIndent, - opStructFieldStructIndent, - opStructFieldOmitEmptyIndent, - opStructFieldOmitEmptySliceIndent, - opStructFieldOmitEmptyArrayIndent, - opStructFieldOmitEmptyMapIndent, - opStructFieldOmitEmptyMapLoadIndent, - opStructFieldOmitEmptyStructIndent, - opStructFieldStringTagIndent: + opStructFieldStringTag: return valueCode.beforeLastCode() } ctx.decIndex() @@ -988,10 +849,10 @@ func (e *Encoder) optimizeAnonymousFields(head *opcode) { var prev *opcode removedFields := map[*opcode]struct{}{} for { - if code.op == opStructEnd || code.op == opStructEndIndent { + if code.op == opStructEnd { break } - if code.op == opStructField || code.op == opStructFieldIndent { + if code.op == opStructField { codeType := code.next.op.codeType() if codeType == codeStructField { if e.isNotExistsField(code.next) { @@ -1252,9 +1113,6 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, } structEndCode.prevField = head ctx.incIndex() - if ctx.withIndent { - head.op = opStructFieldHeadIndent - } code = head } @@ -1262,10 +1120,6 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, structEndCode.idx = opcodeOffset(ctx.ptrIndex) ctx.incIndex() - if ctx.withIndent { - structEndCode.op = opStructEndIndent - } - if prevField != nil && prevField.nextField == nil { prevField.nextField = structEndCode structEndCode.prevField = prevField diff --git a/encode_context.go b/encode_context.go index c3a420d..52f1e93 100644 --- a/encode_context.go +++ b/encode_context.go @@ -6,7 +6,6 @@ import ( type encodeCompileContext struct { typ *rtype - withIndent bool root bool opcodeIndex int ptrIndex int @@ -19,7 +18,6 @@ type encodeCompileContext struct { func (c *encodeCompileContext) context() *encodeCompileContext { return &encodeCompileContext{ typ: c.typ, - withIndent: c.withIndent, root: c.root, opcodeIndex: c.opcodeIndex, ptrIndex: c.ptrIndex, diff --git a/encode_opcode.go b/encode_opcode.go index 756f9f0..d836d61 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -53,10 +53,21 @@ func copyOpcode(code *opcode) *opcode { return code.copy(codeMap) } -func newOpCodeWithNext(ctx *encodeCompileContext, op opType, next *opcode) *opcode { - if op != opEnd && ctx.withIndent { - op = op.toIndent() +func toIndent(c *opcode) *opcode { + c = copyOpcode(c) + 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{ op: op, typ: ctx.typ, diff --git a/encode_vm.go b/encode_vm.go index f396e33..f784ed3 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -319,13 +319,15 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte c, err := e.compileHead(&encodeCompileContext{ typ: header.typ, root: code.root, - withIndent: e.enabledIndent, indent: code.indent, structTypeToCompiledCode: map[uintptr]*compiledCode{}, }) if err != nil { return nil, err } + if e.enabledIndent { + c = toIndent(c) + } beforeLastCode := c.beforeLastCode() lastCode := beforeLastCode.next lastCode.idx = beforeLastCode.idx + uintptrSize @@ -384,10 +386,10 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte var c *opcode if typ.Kind() == reflect.Map { code, err := e.compileMap(&encodeCompileContext{ - typ: typ, - root: code.root, - withIndent: e.enabledIndent, - indent: code.indent, + typ: typ, + root: code.root, + indent: code.indent, + structTypeToCompiledCode: map[uintptr]*compiledCode{}, }, false) if err != nil { return nil, err @@ -395,17 +397,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte c = code } else { code, err := e.compile(&encodeCompileContext{ - typ: typ, - root: code.root, - withIndent: e.enabledIndent, - indent: code.indent, + typ: typ, + root: code.root, + indent: code.indent, + structTypeToCompiledCode: map[uintptr]*compiledCode{}, }) if err != nil { return nil, err } c = code } - + if e.enabledIndent { + c = toIndent(c) + } beforeLastCode := c.beforeLastCode() lastCode := beforeLastCode.next lastCode.idx = beforeLastCode.idx + uintptrSize