82 lines
1.6 KiB
Odin
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)
|
|
}
|