feature_reflect_slice.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package jsoniter
  2. import (
  3. "fmt"
  4. "io"
  5. "reflect"
  6. "unsafe"
  7. )
  8. func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
  9. decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem())
  10. return &sliceDecoder{typ, typ.Elem(), decoder}
  11. }
  12. func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
  13. encoder := encoderOfType(cfg, prefix+"[slice]->", typ.Elem())
  14. return &sliceEncoder{typ, typ.Elem(), encoder}
  15. }
  16. type sliceEncoder struct {
  17. sliceType reflect.Type
  18. elemType reflect.Type
  19. elemEncoder ValEncoder
  20. }
  21. func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
  22. slice := (*sliceHeader)(ptr)
  23. if slice.Data == nil {
  24. stream.WriteNil()
  25. return
  26. }
  27. if slice.Len == 0 {
  28. stream.WriteEmptyArray()
  29. return
  30. }
  31. stream.WriteArrayStart()
  32. elemPtr := unsafe.Pointer(slice.Data)
  33. encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
  34. for i := 1; i < slice.Len; i++ {
  35. stream.WriteMore()
  36. elemPtr = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
  37. encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
  38. }
  39. stream.WriteArrayEnd()
  40. if stream.Error != nil && stream.Error != io.EOF {
  41. stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error())
  42. }
  43. }
  44. func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
  45. slice := (*sliceHeader)(ptr)
  46. return slice.Len == 0
  47. }
  48. type sliceDecoder struct {
  49. sliceType reflect.Type
  50. elemType reflect.Type
  51. elemDecoder ValDecoder
  52. }
  53. // sliceHeader is a safe version of SliceHeader used within this package.
  54. type sliceHeader struct {
  55. Data unsafe.Pointer
  56. Len int
  57. Cap int
  58. }
  59. func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
  60. decoder.doDecode(ptr, iter)
  61. if iter.Error != nil && iter.Error != io.EOF {
  62. iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error())
  63. }
  64. }
  65. func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
  66. slice := (*sliceHeader)(ptr)
  67. if iter.ReadNil() {
  68. slice.Len = 0
  69. slice.Cap = 0
  70. slice.Data = nil
  71. return
  72. }
  73. reuseSlice(slice, decoder.sliceType, 4)
  74. slice.Len = 0
  75. offset := uintptr(0)
  76. iter.ReadArrayCB(func(iter *Iterator) bool {
  77. growOne(slice, decoder.sliceType, decoder.elemType)
  78. decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter)
  79. offset += decoder.elemType.Size()
  80. return true
  81. })
  82. }
  83. // grow grows the slice s so that it can hold extra more values, allocating
  84. // more capacity if needed. It also returns the old and new slice lengths.
  85. func growOne(slice *sliceHeader, sliceType reflect.Type, elementType reflect.Type) {
  86. newLen := slice.Len + 1
  87. if newLen <= slice.Cap {
  88. slice.Len = newLen
  89. return
  90. }
  91. newCap := slice.Cap
  92. if newCap == 0 {
  93. newCap = 1
  94. } else {
  95. for newCap < newLen {
  96. if slice.Len < 1024 {
  97. newCap += newCap
  98. } else {
  99. newCap += newCap / 4
  100. }
  101. }
  102. }
  103. newVal := reflect.MakeSlice(sliceType, newLen, newCap).Interface()
  104. newValPtr := extractInterface(newVal).word
  105. dst := (*sliceHeader)(newValPtr).Data
  106. // copy old array into new array
  107. originalBytesCount := slice.Len * int(elementType.Size())
  108. srcSliceHeader := (unsafe.Pointer)(&sliceHeader{slice.Data, originalBytesCount, originalBytesCount})
  109. dstSliceHeader := (unsafe.Pointer)(&sliceHeader{dst, originalBytesCount, originalBytesCount})
  110. copy(*(*[]byte)(dstSliceHeader), *(*[]byte)(srcSliceHeader))
  111. slice.Data = dst
  112. slice.Len = newLen
  113. slice.Cap = newCap
  114. }
  115. func reuseSlice(slice *sliceHeader, sliceType reflect.Type, expectedCap int) {
  116. if expectedCap <= slice.Cap {
  117. return
  118. }
  119. newVal := reflect.MakeSlice(sliceType, 0, expectedCap).Interface()
  120. newValPtr := extractInterface(newVal).word
  121. dst := (*sliceHeader)(newValPtr).Data
  122. slice.Data = dst
  123. slice.Cap = expectedCap
  124. }