diff --git a/build_file.c b/build_file.c index bb5f65d..2bceba9 100644 --- a/build_file.c +++ b/build_file.c @@ -27,9 +27,9 @@ int main(int argc, char **argv) { bool execute_python_snippets = true; // make sure to not abuse just for quick maths bool run_server = false; - bool core_test_target = false; + bool core_test_target = true; bool win32_target = false; - bool wasm_target = true; + bool wasm_target = false; if (execute_python_snippets) { sb8_t *sb = sb8_serial_begin(arena); @@ -75,13 +75,14 @@ int main(int argc, char **argv) { ok = os_systemf( "cl ../src/core/core_test_entry.c -Fe:core_test.exe -Fd:core_test.pdb" " -I ../src" - " /Zi /FC /nologo /Oi /O2" + " /Zi /FC /nologo /Oi" " /WX /W3 /wd4200 /diagnostics:column" " /link /incremental:no" ); if (ok != 0) return ok; - os_systemf("core_test.exe"); + ok = os_systemf("core_test.exe"); + return ok; } diff --git a/src/core/core_hash_table.c b/src/core/core_hash_table.c new file mode 100644 index 0000000..f112694 --- /dev/null +++ b/src/core/core_hash_table.c @@ -0,0 +1,103 @@ + +typedef struct ht_key_value_t ht_key_value_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; +}; + +u64 ht_hash(s8_t string) { + u8 *data = 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); + result->bucket_count = size; + result->arena = arena; + return result; +} + +ht_node_t *ht_insert_kv(ht_dict_t *ht, u64 hash, ht_key_value_t kv) { + ht_node_t *result = ma_push_type(ht->arena, ht_node_t); + result->kv = kv; + i64 idx = hash % ht->bucket_count; + SLLQ_APPEND(ht->buckets[idx].first, ht->buckets[idx].last, result); + ht->item_count += 1; + return result; +} + +ht_node_t *ht_insert_u64_u64(ht_dict_t *ht, u64 key, u64 value) { + u64 hash = ht_hash(s8((char *)&key, sizeof(key))); + 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) { + return ht_insert_u64_u64(ht, (u64)key, (u64)value); +} + +ht_node_t *ht_insert_string(ht_dict_t *ht, s8_t key, s8_t value) { + u64 hash = ht_hash(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(s8((char *)&key, sizeof(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_u64 == key) { + return it; + } + } + return NULL; +} + +ht_node_t *ht_search_ptr(ht_dict_t *ht, void *key_ptr) { + return ht_search_u64(ht, (u64)key_ptr); +} + +ht_node_t *ht_search_string(ht_dict_t *ht, s8_t key) { + u64 hash = ht_hash(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 (s8_equal(it->kv.key_string, key)) { + return it; + } + } + return NULL; +} \ No newline at end of file diff --git a/src/core/core_inc.c b/src/core/core_inc.c index 764ccaf..2efaafb 100644 --- a/src/core/core_inc.c +++ b/src/core/core_inc.c @@ -44,4 +44,5 @@ #include "core_log.c" #include "core_lexer.c" #include "core_type_info.c" -#include "core_random.c" \ No newline at end of file +#include "core_random.c" +#include "core_hash_table.c" \ No newline at end of file diff --git a/src/core/core_test_entry.c b/src/core/core_test_entry.c index 52a17a2..de51a73 100644 --- a/src/core/core_test_entry.c +++ b/src/core/core_test_entry.c @@ -96,6 +96,44 @@ void test_s8(void) { ma_destroy(arena); } +void test_hash_table(void) { + ma_temp_t scratch = ma_begin_scratch(); + { + ht_dict_t *ht = ht_create(scratch.arena, 16); + + for (u64 i = 0; i < 128; i += 1) { + ht_insert_u64_u64(ht, i, i); + ht_node_t *node = ht_search_u64(ht, i); + assert(node->kv.value_u64 == i); + assert(node->kv.key_u64 == i); + } + for (u64 i = 0; i < 128; i += 1) { + ht_node_t *node = ht_search_u64(ht, i); + assert(node->kv.value_u64 == i); + assert(node->kv.key_u64 == i); + } + + ht_node_t *node = ht_search_u64(ht, 1111); + assert(node == NULL); + } + { + ht_dict_t *ht = ht_create(scratch.arena, 16); + + for (i32 i = 0; i < 128; i += 1) { + s8_t s = s8_printf(scratch.arena, "%d", i); + ht_insert_string(ht, s, s); + ht_node_t *node = ht_search_string(ht, s); + assert(s8_equal(node->kv.value_string, s)); + assert(s8_equal(node->kv.key_string, s)); + } + + ht_node_t *node = ht_search_string(ht, s8_lit("memes")); + assert(node == NULL); + } + + ma_end_scratch(scratch); +} + #include int main(int argc, char **argv) { @@ -110,6 +148,7 @@ int main(int argc, char **argv) { printf("PLATFORM_TCC = %d\n", PLATFORM_TCC); test_s8(); + test_hash_table(); printf("all done!\n"); } \ No newline at end of file