feat(hash_map): hash_map
This commit is contained in:
parent
c299882586
commit
78068f53bd
2 changed files with 207 additions and 0 deletions
173
src/utils/hash_map/hash_map.c
Normal file
173
src/utils/hash_map/hash_map.c
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
#include "hash_map.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** Hash the key using FNV-1a 32 bits hash algorithm.
|
||||
*/
|
||||
static size_t hash(const char *key)
|
||||
{
|
||||
if (key == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t hash = 2166136261; // FNV offset basis
|
||||
uint32_t prime = 16777619; // FNV prime
|
||||
|
||||
while (*key != 0)
|
||||
{
|
||||
hash ^= *key;
|
||||
hash *= prime;
|
||||
key++;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
struct hash_map *hash_map_init(size_t size)
|
||||
{
|
||||
struct hash_map *p = malloc(sizeof(struct hash_map));
|
||||
if (p != NULL)
|
||||
{
|
||||
p->data = calloc(size, sizeof(struct pair_list *));
|
||||
if (p->data == NULL)
|
||||
{
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
p->size = size;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
bool hash_map_insert(struct hash_map *hash_map, const char *key, void *value,
|
||||
bool *updated)
|
||||
{
|
||||
if (hash_map == NULL || hash_map->size == 0 || key == NULL)
|
||||
return false;
|
||||
|
||||
size_t h = hash(key);
|
||||
struct pair_list **l = hash_map->data;
|
||||
size_t i = h % hash_map->size;
|
||||
|
||||
if (l[i] != NULL)
|
||||
{
|
||||
// check if key is in linked list
|
||||
struct pair_list *iter = l[i];
|
||||
while (iter)
|
||||
{
|
||||
if (strcmp(iter->key, key) == 0)
|
||||
{
|
||||
// update
|
||||
iter->value = value;
|
||||
if (updated)
|
||||
*updated = true;
|
||||
return true;
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
// if not found => collision
|
||||
}
|
||||
struct pair_list *p = malloc(sizeof(struct pair_list));
|
||||
if (p == NULL)
|
||||
return false;
|
||||
|
||||
if (updated)
|
||||
*updated = false;
|
||||
|
||||
p->key = key;
|
||||
p->value = value;
|
||||
p->next = l[i];
|
||||
l[i] = p;
|
||||
l[i] = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
void hash_map_free(struct hash_map *hash_map)
|
||||
{
|
||||
struct pair_list *l;
|
||||
struct pair_list *prev;
|
||||
|
||||
if (hash_map)
|
||||
{
|
||||
for (size_t i = 0; i < hash_map->size; i++)
|
||||
{
|
||||
l = hash_map->data[i];
|
||||
while (l != NULL)
|
||||
{
|
||||
prev = l;
|
||||
l = l->next;
|
||||
free(prev);
|
||||
}
|
||||
}
|
||||
free(hash_map->data);
|
||||
free(hash_map);
|
||||
}
|
||||
}
|
||||
|
||||
void hash_map_foreach(struct hash_map *hash_map,
|
||||
void (*fn)(const char *, const void *))
|
||||
{
|
||||
if (hash_map == NULL)
|
||||
return;
|
||||
|
||||
struct pair_list *iter;
|
||||
for (size_t i = 0; i < hash_map->size; i++)
|
||||
{
|
||||
iter = hash_map->data[i];
|
||||
while (iter != NULL)
|
||||
{
|
||||
fn(iter->key, iter->value);
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const void *hash_map_get(const struct hash_map *hash_map, const char *key)
|
||||
{
|
||||
if (hash_map == NULL || hash_map->size == 0)
|
||||
return NULL;
|
||||
|
||||
size_t h = hash(key);
|
||||
size_t i = h % hash_map->size;
|
||||
struct pair_list *l = hash_map->data[i];
|
||||
while (l != NULL)
|
||||
{
|
||||
if (strcmp(l->key, key) == 0)
|
||||
return l->value;
|
||||
l = l->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool hash_map_remove(struct hash_map *hash_map, const char *key)
|
||||
{
|
||||
if (hash_map == NULL || hash_map->size == 0)
|
||||
return false;
|
||||
|
||||
size_t h = hash(key);
|
||||
size_t i = h % hash_map->size;
|
||||
struct pair_list *l = hash_map->data[i];
|
||||
struct pair_list *p = NULL;
|
||||
|
||||
while (l != NULL)
|
||||
{
|
||||
if (strcmp(l->key, key) == 0)
|
||||
{
|
||||
if (p != NULL)
|
||||
p->next = l->next;
|
||||
else
|
||||
hash_map->data[i] = l->next;
|
||||
free(l);
|
||||
return true;
|
||||
}
|
||||
p = l;
|
||||
l = l->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
34
src/utils/hash_map/hash_map.h
Normal file
34
src/utils/hash_map/hash_map.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef HASH_MAP_H
|
||||
#define HASH_MAP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct pair_list
|
||||
{
|
||||
const char *key;
|
||||
void *value;
|
||||
struct pair_list *next;
|
||||
};
|
||||
|
||||
struct hash_map
|
||||
{
|
||||
struct pair_list **data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct hash_map *hash_map_init(size_t size);
|
||||
|
||||
bool hash_map_insert(struct hash_map *hash_map, const char *key, void *value,
|
||||
bool *updated);
|
||||
|
||||
void hash_map_free(struct hash_map *hash_map);
|
||||
|
||||
void hash_map_foreach(struct hash_map *hash_map,
|
||||
void (*fn)(const char *, const void *));
|
||||
|
||||
const void *hash_map_get(const struct hash_map *hash_map, const char *key);
|
||||
|
||||
bool hash_map_remove(struct hash_map *hash_map, const char *key);
|
||||
|
||||
#endif /* ! HASH_MAP_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue