forked from mirror/go-json
Compare commits
3 Commits
master
...
feature/su
Author | SHA1 | Date |
---|---|---|
Masaaki Goshima | 8ec9df385c | |
Masaaki Goshima | 4855599414 | |
Masaaki Goshima | 1d14ceb03e |
|
@ -26,16 +26,11 @@ type headType struct {
|
||||||
OmitEmptyPtrHead string
|
OmitEmptyPtrHead string
|
||||||
AnonymousOmitEmptyHead string
|
AnonymousOmitEmptyHead string
|
||||||
AnonymousOmitEmptyPtrHead string
|
AnonymousOmitEmptyPtrHead string
|
||||||
StringTagHead string
|
|
||||||
StringTagPtrHead string
|
|
||||||
AnonymousStringTagHead string
|
|
||||||
AnonymousStringTagPtrHead string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type fieldType struct {
|
type fieldType struct {
|
||||||
Field string
|
Field string
|
||||||
OmitEmptyField string
|
OmitEmptyField string
|
||||||
StringTagField string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func _main() error {
|
func _main() error {
|
||||||
|
@ -88,6 +83,46 @@ func (t opType) toIndent() opType {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t opType) toString() opType {
|
||||||
|
switch t {
|
||||||
|
case opInt:
|
||||||
|
return opIntString
|
||||||
|
case opInt8:
|
||||||
|
return opInt8String
|
||||||
|
case opInt16:
|
||||||
|
return opInt16String
|
||||||
|
case opInt32:
|
||||||
|
return opInt32String
|
||||||
|
case opInt64:
|
||||||
|
return opInt64String
|
||||||
|
case opUint:
|
||||||
|
return opUintString
|
||||||
|
case opUint8:
|
||||||
|
return opUint8String
|
||||||
|
case opUint16:
|
||||||
|
return opUint16String
|
||||||
|
case opUint32:
|
||||||
|
return opUint32String
|
||||||
|
case opUint64:
|
||||||
|
return opUint64String
|
||||||
|
case opFloat32:
|
||||||
|
return opFloat32String
|
||||||
|
case opFloat64:
|
||||||
|
return opFloat64String
|
||||||
|
case opBool:
|
||||||
|
return opBoolString
|
||||||
|
case opString:
|
||||||
|
return opStringString
|
||||||
|
case opBytes:
|
||||||
|
return opBytesString
|
||||||
|
case opMarshalJSON:
|
||||||
|
return opMarshalJSONString
|
||||||
|
case opMarshalText:
|
||||||
|
return opMarshalTextString
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
func (t opType) headToPtrHead() opType {
|
func (t opType) headToPtrHead() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .HeadTypes }}
|
{{- range $type := .HeadTypes }}
|
||||||
|
@ -99,10 +134,6 @@ func (t opType) headToPtrHead() opType {
|
||||||
return op{{ $type.OmitEmptyPtrHead }}
|
return op{{ $type.OmitEmptyPtrHead }}
|
||||||
case op{{ $type.AnonymousOmitEmptyHead }}:
|
case op{{ $type.AnonymousOmitEmptyHead }}:
|
||||||
return op{{ $type.AnonymousOmitEmptyPtrHead }}
|
return op{{ $type.AnonymousOmitEmptyPtrHead }}
|
||||||
case op{{ $type.StringTagHead }}:
|
|
||||||
return op{{ $type.StringTagPtrHead }}
|
|
||||||
case op{{ $type.AnonymousStringTagHead }}:
|
|
||||||
return op{{ $type.AnonymousStringTagPtrHead }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -119,10 +150,6 @@ func (t opType) headToAnonymousHead() opType {
|
||||||
return op{{ $type.AnonymousOmitEmptyHead }}
|
return op{{ $type.AnonymousOmitEmptyHead }}
|
||||||
case op{{ $type.OmitEmptyPtrHead }}:
|
case op{{ $type.OmitEmptyPtrHead }}:
|
||||||
return op{{ $type.AnonymousOmitEmptyPtrHead }}
|
return op{{ $type.AnonymousOmitEmptyPtrHead }}
|
||||||
case op{{ $type.StringTagHead }}:
|
|
||||||
return op{{ $type.AnonymousStringTagHead }}
|
|
||||||
case op{{ $type.StringTagPtrHead }}:
|
|
||||||
return op{{ $type.AnonymousStringTagPtrHead }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -140,18 +167,6 @@ func (t opType) headToOmitEmptyHead() opType {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t opType) headToStringTagHead() opType {
|
|
||||||
switch t {
|
|
||||||
{{- range $type := .HeadTypes }}
|
|
||||||
case op{{ $type.Head }}:
|
|
||||||
return op{{ $type.StringTagHead }}
|
|
||||||
case op{{ $type.PtrHead }}:
|
|
||||||
return op{{ $type.StringTagPtrHead }}
|
|
||||||
{{- end }}
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t opType) ptrHeadToHead() opType {
|
func (t opType) ptrHeadToHead() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .HeadTypes }}
|
{{- range $type := .HeadTypes }}
|
||||||
|
@ -163,10 +178,6 @@ func (t opType) ptrHeadToHead() opType {
|
||||||
return op{{ $type.OmitEmptyHead }}
|
return op{{ $type.OmitEmptyHead }}
|
||||||
case op{{ $type.AnonymousOmitEmptyPtrHead }}:
|
case op{{ $type.AnonymousOmitEmptyPtrHead }}:
|
||||||
return op{{ $type.AnonymousOmitEmptyHead }}
|
return op{{ $type.AnonymousOmitEmptyHead }}
|
||||||
case op{{ $type.StringTagPtrHead }}:
|
|
||||||
return op{{ $type.StringTagHead }}
|
|
||||||
case op{{ $type.AnonymousStringTagPtrHead }}:
|
|
||||||
return op{{ $type.AnonymousStringTagHead }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -182,16 +193,6 @@ func (t opType) fieldToOmitEmptyField() opType {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t opType) fieldToStringTagField() opType {
|
|
||||||
switch t {
|
|
||||||
{{- range $type := .FieldTypes }}
|
|
||||||
case op{{ $type.Field }}:
|
|
||||||
return op{{ $type.StringTagField }}
|
|
||||||
{{- end }}
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -215,6 +216,14 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
"float32", "float64", "bool", "string", "bytes",
|
"float32", "float64", "bool", "string", "bytes",
|
||||||
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText",
|
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// primitiveStringTypes primitive types for StringTag
|
||||||
|
primitiveStringTypes := []string{}
|
||||||
|
for _, typ := range primitiveTypes {
|
||||||
|
primitiveStringTypes = append(primitiveStringTypes, fmt.Sprintf("%sString", typ))
|
||||||
|
}
|
||||||
|
primitiveTypes = append(primitiveTypes, primitiveStringTypes...)
|
||||||
|
|
||||||
primitiveTypesUpper := []string{}
|
primitiveTypesUpper := []string{}
|
||||||
for _, typ := range primitiveTypes {
|
for _, typ := range primitiveTypes {
|
||||||
primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:])
|
primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:])
|
||||||
|
@ -239,19 +248,15 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
{"MapEnd", "MapEndIndent", "Op"},
|
{"MapEnd", "MapEndIndent", "Op"},
|
||||||
{"StructFieldHead", "StructFieldHeadIndent", "StructField"},
|
{"StructFieldHead", "StructFieldHeadIndent", "StructField"},
|
||||||
{"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmptyIndent", "StructField"},
|
{"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmptyIndent", "StructField"},
|
||||||
{"StructFieldHeadStringTag", "StructFieldHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"},
|
{"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"},
|
||||||
|
{"StructFieldAnonymousSkipHead", "StructFieldAnonymousSkipHeadIndent", "StructField"},
|
||||||
{"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"},
|
{"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"},
|
||||||
{"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"},
|
{"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"},
|
||||||
{"StructFieldAnonymousHeadStringTag", "StructFieldAnonymousHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldPtrAnonymousHeadStringTag", "StructFieldPtrAnonymousHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
|
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
|
||||||
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
|
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
|
||||||
{"StructFieldPtrHeadStringTag", "StructFieldPtrHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
|
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
|
||||||
{"StructField", "StructFieldIndent", "StructField"},
|
{"StructField", "StructFieldIndent", "StructField"},
|
||||||
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
|
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
|
||||||
{"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"},
|
{"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"},
|
||||||
{"StructFieldRecursiveEnd", "StructFieldRecursiveEndIndent", "Op"},
|
{"StructFieldRecursiveEnd", "StructFieldRecursiveEndIndent", "Op"},
|
||||||
{"StructEnd", "StructEndIndent", "StructField"},
|
{"StructEnd", "StructEndIndent", "StructField"},
|
||||||
|
@ -267,20 +272,15 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
for _, prefix := range []string{
|
for _, prefix := range []string{
|
||||||
"StructFieldHead",
|
"StructFieldHead",
|
||||||
"StructFieldHeadOmitEmpty",
|
"StructFieldHeadOmitEmpty",
|
||||||
"StructFieldHeadStringTag",
|
|
||||||
"StructFieldAnonymousHead",
|
"StructFieldAnonymousHead",
|
||||||
"StructFieldAnonymousHeadOmitEmpty",
|
"StructFieldAnonymousHeadOmitEmpty",
|
||||||
"StructFieldAnonymousHeadStringTag",
|
|
||||||
"StructFieldPtrHead",
|
"StructFieldPtrHead",
|
||||||
"StructFieldPtrHeadOmitEmpty",
|
"StructFieldPtrHeadOmitEmpty",
|
||||||
"StructFieldPtrHeadStringTag",
|
|
||||||
"StructFieldPtrAnonymousHead",
|
"StructFieldPtrAnonymousHead",
|
||||||
"StructFieldPtrAnonymousHeadOmitEmpty",
|
"StructFieldPtrAnonymousHeadOmitEmpty",
|
||||||
"StructFieldPtrAnonymousHeadStringTag",
|
|
||||||
"StructField",
|
"StructField",
|
||||||
"StructFieldPtr",
|
"StructFieldPtr",
|
||||||
"StructFieldOmitEmpty",
|
"StructFieldOmitEmpty",
|
||||||
"StructFieldStringTag",
|
|
||||||
} {
|
} {
|
||||||
for _, typ := range primitiveTypesUpper {
|
for _, typ := range primitiveTypesUpper {
|
||||||
opTypes = append(opTypes, opType{
|
opTypes = append(opTypes, opType{
|
||||||
|
@ -304,12 +304,8 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
AnonymousPtrHead: "StructFieldPtrAnonymousHead",
|
AnonymousPtrHead: "StructFieldPtrAnonymousHead",
|
||||||
OmitEmptyHead: "StructFieldHeadOmitEmpty",
|
OmitEmptyHead: "StructFieldHeadOmitEmpty",
|
||||||
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
|
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
|
||||||
StringTagHead: "StructFieldHeadStringTag",
|
|
||||||
StringTagPtrHead: "StructFieldPtrHeadStringTag",
|
|
||||||
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
|
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
|
||||||
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
|
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
|
||||||
AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag",
|
|
||||||
AnonymousStringTagPtrHead: "StructFieldPtrAnonymousHeadStringTag",
|
|
||||||
}
|
}
|
||||||
headTypes := []headType{base}
|
headTypes := []headType{base}
|
||||||
for _, prim := range primitiveTypesUpper {
|
for _, prim := range primitiveTypesUpper {
|
||||||
|
@ -322,10 +318,6 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
|
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
|
||||||
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
|
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
|
||||||
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
|
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
|
||||||
StringTagHead: fmt.Sprintf("%s%s", base.StringTagHead, prim),
|
|
||||||
StringTagPtrHead: fmt.Sprintf("%s%s", base.StringTagPtrHead, prim),
|
|
||||||
AnonymousStringTagHead: fmt.Sprintf("%s%s", base.AnonymousStringTagHead, prim),
|
|
||||||
AnonymousStringTagPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagPtrHead, prim),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, typ := range headTypes {
|
for _, typ := range headTypes {
|
||||||
|
@ -338,31 +330,24 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
|
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
|
||||||
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
|
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
|
||||||
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
|
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
|
||||||
StringTagHead: fmt.Sprintf("%sIndent", typ.StringTagHead),
|
|
||||||
StringTagPtrHead: fmt.Sprintf("%sIndent", typ.StringTagPtrHead),
|
|
||||||
AnonymousStringTagHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagHead),
|
|
||||||
AnonymousStringTagPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagPtrHead),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
baseField := fieldType{
|
baseField := fieldType{
|
||||||
Field: "StructField",
|
Field: "StructField",
|
||||||
OmitEmptyField: "StructFieldOmitEmpty",
|
OmitEmptyField: "StructFieldOmitEmpty",
|
||||||
StringTagField: "StructFieldStringTag",
|
|
||||||
}
|
}
|
||||||
fieldTypes := []fieldType{baseField}
|
fieldTypes := []fieldType{baseField}
|
||||||
for _, prim := range primitiveTypesUpper {
|
for _, prim := range primitiveTypesUpper {
|
||||||
fieldTypes = append(fieldTypes, fieldType{
|
fieldTypes = append(fieldTypes, fieldType{
|
||||||
Field: fmt.Sprintf("%s%s", baseField.Field, prim),
|
Field: fmt.Sprintf("%s%s", baseField.Field, prim),
|
||||||
OmitEmptyField: fmt.Sprintf("%s%s", baseField.OmitEmptyField, prim),
|
OmitEmptyField: fmt.Sprintf("%s%s", baseField.OmitEmptyField, prim),
|
||||||
StringTagField: fmt.Sprintf("%s%s", baseField.StringTagField, prim),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, typ := range fieldTypes {
|
for _, typ := range fieldTypes {
|
||||||
fieldTypes = append(fieldTypes, fieldType{
|
fieldTypes = append(fieldTypes, fieldType{
|
||||||
Field: fmt.Sprintf("%sIndent", typ.Field),
|
Field: fmt.Sprintf("%sIndent", typ.Field),
|
||||||
OmitEmptyField: fmt.Sprintf("%sIndent", typ.OmitEmptyField),
|
OmitEmptyField: fmt.Sprintf("%sIndent", typ.OmitEmptyField),
|
||||||
StringTagField: fmt.Sprintf("%sIndent", typ.StringTagField),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,13 +139,15 @@ func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ptrHeadOp := code.op.headToPtrHead()
|
/*
|
||||||
if code.op != ptrHeadOp {
|
ptrHeadOp := code.op.headToPtrHead()
|
||||||
code.op = ptrHeadOp
|
if code.op != ptrHeadOp {
|
||||||
code.decOpcodeIndex()
|
code.op = ptrHeadOp
|
||||||
ctx.decIndex()
|
code.decOpcodeIndex()
|
||||||
return code, nil
|
ctx.decIndex()
|
||||||
}
|
return code, nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
c := ctx.context()
|
c := ctx.context()
|
||||||
c.opcodeIndex = ptrOpcodeIndex
|
c.opcodeIndex = ptrOpcodeIndex
|
||||||
return newOpCodeWithNext(c, opPtr, code), nil
|
return newOpCodeWithNext(c, opPtr, code), nil
|
||||||
|
@ -571,12 +573,10 @@ func (e *Encoder) typeToFieldType(code *opcode) opType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent bool) opType {
|
func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent bool) opType {
|
||||||
headType := e.typeToHeaderType(op)
|
headType := opStructFieldHead // e.typeToHeaderType(op)
|
||||||
switch {
|
switch {
|
||||||
case tag.isOmitEmpty:
|
case tag.isOmitEmpty:
|
||||||
headType = headType.headToOmitEmptyHead()
|
headType = headType.headToOmitEmptyHead()
|
||||||
case tag.isString:
|
|
||||||
headType = headType.headToStringTagHead()
|
|
||||||
}
|
}
|
||||||
if withIndent {
|
if withIndent {
|
||||||
return headType.toIndent()
|
return headType.toIndent()
|
||||||
|
@ -585,12 +585,10 @@ func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent boo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) optimizeStructField(code *opcode, tag *structTag, withIndent bool) opType {
|
func (e *Encoder) optimizeStructField(code *opcode, tag *structTag, withIndent bool) opType {
|
||||||
fieldType := e.typeToFieldType(code)
|
fieldType := opStructField // e.typeToFieldType(code)
|
||||||
switch {
|
switch {
|
||||||
case tag.isOmitEmpty:
|
case tag.isOmitEmpty:
|
||||||
fieldType = fieldType.fieldToOmitEmptyField()
|
fieldType = fieldType.fieldToOmitEmptyField()
|
||||||
case tag.isString:
|
|
||||||
fieldType = fieldType.fieldToStringTagField()
|
|
||||||
}
|
}
|
||||||
if withIndent {
|
if withIndent {
|
||||||
return fieldType.toIndent()
|
return fieldType.toIndent()
|
||||||
|
@ -636,7 +634,6 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, val
|
||||||
opStructFieldHeadOmitEmptyMap,
|
opStructFieldHeadOmitEmptyMap,
|
||||||
opStructFieldHeadOmitEmptyMapLoad,
|
opStructFieldHeadOmitEmptyMapLoad,
|
||||||
opStructFieldHeadOmitEmptyStruct,
|
opStructFieldHeadOmitEmptyStruct,
|
||||||
opStructFieldHeadStringTag,
|
|
||||||
opStructFieldHeadIndent,
|
opStructFieldHeadIndent,
|
||||||
opStructFieldHeadSliceIndent,
|
opStructFieldHeadSliceIndent,
|
||||||
opStructFieldHeadArrayIndent,
|
opStructFieldHeadArrayIndent,
|
||||||
|
@ -648,8 +645,7 @@ func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, val
|
||||||
opStructFieldHeadOmitEmptyArrayIndent,
|
opStructFieldHeadOmitEmptyArrayIndent,
|
||||||
opStructFieldHeadOmitEmptyMapIndent,
|
opStructFieldHeadOmitEmptyMapIndent,
|
||||||
opStructFieldHeadOmitEmptyMapLoadIndent,
|
opStructFieldHeadOmitEmptyMapLoadIndent,
|
||||||
opStructFieldHeadOmitEmptyStructIndent,
|
opStructFieldHeadOmitEmptyStructIndent:
|
||||||
opStructFieldHeadStringTagIndent:
|
|
||||||
return valueCode.beforeLastCode()
|
return valueCode.beforeLastCode()
|
||||||
}
|
}
|
||||||
ctx.decOpcodeIndex()
|
ctx.decOpcodeIndex()
|
||||||
|
@ -673,7 +669,6 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valu
|
||||||
opStructFieldOmitEmptyMap,
|
opStructFieldOmitEmptyMap,
|
||||||
opStructFieldOmitEmptyMapLoad,
|
opStructFieldOmitEmptyMapLoad,
|
||||||
opStructFieldOmitEmptyStruct,
|
opStructFieldOmitEmptyStruct,
|
||||||
opStructFieldStringTag,
|
|
||||||
opStructFieldIndent,
|
opStructFieldIndent,
|
||||||
opStructFieldSliceIndent,
|
opStructFieldSliceIndent,
|
||||||
opStructFieldArrayIndent,
|
opStructFieldArrayIndent,
|
||||||
|
@ -685,8 +680,7 @@ func (e *Encoder) structField(ctx *encodeCompileContext, fieldCode *opcode, valu
|
||||||
opStructFieldOmitEmptyArrayIndent,
|
opStructFieldOmitEmptyArrayIndent,
|
||||||
opStructFieldOmitEmptyMapIndent,
|
opStructFieldOmitEmptyMapIndent,
|
||||||
opStructFieldOmitEmptyMapLoadIndent,
|
opStructFieldOmitEmptyMapLoadIndent,
|
||||||
opStructFieldOmitEmptyStructIndent,
|
opStructFieldOmitEmptyStructIndent:
|
||||||
opStructFieldStringTagIndent:
|
|
||||||
return valueCode.beforeLastCode()
|
return valueCode.beforeLastCode()
|
||||||
}
|
}
|
||||||
ctx.decIndex()
|
ctx.decIndex()
|
||||||
|
@ -751,16 +745,26 @@ type structFieldPair struct {
|
||||||
linked bool
|
linked bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) isAnonymousStructType(code *opcode) bool {
|
||||||
|
if code.op == opPtr {
|
||||||
|
code = code.next
|
||||||
|
}
|
||||||
|
return code.op.codeType() == codeStructField
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, valueCode *opcode) map[string][]structFieldPair {
|
func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, valueCode *opcode) map[string][]structFieldPair {
|
||||||
anonymousFields := map[string][]structFieldPair{}
|
anonymousFields := map[string][]structFieldPair{}
|
||||||
f := valueCode
|
f := valueCode
|
||||||
|
if f.op == opPtr {
|
||||||
|
f = f.next
|
||||||
|
}
|
||||||
var prevAnonymousField *opcode
|
var prevAnonymousField *opcode
|
||||||
for {
|
for {
|
||||||
existsKey := tags.existsKey(f.displayKey)
|
|
||||||
op := f.op.headToAnonymousHead()
|
op := f.op.headToAnonymousHead()
|
||||||
|
existsKey := tags.existsKey(f.displayKey)
|
||||||
if op != f.op {
|
if op != f.op {
|
||||||
if existsKey {
|
if existsKey {
|
||||||
f.op = opStructFieldAnonymousHead
|
f.op = opStructFieldAnonymousSkipHead
|
||||||
} else {
|
} else {
|
||||||
f.op = op
|
f.op = op
|
||||||
}
|
}
|
||||||
|
@ -773,7 +777,6 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
|
||||||
}
|
}
|
||||||
linkPrevToNextField(prevAnonymousField, f)
|
linkPrevToNextField(prevAnonymousField, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.displayKey == "" {
|
if f.displayKey == "" {
|
||||||
if f.nextField == nil {
|
if f.nextField == nil {
|
||||||
break
|
break
|
||||||
|
@ -802,7 +805,7 @@ func (e *Encoder) anonymousStructFieldPairMap(typ *rtype, tags structTags, value
|
||||||
return anonymousFields
|
return anonymousFields
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPair) {
|
func (e *Encoder) removeConflictAnonymousFields(anonymousFields map[string][]structFieldPair) {
|
||||||
for _, fieldPairs := range anonymousFields {
|
for _, fieldPairs := range anonymousFields {
|
||||||
if len(fieldPairs) == 1 {
|
if len(fieldPairs) == 1 {
|
||||||
continue
|
continue
|
||||||
|
@ -816,7 +819,7 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
|
||||||
if !fieldPair.linked {
|
if !fieldPair.linked {
|
||||||
if fieldPair.prevField == nil {
|
if fieldPair.prevField == nil {
|
||||||
// head operation
|
// head operation
|
||||||
fieldPair.curField.op = opStructFieldAnonymousHead
|
fieldPair.curField.op = opStructFieldAnonymousSkipHead
|
||||||
} else {
|
} else {
|
||||||
diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx
|
diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx
|
||||||
for i := 0; i < diff; i++ {
|
for i := 0; i < diff; i++ {
|
||||||
|
@ -833,7 +836,7 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
|
||||||
if !fieldPair.linked {
|
if !fieldPair.linked {
|
||||||
if fieldPair.prevField == nil {
|
if fieldPair.prevField == nil {
|
||||||
// head operation
|
// head operation
|
||||||
fieldPair.curField.op = opStructFieldAnonymousHead
|
fieldPair.curField.op = opStructFieldAnonymousSkipHead
|
||||||
} else {
|
} else {
|
||||||
diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx
|
diff := fieldPair.curField.nextField.displayIdx - fieldPair.curField.displayIdx
|
||||||
for i := 0; i < diff; i++ {
|
for i := 0; i < diff; i++ {
|
||||||
|
@ -934,13 +937,16 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
|
||||||
idx: opcodeOffset(fieldPtrIndex),
|
idx: opcodeOffset(fieldPtrIndex),
|
||||||
next: valueCode,
|
next: valueCode,
|
||||||
indent: ctx.indent,
|
indent: ctx.indent,
|
||||||
anonymousKey: field.Anonymous,
|
anonymousKey: e.isAnonymousStructType(valueCode) && field.Anonymous,
|
||||||
key: []byte(key),
|
key: []byte(key),
|
||||||
escapedKey: []byte(escapedKey),
|
escapedKey: []byte(escapedKey),
|
||||||
isTaggedKey: tag.isTaggedKey,
|
isTaggedKey: tag.isTaggedKey,
|
||||||
displayKey: tag.key,
|
displayKey: tag.key,
|
||||||
offset: field.Offset,
|
offset: field.Offset,
|
||||||
}
|
}
|
||||||
|
if tag.isString {
|
||||||
|
valueCode.op = valueCode.op.toString()
|
||||||
|
}
|
||||||
if fieldIdx == 0 {
|
if fieldIdx == 0 {
|
||||||
fieldCode.headIdx = fieldCode.idx
|
fieldCode.headIdx = fieldCode.idx
|
||||||
code = e.structHeader(ctx, fieldCode, valueCode, tag)
|
code = e.structHeader(ctx, fieldCode, valueCode, tag)
|
||||||
|
@ -997,8 +1003,8 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
|
||||||
head.end = structEndCode
|
head.end = structEndCode
|
||||||
code.next = structEndCode
|
code.next = structEndCode
|
||||||
|
|
||||||
e.optimizeConflictAnonymousFields(anonymousFields)
|
e.removeConflictAnonymousFields(anonymousFields)
|
||||||
e.optimizeAnonymousFields(head)
|
//e.optimizeAnonymousFields(head)
|
||||||
|
|
||||||
ret := (*opcode)(unsafe.Pointer(head))
|
ret := (*opcode)(unsafe.Pointer(head))
|
||||||
compiled.code = ret
|
compiled.code = ret
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package json
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type encodeOptimizerPlugin interface {
|
||||||
|
optimize(*opcode) (*opcode, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type encodeOptimizer struct {
|
||||||
|
optimizers []encodeOptimizerPlugin
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEncodeOptimizer() *encodeOptimizer {
|
||||||
|
return &encodeOptimizer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *encodeOptimizer) addOptimizer(plg encodeOptimizerPlugin) {
|
||||||
|
o.optimizers = append(o.optimizers, plg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *encodeOptimizer) optimize(code *opcode) (*opcode, error) {
|
||||||
|
for _, optimizer := range o.optimizers {
|
||||||
|
c, err := optimizer.optimize(code)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
code = c
|
||||||
|
}
|
||||||
|
return code, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type encodeStructHeadOptimizer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *encodeStructHeadOptimizer) optimize(code *opcode) (*opcode, error) {
|
||||||
|
head := code
|
||||||
|
for code.op != opEnd {
|
||||||
|
if code.op == opStructFieldHead {
|
||||||
|
fmt.Println("StructHead")
|
||||||
|
}
|
||||||
|
switch code.op.codeType() {
|
||||||
|
case codeArrayElem, codeSliceElem:
|
||||||
|
code = code.end
|
||||||
|
case codeMapKey:
|
||||||
|
code = code.end
|
||||||
|
default:
|
||||||
|
code = code.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return head, nil
|
||||||
|
}
|
8260
encode_optype.go
8260
encode_optype.go
File diff suppressed because it is too large
Load Diff
1675
encode_vm.go
1675
encode_vm.go
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue