From 2d1d7bd16100eb9d702ef67897b2f62a972d6426 Mon Sep 17 00:00:00 2001 From: Danny van Kooten Date: Thu, 12 Mar 2020 17:36:00 +0100 Subject: add hashmap_resolve which handles dot notation --- Makefile | 2 +- src/hashmap.c | 26 +++++++++++++++++++++++++- src/hashmap.h | 3 ++- src/template.c | 32 +++++++++----------------------- tests/test_hashmap.c | 14 ++++++++++++++ 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 : /[a-zA-Z_.]+/ ;" " var_open : /\{{2} ?/ ;" " var_close : / ?}{2}/ ;" - " var : ;" + " var : ;" " block_open: /\{\% ?/ ;" " block_close: / ?\%}/ ;" - " for : \"for \" \" in \" \"endfor\" ;" + " for : \"for \" \" in \" \"endfor\" ;" " text : /[^{][^{%]*/ ;" " content : | | ;" " body : * ;" @@ -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 -- cgit v1.2.3