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

@ -20,16 +20,22 @@ type opType struct {
type headType struct { type headType struct {
Head string Head string
PtrHead string PtrHead string
NPtrHead string
AnonymousHead string AnonymousHead string
AnonymousPtrHead string AnonymousPtrHead string
AnonymousNPtrHead string
OmitEmptyHead string OmitEmptyHead string
OmitEmptyPtrHead string OmitEmptyPtrHead string
OmitEmptyNPtrHead string
AnonymousOmitEmptyHead string AnonymousOmitEmptyHead string
AnonymousOmitEmptyPtrHead string AnonymousOmitEmptyPtrHead string
AnonymousOmitEmptyNPtrHead string
StringTagHead string StringTagHead string
StringTagPtrHead string StringTagPtrHead string
StringTagNPtrHead string
AnonymousStringTagHead string AnonymousStringTagHead string
AnonymousStringTagPtrHead 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",
} { } {
@ -301,48 +347,66 @@ func (t opType) fieldToStringTagField() opType {
base := headType{ base := headType{
Head: "StructFieldHead", Head: "StructFieldHead",
PtrHead: "StructFieldPtrHead", PtrHead: "StructFieldPtrHead",
NPtrHead: "StructFieldNPtrHead",
AnonymousHead: "StructFieldAnonymousHead", AnonymousHead: "StructFieldAnonymousHead",
AnonymousPtrHead: "StructFieldPtrAnonymousHead", AnonymousPtrHead: "StructFieldPtrAnonymousHead",
AnonymousNPtrHead: "StructFieldNPtrAnonymousHead",
OmitEmptyHead: "StructFieldHeadOmitEmpty", OmitEmptyHead: "StructFieldHeadOmitEmpty",
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty", OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
OmitEmptyNPtrHead: "StructFieldNPtrHeadOmitEmpty",
StringTagHead: "StructFieldHeadStringTag", StringTagHead: "StructFieldHeadStringTag",
StringTagPtrHead: "StructFieldPtrHeadStringTag", StringTagPtrHead: "StructFieldPtrHeadStringTag",
StringTagNPtrHead: "StructFieldNPtrHeadStringTag",
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty", AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty", AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
AnonymousOmitEmptyNPtrHead: "StructFieldNPtrAnonymousHeadOmitEmpty",
AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag", AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag",
AnonymousStringTagPtrHead: "StructFieldPtrAnonymousHeadStringTag", 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),
NPtrHead: fmt.Sprintf("%s%s", base.NPtrHead, prim),
AnonymousHead: fmt.Sprintf("%s%s", base.AnonymousHead, prim), AnonymousHead: fmt.Sprintf("%s%s", base.AnonymousHead, prim),
AnonymousPtrHead: fmt.Sprintf("%s%s", base.AnonymousPtrHead, 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), OmitEmptyHead: fmt.Sprintf("%s%s", base.OmitEmptyHead, prim),
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, 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), AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, 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), StringTagHead: fmt.Sprintf("%s%s", base.StringTagHead, prim),
StringTagPtrHead: fmt.Sprintf("%s%s", base.StringTagPtrHead, 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), AnonymousStringTagHead: fmt.Sprintf("%s%s", base.AnonymousStringTagHead, prim),
AnonymousStringTagPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagPtrHead, 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),
NPtrHead: fmt.Sprintf("%sIndent", typ.NPtrHead),
AnonymousHead: fmt.Sprintf("%sIndent", typ.AnonymousHead), AnonymousHead: fmt.Sprintf("%sIndent", typ.AnonymousHead),
AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead), AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead),
AnonymousNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousNPtrHead),
OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead), OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead),
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead), OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
OmitEmptyNPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyNPtrHead),
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead), AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead), AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
AnonymousOmitEmptyNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyNPtrHead),
StringTagHead: fmt.Sprintf("%sIndent", typ.StringTagHead), StringTagHead: fmt.Sprintf("%sIndent", typ.StringTagHead),
StringTagPtrHead: fmt.Sprintf("%sIndent", typ.StringTagPtrHead), StringTagPtrHead: fmt.Sprintf("%sIndent", typ.StringTagPtrHead),
StringTagNPtrHead: fmt.Sprintf("%sIndent", typ.StringTagNPtrHead),
AnonymousStringTagHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagHead), AnonymousStringTagHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagHead),
AnonymousStringTagPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagPtrHead), 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:
ptrNum := 1
ctx.decIndex()
c := code
for {
if code.next.op == opPtr {
ptrNum++
code = code.next
ctx.decIndex()
}
break
}
c.ptrNum = ptrNum
if ptrNum > 1 {
switch code.next.op { switch code.next.op {
case opInt: case opInt:
return opStructFieldPtrInt return opStructFieldIntNPtr
case opInt8: case opInt8:
return opStructFieldPtrInt8 return opStructFieldInt8NPtr
case opInt16: case opInt16:
return opStructFieldPtrInt16 return opStructFieldInt16NPtr
case opInt32: case opInt32:
return opStructFieldPtrInt32 return opStructFieldInt32NPtr
case opInt64: case opInt64:
return opStructFieldPtrInt64 return opStructFieldInt64NPtr
case opUint: case opUint:
return opStructFieldPtrUint return opStructFieldUintNPtr
case opUint8: case opUint8:
return opStructFieldPtrUint8 return opStructFieldUint8NPtr
case opUint16: case opUint16:
return opStructFieldPtrUint16 return opStructFieldUint16NPtr
case opUint32: case opUint32:
return opStructFieldPtrUint32 return opStructFieldUint32NPtr
case opUint64: case opUint64:
return opStructFieldPtrUint64 return opStructFieldUint64NPtr
case opFloat32: case opFloat32:
return opStructFieldPtrFloat32 return opStructFieldFloat32NPtr
case opFloat64: case opFloat64:
return opStructFieldPtrFloat64 return opStructFieldFloat64NPtr
case opString: case opString:
return opStructFieldPtrString return opStructFieldStringNPtr
case opBool: case opBool:
return opStructFieldPtrBool 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)