diff options
Diffstat (limited to 'base')
| -rw-r--r-- | base/base.c | 69 | ||||
| -rw-r--r-- | base/base.h | 85 | ||||
| -rw-r--r-- | base/base_arena.c | 86 | ||||
| -rw-r--r-- | base/base_arena.h | 49 |
4 files changed, 289 insertions, 0 deletions
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 @@ | |||
| 1 | #include "base/base.h" | ||
| 2 | #include "stddef.h" | ||
| 3 | |||
| 4 | /** | ||
| 5 | * Helper function to parse strings to int using ascii codes | ||
| 6 | * */ | ||
| 7 | local_internal u64 | ||
| 8 | parse_u64(char *buf, size_t len) | ||
| 9 | { | ||
| 10 | u64 value = 0; | ||
| 11 | |||
| 12 | for ( | ||
| 13 | size_t buffer_idx = 0; | ||
| 14 | buffer_idx < len; | ||
| 15 | ++buffer_idx) | ||
| 16 | { | ||
| 17 | char c = buf[buffer_idx]; | ||
| 18 | if (c < '0' || c > '9') | ||
| 19 | { | ||
| 20 | break; | ||
| 21 | } | ||
| 22 | value = value * 10 + (c - '0'); | ||
| 23 | } | ||
| 24 | |||
| 25 | return value; | ||
| 26 | } | ||
| 27 | |||
| 28 | /* | ||
| 29 | * is_numeric - Check if a string contains only digits | ||
| 30 | * @s: String to check | ||
| 31 | * | ||
| 32 | * Return: 1 if string contains only numeric characters, 0 otherwise | ||
| 33 | */ | ||
| 34 | local_internal b8 | ||
| 35 | is_numeric(char *s) | ||
| 36 | { | ||
| 37 | for (; *s; ++s) | ||
| 38 | { | ||
| 39 | if (*s < '0' || *s > '9') | ||
| 40 | { | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | return 1; | ||
| 45 | } | ||
| 46 | |||
| 47 | local_internal b8 | ||
| 48 | compare_string(const char *c1, const char *c2) | ||
| 49 | { | ||
| 50 | if (sizeof(c1) != sizeof(c2)) | ||
| 51 | { | ||
| 52 | return -1; | ||
| 53 | } | ||
| 54 | |||
| 55 | for ( | ||
| 56 | u64 word_idx = 0; | ||
| 57 | word_idx <= sizeof(*c1); | ||
| 58 | ++word_idx) | ||
| 59 | { | ||
| 60 | if (*c1 != *c2) | ||
| 61 | { | ||
| 62 | return -1; | ||
| 63 | } | ||
| 64 | ++c1; | ||
| 65 | ++c2; | ||
| 66 | } | ||
| 67 | |||
| 68 | return 0; | ||
| 69 | } | ||
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 @@ | |||
| 1 | #ifndef BASE_H | ||
| 2 | #define BASE_H | ||
| 3 | |||
| 4 | #include <stdint.h> | ||
| 5 | #include <stddef.h> | ||
| 6 | |||
| 7 | /* assert an expression and output the file and the line */ | ||
| 8 | |||
| 9 | #define RED "\x1b[31m" | ||
| 10 | #define GREEN "\x1b[32m" | ||
| 11 | #define RESET "\x1b[0m" | ||
| 12 | |||
| 13 | #define test_assert(expr) \ | ||
| 14 | do \ | ||
| 15 | { \ | ||
| 16 | if (!(expr)) \ | ||
| 17 | { \ | ||
| 18 | fprintf(stderr, RED " [FAILED] %s:%d: expr:%s test:%s\n" RESET, __FILE__, __LINE__, #expr, __func__); \ | ||
| 19 | abort(); \ | ||
| 20 | } \ | ||
| 21 | else\ | ||
| 22 | { \ | ||
| 23 | fprintf(stdout, GREEN "[PASSED] %s\n" RESET, __func__); \ | ||
| 24 | }\ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | #define global_variable static | ||
| 28 | #define local_persist static | ||
| 29 | #define local_internal static | ||
| 30 | |||
| 31 | #define ERR_OK 0 | ||
| 32 | #define ERR_IO 1 | ||
| 33 | #define ERR_PARSE 2 | ||
| 34 | #define ERR_PERM 3 | ||
| 35 | #define ERR_INVALID 4 | ||
| 36 | |||
| 37 | #define KiB(n) (((u64)(n)) << 10) | ||
| 38 | #define MiB(n) (((u64)(n)) << 20) | ||
| 39 | #define GiB(n) (((u64)(n)) << 30) | ||
| 40 | |||
| 41 | #define BUFFER_SIZE_SMALL 128 | ||
| 42 | #define BUFFER_SIZE_DEFAULT 256 | ||
| 43 | #define BUFFER_SIZE_LARGE 512 | ||
| 44 | #define PATH_MAX_LEN 4096 | ||
| 45 | |||
| 46 | #define DEPRECATED __attribute__((__deprecated__)) | ||
| 47 | |||
| 48 | typedef uint64_t u64; | ||
| 49 | typedef uint32_t u32; | ||
| 50 | typedef uint16_t u16; | ||
| 51 | typedef uint8_t u8; | ||
| 52 | |||
| 53 | typedef int8_t i8; | ||
| 54 | typedef int16_t i16; | ||
| 55 | typedef int32_t i32; | ||
| 56 | typedef int64_t i64; | ||
| 57 | |||
| 58 | typedef float f32; | ||
| 59 | typedef double f64; | ||
| 60 | |||
| 61 | typedef i32 b32; | ||
| 62 | typedef i16 b16; | ||
| 63 | typedef u8 b8; | ||
| 64 | |||
| 65 | typedef uintptr_t umm; | ||
| 66 | typedef intptr_t smm; | ||
| 67 | |||
| 68 | #define TRUE 1 | ||
| 69 | #define FALSE 0 | ||
| 70 | |||
| 71 | local_internal u64 | ||
| 72 | parse_u64(char *buf, size_t len); | ||
| 73 | |||
| 74 | local_internal b8 | ||
| 75 | is_numeric(char *s); | ||
| 76 | |||
| 77 | local_internal b8 | ||
| 78 | compare_string(const char *c1, const char *c2); | ||
| 79 | |||
| 80 | /* | ||
| 81 | * TODO(nasr): macro for verbose assertions | ||
| 82 | * | ||
| 83 | * */ | ||
| 84 | |||
| 85 | #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 @@ | |||
| 1 | /** | ||
| 2 | * TODO(nasr): remove stdlib | ||
| 3 | * */ | ||
| 4 | #include <assert.h> | ||
| 5 | #include <stdint.h> | ||
| 6 | #include <string.h> | ||
| 7 | #include <sys/mman.h> | ||
| 8 | #include <sys/stat.h> | ||
| 9 | #include <dirent.h> | ||
| 10 | #include <fcntl.h> | ||
| 11 | #include <unistd.h> | ||
| 12 | |||
| 13 | #include "base_arena.h" | ||
| 14 | |||
| 15 | /* TODO(nasr): reserve pages support */ | ||
| 16 | /* TODO(nasr): check if an arena has been used before */ | ||
| 17 | |||
| 18 | local_internal mem_arena * | ||
| 19 | arena_create(u64 capacity) | ||
| 20 | { | ||
| 21 | mem_arena *arena = (mem_arena *)mmap(0, capacity, PROT_READ | PROT_WRITE | PROT_EXEC, | ||
| 22 | MAP_SHARED | MAP_ANONYMOUS, -1, 0); | ||
| 23 | if (arena == MAP_FAILED) | ||
| 24 | { | ||
| 25 | return NULL; | ||
| 26 | } | ||
| 27 | |||
| 28 | arena->capacity = capacity; | ||
| 29 | arena->pos = ARENA_BASE_POS; | ||
| 30 | |||
| 31 | return arena; | ||
| 32 | } | ||
| 33 | |||
| 34 | /* | ||
| 35 | * make it a void pointer to allow implicit conversion | ||
| 36 | * */ | ||
| 37 | local_internal void | ||
| 38 | arena_destroy(mem_arena *arena) | ||
| 39 | { | ||
| 40 | munmap(arena, arena->capacity); | ||
| 41 | } | ||
| 42 | |||
| 43 | local_internal void * | ||
| 44 | arena_push(mem_arena *arena, u64 size, b32 non_zero) | ||
| 45 | { | ||
| 46 | u64 pos_aligned = ALIGN_UP_POW2(arena->pos, ARENA_ALIGN); | ||
| 47 | u64 new_pos = pos_aligned + size; | ||
| 48 | |||
| 49 | if (new_pos > arena->capacity) | ||
| 50 | { | ||
| 51 | assert(0); | ||
| 52 | return NULL; | ||
| 53 | } | ||
| 54 | |||
| 55 | arena->pos = new_pos; | ||
| 56 | /* | ||
| 57 | * cast to u8 to be able to do pointer arithemtic | ||
| 58 | * */ | ||
| 59 | u8 *out = (u8 *)arena + pos_aligned; | ||
| 60 | |||
| 61 | if (!non_zero) | ||
| 62 | { | ||
| 63 | memset(out, 0, size); | ||
| 64 | } | ||
| 65 | return out; | ||
| 66 | } | ||
| 67 | |||
| 68 | local_internal void | ||
| 69 | arena_pop(mem_arena *arena, u64 size) | ||
| 70 | { | ||
| 71 | size = MIN(size, arena->pos - ARENA_BASE_POS); | ||
| 72 | arena->pos -= size; | ||
| 73 | } | ||
| 74 | |||
| 75 | local_internal void | ||
| 76 | arena_pop_to(mem_arena *arena, u64 pos) | ||
| 77 | { | ||
| 78 | u64 size = pos < arena->pos ? arena->pos - pos : 0; | ||
| 79 | arena_pop(arena, size); | ||
| 80 | } | ||
| 81 | |||
| 82 | local_internal void | ||
| 83 | arena_clear(mem_arena *arena) | ||
| 84 | { | ||
| 85 | arena_pop_to(arena, ARENA_BASE_POS); | ||
| 86 | } | ||
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 @@ | |||
| 1 | #ifndef ARENA_H | ||
| 2 | #define ARENA_H | ||
| 3 | |||
| 4 | #include "base.h" | ||
| 5 | |||
| 6 | /** | ||
| 7 | * Arena Helper macro's | ||
| 8 | * */ | ||
| 9 | |||
| 10 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) | ||
| 11 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) | ||
| 12 | #define ALIGN_UP_POW2(n, p) (((u64)(n) + ((u64)(p) - 1)) & (~((u64)(p) - 1))) | ||
| 13 | |||
| 14 | #define PUSH_STRUCT(arena, T) (T *)arena_push((arena), sizeof(T), 0) | ||
| 15 | #define PUSH_STRUCT_NZ(arena, T) (T *)arena_push((arena), sizeof(T), 1) | ||
| 16 | #define PUSH_ARRAY(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 0) | ||
| 17 | #define PUSH_ARRAY_NZ(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 1) | ||
| 18 | |||
| 19 | #define ARENA_BASE_POS (sizeof(mem_arena)) | ||
| 20 | #define ARENA_ALIGN (sizeof(void *)) | ||
| 21 | |||
| 22 | typedef struct mem_arena mem_arena; | ||
| 23 | |||
| 24 | struct mem_arena | ||
| 25 | { | ||
| 26 | u64 capacity; | ||
| 27 | u64 pos; | ||
| 28 | }; | ||
| 29 | |||
| 30 | local_internal mem_arena * | ||
| 31 | arena_create(u64 capacity); | ||
| 32 | |||
| 33 | local_internal void | ||
| 34 | arena_destroy(mem_arena *arena); | ||
| 35 | |||
| 36 | local_internal void * | ||
| 37 | arena_push(mem_arena *arena, u64 size, b32 non_zero); | ||
| 38 | |||
| 39 | local_internal void | ||
| 40 | arena_pop(mem_arena *arena, u64 size); | ||
| 41 | |||
| 42 | local_internal void | ||
| 43 | arena_pop_to(mem_arena *arena, u64 pos); | ||
| 44 | |||
| 45 | local_internal void | ||
| 46 | arena_clear(mem_arena *arena); | ||
| 47 | |||
| 48 | |||
| 49 | #endif | ||
