small_array.odin 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package container_small_array
  2. import "core:builtin"
  3. import "core:runtime"
  4. _ :: runtime
  5. Small_Array :: struct($N: int, $T: typeid) where N >= 0 {
  6. data: [N]T,
  7. len: int,
  8. }
  9. len :: proc "contextless" (a: $A/Small_Array) -> int {
  10. return a.len
  11. }
  12. cap :: proc "contextless" (a: $A/Small_Array) -> int {
  13. return builtin.len(a.data)
  14. }
  15. space :: proc "contextless" (a: $A/Small_Array) -> int {
  16. return builtin.len(a.data) - a.len
  17. }
  18. slice :: proc "contextless" (a: ^$A/Small_Array($N, $T)) -> []T {
  19. return a.data[:a.len]
  20. }
  21. get :: proc "contextless" (a: $A/Small_Array($N, $T), index: int) -> T {
  22. return a.data[index]
  23. }
  24. get_ptr :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int) -> ^T {
  25. return &a.data[index]
  26. }
  27. get_safe :: proc(a: $A/Small_Array($N, $T), index: int) -> (T, bool) #no_bounds_check {
  28. if index < 0 || index >= a.len {
  29. return {}, false
  30. }
  31. return a.data[index], true
  32. }
  33. get_ptr_safe :: proc(a: ^$A/Small_Array($N, $T), index: int) -> (^T, bool) #no_bounds_check {
  34. if index < 0 || index >= a.len {
  35. return {}, false
  36. }
  37. return &a.data[index], true
  38. }
  39. set :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, item: T) {
  40. a.data[index] = item
  41. }
  42. resize :: proc "contextless" (a: ^$A/Small_Array, length: int) {
  43. a.len = min(length, builtin.len(a.data))
  44. }
  45. push_back :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T) -> bool {
  46. if a.len < cap(a^) {
  47. a.data[a.len] = item
  48. a.len += 1
  49. return true
  50. }
  51. return false
  52. }
  53. push_front :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T) -> bool {
  54. if a.len < cap(a^) {
  55. a.len += 1
  56. data := slice(a)
  57. copy(data[1:], data[:])
  58. data[0] = item
  59. return true
  60. }
  61. return false
  62. }
  63. pop_back :: proc "odin" (a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T {
  64. assert(condition=(N > 0 && a.len > 0), loc=loc)
  65. item := a.data[a.len-1]
  66. a.len -= 1
  67. return item
  68. }
  69. pop_front :: proc "odin" (a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T {
  70. assert(condition=(N > 0 && a.len > 0), loc=loc)
  71. item := a.data[0]
  72. s := slice(a)
  73. copy(s[:], s[1:])
  74. a.len -= 1
  75. return item
  76. }
  77. pop_back_safe :: proc "contextless" (a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) {
  78. if N > 0 && a.len > 0 {
  79. item = a.data[a.len-1]
  80. a.len -= 1
  81. ok = true
  82. }
  83. return
  84. }
  85. pop_front_safe :: proc "contextless" (a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) {
  86. if N > 0 && a.len > 0 {
  87. item = a.data[0]
  88. s := slice(a)
  89. copy(s[:], s[1:])
  90. a.len -= 1
  91. ok = true
  92. }
  93. return
  94. }
  95. consume :: proc "odin" (a: ^$A/Small_Array($N, $T), count: int, loc := #caller_location) {
  96. assert(condition=a.len >= count, loc=loc)
  97. a.len -= count
  98. }
  99. ordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check {
  100. runtime.bounds_check_error_loc(loc, index, a.len)
  101. if index+1 < a.len {
  102. copy(a.data[index:], a.data[index+1:])
  103. }
  104. a.len -= 1
  105. }
  106. unordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check {
  107. runtime.bounds_check_error_loc(loc, index, a.len)
  108. n := a.len-1
  109. if index != n {
  110. a.data[index] = a.data[n]
  111. }
  112. a.len -= 1
  113. }
  114. clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) {
  115. resize(a, 0)
  116. }
  117. push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) {
  118. n := copy(a.data[a.len:], items[:])
  119. a.len += n
  120. }
  121. inject_at :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T, index: int) -> bool #no_bounds_check {
  122. if a.len < cap(a^) && index >= 0 && index <= len(a^) {
  123. a.len += 1
  124. for i := a.len - 1; i >= index + 1; i -= 1 {
  125. a.data[i] = a.data[i - 1]
  126. }
  127. a.data[index] = item
  128. return true
  129. }
  130. return false
  131. }
  132. append_elem :: push_back
  133. append_elems :: push_back_elems
  134. push :: proc{push_back, push_back_elems}
  135. append :: proc{push_back, push_back_elems}