diff options
| author | Lucas Perlind <perlindluca@gmail.com> | 2022-12-17 14:23:05 +1100 |
|---|---|---|
| committer | Lucas Perlind <perlindluca@gmail.com> | 2022-12-21 13:00:33 +1100 |
| commit | f029b4beb1f8a037334ff68bd459049b1e44ef31 (patch) | |
| tree | c59fb5441a5b768b0110db2b562b6516d01fd10f | |
| parent | 0829ac30f743aa567b2da5dc490ff1b2b13ea37c (diff) | |
Add more utility procedures to small array
| -rw-r--r-- | core/container/small_array/small_array.odin | 47 | ||||
| -rw-r--r-- | tests/core/build.bat | 7 | ||||
| -rw-r--r-- | tests/core/container/test_core_small_array.odin | 56 |
3 files changed, 108 insertions, 2 deletions
diff --git a/core/container/small_array/small_array.odin b/core/container/small_array/small_array.odin index b8210d1b0..b471d1706 100644 --- a/core/container/small_array/small_array.odin +++ b/core/container/small_array/small_array.odin @@ -1,6 +1,8 @@ package container_small_array import "core:builtin" +import "core:runtime" +_ :: runtime Small_Array :: struct($N: int, $T: typeid) where N >= 0 { data: [N]T, @@ -32,6 +34,20 @@ get_ptr :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int) -> ^T { return &a.data[index] } +get_safe :: proc(a: $A/Small_Array($N, $T), index: int) -> (T, bool) #no_bounds_check { + if index < 0 || index >= a.len { + return {}, false + } + return a.data[index], true +} + +get_ptr_safe :: proc(a: ^$A/Small_Array($N, $T), index: int) -> (^T, bool) #no_bounds_check { + if index < 0 || index >= a.len { + return {}, false + } + return &a.data[index], true +} + set :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, item: T) { a.data[index] = item } @@ -93,7 +109,7 @@ pop_front_safe :: proc "contextless" (a: ^$A/Small_Array($N, $T)) -> (item: T, o copy(s[:], s[1:]) a.len -= 1 ok = true - } + } return } @@ -102,6 +118,23 @@ consume :: proc "odin" (a: ^$A/Small_Array($N, $T), count: int, loc := #caller_l a.len -= count } +ordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check { + runtime.bounds_check_error_loc(loc, index, a.len) + if index+1 < a.len { + copy(a.data[index:], a.data[index+1:]) + } + a.len -= 1 +} + +unordered_remove :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, loc := #caller_location) #no_bounds_check { + runtime.bounds_check_error_loc(loc, index, a.len) + n := a.len-1 + if index != n { + a.data[index] = a.data[n] + } + a.len -= 1 +} + clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) { resize(a, 0) } @@ -111,6 +144,18 @@ push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) { a.len += n } +inject_at :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T, index: int) -> bool #no_bounds_check { + if a.len < cap(a^) && index >= 0 && index <= len(a^) { + a.len += 1 + for i := a.len - 1; i >= index + 1; i -= 1 { + a.data[i] = a.data[i - 1] + } + a.data[index] = item + return true + } + return false +} + append_elem :: push_back append_elems :: push_back_elems push :: proc{push_back, push_back_elems} diff --git a/tests/core/build.bat b/tests/core/build.bat index 94f8e0fd8..69a102daa 100644 --- a/tests/core/build.bat +++ b/tests/core/build.bat @@ -74,4 +74,9 @@ echo --- echo ---
echo Running core:slice tests
echo ---
-%PATH_TO_ODIN% run slice %COMMON% -out:test_core_slice.exe
\ No newline at end of file +%PATH_TO_ODIN% run slice %COMMON% -out:test_core_slice.exe
+
+echo ---
+echo Running core:container tests
+echo ---
+%PATH_TO_ODIN% run container %COMMON% %COLLECTION% -out:test_core_container.exe
diff --git a/tests/core/container/test_core_small_array.odin b/tests/core/container/test_core_small_array.odin new file mode 100644 index 000000000..88bc8e532 --- /dev/null +++ b/tests/core/container/test_core_small_array.odin @@ -0,0 +1,56 @@ +package test_core_compress + +import "core:fmt" +import "core:testing" +import "core:container/small_array" +import tc "tests:common" + +main :: proc() { + t := testing.T{} + test_small_array_removes(&t) + test_small_array_inject_at(&t) + tc.report(&t) +} + +expect_equal :: proc(t: ^testing.T, the_slice, expected: []int, loc := #caller_location) { + _eq :: proc(a, b: []int) -> bool { + if len(a) != len(b) do return false + for a, i in a { + if b[i] != a do return false + } + return true + } + tc.expect(t, _eq(the_slice, expected), fmt.tprintf("Expected %v, got %v\n", the_slice, expected), loc) +} + +@test +test_small_array_removes :: proc(t: ^testing.T) { + array: small_array.Small_Array(10, int) + small_array.append(&array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + + small_array.ordered_remove(&array, 0) + expect_equal(t, small_array.slice(&array), []int { 1, 2, 3, 4, 5, 6, 7, 8, 9 }) + small_array.ordered_remove(&array, 5) + expect_equal(t, small_array.slice(&array), []int { 1, 2, 3, 4, 5, 7, 8, 9 }) + small_array.ordered_remove(&array, 6) + expect_equal(t, small_array.slice(&array), []int { 1, 2, 3, 4, 5, 7, 9 }) + small_array.unordered_remove(&array, 0) + expect_equal(t, small_array.slice(&array), []int { 9, 2, 3, 4, 5, 7 }) + small_array.unordered_remove(&array, 2) + expect_equal(t, small_array.slice(&array), []int { 9, 2, 7, 4, 5 }) + small_array.unordered_remove(&array, 4) + expect_equal(t, small_array.slice(&array), []int { 9, 2, 7, 4 }) +} + +@test +test_small_array_inject_at :: proc(t: ^testing.T) { + array: small_array.Small_Array(13, int) + small_array.append(&array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + + tc.expect(t, small_array.inject_at(&array, 0, 0), "Expected to be able to inject into small array") + expect_equal(t, small_array.slice(&array), []int { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }) + tc.expect(t, small_array.inject_at(&array, 0, 5), "Expected to be able to inject into small array") + expect_equal(t, small_array.slice(&array), []int { 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9 }) + tc.expect(t, small_array.inject_at(&array, 0, small_array.len(array)), "Expected to be able to inject into small array") + expect_equal(t, small_array.slice(&array), []int { 0, 0, 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 0 }) +} |