Browse Source

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.
wip/maildir-path-under-inbox
Oswald Buddenhagen 2 years ago
parent
commit
80831e50b9
  1. 2
      configure.ac
  2. 1
      src/common.h
  3. 47
      src/util.c

2
configure.ac

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

1
src/common.h

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

@ -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…
Cancel
Save