mirror of https://github.com/goccy/go-json.git
Merge pull request #74 from goccy/feature/add-escaped-op
Optimize about HTML Escape processing
This commit is contained in:
commit
1d1572fb55
|
@ -13,35 +13,34 @@ import (
|
||||||
|
|
||||||
type opType struct {
|
type opType struct {
|
||||||
Op string
|
Op string
|
||||||
IndentOp string
|
|
||||||
Code string
|
Code string
|
||||||
|
Indent func() string
|
||||||
|
Escaped func() string
|
||||||
|
HeadToPtrHead func() string
|
||||||
|
HeadToNPtrHead func() string
|
||||||
|
HeadToAnonymousHead func() string
|
||||||
|
HeadToOmitEmptyHead func() string
|
||||||
|
HeadToStringTagHead func() string
|
||||||
|
PtrHeadToHead func() string
|
||||||
|
FieldToOmitEmptyField func() string
|
||||||
|
FieldToStringTagField func() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type headType struct {
|
func createOpType(op, code string) opType {
|
||||||
Head string
|
return opType{
|
||||||
PtrHead string
|
Op: op,
|
||||||
NPtrHead string
|
Code: code,
|
||||||
AnonymousHead string
|
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
|
||||||
AnonymousPtrHead string
|
Escaped: func() string { return op },
|
||||||
AnonymousNPtrHead string
|
HeadToPtrHead: func() string { return op },
|
||||||
OmitEmptyHead string
|
HeadToNPtrHead: func() string { return op },
|
||||||
OmitEmptyPtrHead string
|
HeadToAnonymousHead: func() string { return op },
|
||||||
OmitEmptyNPtrHead string
|
HeadToOmitEmptyHead: func() string { return op },
|
||||||
AnonymousOmitEmptyHead string
|
HeadToStringTagHead: func() string { return op },
|
||||||
AnonymousOmitEmptyPtrHead string
|
PtrHeadToHead: func() string { return op },
|
||||||
AnonymousOmitEmptyNPtrHead string
|
FieldToOmitEmptyField: func() string { return op },
|
||||||
StringTagHead string
|
FieldToStringTagField: func() string { return op },
|
||||||
StringTagPtrHead string
|
}
|
||||||
StringTagNPtrHead string
|
|
||||||
AnonymousStringTagHead string
|
|
||||||
AnonymousStringTagPtrHead string
|
|
||||||
AnonymousStringTagNPtrHead string
|
|
||||||
}
|
|
||||||
|
|
||||||
type fieldType struct {
|
|
||||||
Field string
|
|
||||||
OmitEmptyField string
|
|
||||||
StringTagField string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func _main() error {
|
func _main() error {
|
||||||
|
@ -88,7 +87,17 @@ func (t opType) toIndent() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .OpTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.Op }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.IndentOp }}
|
return op{{ call $type.Indent }}
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t opType) toEscaped() opType {
|
||||||
|
switch t {
|
||||||
|
{{- range $type := .OpTypes }}
|
||||||
|
case op{{ $type.Op }}:
|
||||||
|
return op{{ call $type.Escaped }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -96,19 +105,9 @@ func (t opType) toIndent() opType {
|
||||||
|
|
||||||
func (t opType) headToPtrHead() opType {
|
func (t opType) headToPtrHead() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .HeadTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.Head }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.PtrHead }}
|
return op{{ call $type.HeadToPtrHead }}
|
||||||
case op{{ $type.AnonymousHead }}:
|
|
||||||
return op{{ $type.AnonymousPtrHead }}
|
|
||||||
case op{{ $type.OmitEmptyHead }}:
|
|
||||||
return op{{ $type.OmitEmptyPtrHead }}
|
|
||||||
case op{{ $type.AnonymousOmitEmptyHead }}:
|
|
||||||
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
|
||||||
|
@ -116,19 +115,9 @@ func (t opType) headToPtrHead() opType {
|
||||||
|
|
||||||
func (t opType) headToNPtrHead() opType {
|
func (t opType) headToNPtrHead() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .HeadTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.Head }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.NPtrHead }}
|
return op{{ call $type.HeadToNPtrHead }}
|
||||||
case op{{ $type.AnonymousHead }}:
|
|
||||||
return op{{ $type.AnonymousNPtrHead }}
|
|
||||||
case op{{ $type.OmitEmptyHead }}:
|
|
||||||
return op{{ $type.OmitEmptyNPtrHead }}
|
|
||||||
case op{{ $type.AnonymousOmitEmptyHead }}:
|
|
||||||
return op{{ $type.AnonymousOmitEmptyNPtrHead }}
|
|
||||||
case op{{ $type.StringTagHead }}:
|
|
||||||
return op{{ $type.StringTagNPtrHead }}
|
|
||||||
case op{{ $type.AnonymousStringTagHead }}:
|
|
||||||
return op{{ $type.AnonymousStringTagNPtrHead }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -136,19 +125,9 @@ func (t opType) headToNPtrHead() opType {
|
||||||
|
|
||||||
func (t opType) headToAnonymousHead() opType {
|
func (t opType) headToAnonymousHead() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .HeadTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.Head }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.AnonymousHead }}
|
return op{{ call $type.HeadToAnonymousHead }}
|
||||||
case op{{ $type.PtrHead }}:
|
|
||||||
return op{{ $type.AnonymousPtrHead }}
|
|
||||||
case op{{ $type.OmitEmptyHead }}:
|
|
||||||
return op{{ $type.AnonymousOmitEmptyHead }}
|
|
||||||
case op{{ $type.OmitEmptyPtrHead }}:
|
|
||||||
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
|
||||||
|
@ -156,11 +135,9 @@ func (t opType) headToAnonymousHead() opType {
|
||||||
|
|
||||||
func (t opType) headToOmitEmptyHead() opType {
|
func (t opType) headToOmitEmptyHead() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .HeadTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.Head }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.OmitEmptyHead }}
|
return op{{ call $type.HeadToOmitEmptyHead }}
|
||||||
case op{{ $type.PtrHead }}:
|
|
||||||
return op{{ $type.OmitEmptyPtrHead }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -168,11 +145,9 @@ func (t opType) headToOmitEmptyHead() opType {
|
||||||
|
|
||||||
func (t opType) headToStringTagHead() opType {
|
func (t opType) headToStringTagHead() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .HeadTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.Head }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.StringTagHead }}
|
return op{{ call $type.HeadToStringTagHead }}
|
||||||
case op{{ $type.PtrHead }}:
|
|
||||||
return op{{ $type.StringTagPtrHead }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -180,19 +155,9 @@ func (t opType) headToStringTagHead() opType {
|
||||||
|
|
||||||
func (t opType) ptrHeadToHead() opType {
|
func (t opType) ptrHeadToHead() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .HeadTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.PtrHead }}, op{{ $type.NPtrHead }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.Head }}
|
return op{{ call $type.PtrHeadToHead }}
|
||||||
case op{{ $type.AnonymousPtrHead }}, op{{ $type.AnonymousNPtrHead }}:
|
|
||||||
return op{{ $type.AnonymousHead }}
|
|
||||||
case op{{ $type.OmitEmptyPtrHead }}, op{{ $type.OmitEmptyNPtrHead }}:
|
|
||||||
return op{{ $type.OmitEmptyHead }}
|
|
||||||
case op{{ $type.AnonymousOmitEmptyPtrHead }}, op{{ $type.AnonymousOmitEmptyNPtrHead }}:
|
|
||||||
return op{{ $type.AnonymousOmitEmptyHead }}
|
|
||||||
case op{{ $type.StringTagPtrHead }}, op{{ $type.StringTagNPtrHead }}:
|
|
||||||
return op{{ $type.StringTagHead }}
|
|
||||||
case op{{ $type.AnonymousStringTagPtrHead }}, op{{ $type.AnonymousStringTagNPtrHead }}:
|
|
||||||
return op{{ $type.AnonymousStringTagHead }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -200,9 +165,9 @@ func (t opType) ptrHeadToHead() opType {
|
||||||
|
|
||||||
func (t opType) fieldToOmitEmptyField() opType {
|
func (t opType) fieldToOmitEmptyField() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .FieldTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.Field }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.OmitEmptyField }}
|
return op{{ call $type.FieldToOmitEmptyField }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -210,9 +175,9 @@ func (t opType) fieldToOmitEmptyField() opType {
|
||||||
|
|
||||||
func (t opType) fieldToStringTagField() opType {
|
func (t opType) fieldToStringTagField() opType {
|
||||||
switch t {
|
switch t {
|
||||||
{{- range $type := .FieldTypes }}
|
{{- range $type := .OpTypes }}
|
||||||
case op{{ $type.Field }}:
|
case op{{ $type.Op }}:
|
||||||
return op{{ $type.StringTagField }}
|
return op{{ call $type.FieldToStringTagField }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
@ -238,210 +203,256 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
primitiveTypes := []string{
|
primitiveTypes := []string{
|
||||||
"int", "int8", "int16", "int32", "int64",
|
"int", "int8", "int16", "int32", "int64",
|
||||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
"float32", "float64", "bool", "string", "bytes",
|
"float32", "float64", "bool", "string", "escapedString", "bytes",
|
||||||
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive",
|
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive",
|
||||||
"intString", "int8String", "int16String", "int32String", "int64String",
|
"intString", "int8String", "int16String", "int32String", "int64String",
|
||||||
"uintString", "uint8String", "uint16String", "uint32String", "uint64String",
|
"uintString", "uint8String", "uint16String", "uint32String", "uint64String",
|
||||||
"intPtr", "int8Ptr", "int16Ptr", "int32Ptr", "int64Ptr",
|
"intPtr", "int8Ptr", "int16Ptr", "int32Ptr", "int64Ptr",
|
||||||
"uintPtr", "uint8Ptr", "uint16Ptr", "uint32Ptr", "uint64Ptr",
|
"uintPtr", "uint8Ptr", "uint16Ptr", "uint32Ptr", "uint64Ptr",
|
||||||
"float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "bytesPtr",
|
"float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "escapedStringPtr", "bytesPtr",
|
||||||
"intNPtr", "int8NPtr", "int16NPtr", "int32NPtr", "int64NPtr",
|
"intNPtr", "int8NPtr", "int16NPtr", "int32NPtr", "int64NPtr",
|
||||||
"uintNPtr", "uint8NPtr", "uint16NPtr", "uint32NPtr", "uint64NPtr",
|
"uintNPtr", "uint8NPtr", "uint16NPtr", "uint32NPtr", "uint64NPtr",
|
||||||
"float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "bytesNPtr",
|
"float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "escapedStringNPtr", "bytesNPtr",
|
||||||
}
|
}
|
||||||
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:])
|
||||||
}
|
}
|
||||||
opTypes := []opType{
|
opTypes := []opType{
|
||||||
{"End", "EndIndent", "Op"},
|
createOpType("End", "Op"),
|
||||||
{"Interface", "InterfaceIndent", "Op"},
|
createOpType("Interface", "Op"),
|
||||||
{"InterfaceEnd", "InterfaceEndIndent", "Op"},
|
createOpType("InterfaceEnd", "Op"),
|
||||||
{"Ptr", "PtrIndent", "Op"},
|
createOpType("Ptr", "Op"),
|
||||||
{"NPtr", "NPtrIndent", "Op"},
|
createOpType("NPtr", "Op"),
|
||||||
{"SliceHead", "SliceHeadIndent", "SliceHead"},
|
createOpType("SliceHead", "SliceHead"),
|
||||||
{"RootSliceHead", "RootSliceHeadIndent", "SliceHead"},
|
createOpType("RootSliceHead", "SliceHead"),
|
||||||
{"SliceElem", "SliceElemIndent", "SliceElem"},
|
createOpType("SliceElem", "SliceElem"),
|
||||||
{"RootSliceElem", "RootSliceElemIndent", "SliceElem"},
|
createOpType("RootSliceElem", "SliceElem"),
|
||||||
{"SliceEnd", "SliceEndIndent", "Op"},
|
createOpType("SliceEnd", "Op"),
|
||||||
{"ArrayHead", "ArrayHeadIndent", "ArrayHead"},
|
createOpType("ArrayHead", "ArrayHead"),
|
||||||
{"ArrayElem", "ArrayElemIndent", "ArrayElem"},
|
createOpType("ArrayElem", "ArrayElem"),
|
||||||
{"ArrayEnd", "ArrayEndIndent", "Op"},
|
createOpType("ArrayEnd", "Op"),
|
||||||
{"MapHead", "MapHeadIndent", "MapHead"},
|
createOpType("MapHead", "MapHead"),
|
||||||
{"MapHeadLoad", "MapHeadLoadIndent", "MapHead"},
|
createOpType("MapHeadLoad", "MapHead"),
|
||||||
{"MapKey", "MapKeyIndent", "MapKey"},
|
createOpType("MapKey", "MapKey"),
|
||||||
{"MapValue", "MapValueIndent", "MapValue"},
|
createOpType("MapValue", "MapValue"),
|
||||||
{"MapEnd", "MapEndIndent", "Op"},
|
createOpType("MapEnd", "Op"),
|
||||||
{"StructFieldHead", "StructFieldHeadIndent", "StructField"},
|
createOpType("StructFieldRecursiveEnd", "Op"),
|
||||||
{"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmptyIndent", "StructField"},
|
createOpType("StructEnd", "StructField"),
|
||||||
{"StructFieldHeadStringTag", "StructFieldHeadStringTagIndent", "StructField"},
|
createOpType("StructAnonymousEnd", "StructField"),
|
||||||
{"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"},
|
|
||||||
{"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"},
|
|
||||||
{"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"},
|
|
||||||
{"StructFieldNPtrAnonymousHeadOmitEmpty", "StructFieldNPtrAnonymousHeadOmitEmptyIndent", "StructField"},
|
|
||||||
{"StructFieldAnonymousHeadStringTag", "StructFieldAnonymousHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldPtrAnonymousHeadStringTag", "StructFieldPtrAnonymousHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldNPtrAnonymousHeadStringTag", "StructFieldNPtrAnonymousHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
|
|
||||||
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
|
|
||||||
{"StructFieldPtrHeadStringTag", "StructFieldPtrHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
|
|
||||||
{"StructFieldNPtrHead", "StructFieldNPtrHeadIndent", "StructField"},
|
|
||||||
{"StructFieldNPtrHeadOmitEmpty", "StructFieldNPtrHeadOmitEmptyIndent", "StructField"},
|
|
||||||
{"StructFieldNPtrHeadStringTag", "StructFieldNPtrHeadStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldNPtrAnonymousHead", "StructFieldNPtrAnonymousHeadIndent", "StructField"},
|
|
||||||
{"StructField", "StructFieldIndent", "StructField"},
|
|
||||||
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
|
|
||||||
{"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"},
|
|
||||||
{"StructFieldRecursiveEnd", "StructFieldRecursiveEndIndent", "Op"},
|
|
||||||
{"StructEnd", "StructEndIndent", "StructField"},
|
|
||||||
{"StructAnonymousEnd", "StructAnonymousEndIndent", "StructField"},
|
|
||||||
}
|
}
|
||||||
for _, typ := range primitiveTypesUpper {
|
for _, typ := range primitiveTypesUpper {
|
||||||
opTypes = append(opTypes, opType{
|
typ := typ
|
||||||
Op: typ,
|
optype := createOpType(typ, "Op")
|
||||||
IndentOp: fmt.Sprintf("%sIndent", typ),
|
switch typ {
|
||||||
Code: "Op",
|
case "String", "StringPtr", "StringNPtr":
|
||||||
})
|
optype.Escaped = func() string {
|
||||||
|
return fmt.Sprintf("Escaped%s", typ)
|
||||||
}
|
}
|
||||||
for _, prefix := range []string{
|
}
|
||||||
"StructFieldHead",
|
opTypes = append(opTypes, optype)
|
||||||
"StructFieldHeadOmitEmpty",
|
}
|
||||||
"StructFieldHeadStringTag",
|
for _, escapedOrNot := range []string{"", "Escaped"} {
|
||||||
"StructFieldAnonymousHead",
|
for _, ptrOrNot := range []string{"", "Ptr", "NPtr"} {
|
||||||
"StructFieldAnonymousHeadOmitEmpty",
|
for _, headType := range []string{"", "Anonymous"} {
|
||||||
"StructFieldAnonymousHeadStringTag",
|
for _, opt := range []string{"", "OmitEmpty", "StringTag"} {
|
||||||
"StructFieldPtrHead",
|
for _, typ := range append(primitiveTypesUpper, "") {
|
||||||
"StructFieldPtrHeadOmitEmpty",
|
escapedOrNot := escapedOrNot
|
||||||
"StructFieldPtrHeadStringTag",
|
ptrOrNot := ptrOrNot
|
||||||
"StructFieldPtrAnonymousHead",
|
headType := headType
|
||||||
"StructFieldPtrAnonymousHeadOmitEmpty",
|
opt := opt
|
||||||
"StructFieldPtrAnonymousHeadStringTag",
|
typ := typ
|
||||||
"StructFieldNPtrHead",
|
|
||||||
"StructFieldNPtrHeadOmitEmpty",
|
op := fmt.Sprintf(
|
||||||
"StructFieldNPtrHeadStringTag",
|
"Struct%sField%s%sHead%s%s",
|
||||||
"StructFieldNPtrAnonymousHead",
|
escapedOrNot,
|
||||||
"StructFieldNPtrAnonymousHeadOmitEmpty",
|
ptrOrNot,
|
||||||
"StructFieldNPtrAnonymousHeadStringTag",
|
headType,
|
||||||
"StructField",
|
opt,
|
||||||
//"StructFieldPtr",
|
typ,
|
||||||
//"StructFieldNPtr",
|
)
|
||||||
"StructFieldOmitEmpty",
|
|
||||||
"StructFieldStringTag",
|
|
||||||
} {
|
|
||||||
for _, typ := range primitiveTypesUpper {
|
|
||||||
opTypes = append(opTypes, opType{
|
opTypes = append(opTypes, opType{
|
||||||
Op: fmt.Sprintf("%s%s", prefix, typ),
|
Op: op,
|
||||||
IndentOp: fmt.Sprintf("%s%sIndent", prefix, typ),
|
|
||||||
Code: "StructField",
|
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,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
HeadToPtrHead: func() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Struct%sFieldPtr%sHead%s%s",
|
||||||
|
escapedOrNot,
|
||||||
|
headType,
|
||||||
|
opt,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
HeadToNPtrHead: func() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Struct%sFieldNPtr%sHead%s%s",
|
||||||
|
escapedOrNot,
|
||||||
|
headType,
|
||||||
|
opt,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
HeadToAnonymousHead: func() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Struct%sField%sAnonymousHead%s%s",
|
||||||
|
escapedOrNot,
|
||||||
|
ptrOrNot,
|
||||||
|
opt,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
HeadToOmitEmptyHead: func() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Struct%sField%s%sHeadOmitEmpty%s",
|
||||||
|
escapedOrNot,
|
||||||
|
ptrOrNot,
|
||||||
|
headType,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
HeadToStringTagHead: func() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Struct%sField%s%sHeadStringTag%s",
|
||||||
|
escapedOrNot,
|
||||||
|
ptrOrNot,
|
||||||
|
headType,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
PtrHeadToHead: func() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Struct%sField%sHead%s%s",
|
||||||
|
escapedOrNot,
|
||||||
|
headType,
|
||||||
|
opt,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
FieldToOmitEmptyField: func() string { return op },
|
||||||
|
FieldToStringTagField: func() string { return op },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, typ := range opTypes {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, escapedOrNot := range []string{"", "Escaped"} {
|
||||||
|
for _, opt := range []string{"", "OmitEmpty", "StringTag"} {
|
||||||
|
for _, typ := range append(primitiveTypesUpper, "") {
|
||||||
|
escapedOrNot := escapedOrNot
|
||||||
|
opt := opt
|
||||||
|
typ := typ
|
||||||
|
|
||||||
|
op := fmt.Sprintf(
|
||||||
|
"Struct%sField%s%s",
|
||||||
|
escapedOrNot,
|
||||||
|
opt,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
opTypes = append(opTypes, opType{
|
opTypes = append(opTypes, opType{
|
||||||
Op: typ.IndentOp,
|
Op: op,
|
||||||
IndentOp: typ.IndentOp,
|
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 },
|
||||||
|
FieldToOmitEmptyField: func() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Struct%sFieldOmitEmpty%s",
|
||||||
|
escapedOrNot,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
FieldToStringTagField: func() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Struct%sFieldStringTag%s",
|
||||||
|
escapedOrNot,
|
||||||
|
typ,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indentOpTypes := []opType{}
|
||||||
|
for _, typ := range opTypes {
|
||||||
|
typ := typ
|
||||||
|
indentOpTypes = append(indentOpTypes, opType{
|
||||||
|
Op: fmt.Sprintf("%sIndent", typ.Op),
|
||||||
Code: typ.Code,
|
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())
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
base := headType{
|
|
||||||
Head: "StructFieldHead",
|
|
||||||
PtrHead: "StructFieldPtrHead",
|
|
||||||
NPtrHead: "StructFieldNPtrHead",
|
|
||||||
AnonymousHead: "StructFieldAnonymousHead",
|
|
||||||
AnonymousPtrHead: "StructFieldPtrAnonymousHead",
|
|
||||||
AnonymousNPtrHead: "StructFieldNPtrAnonymousHead",
|
|
||||||
OmitEmptyHead: "StructFieldHeadOmitEmpty",
|
|
||||||
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
|
|
||||||
OmitEmptyNPtrHead: "StructFieldNPtrHeadOmitEmpty",
|
|
||||||
StringTagHead: "StructFieldHeadStringTag",
|
|
||||||
StringTagPtrHead: "StructFieldPtrHeadStringTag",
|
|
||||||
StringTagNPtrHead: "StructFieldNPtrHeadStringTag",
|
|
||||||
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
|
|
||||||
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
|
|
||||||
AnonymousOmitEmptyNPtrHead: "StructFieldNPtrAnonymousHeadOmitEmpty",
|
|
||||||
AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag",
|
|
||||||
AnonymousStringTagPtrHead: "StructFieldPtrAnonymousHeadStringTag",
|
|
||||||
AnonymousStringTagNPtrHead: "StructFieldNPtrAnonymousHeadStringTag",
|
|
||||||
}
|
|
||||||
headTypes := []headType{base}
|
|
||||||
for _, prim := range primitiveTypesUpper {
|
|
||||||
headTypes = append(headTypes, headType{
|
|
||||||
Head: fmt.Sprintf("%s%s", base.Head, prim),
|
|
||||||
PtrHead: fmt.Sprintf("%s%s", base.PtrHead, prim),
|
|
||||||
NPtrHead: fmt.Sprintf("%s%s", base.NPtrHead, prim),
|
|
||||||
AnonymousHead: fmt.Sprintf("%s%s", base.AnonymousHead, prim),
|
|
||||||
AnonymousPtrHead: fmt.Sprintf("%s%s", base.AnonymousPtrHead, prim),
|
|
||||||
AnonymousNPtrHead: fmt.Sprintf("%s%s", base.AnonymousNPtrHead, prim),
|
|
||||||
OmitEmptyHead: fmt.Sprintf("%s%s", base.OmitEmptyHead, prim),
|
|
||||||
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
|
|
||||||
OmitEmptyNPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyNPtrHead, prim),
|
|
||||||
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
|
|
||||||
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
|
|
||||||
AnonymousOmitEmptyNPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyNPtrHead, prim),
|
|
||||||
StringTagHead: fmt.Sprintf("%s%s", base.StringTagHead, prim),
|
|
||||||
StringTagPtrHead: fmt.Sprintf("%s%s", base.StringTagPtrHead, prim),
|
|
||||||
StringTagNPtrHead: fmt.Sprintf("%s%s", base.StringTagNPtrHead, prim),
|
|
||||||
AnonymousStringTagHead: fmt.Sprintf("%s%s", base.AnonymousStringTagHead, prim),
|
|
||||||
AnonymousStringTagPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagPtrHead, prim),
|
|
||||||
AnonymousStringTagNPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagNPtrHead, prim),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
for _, typ := range headTypes {
|
|
||||||
headTypes = append(headTypes, headType{
|
|
||||||
Head: fmt.Sprintf("%sIndent", typ.Head),
|
|
||||||
PtrHead: fmt.Sprintf("%sIndent", typ.PtrHead),
|
|
||||||
NPtrHead: fmt.Sprintf("%sIndent", typ.NPtrHead),
|
|
||||||
AnonymousHead: fmt.Sprintf("%sIndent", typ.AnonymousHead),
|
|
||||||
AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead),
|
|
||||||
AnonymousNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousNPtrHead),
|
|
||||||
OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead),
|
|
||||||
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
|
|
||||||
OmitEmptyNPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyNPtrHead),
|
|
||||||
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
|
|
||||||
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
|
|
||||||
AnonymousOmitEmptyNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyNPtrHead),
|
|
||||||
StringTagHead: fmt.Sprintf("%sIndent", typ.StringTagHead),
|
|
||||||
StringTagPtrHead: fmt.Sprintf("%sIndent", typ.StringTagPtrHead),
|
|
||||||
StringTagNPtrHead: fmt.Sprintf("%sIndent", typ.StringTagNPtrHead),
|
|
||||||
AnonymousStringTagHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagHead),
|
|
||||||
AnonymousStringTagPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagPtrHead),
|
|
||||||
AnonymousStringTagNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagNPtrHead),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
baseField := fieldType{
|
|
||||||
Field: "StructField",
|
|
||||||
OmitEmptyField: "StructFieldOmitEmpty",
|
|
||||||
StringTagField: "StructFieldStringTag",
|
|
||||||
}
|
|
||||||
fieldTypes := []fieldType{baseField}
|
|
||||||
for _, prim := range primitiveTypesUpper {
|
|
||||||
fieldTypes = append(fieldTypes, fieldType{
|
|
||||||
Field: fmt.Sprintf("%s%s", baseField.Field, prim),
|
|
||||||
OmitEmptyField: fmt.Sprintf("%s%s", baseField.OmitEmptyField, prim),
|
|
||||||
StringTagField: fmt.Sprintf("%s%s", baseField.StringTagField, prim),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
for _, typ := range fieldTypes {
|
|
||||||
fieldTypes = append(fieldTypes, fieldType{
|
|
||||||
Field: fmt.Sprintf("%sIndent", typ.Field),
|
|
||||||
OmitEmptyField: fmt.Sprintf("%sIndent", typ.OmitEmptyField),
|
|
||||||
StringTagField: fmt.Sprintf("%sIndent", typ.StringTagField),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := tmpl.Execute(&b, struct {
|
if err := tmpl.Execute(&b, struct {
|
||||||
CodeTypes []string
|
CodeTypes []string
|
||||||
OpTypes []opType
|
OpTypes []opType
|
||||||
HeadTypes []headType
|
|
||||||
FieldTypes []fieldType
|
|
||||||
}{
|
}{
|
||||||
CodeTypes: codeTypes,
|
CodeTypes: codeTypes,
|
||||||
OpTypes: opTypes,
|
OpTypes: append(opTypes, indentOpTypes...),
|
||||||
HeadTypes: headTypes,
|
|
||||||
FieldTypes: fieldTypes,
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
61
encode.go
61
encode.go
|
@ -34,9 +34,18 @@ const (
|
||||||
bufSize = 1024
|
bufSize = 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opCodeEscapedType = iota
|
||||||
|
opCodeEscapedIndentType
|
||||||
|
opCodeNoEscapeType
|
||||||
|
opCodeNoEscapeIndentType
|
||||||
|
)
|
||||||
|
|
||||||
type opcodeSet struct {
|
type opcodeSet struct {
|
||||||
codeIndent *opcode
|
escapedCode *opcode
|
||||||
|
escapedCodeIndent *opcode
|
||||||
code *opcode
|
code *opcode
|
||||||
|
codeIndent *opcode
|
||||||
codeLength int
|
codeLength int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,10 +196,18 @@ 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 {
|
||||||
|
if e.enabledHTMLEscape {
|
||||||
|
code = codeSet.escapedCodeIndent
|
||||||
|
} else {
|
||||||
code = codeSet.codeIndent
|
code = codeSet.codeIndent
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e.enabledHTMLEscape {
|
||||||
|
code = codeSet.escapedCode
|
||||||
} else {
|
} else {
|
||||||
code = codeSet.code
|
code = codeSet.code
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ctx := e.ctx
|
ctx := e.ctx
|
||||||
p := uintptr(header.ptr)
|
p := uintptr(header.ptr)
|
||||||
ctx.init(p, codeSet.codeLength)
|
ctx.init(p, codeSet.codeLength)
|
||||||
|
@ -200,30 +217,22 @@ 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,
|
escapedCode: toEscaped(code),
|
||||||
|
escapedCodeIndent: toEscaped(codeIndent),
|
||||||
code: code,
|
code: code,
|
||||||
|
codeIndent: codeIndent,
|
||||||
codeLength: codeLength,
|
codeLength: codeLength,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,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 {
|
} else {
|
||||||
c = code
|
c = codeSet.codeIndent
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if e.enabledHTMLEscape {
|
||||||
|
c = codeSet.escapedCode
|
||||||
|
} else {
|
||||||
|
c = codeSet.code
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err = e.run(ctx, b, c)
|
b, err = e.run(ctx, b, c)
|
||||||
|
@ -295,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, '"')
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -53,10 +53,35 @@ 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 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{
|
return &opcode{
|
||||||
op: op,
|
op: op,
|
||||||
typ: ctx.typ,
|
typ: ctx.typ,
|
||||||
|
|
135014
encode_optype.go
135014
encode_optype.go
File diff suppressed because it is too large
Load Diff
6164
encode_vm.go
6164
encode_vm.go
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue