Support multiple pointer

This commit is contained in:
Masaaki Goshima 2020-12-23 13:13:34 +09:00
parent 7e55f41a59
commit 6c3382dc4e
5 changed files with 18356 additions and 2044 deletions

View File

@ -18,18 +18,24 @@ type opType struct {
} }
type headType struct { type headType struct {
Head string Head string
PtrHead string PtrHead string
AnonymousHead string NPtrHead string
AnonymousPtrHead string AnonymousHead string
OmitEmptyHead string AnonymousPtrHead string
OmitEmptyPtrHead string AnonymousNPtrHead string
AnonymousOmitEmptyHead string OmitEmptyHead string
AnonymousOmitEmptyPtrHead string OmitEmptyPtrHead string
StringTagHead string OmitEmptyNPtrHead string
StringTagPtrHead string AnonymousOmitEmptyHead string
AnonymousStringTagHead string AnonymousOmitEmptyPtrHead string
AnonymousStringTagPtrHead string AnonymousOmitEmptyNPtrHead string
StringTagHead string
StringTagPtrHead string
StringTagNPtrHead string
AnonymousStringTagHead string
AnonymousStringTagPtrHead string
AnonymousStringTagNPtrHead string
} }
type fieldType struct { type fieldType struct {
@ -108,6 +114,26 @@ func (t opType) headToPtrHead() opType {
return t return t
} }
func (t opType) headToNPtrHead() opType {
switch t {
{{- range $type := .HeadTypes }}
case op{{ $type.Head }}:
return op{{ $type.NPtrHead }}
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 }}
}
return t
}
func (t opType) headToAnonymousHead() opType { func (t opType) headToAnonymousHead() opType {
switch t { switch t {
{{- range $type := .HeadTypes }} {{- range $type := .HeadTypes }}
@ -155,17 +181,17 @@ func (t opType) headToStringTagHead() opType {
func (t opType) ptrHeadToHead() opType { func (t opType) ptrHeadToHead() opType {
switch t { switch t {
{{- range $type := .HeadTypes }} {{- range $type := .HeadTypes }}
case op{{ $type.PtrHead }}: case op{{ $type.PtrHead }}, op{{ $type.NPtrHead }}:
return op{{ $type.Head }} return op{{ $type.Head }}
case op{{ $type.AnonymousPtrHead }}: case op{{ $type.AnonymousPtrHead }}, op{{ $type.AnonymousNPtrHead }}:
return op{{ $type.AnonymousHead }} return op{{ $type.AnonymousHead }}
case op{{ $type.OmitEmptyPtrHead }}: case op{{ $type.OmitEmptyPtrHead }}, op{{ $type.OmitEmptyNPtrHead }}:
return op{{ $type.OmitEmptyHead }} return op{{ $type.OmitEmptyHead }}
case op{{ $type.AnonymousOmitEmptyPtrHead }}: case op{{ $type.AnonymousOmitEmptyPtrHead }}, op{{ $type.AnonymousOmitEmptyNPtrHead }}:
return op{{ $type.AnonymousOmitEmptyHead }} return op{{ $type.AnonymousOmitEmptyHead }}
case op{{ $type.StringTagPtrHead }}: case op{{ $type.StringTagPtrHead }}, op{{ $type.StringTagNPtrHead }}:
return op{{ $type.StringTagHead }} return op{{ $type.StringTagHead }}
case op{{ $type.AnonymousStringTagPtrHead }}: case op{{ $type.AnonymousStringTagPtrHead }}, op{{ $type.AnonymousStringTagNPtrHead }}:
return op{{ $type.AnonymousStringTagHead }} return op{{ $type.AnonymousStringTagHead }}
{{- end }} {{- end }}
} }
@ -216,6 +242,12 @@ func (t opType) fieldToStringTagField() opType {
"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",
"uintPtr", "uint8Ptr", "uint16Ptr", "uint32Ptr", "uint64Ptr",
"float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "bytesPtr",
"intNPtr", "int8NPtr", "int16NPtr", "int32NPtr", "int64NPtr",
"uintNPtr", "uint8NPtr", "uint16NPtr", "uint32NPtr", "uint64NPtr",
"float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "bytesNPtr",
} }
primitiveTypesUpper := []string{} primitiveTypesUpper := []string{}
for _, typ := range primitiveTypes { for _, typ := range primitiveTypes {
@ -226,6 +258,7 @@ func (t opType) fieldToStringTagField() opType {
{"Interface", "InterfaceIndent", "Op"}, {"Interface", "InterfaceIndent", "Op"},
{"InterfaceEnd", "InterfaceEndIndent", "Op"}, {"InterfaceEnd", "InterfaceEndIndent", "Op"},
{"Ptr", "PtrIndent", "Op"}, {"Ptr", "PtrIndent", "Op"},
{"NPtr", "NPtrIndent", "Op"},
{"SliceHead", "SliceHeadIndent", "SliceHead"}, {"SliceHead", "SliceHeadIndent", "SliceHead"},
{"RootSliceHead", "RootSliceHeadIndent", "SliceHead"}, {"RootSliceHead", "RootSliceHeadIndent", "SliceHead"},
{"SliceElem", "SliceElemIndent", "SliceElem"}, {"SliceElem", "SliceElemIndent", "SliceElem"},
@ -245,12 +278,18 @@ func (t opType) fieldToStringTagField() opType {
{"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"}, {"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"},
{"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"}, {"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"}, {"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldNPtrAnonymousHeadOmitEmpty", "StructFieldNPtrAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldAnonymousHeadStringTag", "StructFieldAnonymousHeadStringTagIndent", "StructField"}, {"StructFieldAnonymousHeadStringTag", "StructFieldAnonymousHeadStringTagIndent", "StructField"},
{"StructFieldPtrAnonymousHeadStringTag", "StructFieldPtrAnonymousHeadStringTagIndent", "StructField"}, {"StructFieldPtrAnonymousHeadStringTag", "StructFieldPtrAnonymousHeadStringTagIndent", "StructField"},
{"StructFieldNPtrAnonymousHeadStringTag", "StructFieldNPtrAnonymousHeadStringTagIndent", "StructField"},
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"}, {"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"}, {"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrHeadStringTag", "StructFieldPtrHeadStringTagIndent", "StructField"}, {"StructFieldPtrHeadStringTag", "StructFieldPtrHeadStringTagIndent", "StructField"},
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"}, {"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
{"StructFieldNPtrHead", "StructFieldNPtrHeadIndent", "StructField"},
{"StructFieldNPtrHeadOmitEmpty", "StructFieldNPtrHeadOmitEmptyIndent", "StructField"},
{"StructFieldNPtrHeadStringTag", "StructFieldNPtrHeadStringTagIndent", "StructField"},
{"StructFieldNPtrAnonymousHead", "StructFieldNPtrAnonymousHeadIndent", "StructField"},
{"StructField", "StructFieldIndent", "StructField"}, {"StructField", "StructFieldIndent", "StructField"},
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"}, {"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
{"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"}, {"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"},
@ -278,8 +317,15 @@ func (t opType) fieldToStringTagField() opType {
"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHead",
"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmpty",
"StructFieldPtrAnonymousHeadStringTag", "StructFieldPtrAnonymousHeadStringTag",
"StructFieldNPtrHead",
"StructFieldNPtrHeadOmitEmpty",
"StructFieldNPtrHeadStringTag",
"StructFieldNPtrAnonymousHead",
"StructFieldNPtrAnonymousHeadOmitEmpty",
"StructFieldNPtrAnonymousHeadStringTag",
"StructField", "StructField",
"StructFieldPtr", //"StructFieldPtr",
//"StructFieldNPtr",
"StructFieldOmitEmpty", "StructFieldOmitEmpty",
"StructFieldStringTag", "StructFieldStringTag",
} { } {
@ -299,50 +345,68 @@ func (t opType) fieldToStringTagField() opType {
}) })
} }
base := headType{ base := headType{
Head: "StructFieldHead", Head: "StructFieldHead",
PtrHead: "StructFieldPtrHead", PtrHead: "StructFieldPtrHead",
AnonymousHead: "StructFieldAnonymousHead", NPtrHead: "StructFieldNPtrHead",
AnonymousPtrHead: "StructFieldPtrAnonymousHead", AnonymousHead: "StructFieldAnonymousHead",
OmitEmptyHead: "StructFieldHeadOmitEmpty", AnonymousPtrHead: "StructFieldPtrAnonymousHead",
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty", AnonymousNPtrHead: "StructFieldNPtrAnonymousHead",
StringTagHead: "StructFieldHeadStringTag", OmitEmptyHead: "StructFieldHeadOmitEmpty",
StringTagPtrHead: "StructFieldPtrHeadStringTag", OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty", OmitEmptyNPtrHead: "StructFieldNPtrHeadOmitEmpty",
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty", StringTagHead: "StructFieldHeadStringTag",
AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag", StringTagPtrHead: "StructFieldPtrHeadStringTag",
AnonymousStringTagPtrHead: "StructFieldPtrAnonymousHeadStringTag", StringTagNPtrHead: "StructFieldNPtrHeadStringTag",
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
AnonymousOmitEmptyNPtrHead: "StructFieldNPtrAnonymousHeadOmitEmpty",
AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag",
AnonymousStringTagPtrHead: "StructFieldPtrAnonymousHeadStringTag",
AnonymousStringTagNPtrHead: "StructFieldNPtrAnonymousHeadStringTag",
} }
headTypes := []headType{base} headTypes := []headType{base}
for _, prim := range primitiveTypesUpper { for _, prim := range primitiveTypesUpper {
headTypes = append(headTypes, headType{ headTypes = append(headTypes, headType{
Head: fmt.Sprintf("%s%s", base.Head, prim), Head: fmt.Sprintf("%s%s", base.Head, prim),
PtrHead: fmt.Sprintf("%s%s", base.PtrHead, prim), PtrHead: fmt.Sprintf("%s%s", base.PtrHead, prim),
AnonymousHead: fmt.Sprintf("%s%s", base.AnonymousHead, prim), NPtrHead: fmt.Sprintf("%s%s", base.NPtrHead, prim),
AnonymousPtrHead: fmt.Sprintf("%s%s", base.AnonymousPtrHead, prim), AnonymousHead: fmt.Sprintf("%s%s", base.AnonymousHead, prim),
OmitEmptyHead: fmt.Sprintf("%s%s", base.OmitEmptyHead, prim), AnonymousPtrHead: fmt.Sprintf("%s%s", base.AnonymousPtrHead, prim),
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim), AnonymousNPtrHead: fmt.Sprintf("%s%s", base.AnonymousNPtrHead, prim),
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim), OmitEmptyHead: fmt.Sprintf("%s%s", base.OmitEmptyHead, prim),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim), OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
StringTagHead: fmt.Sprintf("%s%s", base.StringTagHead, prim), OmitEmptyNPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyNPtrHead, prim),
StringTagPtrHead: fmt.Sprintf("%s%s", base.StringTagPtrHead, prim), AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
AnonymousStringTagHead: fmt.Sprintf("%s%s", base.AnonymousStringTagHead, prim), AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
AnonymousStringTagPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagPtrHead, 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 { for _, typ := range headTypes {
headTypes = append(headTypes, headType{ headTypes = append(headTypes, headType{
Head: fmt.Sprintf("%sIndent", typ.Head), Head: fmt.Sprintf("%sIndent", typ.Head),
PtrHead: fmt.Sprintf("%sIndent", typ.PtrHead), PtrHead: fmt.Sprintf("%sIndent", typ.PtrHead),
AnonymousHead: fmt.Sprintf("%sIndent", typ.AnonymousHead), NPtrHead: fmt.Sprintf("%sIndent", typ.NPtrHead),
AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead), AnonymousHead: fmt.Sprintf("%sIndent", typ.AnonymousHead),
OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead), AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead),
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead), AnonymousNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousNPtrHead),
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead), OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead), OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
StringTagHead: fmt.Sprintf("%sIndent", typ.StringTagHead), OmitEmptyNPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyNPtrHead),
StringTagPtrHead: fmt.Sprintf("%sIndent", typ.StringTagPtrHead), AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
AnonymousStringTagHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagHead), AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
AnonymousStringTagPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagPtrHead), 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),
}) })
} }

View File

@ -508,8 +508,84 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode,
return (*opcode)(unsafe.Pointer(header)), nil return (*opcode)(unsafe.Pointer(header)), nil
} }
func (e *Encoder) typeToHeaderType(op opType) opType { func (e *Encoder) typeToHeaderType(ctx *encodeCompileContext, code *opcode) opType {
switch op { switch code.op {
case opPtr:
ptrNum := 1
c := code
ctx.decIndex()
for {
if code.next.op == opPtr {
ptrNum++
code = code.next
ctx.decIndex()
}
break
}
c.ptrNum = ptrNum
if ptrNum > 1 {
switch code.next.op {
case opInt:
return opStructFieldHeadIntNPtr
case opInt8:
return opStructFieldHeadInt8NPtr
case opInt16:
return opStructFieldHeadInt16NPtr
case opInt32:
return opStructFieldHeadInt32NPtr
case opInt64:
return opStructFieldHeadInt64NPtr
case opUint:
return opStructFieldHeadUintNPtr
case opUint8:
return opStructFieldHeadUint8NPtr
case opUint16:
return opStructFieldHeadUint16NPtr
case opUint32:
return opStructFieldHeadUint32NPtr
case opUint64:
return opStructFieldHeadUint64NPtr
case opFloat32:
return opStructFieldHeadFloat32NPtr
case opFloat64:
return opStructFieldHeadFloat64NPtr
case opString:
return opStructFieldHeadStringNPtr
case opBool:
return opStructFieldHeadBoolNPtr
}
} else {
switch code.next.op {
case opInt:
return opStructFieldHeadIntPtr
case opInt8:
return opStructFieldHeadInt8Ptr
case opInt16:
return opStructFieldHeadInt16Ptr
case opInt32:
return opStructFieldHeadInt32Ptr
case opInt64:
return opStructFieldHeadInt64Ptr
case opUint:
return opStructFieldHeadUintPtr
case opUint8:
return opStructFieldHeadUint8Ptr
case opUint16:
return opStructFieldHeadUint16Ptr
case opUint32:
return opStructFieldHeadUint32Ptr
case opUint64:
return opStructFieldHeadUint64Ptr
case opFloat32:
return opStructFieldHeadFloat32Ptr
case opFloat64:
return opStructFieldHeadFloat64Ptr
case opString:
return opStructFieldHeadStringPtr
case opBool:
return opStructFieldHeadBoolPtr
}
}
case opInt: case opInt:
return opStructFieldHeadInt return opStructFieldHeadInt
case opIntIndent: case opIntIndent:
@ -598,38 +674,83 @@ func (e *Encoder) typeToHeaderType(op opType) opType {
return opStructFieldHead return opStructFieldHead
} }
func (e *Encoder) typeToFieldType(code *opcode) opType { func (e *Encoder) typeToFieldType(ctx *encodeCompileContext, code *opcode) opType {
switch code.op { switch code.op {
case opPtr: case opPtr:
switch code.next.op { ptrNum := 1
case opInt: ctx.decIndex()
return opStructFieldPtrInt c := code
case opInt8: for {
return opStructFieldPtrInt8 if code.next.op == opPtr {
case opInt16: ptrNum++
return opStructFieldPtrInt16 code = code.next
case opInt32: ctx.decIndex()
return opStructFieldPtrInt32 }
case opInt64: break
return opStructFieldPtrInt64 }
case opUint: c.ptrNum = ptrNum
return opStructFieldPtrUint if ptrNum > 1 {
case opUint8: switch code.next.op {
return opStructFieldPtrUint8 case opInt:
case opUint16: return opStructFieldIntNPtr
return opStructFieldPtrUint16 case opInt8:
case opUint32: return opStructFieldInt8NPtr
return opStructFieldPtrUint32 case opInt16:
case opUint64: return opStructFieldInt16NPtr
return opStructFieldPtrUint64 case opInt32:
case opFloat32: return opStructFieldInt32NPtr
return opStructFieldPtrFloat32 case opInt64:
case opFloat64: return opStructFieldInt64NPtr
return opStructFieldPtrFloat64 case opUint:
case opString: return opStructFieldUintNPtr
return opStructFieldPtrString case opUint8:
case opBool: return opStructFieldUint8NPtr
return opStructFieldPtrBool case opUint16:
return opStructFieldUint16NPtr
case opUint32:
return opStructFieldUint32NPtr
case opUint64:
return opStructFieldUint64NPtr
case opFloat32:
return opStructFieldFloat32NPtr
case opFloat64:
return opStructFieldFloat64NPtr
case opString:
return opStructFieldStringNPtr
case opBool:
return opStructFieldBoolNPtr
}
} else {
switch code.next.op {
case opInt:
return opStructFieldIntPtr
case opInt8:
return opStructFieldInt8Ptr
case opInt16:
return opStructFieldInt16Ptr
case opInt32:
return opStructFieldInt32Ptr
case opInt64:
return opStructFieldInt64Ptr
case opUint:
return opStructFieldUintPtr
case opUint8:
return opStructFieldUint8Ptr
case opUint16:
return opStructFieldUint16Ptr
case opUint32:
return opStructFieldUint32Ptr
case opUint64:
return opStructFieldUint64Ptr
case opFloat32:
return opStructFieldFloat32Ptr
case opFloat64:
return opStructFieldFloat64Ptr
case opString:
return opStructFieldStringPtr
case opBool:
return opStructFieldBoolPtr
}
} }
case opInt: case opInt:
return opStructFieldInt return opStructFieldInt
@ -719,8 +840,8 @@ func (e *Encoder) typeToFieldType(code *opcode) opType {
return opStructField return opStructField
} }
func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent bool) opType { func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode, tag *structTag, withIndent bool) opType {
headType := e.typeToHeaderType(op) headType := e.typeToHeaderType(ctx, code)
switch { switch {
case tag.isOmitEmpty: case tag.isOmitEmpty:
headType = headType.headToOmitEmptyHead() headType = headType.headToOmitEmptyHead()
@ -733,8 +854,8 @@ func (e *Encoder) optimizeStructHeader(op opType, tag *structTag, withIndent boo
return headType return headType
} }
func (e *Encoder) optimizeStructField(code *opcode, tag *structTag, withIndent bool) opType { func (e *Encoder) optimizeStructField(ctx *encodeCompileContext, code *opcode, tag *structTag, withIndent bool) opType {
fieldType := e.typeToFieldType(code) fieldType := e.typeToFieldType(ctx, code)
switch { switch {
case tag.isOmitEmpty: case tag.isOmitEmpty:
fieldType = fieldType.fieldToOmitEmptyField() fieldType = fieldType.fieldToOmitEmptyField()
@ -770,8 +891,9 @@ 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(valueCode.op, tag, ctx.withIndent) op := e.optimizeStructHeader(ctx, valueCode, tag, ctx.withIndent)
fieldCode.op = op fieldCode.op = op
fieldCode.ptrNum = valueCode.ptrNum
switch op { switch op {
case opStructFieldHead, case opStructFieldHead,
opStructFieldHeadSlice, opStructFieldHeadSlice,
@ -807,8 +929,9 @@ 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(valueCode, tag, ctx.withIndent) op := e.optimizeStructField(ctx, valueCode, tag, ctx.withIndent)
fieldCode.op = op fieldCode.op = op
fieldCode.ptrNum = valueCode.ptrNum
switch op { switch op {
case opStructField, case opStructField,
opStructFieldSlice, opStructFieldSlice,

View File

@ -14,6 +14,7 @@ type opcode struct {
displayIdx int // opcode index displayIdx int // opcode index
key []byte // struct field key key []byte // struct field key
escapedKey []byte // struct field key ( HTML escaped ) escapedKey []byte // struct field key ( HTML escaped )
ptrNum int // pointer number: e.g. double pointer is 2.
displayKey string // key text to display displayKey string // key text to display
isTaggedKey bool // whether tagged key isTaggedKey bool // whether tagged key
anonymousKey bool // whether anonymous key anonymousKey bool // whether anonymous key
@ -85,6 +86,7 @@ func (c *opcode) copy(codeMap map[uintptr]*opcode) *opcode {
key: c.key, key: c.key,
escapedKey: c.escapedKey, escapedKey: c.escapedKey,
displayKey: c.displayKey, displayKey: c.displayKey,
ptrNum: c.ptrNum,
isTaggedKey: c.isTaggedKey, isTaggedKey: c.isTaggedKey,
anonymousKey: c.anonymousKey, anonymousKey: c.anonymousKey,
root: c.root, root: c.root,

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
var seenPtr map[uintptr]struct{} var seenPtr map[uintptr]struct{}
ptrOffset := uintptr(0) ptrOffset := uintptr(0)
ctxptr := ctx.ptr() ctxptr := ctx.ptr()
for { for {
switch code.op { switch code.op {
default: default:
@ -1169,6 +1168,43 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
} }
case opStructFieldHeadIntPtr:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
} else {
b = append(b, '{')
b = e.encodeKey(b, code)
p = e.ptrToPtr(p)
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
}
}
b = encodeComma(b)
code = code.next
case opStructFieldHeadIntNPtr:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
} else {
b = append(b, '{')
b = e.encodeKey(b, code)
for i := 0; i < code.ptrNum; i++ {
if p == 0 {
break
}
p = e.ptrToPtr(p)
}
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
}
}
b = encodeComma(b)
code = code.next
case opStructFieldPtrAnonymousHeadInt: case opStructFieldPtrAnonymousHeadInt:
store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx)))
fallthrough fallthrough
@ -4738,7 +4774,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
ptr := load(ctxptr, code.headIdx) + code.offset ptr := load(ctxptr, code.headIdx) + code.offset
code = code.next code = code.next
store(ctxptr, code.idx, ptr) store(ctxptr, code.idx, ptr)
case opStructFieldPtrInt: case opStructFieldIntPtr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4749,13 +4785,30 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
} }
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldIntNPtr:
b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset)
for i := 0; i < code.ptrNum-1; i++ {
if p == 0 {
break
}
p = e.ptrToPtr(p)
}
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt(p)))
}
b = encodeComma(b)
code = code.next
case opStructFieldInt: case opStructFieldInt:
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) b = appendInt(b, int64(e.ptrToInt(ptr+code.offset)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrInt8: case opStructFieldInt8Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4772,7 +4825,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendInt(b, int64(e.ptrToInt8(ptr+code.offset))) b = appendInt(b, int64(e.ptrToInt8(ptr+code.offset)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrInt16: case opStructFieldInt16Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4789,7 +4842,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendInt(b, int64(e.ptrToInt16(ptr+code.offset))) b = appendInt(b, int64(e.ptrToInt16(ptr+code.offset)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrInt32: case opStructFieldInt32Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4806,7 +4859,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendInt(b, int64(e.ptrToInt32(ptr+code.offset))) b = appendInt(b, int64(e.ptrToInt32(ptr+code.offset)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrInt64: case opStructFieldInt64Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4823,7 +4876,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendInt(b, e.ptrToInt64(ptr+code.offset)) b = appendInt(b, e.ptrToInt64(ptr+code.offset))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrUint: case opStructFieldUintPtr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4840,7 +4893,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendUint(b, uint64(e.ptrToUint(ptr+code.offset))) b = appendUint(b, uint64(e.ptrToUint(ptr+code.offset)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrUint8: case opStructFieldUint8Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4857,7 +4910,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendUint(b, uint64(e.ptrToUint8(ptr+code.offset))) b = appendUint(b, uint64(e.ptrToUint8(ptr+code.offset)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrUint16: case opStructFieldUint16Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4874,7 +4927,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendUint(b, uint64(e.ptrToUint16(ptr+code.offset))) b = appendUint(b, uint64(e.ptrToUint16(ptr+code.offset)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrUint32: case opStructFieldUint32Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4891,7 +4944,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendUint(b, uint64(e.ptrToUint32(ptr+code.offset))) b = appendUint(b, uint64(e.ptrToUint32(ptr+code.offset)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrUint64: case opStructFieldUint64Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4908,7 +4961,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = appendUint(b, e.ptrToUint64(ptr+code.offset)) b = appendUint(b, e.ptrToUint64(ptr+code.offset))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrFloat32: case opStructFieldFloat32Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4925,7 +4978,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeFloat32(b, e.ptrToFloat32(ptr+code.offset)) b = encodeFloat32(b, e.ptrToFloat32(ptr+code.offset))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrFloat64: case opStructFieldFloat64Ptr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4952,7 +5005,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeFloat64(b, v) b = encodeFloat64(b, v)
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrString: case opStructFieldStringPtr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)
@ -4969,7 +5022,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = e.encodeString(b, e.ptrToString(ptr+code.offset)) b = e.encodeString(b, e.ptrToString(ptr+code.offset))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrBool: case opStructFieldBoolPtr:
b = e.encodeKey(b, code) b = e.encodeKey(b, code)
ptr := load(ctxptr, code.headIdx) ptr := load(ctxptr, code.headIdx)
p := e.ptrToPtr(ptr + code.offset) p := e.ptrToPtr(ptr + code.offset)