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:
parent
0079ec774a
commit
80831e50b9
|
@ -83,7 +83,7 @@ if test "x$ob_cv_strftime_z" = x"no"; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_HEADERS(poll.h sys/select.h)
|
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(socket, socket, [SOCK_LIBS="-lsocket"])
|
||||||
AC_CHECK_LIB(nsl, inet_ntoa, [SOCK_LIBS="$SOCK_LIBS -lnsl"])
|
AC_CHECK_LIB(nsl, inet_ntoa, [SOCK_LIBS="$SOCK_LIBS -lnsl"])
|
||||||
|
|
|
@ -166,6 +166,7 @@ void ATTR_PRINTFLIKE(1, 2) sys_error( const char *, ... );
|
||||||
void flushn( void );
|
void flushn( void );
|
||||||
|
|
||||||
char *xvasprintf( const char *fmt, va_list ap );
|
char *xvasprintf( const char *fmt, va_list ap );
|
||||||
|
void xprintf( const char *fmt, ... );
|
||||||
|
|
||||||
#if !defined(_POSIX_SYNCHRONIZED_IO) || _POSIX_SYNCHRONIZED_IO <= 0
|
#if !defined(_POSIX_SYNCHRONIZED_IO) || _POSIX_SYNCHRONIZED_IO <= 0
|
||||||
# define fdatasync fsync
|
# define fdatasync fsync
|
||||||
|
|
47
src/util.c
47
src/util.c
|
@ -198,8 +198,10 @@ sys_error( const char *msg, ... )
|
||||||
#define QPRINTF_SEGS 16
|
#define QPRINTF_SEGS 16
|
||||||
#define QPRINTF_BUFF 1000
|
#define QPRINTF_BUFF 1000
|
||||||
|
|
||||||
char *
|
typedef void (*printf_cb)( const char **segs, uint *segls, int nsegs, uint totlen, void *aux );
|
||||||
xvasprintf( const char *fmt, va_list ap )
|
|
||||||
|
static void
|
||||||
|
xvprintf_core( const char *fmt, va_list ap, printf_cb cb, void *cb_aux )
|
||||||
{
|
{
|
||||||
int nsegs = 0;
|
int nsegs = 0;
|
||||||
uint totlen = 0;
|
uint totlen = 0;
|
||||||
|
@ -320,15 +322,54 @@ xvasprintf( const char *fmt, va_list ap )
|
||||||
fmt++;
|
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++) {
|
for (int i = 0; i < nsegs; i++) {
|
||||||
memcpy( d, segs[i], segls[i] );
|
memcpy( d, segs[i], segls[i] );
|
||||||
d += segls[i];
|
d += segls[i];
|
||||||
}
|
}
|
||||||
*d = 0;
|
*d = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
xvasprintf( const char *fmt, va_list ap )
|
||||||
|
{
|
||||||
|
char *out;
|
||||||
|
xvprintf_core( fmt, ap, xasprintf_cb, &out );
|
||||||
return 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
|
void
|
||||||
vFprintf( FILE *f, const char *msg, va_list va )
|
vFprintf( FILE *f, const char *msg, va_list va )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user