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.
This commit is contained in:
Oswald Buddenhagen 2022-06-09 14:25:39 +02:00
parent 0079ec774a
commit 80831e50b9
3 changed files with 46 additions and 4 deletions

View File

@ -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"])

View File

@ -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

View File

@ -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 )
{