work cover array

This commit is contained in:
Masaaki Goshima 2021-11-24 13:32:58 +09:00
parent fbeb935655
commit 6a00602e6a
No known key found for this signature in database
GPG Key ID: 6A53785055537153
3 changed files with 57 additions and 53 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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())
}
})
}
}
}