mirror of https://github.com/goccy/go-json.git
Merge pull request #301 from goccy/feature/encode-compiler-v2
Refactor compiler for encoder
This commit is contained in:
commit
fa6c96f02c
|
@ -201,7 +201,6 @@ func (t OpType) FieldToOmitEmptyField() OpType {
|
||||||
createOpType("RecursivePtr", "Op"),
|
createOpType("RecursivePtr", "Op"),
|
||||||
createOpType("RecursiveEnd", "Op"),
|
createOpType("RecursiveEnd", "Op"),
|
||||||
createOpType("InterfaceEnd", "Op"),
|
createOpType("InterfaceEnd", "Op"),
|
||||||
createOpType("StructAnonymousEnd", "StructEnd"),
|
|
||||||
}
|
}
|
||||||
for _, typ := range primitiveTypesUpper {
|
for _, typ := range primitiveTypesUpper {
|
||||||
typ := typ
|
typ := typ
|
||||||
|
|
|
@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.Next
|
code = code.Next
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
}
|
}
|
||||||
case encoder.OpStructAnonymousEnd:
|
|
||||||
code = code.Next
|
|
||||||
case encoder.OpStructEnd:
|
case encoder.OpStructEnd:
|
||||||
b = appendStructEndSkipLast(ctx, code, b)
|
b = appendStructEndSkipLast(ctx, code, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
|
|
|
@ -0,0 +1,875 @@
|
||||||
|
package encoder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Code interface {
|
||||||
|
Kind() CodeKind
|
||||||
|
ToOpcode(*compileContext) Opcodes
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnonymousCode interface {
|
||||||
|
ToAnonymousOpcode(*compileContext) Opcodes
|
||||||
|
}
|
||||||
|
|
||||||
|
type Opcodes []*Opcode
|
||||||
|
|
||||||
|
func (o Opcodes) First() *Opcode {
|
||||||
|
if len(o) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return o[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Opcodes) Last() *Opcode {
|
||||||
|
if len(o) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return o[len(o)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Opcodes) Add(codes ...*Opcode) Opcodes {
|
||||||
|
return append(o, codes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CodeKind int
|
||||||
|
|
||||||
|
const (
|
||||||
|
CodeKindInterface CodeKind = iota
|
||||||
|
CodeKindPtr
|
||||||
|
CodeKindInt
|
||||||
|
CodeKindUint
|
||||||
|
CodeKindFloat
|
||||||
|
CodeKindString
|
||||||
|
CodeKindBool
|
||||||
|
CodeKindStruct
|
||||||
|
CodeKindMap
|
||||||
|
CodeKindSlice
|
||||||
|
CodeKindArray
|
||||||
|
CodeKindBytes
|
||||||
|
CodeKindMarshalJSON
|
||||||
|
CodeKindMarshalText
|
||||||
|
CodeKindRecursive
|
||||||
|
)
|
||||||
|
|
||||||
|
type IntCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
bitSize uint8
|
||||||
|
isString bool
|
||||||
|
isPtr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *IntCode) Kind() CodeKind {
|
||||||
|
return CodeKindInt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *IntCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
var code *Opcode
|
||||||
|
switch {
|
||||||
|
case c.isPtr:
|
||||||
|
code = newOpCode(ctx, c.typ, OpIntPtr)
|
||||||
|
case c.isString:
|
||||||
|
code = newOpCode(ctx, c.typ, OpIntString)
|
||||||
|
default:
|
||||||
|
code = newOpCode(ctx, c.typ, OpInt)
|
||||||
|
}
|
||||||
|
code.NumBitSize = c.bitSize
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type UintCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
bitSize uint8
|
||||||
|
isString bool
|
||||||
|
isPtr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UintCode) Kind() CodeKind {
|
||||||
|
return CodeKindUint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UintCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
var code *Opcode
|
||||||
|
switch {
|
||||||
|
case c.isPtr:
|
||||||
|
code = newOpCode(ctx, c.typ, OpUintPtr)
|
||||||
|
case c.isString:
|
||||||
|
code = newOpCode(ctx, c.typ, OpUintString)
|
||||||
|
default:
|
||||||
|
code = newOpCode(ctx, c.typ, OpUint)
|
||||||
|
}
|
||||||
|
code.NumBitSize = c.bitSize
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FloatCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
bitSize uint8
|
||||||
|
isPtr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FloatCode) Kind() CodeKind {
|
||||||
|
return CodeKindFloat
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FloatCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
var code *Opcode
|
||||||
|
switch {
|
||||||
|
case c.isPtr:
|
||||||
|
switch c.bitSize {
|
||||||
|
case 32:
|
||||||
|
code = newOpCode(ctx, c.typ, OpFloat32Ptr)
|
||||||
|
default:
|
||||||
|
code = newOpCode(ctx, c.typ, OpFloat64Ptr)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
switch c.bitSize {
|
||||||
|
case 32:
|
||||||
|
code = newOpCode(ctx, c.typ, OpFloat32)
|
||||||
|
default:
|
||||||
|
code = newOpCode(ctx, c.typ, OpFloat64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StringCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
isPtr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StringCode) Kind() CodeKind {
|
||||||
|
return CodeKindString
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StringCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
isJSONNumberType := c.typ == runtime.Type2RType(jsonNumberType)
|
||||||
|
var code *Opcode
|
||||||
|
if c.isPtr {
|
||||||
|
if isJSONNumberType {
|
||||||
|
code = newOpCode(ctx, c.typ, OpNumberPtr)
|
||||||
|
} else {
|
||||||
|
code = newOpCode(ctx, c.typ, OpStringPtr)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if isJSONNumberType {
|
||||||
|
code = newOpCode(ctx, c.typ, OpNumber)
|
||||||
|
} else {
|
||||||
|
code = newOpCode(ctx, c.typ, OpString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BoolCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
isPtr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *BoolCode) Kind() CodeKind {
|
||||||
|
return CodeKindBool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *BoolCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
var code *Opcode
|
||||||
|
switch {
|
||||||
|
case c.isPtr:
|
||||||
|
code = newOpCode(ctx, c.typ, OpBoolPtr)
|
||||||
|
default:
|
||||||
|
code = newOpCode(ctx, c.typ, OpBool)
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BytesCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
isPtr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *BytesCode) Kind() CodeKind {
|
||||||
|
return CodeKindBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *BytesCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
var code *Opcode
|
||||||
|
switch {
|
||||||
|
case c.isPtr:
|
||||||
|
code = newOpCode(ctx, c.typ, OpBytesPtr)
|
||||||
|
default:
|
||||||
|
code = newOpCode(ctx, c.typ, OpBytes)
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SliceCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
value Code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SliceCode) Kind() CodeKind {
|
||||||
|
return CodeKindSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
// header => opcode => elem => end
|
||||||
|
// ^ |
|
||||||
|
// |________|
|
||||||
|
size := c.typ.Elem().Size()
|
||||||
|
header := newSliceHeaderCode(ctx, c.typ)
|
||||||
|
ctx.incIndex()
|
||||||
|
|
||||||
|
ctx.incIndent()
|
||||||
|
codes := c.value.ToOpcode(ctx)
|
||||||
|
ctx.decIndent()
|
||||||
|
|
||||||
|
codes.First().Flags |= IndirectFlags
|
||||||
|
elemCode := newSliceElemCode(ctx, c.typ.Elem(), header, size)
|
||||||
|
ctx.incIndex()
|
||||||
|
end := newOpCode(ctx, c.typ, OpSliceEnd)
|
||||||
|
ctx.incIndex()
|
||||||
|
header.End = end
|
||||||
|
header.Next = codes.First()
|
||||||
|
codes.Last().Next = elemCode
|
||||||
|
elemCode.Next = codes.First()
|
||||||
|
elemCode.End = end
|
||||||
|
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArrayCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
value Code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ArrayCode) Kind() CodeKind {
|
||||||
|
return CodeKindArray
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
// header => opcode => elem => end
|
||||||
|
// ^ |
|
||||||
|
// |________|
|
||||||
|
elem := c.typ.Elem()
|
||||||
|
alen := c.typ.Len()
|
||||||
|
size := elem.Size()
|
||||||
|
|
||||||
|
header := newArrayHeaderCode(ctx, c.typ, alen)
|
||||||
|
ctx.incIndex()
|
||||||
|
|
||||||
|
ctx.incIndent()
|
||||||
|
codes := c.value.ToOpcode(ctx)
|
||||||
|
ctx.decIndent()
|
||||||
|
|
||||||
|
codes.First().Flags |= IndirectFlags
|
||||||
|
|
||||||
|
elemCode := newArrayElemCode(ctx, elem, header, alen, size)
|
||||||
|
ctx.incIndex()
|
||||||
|
|
||||||
|
end := newOpCode(ctx, c.typ, OpArrayEnd)
|
||||||
|
ctx.incIndex()
|
||||||
|
|
||||||
|
header.End = end
|
||||||
|
header.Next = codes.First()
|
||||||
|
codes.Last().Next = elemCode
|
||||||
|
elemCode.Next = codes.First()
|
||||||
|
elemCode.End = end
|
||||||
|
|
||||||
|
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MapCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
key Code
|
||||||
|
value Code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MapCode) Kind() CodeKind {
|
||||||
|
return CodeKindMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
// header => code => value => code => key => code => value => code => end
|
||||||
|
// ^ |
|
||||||
|
// |_______________________|
|
||||||
|
header := newMapHeaderCode(ctx, c.typ)
|
||||||
|
ctx.incIndex()
|
||||||
|
|
||||||
|
keyCodes := c.key.ToOpcode(ctx)
|
||||||
|
|
||||||
|
value := newMapValueCode(ctx, c.typ.Elem(), header)
|
||||||
|
ctx.incIndex()
|
||||||
|
|
||||||
|
ctx.incIndent()
|
||||||
|
valueCodes := c.value.ToOpcode(ctx)
|
||||||
|
ctx.decIndent()
|
||||||
|
|
||||||
|
valueCodes.First().Flags |= IndirectFlags
|
||||||
|
|
||||||
|
key := newMapKeyCode(ctx, c.typ.Key(), header)
|
||||||
|
ctx.incIndex()
|
||||||
|
|
||||||
|
end := newMapEndCode(ctx, c.typ, header)
|
||||||
|
ctx.incIndex()
|
||||||
|
|
||||||
|
header.Next = keyCodes.First()
|
||||||
|
keyCodes.Last().Next = value
|
||||||
|
value.Next = valueCodes.First()
|
||||||
|
valueCodes.Last().Next = key
|
||||||
|
key.Next = keyCodes.First()
|
||||||
|
|
||||||
|
header.End = end
|
||||||
|
key.End = end
|
||||||
|
value.End = end
|
||||||
|
return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end)
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
fields []*StructFieldCode
|
||||||
|
isPtr bool
|
||||||
|
disableIndirectConversion bool
|
||||||
|
isIndirect bool
|
||||||
|
isRecursive bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructCode) Kind() CodeKind {
|
||||||
|
return CodeKindStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode {
|
||||||
|
if field.isAnonymous {
|
||||||
|
return c.lastAnonymousFieldCode(firstField)
|
||||||
|
}
|
||||||
|
lastField := firstField
|
||||||
|
for lastField.NextField != nil {
|
||||||
|
lastField = lastField.NextField
|
||||||
|
}
|
||||||
|
return lastField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode {
|
||||||
|
// firstField is special StructHead operation for anonymous structure.
|
||||||
|
// So, StructHead's next operation is truly struct head operation.
|
||||||
|
lastField := firstField.Next
|
||||||
|
for lastField.NextField != nil {
|
||||||
|
lastField = lastField.NextField
|
||||||
|
}
|
||||||
|
return lastField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
// header => code => structField => code => end
|
||||||
|
// ^ |
|
||||||
|
// |__________|
|
||||||
|
if c.isRecursive {
|
||||||
|
recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
|
||||||
|
recursive.Type = c.typ
|
||||||
|
ctx.incIndex()
|
||||||
|
*ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
|
||||||
|
return Opcodes{recursive}
|
||||||
|
}
|
||||||
|
codes := Opcodes{}
|
||||||
|
var prevField *Opcode
|
||||||
|
ctx.incIndent()
|
||||||
|
for idx, field := range c.fields {
|
||||||
|
isFirstField := idx == 0
|
||||||
|
isEndField := idx == len(c.fields)-1
|
||||||
|
fieldCodes := field.ToOpcode(ctx, isFirstField, isEndField)
|
||||||
|
for _, code := range fieldCodes {
|
||||||
|
if c.isIndirect {
|
||||||
|
code.Flags |= IndirectFlags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firstField := fieldCodes.First()
|
||||||
|
if len(codes) > 0 {
|
||||||
|
codes.Last().Next = firstField
|
||||||
|
firstField.Idx = codes.First().Idx
|
||||||
|
}
|
||||||
|
if prevField != nil {
|
||||||
|
prevField.NextField = firstField
|
||||||
|
}
|
||||||
|
if isEndField {
|
||||||
|
endField := fieldCodes.Last()
|
||||||
|
if len(codes) > 0 {
|
||||||
|
codes.First().End = endField
|
||||||
|
} else if field.isAnonymous {
|
||||||
|
firstField.End = endField
|
||||||
|
lastField := c.lastAnonymousFieldCode(firstField)
|
||||||
|
lastField.NextField = endField
|
||||||
|
} else {
|
||||||
|
firstField.End = endField
|
||||||
|
}
|
||||||
|
codes = codes.Add(fieldCodes...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
prevField = c.lastFieldCode(field, firstField)
|
||||||
|
codes = codes.Add(fieldCodes...)
|
||||||
|
}
|
||||||
|
if len(codes) == 0 {
|
||||||
|
head := &Opcode{
|
||||||
|
Op: OpStructHead,
|
||||||
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
|
Type: c.typ,
|
||||||
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
|
Indent: ctx.indent,
|
||||||
|
}
|
||||||
|
ctx.incOpcodeIndex()
|
||||||
|
end := &Opcode{
|
||||||
|
Op: OpStructEnd,
|
||||||
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
|
Indent: ctx.indent,
|
||||||
|
}
|
||||||
|
head.NextField = end
|
||||||
|
head.Next = end
|
||||||
|
head.End = end
|
||||||
|
codes = codes.Add(head, end)
|
||||||
|
ctx.incIndex()
|
||||||
|
}
|
||||||
|
ctx.decIndent()
|
||||||
|
ctx.structTypeToCodes[uintptr(unsafe.Pointer(c.typ))] = codes
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
|
||||||
|
// header => code => structField => code => end
|
||||||
|
// ^ |
|
||||||
|
// |__________|
|
||||||
|
if c.isRecursive {
|
||||||
|
recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
|
||||||
|
recursive.Type = c.typ
|
||||||
|
ctx.incIndex()
|
||||||
|
*ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
|
||||||
|
return Opcodes{recursive}
|
||||||
|
}
|
||||||
|
codes := Opcodes{}
|
||||||
|
var prevField *Opcode
|
||||||
|
for idx, field := range c.fields {
|
||||||
|
isFirstField := idx == 0
|
||||||
|
isEndField := idx == len(c.fields)-1
|
||||||
|
fieldCodes := field.ToAnonymousOpcode(ctx, isFirstField, isEndField)
|
||||||
|
for _, code := range fieldCodes {
|
||||||
|
if c.isIndirect {
|
||||||
|
code.Flags |= IndirectFlags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firstField := fieldCodes.First()
|
||||||
|
if len(codes) > 0 {
|
||||||
|
codes.Last().Next = firstField
|
||||||
|
firstField.Idx = codes.First().Idx
|
||||||
|
}
|
||||||
|
if prevField != nil {
|
||||||
|
prevField.NextField = firstField
|
||||||
|
}
|
||||||
|
if isEndField {
|
||||||
|
lastField := fieldCodes.Last()
|
||||||
|
if len(codes) > 0 {
|
||||||
|
codes.First().End = lastField
|
||||||
|
} else {
|
||||||
|
firstField.End = lastField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevField = firstField
|
||||||
|
codes = codes.Add(fieldCodes...)
|
||||||
|
}
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) {
|
||||||
|
fields := make([]*StructFieldCode, 0, len(c.fields))
|
||||||
|
for _, field := range c.fields {
|
||||||
|
if field.isAnonymous {
|
||||||
|
structCode := field.getAnonymousStruct()
|
||||||
|
if structCode != nil && !structCode.isRecursive {
|
||||||
|
structCode.removeFieldsByTags(tags)
|
||||||
|
if len(structCode.fields) > 0 {
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tags.ExistsKey(field.key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
c.fields = fields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructCode) enableIndirect() {
|
||||||
|
if c.isIndirect {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.isIndirect = true
|
||||||
|
if len(c.fields) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
structCode := c.fields[0].getStruct()
|
||||||
|
if structCode == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
structCode.enableIndirect()
|
||||||
|
}
|
||||||
|
|
||||||
|
type StructFieldCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
key string
|
||||||
|
tag *runtime.StructTag
|
||||||
|
value Code
|
||||||
|
offset uintptr
|
||||||
|
isAnonymous bool
|
||||||
|
isTaggedKey bool
|
||||||
|
isNilableType bool
|
||||||
|
isNilCheck bool
|
||||||
|
isAddrForMarshaler bool
|
||||||
|
isNextOpPtrType bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) getStruct() *StructCode {
|
||||||
|
value := c.value
|
||||||
|
ptr, ok := value.(*PtrCode)
|
||||||
|
if ok {
|
||||||
|
value = ptr.value
|
||||||
|
}
|
||||||
|
structCode, ok := value.(*StructCode)
|
||||||
|
if ok {
|
||||||
|
return structCode
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) getAnonymousStruct() *StructCode {
|
||||||
|
if !c.isAnonymous {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.getStruct()
|
||||||
|
}
|
||||||
|
|
||||||
|
func optimizeStructHeader(code *Opcode, tag *runtime.StructTag) OpType {
|
||||||
|
headType := code.ToHeaderType(tag.IsString)
|
||||||
|
if tag.IsOmitEmpty {
|
||||||
|
headType = headType.HeadToOmitEmptyHead()
|
||||||
|
}
|
||||||
|
return headType
|
||||||
|
}
|
||||||
|
|
||||||
|
func optimizeStructField(code *Opcode, tag *runtime.StructTag) OpType {
|
||||||
|
fieldType := code.ToFieldType(tag.IsString)
|
||||||
|
if tag.IsOmitEmpty {
|
||||||
|
fieldType = fieldType.FieldToOmitEmptyField()
|
||||||
|
}
|
||||||
|
return fieldType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) headerOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
|
||||||
|
value := valueCodes.First()
|
||||||
|
op := optimizeStructHeader(value, c.tag)
|
||||||
|
field.Op = op
|
||||||
|
field.NumBitSize = value.NumBitSize
|
||||||
|
field.PtrNum = value.PtrNum
|
||||||
|
fieldCodes := Opcodes{field}
|
||||||
|
if op.IsMultipleOpHead() {
|
||||||
|
field.Next = value
|
||||||
|
fieldCodes = fieldCodes.Add(valueCodes...)
|
||||||
|
} else {
|
||||||
|
ctx.decIndex()
|
||||||
|
}
|
||||||
|
return fieldCodes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) fieldOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
|
||||||
|
value := valueCodes.First()
|
||||||
|
op := optimizeStructField(value, c.tag)
|
||||||
|
field.Op = op
|
||||||
|
field.NumBitSize = value.NumBitSize
|
||||||
|
field.PtrNum = value.PtrNum
|
||||||
|
|
||||||
|
fieldCodes := Opcodes{field}
|
||||||
|
if op.IsMultipleOpField() {
|
||||||
|
field.Next = value
|
||||||
|
fieldCodes = fieldCodes.Add(valueCodes...)
|
||||||
|
} else {
|
||||||
|
ctx.decIndex()
|
||||||
|
}
|
||||||
|
return fieldCodes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) addStructEndCode(ctx *compileContext, codes Opcodes) Opcodes {
|
||||||
|
end := &Opcode{
|
||||||
|
Op: OpStructEnd,
|
||||||
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
|
Indent: ctx.indent,
|
||||||
|
}
|
||||||
|
codes.Last().Next = end
|
||||||
|
codes.First().NextField = end
|
||||||
|
codes = codes.Add(end)
|
||||||
|
ctx.incOpcodeIndex()
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) structKey(ctx *compileContext) string {
|
||||||
|
if ctx.escapeKey {
|
||||||
|
rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
|
||||||
|
return fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key)))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(`"%s":`, c.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) flags() OpFlags {
|
||||||
|
var flags OpFlags
|
||||||
|
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
|
||||||
|
}
|
||||||
|
if c.isAnonymous {
|
||||||
|
flags |= AnonymousKeyFlags
|
||||||
|
}
|
||||||
|
return flags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) toValueOpcodes(ctx *compileContext) Opcodes {
|
||||||
|
if c.isAnonymous {
|
||||||
|
anonymCode, ok := c.value.(AnonymousCode)
|
||||||
|
if ok {
|
||||||
|
return anonymCode.ToAnonymousOpcode(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c.value.ToOpcode(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
|
||||||
|
field := &Opcode{
|
||||||
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
|
Flags: c.flags(),
|
||||||
|
Key: c.structKey(ctx),
|
||||||
|
Offset: uint32(c.offset),
|
||||||
|
Type: c.typ,
|
||||||
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
|
Indent: ctx.indent,
|
||||||
|
DisplayKey: c.key,
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
valueCodes := c.toValueOpcodes(ctx)
|
||||||
|
if isFirstField {
|
||||||
|
codes := c.headerOpcodes(ctx, field, valueCodes)
|
||||||
|
if isEndField {
|
||||||
|
codes = c.addStructEndCode(ctx, codes)
|
||||||
|
}
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
codes := c.fieldOpcodes(ctx, field, valueCodes)
|
||||||
|
if isEndField {
|
||||||
|
if isEnableStructEndOptimization(c.value) {
|
||||||
|
field.Op = field.Op.FieldToEnd()
|
||||||
|
} else {
|
||||||
|
codes = c.addStructEndCode(ctx, codes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
|
||||||
|
field := &Opcode{
|
||||||
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
|
Flags: c.flags() | AnonymousHeadFlags,
|
||||||
|
Key: c.structKey(ctx),
|
||||||
|
Offset: uint32(c.offset),
|
||||||
|
Type: c.typ,
|
||||||
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
|
Indent: ctx.indent,
|
||||||
|
DisplayKey: c.key,
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
valueCodes := c.toValueOpcodes(ctx)
|
||||||
|
if isFirstField {
|
||||||
|
return c.headerOpcodes(ctx, field, valueCodes)
|
||||||
|
}
|
||||||
|
return c.fieldOpcodes(ctx, field, valueCodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEnableStructEndOptimization(value Code) bool {
|
||||||
|
switch value.Kind() {
|
||||||
|
case CodeKindInt,
|
||||||
|
CodeKindUint,
|
||||||
|
CodeKindFloat,
|
||||||
|
CodeKindString,
|
||||||
|
CodeKindBool,
|
||||||
|
CodeKindBytes:
|
||||||
|
return true
|
||||||
|
case CodeKindPtr:
|
||||||
|
return isEnableStructEndOptimization(value.(*PtrCode).value)
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type InterfaceCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
isPtr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *InterfaceCode) Kind() CodeKind {
|
||||||
|
return CodeKindInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *InterfaceCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
var code *Opcode
|
||||||
|
switch {
|
||||||
|
case c.isPtr:
|
||||||
|
code = newOpCode(ctx, c.typ, OpInterfacePtr)
|
||||||
|
default:
|
||||||
|
code = newOpCode(ctx, c.typ, OpInterface)
|
||||||
|
}
|
||||||
|
if c.typ.NumMethod() > 0 {
|
||||||
|
code.Flags |= NonEmptyInterfaceFlags
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MarshalJSONCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
isAddrForMarshaler bool
|
||||||
|
isNilableType bool
|
||||||
|
isMarshalerContext bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MarshalJSONCode) Kind() CodeKind {
|
||||||
|
return CodeKindMarshalJSON
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MarshalJSONCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
code := newOpCode(ctx, c.typ, OpMarshalJSON)
|
||||||
|
if c.isAddrForMarshaler {
|
||||||
|
code.Flags |= AddrForMarshalerFlags
|
||||||
|
}
|
||||||
|
if c.isMarshalerContext {
|
||||||
|
code.Flags |= MarshalerContextFlags
|
||||||
|
}
|
||||||
|
if c.isNilableType {
|
||||||
|
code.Flags |= IsNilableTypeFlags
|
||||||
|
} else {
|
||||||
|
code.Flags &= ^IsNilableTypeFlags
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MarshalTextCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
isAddrForMarshaler bool
|
||||||
|
isNilableType bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MarshalTextCode) Kind() CodeKind {
|
||||||
|
return CodeKindMarshalText
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MarshalTextCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
code := newOpCode(ctx, c.typ, OpMarshalText)
|
||||||
|
if c.isAddrForMarshaler {
|
||||||
|
code.Flags |= AddrForMarshalerFlags
|
||||||
|
}
|
||||||
|
if c.isNilableType {
|
||||||
|
code.Flags |= IsNilableTypeFlags
|
||||||
|
} else {
|
||||||
|
code.Flags &= ^IsNilableTypeFlags
|
||||||
|
}
|
||||||
|
ctx.incIndex()
|
||||||
|
return Opcodes{code}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PtrCode struct {
|
||||||
|
typ *runtime.Type
|
||||||
|
value Code
|
||||||
|
ptrNum uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PtrCode) Kind() CodeKind {
|
||||||
|
return CodeKindPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PtrCode) ToOpcode(ctx *compileContext) Opcodes {
|
||||||
|
codes := c.value.ToOpcode(ctx)
|
||||||
|
codes.First().Op = convertPtrOp(codes.First())
|
||||||
|
codes.First().PtrNum = c.ptrNum
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PtrCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
|
||||||
|
var codes Opcodes
|
||||||
|
anonymCode, ok := c.value.(AnonymousCode)
|
||||||
|
if ok {
|
||||||
|
codes = anonymCode.ToAnonymousOpcode(ctx)
|
||||||
|
} else {
|
||||||
|
codes = c.value.ToOpcode(ctx)
|
||||||
|
}
|
||||||
|
codes.First().Op = convertPtrOp(codes.First())
|
||||||
|
codes.First().PtrNum = c.ptrNum
|
||||||
|
return codes
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertPtrOp(code *Opcode) OpType {
|
||||||
|
ptrHeadOp := code.Op.HeadToPtrHead()
|
||||||
|
if code.Op != ptrHeadOp {
|
||||||
|
if code.PtrNum > 0 {
|
||||||
|
// ptr field and ptr head
|
||||||
|
code.PtrNum--
|
||||||
|
}
|
||||||
|
return ptrHeadOp
|
||||||
|
}
|
||||||
|
switch code.Op {
|
||||||
|
case OpInt:
|
||||||
|
return OpIntPtr
|
||||||
|
case OpUint:
|
||||||
|
return OpUintPtr
|
||||||
|
case OpFloat32:
|
||||||
|
return OpFloat32Ptr
|
||||||
|
case OpFloat64:
|
||||||
|
return OpFloat64Ptr
|
||||||
|
case OpString:
|
||||||
|
return OpStringPtr
|
||||||
|
case OpBool:
|
||||||
|
return OpBoolPtr
|
||||||
|
case OpBytes:
|
||||||
|
return OpBytesPtr
|
||||||
|
case OpNumber:
|
||||||
|
return OpNumberPtr
|
||||||
|
case OpArray:
|
||||||
|
return OpArrayPtr
|
||||||
|
case OpSlice:
|
||||||
|
return OpSlicePtr
|
||||||
|
case OpMap:
|
||||||
|
return OpMapPtr
|
||||||
|
case OpMarshalJSON:
|
||||||
|
return OpMarshalJSONPtr
|
||||||
|
case OpMarshalText:
|
||||||
|
return OpMarshalTextPtr
|
||||||
|
case OpInterface:
|
||||||
|
return OpInterfacePtr
|
||||||
|
case OpRecursive:
|
||||||
|
return OpRecursivePtr
|
||||||
|
}
|
||||||
|
return code.Op
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +1,8 @@
|
||||||
|
//go:build !race
|
||||||
// +build !race
|
// +build !race
|
||||||
|
|
||||||
package encoder
|
package encoder
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
||||||
if typeptr > typeAddr.MaxTypeAddr {
|
if typeptr > typeAddr.MaxTypeAddr {
|
||||||
return compileToGetCodeSetSlowPath(typeptr)
|
return compileToGetCodeSetSlowPath(typeptr)
|
||||||
|
@ -16,41 +11,10 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
||||||
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
|
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
|
||||||
return codeSet, nil
|
return codeSet, nil
|
||||||
}
|
}
|
||||||
|
codeSet, err := newCompiler().compile(typeptr)
|
||||||
// noescape trick for header.typ ( reflect.*rtype )
|
|
||||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
|
||||||
|
|
||||||
noescapeKeyCode, err := compileHead(&compileContext{
|
|
||||||
typ: copiedType,
|
|
||||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
escapeKeyCode, err := compileHead(&compileContext{
|
|
||||||
typ: copiedType,
|
|
||||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
|
||||||
escapeKey: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
noescapeKeyCode = copyOpcode(noescapeKeyCode)
|
|
||||||
escapeKeyCode = copyOpcode(escapeKeyCode)
|
|
||||||
setTotalLengthToInterfaceOp(noescapeKeyCode)
|
|
||||||
setTotalLengthToInterfaceOp(escapeKeyCode)
|
|
||||||
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
|
|
||||||
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
|
|
||||||
codeLength := noescapeKeyCode.TotalLength()
|
|
||||||
codeSet := &OpcodeSet{
|
|
||||||
Type: copiedType,
|
|
||||||
NoescapeKeyCode: noescapeKeyCode,
|
|
||||||
EscapeKeyCode: escapeKeyCode,
|
|
||||||
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
|
|
||||||
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
|
|
||||||
CodeLength: codeLength,
|
|
||||||
EndCode: ToEndCode(interfaceNoescapeKeyCode),
|
|
||||||
}
|
|
||||||
cachedOpcodeSets[index] = codeSet
|
cachedOpcodeSets[index] = codeSet
|
||||||
return codeSet, nil
|
return codeSet, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
|
//go:build race
|
||||||
// +build race
|
// +build race
|
||||||
|
|
||||||
package encoder
|
package encoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var setsMu sync.RWMutex
|
var setsMu sync.RWMutex
|
||||||
|
@ -23,41 +21,10 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
|
||||||
}
|
}
|
||||||
setsMu.RUnlock()
|
setsMu.RUnlock()
|
||||||
|
|
||||||
// noescape trick for header.typ ( reflect.*rtype )
|
codeSet, err := newCompiler().compile(typeptr)
|
||||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
|
||||||
|
|
||||||
noescapeKeyCode, err := compileHead(&compileContext{
|
|
||||||
typ: copiedType,
|
|
||||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
escapeKeyCode, err := compileHead(&compileContext{
|
|
||||||
typ: copiedType,
|
|
||||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
|
||||||
escapeKey: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
noescapeKeyCode = copyOpcode(noescapeKeyCode)
|
|
||||||
escapeKeyCode = copyOpcode(escapeKeyCode)
|
|
||||||
setTotalLengthToInterfaceOp(noescapeKeyCode)
|
|
||||||
setTotalLengthToInterfaceOp(escapeKeyCode)
|
|
||||||
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
|
|
||||||
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
|
|
||||||
codeLength := noescapeKeyCode.TotalLength()
|
|
||||||
codeSet := &OpcodeSet{
|
|
||||||
Type: copiedType,
|
|
||||||
NoescapeKeyCode: noescapeKeyCode,
|
|
||||||
EscapeKeyCode: escapeKeyCode,
|
|
||||||
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
|
|
||||||
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
|
|
||||||
CodeLength: codeLength,
|
|
||||||
EndCode: ToEndCode(interfaceNoescapeKeyCode),
|
|
||||||
}
|
|
||||||
setsMu.Lock()
|
setsMu.Lock()
|
||||||
cachedOpcodeSets[index] = codeSet
|
cachedOpcodeSets[index] = codeSet
|
||||||
setsMu.Unlock()
|
setsMu.Unlock()
|
||||||
|
|
|
@ -9,44 +9,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type compileContext struct {
|
type compileContext struct {
|
||||||
typ *runtime.Type
|
opcodeIndex uint32
|
||||||
opcodeIndex uint32
|
ptrIndex int
|
||||||
ptrIndex int
|
indent uint32
|
||||||
indent uint32
|
escapeKey bool
|
||||||
escapeKey bool
|
structTypeToCodes map[uintptr]Opcodes
|
||||||
structTypeToCompiledCode map[uintptr]*CompiledCode
|
recursiveCodes *Opcodes
|
||||||
|
|
||||||
parent *compileContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) context() *compileContext {
|
func (c *compileContext) incIndent() {
|
||||||
return &compileContext{
|
c.indent++
|
||||||
typ: c.typ,
|
|
||||||
opcodeIndex: c.opcodeIndex,
|
|
||||||
ptrIndex: c.ptrIndex,
|
|
||||||
indent: c.indent,
|
|
||||||
escapeKey: c.escapeKey,
|
|
||||||
structTypeToCompiledCode: c.structTypeToCompiledCode,
|
|
||||||
parent: c,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) withType(typ *runtime.Type) *compileContext {
|
func (c *compileContext) decIndent() {
|
||||||
ctx := c.context()
|
c.indent--
|
||||||
ctx.typ = typ
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *compileContext) incIndent() *compileContext {
|
|
||||||
ctx := c.context()
|
|
||||||
ctx.indent++
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *compileContext) decIndent() *compileContext {
|
|
||||||
ctx := c.context()
|
|
||||||
ctx.indent--
|
|
||||||
return ctx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) incIndex() {
|
func (c *compileContext) incIndex() {
|
||||||
|
@ -61,30 +37,18 @@ func (c *compileContext) decIndex() {
|
||||||
|
|
||||||
func (c *compileContext) incOpcodeIndex() {
|
func (c *compileContext) incOpcodeIndex() {
|
||||||
c.opcodeIndex++
|
c.opcodeIndex++
|
||||||
if c.parent != nil {
|
|
||||||
c.parent.incOpcodeIndex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) decOpcodeIndex() {
|
func (c *compileContext) decOpcodeIndex() {
|
||||||
c.opcodeIndex--
|
c.opcodeIndex--
|
||||||
if c.parent != nil {
|
|
||||||
c.parent.decOpcodeIndex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) incPtrIndex() {
|
func (c *compileContext) incPtrIndex() {
|
||||||
c.ptrIndex++
|
c.ptrIndex++
|
||||||
if c.parent != nil {
|
|
||||||
c.parent.incPtrIndex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compileContext) decPtrIndex() {
|
func (c *compileContext) decPtrIndex() {
|
||||||
c.ptrIndex--
|
c.ptrIndex--
|
||||||
if c.parent != nil {
|
|
||||||
c.parent.decPtrIndex()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -38,7 +38,6 @@ type Opcode struct {
|
||||||
Flags OpFlags
|
Flags OpFlags
|
||||||
|
|
||||||
Type *runtime.Type // go type
|
Type *runtime.Type // go type
|
||||||
PrevField *Opcode // prev struct field
|
|
||||||
Jmp *CompiledCode // for recursive call
|
Jmp *CompiledCode // for recursive call
|
||||||
ElemIdx uint32 // offset to access array/slice/map elem
|
ElemIdx uint32 // offset to access array/slice/map elem
|
||||||
Length uint32 // offset to access slice/map length or array length
|
Length uint32 // offset to access slice/map length or array length
|
||||||
|
@ -50,18 +49,40 @@ type Opcode struct {
|
||||||
DisplayKey string // key text to display
|
DisplayKey string // key text to display
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) IsStructHeadOp() bool {
|
func (c *Opcode) Validate() error {
|
||||||
if c == nil {
|
var prevIdx uint32
|
||||||
return false
|
for code := c; !code.IsEnd(); {
|
||||||
|
if prevIdx != 0 {
|
||||||
|
if code.DisplayIdx != prevIdx+1 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"invalid index. previous display index is %d but next is %d. dump = %s",
|
||||||
|
prevIdx, code.DisplayIdx, c.Dump(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevIdx = code.DisplayIdx
|
||||||
|
code = code.IterNext()
|
||||||
}
|
}
|
||||||
return strings.Contains(c.Op.String(), "Head")
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) IsRecursiveOp() bool {
|
func (c *Opcode) IterNext() *Opcode {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
return strings.Contains(c.Op.String(), "Recursive")
|
switch c.Op.CodeType() {
|
||||||
|
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
||||||
|
return c.End
|
||||||
|
default:
|
||||||
|
return c.Next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Opcode) IsEnd() bool {
|
||||||
|
if c == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) MaxIdx() uint32 {
|
func (c *Opcode) MaxIdx() uint32 {
|
||||||
|
@ -287,43 +308,76 @@ func (c *Opcode) ToFieldType(isString bool) OpType {
|
||||||
return OpStructField
|
return OpStructField
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOpCode(ctx *compileContext, op OpType) *Opcode {
|
func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode {
|
||||||
return newOpCodeWithNext(ctx, op, newEndOp(ctx))
|
return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
func opcodeOffset(idx int) uint32 {
|
func opcodeOffset(idx int) uint32 {
|
||||||
return uint32(idx) * uintptrSize
|
return uint32(idx) * uintptrSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode {
|
||||||
|
addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{})
|
||||||
|
return *(**Opcode)(unsafe.Pointer(&addr))
|
||||||
|
}
|
||||||
|
|
||||||
func copyOpcode(code *Opcode) *Opcode {
|
func copyOpcode(code *Opcode) *Opcode {
|
||||||
codeMap := map[uintptr]*Opcode{}
|
codeNum := ToEndCode(code).DisplayIdx + 1
|
||||||
return code.copy(codeMap)
|
codeSlice := make([]Opcode, codeNum)
|
||||||
|
head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data)
|
||||||
|
ptr := head
|
||||||
|
c := code
|
||||||
|
for {
|
||||||
|
*ptr = Opcode{
|
||||||
|
Op: c.Op,
|
||||||
|
Key: c.Key,
|
||||||
|
PtrNum: c.PtrNum,
|
||||||
|
NumBitSize: c.NumBitSize,
|
||||||
|
Flags: c.Flags,
|
||||||
|
Idx: c.Idx,
|
||||||
|
Offset: c.Offset,
|
||||||
|
Type: c.Type,
|
||||||
|
DisplayIdx: c.DisplayIdx,
|
||||||
|
DisplayKey: c.DisplayKey,
|
||||||
|
ElemIdx: c.ElemIdx,
|
||||||
|
Length: c.Length,
|
||||||
|
MapIter: c.MapIter,
|
||||||
|
MapPos: c.MapPos,
|
||||||
|
Size: c.Size,
|
||||||
|
Indent: c.Indent,
|
||||||
|
Jmp: c.Jmp,
|
||||||
|
}
|
||||||
|
if c.End != nil {
|
||||||
|
ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx)
|
||||||
|
}
|
||||||
|
if c.NextField != nil {
|
||||||
|
ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx)
|
||||||
|
}
|
||||||
|
if c.Next != nil {
|
||||||
|
ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx)
|
||||||
|
}
|
||||||
|
if c.IsEnd() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ptr = getCodeAddrByIdx(head, c.DisplayIdx+1)
|
||||||
|
c = c.IterNext()
|
||||||
|
}
|
||||||
|
return head
|
||||||
}
|
}
|
||||||
|
|
||||||
func setTotalLengthToInterfaceOp(code *Opcode) {
|
func setTotalLengthToInterfaceOp(code *Opcode) {
|
||||||
c := code
|
for c := code; !c.IsEnd(); {
|
||||||
for c.Op != OpEnd && c.Op != OpInterfaceEnd {
|
|
||||||
if c.Op == OpInterface {
|
if c.Op == OpInterface {
|
||||||
c.Length = uint32(code.TotalLength())
|
c.Length = uint32(code.TotalLength())
|
||||||
}
|
}
|
||||||
switch c.Op.CodeType() {
|
c = c.IterNext()
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
c = c.End
|
|
||||||
default:
|
|
||||||
c = c.Next
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToEndCode(code *Opcode) *Opcode {
|
func ToEndCode(code *Opcode) *Opcode {
|
||||||
c := code
|
c := code
|
||||||
for c.Op != OpEnd && c.Op != OpInterfaceEnd {
|
for !c.IsEnd() {
|
||||||
switch c.Op.CodeType() {
|
c = c.IterNext()
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
c = c.End
|
|
||||||
default:
|
|
||||||
c = c.Next
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -339,77 +393,25 @@ func copyToInterfaceOpcode(code *Opcode) *Opcode {
|
||||||
return copied
|
return copied
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOpCodeWithNext(ctx *compileContext, op OpType, next *Opcode) *Opcode {
|
func newOpCodeWithNext(ctx *compileContext, typ *runtime.Type, op OpType, next *Opcode) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: op,
|
Op: op,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
Next: next,
|
Next: next,
|
||||||
Type: ctx.typ,
|
Type: typ,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEndOp(ctx *compileContext) *Opcode {
|
func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||||
return newOpCodeWithNext(ctx, OpEnd, nil)
|
return newOpCodeWithNext(ctx, typ, OpEnd, nil)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
addr := uintptr(unsafe.Pointer(c))
|
|
||||||
if code, exists := codeMap[addr]; exists {
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
copied := &Opcode{
|
|
||||||
Op: c.Op,
|
|
||||||
Key: c.Key,
|
|
||||||
PtrNum: c.PtrNum,
|
|
||||||
NumBitSize: c.NumBitSize,
|
|
||||||
Flags: c.Flags,
|
|
||||||
Idx: c.Idx,
|
|
||||||
Offset: c.Offset,
|
|
||||||
Type: c.Type,
|
|
||||||
DisplayIdx: c.DisplayIdx,
|
|
||||||
DisplayKey: c.DisplayKey,
|
|
||||||
ElemIdx: c.ElemIdx,
|
|
||||||
Length: c.Length,
|
|
||||||
MapIter: c.MapIter,
|
|
||||||
MapPos: c.MapPos,
|
|
||||||
Size: c.Size,
|
|
||||||
Indent: c.Indent,
|
|
||||||
}
|
|
||||||
codeMap[addr] = copied
|
|
||||||
copied.End = c.End.copy(codeMap)
|
|
||||||
copied.PrevField = c.PrevField.copy(codeMap)
|
|
||||||
copied.NextField = c.NextField.copy(codeMap)
|
|
||||||
copied.Next = c.Next.copy(codeMap)
|
|
||||||
copied.Jmp = c.Jmp
|
|
||||||
return copied
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Opcode) BeforeLastCode() *Opcode {
|
|
||||||
code := c
|
|
||||||
for {
|
|
||||||
var nextCode *Opcode
|
|
||||||
switch code.Op.CodeType() {
|
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
nextCode = code.End
|
|
||||||
default:
|
|
||||||
nextCode = code.Next
|
|
||||||
}
|
|
||||||
if nextCode.Op == OpEnd {
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
code = nextCode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) TotalLength() int {
|
func (c *Opcode) TotalLength() int {
|
||||||
var idx int
|
var idx int
|
||||||
code := c
|
code := c
|
||||||
for code.Op != OpEnd && code.Op != OpInterfaceEnd {
|
for !code.IsEnd() {
|
||||||
maxIdx := int(code.MaxIdx() / uintptrSize)
|
maxIdx := int(code.MaxIdx() / uintptrSize)
|
||||||
if idx < maxIdx {
|
if idx < maxIdx {
|
||||||
idx = maxIdx
|
idx = maxIdx
|
||||||
|
@ -417,12 +419,7 @@ func (c *Opcode) TotalLength() int {
|
||||||
if code.Op == OpRecursiveEnd {
|
if code.Op == OpRecursiveEnd {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch code.Op.CodeType() {
|
code = code.IterNext()
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
code = code.End
|
|
||||||
default:
|
|
||||||
code = code.Next
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
maxIdx := int(code.MaxIdx() / uintptrSize)
|
maxIdx := int(code.MaxIdx() / uintptrSize)
|
||||||
if idx < maxIdx {
|
if idx < maxIdx {
|
||||||
|
@ -431,42 +428,6 @@ func (c *Opcode) TotalLength() int {
|
||||||
return idx + 1
|
return idx + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Opcode) decOpcodeIndex() {
|
|
||||||
for code := c; code.Op != OpEnd; {
|
|
||||||
code.DisplayIdx--
|
|
||||||
if code.Idx > 0 {
|
|
||||||
code.Idx -= uintptrSize
|
|
||||||
}
|
|
||||||
if code.ElemIdx > 0 {
|
|
||||||
code.ElemIdx -= uintptrSize
|
|
||||||
}
|
|
||||||
if code.MapIter > 0 {
|
|
||||||
code.MapIter -= uintptrSize
|
|
||||||
}
|
|
||||||
if code.Length > 0 && code.Op.CodeType() != CodeArrayHead && code.Op.CodeType() != CodeArrayElem {
|
|
||||||
code.Length -= uintptrSize
|
|
||||||
}
|
|
||||||
switch code.Op.CodeType() {
|
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
code = code.End
|
|
||||||
default:
|
|
||||||
code = code.Next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Opcode) decIndent() {
|
|
||||||
for code := c; code.Op != OpEnd; {
|
|
||||||
code.Indent--
|
|
||||||
switch code.Op.CodeType() {
|
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
code = code.End
|
|
||||||
default:
|
|
||||||
code = code.Next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Opcode) dumpHead(code *Opcode) string {
|
func (c *Opcode) dumpHead(code *Opcode) string {
|
||||||
var length uint32
|
var length uint32
|
||||||
if code.Op.CodeType() == CodeArrayHead {
|
if code.Op.CodeType() == CodeArrayHead {
|
||||||
|
@ -475,7 +436,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])`,
|
`[%03d]%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,
|
||||||
|
@ -487,7 +448,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])`,
|
`[%03d]%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,
|
||||||
|
@ -500,7 +461,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])`,
|
`[%03d]%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,
|
||||||
|
@ -518,7 +479,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])`,
|
`[%03d]%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,
|
||||||
|
@ -531,7 +492,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])`,
|
`[%03d]%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,
|
||||||
|
@ -543,7 +504,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])`,
|
`[%03d]%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,
|
||||||
|
@ -556,7 +517,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])`,
|
`[%03d]%s%s ([idx:%d][mapIter:%d])`,
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -567,7 +528,7 @@ func (c *Opcode) dumpValue(code *Opcode) string {
|
||||||
|
|
||||||
func (c *Opcode) Dump() string {
|
func (c *Opcode) Dump() string {
|
||||||
codes := []string{}
|
codes := []string{}
|
||||||
for code := c; code.Op != OpEnd && code.Op != OpInterfaceEnd; {
|
for code := c; !code.IsEnd(); {
|
||||||
switch code.Op.CodeType() {
|
switch code.Op.CodeType() {
|
||||||
case CodeSliceHead:
|
case CodeSliceHead:
|
||||||
codes = append(codes, c.dumpHead(code))
|
codes = append(codes, c.dumpHead(code))
|
||||||
|
@ -595,7 +556,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])",
|
"[%03d]%s%s ([idx:%d])",
|
||||||
code.DisplayIdx,
|
code.DisplayIdx,
|
||||||
strings.Repeat("-", int(code.Indent)),
|
strings.Repeat("-", int(code.Indent)),
|
||||||
code.Op,
|
code.Op,
|
||||||
|
@ -607,44 +568,7 @@ func (c *Opcode) Dump() string {
|
||||||
return strings.Join(codes, "\n")
|
return strings.Join(codes, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func prevField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode {
|
func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||||
if _, exists := removedFields[code]; exists {
|
|
||||||
return prevField(code.PrevField, removedFields)
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode {
|
|
||||||
if _, exists := removedFields[code]; exists {
|
|
||||||
return nextField(code.NextField, removedFields)
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
func linkPrevToNextField(cur *Opcode, removedFields map[*Opcode]struct{}) {
|
|
||||||
prev := prevField(cur.PrevField, removedFields)
|
|
||||||
prev.NextField = nextField(cur.NextField, removedFields)
|
|
||||||
code := prev
|
|
||||||
fcode := cur
|
|
||||||
for {
|
|
||||||
var nextCode *Opcode
|
|
||||||
switch code.Op.CodeType() {
|
|
||||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
|
||||||
nextCode = code.End
|
|
||||||
default:
|
|
||||||
nextCode = code.Next
|
|
||||||
}
|
|
||||||
if nextCode == fcode {
|
|
||||||
code.Next = fcode.NextField
|
|
||||||
break
|
|
||||||
} else if nextCode.Op == OpEnd {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
code = nextCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSliceHeaderCode(ctx *compileContext) *Opcode {
|
|
||||||
idx := opcodeOffset(ctx.ptrIndex)
|
idx := opcodeOffset(ctx.ptrIndex)
|
||||||
ctx.incPtrIndex()
|
ctx.incPtrIndex()
|
||||||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
elemIdx := opcodeOffset(ctx.ptrIndex)
|
||||||
|
@ -652,6 +576,7 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
|
||||||
length := opcodeOffset(ctx.ptrIndex)
|
length := opcodeOffset(ctx.ptrIndex)
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpSlice,
|
Op: OpSlice,
|
||||||
|
Type: typ,
|
||||||
Idx: idx,
|
Idx: idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: elemIdx,
|
ElemIdx: elemIdx,
|
||||||
|
@ -660,9 +585,10 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
|
func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpSliceElem,
|
Op: OpSliceElem,
|
||||||
|
Type: typ,
|
||||||
Idx: head.Idx,
|
Idx: head.Idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: head.ElemIdx,
|
ElemIdx: head.ElemIdx,
|
||||||
|
@ -672,12 +598,13 @@ func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
|
func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode {
|
||||||
idx := opcodeOffset(ctx.ptrIndex)
|
idx := opcodeOffset(ctx.ptrIndex)
|
||||||
ctx.incPtrIndex()
|
ctx.incPtrIndex()
|
||||||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
elemIdx := opcodeOffset(ctx.ptrIndex)
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpArray,
|
Op: OpArray,
|
||||||
|
Type: typ,
|
||||||
Idx: idx,
|
Idx: idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: elemIdx,
|
ElemIdx: elemIdx,
|
||||||
|
@ -686,9 +613,10 @@ func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintptr) *Opcode {
|
func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpArrayElem,
|
Op: OpArrayElem,
|
||||||
|
Type: typ,
|
||||||
Idx: head.Idx,
|
Idx: head.Idx,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: head.ElemIdx,
|
ElemIdx: head.ElemIdx,
|
||||||
|
@ -698,7 +626,7 @@ func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintpt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapHeaderCode(ctx *compileContext) *Opcode {
|
func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||||
idx := opcodeOffset(ctx.ptrIndex)
|
idx := opcodeOffset(ctx.ptrIndex)
|
||||||
ctx.incPtrIndex()
|
ctx.incPtrIndex()
|
||||||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
elemIdx := opcodeOffset(ctx.ptrIndex)
|
||||||
|
@ -708,8 +636,8 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
|
||||||
mapIter := opcodeOffset(ctx.ptrIndex)
|
mapIter := opcodeOffset(ctx.ptrIndex)
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpMap,
|
Op: OpMap,
|
||||||
|
Type: typ,
|
||||||
Idx: idx,
|
Idx: idx,
|
||||||
Type: ctx.typ,
|
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: elemIdx,
|
ElemIdx: elemIdx,
|
||||||
Length: length,
|
Length: length,
|
||||||
|
@ -718,9 +646,10 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
|
func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpMapKey,
|
Op: OpMapKey,
|
||||||
|
Type: typ,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: head.ElemIdx,
|
ElemIdx: head.ElemIdx,
|
||||||
|
@ -730,9 +659,10 @@ func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode {
|
func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpMapValue,
|
Op: OpMapValue,
|
||||||
|
Type: typ,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
ElemIdx: head.ElemIdx,
|
ElemIdx: head.ElemIdx,
|
||||||
|
@ -742,14 +672,15 @@ func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
|
func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||||
mapPos := opcodeOffset(ctx.ptrIndex)
|
mapPos := opcodeOffset(ctx.ptrIndex)
|
||||||
ctx.incPtrIndex()
|
ctx.incPtrIndex()
|
||||||
idx := opcodeOffset(ctx.ptrIndex)
|
idx := opcodeOffset(ctx.ptrIndex)
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpMapEnd,
|
Op: OpMapEnd,
|
||||||
|
Type: typ,
|
||||||
Idx: idx,
|
Idx: idx,
|
||||||
Next: newEndOp(ctx),
|
Next: newEndOp(ctx, typ),
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
Length: head.Length,
|
Length: head.Length,
|
||||||
MapPos: mapPos,
|
MapPos: mapPos,
|
||||||
|
@ -757,28 +688,12 @@ func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInterfaceCode(ctx *compileContext) *Opcode {
|
func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode {
|
||||||
var flag OpFlags
|
|
||||||
if ctx.typ.NumMethod() > 0 {
|
|
||||||
flag |= NonEmptyInterfaceFlags
|
|
||||||
}
|
|
||||||
return &Opcode{
|
|
||||||
Op: OpInterface,
|
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
|
||||||
Next: newEndOp(ctx),
|
|
||||||
Type: ctx.typ,
|
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
|
||||||
Indent: ctx.indent,
|
|
||||||
Flags: flag,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRecursiveCode(ctx *compileContext, jmp *CompiledCode) *Opcode {
|
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpRecursive,
|
Op: OpRecursive,
|
||||||
|
Type: typ,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
Next: newEndOp(ctx),
|
Next: newEndOp(ctx, typ),
|
||||||
Type: ctx.typ,
|
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
Jmp: jmp,
|
Jmp: jmp,
|
||||||
|
|
|
@ -22,7 +22,7 @@ const (
|
||||||
CodeStructEnd CodeType = 11
|
CodeStructEnd CodeType = 11
|
||||||
)
|
)
|
||||||
|
|
||||||
var opTypeStrings = [401]string{
|
var opTypeStrings = [400]string{
|
||||||
"End",
|
"End",
|
||||||
"Interface",
|
"Interface",
|
||||||
"Ptr",
|
"Ptr",
|
||||||
|
@ -37,7 +37,6 @@ var opTypeStrings = [401]string{
|
||||||
"RecursivePtr",
|
"RecursivePtr",
|
||||||
"RecursiveEnd",
|
"RecursiveEnd",
|
||||||
"InterfaceEnd",
|
"InterfaceEnd",
|
||||||
"StructAnonymousEnd",
|
|
||||||
"Int",
|
"Int",
|
||||||
"Uint",
|
"Uint",
|
||||||
"Float32",
|
"Float32",
|
||||||
|
@ -443,397 +442,396 @@ const (
|
||||||
OpRecursivePtr OpType = 11
|
OpRecursivePtr OpType = 11
|
||||||
OpRecursiveEnd OpType = 12
|
OpRecursiveEnd OpType = 12
|
||||||
OpInterfaceEnd OpType = 13
|
OpInterfaceEnd OpType = 13
|
||||||
OpStructAnonymousEnd OpType = 14
|
OpInt OpType = 14
|
||||||
OpInt OpType = 15
|
OpUint OpType = 15
|
||||||
OpUint OpType = 16
|
OpFloat32 OpType = 16
|
||||||
OpFloat32 OpType = 17
|
OpFloat64 OpType = 17
|
||||||
OpFloat64 OpType = 18
|
OpBool OpType = 18
|
||||||
OpBool OpType = 19
|
OpString OpType = 19
|
||||||
OpString OpType = 20
|
OpBytes OpType = 20
|
||||||
OpBytes OpType = 21
|
OpNumber OpType = 21
|
||||||
OpNumber OpType = 22
|
OpArray OpType = 22
|
||||||
OpArray OpType = 23
|
OpMap OpType = 23
|
||||||
OpMap OpType = 24
|
OpSlice OpType = 24
|
||||||
OpSlice OpType = 25
|
OpStruct OpType = 25
|
||||||
OpStruct OpType = 26
|
OpMarshalJSON OpType = 26
|
||||||
OpMarshalJSON OpType = 27
|
OpMarshalText OpType = 27
|
||||||
OpMarshalText OpType = 28
|
OpIntString OpType = 28
|
||||||
OpIntString OpType = 29
|
OpUintString OpType = 29
|
||||||
OpUintString OpType = 30
|
OpFloat32String OpType = 30
|
||||||
OpFloat32String OpType = 31
|
OpFloat64String OpType = 31
|
||||||
OpFloat64String OpType = 32
|
OpBoolString OpType = 32
|
||||||
OpBoolString OpType = 33
|
OpStringString OpType = 33
|
||||||
OpStringString OpType = 34
|
OpNumberString OpType = 34
|
||||||
OpNumberString OpType = 35
|
OpIntPtr OpType = 35
|
||||||
OpIntPtr OpType = 36
|
OpUintPtr OpType = 36
|
||||||
OpUintPtr OpType = 37
|
OpFloat32Ptr OpType = 37
|
||||||
OpFloat32Ptr OpType = 38
|
OpFloat64Ptr OpType = 38
|
||||||
OpFloat64Ptr OpType = 39
|
OpBoolPtr OpType = 39
|
||||||
OpBoolPtr OpType = 40
|
OpStringPtr OpType = 40
|
||||||
OpStringPtr OpType = 41
|
OpBytesPtr OpType = 41
|
||||||
OpBytesPtr OpType = 42
|
OpNumberPtr OpType = 42
|
||||||
OpNumberPtr OpType = 43
|
OpArrayPtr OpType = 43
|
||||||
OpArrayPtr OpType = 44
|
OpMapPtr OpType = 44
|
||||||
OpMapPtr OpType = 45
|
OpSlicePtr OpType = 45
|
||||||
OpSlicePtr OpType = 46
|
OpMarshalJSONPtr OpType = 46
|
||||||
OpMarshalJSONPtr OpType = 47
|
OpMarshalTextPtr OpType = 47
|
||||||
OpMarshalTextPtr OpType = 48
|
OpInterfacePtr OpType = 48
|
||||||
OpInterfacePtr OpType = 49
|
OpIntPtrString OpType = 49
|
||||||
OpIntPtrString OpType = 50
|
OpUintPtrString OpType = 50
|
||||||
OpUintPtrString OpType = 51
|
OpFloat32PtrString OpType = 51
|
||||||
OpFloat32PtrString OpType = 52
|
OpFloat64PtrString OpType = 52
|
||||||
OpFloat64PtrString OpType = 53
|
OpBoolPtrString OpType = 53
|
||||||
OpBoolPtrString OpType = 54
|
OpStringPtrString OpType = 54
|
||||||
OpStringPtrString OpType = 55
|
OpNumberPtrString OpType = 55
|
||||||
OpNumberPtrString OpType = 56
|
OpStructHeadInt OpType = 56
|
||||||
OpStructHeadInt OpType = 57
|
OpStructHeadOmitEmptyInt OpType = 57
|
||||||
OpStructHeadOmitEmptyInt OpType = 58
|
OpStructPtrHeadInt OpType = 58
|
||||||
OpStructPtrHeadInt OpType = 59
|
OpStructPtrHeadOmitEmptyInt OpType = 59
|
||||||
OpStructPtrHeadOmitEmptyInt OpType = 60
|
OpStructHeadUint OpType = 60
|
||||||
OpStructHeadUint OpType = 61
|
OpStructHeadOmitEmptyUint OpType = 61
|
||||||
OpStructHeadOmitEmptyUint OpType = 62
|
OpStructPtrHeadUint OpType = 62
|
||||||
OpStructPtrHeadUint OpType = 63
|
OpStructPtrHeadOmitEmptyUint OpType = 63
|
||||||
OpStructPtrHeadOmitEmptyUint OpType = 64
|
OpStructHeadFloat32 OpType = 64
|
||||||
OpStructHeadFloat32 OpType = 65
|
OpStructHeadOmitEmptyFloat32 OpType = 65
|
||||||
OpStructHeadOmitEmptyFloat32 OpType = 66
|
OpStructPtrHeadFloat32 OpType = 66
|
||||||
OpStructPtrHeadFloat32 OpType = 67
|
OpStructPtrHeadOmitEmptyFloat32 OpType = 67
|
||||||
OpStructPtrHeadOmitEmptyFloat32 OpType = 68
|
OpStructHeadFloat64 OpType = 68
|
||||||
OpStructHeadFloat64 OpType = 69
|
OpStructHeadOmitEmptyFloat64 OpType = 69
|
||||||
OpStructHeadOmitEmptyFloat64 OpType = 70
|
OpStructPtrHeadFloat64 OpType = 70
|
||||||
OpStructPtrHeadFloat64 OpType = 71
|
OpStructPtrHeadOmitEmptyFloat64 OpType = 71
|
||||||
OpStructPtrHeadOmitEmptyFloat64 OpType = 72
|
OpStructHeadBool OpType = 72
|
||||||
OpStructHeadBool OpType = 73
|
OpStructHeadOmitEmptyBool OpType = 73
|
||||||
OpStructHeadOmitEmptyBool OpType = 74
|
OpStructPtrHeadBool OpType = 74
|
||||||
OpStructPtrHeadBool OpType = 75
|
OpStructPtrHeadOmitEmptyBool OpType = 75
|
||||||
OpStructPtrHeadOmitEmptyBool OpType = 76
|
OpStructHeadString OpType = 76
|
||||||
OpStructHeadString OpType = 77
|
OpStructHeadOmitEmptyString OpType = 77
|
||||||
OpStructHeadOmitEmptyString OpType = 78
|
OpStructPtrHeadString OpType = 78
|
||||||
OpStructPtrHeadString OpType = 79
|
OpStructPtrHeadOmitEmptyString OpType = 79
|
||||||
OpStructPtrHeadOmitEmptyString OpType = 80
|
OpStructHeadBytes OpType = 80
|
||||||
OpStructHeadBytes OpType = 81
|
OpStructHeadOmitEmptyBytes OpType = 81
|
||||||
OpStructHeadOmitEmptyBytes OpType = 82
|
OpStructPtrHeadBytes OpType = 82
|
||||||
OpStructPtrHeadBytes OpType = 83
|
OpStructPtrHeadOmitEmptyBytes OpType = 83
|
||||||
OpStructPtrHeadOmitEmptyBytes OpType = 84
|
OpStructHeadNumber OpType = 84
|
||||||
OpStructHeadNumber OpType = 85
|
OpStructHeadOmitEmptyNumber OpType = 85
|
||||||
OpStructHeadOmitEmptyNumber OpType = 86
|
OpStructPtrHeadNumber OpType = 86
|
||||||
OpStructPtrHeadNumber OpType = 87
|
OpStructPtrHeadOmitEmptyNumber OpType = 87
|
||||||
OpStructPtrHeadOmitEmptyNumber OpType = 88
|
OpStructHeadArray OpType = 88
|
||||||
OpStructHeadArray OpType = 89
|
OpStructHeadOmitEmptyArray OpType = 89
|
||||||
OpStructHeadOmitEmptyArray OpType = 90
|
OpStructPtrHeadArray OpType = 90
|
||||||
OpStructPtrHeadArray OpType = 91
|
OpStructPtrHeadOmitEmptyArray OpType = 91
|
||||||
OpStructPtrHeadOmitEmptyArray OpType = 92
|
OpStructHeadMap OpType = 92
|
||||||
OpStructHeadMap OpType = 93
|
OpStructHeadOmitEmptyMap OpType = 93
|
||||||
OpStructHeadOmitEmptyMap OpType = 94
|
OpStructPtrHeadMap OpType = 94
|
||||||
OpStructPtrHeadMap OpType = 95
|
OpStructPtrHeadOmitEmptyMap OpType = 95
|
||||||
OpStructPtrHeadOmitEmptyMap OpType = 96
|
OpStructHeadSlice OpType = 96
|
||||||
OpStructHeadSlice OpType = 97
|
OpStructHeadOmitEmptySlice OpType = 97
|
||||||
OpStructHeadOmitEmptySlice OpType = 98
|
OpStructPtrHeadSlice OpType = 98
|
||||||
OpStructPtrHeadSlice OpType = 99
|
OpStructPtrHeadOmitEmptySlice OpType = 99
|
||||||
OpStructPtrHeadOmitEmptySlice OpType = 100
|
OpStructHeadStruct OpType = 100
|
||||||
OpStructHeadStruct OpType = 101
|
OpStructHeadOmitEmptyStruct OpType = 101
|
||||||
OpStructHeadOmitEmptyStruct OpType = 102
|
OpStructPtrHeadStruct OpType = 102
|
||||||
OpStructPtrHeadStruct OpType = 103
|
OpStructPtrHeadOmitEmptyStruct OpType = 103
|
||||||
OpStructPtrHeadOmitEmptyStruct OpType = 104
|
OpStructHeadMarshalJSON OpType = 104
|
||||||
OpStructHeadMarshalJSON OpType = 105
|
OpStructHeadOmitEmptyMarshalJSON OpType = 105
|
||||||
OpStructHeadOmitEmptyMarshalJSON OpType = 106
|
OpStructPtrHeadMarshalJSON OpType = 106
|
||||||
OpStructPtrHeadMarshalJSON OpType = 107
|
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 107
|
||||||
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 108
|
OpStructHeadMarshalText OpType = 108
|
||||||
OpStructHeadMarshalText OpType = 109
|
OpStructHeadOmitEmptyMarshalText OpType = 109
|
||||||
OpStructHeadOmitEmptyMarshalText OpType = 110
|
OpStructPtrHeadMarshalText OpType = 110
|
||||||
OpStructPtrHeadMarshalText OpType = 111
|
OpStructPtrHeadOmitEmptyMarshalText OpType = 111
|
||||||
OpStructPtrHeadOmitEmptyMarshalText OpType = 112
|
OpStructHeadIntString OpType = 112
|
||||||
OpStructHeadIntString OpType = 113
|
OpStructHeadOmitEmptyIntString OpType = 113
|
||||||
OpStructHeadOmitEmptyIntString OpType = 114
|
OpStructPtrHeadIntString OpType = 114
|
||||||
OpStructPtrHeadIntString OpType = 115
|
OpStructPtrHeadOmitEmptyIntString OpType = 115
|
||||||
OpStructPtrHeadOmitEmptyIntString OpType = 116
|
OpStructHeadUintString OpType = 116
|
||||||
OpStructHeadUintString OpType = 117
|
OpStructHeadOmitEmptyUintString OpType = 117
|
||||||
OpStructHeadOmitEmptyUintString OpType = 118
|
OpStructPtrHeadUintString OpType = 118
|
||||||
OpStructPtrHeadUintString OpType = 119
|
OpStructPtrHeadOmitEmptyUintString OpType = 119
|
||||||
OpStructPtrHeadOmitEmptyUintString OpType = 120
|
OpStructHeadFloat32String OpType = 120
|
||||||
OpStructHeadFloat32String OpType = 121
|
OpStructHeadOmitEmptyFloat32String OpType = 121
|
||||||
OpStructHeadOmitEmptyFloat32String OpType = 122
|
OpStructPtrHeadFloat32String OpType = 122
|
||||||
OpStructPtrHeadFloat32String OpType = 123
|
OpStructPtrHeadOmitEmptyFloat32String OpType = 123
|
||||||
OpStructPtrHeadOmitEmptyFloat32String OpType = 124
|
OpStructHeadFloat64String OpType = 124
|
||||||
OpStructHeadFloat64String OpType = 125
|
OpStructHeadOmitEmptyFloat64String OpType = 125
|
||||||
OpStructHeadOmitEmptyFloat64String OpType = 126
|
OpStructPtrHeadFloat64String OpType = 126
|
||||||
OpStructPtrHeadFloat64String OpType = 127
|
OpStructPtrHeadOmitEmptyFloat64String OpType = 127
|
||||||
OpStructPtrHeadOmitEmptyFloat64String OpType = 128
|
OpStructHeadBoolString OpType = 128
|
||||||
OpStructHeadBoolString OpType = 129
|
OpStructHeadOmitEmptyBoolString OpType = 129
|
||||||
OpStructHeadOmitEmptyBoolString OpType = 130
|
OpStructPtrHeadBoolString OpType = 130
|
||||||
OpStructPtrHeadBoolString OpType = 131
|
OpStructPtrHeadOmitEmptyBoolString OpType = 131
|
||||||
OpStructPtrHeadOmitEmptyBoolString OpType = 132
|
OpStructHeadStringString OpType = 132
|
||||||
OpStructHeadStringString OpType = 133
|
OpStructHeadOmitEmptyStringString OpType = 133
|
||||||
OpStructHeadOmitEmptyStringString OpType = 134
|
OpStructPtrHeadStringString OpType = 134
|
||||||
OpStructPtrHeadStringString OpType = 135
|
OpStructPtrHeadOmitEmptyStringString OpType = 135
|
||||||
OpStructPtrHeadOmitEmptyStringString OpType = 136
|
OpStructHeadNumberString OpType = 136
|
||||||
OpStructHeadNumberString OpType = 137
|
OpStructHeadOmitEmptyNumberString OpType = 137
|
||||||
OpStructHeadOmitEmptyNumberString OpType = 138
|
OpStructPtrHeadNumberString OpType = 138
|
||||||
OpStructPtrHeadNumberString OpType = 139
|
OpStructPtrHeadOmitEmptyNumberString OpType = 139
|
||||||
OpStructPtrHeadOmitEmptyNumberString OpType = 140
|
OpStructHeadIntPtr OpType = 140
|
||||||
OpStructHeadIntPtr OpType = 141
|
OpStructHeadOmitEmptyIntPtr OpType = 141
|
||||||
OpStructHeadOmitEmptyIntPtr OpType = 142
|
OpStructPtrHeadIntPtr OpType = 142
|
||||||
OpStructPtrHeadIntPtr OpType = 143
|
OpStructPtrHeadOmitEmptyIntPtr OpType = 143
|
||||||
OpStructPtrHeadOmitEmptyIntPtr OpType = 144
|
OpStructHeadUintPtr OpType = 144
|
||||||
OpStructHeadUintPtr OpType = 145
|
OpStructHeadOmitEmptyUintPtr OpType = 145
|
||||||
OpStructHeadOmitEmptyUintPtr OpType = 146
|
OpStructPtrHeadUintPtr OpType = 146
|
||||||
OpStructPtrHeadUintPtr OpType = 147
|
OpStructPtrHeadOmitEmptyUintPtr OpType = 147
|
||||||
OpStructPtrHeadOmitEmptyUintPtr OpType = 148
|
OpStructHeadFloat32Ptr OpType = 148
|
||||||
OpStructHeadFloat32Ptr OpType = 149
|
OpStructHeadOmitEmptyFloat32Ptr OpType = 149
|
||||||
OpStructHeadOmitEmptyFloat32Ptr OpType = 150
|
OpStructPtrHeadFloat32Ptr OpType = 150
|
||||||
OpStructPtrHeadFloat32Ptr OpType = 151
|
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 151
|
||||||
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 152
|
OpStructHeadFloat64Ptr OpType = 152
|
||||||
OpStructHeadFloat64Ptr OpType = 153
|
OpStructHeadOmitEmptyFloat64Ptr OpType = 153
|
||||||
OpStructHeadOmitEmptyFloat64Ptr OpType = 154
|
OpStructPtrHeadFloat64Ptr OpType = 154
|
||||||
OpStructPtrHeadFloat64Ptr OpType = 155
|
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 155
|
||||||
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 156
|
OpStructHeadBoolPtr OpType = 156
|
||||||
OpStructHeadBoolPtr OpType = 157
|
OpStructHeadOmitEmptyBoolPtr OpType = 157
|
||||||
OpStructHeadOmitEmptyBoolPtr OpType = 158
|
OpStructPtrHeadBoolPtr OpType = 158
|
||||||
OpStructPtrHeadBoolPtr OpType = 159
|
OpStructPtrHeadOmitEmptyBoolPtr OpType = 159
|
||||||
OpStructPtrHeadOmitEmptyBoolPtr OpType = 160
|
OpStructHeadStringPtr OpType = 160
|
||||||
OpStructHeadStringPtr OpType = 161
|
OpStructHeadOmitEmptyStringPtr OpType = 161
|
||||||
OpStructHeadOmitEmptyStringPtr OpType = 162
|
OpStructPtrHeadStringPtr OpType = 162
|
||||||
OpStructPtrHeadStringPtr OpType = 163
|
OpStructPtrHeadOmitEmptyStringPtr OpType = 163
|
||||||
OpStructPtrHeadOmitEmptyStringPtr OpType = 164
|
OpStructHeadBytesPtr OpType = 164
|
||||||
OpStructHeadBytesPtr OpType = 165
|
OpStructHeadOmitEmptyBytesPtr OpType = 165
|
||||||
OpStructHeadOmitEmptyBytesPtr OpType = 166
|
OpStructPtrHeadBytesPtr OpType = 166
|
||||||
OpStructPtrHeadBytesPtr OpType = 167
|
OpStructPtrHeadOmitEmptyBytesPtr OpType = 167
|
||||||
OpStructPtrHeadOmitEmptyBytesPtr OpType = 168
|
OpStructHeadNumberPtr OpType = 168
|
||||||
OpStructHeadNumberPtr OpType = 169
|
OpStructHeadOmitEmptyNumberPtr OpType = 169
|
||||||
OpStructHeadOmitEmptyNumberPtr OpType = 170
|
OpStructPtrHeadNumberPtr OpType = 170
|
||||||
OpStructPtrHeadNumberPtr OpType = 171
|
OpStructPtrHeadOmitEmptyNumberPtr OpType = 171
|
||||||
OpStructPtrHeadOmitEmptyNumberPtr OpType = 172
|
OpStructHeadArrayPtr OpType = 172
|
||||||
OpStructHeadArrayPtr OpType = 173
|
OpStructHeadOmitEmptyArrayPtr OpType = 173
|
||||||
OpStructHeadOmitEmptyArrayPtr OpType = 174
|
OpStructPtrHeadArrayPtr OpType = 174
|
||||||
OpStructPtrHeadArrayPtr OpType = 175
|
OpStructPtrHeadOmitEmptyArrayPtr OpType = 175
|
||||||
OpStructPtrHeadOmitEmptyArrayPtr OpType = 176
|
OpStructHeadMapPtr OpType = 176
|
||||||
OpStructHeadMapPtr OpType = 177
|
OpStructHeadOmitEmptyMapPtr OpType = 177
|
||||||
OpStructHeadOmitEmptyMapPtr OpType = 178
|
OpStructPtrHeadMapPtr OpType = 178
|
||||||
OpStructPtrHeadMapPtr OpType = 179
|
OpStructPtrHeadOmitEmptyMapPtr OpType = 179
|
||||||
OpStructPtrHeadOmitEmptyMapPtr OpType = 180
|
OpStructHeadSlicePtr OpType = 180
|
||||||
OpStructHeadSlicePtr OpType = 181
|
OpStructHeadOmitEmptySlicePtr OpType = 181
|
||||||
OpStructHeadOmitEmptySlicePtr OpType = 182
|
OpStructPtrHeadSlicePtr OpType = 182
|
||||||
OpStructPtrHeadSlicePtr OpType = 183
|
OpStructPtrHeadOmitEmptySlicePtr OpType = 183
|
||||||
OpStructPtrHeadOmitEmptySlicePtr OpType = 184
|
OpStructHeadMarshalJSONPtr OpType = 184
|
||||||
OpStructHeadMarshalJSONPtr OpType = 185
|
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 185
|
||||||
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 186
|
OpStructPtrHeadMarshalJSONPtr OpType = 186
|
||||||
OpStructPtrHeadMarshalJSONPtr OpType = 187
|
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 187
|
||||||
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 188
|
OpStructHeadMarshalTextPtr OpType = 188
|
||||||
OpStructHeadMarshalTextPtr OpType = 189
|
OpStructHeadOmitEmptyMarshalTextPtr OpType = 189
|
||||||
OpStructHeadOmitEmptyMarshalTextPtr OpType = 190
|
OpStructPtrHeadMarshalTextPtr OpType = 190
|
||||||
OpStructPtrHeadMarshalTextPtr OpType = 191
|
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 191
|
||||||
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 192
|
OpStructHeadInterfacePtr OpType = 192
|
||||||
OpStructHeadInterfacePtr OpType = 193
|
OpStructHeadOmitEmptyInterfacePtr OpType = 193
|
||||||
OpStructHeadOmitEmptyInterfacePtr OpType = 194
|
OpStructPtrHeadInterfacePtr OpType = 194
|
||||||
OpStructPtrHeadInterfacePtr OpType = 195
|
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 195
|
||||||
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 196
|
OpStructHeadIntPtrString OpType = 196
|
||||||
OpStructHeadIntPtrString OpType = 197
|
OpStructHeadOmitEmptyIntPtrString OpType = 197
|
||||||
OpStructHeadOmitEmptyIntPtrString OpType = 198
|
OpStructPtrHeadIntPtrString OpType = 198
|
||||||
OpStructPtrHeadIntPtrString OpType = 199
|
OpStructPtrHeadOmitEmptyIntPtrString OpType = 199
|
||||||
OpStructPtrHeadOmitEmptyIntPtrString OpType = 200
|
OpStructHeadUintPtrString OpType = 200
|
||||||
OpStructHeadUintPtrString OpType = 201
|
OpStructHeadOmitEmptyUintPtrString OpType = 201
|
||||||
OpStructHeadOmitEmptyUintPtrString OpType = 202
|
OpStructPtrHeadUintPtrString OpType = 202
|
||||||
OpStructPtrHeadUintPtrString OpType = 203
|
OpStructPtrHeadOmitEmptyUintPtrString OpType = 203
|
||||||
OpStructPtrHeadOmitEmptyUintPtrString OpType = 204
|
OpStructHeadFloat32PtrString OpType = 204
|
||||||
OpStructHeadFloat32PtrString OpType = 205
|
OpStructHeadOmitEmptyFloat32PtrString OpType = 205
|
||||||
OpStructHeadOmitEmptyFloat32PtrString OpType = 206
|
OpStructPtrHeadFloat32PtrString OpType = 206
|
||||||
OpStructPtrHeadFloat32PtrString OpType = 207
|
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 207
|
||||||
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 208
|
OpStructHeadFloat64PtrString OpType = 208
|
||||||
OpStructHeadFloat64PtrString OpType = 209
|
OpStructHeadOmitEmptyFloat64PtrString OpType = 209
|
||||||
OpStructHeadOmitEmptyFloat64PtrString OpType = 210
|
OpStructPtrHeadFloat64PtrString OpType = 210
|
||||||
OpStructPtrHeadFloat64PtrString OpType = 211
|
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 211
|
||||||
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 212
|
OpStructHeadBoolPtrString OpType = 212
|
||||||
OpStructHeadBoolPtrString OpType = 213
|
OpStructHeadOmitEmptyBoolPtrString OpType = 213
|
||||||
OpStructHeadOmitEmptyBoolPtrString OpType = 214
|
OpStructPtrHeadBoolPtrString OpType = 214
|
||||||
OpStructPtrHeadBoolPtrString OpType = 215
|
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 215
|
||||||
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 216
|
OpStructHeadStringPtrString OpType = 216
|
||||||
OpStructHeadStringPtrString OpType = 217
|
OpStructHeadOmitEmptyStringPtrString OpType = 217
|
||||||
OpStructHeadOmitEmptyStringPtrString OpType = 218
|
OpStructPtrHeadStringPtrString OpType = 218
|
||||||
OpStructPtrHeadStringPtrString OpType = 219
|
OpStructPtrHeadOmitEmptyStringPtrString OpType = 219
|
||||||
OpStructPtrHeadOmitEmptyStringPtrString OpType = 220
|
OpStructHeadNumberPtrString OpType = 220
|
||||||
OpStructHeadNumberPtrString OpType = 221
|
OpStructHeadOmitEmptyNumberPtrString OpType = 221
|
||||||
OpStructHeadOmitEmptyNumberPtrString OpType = 222
|
OpStructPtrHeadNumberPtrString OpType = 222
|
||||||
OpStructPtrHeadNumberPtrString OpType = 223
|
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 223
|
||||||
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 224
|
OpStructHead OpType = 224
|
||||||
OpStructHead OpType = 225
|
OpStructHeadOmitEmpty OpType = 225
|
||||||
OpStructHeadOmitEmpty OpType = 226
|
OpStructPtrHead OpType = 226
|
||||||
OpStructPtrHead OpType = 227
|
OpStructPtrHeadOmitEmpty OpType = 227
|
||||||
OpStructPtrHeadOmitEmpty OpType = 228
|
OpStructFieldInt OpType = 228
|
||||||
OpStructFieldInt OpType = 229
|
OpStructFieldOmitEmptyInt OpType = 229
|
||||||
OpStructFieldOmitEmptyInt OpType = 230
|
OpStructEndInt OpType = 230
|
||||||
OpStructEndInt OpType = 231
|
OpStructEndOmitEmptyInt OpType = 231
|
||||||
OpStructEndOmitEmptyInt OpType = 232
|
OpStructFieldUint OpType = 232
|
||||||
OpStructFieldUint OpType = 233
|
OpStructFieldOmitEmptyUint OpType = 233
|
||||||
OpStructFieldOmitEmptyUint OpType = 234
|
OpStructEndUint OpType = 234
|
||||||
OpStructEndUint OpType = 235
|
OpStructEndOmitEmptyUint OpType = 235
|
||||||
OpStructEndOmitEmptyUint OpType = 236
|
OpStructFieldFloat32 OpType = 236
|
||||||
OpStructFieldFloat32 OpType = 237
|
OpStructFieldOmitEmptyFloat32 OpType = 237
|
||||||
OpStructFieldOmitEmptyFloat32 OpType = 238
|
OpStructEndFloat32 OpType = 238
|
||||||
OpStructEndFloat32 OpType = 239
|
OpStructEndOmitEmptyFloat32 OpType = 239
|
||||||
OpStructEndOmitEmptyFloat32 OpType = 240
|
OpStructFieldFloat64 OpType = 240
|
||||||
OpStructFieldFloat64 OpType = 241
|
OpStructFieldOmitEmptyFloat64 OpType = 241
|
||||||
OpStructFieldOmitEmptyFloat64 OpType = 242
|
OpStructEndFloat64 OpType = 242
|
||||||
OpStructEndFloat64 OpType = 243
|
OpStructEndOmitEmptyFloat64 OpType = 243
|
||||||
OpStructEndOmitEmptyFloat64 OpType = 244
|
OpStructFieldBool OpType = 244
|
||||||
OpStructFieldBool OpType = 245
|
OpStructFieldOmitEmptyBool OpType = 245
|
||||||
OpStructFieldOmitEmptyBool OpType = 246
|
OpStructEndBool OpType = 246
|
||||||
OpStructEndBool OpType = 247
|
OpStructEndOmitEmptyBool OpType = 247
|
||||||
OpStructEndOmitEmptyBool OpType = 248
|
OpStructFieldString OpType = 248
|
||||||
OpStructFieldString OpType = 249
|
OpStructFieldOmitEmptyString OpType = 249
|
||||||
OpStructFieldOmitEmptyString OpType = 250
|
OpStructEndString OpType = 250
|
||||||
OpStructEndString OpType = 251
|
OpStructEndOmitEmptyString OpType = 251
|
||||||
OpStructEndOmitEmptyString OpType = 252
|
OpStructFieldBytes OpType = 252
|
||||||
OpStructFieldBytes OpType = 253
|
OpStructFieldOmitEmptyBytes OpType = 253
|
||||||
OpStructFieldOmitEmptyBytes OpType = 254
|
OpStructEndBytes OpType = 254
|
||||||
OpStructEndBytes OpType = 255
|
OpStructEndOmitEmptyBytes OpType = 255
|
||||||
OpStructEndOmitEmptyBytes OpType = 256
|
OpStructFieldNumber OpType = 256
|
||||||
OpStructFieldNumber OpType = 257
|
OpStructFieldOmitEmptyNumber OpType = 257
|
||||||
OpStructFieldOmitEmptyNumber OpType = 258
|
OpStructEndNumber OpType = 258
|
||||||
OpStructEndNumber OpType = 259
|
OpStructEndOmitEmptyNumber OpType = 259
|
||||||
OpStructEndOmitEmptyNumber OpType = 260
|
OpStructFieldArray OpType = 260
|
||||||
OpStructFieldArray OpType = 261
|
OpStructFieldOmitEmptyArray OpType = 261
|
||||||
OpStructFieldOmitEmptyArray OpType = 262
|
OpStructEndArray OpType = 262
|
||||||
OpStructEndArray OpType = 263
|
OpStructEndOmitEmptyArray OpType = 263
|
||||||
OpStructEndOmitEmptyArray OpType = 264
|
OpStructFieldMap OpType = 264
|
||||||
OpStructFieldMap OpType = 265
|
OpStructFieldOmitEmptyMap OpType = 265
|
||||||
OpStructFieldOmitEmptyMap OpType = 266
|
OpStructEndMap OpType = 266
|
||||||
OpStructEndMap OpType = 267
|
OpStructEndOmitEmptyMap OpType = 267
|
||||||
OpStructEndOmitEmptyMap OpType = 268
|
OpStructFieldSlice OpType = 268
|
||||||
OpStructFieldSlice OpType = 269
|
OpStructFieldOmitEmptySlice OpType = 269
|
||||||
OpStructFieldOmitEmptySlice OpType = 270
|
OpStructEndSlice OpType = 270
|
||||||
OpStructEndSlice OpType = 271
|
OpStructEndOmitEmptySlice OpType = 271
|
||||||
OpStructEndOmitEmptySlice OpType = 272
|
OpStructFieldStruct OpType = 272
|
||||||
OpStructFieldStruct OpType = 273
|
OpStructFieldOmitEmptyStruct OpType = 273
|
||||||
OpStructFieldOmitEmptyStruct OpType = 274
|
OpStructEndStruct OpType = 274
|
||||||
OpStructEndStruct OpType = 275
|
OpStructEndOmitEmptyStruct OpType = 275
|
||||||
OpStructEndOmitEmptyStruct OpType = 276
|
OpStructFieldMarshalJSON OpType = 276
|
||||||
OpStructFieldMarshalJSON OpType = 277
|
OpStructFieldOmitEmptyMarshalJSON OpType = 277
|
||||||
OpStructFieldOmitEmptyMarshalJSON OpType = 278
|
OpStructEndMarshalJSON OpType = 278
|
||||||
OpStructEndMarshalJSON OpType = 279
|
OpStructEndOmitEmptyMarshalJSON OpType = 279
|
||||||
OpStructEndOmitEmptyMarshalJSON OpType = 280
|
OpStructFieldMarshalText OpType = 280
|
||||||
OpStructFieldMarshalText OpType = 281
|
OpStructFieldOmitEmptyMarshalText OpType = 281
|
||||||
OpStructFieldOmitEmptyMarshalText OpType = 282
|
OpStructEndMarshalText OpType = 282
|
||||||
OpStructEndMarshalText OpType = 283
|
OpStructEndOmitEmptyMarshalText OpType = 283
|
||||||
OpStructEndOmitEmptyMarshalText OpType = 284
|
OpStructFieldIntString OpType = 284
|
||||||
OpStructFieldIntString OpType = 285
|
OpStructFieldOmitEmptyIntString OpType = 285
|
||||||
OpStructFieldOmitEmptyIntString OpType = 286
|
OpStructEndIntString OpType = 286
|
||||||
OpStructEndIntString OpType = 287
|
OpStructEndOmitEmptyIntString OpType = 287
|
||||||
OpStructEndOmitEmptyIntString OpType = 288
|
OpStructFieldUintString OpType = 288
|
||||||
OpStructFieldUintString OpType = 289
|
OpStructFieldOmitEmptyUintString OpType = 289
|
||||||
OpStructFieldOmitEmptyUintString OpType = 290
|
OpStructEndUintString OpType = 290
|
||||||
OpStructEndUintString OpType = 291
|
OpStructEndOmitEmptyUintString OpType = 291
|
||||||
OpStructEndOmitEmptyUintString OpType = 292
|
OpStructFieldFloat32String OpType = 292
|
||||||
OpStructFieldFloat32String OpType = 293
|
OpStructFieldOmitEmptyFloat32String OpType = 293
|
||||||
OpStructFieldOmitEmptyFloat32String OpType = 294
|
OpStructEndFloat32String OpType = 294
|
||||||
OpStructEndFloat32String OpType = 295
|
OpStructEndOmitEmptyFloat32String OpType = 295
|
||||||
OpStructEndOmitEmptyFloat32String OpType = 296
|
OpStructFieldFloat64String OpType = 296
|
||||||
OpStructFieldFloat64String OpType = 297
|
OpStructFieldOmitEmptyFloat64String OpType = 297
|
||||||
OpStructFieldOmitEmptyFloat64String OpType = 298
|
OpStructEndFloat64String OpType = 298
|
||||||
OpStructEndFloat64String OpType = 299
|
OpStructEndOmitEmptyFloat64String OpType = 299
|
||||||
OpStructEndOmitEmptyFloat64String OpType = 300
|
OpStructFieldBoolString OpType = 300
|
||||||
OpStructFieldBoolString OpType = 301
|
OpStructFieldOmitEmptyBoolString OpType = 301
|
||||||
OpStructFieldOmitEmptyBoolString OpType = 302
|
OpStructEndBoolString OpType = 302
|
||||||
OpStructEndBoolString OpType = 303
|
OpStructEndOmitEmptyBoolString OpType = 303
|
||||||
OpStructEndOmitEmptyBoolString OpType = 304
|
OpStructFieldStringString OpType = 304
|
||||||
OpStructFieldStringString OpType = 305
|
OpStructFieldOmitEmptyStringString OpType = 305
|
||||||
OpStructFieldOmitEmptyStringString OpType = 306
|
OpStructEndStringString OpType = 306
|
||||||
OpStructEndStringString OpType = 307
|
OpStructEndOmitEmptyStringString OpType = 307
|
||||||
OpStructEndOmitEmptyStringString OpType = 308
|
OpStructFieldNumberString OpType = 308
|
||||||
OpStructFieldNumberString OpType = 309
|
OpStructFieldOmitEmptyNumberString OpType = 309
|
||||||
OpStructFieldOmitEmptyNumberString OpType = 310
|
OpStructEndNumberString OpType = 310
|
||||||
OpStructEndNumberString OpType = 311
|
OpStructEndOmitEmptyNumberString OpType = 311
|
||||||
OpStructEndOmitEmptyNumberString OpType = 312
|
OpStructFieldIntPtr OpType = 312
|
||||||
OpStructFieldIntPtr OpType = 313
|
OpStructFieldOmitEmptyIntPtr OpType = 313
|
||||||
OpStructFieldOmitEmptyIntPtr OpType = 314
|
OpStructEndIntPtr OpType = 314
|
||||||
OpStructEndIntPtr OpType = 315
|
OpStructEndOmitEmptyIntPtr OpType = 315
|
||||||
OpStructEndOmitEmptyIntPtr OpType = 316
|
OpStructFieldUintPtr OpType = 316
|
||||||
OpStructFieldUintPtr OpType = 317
|
OpStructFieldOmitEmptyUintPtr OpType = 317
|
||||||
OpStructFieldOmitEmptyUintPtr OpType = 318
|
OpStructEndUintPtr OpType = 318
|
||||||
OpStructEndUintPtr OpType = 319
|
OpStructEndOmitEmptyUintPtr OpType = 319
|
||||||
OpStructEndOmitEmptyUintPtr OpType = 320
|
OpStructFieldFloat32Ptr OpType = 320
|
||||||
OpStructFieldFloat32Ptr OpType = 321
|
OpStructFieldOmitEmptyFloat32Ptr OpType = 321
|
||||||
OpStructFieldOmitEmptyFloat32Ptr OpType = 322
|
OpStructEndFloat32Ptr OpType = 322
|
||||||
OpStructEndFloat32Ptr OpType = 323
|
OpStructEndOmitEmptyFloat32Ptr OpType = 323
|
||||||
OpStructEndOmitEmptyFloat32Ptr OpType = 324
|
OpStructFieldFloat64Ptr OpType = 324
|
||||||
OpStructFieldFloat64Ptr OpType = 325
|
OpStructFieldOmitEmptyFloat64Ptr OpType = 325
|
||||||
OpStructFieldOmitEmptyFloat64Ptr OpType = 326
|
OpStructEndFloat64Ptr OpType = 326
|
||||||
OpStructEndFloat64Ptr OpType = 327
|
OpStructEndOmitEmptyFloat64Ptr OpType = 327
|
||||||
OpStructEndOmitEmptyFloat64Ptr OpType = 328
|
OpStructFieldBoolPtr OpType = 328
|
||||||
OpStructFieldBoolPtr OpType = 329
|
OpStructFieldOmitEmptyBoolPtr OpType = 329
|
||||||
OpStructFieldOmitEmptyBoolPtr OpType = 330
|
OpStructEndBoolPtr OpType = 330
|
||||||
OpStructEndBoolPtr OpType = 331
|
OpStructEndOmitEmptyBoolPtr OpType = 331
|
||||||
OpStructEndOmitEmptyBoolPtr OpType = 332
|
OpStructFieldStringPtr OpType = 332
|
||||||
OpStructFieldStringPtr OpType = 333
|
OpStructFieldOmitEmptyStringPtr OpType = 333
|
||||||
OpStructFieldOmitEmptyStringPtr OpType = 334
|
OpStructEndStringPtr OpType = 334
|
||||||
OpStructEndStringPtr OpType = 335
|
OpStructEndOmitEmptyStringPtr OpType = 335
|
||||||
OpStructEndOmitEmptyStringPtr OpType = 336
|
OpStructFieldBytesPtr OpType = 336
|
||||||
OpStructFieldBytesPtr OpType = 337
|
OpStructFieldOmitEmptyBytesPtr OpType = 337
|
||||||
OpStructFieldOmitEmptyBytesPtr OpType = 338
|
OpStructEndBytesPtr OpType = 338
|
||||||
OpStructEndBytesPtr OpType = 339
|
OpStructEndOmitEmptyBytesPtr OpType = 339
|
||||||
OpStructEndOmitEmptyBytesPtr OpType = 340
|
OpStructFieldNumberPtr OpType = 340
|
||||||
OpStructFieldNumberPtr OpType = 341
|
OpStructFieldOmitEmptyNumberPtr OpType = 341
|
||||||
OpStructFieldOmitEmptyNumberPtr OpType = 342
|
OpStructEndNumberPtr OpType = 342
|
||||||
OpStructEndNumberPtr OpType = 343
|
OpStructEndOmitEmptyNumberPtr OpType = 343
|
||||||
OpStructEndOmitEmptyNumberPtr OpType = 344
|
OpStructFieldArrayPtr OpType = 344
|
||||||
OpStructFieldArrayPtr OpType = 345
|
OpStructFieldOmitEmptyArrayPtr OpType = 345
|
||||||
OpStructFieldOmitEmptyArrayPtr OpType = 346
|
OpStructEndArrayPtr OpType = 346
|
||||||
OpStructEndArrayPtr OpType = 347
|
OpStructEndOmitEmptyArrayPtr OpType = 347
|
||||||
OpStructEndOmitEmptyArrayPtr OpType = 348
|
OpStructFieldMapPtr OpType = 348
|
||||||
OpStructFieldMapPtr OpType = 349
|
OpStructFieldOmitEmptyMapPtr OpType = 349
|
||||||
OpStructFieldOmitEmptyMapPtr OpType = 350
|
OpStructEndMapPtr OpType = 350
|
||||||
OpStructEndMapPtr OpType = 351
|
OpStructEndOmitEmptyMapPtr OpType = 351
|
||||||
OpStructEndOmitEmptyMapPtr OpType = 352
|
OpStructFieldSlicePtr OpType = 352
|
||||||
OpStructFieldSlicePtr OpType = 353
|
OpStructFieldOmitEmptySlicePtr OpType = 353
|
||||||
OpStructFieldOmitEmptySlicePtr OpType = 354
|
OpStructEndSlicePtr OpType = 354
|
||||||
OpStructEndSlicePtr OpType = 355
|
OpStructEndOmitEmptySlicePtr OpType = 355
|
||||||
OpStructEndOmitEmptySlicePtr OpType = 356
|
OpStructFieldMarshalJSONPtr OpType = 356
|
||||||
OpStructFieldMarshalJSONPtr OpType = 357
|
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 357
|
||||||
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 358
|
OpStructEndMarshalJSONPtr OpType = 358
|
||||||
OpStructEndMarshalJSONPtr OpType = 359
|
OpStructEndOmitEmptyMarshalJSONPtr OpType = 359
|
||||||
OpStructEndOmitEmptyMarshalJSONPtr OpType = 360
|
OpStructFieldMarshalTextPtr OpType = 360
|
||||||
OpStructFieldMarshalTextPtr OpType = 361
|
OpStructFieldOmitEmptyMarshalTextPtr OpType = 361
|
||||||
OpStructFieldOmitEmptyMarshalTextPtr OpType = 362
|
OpStructEndMarshalTextPtr OpType = 362
|
||||||
OpStructEndMarshalTextPtr OpType = 363
|
OpStructEndOmitEmptyMarshalTextPtr OpType = 363
|
||||||
OpStructEndOmitEmptyMarshalTextPtr OpType = 364
|
OpStructFieldInterfacePtr OpType = 364
|
||||||
OpStructFieldInterfacePtr OpType = 365
|
OpStructFieldOmitEmptyInterfacePtr OpType = 365
|
||||||
OpStructFieldOmitEmptyInterfacePtr OpType = 366
|
OpStructEndInterfacePtr OpType = 366
|
||||||
OpStructEndInterfacePtr OpType = 367
|
OpStructEndOmitEmptyInterfacePtr OpType = 367
|
||||||
OpStructEndOmitEmptyInterfacePtr OpType = 368
|
OpStructFieldIntPtrString OpType = 368
|
||||||
OpStructFieldIntPtrString OpType = 369
|
OpStructFieldOmitEmptyIntPtrString OpType = 369
|
||||||
OpStructFieldOmitEmptyIntPtrString OpType = 370
|
OpStructEndIntPtrString OpType = 370
|
||||||
OpStructEndIntPtrString OpType = 371
|
OpStructEndOmitEmptyIntPtrString OpType = 371
|
||||||
OpStructEndOmitEmptyIntPtrString OpType = 372
|
OpStructFieldUintPtrString OpType = 372
|
||||||
OpStructFieldUintPtrString OpType = 373
|
OpStructFieldOmitEmptyUintPtrString OpType = 373
|
||||||
OpStructFieldOmitEmptyUintPtrString OpType = 374
|
OpStructEndUintPtrString OpType = 374
|
||||||
OpStructEndUintPtrString OpType = 375
|
OpStructEndOmitEmptyUintPtrString OpType = 375
|
||||||
OpStructEndOmitEmptyUintPtrString OpType = 376
|
OpStructFieldFloat32PtrString OpType = 376
|
||||||
OpStructFieldFloat32PtrString OpType = 377
|
OpStructFieldOmitEmptyFloat32PtrString OpType = 377
|
||||||
OpStructFieldOmitEmptyFloat32PtrString OpType = 378
|
OpStructEndFloat32PtrString OpType = 378
|
||||||
OpStructEndFloat32PtrString OpType = 379
|
OpStructEndOmitEmptyFloat32PtrString OpType = 379
|
||||||
OpStructEndOmitEmptyFloat32PtrString OpType = 380
|
OpStructFieldFloat64PtrString OpType = 380
|
||||||
OpStructFieldFloat64PtrString OpType = 381
|
OpStructFieldOmitEmptyFloat64PtrString OpType = 381
|
||||||
OpStructFieldOmitEmptyFloat64PtrString OpType = 382
|
OpStructEndFloat64PtrString OpType = 382
|
||||||
OpStructEndFloat64PtrString OpType = 383
|
OpStructEndOmitEmptyFloat64PtrString OpType = 383
|
||||||
OpStructEndOmitEmptyFloat64PtrString OpType = 384
|
OpStructFieldBoolPtrString OpType = 384
|
||||||
OpStructFieldBoolPtrString OpType = 385
|
OpStructFieldOmitEmptyBoolPtrString OpType = 385
|
||||||
OpStructFieldOmitEmptyBoolPtrString OpType = 386
|
OpStructEndBoolPtrString OpType = 386
|
||||||
OpStructEndBoolPtrString OpType = 387
|
OpStructEndOmitEmptyBoolPtrString OpType = 387
|
||||||
OpStructEndOmitEmptyBoolPtrString OpType = 388
|
OpStructFieldStringPtrString OpType = 388
|
||||||
OpStructFieldStringPtrString OpType = 389
|
OpStructFieldOmitEmptyStringPtrString OpType = 389
|
||||||
OpStructFieldOmitEmptyStringPtrString OpType = 390
|
OpStructEndStringPtrString OpType = 390
|
||||||
OpStructEndStringPtrString OpType = 391
|
OpStructEndOmitEmptyStringPtrString OpType = 391
|
||||||
OpStructEndOmitEmptyStringPtrString OpType = 392
|
OpStructFieldNumberPtrString OpType = 392
|
||||||
OpStructFieldNumberPtrString OpType = 393
|
OpStructFieldOmitEmptyNumberPtrString OpType = 393
|
||||||
OpStructFieldOmitEmptyNumberPtrString OpType = 394
|
OpStructEndNumberPtrString OpType = 394
|
||||||
OpStructEndNumberPtrString OpType = 395
|
OpStructEndOmitEmptyNumberPtrString OpType = 395
|
||||||
OpStructEndOmitEmptyNumberPtrString OpType = 396
|
OpStructField OpType = 396
|
||||||
OpStructField OpType = 397
|
OpStructFieldOmitEmpty OpType = 397
|
||||||
OpStructFieldOmitEmpty OpType = 398
|
OpStructEnd OpType = 398
|
||||||
OpStructEnd OpType = 399
|
OpStructEndOmitEmpty OpType = 399
|
||||||
OpStructEndOmitEmpty OpType = 400
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t OpType) String() string {
|
func (t OpType) String() string {
|
||||||
if int(t) >= 401 {
|
if int(t) >= 400 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return opTypeStrings[int(t)]
|
return opTypeStrings[int(t)]
|
||||||
|
|
|
@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.Next
|
code = code.Next
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
}
|
}
|
||||||
case encoder.OpStructAnonymousEnd:
|
|
||||||
code = code.Next
|
|
||||||
case encoder.OpStructEnd:
|
case encoder.OpStructEnd:
|
||||||
b = appendStructEndSkipLast(ctx, code, b)
|
b = appendStructEndSkipLast(ctx, code, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
|
|
|
@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.Next
|
code = code.Next
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
}
|
}
|
||||||
case encoder.OpStructAnonymousEnd:
|
|
||||||
code = code.Next
|
|
||||||
case encoder.OpStructEnd:
|
case encoder.OpStructEnd:
|
||||||
b = appendStructEndSkipLast(ctx, code, b)
|
b = appendStructEndSkipLast(ctx, code, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
|
|
|
@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.Next
|
code = code.Next
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
}
|
}
|
||||||
case encoder.OpStructAnonymousEnd:
|
|
||||||
code = code.Next
|
|
||||||
case encoder.OpStructEnd:
|
case encoder.OpStructEnd:
|
||||||
b = appendStructEndSkipLast(ctx, code, b)
|
b = appendStructEndSkipLast(ctx, code, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
|
|
|
@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
code = code.Next
|
code = code.Next
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
}
|
}
|
||||||
case encoder.OpStructAnonymousEnd:
|
|
||||||
code = code.Next
|
|
||||||
case encoder.OpStructEnd:
|
case encoder.OpStructEnd:
|
||||||
b = appendStructEndSkipLast(ctx, code, b)
|
b = appendStructEndSkipLast(ctx, code, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
|
|
|
@ -11,8 +11,8 @@ func TestOpcodeSize(t *testing.T) {
|
||||||
const uintptrSize = 4 << (^uintptr(0) >> 63)
|
const uintptrSize = 4 << (^uintptr(0) >> 63)
|
||||||
if uintptrSize == 8 {
|
if uintptrSize == 8 {
|
||||||
size := unsafe.Sizeof(encoder.Opcode{})
|
size := unsafe.Sizeof(encoder.Opcode{})
|
||||||
if size != 128 {
|
if size != 120 {
|
||||||
t.Fatalf("unexpected opcode size: expected 128bytes but got %dbytes", size)
|
t.Fatalf("unexpected opcode size: expected 120bytes but got %dbytes", size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package json_test
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
stdjson "encoding/json"
|
stdjson "encoding/json"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -2653,19 +2654,21 @@ func TestCoverBool(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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1807,19 +1808,21 @@ func TestCoverBytes(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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -2334,19 +2335,21 @@ func TestCoverFloat32(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -2334,19 +2335,21 @@ func TestCoverFloat64(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1811,19 +1812,21 @@ func TestCoverInt16(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1788,19 +1789,21 @@ func TestCoverInt32(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1788,19 +1789,21 @@ func TestCoverInt64(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1788,19 +1789,21 @@ func TestCoverInt8(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -2410,19 +2411,21 @@ func TestCoverInt(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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1881,19 +1882,21 @@ func TestCoverMap(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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3690,19 +3690,21 @@ func TestCoverMarshalJSON(t *testing.T) {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -3527,19 +3528,21 @@ func TestCoverMarshalText(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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -2334,19 +2335,21 @@ func TestCoverNumber(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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -2047,9 +2048,9 @@ func TestCoverSlice(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
for _, indent := range []bool{true, false} {
|
||||||
for _, indent := range []bool{true, false} {
|
for _, htmlEscape := range []bool{true, false} {
|
||||||
for _, htmlEscape := range []bool{true, false} {
|
t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := json.NewEncoder(&buf)
|
enc := json.NewEncoder(&buf)
|
||||||
enc.SetEscapeHTML(htmlEscape)
|
enc.SetEscapeHTML(htmlEscape)
|
||||||
|
@ -2063,8 +2064,8 @@ func TestCoverSlice(t *testing.T) {
|
||||||
if buf.String() != stdresult {
|
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.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -2370,19 +2371,21 @@ func TestCoverString(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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1788,19 +1789,21 @@ func TestCoverUint16(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())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1788,19 +1789,21 @@ func TestCoverUint32(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1788,19 +1789,21 @@ func TestCoverUint64(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -1788,19 +1789,21 @@ func TestCoverUint8(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package json_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -2334,19 +2335,21 @@ func TestCoverUint(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:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
if err := enc.Encode(test.data); err != nil {
|
||||||
}
|
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
|
||||||
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
}
|
||||||
if buf.String() != stdresult {
|
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
|
||||||
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
if buf.String() != stdresult {
|
||||||
}
|
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue