From a89f68f2d194d87b5e0eeeab94bfd2827059f7bb Mon Sep 17 00:00:00 2001 From: Timo Lassmann Date: Thu, 3 Oct 2024 16:57:31 +0200 Subject: [PATCH] Fixed template --- src/template/template.c | 357 +---------------------------------- src/template/template.h | 24 +-- tests/utests/unit_template.c | 174 ++++++++++++++++- 3 files changed, 169 insertions(+), 386 deletions(-) diff --git a/src/template/template.c b/src/template/template.c index 03eabf3..db36a55 100644 --- a/src/template/template.c +++ b/src/template/template.c @@ -115,6 +115,7 @@ int tld_template_rename_var(tld_template_hash *h, char *key, char* new_key) { while (entry) { if (strcmp(TLD_STR(entry->key), key) == 0) { tld_strbuf* tmp = NULL; + tld_strbuf_alloc(&tmp, 64); // Remove the old key from the hash table tld_strbuf_copy(tmp, entry->value); @@ -227,13 +228,6 @@ typedef struct { char error[MAX_ERROR_MSG]; } Parser; -/* tld_internal int find(tld_strbuf *txt, int offset, tld_strbuf *delim,int*start_pos,int* end_pos); */ -/* tld_internal int find_open(tld_strbuf *txt,int offset, tld_strbuf *delim, int*pos); */ -/* tld_internal int find_end(tld_strbuf *txt,int offset, tld_strbuf* delim, int*pos); */ - -/* tld_internal int tld_template_allocate(tld_template_map **map, int n); */ -/* tld_internal int tld_template_resize(tld_template_map *m); */ - tld_internal int parse_text(Parser *parser, template_node **node); tld_internal int parse_tag(Parser *parser, template_node **node); @@ -402,73 +396,6 @@ int parse_tag(Parser *parser, template_node **node) } } - -/* node *parse_template(Parser *parser) { */ -/* Node *root = create_node(NODE_ROOT, NULL); */ -/* Node *current = root; */ -/* Node *stack[MAX_CHILDREN]; */ -/* int stack_top = 0; */ - -/* while (!is_end_of_input(parser)) { */ -/* if (strncmp(parser->input + parser->position, "{{", 2) == 0) { */ -/* Node *tag_node = parse_tag(parser); */ -/* if(tag_node){ */ -/* switch(tag_node->type){ */ -/* case NODE_IF: */ -/* add_child(current, tag_node); */ -/* if (stack_top >= MAX_CHILDREN) { */ -/* snprintf(parser->error, MAX_ERROR_MSG, "Nesting too deep"); */ -/* return root; */ -/* } */ -/* stack[stack_top++] = current; */ -/* current = tag_node; */ -/* break; */ -/* case NODE_ELSE: */ -/* if(stack_top > 0 && current->type == NODE_IF){ */ -/* current = stack[stack_top - 1]; */ -/* add_child(current, tag_node); */ -/* current = tag_node; */ -/* }else{ */ -/* snprintf(parser->error, MAX_ERROR_MSG, "ELSE without matching IF"); */ -/* free_node(tag_node); */ -/* } */ -/* break; */ -/* case NODE_ENDIF: */ -/* if(stack_top > 0){ */ -/* current = stack[--stack_top]; */ -/* free_node(tag_node); */ -/* }else{ */ -/* snprintf(parser->error, MAX_ERROR_MSG, "ENDIF without matching IF"); */ -/* free_node(tag_node); */ -/* } */ -/* break; */ -/* default: */ -/* add_child(current, tag_node); */ -/* } */ -/* }else if(parser->error[0] == '\0'){ */ -/* snprintf(parser->error, MAX_ERROR_MSG, "Failed to parse tag"); */ -/* } */ -/* }else{ */ -/* Node *text_node = parse_text(parser); */ -/* if(text_node){ */ -/* add_child(current, text_node); */ -/* }else if(parser->error[0] == '\0'){ */ -/* snprintf(parser->error, MAX_ERROR_MSG, "Failed to parse text"); */ -/* } */ -/* } */ - -/* if(parser->error[0] != '\0'){ */ -/* break; */ -/* } */ -/* } */ - -/* if(stack_top > 0){ */ -/* snprintf(parser->error, MAX_ERROR_MSG, "Unclosed IF statement"); */ -/* } */ - -/* return root; */ -/* } */ - void print_tree(template_node *node, int depth) { for (int i = 0; i < depth; i++) { printf(" "); @@ -615,292 +542,10 @@ int tld_template_apply(tld_strbuf *txt, tld_template_hash *hash) return FAIL; } - -/* int tld_template_apply2(tld_strbuf *txt, tld_template_map *map) */ -/* { */ -/* /\* loop until there are no more valid reps *\/ */ -/* tld_strbuf* out = NULL; */ -/* tld_strbuf* pattern = NULL; */ -/* int offset = 0; */ -/* int start; */ -/* int stop; */ - -/* int read_header = 0; */ -/* /\* int substitutions_made = 0; *\/ */ - -/* map->status = TEMPLATE_OK; */ -/* map->n_rep = 0; */ - -/* RUN(tld_strbuf_alloc(&out, 32)); */ -/* RUN(tld_strbuf_alloc(&pattern, 32)); */ - - -/* while(1){ */ -/* start = -1; */ -/* stop = -1; */ -/* find_open(txt, offset, map->delim_start, &start); */ -/* if(start != -1){ */ -/* find_end(txt, start, map->delim_end, &stop); */ -/* if(stop != -1){ */ -/* offset = stop; */ -/* pattern->len = 0; */ -/* for(int i = start; i < stop;i++){ */ -/* RUN(tld_append_char(pattern, txt->str[i])); */ -/* /\* fprintf(stdout,"%c",txt->str[i]); *\/ */ -/* } */ -/* int internal_start = -1; */ -/* find_open(pattern, 0, map->delim_start, &internal_start); */ -/* if(internal_start != -1){ */ -/* map->status = TEMPLATE_MISMATCH_DELIM; */ -/* } */ - -/* /\* fprintf(stdout,"%s (%d - %d)\n", TLD_STR(pattern), start , stop); *\/ */ -/* int idx = -1; */ -/* int a = TLD_STRLEN(pattern); */ -/* for(int i = 0; i < map->n;i++){ */ -/* int b = TLD_STRLEN(map->identifier[i]); */ -/* if(a == b){ */ -/* if(strncmp(TLD_STR(pattern), TLD_STR(map->identifier[i]), a) == 0){ */ -/* idx = i; */ -/* break; */ -/* } */ -/* } */ -/* } */ -/* if(idx != -1){ */ -/* /\* fprintf(stdout,"%s -> %s \n", TLD_STR(map->identifier[idx]), TLD_STR(map->replacement[idx])); *\/ */ - -/* for(int i = read_header; i < start-TLD_STRLEN(map->delim_start);i++){ */ -/* RUN(tld_append_char(out, txt->str[i])); */ -/* } */ -/* RUN(tld_append(out,TLD_STR(map->replacement[idx]))); */ -/* read_header = stop + TLD_STRLEN(map->delim_end); */ -/* map->n_rep++; */ -/* }else{ */ -/* map->status = TEMPLATE_NOREP; */ -/* /\* WARNING_MSG("No replacement found"); *\/ */ -/* } */ -/* }else{ */ -/* map->status = TEMPLATE_MISMATCH_DELIM; */ -/* /\* break; *\/ */ -/* } */ -/* }else{ */ -/* break; */ -/* } */ -/* } */ -/* if(read_header < TLD_STRLEN(txt)){ */ -/* RUN(tld_append(out, TLD_STR(txt) + read_header)); */ -/* } */ - -/* /\* LOG_MSG("%s", TLD_STR(text)); *\/ */ -/* /\* LOG_MSG("READ HEADER: %d", read_header); *\/ */ -/* RUN(tld_strbuf_copy(txt, out)); */ - -/* tld_strbuf_free(pattern); */ -/* tld_strbuf_free(out); */ -/* return OK; */ -/* ERROR: */ -/* if(pattern){ */ -/* tld_strbuf_free(pattern); */ -/* } */ -/* if(out){ */ -/* tld_strbuf_free(out); */ -/* } */ -/* return FAIL; */ - -/* } */ - - - -/* int tld_template_chk(tld_template_map *map, int verbose) */ -/* { */ -/* if(verbose){ */ -/* LOG_MSG("%d replacement made", map->n_rep); */ -/* } */ -/* switch (map->status) { */ -/* case TEMPLATE_OK: */ -/* break; */ -/* case TEMPLATE_NOREP: */ - -/* ERROR_MSG("tag found in text but no matching replacement!"); */ -/* break; */ -/* case TEMPLATE_MISMATCH_DELIM: */ -/* ERROR_MSG("Mismatched deliminters!"); */ -/* break; */ -/* } */ -/* return OK; */ -/* ERROR: */ -/* return FAIL; */ -/* } */ - #undef TEMPLATE_OK #undef TEMPLATE_MISMATCH_DELIM #undef TEMPLATE_NOREP -/* int find(tld_strbuf *txt, int offset, tld_strbuf *delim,int*start_pos,int* end_pos) */ -/* { */ -/* int d_len = -1; */ -/* int t_len = -1; */ - -/* t_len = TLD_STRLEN(txt); */ -/* d_len = TLD_STRLEN(delim); */ -/* int start = -1; */ -/* int end= -1; */ -/* if(offset >= TLD_STRLEN(txt)){ */ -/* return OK; */ -/* } */ - -/* for(int i = offset; i < t_len-1;i++){ */ -/* int m = 0; */ -/* for(int j = 0; j < d_len;j++){ */ -/* if(txt->str[i+j] != delim->str[j]){ */ -/* break; */ -/* } */ -/* m++; */ -/* } */ -/* if(m == d_len){ */ -/* start = i; */ -/* end = i+m; */ -/* break; */ -/* } */ -/* } */ -/* *start_pos = start; */ -/* *end_pos = end; */ -/* return OK; */ -/* } */ - -int find_open(tld_strbuf *txt, int offset, tld_strbuf *delim,int*pos) -{ - int d_len = -1; - int t_len = -1; - - t_len = TLD_STRLEN(txt); - d_len = TLD_STRLEN(delim); - int p = -1; - if(offset >= TLD_STRLEN(txt)){ - return OK; - } - - for(int i = offset; i < t_len-1;i++){ - int m = 0; - for(int j = 0; j < d_len;j++){ - if(txt->str[i+j] != delim->str[j]){ - break; - } - m++; - } - if(m == d_len){ - p = i+m; - break; - } - } - *pos = p; - return OK; -} - -int find_end(tld_strbuf *txt, int offset, tld_strbuf *delim,int*pos) -{ - int d_len = -1; - int t_len = -1; - - t_len = TLD_STRLEN(txt); - d_len = TLD_STRLEN(delim); - int p = -1; - if(offset >= TLD_STRLEN(txt)){ - return OK; - } - - for(int i = offset; i < t_len-1;i++){ - int m = 0; - for(int j = 0; j < d_len;j++){ - if(txt->str[i+j] != delim->str[j]){ - break; - } - m++; - } - if(m == d_len){ - p = i; - break; - } - } - *pos = p; - return OK; -} - - -/* int tld_template_add(tld_template_map **map, char *id, char *rep) */ -/* { */ -/* tld_template_map* m = NULL; */ -/* int idx; */ - -/* if(*map){ */ -/* m = *map; */ -/* }else{ */ -/* RUN(tld_template_allocate(&m, 16)); */ -/* } */ - -/* ASSERT(m != NULL,"No Map"); */ - -/* idx = m->n; */ - -/* tld_append(m->identifier[idx], id); */ -/* tld_append(m->replacement[idx], rep); */ -/* m->n++; */ -/* if(m->n == m->n_alloc){ */ -/* tld_template_resize(m); */ -/* } */ -/* *map = m; */ -/* return OK; */ -/* ERROR: */ -/* return FAIL; */ -/* } */ - -/* int tld_template_get(tld_template_map *m, char *key, char** val) */ -/* { */ -/* ASSERT(m != NULL," No Map!!"); */ -/* ASSERT(key != NULL, "No key)"); */ - -/* int k_len = strnlen(key, 1024); */ - -/* *val = NULL; */ -/* for(int i = 0 ; i < m->n;i++){ */ -/* int t_len = TLD_STRLEN(m->identifier[i]); */ -/* if(k_len == t_len){ */ -/* if(strncmp(key, TLD_STR(m->identifier[i]), k_len) == 0){ */ -/* *val = TLD_STR(m->replacement[i]); */ -/* break; */ -/* } */ -/* } */ -/* } */ - -/* return OK; */ -/* ERROR: */ -/* return FAIL; */ -/* } */ - -/* int tld_template_rename_var(tld_template_map *m, char *key, char* new_key) */ -/* { */ -/* ASSERT(m != NULL," No Map!!"); */ -/* ASSERT(key != NULL, "No key)"); */ - -/* int k_len = strnlen(key, 1024); */ - - -/* for(int i = 0 ; i < m->n;i++){ */ -/* int t_len = TLD_STRLEN(m->identifier[i]); */ -/* if(k_len == t_len){ */ -/* if(strncmp(key, TLD_STR(m->identifier[i]), k_len) == 0){ */ -/* tld_strbuf_clear(m->identifier[i]); */ -/* tld_append(m->identifier[i], new_key); */ -/* break; */ -/* } */ -/* } */ -/* } */ - -/* return OK; */ -/* ERROR: */ -/* return FAIL; */ -/* } */ - int template_node_create(template_node **node, template_node_type type, char *content) { diff --git a/src/template/template.h b/src/template/template.h index 9617bb1..21fa479 100644 --- a/src/template/template.h +++ b/src/template/template.h @@ -5,21 +5,8 @@ #include "../string/str.h" -/* typedef struct tld_template_map { */ -/* tld_strbuf** identifier; */ -/* tld_strbuf** replacement; */ -/* tld_strbuf* delim_start; */ -/* tld_strbuf* delim_end; */ -/* tld_strbuf* if_delim_start; */ -/* tld_strbuf* if_delim_end; */ -/* int n; */ -/* int n_alloc; */ -/* int n_rep; */ -/* int status; */ -/* } tld_template_map; */ - - typedef struct tld_template_hash tld_template_hash; + tld_external int tld_template_add(tld_template_hash **hash, char *key, char *val); tld_external int tld_template_get(tld_template_hash *h, char *key, char **val); tld_external int tld_template_rename_var(tld_template_hash *h, char *key, char* new_key); @@ -28,15 +15,6 @@ tld_external int tld_template_remove(tld_template_hash *h, char *key); tld_external int tld_template_hash_alloc(tld_template_hash **hash, int size); tld_external void tld_template_hash_free(tld_template_hash *h); -/* tld_external int parse_template(tld_strbuf *txt); */ -/* tld_external int parse_content(tld_strbuf *txt); */ -/* tld_external int tld_template_apply2(tld_strbuf *txt, tld_template_map *map); */ tld_external int tld_template_apply(tld_strbuf *txt, tld_template_hash *map); -/* tld_external int tld_template_chk(tld_template_map *map, int verbose); */ -/* tld_external int tld_template_add(tld_template_map **map, char *id, char *rep); */ -/* tld_external int tld_template_get(tld_template_map *m, char *key, char **val); */ -/* tld_external int tld_template_rename_var(tld_template_map *m, char *key, char* new_key); */ -/* tld_external int tld_template_init(tld_template_map **map, char **id, char **rep, int n); */ -/* tld_external void tld_template_free(tld_template_map *m); */ #endif diff --git a/tests/utests/unit_template.c b/tests/utests/unit_template.c index ec52a79..2931ba7 100644 --- a/tests/utests/unit_template.c +++ b/tests/utests/unit_template.c @@ -1,25 +1,185 @@ #include "tld.h" -/* int test_default(tld_template_map *map); */ -/* int test_mismatch(tld_template_map *map); */ -/* int test_mismatch2(tld_template_map *map); */ -/* int test_norep (tld_template_map *map); */ -/* int test_ifrep(tld_template_map *map); */ int test_new_template(void); - +int test_hash_operations(void); int main(void) { test_new_template(); - /* LOG_MSG("Success"); */ + + test_hash_operations(); + /* LOG_MSG("Success"); */ return EXIT_SUCCESS; ERROR: /* LOG_MSG("FAIL"); */ return EXIT_FAILURE; +} + +int test_hash_operations(void) { + tld_template_hash *hash = NULL; + + // Step 1: Initialize the hash + printf("Initializing hash...\n"); + if (tld_template_hash_alloc(&hash, 1024) != 0) { + fprintf(stderr, "Error: Hash initialization failed!\n"); + return -1; + } + // Step 2: Add key-value pairs + printf("Adding key-value pairs...\n"); + tld_template_add(&hash, "key1", "value1"); + tld_template_add(&hash, "key2", "value2"); + tld_template_add(&hash, "key3", "value3"); + + // Step 3: Retrieve values and verify correctness + printf("Retrieving values...\n"); + char *value; + if (tld_template_get(hash, "key1", &value) == 0 && strcmp(value, "value1") == 0) { + printf("key1: %s\n", value); // Expected: value1 + } else { + printf("Error: key1 retrieval failed\n"); + } + + if (tld_template_get(hash, "key2", &value) == 0 && strcmp(value, "value2") == 0) { + printf("key2: %s\n", value); // Expected: value2 + } else { + printf("Error: key2 retrieval failed\n"); + } + + // Step 4: Test overwriting a key + printf("Overwriting key1...\n"); + tld_template_add(&hash, "key1", "new_value1"); + tld_template_get(hash, "key1", &value); + printf("key1 (overwritten): %s\n", value); // Expected: new_value1 + + // Step 5: Test retrieving non-existent key + printf("Retrieving non-existent key...\n"); + if (tld_template_get(hash, "nonexistent", &value) == -1) { + printf("nonexistent key not found\n"); + } else { + printf("Error: nonexistent key found: %s\n", value); + } + + // Step 6: Test deleting a key + printf("Deleting key2...\n"); + tld_template_remove(hash, "key2"); + if (tld_template_get(hash, "key2", &value) == -1) { + printf("key2 deleted successfully\n"); + } else { + printf("Error: key2 still exists\n"); + } + + // Step 7: Test hash collisions by adding many keys with similar prefixes + printf("Testing hash collisions...\n"); + char key[20], val[20]; + for (int i = 0; i < 1000; i++) { + snprintf(key, 20,"collide_key%d", i); + snprintf(val,20, "value%d", i); + tld_template_add(&hash, key, val); + } + + // Verify a few random keys + printf("Verifying collision keys...\n"); + for (int i = 0; i < 1000; i += 100) { + snprintf(key, 20,"collide_key%d", i); + tld_template_get(hash, key, &value); + printf("%s: %s\n", key, value); // Expected: valuei + } + + // Step 8: Test hash size limit and expansion + printf("Testing hash size limit and expansion...\n"); + for (int i = 1000; i < 1100; i++) { + snprintf(key,20, "extra_key%d", i); + snprintf(val,20, "value%d", i); + tld_template_add(&hash, key, val); + } + + // Verify new keys + for (int i = 1000; i < 1100; i++) { + snprintf(key, 20,"extra_key%d", i); + tld_template_get(hash, key, &value); + printf("%s: %s\n", key, value); // Expected: valuei + } + + // Step 9: Stress test with large amounts of data + printf("Stress test with large amount of data...\n"); + for (int i = 1100; i < 2100; i++) { + snprintf(key, 20,"large_key%d", i); + snprintf(val, 20,"value%d", i); + tld_template_add(&hash, key, val); + } + + // Verify a few random keys + for (int i = 1100; i < 2100; i += 100) { + snprintf(key, 20, "large_key%d", i); + tld_template_get(hash, key, &value); + printf("%s: %s\n", key, value); // Expected: valuei + } + + // Step 10: Clean up + printf("Freeing hash...\n"); + tld_template_hash_free(hash); + + return 0; } + +/* int test_hash_operations(void) */ +/* { */ +/* tld_template_hash *hash = NULL; */ + +/* // Step 1: Initialize the hash */ +/* printf("Initializing hash...\n"); */ +/* if (tld_template_hash_alloc(&hash,1024) != 0) { */ +/* ERROR_MSG("Hash initialization failed!"); */ +/* } */ + +/* // Step 2: Add key-value pairs */ +/* printf("Adding key-value pairs...\n"); */ +/* tld_template_add(&hash, "key1", "value1"); */ +/* tld_template_add(&hash, "key2", "value2"); */ +/* tld_template_add(&hash, "key3", "value3"); */ + +/* // Step 3: Retrieve values */ +/* printf("Retrieving values...\n"); */ +/* char *value; */ +/* tld_template_get(hash, "key1", &value); */ +/* printf("key1: %s\n", value); // Expected: value1 */ +/* tld_template_get(hash, "key2", &value); */ +/* printf("key2: %s\n", value); // Expected: value2 */ + +/* // Step 4: Test overwriting a key */ +/* printf("Overwriting key1...\n"); */ +/* tld_template_add(&hash, "key1", "new_value1"); */ +/* tld_template_add(&hash, "key1", value); */ +/* printf("key1 (overwritten): %s\n", value); // Expected: new_value1 */ + +/* // Step 5: Test retrieving non-existent key */ +/* printf("Retrieving non-existent key...\n"); */ +/* if (tld_template_get(hash, "nonexistent", &value) == -1) { */ +/* printf("nonexistent key not found\n"); */ +/* } else { */ +/* printf("nonexistent key found: %s\n", value); // Should not happen */ +/* } */ + +/* // Step 6: Delete a key */ +/* printf("Deleting key2...\n"); */ +/* tld_template_remove(hash, "key2"); */ +/* if (tld_template_get(hash, "key2", &value) == -1) { */ +/* printf("key2 deleted successfully\n"); */ +/* } else { */ +/* printf("Error: key2 still exists\n"); */ +/* } */ + +/* // Step 7: Clean up */ +/* printf("Freeing hash...\n"); */ +/* tld_template_hash_free(hash); */ +/* return OK; */ +/* ERROR: */ +/* return FAIL; */ +/* } */ + int test_new_template(void) { // Array of test templates