aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny van Kooten <dannyvankooten@users.noreply.github.com>2020-03-18 19:21:48 +0100
committerDanny van Kooten <dannyvankooten@users.noreply.github.com>2020-03-18 19:21:48 +0100
commit8d74fd5b0e5fc9f319a5b7d2e0716afcc312fd75 (patch)
treea6c195d183694304fbe238a68486aceea01d404a
parent82de777afb99aa4129abcb01da76bf62e7b45263 (diff)
downloadunja-8d74fd5b0e5fc9f319a5b7d2e0716afcc312fd75.tar.gz
unja-8d74fd5b0e5fc9f319a5b7d2e0716afcc312fd75.zip
clean-up environment in env_free(). add hashmap_walk function for visiting all values in a hashmap.
-rw-r--r--src/hashmap.c16
-rw-r--r--src/hashmap.h3
-rw-r--r--src/parser.c94
-rw-r--r--src/template.c21
-rw-r--r--tests/test_template.c7
5 files changed, 38 insertions, 103 deletions
diff --git a/src/hashmap.c b/src/hashmap.c
index f99ba4c..600a005 100644
--- a/src/hashmap.c
+++ b/src/hashmap.c
@@ -51,7 +51,7 @@ void *hashmap_get(struct hashmap *hm, char *key) {
int pos = HASH(key);
struct node *node = hm->buckets[pos];
while (node) {
- if (strcmp(node->key, key) == 0) {
+ if (node->key && strcmp(node->key, key) == 0) {
return node->value;
}
@@ -112,6 +112,20 @@ void *hashmap_remove(struct hashmap *hm, char *key) {
return NULL;
}
+void hashmap_walk(struct hashmap *hm, void (*fn)(void *value)) {
+ struct node *node;
+ struct node *next;
+
+ for (int i=0; i < HASHMAP_CAP; i++) {
+ node = hm->buckets[i];
+ while (node) {
+ next = node->next;
+ fn(node->value);
+ node = next;
+ }
+ }
+}
+
/* free hashmap related memory */
void hashmap_free(struct hashmap *hm) {
struct node *node;
diff --git a/src/hashmap.h b/src/hashmap.h
index be2b80e..dbb45da 100644
--- a/src/hashmap.h
+++ b/src/hashmap.h
@@ -9,4 +9,5 @@ void *hashmap_insert(struct hashmap *hm, char *key, void *value);
void *hashmap_get(struct hashmap *hm, char *key);
void *hashmap_resolve(struct hashmap *hm, char *key);
void *hashmap_remove(struct hashmap *hm, char *key);
-void hashmap_free(struct hashmap *hm); \ No newline at end of file
+void hashmap_free(struct hashmap *hm);
+void hashmap_walk(struct hashmap *hm, void (*fn)(void *value)); \ No newline at end of file
diff --git a/src/parser.c b/src/parser.c
deleted file mode 100644
index e61b1e5..0000000
--- a/src/parser.c
+++ /dev/null
@@ -1,94 +0,0 @@
-
-#include <stdlib.h>
-#include <string.h>
-
-struct text {
- char *str;
-};
-
-struct symbol {
- char *value;
-};
-
-struct expression {
- struct symbol symbol;
-};
-
-struct statement {
-
-};
-
-/* discard during parsing phase */
-struct comment {};
-
-
-enum node_type {
- NODE_EXPR,
- NODE_COMMENT,
- NODE_TEXT,
-};
-
-struct node {
- enum node_type type;
- union content {
- struct expression expr;
- struct comment comment;
- struct text text;
- } content;
-};
-
-struct ast {
- int size;
- int cap;
- struct node **nodes;
-};
-
-enum token_type {
- TOK_EOF,
- TOK_EXPR_OPEN,
- TOK_EXPR_CLOSE,
- TOK_COMMENT_OPEN,
- TOK_COMMENT_CLOSE,
- TOK_STMT_OPEN,
- TOK_STMT_CLOSE,
- TOK_MINUS,
- TOK_SYMBOL,
- TOK_TEXT,
-};
-
-struct token {
- enum token_type type;
- char *literal;
-};
-
-struct token gettoken(char *str) {
- struct token t;
- switch (str[0]) {
- case '{':
-
- break;
-
- case '}':
-
- break;
-
- case '\0':
- t.type = TOK_EOF;
- break;
- }
-
- return t;
-};
-
-struct ast* parse(char *str) {
- struct ast* ast = malloc(sizeof *ast);
- ast->size = 0;
- ast->cap = 64;
- ast->nodes = malloc(ast->cap * sizeof *ast->nodes);
-
- for (struct token t = gettoken(str); t.type != TOK_EOF; t= gettoken(str)) {
-
- }
-
- return ast;
-} \ No newline at end of file
diff --git a/src/template.c b/src/template.c
index 7ea4d05..a1b3ef4 100644
--- a/src/template.c
+++ b/src/template.c
@@ -3,6 +3,7 @@
#include <err.h>
#include <unistd.h>
#include <dirent.h>
+#include <string.h>
#include "vendor/mpc.h"
#include "template.h"
@@ -167,9 +168,13 @@ struct env *env_new(char *dirname) {
continue;
}
- char *name = de->d_name;
+ // copy template name as closedir free's it otherwise
+ char *name = malloc(strlen(de->d_name) + 1);
+ strcpy(name, de->d_name);
+
char *tmpl = read_file(name);
mpc_ast_t *ast = parse(tmpl);
+ free(tmpl);
struct template *t = malloc(sizeof *t);
t->ast = ast;
@@ -182,14 +187,24 @@ struct env *env_new(char *dirname) {
}
hashmap_insert(env->templates, name, t);
+
}
closedir(dr);
return env;
}
+void template_free(void *v) {
+ struct template *t = (struct template *)v;
+ hashmap_free(t->blocks);
+ mpc_ast_delete(t->ast);
+ free(t->name);
+ free(t);
+}
+
void env_free(struct env *env) {
- // TODO: Free template strings
+ hashmap_walk(env->templates, template_free);
+ hashmap_free(env->templates);
free(env);
}
@@ -215,7 +230,7 @@ char *read_file(char *filename) {
}
char *trim_trailing_whitespace(char *str) {
- for (int i=strlen(str)-1; isspace(str[i]); i--) {
+ for (int i=strlen(str)-1; i >= 0 && isspace(str[i]); i--) {
str[i] = '\0';
}
return str;
diff --git a/tests/test_template.c b/tests/test_template.c
index 34022fa..b427f7c 100644
--- a/tests/test_template.c
+++ b/tests/test_template.c
@@ -182,14 +182,13 @@ TEST(for_block_whitespace) {
TEST(var_dot_notation) {
char *input = "Hello {{user.name}}!";
- struct hashmap *user = hashmap_new();
- hashmap_insert(user, "name", "Danny");
-
struct hashmap *ctx = hashmap_new();
+ struct hashmap *user = hashmap_new();
+ hashmap_insert(user, "name", "Danny");
hashmap_insert(ctx, "user", user);
-
char *output = template_string(input, ctx);
assert_str(output, "Hello Danny!");
+ hashmap_free(user);
hashmap_free(ctx);
free(output);
}