#include #include #include "common.h" #include "env.h" #include "hashtable.h" #include "value.h" struct env { hashtable_t table; struct env *parent; size_t refs; env_destroy_func destroy_func; }; #include "mempool.h" MEMPOOL_GENERATE(env, struct env, 64) #define ENV_TABLE_CAP (1 << 3) 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; } env_t env_create(env_t parent, env_destroy_func destroy_func) { // env_t env = malloc(sizeof(*env)); env_t env = env_mempool_allocate(); env->destroy_func = destroy_func; env->parent = parent; env->refs = 1; 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); env_mempool_free(env); } int env_insert(env_t env, char *key, value_t data, char **prevkey, value_t *prevdata) { return hashtable_insert(env->table, (void *)key, (void *)data, (void **)prevkey, (void **)prevdata); } int env_query(env_t env, char *key, value_t *data) { return hashtable_query(env->table, (void *)key, (void **)data); } env_t env_copy(env_t env) { if(env == ENV_EMPTY) return ENV_EMPTY; env->refs++; env_copy(env->parent); return env; } env_t env_parent(env_t env) { return env->parent; }