goversion_maprange_unsafe_gte_go112.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
  2. // Use of this source code is governed by a MIT license found in the LICENSE file.
  3. // +build !safe
  4. // +build !appengine
  5. // +build go1.12
  6. package codec
  7. import (
  8. "reflect"
  9. "unsafe"
  10. )
  11. type unsafeReflectMapIter struct {
  12. m unsafeReflectValue
  13. it unsafe.Pointer
  14. }
  15. type mapIter struct {
  16. t *reflect.MapIter
  17. m, k, v reflect.Value
  18. ktyp, vtyp unsafe.Pointer
  19. kptr, vptr unsafe.Pointer
  20. kisref, visref bool
  21. mapvalues bool
  22. done bool
  23. _ uint64 // padding (cache-aligned)
  24. }
  25. func (t *mapIter) Next() (r bool) {
  26. if t.done {
  27. return
  28. }
  29. r = t.t.Next()
  30. if r {
  31. it := (*unsafeReflectMapIter)(unsafe.Pointer(t.t))
  32. mapSet(t.kptr, t.ktyp, mapiterkey(it.it), t.kisref)
  33. if t.mapvalues {
  34. mapSet(t.vptr, t.vtyp, mapiterelem(it.it), t.visref)
  35. }
  36. } else {
  37. t.done = true
  38. }
  39. return
  40. }
  41. func (t *mapIter) Key() reflect.Value {
  42. return t.k
  43. }
  44. func (t *mapIter) Value() (r reflect.Value) {
  45. if t.mapvalues {
  46. return t.v
  47. }
  48. return
  49. }
  50. func mapSet(p, ptyp, p2 unsafe.Pointer, isref bool) {
  51. if isref {
  52. *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(p2) // p2
  53. } else {
  54. typedmemmove(ptyp, p, p2) // *(*unsafe.Pointer)(p2)) // p2)
  55. }
  56. }
  57. func mapRange(m, k, v reflect.Value, mapvalues bool) *mapIter {
  58. if m.IsNil() {
  59. return &mapIter{done: true}
  60. }
  61. t := &mapIter{
  62. m: m, k: k, v: v,
  63. t: m.MapRange(), mapvalues: mapvalues,
  64. }
  65. var urv *unsafeReflectValue
  66. urv = (*unsafeReflectValue)(unsafe.Pointer(&k))
  67. t.ktyp = urv.typ
  68. t.kptr = urv.ptr
  69. t.kisref = refBitset.isset(byte(k.Kind()))
  70. if mapvalues {
  71. urv = (*unsafeReflectValue)(unsafe.Pointer(&v))
  72. t.vtyp = urv.typ
  73. t.vptr = urv.ptr
  74. t.visref = refBitset.isset(byte(v.Kind()))
  75. }
  76. return t
  77. }
  78. func mapIndex(m, k, v reflect.Value) (vv reflect.Value) {
  79. var urv = (*unsafeReflectValue)(unsafe.Pointer(&k))
  80. var kptr unsafe.Pointer
  81. if urv.flag&unsafeFlagIndir == 0 {
  82. kptr = unsafe.Pointer(&urv.ptr)
  83. } else {
  84. kptr = urv.ptr
  85. }
  86. urv = (*unsafeReflectValue)(unsafe.Pointer(&m))
  87. vvptr := mapaccess(urv.typ, rv2ptr(urv), kptr)
  88. if vvptr == nil {
  89. return
  90. }
  91. // vvptr = *(*unsafe.Pointer)(vvptr)
  92. urv = (*unsafeReflectValue)(unsafe.Pointer(&v))
  93. mapSet(urv.ptr, urv.typ, vvptr, refBitset.isset(byte(v.Kind())))
  94. return v
  95. }
  96. // return an addressable reflect value that can be used in mapRange and mapIndex operations.
  97. //
  98. // all calls to mapIndex or mapRange will call here to get an addressable reflect.Value.
  99. func mapAddressableRV(t reflect.Type) (r reflect.Value) {
  100. return reflect.New(t).Elem()
  101. }
  102. //go:linkname mapiterkey reflect.mapiterkey
  103. //go:noescape
  104. func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer)
  105. //go:linkname mapiterelem reflect.mapiterelem
  106. //go:noescape
  107. func mapiterelem(it unsafe.Pointer) (elem unsafe.Pointer)
  108. //go:linkname mapaccess reflect.mapaccess
  109. //go:noescape
  110. func mapaccess(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
  111. //go:linkname typedmemmove reflect.typedmemmove
  112. //go:noescape
  113. func typedmemmove(typ unsafe.Pointer, dst, src unsafe.Pointer)