102 lines
2.1 KiB
Odin

// String interning thingy
package name
import "core:mem"
import "core:strings"
import "core:sync"
import "libs:tracy"
// When enabled name globals will be initialized automatically
NAME_STATIC_INIT :: #config(NAME_STATIC_INIT, true)
MAX_STATIC_NAMES :: #config(MAX_STATIC_NAMES, 1024)
Name :: distinct u32
NONE :: Name(0)
Container :: struct {
lock: sync.Atomic_RW_Mutex,
names_lookup: map[string]Name,
names_allocator: mem.Dynamic_Arena,
names_array: [dynamic]string,
}
@(private = "file")
global_container: ^Container
setup_global_container :: proc(cnt: ^Container) {
global_container = cnt
}
init :: proc(cnt: ^Container) {
mem.dynamic_arena_init(&cnt.names_allocator)
assert(len(cnt.names_array) == 0)
append(&cnt.names_array, "None")
}
destroy :: proc() {
assert(global_container != nil)
delete(global_container.names_array)
delete(global_container.names_lookup)
mem.dynamic_arena_destroy(&global_container.names_allocator)
global_container = nil
}
when NAME_STATIC_INIT {
@(private = "file")
static_container: Container
@(init)
init_static :: proc() {
init(&static_container)
setup_global_container(&static_container)
}
@(fini)
fini_static :: proc() {
destroy()
}
}
from_string :: proc(str: string) -> Name {
tracy.Zone()
existing: Name
ok: bool
{
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
existing, ok = global_container.names_lookup[str]
}
if ok {
return existing
} else {
sync.atomic_rw_mutex_guard(&global_container.lock)
new_str := strings.clone_to_cstring(
str,
mem.dynamic_arena_allocator(&global_container.names_allocator),
)
idx := u32(len(global_container.names_array))
append(&global_container.names_array, string(new_str))
global_container.names_lookup[str] = Name(idx)
return Name(idx)
}
}
from_cstring :: proc(str: cstring) -> Name {
return from_string(string(str))
}
to_string :: proc(name: Name) -> string {
tracy.Zone()
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
return global_container.names_array[name]
}
to_cstring :: proc(name: Name) -> cstring {
return strings.unsafe_string_to_cstring(to_string(name))
}