From 14c246de3e807f3e8f727ded3b745e36b2000a10 Mon Sep 17 00:00:00 2001 From: yukkop Date: Sat, 5 Apr 2025 21:31:35 +0000 Subject: [PATCH] feat: `hmpl`: section test passeeed --- package/c/hmpl/hmpl.c | 77 ++++++++++++++++++++++---------------- package/c/hmpl/test/test.c | 4 +- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/package/c/hmpl/hmpl.c b/package/c/hmpl/hmpl.c index 1882ab1..c2e1d66 100644 --- a/package/c/hmpl/hmpl.c +++ b/package/c/hmpl/hmpl.c @@ -1,6 +1,7 @@ #include "hmpl.h" Json *eval_object(Arena *arena, const Json * const context, const char * const query) { + raise_debug("eval_object(%p, %s, %s)", arena, json_to_string(arena, context), query); if (!context || !query) return NULL; const Json *res = context; @@ -29,7 +30,7 @@ char *eval_string(Arena *arena, const Json * const context, const char * const q /* Modified: text is passed by reference so we can update it and free old allocations */ // {{[prefix]key}} void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, const Json * const context, const char * const prefix) { - raise_debug("hmpl_render_interpolation_tags"); + raise_debug("hmpl_render_interpolation_tags(%p, %s, %s)", arena, *text_ptr, prefix); char start_pattern[256]; snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix); int start_pattern_length = strlen(start_pattern); @@ -53,6 +54,7 @@ void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, const Json * char *replacement = eval_string(arena, context, key); if (!replacement) { + raise_debug("no replacement for key: `%s`", key); offset = (end - current_text) + 2; continue; } @@ -61,6 +63,9 @@ void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, const Json * end - start + 2, replacement); + raise_zalupa("old_text: `%s`", current_text); + raise_zalupa("new_text: `%s`", new_text); + *text_ptr = new_text; offset = start_index; } @@ -74,14 +79,14 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons char start_pattern[32]; snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix_start); Slice start_slice = slice_create(char, start_pattern, strlen(start_pattern), 0, strlen(start_pattern)); - raise_trace("start_slice: %s", start_slice.data); + raise_zalupa("start_slice: `%s`", start_slice.data); // Create a mutable copy of separator_pattern char separator_copy[32]; strncpy(separator_copy, separator_pattern, sizeof(separator_copy) - 1); separator_copy[sizeof(separator_copy) - 1] = '\0'; Slice separator_slice = slice_create(char, separator_copy, strlen(separator_copy), 0, strlen(separator_copy)); - raise_trace("separator_slice: %s", separator_slice.data); + raise_zalupa("separator_slice: `%s`", separator_slice.data); if (separator_slice.len == 0) { raise_exception("Unexpected usage: separator pattern cannot be empty"); } @@ -102,19 +107,21 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons // Find separator char *opening_tag_separator = strstr((char*)remaining_slice.data, (char*)separator_slice.data); + raise_zalupa("opening_tag_separator: `%s`", opening_tag_separator); if (!opening_tag_separator) { raise_exception("Malformed template: missing separator for section tag or not specified name for element"); exit(1); } // Extract element name (now before separator) - size_t separator_index = opening_tag_separator - (char*)remaining_slice.data; + size_t separator_index = opening_tag_separator - (char*)remaining_slice.data - strlen(start_slice.data); size_t element_name_start = start_slice.len; size_t element_name_length = separator_index; - + raise_zalupa("element_name_length: %zu", element_name_length); + char *element_name = arena_alloc(arena, element_name_length + 1); substr_clone((char*)remaining_slice.data, element_name, element_name_start, element_name_length); - element_name[element_name_length] = '\0'; + raise_zalupa("element_name: `%s`", element_name); // Find closing braces Slice after_separator = slice_subslice(remaining_slice, separator_index + separator_slice.len, @@ -126,33 +133,35 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons } // Extract key (now after separator) - size_t key_start = 0; - size_t key_length = opening_tag_end - (char*)after_separator.data; + size_t key_start = strlen(start_slice.data); + size_t key_length = opening_tag_end - (char*)after_separator.data - strlen(start_slice.data); char *key = arena_alloc(arena, key_length + 1); substr_clone((char*)after_separator.data, key, key_start, key_length); + raise_zalupa("key: `%s`", key); key[key_length] = '\0'; - // Create pattern for closing tag - char *close_tag_pattern = arena_alloc(arena, start_slice.len + key_length + 3); // +3 for "{{" and "}}" - snprintf(close_tag_pattern, start_slice.len + key_length + 3, - "{{%s%s}}", prefix_end, key); - raise_trace("close_tag_pattern: %s", close_tag_pattern); + // +2 for "{{" and "}}" + char *close_tag_pattern = arena_alloc(arena, start_slice.len + key_length + strlen(prefix_end) + 2); + snprintf( + close_tag_pattern, + start_slice.len + key_length + strlen(prefix_end) + 2, + "{{%s%s}}", + prefix_end, + key + ); + raise_zalupa("close_tag_pattern: `%s`", close_tag_pattern); - // Find closing tag size_t after_opening_end = (opening_tag_end - (char*)after_separator.data) + 2; - Slice after_opening_slice = slice_subslice(after_separator, after_opening_end, - after_separator.len - after_opening_end); + Slice after_opening_slice = slice_subslice( + after_separator, + after_opening_end, + after_separator.len - after_opening_end + ); + raise_zalupa("after_opening_slice: `%s`", after_opening_slice.data); - // Find the exact closing tag by checking for complete tag pattern - char *close_tag = NULL; - char *search_start = (char*)after_opening_slice.data; - while ((search_start = strstr(search_start, "{{")) != NULL) { - if (strncmp(search_start, close_tag_pattern, strlen(close_tag_pattern)) == 0) { - close_tag = search_start; - break; - } - search_start += 2; // Move past the "{{" we found - } + // Find the exact closing tag by directly searching for the closing tag pattern + char *close_tag = strstr(after_opening_slice.data, close_tag_pattern); + raise_zalupa("close_tag: `%s` (%p)", close_tag, close_tag); if (!close_tag) { raise_exception("Malformed template: missing loop end for key %s", key); @@ -161,6 +170,7 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons // Get array from context Json *arr = eval_object(arena, context, key); + raise_zalupa("arr: %s", json_to_string(arena, arr)); if (arr && arr->type == JSON_ARRAY) { // Count array elements @@ -172,11 +182,11 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons size_t replacement_offset = 0; // Extract template block - size_t block_start = after_opening_end; size_t block_length = (close_tag - (char*)after_opening_slice.data); char *block_buff = arena_alloc(arena, block_length + 1); - substr_clone((char*)after_opening_slice.data, block_buff, block_start, block_length); + substr_clone((char*)after_opening_slice.data, block_buff, 0, block_length); block_buff[block_length] = '\0'; + raise_zalupa("block_buff: `%s`", block_buff); // Process each array element for (Json *elem = arr->child; elem; elem = elem->next) { @@ -184,8 +194,9 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons char *prefix = arena_alloc(arena, element_name_length + 2); snprintf(prefix, element_name_length + 2, "%s.", element_name); - - hmpl_render_interpolation_tags(arena, &block, context, prefix); + raise_zalupa("prefix: `%s`", prefix); + + hmpl_render_interpolation_tags(arena, &block, elem, prefix); raise_trace("block after: %s", block); size_t block_len = strlen(block); @@ -194,12 +205,12 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons } replacement[replacement_offset] = '\0'; - raise_trace("replacement: %s", replacement); + raise_zalupa("replacement: %s", replacement); // Calculate replacement positions size_t replace_start = start_index; - size_t replace_length = (close_tag - (char*)after_opening_slice.data) + - start_slice.len + key_length + 2; + size_t replace_length = (close_tag - opening_tag_start) + strlen(close_tag_pattern); + raise_zalupa("replace_length: %zu = %zu - %zu + %zu", replace_length, (size_t)close_tag, start_index, strlen(close_tag_pattern)); // Perform replacement char *new_text = arena_repstr(arena, (char*)text_slice.data, replace_start, replace_length, replacement); diff --git a/package/c/hmpl/test/test.c b/package/c/hmpl/test/test.c index 0c54798..534dcbe 100644 --- a/package/c/hmpl/test/test.c +++ b/package/c/hmpl/test/test.c @@ -106,9 +106,7 @@ "{{/array}}" #define TEST_DATA_SIMPLE_SECTION_ITERATION_RESULT \ - "value1" \ - "value2" \ - "value3" + " value1 value2 value3" #define TEST_DATA_COMPLEX_SECTION_ITERATION_CONTEXT \ "{" \