Zero-heap memory manager in C11.
You declare a pool: a block of bytes, whose placement is settled by which declaration you write. LocusCarcerum dresses a pool as a cellblock, and a cellblock hands out cells from both ends. The persistent tier grows up from base, the temporary tier grows down from size, and the gap between them is what either can still take. An allocation neither the gap nor a free cell of its tier can meet returns NULL and moves no boundary. Spans are bounded views over cells, and rings move bytes between one producer and one consumer.
Nothing calls malloc. Every size is fixed before the program runs. The footprint is a number you can check against a budget before the program starts.
Each of these is a claim the documentation has to answer for, and each links to the page that does.
| If you want to | Read |
|---|---|
| Build it and run something | Start here |
| Understand how the pieces fit | How it works |
| Find the module you need | The modules |
| Look up a knob, a name or a number | Reference |
| Know what is tested and analyzed | Correctness |
| Contribute, or read the license | Project |
The modules carry Latin category names: locus_carcerum is the region and its pools, spatium is a span, verbum_scrutor is the SWAR scanner. Every one of them is decoded in The Latin, decoded.
The reason is that libc and <string.h> are everywhere, and these are not libc functions. They reach the same conclusion for the same input, across every domain, and share nothing else. How they reach it is entirely different.
The backend is machine-width parallel word processing throughout. Bitmath is extensive and SIMD within a register is used wherever it applies. That gives speed far above the traditional embedded string and memory routines in far less space. A name that collided with libc's would suggest a drop-in replacement of the implementation as well as the result, and it is not one.
That difference is also why the testing is what it is. Every translation unit is fuzzed with bit strobing, bit waves, clock stretching and other abuse the internals will never meet in service. On top of that: interoperability against libc, newlib and GNU; correctness; binary size; and resource allocation lifetime cycles.
The call-site idiom follows from that. Each module exposes a dispatch table named for a short stem, and every entry takes one argument: a pointer to that module's config struct. EMBED_CALL builds it as a compound literal. A call reads EMBED_CALL(spat.from, SpatiumCfg, .buf = buf, .cap = n) with the arguments named instead of ordered. Both forms exist and both are documented; the free function is what the table points at. The dispatch table idiom