PatchworkOS  c9fea19
A non-POSIX operating system.
Loading...
Searching...
No Matches
map.h
Go to the documentation of this file.
1#pragma once
2
3#include <assert.h>
4#include <stdbool.h>
5#include <stdint.h>
6#include <string.h>
7#include <sys/io.h>
8
9typedef struct map_key map_key_t;
10typedef struct map_entry map_entry_t;
11typedef struct map map_t;
12
13/**
14 * @brief Hash Map
15 * @defgroup kernel_utils_map Hash Map
16 * @ingroup kernel_utils
17 *
18 * @todo Dynamically sized keys without heap allocation?
19 *
20 * @{
21 */
22
23/**
24 * @brief The minimum capacity of a map.
25 */
26#define MAP_MIN_CAPACITY 16
27
28/**
29 * @brief The maximum load percentage of a map before it resizes.
30 */
31#define MAP_MAX_LOAD_PERCENTAGE 75
32
33/**
34 * @brief The minimum load percentage of a map before it resizes down.
35 */
36#define MAP_MIN_LOAD_PERCENTAGE 25
37
38/**
39 * @brief The value used to indicate a tombstone (removed entry).
40 */
41#define MAP_TOMBSTONE ((map_entry_t*)1)
42
43/**
44 * @brief The maximum length of a key in the map.
45 */
46#define MAP_KEY_MAX_LENGTH 118
47
48/**
49 * @brief Map key stucture.
50 *
51 * Is used to implement a generic key for the map. The object is copied into `key` and hashed.
52 * We can then use the hash for quick comparisons and lookups while using the key itself for full comparisons no matter
53 * the type of the key.
54 */
55typedef struct map_key
56{
60} map_key_t;
61
62/**
63 * @brief Map entry structure.
64 *
65 * Place this in a structure to make it addable to a map and then use `CONTAINER_OF` to get the structure back.
66 */
67typedef struct map_entry
68{
73
74/**
75 * @brief Check if a map entry pointer is valid (not NULL or tombstone).
76 *
77 * @param entryPtr The map entry pointer to check.
78 * @return true if the entry pointer is valid, false otherwise.
79 */
80#define MAP_ENTRY_PTR_IS_VALID(entryPtr) ((entryPtr) != NULL && (entryPtr) != MAP_TOMBSTONE)
81
82/**
83 * @brief Hash map structure.
84 *
85 * The entries can be safely iterated over as an array as long sa the `MAP_ENTRY_PTR_IS_VALID` macro is used to check
86 * each entry before dereferencing it.
87 */
95
96/**
97 * @brief Hash a object.
98 *
99 * @param object The object to hash.
100 * @param length The length of the object in bytes.
101 * @return The hash of the object.
102 */
103uint64_t hash_object(const void* object, uint64_t length);
104
105/**
106 * @brief Create a map key from a buffer.
107 *
108 * @param buffer The buffer to create the key from.
109 * @param length The length of the buffer in bytes.
110 * @return The map key.
111 */
112static inline map_key_t map_key_buffer(const void* buffer, uint64_t length)
113{
114 assert(length <= MAP_KEY_MAX_LENGTH);
115 map_key_t key;
116 memcpy(key.key, buffer, length);
117 key.len = length;
118 key.hash = hash_object(buffer, length);
119 return key;
120}
121
122/**
123 * @brief Create a map key from a uint64_t.
124 *
125 * @param uint64 The uint64_t to create the key from.
126 * @return The map key.
127 */
128static inline map_key_t map_key_uint64(uint64_t uint64)
129{
130 map_key_t key;
131 memcpy(key.key, &uint64, sizeof(uint64_t));
132 key.len = sizeof(uint64_t);
133 key.hash = hash_object(&uint64, sizeof(uint64_t));
134 return key;
135}
136
137/**
138 * @brief Create a map key from a string.
139 *
140 * @param str The string to create the key from.
141 * @return The map key.
142 */
143static inline map_key_t map_key_string(const char* str)
144{
146}
147
148/**
149 * @brief Initialize a map entry.
150 *
151 * @param entry The map entry to initialize.
152 */
153void map_entry_init(map_entry_t* entry);
154
155/**
156 * @brief Create a map initializer.
157 *
158 * @return A map initializer.
159 */
160#define MAP_CREATE() {.entries = NULL, .capacity = 0, .length = 0, .tombstones = 0}
161
162/**
163 * @brief Initialize a map.
164 *
165 * @param map The map to initialize.
166 */
167void map_init(map_t* map);
168
169/**
170 * @brief Deinitialize a map.
171 *
172 * @param map The map to deinitialize.
173 */
174void map_deinit(map_t* map);
175
176/**
177 * @brief Insert a key-value pair into the map.
178 *
179 * If the key already exists, then an `EEXIST` error is returned.
180 *
181 * @param map The map to insert into.
182 * @param key The key to insert.
183 * @param value The value to insert.
184 * @return On success, `0`. On failure, `ERR` and `errno` is set.
185 */
186uint64_t map_insert(map_t* map, const map_key_t* key, map_entry_t* value);
187
188/**
189 * @brief Replace a key-value pair in the map.
190 *
191 * If the key does not exist, it is inserted.
192 *
193 * @param map The map to replace in.
194 * @param key The key to replace.
195 * @param value The value to replace.
196 * @return On success, `0`. On failure, `ERR` and `errno` is set.
197 */
198uint64_t map_replace(map_t* map, const map_key_t* key, map_entry_t* entry);
199
200/**
201 * @brief Get a value from the map by key.
202 *
203 * @param map The map to get from.
204 * @param key The key to get.
205 * @return On success, the value. If the key does not exist, returns `NULL`.
206 */
207map_entry_t* map_get(map_t* map, const map_key_t* key);
208
209/**
210 * @brief Get and remove a key-value pair from the map.
211 *
212 * @param map The map to get from.
213 * @param key The key to get and remove.
214 * @return On success, the value. If the key does not exist, returns `NULL`.
215 */
217
218/**
219 * @brief Remove a entry from the map.
220 *
221 * If the entry does not exist, nothing happens.
222 *
223 * @param map The map to remove from.
224 * @param entry The entry to remove.
225 */
226void map_remove(map_t* map, map_entry_t* entry);
227
228/**
229 * @brief Remove a key-value pair from the map by key.
230 *
231 * If the key does not exist, nothing happens.
232 *
233 * @param map The map to remove from.
234 * @param key The key to remove.
235 */
236void map_remove_key(map_t* map, const map_key_t* key);
237
238/**
239 * @brief Get the number of entries in the map.
240 *
241 * @param map The map to get the size of.
242 * @return The number of entries in the map.
243 */
244uint64_t map_size(const map_t* map);
245
246/**
247 * @brief Get the capacity of the map.
248 *
249 * @param map The map to get the capacity of.
250 * @return The capacity of the map.
251 */
253
254/**
255 * @brief Check if the map is empty.
256 *
257 * @param map The map to check.
258 * @return `true` if the map is empty, `false` otherwise.
259 */
260bool map_is_empty(const map_t* map);
261
262/**
263 * @brief Check if the map contains a key.
264 *
265 * @param map The map to check.
266 * @param key The key to check for.
267 * @return `true` if the map contains the key, `false` otherwise.
268 */
269bool map_contains(map_t* map, const map_key_t* key);
270
271/**
272 * @brief Clear all entries from the map.
273 *
274 * Note that this does not free the entries themselves, only removes them from the map.
275 *
276 * @param map The map to clear.
277 */
278void map_clear(map_t* map);
279
280/**
281 * @brief Reserve space in the map for at least `minCapacity` entries.
282 *
283 * @param map The map to reserve space in.
284 * @param minCapacity The minimum capacity to reserve.
285 * @return On success, `0`. On failure, `ERR` and `errno` is set.
286 */
287uint64_t map_reserve(map_t* map, uint64_t minCapacity);
288
289/** @} */
#define assert(expression)
Definition assert.h:29
uint64_t hash_object(const void *object, uint64_t length)
Hash a object.
Definition map.c:42
static map_key_t map_key_buffer(const void *buffer, uint64_t length)
Create a map key from a buffer.
Definition map.h:112
void map_init(map_t *map)
Initialize a map.
Definition map.c:176
uint64_t map_capacity(const map_t *map)
Get the capacity of the map.
Definition map.c:386
bool map_contains(map_t *map, const map_key_t *key)
Check if the map contains a key.
Definition map.c:396
void map_clear(map_t *map)
Clear all entries from the map.
Definition map.c:401
void map_deinit(map_t *map)
Deinitialize a map.
Definition map.c:184
#define MAP_KEY_MAX_LENGTH
The maximum length of a key in the map.
Definition map.h:46
uint64_t map_replace(map_t *map, const map_key_t *key, map_entry_t *entry)
Replace a key-value pair in the map.
Definition map.c:247
void map_entry_init(map_entry_t *entry)
Initialize a map entry.
Definition map.c:71
static map_key_t map_key_uint64(uint64_t uint64)
Create a map key from a uint64_t.
Definition map.h:128
uint64_t map_size(const map_t *map)
Get the number of entries in the map.
Definition map.c:381
uint64_t map_insert(map_t *map, const map_key_t *key, map_entry_t *value)
Insert a key-value pair into the map.
Definition map.c:204
map_entry_t * map_get_and_remove(map_t *map, const map_key_t *key)
Get and remove a key-value pair from the map.
Definition map.c:335
void map_remove(map_t *map, map_entry_t *entry)
Remove a entry from the map.
Definition map.c:353
void map_remove_key(map_t *map, const map_key_t *key)
Remove a key-value pair from the map by key.
Definition map.c:364
bool map_is_empty(const map_t *map)
Check if the map is empty.
Definition map.c:391
map_entry_t * map_get(map_t *map, const map_key_t *key)
Get a value from the map by key.
Definition map.c:287
uint64_t map_reserve(map_t *map, uint64_t minCapacity)
Reserve space in the map for at least minCapacity entries.
Definition map.c:418
static map_key_t map_key_string(const char *str)
Create a map key from a string.
Definition map.h:143
boot_memory_map_t * map
Definition mem.c:19
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:61
size_t strnlen_s(const char *s, size_t maxsize)
Definition strnlen_s.c:4
Map entry structure.
Definition map.h:68
uint64_t index
Definition map.h:70
map_t * map
Definition map.h:71
map_key_t key
Definition map.h:69
Map key stucture.
Definition map.h:56
uint8_t key[MAP_KEY_MAX_LENGTH]
Definition map.h:57
uint8_t len
Definition map.h:58
uint64_t hash
Definition map.h:59
Hash map structure.
Definition map.h:89
uint64_t capacity
Definition map.h:91
map_entry_t ** entries
Definition map.h:90
uint64_t tombstones
Definition map.h:93
uint64_t length
Definition map.h:92