context.go 1.8 KB

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