forked from mirror/go-json
Add InterfaceEnd operation
This commit is contained in:
parent
4f4060f808
commit
34b662b98e
|
@ -220,6 +220,7 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
opTypes := []opType{
|
opTypes := []opType{
|
||||||
{"End", "EndIndent", "Op"},
|
{"End", "EndIndent", "Op"},
|
||||||
{"Interface", "InterfaceIndent", "Op"},
|
{"Interface", "InterfaceIndent", "Op"},
|
||||||
|
{"InterfaceEnd", "InterfaceEndIndent", "Op"},
|
||||||
{"Ptr", "PtrIndent", "Op"},
|
{"Ptr", "PtrIndent", "Op"},
|
||||||
{"SliceHead", "SliceHeadIndent", "SliceHead"},
|
{"SliceHead", "SliceHeadIndent", "SliceHead"},
|
||||||
{"RootSliceHead", "RootSliceHeadIndent", "SliceHead"},
|
{"RootSliceHead", "RootSliceHeadIndent", "SliceHead"},
|
||||||
|
@ -252,6 +253,7 @@ func (t opType) fieldToStringTagField() opType {
|
||||||
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
|
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
|
||||||
{"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"},
|
{"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"},
|
||||||
{"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"},
|
{"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"},
|
||||||
|
{"StructFieldRecursiveEnd", "StructFieldRecursiveEndIndent", "Op"},
|
||||||
{"StructEnd", "StructEndIndent", "StructField"},
|
{"StructEnd", "StructEndIndent", "StructField"},
|
||||||
{"StructAnonymousEnd", "StructAnonymousEndIndent", "StructField"},
|
{"StructAnonymousEnd", "StructAnonymousEndIndent", "StructField"},
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,10 @@ func (c *opcode) beforeLastCode() *opcode {
|
||||||
func (c *opcode) totalLength() int {
|
func (c *opcode) totalLength() int {
|
||||||
var idx int
|
var idx int
|
||||||
for code := c; code.op != opEnd; {
|
for code := c; code.op != opEnd; {
|
||||||
idx = code.displayIdx
|
idx = int(code.idx / uintptrSize)
|
||||||
|
if code.op == opInterfaceEnd {
|
||||||
|
break
|
||||||
|
}
|
||||||
switch code.op.codeType() {
|
switch code.op.codeType() {
|
||||||
case codeArrayElem, codeSliceElem, codeMapKey:
|
case codeArrayElem, codeSliceElem, codeMapKey:
|
||||||
code = code.end
|
code = code.end
|
||||||
|
@ -88,7 +91,7 @@ func (c *opcode) totalLength() int {
|
||||||
code = code.next
|
code = code.next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return idx + 1
|
return idx + 2 // opEnd + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *opcode) decOpcodeIndex() {
|
func (c *opcode) decOpcodeIndex() {
|
||||||
|
@ -378,8 +381,8 @@ func newInterfaceCode(ctx *encodeCompileContext) *opcode {
|
||||||
displayIdx: ctx.opcodeIndex,
|
displayIdx: ctx.opcodeIndex,
|
||||||
idx: opcodeOffset(ctx.ptrIndex),
|
idx: opcodeOffset(ctx.ptrIndex),
|
||||||
indent: ctx.indent,
|
indent: ctx.indent,
|
||||||
next: newEndOp(ctx),
|
|
||||||
root: ctx.root,
|
root: ctx.root,
|
||||||
|
next: newEndOp(ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1576
encode_optype.go
1576
encode_optype.go
File diff suppressed because it is too large
Load Diff
41
encode_vm.go
41
encode_vm.go
|
@ -22,6 +22,7 @@ func store(base uintptr, idx uintptr, p uintptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map[uintptr]struct{}, code *opcode) error {
|
func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map[uintptr]struct{}, code *opcode) error {
|
||||||
|
ptrOffset := uintptr(0)
|
||||||
ctxptr := ctx.ptr()
|
ctxptr := ctx.ptr()
|
||||||
for {
|
for {
|
||||||
switch code.op {
|
switch code.op {
|
||||||
|
@ -142,13 +143,43 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, recursiveLevel int, seenPtr map
|
||||||
}
|
}
|
||||||
c = code
|
c = code
|
||||||
}
|
}
|
||||||
ctx := &encodeRuntimeContext{
|
|
||||||
ptrs: make([]uintptr, c.totalLength()),
|
beforeLastCode := c.beforeLastCode()
|
||||||
|
lastCode := beforeLastCode.next
|
||||||
|
lastCode.idx = beforeLastCode.idx + uintptrSize
|
||||||
|
totalLength := uintptr(code.totalLength())
|
||||||
|
nextTotalLength := uintptr(c.totalLength())
|
||||||
|
curlen := uintptr(len(ctx.ptrs))
|
||||||
|
offsetNum := ptrOffset / uintptrSize
|
||||||
|
oldOffset := ptrOffset
|
||||||
|
ptrOffset = ptrOffset + totalLength*uintptrSize // curlen * uintptrSize
|
||||||
}
|
}
|
||||||
ctx.init(uintptr(header.ptr))
|
newLen := offsetNum + totalLength + nextTotalLength
|
||||||
if err := e.run(ctx, recursiveLevel+1, seenPtr, c); err != nil {
|
if curlen < newLen {
|
||||||
return err
|
ctx.ptrs = append(ctx.ptrs, make([]uintptr, newLen-curlen)...)
|
||||||
|
store(ctx.ptr()+ptrOffset, 0, uintptr(header.ptr))
|
||||||
|
} else {
|
||||||
|
store(ctx.ptr()+ptrOffset, 0, uintptr(header.ptr))
|
||||||
}
|
}
|
||||||
|
ctxptr = ctx.ptr() + ptrOffset // assign new ctxptr
|
||||||
|
if load(ctxptr, 0) != uintptr(header.ptr) {
|
||||||
|
panic(nil)
|
||||||
|
}
|
||||||
|
// save current ctxptr
|
||||||
|
store(ctxptr, lastCode.idx, oldOffset)
|
||||||
|
|
||||||
|
// link lastCode ( opInterfaceEnd ) => code.next
|
||||||
|
lastCode.op = opInterfaceEnd
|
||||||
|
lastCode.next = code.next
|
||||||
|
|
||||||
|
code = c
|
||||||
|
recursiveLevel++
|
||||||
|
case opInterfaceEnd:
|
||||||
|
recursiveLevel--
|
||||||
|
// restore ctxptr
|
||||||
|
offset := load(ctxptr, code.idx)
|
||||||
|
ctxptr = ctx.ptr() + offset
|
||||||
|
ptrOffset = offset
|
||||||
code = code.next
|
code = code.next
|
||||||
case opMarshalJSON:
|
case opMarshalJSON:
|
||||||
ptr := load(ctxptr, code.idx)
|
ptr := load(ctxptr, code.idx)
|
||||||
|
|
Loading…
Reference in New Issue