feat(libhectic): arenas

This commit is contained in:
2025-03-21 01:53:02 +00:00
parent 647155f859
commit 4f2391e9b5
8 changed files with 239 additions and 5 deletions

View File

@@ -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 = {

View File

@@ -0,0 +1,87 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#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;
}

8
package/c/hmpl/libhmpl.c Normal file
View File

@@ -0,0 +1,8 @@
#include <stdio.h>
#include "libhectic.h"
int main(void) {
raise_info("hello world");
return 0;
}

8
package/c/hmpl/libhmpl.h Normal file
View File

@@ -0,0 +1,8 @@
#include <stdio.h>
#include "libhectic.h"
int main(void) {
raise_info("hello world");
return 0;
}

View File

@@ -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;
}

View File

@@ -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;
// }

View File

@@ -0,0 +1,55 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#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");
}

View File

@@ -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");