diff options
author | kartofen <mladenovnasko0@gmail.com> | 2024-08-23 19:55:13 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2024-08-23 19:55:13 +0300 |
commit | 68a62ad356603d64d537e231f06b5d9445e79abe (patch) | |
tree | 3682d6b607fed96eafaf7e218d85a03fbc71d914 /src/env.c |
usefull commit message
Diffstat (limited to 'src/env.c')
-rw-r--r-- | src/env.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/env.c b/src/env.c new file mode 100644 index 0000000..1aa452b --- /dev/null +++ b/src/env.c @@ -0,0 +1,78 @@ +#include <stdlib.h> +#include <string.h> + +#include "common.h" +#include "env.h" +#include "hashtable.h" + +#define ENV_TABLE_CAP (1 << 8) + +static unsigned long str_hash(char *str) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +static size_t hash(void *key) +{ + return str_hash((char*)key); +} + +static bool equal(void *key1, void *key2) +{ + if(strcmp((char *)key1, (char*)key2) == 0) { + return true; + } + + return false; +} + +static void env_add_ref(env_t env); + +env_t env_create(env_t parent, env_destroy_func destroy_func) +{ + env_t env = malloc(sizeof(*env)); + env->destroy_func = destroy_func; + env->parent = parent; + env->refs = 0; + + env_add_ref(env); + + ERR_Z(env->table = hashtable_create(ENV_TABLE_CAP, hash, equal), + env_destroy(env)); + + return env; +} + +void env_destroy(env_t env) +{ + if(!env) return; + + env->refs--; + env_destroy(env->parent); + + if(env->refs > 0) return; + + + hashtable_for_each_item(env->table, item, i) { + env->destroy_func((char *)item->key, (value_t)item->data); + } + + hashtable_destroy(env->table); + free(env); +} + + +static void env_add_ref(env_t env) +{ + env->refs++; + + if(env->parent) { + env_add_ref(env->parent); + } +} |