1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#ifndef ENGINE_HASHMAP_H
#define ENGINE_HASHMAP_H
#include "types.h"
#include <stdlib.h>
#include "list.h"
#include "memory.h"
i32 lolhash(const usize s, i32 v);
/* Define a linked list before using this */
/* Example: DEFINE_LLIST(i32) */
#define DEFINE_HASHMAP(type, lsize, cmp, type_to_int) \
typedef DEFINE_LLIST(type); \
typedef struct hashmap_##type { \
usize size; \
List_##type elems[64]; \
} hashmap_##type; \
\
type* hashmap_##type##_lookup(hashmap_##type* hmap, const type* val) { \
const i32 idx = lolhash(64, type_to_int(val)); \
List_##type *head = &hmap->elems[idx]; \
while (head != NULL) { \
if (!cmp(&(head->value), val)) return &(head->value); \
head = head->next; \
} \
return NULL; \
} \
\
void hashmap_##type##_insert(memory *m, hashmap_##type *hmap, const type *val) { \
const i32 idx = lolhash(64, type_to_int(val)); \
List_##type *head = &(hmap->elems[idx]); \
\
/* This is highly dependant on whether the memory is zero-initialized */ \
if (!type_to_int(&(head->value))) \
{ \
memcpy(&(head->value), val, sizeof(type)); \
return; \
} \
\
\
while (head->next != NULL && cmp(&head->value, val)) { \
head = head->next; \
} \
\
if (!cmp(&head->value, val)) memcpy(&(head->value), val, sizeof(type)); \
else { \
head->next = memory_allocate(m, sizeof(List_##type)); \
memcpy(&(head->next->value), val, sizeof(type)); \
} \
}
#endif
|