...
1 package encoder
2
3 import (
4 "context"
5 "sync"
6 "unsafe"
7
8 "github.com/goccy/go-json/internal/runtime"
9 )
10
11 type compileContext struct {
12 opcodeIndex uint32
13 ptrIndex int
14 indent uint32
15 escapeKey bool
16 structTypeToCodes map[uintptr]Opcodes
17 recursiveCodes *Opcodes
18 }
19
20 func (c *compileContext) incIndent() {
21 c.indent++
22 }
23
24 func (c *compileContext) decIndent() {
25 c.indent--
26 }
27
28 func (c *compileContext) incIndex() {
29 c.incOpcodeIndex()
30 c.incPtrIndex()
31 }
32
33 func (c *compileContext) decIndex() {
34 c.decOpcodeIndex()
35 c.decPtrIndex()
36 }
37
38 func (c *compileContext) incOpcodeIndex() {
39 c.opcodeIndex++
40 }
41
42 func (c *compileContext) decOpcodeIndex() {
43 c.opcodeIndex--
44 }
45
46 func (c *compileContext) incPtrIndex() {
47 c.ptrIndex++
48 }
49
50 func (c *compileContext) decPtrIndex() {
51 c.ptrIndex--
52 }
53
54 const (
55 bufSize = 1024
56 )
57
58 var (
59 runtimeContextPool = sync.Pool{
60 New: func() interface{} {
61 return &RuntimeContext{
62 Buf: make([]byte, 0, bufSize),
63 Ptrs: make([]uintptr, 128),
64 KeepRefs: make([]unsafe.Pointer, 0, 8),
65 Option: &Option{},
66 }
67 },
68 }
69 )
70
71 type RuntimeContext struct {
72 Context context.Context
73 Buf []byte
74 MarshalBuf []byte
75 Ptrs []uintptr
76 KeepRefs []unsafe.Pointer
77 SeenPtr []uintptr
78 BaseIndent uint32
79 Prefix []byte
80 IndentStr []byte
81 Option *Option
82 }
83
84 func (c *RuntimeContext) Init(p uintptr, codelen int) {
85 if len(c.Ptrs) < codelen {
86 c.Ptrs = make([]uintptr, codelen)
87 }
88 c.Ptrs[0] = p
89 c.KeepRefs = c.KeepRefs[:0]
90 c.SeenPtr = c.SeenPtr[:0]
91 c.BaseIndent = 0
92 }
93
94 func (c *RuntimeContext) Ptr() uintptr {
95 header := (*runtime.SliceHeader)(unsafe.Pointer(&c.Ptrs))
96 return uintptr(header.Data)
97 }
98
99 func TakeRuntimeContext() *RuntimeContext {
100 return runtimeContextPool.Get().(*RuntimeContext)
101 }
102
103 func ReleaseRuntimeContext(ctx *RuntimeContext) {
104 runtimeContextPool.Put(ctx)
105 }
106
View as plain text