array.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package decoder
  2. import (
  3. "fmt"
  4. "unsafe"
  5. "github.com/goccy/go-json/internal/errors"
  6. "github.com/goccy/go-json/internal/runtime"
  7. )
  8. type arrayDecoder struct {
  9. elemType *runtime.Type
  10. size uintptr
  11. valueDecoder Decoder
  12. alen int
  13. structName string
  14. fieldName string
  15. zeroValue unsafe.Pointer
  16. }
  17. func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
  18. // workaround to avoid checkptr errors. cannot use `*(*unsafe.Pointer)(unsafe_New(elemType))` directly.
  19. zeroValuePtr := unsafe_New(elemType)
  20. zeroValue := **(**unsafe.Pointer)(unsafe.Pointer(&zeroValuePtr))
  21. return &arrayDecoder{
  22. valueDecoder: dec,
  23. elemType: elemType,
  24. size: elemType.Size(),
  25. alen: alen,
  26. structName: structName,
  27. fieldName: fieldName,
  28. zeroValue: zeroValue,
  29. }
  30. }
  31. func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
  32. depth++
  33. if depth > maxDecodeNestingDepth {
  34. return errors.ErrExceededMaxDepth(s.char(), s.cursor)
  35. }
  36. for {
  37. switch s.char() {
  38. case ' ', '\n', '\t', '\r':
  39. case 'n':
  40. if err := nullBytes(s); err != nil {
  41. return err
  42. }
  43. return nil
  44. case '[':
  45. idx := 0
  46. s.cursor++
  47. if s.skipWhiteSpace() == ']' {
  48. for idx < d.alen {
  49. *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
  50. idx++
  51. }
  52. s.cursor++
  53. return nil
  54. }
  55. for {
  56. if idx < d.alen {
  57. if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
  58. return err
  59. }
  60. } else {
  61. if err := s.skipValue(depth); err != nil {
  62. return err
  63. }
  64. }
  65. idx++
  66. switch s.skipWhiteSpace() {
  67. case ']':
  68. for idx < d.alen {
  69. *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
  70. idx++
  71. }
  72. s.cursor++
  73. return nil
  74. case ',':
  75. s.cursor++
  76. continue
  77. case nul:
  78. if s.read() {
  79. s.cursor++
  80. continue
  81. }
  82. goto ERROR
  83. default:
  84. goto ERROR
  85. }
  86. }
  87. case nul:
  88. if s.read() {
  89. continue
  90. }
  91. goto ERROR
  92. default:
  93. goto ERROR
  94. }
  95. s.cursor++
  96. }
  97. ERROR:
  98. return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
  99. }
  100. func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
  101. buf := ctx.Buf
  102. depth++
  103. if depth > maxDecodeNestingDepth {
  104. return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
  105. }
  106. for {
  107. switch buf[cursor] {
  108. case ' ', '\n', '\t', '\r':
  109. cursor++
  110. continue
  111. case 'n':
  112. if err := validateNull(buf, cursor); err != nil {
  113. return 0, err
  114. }
  115. cursor += 4
  116. return cursor, nil
  117. case '[':
  118. idx := 0
  119. cursor++
  120. cursor = skipWhiteSpace(buf, cursor)
  121. if buf[cursor] == ']' {
  122. for idx < d.alen {
  123. *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
  124. idx++
  125. }
  126. cursor++
  127. return cursor, nil
  128. }
  129. for {
  130. if idx < d.alen {
  131. c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
  132. if err != nil {
  133. return 0, err
  134. }
  135. cursor = c
  136. } else {
  137. c, err := skipValue(buf, cursor, depth)
  138. if err != nil {
  139. return 0, err
  140. }
  141. cursor = c
  142. }
  143. idx++
  144. cursor = skipWhiteSpace(buf, cursor)
  145. switch buf[cursor] {
  146. case ']':
  147. for idx < d.alen {
  148. *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
  149. idx++
  150. }
  151. cursor++
  152. return cursor, nil
  153. case ',':
  154. cursor++
  155. continue
  156. default:
  157. return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
  158. }
  159. }
  160. default:
  161. return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
  162. }
  163. }
  164. }
  165. func (d *arrayDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
  166. return nil, 0, fmt.Errorf("json: array decoder does not support decode path")
  167. }