iterator.odin 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package reflect
  2. import "base:runtime"
  3. // An iterator to dynamically iterate across something that is array-like (or pointer-to-array-like)
  4. // Example:
  5. // it: int // used as a tracking value
  6. // for elem, idx in iterate_array(any_array_val, &it) { ... }
  7. @(require_results)
  8. iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) {
  9. if val == nil || it == nil {
  10. return
  11. }
  12. ti := type_info_base(type_info_of(val.id))
  13. #partial switch info in ti.variant {
  14. case Type_Info_Pointer:
  15. if ptr := (^rawptr)(val.data)^; ptr != nil {
  16. return iterate_array(any{ptr, info.elem.id}, it)
  17. }
  18. case Type_Info_Array:
  19. if it^ < info.count {
  20. elem.data = rawptr(uintptr(val.data) + uintptr(it^ * info.elem_size))
  21. elem.id = info.elem.id
  22. ok = true
  23. index = it^
  24. it^ += 1
  25. }
  26. case Type_Info_Slice:
  27. array := (^runtime.Raw_Slice)(val.data)
  28. if it^ < array.len {
  29. elem.data = rawptr(uintptr(array.data) + uintptr(it^ * info.elem_size))
  30. elem.id = info.elem.id
  31. ok = true
  32. index = it^
  33. it^ += 1
  34. }
  35. case Type_Info_Dynamic_Array:
  36. array := (^runtime.Raw_Dynamic_Array)(val.data)
  37. if it^ < array.len {
  38. elem.data = rawptr(uintptr(array.data) + uintptr(it^ * info.elem_size))
  39. elem.id = info.elem.id
  40. ok = true
  41. index = it^
  42. it^ += 1
  43. }
  44. }
  45. return
  46. }
  47. // An iterator to dynamically iterate across map (or pointer-to-map)
  48. // Example:
  49. // it: int // used as a tracking value
  50. // for key, val in iterate_map(any_map_val, &it) { ... }
  51. @(require_results)
  52. iterate_map :: proc(val: any, it: ^int) -> (key, value: any, ok: bool) {
  53. if val == nil || it == nil {
  54. return
  55. }
  56. ti := type_info_base(type_info_of(val.id))
  57. #partial switch info in ti.variant {
  58. case Type_Info_Pointer:
  59. if ptr := (^rawptr)(val.data)^; ptr != nil {
  60. return iterate_map(any{ptr, info.elem.id}, it)
  61. }
  62. case Type_Info_Map:
  63. if info.map_info == nil {
  64. break
  65. }
  66. rm := (^runtime.Raw_Map)(val.data)
  67. ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(rm^, info.map_info)
  68. for /**/ ; it^ < int(runtime.map_cap(rm^)); it^ += 1 {
  69. if hash := hs[it^]; runtime.map_hash_is_valid(hash) {
  70. key_ptr := runtime.map_cell_index_dynamic(ks, info.map_info.ks, uintptr(it^))
  71. value_ptr := runtime.map_cell_index_dynamic(vs, info.map_info.vs, uintptr(it^))
  72. key.data = rawptr(key_ptr)
  73. value.data = rawptr(value_ptr)
  74. key.id = info.key.id
  75. value.id = info.value.id
  76. ok = true
  77. it^ += 1
  78. break
  79. }
  80. }
  81. }
  82. return
  83. }