From 1f25c4fcad108a75e26879bfb7eceb1316c1b01a Mon Sep 17 00:00:00 2001 From: yukkop Date: Sat, 12 Apr 2025 15:21:33 +0000 Subject: [PATCH] feat: `hectic` C: generic result --- package/c/hectic/hectic.c | 84 +++++++++++++++++---------- package/c/hectic/hectic.h | 49 +++++++++++----- package/c/hectic/test/01-debug.c | 10 ++-- package/c/hectic/test/02-logger-rules | 16 +++++ 4 files changed, 107 insertions(+), 52 deletions(-) create mode 100755 package/c/hectic/test/02-logger-rules diff --git a/package/c/hectic/hectic.c b/package/c/hectic/hectic.c index 91720f4..05ea08d 100644 --- a/package/c/hectic/hectic.c +++ b/package/c/hectic/hectic.c @@ -226,10 +226,27 @@ char *string_to_debug_str__(CTX_DECLARATION, const char *name, const char *strin return arena_strdup_fmt__(CTX(arena), "%s = %p \"%s\"", name, string, string); } -char *number_to_debug_str__(CTX_DECLARATION, const char *name, int number) { +char *int_to_debug_str__(CTX_DECLARATION, const char *name, int number) { return arena_strdup_fmt__(CTX(arena), "%s = %d", name, number); } +char *float_to_debug_str__(CTX_DECLARATION, const char *name, double number) { + return arena_strdup_fmt__(CTX(arena), "%s = %f", name, number); +} + +char *size_t_to_debug_str__(CTX_DECLARATION, const char *name, size_t number) { + return arena_strdup_fmt__(CTX(arena), "%s = %zu", name, number); +} + +char *ptr_to_debug_str__(CTX_DECLARATION, const char *name, void *ptr) { + return arena_strdup_fmt__(CTX(arena), "%s = %p", name, ptr); +} + +char *char_to_debug_str__(CTX_DECLARATION, const char *name, char c) { + return arena_strdup_fmt__(CTX(arena), "%s = %c", name, c); +} + + /* Private function */ char *debug_join_debug_strings_v(CTX_DECLARATION, int count, va_list args) { raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "DEBUG JOIN: Joining %d strings", count); @@ -1718,6 +1735,19 @@ char* logger_rules_to_string(Arena *arena) { return buffer; } +char *log_rules_to_debug_str__(CTX_DECLARATION, char *name, LogRule *self, PtrSet *visited) { + char *result = arena_alloc(arena, MEM_KiB); + STRUCT_TO_DEBUG_STR(arena, result, LogRule, name, self, visited, 6, + string_to_debug_str__(POSITION_INFO, arena, "level", log_level_to_string(self->level)), + string_to_debug_str__(POSITION_INFO, arena, "file_pattern", self->file_pattern), + string_to_debug_str__(POSITION_INFO, arena, "function_pattern", self->function_pattern), + int_to_debug_str__(POSITION_INFO, arena, "line_start", self->line_start), + int_to_debug_str__(POSITION_INFO, arena, "line_end", self->line_end), + log_rules_to_debug_str__(POSITION_INFO, arena, "next", self->next, visited) + ); + return result; +} + // --------------- // -- Templater -- // --------------- @@ -1760,16 +1790,6 @@ bool template_validate_config__(POSITION_INFO_DECLARATION, const TemplateConfig return false; } - assert(config->Syntax.Braces.open != NULL); - assert(config->Syntax.Braces.close != NULL); - assert(config->Syntax.Section.control != NULL); - assert(config->Syntax.Section.source != NULL); - assert(config->Syntax.Section.begin != NULL); - assert(config->Syntax.Interpolate.invoke != NULL); - assert(config->Syntax.Include.invoke != NULL); - assert(config->Syntax.Execute.invoke != NULL); - assert(config->Syntax.nesting != NULL); - CHECK_CONFIG_STR(Braces.open, "Open brace"); CHECK_CONFIG_STR(Braces.close, "Close brace"); CHECK_CONFIG_STR(Section.control, "Section control"); @@ -1788,7 +1808,7 @@ bool template_validate_config__(POSITION_INFO_DECLARATION, const TemplateConfig #define TEMPLATE_ASSERT_SYNTAX(pattern, message_arg, code_arg) \ if (strncmp(*s, pattern, strlen(pattern))) { \ raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO, "PARSE: " message_arg); \ - result->type = TEMPLATE_RESULT_ERROR; \ + result->type = RESULT_ERROR; \ result->Result.error.code = code_arg; \ result->Result.error.message = message_arg; \ return result; \ @@ -1819,10 +1839,10 @@ TemplateResult *template_parse_interpolation__(POSITION_INFO_DECLARATION, Arena } size_t key_len = *s - key_start; - result->Result.node.value.interpolate.key = arena_strncpy__(POSITION_INFO, arena, key_start, key_len); + result->Result.some.value.interpolate.key = arena_strncpy__(POSITION_INFO, arena, key_start, key_len); - result->type = TEMPLATE_RESULT_NODE; - result->Result.node.type = TEMPLATE_NODE_INTERPOLATE; + result->type = RESULT_SOME; + result->Result.some.type = TEMPLATE_NODE_INTERPOLATE; *s_ptr = *s + strlen(config->Syntax.Braces.close); @@ -1833,8 +1853,8 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Section"); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); - result->type = TEMPLATE_RESULT_NODE; - result->Result.node.type = TEMPLATE_NODE_SECTION; + result->type = RESULT_SOME; + result->Result.some.type = TEMPLATE_NODE_SECTION; const char **s = s_ptr; @@ -1856,7 +1876,7 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena } size_t iterator_len = *s - iterator_start; - result->Result.node.value.section.iterator = arena_strncpy__(POSITION_INFO, arena, iterator_start, iterator_len); + result->Result.some.value.section.iterator = arena_strncpy__(POSITION_INFO, arena, iterator_start, iterator_len); // Find the collection name *s = skip_whitespace(*s); @@ -1871,15 +1891,15 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena } size_t collection_len = *s - collection_start; - result->Result.node.value.section.collection = arena_strncpy__(POSITION_INFO, arena, collection_start, collection_len); + result->Result.some.value.section.collection = arena_strncpy__(POSITION_INFO, arena, collection_start, collection_len); // Parse the body TemplateResult *body_result = template_parse__(POSITION_INFO, arena, s, config); - if (body_result->type == TEMPLATE_RESULT_ERROR) { + if (body_result->type == RESULT_ERROR) { return body_result; } - result->Result.node.value.section.body = &body_result->Result.node; + result->Result.some.value.section.body = &body_result->Result.some; *s_ptr = *s + strlen(config->Syntax.Braces.close); @@ -1889,8 +1909,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) { raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Include"); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); - result->type = TEMPLATE_RESULT_NODE; - result->Result.node.type = TEMPLATE_NODE_INCLUDE; + result->type = RESULT_SOME; + result->Result.some.type = TEMPLATE_NODE_INCLUDE; const char **s = s_ptr; @@ -1910,7 +1930,7 @@ TemplateResult *template_parse_include__(POSITION_INFO_DECLARATION, Arena *arena } size_t include_len = *s - include_start; - result->Result.node.value.include.key = arena_strncpy__(POSITION_INFO, arena, include_start, include_len); + result->Result.some.value.include.key = arena_strncpy__(POSITION_INFO, arena, include_start, include_len); *s_ptr = *s + strlen(config->Syntax.Braces.close); @@ -1921,8 +1941,8 @@ TemplateResult *template_parse_execute__(POSITION_INFO_DECLARATION, Arena *arena raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Execute"); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); - result->type = TEMPLATE_RESULT_NODE; - result->Result.node.type = TEMPLATE_NODE_EXECUTE; + result->type = RESULT_SOME; + result->Result.some.type = TEMPLATE_NODE_EXECUTE; const char **s = s_ptr; @@ -1939,7 +1959,7 @@ TemplateResult *template_parse_execute__(POSITION_INFO_DECLARATION, Arena *arena } size_t code_len = *s - code_start; - result->Result.node.value.execute.code = arena_strncpy__(POSITION_INFO, arena, code_start, code_len); + result->Result.some.value.execute.code = arena_strncpy__(POSITION_INFO, arena, code_start, code_len); *s_ptr = *s + strlen(config->Syntax.Braces.close); @@ -2002,7 +2022,7 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const TemplateResult *error_result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); - error_result->type = TEMPLATE_RESULT_ERROR; + error_result->type = RESULT_ERROR; error_result->Result.error.code = TEMPLATE_ERROR_UNKNOWN_TAG; error_result->Result.error.message = "Unknown tag prefix"; @@ -2010,11 +2030,11 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const } } - if (current_result->type == TEMPLATE_RESULT_ERROR) { + if (current_result->type == RESULT_ERROR) { return current_result; } - *current = current_result->Result.node; + *current = current_result->Result.some; current->next = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateNode)); current = current->next; } @@ -2029,8 +2049,8 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const } TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); - result->type = TEMPLATE_RESULT_NODE; - result->Result.node = *root; + result->type = RESULT_SOME; + result->Result.some = *root; return result; } diff --git a/package/c/hectic/hectic.h b/package/c/hectic/hectic.h index f36a9a2..d10833e 100644 --- a/package/c/hectic/hectic.h +++ b/package/c/hectic/hectic.h @@ -55,6 +55,20 @@ void set_output_color_mode(ColorMode mode); #define OPTIONAL_COLOR(color) (USE_COLOR() ? color : "") +typedef enum { + RESULT_ERROR, + RESULT_SOME, +} ResultType; + +#define RESULT(name, error_type, result_type) \ + typedef struct { \ + ResultType type; \ + union { \ + error_type error; \ + result_type some; \ + } Result; \ + } name##Result + // ------------ // -- Errors -- // ------------ @@ -378,14 +392,30 @@ char* logger_rules_to_string(Arena *arena); char *string_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, const char *string); -char *number_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, int number); +char *int_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, int number); + +char *float_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, double number); + +char *size_t_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, size_t number); + +char *ptr_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, void *ptr); + +char *char_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, char c); char *struct_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *type, const char *name, void *ptr, int count, ...); #define STRING_TO_DEBUG_STR(arena, name, string) \ string_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, string) -#define NUMBER_TO_DEBUG_STR(arena, name, number) \ - number_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, number) +#define INT_TO_DEBUG_STR(arena, name, number) \ + int_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, number) +#define FLOAT_TO_DEBUG_STR(arena, name, number) \ + float_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, number) +#define SIZE_T_TO_DEBUG_STR(arena, name, number) \ + size_t_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, number) +#define PTR_TO_DEBUG_STR(arena, name, ptr) \ + ptr_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, ptr) +#define CHAR_TO_DEBUG_STR(arena, name, c) \ + char_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, c) bool debug_ptrset_contains(PtrSet *set, void *ptr); @@ -600,18 +630,7 @@ struct TemplateNode { TemplateNode *next; // sibling nodes }; -typedef enum { - TEMPLATE_RESULT_ERROR, - TEMPLATE_RESULT_NODE, -} TemplateResultType; - -typedef struct { - TemplateResultType type; - union { - TemplateError error; - TemplateNode node; - } Result; -} TemplateResult; +RESULT(Template, TemplateError, TemplateNode); TemplateResult *template_parse__(const char *file, const char *func, int line, Arena *arena, const char **s, const TemplateConfig *config); diff --git a/package/c/hectic/test/01-debug.c b/package/c/hectic/test/01-debug.c index 6eeaedd..0cae17e 100755 --- a/package/c/hectic/test/01-debug.c +++ b/package/c/hectic/test/01-debug.c @@ -25,8 +25,8 @@ char *struct_to_debug_str(Arena *arena, char *name, Struct *self, PtrSet *visite char *result = arena_alloc(arena, MEM_KiB); STRUCT_TO_DEBUG_STR(arena, result, Struct, name, self, visited, 3, - NUMBER_TO_DEBUG_STR(arena, "a", self->a), - NUMBER_TO_DEBUG_STR(arena, "b", self->b), + INT_TO_DEBUG_STR(arena, "a", self->a), + INT_TO_DEBUG_STR(arena, "b", self->b), struct_to_debug_str(arena, "next", self->next, visited) ); return result; @@ -37,8 +37,8 @@ char *struct2_to_debug_str(Arena *arena, char *name, Struct2 *self, PtrSet *visi char *result = arena_alloc(arena, MEM_KiB); STRUCT_TO_DEBUG_STR(arena, result, Struct2, name, self, visited, 5, - NUMBER_TO_DEBUG_STR(arena, "a", self->a), - NUMBER_TO_DEBUG_STR(arena, "f", self->f), + INT_TO_DEBUG_STR(arena, "a", self->a), + FLOAT_TO_DEBUG_STR(arena, "f", self->f), STRING_TO_DEBUG_STR(arena, "c", self->c), struct_to_debug_str(arena, "other", self->other, visited), struct2_to_debug_str(arena, "left", self->left, visited) @@ -74,7 +74,7 @@ void test_struct2_to_debug_str(Arena *arena) { char *result = struct2_to_debug_str(arena, "struct2", &test_struct2, visited); raise_notice("result: %s", result); char *check = arena_alloc(arena, MEM_KiB); - sprintf(check, "Struct2 struct2 = {a = 1, f = 3, c = %p \"hello\", Struct other = {a = 1, b = 2, Struct next = {cycle detected} %p} %p, Struct2 left = NULL} %p", (void*)test_struct2.c,(void*)&test_struct, (void*)&test_struct, (void*)&test_struct2); + sprintf(check, "Struct2 struct2 = {a = 1, f = 3.140000, c = %p \"hello\", Struct other = {a = 1, b = 2, Struct next = {cycle detected} %p} %p, Struct2 left = NULL} %p", (void*)test_struct2.c,(void*)&test_struct, (void*)&test_struct, (void*)&test_struct2); raise_notice("check: %s", check); assert(strcmp(result, check) == 0); } diff --git a/package/c/hectic/test/02-logger-rules b/package/c/hectic/test/02-logger-rules new file mode 100755 index 0000000..8b23aca --- /dev/null +++ b/package/c/hectic/test/02-logger-rules @@ -0,0 +1,16 @@ +#include "hectic.h" +#include + +int main(void) { + printf("%sRunning %s%s%s\n", OPTIONAL_COLOR(COLOR_GREEN), OPTIONAL_COLOR(COLOR_CYAN), __FILE__, OPTIONAL_COLOR(COLOR_RESET)); + init_logger(); + + Arena arena = arena_init(MEM_MiB); + + char *rules = arena_alloc(&arena, MEM_KiB); + strcpy(rules, "trace:file:test.c:100-150"); + + arena_free(&arena); + printf("%sAll tests passed %s%s%s\n", OPTIONAL_COLOR(COLOR_GREEN), OPTIONAL_COLOR(COLOR_CYAN), __FILE__, OPTIONAL_COLOR(COLOR_RESET)); + return 0; +} \ No newline at end of file