Zero: A Bunch of Single-File Libraries for C/C++

For the needs of a project I’m working on, I had to write an aligned allocator on top of malloc()/realloc()/free() and a simple logger featuring different log levels and basic colouring. Nothing too fancy here.

It was obvious that the code had nothing specific to that project and was in fact a good fit for a more general-purpose library.

So I decided to jump into the single-file, header-only, libraries bandwagon started by Sean Barrett and his popular stb project by releasing my own: Zero.

ZeroView on GitHub

While developing Zero, I was influenced by the Physical Design of The Machinery and chose not to have any #include dependency within the library headers. That’s right. Not even standard headers. [1] Why’s that? Because standard headers contain thousands of lines of code when counting their own dependencies and I do not want to slow down compilation times by burdening projects that include my headers into their own headers. At least, not without a good reason. Are fixed integer types or size_t a good enough reason? Not even.

Most projects target common platforms (Windows, Linux, macOS) and hence use either the ILP32, LP64, or LLP64 data models. All of these data models guarantee the char type to be 8 bits, short to be 16 bits, int to be 32 bits, and long long to be 64 bits. For people using more exotic platforms, Zero can fallback to using <stdint.h> if the macro ZR_USE_STD_FIXED_TYPES is defined. Even better, each type can be overridden individually through macros such as ZR_INT32.

The same goes for size_t—on almost all platforms the size of size_t equals the targetted architecture, that is either 32 or 64 bits. Here again, there is a fallback macro with ZR_USE_STD_BASIC_TYPES that includes <stddef.h>, and a more granular one ZR_SIZE_TYPE to directly set the size type to be used.

Note that these custom types are only used in the public interface defined within the headers. The implementation side of things is free to include whatever file is needed, which is fine since these dependencies are to remain within a single translation unit rather than spreading all over the place through the #include mechanism.

As always, it’s all on GitHub, so go get it!