summaryrefslogtreecommitdiff
path: root/include/engine/hashmap.h
blob: 4b97b8e2b1a3976d7d7347b5f5c8ddb905ba7a0f (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
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