From 3913d1778318cd0c6bfb871148d38abb33ec7fd3 Mon Sep 17 00:00:00 2001 From: nasr Date: Wed, 28 Jan 2026 13:13:40 +0100 Subject: checkpoint --- base/base.c | 69 ++++++++++++++++++++++++++++++++++++++++++++ base/base.h | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ base/base_arena.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ base/base_arena.h | 49 +++++++++++++++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 base/base.c create mode 100644 base/base.h create mode 100644 base/base_arena.c create mode 100644 base/base_arena.h (limited to 'base') diff --git a/base/base.c b/base/base.c new file mode 100644 index 0000000..ba8ba32 --- /dev/null +++ b/base/base.c @@ -0,0 +1,69 @@ +#include "base/base.h" +#include "stddef.h" + +/** + * Helper function to parse strings to int using ascii codes + * */ +local_internal u64 +parse_u64(char *buf, size_t len) +{ + u64 value = 0; + + for ( + size_t buffer_idx = 0; + buffer_idx < len; + ++buffer_idx) + { + char c = buf[buffer_idx]; + if (c < '0' || c > '9') + { + break; + } + value = value * 10 + (c - '0'); + } + + return value; +} + +/* + * is_numeric - Check if a string contains only digits + * @s: String to check + * + * Return: 1 if string contains only numeric characters, 0 otherwise + */ +local_internal b8 +is_numeric(char *s) +{ + for (; *s; ++s) + { + if (*s < '0' || *s > '9') + { + return 0; + } + } + return 1; +} + +local_internal b8 +compare_string(const char *c1, const char *c2) +{ + if (sizeof(c1) != sizeof(c2)) + { + return -1; + } + + for ( + u64 word_idx = 0; + word_idx <= sizeof(*c1); + ++word_idx) + { + if (*c1 != *c2) + { + return -1; + } + ++c1; + ++c2; + } + + return 0; +} diff --git a/base/base.h b/base/base.h new file mode 100644 index 0000000..8ce6cba --- /dev/null +++ b/base/base.h @@ -0,0 +1,85 @@ +#ifndef BASE_H +#define BASE_H + +#include +#include + +/* assert an expression and output the file and the line */ + +#define RED "\x1b[31m" +#define GREEN "\x1b[32m" +#define RESET "\x1b[0m" + +#define test_assert(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf(stderr, RED " [FAILED] %s:%d: expr:%s test:%s\n" RESET, __FILE__, __LINE__, #expr, __func__); \ + abort(); \ + } \ + else\ + { \ + fprintf(stdout, GREEN "[PASSED] %s\n" RESET, __func__); \ + }\ + } while (0) + +#define global_variable static +#define local_persist static +#define local_internal static + +#define ERR_OK 0 +#define ERR_IO 1 +#define ERR_PARSE 2 +#define ERR_PERM 3 +#define ERR_INVALID 4 + +#define KiB(n) (((u64)(n)) << 10) +#define MiB(n) (((u64)(n)) << 20) +#define GiB(n) (((u64)(n)) << 30) + +#define BUFFER_SIZE_SMALL 128 +#define BUFFER_SIZE_DEFAULT 256 +#define BUFFER_SIZE_LARGE 512 +#define PATH_MAX_LEN 4096 + +#define DEPRECATED __attribute__((__deprecated__)) + +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef float f32; +typedef double f64; + +typedef i32 b32; +typedef i16 b16; +typedef u8 b8; + +typedef uintptr_t umm; +typedef intptr_t smm; + +#define TRUE 1 +#define FALSE 0 + +local_internal u64 +parse_u64(char *buf, size_t len); + +local_internal b8 +is_numeric(char *s); + +local_internal b8 +compare_string(const char *c1, const char *c2); + +/* + * TODO(nasr): macro for verbose assertions + * + * */ + +#endif diff --git a/base/base_arena.c b/base/base_arena.c new file mode 100644 index 0000000..16997b2 --- /dev/null +++ b/base/base_arena.c @@ -0,0 +1,86 @@ +/** + * TODO(nasr): remove stdlib + * */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "base_arena.h" + +/* TODO(nasr): reserve pages support */ +/* TODO(nasr): check if an arena has been used before */ + +local_internal mem_arena * +arena_create(u64 capacity) +{ + mem_arena *arena = (mem_arena *)mmap(0, capacity, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (arena == MAP_FAILED) + { + return NULL; + } + + arena->capacity = capacity; + arena->pos = ARENA_BASE_POS; + + return arena; +} + +/* + * make it a void pointer to allow implicit conversion + * */ +local_internal void +arena_destroy(mem_arena *arena) +{ + munmap(arena, arena->capacity); +} + +local_internal void * +arena_push(mem_arena *arena, u64 size, b32 non_zero) +{ + u64 pos_aligned = ALIGN_UP_POW2(arena->pos, ARENA_ALIGN); + u64 new_pos = pos_aligned + size; + + if (new_pos > arena->capacity) + { + assert(0); + return NULL; + } + + arena->pos = new_pos; + /* + * cast to u8 to be able to do pointer arithemtic + * */ + u8 *out = (u8 *)arena + pos_aligned; + + if (!non_zero) + { + memset(out, 0, size); + } + return out; +} + +local_internal void +arena_pop(mem_arena *arena, u64 size) +{ + size = MIN(size, arena->pos - ARENA_BASE_POS); + arena->pos -= size; +} + +local_internal void +arena_pop_to(mem_arena *arena, u64 pos) +{ + u64 size = pos < arena->pos ? arena->pos - pos : 0; + arena_pop(arena, size); +} + +local_internal void +arena_clear(mem_arena *arena) +{ + arena_pop_to(arena, ARENA_BASE_POS); +} diff --git a/base/base_arena.h b/base/base_arena.h new file mode 100644 index 0000000..19c4f3d --- /dev/null +++ b/base/base_arena.h @@ -0,0 +1,49 @@ +#ifndef ARENA_H +#define ARENA_H + +#include "base.h" + +/** + * Arena Helper macro's + * */ + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define ALIGN_UP_POW2(n, p) (((u64)(n) + ((u64)(p) - 1)) & (~((u64)(p) - 1))) + +#define PUSH_STRUCT(arena, T) (T *)arena_push((arena), sizeof(T), 0) +#define PUSH_STRUCT_NZ(arena, T) (T *)arena_push((arena), sizeof(T), 1) +#define PUSH_ARRAY(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 0) +#define PUSH_ARRAY_NZ(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 1) + +#define ARENA_BASE_POS (sizeof(mem_arena)) +#define ARENA_ALIGN (sizeof(void *)) + +typedef struct mem_arena mem_arena; + +struct mem_arena +{ + u64 capacity; + u64 pos; +}; + +local_internal mem_arena * +arena_create(u64 capacity); + +local_internal void +arena_destroy(mem_arena *arena); + +local_internal void * +arena_push(mem_arena *arena, u64 size, b32 non_zero); + +local_internal void +arena_pop(mem_arena *arena, u64 size); + +local_internal void +arena_pop_to(mem_arena *arena, u64 pos); + +local_internal void +arena_clear(mem_arena *arena); + + +#endif -- cgit v1.3