ui id strategy and core_hash.c

This commit is contained in:
Krzosa Karol
2025-01-12 17:27:53 +01:00
parent 16125f5605
commit dd796b12f4
5 changed files with 65 additions and 54 deletions

View File

@@ -4,7 +4,7 @@ struct random_seed_t {
}; };
// xorshift64 // xorshift64
u64 get_random_u64(random_seed_t *seed) { fn u64 get_random_u64(random_seed_t *seed) {
u64 x = seed->a; u64 x = seed->a;
x ^= x << 13; x ^= x << 13;
x ^= x >> 7; x ^= x >> 7;
@@ -12,7 +12,7 @@ u64 get_random_u64(random_seed_t *seed) {
return seed->a = x; 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 r = get_random_u64(seed);
u64 diff = one_past_end - start; u64 diff = one_past_end - start;
u64 rr = r % diff; 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; 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); u64 r = get_random_u64(seed);
i64 diff = one_past_end - start; i64 diff = one_past_end - start;
u64 rr = r % diff; 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; 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 random = (f64)get_random_in_range_u64(seed, 0, UINT32_MAX);
f64 result = random / (f64)(UINT32_MAX - 1u); f64 result = random / (f64)(UINT32_MAX - 1u);
return result; return result;
} }
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;
}

View File

@@ -33,16 +33,6 @@ struct ht_dict_t {
ht_bucket_t *buckets; 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 *ht_create(ma_arena_t *arena, i32 size) {
ht_dict_t *result = ma_push_type(arena, ht_dict_t); 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);
@@ -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) { 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}); 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) { 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}); 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) { 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; i64 idx = hash % ht->bucket_count;
ht_bucket_t *bucket = ht->buckets + idx; ht_bucket_t *bucket = ht->buckets + idx;
for (ht_node_t *it = bucket->first; it; it = it->next) { 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) { 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; i64 idx = hash % ht->bucket_count;
ht_bucket_t *bucket = ht->buckets + idx; ht_bucket_t *bucket = ht->buckets + idx;
for (ht_node_t *it = bucket->first; it; it = it->next) { for (ht_node_t *it = bucket->first; it; it = it->next) {

View File

@@ -44,5 +44,5 @@
#include "core_log.c" #include "core_log.c"
#include "core_lexer.c" #include "core_lexer.c"
#include "core_type_info.c" #include "core_type_info.c"
#include "core_random.c" #include "core_hash.c"
#include "core_hash_table.c" #include "core_hash_table.c"

View File

@@ -155,6 +155,7 @@ void *sbin_read_data(stream_t *stream, i64 size);
// //
// other // other
#define s8_fmtspec(string) (int)(string).len, (string).str #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_CODE(...) s8_lit(#__VA_ARGS__)
#define S8_FILE s8_lit(__FILE__) #define S8_FILE s8_lit(__FILE__)
#define S8_FILE_AND_LINE s8_lit(FILE_AND_LINE) #define S8_FILE_AND_LINE s8_lit(FILE_AND_LINE)

View File

@@ -4,7 +4,7 @@
** [ ] Using file and line ** [ ] Using file and line
** [ ] Keyboard friendliness ** [ ] Keyboard friendliness
** [ ] ui_em size ** [ ] ui_em size
** ** [ ] strict
*/ */
typedef struct ui_id_t ui_id_t; typedef struct ui_id_t ui_id_t;
@@ -86,8 +86,10 @@ struct ui_signal_t {
}; };
typedef enum { typedef enum {
ui_id_strategy_hierarchy, ui_id_strategy_null = 0,
ui_id_strategy_code_loc, 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; } ui_id_strategy_t;
typedef struct ui_t ui_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_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)) #define ev_left_down(ev) ((ev)->kind == app_event_kind_mouse_down && ev_left(ev))
fn u64 ui_hash_mix(u64 x, u64 y) { fn s8_t ui_get_display_string(s8_t string) {
x ^= y;
x *= 0xff51afd7ed558ccd;
x ^= x >> 32;
return x;
}
s8_t ui_get_display_string(s8_t string) {
s8_t result = string; s8_t result = string;
if (s8_seek(result, s8_lit("##"), s8_seek_none, &result.len)) { if (s8_seek(result, s8_lit("##"), s8_seek_none, &result.len)) {
int a = 10; int a = 10;
@@ -141,7 +136,7 @@ s8_t ui_get_display_string(s8_t string) {
return result; return result;
} }
s8_t ui_get_hash_string(s8_t string) { fn s8_t ui_get_hash_string(s8_t string) {
i64 len = 0; i64 len = 0;
if (s8_seek(string, s8_lit("##"), s8_seek_none, &len)) { if (s8_seek(string, s8_lit("##"), s8_seek_none, &len)) {
string = s8_skip(string, len + 2); string = s8_skip(string, len + 2);
@@ -149,12 +144,6 @@ s8_t ui_get_hash_string(s8_t string) {
return 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) { fn ui_id_t ui_find_valid_id(ui_box_t *box) {
for (ui_box_t *it = box; it; it = it->parent) { for (ui_box_t *it = box; it; it = it->parent) {
if (!ui_is_null_box(it)) return it->id; 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; 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); ui_id_t parent_id = ui_find_valid_id(ui->top);
if (ui_is_null_id(parent_id)) parent_id.value = 1423; if (ui_is_null_id(parent_id)) parent_id.value = 1423;
return parent_id; 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; return box;
} }
fn ui_box_t *ui_build_box_from_string(ui_code_loc_t loc, s8_t string) { fn ui_id_t ui_gen_id(ui_id_strategy_t strat, ui_code_loc_t loc, s8_t string) {
ui_id_t id = {32}; assert(strat != 0);
ui_id_t string_id = ui_id_from_string(string); u64 result = 42523423493;
if (ui->id_strategy == ui_id_strategy_code_loc) { if (strat & ui_id_strategy_use_string) {
u64 file_hash = ht_hash_data(s8_from_char(loc.file)); u64 string_hash = hash_data(string);
u64 line_hash = ht_hash_data(s8((char *)&loc.line, sizeof(loc.line))); result = hash_mix(string_hash, result);
u64 cont_hash = ht_hash_data(s8((char *)&loc.counter, sizeof(loc.counter))); }
id.value = ui_hash_mix(file_hash, line_hash); if (strat & ui_id_strategy_use_hierarchy) {
id.value = ui_hash_mix(id.value, cont_hash); ui_id_t top_id = ui_find_top_id();
} else if (ui->id_strategy == ui_id_strategy_hierarchy) { result = hash_mix(top_id.value, result);
ui_id_t id_from_stack = ui_id_from_parent(); }
id.value = ui_hash_mix(string_id.value, id_from_stack.value); if (strat & ui_id_strategy_use_code_loc) {
} else_is_invalid; 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); ui_box_t *box = ui_build_box_from_id(loc, id);
box->string = ui_get_display_string(string); box->string = ui_get_display_string(string);
return box; return box;
@@ -269,6 +269,7 @@ fn void ui_init(ma_arena_t *arena) {
ui = ma_push_type(arena, ui_t); ui = ma_push_type(arena, ui_t);
ui->box_arena = arena; ui->box_arena = arena;
ui->root = ma_push_type(arena, ui_box_t); 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); ui->box_array = ma_push_type(arena, ui_box_t);
SLLS_PUSH(ui->free_first, ui->box_array); SLLS_PUSH(ui->free_first, ui->box_array);
@@ -499,12 +500,14 @@ fn void ui_draw(void) {
// compute: (percent_of_parent) // 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)) { 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 *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) { for (i32 i = 0; i < ui_axis2_count; i += 1) {
ui_size_t sem = box->semantic_size[i]; ui_size_t sem = box->semantic_size[i];
if (sem.kind == ui_size_kind_percent_of_parent) { if (sem.kind == ui_size_kind_percent_of_parent) {
assert(sem.value >= 0 && sem.value <= 1.0); 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]; box->computed_size[i] = sem.value * parent->computed_size[i];
} }
} }