From a17cb85b9288fc5a4285afd05c60f888eedc4d0f Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Thu, 30 Mar 2017 01:33:19 +0500 Subject: [PATCH] Added hashmaps --- orgfile.org | 6 +- src/array.h | 2 +- src/config_vars.c | 33 ++++++ src/config_vars.h | 13 +++ src/hashmap.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++ src/hashmap.h | 39 +++++++ src/linmath.c | 4 +- src/linmath.h | 4 +- src/scene.c | 1 - src/variant.c | 79 ++++++++++----- src/variant.h | 14 ++- 11 files changed, 410 insertions(+), 38 deletions(-) create mode 100644 src/config_vars.c create mode 100644 src/config_vars.h create mode 100644 src/hashmap.c create mode 100644 src/hashmap.h diff --git a/orgfile.org b/orgfile.org index de50e5d..33f5948 100644 --- a/orgfile.org +++ b/orgfile.org @@ -23,7 +23,7 @@ diffuse_color: 1 0 0 1 diffuse_texture: "checkered.tga" specular: 0.55 -*** Configuration Variables a.k.a cvars +*** Configuration Variables a.k.a cfg-vars // Comment render_width: 1024 render_height: 1024 @@ -37,6 +37,8 @@ msaa_levels: 8 *** Keybindings *** Level/Scene +*** Materials +*** Mesh/Geometry * Things TODO ** DONE Input - State "DONE" from "TODO" [2015-07-02 Thu 01:24] @@ -166,7 +168,7 @@ x Font atlas proper cleanup - Keybindings in config - Log output on every run. ** TODO Do input maps really need to be queried by their string names? -** TODO Reloading shaders? +** TODO Reloading all the things! (textures/shaders/models/settings/entities etc) ** TODO Separate Debug/Editor camera from the active camera in the scene that can be switched to at any time ** DONE Live data views in editor - State "DONE" from "TODO" [2017-03-22 Wed 02:14] diff --git a/src/array.h b/src/array.h index a5105c4..62cdaa2 100644 --- a/src/array.h +++ b/src/array.h @@ -6,7 +6,7 @@ /* Private use */ void* array_new_(size_t object_size, int capacity); void* array_grow_(void** array); -int array_reset_(void** array, int length); // Resize to length objects whose data is unspecified +int array_reset_(void** array, int length); // Resize to length objects whose data is unspecified, previous data is freed int array_pop_(void** array); // Remove object with highest index int array_remove_at_(void** array, int index); void array_match_len_cap_(void** array); diff --git a/src/config_vars.c b/src/config_vars.c new file mode 100644 index 0000000..1b95be4 --- /dev/null +++ b/src/config_vars.c @@ -0,0 +1,33 @@ +#include "config_vars.h" +#include "string_utils.h" +#include "variant.h" +#include "hashmap.h" + +#include + +static struct Hashmap* cvars = NULL; + +void config_vars_init(void) +{ + cvars = hashmap_new(); +} + +void config_vars_cleanup(void) +{ + hashmap_free(cvars); +} + +struct Hashmap* config_vars_get(void) +{ + return cvars; +} + +int config_vars_load(const char* filename) +{ + +} + +void config_vars_save(const char* filename) +{ + +} diff --git a/src/config_vars.h b/src/config_vars.h new file mode 100644 index 0000000..5c64575 --- /dev/null +++ b/src/config_vars.h @@ -0,0 +1,13 @@ +#ifndef CONFIG_VARS_H +#define CONFIG_VARS_H + +struct Hashmap; + +void config_vars_init(void); +void config_vars_cleanup(void); +int config_vars_load(const char* filename); +void config_vars_save(const char* filename); +struct Hashmap* config_vars_get(void); + + +#endif diff --git a/src/hashmap.c b/src/hashmap.c new file mode 100644 index 0000000..e430ebd --- /dev/null +++ b/src/hashmap.c @@ -0,0 +1,253 @@ +#include "hashmap.h" +#include "array.h" +#include "variant.h" +#include "string_utils.h" + +#include +#include + +#define HASH_MAP_NUM_BUCKETS 10 +#define HASH_MAX_KEY_LEN 128 + +struct Hashmap_Entry +{ + char* key; + struct Variant value; +}; + +struct Hashmap +{ + struct Hashmap_Entry* buckets[HASH_MAP_NUM_BUCKETS]; +}; + +static int hashmap_generate_hash(const char* key); +static struct Hashmap_Entry* hashmap_entry_new(struct Hashmap* hashmap, const char* key); + +static struct Hashmap_Entry* hashmap_entry_new(struct Hashmap* hashmap, const char* key) +{ + int index = hashmap_generate_hash(key); + struct Hashmap_Entry* new_entry = NULL; + for(int i = 0; i < array_len(hashmap->buckets[index]); i++) /* Look for duplicates and over-write if found */ + { + if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) + { + new_entry = &hashmap->buckets[index][i]; + if(new_entry->key) free(new_entry->key); + break; + } + } + if(!new_entry) new_entry = array_grow(hashmap->buckets[index], struct Hashmap_Entry); + new_entry->key = str_new(key); + return new_entry; +} + +int hashmap_generate_hash(const char* key) +{ + int index = -1; + const int multiplier = 51; + for(int i = 0; i < (int)strlen(key); i++) + index = index * multiplier + key[i]; + return index % HASH_MAP_NUM_BUCKETS; +} + +struct Hashmap* hashmap_new(void) +{ + struct Hashmap* hashmap = malloc(sizeof(*hashmap)); + if(!hashmap) + return NULL; + for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) + hashmap->buckets[i] = array_new(struct Hashmap_Entry); + return hashmap; +} + +void hashmap_free(struct Hashmap* hashmap) +{ + if(!hashmap) return; + for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) + { + for(int j = 0; j < array_len(hashmap->buckets[j]); j++) + { + struct Hashmap_Entry* entry = &hashmap->buckets[i][j]; + if(entry->key) + { + free(entry->key); + entry->key = NULL; + } + variant_free(&entry->value); + } + } + free(hashmap); + hashmap = NULL; +} + +void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value) +{ + if(!hashmap || !key || !value) return; + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_copy(&new_entry->value, value); +} + +const struct Variant* hashmap_value_get(struct Hashmap* hashmap, const char* key) +{ + if(!hashmap || !key) return NULL; + struct Variant* value = NULL; + int index = hashmap_generate_hash(key); + for(int i = 0; i < array_len(hashmap->buckets[index]); i++) + { + if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) + { + value = &hashmap->buckets[index][i].value; + break; + } + } + return value; +} + +void hashmap_value_remove(struct Hashmap* hashmap, const char* key) +{ + if(!hashmap || !key) return; + int index = hashmap_generate_hash(key); + int index_to_remove = -1; + for(int i = 0; i < array_len(hashmap->buckets[index]); i++) + { + if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) + { + index_to_remove = i; + break; + } + } + if(index_to_remove != -1) array_remove_at(hashmap->buckets[index], index_to_remove); +} + + +void hashmap_float_set(struct Hashmap* hashmap, const char* key, float value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_float(&new_entry->value, value); +} + +void hashmap_int_set(struct Hashmap* hashmap, const char* key, int value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_int(&new_entry->value, value); +} + +void hashmap_double_set(struct Hashmap* hashmap, const char* key, double value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_double(&new_entry->value, value); +} + +void hashmap_bool_set(struct Hashmap* hashmap, const char* key, int value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_bool(&new_entry->value, value); +} + +void hashmap_vec2_set(struct Hashmap* hashmap, const char* key, const vec2* value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_vec2(&new_entry->value, value); +} + +void hashmap_vec3_set(struct Hashmap* hashmap, const char* key, const vec3* value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_vec3(&new_entry->value, value); +} + +void hashmap_vec4_set(struct Hashmap* hashmap, const char* key, const vec4* value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_vec4(&new_entry->value, value); +} + +void hashmap_quat_set(struct Hashmap* hashmap, const char* key, const quat* value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_quat(&new_entry->value, value); +} + +void hashmap_mat4_set(struct Hashmap* hashmap, const char* key, const mat4* value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_mat4(&new_entry->value, value); +} + +void hashmap_str_set(struct Hashmap* hashmap, const char* key, const char* value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_str(&new_entry->value, value); +} + +void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value) +{ + struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); + variant_assign_ptr(&new_entry->value, value); +} + +float hashmap_float_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_float; +} + +int hashmap_int_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_int; +} + +double hashmap_double_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_double; +} + +int hashmap_get_bool(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_bool; +} + +vec2 hashmap_vec2_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_vec2; +} + +vec3 hashmap_vec3_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_vec3; +} + +vec4 hashmap_vec4_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_vec4; +} + +quat hashmap_quat_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_quat; +} + +const mat4* hashmap_mat4_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_mat4; +} + +const char* hashmap_str_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_str; +} + +void* hashmap_ptr_get(struct Hashmap* hashmap, const char* key) +{ + const struct Variant* variant = hashmap_value_get(hashmap, key); + return variant->val_voidptr; +} diff --git a/src/hashmap.h b/src/hashmap.h new file mode 100644 index 0000000..23a6da7 --- /dev/null +++ b/src/hashmap.h @@ -0,0 +1,39 @@ +#ifndef HASHMAP_H +#define HASHMAP_H + +#include "linmath.h" + +struct Hashmap; +struct Variant; + +struct Hashmap* hashmap_new(void); +void hashmap_free(struct Hashmap* hashmap); +void hashmap_value_remove(struct Hashmap* hashmap, const char* key); +void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value); +const struct Variant* hashmap_value_get(struct Hashmap* hashmap, const char* key); + +void hashmap_float_set(struct Hashmap* hashmap, const char* key, float value); +void hashmap_int_set(struct Hashmap* hashmap, const char* key, int value); +void hashmap_double_set(struct Hashmap* hashmap, const char* key, double value); +void hashmap_bool_set(struct Hashmap* hashmap, const char* key, int value); +void hashmap_vec2_set(struct Hashmap* hashmap, const char* key, const vec2* value); +void hashmap_vec3_set(struct Hashmap* hashmap, const char* key, const vec3* value); +void hashmap_vec4_set(struct Hashmap* hashmap, const char* key, const vec4* value); +void hashmap_quat_set(struct Hashmap* hashmap, const char* key, const quat* value); +void hashmap_mat4_set(struct Hashmap* hashmap, const char* key, const mat4* value); +void hashmap_str_set(struct Hashmap* hashmap, const char* key, const char* value); +void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value); + +float hashmap_float_get(struct Hashmap* hashmap, const char* key); +int hashmap_int_get(struct Hashmap* hashmap, const char* key); +double hashmap_double_get(struct Hashmap* hashmap, const char* key); +int hashmap_get_bool(struct Hashmap* hashmap, const char* key); +vec2 hashmap_vec2_get(struct Hashmap* hashmap, const char* key); +vec3 hashmap_vec3_get(struct Hashmap* hashmap, const char* key); +vec4 hashmap_vec4_get(struct Hashmap* hashmap, const char* key); +quat hashmap_quat_get(struct Hashmap* hashmap, const char* key); +const mat4* hashmap_mat4_get(struct Hashmap* hashmap, const char* key); +const char* hashmap_str_get(struct Hashmap* hashmap, const char* key); +void* hashmap_ptr_get(struct Hashmap* hashmap, const char* key); + +#endif diff --git a/src/linmath.c b/src/linmath.c index bee1c47..768dae1 100644 --- a/src/linmath.c +++ b/src/linmath.c @@ -31,7 +31,7 @@ void vec2_sub(vec2* res, vec2* v1, vec2* v2) res->y = v1->y - v2->y; } -void vec2_assign(vec2* res, vec2* val) +void vec2_assign(vec2* res, const vec2* val) { res->x = val->x; res->y = val->y; @@ -221,7 +221,7 @@ void vec4_sub(vec4* res, vec4* v1, vec4* v4) res->w = v1->w - v4->w; } -void vec4_assign(vec4* res, vec4* val) +void vec4_assign(vec4* res, const vec4* val) { res->x = val->x; res->y = val->y; diff --git a/src/linmath.h b/src/linmath.h index 432db1d..d9c065e 100644 --- a/src/linmath.h +++ b/src/linmath.h @@ -62,7 +62,7 @@ extern const vec3 UNIT_Z_NEG; void vec2_fill(vec2* res, float x, float y); void vec2_add(vec2* res, vec2* v1, vec2* v2); void vec2_sub(vec2* res, vec2* v1, vec2* v2); -void vec2_assign(vec2* res, vec2* val); +void vec2_assign(vec2* res, const vec2* val); void vec2_mul(vec2* res, vec2* v1, vec2* v2); float vec2_len(vec2* val);void vec2_norm(vec2* res, vec2* val); @@ -91,7 +91,7 @@ void vec4_mul_mat4(vec4* res, vec4* val, mat4* mat); void vec4_mul(vec4* res, vec4* v1, vec4* v4); void vec4_norm(vec4* res, vec4* val); float vec4_len(vec4* val); -void vec4_assign(vec4* res, vec4* val); +void vec4_assign(vec4* res, const vec4* val); void vec4_sub(vec4* res, vec4* v1, vec4* v4); void vec4_add(vec4* res, vec4* v1, vec4* v4); diff --git a/src/scene.c b/src/scene.c index de8f86c..a164f2b 100644 --- a/src/scene.c +++ b/src/scene.c @@ -14,7 +14,6 @@ void scene_init(void) /* Add root node to scene */ struct Entity* root = entity_create("ROOT", NULL); root_node = root->node; - log_message("Root Parent : %d", root->parent); } struct Entity* scene_add_new(const char* name, const char* tag) diff --git a/src/variant.c b/src/variant.c index 0e0d697..83826d2 100644 --- a/src/variant.c +++ b/src/variant.c @@ -6,23 +6,10 @@ void variant_init_empty(struct Variant* variant) { - variant->type = VT_NONE; + variant->type = VT_NONE; variant->val_voidptr = NULL; -} - -void variant_assign_mat4(struct Variant* variant, const mat4* source) -{ - if(variant->type != VT_MAT4) variant_free(variant); - if(!variant->val_voidptr) - { - variant->val_voidptr = malloc(sizeof(mat4)); - if(!variant->val_voidptr) - { - log_error("variant_init_mat4", "Out of memory"); - return; - } - } - mat4_assign(variant->val_voidptr, source); + variant->val_mat4 = NULL; + variant->val_str = NULL; } void variant_assign_float(struct Variant* variant, float value) @@ -49,8 +36,8 @@ void variant_assign_double(struct Variant* variant, double value) void variant_assign_bool(struct Variant* variant, int value) { if(variant->type != VT_BOOL) variant_free(variant); - variant->type = VT_BOOL; - variant->val_int = value; + variant->type = VT_BOOL; + variant->val_bool = value; } void variant_assign_str(struct Variant* variant, const char* value) @@ -60,43 +47,62 @@ void variant_assign_str(struct Variant* variant, const char* value) variant->val_str = str_new(value); } -void variant_assign_vec2(struct Variant* variant, vec2* value) +void variant_assign_vec2(struct Variant* variant, const vec2* value) { if(variant->type != VT_VEC2) variant_free(variant); variant->type = VT_VEC2; vec2_assign(&variant->val_vec2, value); } -void variant_assign_vec3(struct Variant* variant, vec3* value) +void variant_assign_vec3(struct Variant* variant, const vec3* value) { if(variant->type != VT_VEC3) variant_free(variant); variant->type = VT_VEC3; vec3_assign(&variant->val_vec3, value); } -void variant_assign_vec4(struct Variant* variant, vec4* value) +void variant_assign_vec4(struct Variant* variant, const vec4* value) { if(variant->type != VT_VEC4) variant_free(variant); variant->type = VT_VEC4; vec4_assign(&variant->val_vec4, value); } -void variant_assign_quat(struct Variant* variant, quat* value) +void variant_assign_quat(struct Variant* variant, const quat* value) { if(variant->type != VT_QUAT) variant_free(variant); variant->type = VT_QUAT; quat_assign(&variant->val_quat, value); } +void variant_assign_mat4(struct Variant* variant, const mat4* source) +{ + if(variant->type != VT_MAT4) variant_free(variant); + variant->val_mat4 = malloc(sizeof(mat4)); + if(!variant->val_mat4) + { + log_error("variant_init_mat4", "Out of memory"); + return; + } + mat4_assign(variant->val_voidptr, source); +} + +void variant_assign_ptr(struct Variant* variant, void* source) +{ + if(variant->type != VT_VOID_PTR) variant_free(variant); + variant->type = VT_VOID_PTR; + variant->val_voidptr = source; +} + void variant_free(struct Variant* variant) { switch(variant->type) { case VT_MAT4: - if(variant->val_voidptr) + if(variant->val_mat4) { - free(variant->val_voidptr); - variant->val_voidptr = NULL; + free(variant->val_mat4); + variant->val_mat4 = NULL; } break; case VT_STR: @@ -106,8 +112,31 @@ void variant_free(struct Variant* variant) variant->val_str = NULL; } break; + case VT_VOID_PTR: + variant->val_voidptr = NULL; + break; default: /* Nothing to be done for the rest*/ break; }; variant->type = VT_NONE; } + +void variant_copy(struct Variant* to, const struct Variant* from) +{ + to->type = from->type; + switch(from->type) + { + case VT_BOOL: variant_assign_bool(to, from->val_int); break; + case VT_INT: variant_assign_int(to, from->val_bool); break; + case VT_FLOAT: variant_assign_float(to, from->val_float); break; + case VT_DOUBLE: variant_assign_double(to, from->val_double); break; + case VT_VEC2: variant_assign_vec2(to, &from->val_vec2); break; + case VT_VEC3: variant_assign_vec3(to, &from->val_vec3); break; + case VT_VEC4: variant_assign_vec4(to, &from->val_vec4); break; + case VT_QUAT: variant_assign_quat(to, &from->val_quat); break; + case VT_MAT4: variant_assign_mat4(to, from->val_mat4); break; + case VT_STR: variant_assign_str(to, from->val_str); break; + default: /* Nothing to be done for the rest*/ + break; + } +} diff --git a/src/variant.h b/src/variant.h index 75752ab..e3e75de 100644 --- a/src/variant.h +++ b/src/variant.h @@ -26,6 +26,7 @@ struct Variant union { int val_int; + int val_bool; float val_float; double val_double; char* val_str; @@ -33,21 +34,24 @@ struct Variant vec3 val_vec3; vec4 val_vec4; quat val_quat; + mat4* val_mat4; void* val_voidptr; }; }; void variant_init_empty(struct Variant* variant); -void variant_assign_mat4(struct Variant* variant, const mat4* source); void variant_assign_float(struct Variant* variant, float value); void variant_assign_int(struct Variant* variant, int value); void variant_assign_double(struct Variant* variant, double value); void variant_assign_bool(struct Variant* variant, int value); void variant_assign_str(struct Variant* variant, const char* value); -void variant_assign_vec2(struct Variant* variant, vec2* value); -void variant_assign_vec3(struct Variant* variant, vec3* value); -void variant_assign_vec4(struct Variant* variant, vec4* value); -void variant_assign_quat(struct Variant* variant, quat* value); +void variant_assign_vec2(struct Variant* variant, const vec2* value); +void variant_assign_vec3(struct Variant* variant, const vec3* value); +void variant_assign_vec4(struct Variant* variant, const vec4* value); +void variant_assign_quat(struct Variant* variant, const quat* value); +void variant_assign_mat4(struct Variant* variant, const mat4* source); +void variant_assign_ptr(struct Variant* variant, void* source); +void variant_copy(struct Variant* to, const struct Variant* from); void variant_free(struct Variant* variant); #endif