sc/map/README.md

135 lines
2.8 KiB
Markdown
Raw Normal View History

2021-02-07 22:31:04 +03:00
### Hashmap
2020-12-27 17:41:44 +03:00
### Overview
- Open addressing hashmap with linear probing.
- Requires postfix naming, it's ugly but macros are necessary to avoid
2021-02-03 08:09:50 +03:00
copy/compare function pointers, memcpy calls etc..
2020-12-27 17:41:44 +03:00
- Comes with predefined key value pairs :
2020-12-27 17:41:44 +03:00
```
name key type value type
sc_map_of_scalar(32, uint32_t, uint32_t)
sc_map_of_scalar(64, uint64_t, uint64_t)
sc_map_of_scalar(64v, uint64_t, void *)
sc_map_of_scalar(64s, uint64_t, const char *)
sc_map_of_strkey(str, const char *, const char *)
sc_map_of_strkey(sv, const char *, void*)
sc_map_of_strkey(s64, const char *, uint64_t)
```
- This is a very fast hashmap.
- Single array allocation for all data.
- Linear probing over an array.
- Deletion without tombstones.
- Macros generate functions in sc_map.c. So, inlining is upto the compiler.
### Note
Key and value types can be integers(32bit/64bit) or pointers only.
Other types can be added but must be scalar types, not structs. This is a
design decision, I don't remember when was the last time I wanted to store
struct as a key or value. I use hashmap for fast look-ups and small key-value
pairs with linear probing play well with cache lines and hardware-prefetcher.
If you want to use structs anyway, you need to change the code a little.
2021-02-07 22:31:04 +03:00
### Usage
2020-12-27 17:41:44 +03:00
```c
2020-12-27 17:41:44 +03:00
#include "sc_map.h"
#include <stdio.h>
void example_str(void)
2020-12-27 17:41:44 +03:00
{
2021-04-26 22:04:29 +03:00
const char *key, *value;
struct sc_map_str map;
2020-12-27 17:41:44 +03:00
2021-04-26 22:04:29 +03:00
sc_map_init_str(&map, 0, 0);
2020-12-27 17:41:44 +03:00
2021-04-26 22:04:29 +03:00
sc_map_put_str(&map, "jack", "chicago");
sc_map_put_str(&map, "jane", "new york");
sc_map_put_str(&map, "janie", "atlanta");
2020-12-27 17:41:44 +03:00
2021-04-26 22:04:29 +03:00
sc_map_foreach (&map, key, value) {
printf("Key:[%s], Value:[%s] \n", key, value);
}
2020-12-27 17:41:44 +03:00
2021-04-26 22:04:29 +03:00
sc_map_term_str(&map);
}
void example_int_to_str(void)
{
2021-04-26 22:04:29 +03:00
uint32_t key;
const char *elem;
const char **value;
2021-04-26 22:04:29 +03:00
struct sc_map_64s map;
2021-04-26 22:04:29 +03:00
sc_map_init_64s(&map, 0, 0);
2021-04-26 22:04:29 +03:00
sc_map_put_64s(&map, 100, "chicago");
sc_map_put_64s(&map, 200, "new york");
sc_map_put_64s(&map, 300, "atlanta");
2021-04-26 22:04:29 +03:00
value = sc_map_del_64s(&map, 100);
if (value != NULL) {
printf("Deleted : %s \n", *value);
2021-04-26 23:00:50 +03:00
}
sc_map_foreach (&map, key, elem) {
printf("Key:[%d], Value:[%s] \n", key, elem);
}
2021-04-26 22:04:29 +03:00
sc_map_term_64s(&map);
}
void example_errcheck(void)
{
bool ret;
uint32_t *val;
struct sc_map_32 map;
ret = sc_map_init_32(&map, 0, 0);
if (!ret) {
perror("Out of memory!");
abort();
}
ret = sc_map_put_32(&map, 0, 0);
if (!ret) {
perror("Out of memory!");
abort();
}
val = sc_map_get_32(&map, 0);
if (val != NULL) {
// set current value to 3
*val = 3;
}
val = sc_map_get_32(&map, 0);
if (val != NULL) {
printf("Read value : %u \n", *val);
}
val = sc_map_del_32(&map, 0);
if (val != NULL) {
printf("Deleted : %u \n", *val);
}
sc_map_term_32(&map);
}
int main()
{
example_errcheck();
example_str();
example_int_to_str();
2020-12-27 17:41:44 +03:00
return 0;
2020-12-27 17:41:44 +03:00
}
2020-12-27 17:41:44 +03:00
```