20
points
I've been frustrated by the lack of a truly portable, no-dependency printf for embedded and kernel development. Most solutions are either too bloated or missing key features.
So I built Uprintf. It's a single-header library that gives you full printf (flags, width, precision, floats, even custom specifiers) from bare metal to desktop, with zero dependencies or #ifdef hell.
Key features:
· One header file, no dependencies, no dynamic allocation
· Full standard support: %d, %x, %f, %.*s, etc.
· Extensible with custom format handlers (add %T for your project)
· Configurable: disable floats, set locale, etc.
· MIT Licensed.
GitHub: https://github.com/Ferki-git-creator/Uprintf
I'd love your feedback and contributions!
Is it really possible to reconcile "no bloat" with "fully standard compliant"?
Maybe have a look at https://github.com/eyalroz/printf, if only for the test suite, which looks pretty comprehensive and still fails.
Maybe "key features" does not mean the same in all projects, making every project appear "unnecessarily bloated while missing key features" in every other context?
I encourage you to continue working on your projects.
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdl...
https://manpages.debian.org/testing/avr-libc/ultoa.3avr.en.h...
https://www.ibm.com/docs/en/zos/2.4.0?topic=functions-utoa-c...
https://www.qnx.com/developers/docs/6.3.2/neutrino/lib_ref/u...
Here is the documentation for the problem you mentioned.
I had a bug:
prints:--42
I may have found an explanation. In u_parse_format(), case 'i': calls u_itoa( value, buffer, 10, false ); which outputs minus sign.
Then if ( number ) does if ( sign ) { output_cb( '-', ctx ); chars_written++; } which outputs another minus sign.
https://github.com/Ferki-git-creator/Uprintf/issues/1
https://github.com/Ferki-git-creator/Uprintf/issues/2
https://github.com/Ferki-git-creator/Uprintf/pull/3
https://github.com/Ferki-git-creator/Uprintf/pull/4
You could add a c file with some unittests.
snprintf always null-terminates when the buffer length is greater than 0 and there's no error. That is, if snprintf returns >= 0 and the buffer length is > 0, the output is null-terminated.
This should be clear from your local snprintf(3) man page (e.g. https://man.openbsd.org/snprintf), but also see the C23 standard (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf) and POSIX (https://pubs.opengroup.org/onlinepubs/9799919799/).
There's the infamous strncpy, of course, which understandably could cause some confusion. And various non-vendor faux-snprintf implementations, like uprintf, that have different semantics. It's hazardous to reuse a standardized name like snprintf, even as a suffix, in an API but not implement the same fundamental semantics.
See section 'Remark' on: https://learn.microsoft.com/en-us/cpp/c-runtime-library/refe...