fix: hectic C: template parser config

This commit is contained in:
2025-04-10 14:26:21 +00:00
parent b3d040d6fd
commit de08900297
3 changed files with 291 additions and 137 deletions

View File

@@ -200,7 +200,7 @@ char* raise_message(
Arena arena_init__(POSITION_INFO_DECLARATION, size_t size) { Arena arena_init__(POSITION_INFO_DECLARATION, size_t size) {
// Function entry logging // Function entry logging
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"INIT: Creating arena (size: %zu bytes)", size); "ARENA INIT: Creating arena (size: %zu bytes)", size);
Arena arena; Arena arena;
arena.begin = malloc(size); arena.begin = malloc(size);
@@ -208,7 +208,7 @@ Arena arena_init__(POSITION_INFO_DECLARATION, size_t size) {
// Check for allocation failure // Check for allocation failure
if (!arena.begin) { if (!arena.begin) {
raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO, raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO,
"INIT: Failed to allocate memory for arena (requested: %zu bytes)", size); "ARENA INIT: Failed to allocate memory for arena (requested: %zu bytes)", size);
exit(1); exit(1);
} }
@@ -218,17 +218,17 @@ Arena arena_init__(POSITION_INFO_DECLARATION, size_t size) {
// Success logging at LOG level // Success logging at LOG level
raise_message(LOG_LEVEL_LOG, POSITION_INFO, raise_message(LOG_LEVEL_LOG, POSITION_INFO,
"INIT: Arena initialized successfully (address: %p, capacity: %zu bytes)", arena.begin, size); "ARENA INIT: Arena initialized successfully (address: %p, capacity: %zu bytes)", arena.begin, size);
return arena; return arena;
} }
void* arena_alloc_or_null__(POSITION_INFO_DECLARATION, Arena *arena, size_t size, bool expand) { void* arena_alloc_or_null__(POSITION_INFO_DECLARATION, Arena *arena, size_t size, bool expand) {
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, raise_message(LOG_LEVEL_TRACE, POSITION_INFO,
"ALLOC: Requesting memory from arena (arena: %p, size: %zu bytes)", arena, size); "ARENA ALLOC: Requesting memory from arena (arena: %p, size: %zu bytes)", arena, size);
if (arena->begin == 0) { if (arena->begin == 0) {
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: Arena not initialized, creating new arena"); "ARENA ALLOC: Arena not initialized, creating new arena");
*arena = arena_init__(POSITION_INFO, 1024); *arena = arena_init__(POSITION_INFO, 1024);
} }
@@ -244,12 +244,12 @@ void* arena_alloc_or_null__(POSITION_INFO_DECLARATION, Arena *arena, size_t size
// We need to use a virtual memory allocator to avoid this issue // We need to use a virtual memory allocator to avoid this issue
size_t new_capacity = arena->capacity * 2 + size; size_t new_capacity = arena->capacity * 2 + size;
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"ALLOC: Expanding arena (old: %zu, new: %zu)", arena->capacity, new_capacity); "ARENA ALLOC: Expanding arena (old: %zu, new: %zu)", arena->capacity, new_capacity);
void *new_mem = malloc(new_capacity); void *new_mem = malloc(new_capacity);
if (!new_mem) { if (!new_mem) {
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"ALLOC: Failed to expand arena (requested: %zu bytes)", new_capacity); "ARENA ALLOC: Failed to expand arena (requested: %zu bytes)", new_capacity);
return NULL; return NULL;
} }
@@ -260,10 +260,10 @@ void* arena_alloc_or_null__(POSITION_INFO_DECLARATION, Arena *arena, size_t size
arena->capacity = new_capacity; arena->capacity = new_capacity;
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"ALLOC: Arena expanded successfully (address: %p, capacity: %zu)", new_mem, new_capacity); "ARENA ALLOC: Arena expanded successfully (address: %p, capacity: %zu)", new_mem, new_capacity);
} else { } else {
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"ALLOC: Insufficient memory in arena (address: %p, capacity: %zu bytes, used: %zu bytes, requested: %zu bytes)", "ARENA ALLOC: Insufficient memory in arena (address: %p, capacity: %zu bytes, used: %zu bytes, requested: %zu bytes)",
arena->begin, arena->capacity, used, size); arena->begin, arena->capacity, used, size);
return NULL; return NULL;
} }
@@ -273,39 +273,39 @@ void* arena_alloc_or_null__(POSITION_INFO_DECLARATION, Arena *arena, size_t size
arena->current = (char*)arena->current + size; arena->current = (char*)arena->current + size;
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: Memory allocated (address: %p, size: %zu)", mem, size); "ARENA ALLOC: Memory allocated (address: %p, size: %zu)", mem, size);
return mem; return mem;
} }
void* arena_alloc__(POSITION_INFO_DECLARATION, Arena *arena, size_t size) { void* arena_alloc__(POSITION_INFO_DECLARATION, Arena *arena, size_t size) {
// Function entry logging // Function entry logging
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: Allocating memory (arena: %p, size: %zu bytes)", arena, size); "ARENA ALLOC: Allocating memory (arena: %p, size: %zu bytes)", arena, size);
void *mem = arena_alloc_or_null__(POSITION_INFO, arena, size, true); void *mem = arena_alloc_or_null__(POSITION_INFO, arena, size, true);
if (!mem) { if (!mem) {
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: Allocation failed (arena: %p, requested: %zu bytes)", arena, size); "ARENA ALLOC: Allocation failed (arena: %p, requested: %zu bytes)", arena, size);
raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO, raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO,
"ALLOC: Arena out of memory (requested: %zu bytes)", size); "ARENA ALLOC: Arena out of memory (requested: %zu bytes)", size);
exit(1); exit(1);
} }
// Success logging // Success logging
raise_message(LOG_LEVEL_LOG, POSITION_INFO, raise_message(LOG_LEVEL_LOG, POSITION_INFO,
"ALLOC: Memory allocated successfully (address: %p, size: %zu bytes)", mem, size); "ARENA ALLOC: Memory allocated successfully (address: %p, size: %zu bytes)", mem, size);
return mem; return mem;
} }
void arena_reset__(POSITION_INFO_DECLARATION, Arena *arena) { void arena_reset__(POSITION_INFO_DECLARATION, Arena *arena) {
// Function entry logging // Function entry logging
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: Resetting arena (address: %p)", arena); "ARENA RESET: Resetting arena (address: %p)", arena);
// Check for NULL arena // Check for NULL arena
if (!arena) { if (!arena) {
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"ALLOC: Attempted to reset NULL arena"); "ARENA RESET: Attempted to reset NULL arena");
return; return;
} }
@@ -314,26 +314,26 @@ void arena_reset__(POSITION_INFO_DECLARATION, Arena *arena) {
// Operation success logging // Operation success logging
raise_message(LOG_LEVEL_LOG, POSITION_INFO, raise_message(LOG_LEVEL_LOG, POSITION_INFO,
"ALLOC: Arena reset successfully (address: %p, capacity: %zu bytes)", "ARENA RESET: Arena reset successfully (address: %p, capacity: %zu bytes)",
arena->begin, arena->capacity); arena->begin, arena->capacity);
} }
void arena_free__(POSITION_INFO_DECLARATION, Arena *arena) { void arena_free__(POSITION_INFO_DECLARATION, Arena *arena) {
// Function entry logging // Function entry logging
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"FREE: Releasing arena memory (address: %p)", arena); "ARENA FREE: Releasing arena memory (address: %p)", arena);
// Check for NULL arena // Check for NULL arena
if (!arena) { if (!arena) {
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"FREE: Attempted to free NULL arena"); "ARENA FREE: Attempted to free NULL arena");
return; return;
} }
// Check for NULL begin pointer // Check for NULL begin pointer
if (!arena->begin) { if (!arena->begin) {
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"FREE: Attempted to free arena with NULL memory block"); "ARENA FREE: Attempted to free arena with NULL memory block");
return; return;
} }
@@ -345,7 +345,7 @@ void arena_free__(POSITION_INFO_DECLARATION, Arena *arena) {
// Success logging // Success logging
raise_message(LOG_LEVEL_LOG, POSITION_INFO, raise_message(LOG_LEVEL_LOG, POSITION_INFO,
"FREE: Arena released successfully (address: %p, capacity: %zu bytes, used: %zu bytes)", "ARENA FREE: Arena released successfully (address: %p, capacity: %zu bytes, used: %zu bytes)",
arena->begin, arena->capacity, used); arena->begin, arena->capacity, used);
// Clear the pointers // Clear the pointers
@@ -357,13 +357,13 @@ void arena_free__(POSITION_INFO_DECLARATION, Arena *arena) {
char* arena_strdup__(POSITION_INFO_DECLARATION, Arena *arena, const char *s) { char* arena_strdup__(POSITION_INFO_DECLARATION, Arena *arena, const char *s) {
// Function entry logging // Function entry logging
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, raise_message(LOG_LEVEL_TRACE, POSITION_INFO,
"ALLOC: Duplicating string (arena: %p, source: %p, preview: %.20s%s)", "ARENA STRDUP: Duplicating string (arena: %p, source: %p, preview: %.20s%s)",
arena, s, s ? s : "", s && strlen(s) > 20 ? "..." : ""); arena, s, s ? s : "", s && strlen(s) > 20 ? "..." : "");
// Check for NULL string // Check for NULL string
if (!s) { if (!s) {
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: Source string is NULL, returning NULL"); "ARENA STRDUP: Source string is NULL, returning NULL");
return NULL; return NULL;
} }
@@ -378,7 +378,7 @@ char* arena_strdup__(POSITION_INFO_DECLARATION, Arena *arena, const char *s) {
// Success logging // Success logging
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: String duplicated successfully (result: %p, length: %zu bytes)", "ARENA STRDUP: String duplicated successfully (result: %p, length: %zu bytes)",
result, len); result, len);
return result; return result;
@@ -387,13 +387,13 @@ char* arena_strdup__(POSITION_INFO_DECLARATION, Arena *arena, const char *s) {
char* arena_strncpy__(POSITION_INFO_DECLARATION, Arena *arena, const char *start, size_t len) { char* arena_strncpy__(POSITION_INFO_DECLARATION, Arena *arena, const char *start, size_t len) {
// Function entry logging // Function entry logging
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, raise_message(LOG_LEVEL_TRACE, POSITION_INFO,
"ALLOC: Copying string (arena: %p, source: %p, length: %zu, preview: %.20s%s)", "ARENA STRNCPY: Copying string (arena: %p, source: %p, length: %zu, preview: %.20s%s)",
arena, start, len, start ? start : "", start && strlen(start) > 20 ? "..." : ""); arena, start, len, start ? start : "", start && strlen(start) > 20 ? "..." : "");
// Check for NULL string // Check for NULL string
if (!start) { if (!start) {
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: Source string is NULL, returning NULL"); "ARENA STRNCPY: Source string is NULL, returning NULL");
return NULL; return NULL;
} }
@@ -401,7 +401,7 @@ char* arena_strncpy__(POSITION_INFO_DECLARATION, Arena *arena, const char *start
char *result = (char*)arena_alloc__(POSITION_INFO, arena, len + 1); char *result = (char*)arena_alloc__(POSITION_INFO, arena, len + 1);
if (!result) { if (!result) {
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: Memory allocation failed"); "ARENA STRNCPY: Memory allocation failed");
return NULL; return NULL;
} }
@@ -411,7 +411,7 @@ char* arena_strncpy__(POSITION_INFO_DECLARATION, Arena *arena, const char *start
// Success logging // Success logging
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"ALLOC: String copied successfully (result: %p, length: %zu bytes)", "ARENA STRNCPY: String copied successfully (result: %p, length: %zu bytes)",
result, len + 1); result, len + 1);
return result; return result;
@@ -421,19 +421,19 @@ char* arena_repstr__(POSITION_INFO_DECLARATION, 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) {
// Function entry logging // Function entry logging
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, raise_message(LOG_LEVEL_TRACE, POSITION_INFO,
"STRING: Replacing substring (source: %p, start: %zu, length: %zu, replacement: %.20s%s)", "ARENA REPSTR: Replacing substring (source: %p, start: %zu, length: %zu, replacement: %.20s%s)",
src, start, len, rep, strlen(rep) > 20 ? "..." : ""); src, start, len, rep, strlen(rep) > 20 ? "..." : "");
// Check inputs // Check inputs
if (!src) { if (!src) {
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"STRING: Source string is NULL"); "ARENA REPSTR: Source string is NULL");
return NULL; return NULL;
} }
if (!rep) { if (!rep) {
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"STRING: Replacement string is NULL"); "ARENA REPSTR: Replacement string is NULL");
return NULL; return NULL;
} }
@@ -444,7 +444,7 @@ char* arena_repstr__(POSITION_INFO_DECLARATION, Arena *arena,
// Validate start and length // Validate start and length
if (start > (size_t)src_len) { if (start > (size_t)src_len) {
raise_message(LOG_LEVEL_WARN, POSITION_INFO, raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"STRING: Start position %zu exceeds source length %d", start, src_len); "ARENA REPSTR: Start position %zu exceeds source length %d", start, src_len);
// Return a copy of the source string // Return a copy of the source string
return arena_strdup__(POSITION_INFO, arena, src); return arena_strdup__(POSITION_INFO, arena, src);
} }
@@ -453,7 +453,7 @@ char* arena_repstr__(POSITION_INFO_DECLARATION, Arena *arena,
size_t old_len = len; size_t old_len = len;
len = src_len - start; len = src_len - start;
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"STRING: Adjusted length from %zu to %zu to fit source bounds", old_len, len); "ARENA REPSTR: Adjusted length from %zu to %zu to fit source bounds", old_len, len);
} }
// Calculate new length and allocate memory // Calculate new length and allocate memory
@@ -467,7 +467,7 @@ char* arena_repstr__(POSITION_INFO_DECLARATION, Arena *arena,
// Success logging // Success logging
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"STRING: Replacement complete (result: %p, new length: %d)", new_str, new_len); "ARENA REPSTR: Replacement complete (result: %p, new length: %d)", new_str, new_len);
return new_str; return new_str;
} }
@@ -540,6 +540,126 @@ void substr_clone__(POSITION_INFO_DECLARATION, const char * const src, char *des
// -- Json -- // -- Json --
// ---------- // ----------
char *json_to_pretty_str__(POSITION_INFO_DECLARATION, Arena *arena, const Json * const item, int indent_level) {
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
"PRETTY: Starting JSON prettification (item: %p, indent: %d)",
item, indent_level);
if (!item) {
raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO,
"PRETTY: Invalid JSON object (NULL) provided for prettification");
return NULL;
}
if (!arena) {
raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO,
"PRETTY: Invalid arena (NULL) provided for prettification");
return NULL;
}
char *out = arena_alloc__(POSITION_INFO, arena, 1024);
if (!out) {
raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO,
"PRETTY: Memory allocation failed during JSON prettification");
return NULL;
}
char *ptr = out;
if (item->type == JSON_OBJECT) {
ptr += sprintf(ptr, "{\n");
Json *child = item->child;
int child_count = 0;
raise_message(LOG_LEVEL_TRACE, POSITION_INFO,
"PRETTY: Processing JSON object children");
while (child) {
for (int i = 0; i < indent_level + 1; i++) {
ptr += sprintf(ptr, " ");
}
ptr += sprintf(ptr, "\"%s\": ", child->key ? child->key : "");
char *child_str = json_to_pretty_str__(POSITION_INFO, arena, child, indent_level + 1);
if (child_str) {
ptr += sprintf(ptr, "%s", child_str);
} else {
raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"PRETTY: Failed to prettify child element (key=%s)",
child->key ? child->key : "<null>");
}
if (child->next) {
ptr += sprintf(ptr, ",\n");
} else {
ptr += sprintf(ptr, "\n");
}
child = child->next;
child_count++;
}
for (int i = 0; i < indent_level; i++) {
ptr += sprintf(ptr, " ");
}
sprintf(ptr, "}");
raise_message(LOG_LEVEL_TRACE, POSITION_INFO,
"PRETTY: Object prettification complete with %d child elements", child_count);
} else if (item->type == JSON_ARRAY) {
ptr += sprintf(ptr, "[\n");
Json *child = item->child;
int child_count = 0;
raise_message(LOG_LEVEL_TRACE, POSITION_INFO,
"PRETTY: Processing JSON array elements");
while (child) {
// Add indentation
for (int i = 0; i < indent_level + 1; i++) {
ptr += sprintf(ptr, " ");
}
char *child_str = json_to_pretty_str__(POSITION_INFO, arena, child, indent_level + 1);
if (child_str) {
ptr += sprintf(ptr, "%s", child_str);
} else {
raise_message(LOG_LEVEL_WARN, POSITION_INFO,
"PRETTY: Failed to prettify array element at index %d", child_count);
}
if (child->next) {
ptr += sprintf(ptr, ",\n");
} else {
ptr += sprintf(ptr, "\n");
}
child = child->next;
child_count++;
}
for (int i = 0; i < indent_level; i++) {
ptr += sprintf(ptr, " ");
}
sprintf(ptr, "]");
raise_message(LOG_LEVEL_TRACE, POSITION_INFO,
"PRETTY: Array prettification complete with %d elements", child_count);
} else if (item->type == JSON_STRING) {
sprintf(ptr, "\"%s\"", item->JsonValue.string ? item->JsonValue.string : "");
} else if (item->type == JSON_NUMBER) {
sprintf(ptr, "%g", item->JsonValue.number);
} else if (item->type == JSON_BOOL) {
sprintf(ptr, item->JsonValue.boolean ? "true" : "false");
} else if (item->type == JSON_NULL) {
sprintf(ptr, "null");
}
raise_message(LOG_LEVEL_LOG, POSITION_INFO,
"PRETTY: JSON %s prettified (length=%zu)",
json_type_to_string(item->type), strlen(out));
return out;
}
const char* json_type_to_string(JsonType type) { const char* json_type_to_string(JsonType type) {
switch (type) { switch (type) {
case JSON_NULL: return "NULL"; case JSON_NULL: return "NULL";
@@ -997,71 +1117,6 @@ Json *json_get_object_item__(POSITION_INFO_DECLARATION, const Json * const objec
return NULL; return NULL;
} }
char* slice_to_debug_str__(POSITION_INFO_DECLARATION, Arena *arena, Slice slice) {
// Create complete information about the Slice structure
char buffer_meta[128];
snprintf(buffer_meta, sizeof(buffer_meta), "Slice{addr=%p, data=%p, len=%zu, isize=%zu, content=",
(void*)&slice, slice.data, slice.len, slice.isize);
size_t meta_len = strlen(buffer_meta);
// For NULL data, output a simple message
if (!slice.data) {
char* result = arena_alloc(arena, meta_len + 6);
strcpy(result, buffer_meta);
strcat(result, "NULL}");
return result;
}
// Allocate buffer with space for quotes, metadata and null terminator
size_t buffer_size = meta_len + slice.len * 4 + 20; // Extra space for escaping and closing brace
char* buffer = arena_alloc(arena, buffer_size);
// Copy metadata
strcpy(buffer, buffer_meta);
char* pos = buffer + meta_len;
*pos++ = '"';
// Copy slice data with escaping
for (size_t i = 0; i < slice.len; i++) {
char c = ((char*)slice.data)[i];
if (c == '\0') {
*pos++ = '\\';
*pos++ = '0';
} else if (c == '\n') {
*pos++ = '\\';
*pos++ = 'n';
} else if (c == '\r') {
*pos++ = '\\';
*pos++ = 'r';
} else if (c == '\t') {
*pos++ = '\\';
*pos++ = 't';
} else if (c == '"') {
*pos++ = '\\';
*pos++ = '"';
} else if (c == '\\') {
*pos++ = '\\';
*pos++ = '\\';
} else if (c < 32 || c > 126) {
// Non-printable characters as hex
pos += sprintf(pos, "\\x%02x", (unsigned char)c);
} else {
*pos++ = c;
}
}
*pos++ = '"';
*pos++ = '}'; // Closing brace for the structure
*pos = '\0';
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "slice_to_debug_str: %s", buffer);
return buffer;
}
// ----------- // -----------
// -- slice -- // -- slice --
// ----------- // -----------
@@ -1129,7 +1184,6 @@ int* arena_slice_copy__(POSITION_INFO_DECLARATION, Arena *arena, Slice s) {
char* json_to_debug_str__(POSITION_INFO_DECLARATION, Arena *arena, Json json) { char* json_to_debug_str__(POSITION_INFO_DECLARATION, Arena *arena, Json json) {
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "json_to_debug_str(<optimized>, <optimized>)"); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "json_to_debug_str(<optimized>, <optimized>)");
// Add information about the JSON structure itself
char meta_buffer[256]; char meta_buffer[256];
snprintf(meta_buffer, sizeof(meta_buffer), "Json{addr=%p, type=%s, key=%s, child=%p, next=%p, value=", snprintf(meta_buffer, sizeof(meta_buffer), "Json{addr=%p, type=%s, key=%s, child=%p, next=%p, value=",
@@ -1482,6 +1536,71 @@ char* logger_rules_to_string(Arena *arena) {
return buffer; return buffer;
} }
char* slice_to_debug_str__(POSITION_INFO_DECLARATION, Arena *arena, Slice slice) {
// Create complete information about the Slice structure
char buffer_meta[128];
snprintf(buffer_meta, sizeof(buffer_meta), "Slice{addr=%p, data=%p, len=%zu, isize=%zu, content=",
(void*)&slice, slice.data, slice.len, slice.isize);
size_t meta_len = strlen(buffer_meta);
// For NULL data, output a simple message
if (!slice.data) {
char* result = arena_alloc(arena, meta_len + 6);
strcpy(result, buffer_meta);
strcat(result, "NULL}");
return result;
}
// Allocate buffer with space for quotes, metadata and null terminator
size_t buffer_size = meta_len + slice.len * 4 + 20; // Extra space for escaping and closing brace
char* buffer = arena_alloc(arena, buffer_size);
// Copy metadata
strcpy(buffer, buffer_meta);
char* pos = buffer + meta_len;
*pos++ = '"';
// Copy slice data with escaping
for (size_t i = 0; i < slice.len; i++) {
char c = ((char*)slice.data)[i];
if (c == '\0') {
*pos++ = '\\';
*pos++ = '0';
} else if (c == '\n') {
*pos++ = '\\';
*pos++ = 'n';
} else if (c == '\r') {
*pos++ = '\\';
*pos++ = 'r';
} else if (c == '\t') {
*pos++ = '\\';
*pos++ = 't';
} else if (c == '"') {
*pos++ = '\\';
*pos++ = '"';
} else if (c == '\\') {
*pos++ = '\\';
*pos++ = '\\';
} else if (c < 32 || c > 126) {
// Non-printable characters as hex
pos += sprintf(pos, "\\x%02x", (unsigned char)c);
} else {
*pos++ = c;
}
}
*pos++ = '"';
*pos++ = '}'; // Closing brace for the structure
*pos = '\0';
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "slice_to_debug_str: %s", buffer);
return buffer;
}
// --------------- // ---------------
// -- Templater -- // -- Templater --
// --------------- // ---------------
@@ -1552,8 +1671,9 @@ bool template_validate_config__(POSITION_INFO_DECLARATION, const TemplateConfig
#define TEMPLATE_ASSERT_SYNTAX(pattern, message_arg, code_arg) \ #define TEMPLATE_ASSERT_SYNTAX(pattern, message_arg, code_arg) \
if (strncmp(*s, pattern, strlen(pattern))) { \ if (strncmp(*s, pattern, strlen(pattern))) { \
raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO, "PARSE: " message_arg); \ raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO, "PARSE: " message_arg); \
result->error.code = code_arg; \ result->type = TEMPLATE_RESULT_ERROR; \
result->error.message = message_arg; \ result->Result.error.code = code_arg; \
result->Result.error.message = message_arg; \
return result; \ return result; \
} }
@@ -1582,9 +1702,10 @@ TemplateResult *template_parse_interpolation__(POSITION_INFO_DECLARATION, Arena
} }
size_t key_len = *s - key_start; size_t key_len = *s - key_start;
result->node.value.interpolate.key = arena_strncpy__(POSITION_INFO, arena, key_start, key_len); result->Result.node.value.interpolate.key = arena_strncpy__(POSITION_INFO, arena, key_start, key_len);
result->node.type = TEMPLATE_NODE_INTERPOLATE; result->type = TEMPLATE_RESULT_NODE;
result->Result.node.type = TEMPLATE_NODE_INTERPOLATE;
*s_ptr = *s + strlen(config->Syntax.Braces.close); *s_ptr = *s + strlen(config->Syntax.Braces.close);
@@ -1595,7 +1716,8 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Section"); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Section");
TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
result->node.type = TEMPLATE_NODE_SECTION; result->type = TEMPLATE_RESULT_NODE;
result->Result.node.type = TEMPLATE_NODE_SECTION;
const char **s = s_ptr; const char **s = s_ptr;
@@ -1617,7 +1739,7 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena
} }
size_t iterator_len = *s - iterator_start; size_t iterator_len = *s - iterator_start;
result->node.value.section.iterator = arena_strncpy__(POSITION_INFO, arena, iterator_start, iterator_len); result->Result.node.value.section.iterator = arena_strncpy__(POSITION_INFO, arena, iterator_start, iterator_len);
// Find the collection name // Find the collection name
*s = skip_whitespace(*s); *s = skip_whitespace(*s);
@@ -1632,15 +1754,15 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena
} }
size_t collection_len = *s - collection_start; size_t collection_len = *s - collection_start;
result->node.value.section.collection = arena_strncpy__(POSITION_INFO, arena, collection_start, collection_len); result->Result.node.value.section.collection = arena_strncpy__(POSITION_INFO, arena, collection_start, collection_len);
// Parse the body // Parse the body
TemplateResult *body_result = template_parse__(POSITION_INFO, arena, s, config); TemplateResult *body_result = template_parse__(POSITION_INFO, arena, s, config);
if (body_result->error.code != TEMPLATE_ERROR_NONE) { if (body_result->type == TEMPLATE_RESULT_ERROR) {
return body_result; return body_result;
} }
result->node.value.section.body = &body_result->node; result->Result.node.value.section.body = &body_result->Result.node;
*s_ptr = *s + strlen(config->Syntax.Braces.close); *s_ptr = *s + strlen(config->Syntax.Braces.close);
@@ -1650,7 +1772,8 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena
TemplateResult *template_parse_include__(POSITION_INFO_DECLARATION, Arena *arena, const char **s_ptr, const TemplateConfig *config) { TemplateResult *template_parse_include__(POSITION_INFO_DECLARATION, Arena *arena, const char **s_ptr, const TemplateConfig *config) {
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Include"); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Include");
TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
result->node.type = TEMPLATE_NODE_INCLUDE; result->type = TEMPLATE_RESULT_NODE;
result->Result.node.type = TEMPLATE_NODE_INCLUDE;
const char **s = s_ptr; const char **s = s_ptr;
@@ -1670,7 +1793,7 @@ TemplateResult *template_parse_include__(POSITION_INFO_DECLARATION, Arena *arena
} }
size_t include_len = *s - include_start; size_t include_len = *s - include_start;
result->node.value.include.key = arena_strncpy__(POSITION_INFO, arena, include_start, include_len); result->Result.node.value.include.key = arena_strncpy__(POSITION_INFO, arena, include_start, include_len);
*s_ptr = *s + strlen(config->Syntax.Braces.close); *s_ptr = *s + strlen(config->Syntax.Braces.close);
@@ -1681,7 +1804,8 @@ TemplateResult *template_parse_execute__(POSITION_INFO_DECLARATION, Arena *arena
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Execute"); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Execute");
TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
result->node.type = TEMPLATE_NODE_EXECUTE; result->type = TEMPLATE_RESULT_NODE;
result->Result.node.type = TEMPLATE_NODE_EXECUTE;
const char **s = s_ptr; const char **s = s_ptr;
@@ -1698,7 +1822,7 @@ TemplateResult *template_parse_execute__(POSITION_INFO_DECLARATION, Arena *arena
} }
size_t code_len = *s - code_start; size_t code_len = *s - code_start;
result->node.value.execute.code = arena_strncpy__(POSITION_INFO, arena, code_start, code_len); result->Result.node.value.execute.code = arena_strncpy__(POSITION_INFO, arena, code_start, code_len);
*s_ptr = *s + strlen(config->Syntax.Braces.close); *s_ptr = *s + strlen(config->Syntax.Braces.close);
@@ -1718,8 +1842,6 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const
return NULL; return NULL;
} }
assert(config->Syntax.Braces.open != NULL);
const char *start = *s; const char *start = *s;
TemplateNode *root = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateNode)); TemplateNode *root = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateNode));
@@ -1745,12 +1867,6 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const
const char *tag_prefix = *s + open_brace_len; const char *tag_prefix = *s + open_brace_len;
tag_prefix = skip_whitespace(tag_prefix); tag_prefix = skip_whitespace(tag_prefix);
raise_trace("tag_prefix: %p", tag_prefix); raise_trace("tag_prefix: %p", tag_prefix);
assert(tag_prefix != NULL);
assert(config->Syntax.Section.control != NULL);
assert(config->Syntax.Interpolate.invoke != NULL);
assert(config->Syntax.Include.invoke != NULL);
assert(config->Syntax.Execute.invoke != NULL);
assert(config->Syntax.nesting != NULL);
if (strncmp(tag_prefix, config->Syntax.Section.control, strlen(config->Syntax.Section.control)) == 0) { if (strncmp(tag_prefix, config->Syntax.Section.control, strlen(config->Syntax.Section.control)) == 0) {
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Section tag"); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Section tag");
@@ -1769,18 +1885,19 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const
TemplateResult *error_result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *error_result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
error_result->error.code = TEMPLATE_ERROR_UNKNOWN_TAG; error_result->type = TEMPLATE_RESULT_ERROR;
error_result->error.message = "Unknown tag prefix"; error_result->Result.error.code = TEMPLATE_ERROR_UNKNOWN_TAG;
error_result->Result.error.message = "Unknown tag prefix";
return error_result; return error_result;
} }
} }
if (current_result->error.code != TEMPLATE_ERROR_NONE) { if (current_result->type == TEMPLATE_RESULT_ERROR) {
return current_result; return current_result;
} }
*current = current_result->node; *current = current_result->Result.node;
current->next = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateNode)); current->next = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateNode));
current = current->next; current = current->next;
} }
@@ -1795,7 +1912,8 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const
} }
TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
result->node = *root; result->type = TEMPLATE_RESULT_NODE;
result->Result.node = *root;
return result; return result;
} }
@@ -1804,6 +1922,22 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const
#define TEMPLATE_NODE_MAX_DEBUG_DEPTH 20 #define TEMPLATE_NODE_MAX_DEBUG_DEPTH 20
static const char *template_error_code_to_string(TemplateErrorCode code) {
switch (code) {
case TEMPLATE_ERROR_NONE: return "NONE";
case TEMPLATE_ERROR_UNKNOWN_TAG: return "UNKNOWN_TAG";
case TEMPLATE_ERROR_NESTED_INTERPOLATION: return "NESTED_INTERPOLATION";
case TEMPLATE_ERROR_UNEXPECTED_SECTION_END: return "UNEXPECTED_SECTION_END";
case TEMPLATE_ERROR_NESTED_SECTION_ITERATOR: return "NESTED_SECTION_ITERATOR";
case TEMPLATE_ERROR_NESTED_INCLUDE: return "NESTED_INCLUDE";
case TEMPLATE_ERROR_NESTED_EXECUTE: return "NESTED_EXECUTE";
default: {
raise_exception("HECTICLIB ERROR: Unknown template error code: %d", code);
return "UNKNOWN";
};
}
}
static char *template_node_type_to_string(TemplateNodeType type) { static char *template_node_type_to_string(TemplateNodeType type) {
switch (type) { switch (type) {
case TEMPLATE_NODE_SECTION: return "SECTION"; case TEMPLATE_NODE_SECTION: return "SECTION";
@@ -1811,7 +1945,10 @@ static char *template_node_type_to_string(TemplateNodeType type) {
case TEMPLATE_NODE_EXECUTE: return "EXECUTE"; case TEMPLATE_NODE_EXECUTE: return "EXECUTE";
case TEMPLATE_NODE_INCLUDE: return "INCLUDE"; case TEMPLATE_NODE_INCLUDE: return "INCLUDE";
case TEMPLATE_NODE_TEXT: return "TEXT"; case TEMPLATE_NODE_TEXT: return "TEXT";
default: return "UNKNOWN"; default: {
raise_exception("HECTICLIB ERROR: Unknown template node type: %d", type);
return "UNKNOWN";
};
} }
} }
@@ -1863,14 +2000,13 @@ char *template_node_to_debug_str__(POSITION_INFO_DECLARATION, Arena *arena, cons
default: default:
break; break;
} }
APPEND("}");
if (node->error.code != TEMPLATE_ERROR_NONE) { if (node->error.code != TEMPLATE_ERROR_NONE) {
APPEND("\"error\":{\"code\":%d,\"message\":\"%s\"}", node->error.code, node->error.message); APPEND(",\"error\":{\"code\":\"%s\",\"message\":\"%s\"}", template_error_code_to_string(node->error.code), node->error.message);
} }
if (node->children) { if (node->children) {
APPEND("\"children\":["); APPEND(",\"children\":[");
char *child_str = template_node_to_debug_str__(POSITION_INFO, arena, node->children, depth + 1); char *child_str = template_node_to_debug_str__(POSITION_INFO, arena, node->children, depth + 1);
if (child_str) { if (child_str) {
APPEND(",%s", child_str); APPEND(",%s", child_str);
@@ -1878,6 +2014,8 @@ char *template_node_to_debug_str__(POSITION_INFO_DECLARATION, Arena *arena, cons
APPEND("]"); APPEND("]");
} }
APPEND("}");
if (node->next) { if (node->next) {
char *next_str = template_node_to_debug_str__(POSITION_INFO, arena, node->next, depth + 1); char *next_str = template_node_to_debug_str__(POSITION_INFO, arena, node->next, depth + 1);
if (next_str) { if (next_str) {

View File

@@ -397,13 +397,18 @@ char *json_to_string__(const char* file, const char* func, int line, Arena *aren
char *json_to_string_with_opts__(const char* file, const char* func, int line, Arena *arena, const Json * const item, JsonRawOpt raw); char *json_to_string_with_opts__(const char* file, const char* func, int line, Arena *arena, const Json * const item, JsonRawOpt raw);
/* Retrieve an object item by key (case-sensitive) */ /* Retrieve an object item by key (case-sensitive) */
#define json_get_object_item(object, key) json_get_object_item__(__FILE__, __func__, __LINE__, object, key)
Json *json_get_object_item__(const char* file, const char* func, int line, const Json * const object, const char * const key); Json *json_get_object_item__(const char* file, const char* func, int line, const Json * const object, const char * const key);
#define json_get_object_item(object, key) json_get_object_item__(__FILE__, __func__, __LINE__, object, key)
char* json_to_debug_str__(const char* file, const char* func, int line, Arena *arena, Json json); char* json_to_debug_str__(const char* file, const char* func, int line, Arena *arena, Json json);
#define json_to_debug_str(arena, json) json_to_debug_str__(__FILE__, __func__, __LINE__, arena, json) #define json_to_debug_str(arena, json) json_to_debug_str__(__FILE__, __func__, __LINE__, arena, json)
char *json_to_pretty_str__(const char* file, const char* func, int line, Arena *arena, const Json * const item, int indent_level);
#define json_to_pretty_str(arena, json) json_to_pretty_str__(__FILE__, __func__, __LINE__, arena, json, 0)
// ----------- // -----------
// -- Slice -- // -- Slice --
// ----------- // -----------
@@ -547,9 +552,17 @@ struct TemplateNode {
TemplateNode *next; // sibling nodes TemplateNode *next; // sibling nodes
}; };
typedef union { typedef enum {
TEMPLATE_RESULT_ERROR,
TEMPLATE_RESULT_NODE,
} TemplateResultType;
typedef struct {
TemplateResultType type;
union {
TemplateError error; TemplateError error;
TemplateNode node; TemplateNode node;
} Result;
} TemplateResult; } TemplateResult;
TemplateResult *template_parse__(const char *file, const char *func, int line, Arena *arena, const char **s, const TemplateConfig *config); TemplateResult *template_parse__(const char *file, const char *func, int line, Arena *arena, const char **s, const TemplateConfig *config);

View File

@@ -62,8 +62,11 @@ static void test_template_parse(Arena *arena, TemplateConfig *config) {
const char *template = "Hello {% name %}!"; const char *template = "Hello {% name %}!";
TemplateResult *result = template_parse(arena, &template, config); TemplateResult *result = template_parse(arena, &template, config);
raise_notice("result: %s", template_node_to_debug_str(DISPOSABLE_ARENA, &result->node)); Arena *debug_arena = DISPOSABLE_ARENA;
assert(result->error.code == TEMPLATE_ERROR_NONE); const char *debug_str = template_node_to_debug_str(debug_arena, &result->Result.node);
raise_notice("debug_str: %s", debug_str);
raise_notice("result: %s", json_to_pretty_str(debug_arena, json_parse(debug_arena, &debug_str)));
assert(result->type == TEMPLATE_RESULT_NODE);
} }
int main(void) { int main(void) {