|
| 1 | +/* ***************************************************************************** |
| 2 | +
|
| 3 | + Hash Maps |
| 4 | +
|
| 5 | +
|
| 6 | +Easily define key-value String Hash Map, also sometimes called a "dictionary", |
| 7 | +using different smart defaults for short keys `FIO_MAP_KEY_KSTR` vs longer keys |
| 8 | +(or when expecting a sparsely populated map) `FIO_MAP_KEY_BSTR`. |
| 9 | +
|
| 10 | +***************************************************************************** */ |
| 11 | + |
| 12 | +/* ***************************************************************************** |
| 13 | +(2) Hash Map: String Dictionary (automatic setup) |
| 14 | +***************************************************************************** */ |
| 15 | + |
| 16 | +/* Set the properties for the key-value Unordered Map type called `dict_s` */ |
| 17 | +#define FIO_UMAP_NAME dict |
| 18 | +#define FIO_MAP_KEY_KSTR /* pre-defined macro for using fio_keystr_s keys. */ |
| 19 | +#define FIO_MAP_VALUE_BSTR /* pre-defined macro for using String values. */ |
| 20 | +#define FIO_MAP_HASH_FN(str) \ |
| 21 | + fio_risky_hash(str.buf, str.len, (uint64_t)&fio_risky_hash) |
| 22 | +#include "fio-stl/include.h" /* or "fio-stl.h" */ |
| 23 | + |
| 24 | +void easy_dict_example(void) { |
| 25 | + dict_s dictionary = FIO_MAP_INIT; |
| 26 | + /* insertion using dict_set */ |
| 27 | + dict_set(&dictionary, |
| 28 | + FIO_STR_INFO1("Hello"), |
| 29 | + FIO_STR_INFO1("Hello World!"), |
| 30 | + NULL); |
| 31 | + dict_set(&dictionary, |
| 32 | + FIO_STR_INFO1("42"), |
| 33 | + FIO_STR_INFO1("Meaning of life..."), |
| 34 | + NULL); |
| 35 | + /* access using dict_get */ |
| 36 | + printf("- Printing each key: value\n"); |
| 37 | + printf("Hello: %s\n", dict_get(&dictionary, FIO_STR_INFO1("Hello")).buf); |
| 38 | + printf("42: %s\n", dict_get(&dictionary, FIO_STR_INFO1("42")).buf); |
| 39 | + /* update using dict_set */ |
| 40 | + printf("- Updating value for 42 and reprinting\n"); |
| 41 | + dict_set(&dictionary, |
| 42 | + FIO_STR_INFO1("42"), |
| 43 | + FIO_STR_INFO1("What was the question?"), |
| 44 | + NULL); |
| 45 | + /* map iteration - this is an unordered map, order is incidental. */ |
| 46 | + FIO_MAP_EACH(dict, &dictionary, i) { |
| 47 | + printf("%-8s: %s\n", i.key.buf, i.value.buf); |
| 48 | + } |
| 49 | + /* removal using dict_remove */ |
| 50 | + dict_remove(&dictionary, FIO_STR_INFO1("42"), NULL); |
| 51 | + /* Since the "42" key was removed, its `buf` value will point to NULL. */ |
| 52 | + printf("Did we remove 42 ... ? - %s\n", |
| 53 | + dict_get(&dictionary, FIO_STR_INFO1("42")).buf |
| 54 | + ? dict_get(&dictionary, FIO_STR_INFO1("42")).buf |
| 55 | + : "removed"); |
| 56 | + /* Cleanup. */ |
| 57 | + dict_destroy(&dictionary); |
| 58 | +} |
| 59 | + |
| 60 | +/* ***************************************************************************** |
| 61 | +(2) Hash Map: String Dictionary (manual setup) |
| 62 | +***************************************************************************** */ |
| 63 | + |
| 64 | +/* Create a binary safe String type for Strings that aren't mutated often */ |
| 65 | +#define FIO_STR_SMALL str |
| 66 | +#include "fio-stl/include.h" /* or "fio-stl.h" */ |
| 67 | + |
| 68 | +/* Defines a key-value Unordered Map type called `dictionary_s` */ |
| 69 | +#define FIO_MAP_NAME dictionary |
| 70 | +#define FIO_MAP_ORDERED 0 |
| 71 | +#define FIO_MAP_VALUE str_s |
| 72 | +#define FIO_MAP_VALUE_COPY(dest, src) str_init_copy2(&(dest), &(src)) |
| 73 | +#define FIO_MAP_VALUE_DESTROY(k) str_destroy(&k) |
| 74 | +#define FIO_MAP_VALUE_CMP(a, b) str_is_eq(&(a), &(b)) |
| 75 | +#define FIO_MAP_KEY FIO_MAP_VALUE |
| 76 | +#define FIO_MAP_KEY_COPY FIO_MAP_VALUE_COPY |
| 77 | +#define FIO_MAP_KEY_DESTROY FIO_MAP_VALUE_DESTROY |
| 78 | +#define FIO_MAP_KEY_CMP FIO_MAP_VALUE_CMP |
| 79 | +#include "fio-stl/include.h" /* or "fio-stl.h" */ |
| 80 | +/** set helper for consistent hash values */ |
| 81 | +FIO_IFUNC str_s dictionary_set2(dictionary_s *m, str_s key, str_s obj) { |
| 82 | + return dictionary_set(m, str_hash(&key, (uint64_t)m), key, obj, NULL); |
| 83 | +} |
| 84 | +/** get helper for consistent hash values */ |
| 85 | +FIO_IFUNC str_s *dictionary_get2(dictionary_s *m, str_s key) { |
| 86 | + return &(dictionary_get_ptr(m, str_hash(&key, (uint64_t)m), key)->value); |
| 87 | +} |
| 88 | + |
| 89 | +void dictionary_example(void) { |
| 90 | + dictionary_s dictionary = FIO_MAP_INIT; |
| 91 | + str_s key, val; |
| 92 | + str_init_const(&key, "hello", 5); |
| 93 | + str_init_const(&val, "Hello World!", 12); |
| 94 | + dictionary_set2(&dictionary, key, val); |
| 95 | + printf("%s\n", str_ptr(dictionary_get2(&dictionary, key))); |
| 96 | + dictionary_destroy(&dictionary); |
| 97 | +} |
| 98 | + |
| 99 | +/* ***************************************************************************** |
| 100 | +(3) Hash Map: Strings to Numbers |
| 101 | +***************************************************************************** */ |
| 102 | + |
| 103 | +/* map words to numbers. */ |
| 104 | +#define FIO_UMAP_NAME umap |
| 105 | +#define FIO_MAP_KEY_KSTR |
| 106 | +#define FIO_MAP_VALUE uintptr_t |
| 107 | +#define FIO_MAP_HASH_FN(k) \ |
| 108 | + fio_risky_hash((k).buf, (k).len, (uint64_t)(uintptr_t)&umap_destroy) |
| 109 | +#include "fio-stl/include.h" /* or "fio-stl.h" */ |
| 110 | + |
| 111 | +/* example adding strings to map and printing data. */ |
| 112 | +void map_keystr_example(void) { |
| 113 | + umap_s map = FIO_MAP_INIT; |
| 114 | + /* FIO_KEYSTR_CONST prevents copying of longer constant strings */ |
| 115 | + umap_set(&map, FIO_STR_INFO3("One", 3, FIO_KEYSTR_CONST), 1, NULL); |
| 116 | + umap_set(&map, FIO_STR_INFO3("Two", 3, FIO_KEYSTR_CONST), 2, NULL); |
| 117 | + umap_set(&map, FIO_STR_INFO3("Three", 5, FIO_KEYSTR_CONST), 3, NULL); |
| 118 | + FIO_MAP_EACH(umap, &map, pos) { |
| 119 | + uintptr_t value = pos.value; |
| 120 | + printf("%.*s: %llu\n", |
| 121 | + (int)pos.key.len, |
| 122 | + pos.key.buf, |
| 123 | + (unsigned long long)value); |
| 124 | + } |
| 125 | + umap_destroy(&map); |
| 126 | +} |
| 127 | + |
| 128 | +/* ***************************************************************************** |
| 129 | +main |
| 130 | +***************************************************************************** */ |
| 131 | + |
| 132 | +int main(void) { |
| 133 | + printf("=====================================\n"); |
| 134 | + easy_dict_example(); |
| 135 | + printf("=====================================\n"); |
| 136 | + dictionary_example(); |
| 137 | + printf("=====================================\n"); |
| 138 | + map_keystr_example(); |
| 139 | + printf("=====================================\n"); |
| 140 | +} |
0 commit comments