| #include "map.h" |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| |
| #ifdef MAP_DEBUG |
| #define MAP_DEBUG_PRINTF printf |
| #else |
| #define MAP_DEBUG_PRINTF // nothing |
| #endif |
| |
| map_t *new_map_sized(uint64_t size) |
| { |
| map_t *m = malloc(sizeof(map_t)); |
| |
| /* |
| * Calloc zeroes the memory, which is what we want. |
| */ |
| |
| map_node empty = EMPTY_NODE; |
| |
| m->items = calloc(size, sizeof(map_node)); |
| m->len = MAP_ALLOC_SIZE; |
| m->full = 0; |
| |
| for (int i = 0; i < m->len; i++) |
| { |
| m->items[i] = empty; |
| } |
| |
| return m; |
| } |
| |
| map_t *new_map() |
| { |
| return new_map_sized(MAP_ALLOC_SIZE); |
| } |
| |
| void free_map(map_t *m) |
| { |
| free(m->items); |
| free(m); |
| } |
| |
| void free_map_items(map_t *m) |
| { |
| for (int i = 0; i < m->len; i++) |
| { |
| if (m->items[i].key != NULL) |
| { |
| free(m->items[i].key); |
| free(m->items[i].val); |
| } |
| } |
| free(m->items); |
| free(m); |
| } |
| |
| void map_set(map_t *m, char *k, void *v) |
| { |
| uint64_t h = hash(k); |
| uint32_t i = h % m->len; |
| |
| MAP_DEBUG_PRINTF("hash %u i %u\n", h, i); |
| |
| m->count++; |
| |
| if (m->full++ < m->len) |
| { |
| map_node val = |
| { |
| malloc(strlen(k) + 1), |
| v, |
| 1, |
| h, |
| }; |
| |
| strcpy(val.key, k); |
| |
| uint32_t current = i; |
| |
| while (MAP_USED_AT(m->items, current)) |
| { |
| if (current == m->len - 1) |
| { |
| current = 0; |
| } |
| else |
| { |
| current++; |
| } |
| } |
| |
| MAP_DEBUG_PRINTF("Current %d\n", current); |
| |
| m->items[current] = val; |
| |
| MAP_DEBUG_PRINTF("val %d\n", *(int *) m->items[current].val); |
| } |
| else |
| { |
| /* resize map */ |
| map_t *n_m = new_map_sized(m->len * 2); |
| |
| for (uint64_t j = 0; j < m->len; j++) |
| { |
| if (!MAP_USED_AT(m->items, j)) |
| { |
| continue; |
| } |
| |
| uint32_t current = m->items[j].h; |
| |
| while (MAP_USED_AT(m->items, current)) |
| { |
| if (current == m->len - 1) |
| { |
| current = 0; |
| } |
| else |
| { |
| current++; |
| } |
| } |
| |
| n_m->items[current] = m->items[j]; |
| } |
| |
| free_map(m); |
| m = n_m; |
| } |
| } |
| |
| int map_exists(map_t *m, char *k) |
| { |
| uint64_t h = hash(k); |
| uint32_t i = h % m->len; |
| |
| uint32_t current = i; |
| |
| while (m->items[current].used) |
| { |
| if (strcmp(m->items[current].key, k) == 0) |
| { |
| return 1; |
| } |
| |
| if (current >= m->len - 1) |
| { |
| current = 0; |
| MAP_DEBUG_PRINTF("Current reset to 0\n"); |
| } |
| else |
| { |
| current++; |
| MAP_DEBUG_PRINTF("Incrementing current\n"); |
| } |
| } |
| |
| return 0; |
| } |
| |
| void *map_get(map_t *m, char *k) |
| { |
| uint64_t h = hash(k); |
| uint32_t i = h % m->len; |
| |
| uint32_t current = i; |
| |
| MAP_DEBUG_PRINTF("%s should be %s\n", m->items[current].key, k); |
| MAP_DEBUG_PRINTF("streq %d\n", strcmp(m->items[current].key, k)); |
| |
| MAP_DEBUG_PRINTF("Current get %d\n", current); |
| |
| while (strcmp(m->items[current].key, k) != 0) |
| { |
| MAP_DEBUG_PRINTF("While at %d\n", current); |
| if (current >= m->len - 1) |
| { |
| current = 0; |
| MAP_DEBUG_PRINTF("Current reset to 0\n"); |
| } |
| else |
| { |
| current++; |
| MAP_DEBUG_PRINTF("Incrementing current\n"); |
| } |
| } |
| |
| MAP_DEBUG_PRINTF("val %d\n", *(int *) m->items[current].val); |
| |
| return m->items[current].val; |
| |
| //return 1; |
| } |
| |
| void map_debug(map_t *m) |
| { |
| for (int i = 0; i < m->len; i++) |
| { |
| if (m->items[i].val != NULL) |
| { |
| MAP_DEBUG_PRINTF("i = %d, k = %s, v = %d\n", |
| i, m->items[i].key, *(int *) m->items[i].val); |
| } |
| } |
| } |