array.odin 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package container
  2. import "core:mem"
  3. import "core:runtime"
  4. Array :: struct(T: typeid) {
  5. data: ^T,
  6. len: int,
  7. cap: int,
  8. allocator: mem.Allocator,
  9. }
  10. /*
  11. array_init :: proc {
  12. array_init_none,
  13. array_init_len,
  14. array_init_len_cap,
  15. }
  16. array_init
  17. array_delete
  18. array_len
  19. array_cap
  20. array_space
  21. array_slice
  22. array_get
  23. array_get_ptr
  24. array_set
  25. array_reserve
  26. array_resize
  27. array_push = array_append :: proc{
  28. array_push_back,
  29. array_push_back_elems,
  30. }
  31. array_push_front
  32. array_pop_back
  33. array_pop_front
  34. array_consume
  35. array_trim
  36. array_clear
  37. array_clone
  38. array_set_capacity
  39. array_grow
  40. */
  41. array_init_none :: proc(a: ^$A/Array, allocator := context.allocator) {
  42. array_init_len(a, 0, allocator);
  43. }
  44. array_init_len :: proc(a: ^$A/Array, len: int, allocator := context.allocator) {
  45. array_init_len_cap(a, 0, 16, allocator);
  46. }
  47. array_init_len_cap :: proc(a: ^$A/Array($T), len: int, cap: int, allocator := context.allocator) {
  48. a.allocator = allocator;
  49. a.data = (^T)(mem.alloc(size_of(T)*cap, align_of(T), a.allocator));
  50. a.len = len;
  51. a.cap = cap;
  52. }
  53. array_init :: proc{array_init_none, array_init_len, array_init_len_cap};
  54. array_delete :: proc(a: $A/Array) {
  55. mem.free(a.data, a.allocator);
  56. }
  57. array_len :: proc(a: $A/Array) -> int {
  58. return a.len;
  59. }
  60. array_cap :: proc(a: $A/Array) -> int {
  61. return a.cap;
  62. }
  63. array_space :: proc(a: $A/Array) -> int {
  64. return a.cap - a.len;
  65. }
  66. array_slice :: proc(a: $A/Array($T)) -> []T {
  67. s := mem.Raw_Slice{a.data, a.len};
  68. return transmute([]T)s;
  69. }
  70. array_cap_slice :: proc(a: $A/Array($T)) -> []T {
  71. s := mem.Raw_Slice{a.data, a.cap};
  72. return transmute([]T)s;
  73. }
  74. array_get :: proc(a: $A/Array($T), index: int, loc := #caller_location) -> T {
  75. runtime.bounds_check_error_loc(loc, index, array_len(a));
  76. return (^T)(uintptr(a.data) + size_of(T)*uintptr(index))^;
  77. }
  78. array_get_ptr :: proc(a: $A/Array($T), index: int, loc := #caller_location) -> ^T {
  79. runtime.bounds_check_error_loc(loc, index, array_len(a));
  80. return (^T)(uintptr(a.data) + size_of(T)*uintptr(index));
  81. }
  82. array_set :: proc(a: ^$A/Array($T), index: int, item: T, loc := #caller_location) {
  83. runtime.bounds_check_error_loc(loc, index, array_len(a^));
  84. (^T)(uintptr(a.data) + size_of(T)*uintptr(index))^ = item;
  85. }
  86. array_reserve :: proc(a: ^$A/Array, capacity: int) {
  87. if capacity > a.len {
  88. array_set_capacity(a, capacity);
  89. }
  90. }
  91. array_resize :: proc(a: ^$A/Array, length: int) {
  92. if length > a.len {
  93. array_set_capacity(a, length);
  94. }
  95. a.len = length;
  96. }
  97. array_push_back :: proc(a: ^$A/Array($T), item: T) {
  98. if array_space(a^) == 0 {
  99. array_grow(a);
  100. }
  101. a.len += 1;
  102. array_set(a, a.len-1, item);
  103. }
  104. array_push_front :: proc(a: ^$A/Array($T), item: T) {
  105. if array_space(a^) == 0 {
  106. array_grow(a);
  107. }
  108. a.len += 1;
  109. data := array_slice(a^);
  110. copy(data[1:], data[:]);
  111. data[0] = item;
  112. }
  113. array_pop_back :: proc(a: ^$A/Array($T), loc := #caller_location) -> T {
  114. assert(condition=a.len > 0, loc=loc);
  115. item := array_get(a^, a.len-1);
  116. a.len -= 1;
  117. return item;
  118. }
  119. array_pop_front :: proc(a: ^$A/Array($T), loc := #caller_location) -> T {
  120. assert(condition=a.len > 0, loc=loc);
  121. item := array_get(a^, 0);
  122. s := array_slice(a^);
  123. copy(s[:], s[1:]);
  124. a.len -= 1;
  125. return item;
  126. }
  127. array_consume :: proc(a: ^$A/Array($T), count: int, loc := #caller_location) {
  128. assert(condition=a.len >= count, loc=loc);
  129. a.len -= count;
  130. }
  131. array_trim :: proc(a: ^$A/Array($T)) {
  132. array_set_capacity(a, a.len);
  133. }
  134. array_clear :: proc(a: ^$A/Array($T)) {
  135. array_resize(a, 0);
  136. }
  137. array_clone :: proc(a: $A/Array($T), allocator := context.allocator) -> A {
  138. res: A;
  139. array_init(&res, array_len(a), array_len(a), allocator);
  140. copy(array_slice(res), array_slice(a));
  141. return res;
  142. }
  143. array_push_back_elems :: proc(a: ^$A/Array($T), items: ..T) {
  144. if array_space(a^) < len(items) {
  145. array_grow(a, a.len + len(items));
  146. }
  147. offset := a.len;
  148. data := array_cap_slice(a^);
  149. n := copy(data[a.len:], items);
  150. a.len += n;
  151. }
  152. array_push :: proc{array_push_back, array_push_back_elems};
  153. array_append :: proc{array_push_back, array_push_back_elems};
  154. array_set_capacity :: proc(a: ^$A/Array($T), new_capacity: int) {
  155. if new_capacity == a.cap {
  156. return;
  157. }
  158. if new_capacity < a.len {
  159. array_resize(a, new_capacity);
  160. }
  161. new_data: ^T;
  162. if new_capacity > 0 {
  163. if a.allocator.procedure == nil {
  164. a.allocator = context.allocator;
  165. }
  166. new_data = (^T)(mem.alloc(size_of(T)*new_capacity, align_of(T), a.allocator));
  167. if new_data != nil {
  168. mem.copy(new_data, a.data, size_of(T)*a.len);
  169. }
  170. }
  171. mem.free(a.data, a.allocator);
  172. a.data = new_data;
  173. a.cap = new_capacity;
  174. }
  175. array_grow :: proc(a: ^$A/Array, min_capacity: int = 0) {
  176. new_capacity := max(array_len(a^)*2 + 8, min_capacity);
  177. array_set_capacity(a, new_capacity);
  178. }