refactor(hmpl): fix warnings

This commit is contained in:
2025-03-24 19:27:11 +00:00
parent 4280f0df95
commit 3bb2b23be5
6 changed files with 130 additions and 77 deletions

View File

@@ -154,14 +154,15 @@ char* arena_strdup__(const char *file, int line, Arena *arena, const char *s) {
char* arena_repstr__(const char *file, int line, Arena *arena, char* arena_repstr__(const char *file, int line, Arena *arena,
const char *src, size_t start, size_t len, const char *rep) { const char *src, size_t start, size_t len, const char *rep) {
int src_len = strlen(src); raise_message(LOG_LEVEL_TRACE, file, line, "arena_repstr__(%p, %p, %zu, \"%s\")", src, start, len, rep);
int rep_len = strlen(rep); int src_len = strlen(src);
int new_len = src_len - (int)len + rep_len; int rep_len = strlen(rep);
char *new_str = (char*)arena_alloc__(file, line, arena, new_len + 1); int new_len = src_len - (int)len + rep_len;
memcpy(new_str, src, start); char *new_str = (char*)arena_alloc__(file, line, arena, new_len + 1);
memcpy(new_str + start, rep, rep_len); memcpy(new_str, src, start);
strcpy(new_str + start + rep_len, src + start + len); memcpy(new_str + start, rep, rep_len);
return new_str; strcpy(new_str + start + rep_len, src + start + len);
return new_str;
} }
void* arena_realloc_copy__(const char *file, int line, Arena *arena, void* arena_realloc_copy__(const char *file, int line, Arena *arena,
@@ -183,18 +184,31 @@ void* arena_realloc_copy__(const char *file, int line, Arena *arena,
// -- misc -- // -- misc --
// ---------- // ----------
void substr_clone(const char *src, char *dest, size_t start, size_t len) { void substr_clone__(const char *file, int line, const char * const src, char *dest, size_t from, size_t len) {
raise_debug("substr_cloneing %s (%p) from %p to %zu", src, src, start, len); // Log function entry with all parameters.
raise_message(LOG_LEVEL_TRACE, file, line,
"substr_cloning(src=\"%s\", src_ptr=%p, dest=%p, from=%zu, len=%zu)",
src, src, dest, from, len);
size_t srclen = strlen(src); size_t srclen = strlen(src);
if (start >= srclen) { if (from >= srclen) {
// Log warning with context when 'from' is out of range.
raise_message(LOG_LEVEL_WARN, file, line,
"Invalid 'from' index (%zu): exceeds source length (%zu)",
from, srclen);
dest[0] = '\0'; dest[0] = '\0';
return; return;
} }
if (start + len > srclen) if (from + len > srclen)
len = srclen - start; len = srclen - from;
strncpy(dest, src + start, len);
strncpy(dest, src + from, len);
dest[len] = '\0'; dest[len] = '\0';
raise_trace("%s", dest);
// Log success message with result.
raise_message(LOG_LEVEL_TRACE, file, line,
"Completed substr_cloning: result=\"%s\", copied_length=%zu",
dest, len);
} }
// ---------- // ----------
@@ -202,7 +216,7 @@ void substr_clone(const char *src, char *dest, size_t start, size_t len) {
// ---------- // ----------
/* Utility: Skip whitespace */ /* Utility: Skip whitespace */
static const char *json_skip_whitespace(const char *s) { static const char *skip_whitespace(const char *s) {
while (*s && isspace((unsigned char)*s)) while (*s && isspace((unsigned char)*s))
s++; s++;
return s; return s;
@@ -243,7 +257,7 @@ static Json *json_parse_value__(const char **s, Arena *arena);
static Json *json_parse_array__(const char **s, Arena *arena) { static Json *json_parse_array__(const char **s, Arena *arena) {
if (**s != '[') return NULL; if (**s != '[') return NULL;
(*s)++; // skip '[' (*s)++; // skip '['
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
Json *array = arena_alloc(arena, sizeof(Json)); Json *array = arena_alloc(arena, sizeof(Json));
if (!array) return NULL; if (!array) return NULL;
memset(array, 0, sizeof(Json)); memset(array, 0, sizeof(Json));
@@ -262,10 +276,10 @@ static Json *json_parse_array__(const char **s, Arena *arena) {
last->next = element; last->next = element;
} }
last = element; last = element;
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
if (**s == ',') { if (**s == ',') {
(*s)++; (*s)++;
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
} else if (**s == ']') { } else if (**s == ']') {
(*s)++; (*s)++;
break; break;
@@ -280,7 +294,7 @@ static Json *json_parse_array__(const char **s, Arena *arena) {
static Json *json_parse_object__(const char **s, Arena *arena) { static Json *json_parse_object__(const char **s, Arena *arena) {
if (**s != '{') return NULL; if (**s != '{') return NULL;
(*s)++; // skip '{' (*s)++; // skip '{'
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
Json *object = arena_alloc(arena, sizeof(Json)); Json *object = arena_alloc(arena, sizeof(Json));
if (!object) return NULL; if (!object) return NULL;
memset(object, 0, sizeof(Json)); memset(object, 0, sizeof(Json));
@@ -293,10 +307,10 @@ static Json *json_parse_object__(const char **s, Arena *arena) {
while (**s) { while (**s) {
char *key = json_parse_string__(s, arena); char *key = json_parse_string__(s, arena);
if (!key) return NULL; if (!key) return NULL;
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
if (**s != ':') return NULL; if (**s != ':') return NULL;
(*s)++; // skip ':' (*s)++; // skip ':'
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
Json *value = json_parse_value__(s, arena); Json *value = json_parse_value__(s, arena);
if (!value) return NULL; if (!value) return NULL;
value->key = key; // assign key to the value value->key = key; // assign key to the value
@@ -306,10 +320,10 @@ static Json *json_parse_object__(const char **s, Arena *arena) {
last->next = value; last->next = value;
} }
last = value; last = value;
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
if (**s == ',') { if (**s == ',') {
(*s)++; (*s)++;
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
} else if (**s == '}') { } else if (**s == '}') {
(*s)++; (*s)++;
break; break;
@@ -322,7 +336,7 @@ static Json *json_parse_object__(const char **s, Arena *arena) {
/* Full JSON value parser */ /* Full JSON value parser */
static Json *json_parse_value__(const char **s, Arena *arena) { static Json *json_parse_value__(const char **s, Arena *arena) {
*s = json_skip_whitespace(*s); *s = skip_whitespace(*s);
if (**s == '"') { if (**s == '"') {
Json *item = arena_alloc(arena, sizeof(Json)); Json *item = arena_alloc(arena, sizeof(Json));
if (!item) return NULL; if (!item) return NULL;
@@ -423,7 +437,7 @@ char *json_to_string_with_opts(Arena *arena, const Json * const item, JsonRawOpt
} }
/* Retrieve an object item by key (case-sensitive) */ /* Retrieve an object item by key (case-sensitive) */
Json *json_get_object_item(Json *object, const char *key) { Json *json_get_object_item(const Json * const object, const char * const key) {
raise_debug("json get object item for %s", key); raise_debug("json get object item for %s", key);
if (!object || object->type != JSON_OBJECT) if (!object || object->type != JSON_OBJECT)
return NULL; return NULL;

View File

@@ -76,19 +76,59 @@ typedef enum {
void logger_level_reset(); void logger_level_reset();
void init_logger(void);
void logger_level(LogLevel level); void logger_level(LogLevel level);
LogLevel log_level_from_string(const char *level_str); LogLevel log_level_from_string(const char *level_str);
char* raise_message(LogLevel level, const char *file, int line, const char *format, ...); char* raise_message(LogLevel level, const char *file, int line, const char *format, ...);
#define raise_trace(fmt, ...) raise_message(LOG_LEVEL_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #ifndef PRECOMPILED_LOG_LEVEL
#define raise_debug(fmt, ...) raise_message(LOG_LEVEL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #define PRECOMPILED_LOG_LEVEL LOG_LEVEL_TRACE // default level
#define raise_log(fmt, ...) raise_message(LOG_LEVEL_LOG, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #endif
#define raise_info(fmt, ...) raise_message(LOG_LEVEL_INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define raise_notice(fmt, ...) raise_message(LOG_LEVEL_NOTICE, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #if PRECOMPILED_LOG_LEVEL > LOG_LEVEL_TRACE
#define raise_warn(fmt, ...) raise_message(LOG_LEVEL_WARN, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #define raise_trace(...) ((void)0) // log removed at compile time
#define raise_exception(fmt, ...) raise_message(LOG_LEVEL_EXCEPTION, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #else
#define raise_trace(...) raise_message(LOG_LEVEL_TRACE, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#if PRECOMPILED_LOG_LEVEL > LOG_LEVEL_DEBUG
#define raise_debug(...) ((void)0)
#else
#define raise_debug(...) raise_message(LOG_LEVEL_DEBUG, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#if PRECOMPILED_LOG_LEVEL > LOG_LEVEL_LOG
#define raise_log(...) ((void)0)
#else
#define raise_log(...) raise_message(LOG_LEVEL_LOG, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#if PRECOMPILED_LOG_LEVEL > LOG_LEVEL_INFO
#define raise_info(...) ((void)0)
#else
#define raise_info(...) raise_message(LOG_LEVEL_INFO, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#if PRECOMPILED_LOG_LEVEL > LOG_LEVEL_NOTICE
#define raise_notice(...) ((void)0)
#else
#define raise_notice(...) raise_message(LOG_LEVEL_NOTICE, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#if PRECOMPILED_LOG_LEVEL > LOG_LEVEL_WARN
#define raise_warn(...) ((void)0)
#else
#define raise_warn(...) raise_message(LOG_LEVEL_WARN, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#if PRECOMPILED_LOG_LEVEL > LOG_LEVEL_EXCEPTION
#define raise_exception(...) ((void)0)
#else
#define raise_exception(...) raise_message(LOG_LEVEL_EXCEPTION, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
// ----------- // -----------
// -- arena -- // -- arena --
@@ -162,6 +202,9 @@ void* arena_realloc_copy__(const char *file, int line, Arena *arena,
#define MEM_RiB (MEM_YiB * 1024) #define MEM_RiB (MEM_YiB * 1024)
#define MEM_QiB (MEM_RiB * 1024) #define MEM_QiB (MEM_RiB * 1024)
void substr_clone__(const char *file, int line, const char * const src, char *dest, size_t from, size_t len);
#define substr_clone(src, dest, from, len) substr_clone__(__FILE__, __LINE__, src, dest, from, len)
// ---------- // ----------
// -- Json -- // -- Json --
// ---------- // ----------
@@ -200,6 +243,6 @@ char *json_to_string(Arena *arena, const Json * const item);
char *json_to_string_with_opts(Arena *arena, const Json * const item, JsonRawOpt raw); char *json_to_string_with_opts(Arena *arena, const Json * const item, JsonRawOpt raw);
/* Retrieve an object item by key (case-sensitive) */ /* Retrieve an object item by key (case-sensitive) */
Json *json_get_object_item(Json *object, const char *key); Json *json_get_object_item(const Json * const object, const char * const key);
#endif // EPRINTF_H #endif // EPRINTF_H

View File

@@ -10,11 +10,11 @@ stdenv.mkDerivation {
nativeBuildInputs = [ gcc ]; nativeBuildInputs = [ gcc ];
buildPhase = '' buildPhase = ''
${bash}/bin/sh ./build.sh ${bash}/bin/sh ./make.sh build
''; '';
checkPhase = '' checkPhase = ''
${bash}/bin/sh ./check.sh ${bash}/bin/sh ./make.sh check
''; '';
installPhase = '' installPhase = ''

View File

@@ -28,7 +28,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 */ /* Modified: text is passed by reference so we can update it and free old allocations */
// {{[prefix]key}} // {{[prefix]key}}
void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix) { 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");
char start_pattern[256]; char start_pattern[256];
snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix); snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix);
@@ -58,7 +58,7 @@ void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, Json *context
} }
char *new_text = arena_repstr(arena, current_text, char *new_text = arena_repstr(arena, current_text,
start_index, start_index,
end - start + 1, end - start + 2,
replacement); replacement);
*text_ptr = new_text; *text_ptr = new_text;
@@ -134,8 +134,7 @@ void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, Json *context
// {{#array_key}} // {{#array_key}}
void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix_start, const char * const prefix_end, const char * const separator_pattern){ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix_start, const char * const prefix_end, const char * const separator_pattern){
raise_debug("hmpl_render_section_tags"); raise_debug("hmpl_render_section_tags(%p, %s, <optimized>, %s, %s, %s)", arena, *text_ptr, prefix_start, prefix_end, separator_pattern);
printf('key');
char start_pattern[32]; char start_pattern[32];
snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix_start); snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix_start);
int start_pattern_length = strlen(start_pattern); int start_pattern_length = strlen(start_pattern);
@@ -153,7 +152,6 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons
int offset = 0; int offset = 0;
while (1) { while (1) {
printf('key');
char *current_text = *text_ptr; char *current_text = *text_ptr;
char *opening_tag_start = strstr(current_text + offset, start_pattern); char *opening_tag_start = strstr(current_text + offset, start_pattern);
if (!opening_tag_start) if (!opening_tag_start)
@@ -174,26 +172,14 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons
raise_exception("Malformed template: missing closing braces for section tag"); raise_exception("Malformed template: missing closing braces for section tag");
exit(1); exit(1);
} }
printf('key');
printf('key');
assert((size_t)opening_tag_end > (size_t)opening_tag_separator); assert((size_t)opening_tag_end > (size_t)opening_tag_separator);
assert((size_t)opening_tag_separator > (size_t)opening_tag_start); assert((size_t)opening_tag_separator > (size_t)opening_tag_start);
printf('key');
int key_length = (opening_tag_separator - current_text) - relative_key_start; int key_length = (opening_tag_separator - current_text) - relative_key_start;
assert(key_length > 0); assert(key_length > 0);
printf('key');
char *key = arena_alloc(arena, key_length + 1); char *key = arena_alloc(arena, key_length + 1);
//substr_clone(current_text, key, relative_key_start, key_length); substr_clone(current_text, key, relative_key_start, key_length);
printf('key');
key[2] = 'c';
char c=key[2];
printf('ksdjfoejisvjmeiw');
printf('key: %d\n', c);
printf('key: %p\n', key[2]);
printf('key: %p\n', key);
int element_name_length = (opening_tag_end - current_text) - element_name_start; int element_name_length = (opening_tag_end - current_text) - element_name_start;
assert(element_name_length > 0); assert(element_name_length > 0);
@@ -203,11 +189,11 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons
int close_tag_patern_length = start_pattern_length + key_length + end_pattern_length; int close_tag_patern_length = start_pattern_length + key_length + end_pattern_length;
char *close_tag_patern = arena_alloc(arena, close_tag_patern_length + 1); char *close_tag_patern = arena_alloc(arena, close_tag_patern_length + 1);
snprintf(close_tag_patern, sizeof(close_tag_patern), "%s%s%s", start_pattern, key, end_pattern); snprintf(close_tag_patern, sizeof(*close_tag_patern), "%s%s%s", start_pattern, key, end_pattern);
char *close_tag = strstr(opening_tag_end + offset + 1, close_tag_patern); char *close_tag = strstr(opening_tag_end + offset + 1, close_tag_patern);
if (!close_tag) { if (!close_tag) {
raise_exception('Malformed template: missing loop end for key %s', key); raise_exception("Malformed template: missing loop end for key %s", key);
exit(1); exit(1);
} }
@@ -220,14 +206,21 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons
char *replacement = arena_alloc(arena, MEM_KiB * elem_count); char *replacement = arena_alloc(arena, MEM_KiB * elem_count);
size_t offset = 0; size_t offset = 0;
char *block_buff = arena_alloc(arena, MEM_KiB);
size_t block_start = (size_t)opening_tag_end + 2;
size_t block_len = (size_t)opening_tag_end - (size_t)close_tag - 2;
raise_trace("block_len %p = %p - %p - 2", block_len, opening_tag_end, close_tag);
assert(block_len > 0);
substr_clone(current_text, block_buff, block_start, block_len);
for (Json *elem = arr->child; elem; elem = elem->next) { for (Json *elem = arr->child; elem; elem = elem->next) {
char *block = arena_alloc(arena, MEM_KiB); char *block = arena_strdup(arena, block_buff);
substr_clone(current_text, block, opening_tag_end + 2, close_tag - opening_tag_end - 2);
char *prefix = arena_alloc(arena, element_name_length + 2); char *prefix = arena_alloc(arena, element_name_length + 2);
snprintf(prefix, element_name_length + 2, "%s.", element_name); snprintf(prefix, element_name_length + 2, "%s.", element_name);
hmpl_render_interpolation_tags(arena, block, context, prefix); hmpl_render_interpolation_tags(arena, &block, context, prefix);
raise_trace("block after: %s", block);
size_t block_len = strlen(block); size_t block_len = strlen(block);
memcpy(replacement + offset, block, block_len); memcpy(replacement + offset, block, block_len);
@@ -235,10 +228,11 @@ void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, cons
} }
replacement[offset] = '\0'; replacement[offset] = '\0';
raise_trace("replacement: %s", replacement);
char *new_text = arena_repstr(arena, current_text, char *new_text = arena_repstr(arena, current_text,
opening_tag_start - 1, (size_t)opening_tag_start - 1,
close_tag + close_tag_patern_length - opening_tag_start + 1, close_tag + close_tag_patern_length - opening_tag_start + 2,
replacement); replacement);
*text_ptr = new_text; *text_ptr = new_text;

View File

@@ -13,12 +13,12 @@ void init_cjson_with_arenas(Arena *arena);
char *eval_string(Arena *arena, const Json * const context, const char * const key); char *eval_string(Arena *arena, const Json * const context, const char * const key);
/* Modified: text is passed by reference so we can update it and free old allocations */ /* Modified: text is passed by reference so we can update it and free old allocations */
void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix); void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, const Json * const context, const char * const prefix);
void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix_start, const char * const prefix_end, const char * const separator_pattern); void hmpl_render_section_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix_start, const char * const prefix_end, const char * const separator_pattern);
void render_template_with_arena(Arena *arena, char **text, const Json * const ccontext); void hmpl_render_with_arena(Arena *arena, char **text, const Json * const context);
void render_template(char **text, const Json * const context); void hmpl_render(char **text, const Json * const context);
#endif // EPRINTF_HMPL #endif // EPRINTF_HMPL

View File

@@ -111,7 +111,7 @@
"value3" "value3"
void test_eval_single_level_key(Arena *arena) { void test_eval_single_level_key(Arena *arena) {
char *context_text = arena_strdup(arena, "{\"name\": \"world\"}"); const char *context_text = arena_strdup(arena, "{\"name\": \"world\"}");
Json *context = json_parse(arena, &context_text); Json *context = json_parse(arena, &context_text);
if (!context) { raise_exception("Malformed json"); exit(1); } if (!context) { raise_exception("Malformed json"); exit(1); }
@@ -121,7 +121,7 @@ void test_eval_single_level_key(Arena *arena) {
} }
void test_eval_nested_key(Arena *arena) { void test_eval_nested_key(Arena *arena) {
char *context_text = arena_strdup(arena, "{\"person\": {\"name\": \"Alice\"}}"); const char *context_text = arena_strdup(arena, "{\"person\": {\"name\": \"Alice\"}}");
Json *context = json_parse(arena, &context_text); Json *context = json_parse(arena, &context_text);
if (!context) { raise_exception("Malformed json"); exit(1); } if (!context) { raise_exception("Malformed json"); exit(1); }
@@ -131,18 +131,20 @@ void test_eval_nested_key(Arena *arena) {
} }
void test_render_interpolation_tags(Arena *arena) { void test_render_interpolation_tags(Arena *arena) {
char *context_text = arena_strdup(arena, TEST_DATA_INTERPOLATION_CONTEXT); raise_trace("test_render_interpolation_tags(arena)");
const char *context_text = arena_strdup(arena, TEST_DATA_INTERPOLATION_CONTEXT);
Json *context = json_parse(arena, &context_text); Json *context = json_parse(arena, &context_text);
if (!context) { raise_exception("Malformed json"); exit(1); } if (!context) { raise_exception("Malformed json"); exit(1); }
char *text = arena_strdup(arena, TEST_DATA_INTERPOLATION_TEMPLATE); char *text = arena_strdup(arena, TEST_DATA_INTERPOLATION_TEMPLATE);
hmpl_render_interpolation_tags(arena, &text, context, ""); hmpl_render_interpolation_tags(arena, &text, context, "");
raise_trace("text: %s", text);
assert(strcmp(text, TEST_DATA_INTERPOLATION_RESULT) == 0); assert(strcmp(text, TEST_DATA_INTERPOLATION_RESULT) == 0);
} }
void test_render_interpolation_tags_with_prefix(Arena *arena) { void test_render_interpolation_tags_with_prefix(Arena *arena) {
char *context_text = arena_strdup(arena, TEST_DATA_INTERPOLATION_WITH_PREFIX_CONTEXT); const char *context_text = arena_strdup(arena, TEST_DATA_INTERPOLATION_WITH_PREFIX_CONTEXT);
Json *context = json_parse(arena, &context_text); Json *context = json_parse(arena, &context_text);
if (!context) { raise_exception("Malformed json"); exit(1); } if (!context) { raise_exception("Malformed json"); exit(1); }
@@ -153,7 +155,7 @@ void test_render_interpolation_tags_with_prefix(Arena *arena) {
} }
void test_render_section_tags(Arena *arena) { void test_render_section_tags(Arena *arena) {
char *context_text = arena_strdup(arena, TEST_DATA_SIMPLE_SECTION_ITERATION_CONTEXT); const char *context_text = arena_strdup(arena, TEST_DATA_SIMPLE_SECTION_ITERATION_CONTEXT);
Json *context = json_parse(arena, &context_text); Json *context = json_parse(arena, &context_text);
if (!context) { raise_exception("Malformed json"); exit(1); } if (!context) { raise_exception("Malformed json"); exit(1); }