From 5f52fc42af0473bd084d418649a6eb695e456884 Mon Sep 17 00:00:00 2001 From: yukkop Date: Sat, 10 May 2025 11:00:36 +0000 Subject: [PATCH] feat!: many work useles with hemar --- flake.nix | 231 ++++++++++++++++++--------- package/c/hectic/expected.log | 47 ++++++ package/c/hectic/hectic.c | 92 ++++++++++- package/c/hectic/hectic.h | 39 ++++- package/c/hectic/result.log | 47 ++++++ package/c/hectic/test/04-json.c | 10 +- package/c/hectic/test/06-templater.c | 81 +++++++++- package/c/hemar/default.nix | 17 ++ package/c/hemar/hemar--0.1.sql | 4 +- package/c/hemar/hemar.c | 62 ++++--- 10 files changed, 503 insertions(+), 127 deletions(-) create mode 100644 package/c/hectic/expected.log create mode 100644 package/c/hectic/result.log create mode 100755 package/c/hemar/default.nix diff --git a/flake.nix b/flake.nix index 64a1f4a..7daa12c 100644 --- a/flake.nix +++ b/flake.nix @@ -201,87 +201,161 @@ buildInputs = [pkgs.stack]; }); }; - nixosConfigurations."${system}_manual_test" = nixpkgs.lib.nixosSystem { - inherit system; - modules = [ - self.nixosModules."preset.default" - self.nixosModules."hardware.hetzner" - ({modulesPath, pkgs, ...}: { - imports = [ - (modulesPath + "/profiles/qemu-guest.nix") - ]; + nixosConfigurations = { + "${system}_manual_test" = nixpkgs.lib.nixosSystem { + inherit system; + modules = [ + self.nixosModules."preset.default" + self.nixosModules."hardware.hetzner" + ({modulesPath, pkgs, ...}: { + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; - users.users.root.openssh.authorizedKeys.keys = [ ]; - environment.systemPackages = with pkgs; [ - (pkgs.writers.writeMinCBin "minc-hello-world" [""] /*c*/ '' - printf("hello world\n"); - '') - (pkgs.writers.writeMinCBin "minc-env" ["" ""] /*c*/ '' - char *env_name; - if (argc > 1) { - env_name = argv[1]; - } else { - env_name = "HOME"; - } - char *value = getenv(env_name); - if (value) { - printf("%s: %s\n", env_name, value); - } else { - printf("Environment variable %s not found.\n", env_name); - } - '') - (pkgs.writers.writeMinCBin "minc-env-check" ["" ""] /*c*/ '' - char *env_name; - if (argc > 1) { - env_name = argv[1]; - } else { - env_name = "HOME"; - } + environment.systemPackages = with pkgs; [ + (pkgs.writers.writeMinCBin "minc-hello-world" [""] /*c*/ '' + printf("hello world\n"); + '') + (pkgs.writers.writeMinCBin "minc-env" ["" ""] /*c*/ '' + char *env_name; + if (argc > 1) { + env_name = argv[1]; + } else { + env_name = "HOME"; + } + char *value = getenv(env_name); + if (value) { + printf("%s: %s\n", env_name, value); + } else { + printf("Environment variable %s not found.\n", env_name); + } + '') + (pkgs.writers.writeMinCBin "minc-env-check" ["" ""] /*c*/ '' + char *env_name; + if (argc > 1) { + env_name = argv[1]; + } else { + env_name = "HOME"; + } - char *value = getenv(env_name); - if (value) { - char buffer[128]; - sprintf(buffer, "echo $%s\n", env_name); - system(buffer); - } else { - printf("Environment variable %s not found.\n", env_name); - } - '') - ]; - programs.zsh.shellAliases = { - jc = ''journalctl''; - sc = ''journalctl''; - nv = ''nvim''; - sd = "shutdown now"; - }; + char *value = getenv(env_name); + if (value) { + char buffer[128]; + sprintf(buffer, "echo $%s\n", env_name); + system(buffer); + } else { + printf("Environment variable %s not found.\n", env_name); + } + '') + ]; - virtualisation = { - vmVariant = { - systemd.services.fix-root-perms = { - description = "Fix root directory permissions"; - after = [ "local-fs.target" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.coreutils}/bin/chmod 755 /"; + users.users.root.openssh.authorizedKeys.keys = [ + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrbBG+U07f7OKvOxYIGYCaNvyozzxQF+I9Fb5TYZErK yukkop vm-postgres'' + ]; + + programs.zsh.shellAliases = self.lib.sharedShellAliases; + + virtualisation = { + vmVariant = { + systemd.services.fix-root-perms = { + description = "Fix root directory permissions"; + after = [ "local-fs.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.coreutils}/bin/chmod 755 /"; + }; + }; + virtualisation = { + diskSize = 1024*6; + diskImage = null; + forwardPorts = [ ]; }; }; - virtualisation = { - diskSize = 1024*6; - diskImage = null; - forwardPorts = [ ]; + }; + networking.firewall = { + enable = true; + allowedTCPPorts = [ + 80 + ]; + }; + }) + ]; + pkgs = import nixpkgs {inherit system; overlays = [ self.overlays.default ];}; + }; + "${system}_hemar_test" = nixpkgs.lib.nixosSystem { + inherit system; + modules = [ + self.nixosModules."preset.default" + self.nixosModules."hardware.hetzner" + ({modulesPath, pkgs, ...}: { + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + users.users.root.openssh.authorizedKeys.keys = [ + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrbBG+U07f7OKvOxYIGYCaNvyozzxQF+I9Fb5TYZErK yukkop vm-postgres'' + ]; + + services.postgresql = + let + package = pkgs.postgresql_15; + in { + enable = true; + package = package; + settings = + { + port = 64317; + listen_addresses = lib.mkForce "*"; + shared_preload_libraries = ""; + }; + extensions = [ package.pkgs.hemar ]; + authentication = builtins.concatStringsSep "\n" [ + "local all all trust" + "host sameuser all 127.0.0.1/32 scram-sha-256" + "host sameuser all ::1/128 scram-sha-256" + ]; + initialScript = pkgs.writeText "init-sql-script" '' + CREATE EXTENSION "hemar"; + + SELECT hemar.parse('{% zalupa %}'); + SELECT hemar.parse('{% zalupa %}'); + ''; + }; + + environment.systemPackages = with pkgs; [ ]; + programs.zsh.shellAliases = self.lib.sharedShellAliases // { + conn = "sudo su postgres -c 'psql -p 64317'"; + }; + + virtualisation = { + vmVariant = { + systemd.services.fix-root-perms = { + description = "Fix root directory permissions"; + after = [ "local-fs.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.coreutils}/bin/chmod 755 /"; + }; + }; + virtualisation = { + diskSize = 1024*6; + diskImage = null; + forwardPorts = [ ]; + }; }; }; - }; - networking.firewall = { - enable = true; - allowedTCPPorts = [ - 80 - ]; - }; - }) - ]; - pkgs = import nixpkgs {inherit system; overlays = [ self.overlays.default ];}; + networking.firewall = { + enable = true; + allowedTCPPorts = [ + 80 + ]; + }; + }) + ]; + pkgs = import nixpkgs {inherit system; overlays = [ self.overlays.default ];}; + }; }; }) // { @@ -532,6 +606,13 @@ # -- For all systems -- inherit dotEnv minorEnvironment parseEnv forAllSystemsWithPkgs forSpecSystemsWithPkgs; + sharedShellAliases = { + jc = ''journalctl''; + sc = ''journalctl''; + nv = ''nvim''; + sd = "shutdown now"; + }; + readEnvironment = { envVarsToRead, prefix ? "" }: builtins.listToAttrs (map (name: { @@ -560,4 +641,4 @@ }; }; }; -} \ No newline at end of file +} diff --git a/package/c/hectic/expected.log b/package/c/hectic/expected.log new file mode 100644 index 0000000..f836351 --- /dev/null +++ b/package/c/hectic/expected.log @@ -0,0 +1,47 @@ +[ + { + "type": "SECTION", + "content": { + "iterator": "item", + "collection": "items" + }, + "body": [ + { + "type": "INTERPOLATE", + "content": { + "key": "name" + } + }, + { + "type": "TEXT", + "content": { + "content": " " + } + }, + { + "type": "INTERPOLATE", + "content": { + "key": "item.name" + } + }, + { + "type": "TEXT", + "content": { + "content": " " + } + } + ] + }, + { + "type": "TEXT", + "content": { + "content": " " + } + }, + { + "type": "INTERPOLATE", + "content": { + "key": "name2" + } + } +] \ No newline at end of file diff --git a/package/c/hectic/hectic.c b/package/c/hectic/hectic.c index 3be4781..b545818 100644 --- a/package/c/hectic/hectic.c +++ b/package/c/hectic/hectic.c @@ -1429,14 +1429,14 @@ Json *json_parse__(POSITION_INFO_DECLARATION, Arena *arena, const char **s) { return result; } -char *json_to_string__(POSITION_INFO_DECLARATION, Arena *arena, const Json * const item) { - return json_to_string_with_opts__(POSITION_INFO, arena, item, JSON_NORAW); +char *json_to_str__(POSITION_INFO_DECLARATION, Arena *arena, const Json * const item) { + return json_to_str_with_opts__(POSITION_INFO, arena, item, JSON_NORAW); } /* Minimal JSON printer with raw output option. When raw is non-zero and the item is a JSON_STRING, it is printed without quotes. */ -char *json_to_string_with_opts__(POSITION_INFO_DECLARATION, Arena *arena, const Json * const item, JsonRawOpt raw) { +char *json_to_str_with_opts__(POSITION_INFO_DECLARATION, Arena *arena, const Json * const item, JsonRawOpt raw) { // Function entry with DEBUG level raise_message(LOG_LEVEL_DEBUG, POSITION_INFO, "FORMAT: Starting JSON conversion to string (item: %p, raw_mode: %s)", @@ -1479,7 +1479,7 @@ char *json_to_string_with_opts__(POSITION_INFO_DECLARATION, Arena *arena, const while (child) { ptr += sprintf(ptr, "\"%s\":", child->key ? child->key : ""); - char *child_str = json_to_string_with_opts__(POSITION_INFO, arena, child, raw); + char *child_str = json_to_str_with_opts__(POSITION_INFO, arena, child, raw); if (child_str) { ptr += sprintf(ptr, "%s", child_str); } else { @@ -1509,7 +1509,7 @@ char *json_to_string_with_opts__(POSITION_INFO_DECLARATION, Arena *arena, const "FORMAT: Processing JSON array elements"); while (child) { - char *child_str = json_to_string_with_opts__(POSITION_INFO, arena, child, raw); + char *child_str = json_to_str_with_opts__(POSITION_INFO, arena, child, raw); if (child_str) { ptr += sprintf(ptr, "%s", child_str); } else { @@ -2280,8 +2280,8 @@ TemplateConfig template_default_config__(POSITION_INFO_DECLARATION, Arena *arena }, .Section = { .control = string_to_view_ptr__(POSITION_INFO, arena, "for "), - .source = string_to_view_ptr__(POSITION_INFO, arena, " in "), - .begin = string_to_view_ptr__(POSITION_INFO, arena, " do ") + .source = string_to_view_ptr__(POSITION_INFO, arena, "in "), + .begin = string_to_view_ptr__(POSITION_INFO, arena, "do ") }, .Interpolate = { .invoke = string_to_view_ptr__(POSITION_INFO, arena, "") @@ -2862,6 +2862,84 @@ char *template_node_to_json_str__(POSITION_INFO_DECLARATION, Arena *arena, const return result; } +// ---------- +// -- diff -- +// ---------- + +//int diff_str__(POSITION_INFO_DECLARATION, Arena *arena, const char **str1, const char **str2) { +// if (!str1 || !str2) { +// return 0; +// } +// +// const char *s1 = *str1; +// const char *s2 = *str2; +// +// int diff = 0; +// +// while (*s1 && *s2) { +// if (*s1 != *s2) { +// diff++; +// } +// s1++; +// s2++; +// } +// +// return diff; +//} + +// -------------- +// -- Colorize -- +// -------------- + +char *colorize_partial_patterns(char *output, const char *input, PatternHighlight *patterns, size_t pattern_count) { + size_t len = strlen(input); + if (!output) return NULL; + size_t out_idx = 0; + + for (size_t i = 0; i < len;) { + int matched = 0; + for (size_t j = 0; j < pattern_count; j++) { + size_t pat_len = strlen(patterns[j].pattern); + if (strncmp(&input[i], patterns[j].pattern, pat_len) == 0) { + const char *pre = &input[i]; + const char *hl_start = &input[i + patterns[j].highlight_start]; + const char *hl_end = &input[i + patterns[j].highlight_start + patterns[j].highlight_len]; + + // Copy pre-highlight part + size_t pre_len = patterns[j].highlight_start; + memcpy(&output[out_idx], pre, pre_len); + out_idx += pre_len; + + // Add color code and highlighted part + size_t color_len = strlen(patterns[j].color); + memcpy(&output[out_idx], patterns[j].color, color_len); + out_idx += color_len; + + memcpy(&output[out_idx], hl_start, patterns[j].highlight_len); + out_idx += patterns[j].highlight_len; + + memcpy(&output[out_idx], "\033[0m", 4); + out_idx += 4; + + // Copy post-highlight part + size_t post_len = pat_len - patterns[j].highlight_start - patterns[j].highlight_len; + memcpy(&output[out_idx], hl_end, post_len); + out_idx += post_len; + + i += pat_len; + matched = 1; + break; + } + } + if (!matched) { + output[out_idx++] = input[i++]; + } + } + + output[out_idx] = '\0'; + return output; +} + // --------- // -- End -- // --------- diff --git a/package/c/hectic/hectic.h b/package/c/hectic/hectic.h index 2fd662b..e06a88d 100644 --- a/package/c/hectic/hectic.h +++ b/package/c/hectic/hectic.h @@ -427,6 +427,8 @@ char* arena_strncpy__(const char *file, const char *func, int line, Arena *arena static Arena disposable_arena __attribute__((unused)) = {0}; +#define DISPOSABLE_ARENA_FREE arena_free(&disposable_arena) + #define DISPOSABLE_ARENA __extension__ ({ \ if (disposable_arena.begin == NULL) { \ disposable_arena = arena_init__(__FILE__, __func__, __LINE__, MEM_MiB * 8); \ @@ -653,11 +655,11 @@ RESULT(Json, Json); Json *json_parse__(const char* file, const char* func, int line, Arena *arena, const char **s); #define json_parse(arena, s) json_parse__(__FILE__, __func__, __LINE__, arena, s) -char *json_to_string__(const char* file, const char* func, int line, Arena *arena, const Json * const item); -#define json_to_string(arena, item) json_to_string__(__FILE__, __func__, __LINE__, arena, item) +char *json_to_str__(const char* file, const char* func, int line, Arena *arena, const Json * const item); +#define JSON_TO_STR(arena, item) json_to_str__(__FILE__, __func__, __LINE__, arena, item) -#define json_to_string_with_opts(arena, item, raw) json_to_string_with_opts__(__FILE__, __func__, __LINE__, arena, item, raw) -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_str_with_opts__(const char* file, const char* func, int line, Arena *arena, const Json * const item, JsonRawOpt raw); +#define JSON_TO_STR_WITH_OPTS(arena, item, raw) json_to_str_with_opts__(__FILE__, __func__, __LINE__, arena, item, raw) /* Retrieve an object item by key (case-sensitive) */ Json *json_get_object_item__(const char* file, const char* func, int line, const Json * const object, const char * const key); @@ -839,4 +841,31 @@ TemplateNode init_template_node__(const char *file, const char *func, int line, #define init_template_node(arena, type) \ init_template_node__(__FILE__, __func__, __LINE__, arena, type) -#endif // EPRINTF_H \ No newline at end of file +#define TEMPLATE_NODE_DISPOSABLE_JSON(node) __extension__ ({ \ + Arena *debug_arena = DISPOSABLE_ARENA; \ + const char *json_str = TEMPLATE_NODE_TO_JSON_STR(debug_arena, &node); \ + Json *json = json_parse(debug_arena, &json_str); \ + arena_strdup(debug_arena, JSON_TO_PRETTY_STR(debug_arena, json)); \ +}) + +#define TEMPLATE_NODE_PRETTY_JSON(node, arena) __extension__ ({ \ + Arena *debug_arena = DISPOSABLE_ARENA; \ + const char *json_str = TEMPLATE_NODE_TO_JSON_STR(debug_arena, &node); \ + Json *json = json_parse(debug_arena, &json_str); \ + arena_strdup(arena, JSON_TO_PRETTY_STR(debug_arena, json)); \ +}) + +// -------------- +// -- Colorize -- +// -------------- + +typedef struct { + const char *pattern; + int highlight_start; + int highlight_len; + const char *color; +} PatternHighlight; + +char *colorize_partial_patterns(char *output, const char *input, PatternHighlight *patterns, size_t pattern_count); + +#endif // EPRINTF_H diff --git a/package/c/hectic/result.log b/package/c/hectic/result.log new file mode 100644 index 0000000..f836351 --- /dev/null +++ b/package/c/hectic/result.log @@ -0,0 +1,47 @@ +[ + { + "type": "SECTION", + "content": { + "iterator": "item", + "collection": "items" + }, + "body": [ + { + "type": "INTERPOLATE", + "content": { + "key": "name" + } + }, + { + "type": "TEXT", + "content": { + "content": " " + } + }, + { + "type": "INTERPOLATE", + "content": { + "key": "item.name" + } + }, + { + "type": "TEXT", + "content": { + "content": " " + } + } + ] + }, + { + "type": "TEXT", + "content": { + "content": " " + } + }, + { + "type": "INTERPOLATE", + "content": { + "key": "name2" + } + } +] \ No newline at end of file diff --git a/package/c/hectic/test/04-json.c b/package/c/hectic/test/04-json.c index 95e6924..ced4bcf 100644 --- a/package/c/hectic/test/04-json.c +++ b/package/c/hectic/test/04-json.c @@ -53,7 +53,7 @@ static void test_get_object_items(Arena *arena) { static void test_print_json_object(Arena *arena) { const char *json = "{\"key\":\"value\", \"num\":3.14}"; Json *root = json_parse(arena, &json); - char *printed = json_to_string(arena, root); + char *printed = JSON_TO_STR(arena, root); assert(strstr(printed, "\"key\":") != NULL); assert(strstr(printed, "\"value\"") != NULL); assert(strstr(printed, "\"num\":") != NULL); @@ -64,7 +64,7 @@ static void test_print_json_object(Arena *arena) { static void test_print_json_number(Arena *arena) { const char *json = "123.456"; Json *root = json_parse(arena, &json); - char *printed = json_to_string(arena, root); + char *printed = JSON_TO_STR(arena, root); double val = atof(printed); assert(val == 123.456); } @@ -73,7 +73,7 @@ static void test_print_json_number(Arena *arena) { static void test_print_json_string(Arena *arena) { const char *json = "\"test string\""; Json *root = json_parse(arena, &json); - char *printed = json_to_string(arena, root); + char *printed = JSON_TO_STR(arena, root); assert(strcmp(printed, "\"test string\"") == 0); } @@ -99,12 +99,12 @@ static void test_nested_json_object(Arena *arena) { static void test_arena_reset_reuse(Arena *arena) { const char *json1 = "{\"key\":\"value\"}"; Json *root1 = json_parse(arena, &json1); - char *printed1 = json_to_string(arena, root1); + char *printed1 = JSON_TO_STR(arena, root1); assert(strcmp(printed1, "{\"key\":\"value\"}") == 0); arena_reset(arena); const char *json2 = "\"another test\""; Json *root2 = json_parse(arena, &json2); - char *printed2 = json_to_string(arena, root2); + char *printed2 = JSON_TO_STR(arena, root2); assert(strcmp(printed2, "\"another test\"") == 0); } diff --git a/package/c/hectic/test/06-templater.c b/package/c/hectic/test/06-templater.c index a2a29a8..d04c106 100755 --- a/package/c/hectic/test/06-templater.c +++ b/package/c/hectic/test/06-templater.c @@ -233,12 +233,87 @@ static void simplest_separator_test_template_parse(Arena *arena, TemplateConfig TemplateNode node = RESULT_SOME_VALUE(template_result); + char *result_str = TEMPLATE_NODE_PRETTY_JSON(node, arena); + + char *expected_result_str = arena_strdup(arena, + "[\n" + " {\n" + " \"type\": \"SECTION\",\n" + " \"content\": {\n" + " \"iterator\": \"item\",\n" + " \"collection\": \"items\"\n" + " },\n" + " \"body\": [\n" + " {\n" + " \"type\": \"INTERPOLATE\",\n" + " \"content\": {\n" + " \"key\": \"name\"\n" + " }\n" + " },\n" + " {\n" + " \"type\": \"TEXT\",\n" + " \"content\": {\n" + " \"content\": \" \"\n" + " }\n" + " },\n" + " {\n" + " \"type\": \"INTERPOLATE\",\n" + " \"content\": {\n" + " \"key\": \"item.name\"\n" + " }\n" + " },\n" + " {\n" + " \"type\": \"TEXT\",\n" + " \"content\": {\n" + " \"content\": \" \"\n" + " }\n" + " }\n" + " ]\n" + " },\n" + " {\n" + " \"type\": \"TEXT\",\n" + " \"content\": {\n" + " \"content\": \" \"\n" + " }\n" + " },\n" + " {\n" + " \"type\": \"INTERPOLATE\",\n" + " \"content\": {\n" + " \"key\": \"name2\"\n" + " }\n" + " }\n" + "]"); + + raise_log("result_str: \n%s", result_str); + + assert(strcmp(result_str, expected_result_str) == 0); +} + +static void simplest_execute_test_template_parse(Arena *arena, TemplateConfig *config) { + const char *template_str = + "{% %}" + "{% execute RETURN 'aaaaaa' %}" + "{% name %}" + "{% name2 %}" + "{% name3 %}"; + + TemplateResult template_result = template_parse(arena, &template_str, config); + + if (IS_RESULT_ERROR(template_result)) { + raise_exception("template_parse failed"); + return; + } + + TemplateNode node = RESULT_SOME_VALUE(template_result); + + //char *result_str; { // some debug output Arena *debug_arena = DISPOSABLE_ARENA; const char *json_str = TEMPLATE_NODE_TO_JSON_STR(debug_arena, &node); raise_log("json_str: \n%s", json_str); Json *json = json_parse(debug_arena, &json_str); raise_notice("json_str: \n%s", JSON_TO_PRETTY_STR(debug_arena, json)); + //result_str = arena_strdup(arena, JSON_TO_PRETTY_STR(debug_arena, json)); } } @@ -274,9 +349,13 @@ int main(void) { printf("%sTest 4: simplest_separator_test_template_parse passed%s\n", OPTIONAL_COLOR(COLOR_GREEN), OPTIONAL_COLOR(COLOR_RESET)); arena_reset(&arena); + simplest_execute_test_template_parse(&arena, &config); + printf("%sTest 5: simplest_execute_test_template_parse passed%s\n", OPTIONAL_COLOR(COLOR_GREEN), OPTIONAL_COLOR(COLOR_RESET)); + arena_reset(&arena); + logger_free(); arena_free(&config_arena); 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 +} diff --git a/package/c/hemar/default.nix b/package/c/hemar/default.nix new file mode 100755 index 0000000..91817bd --- /dev/null +++ b/package/c/hemar/default.nix @@ -0,0 +1,17 @@ +{ postgresql, pkg-config, patchelf }: +buildPostgresqlExtension { inherit postgresql; } { + pname = "hemar"; + version = "0.1"; + src = ./.; + + nativeBuildInputs = [pkg-config c-hectic]; + + dontShrinkRPath = true; + + postFixup = '' + echo ">>> postFixup running..." + ${patchelf}/bin/patchelf --set-rpath ${c-hectic}/lib $out/lib/hemar.so + ''; + + preInstall = ''mkdir $out''; +}; \ No newline at end of file diff --git a/package/c/hemar/hemar--0.1.sql b/package/c/hemar/hemar--0.1.sql index f49a958..ede0943 100755 --- a/package/c/hemar/hemar--0.1.sql +++ b/package/c/hemar/hemar--0.1.sql @@ -40,7 +40,7 @@ RETURNS void AS 'hemar', 'pg_test_log_2' LANGUAGE C STRICT; -CREATE FUNCTION "hemar"."template_parse"(text) -RETURNS void +CREATE FUNCTION "hemar"."parse"("template" text) +RETURNS text AS 'hemar', 'pg_template_parse' LANGUAGE C STRICT; diff --git a/package/c/hemar/hemar.c b/package/c/hemar/hemar.c index 1fb1c75..8bd2455 100755 --- a/package/c/hemar/hemar.c +++ b/package/c/hemar/hemar.c @@ -14,14 +14,14 @@ PG_MODULE_MAGIC; #define INIT \ logger_init(); \ - logger_level(LOG_LEVEL_TRACE); \ logger_set_file(LOG_FILE); \ logger_set_output_mode(LOG_OUTPUT_BOTH); \ Arena arena = arena_init(MEM_MiB); #define FREE \ + DISPOSABLE_ARENA_FREE; \ arena_free(&arena); \ - logger_free(); + logger_free(); /* helper function to get a JSON value by key path */ static Json *json_get_by_path(Arena *arena, const Json *context, const char *key_path) { @@ -66,7 +66,7 @@ static char *json_value_to_string(Arena *arena, const Json *json) { return ""; case JSON_ARRAY: case JSON_OBJECT: - return json_to_string(arena, json); + return JSON_TO_STR(arena, json); default: return ""; } @@ -81,7 +81,7 @@ static char *render_text_node(Arena *arena, const TemplateNode *node) { return ""; } - return node->value.text.content; + return node->value->text.content; } /* Render an interpolation node */ @@ -93,7 +93,7 @@ static char *render_interpolation_node(Arena *arena, const TemplateNode *node, c return ""; } - key = node->value.interpolate.key; + key = node->value->interpolate.key; value = json_get_by_path(arena, context, key); if (!value) { @@ -129,9 +129,9 @@ static char *render_section_node(Arena *arena, const TemplateNode *node, const J return ""; } - collection_key = node->value.section.collection; - iterator_name = node->value.section.iterator; - body = node->value.section.body; + collection_key = node->value->section.collection; + iterator_name = node->value->section.iterator; + body = node->value->section.body; collection = json_get_by_path(arena, context, collection_key); @@ -191,7 +191,7 @@ static char *render_include_node(Arena *arena, const TemplateNode *node, const J if (!node || node->type != TEMPLATE_NODE_INCLUDE || !context) { return ""; } - include_key = node->value.include.key; + include_key = node->value->include.key; include_value = json_get_by_path(arena, context, include_key); if (!include_value || include_value->type != JSON_ARRAY) { @@ -213,7 +213,7 @@ static char *render_include_node(Arena *arena, const TemplateNode *node, const J const char *template_str = template_json->value.string; const Json *include_context = context_json ? context_json : context; - TemplateConfig config = template_default_config(); + TemplateConfig config = template_default_config(arena); TemplateResult template_result = template_parse(arena, &template_str, &config); if (!IS_RESULT_ERROR(template_result)) { @@ -290,19 +290,6 @@ static char *render_template_node(Arena *arena, const TemplateNode *node, const strcpy(output + output_pos, rendered); output_pos += rendered_len; - if (current->children) { - char *children_rendered = render_template_node(arena, current->children, context); - size_t children_len = strlen(children_rendered); - - if (output_pos + children_len + 1 > buffer_size) { - buffer_size = (output_pos + children_len + 1) * 2; - output = arena_realloc(arena, output, buffer_size / 2, buffer_size); - } - - strcpy(output + output_pos, children_rendered); - output_pos += children_len; - } - current = current->next; } @@ -338,7 +325,6 @@ Datum pg_render(PG_FUNCTION_ARGS) TemplateNode root_node; TemplateResult template_result; - TemplateConfig config; Json *context; @@ -349,6 +335,7 @@ Datum pg_render(PG_FUNCTION_ARGS) /* Parse the JSON context */ const char *json_ptr = context_str; + TemplateConfig config = template_default_config(&arena); context = json_parse(&arena, &json_ptr); if (!context) { @@ -359,7 +346,6 @@ Datum pg_render(PG_FUNCTION_ARGS) /* Parse the template text */ template_ptr = template_str; - config = template_default_config(); template_result = template_parse(&arena, &template_ptr, &config); if (IS_RESULT_ERROR(template_result)) { @@ -411,13 +397,16 @@ PG_FUNCTION_INFO_V1(pg_template_parse); Datum pg_template_parse(PG_FUNCTION_ARGS) { INIT; - TemplateConfig config; + text *context_text = PG_GETARG_TEXT_PP(0); + char *content = text_to_cstring(context_text); + const char *template_ptr; TemplateResult template_result; + TemplateConfig config = template_default_config(&arena); - template_ptr = "{{ name }}"; - config = template_default_config(); + raise_info("start parsing...."); template_result = template_parse(&arena, &template_ptr, &config); + raise_info("parsing finished...."); if (IS_RESULT_ERROR(template_result)) { FREE; @@ -426,9 +415,18 @@ Datum pg_template_parse(PG_FUNCTION_ARGS) { RESULT_ERROR_MESSAGE(template_result)))); } - const char *json_str = "{\"a\": 1}"; - Jsonb *jb = DatumGetJsonbP(DirectFunctionCall1(jsonb_in, CStringGetDatum(json_str))); + const char *json_str = TEMPLATE_NODE_TO_JSON_STR(&arena, &(RESULT_SOME_VALUE(template_result))); + Json *json = json_parse(&arena, &json_str); \ + + char *result_str = JSON_TO_STR(&arena, json); + + raise_notice("%s", result_str); + + char *result_str_clone = malloc(strlen(result_str) + 1); + if (result_str_clone) strcpy(result_str_clone, result_str); FREE; - PG_RETURN_VOID(); -} \ No newline at end of file + + text *result = cstring_to_text(result_str_clone); + PG_RETURN_TEXT_P(result); +}