For a couple of embedded use case, I ended up implementing a small subset of C++’s std::format. Mine handles integer, string, and pointer arguments (including CHERI capabilities), but no positional arguments or format specifiers. It compiles down to tiny code and is type safe (it can also work with a static buffer and silently truncate the input, or write directly to a UART, with different template arguments). I can’t imagine trying to hit the same efficiency and usability point in C without a lot of macros and GCC extensions.
Your solution seems very good. Is it open source? I run a newsletter on embedded systems and I’ll be happy to share your work in it.
There’s an old version in the snmalloc repo (that’s what I wrote it for originally: I wanted to be able to do rich logging from a memory allocator, where we can’t have external dependencies and, in our error paths, can’t depend on anything other than raw system calls working). In the CHERI RTOS I have an improved version. That has a few more features (and more tuned use of always/never inline attributes to keep code size down), so I’ll probably sync it back to snmalloc at some point. I hope the repo it’s in now will be open sourced at some point soon but I want to have our red team attack it a bit more first: it’s embarrassing to releases a new secure OS and have the first security vulnerability reported in less than a day (just ask the seL4 team…).
Of course, I understand! If you know any tips for me to follow closely when it will be open source, please, let me know!
I plan on submitting it here, but the snmalloc::message API is open now if you want to take a look.