forked from mirror/go-json
work cover array
This commit is contained in:
parent
fbeb935655
commit
6a00602e6a
|
@ -238,7 +238,7 @@ func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes {
|
|||
codes.Last().Next = elemCode
|
||||
elemCode.Next = codes.First()
|
||||
elemCode.End = end
|
||||
return Opcodes{header}
|
||||
return append(append(Opcodes{header}, codes...), elemCode, end)
|
||||
}
|
||||
|
||||
type ArrayCode struct {
|
||||
|
@ -261,9 +261,9 @@ func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
|
|||
header := newArrayHeaderCode(ctx, alen)
|
||||
ctx.incIndex()
|
||||
|
||||
codes := c.value.ToOpcode(ctx)
|
||||
codes := c.value.ToOpcode(ctx.incIndent())
|
||||
|
||||
elemCode := newArrayElemCode(ctx.withType(c.typ.Elem()).incIndent(), header, alen, size)
|
||||
elemCode := newArrayElemCode(ctx.withType(elem), header, alen, size)
|
||||
ctx.incIndex()
|
||||
|
||||
end := newOpCode(ctx, OpArrayEnd)
|
||||
|
@ -274,7 +274,8 @@ func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
|
|||
codes.Last().Next = elemCode
|
||||
elemCode.Next = codes.First()
|
||||
elemCode.End = end
|
||||
return Opcodes{header}
|
||||
|
||||
return append(append(Opcodes{header}, codes...), elemCode, end)
|
||||
}
|
||||
|
||||
type MapCode struct {
|
||||
|
@ -318,7 +319,7 @@ func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
|
|||
header.End = end
|
||||
key.End = end
|
||||
value.End = end
|
||||
return Opcodes{header}
|
||||
return append(append(append(append(append(Opcodes{header}, keyCodes...), value), valueCodes...), key), end)
|
||||
}
|
||||
|
||||
type StructCode struct {
|
||||
|
@ -371,11 +372,21 @@ func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
|
|||
if isEndField {
|
||||
if len(codes) > 0 {
|
||||
codes.First().End = fieldCodes.Last()
|
||||
} else if field.isAnonymous {
|
||||
fieldCodes.First().End = fieldCodes.Last()
|
||||
//fieldCodes.First().Next.End = fieldCodes.Last()
|
||||
fieldCodes.First().Next.NextField = fieldCodes.Last()
|
||||
} else {
|
||||
fieldCodes.First().End = fieldCodes.Last()
|
||||
}
|
||||
}
|
||||
prevField = fieldCodes.First()
|
||||
if field.isAnonymous {
|
||||
// fieldCodes.First() is StructHead operation.
|
||||
// StructHead's next operation is truely head operation.
|
||||
prevField = fieldCodes.First().Next
|
||||
} else {
|
||||
prevField = fieldCodes.First()
|
||||
}
|
||||
codes = append(codes, fieldCodes...)
|
||||
}
|
||||
ctx = ctx.decIndent()
|
||||
|
@ -539,25 +550,10 @@ func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField
|
|||
} else {
|
||||
key = fmt.Sprintf(`"%s":`, c.key)
|
||||
}
|
||||
var flags OpFlags
|
||||
flags := c.flags()
|
||||
if c.isAnonymous {
|
||||
flags |= AnonymousKeyFlags
|
||||
}
|
||||
if c.isTaggedKey {
|
||||
flags |= IsTaggedKeyFlags
|
||||
}
|
||||
if c.isNilableType {
|
||||
flags |= IsNilableTypeFlags
|
||||
}
|
||||
if c.isNilCheck {
|
||||
flags |= NilCheckFlags
|
||||
}
|
||||
if c.isAddrForMarshaler {
|
||||
flags |= AddrForMarshalerFlags
|
||||
}
|
||||
if c.isNextOpPtrType {
|
||||
flags |= IsNextOpPtrTypeFlags
|
||||
}
|
||||
field := &Opcode{
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Flags: flags,
|
||||
|
@ -633,17 +629,8 @@ func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField
|
|||
return fieldCodes
|
||||
}
|
||||
|
||||
func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
|
||||
var key string
|
||||
if ctx.escapeKey {
|
||||
rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
|
||||
key = fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key)))
|
||||
} else {
|
||||
key = fmt.Sprintf(`"%s":`, c.key)
|
||||
}
|
||||
func (c *StructFieldCode) flags() OpFlags {
|
||||
var flags OpFlags
|
||||
flags |= AnonymousHeadFlags
|
||||
flags |= AnonymousKeyFlags
|
||||
if c.isTaggedKey {
|
||||
flags |= IsTaggedKeyFlags
|
||||
}
|
||||
|
@ -659,6 +646,20 @@ func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, i
|
|||
if c.isNextOpPtrType {
|
||||
flags |= IsNextOpPtrTypeFlags
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
|
||||
var key string
|
||||
if ctx.escapeKey {
|
||||
rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
|
||||
key = fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key)))
|
||||
} else {
|
||||
key = fmt.Sprintf(`"%s":`, c.key)
|
||||
}
|
||||
flags := c.flags()
|
||||
flags |= AnonymousHeadFlags
|
||||
flags |= AnonymousKeyFlags
|
||||
field := &Opcode{
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Flags: flags,
|
||||
|
|
|
@ -490,7 +490,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
|
|||
length = code.Length / uintptrSize
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
|
||||
`[%02d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
|
@ -502,7 +502,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
|
|||
|
||||
func (c *Opcode) dumpMapHead(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
||||
`[%02d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
|
@ -515,7 +515,7 @@ func (c *Opcode) dumpMapHead(code *Opcode) string {
|
|||
|
||||
func (c *Opcode) dumpMapEnd(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
|
||||
`[%02d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
|
@ -533,7 +533,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
|
|||
length = code.Length / uintptrSize
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
|
||||
`[%02d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
|
@ -546,7 +546,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
|
|||
|
||||
func (c *Opcode) dumpField(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][key:%s][offset:%d])`,
|
||||
`[%02d]%s%s ([idx:%d][key:%s][offset:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
|
@ -558,7 +558,7 @@ func (c *Opcode) dumpField(code *Opcode) string {
|
|||
|
||||
func (c *Opcode) dumpKey(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
||||
`[%02d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
|
@ -571,7 +571,7 @@ func (c *Opcode) dumpKey(code *Opcode) string {
|
|||
|
||||
func (c *Opcode) dumpValue(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%d]%s%s ([idx:%d][mapIter:%d])`,
|
||||
`[%02d]%s%s ([idx:%d][mapIter:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
|
@ -610,7 +610,7 @@ func (c *Opcode) Dump() string {
|
|||
code = code.Next
|
||||
default:
|
||||
codes = append(codes, fmt.Sprintf(
|
||||
"[%d]%s%s ([idx:%d])",
|
||||
"[%02d]%s%s ([idx:%d])",
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
@ -1840,19 +1841,21 @@ func TestCoverArray(t *testing.T) {
|
|||
for _, test := range tests {
|
||||
for _, indent := range []bool{true, false} {
|
||||
for _, htmlEscape := range []bool{true, false} {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
enc.SetEscapeHTML(htmlEscape)
|
||||
if indent {
|
||||
enc.SetIndent("", " ")
|
||||
}
|
||||
if err := enc.Encode(test.data); err != nil {
|
||||
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:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
|
||||
}
|
||||
t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
enc.SetEscapeHTML(htmlEscape)
|
||||
if indent {
|
||||
enc.SetIndent("", " ")
|
||||
}
|
||||
if err := enc.Encode(test.data); err != nil {
|
||||
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:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue