diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bug_report.cpp | 27 | ||||
| -rw-r--r-- | src/build_settings.cpp | 6 | ||||
| -rw-r--r-- | src/check_expr.cpp | 10 | ||||
| -rw-r--r-- | src/check_stmt.cpp | 57 | ||||
| -rw-r--r-- | src/checker.cpp | 31 | ||||
| -rw-r--r-- | src/docs_writer.cpp | 11 | ||||
| -rw-r--r-- | src/error.cpp | 4 | ||||
| -rw-r--r-- | src/exact_value.cpp | 37 | ||||
| -rw-r--r-- | src/linker.cpp | 2 | ||||
| -rw-r--r-- | src/llvm_backend_general.cpp | 2 | ||||
| -rw-r--r-- | src/llvm_backend_stmt.cpp | 53 | ||||
| -rw-r--r-- | src/llvm_backend_type.cpp | 2 | ||||
| -rw-r--r-- | src/ptr_map.cpp | 447 | ||||
| -rw-r--r-- | src/string_map.cpp | 300 | ||||
| -rw-r--r-- | src/string_set.cpp | 4 | ||||
| -rw-r--r-- | src/tokenizer.cpp | 3 |
16 files changed, 520 insertions, 476 deletions
diff --git a/src/bug_report.cpp b/src/bug_report.cpp index 0ec383b44..c73595e99 100644 --- a/src/bug_report.cpp +++ b/src/bug_report.cpp @@ -204,14 +204,27 @@ gb_internal void report_cpu_info() { } #elif defined(GB_CPU_ARM) - /* - TODO(Jeroen): On *nix, perhaps query `/proc/cpuinfo`. - */ - #if defined(GB_ARCH_64_BIT) - gb_printf("ARM64\n"); - #else - gb_printf("ARM\n"); + bool generic = true; + + #if defined(GB_SYSTEM_OSX) + char cpu_name[128] = {}; + size_t cpu_name_size = 128; + if (sysctlbyname("machdep.cpu.brand_string", &cpu_name, &cpu_name_size, nullptr, 0) == 0) { + generic = false; + gb_printf("%s\n", (char *)&cpu_name[0]); + } #endif + + if (generic) { + /* + TODO(Jeroen): On *nix, perhaps query `/proc/cpuinfo`. + */ + #if defined(GB_ARCH_64_BIT) + gb_printf("ARM64\n"); + #else + gb_printf("ARM\n"); + #endif + } #else gb_printf("Unknown\n"); #endif diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 9ecc11cb5..b63f08980 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1596,8 +1596,10 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (bc->metrics.os == TargetOs_js || bc->metrics.os == TargetOs_wasi) { // TODO(bill): Should these even have a default "heap-like" allocator? } - bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR = true; - bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR = !bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR; + + if (!bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR && !bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR) { + bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR = true; + } } } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b893b3a00..06d0a8b12 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8079,11 +8079,10 @@ gb_internal void add_constant_switch_case(CheckerContext *ctx, SeenMap *seen, Op } uintptr key = hash_exact_value(operand.value); - TypeAndToken *found = map_get(seen, key); - if (found != nullptr) { + GB_ASSERT(key != 0); + isize count = multi_map_count(seen, key); + if (count) { TEMPORARY_ALLOCATOR_GUARD(); - - isize count = multi_map_count(seen, key); TypeAndToken *taps = gb_alloc_array(temporary_allocator(), TypeAndToken, count); multi_map_get_all(seen, key, taps); @@ -9406,7 +9405,8 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * continue; } ExactValue v = f->Constant.value; - auto found = map_get(&seen, hash_exact_value(v)); + uintptr hash = hash_exact_value(v); + auto found = map_get(&seen, hash); if (!found) { array_add(&unhandled, f); } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 971841165..cccbab4f6 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1629,6 +1629,17 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) if (build_context.no_rtti && is_type_enum(t->BitSet.elem)) { error(node, "Iteration over a bit_set of an enum is not allowed runtime type information (RTTI) has been disallowed"); } + if (rs->vals.count == 1 && rs->vals[0] && rs->vals[0]->kind == Ast_Ident) { + String name = rs->vals[0]->Ident.token.string; + Entity *found = scope_lookup(ctx->scope, name); + if (found && are_types_identical(found->type, t->BitSet.elem)) { + ERROR_BLOCK(); + gbString s = expr_to_string(expr); + error(rs->vals[0], "'%.*s' shadows a previous declaration which might be ambiguous with 'for (%.*s in %s)'", LIT(name), LIT(name), s); + error_line("\tSuggestion: Use a different identifier if iteration is wanted, or surround in parentheses if a normal for loop is wanted\n"); + gb_string_free(s); + } + } break; case Type_EnumeratedArray: @@ -1664,17 +1675,36 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) if (is_reverse) { error(node, "#reverse for is not supported for map types, as maps are unordered"); } + if (rs->vals.count == 1 && rs->vals[0] && rs->vals[0]->kind == Ast_Ident) { + String name = rs->vals[0]->Ident.token.string; + Entity *found = scope_lookup(ctx->scope, name); + if (found && are_types_identical(found->type, t->Map.key)) { + ERROR_BLOCK(); + gbString s = expr_to_string(expr); + error(rs->vals[0], "'%.*s' shadows a previous declaration which might be ambiguous with 'for (%.*s in %s)'", LIT(name), LIT(name), s); + error_line("\tSuggestion: Use a different identifier if iteration is wanted, or surround in parentheses if a normal for loop is wanted\n"); + gb_string_free(s); + } + } break; case Type_Tuple: { isize count = t->Tuple.variables.count; - if (count < 1 || count > 3) { + if (count < 1) { + ERROR_BLOCK(); + check_not_tuple(ctx, &operand); + error_line("\tMultiple return valued parameters in a range statement are limited to a minimum of 1 usable values with a trailing boolean for the conditional, got %td\n", count); + break; + } + enum : isize {MAXIMUM_COUNT = 100}; + if (count > MAXIMUM_COUNT) { ERROR_BLOCK(); check_not_tuple(ctx, &operand); - error_line("\tMultiple return valued parameters in a range statement are limited to a maximum of 2 usable values with a trailing boolean for the conditional\n"); + error_line("\tMultiple return valued parameters in a range statement are limited to a maximum of %td usable values with a trailing boolean for the conditional, got %td\n", MAXIMUM_COUNT, count); break; } + Type *cond_type = t->Tuple.variables[count-1]->type; if (!is_type_boolean(cond_type)) { gbString s = type_to_string(cond_type); @@ -1683,24 +1713,23 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) break; } + max_val_count = count; + for (Entity *e : t->Tuple.variables) { array_add(&vals, e->type); } is_possibly_addressable = false; - if (rs->vals.count > 1 && rs->vals[1] != nullptr && count < 3) { - gbString s = type_to_string(t); - error(operand.expr, "Expected a 3-valued expression on the rhs, got (%s)", s); - gb_string_free(s); - break; - } - - if (rs->vals.count > 0 && rs->vals[0] != nullptr && count < 2) { - gbString s = type_to_string(t); - error(operand.expr, "Expected at least a 2-valued expression on the rhs, got (%s)", s); - gb_string_free(s); - break; + bool do_break = false; + for (isize i = rs->vals.count-1; i >= 0; i--) { + if (rs->vals[i] != nullptr && count < i+2) { + gbString s = type_to_string(t); + error(operand.expr, "Expected a %td-valued expression on the rhs, got (%s)", i+2, s); + gb_string_free(s); + do_break = true; + break; + } } if (is_reverse) { diff --git a/src/checker.cpp b/src/checker.cpp index f36677c84..12c8f5291 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1898,8 +1898,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { add_type_info_dependency(c->info, c->decl, t); MUTEX_GUARD_BLOCK(&c->info->type_info_mutex) { - MapFindResult fr; - auto found = map_try_get(&c->info->type_info_map, t, &fr); + auto found = map_get(&c->info->type_info_map, t); if (found != nullptr) { // Types have already been added return; @@ -1923,7 +1922,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { ti_index = c->info->type_info_types.count; array_add(&c->info->type_info_types, t); } - map_set_internal_from_try_get(&c->checker->info.type_info_map, t, ti_index, fr); + map_set(&c->checker->info.type_info_map, t, ti_index); if (prev) { // NOTE(bill): If a previous one exists already, no need to continue @@ -2194,7 +2193,7 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { // IMPORTANT NOTE(bill): this must be copied as `map_set` takes a const ref // and effectively assigns the `+1` of the value isize const count = set->count; - if (map_set_if_not_previously_exists(set, ti_index, count)) { + if (map_set_if_not_previously_exists(set, ti_index+1, count)) { // Type already exists; return; } @@ -2537,6 +2536,11 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st is_init = false; } + if ((e->flags & EntityFlag_Disabled) != 0) { + warning(e->token, "This @(init) procedure is disabled; you must call it manually"); + is_init = false; + } + if (is_init) { add_dependency_to_set(c, e); array_add(&c->info.init_procedures, e); @@ -2927,6 +2931,8 @@ gb_internal void init_core_type_info(Checker *c) { return; } Entity *type_info_entity = find_core_entity(c, str_lit("Type_Info")); + GB_ASSERT(type_info_entity != nullptr); + GB_ASSERT(type_info_entity->type != nullptr); t_type_info = type_info_entity->type; t_type_info_ptr = alloc_type_pointer(t_type_info); @@ -4310,17 +4316,22 @@ gb_internal bool correct_single_type_alias(CheckerContext *c, Entity *e) { gb_internal bool correct_type_alias_in_scope_backwards(CheckerContext *c, Scope *s) { bool correction = false; - u32 n = s->elements.count; - for (u32 i = n-1; i < n; i--) { - correction |= correct_single_type_alias(c, s->elements.entries[i].value); + for (u32 n = s->elements.count, i = n-1; i < n; i--) { + auto const &entry = s->elements.entries[i]; + Entity *e = entry.value; + if (entry.hash && e != nullptr) { + correction |= correct_single_type_alias(c, e); + } } return correction; } gb_internal bool correct_type_alias_in_scope_forwards(CheckerContext *c, Scope *s) { bool correction = false; - u32 n = s->elements.count; - for (isize i = 0; i < n; i++) { - correction |= correct_single_type_alias(c, s->elements.entries[i].value); + for (auto const &entry : s->elements) { + Entity *e = entry.value; + if (e != nullptr) { + correction |= correct_single_type_alias(c, entry.value); + } } return correction; } diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 9ced78d33..ba71eae4d 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -987,9 +987,8 @@ gb_internal void odin_doc_update_entities(OdinDocWriter *w) { auto entities = array_make<Entity *>(heap_allocator(), 0, w->entity_cache.count); defer (array_free(&entities)); - for (u32 i = 0; i < w->entity_cache.count; i++) { - Entity *e = w->entity_cache.entries[i].key; - array_add(&entities, e); + for (auto const &entry : w->entity_cache) { + array_add(&entities, entry.key); } for (Entity *e : entities) { GB_ASSERT(e != nullptr); @@ -998,9 +997,9 @@ gb_internal void odin_doc_update_entities(OdinDocWriter *w) { } } - for (u32 i = 0; i < w->entity_cache.count; i++) { - Entity *e = w->entity_cache.entries[i].key; - OdinDocEntityIndex entity_index = w->entity_cache.entries[i].value; + for (auto const &entry : w->entity_cache) { + Entity *e = entry.key; + OdinDocEntityIndex entity_index = entry.value; OdinDocTypeIndex type_index = odin_doc_type(w, e->type); OdinDocEntityIndex foreign_library = 0; diff --git a/src/error.cpp b/src/error.cpp index 7fb62c966..1b091f88e 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -376,11 +376,11 @@ gb_internal void error_out_coloured(char const *str, TerminalStyle style, Termin gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) { global_error_collector.count.fetch_add(1); + mutex_lock(&global_error_collector.mutex); if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) { print_all_errors(); gb_exit(1); } - mutex_lock(&global_error_collector.mutex); push_error_value(pos, ErrorValue_Error); // NOTE(bill): Duplicate error, skip it @@ -403,6 +403,8 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va error_out("\n"); show_error_on_line(pos, end); } else { + global_error_collector.curr_error_value = {}; + global_error_collector.curr_error_value_set.store(false); global_error_collector.count.fetch_sub(1); } try_pop_error_value(); diff --git a/src/exact_value.cpp b/src/exact_value.cpp index b744d2db0..83af82f55 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -54,37 +54,50 @@ gb_global ExactValue const empty_exact_value = {}; gb_internal uintptr hash_exact_value(ExactValue v) { mutex_lock(&hash_exact_value_mutex); defer (mutex_unlock(&hash_exact_value_mutex)); + + uintptr res = 0; switch (v.kind) { case ExactValue_Invalid: return 0; case ExactValue_Bool: - return gb_fnv32a(&v.value_bool, gb_size_of(v.value_bool)); + res = gb_fnv32a(&v.value_bool, gb_size_of(v.value_bool)); + break; case ExactValue_String: - return gb_fnv32a(v.value_string.text, v.value_string.len); + res = gb_fnv32a(v.value_string.text, v.value_string.len); + break; case ExactValue_Integer: { u32 key = gb_fnv32a(v.value_integer.dp, gb_size_of(*v.value_integer.dp) * v.value_integer.used); u8 last = (u8)v.value_integer.sign; - return (key ^ last) * 0x01000193; + res = (key ^ last) * 0x01000193; + break; } case ExactValue_Float: - return gb_fnv32a(&v.value_float, gb_size_of(v.value_float)); + res = gb_fnv32a(&v.value_float, gb_size_of(v.value_float)); + break; case ExactValue_Pointer: - return ptr_map_hash_key(v.value_pointer); + res = ptr_map_hash_key(v.value_pointer); + break; case ExactValue_Complex: - return gb_fnv32a(v.value_complex, gb_size_of(Complex128)); + res = gb_fnv32a(v.value_complex, gb_size_of(Complex128)); + break; case ExactValue_Quaternion: - return gb_fnv32a(v.value_quaternion, gb_size_of(Quaternion256)); + res = gb_fnv32a(v.value_quaternion, gb_size_of(Quaternion256)); + break; case ExactValue_Compound: - return ptr_map_hash_key(v.value_compound); + res = ptr_map_hash_key(v.value_compound); + break; case ExactValue_Procedure: - return ptr_map_hash_key(v.value_procedure); + res = ptr_map_hash_key(v.value_procedure); + break; case ExactValue_Typeid: - return ptr_map_hash_key(v.value_typeid); + res = ptr_map_hash_key(v.value_typeid); + break; + default: + res = gb_fnv32a(&v, gb_size_of(ExactValue)); } - return gb_fnv32a(&v, gb_size_of(ExactValue)); - + return res & 0x7fffffff; } diff --git a/src/linker.cpp b/src/linker.cpp index 498a96c5f..e694fd999 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -167,7 +167,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { if (has_asm_extension(lib)) { if (!string_set_update(&asm_files, lib)) { - String asm_file = asm_files.entries[i].value; + String asm_file = lib; String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".obj")); String obj_format = str_lit("win64"); #if defined(GB_ARCH_32_BIT) diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 02afa628c..15cbb7c71 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -140,7 +140,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { } gen->default_module.gen = gen; - map_set(&gen->modules, cast(void *)nullptr, &gen->default_module); + map_set(&gen->modules, cast(void *)1, &gen->default_module); lb_init_module(&gen->default_module, c); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 24dd321f6..851433415 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -802,8 +802,19 @@ gb_internal void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_ if (done_) *done_ = done; } -gb_internal void lb_build_range_tuple(lbProcedure *p, Ast *expr, Type *val0_type, Type *val1_type, - lbValue *val0_, lbValue *val1_, lbBlock **loop_, lbBlock **done_) { +gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *scope) { + Ast *expr = unparen_expr(rs->expr); + + Type *expr_type = type_of_expr(expr); + Type *et = base_type(type_deref(expr_type)); + GB_ASSERT(et->kind == Type_Tuple); + + i32 value_count = cast(i32)et->Tuple.variables.count; + + lbValue *values = gb_alloc_array(permanent_allocator(), lbValue, value_count); + + lb_open_scope(p, scope); + lbBlock *loop = lb_create_block(p, "for.tuple.loop"); lb_emit_jump(p, loop); lb_start_block(p, loop); @@ -821,11 +832,26 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, Ast *expr, Type *val0_type lb_emit_if(p, cond, body, done); lb_start_block(p, body); + for (i32 i = 0; i < value_count; i++) { + values[i] = lb_emit_tuple_ev(p, tuple_value, i); + } - if (val0_) *val0_ = lb_emit_tuple_ev(p, tuple_value, 0); - if (val1_) *val1_ = lb_emit_tuple_ev(p, tuple_value, 1); - if (loop_) *loop_ = loop; - if (done_) *done_ = done; + GB_ASSERT(rs->vals.count <= value_count); + for (isize i = 0; i < rs->vals.count; i++) { + Ast *val = rs->vals[i]; + if (val != nullptr) { + lb_store_range_stmt_val(p, val, values[i]); + } + } + + lb_push_target_list(p, rs->label, done, loop, nullptr); + + lb_build_stmt(p, rs->body); + + lb_close_scope(p, lbDeferExit_Default, nullptr); + lb_pop_target_list(p); + lb_emit_jump(p, loop); + lb_start_block(p, done); } gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs, Scope *scope) { @@ -968,6 +994,17 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc } } + TypeAndValue tav = type_and_value_of_expr(expr); + if (tav.mode != Addressing_Type) { + Type *expr_type = type_of_expr(expr); + Type *et = base_type(type_deref(expr_type)); + if (et->kind == Type_Tuple) { + lb_build_range_tuple(p, rs, scope); + return; + } + } + + lb_open_scope(p, scope); Ast *val0 = rs->vals.count > 0 ? lb_strip_and_prefix(rs->vals[0]) : nullptr; @@ -986,7 +1023,6 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc lbBlock *loop = nullptr; lbBlock *done = nullptr; bool is_map = false; - TypeAndValue tav = type_and_value_of_expr(expr); if (tav.mode == Addressing_Type) { lb_build_range_enum(p, type_deref(tav.type), val0_type, &val, &key, &loop, &done); @@ -1062,8 +1098,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc break; } case Type_Tuple: - lb_build_range_tuple(p, expr, val0_type, val1_type, &val, &key, &loop, &done); - break; + GB_PANIC("Should be handled already"); case Type_BitSet: { lbModule *m = p->module; diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index e202a59ba..2c4abbb4d 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -2,7 +2,7 @@ gb_internal isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_ auto *set = &info->minimum_dependency_type_info_set; isize index = type_info_index(info, type, err_on_not_found); if (index >= 0) { - auto *found = map_get(set, index); + auto *found = map_get(set, index+1); if (found) { GB_ASSERT(*found >= 0); return *found + 1; diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 23278014f..362e412ba 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -16,23 +16,21 @@ struct MapFindResult { }; enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 }; +static void *const MAP_TOMBSTONE = (void *)~(uintptr)0; template <typename K, typename V> struct PtrMapEntry { static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size"); - K key; - V value; - MapIndex next; + K key; + V value; }; template <typename K, typename V> struct PtrMap { - MapIndex * hashes; - usize hashes_count; PtrMapEntry<K, V> *entries; u32 count; - u32 entries_capacity; + u32 capacity; }; @@ -69,7 +67,6 @@ template <typename K, typename V> gb_internal void map_grow (PtrMap< template <typename K, typename V> gb_internal void map_rehash (PtrMap<K, V> *h, isize new_count); template <typename K, typename V> gb_internal void map_reserve (PtrMap<K, V> *h, isize cap); -#if PTR_MAP_ENABLE_MULTI_MAP // Mutlivalued map procedure template <typename K, typename V> gb_internal PtrMapEntry<K, V> * multi_map_find_first(PtrMap<K, V> *h, K key); template <typename K, typename V> gb_internal PtrMapEntry<K, V> * multi_map_find_next (PtrMap<K, V> *h, PtrMapEntry<K, V> *e); @@ -79,7 +76,6 @@ template <typename K, typename V> gb_internal void multi_map_get_all (PtrMap< template <typename K, typename V> gb_internal void multi_map_insert (PtrMap<K, V> *h, K key, V const &value); template <typename K, typename V> gb_internal void multi_map_remove (PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e); template <typename K, typename V> gb_internal void multi_map_remove_all(PtrMap<K, V> *h, K key); -#endif gb_internal gbAllocator map_allocator(void) { return heap_allocator(); @@ -94,170 +90,141 @@ gb_internal gb_inline void map_init(PtrMap<K, V> *h, isize capacity) { template <typename K, typename V> gb_internal gb_inline void map_destroy(PtrMap<K, V> *h) { gbAllocator a = map_allocator(); - gb_free(a, h->hashes); gb_free(a, h->entries); } -template <typename K, typename V> -gb_internal void map__resize_hashes(PtrMap<K, V> *h, usize count) { - h->hashes_count = cast(u32)resize_array_raw(&h->hashes, map_allocator(), h->hashes_count, count, MAP_CACHE_LINE_SIZE); -} - -template <typename K, typename V> -gb_internal void map__reserve_entries(PtrMap<K, V> *h, usize capacity) { - h->entries_capacity = cast(u32)resize_array_raw(&h->entries, map_allocator(), h->entries_capacity, capacity, MAP_CACHE_LINE_SIZE); -} - template <typename K, typename V> -gb_internal MapIndex map__add_entry(PtrMap<K, V> *h, K key) { - PtrMapEntry<K, V> e = {}; - e.key = key; - e.next = MAP_SENTINEL; - if (h->count+1 >= h->entries_capacity) { - map__reserve_entries(h, gb_max(h->entries_capacity*2, 4)); - } - h->entries[h->count++] = e; - return cast(MapIndex)(h->count-1); -} - -template <typename K, typename V> -gb_internal MapFindResult map__find(PtrMap<K, V> *h, K key) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count == 0) { - return fr; +gb_internal void map__insert(PtrMap<K, V> *h, K key, V const &value) { + if (h->count+1 >= h->capacity) { + map_grow(h); } u32 hash = ptr_map_hash_key(key); - fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[fr.entry_index]; - if (entry->key == key) { - return fr; + u32 mask = h->capacity-1; + MapIndex index = hash & mask; + MapIndex original_index = index; + do { + auto *entry = h->entries+index; + if (!entry->key || entry->key == cast(K)MAP_TOMBSTONE) { + entry->key = key; + entry->value = value; + h->count += 1; + return; } - fr.entry_prev = fr.entry_index; - fr.entry_index = entry->next; - } - return fr; -} + index = (index+1)&mask; + } while (index != original_index); -template <typename K, typename V> -gb_internal MapFindResult map__find_from_entry(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count == 0) { - return fr; - } - u32 hash = ptr_map_hash_key(e->key); - fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - if (&h->entries[fr.entry_index] == e) { - return fr; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = h->entries[fr.entry_index].next; - } - return fr; + GB_PANIC("FAILED TO INSERT"); } template <typename K, typename V> gb_internal b32 map__full(PtrMap<K, V> *h) { - return 0.75f * h->hashes_count <= h->count; + return 0.75f * h->capacity <= h->count; } template <typename K, typename V> gb_internal gb_inline void map_grow(PtrMap<K, V> *h) { - isize new_count = gb_max(h->hashes_count<<1, 16); - map_rehash(h, new_count); + isize new_capacity = gb_max(h->capacity<<1, 16); + map_reserve(h, new_capacity); } template <typename K, typename V> -gb_internal void map_reset_entries(PtrMap<K, V> *h) { - for (usize i = 0; i < h->hashes_count; i++) { - h->hashes[i] = MAP_SENTINEL; - } - for (usize i = 0; i < h->count; i++) { - MapFindResult fr; - PtrMapEntry<K, V> *e = &h->entries[i]; - e->next = MAP_SENTINEL; - fr = map__find_from_entry(h, e); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = cast(MapIndex)i; - } else { - h->entries[fr.entry_prev].next = cast(MapIndex)i; - } +gb_internal void try_map_grow(PtrMap<K, V> *h) { + if (h->capacity == 0 || map__full(h)) { + map_grow(h); } } + template <typename K, typename V> gb_internal void map_reserve(PtrMap<K, V> *h, isize cap) { - if (h->count*2 < h->hashes_count) { + if (cap < h->capacity) { return; } - map__reserve_entries(h, cap); - map__resize_hashes(h, cap*2); - map_reset_entries(h); -} + cap = next_pow2_isize(cap); + typedef PtrMapEntry<K, V> EntryType; + PtrMap<K, V> new_h = {}; + new_h.count = 0; + new_h.capacity = cast(u32)cap; + new_h.entries = gb_alloc_array(map_allocator(), EntryType, new_h.capacity); -template <typename K, typename V> -gb_internal void map_rehash(PtrMap<K, V> *h, isize new_count) { - map_reserve(h, new_count); + if (h->count) { + for (u32 i = 0; i < h->capacity; i++) { + auto *entry = h->entries+i; + if (entry->key && + entry->key != cast(K)MAP_TOMBSTONE) { + map__insert(&new_h, entry->key, entry->value); + } + } + } + map_destroy(h); + *h = new_h; } template <typename K, typename V> gb_internal V *map_get(PtrMap<K, V> *h, K key) { - MapIndex hash_index = MAP_SENTINEL; - MapIndex entry_prev = MAP_SENTINEL; - MapIndex entry_index = MAP_SENTINEL; - if (h->hashes_count != 0) { - u32 hash = ptr_map_hash_key(key); - hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - entry_index = h->hashes[hash_index]; - while (entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[entry_index]; - if (entry->key == key) { - return &entry->value; - } - entry_prev = entry_index; - entry_index = entry->next; - } + if (h->count == 0) { + return nullptr; + } + if (key == 0) { + GB_PANIC("0 key"); } + + u32 hash = ptr_map_hash_key(key); + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + if (!entry->key) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (entry->key == key) { + return &entry->value; + } + index = (index+1) & mask; + } while (original_index != index); return nullptr; } template <typename K, typename V> -gb_internal V *map_try_get(PtrMap<K, V> *h, K key, MapFindResult *fr_) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count != 0) { - u32 hash = ptr_map_hash_key(key); - fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[fr.entry_index]; - if (entry->key == key) { - return &entry->value; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = entry->next; - } +gb_internal V *map_try_get(PtrMap<K, V> *h, K key, MapIndex *found_index_) { + if (found_index_) *found_index_ = ~(MapIndex)0; + + if (h->count == 0) { + return nullptr; } - if (h->hashes_count == 0 || map__full(h)) { - map_grow(h); + if (key == 0) { + GB_PANIC("0 key"); } - if (fr_) *fr_ = fr; + + u32 hash = ptr_map_hash_key(key); + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + if (!entry->key) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (entry->key == key) { + if (found_index_) *found_index_ = index; + return &entry->value; + } + index = (index+1) & mask; + } while (original_index != index); return nullptr; } template <typename K, typename V> -gb_internal void map_set_internal_from_try_get(PtrMap<K, V> *h, K key, V const &value, MapFindResult const &fr) { - MapIndex index = map__add_entry(h, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries[fr.entry_prev].next = index; +gb_internal void map_set_internal_from_try_get(PtrMap<K, V> *h, K key, V const &value, MapIndex found_index) { + if (found_index != MAP_SENTINEL) { + GB_ASSERT(h->entries[found_index].key == key); + h->entries[found_index].value = value; } else { - h->hashes[fr.hash_index] = index; + map_set(h, key, value); } - h->entries[index].value = value; } template <typename K, typename V> @@ -269,116 +236,83 @@ gb_internal V &map_must_get(PtrMap<K, V> *h, K key) { template <typename K, typename V> gb_internal void map_set(PtrMap<K, V> *h, K key, V const &value) { - MapIndex index; - MapFindResult fr; - if (h->hashes_count == 0) { - map_grow(h); - } - fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { - index = fr.entry_index; - } else { - index = map__add_entry(h, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries[fr.entry_prev].next = index; - } else { - h->hashes[fr.hash_index] = index; - } - } - h->entries[index].value = value; - - if (map__full(h)) { - map_grow(h); + GB_ASSERT(key != 0); + try_map_grow(h); + auto *found = map_get(h, key); + if (found) { + *found = value; + return; } + map__insert(h, key, value); } // returns true if it previously existed template <typename K, typename V> gb_internal bool map_set_if_not_previously_exists(PtrMap<K, V> *h, K key, V const &value) { - MapIndex index; - MapFindResult fr; - if (h->hashes_count == 0) { - map_grow(h); - } - fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { + try_map_grow(h); + auto *found = map_get(h, key); + if (found) { return true; - } else { - index = map__add_entry(h, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries[fr.entry_prev].next = index; - } else { - h->hashes[fr.hash_index] = index; - } - } - h->entries[index].value = value; - - if (map__full(h)) { - map_grow(h); } + map__insert(h, key, value); return false; } template <typename K, typename V> -gb_internal void map__erase(PtrMap<K, V> *h, MapFindResult const &fr) { - MapFindResult last; - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = h->entries[fr.entry_index].next; - } else { - h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next; - } - if (fr.entry_index == h->count-1) { - h->count--; - return; - } - h->entries[fr.entry_index] = h->entries[h->count-1]; - h->count--; - - last = map__find(h, h->entries[fr.entry_index].key); - if (last.entry_prev != MAP_SENTINEL) { - h->entries[last.entry_prev].next = fr.entry_index; - } else { - h->hashes[last.hash_index] = fr.entry_index; - } -} - -template <typename K, typename V> gb_internal void map_remove(PtrMap<K, V> *h, K key) { - MapFindResult fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { - map__erase(h, fr); + MapIndex found_index = 0; + if (map_try_get(h, key, &found_index)) { + h->entries[found_index].key = cast(K)MAP_TOMBSTONE; + h->count -= 1; } } template <typename K, typename V> gb_internal gb_inline void map_clear(PtrMap<K, V> *h) { h->count = 0; - for (usize i = 0; i < h->hashes_count; i++) { - h->hashes[i] = MAP_SENTINEL; - } + gb_zero_array(h->entries, h->capacity); } #if PTR_MAP_ENABLE_MULTI_MAP template <typename K, typename V> gb_internal PtrMapEntry<K, V> *multi_map_find_first(PtrMap<K, V> *h, K key) { - MapIndex i = map__find(h, key).entry_index; - if (i == MAP_SENTINEL) { + if (h->count == 0) { return nullptr; } - return &h->entries[i]; + u32 hash = ptr_map_hash_key(key); + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + if (!entry->key) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (entry->key == key) { + return entry; + } + index = (index+1) & mask; + } while (original_index != index); + return nullptr; } template <typename K, typename V> gb_internal PtrMapEntry<K, V> *multi_map_find_next(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) { - MapIndex i = e->next; - while (i != MAP_SENTINEL) { - if (h->entries[i].key == e->key) { - return &h->entries[i]; + u32 mask = h->capacity-1; + MapIndex index = cast(MapIndex)(e - h->entries); + MapIndex original_index = index; + do { + index = (index+1)&mask; + auto *entry = h->entries+index; + if (!entry->key) { + return nullptr; } - i = h->entries[i].next; - } + if (entry->key == e->key) { + return entry; + } + } while (original_index != index); return nullptr; } @@ -405,34 +339,16 @@ gb_internal void multi_map_get_all(PtrMap<K, V> *h, K key, V *items) { template <typename K, typename V> gb_internal void multi_map_insert(PtrMap<K, V> *h, K key, V const &value) { - MapFindResult fr; - MapIndex i; - if (h->hashes_count == 0) { - map_grow(h); - } - // Make - fr = map__find(h, key); - i = map__add_entry(h, key); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = i; - } else { - h->entries[fr.entry_prev].next = i; - } - h->entries[i].next = fr.entry_index; - h->entries[i].value = value; - // Grow if needed - if (map__full(h)) { - map_grow(h); - } + try_map_grow(h); + map__insert(h, key, value); } -template <typename K, typename V> -gb_internal void multi_map_remove(PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e) { - MapFindResult fr = map__find_from_entry(h, e); - if (fr.entry_index != MAP_SENTINEL) { - map__erase(h, fr); - } -} +// template <typename K, typename V> +// gb_internal void multi_map_remove(PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e) { +// if (fr.entry_index != MAP_SENTINEL) { +// map__erase(h, fr); +// } +// } template <typename K, typename V> gb_internal void multi_map_remove_all(PtrMap<K, V> *h, K key) { @@ -443,22 +359,77 @@ gb_internal void multi_map_remove_all(PtrMap<K, V> *h, K key) { #endif + + +template <typename K, typename V> +struct PtrMapIterator { + PtrMap<K, V> *map; + MapIndex index; + + PtrMapIterator<K, V> &operator++() noexcept { + for (;;) { + ++index; + if (map->capacity == index) { + return *this; + } + PtrMapEntry<K, V> *entry = map->entries+index; + if (entry->key && entry->key != cast(K)MAP_TOMBSTONE) { + return *this; + } + } + } + + bool operator==(PtrMapIterator<K, V> const &other) const noexcept { + return this->map == other->map && this->index == other->index; + } + + operator PtrMapEntry<K, V> *() const { + return map->entries+index; + } +}; + + template <typename K, typename V> -gb_internal PtrMapEntry<K, V> *begin(PtrMap<K, V> &m) { - return m.entries; +gb_internal PtrMapIterator<K, V> end(PtrMap<K, V> &m) noexcept { + return PtrMapIterator<K, V>{&m, m.capacity}; } + template <typename K, typename V> -gb_internal PtrMapEntry<K, V> const *begin(PtrMap<K, V> const &m) { - return m.entries; +gb_internal PtrMapIterator<K, V> const end(PtrMap<K, V> const &m) noexcept { + return PtrMapIterator<K, V>{&m, m.capacity}; } + template <typename K, typename V> -gb_internal PtrMapEntry<K, V> *end(PtrMap<K, V> &m) { - return m.entries + m.count; -} +gb_internal PtrMapIterator<K, V> begin(PtrMap<K, V> &m) noexcept { + if (m.count == 0) { + return end(m); + } + MapIndex index = 0; + while (index < m.capacity) { + auto key = m.entries[index].key; + if (key && key != cast(K)MAP_TOMBSTONE) { + break; + } + index++; + } + return PtrMapIterator<K, V>{&m, index}; +} template <typename K, typename V> -gb_internal PtrMapEntry<K, V> const *end(PtrMap<K, V> const &m) { - return m.entries + m.count; +gb_internal PtrMapIterator<K, V> const begin(PtrMap<K, V> const &m) noexcept { + if (m.count == 0) { + return end(m); + } + + MapIndex index = 0; + while (index < m.capacity) { + auto key = m.entries[index].key; + if (key && key != cast(K)MAP_TOMBSTONE) { + break; + } + index++; + } + return PtrMapIterator<K, V>{&m, index}; } diff --git a/src/string_map.cpp b/src/string_map.cpp index f8b86a950..4de88bbf9 100644 --- a/src/string_map.cpp +++ b/src/string_map.cpp @@ -2,8 +2,8 @@ GB_STATIC_ASSERT(sizeof(MapIndex) == sizeof(u32)); struct StringHashKey { - u32 hash; String string; + u32 hash; operator String() const noexcept { return this->string; @@ -13,7 +13,8 @@ struct StringHashKey { } }; gb_internal gb_inline u32 string_hash(String const &s) { - return fnv32a(s.text, s.len) & 0x7fffffff; + u32 res = fnv32a(s.text, s.len) & 0x7fffffff; + return res | (res == 0); } gb_internal gb_inline StringHashKey string_hash_string(String const &s) { @@ -25,19 +26,16 @@ gb_internal gb_inline StringHashKey string_hash_string(String const &s) { template <typename T> struct StringMapEntry { - String key; - u32 hash; - MapIndex next; - T value; + String key; + u32 hash; + T value; }; template <typename T> struct StringMap { - MapIndex * hashes; - usize hashes_count; StringMapEntry<T> *entries; u32 count; - u32 entries_capacity; + u32 capacity; }; @@ -73,127 +71,91 @@ gb_internal gb_inline void string_map_init(StringMap<T> *h, usize capacity) { template <typename T> gb_internal gb_inline void string_map_destroy(StringMap<T> *h) { - gb_free(string_map_allocator(), h->hashes); gb_free(string_map_allocator(), h->entries); } template <typename T> -gb_internal void string_map__resize_hashes(StringMap<T> *h, usize count) { - h->hashes_count = cast(u32)resize_array_raw(&h->hashes, string_map_allocator(), h->hashes_count, count, MAP_CACHE_LINE_SIZE); -} - - -template <typename T> -gb_internal void string_map__reserve_entries(StringMap<T> *h, usize capacity) { - h->entries_capacity = cast(u32)resize_array_raw(&h->entries, string_map_allocator(), h->entries_capacity, capacity, MAP_CACHE_LINE_SIZE); -} - - -template <typename T> -gb_internal MapIndex string_map__add_entry(StringMap<T> *h, u32 hash, String const &key) { - StringMapEntry<T> e = {}; - e.key = key; - e.hash = hash; - e.next = MAP_SENTINEL; - if (h->count+1 >= h->entries_capacity) { - string_map__reserve_entries(h, gb_max(h->entries_capacity*2, 4)); +gb_internal void string_map__insert(StringMap<T> *h, u32 hash, String const &key, T const &value) { + if (h->count+1 >= h->capacity) { + string_map_grow(h); } - h->entries[h->count++] = e; - return cast(MapIndex)(h->count-1); -} - -template <typename T> -gb_internal MapFindResult string_map__find(StringMap<T> *h, u32 hash, String const &key) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count != 0) { - fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[fr.entry_index]; - if (entry->hash == hash && entry->key == key) { - return fr; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = entry->next; + GB_ASSERT(h->count+1 < h->capacity); + + u32 mask = h->capacity-1; + MapIndex index = hash & mask; + MapIndex original_index = index; + do { + auto *entry = h->entries+index; + if (entry->hash == 0) { + entry->key = key; + entry->hash = hash; + entry->value = value; + + h->count += 1; + return; } - } - return fr; -} + index = (index+1)&mask; + } while (index != original_index); -template <typename T> -gb_internal MapFindResult string_map__find_from_entry(StringMap<T> *h, StringMapEntry<T> *e) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count != 0) { - fr.hash_index = cast(MapIndex)(e->hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[fr.entry_index]; - if (entry == e) { - return fr; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = entry->next; - } - } - return fr; + GB_PANIC("Full map"); } template <typename T> gb_internal b32 string_map__full(StringMap<T> *h) { - return 0.75f * h->hashes_count <= h->count; + return 0.75f * h->count <= h->capacity; } template <typename T> gb_inline void string_map_grow(StringMap<T> *h) { - isize new_count = gb_max(h->hashes_count<<1, 16); - string_map_reserve(h, new_count); + isize new_capacity = gb_max(h->capacity<<1, 16); + string_map_reserve(h, new_capacity); } template <typename T> -gb_internal void string_map_reset_entries(StringMap<T> *h) { - for (u32 i = 0; i < h->hashes_count; i++) { - h->hashes[i] = MAP_SENTINEL; - } - for (isize i = 0; i < h->count; i++) { - MapFindResult fr; - StringMapEntry<T> *e = &h->entries[i]; - e->next = MAP_SENTINEL; - fr = string_map__find_from_entry(h, e); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = cast(MapIndex)i; - } else { - h->entries[fr.entry_prev].next = cast(MapIndex)i; - } - } -} - -template <typename T> gb_internal void string_map_reserve(StringMap<T> *h, usize cap) { - if (h->count*2 < h->hashes_count) { + if (cap < h->capacity) { return; } - string_map__reserve_entries(h, cap); - string_map__resize_hashes(h, cap*2); - string_map_reset_entries(h); + cap = next_pow2_isize(cap); + + StringMap<T> new_h = {}; + new_h.count = 0; + new_h.capacity = cast(u32)cap; + new_h.entries = gb_alloc_array(string_map_allocator(), StringMapEntry<T>, new_h.capacity); + + if (h->count) { + for (u32 i = 0; i < h->capacity; i++) { + auto *entry = h->entries+i; + if (entry->hash) { + string_map__insert(&new_h, entry->hash, entry->key, entry->value); + } + } + } + string_map_destroy(h); + *h = new_h; } template <typename T> gb_internal T *string_map_get(StringMap<T> *h, u32 hash, String const &key) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes_count != 0) { - fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); - fr.entry_index = h->hashes[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - auto *entry = &h->entries[fr.entry_index]; - if (entry->hash == hash && entry->key == key) { - return &entry->value; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = entry->next; - } + if (h->count == 0) { + return nullptr; } + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + u32 curr_hash = entry->hash; + if (curr_hash == 0) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (curr_hash == hash && entry->key == key) { + return &entry->value; + } + index = (index+1) & mask; + } while (original_index != index); return nullptr; } @@ -216,9 +178,9 @@ gb_internal gb_inline T *string_map_get(StringMap<T> *h, char const *key) { template <typename T> gb_internal T &string_map_must_get(StringMap<T> *h, u32 hash, String const &key) { - isize index = string_map__find(h, hash, key).entry_index; - GB_ASSERT(index != MAP_SENTINEL); - return h->entries[index].value; + T *found = string_map_get(h, hash, key); + GB_ASSERT(found != nullptr); + return *found; } template <typename T> @@ -239,27 +201,15 @@ gb_internal gb_inline T &string_map_must_get(StringMap<T> *h, char const *key) { template <typename T> gb_internal void string_map_set(StringMap<T> *h, u32 hash, String const &key, T const &value) { - MapIndex index; - MapFindResult fr; - if (h->hashes_count == 0) { + if (h->count == 0) { string_map_grow(h); } - fr = string_map__find(h, hash, key); - if (fr.entry_index != MAP_SENTINEL) { - index = fr.entry_index; - } else { - index = string_map__add_entry(h, hash, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries[fr.entry_prev].next = index; - } else { - h->hashes[fr.hash_index] = index; - } - } - h->entries[index].value = value; - - if (string_map__full(h)) { - string_map_grow(h); + auto *found = string_map_get(h, hash, key); + if (found) { + *found = value; + return; } + string_map__insert(h, hash, key, value); } template <typename T> @@ -278,62 +228,80 @@ gb_internal gb_inline void string_map_set(StringMap<T> *h, StringHashKey const & } - -// template <typename T> -// gb_internal void string_map__erase(StringMap<T> *h, MapFindResult const &fr) { -// MapFindResult last; -// if (fr.entry_prev == MAP_SENTINEL) { -// h->hashes[fr.hash_index] = h->entries[fr.entry_index].next; -// } else { -// h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next; -// } -// if (fr.entry_index == h->count-1) { -// array_pop(&h->entries); -// return; -// } -// h->entries[fr.entry_index] = h->entries[h->count-1]; -// last = string_map__find(h, h->entries[fr.entry_index].key); -// if (last.entry_prev != MAP_SENTINEL) { -// h->entries[last.entry_prev].next = fr.entry_index; -// } else { -// h->hashes[last.hash_index] = fr.entry_index; -// } -// } - -// template <typename T> -// gb_internal void string_map_remove(StringMap<T> *h, StringHashKey const &key) { -// MapFindResult fr = string_map__find(h, key); -// if (fr.entry_index != MAP_SENTINEL) { -// string_map__erase(h, fr); -// } -// } - template <typename T> gb_internal gb_inline void string_map_clear(StringMap<T> *h) { h->count = 0; - for (u32 i = 0; i < h->hashes_count; i++) { - h->hashes[i] = MAP_SENTINEL; - } + gb_zero_array(h->entries, h->capacity); } +template <typename T> +struct StringMapIterator { + StringMap<T> *map; + MapIndex index; + + StringMapIterator<T> &operator++() noexcept { + for (;;) { + ++index; + if (map->capacity == index) { + return *this; + } + StringMapEntry<T> *entry = map->entries+index; + if (entry->hash != 0) { + return *this; + } + } + } + + bool operator==(StringMapIterator<T> const &other) const noexcept { + return this->map == other->map && this->index == other->index; + } + + operator StringMapEntry<T> *() const { + return map->entries+index; + } +}; + template <typename T> -gb_internal StringMapEntry<T> *begin(StringMap<T> &m) noexcept { - return m.entries; +gb_internal StringMapIterator<T> end(StringMap<T> &m) noexcept { + return StringMapIterator<T>{&m, m.capacity}; } + template <typename T> -gb_internal StringMapEntry<T> const *begin(StringMap<T> const &m) noexcept { - return m.entries; +gb_internal StringMapIterator<T> const end(StringMap<T> const &m) noexcept { + return StringMapIterator<T>{&m, m.capacity}; } + template <typename T> -gb_internal StringMapEntry<T> *end(StringMap<T> &m) { - return m.entries + m.count; -} +gb_internal StringMapIterator<T> begin(StringMap<T> &m) noexcept { + if (m.count == 0) { + return end(m); + } + MapIndex index = 0; + while (index < m.capacity) { + if (m.entries[index].hash) { + break; + } + index++; + } + return StringMapIterator<T>{&m, index}; +} template <typename T> -gb_internal StringMapEntry<T> const *end(StringMap<T> const &m) noexcept { - return m.entries + m.count; -}
\ No newline at end of file +gb_internal StringMapIterator<T> const begin(StringMap<T> const &m) noexcept { + if (m.count == 0) { + return end(m); + } + + MapIndex index = 0; + while (index < m.capacity) { + if (m.entries[index].hash) { + break; + } + index++; + } + return StringMapIterator<T>{&m, index}; +} diff --git a/src/string_set.cpp b/src/string_set.cpp index fb4640c20..a37d8ba80 100644 --- a/src/string_set.cpp +++ b/src/string_set.cpp @@ -208,7 +208,9 @@ gb_internal void string_set__erase(StringSet *s, MapFindResult fr) { } auto *entry = &s->entries[fr.entry_index]; *entry = s->entries[s->entries.count-1]; - StringHashKey key = {entry->hash, entry->value}; + StringHashKey key; + key.hash = entry->hash; + key.string = entry->value; last = string_set__find(s, key); if (last.entry_prev != MAP_SENTINEL) { s->entries[last.entry_prev].next = fr.entry_index; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index fdff9224a..f7751d840 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -767,9 +767,8 @@ gb_internal void tokenizer_get_token(Tokenizer *t, Token *token, int repeat=0) { } } - // TODO(bill): Better Error Handling if (valid && n != 1) { - tokenizer_err(t, "Invalid rune literal"); + tokenizer_err(t, token->pos, "Invalid rune literal"); } token->string.len = t->curr - token->string.text; goto semicolon_check; |