mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
xsnprintf: various improvements related to xvsnprintf() and xsnprintf()
Summary of changes:
* Make xvsnprintf() static
* restrict-qualify pointer arguments (as done by the libc equivalents)
* Make comments and spec references more thorough
* Remove pointless `n <= INT_MAX` assertion (see comment)
* Use FATAL_ERROR() instead of xassert() (since the assertion is inside
a shared util function but the caller is responsible for ensuring the
condition holds true)
* Change some callers to use size_t instead of int for the return value
(negative returns are impossible and all subsequent uses are size_t)
The updated comments and code were taken (and adapted) from:
49260bb154/src/util/xsnprintf.c (L6-50)
This work was entirely authored by me and I hereby license this
contribution under the MIT license (stated explicitly, so that
there's no ambiguity w.r.t. the original license).
This commit is contained in:
parent
31f88e636c
commit
d4a1283797
8 changed files with 54 additions and 35 deletions
53
xsnprintf.c
53
xsnprintf.c
|
|
@ -1,32 +1,51 @@
|
|||
#include "xsnprintf.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include "debug.h"
|
||||
#include "macros.h"
|
||||
|
||||
size_t
|
||||
xvsnprintf(char *buf, size_t n, const char *format, va_list ap)
|
||||
/*
|
||||
* ISO C doesn't require vsnprintf(3) to set errno on failure, but
|
||||
* POSIX does:
|
||||
*
|
||||
* "If an output error was encountered, these functions shall return
|
||||
* a negative value and set errno to indicate the error."
|
||||
*
|
||||
* The mandated errors of interest are:
|
||||
*
|
||||
* - EILSEQ: A wide-character code does not correspond to a valid character
|
||||
* - EOVERFLOW: The value of n is greater than INT_MAX
|
||||
* - EOVERFLOW: The value to be returned is greater than INT_MAX
|
||||
*
|
||||
* ISO C11 states:
|
||||
*
|
||||
* "The vsnprintf function returns the number of characters that would
|
||||
* have been written had n been sufficiently large, not counting the
|
||||
* terminating null character, or a negative value if an encoding error
|
||||
* occurred. Thus, the null-terminated output has been completely
|
||||
* written if and only if the returned value is nonnegative and less
|
||||
* than n."
|
||||
*
|
||||
* See also:
|
||||
*
|
||||
* - ISO C11 §7.21.6.12p3
|
||||
* - https://pubs.opengroup.org/onlinepubs/9699919799/functions/vsnprintf.html
|
||||
* - https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html
|
||||
*/
|
||||
static size_t
|
||||
xvsnprintf(char *restrict buf, size_t n, const char *restrict format, va_list ap)
|
||||
{
|
||||
xassert(n <= INT_MAX);
|
||||
int len = vsnprintf(buf, n, format, ap);
|
||||
|
||||
/*
|
||||
* ISO C11 §7.21.6.5 states:
|
||||
* "The snprintf function returns the number of characters that
|
||||
* would have been written had n been sufficiently large, not
|
||||
* counting the terminating null character, or a negative value
|
||||
* if an encoding error occurred. Thus, the null-terminated output
|
||||
* has been completely written if and only if the returned value
|
||||
* is nonnegative and less than n."
|
||||
*/
|
||||
xassert(len >= 0);
|
||||
xassert(len < (int)n);
|
||||
|
||||
if (unlikely(len < 0 || len >= (int)n)) {
|
||||
FATAL_ERROR(__func__, (len < 0) ? errno : ENOBUFS);
|
||||
}
|
||||
return (size_t)len;
|
||||
}
|
||||
|
||||
size_t
|
||||
xsnprintf(char *buf, size_t n, const char *format, ...)
|
||||
xsnprintf(char *restrict buf, size_t n, const char *restrict format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue