From dd796b12f4643e871977b3c50d721023196d8932 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 12 Jan 2025 17:27:53 +0100 Subject: [PATCH] ui id strategy and core_hash.c --- src/core/{core_random.c => core_hash.c} | 27 ++++++++-- src/core/core_hash_table.c | 18 ++----- src/core/core_inc.c | 2 +- src/core/core_string.h | 1 + src/wasm_app/ui.c | 71 +++++++++++++------------ 5 files changed, 65 insertions(+), 54 deletions(-) rename src/core/{core_random.c => core_hash.c} (50%) diff --git a/src/core/core_random.c b/src/core/core_hash.c similarity index 50% rename from src/core/core_random.c rename to src/core/core_hash.c index 3a3db9e..2d65030 100644 --- a/src/core/core_random.c +++ b/src/core/core_hash.c @@ -4,7 +4,7 @@ struct random_seed_t { }; // xorshift64 -u64 get_random_u64(random_seed_t *seed) { +fn u64 get_random_u64(random_seed_t *seed) { u64 x = seed->a; x ^= x << 13; x ^= x >> 7; @@ -12,7 +12,7 @@ u64 get_random_u64(random_seed_t *seed) { return seed->a = x; } -u64 get_random_in_range_u64(random_seed_t *seed, u64 start, u64 one_past_end) { +fn u64 get_random_in_range_u64(random_seed_t *seed, u64 start, u64 one_past_end) { u64 r = get_random_u64(seed); u64 diff = one_past_end - start; u64 rr = r % diff; @@ -20,7 +20,7 @@ u64 get_random_in_range_u64(random_seed_t *seed, u64 start, u64 one_past_end) { return rrr; } -i64 get_random_in_range_i64(random_seed_t *seed, i64 start, i64 one_past_end) { +fn i64 get_random_in_range_i64(random_seed_t *seed, i64 start, i64 one_past_end) { u64 r = get_random_u64(seed); i64 diff = one_past_end - start; u64 rr = r % diff; @@ -28,8 +28,25 @@ i64 get_random_in_range_i64(random_seed_t *seed, i64 start, i64 one_past_end) { return rrr; } -f64 get_random_f64(random_seed_t *seed) { +fn f64 get_random_f64(random_seed_t *seed) { f64 random = (f64)get_random_in_range_u64(seed, 0, UINT32_MAX); f64 result = random / (f64)(UINT32_MAX - 1u); return result; -} \ No newline at end of file +} + +fn u64 hash_data(s8_t string) { + u8 *data = (u8 *)string.str; + u64 hash = (u64)14695981039346656037ULL; + for (i64 i = 0; i < string.len; i++) { + hash = hash ^ (u64)(data[i]); + hash = hash * (u64)1099511628211ULL; + } + return hash; +} + +fn u64 hash_mix(u64 x, u64 y) { + x ^= y; + x *= 0xff51afd7ed558ccd; + x ^= x >> 32; + return x; +} diff --git a/src/core/core_hash_table.c b/src/core/core_hash_table.c index 700fcb0..0f6f4a8 100644 --- a/src/core/core_hash_table.c +++ b/src/core/core_hash_table.c @@ -33,16 +33,6 @@ struct ht_dict_t { ht_bucket_t *buckets; }; -u64 ht_hash_data(s8_t string) { - u8 *data = (u8 *)string.str; - uint64_t hash = (u64)14695981039346656037ULL; - for (i64 i = 0; i < string.len; i++) { - hash = hash ^ (u64)(data[i]); - hash = hash * (u64)1099511628211ULL; - } - return hash; -} - 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); @@ -61,7 +51,7 @@ ht_node_t *ht_insert_kv(ht_dict_t *ht, u64 hash, ht_key_value_t kv) { } ht_node_t *ht_insert_u64_u64(ht_dict_t *ht, u64 key, u64 value) { - u64 hash = ht_hash_data(s8((char *)&key, sizeof(key))); + u64 hash = hash_data(s8_struct(key)); return ht_insert_kv(ht, hash, (ht_key_value_t){.key_u64 = key, .value_u64 = value}); } @@ -70,12 +60,12 @@ ht_node_t *ht_insert_ptr(ht_dict_t *ht, void *key, void *value) { } ht_node_t *ht_insert_string(ht_dict_t *ht, s8_t key, s8_t value) { - u64 hash = ht_hash_data(key); + u64 hash = hash_data(key); 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) { - u64 hash = ht_hash_data(s8((char *)&key, sizeof(key))); + 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) { @@ -91,7 +81,7 @@ ht_node_t *ht_search_ptr(ht_dict_t *ht, void *key_ptr) { } ht_node_t *ht_search_string(ht_dict_t *ht, s8_t key) { - u64 hash = ht_hash_data(key); + u64 hash = hash_data(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) { diff --git a/src/core/core_inc.c b/src/core/core_inc.c index 2efaafb..be288cd 100644 --- a/src/core/core_inc.c +++ b/src/core/core_inc.c @@ -44,5 +44,5 @@ #include "core_log.c" #include "core_lexer.c" #include "core_type_info.c" -#include "core_random.c" +#include "core_hash.c" #include "core_hash_table.c" \ No newline at end of file diff --git a/src/core/core_string.h b/src/core/core_string.h index c779686..75855b4 100644 --- a/src/core/core_string.h +++ b/src/core/core_string.h @@ -155,6 +155,7 @@ void *sbin_read_data(stream_t *stream, i64 size); // // other #define s8_fmtspec(string) (int)(string).len, (string).str +#define s8_struct(DATA) (s8_t){.str = (char *)&(DATA), .len = sizeof(DATA)} #define S8_CODE(...) s8_lit(#__VA_ARGS__) #define S8_FILE s8_lit(__FILE__) #define S8_FILE_AND_LINE s8_lit(FILE_AND_LINE) diff --git a/src/wasm_app/ui.c b/src/wasm_app/ui.c index c940e03..0ab1c03 100644 --- a/src/wasm_app/ui.c +++ b/src/wasm_app/ui.c @@ -4,7 +4,7 @@ ** [ ] Using file and line ** [ ] Keyboard friendliness ** [ ] ui_em size -** +** [ ] strict */ typedef struct ui_id_t ui_id_t; @@ -86,8 +86,10 @@ struct ui_signal_t { }; typedef enum { - ui_id_strategy_hierarchy, - ui_id_strategy_code_loc, + ui_id_strategy_null = 0, + ui_id_strategy_use_hierarchy = set_bit(0), + ui_id_strategy_use_code_loc = set_bit(1), + ui_id_strategy_use_string = set_bit(2), } ui_id_strategy_t; typedef struct ui_t ui_t; @@ -126,14 +128,7 @@ fn b32 ui_is_active_box(ui_box_t *box) { return !ui_is_null_box(box) && box->id. #define ev_left_up(ev) ((ev)->kind == app_event_kind_mouse_up && ev_left(ev)) #define ev_left_down(ev) ((ev)->kind == app_event_kind_mouse_down && ev_left(ev)) -fn u64 ui_hash_mix(u64 x, u64 y) { - x ^= y; - x *= 0xff51afd7ed558ccd; - x ^= x >> 32; - return x; -} - -s8_t ui_get_display_string(s8_t string) { +fn s8_t ui_get_display_string(s8_t string) { s8_t result = string; if (s8_seek(result, s8_lit("##"), s8_seek_none, &result.len)) { int a = 10; @@ -141,7 +136,7 @@ s8_t ui_get_display_string(s8_t string) { return result; } -s8_t ui_get_hash_string(s8_t string) { +fn s8_t ui_get_hash_string(s8_t string) { i64 len = 0; if (s8_seek(string, s8_lit("##"), s8_seek_none, &len)) { string = s8_skip(string, len + 2); @@ -149,12 +144,6 @@ s8_t ui_get_hash_string(s8_t string) { return string; } -fn ui_id_t ui_id_from_string(s8_t string) { - u64 value = ht_hash_data(ui_get_hash_string(string)); - ui_id_t id = {value}; - return id; -} - fn ui_id_t ui_find_valid_id(ui_box_t *box) { for (ui_box_t *it = box; it; it = it->parent) { if (!ui_is_null_box(it)) return it->id; @@ -162,7 +151,7 @@ fn ui_id_t ui_find_valid_id(ui_box_t *box) { return ui_id_null; } -fn ui_id_t ui_id_from_parent(void) { +fn ui_id_t ui_find_top_id(void) { ui_id_t parent_id = ui_find_valid_id(ui->top); if (ui_is_null_id(parent_id)) parent_id.value = 1423; return parent_id; @@ -216,20 +205,31 @@ fn ui_box_t *ui_build_box_from_id(ui_code_loc_t loc, ui_id_t id) { return box; } -fn ui_box_t *ui_build_box_from_string(ui_code_loc_t loc, s8_t string) { - ui_id_t id = {32}; - ui_id_t string_id = ui_id_from_string(string); - if (ui->id_strategy == ui_id_strategy_code_loc) { - u64 file_hash = ht_hash_data(s8_from_char(loc.file)); - u64 line_hash = ht_hash_data(s8((char *)&loc.line, sizeof(loc.line))); - u64 cont_hash = ht_hash_data(s8((char *)&loc.counter, sizeof(loc.counter))); - id.value = ui_hash_mix(file_hash, line_hash); - id.value = ui_hash_mix(id.value, cont_hash); - } else if (ui->id_strategy == ui_id_strategy_hierarchy) { - ui_id_t id_from_stack = ui_id_from_parent(); - id.value = ui_hash_mix(string_id.value, id_from_stack.value); - } else_is_invalid; +fn ui_id_t ui_gen_id(ui_id_strategy_t strat, ui_code_loc_t loc, s8_t string) { + assert(strat != 0); + u64 result = 42523423493; + if (strat & ui_id_strategy_use_string) { + u64 string_hash = hash_data(string); + result = hash_mix(string_hash, result); + } + if (strat & ui_id_strategy_use_hierarchy) { + ui_id_t top_id = ui_find_top_id(); + result = hash_mix(top_id.value, result); + } + if (strat & ui_id_strategy_use_code_loc) { + u64 file_hash = hash_data(s8_from_char(loc.file)); + u64 line_hash = hash_data(s8_struct(loc.line)); + u64 cont_hash = hash_data(s8_struct(loc.counter)); + result = hash_mix(result, file_hash); + result = hash_mix(result, line_hash); + result = hash_mix(result, cont_hash); + } + ui_id_t id = {result}; + return id; +} +fn ui_box_t *ui_build_box_from_string(ui_code_loc_t loc, s8_t string) { + ui_id_t id = ui_gen_id(ui->id_strategy, loc, ui_get_hash_string(string)); ui_box_t *box = ui_build_box_from_id(loc, id); box->string = ui_get_display_string(string); return box; @@ -269,6 +269,7 @@ fn void ui_init(ma_arena_t *arena) { ui = ma_push_type(arena, ui_t); ui->box_arena = arena; ui->root = ma_push_type(arena, ui_box_t); + ui->id_strategy = ui_id_strategy_use_string | ui_id_strategy_use_code_loc; ui->box_array = ma_push_type(arena, ui_box_t); SLLS_PUSH(ui->free_first, ui->box_array); @@ -499,12 +500,14 @@ fn void ui_draw(void) { // compute: (percent_of_parent) for (ui_preorder_iter_t it = ui_iterate_preorder(ui->root); ui_preorder_iter_is_valid(it); ui_iter_advance_preorder(&it)) { ui_box_t *box = it.box; - ui_box_t *parent = box->parent; + ui_box_t *parent = box->parent; // @todo: I'm not sure why Ryan uses a loop to find a parent with fixed size_kind for (i32 i = 0; i < ui_axis2_count; i += 1) { ui_size_t sem = box->semantic_size[i]; if (sem.kind == ui_size_kind_percent_of_parent) { assert(sem.value >= 0 && sem.value <= 1.0); - assert(parent->semantic_size[i].kind == ui_size_kind_pixels || parent->semantic_size[i].kind == ui_size_kind_text_content); + assert(parent->semantic_size[i].kind == ui_size_kind_pixels || + parent->semantic_size[i].kind == ui_size_kind_text_content || + parent->semantic_size[i].kind == ui_size_kind_percent_of_parent); box->computed_size[i] = sem.value * parent->computed_size[i]; } }