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. }