revisit hash_table, add interning

This commit is contained in:
Krzosa Karol
2025-01-20 10:24:03 +01:00
parent 63cc0d92f1
commit f863f847dc
7 changed files with 95 additions and 82 deletions

View File

@@ -16,6 +16,8 @@ struct thread_ctx_t {
gb_thread thread_ctx_t tcx = { gb_thread thread_ctx_t tcx = {
.log = { .log = {
.break_on_fatal = true, .break_on_fatal = true,
.break_on_error = true,
.break_on_warning = true,
.log_proc = default_log_proc, .log_proc = default_log_proc,
} }
}; };

View File

@@ -1,47 +1,12 @@
fn ht_t *ht_create(ma_arena_t *arena, i32 size) {
typedef struct ht_key_value_t ht_key_value_t; ht_t *result = ma_push_type(arena, ht_t);
struct ht_key_value_t {
union {
s8_t key_string;
u64 key_u64;
void *key_ptr;
};
union {
s8_t value_string;
void *value_ptr;
u64 value_u64;
};
};
typedef struct ht_node_t ht_node_t;
struct ht_node_t {
ht_node_t *next;
ht_key_value_t kv;
};
typedef struct ht_bucket_t ht_bucket_t;
struct ht_bucket_t {
ht_node_t *first;
ht_node_t *last;
};
typedef struct ht_dict_t ht_dict_t;
struct ht_dict_t {
ma_arena_t *arena;
i32 item_count;
i32 bucket_count;
ht_bucket_t *buckets;
};
ht_dict_t *ht_create(ma_arena_t *arena, i32 size) {
ht_dict_t *result = ma_push_type(arena, ht_dict_t);
result->buckets = ma_push_array(arena, ht_bucket_t, size); result->buckets = ma_push_array(arena, ht_bucket_t, size);
result->bucket_count = size; result->bucket_count = size;
result->arena = arena; result->arena = arena;
return result; return result;
} }
ht_node_t *ht_insert_kv(ht_dict_t *ht, u64 hash, ht_key_value_t kv) { fn ht_node_t *ht_insert_kv(ht_t *ht, u64 hash, ht_key_value_t kv) {
ht_node_t *result = ma_push_type(ht->arena, ht_node_t); ht_node_t *result = ma_push_type(ht->arena, ht_node_t);
result->kv = kv; result->kv = kv;
i64 idx = hash % ht->bucket_count; i64 idx = hash % ht->bucket_count;
@@ -50,21 +15,26 @@ ht_node_t *ht_insert_kv(ht_dict_t *ht, u64 hash, ht_key_value_t kv) {
return result; return result;
} }
ht_node_t *ht_insert_u64_u64(ht_dict_t *ht, u64 key, u64 value) { fn ht_node_t *ht_insert_u64(ht_t *ht, u64 key, u64 value) {
u64 hash = hash_data(s8_struct(key)); u64 hash = hash_data(s8_struct(key));
return ht_insert_kv(ht, hash, (ht_key_value_t){.key_u64 = key, .value_u64 = value}); return ht_insert_kv(ht, hash, (ht_key_value_t){.key_u64 = key, .value_u64 = value});
} }
ht_node_t *ht_insert_ptr(ht_dict_t *ht, void *key, void *value) { fn ht_node_t *ht_insert_ptr(ht_t *ht, void *key, void *value) {
return ht_insert_u64_u64(ht, (u64)key, (u64)value); return ht_insert_u64(ht, (u64)key, (u64)value);
} }
ht_node_t *ht_insert_string(ht_dict_t *ht, s8_t key, s8_t value) { fn ht_node_t *ht_insert_string(ht_t *ht, s8_t key, s8_t value) {
u64 hash = hash_data(key); u64 hash = hash_data(key);
return ht_insert_kv(ht, hash, (ht_key_value_t){.key_string = key, .value_string = value}); return ht_insert_kv(ht, hash, (ht_key_value_t){.key_string = key, .value_string = value});
} }
ht_node_t *ht_search_u64(ht_dict_t *ht, u64 key) { fn ht_node_t *ht_insert_string_ptr(ht_t *ht, s8_t key, void *value) {
u64 hash = hash_data(key);
return ht_insert_kv(ht, hash, (ht_key_value_t){.key_string = key, .value_ptr = value});
}
fn ht_node_t *ht_search_u64_ex(ht_t *ht, u64 key) {
u64 hash = hash_data(s8_struct(key)); u64 hash = hash_data(s8_struct(key));
i64 idx = hash % ht->bucket_count; i64 idx = hash % ht->bucket_count;
ht_bucket_t *bucket = ht->buckets + idx; ht_bucket_t *bucket = ht->buckets + idx;
@@ -76,11 +46,19 @@ ht_node_t *ht_search_u64(ht_dict_t *ht, u64 key) {
return NULL; return NULL;
} }
ht_node_t *ht_search_ptr(ht_dict_t *ht, void *key_ptr) { fn ht_node_t *ht_search_ptr_ex(ht_t *ht, void *key) {
return ht_search_u64(ht, (u64)key_ptr); u64 hash = hash_data(s8_struct(key));
i64 idx = hash % ht->bucket_count;
ht_bucket_t *bucket = ht->buckets + idx;
for (ht_node_t *it = bucket->first; it; it = it->next) {
if (it->kv.key_ptr == key) {
return it;
}
}
return NULL;
} }
ht_node_t *ht_search_string(ht_dict_t *ht, s8_t key) { fn ht_node_t *ht_search_string_ex(ht_t *ht, s8_t key) {
u64 hash = hash_data(key); u64 hash = hash_data(key);
i64 idx = hash % ht->bucket_count; i64 idx = hash % ht->bucket_count;
ht_bucket_t *bucket = ht->buckets + idx; ht_bucket_t *bucket = ht->buckets + idx;
@@ -91,3 +69,44 @@ ht_node_t *ht_search_string(ht_dict_t *ht, s8_t key) {
} }
return NULL; return NULL;
} }
fn u64 *ht_search_u64(ht_t *ht, u64 key) {
ht_node_t *node = ht_search_u64_ex(ht, key);
if (node) return &node->kv.value_u64;
return NULL;
}
fn void **ht_search_ptr(ht_t *ht, void *key) {
ht_node_t *node = ht_search_ptr_ex(ht, key);
if (node) return &node->kv.value_ptr;
return NULL;
}
fn s8_t *ht_search_string(ht_t *ht, s8_t key) {
ht_node_t *node = ht_search_string_ex(ht, key);
if (node) return &node->kv.value_string;
return NULL;
}
fn void **ht_search_string_ptr(ht_t *ht, s8_t key) {
ht_node_t *node = ht_search_string_ex(ht, key);
if (node) return &node->kv.value_ptr;
return NULL;
}
///////////////////////////////
// string interning
fn s8i_t *intern_string(ht_t *ht, s8_t string) {
s8_t *item = ht_search_string(ht, string);
if (!item) {
string = s8_copy(ht->arena, string);
ht_node_t *node = ht_insert_string(ht, string, string);
item = &node->kv.value_string;
}
return item;
}
fn s8i_t *internf(ht_t *ht, char *str, ...) {
S8_FMT(ht->arena, str, string);
return intern_string(ht, string);
}

View File

@@ -12,4 +12,5 @@
#include "core_type_info.h" #include "core_type_info.h"
#include "core_intrin.h" #include "core_intrin.h"
#include "core_platform.h" #include "core_platform.h"
#include "core_hash_table.h"
#include "core_ctx.h" #include "core_ctx.h"

View File

@@ -99,41 +99,54 @@ void test_s8(void) {
void test_hash_table(void) { void test_hash_table(void) {
ma_temp_t scratch = ma_begin_scratch(); ma_temp_t scratch = ma_begin_scratch();
{ {
ht_dict_t *ht = ht_create(scratch.arena, 16); ht_t *ht = ht_create(scratch.arena, 16);
for (u64 i = 0; i < 128; i += 1) { for (u64 i = 0; i < 128; i += 1) {
ht_insert_u64_u64(ht, i, i); ht_insert_u64(ht, i, i);
ht_node_t *node = ht_search_u64(ht, i); ht_node_t *node = ht_search_u64_ex(ht, i);
assert(node->kv.value_u64 == i); assert(node->kv.value_u64 == i);
assert(node->kv.key_u64 == i); assert(node->kv.key_u64 == i);
} }
for (u64 i = 0; i < 128; i += 1) { for (u64 i = 0; i < 128; i += 1) {
ht_node_t *node = ht_search_u64(ht, i); ht_node_t *node = ht_search_u64_ex(ht, i);
assert(node->kv.value_u64 == i); assert(node->kv.value_u64 == i);
assert(node->kv.key_u64 == i); assert(node->kv.key_u64 == i);
} }
ht_node_t *node = ht_search_u64(ht, 1111); ht_node_t *node = ht_search_u64_ex(ht, 1111);
assert(node == NULL); assert(node == NULL);
} }
{ {
ht_dict_t *ht = ht_create(scratch.arena, 16); ht_t *ht = ht_create(scratch.arena, 16);
for (i32 i = 0; i < 128; i += 1) { for (i32 i = 0; i < 128; i += 1) {
s8_t s = s8_printf(scratch.arena, "%d", i); s8_t s = s8_printf(scratch.arena, "%d", i);
ht_insert_string(ht, s, s); ht_insert_string(ht, s, s);
ht_node_t *node = ht_search_string(ht, s); ht_node_t *node = ht_search_string_ex(ht, s);
assert(s8_are_equal(node->kv.value_string, s)); assert(s8_are_equal(node->kv.value_string, s));
assert(s8_are_equal(node->kv.key_string, s)); assert(s8_are_equal(node->kv.key_string, s));
} }
ht_node_t *node = ht_search_string(ht, s8_lit("memes")); ht_node_t *node = ht_search_string_ex(ht, s8_lit("memes"));
assert(node == NULL); assert(node == NULL);
} }
ma_end_scratch(scratch); ma_end_scratch(scratch);
} }
void test_intern_table(void) {
ma_temp_t scratch = ma_begin_scratch();
ht_t *ht = ht_create(scratch.arena, 4);
assert(internf(ht, "asd") == internf(ht, "asd"));
assert(internf(ht, "asdf") != internf(ht, "asd"));
assert(internf(ht, "asdf") == internf(ht, "asdf"));
assert(internf(ht, "123asdf") == internf(ht, "123asdf"));
assert(internf(ht, "123asdf") != internf(ht, "133asdf"));
assert(internf(ht, "") == internf(ht, ""));
assert(internf(ht, "") != internf(ht, "a"));
ma_end_scratch(scratch);
}
#include <stdio.h> #include <stdio.h>
int main(int argc, char **argv) { int main(int argc, char **argv) {
@@ -149,6 +162,7 @@ int main(int argc, char **argv) {
test_s8(); test_s8();
test_hash_table(); test_hash_table();
test_intern_table();
printf("all done!\n"); printf("all done!\n");
} }

View File

@@ -118,7 +118,7 @@ fn s8_t cg_byte_array_from_data(ma_arena_t *arena, s8_t file, s8_t var_name) {
#define cg_cpath(arena) cg_gen_filename(arena, s8_lit(__FILE__), s8_lit("c")) #define cg_cpath(arena) cg_gen_filename(arena, s8_lit(__FILE__), s8_lit("c"))
#define cg_hpath(arena) cg_gen_filename(arena, s8_lit(__FILE__), s8_lit("h")) #define cg_hpath(arena) cg_gen_filename(arena, s8_lit(__FILE__), s8_lit("h"))
s8_t cg_gen_filename(ma_arena_t *arena, s8_t lit_file, s8_t ext) { fn s8_t cg_gen_filename(ma_arena_t *arena, s8_t lit_file, s8_t ext) {
s8_t file_noext = s8_chop_last_period(s8_chop_last_period(lit_file)); s8_t file_noext = s8_chop_last_period(s8_chop_last_period(lit_file));
s8_t file = s8_printf(arena, "%S.gen.%S", file_noext, ext); s8_t file = s8_printf(arena, "%S.gen.%S", file_noext, ext);
return file; return file;

View File

@@ -588,7 +588,7 @@ fn void ui_demo_update(app_frame_t *frame) {
ui_set_rect(item_box, r2f32_cut_left(&ui->top->rect, ui_max)); ui_set_rect(item_box, r2f32_cut_left(&ui->top->rect, ui_max));
static f32 scroller_value; static f32 scroller_value;
ui_set_text_align(ui_text_align_center) ui_set_text_align(ui_text_align_left)
ui_set_top(item_box) { ui_set_top(item_box) {
for (i32 i = 0; i < lengthof(tweak_table); i += 1) { for (i32 i = 0; i < lengthof(tweak_table); i += 1) {
mt_tweak_t *tweak = tweak_table + i; mt_tweak_t *tweak = tweak_table + i;
@@ -610,29 +610,7 @@ fn void ui_demo_update(app_frame_t *frame) {
} }
} else_is_invalid; } else_is_invalid;
} }
ui_serial_subtype(&primary_color_global, type(v4f32_t), s8_lit("primary_color_global"));
ui_serial_subtype(&secondary_color_global, type(v4f32_t), s8_lit("secondary_color_global"));
ui_serial_subtype(&accent1_color_global, type(v4f32_t), s8_lit("accent1_color_global"));
ui_serial_subtype(&accent2_color_global, type(v4f32_t), s8_lit("accent2_color_global"));
ui_serial_subtype(&white_color_global, type(v4f32_t), s8_lit("white_color_global"));
ui_serial_subtype(&black_color_global, type(v4f32_t), s8_lit("black_color_global"));
ui_serial_type(&ui_test_event, type(app_event_t)); ui_serial_type(&ui_test_event, type(app_event_t));
ui_expander("app_event_t") {
for (int i = 0; i < 2; i += 1) {
ui_label("kind: app_event_kind_t##a%d", i);
ui_label("ctrl: b8##ds%d", i);
ui_label("shift: b8##f%d", i);
ui_expander("pos: v3f32_t##gg%d", i) {
ui_label("x: f64 = value##hgt%d", i);
ui_label("y: f64 = value##r%d", i);
ui_label("z: f64 = value##yr%d", i);
}
ui_expander("mouse_pos: v2f32_t##i2%d", i) {
ui_label("x: f64 = value##i3%d", i);
ui_label("y: f64 = value##i4%d", i);
}
}
}
} }
// @todo: fix scroller to match mouse // @todo: fix scroller to match mouse

View File

@@ -23,10 +23,9 @@
[x] remove dates and time from core [x] remove dates and time from core
[ ] meta [ ] meta
[x] search for python snippets and execute meta.py script on that file [x] search for python snippets and execute meta.py script on that file
[ ] simplify logging!!!! [x] simplify logging!!!!
[ ] somehow index properly the meta files and ignore generated files [x] somehow index properly the meta files and ignore generated files
[x] extract declarations from c files meta(introspect) [x] extract declarations from c files meta(introspect)
[ ] extract all globals from c files
[x] tweak variables and embeds declared in c code [x] tweak variables and embeds declared in c code
[ ] new simple format with tags [ ] new simple format with tags
[x] revisit api [x] revisit api