aboutsummaryrefslogtreecommitdiff
path: root/src/env.c
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2024-11-03 17:35:51 +0200
committerkartofen <mladenovnasko0@gmail.com>2024-11-03 17:35:51 +0200
commit0dd38d08551ac2fcff53eb604f6363f37b25aef9 (patch)
treeb9c29e5c0a3467cc6fbec72fb292e5414a8c7f4b /src/env.c
parent7edffea39a3d666098ebeca27ea398769e8b981b (diff)
env is just linked list now, uses much less memory
Diffstat (limited to 'src/env.c')
-rw-r--r--src/env.c151
1 files changed, 101 insertions, 50 deletions
diff --git a/src/env.c b/src/env.c
index b78b095..ee2e65e 100644
--- a/src/env.c
+++ b/src/env.c
@@ -4,102 +4,153 @@
#include "common.h"
#include "env.h"
-#include "hashtable.h"
+#include "list.h"
#include "value.h"
-struct env {
- hashtable_t table;
+#define HAS(v, flag) (((v) & (flag)) == (flag))
+struct env {
struct env *parent;
+ struct list_head *head;
+
size_t refs;
+ size_t circular_refs;
+};
- env_destroy_func destroy_func;
+struct env_kv {
+ char *key;
+ _value_t value;
+ struct list_head list;
+
+ int flags;
};
#include "mempool.h"
-MEMPOOL_GENERATE(env, struct env, 64)
-
-#define ENV_TABLE_CAP (1 << 3)
+MEMPOOL_GENERATE(env, struct env, 256)
+MEMPOOL_GENERATE(env_kv, struct env_kv, 1024)
-static unsigned long str_hash(char *str)
+static int equal(char *key1, char *key2)
{
- unsigned long hash = 5381;
- int c;
-
- while ((c = *str++))
- hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
-
- return hash;
+ return (strcmp(key1, key2) == 0);
}
-static size_t hash(void *key)
+static struct env_kv *env_kv_create(char *key, value_t value, int flags)
{
- return str_hash((char*)key);
+ struct env_kv *pair = env_kv_mempool_allocate();
+
+ pair->key = key;
+ pair->value = value;
+ LIST_EMPTY(&pair->list);
+ pair->flags = flags;
+
+ return pair;
}
-static bool equal(void *key1, void *key2)
+static void env_kv_destroy(struct env_kv *pair)
{
- if(strcmp((char *)key1, (char*)key2) == 0) {
- return true;
- }
+ if(HAS(pair->flags, ENV_KV_FREE_KEY))
+ free(pair->key);
- return false;
+ value_destroy(pair->value);
+ env_kv_mempool_free(pair);
}
-env_t env_create(env_t parent, env_destroy_func destroy_func)
+env_t env_create(env_t parent)
{
- // 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));
+ env->parent = env_copy(parent);
+ env->head = NULL;
+ env->refs = 0;
+ env->circular_refs = 0;
return env;
}
void env_destroy(env_t env)
{
- if(!env) return;
+ if(env == ENV_EMPTY) return;
- env->refs--;
- env_destroy(env->parent);
+ if(env->refs > env->circular_refs) {
+ env->refs--;
+ return;
+ }
- if(env->refs > 0) return;
+ list_for_each_safe(head, env->head) {
+ struct env_kv *p = list_entry(head, struct env_kv, list);
- hashtable_for_each_item(env->table, item, i) {
- env->destroy_func((char *)item->key, (value_t)item->data);
+ if(HAS(p->flags, ENV_KV_CIRCULAR_REF)) env->circular_refs--;
+ env_kv_destroy(p);
}
- hashtable_destroy(env->table);
- // free(env);
+ env_destroy(env->parent);
env_mempool_free(env);
}
-int env_insert(env_t env, char *key, value_t data,
- char **prevkey, value_t *prevdata)
+int env_insert(env_t env, char *key, _value_t value,
+ _value_t *prevval, int flags)
{
- return hashtable_insert(env->table, (void *)key, (void *)data, (void **)prevkey, (void **)prevdata);
+ if(env->head)
+ list_for_each_entry(struct env_kv, p, list, env->head) {
+ if(!equal(p->key, key)) continue;
+
+ env->circular_refs +=
+ (HAS(flags, ENV_KV_CIRCULAR_REF) -
+ HAS(p->flags, ENV_KV_CIRCULAR_REF));
+ p->flags = flags;
+
+ if(prevval) *prevval = p->value;
+ p->value = value;
+ return 0;
+ }
+
+ if(HAS(flags, ENV_KV_CIRCULAR_REF)) env->circular_refs++;
+
+ struct env_kv *pair = env_kv_create(key, value, flags);
+ if(env->head) list_append(&pair->list, env->head);
+ env->head = &pair->list;
+
+ return 0;
}
-int env_query(env_t env, char *key, value_t *data)
+int env_query(env_t env, char *key, _value_t *data)
{
- return hashtable_query(env->table, (void *)key, (void **)data);
+ struct env_kv *pair = NULL;
+
+ for(env_t e = env; e; e = e->parent) {
+ if(e->head == NULL) continue;
+ list_for_each_entry(struct env_kv, p, list, e->head) {
+ if(equal(p->key, key)) pair = p;
+ }
+
+ if(pair) break;
+ }
+
+ if(!pair) return 1;
+
+ *data = pair->value;
+ return 0;
}
env_t env_copy(env_t env)
{
- if(env == ENV_EMPTY) return ENV_EMPTY;
+ if(!env) return env;
env->refs++;
- env_copy(env->parent);
-
return env;
}
-env_t env_parent(env_t env)
-{
- return env->parent;
-}
+// void env_print(env_t env)
+// {
+// printf("REFS: %d\n", env->refs);
+// printf("CREFS: %d\n", env->circular_refs);
+// if(!env || !env->head) return;
+// list_for_each_entry(struct env_kv, pair, list, env->head) {
+// printf("ENTRY: %s %s\n", pair->key, pair->value);
+// }
+
+// if(env->parent) {
+// printf("---- PARENT ----\n");
+// env_print(env->parent);
+// printf("-- END PARENT --\n");
+// }
+// }