feat!: many work useles with hemar
This commit is contained in:
95
flake.nix
95
flake.nix
@@ -201,7 +201,8 @@
|
|||||||
buildInputs = [pkgs.stack];
|
buildInputs = [pkgs.stack];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
nixosConfigurations."${system}_manual_test" = nixpkgs.lib.nixosSystem {
|
nixosConfigurations = {
|
||||||
|
"${system}_manual_test" = nixpkgs.lib.nixosSystem {
|
||||||
inherit system;
|
inherit system;
|
||||||
modules = [
|
modules = [
|
||||||
self.nixosModules."preset.default"
|
self.nixosModules."preset.default"
|
||||||
@@ -211,7 +212,6 @@
|
|||||||
(modulesPath + "/profiles/qemu-guest.nix")
|
(modulesPath + "/profiles/qemu-guest.nix")
|
||||||
];
|
];
|
||||||
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [ ];
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
(pkgs.writers.writeMinCBin "minc-hello-world" ["<stdio.h>"] /*c*/ ''
|
(pkgs.writers.writeMinCBin "minc-hello-world" ["<stdio.h>"] /*c*/ ''
|
||||||
printf("hello world\n");
|
printf("hello world\n");
|
||||||
@@ -248,11 +248,84 @@
|
|||||||
}
|
}
|
||||||
'')
|
'')
|
||||||
];
|
];
|
||||||
programs.zsh.shellAliases = {
|
|
||||||
jc = ''journalctl'';
|
users.users.root.openssh.authorizedKeys.keys = [
|
||||||
sc = ''journalctl'';
|
''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrbBG+U07f7OKvOxYIGYCaNvyozzxQF+I9Fb5TYZErK yukkop vm-postgres''
|
||||||
nv = ''nvim'';
|
];
|
||||||
sd = "shutdown now";
|
|
||||||
|
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 = [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
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 = {
|
virtualisation = {
|
||||||
@@ -283,6 +356,7 @@
|
|||||||
];
|
];
|
||||||
pkgs = import nixpkgs {inherit system; overlays = [ self.overlays.default ];};
|
pkgs = import nixpkgs {inherit system; overlays = [ self.overlays.default ];};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
})
|
})
|
||||||
// {
|
// {
|
||||||
nixosModules = {
|
nixosModules = {
|
||||||
@@ -532,6 +606,13 @@
|
|||||||
# -- For all systems --
|
# -- For all systems --
|
||||||
inherit dotEnv minorEnvironment parseEnv forAllSystemsWithPkgs forSpecSystemsWithPkgs;
|
inherit dotEnv minorEnvironment parseEnv forAllSystemsWithPkgs forSpecSystemsWithPkgs;
|
||||||
|
|
||||||
|
sharedShellAliases = {
|
||||||
|
jc = ''journalctl'';
|
||||||
|
sc = ''journalctl'';
|
||||||
|
nv = ''nvim'';
|
||||||
|
sd = "shutdown now";
|
||||||
|
};
|
||||||
|
|
||||||
readEnvironment = { envVarsToRead, prefix ? "" }:
|
readEnvironment = { envVarsToRead, prefix ? "" }:
|
||||||
builtins.listToAttrs
|
builtins.listToAttrs
|
||||||
(map (name: {
|
(map (name: {
|
||||||
|
|||||||
47
package/c/hectic/expected.log
Normal file
47
package/c/hectic/expected.log
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1429,14 +1429,14 @@ Json *json_parse__(POSITION_INFO_DECLARATION, Arena *arena, const char **s) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *json_to_string__(POSITION_INFO_DECLARATION, Arena *arena, const Json * const item) {
|
char *json_to_str__(POSITION_INFO_DECLARATION, Arena *arena, const Json * const item) {
|
||||||
return json_to_string_with_opts__(POSITION_INFO, arena, item, JSON_NORAW);
|
return json_to_str_with_opts__(POSITION_INFO, arena, item, JSON_NORAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Minimal JSON printer with raw output option.
|
/* Minimal JSON printer with raw output option.
|
||||||
When raw is non-zero and the item is a JSON_STRING, it is printed without quotes.
|
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
|
// Function entry with DEBUG level
|
||||||
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
|
raise_message(LOG_LEVEL_DEBUG, POSITION_INFO,
|
||||||
"FORMAT: Starting JSON conversion to string (item: %p, raw_mode: %s)",
|
"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) {
|
while (child) {
|
||||||
ptr += sprintf(ptr, "\"%s\":", child->key ? child->key : "");
|
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) {
|
if (child_str) {
|
||||||
ptr += sprintf(ptr, "%s", child_str);
|
ptr += sprintf(ptr, "%s", child_str);
|
||||||
} else {
|
} else {
|
||||||
@@ -1509,7 +1509,7 @@ char *json_to_string_with_opts__(POSITION_INFO_DECLARATION, Arena *arena, const
|
|||||||
"FORMAT: Processing JSON array elements");
|
"FORMAT: Processing JSON array elements");
|
||||||
|
|
||||||
while (child) {
|
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) {
|
if (child_str) {
|
||||||
ptr += sprintf(ptr, "%s", child_str);
|
ptr += sprintf(ptr, "%s", child_str);
|
||||||
} else {
|
} else {
|
||||||
@@ -2862,6 +2862,84 @@ char *template_node_to_json_str__(POSITION_INFO_DECLARATION, Arena *arena, const
|
|||||||
return result;
|
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 --
|
// -- End --
|
||||||
// ---------
|
// ---------
|
||||||
|
|||||||
@@ -427,6 +427,8 @@ char* arena_strncpy__(const char *file, const char *func, int line, Arena *arena
|
|||||||
|
|
||||||
static Arena disposable_arena __attribute__((unused)) = {0};
|
static Arena disposable_arena __attribute__((unused)) = {0};
|
||||||
|
|
||||||
|
#define DISPOSABLE_ARENA_FREE arena_free(&disposable_arena)
|
||||||
|
|
||||||
#define DISPOSABLE_ARENA __extension__ ({ \
|
#define DISPOSABLE_ARENA __extension__ ({ \
|
||||||
if (disposable_arena.begin == NULL) { \
|
if (disposable_arena.begin == NULL) { \
|
||||||
disposable_arena = arena_init__(__FILE__, __func__, __LINE__, MEM_MiB * 8); \
|
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);
|
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)
|
#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);
|
char *json_to_str__(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)
|
#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_str_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);
|
#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) */
|
/* 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);
|
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) \
|
#define init_template_node(arena, type) \
|
||||||
init_template_node__(__FILE__, __func__, __LINE__, arena, type)
|
init_template_node__(__FILE__, __func__, __LINE__, arena, type)
|
||||||
|
|
||||||
|
#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
|
#endif // EPRINTF_H
|
||||||
47
package/c/hectic/result.log
Normal file
47
package/c/hectic/result.log
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -53,7 +53,7 @@ static void test_get_object_items(Arena *arena) {
|
|||||||
static void test_print_json_object(Arena *arena) {
|
static void test_print_json_object(Arena *arena) {
|
||||||
const char *json = "{\"key\":\"value\", \"num\":3.14}";
|
const char *json = "{\"key\":\"value\", \"num\":3.14}";
|
||||||
Json *root = json_parse(arena, &json);
|
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, "\"key\":") != NULL);
|
||||||
assert(strstr(printed, "\"value\"") != NULL);
|
assert(strstr(printed, "\"value\"") != NULL);
|
||||||
assert(strstr(printed, "\"num\":") != 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) {
|
static void test_print_json_number(Arena *arena) {
|
||||||
const char *json = "123.456";
|
const char *json = "123.456";
|
||||||
Json *root = json_parse(arena, &json);
|
Json *root = json_parse(arena, &json);
|
||||||
char *printed = json_to_string(arena, root);
|
char *printed = JSON_TO_STR(arena, root);
|
||||||
double val = atof(printed);
|
double val = atof(printed);
|
||||||
assert(val == 123.456);
|
assert(val == 123.456);
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ static void test_print_json_number(Arena *arena) {
|
|||||||
static void test_print_json_string(Arena *arena) {
|
static void test_print_json_string(Arena *arena) {
|
||||||
const char *json = "\"test string\"";
|
const char *json = "\"test string\"";
|
||||||
Json *root = json_parse(arena, &json);
|
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);
|
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) {
|
static void test_arena_reset_reuse(Arena *arena) {
|
||||||
const char *json1 = "{\"key\":\"value\"}";
|
const char *json1 = "{\"key\":\"value\"}";
|
||||||
Json *root1 = json_parse(arena, &json1);
|
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);
|
assert(strcmp(printed1, "{\"key\":\"value\"}") == 0);
|
||||||
arena_reset(arena);
|
arena_reset(arena);
|
||||||
const char *json2 = "\"another test\"";
|
const char *json2 = "\"another test\"";
|
||||||
Json *root2 = json_parse(arena, &json2);
|
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);
|
assert(strcmp(printed2, "\"another test\"") == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -233,12 +233,87 @@ static void simplest_separator_test_template_parse(Arena *arena, TemplateConfig
|
|||||||
|
|
||||||
TemplateNode node = RESULT_SOME_VALUE(template_result);
|
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
|
{ // some debug output
|
||||||
Arena *debug_arena = DISPOSABLE_ARENA;
|
Arena *debug_arena = DISPOSABLE_ARENA;
|
||||||
const char *json_str = TEMPLATE_NODE_TO_JSON_STR(debug_arena, &node);
|
const char *json_str = TEMPLATE_NODE_TO_JSON_STR(debug_arena, &node);
|
||||||
raise_log("json_str: \n%s", json_str);
|
raise_log("json_str: \n%s", json_str);
|
||||||
Json *json = json_parse(debug_arena, &json_str);
|
Json *json = json_parse(debug_arena, &json_str);
|
||||||
raise_notice("json_str: \n%s", JSON_TO_PRETTY_STR(debug_arena, json));
|
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,6 +349,10 @@ int main(void) {
|
|||||||
printf("%sTest 4: simplest_separator_test_template_parse passed%s\n", OPTIONAL_COLOR(COLOR_GREEN), OPTIONAL_COLOR(COLOR_RESET));
|
printf("%sTest 4: simplest_separator_test_template_parse passed%s\n", OPTIONAL_COLOR(COLOR_GREEN), OPTIONAL_COLOR(COLOR_RESET));
|
||||||
arena_reset(&arena);
|
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();
|
logger_free();
|
||||||
arena_free(&config_arena);
|
arena_free(&config_arena);
|
||||||
arena_free(&arena);
|
arena_free(&arena);
|
||||||
|
|||||||
17
package/c/hemar/default.nix
Executable file
17
package/c/hemar/default.nix
Executable file
@@ -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'';
|
||||||
|
};
|
||||||
@@ -40,7 +40,7 @@ RETURNS void
|
|||||||
AS 'hemar', 'pg_test_log_2'
|
AS 'hemar', 'pg_test_log_2'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
CREATE FUNCTION "hemar"."template_parse"(text)
|
CREATE FUNCTION "hemar"."parse"("template" text)
|
||||||
RETURNS void
|
RETURNS text
|
||||||
AS 'hemar', 'pg_template_parse'
|
AS 'hemar', 'pg_template_parse'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ PG_MODULE_MAGIC;
|
|||||||
|
|
||||||
#define INIT \
|
#define INIT \
|
||||||
logger_init(); \
|
logger_init(); \
|
||||||
logger_level(LOG_LEVEL_TRACE); \
|
|
||||||
logger_set_file(LOG_FILE); \
|
logger_set_file(LOG_FILE); \
|
||||||
logger_set_output_mode(LOG_OUTPUT_BOTH); \
|
logger_set_output_mode(LOG_OUTPUT_BOTH); \
|
||||||
Arena arena = arena_init(MEM_MiB);
|
Arena arena = arena_init(MEM_MiB);
|
||||||
|
|
||||||
#define FREE \
|
#define FREE \
|
||||||
|
DISPOSABLE_ARENA_FREE; \
|
||||||
arena_free(&arena); \
|
arena_free(&arena); \
|
||||||
logger_free();
|
logger_free();
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ static char *json_value_to_string(Arena *arena, const Json *json) {
|
|||||||
return "";
|
return "";
|
||||||
case JSON_ARRAY:
|
case JSON_ARRAY:
|
||||||
case JSON_OBJECT:
|
case JSON_OBJECT:
|
||||||
return json_to_string(arena, json);
|
return JSON_TO_STR(arena, json);
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ static char *render_text_node(Arena *arena, const TemplateNode *node) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return node->value.text.content;
|
return node->value->text.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render an interpolation node */
|
/* Render an interpolation node */
|
||||||
@@ -93,7 +93,7 @@ static char *render_interpolation_node(Arena *arena, const TemplateNode *node, c
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
key = node->value.interpolate.key;
|
key = node->value->interpolate.key;
|
||||||
value = json_get_by_path(arena, context, key);
|
value = json_get_by_path(arena, context, key);
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
@@ -129,9 +129,9 @@ static char *render_section_node(Arena *arena, const TemplateNode *node, const J
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
collection_key = node->value.section.collection;
|
collection_key = node->value->section.collection;
|
||||||
iterator_name = node->value.section.iterator;
|
iterator_name = node->value->section.iterator;
|
||||||
body = node->value.section.body;
|
body = node->value->section.body;
|
||||||
|
|
||||||
collection = json_get_by_path(arena, context, collection_key);
|
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) {
|
if (!node || node->type != TEMPLATE_NODE_INCLUDE || !context) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
include_key = node->value.include.key;
|
include_key = node->value->include.key;
|
||||||
include_value = json_get_by_path(arena, context, include_key);
|
include_value = json_get_by_path(arena, context, include_key);
|
||||||
|
|
||||||
if (!include_value || include_value->type != JSON_ARRAY) {
|
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 char *template_str = template_json->value.string;
|
||||||
const Json *include_context = context_json ? context_json : context;
|
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);
|
TemplateResult template_result = template_parse(arena, &template_str, &config);
|
||||||
|
|
||||||
if (!IS_RESULT_ERROR(template_result)) {
|
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);
|
strcpy(output + output_pos, rendered);
|
||||||
output_pos += rendered_len;
|
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;
|
current = current->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +325,6 @@ Datum pg_render(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
TemplateNode root_node;
|
TemplateNode root_node;
|
||||||
TemplateResult template_result;
|
TemplateResult template_result;
|
||||||
TemplateConfig config;
|
|
||||||
|
|
||||||
Json *context;
|
Json *context;
|
||||||
|
|
||||||
@@ -349,6 +335,7 @@ Datum pg_render(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Parse the JSON context */
|
/* Parse the JSON context */
|
||||||
const char *json_ptr = context_str;
|
const char *json_ptr = context_str;
|
||||||
|
TemplateConfig config = template_default_config(&arena);
|
||||||
context = json_parse(&arena, &json_ptr);
|
context = json_parse(&arena, &json_ptr);
|
||||||
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
@@ -359,7 +346,6 @@ Datum pg_render(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Parse the template text */
|
/* Parse the template text */
|
||||||
template_ptr = template_str;
|
template_ptr = template_str;
|
||||||
config = template_default_config();
|
|
||||||
template_result = template_parse(&arena, &template_ptr, &config);
|
template_result = template_parse(&arena, &template_ptr, &config);
|
||||||
|
|
||||||
if (IS_RESULT_ERROR(template_result)) {
|
if (IS_RESULT_ERROR(template_result)) {
|
||||||
@@ -411,13 +397,16 @@ PG_FUNCTION_INFO_V1(pg_template_parse);
|
|||||||
Datum pg_template_parse(PG_FUNCTION_ARGS) {
|
Datum pg_template_parse(PG_FUNCTION_ARGS) {
|
||||||
INIT;
|
INIT;
|
||||||
|
|
||||||
TemplateConfig config;
|
text *context_text = PG_GETARG_TEXT_PP(0);
|
||||||
|
char *content = text_to_cstring(context_text);
|
||||||
|
|
||||||
const char *template_ptr;
|
const char *template_ptr;
|
||||||
TemplateResult template_result;
|
TemplateResult template_result;
|
||||||
|
TemplateConfig config = template_default_config(&arena);
|
||||||
|
|
||||||
template_ptr = "{{ name }}";
|
raise_info("start parsing....");
|
||||||
config = template_default_config();
|
|
||||||
template_result = template_parse(&arena, &template_ptr, &config);
|
template_result = template_parse(&arena, &template_ptr, &config);
|
||||||
|
raise_info("parsing finished....");
|
||||||
|
|
||||||
if (IS_RESULT_ERROR(template_result)) {
|
if (IS_RESULT_ERROR(template_result)) {
|
||||||
FREE;
|
FREE;
|
||||||
@@ -426,9 +415,18 @@ Datum pg_template_parse(PG_FUNCTION_ARGS) {
|
|||||||
RESULT_ERROR_MESSAGE(template_result))));
|
RESULT_ERROR_MESSAGE(template_result))));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *json_str = "{\"a\": 1}";
|
const char *json_str = TEMPLATE_NODE_TO_JSON_STR(&arena, &(RESULT_SOME_VALUE(template_result)));
|
||||||
Jsonb *jb = DatumGetJsonbP(DirectFunctionCall1(jsonb_in, CStringGetDatum(json_str)));
|
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;
|
FREE;
|
||||||
PG_RETURN_VOID();
|
|
||||||
|
text *result = cstring_to_text(result_str_clone);
|
||||||
|
PG_RETURN_TEXT_P(result);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user