summaryrefslogtreecommitdiff
path: root/include/engine/hashmap.h
blob: bf1d87c0bb572c6f9de8873faad92a8b3a22fc80 (plain)
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
#ifndef ENGINE_HASHMAP_H
#define ENGINE_HASHMAP_H

#include "types.h"

#include "list.h"
#include "memory.h"
#include <stdlib.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