/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* ft_hashmap.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: thrieg +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/11/07 12:14:50 by thrieg #+# #+# */ /* Updated: 2025/02/16 19:08:34 by thrieg ### ########.fr */ /* */ /* ************************************************************************** */ #include "ft_hashmap_private.h" //allocates an array of initial_size, and sets nb_elems/hashmap_size to 0 //cmp is a function that returns 0 if both keys are the same //returns NULL if any allocation fails t_hashmap *ft_create_hashmap( size_t initial_size, void (*free_key)(void *), void (*free_value)(void *), int (*cmp)(void *key, void *key_to_compare)) { t_hashmap *map; if (initial_size == 0) return (NULL); map = malloc(sizeof(t_hashmap)); if (!map) return (NULL); map->nb_elems = 0; map->hashmap_size = initial_size; map->cmp = cmp; map->free_key = free_key; map->free_value = free_value; map->table = ft_calloc((initial_size), sizeof(t_list *)); if (!(map->table)) return (free(map), NULL); return (map); } // Inserts a key-value pair into the hashmap, //returns 0 for an error, 1 for remplaced value for a key and 2 for new key int ft_hashmap_insert_element( t_hashmap *map, void *key, void *value, size_t hash) { size_t index; t_list *current; t_hash_element *element; if (!map || !key) return (0); if ((map->nb_elems * 100) > map->hashmap_size * HASHMAP_FILL_PERCENT_MAX) ft_resize_hashmap(map); index = hash % map->hashmap_size; current = map->table[index]; while (current) { if (map->cmp(((t_hash_element *)(current->content))->key, key) == 0) { map->free_value(((t_hash_element *)(current->content))->value); return (((t_hash_element *)(current->content))->value = value, 1); } current = current->next; } element = ft_create_hash_element(key, value, hash); if (!element) return (0); if (!ft_add_hashmap_element(index, map, element)) return (ft_free_hash_element(element, map), 0); return (2); } //returns 1 if the element has been deleted //returns 0 if the element has not been found int ft_delete_hashmap_element(t_hashmap *map, void *key, size_t hash) { size_t index; t_list *curr; t_list *prev; t_hash_element *elem; if (!map || !key || map->hashmap_size == 0) return (0); if (((map->nb_elems * 100) / map->hashmap_size) <= HASHMAP_FILL_PERCENT_BEFORE_SHRINK) ft_shrink_hashmap(map); index = hash % map->hashmap_size; curr = map->table[index]; prev = NULL; while (curr) { elem = (t_hash_element *)curr->content; if (map->cmp(elem->key, key) == 0) { return (ft_delete_hashmap_list_node(curr, prev, index, map), 1); } prev = curr; curr = curr->next; } return (0); } //returns a pointer to the value of key, or a NULL pointer if not found void *ft_lookup_hashmap_element(t_hashmap *map, void *key, size_t hash) { size_t index; t_list *curr; t_hash_element *elem; if (!map || !key || map->hashmap_size == 0) return (NULL); index = hash % map->hashmap_size; curr = map->table[index]; while (curr) { elem = (t_hash_element *)curr->content; if (map->cmp(elem->key, key) == 0) return (elem->value); curr = curr->next; } return (NULL); } //frees the entire hashmap and then returns NULL once done void *ft_free_hashmap(t_hashmap *map) { size_t index; t_list *curr; t_list *next; t_hash_element *elem; if (!map) return (NULL); if (!map->table) return (free(map), NULL); index = 0; while (index < map->hashmap_size) { curr = map->table[index]; while (curr) { next = curr->next; elem = (t_hash_element *)curr->content; ft_free_hash_element(elem, map); free(curr); curr = next; } index++; } free(map->table); return (free(map), NULL); }