dynamic_array_internal.odin 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package runtime
  2. __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int, loc := #caller_location) {
  3. array := (^Raw_Dynamic_Array)(array_)
  4. array.allocator = context.allocator
  5. assert(array.allocator.procedure != nil)
  6. if cap > 0 {
  7. __dynamic_array_reserve(array_, elem_size, elem_align, cap, loc)
  8. array.len = len
  9. }
  10. }
  11. __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool {
  12. array := (^Raw_Dynamic_Array)(array_)
  13. // NOTE(tetra, 2020-01-26): We set the allocator before earlying-out below, because user code is usually written
  14. // assuming that appending/reserving will set the allocator, if it is not already set.
  15. if array.allocator.procedure == nil {
  16. array.allocator = context.allocator
  17. }
  18. assert(array.allocator.procedure != nil)
  19. if cap <= array.cap {
  20. return true
  21. }
  22. old_size := array.cap * elem_size
  23. new_size := cap * elem_size
  24. allocator := array.allocator
  25. new_data, err := allocator.procedure(allocator.data, .Resize, new_size, elem_align, array.data, old_size, loc)
  26. if err != nil {
  27. return false
  28. }
  29. if new_data != nil || elem_size == 0 {
  30. array.data = raw_data(new_data)
  31. array.cap = min(cap, len(new_data)/elem_size)
  32. return true
  33. }
  34. return false
  35. }
  36. __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int, loc := #caller_location) -> bool {
  37. array := (^Raw_Dynamic_Array)(array_)
  38. ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc)
  39. if ok {
  40. array.len = len
  41. }
  42. return ok
  43. }
  44. __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
  45. items: rawptr, item_count: int, loc := #caller_location) -> int {
  46. array := (^Raw_Dynamic_Array)(array_)
  47. if items == nil {
  48. return 0
  49. }
  50. if item_count <= 0 {
  51. return 0
  52. }
  53. ok := true
  54. if array.cap <= array.len+item_count {
  55. cap := 2 * array.cap + max(8, item_count)
  56. ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc)
  57. }
  58. // TODO(bill): Better error handling for failed reservation
  59. if !ok {
  60. return array.len
  61. }
  62. assert(array.data != nil)
  63. data := uintptr(array.data) + uintptr(elem_size*array.len)
  64. mem_copy(rawptr(data), items, elem_size * item_count)
  65. array.len += item_count
  66. return array.len
  67. }
  68. __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int, loc := #caller_location) -> int {
  69. array := (^Raw_Dynamic_Array)(array_)
  70. ok := true
  71. if array.cap <= array.len+1 {
  72. cap := 2 * array.cap + max(8, 1)
  73. ok = __dynamic_array_reserve(array, elem_size, elem_align, cap, loc)
  74. }
  75. // TODO(bill): Better error handling for failed reservation
  76. if !ok {
  77. return array.len
  78. }
  79. assert(array.data != nil)
  80. data := uintptr(array.data) + uintptr(elem_size*array.len)
  81. mem_zero(rawptr(data), elem_size)
  82. array.len += 1
  83. return array.len
  84. }