From 4f2391e9b5b012bde76dce272ad84d95c17cff00 Mon Sep 17 00:00:00 2001 From: yukkop Date: Fri, 21 Mar 2025 01:53:02 +0000 Subject: [PATCH] feat(libhectic): arenas --- package/c/hmpl/default.nix | 9 ++-- package/c/hmpl/hmpl.c | 87 ++++++++++++++++++++++++++++++++ package/c/hmpl/libhmpl.c | 8 +++ package/c/hmpl/libhmpl.h | 8 +++ package/c/libhectic/libhectic.c | 43 ++++++++++++++++ package/c/libhectic/libhectic.h | 33 ++++++++++++ package/c/libhectic/test/arena.c | 55 ++++++++++++++++++++ package/c/libhectic/test/test.c | 1 - 8 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 package/c/hmpl/libhmpl.c create mode 100644 package/c/hmpl/libhmpl.h create mode 100644 package/c/libhectic/test/arena.c diff --git a/package/c/hmpl/default.nix b/package/c/hmpl/default.nix index 2ea3e7d..646f298 100644 --- a/package/c/hmpl/default.nix +++ b/package/c/hmpl/default.nix @@ -1,7 +1,7 @@ { stdenv, gcc, lib, libhectic }: stdenv.mkDerivation { - pname = "libhectic"; + pname = "hmpl"; version = "1.0"; src = ./.; doCheck = true; @@ -11,14 +11,15 @@ stdenv.mkDerivation { buildPhase = '' mkdir -p target ${gcc}/bin/cc -Wall -Wextra -g \ - -pedantic -fsanitize=address -c hmpl.c \ - -l:libhectic.a -o target/libhectic.o + -pedantic -fsanitize=address hmpl.c \ + -l:libhectic.a -o target/hmpl ''; checkPhase = '' ''; installPhase = '' - mkdir -p $out/lib $out/include + mkdir -p $out/bin + cp target/hmpl $out/bin/hmpl ''; meta = { diff --git a/package/c/hmpl/hmpl.c b/package/c/hmpl/hmpl.c index e69de29..33c0756 100644 --- a/package/c/hmpl/hmpl.c +++ b/package/c/hmpl/hmpl.c @@ -0,0 +1,87 @@ +#include +#include +#include +//#include "libhmpl.h" +#include "libhectic.h" + +#define KB128 131072 + +// CREATE OR REPLACE FUNCTION common.render_template_placeholders(result TEXT, context JSONB, prefix CHAR(1) DEFAULT '') +// RETURNS text LANGUAGE plpgsql AS $$ +// DECLARE +// simple_start INT; +// simple_end INT; +// simple_key TEXT; +// replacement TEXT; +// first_char CHAR(1); +// _offset INT := 0; +// +// start_pattern CHAR(3); +// start_pattern_length INT; +// BEGIN +// start_pattern = '{{' || prefix; +// start_pattern_length = char_length(start_pattern); +// +// LOOP +// -- Locate the start of the simple key marker. +// simple_start := strpos(substring(result from _offset), start_pattern); +// EXIT WHEN simple_start = 0; -- Exit if no simple marker is found. +// +// IF _offset != 0 THEN +// simple_start := _offset + simple_start - 1; +// END IF; +// +// -- Locate the end of the simple key marker. +// simple_end := strpos(result, '}}', simple_start); +// IF simple_end = 0 THEN +// RAISE EXCEPTION 'Malformed template: missing closing braces for loop start'; +// END IF; +// +// simple_key := substring(result from simple_start + start_pattern_length for simple_end - simple_start - start_pattern_length); +// +// +// replacement := eval_value(context, simple_key); +// RAISE LOG '% := eval_value(%, %)', replacement, context, simple_key; +// IF replacement IS NULL THEN +// _offset := simple_start + start_pattern_length; +// RAISE LOG '% := % + %', _offset, simple_start, start_pattern_length; +// IF _offset = 0 THEN +// RAISE EXCEPTION 'Malformed template: offcet cannot be 0'; +// END IF; +// CONTINUE; +// END IF; +// result := replace( +// result, +// substring(result from simple_start for simple_end - simple_start + 2), +// replacement); +// END LOOP; +// +// RETURN result; +// END $$; + +void render_template_placeholders(char *text, char *context, char prefix[1]) { + // start + char start_pattern[4]; + sprintf(&start_pattern[0], "{{%s", prefix); + + int start_pattern_length = strlen(start_pattern); + int offset = 0; + + while (1) { + // find tag start + char *placeholder_start = strstr(text + offset, start_pattern); + if (!placeholder_start) { + break; + } + }; +} + +void render_template(char *text, char *context) { + render_template_placeholders(text, context, ""); +} + +int main(void) { + render_template(text, context); + + return 0; +} diff --git a/package/c/hmpl/libhmpl.c b/package/c/hmpl/libhmpl.c new file mode 100644 index 0000000..e0d7872 --- /dev/null +++ b/package/c/hmpl/libhmpl.c @@ -0,0 +1,8 @@ +#include +#include "libhectic.h" + +int main(void) { + raise_info("hello world"); + + return 0; +} diff --git a/package/c/hmpl/libhmpl.h b/package/c/hmpl/libhmpl.h new file mode 100644 index 0000000..e0d7872 --- /dev/null +++ b/package/c/hmpl/libhmpl.h @@ -0,0 +1,8 @@ +#include +#include "libhectic.h" + +int main(void) { + raise_info("hello world"); + + return 0; +} diff --git a/package/c/libhectic/libhectic.c b/package/c/libhectic/libhectic.c index 1c17e3f..a9948d3 100644 --- a/package/c/libhectic/libhectic.c +++ b/package/c/libhectic/libhectic.c @@ -74,3 +74,46 @@ char* log_message(LogLevel level, int line, const char *format, ...) { return timeStr; } + +// ----------- +// -- arena -- +// ----------- + +Arena arena_init(size_t size) { + Arena arena; + arena.begin = malloc(size); + memset(arena.begin, 0, size); + arena.current = arena.begin; + arena.capacity = size; + + return arena; +} + +void *arena_alloc_or_null(Arena *arena, size_t size) { + if (arena->begin == 0) { + *arena = arena_init(ARENA_DEFAULT_SIZE); + } + size_t current = (size_t)arena->current - (size_t)arena->begin; + // TODO(yukkop): maybe -1 + if (arena->capacity <= current && current < size) { + return NULL; + } + return arena; +} + +void arena_reset(Arena *arena) { + arena->current = arena->begin; +} + +void arena_free(Arena *arena) { + free(arena->begin); +} + +void *arena_alloc(Arena *arena, size_t size) { + void *mem = arena_alloc_or_null(arena, size); + if (!mem) { + raise_exception("Arena out of memory"); + exit(1); + } + return mem; +} diff --git a/package/c/libhectic/libhectic.h b/package/c/libhectic/libhectic.h index e9c33b0..f6dd2e3 100644 --- a/package/c/libhectic/libhectic.h +++ b/package/c/libhectic/libhectic.h @@ -138,3 +138,36 @@ char* log_message(LogLevel level, int line, const char *format, ...); PP_CAT(raise_exception_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) #endif // EPRINTF_H + +// ----------- +// -- arena -- +// ----------- + +#define ARENA_DEFAULT_SIZE 1024 + +typedef struct { + void *begin; + void *current; + size_t capacity; +} Arena; + +Arena arena_init(size_t size); + +void *arena_alloc_or_null(Arena *arena, size_t size); + +void arena_reset(Arena *arena); + +void arena_free(Arena *arena); + +void *arena_alloc(Arena *arena, size_t size); + +// TODO: mmap +// TODO: dynamic array style +// void *arena_realloc(Arena *arena, size_t size) { +// void *mem = arena_alloc_or_null(arena, size); +// if (!mem) { +// raise_exception("Arena out of memory"); +// exit(1); +// } +// return mem; +// } diff --git a/package/c/libhectic/test/arena.c b/package/c/libhectic/test/arena.c new file mode 100644 index 0000000..e302270 --- /dev/null +++ b/package/c/libhectic/test/arena.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include "libhectic.h" + +void test_arena_init() { + Arena arena = arena_init(128); + assert(arena.begin != NULL); + assert(arena.current == arena.begin); + assert(arena.capacity == 128); + arena_free(&arena); +} + +void test_arena_alloc() { + Arena arena = arena_init(64); + void *ptr1 = arena_alloc(&arena, 16); + assert(ptr1 != NULL); + void *ptr2 = arena_alloc(&arena, 16); + assert(ptr2 != NULL); + assert((char *)ptr2 - (char *)ptr1 == 16); + arena_free(&arena); +} + +void test_arena_alloc_or_null_out_of_memory() { + Arena arena = arena_init(32); + void *ptr = arena_alloc_or_null(&arena, 64); + assert(ptr == NULL); + arena_free(&arena); +} + +void test_arena_reset() { + Arena arena = arena_init(64); + void *ptr1 = arena_alloc(&arena, 16); + arena_reset(&arena); + void *ptr2 = arena_alloc(&arena, 16); + assert(ptr1 == ptr2); // same address after reset + arena_free(&arena); +} + +void test_arena_null_init() { + Arena arena = {0}; + void *ptr = arena_alloc_or_null(&arena, 32); + assert(ptr != NULL); + arena_free(&arena); +} + +int main() { + test_arena_init(); + test_arena_alloc(); + test_arena_alloc_or_null_out_of_memory(); + test_arena_reset(); + test_arena_null_init(); + printf("All tests passed.\n"); +} diff --git a/package/c/libhectic/test/test.c b/package/c/libhectic/test/test.c index f80085d..aac2aa1 100644 --- a/package/c/libhectic/test/test.c +++ b/package/c/libhectic/test/test.c @@ -27,7 +27,6 @@ int main(void) { set_output_color_mode(COLOR_MODE_DISABLE); - raise_log("zalupa"); TEST_RAISE_GENERIC(raise_debug, LOG_LEVEL_DEBUG, "DEBUG"); TEST_RAISE_GENERIC(raise_log, LOG_LEVEL_LOG, "LOG");