forked from mirror/go-json
Remove only operation and add indirect property to opcode
This commit is contained in:
parent
40cc5ff367
commit
c6f40ed546
|
@ -163,7 +163,7 @@ func (t opType) headToPtrHead() opType {
|
|||
}
|
||||
suffix := "Ptr"+t.String()[idx+len("Field"):]
|
||||
|
||||
const toPtrOffset = 12
|
||||
const toPtrOffset = 6
|
||||
if strings.Contains(opType(int(t) + toPtrOffset).String(), suffix) {
|
||||
return opType(int(t) + toPtrOffset)
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ func (t opType) headToNPtrHead() opType {
|
|||
}
|
||||
suffix := "NPtr"+t.String()[idx+len("Field"):]
|
||||
|
||||
const toPtrOffset = 24
|
||||
const toPtrOffset = 12
|
||||
if strings.Contains(opType(int(t) + toPtrOffset).String(), suffix) {
|
||||
return opType(int(t) + toPtrOffset)
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ func (t opType) headToNPtrHead() opType {
|
|||
}
|
||||
|
||||
func (t opType) headToAnonymousHead() opType {
|
||||
const toAnonymousOffset = 6
|
||||
const toAnonymousOffset = 3
|
||||
if strings.Contains(opType(int(t) + toAnonymousOffset).String(), "Anonymous") {
|
||||
return opType(int(t) + toAnonymousOffset)
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func (t opType) headToAnonymousHead() opType {
|
|||
}
|
||||
|
||||
func (t opType) headToOmitEmptyHead() opType {
|
||||
const toOmitEmptyOffset = 2
|
||||
const toOmitEmptyOffset = 1
|
||||
if strings.Contains(opType(int(t) + toOmitEmptyOffset).String(), "OmitEmpty") {
|
||||
return opType(int(t) + toOmitEmptyOffset)
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ func (t opType) headToOmitEmptyHead() opType {
|
|||
}
|
||||
|
||||
func (t opType) headToStringTagHead() opType {
|
||||
const toStringTagOffset = 4
|
||||
const toStringTagOffset = 2
|
||||
if strings.Contains(opType(int(t) + toStringTagOffset).String(), "StringTag") {
|
||||
return opType(int(t) + toStringTagOffset)
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ func (t opType) ptrHeadToHead() opType {
|
|||
}
|
||||
suffix := t.String()[idx+len("Ptr"):]
|
||||
|
||||
const toPtrOffset = 12
|
||||
const toPtrOffset = 6
|
||||
if strings.Contains(opType(int(t) - toPtrOffset).String(), suffix) {
|
||||
return opType(int(t) - toPtrOffset)
|
||||
}
|
||||
|
|
|
@ -1774,11 +1774,11 @@ func TestCoverInt(t *testing.T) {
|
|||
enc.SetIndent("", " ")
|
||||
}
|
||||
if err := enc.Encode(test.data); err != nil {
|
||||
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
|
||||
}
|
||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||
if buf.String() != stdresult {
|
||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,7 +96,9 @@ func encodeCompileHead(ctx *encodeCompileContext) (*opcode, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encodeConvertHeadOnlyCode(code, isPtr)
|
||||
if !code.indirect && isPtr {
|
||||
code.indirect = true
|
||||
}
|
||||
encodeOptimizeStructEnd(code)
|
||||
encodeLinkRecursiveCode(code)
|
||||
return code, nil
|
||||
|
@ -105,11 +107,13 @@ func encodeCompileHead(ctx *encodeCompileContext) (*opcode, error) {
|
|||
} else if isPtr && typ.Implements(marshalJSONType) {
|
||||
typ = orgType
|
||||
}
|
||||
code, err := encodeCompile(ctx.withType(typ))
|
||||
code, err := encodeCompile(ctx.withType(typ), isPtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encodeConvertHeadOnlyCode(code, isPtr)
|
||||
if !code.indirect && isPtr {
|
||||
code.indirect = true
|
||||
}
|
||||
encodeOptimizeStructEnd(code)
|
||||
encodeLinkRecursiveCode(code)
|
||||
return code, nil
|
||||
|
@ -200,55 +204,6 @@ func encodeOptimizeStructEnd(c *opcode) {
|
|||
}
|
||||
}
|
||||
|
||||
func encodeConvertHeadOnlyCode(c *opcode, isPtrHead bool) {
|
||||
if c.nextField == nil {
|
||||
return
|
||||
}
|
||||
if c.nextField.op.codeType() != codeStructEnd {
|
||||
return
|
||||
}
|
||||
switch c.op {
|
||||
case opStructFieldHead:
|
||||
encodeConvertHeadOnlyCode(c.next, false)
|
||||
if !strings.Contains(c.next.op.String(), "Only") {
|
||||
return
|
||||
}
|
||||
c.op = opStructFieldHeadOnly
|
||||
case opStructFieldHeadOmitEmpty:
|
||||
encodeConvertHeadOnlyCode(c.next, false)
|
||||
if !strings.Contains(c.next.op.String(), "Only") {
|
||||
return
|
||||
}
|
||||
c.op = opStructFieldHeadOmitEmptyOnly
|
||||
case opStructFieldHeadStringTag:
|
||||
encodeConvertHeadOnlyCode(c.next, false)
|
||||
if !strings.Contains(c.next.op.String(), "Only") {
|
||||
return
|
||||
}
|
||||
c.op = opStructFieldHeadStringTagOnly
|
||||
case opStructFieldPtrHead:
|
||||
}
|
||||
|
||||
if strings.Contains(c.op.String(), "Marshal") {
|
||||
return
|
||||
}
|
||||
if strings.Contains(c.op.String(), "Slice") {
|
||||
return
|
||||
}
|
||||
if strings.Contains(c.op.String(), "Map") {
|
||||
return
|
||||
}
|
||||
|
||||
isPtrOp := strings.Contains(c.op.String(), "Ptr")
|
||||
if isPtrOp && !isPtrHead {
|
||||
c.op = c.op.headToOnlyHead()
|
||||
} else if !isPtrOp && isPtrHead {
|
||||
c.op = c.op.headToPtrHead().headToOnlyHead()
|
||||
} else if isPtrOp && isPtrHead {
|
||||
c.op = c.op.headToPtrHead().headToOnlyHead()
|
||||
}
|
||||
}
|
||||
|
||||
func encodeImplementsMarshaler(typ *rtype) bool {
|
||||
switch {
|
||||
case typ.Implements(marshalJSONType):
|
||||
|
@ -263,7 +218,7 @@ func encodeImplementsMarshaler(typ *rtype) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func encodeCompile(ctx *encodeCompileContext) (*opcode, error) {
|
||||
func encodeCompile(ctx *encodeCompileContext, isPtr bool) (*opcode, error) {
|
||||
typ := ctx.typ
|
||||
switch {
|
||||
case typ.Implements(marshalJSONType):
|
||||
|
@ -289,7 +244,7 @@ func encodeCompile(ctx *encodeCompileContext) (*opcode, error) {
|
|||
case reflect.Map:
|
||||
return encodeCompileMap(ctx, true)
|
||||
case reflect.Struct:
|
||||
return encodeCompileStruct(ctx, false)
|
||||
return encodeCompileStruct(ctx, isPtr)
|
||||
case reflect.Interface:
|
||||
return encodeCompileInterface(ctx)
|
||||
case reflect.Int:
|
||||
|
@ -371,7 +326,7 @@ func encodeCompilePtr(ctx *encodeCompileContext) (*opcode, error) {
|
|||
ptrOpcodeIndex := ctx.opcodeIndex
|
||||
ptrIndex := ctx.ptrIndex
|
||||
ctx.incIndex()
|
||||
code, err := encodeCompile(ctx.withType(ctx.typ.Elem()))
|
||||
code, err := encodeCompile(ctx.withType(ctx.typ.Elem()), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -642,7 +597,7 @@ func encodeCompileSlice(ctx *encodeCompileContext) (*opcode, error) {
|
|||
header := newSliceHeaderCode(ctx)
|
||||
ctx.incIndex()
|
||||
|
||||
code, err := encodeCompile(ctx.withType(ctx.typ.Elem()).incIndent())
|
||||
code, err := encodeCompile(ctx.withType(ctx.typ.Elem()).incIndent(), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -676,7 +631,7 @@ func encodeCompileArray(ctx *encodeCompileContext) (*opcode, error) {
|
|||
header := newArrayHeaderCode(ctx, alen)
|
||||
ctx.incIndex()
|
||||
|
||||
code, err := encodeCompile(ctx.withType(elem).incIndent())
|
||||
code, err := encodeCompile(ctx.withType(elem).incIndent(), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -734,7 +689,7 @@ func encodeCompileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, error)
|
|||
ctx.incIndex()
|
||||
|
||||
valueType := typ.Elem()
|
||||
valueCode, err := encodeCompile(ctx.withType(valueType))
|
||||
valueCode, err := encodeCompile(ctx.withType(valueType), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1227,6 +1182,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
|||
// ^ |
|
||||
// |__________|
|
||||
fieldNum := typ.NumField()
|
||||
indirect := ifaceIndir(typ)
|
||||
fieldIdx := 0
|
||||
var (
|
||||
head *opcode
|
||||
|
@ -1258,7 +1214,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
|||
fieldOpcodeIndex := ctx.opcodeIndex
|
||||
fieldPtrIndex := ctx.ptrIndex
|
||||
ctx.incIndex()
|
||||
valueCode, err := encodeCompile(ctx.withType(fieldType))
|
||||
valueCode, err := encodeCompile(ctx.withType(fieldType), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1280,6 +1236,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
|||
}
|
||||
key := fmt.Sprintf(`"%s":`, tag.key)
|
||||
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))
|
||||
valueCode.indirect = indirect
|
||||
fieldCode := &opcode{
|
||||
typ: valueCode.typ,
|
||||
displayIdx: fieldOpcodeIndex,
|
||||
|
@ -1292,6 +1249,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
|
|||
isTaggedKey: tag.isTaggedKey,
|
||||
displayKey: tag.key,
|
||||
offset: field.Offset,
|
||||
indirect: indirect,
|
||||
}
|
||||
if fieldIdx == 0 {
|
||||
fieldCode.headIdx = fieldCode.idx
|
||||
|
|
|
@ -19,11 +19,10 @@ type opcode struct {
|
|||
isTaggedKey bool // whether tagged key
|
||||
anonymousKey bool // whether anonymous key
|
||||
root bool // whether root
|
||||
indirect bool // whether indirect or not
|
||||
rshiftNum uint8 // use to take bit for judging whether negative integer or not
|
||||
mask uint64 // mask for number
|
||||
indent int // indent number
|
||||
rshiftNum uint8 // use to take bit for judging whether negative integer or not
|
||||
mask uint64 // mask for number
|
||||
|
||||
idx uintptr // offset to access ptr
|
||||
headIdx uintptr // offset to access slice/struct head
|
||||
|
@ -93,6 +92,7 @@ func (c *opcode) copy(codeMap map[uintptr]*opcode) *opcode {
|
|||
isTaggedKey: c.isTaggedKey,
|
||||
anonymousKey: c.anonymousKey,
|
||||
root: c.root,
|
||||
indirect: c.indirect,
|
||||
indent: c.indent,
|
||||
idx: c.idx,
|
||||
headIdx: c.headIdx,
|
||||
|
|
|
@ -1722,7 +1722,7 @@ func (t opType) headToPtrHead() opType {
|
|||
}
|
||||
suffix := "Ptr" + t.String()[idx+len("Field"):]
|
||||
|
||||
const toPtrOffset = 12
|
||||
const toPtrOffset = 6
|
||||
if strings.Contains(opType(int(t)+toPtrOffset).String(), suffix) {
|
||||
return opType(int(t) + toPtrOffset)
|
||||
}
|
||||
|
@ -1743,7 +1743,7 @@ func (t opType) headToNPtrHead() opType {
|
|||
}
|
||||
suffix := "NPtr" + t.String()[idx+len("Field"):]
|
||||
|
||||
const toPtrOffset = 24
|
||||
const toPtrOffset = 12
|
||||
if strings.Contains(opType(int(t)+toPtrOffset).String(), suffix) {
|
||||
return opType(int(t) + toPtrOffset)
|
||||
}
|
||||
|
@ -1751,7 +1751,7 @@ func (t opType) headToNPtrHead() opType {
|
|||
}
|
||||
|
||||
func (t opType) headToAnonymousHead() opType {
|
||||
const toAnonymousOffset = 6
|
||||
const toAnonymousOffset = 3
|
||||
if strings.Contains(opType(int(t)+toAnonymousOffset).String(), "Anonymous") {
|
||||
return opType(int(t) + toAnonymousOffset)
|
||||
}
|
||||
|
@ -1759,7 +1759,7 @@ func (t opType) headToAnonymousHead() opType {
|
|||
}
|
||||
|
||||
func (t opType) headToOmitEmptyHead() opType {
|
||||
const toOmitEmptyOffset = 2
|
||||
const toOmitEmptyOffset = 1
|
||||
if strings.Contains(opType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") {
|
||||
return opType(int(t) + toOmitEmptyOffset)
|
||||
}
|
||||
|
@ -1768,7 +1768,7 @@ func (t opType) headToOmitEmptyHead() opType {
|
|||
}
|
||||
|
||||
func (t opType) headToStringTagHead() opType {
|
||||
const toStringTagOffset = 4
|
||||
const toStringTagOffset = 2
|
||||
if strings.Contains(opType(int(t)+toStringTagOffset).String(), "StringTag") {
|
||||
return opType(int(t) + toStringTagOffset)
|
||||
}
|
||||
|
@ -1782,7 +1782,7 @@ func (t opType) ptrHeadToHead() opType {
|
|||
}
|
||||
suffix := t.String()[idx+len("Ptr"):]
|
||||
|
||||
const toPtrOffset = 12
|
||||
const toPtrOffset = 6
|
||||
if strings.Contains(opType(int(t)-toPtrOffset).String(), suffix) {
|
||||
return opType(int(t) - toPtrOffset)
|
||||
}
|
||||
|
|
1311
encode_vm.go
1311
encode_vm.go
File diff suppressed because it is too large
Load Diff
1297
encode_vm_escaped.go
1297
encode_vm_escaped.go
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1420
encode_vm_indent.go
1420
encode_vm_indent.go
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue