Started implementing a hashmap that includes tags for the all the game
objects.
This commit is contained in:
1 parent
6b1197bfca
commit
20f476c4ab
7 files changed
+196
-3
No files matched your search
+164
@@ -0,0 +1,164 @@
|
||||
#include "Hashmap.h"
|
||||
#include "constants.h"
|
||||
#include "engine_build_config.h"
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG_ENGINE
|
||||
#include <stdio.h>
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
INTERNAL struct objects_hashmap {
|
||||
size_t count;
|
||||
char *keys[MAX_OBJ_COUNT];
|
||||
int32_t active_indices[MAX_OBJ_COUNT];
|
||||
} map = {};
|
||||
|
||||
void init_hashmap() {
|
||||
// Technically, memset shouldn't be used to set the values of any thing other
|
||||
// than byte arrays, but since it works in certain cases (e.g. 0 and -1) and
|
||||
// it is faster than doing a for loop, I am using it here to initialise the
|
||||
// active_indices array to -1
|
||||
memset(map.active_indices, -1, sizeof(map.active_indices));
|
||||
}
|
||||
|
||||
size_t hash_key(const char *key) {
|
||||
size_t i = 0;
|
||||
|
||||
for (size_t j = 0; key[j]; ++j) {
|
||||
i += (size_t)key[j] * HASH_PRIME_01 % MAX_OBJ_COUNT;
|
||||
}
|
||||
|
||||
i = (i * HASH_PRIME_02) % MAX_OBJ_COUNT;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int32_t add_object_to_map(const char *key) {
|
||||
if (map.count + 1 == MAX_OBJ_COUNT) {
|
||||
#ifdef DEBUG_ENGINE
|
||||
printf("Map full\n");
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t index = hash_key(key);
|
||||
|
||||
if (map.keys[index]) {
|
||||
if (strcmp(map.keys[index], key) == 0) {
|
||||
#ifdef DEBUG_ENGINE
|
||||
printf("Key \"%s\" already exists\n", key);
|
||||
#endif /* DEBUG_ENGINE */
|
||||
} else {
|
||||
// TODO (Abdelrahman): Implement a way to resolve collisions between
|
||||
// multiple keys
|
||||
#ifdef DEBUG_ENGINE
|
||||
printf("Collision detected. Key \"%s\" collides with key \"%s\"\n", key,
|
||||
map.keys[index]);
|
||||
#endif /* DEBUG_ENGINE */
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
map.keys[index] = malloc(strlen(key) + 1);
|
||||
strcpy(map.keys[index], key);
|
||||
map.active_indices[map.count] = index;
|
||||
map.count += 1;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int32_t get_object_index(const char *key) {
|
||||
if (map.count == 0) {
|
||||
#ifdef DEBUG_ENGINE
|
||||
printf("Key \"%s\" doesn't exist\n", key);
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t index = hash_key(key);
|
||||
|
||||
if (!(map.keys[index]) || strcmp(map.keys[index], key) != 0) {
|
||||
#ifdef DEBUG_ENGINE
|
||||
printf("Key \"%s\" doesn't exist\n", key);
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int32_t)index;
|
||||
}
|
||||
|
||||
void delete_object_from_map(const char *key) {
|
||||
if (map.count == 0) {
|
||||
#ifdef DEBUG_ENGINE
|
||||
printf("Key \"%s\" doesn't exist\n", key);
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
size_t index = hash_key(key);
|
||||
|
||||
if (!(map.keys[index]) || strcmp(map.keys[index], key) != 0) {
|
||||
#ifdef DEBUG_ENGINE
|
||||
printf("Key \"%s\" doesn't exist\n", key);
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
free(map.keys[index]);
|
||||
map.keys[index] = NULL;
|
||||
|
||||
size_t packing_start_index = 0;
|
||||
|
||||
for (size_t i = 0; i < map.count; ++i) {
|
||||
if (map.active_indices[i] == index) {
|
||||
map.active_indices[i] = -1;
|
||||
packing_start_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the indices are packed in the array
|
||||
for (; packing_start_index < map.count; ++packing_start_index) {
|
||||
if (packing_start_index + 1 == MAX_OBJ_COUNT) {
|
||||
// Make sure we don't go out of bounds if we are at the last item
|
||||
map.active_indices[packing_start_index] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
map.active_indices[packing_start_index] =
|
||||
map.active_indices[packing_start_index + 1];
|
||||
}
|
||||
|
||||
map.count -= 1;
|
||||
}
|
||||
|
||||
void destroy_hashmap() {
|
||||
for (size_t i = 0; i < map.count; ++i) {
|
||||
size_t index = map.active_indices[i];
|
||||
|
||||
if (index == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
free(map.keys[index]);
|
||||
map.keys[index] = NULL;
|
||||
}
|
||||
|
||||
map.count = 0;
|
||||
|
||||
// Technically, memset shouldn't be used to set the values of any thing other
|
||||
// than byte arrays, but since it works in certain cases (e.g. 0 and -1) and
|
||||
// it is faster than doing a for loop, I am using it here to initialise the
|
||||
// active_indices array to -1
|
||||
memset(map.active_indices, -1, sizeof(map.active_indices));
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#include "ObjectStore.h"
|
||||
+2
-2
@@ -9,9 +9,9 @@
|
||||
#include <stdio.h>
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
typedef struct renderer {
|
||||
struct renderer {
|
||||
SDL_Renderer *SDL_base_renderer;
|
||||
} Renderer;
|
||||
};
|
||||
|
||||
Renderer *create_renderer() { return (Renderer *)malloc(sizeof(Renderer)); }
|
||||
|
||||
|
||||
Reference in new issue
Block a user