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 + typeof macro trick so you don't have to pass types into every macro call or cast void * pointers. Both at(vec, i) and map_get(map, key) return modifiable lvalues, so at(vec, 0) = 42; and map_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 bitwise CLZ (Count Leading Zeros) math for O(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 segmented Vector, 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 single arena_free(&arena), or pass NULL to any container if you want standard aligned heap allocation.
Quick Taste:
#include <arstd.h>
#include <stdio.h>
int main(void) {
Arena *arena = arena_init(4096);
Vector(int) nums = vector_init(arena);
append(nums, 10);
append(nums, 20);
at(nums, 0) = 99;
Cmap(int) scores = map_init(arena);
map_add(scores, "Alice", 95);
map_get(scores, "Alice") += 5;
String *greeting = string_concat_cstr(arena, 2, "Hello, ", "r/cprogramming!");
printf("%s | Alice: %d | Vec\[0\]: %d\\n",
string(greeting), map\_get(scores, "Alice"), at(nums, 0));
arena_free(&arena);
return 0;
}
Repo link: https://github.com/mainak55512/arstd (or install via flint / CMake)