Improved consistency with naming of init / create / destroy and when to propagate allocation errors and (#18)

Co-authored-by: Zachary Levy <zachary@sunforge.is>
Reviewed-on: #18
This commit was merged in pull request #18.
This commit is contained in:
2026-04-24 21:46:21 +00:00
parent bca19277b3
commit e36229a3ef
3 changed files with 325 additions and 146 deletions
+34 -28
View File
@@ -2,6 +2,7 @@ package many_bits
import "base:builtin"
import "base:intrinsics"
import "base:runtime"
import "core:fmt"
import "core:slice"
@@ -25,15 +26,20 @@ Bits :: struct {
length: int, // Total number of bits being stored
}
delete :: proc(bits: Bits, allocator := context.allocator) {
delete_slice(bits.int_array, allocator)
destroy :: proc(bits: Bits, allocator := context.allocator) -> runtime.Allocator_Error {
return delete_slice(bits.int_array, allocator)
}
make :: proc(#any_int length: int, allocator := context.allocator) -> Bits {
return Bits {
int_array = make_slice([]Int_Bits, ((length - 1) >> INDEX_SHIFT) + 1, allocator),
length = length,
}
create :: proc(
#any_int length: int,
allocator := context.allocator,
) -> (
bits: Bits,
err: runtime.Allocator_Error,
) #optional_allocator_error {
bits.int_array, err = make_slice([]Int_Bits, ((length - 1) >> INDEX_SHIFT) + 1, allocator)
bits.length = length
return bits, err
}
// Sets all bits to 0 (false)
@@ -507,8 +513,8 @@ import "core:testing"
@(test)
test_set :: proc(t: ^testing.T) {
bits := make(128)
defer delete(bits)
bits := create(128)
defer destroy(bits)
set(bits, 0, true)
testing.expect_value(t, bits.int_array[0], Int_Bits{0})
@@ -524,8 +530,8 @@ test_set :: proc(t: ^testing.T) {
@(test)
test_get :: proc(t: ^testing.T) {
bits := make(128)
defer delete(bits)
bits := create(128)
defer destroy(bits)
// Default is false
testing.expect(t, !get(bits, 0))
@@ -560,8 +566,8 @@ test_get :: proc(t: ^testing.T) {
@(test)
test_set_true_set_false :: proc(t: ^testing.T) {
bits := make(128)
defer delete(bits)
bits := create(128)
defer destroy(bits)
// set_true within first uint
set_true(bits, 0)
@@ -605,8 +611,8 @@ all_true_test :: proc(t: ^testing.T) {
uint_max := UINT_MAX
all_ones := transmute(Int_Bits)uint_max
bits := make(132)
defer delete(bits)
bits := create(132)
defer destroy(bits)
bits.int_array[0] = all_ones
bits.int_array[1] = all_ones
@@ -616,8 +622,8 @@ all_true_test :: proc(t: ^testing.T) {
bits.int_array[2] = {0, 1, 2}
testing.expect(t, !all_true(bits))
bits2 := make(1)
defer delete(bits2)
bits2 := create(1)
defer destroy(bits2)
bits2.int_array[0] = {0}
testing.expect(t, all_true(bits2))
@@ -628,8 +634,8 @@ test_range_true :: proc(t: ^testing.T) {
uint_max := UINT_MAX
all_ones := transmute(Int_Bits)uint_max
bits := make(192)
defer delete(bits)
bits := create(192)
defer destroy(bits)
// Empty range is vacuously true
testing.expect(t, range_true(bits, 0, 0))
@@ -676,7 +682,7 @@ test_range_true :: proc(t: ^testing.T) {
@(test)
nearest_true_handles_same_word_and_boundaries :: proc(t: ^testing.T) {
bits := make(128, context.temp_allocator)
bits := create(128, context.temp_allocator)
set_true(bits, 0)
set_true(bits, 10)
@@ -710,7 +716,7 @@ nearest_true_handles_same_word_and_boundaries :: proc(t: ^testing.T) {
@(test)
nearest_false_handles_same_word_and_boundaries :: proc(t: ^testing.T) {
bits := make(128, context.temp_allocator)
bits := create(128, context.temp_allocator)
// Start with all bits true, then clear a few to false.
for i := 0; i < bits.length; i += 1 {
@@ -749,7 +755,7 @@ nearest_false_handles_same_word_and_boundaries :: proc(t: ^testing.T) {
@(test)
nearest_false_scans_across_words_and_returns_false_when_all_true :: proc(t: ^testing.T) {
bits := make(192, context.temp_allocator)
bits := create(192, context.temp_allocator)
// Start with all bits true, then clear a couple far apart.
for i := 0; i < bits.length; i += 1 {
@@ -773,7 +779,7 @@ nearest_false_scans_across_words_and_returns_false_when_all_true :: proc(t: ^tes
@(test)
nearest_true_scans_across_words_and_returns_false_when_empty :: proc(t: ^testing.T) {
bits := make(192, context.temp_allocator)
bits := create(192, context.temp_allocator)
set_true(bits, 5)
set_true(bits, 130)
@@ -790,7 +796,7 @@ nearest_true_scans_across_words_and_returns_false_when_empty :: proc(t: ^testing
@(test)
nearest_false_handles_last_word_partial_length :: proc(t: ^testing.T) {
bits := make(130, context.temp_allocator)
bits := create(130, context.temp_allocator)
// Start with all bits true, then clear the first and last valid bits.
for i := 0; i < bits.length; i += 1 {
@@ -811,7 +817,7 @@ nearest_false_handles_last_word_partial_length :: proc(t: ^testing.T) {
@(test)
nearest_true_handles_last_word_partial_length :: proc(t: ^testing.T) {
bits := make(130, context.temp_allocator)
bits := create(130, context.temp_allocator)
set_true(bits, 0)
set_true(bits, 129)
@@ -828,7 +834,7 @@ nearest_true_handles_last_word_partial_length :: proc(t: ^testing.T) {
@(test)
iterator_basic_mixed_bits :: proc(t: ^testing.T) {
// Use non-word-aligned length to test partial last word handling
bits := make(100, context.temp_allocator)
bits := create(100, context.temp_allocator)
// Set specific bits: 0, 3, 64, 99 (last valid index)
set_true(bits, 0)
@@ -903,7 +909,7 @@ iterator_basic_mixed_bits :: proc(t: ^testing.T) {
@(test)
iterator_all_false_bits :: proc(t: ^testing.T) {
// Use non-word-aligned length
bits := make(100, context.temp_allocator)
bits := create(100, context.temp_allocator)
// All bits default to false, no need to set anything
// Test iterate - should return all 100 bits as false
@@ -944,7 +950,7 @@ iterator_all_false_bits :: proc(t: ^testing.T) {
@(test)
iterator_all_true_bits :: proc(t: ^testing.T) {
// Use non-word-aligned length
bits := make(100, context.temp_allocator)
bits := create(100, context.temp_allocator)
// Set all bits to true
for i := 0; i < bits.length; i += 1 {
set_true(bits, i)