mirror of https://github.com/goccy/go-json.git
Refactor encode option
This commit is contained in:
parent
ca4e811a0b
commit
a56c080959
112
encode.go
112
encode.go
|
@ -20,15 +20,6 @@ type Encoder struct {
|
||||||
indentStr string
|
indentStr string
|
||||||
}
|
}
|
||||||
|
|
||||||
type EncodeOption int
|
|
||||||
|
|
||||||
const (
|
|
||||||
EncodeOptionHTMLEscape EncodeOption = 1 << iota
|
|
||||||
EncodeOptionIndent
|
|
||||||
EncodeOptionUnorderedMap
|
|
||||||
EncodeOptionDebug
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewEncoder returns a new encoder that writes to w.
|
// NewEncoder returns a new encoder that writes to w.
|
||||||
func NewEncoder(w io.Writer) *Encoder {
|
func NewEncoder(w io.Writer) *Encoder {
|
||||||
return &Encoder{w: w, enabledHTMLEscape: true}
|
return &Encoder{w: w, enabledHTMLEscape: true}
|
||||||
|
@ -52,21 +43,21 @@ func (e *Encoder) EncodeWithOption(v interface{}, optFuncs ...EncodeOptionFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, optFuncs ...EncodeOptionFunc) error {
|
func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, optFuncs ...EncodeOptionFunc) error {
|
||||||
var opt EncodeOption
|
initOption(ctx.Option)
|
||||||
if e.enabledHTMLEscape {
|
if e.enabledHTMLEscape {
|
||||||
opt |= EncodeOptionHTMLEscape
|
ctx.Option.HTMLEscape = true
|
||||||
}
|
}
|
||||||
for _, optFunc := range optFuncs {
|
for _, optFunc := range optFuncs {
|
||||||
opt = optFunc(opt)
|
optFunc(ctx.Option)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
buf []byte
|
buf []byte
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if e.enabledIndent {
|
if e.enabledIndent {
|
||||||
buf, err = encodeIndent(ctx, v, e.prefix, e.indentStr, opt)
|
buf, err = encodeIndent(ctx, v, e.prefix, e.indentStr)
|
||||||
} else {
|
} else {
|
||||||
buf, err = encode(ctx, v, opt)
|
buf, err = encode(ctx, v)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -103,10 +94,16 @@ func (e *Encoder) SetIndent(prefix, indent string) {
|
||||||
e.enabledIndent = true
|
e.enabledIndent = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshal(v interface{}, opt EncodeOption) ([]byte, error) {
|
func marshal(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||||
ctx := encoder.TakeRuntimeContext()
|
ctx := encoder.TakeRuntimeContext()
|
||||||
|
|
||||||
buf, err := encode(ctx, v, opt|EncodeOptionHTMLEscape)
|
initOption(ctx.Option)
|
||||||
|
ctx.Option.HTMLEscape = true
|
||||||
|
for _, optFunc := range optFuncs {
|
||||||
|
optFunc(ctx.Option)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := encode(ctx, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
encoder.ReleaseRuntimeContext(ctx)
|
encoder.ReleaseRuntimeContext(ctx)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -124,10 +121,13 @@ func marshal(v interface{}, opt EncodeOption) ([]byte, error) {
|
||||||
return copied, nil
|
return copied, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) {
|
func marshalNoEscape(v interface{}) ([]byte, error) {
|
||||||
ctx := encoder.TakeRuntimeContext()
|
ctx := encoder.TakeRuntimeContext()
|
||||||
|
|
||||||
buf, err := encodeNoEscape(ctx, v, opt|EncodeOptionHTMLEscape)
|
initOption(ctx.Option)
|
||||||
|
ctx.Option.HTMLEscape = true
|
||||||
|
|
||||||
|
buf, err := encodeNoEscape(ctx, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
encoder.ReleaseRuntimeContext(ctx)
|
encoder.ReleaseRuntimeContext(ctx)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -145,10 +145,17 @@ func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) {
|
||||||
return copied, nil
|
return copied, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalIndent(v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) {
|
func marshalIndent(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||||
ctx := encoder.TakeRuntimeContext()
|
ctx := encoder.TakeRuntimeContext()
|
||||||
|
|
||||||
buf, err := encodeIndent(ctx, v, prefix, indent, opt|EncodeOptionHTMLEscape)
|
initOption(ctx.Option)
|
||||||
|
ctx.Option.HTMLEscape = true
|
||||||
|
ctx.Option.Indent = true
|
||||||
|
for _, optFunc := range optFuncs {
|
||||||
|
optFunc(ctx.Option)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := encodeIndent(ctx, v, prefix, indent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
encoder.ReleaseRuntimeContext(ctx)
|
encoder.ReleaseRuntimeContext(ctx)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -162,7 +169,7 @@ func marshalIndent(v interface{}, prefix, indent string, opt EncodeOption) ([]by
|
||||||
return copied, nil
|
return copied, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byte, error) {
|
func encode(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) {
|
||||||
b := ctx.Buf[:0]
|
b := ctx.Buf[:0]
|
||||||
if v == nil {
|
if v == nil {
|
||||||
b = encoder.AppendNull(b)
|
b = encoder.AppendNull(b)
|
||||||
|
@ -180,7 +187,7 @@ func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byt
|
||||||
|
|
||||||
p := uintptr(header.ptr)
|
p := uintptr(header.ptr)
|
||||||
var code *encoder.Opcode
|
var code *encoder.Opcode
|
||||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
if ctx.Option.HTMLEscape {
|
||||||
code = codeSet.EscapeKeyCode
|
code = codeSet.EscapeKeyCode
|
||||||
} else {
|
} else {
|
||||||
code = codeSet.NoescapeKeyCode
|
code = codeSet.NoescapeKeyCode
|
||||||
|
@ -188,7 +195,7 @@ func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byt
|
||||||
ctx.Init(code, p, codeSet.CodeLength)
|
ctx.Init(code, p, codeSet.CodeLength)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
|
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
|
||||||
|
|
||||||
buf, err := encodeRunCode(ctx, b, codeSet, opt)
|
buf, err := encodeRunCode(ctx, b, codeSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -196,7 +203,7 @@ func encode(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byt
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption) ([]byte, error) {
|
func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) {
|
||||||
b := ctx.Buf[:0]
|
b := ctx.Buf[:0]
|
||||||
if v == nil {
|
if v == nil {
|
||||||
b = encoder.AppendNull(b)
|
b = encoder.AppendNull(b)
|
||||||
|
@ -213,14 +220,14 @@ func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption
|
||||||
}
|
}
|
||||||
|
|
||||||
var code *encoder.Opcode
|
var code *encoder.Opcode
|
||||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
if ctx.Option.HTMLEscape {
|
||||||
code = codeSet.EscapeKeyCode
|
code = codeSet.EscapeKeyCode
|
||||||
} else {
|
} else {
|
||||||
code = codeSet.NoescapeKeyCode
|
code = codeSet.NoescapeKeyCode
|
||||||
}
|
}
|
||||||
p := uintptr(header.ptr)
|
p := uintptr(header.ptr)
|
||||||
ctx.Init(code, p, codeSet.CodeLength)
|
ctx.Init(code, p, codeSet.CodeLength)
|
||||||
buf, err := encodeRunCode(ctx, b, codeSet, opt)
|
buf, err := encodeRunCode(ctx, b, codeSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -229,7 +236,7 @@ func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}, opt EncodeOption
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) {
|
func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent string) ([]byte, error) {
|
||||||
b := ctx.Buf[:0]
|
b := ctx.Buf[:0]
|
||||||
if v == nil {
|
if v == nil {
|
||||||
b = encoder.AppendNull(b)
|
b = encoder.AppendNull(b)
|
||||||
|
@ -246,14 +253,14 @@ func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent str
|
||||||
}
|
}
|
||||||
|
|
||||||
var code *encoder.Opcode
|
var code *encoder.Opcode
|
||||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
if ctx.Option.HTMLEscape {
|
||||||
code = codeSet.EscapeKeyCode
|
code = codeSet.EscapeKeyCode
|
||||||
} else {
|
} else {
|
||||||
code = codeSet.NoescapeKeyCode
|
code = codeSet.NoescapeKeyCode
|
||||||
}
|
}
|
||||||
p := uintptr(header.ptr)
|
p := uintptr(header.ptr)
|
||||||
ctx.Init(code, p, codeSet.CodeLength)
|
ctx.Init(code, p, codeSet.CodeLength)
|
||||||
buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent, opt)
|
buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent)
|
||||||
|
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
|
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
|
||||||
|
|
||||||
|
@ -265,38 +272,45 @@ func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent str
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt EncodeOption) ([]byte, error) {
|
func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
if (opt & EncodeOptionDebug) != 0 {
|
if ctx.Option.Debug {
|
||||||
return encodeDebugRunCode(ctx, b, codeSet, opt)
|
return encodeDebugRunCode(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
if ctx.Option.HTMLEscape {
|
||||||
return vm_escaped.Run(ctx, b, codeSet, encoder.Option(opt))
|
return vm_escaped.Run(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
return vm.Run(ctx, b, codeSet, encoder.Option(opt))
|
return vm.Run(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeDebugRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt EncodeOption) ([]byte, error) {
|
func encodeDebugRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
if ctx.Option.HTMLEscape {
|
||||||
return vm_escaped.DebugRun(ctx, b, codeSet, encoder.Option(opt))
|
return vm_escaped.DebugRun(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
return vm.DebugRun(ctx, b, codeSet, encoder.Option(opt))
|
return vm.DebugRun(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, prefix, indent string, opt EncodeOption) ([]byte, error) {
|
func encodeRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, prefix, indent string) ([]byte, error) {
|
||||||
ctx.Prefix = []byte(prefix)
|
ctx.Prefix = []byte(prefix)
|
||||||
ctx.IndentStr = []byte(indent)
|
ctx.IndentStr = []byte(indent)
|
||||||
if (opt & EncodeOptionDebug) != 0 {
|
if ctx.Option.Debug {
|
||||||
return encodeDebugRunIndentCode(ctx, b, codeSet, opt)
|
return encodeDebugRunIndentCode(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
if ctx.Option.HTMLEscape {
|
||||||
return vm_escaped_indent.Run(ctx, b, codeSet, encoder.Option(opt))
|
return vm_escaped_indent.Run(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
return vm_indent.Run(ctx, b, codeSet, encoder.Option(opt))
|
return vm_indent.Run(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeDebugRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt EncodeOption) ([]byte, error) {
|
func encodeDebugRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
if (opt & EncodeOptionHTMLEscape) != 0 {
|
if ctx.Option.HTMLEscape {
|
||||||
return vm_escaped_indent.DebugRun(ctx, b, codeSet, encoder.Option(opt))
|
return vm_escaped_indent.DebugRun(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
return vm_indent.DebugRun(ctx, b, codeSet, encoder.Option(opt))
|
return vm_indent.DebugRun(ctx, b, codeSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initOption(opt *EncodeOption) {
|
||||||
|
opt.HTMLEscape = false
|
||||||
|
opt.Indent = false
|
||||||
|
opt.UnorderedMap = false
|
||||||
|
opt.Debug = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
recursiveLevel := 0
|
recursiveLevel := 0
|
||||||
ptrOffset := uintptr(0)
|
ptrOffset := uintptr(0)
|
||||||
ctxptr := ctx.Ptr()
|
ctxptr := ctx.Ptr()
|
||||||
|
@ -185,7 +185,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bb, err := appendInterface(ctx, codeSet, opt, code, b, iface, ptrOffset)
|
bb, err := appendInterface(ctx, codeSet, code, b, iface, ptrOffset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -365,13 +365,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.ElemIdx, 0)
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
store(ctxptr, code.Length, uintptr(mlen))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
store(ctxptr, code.MapIter, uintptr(iter))
|
||||||
if (opt & encoder.UnorderedMapOption) == 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
} else {
|
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
|
@ -380,7 +380,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
idx := load(ctxptr, code.ElemIdx)
|
||||||
length := load(ctxptr, code.Length)
|
length := load(ctxptr, code.Length)
|
||||||
idx++
|
idx++
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
if idx < length {
|
if idx < length {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
store(ctxptr, code.ElemIdx, idx)
|
||||||
|
@ -409,7 +409,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
b = appendColon(b)
|
b = appendColon(b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
ptr := load(ctxptr, code.End.MapPos)
|
||||||
|
|
|
@ -97,6 +97,7 @@ var (
|
||||||
Buf: make([]byte, 0, bufSize),
|
Buf: make([]byte, 0, bufSize),
|
||||||
Ptrs: make([]uintptr, 128),
|
Ptrs: make([]uintptr, 128),
|
||||||
KeepRefs: make([]unsafe.Pointer, 0, 8),
|
KeepRefs: make([]unsafe.Pointer, 0, 8),
|
||||||
|
Option: &Option{},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -112,6 +113,7 @@ type RuntimeContext struct {
|
||||||
Prefix []byte
|
Prefix []byte
|
||||||
IndentStr []byte
|
IndentStr []byte
|
||||||
Code *Opcode
|
Code *Opcode
|
||||||
|
Option *Option
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RuntimeContext) Init(code *Opcode, p uintptr, codelen int) {
|
func (c *RuntimeContext) Init(code *Opcode, p uintptr, codelen int) {
|
||||||
|
|
|
@ -17,14 +17,6 @@ import (
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Option int
|
|
||||||
|
|
||||||
const (
|
|
||||||
HTMLEscapeOption Option = 1 << iota
|
|
||||||
IndentOption
|
|
||||||
UnorderedMapOption
|
|
||||||
)
|
|
||||||
|
|
||||||
func (t OpType) IsMultipleOpHead() bool {
|
func (t OpType) IsMultipleOpHead() bool {
|
||||||
switch t {
|
switch t {
|
||||||
case OpStructHead:
|
case OpStructHead:
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package encoder
|
||||||
|
|
||||||
|
type Option struct {
|
||||||
|
HTMLEscape bool
|
||||||
|
Indent bool
|
||||||
|
UnorderedMap bool
|
||||||
|
Debug bool
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
fmt.Println("=============[DEBUG]===============")
|
fmt.Println("=============[DEBUG]===============")
|
||||||
|
@ -23,5 +23,5 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return Run(ctx, b, codeSet, opt)
|
return Run(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, opt encoder.Option, _ *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, _ *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -148,7 +148,7 @@ func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, op
|
||||||
ctx.Ptrs = newPtrs
|
ctx.Ptrs = newPtrs
|
||||||
ctx.Code = ifaceCodeSet.NoescapeKeyCode
|
ctx.Code = ifaceCodeSet.NoescapeKeyCode
|
||||||
|
|
||||||
bb, err := Run(ctx, b, ifaceCodeSet, opt)
|
bb, err := Run(ctx, b, ifaceCodeSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
recursiveLevel := 0
|
recursiveLevel := 0
|
||||||
ptrOffset := uintptr(0)
|
ptrOffset := uintptr(0)
|
||||||
ctxptr := ctx.Ptr()
|
ctxptr := ctx.Ptr()
|
||||||
|
@ -185,7 +185,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bb, err := appendInterface(ctx, codeSet, opt, code, b, iface, ptrOffset)
|
bb, err := appendInterface(ctx, codeSet, code, b, iface, ptrOffset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -365,13 +365,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.ElemIdx, 0)
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
store(ctxptr, code.Length, uintptr(mlen))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
store(ctxptr, code.MapIter, uintptr(iter))
|
||||||
if (opt & encoder.UnorderedMapOption) == 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
} else {
|
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
|
@ -380,7 +380,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
idx := load(ctxptr, code.ElemIdx)
|
||||||
length := load(ctxptr, code.Length)
|
length := load(ctxptr, code.Length)
|
||||||
idx++
|
idx++
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
if idx < length {
|
if idx < length {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
store(ctxptr, code.ElemIdx, idx)
|
||||||
|
@ -409,7 +409,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
b = appendColon(b)
|
b = appendColon(b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
ptr := load(ctxptr, code.End.MapPos)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
fmt.Println("=============[DEBUG]===============")
|
fmt.Println("=============[DEBUG]===============")
|
||||||
|
@ -23,5 +23,5 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return Run(ctx, b, codeSet, opt)
|
return Run(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, opt encoder.Option, _ *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, _ *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -148,7 +148,7 @@ func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, op
|
||||||
ctx.Ptrs = newPtrs
|
ctx.Ptrs = newPtrs
|
||||||
ctx.Code = ifaceCodeSet.EscapeKeyCode
|
ctx.Code = ifaceCodeSet.EscapeKeyCode
|
||||||
|
|
||||||
bb, err := Run(ctx, b, ifaceCodeSet, opt)
|
bb, err := Run(ctx, b, ifaceCodeSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
recursiveLevel := 0
|
recursiveLevel := 0
|
||||||
ptrOffset := uintptr(0)
|
ptrOffset := uintptr(0)
|
||||||
ctxptr := ctx.Ptr()
|
ctxptr := ctx.Ptr()
|
||||||
|
@ -185,7 +185,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bb, err := appendInterface(ctx, codeSet, opt, code, b, iface, ptrOffset)
|
bb, err := appendInterface(ctx, codeSet, code, b, iface, ptrOffset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -365,13 +365,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.ElemIdx, 0)
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
store(ctxptr, code.Length, uintptr(mlen))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
store(ctxptr, code.MapIter, uintptr(iter))
|
||||||
if (opt & encoder.UnorderedMapOption) == 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
} else {
|
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
|
@ -380,7 +380,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
idx := load(ctxptr, code.ElemIdx)
|
||||||
length := load(ctxptr, code.Length)
|
length := load(ctxptr, code.Length)
|
||||||
idx++
|
idx++
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
if idx < length {
|
if idx < length {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
store(ctxptr, code.ElemIdx, idx)
|
||||||
|
@ -409,7 +409,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
b = appendColon(b)
|
b = appendColon(b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
ptr := load(ctxptr, code.End.MapPos)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
fmt.Println("=============[DEBUG]===============")
|
fmt.Println("=============[DEBUG]===============")
|
||||||
|
@ -23,5 +23,5 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return Run(ctx, b, codeSet, opt)
|
return Run(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ func appendColon(b []byte) []byte {
|
||||||
return append(b, ':', ' ')
|
return append(b, ':', ' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, opt encoder.Option, code *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, code *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -138,7 +138,7 @@ func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, op
|
||||||
oldBaseIndent := ctx.BaseIndent
|
oldBaseIndent := ctx.BaseIndent
|
||||||
ctx.BaseIndent = code.Indent
|
ctx.BaseIndent = code.Indent
|
||||||
ctx.Code = ifaceCodeSet.EscapeKeyCode
|
ctx.Code = ifaceCodeSet.EscapeKeyCode
|
||||||
bb, err := Run(ctx, b, ifaceCodeSet, opt)
|
bb, err := Run(ctx, b, ifaceCodeSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
recursiveLevel := 0
|
recursiveLevel := 0
|
||||||
ptrOffset := uintptr(0)
|
ptrOffset := uintptr(0)
|
||||||
ctxptr := ctx.Ptr()
|
ctxptr := ctx.Ptr()
|
||||||
|
@ -185,7 +185,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bb, err := appendInterface(ctx, codeSet, opt, code, b, iface, ptrOffset)
|
bb, err := appendInterface(ctx, codeSet, code, b, iface, ptrOffset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -365,13 +365,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.ElemIdx, 0)
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
store(ctxptr, code.Length, uintptr(mlen))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
store(ctxptr, code.MapIter, uintptr(iter))
|
||||||
if (opt & encoder.UnorderedMapOption) == 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
} else {
|
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
|
@ -380,7 +380,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
idx := load(ctxptr, code.ElemIdx)
|
||||||
length := load(ctxptr, code.Length)
|
length := load(ctxptr, code.Length)
|
||||||
idx++
|
idx++
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
if idx < length {
|
if idx < length {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
store(ctxptr, code.ElemIdx, idx)
|
||||||
|
@ -409,7 +409,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
b = appendColon(b)
|
b = appendColon(b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
ptr := load(ctxptr, code.End.MapPos)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
fmt.Println("=============[DEBUG]===============")
|
fmt.Println("=============[DEBUG]===============")
|
||||||
|
@ -23,5 +23,5 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet,
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return Run(ctx, b, codeSet, opt)
|
return Run(ctx, b, codeSet)
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ func appendColon(b []byte) []byte {
|
||||||
return append(b, ':', ' ')
|
return append(b, ':', ' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, opt encoder.Option, code *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, code *encoder.Opcode, b []byte, iface *emptyInterface, ptrOffset uintptr) ([]byte, error) {
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -138,7 +138,7 @@ func appendInterface(ctx *encoder.RuntimeContext, codeSet *encoder.OpcodeSet, op
|
||||||
oldBaseIndent := ctx.BaseIndent
|
oldBaseIndent := ctx.BaseIndent
|
||||||
ctx.BaseIndent = code.Indent
|
ctx.BaseIndent = code.Indent
|
||||||
ctx.Code = ifaceCodeSet.NoescapeKeyCode
|
ctx.Code = ifaceCodeSet.NoescapeKeyCode
|
||||||
bb, err := Run(ctx, b, ifaceCodeSet, opt)
|
bb, err := Run(ctx, b, ifaceCodeSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt encoder.Option) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
recursiveLevel := 0
|
recursiveLevel := 0
|
||||||
ptrOffset := uintptr(0)
|
ptrOffset := uintptr(0)
|
||||||
ctxptr := ctx.Ptr()
|
ctxptr := ctx.Ptr()
|
||||||
|
@ -185,7 +185,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bb, err := appendInterface(ctx, codeSet, opt, code, b, iface, ptrOffset)
|
bb, err := appendInterface(ctx, codeSet, code, b, iface, ptrOffset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -365,13 +365,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
store(ctxptr, code.ElemIdx, 0)
|
store(ctxptr, code.ElemIdx, 0)
|
||||||
store(ctxptr, code.Length, uintptr(mlen))
|
store(ctxptr, code.Length, uintptr(mlen))
|
||||||
store(ctxptr, code.MapIter, uintptr(iter))
|
store(ctxptr, code.MapIter, uintptr(iter))
|
||||||
if (opt & encoder.UnorderedMapOption) == 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
|
b = appendMapKeyIndent(ctx, code.Next, b)
|
||||||
|
} else {
|
||||||
mapCtx := encoder.NewMapContext(mlen)
|
mapCtx := encoder.NewMapContext(mlen)
|
||||||
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
mapCtx.Pos = append(mapCtx.Pos, len(b))
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
|
||||||
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
store(ctxptr, code.End.MapPos, uintptr(unsafe.Pointer(mapCtx)))
|
||||||
} else {
|
|
||||||
b = appendMapKeyIndent(ctx, code.Next, b)
|
|
||||||
}
|
}
|
||||||
key := mapiterkey(iter)
|
key := mapiterkey(iter)
|
||||||
store(ctxptr, code.Next.Idx, uintptr(key))
|
store(ctxptr, code.Next.Idx, uintptr(key))
|
||||||
|
@ -380,7 +380,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
idx := load(ctxptr, code.ElemIdx)
|
idx := load(ctxptr, code.ElemIdx)
|
||||||
length := load(ctxptr, code.Length)
|
length := load(ctxptr, code.Length)
|
||||||
idx++
|
idx++
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
if idx < length {
|
if idx < length {
|
||||||
b = appendMapKeyIndent(ctx, code, b)
|
b = appendMapKeyIndent(ctx, code, b)
|
||||||
store(ctxptr, code.ElemIdx, idx)
|
store(ctxptr, code.ElemIdx, idx)
|
||||||
|
@ -409,7 +409,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case encoder.OpMapValue:
|
case encoder.OpMapValue:
|
||||||
if (opt & encoder.UnorderedMapOption) != 0 {
|
if ctx.Option.UnorderedMap {
|
||||||
b = appendColon(b)
|
b = appendColon(b)
|
||||||
} else {
|
} else {
|
||||||
ptr := load(ctxptr, code.End.MapPos)
|
ptr := load(ctxptr, code.End.MapPos)
|
||||||
|
|
16
json.go
16
json.go
|
@ -160,16 +160,12 @@ func Marshal(v interface{}) ([]byte, error) {
|
||||||
|
|
||||||
// MarshalNoEscape
|
// MarshalNoEscape
|
||||||
func MarshalNoEscape(v interface{}) ([]byte, error) {
|
func MarshalNoEscape(v interface{}) ([]byte, error) {
|
||||||
return marshalNoEscape(v, EncodeOptionHTMLEscape)
|
return marshalNoEscape(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalWithOption returns the JSON encoding of v with EncodeOption.
|
// MarshalWithOption returns the JSON encoding of v with EncodeOption.
|
||||||
func MarshalWithOption(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
func MarshalWithOption(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||||
opt := EncodeOptionHTMLEscape
|
return marshal(v, optFuncs...)
|
||||||
for _, optFunc := range optFuncs {
|
|
||||||
opt = optFunc(opt)
|
|
||||||
}
|
|
||||||
return marshal(v, opt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalIndent is like Marshal but applies Indent to format the output.
|
// MarshalIndent is like Marshal but applies Indent to format the output.
|
||||||
|
@ -181,11 +177,7 @@ func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
|
||||||
|
|
||||||
// MarshalIndentWithOption is like Marshal but applies Indent to format the output with EncodeOption.
|
// MarshalIndentWithOption is like Marshal but applies Indent to format the output with EncodeOption.
|
||||||
func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) {
|
||||||
opt := EncodeOptionHTMLEscape | EncodeOptionIndent
|
return marshalIndent(v, prefix, indent, optFuncs...)
|
||||||
for _, optFunc := range optFuncs {
|
|
||||||
opt = optFunc(opt)
|
|
||||||
}
|
|
||||||
return marshalIndent(v, prefix, indent, opt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal parses the JSON-encoded data and stores the result
|
// Unmarshal parses the JSON-encoded data and stores the result
|
||||||
|
@ -326,7 +318,7 @@ func HTMLEscape(dst *bytes.Buffer, src []byte) {
|
||||||
if err := dec.Decode(&v); err != nil {
|
if err := dec.Decode(&v); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
buf, _ := marshal(v, EncodeOptionHTMLEscape)
|
buf, _ := marshal(v)
|
||||||
dst.Write(buf)
|
dst.Write(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
option.go
20
option.go
|
@ -1,15 +1,21 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
type EncodeOptionFunc func(EncodeOption) EncodeOption
|
import (
|
||||||
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
|
)
|
||||||
|
|
||||||
func UnorderedMap() func(EncodeOption) EncodeOption {
|
type EncodeOption = encoder.Option
|
||||||
return func(opt EncodeOption) EncodeOption {
|
|
||||||
return opt | EncodeOptionUnorderedMap
|
type EncodeOptionFunc func(*EncodeOption)
|
||||||
|
|
||||||
|
func UnorderedMap() EncodeOptionFunc {
|
||||||
|
return func(opt *EncodeOption) {
|
||||||
|
opt.UnorderedMap = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Debug() func(EncodeOption) EncodeOption {
|
func Debug() EncodeOptionFunc {
|
||||||
return func(opt EncodeOption) EncodeOption {
|
return func(opt *EncodeOption) {
|
||||||
return opt | EncodeOptionDebug
|
opt.Debug = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue