bunkum

an old and silly c99 web server with some fun features
Log | Files | Refs | README

commit 9a3f229d3556657e4442bf407a3e7179748cb59c
parent e6baea87a494775c0f245e77ca254c395db56d54
Author: quantumish <freifeld.david@gmail.com>
Date:   Sun, 19 Nov 2023 15:44:37 -0500

Actually add README.

Diffstat:
Areadme.md | 17+++++++++++++++++
Autils/result.c | 0
Autils/toml.c | 0
Autils/vec.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autils/vec.h | 29+++++++++++++++++++++++++++++
5 files changed, 119 insertions(+), 0 deletions(-)

diff --git a/readme.md b/readme.md @@ -0,0 +1,17 @@ +# bunkum + +A silly personal webserver with the goal to hand-roll basically whatever I can (only dependencies are pthread, zlib, and libunwind). + +Fun features include +- **Self-profiling**. If you pass a "Profile" header in any request, `bunkum` will automatically profile itself as it serves the request and report the profile info. This was remarkably painful to implement given weird quirks of the ptrace() API for child threads. +- A **custom testing framework** with **automatic test discovery**. After compiling the code as a dynamic library, It works by parsing the ELF file to extract symbol names and find all of those that start with "test". As there's an enforced test interface, it can then load the dynamic library and run the tests. +- A custom **channel type** for inter-thread communications that is directly implemented with atomic intrinsics +- A silly **PHF** for rapidly converting HTTP methods to their enum form +```c +const enum http_method method_codes[] = {DELETE, CONNECT, PUT, POST, TRACE, HEAD, OPTIONS, GET}; +enum http_method method_enum(char* p) { + return method_codes[((*(uint64_t*)p*0x1b8b6e6d) % 0x100000000) >> 28]; +} +``` +alongside others (custom logging, data structures, html generation utilities, etc.) + diff --git a/utils/result.c b/utils/result.c diff --git a/utils/toml.c b/utils/toml.c diff --git a/utils/vec.c b/utils/vec.c @@ -0,0 +1,73 @@ +#include <stdlib.h> +#include <string.h> + +#include "vec.h" + +vec_t vec_new(size_t e_sz) { + vec_t sv; + sv.alloc_sz = SHITVEC_INIT_SZ; + sv.vec_sz = 0; + sv.e_sz = e_sz; + sv.arr = malloc(sv.alloc_sz); + memset(sv.arr, 0, sv.alloc_sz); + return sv; +} + +void* vec_get(vec_t* sv, size_t index) { + if (index > sv->vec_sz) return 0x0; + return sv->arr+(sv->e_sz * index); +} + +void* vec_last(vec_t* sv) { + return vec_get(sv, sv->vec_sz-1); +} + +void vec_push(vec_t* sv, void* item) { + // FIXME sketchy af + if ((sv->arr+(2 * sv->e_sz * sv->vec_sz)) > sv->arr+sv->alloc_sz) { + sv->arr = realloc(sv->arr, sv->alloc_sz * 2); + sv->alloc_sz *= 2; + } + memcpy(sv->arr+(sv->vec_sz * sv->e_sz), item, sv->e_sz); + sv->vec_sz += 1; +} + +void vec_subpush(vec_t* sv, void* item, size_t sz) { + sv->vec_sz += 1; + if ((sv->arr+(sv->e_sz * sv->vec_sz)) > sv->arr+sv->alloc_sz) { + sv->arr = realloc(sv->arr, sv->alloc_sz * 2); + } + memcpy(sv->arr+(sv->vec_sz * sv->e_sz), item, sz); +} + +int vec_check(vec_t* sv, void* item, sv_cmp_t cmp) { + for (size_t i = 0; i < sv->vec_sz; i++) { + if (cmp(sv->arr+(i*sv->e_sz), item) == 0) { + return i; + } + } + return -1; +} + +void vec_sort(vec_t* sv, int(*cmp)(const void*, const void*)) { + qsort(sv->arr, sv->vec_sz, sv->e_sz, cmp); +} + +void vec_free(vec_t* sv) { + free(sv->arr); +} + +#ifdef TEST +#include "../test.h" + +void test_vec_sanity() { + vec_t sv = vec_new(8); + vec_push(&sv, "whee"); + vec_push(&sv, "whoo"); + assert_str_eq("whee", vec_get(&sv, 0)); + assert_str_eq("whoo", vec_get(&sv, 1)); + assert_size_eq(2, sv.vec_sz); + assert_size_eq(8, sv.e_sz); + assert_bool(vec_check(&sv, "whoo", (sv_cmp_t)strcmp)); +}; +#endif diff --git a/utils/vec.h b/utils/vec.h @@ -0,0 +1,29 @@ +#ifndef SHITVEC_H +#define SHITVEC_H + +#include <stddef.h> +#include <stdbool.h> + +#define SHITVEC_INIT_SZ 1024 + +typedef struct vec { + void* arr; + size_t e_sz; + size_t alloc_sz; + size_t vec_sz; +} vec_t; + +typedef int(*sv_cmp_t)(void*, void*); + +vec_t vec_new(size_t e_sz); +void* vec_get(vec_t* sv, size_t index); +void* vec_last(vec_t* sv); +void vec_push(vec_t* sv, void* item); +void vec_subpush(vec_t* sv, void* item, size_t sz); +int vec_check(vec_t* sv, void* item, sv_cmp_t cmp); +void vec_sort(vec_t* sv, int(*cmp)(const void*, const void*)); +void vec_free(vec_t* sv); + +#endif + +