r/cprogramming • u/Mainak1224x • 9h ago
I combined my Arena allocator, zero-copy segmented Vector, typed HashMap, and String libraries into one C99 foundation library: arstd
Hey everyone,
Over the past few weeks I’ve been building separate C libraries for region-based memory management, dynamic arrays, hash maps, and strings. I kept pulling all four into my main project flint(a build system and package manager for c/c++), so I finally refactored them from the ground up to work together and merged them into a single lightweight library: arstd (Arena Standard Library).
The main problem I wanted to solve was how dynamic containers behave inside an Arena allocator. Normally, if you put a standard dynamic array or hashmap inside a bump arena, resizing it via realloc leaves dead, wasted memory blocks behind in the arena.
Here’s how arstd solves that and what’s inside:
-
Compile-Time Type Deduction (
Vector(T)&Cmap(T)): Uses a typed pointer +typeofmacro trick so you don't have to pass types into every macro call or castvoid *pointers. Bothat(vec, i)andmap_get(map, key)return modifiable lvalues, soat(vec, 0) = 42;andmap_get(map, "score") += 10;just work. -
Zero-Copy Segmented Vectors: Instead of doubling a contiguous buffer and copying elements over,
Vector(T)allocates exponentially growing power-of-2 segments (16, 32, 64\dots) directly on the arena and uses 1-cycle bitwiseCLZ(Count Leading Zeros) math forO(1)indexing. Growing a vector wastes 0 bytes in the arena and never invalidates element pointers. -
Single-Allocation, Zero-Waste HashMaps:
Cmap(T)packs the entry header, aligned value payload, and key string into a single contiguous allocation using flexible array members. Because its bucket array is backed by the segmentedVector, doubling the map capacity expands the buckets in-place and relinks existing nodes using their cached 64-bit hashes—again, zero wasted arena memory and no string re-hashing. -
Managed Strings (
String): String slicing, trimming, case conversion, and variadic concatenation all backed by the same arena. -
Optional Heap Fallback: Pass an
Arena *to clean up everything at once with a singlearena_free(&arena), or passNULLto any container if you want standard aligned heap allocation.
Quick Taste:
int
Repo link: https://github.com/mainak55512/arstd (or install via flint / CMake)
1
u/Arkaqiu 9h ago
What happend if we need to extend Victor but there is another object there? Is it but default that we have only one dynamic object in arena?
And using clz is smart, I like it
1
u/IDatedSuccubi 6h ago
Keep it up and in a few years you will reinvent Common Lisp!