test(hmpl): render interpolation tags
This commit is contained in:
@@ -85,9 +85,9 @@
|
|||||||
pg-from = pkgs.callPackage ./package/postgres/pg-from/default.nix rust.commonArgs;
|
pg-from = pkgs.callPackage ./package/postgres/pg-from/default.nix rust.commonArgs;
|
||||||
pg-schema = pkgs.callPackage ./package/postgres/pg-schema/default.nix rust.commonArgs;
|
pg-schema = pkgs.callPackage ./package/postgres/pg-schema/default.nix rust.commonArgs;
|
||||||
pg-migration = pkgs.callPackage ./package/postgres/pg-migration/default.nix rust.commonArgs;
|
pg-migration = pkgs.callPackage ./package/postgres/pg-migration/default.nix rust.commonArgs;
|
||||||
chectic = pkgs.callPackage ./package/c/chectic/default.nix {};
|
hectic = pkgs.callPackage ./package/c/hectic/default.nix {};
|
||||||
hmpl = pkgs.callPackage ./package/c/hmpl/default.nix {
|
hmpl = pkgs.callPackage ./package/c/hmpl/default.nix {
|
||||||
chectic = self.packages.${system}.chectic;
|
hectic = self.packages.${system}.hectic;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ stdenv, gcc, lib }:
|
{ stdenv, gcc, lib }:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
pname = "chectic";
|
pname = "hectic";
|
||||||
version = "1.0";
|
version = "1.0";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
@@ -11,23 +11,23 @@ stdenv.mkDerivation {
|
|||||||
${gcc}/bin/cc -Wall -Wextra -g \
|
${gcc}/bin/cc -Wall -Wextra -g \
|
||||||
-std=c99 \
|
-std=c99 \
|
||||||
-pedantic -fsanitize=address \
|
-pedantic -fsanitize=address \
|
||||||
-c chectic.c -o target/chectic.o
|
-c hectic.c -o target/hectic.o
|
||||||
${gcc}/bin/ar rcs target/libchectic.a target/chectic.o
|
${gcc}/bin/ar rcs target/libhectic.a target/hectic.o
|
||||||
'';
|
'';
|
||||||
|
|
||||||
checkPhase = ''
|
checkPhase = ''
|
||||||
mkdir -p target/test
|
mkdir -p target/test
|
||||||
for test_file in test/*.c; do
|
for test_file in test/*.c; do
|
||||||
exe="target/test/$(basename ''${test_file%.c})"
|
exe="target/test/$(basename ''${test_file%.c})"
|
||||||
${gcc}/bin/cc -Wall -Wextra -g -pedantic -fsanitize=address -I. "$test_file" -Ltarget -lchectic -o "$exe"
|
${gcc}/bin/cc -Wall -Wextra -g -pedantic -fsanitize=address -I. "$test_file" -Ltarget -lhectic -o "$exe"
|
||||||
"$exe"
|
"$exe"
|
||||||
done
|
done
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out/lib $out/include
|
mkdir -p $out/lib $out/include
|
||||||
cp target/libchectic.a $out/lib/
|
cp target/libhectic.a $out/lib/
|
||||||
cp chectic.h $out/include/
|
cp hectic.h $out/include/
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "chectic.h"
|
#include "hectic.h"
|
||||||
|
|
||||||
void set_output_color_mode(ColorMode mode) {
|
void set_output_color_mode(ColorMode mode) {
|
||||||
color_mode = mode;
|
color_mode = mode;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef EPRINTF_CHECTIC
|
#ifndef EPRINTF_HECTIC
|
||||||
#define EPRINTF_CHECTIC
|
#define EPRINTF_HECTIC
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "chectic.h"
|
#include "hectic.h"
|
||||||
|
|
||||||
#define TEST_RAISE_GENERIC(LOG_MACRO, LEVEL, LEVEL_STR) do { \
|
#define TEST_RAISE_GENERIC(LOG_MACRO, LEVEL, LEVEL_STR) do { \
|
||||||
FILE *orig_stderr = stderr; \
|
FILE *orig_stderr = stderr; \
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "chectic.h"
|
#include "hectic.h"
|
||||||
|
|
||||||
void test_arena_init() {
|
void test_arena_init() {
|
||||||
Arena arena = arena_init(128);
|
Arena arena = arena_init(128);
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "chectic.h"
|
#include "hectic.h"
|
||||||
|
|
||||||
#define ARENA_SIZE 1024 * 1024
|
#define ARENA_SIZE 1024 * 1024
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{ stdenv, gcc, lib, chectic }:
|
{ stdenv, gcc, lib, hectic }:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
pname = "hmpl";
|
pname = "hmpl";
|
||||||
@@ -6,7 +6,7 @@ stdenv.mkDerivation {
|
|||||||
src = ./.;
|
src = ./.;
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
|
|
||||||
buildInputs = [ chectic ];
|
buildInputs = [ hectic ];
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
mkdir -p target
|
mkdir -p target
|
||||||
@@ -15,7 +15,7 @@ stdenv.mkDerivation {
|
|||||||
${gcc}/bin/cc -Wall -Wextra -g \
|
${gcc}/bin/cc -Wall -Wextra -g \
|
||||||
-std=c99 \
|
-std=c99 \
|
||||||
-pedantic -fsanitize=address -c hmpl.c \
|
-pedantic -fsanitize=address -c hmpl.c \
|
||||||
-lchectic \
|
-lhectic \
|
||||||
-o target/hmpl.o
|
-o target/hmpl.o
|
||||||
${gcc}/bin/ar rcs target/libhmpl.a target/hmpl.o
|
${gcc}/bin/ar rcs target/libhmpl.a target/hmpl.o
|
||||||
|
|
||||||
@@ -23,10 +23,19 @@ stdenv.mkDerivation {
|
|||||||
${gcc}/bin/cc -Wall -Wextra -g \
|
${gcc}/bin/cc -Wall -Wextra -g \
|
||||||
-pedantic -fsanitize=address main.c \
|
-pedantic -fsanitize=address main.c \
|
||||||
-Ltarget -lhmpl \
|
-Ltarget -lhmpl \
|
||||||
-lchectic -o target/hmpl
|
-lhectic -o target/hmpl
|
||||||
'';
|
'';
|
||||||
|
|
||||||
checkPhase = '' '';
|
checkPhase = ''
|
||||||
|
mkdir -p target/test
|
||||||
|
for test_file in test/*.c; do
|
||||||
|
exe="target/test/$(basename ''${test_file%.c})"
|
||||||
|
${gcc}/bin/cc -Wall -Wextra -g -pedantic \
|
||||||
|
-fsanitize=address -I. "$test_file" \
|
||||||
|
-Ltarget -lhmpl -lhectic -o "$exe"
|
||||||
|
"$exe"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out/bin $out/lib $out/include
|
mkdir -p $out/bin $out/lib $out/include
|
||||||
@@ -36,7 +45,7 @@ stdenv.mkDerivation {
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "chectic";
|
description = "hectic";
|
||||||
license = lib.licenses.mit;
|
license = lib.licenses.mit;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ char *eval(Arena *arena, const Json * const context, const char * const key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Modified: text is passed by reference so we can update it and free old allocations */
|
/* Modified: text is passed by reference so we can update it and free old allocations */
|
||||||
void render_template_placeholders(Arena *arena, char **text_ptr, Json *context, const char * const prefix) {
|
void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix) {
|
||||||
raise_debug("render_template_placeholders");
|
raise_debug("hmpl_render_interpolation_tags");
|
||||||
char start_pattern[256];
|
char start_pattern[256];
|
||||||
snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix);
|
snprintf(start_pattern, sizeof(start_pattern), "{{%s", prefix);
|
||||||
int start_pattern_length = strlen(start_pattern);
|
int start_pattern_length = strlen(start_pattern);
|
||||||
@@ -67,19 +67,19 @@ void render_template_placeholders(Arena *arena, char **text_ptr, Json *context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_template_with_arena(Arena *arena, char **text, const Json * const context) {
|
void hmpl_render_with_arena(Arena *arena, char **text, const Json * const context) {
|
||||||
if (context->type != JSON_OBJECT) {
|
if (context->type != JSON_OBJECT) {
|
||||||
raise_exception("Malformed context: context is not json");
|
raise_exception("Malformed context: context is not json");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_template_placeholders(arena, text, context, "");
|
hmpl_render_interpolation_tags(arena, text, context, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_template(char **text, const Json * const context) {
|
void hmpl_render(char **text, const Json * const context) {
|
||||||
Arena arena = arena_init(1024 * 1024);
|
Arena arena = arena_init(1024 * 1024);
|
||||||
|
|
||||||
render_template_with_arena(&arena, text, context);
|
hmpl_render_with_arena(&arena, text, context);
|
||||||
|
|
||||||
arena_free(&arena);
|
arena_free(&arena);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "chectic.h"
|
#include "hectic.h"
|
||||||
|
|
||||||
void init_cjson_with_arenas(Arena *arena);
|
void init_cjson_with_arenas(Arena *arena);
|
||||||
|
|
||||||
char *eval(Arena *arena, const Json * const context, const char * const key);
|
char *eval(Arena *arena, const Json * const context, const char * const key);
|
||||||
|
|
||||||
/* Modified: text is passed by reference so we can update it and free old allocations */
|
/* Modified: text is passed by reference so we can update it and free old allocations */
|
||||||
void render_template_placeholders(Arena *arena, char **text_ptr, Json *context, const char * const prefix);
|
void hmpl_render_interpolation_tags(Arena *arena, char **text_ptr, Json *context, const char * const prefix);
|
||||||
|
|
||||||
void render_template_with_arena(Arena *arena, char **text, const Json * const ccontext);
|
void render_template_with_arena(Arena *arena, char **text, const Json * const ccontext);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "chectic.h"
|
#include "hectic.h"
|
||||||
#include "hmpl.h"
|
#include "hmpl.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
@@ -38,7 +38,7 @@ int main(int argc, char *argv[]) {
|
|||||||
text = arena_strdup(&arena, "");
|
text = arena_strdup(&arena, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
render_template_with_arena(&arena, &text, context);
|
hmpl_render_with_arena(&arena, &text, context);
|
||||||
printf("%s", text);
|
printf("%s", text);
|
||||||
|
|
||||||
arena_free(&arena);
|
arena_free(&arena);
|
||||||
|
|||||||
107
package/c/hmpl/test/test.c
Normal file
107
package/c/hmpl/test/test.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "hmpl.h"
|
||||||
|
#include "hectic.h"
|
||||||
|
|
||||||
|
void test_eval_single_level_key(Arena *arena) {
|
||||||
|
char *context_text = arena_strdup(arena, "{\"name\": \"world\"}");
|
||||||
|
Json *context = json_parse(arena, &context_text);
|
||||||
|
if (!context) { raise_exception("Malformed json"); exit(1); }
|
||||||
|
|
||||||
|
char *result = eval(arena, context, "name");
|
||||||
|
raise_debug("eval result: %s", result);
|
||||||
|
assert(result && strcmp(result, "world") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_eval_nested_key(Arena *arena) {
|
||||||
|
char *context_text = arena_strdup(arena, "{\"person\": {\"name\": \"Alice\"}}");
|
||||||
|
Json *context = json_parse(arena, &context_text);
|
||||||
|
if (!context) { raise_exception("Malformed json"); exit(1); }
|
||||||
|
|
||||||
|
char *result = eval(arena, context, "person.name");
|
||||||
|
raise_notice("context: %s, eval result: %s", json_to_string(arena, context), result);
|
||||||
|
assert(result && strcmp(result, "Alice") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_render_interpolation_tags(Arena *arena) {
|
||||||
|
char *context_text = arena_strdup(arena,
|
||||||
|
"{\n"
|
||||||
|
" \"persona\": {\n"
|
||||||
|
" \"name\": \"John\",\n"
|
||||||
|
" \"surname\": \"Doe\",\n"
|
||||||
|
" \"address\": {\n"
|
||||||
|
" \"home\": {\n"
|
||||||
|
" \"street\": \"123 Main St\",\n"
|
||||||
|
" \"city\": \"Springfield\",\n"
|
||||||
|
" \"zip\": \"12345\"\n"
|
||||||
|
" },\n"
|
||||||
|
" \"work\": {\n"
|
||||||
|
" \"street\": \"456 Business Rd\",\n"
|
||||||
|
" \"city\": \"Metropolis\",\n"
|
||||||
|
" \"zip\": \"67890\"\n"
|
||||||
|
" }\n"
|
||||||
|
" },\n"
|
||||||
|
" \"contact\": {\n"
|
||||||
|
" \"email\": \"john@example.com\",\n"
|
||||||
|
" \"phone\": {\n"
|
||||||
|
" \"home\": \"555-1234\",\n"
|
||||||
|
" \"mobile\": \"555-5678\"\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"}");
|
||||||
|
Json *context = json_parse(arena, &context_text);
|
||||||
|
if (!context) { raise_exception("Malformed json"); exit(1); }
|
||||||
|
|
||||||
|
char *text = arena_strdup(arena,
|
||||||
|
"Hello {{persona.name}} {{persona.surname}},\n"
|
||||||
|
"\n"
|
||||||
|
"Your home address:\n"
|
||||||
|
"{{persona.address.home.street}},\n"
|
||||||
|
"{{persona.address.home.city}},\n"
|
||||||
|
"{{persona.address.home.zip}}\n"
|
||||||
|
"\n"
|
||||||
|
"Your work address:\n"
|
||||||
|
"{{persona.address.work.street}},\n"
|
||||||
|
"{{persona.address.work.city}},\n"
|
||||||
|
"{{persona.address.work.zip}}\n"
|
||||||
|
"\n"
|
||||||
|
"Contact information:\n"
|
||||||
|
"Email: {{persona.contact.email}}\n"
|
||||||
|
"Home Phone: {{persona.contact.phone.home}}\n"
|
||||||
|
"Mobile Phone: {{persona.contact.phone.mobile}}\n");
|
||||||
|
|
||||||
|
hmpl_render_with_arena(arena, &text, context);
|
||||||
|
assert(strcmp(text,
|
||||||
|
"Hello John Doe,\n"
|
||||||
|
"\n"
|
||||||
|
"Your home address:\n"
|
||||||
|
"123 Main St,\n"
|
||||||
|
"Springfield,\n"
|
||||||
|
"12345\n"
|
||||||
|
"\n"
|
||||||
|
"Your work address:\n"
|
||||||
|
"456 Business Rd,\n"
|
||||||
|
"Metropolis,\n"
|
||||||
|
"67890\n"
|
||||||
|
"\n"
|
||||||
|
"Contact information:\n"
|
||||||
|
"Email: john@example.com\n"
|
||||||
|
"Home Phone: 555-1234\n"
|
||||||
|
"Mobile Phone: 555-5678\n") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
Arena arena = arena_init(1024 * 1024);
|
||||||
|
|
||||||
|
test_eval_single_level_key(&arena);
|
||||||
|
test_eval_nested_key(&arena);
|
||||||
|
test_render_interpolation_tags(&arena);
|
||||||
|
|
||||||
|
printf("All tests passed.\n");
|
||||||
|
|
||||||
|
arena_free(&arena);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user