isync

mailbox synchronization program
git clone https://git.code.sf.net/p/isync/isync
Log | Files | Refs | README | LICENSE

commit 80831e50b967c8475f1fcc0e19e3aa992f9eb242
parent 0079ec774a6e79b417a1f2daa1220d1c5df6e5b8
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date:   Thu,  9 Jun 2022 14:25:39 +0200

add xprintf()

this introduces a "commit" callback to the xprintf kernel, to avoid
pointlessly assembling a temporary output string prior to printing it.

one could lift the buffer limitations by introducing a "segment"
callback instead, but that would slow down xvasprintf() due to the
higher callback rate, for no good reason.

Diffstat:
Mconfigure.ac | 2+-
Msrc/common.h | 1+
Msrc/util.c | 47++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -83,7 +83,7 @@ if test "x$ob_cv_strftime_z" = x"no"; then fi AC_CHECK_HEADERS(poll.h sys/select.h) -AC_CHECK_FUNCS(vasprintf strnlen memrchr timegm) +AC_CHECK_FUNCS(vasprintf strnlen memrchr timegm fwrite_unlocked) AC_CHECK_LIB(socket, socket, [SOCK_LIBS="-lsocket"]) AC_CHECK_LIB(nsl, inet_ntoa, [SOCK_LIBS="$SOCK_LIBS -lnsl"]) diff --git a/src/common.h b/src/common.h @@ -166,6 +166,7 @@ void ATTR_PRINTFLIKE(1, 2) sys_error( const char *, ... ); void flushn( void ); char *xvasprintf( const char *fmt, va_list ap ); +void xprintf( const char *fmt, ... ); #if !defined(_POSIX_SYNCHRONIZED_IO) || _POSIX_SYNCHRONIZED_IO <= 0 # define fdatasync fsync diff --git a/src/util.c b/src/util.c @@ -198,8 +198,10 @@ sys_error( const char *msg, ... ) #define QPRINTF_SEGS 16 #define QPRINTF_BUFF 1000 -char * -xvasprintf( const char *fmt, va_list ap ) +typedef void (*printf_cb)( const char **segs, uint *segls, int nsegs, uint totlen, void *aux ); + +static void +xvprintf_core( const char *fmt, va_list ap, printf_cb cb, void *cb_aux ) { int nsegs = 0; uint totlen = 0; @@ -320,15 +322,54 @@ xvasprintf( const char *fmt, va_list ap ) fmt++; } } - char *out = d = nfmalloc( totlen + 1 ); + cb( segs, segls, nsegs, totlen, cb_aux ); +} + +static void +xasprintf_cb( const char **segs, uint *segls, int nsegs, uint totlen, void *aux ) +{ + char *d = nfmalloc( totlen + 1 ); + *(char **)aux = d; for (int i = 0; i < nsegs; i++) { memcpy( d, segs[i], segls[i] ); d += segls[i]; } *d = 0; +} + +char * +xvasprintf( const char *fmt, va_list ap ) +{ + char *out; + xvprintf_core( fmt, ap, xasprintf_cb, &out ); return out; } +#ifndef HAVE_FWRITE_UNLOCKED +# define flockfile(f) +# define funlockfile(f) +# define fwrite_unlocked(b, l, n, f) fwrite(b, l, n, f) +#endif + +static void +xprintf_cb( const char **segs, uint *segls, int nsegs, uint totlen ATTR_UNUSED, void *aux ATTR_UNUSED ) +{ + flockfile( stdout ); + for (int i = 0; i < nsegs; i++) + fwrite_unlocked( segs[i], 1, segls[i], stdout ); + funlockfile( stdout ); +} + +void +xprintf( const char *fmt, ... ) +{ + va_list va; + + va_start( va, fmt ); + xvprintf_core( fmt, va, xprintf_cb, NULL ); + va_end( va ); +} + void vFprintf( FILE *f, const char *msg, va_list va ) {