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

View File

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

View File

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