106 lines
1.8 KiB
Go
106 lines
1.8 KiB
Go
|
package encoder
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sync"
|
||
|
"unsafe"
|
||
|
|
||
|
"github.com/goccy/go-json/internal/runtime"
|
||
|
)
|
||
|
|
||
|
type compileContext struct {
|
||
|
opcodeIndex uint32
|
||
|
ptrIndex int
|
||
|
indent uint32
|
||
|
escapeKey bool
|
||
|
structTypeToCodes map[uintptr]Opcodes
|
||
|
recursiveCodes *Opcodes
|
||
|
}
|
||
|
|
||
|
func (c *compileContext) incIndent() {
|
||
|
c.indent++
|
||
|
}
|
||
|
|
||
|
func (c *compileContext) decIndent() {
|
||
|
c.indent--
|
||
|
}
|
||
|
|
||
|
func (c *compileContext) incIndex() {
|
||
|
c.incOpcodeIndex()
|
||
|
c.incPtrIndex()
|
||
|
}
|
||
|
|
||
|
func (c *compileContext) decIndex() {
|
||
|
c.decOpcodeIndex()
|
||
|
c.decPtrIndex()
|
||
|
}
|
||
|
|
||
|
func (c *compileContext) incOpcodeIndex() {
|
||
|
c.opcodeIndex++
|
||
|
}
|
||
|
|
||
|
func (c *compileContext) decOpcodeIndex() {
|
||
|
c.opcodeIndex--
|
||
|
}
|
||
|
|
||
|
func (c *compileContext) incPtrIndex() {
|
||
|
c.ptrIndex++
|
||
|
}
|
||
|
|
||
|
func (c *compileContext) decPtrIndex() {
|
||
|
c.ptrIndex--
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
bufSize = 1024
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
runtimeContextPool = sync.Pool{
|
||
|
New: func() interface{} {
|
||
|
return &RuntimeContext{
|
||
|
Buf: make([]byte, 0, bufSize),
|
||
|
Ptrs: make([]uintptr, 128),
|
||
|
KeepRefs: make([]unsafe.Pointer, 0, 8),
|
||
|
Option: &Option{},
|
||
|
}
|
||
|
},
|
||
|
}
|
||
|
)
|
||
|
|
||
|
type RuntimeContext struct {
|
||
|
Context context.Context
|
||
|
Buf []byte
|
||
|
MarshalBuf []byte
|
||
|
Ptrs []uintptr
|
||
|
KeepRefs []unsafe.Pointer
|
||
|
SeenPtr []uintptr
|
||
|
BaseIndent uint32
|
||
|
Prefix []byte
|
||
|
IndentStr []byte
|
||
|
Option *Option
|
||
|
}
|
||
|
|
||
|
func (c *RuntimeContext) Init(p uintptr, codelen int) {
|
||
|
if len(c.Ptrs) < codelen {
|
||
|
c.Ptrs = make([]uintptr, codelen)
|
||
|
}
|
||
|
c.Ptrs[0] = p
|
||
|
c.KeepRefs = c.KeepRefs[:0]
|
||
|
c.SeenPtr = c.SeenPtr[:0]
|
||
|
c.BaseIndent = 0
|
||
|
}
|
||
|
|
||
|
func (c *RuntimeContext) Ptr() uintptr {
|
||
|
header := (*runtime.SliceHeader)(unsafe.Pointer(&c.Ptrs))
|
||
|
return uintptr(header.Data)
|
||
|
}
|
||
|
|
||
|
func TakeRuntimeContext() *RuntimeContext {
|
||
|
return runtimeContextPool.Get().(*RuntimeContext)
|
||
|
}
|
||
|
|
||
|
func ReleaseRuntimeContext(ctx *RuntimeContext) {
|
||
|
runtimeContextPool.Put(ctx)
|
||
|
}
|