2025-01-03 00:42:38 +04:00

82 lines
1.6 KiB
Odin

package freelist
import "base:builtin"
import "base:runtime"
Element :: struct($T: typeid) {
value: T,
next_plus_one: int,
}
Free_List :: struct($T: typeid) {
data: [dynamic]Element(T),
len: int,
first_free_plus_one: int,
}
init :: proc(f: ^$T/Free_List($E), allocator := context.allocator) -> Free_List(T) {
if f.data.allocator.procedure == nil {
f.data.allocator = allocator
}
clear(f)
}
insert :: proc(
f: ^$T/Free_List($E),
value: E,
loc := #caller_location,
) -> (
int,
runtime.Allocator_Error,
) #optional_allocator_error {
if (f.first_free_plus_one > 0) {
index := f.first_free_plus_one - 1
result := &f.data[index]
f.first_free_plus_one = result.next_plus_one
result.value = value
f.len += 1
return index, nil
} else {
_, err := builtin.append(&f.data, Element(E){value = value}, loc)
if err == nil {
f.len += 1
}
return builtin.len(f.data) - 1, err
}
}
remove :: proc(f: ^$T/Free_List($E), #any_int index: int) {
elem := &f.data[index]
elem.next_plus_one = f.first_free_plus_one
f.first_free_plus_one = index + 1
f.len -= 1
}
len :: proc(f: ^$T/Free_List($E)) -> int {
return f.len
}
cap :: proc(f: ^$T/Free_List($E)) -> int {
return builtin.len(f.data)
}
// Remaining space in the freelist (cap-len)
space :: proc(f: ^$T/Free_List($E)) -> int {
return builtin.len(f.data) - int(f.len)
}
reserve :: proc(f: ^$T/Free_List($E), capacity: int) -> runtime.Allocator_Error {
return builtin.reserve(f.data, capacity)
}
clear :: proc(f: ^$T/Free_List($E)) {
builtin.clear(f.data)
f.first_free_plus_one = 0
}
destroy :: proc(f: ^$T/Free_List) {
delete(f.data)
}