Merge pull request #81 from goccy/feature/coverage

Add many test codes and distribute `case` operation ( of `switch` ) to some switch statements
This commit is contained in:
Masaaki Goshima 2021-01-11 19:36:30 +09:00 committed by GitHub
commit af9168203a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 37138 additions and 52122 deletions

View File

@ -5,7 +5,7 @@ jobs:
name: Test
strategy:
matrix:
os: [ "ubuntu-latest", "windows-latest", "macos-latest" ]
os: [ "ubuntu-latest", "macos-latest", "windows-latest" ]
go-version: [ "1.13", "1.14", "1.15" ]
runs-on: ${{ matrix.os }}
steps:

View File

@ -14,23 +14,18 @@ import (
type opType struct {
Op string
Code string
Indent func() string
Escaped func() string
HeadToPtrHead func() string
HeadToNPtrHead func() string
HeadToAnonymousHead func() string
HeadToOmitEmptyHead func() string
HeadToStringTagHead func() string
HeadToOnlyHead func() string
PtrHeadToHead func() string
FieldToEnd func() string
FieldToOmitEmptyField func() string
FieldToStringTagField func() string
}
func (t opType) IsEscaped() bool {
return t.Op != t.Escaped()
}
func (t opType) IsHeadToPtrHead() bool {
return t.Op != t.HeadToPtrHead()
}
@ -55,6 +50,10 @@ func (t opType) IsPtrHeadToHead() bool {
return t.Op != t.PtrHeadToHead()
}
func (t opType) IsHeadToOnlyHead() bool {
return t.Op != t.HeadToOnlyHead()
}
func (t opType) IsFieldToEnd() bool {
return t.Op != t.FieldToEnd()
}
@ -71,13 +70,12 @@ func createOpType(op, code string) opType {
return opType{
Op: op,
Code: code,
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
Escaped: func() string { return op },
HeadToPtrHead: func() string { return op },
HeadToNPtrHead: func() string { return op },
HeadToAnonymousHead: func() string { return op },
HeadToOmitEmptyHead: func() string { return op },
HeadToStringTagHead: func() string { return op },
HeadToOnlyHead: func() string { return op },
PtrHeadToHead: func() string { return op },
FieldToEnd: func() string { return op },
FieldToOmitEmptyField: func() string { return op },
@ -89,6 +87,10 @@ func _main() error {
tmpl, err := template.New("").Parse(`// Code generated by cmd/generator. DO NOT EDIT!
package json
import (
"strings"
)
type codeType int
const (
@ -106,12 +108,8 @@ const (
)
func (t opType) String() string {
if int(t) >= {{ .OpLen }} {
return t.toNotIndent().String() + "Indent"
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return "{{ $type.Op }}"
{{- end }}
@ -120,152 +118,136 @@ func (t opType) String() string {
}
func (t opType) codeType() codeType {
if int(t) >= {{ .OpLen }} {
return t.toNotIndent().codeType()
if strings.Contains(t.String(), "Struct") {
if strings.Contains(t.String(), "End") {
return codeStructEnd
}
return codeStructField
}
if strings.Contains(t.String(), "ArrayHead") {
return codeArrayHead
}
if strings.Contains(t.String(), "ArrayElem") {
return codeArrayElem
}
if strings.Contains(t.String(), "SliceHead") {
return codeSliceHead
}
if strings.Contains(t.String(), "SliceElem") {
return codeSliceElem
}
if strings.Contains(t.String(), "MapHead") {
return codeMapHead
}
if strings.Contains(t.String(), "MapKey") {
return codeMapKey
}
if strings.Contains(t.String(), "MapValue") {
return codeMapValue
}
if strings.Contains(t.String(), "MapEnd") {
return codeMapEnd
}
switch t {
{{- range $type := .OpNotIndentTypes }}
case op{{ $type.Op }}:
return code{{ $type.Code }}
{{- end }}
}
return codeOp
}
func (t opType) toNotIndent() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t) - {{ .OpLen }})
}
return t
}
func (t opType) toIndent() opType {
if int(t) >= {{ .OpLen }} {
func (t opType) headToPtrHead() opType {
if strings.Index(t.String(), "PtrHead") > 0 {
return t
}
return opType(int(t) + {{ .OpLen }})
}
func (t opType) toEscaped() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().toEscaped()) + {{ .OpLen }})
if strings.Index(t.String(), "PtrAnonymousHead") > 0 {
return t
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsEscaped }}
case op{{ $type.Op }}:
return op{{ call $type.Escaped }}
{{- end }}
{{- end }}
idx := strings.Index(t.String(), "Field")
if idx == -1 {
return t
}
return t
}
suffix := "Ptr"+t.String()[idx+len("Field"):]
func (t opType) headToPtrHead() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().headToPtrHead()) + {{ .OpLen }})
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsHeadToPtrHead }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToPtrHead }}
{{- end }}
{{- end }}
const toPtrOffset = 12
if strings.Contains(opType(int(t) + toPtrOffset).String(), suffix) {
return opType(int(t) + toPtrOffset)
}
return t
}
func (t opType) headToNPtrHead() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().headToNPtrHead()) + {{ .OpLen }})
if strings.Index(t.String(), "PtrHead") > 0 {
return t
}
if strings.Index(t.String(), "PtrAnonymousHead") > 0 {
return t
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsHeadToNPtrHead }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToNPtrHead }}
{{- end }}
{{- end }}
idx := strings.Index(t.String(), "Field")
if idx == -1 {
return t
}
suffix := "NPtr"+t.String()[idx+len("Field"):]
const toPtrOffset = 24
if strings.Contains(opType(int(t) + toPtrOffset).String(), suffix) {
return opType(int(t) + toPtrOffset)
}
return t
}
func (t opType) headToAnonymousHead() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().headToAnonymousHead()) + {{ .OpLen }})
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsHeadToAnonymousHead }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToAnonymousHead }}
{{- end }}
{{- end }}
const toAnonymousOffset = 6
if strings.Contains(opType(int(t) + toAnonymousOffset).String(), "Anonymous") {
return opType(int(t) + toAnonymousOffset)
}
return t
}
func (t opType) headToOmitEmptyHead() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().headToOmitEmptyHead()) + {{ .OpLen }})
const toOmitEmptyOffset = 2
if strings.Contains(opType(int(t) + toOmitEmptyOffset).String(), "OmitEmpty") {
return opType(int(t) + toOmitEmptyOffset)
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsHeadToOmitEmptyHead }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToOmitEmptyHead }}
{{- end }}
{{- end }}
}
return t
}
func (t opType) headToStringTagHead() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().headToStringTagHead()) + {{ .OpLen }})
const toStringTagOffset = 4
if strings.Contains(opType(int(t) + toStringTagOffset).String(), "StringTag") {
return opType(int(t) + toStringTagOffset)
}
return t
}
func (t opType) headToOnlyHead() opType {
if strings.HasSuffix(t.String(), "Head") || strings.HasSuffix(t.String(), "HeadOmitEmpty") || strings.HasSuffix(t.String(), "HeadStringTag") {
return t
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsHeadToStringTagHead }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToStringTagHead }}
{{- end }}
{{- end }}
const toOnlyOffset = 1
if opType(int(t) + toOnlyOffset).String() == t.String() + "Only" {
return opType(int(t) + toOnlyOffset)
}
return t
}
func (t opType) ptrHeadToHead() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().ptrHeadToHead()) + {{ .OpLen }})
idx := strings.Index(t.String(), "Ptr")
if idx == -1 {
return t
}
suffix := t.String()[idx+len("Ptr"):]
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsPtrHeadToHead }}
case op{{ $type.Op }}:
return op{{ call $type.PtrHeadToHead }}
{{- end }}
{{- end }}
const toPtrOffset = 12
if strings.Contains(opType(int(t) - toPtrOffset).String(), suffix) {
return opType(int(t) - toPtrOffset)
}
return t
}
func (t opType) fieldToEnd() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().fieldToEnd()) + {{ .OpLen }})
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- range $type := .OpTypes }}
{{- if $type.IsFieldToEnd }}
case op{{ $type.Op }}:
return op{{ call $type.FieldToEnd }}
@ -276,33 +258,17 @@ func (t opType) fieldToEnd() opType {
}
func (t opType) fieldToOmitEmptyField() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().fieldToOmitEmptyField()) + {{ .OpLen }})
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsFieldToOmitEmptyField }}
case op{{ $type.Op }}:
return op{{ call $type.FieldToOmitEmptyField }}
{{- end }}
{{- end }}
const toOmitEmptyOffset = 1
if strings.Contains(opType(int(t) + toOmitEmptyOffset).String(), "OmitEmpty") {
return opType(int(t) + toOmitEmptyOffset)
}
return t
}
func (t opType) fieldToStringTagField() opType {
if int(t) >= {{ .OpLen }} {
return opType(int(t.toNotIndent().fieldToStringTagField()) + {{ .OpLen }})
}
switch t {
{{- range $type := .OpNotIndentTypes }}
{{- if $type.IsFieldToStringTagField }}
case op{{ $type.Op }}:
return op{{ call $type.FieldToStringTagField }}
{{- end }}
{{- end }}
const toStringTagOffset = 2
if strings.Contains(opType(int(t) + toStringTagOffset).String(), "StringTag") {
return opType(int(t) + toStringTagOffset)
}
return t
}
@ -328,16 +294,16 @@ func (t opType) fieldToStringTagField() opType {
primitiveTypes := []string{
"int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64",
"float32", "float64", "bool", "string", "escapedString", "bytes",
"float32", "float64", "bool", "string", "bytes",
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive",
"intString", "int8String", "int16String", "int32String", "int64String",
"uintString", "uint8String", "uint16String", "uint32String", "uint64String",
"intPtr", "int8Ptr", "int16Ptr", "int32Ptr", "int64Ptr",
"uintPtr", "uint8Ptr", "uint16Ptr", "uint32Ptr", "uint64Ptr",
"float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "escapedStringPtr", "bytesPtr",
"float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "bytesPtr",
"intNPtr", "int8NPtr", "int16NPtr", "int32NPtr", "int64NPtr",
"uintNPtr", "uint8NPtr", "uint16NPtr", "uint32NPtr", "uint64NPtr",
"float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "escapedStringNPtr", "bytesNPtr",
"float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "bytesNPtr",
}
primitiveTypesUpper := []string{}
for _, typ := range primitiveTypes {
@ -367,109 +333,98 @@ func (t opType) fieldToStringTagField() opType {
}
for _, typ := range primitiveTypesUpper {
typ := typ
optype := createOpType(typ, "Op")
switch typ {
case "String", "StringPtr", "StringNPtr":
optype.Escaped = func() string {
return fmt.Sprintf("Escaped%s", typ)
}
}
opTypes = append(opTypes, optype)
opTypes = append(opTypes, createOpType(typ, "Op"))
}
for _, escapedOrNot := range []string{"", "Escaped"} {
for _, typ := range append(primitiveTypesUpper, "") {
for _, ptrOrNot := range []string{"", "Ptr", "NPtr"} {
for _, headType := range []string{"", "Anonymous"} {
for _, opt := range []string{"", "OmitEmpty", "StringTag"} {
for _, typ := range append(primitiveTypesUpper, "") {
escapedOrNot := escapedOrNot
for _, onlyOrNot := range []string{"", "Only"} {
ptrOrNot := ptrOrNot
headType := headType
opt := opt
typ := typ
onlyOrNot := onlyOrNot
op := fmt.Sprintf(
"Struct%sField%s%sHead%s%s",
escapedOrNot,
"StructField%s%sHead%s%s%s",
ptrOrNot,
headType,
opt,
typ,
onlyOrNot,
)
opTypes = append(opTypes, opType{
Op: op,
Code: "StructField",
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
Escaped: func() string {
switch typ {
case "String", "StringPtr", "StringNPtr":
return fmt.Sprintf(
"StructEscapedField%s%sHead%sEscaped%s",
ptrOrNot,
headType,
opt,
typ,
)
}
return fmt.Sprintf(
"StructEscapedField%s%sHead%s%s",
ptrOrNot,
headType,
opt,
typ,
)
},
Op: op,
Code: "StructField",
HeadToPtrHead: func() string {
return fmt.Sprintf(
"Struct%sFieldPtr%sHead%s%s",
escapedOrNot,
"StructFieldPtr%sHead%s%s%s",
headType,
opt,
typ,
onlyOrNot,
)
},
HeadToNPtrHead: func() string {
return fmt.Sprintf(
"Struct%sFieldNPtr%sHead%s%s",
escapedOrNot,
"StructFieldNPtr%sHead%s%s%s",
headType,
opt,
typ,
onlyOrNot,
)
},
HeadToAnonymousHead: func() string {
return fmt.Sprintf(
"Struct%sField%sAnonymousHead%s%s",
escapedOrNot,
"StructField%sAnonymousHead%s%s%s",
ptrOrNot,
opt,
typ,
onlyOrNot,
)
},
HeadToOmitEmptyHead: func() string {
return fmt.Sprintf(
"Struct%sField%s%sHeadOmitEmpty%s",
escapedOrNot,
"StructField%s%sHeadOmitEmpty%s%s",
ptrOrNot,
headType,
typ,
onlyOrNot,
)
},
HeadToStringTagHead: func() string {
return fmt.Sprintf(
"Struct%sField%s%sHeadStringTag%s",
escapedOrNot,
"StructField%s%sHeadStringTag%s%s",
ptrOrNot,
headType,
typ,
onlyOrNot,
)
},
HeadToOnlyHead: func() string {
switch typ {
case "", "Array", "Map", "MapLoad", "Slice",
"Struct", "Recursive", "MarshalJSON", "MarshalText",
"IntString", "Int8String", "Int16String", "Int32String", "Int64String",
"UintString", "Uint8String", "Uint16String", "Uint32String", "Uint64String":
return op
}
return fmt.Sprintf(
"StructField%s%sHead%s%sOnly",
ptrOrNot,
headType,
opt,
typ,
)
},
PtrHeadToHead: func() string {
return fmt.Sprintf(
"Struct%sField%sHead%s%s",
escapedOrNot,
"StructField%sHead%s%s%s",
headType,
opt,
typ,
onlyOrNot,
)
},
FieldToEnd: func() string { return op },
@ -481,169 +436,87 @@ func (t opType) fieldToStringTagField() opType {
}
}
}
for _, escapedOrNot := range []string{"", "Escaped"} {
for _, typ := range append(primitiveTypesUpper, "") {
for _, opt := range []string{"", "OmitEmpty", "StringTag"} {
for _, typ := range append(primitiveTypesUpper, "") {
escapedOrNot := escapedOrNot
opt := opt
typ := typ
opt := opt
typ := typ
op := fmt.Sprintf(
"Struct%sField%s%s",
escapedOrNot,
opt,
typ,
)
opTypes = append(opTypes, opType{
Op: op,
Code: "StructField",
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
Escaped: func() string {
switch typ {
case "String", "StringPtr", "StringNPtr":
return fmt.Sprintf(
"StructEscapedField%sEscaped%s",
opt,
typ,
)
}
return fmt.Sprintf(
"StructEscapedField%s%s",
opt,
typ,
)
},
HeadToPtrHead: func() string { return op },
HeadToNPtrHead: func() string { return op },
HeadToAnonymousHead: func() string { return op },
HeadToOmitEmptyHead: func() string { return op },
HeadToStringTagHead: func() string { return op },
PtrHeadToHead: func() string { return op },
FieldToEnd: func() string {
switch typ {
case "", "Array", "Map", "MapLoad", "Slice", "Struct", "Recursive":
return op
}
return fmt.Sprintf(
"Struct%sEnd%s%s",
escapedOrNot,
opt,
typ,
)
},
FieldToOmitEmptyField: func() string {
return fmt.Sprintf(
"Struct%sFieldOmitEmpty%s",
escapedOrNot,
typ,
)
},
FieldToStringTagField: func() string {
return fmt.Sprintf(
"Struct%sFieldStringTag%s",
escapedOrNot,
typ,
)
},
})
}
op := fmt.Sprintf(
"StructField%s%s",
opt,
typ,
)
opTypes = append(opTypes, opType{
Op: op,
Code: "StructField",
HeadToPtrHead: func() string { return op },
HeadToNPtrHead: func() string { return op },
HeadToAnonymousHead: func() string { return op },
HeadToOmitEmptyHead: func() string { return op },
HeadToStringTagHead: func() string { return op },
HeadToOnlyHead: func() string { return op },
PtrHeadToHead: func() string { return op },
FieldToEnd: func() string {
switch typ {
case "", "Array", "Map", "MapLoad", "Slice", "Struct", "Recursive":
return op
}
return fmt.Sprintf(
"StructEnd%s%s",
opt,
typ,
)
},
FieldToOmitEmptyField: func() string {
return fmt.Sprintf(
"StructFieldOmitEmpty%s",
typ,
)
},
FieldToStringTagField: func() string {
return fmt.Sprintf(
"StructFieldStringTag%s",
typ,
)
},
})
}
}
for _, escapedOrNot := range []string{"", "Escaped"} {
for _, typ := range append(primitiveTypesUpper, "") {
for _, opt := range []string{"", "OmitEmpty", "StringTag"} {
for _, typ := range append(primitiveTypesUpper, "") {
escapedOrNot := escapedOrNot
opt := opt
typ := typ
opt := opt
typ := typ
op := fmt.Sprintf(
"Struct%sEnd%s%s",
escapedOrNot,
opt,
typ,
)
opTypes = append(opTypes, opType{
Op: op,
Code: "StructEnd",
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
Escaped: func() string {
switch typ {
case "String", "StringPtr", "StringNPtr":
return fmt.Sprintf(
"StructEscapedEnd%sEscaped%s",
opt,
typ,
)
}
return fmt.Sprintf(
"StructEscapedEnd%s%s",
opt,
typ,
)
},
HeadToPtrHead: func() string { return op },
HeadToNPtrHead: func() string { return op },
HeadToAnonymousHead: func() string { return op },
HeadToOmitEmptyHead: func() string { return op },
HeadToStringTagHead: func() string { return op },
PtrHeadToHead: func() string { return op },
FieldToEnd: func() string { return op },
FieldToOmitEmptyField: func() string { return op },
FieldToStringTagField: func() string { return op },
})
}
op := fmt.Sprintf(
"StructEnd%s%s",
opt,
typ,
)
opTypes = append(opTypes, opType{
Op: op,
Code: "StructEnd",
HeadToPtrHead: func() string { return op },
HeadToNPtrHead: func() string { return op },
HeadToAnonymousHead: func() string { return op },
HeadToOmitEmptyHead: func() string { return op },
HeadToStringTagHead: func() string { return op },
HeadToOnlyHead: func() string { return op },
PtrHeadToHead: func() string { return op },
FieldToEnd: func() string { return op },
FieldToOmitEmptyField: func() string { return op },
FieldToStringTagField: func() string { return op },
})
}
}
indentOpTypes := []opType{}
for _, typ := range opTypes {
typ := typ
indentOpTypes = append(indentOpTypes, opType{
Op: fmt.Sprintf("%sIndent", typ.Op),
Code: typ.Code,
Indent: func() string { return fmt.Sprintf("%sIndent", typ.Op) },
Escaped: func() string { return fmt.Sprintf("%sIndent", typ.Escaped()) },
HeadToPtrHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToPtrHead())
},
HeadToNPtrHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToNPtrHead())
},
HeadToAnonymousHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToAnonymousHead())
},
HeadToOmitEmptyHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToOmitEmptyHead())
},
HeadToStringTagHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToStringTagHead())
},
PtrHeadToHead: func() string {
return fmt.Sprintf("%sIndent", typ.PtrHeadToHead())
},
FieldToOmitEmptyField: func() string {
return fmt.Sprintf("%sIndent", typ.FieldToOmitEmptyField())
},
FieldToStringTagField: func() string {
return fmt.Sprintf("%sIndent", typ.FieldToStringTagField())
},
FieldToEnd: func() string {
return fmt.Sprintf("%sIndent", typ.FieldToEnd())
},
})
}
var b bytes.Buffer
if err := tmpl.Execute(&b, struct {
CodeTypes []string
OpTypes []opType
OpNotIndentTypes []opType
OpLen int
OpIndentLen int
CodeTypes []string
OpTypes []opType
OpLen int
}{
CodeTypes: codeTypes,
OpTypes: append(opTypes, indentOpTypes...),
OpNotIndentTypes: opTypes,
OpLen: len(opTypes),
OpIndentLen: len(indentOpTypes),
CodeTypes: codeTypes,
OpTypes: opTypes,
OpLen: len(opTypes),
}); err != nil {
return err
}

12414
coverage_test.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -42,11 +42,8 @@ const (
)
type opcodeSet struct {
escapedCode *opcode
escapedCodeIndent *opcode
code *opcode
codeIndent *opcode
codeLength int
code *opcode
codeLength int
}
func loadOpcodeMap() map[uintptr]*opcodeSet {
@ -194,24 +191,21 @@ func (e *Encoder) encode(header *interfaceHeader, isNil bool) ([]byte, error) {
typeptr := uintptr(unsafe.Pointer(typ))
opcodeMap := loadOpcodeMap()
if codeSet, exists := opcodeMap[typeptr]; exists {
var code *opcode
if e.enabledIndent {
if e.enabledHTMLEscape {
code = codeSet.escapedCodeIndent
} else {
code = codeSet.codeIndent
}
} else {
if e.enabledHTMLEscape {
code = codeSet.escapedCode
} else {
code = codeSet.code
}
}
ctx := e.ctx
p := uintptr(header.ptr)
ctx.init(p, codeSet.codeLength)
return e.run(ctx, b, code)
if e.enabledIndent {
if e.enabledHTMLEscape {
return e.runEscapedIndent(ctx, b, codeSet.code)
} else {
return e.runIndent(ctx, b, codeSet.code)
}
}
if e.enabledHTMLEscape {
return e.runEscaped(ctx, b, codeSet.code)
}
return e.run(ctx, b, codeSet.code)
}
// noescape trick for header.typ ( reflect.*rtype )
@ -226,14 +220,10 @@ func (e *Encoder) encode(header *interfaceHeader, isNil bool) ([]byte, error) {
return nil, err
}
code = copyOpcode(code)
codeIndent := toIndent(code)
codeLength := code.totalLength()
codeSet := &opcodeSet{
escapedCode: toEscaped(code),
escapedCodeIndent: toEscaped(codeIndent),
code: code,
codeIndent: codeIndent,
codeLength: codeLength,
code: code,
codeLength: codeLength,
}
storeOpcodeSet(typeptr, codeSet, opcodeMap)
@ -241,26 +231,17 @@ func (e *Encoder) encode(header *interfaceHeader, isNil bool) ([]byte, error) {
ctx := e.ctx
ctx.init(p, codeLength)
var c *opcode
if e.enabledIndent {
if e.enabledHTMLEscape {
c = codeSet.escapedCodeIndent
return e.runEscapedIndent(ctx, b, codeSet.code)
} else {
c = codeSet.codeIndent
}
} else {
if e.enabledHTMLEscape {
c = codeSet.escapedCode
} else {
c = codeSet.code
return e.runIndent(ctx, b, codeSet.code)
}
}
b, err = e.run(ctx, b, c)
if err != nil {
return nil, err
if e.enabledHTMLEscape {
return e.runEscaped(ctx, b, codeSet.code)
}
return b, nil
return e.run(ctx, b, codeSet.code)
}
func encodeFloat32(b []byte, v float32) []byte {

View File

@ -32,6 +32,7 @@ func (e *Encoder) compileHead(ctx *encodeCompileContext) (*opcode, error) {
if err != nil {
return nil, err
}
e.convertHeadOnlyCode(code, isPtr)
e.optimizeStructEnd(code)
return code, nil
} else if isPtr && typ.Implements(marshalTextType) {
@ -43,6 +44,7 @@ func (e *Encoder) compileHead(ctx *encodeCompileContext) (*opcode, error) {
if err != nil {
return nil, err
}
e.convertHeadOnlyCode(code, isPtr)
e.optimizeStructEnd(code)
return code, nil
}
@ -88,6 +90,45 @@ func (e *Encoder) optimizeStructEnd(c *opcode) {
}
}
func (e *Encoder) convertHeadOnlyCode(c *opcode, isPtrHead bool) {
if c.nextField == nil {
return
}
if c.nextField.op.codeType() != codeStructEnd {
return
}
switch c.op {
case opStructFieldHead:
e.convertHeadOnlyCode(c.next, false)
if !strings.Contains(c.next.op.String(), "Only") {
return
}
c.op = opStructFieldHeadOnly
case opStructFieldHeadOmitEmpty:
return
case opStructFieldPtrHead:
}
if strings.Contains(c.op.String(), "Marshal") {
return
}
if strings.Contains(c.op.String(), "Slice") {
return
}
if strings.Contains(c.op.String(), "Map") {
return
}
isPtrOp := strings.Contains(c.op.String(), "Ptr")
if isPtrOp && !isPtrHead {
c.op = c.op.headToOnlyHead()
} else if !isPtrOp && isPtrHead {
c.op = c.op.headToPtrHead().headToOnlyHead()
} else if isPtrOp && isPtrHead {
c.op = c.op.headToPtrHead().headToOnlyHead()
}
}
func (e *Encoder) implementsMarshaler(typ *rtype) bool {
switch {
case typ.Implements(marshalJSONType):
@ -1102,17 +1143,6 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
anonymousFields[k] = append(anonymousFields[k], v...)
}
}
if fieldNum == 1 && valueCode.op == opPtr {
// if field number is one and primitive pointer type,
// it should encode as **not** pointer .
switch valueCode.next.op {
case opInt, opInt8, opInt16, opInt32, opInt64,
opUint, opUint8, opUint16, opUint32, opUint64,
opFloat32, opFloat64, opBool, opString, opBytes:
valueCode = valueCode.next
ctx.decOpcodeIndex()
}
}
key := fmt.Sprintf(`"%s":`, tag.key)
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))
fieldCode := &opcode{

View File

@ -53,34 +53,6 @@ func copyOpcode(code *opcode) *opcode {
return code.copy(codeMap)
}
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 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 {
return &opcode{
op: op,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

5700
encode_vm_escaped.go Normal file

File diff suppressed because it is too large Load Diff

4850
encode_vm_escaped_indent.go Normal file

File diff suppressed because it is too large Load Diff

4850
encode_vm_indent.go Normal file

File diff suppressed because it is too large Load Diff