mirror of https://github.com/goccy/go-json.git
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
|
codes.Last().Next = elemCode
|
||||||
elemCode.Next = codes.First()
|
elemCode.Next = codes.First()
|
||||||
elemCode.End = end
|
elemCode.End = end
|
||||||
return Opcodes{header}
|
return append(append(Opcodes{header}, codes...), elemCode, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArrayCode struct {
|
type ArrayCode struct {
|
||||||
|
@ -261,9 +261,9 @@ func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
header := newArrayHeaderCode(ctx, alen)
|
header := newArrayHeaderCode(ctx, alen)
|
||||||
ctx.incIndex()
|
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()
|
ctx.incIndex()
|
||||||
|
|
||||||
end := newOpCode(ctx, OpArrayEnd)
|
end := newOpCode(ctx, OpArrayEnd)
|
||||||
|
@ -274,7 +274,8 @@ func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
codes.Last().Next = elemCode
|
codes.Last().Next = elemCode
|
||||||
elemCode.Next = codes.First()
|
elemCode.Next = codes.First()
|
||||||
elemCode.End = end
|
elemCode.End = end
|
||||||
return Opcodes{header}
|
|
||||||
|
return append(append(Opcodes{header}, codes...), elemCode, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MapCode struct {
|
type MapCode struct {
|
||||||
|
@ -318,7 +319,7 @@ func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
header.End = end
|
header.End = end
|
||||||
key.End = end
|
key.End = end
|
||||||
value.End = end
|
value.End = end
|
||||||
return Opcodes{header}
|
return append(append(append(append(append(Opcodes{header}, keyCodes...), value), valueCodes...), key), end)
|
||||||
}
|
}
|
||||||
|
|
||||||
type StructCode struct {
|
type StructCode struct {
|
||||||
|
@ -371,11 +372,21 @@ func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
if isEndField {
|
if isEndField {
|
||||||
if len(codes) > 0 {
|
if len(codes) > 0 {
|
||||||
codes.First().End = fieldCodes.Last()
|
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 {
|
} else {
|
||||||
fieldCodes.First().End = fieldCodes.Last()
|
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...)
|
codes = append(codes, fieldCodes...)
|
||||||
}
|
}
|
||||||
ctx = ctx.decIndent()
|
ctx = ctx.decIndent()
|
||||||
|
@ -539,25 +550,10 @@ func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField
|
||||||
} else {
|
} else {
|
||||||
key = fmt.Sprintf(`"%s":`, c.key)
|
key = fmt.Sprintf(`"%s":`, c.key)
|
||||||
}
|
}
|
||||||
var flags OpFlags
|
flags := c.flags()
|
||||||
if c.isAnonymous {
|
if c.isAnonymous {
|
||||||
flags |= AnonymousKeyFlags
|
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{
|
field := &Opcode{
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
Flags: flags,
|
Flags: flags,
|
||||||
|
@ -633,17 +629,8 @@ func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField
|
||||||
return fieldCodes
|
return fieldCodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
|
func (c *StructFieldCode) flags() OpFlags {
|
||||||
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)
|
|
||||||
}
|
|
||||||
var flags OpFlags
|
var flags OpFlags
|
||||||
flags |= AnonymousHeadFlags
|
|
||||||
flags |= AnonymousKeyFlags
|
|
||||||
if c.isTaggedKey {
|
if c.isTaggedKey {
|
||||||
flags |= IsTaggedKeyFlags
|
flags |= IsTaggedKeyFlags
|
||||||
}
|
}
|
||||||
|
@ -659,6 +646,20 @@ func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, i
|
||||||
if c.isNextOpPtrType {
|
if c.isNextOpPtrType {
|
||||||
flags |= IsNextOpPtrTypeFlags
|
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{
|
field := &Opcode{
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
Flags: flags,
|
Flags: flags,
|
||||||
|
|
|
@ -490,7 +490,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
|
||||||
length = code.Length / uintptrSize
|
length = code.Length / uintptrSize
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
|
`[%02d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -502,7 +502,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
|
||||||
|
|
||||||
func (c *Opcode) dumpMapHead(code *Opcode) string {
|
func (c *Opcode) dumpMapHead(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
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,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -515,7 +515,7 @@ func (c *Opcode) dumpMapHead(code *Opcode) string {
|
||||||
|
|
||||||
func (c *Opcode) dumpMapEnd(code *Opcode) string {
|
func (c *Opcode) dumpMapEnd(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
|
`[%02d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -533,7 +533,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
|
||||||
length = code.Length / uintptrSize
|
length = code.Length / uintptrSize
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(
|
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,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -546,7 +546,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
|
||||||
|
|
||||||
func (c *Opcode) dumpField(code *Opcode) string {
|
func (c *Opcode) dumpField(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][key:%s][offset:%d])`,
|
`[%02d]%s%s ([idx:%d][key:%s][offset:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -558,7 +558,7 @@ func (c *Opcode) dumpField(code *Opcode) string {
|
||||||
|
|
||||||
func (c *Opcode) dumpKey(code *Opcode) string {
|
func (c *Opcode) dumpKey(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
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,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -571,7 +571,7 @@ func (c *Opcode) dumpKey(code *Opcode) string {
|
||||||
|
|
||||||
func (c *Opcode) dumpValue(code *Opcode) string {
|
func (c *Opcode) dumpValue(code *Opcode) string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
`[%d]%s%s ([idx:%d][mapIter:%d])`,
|
`[%02d]%s%s ([idx:%d][mapIter:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -610,7 +610,7 @@ func (c *Opcode) Dump() string {
|
||||||
code = code.Next
|
code = code.Next
|
||||||
default:
|
default:
|
||||||
codes = append(codes, fmt.Sprintf(
|
codes = append(codes, fmt.Sprintf(
|
||||||
"[%d]%s%s ([idx:%d])",
|
"[%02d]%s%s ([idx:%d])",
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1840,19 +1841,21 @@ func TestCoverArray(t *testing.T) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
for _, indent := range []bool{true, false} {
|
for _, indent := range []bool{true, false} {
|
||||||
for _, htmlEscape := range []bool{true, false} {
|
for _, htmlEscape := range []bool{true, false} {
|
||||||
var buf bytes.Buffer
|
t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
|
||||||
enc := json.NewEncoder(&buf)
|
var buf bytes.Buffer
|
||||||
enc.SetEscapeHTML(htmlEscape)
|
enc := json.NewEncoder(&buf)
|
||||||
if indent {
|
enc.SetEscapeHTML(htmlEscape)
|
||||||
enc.SetIndent("", " ")
|
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)
|
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 {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
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())
|
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