intern identifiers
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package symbol
|
||||
|
||||
import "core:mem"
|
||||
import "core:strings"
|
||||
|
||||
Id :: distinct u32
|
||||
|
||||
INVALID :: Id(0)
|
||||
|
||||
Table :: struct {
|
||||
items: [dynamic]string,
|
||||
lookup: map[string]Id,
|
||||
stored_bytes: int,
|
||||
allocator: mem.Allocator,
|
||||
}
|
||||
|
||||
init_table :: proc(allocator := context.allocator) -> Table {
|
||||
table: Table
|
||||
table.items.allocator = allocator
|
||||
table.lookup.allocator = allocator
|
||||
table.allocator = allocator
|
||||
return table
|
||||
}
|
||||
|
||||
destroy_table :: proc(table: ^Table) {
|
||||
delete(table.lookup)
|
||||
for item in table.items {
|
||||
delete(item, table.allocator)
|
||||
}
|
||||
delete(table.items)
|
||||
}
|
||||
|
||||
intern :: proc(table: ^Table, text: string) -> Id {
|
||||
if len(text) == 0 {
|
||||
return INVALID
|
||||
}
|
||||
if id, ok := table.lookup[text]; ok {
|
||||
return id
|
||||
}
|
||||
cloned := strings.clone(text, table.allocator)
|
||||
id := Id(len(table.items) + 1)
|
||||
append(&table.items, cloned)
|
||||
table.lookup[cloned] = id
|
||||
table.stored_bytes += len(cloned)
|
||||
return id
|
||||
}
|
||||
|
||||
resolve :: proc(table: ^Table, id: Id) -> string {
|
||||
index := int(id) - 1
|
||||
if index < 0 || index >= len(table.items) {
|
||||
return ""
|
||||
}
|
||||
return table.items[index]
|
||||
}
|
||||
|
||||
is_valid :: proc(id: Id) -> bool {
|
||||
return id != INVALID
|
||||
}
|
||||
Reference in New Issue
Block a user