diff --git a/include/tlibc/collections/HashMap.h b/include/tlibc/collections/HashMap.h index a7f0514..2a68b9b 100755 --- a/include/tlibc/collections/HashMap.h +++ b/include/tlibc/collections/HashMap.h @@ -29,6 +29,8 @@ typedef struct HashMap_ { #define HashMap_construct(PTR, T, VALUE_DESTRUCTOR) HashMap_construct_size(PTR, sizeof(T), VALUE_DESTRUCTOR) void HashMap_construct_size(HashMap_* ptr, u32 value_t_size, FreeFunction NULLABLE(value_destructor)); void HashMap_destroy(HashMap_* ptr); -void* NULLABLE(HashMap_tryGetPtr)(HashMap_* ptr, str key); -bool HashMap_tryPush(HashMap_* ptr, str key, void* value_ptr); -bool HashMap_tryDelete(HashMap_* ptr, str key); + +bool HashMap_tryPush(HashMap_* ptr, const str key, void* value_ptr); +void HashMap_pushOrUpdate(HashMap_* ptr, const str key, void* value_ptr); +NULLABLE(void*) HashMap_tryGetPtr(const HashMap_* ptr, const str key); +bool HashMap_tryDelete(HashMap_* ptr, const str key); diff --git a/src/collections/HashMap.c b/src/collections/HashMap.c index 16a6e77..54ae1a0 100755 --- a/src/collections/HashMap.c +++ b/src/collections/HashMap.c @@ -62,7 +62,7 @@ typedef struct BucketAndIndex { ///@returns `HashMapBucket*` for specified key or NULL, if table hasn't been allocated yet; /// Index of existing item with the same key or -1 if no item is present. -static BucketAndIndex __HashMap_search(HashMap_* ptr, str key, u32 hash){ +static BucketAndIndex __HashMap_search(const HashMap_* ptr, const str key, u32 hash){ if(ptr->height == 0) return BucketAndIndex_null; @@ -79,7 +79,7 @@ static BucketAndIndex __HashMap_search(HashMap_* ptr, str key, u32 hash){ return r; } -void* NULLABLE(HashMap_tryGetPtr)(HashMap_* ptr, str key){ +void* HashMap_tryGetPtr(const HashMap_* ptr, const str key){ u32 hash = __HashMap_HASH_FUNC(key); BucketAndIndex r = __HashMap_search(ptr, key, hash); // key not found @@ -121,7 +121,7 @@ static void __HashMap_expand(HashMap_* ptr){ ptr->height_n = height_expanded_n; } -bool HashMap_tryPush(HashMap_* ptr, str key, void* value_ptr){ +bool HashMap_tryPush(HashMap_* ptr, const str key, void* value_ptr){ u32 hash = __HashMap_HASH_FUNC(key); BucketAndIndex r = __HashMap_search(ptr, key, hash); // found existing item with the same key @@ -140,7 +140,27 @@ bool HashMap_tryPush(HashMap_* ptr, str key, void* value_ptr){ return true; } -bool HashMap_tryDelete(HashMap_* ptr, str key){ +void HashMap_pushOrUpdate(HashMap_* ptr, const str key, void* value_ptr){ + u32 hash = __HashMap_HASH_FUNC(key); + BucketAndIndex r = __HashMap_search(ptr, key, hash); + // found existing item with the same key + if(r.i != -1){ + void* existing_item = ((u8*)r.bu->value_list.data) + r.i * ptr->value_t_size; + memcpy(existing_item, value_ptr, ptr->value_t_size); + } + + HashMapBucket* bu = r.bu; + if(bu == NULL || List_len(&bu->key_hash_list, KeyHash) >= __HashMapBucket_MAX_LEN){ + __HashMap_expand(ptr); + bu = &ptr->table[hash % ptr->height]; + } + + KeyHash kh = { .key = str_copy(key), .hash = hash }; + List_push(&bu->key_hash_list, KeyHash, kh); + List_push_size(&bu->value_list, value_ptr, ptr->value_t_size); +} + +bool HashMap_tryDelete(HashMap_* ptr, const str key){ u32 hash = __HashMap_HASH_FUNC(key); BucketAndIndex r = __HashMap_search(ptr, key, hash); // key not found