aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny van Kooten <dannyvankooten@users.noreply.github.com>2020-03-12 17:36:00 +0100
committerDanny van Kooten <dannyvankooten@users.noreply.github.com>2020-03-12 17:36:00 +0100
commit2d1d7bd16100eb9d702ef67897b2f62a972d6426 (patch)
tree249a995c033e17b87c8a633867e2e5de531c9633
parent9acd91d41469ed4024e3a8aa85ef1fb2eec909bd (diff)
downloadunja-2d1d7bd16100eb9d702ef67897b2f62a972d6426.tar.gz
unja-2d1d7bd16100eb9d702ef67897b2f62a972d6426.zip
add hashmap_resolve which handles dot notation
-rw-r--r--Makefile2
-rw-r--r--src/hashmap.c26
-rw-r--r--src/hashmap.h3
-rw-r--r--src/template.c32
-rw-r--r--tests/test_hashmap.c14
5 files changed, 51 insertions, 26 deletions
diff --git a/Makefile b/Makefile
index 56f1d9f..b5fca94 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS= -g -Wall -std=c11 -I.
+override CFLAGS+= -g -Wall -std=c11 -I.
LIBS=
TESTFLAGS= $(CFLAGS) -Isrc/
diff --git a/src/hashmap.c b/src/hashmap.c
index b56b364..9f36a58 100644
--- a/src/hashmap.c
+++ b/src/hashmap.c
@@ -55,8 +55,32 @@ void *hashmap_get(struct hashmap *hm, char *key) {
return NULL;
}
-void hashmap_remove(char *key) {
+void *hashmap_resolve(struct hashmap *hm, char *key) {
+ char tmp_key[64];
+ int i = 0;
+ int j = 0;
+
+ while (1) {
+ for (j=0; key[i] != '.' && key[i] != '\0'; i++, j++) {
+ tmp_key[j] = key[i];
+ }
+ tmp_key[j] = '\0';
+ hm = hashmap_get(hm, tmp_key);
+
+ // stop if we read key to end of string
+ if (key[i] == '\0') {
+ break;
+ }
+
+ // otherwise, continue reading keys
+ i++;
+ }
+ return hm;
+}
+
+void hashmap_remove(char *key) {
+ // TODO: Implement this
}
void hashmap_free(struct hashmap *hm) {
diff --git a/src/hashmap.h b/src/hashmap.h
index 93297af..369f594 100644
--- a/src/hashmap.h
+++ b/src/hashmap.h
@@ -8,4 +8,5 @@ void hashmap_insert(struct hashmap *hm, char *key, void *value);
void *hashmap_get(struct hashmap *hm, char *key);
void hashmap_remove(char *key);
struct hashmap *hashmap_new();
-void hashmap_free(struct hashmap *hm); \ No newline at end of file
+void hashmap_free(struct hashmap *hm);
+void *hashmap_resolve(struct hashmap *hm, char *key); \ No newline at end of file
diff --git a/src/template.c b/src/template.c
index db0128d..f945b7e 100644
--- a/src/template.c
+++ b/src/template.c
@@ -29,23 +29,9 @@ char *read_file(char *filename) {
int eval(char *dest, mpc_ast_t* t, struct hashmap *ctx) {
if (strstr(t->tag, "content|var")) {
char *value = NULL;
-
- // TODO: Optimize this so we can use it for 1..n keys
- if (t->children[1]->children_num == 0) {
- char *key = t->children[1]->contents;
- value = hashmap_get(ctx, key);
- } else {
- char *key = t->children[1]->children[0]->contents;
- ctx = hashmap_get(ctx, key);
- if (ctx == NULL) {
- // TODO: Handle unexisting keys
- return 1;
- }
-
- char *subkey = t->children[1]->children[2]->contents;
- value = hashmap_get(ctx, subkey);
- }
-
+ char *key = t->children[1]->contents;
+ value = hashmap_resolve(ctx, key);
+
// TODO: Handle unexisting keys
if (value == NULL) {
return 1;
@@ -56,9 +42,8 @@ int eval(char *dest, mpc_ast_t* t, struct hashmap *ctx) {
if (strstr(t->tag, "content|for")) {
char *tmp_key = t->children[2]->contents;
- // TODO: Handle dot notation here.
char *iterator_key = t->children[4]->contents;
- struct vector *list = hashmap_get(ctx, iterator_key);
+ struct vector *list = hashmap_resolve(ctx, iterator_key);
for (int i=0; i < list->size; i++) {
hashmap_insert(ctx, tmp_key, list->values[i]);
eval(dest, t->children[6], ctx);
@@ -92,14 +77,13 @@ mpc_parser_t *parser_init() {
mpc_parser_t *Content = mpc_new("content");
mpc_parser_t *Template = mpc_new("template");
mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE,
- " symbol : /[a-zA-Z_]+/ ;"
- " symbols : <symbol>\".\"?<symbol>? ;"
+ " symbol : /[a-zA-Z_.]+/ ;"
" var_open : /\{{2} ?/ ;"
" var_close : / ?}{2}/ ;"
- " var : <var_open> <symbols> <var_close> ;"
+ " var : <var_open> <symbol> <var_close> ;"
" block_open: /\{\% ?/ ;"
" block_close: / ?\%}/ ;"
- " for : <block_open> \"for \" <symbol> \" in \" <symbols> <block_close> <body> <block_open> \"endfor\" <block_close> ;"
+ " for : <block_open> \"for \" <symbol> \" in \" <symbol> <block_close> <body> <block_open> \"endfor\" <block_close> ;"
" text : /[^{][^{%]*/ ;"
" content : <var> | <for> | <text>;"
" body : <content>* ;"
@@ -118,10 +102,12 @@ char *template(char *tmpl, struct hashmap *ctx) {
return NULL;
}
+ #if DEBUG
printf("Template: %s\n", tmpl);
printf("AST: ");
mpc_ast_print(r.output);
printf("\n");
+ #endif
// FIXME: Allocate precisely
char *output = malloc(strlen(tmpl) * 2);
diff --git a/tests/test_hashmap.c b/tests/test_hashmap.c
index 68b8d0c..d78f768 100644
--- a/tests/test_hashmap.c
+++ b/tests/test_hashmap.c
@@ -15,4 +15,18 @@ TEST(hashmap) {
hashmap_free(hm);
}
+
+TEST(dot_notation) {
+
+ struct hashmap *user = hashmap_new();
+ hashmap_insert(user, "name", "Danny");
+ struct hashmap *hm = hashmap_new();
+ hashmap_insert(hm, "user", user);
+ char *value = (char *) hashmap_resolve(hm, "user.name");
+ assert(value != NULL, "expected value, got NULL");
+ assert(strcmp(value, "Danny") == 0, "expected %s, got %s", "Danny", value);
+
+ hashmap_free(hm);
+}
+
END_TESTS \ No newline at end of file