Added hashmap source files

This commit is contained in:
Lucian Popescu 2021-03-13 10:42:55 +02:00
parent ac80889190
commit da7d31bad8
3 changed files with 201 additions and 0 deletions

164
hashmap.c Normal file
View File

@ -0,0 +1,164 @@
// SPDX-License-Identifier: BSD-2
#include <hashmap.h>
#include <stdlib.h>
#define MAP_INIT_SIZE 1024
struct hashmap_elem {
int key;
int in_use;
void *val;
};
struct hashmap_map {
int max_size;
int curr_size;
struct hashmap_elem *data;
};
map_t hashmap_new(void)
{
struct hashmap_map *m;
m = calloc(1, sizeof(struct hashmap_map));
if (!m)
goto err;
m->data = calloc(MAP_INIT_SIZE, sizeof(struct hashmap_elem));
if (!m->data)
goto err;
m->max_size = MAP_INIT_SIZE;
m->curr_size = 0;
return m;
err:
hashmap_free(m);
return NULL;
}
unsigned int _hashmap_hash_int(struct hashmap_map *m, unsigned int key)
{
key += (key << 12);
key ^= (key >> 22);
key += (key << 4);
key ^= (key >> 9);
key += (key << 10);
key ^= (key >> 2);
key += (key << 7);
key ^= (key >> 12);
key = (key >> 3) * 2654435761;
return key % m->max_size;
}
int _hashmap_hash(struct hashmap_map *m, int key)
{
int pos;
int i;
if (m->curr_size == m->max_size)
return MAP_FULL;
pos = _hashmap_hash_int(m, key);
i = 0;
while (i < m->max_size) {
if (!m->data[pos].in_use)
return pos;
if (m->data[pos].key == key && m->data[pos].in_use)
return pos;
pos = (pos + 1) % m->max_size;
i++;
}
return MAP_FULL;
}
int _hashmap_rehash(struct hashmap_map *m)
{
int i;
int old_size;
int status;
struct hashmap_elem *curr;
struct hashmap_elem *temp;
temp = calloc(2 * m->max_size, sizeof(struct hashmap_elem));
if (!temp)
return MAP_OMEM;
curr = m->data;
m->data = temp;
old_size = m->max_size;
m->max_size *= 2;
m->curr_size = 0;
for (i = 0; i < old_size; i++) {
status = hashmap_put(m, curr[i].key, curr[i].val);
if (status != MAP_OK)
return status;
}
free(curr);
return MAP_OK;
}
int hashmap_put(map_t map, int key, void *value)
{
int index;
struct hashmap_map *m;
m = (struct hashmap_map *) map;
index = _hashmap_hash(m, key);
while (index == MAP_FULL) {
if (_hashmap_rehash(m) == MAP_OMEM)
return MAP_OMEM;
index = _hashmap_hash(m, key);
}
m->data[index] = (struct hashmap_elem) {key, 1, value};
m->curr_size++;
return MAP_OK;
}
int hashmap_get(map_t map, int key, void **ret_val)
{
int pos;
int i;
struct hashmap_map *m;
m = (struct hashmap_map *) map;
pos = _hashmap_hash_int(m, key);
i = 0;
while (i < m->max_size) {
if (m->data[pos].key == key && m->data[pos].in_use) {
*ret_val = m->data[pos].val;
return MAP_OK;
}
pos = (pos + 1) % m->max_size;
i++;
}
*ret_val = NULL;
return MAP_MISSING;
}
void hashmap_free(map_t map)
{
struct hashmap_map *m;
m = (struct hashmap_map *) map;
free(m->data);
free(m);
}

19
include/hashmap.h Normal file
View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: BSD-2 */
#ifndef _hashmap_h
#define _hashmap_h
#define MAP_OK 0
#define MAP_OMEM -1
#define MAP_FULL -2
#define MAP_MISSING -3
typedef void *map_t;
extern map_t hashmap_new(void);
extern void hashmap_free(map_t map);
extern int hashmap_put(map_t map, int key, void *val);
extern int hashmap_get(map_t map, int key, void **ret_val);
#endif

18
so-cpp.c Normal file
View File

@ -0,0 +1,18 @@
// SPDX-License-Identifier: BSD-2
#include "hashmap.h"
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *saved_str = calloc(1, sizeof(char *));
map_t m = hashmap_new();
hashmap_put(m, 2, "Salut");
hashmap_get(m, 2, (void **) &saved_str);
hashmap_free(m);
printf("%s\n", saved_str);
return 0;
}