array.odin 4.6 KB

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