X-Git-Url: https://pd.if.org/git/?p=pdclib.old;a=blobdiff_plain;f=functions%2Fstdio%2F_vcbprintf.c;fp=functions%2Fstdio%2F_vcbprintf.c;h=dbb217115553a93fa95d3fad5c9f3a7912043133;hp=0000000000000000000000000000000000000000;hb=3309ec3ad8a5db735eaa2de7f5dc6a331d8e7319;hpb=2d43dbb1c70aee6c3474c254c0a2302ef39c0c7a diff --git a/functions/stdio/_vcbprintf.c b/functions/stdio/_vcbprintf.c new file mode 100644 index 0000000..dbb2171 --- /dev/null +++ b/functions/stdio/_vcbprintf.c @@ -0,0 +1,126 @@ +/* $Id$ */ + +/* vsnprintf( char *, size_t, const char *, va_list ap ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include +#include +#include + +#ifndef REGTEST +#include <_PDCLIB_io.h> + +/* returns true if callback-based output succeeded; else false */ +static inline bool cbout( + struct _PDCLIB_status_t * status, + const char *buf, + size_t size ) +{ + size_t rv = status->write( status->ctx, buf, size ); + status->i += rv; + return rv == size; +} + +int _vcbprintf( + void *p, + size_t ( *cb ) ( void *p, const char *buf, size_t size ), + const char *format, + va_list arg ) +{ + struct _PDCLIB_status_t status; + status.base = 0; + status.flags = 0; + status.n = 0; + status.i = 0; + status.current = 0; + status.width = 0; + status.prec = 0; + status.ctx = p; + status.write = cb; + va_copy( status.arg, arg ); + + /* Alternate between outputing runs of verbatim text and conversions */ + while ( *format != '\0' ) + { + const char *mark = format; + while ( *format != '\0' && *format != '%') + { + format++; + } + + if ( mark != format ) + { + if ( !cbout(&status, mark, format - mark) ) + return -1; + } + + if ( *format == '%' ) { + int consumed = _PDCLIB_print( format, &status ); + if ( consumed > 0 ) + { + format += consumed; + } + else if ( consumed == 0 ) + { + /* not a conversion specifier, print verbatim */ + if ( !cbout(&status, format++, 1) ) + return -1; + } + else + { + /* I/O callback error */ + return -1; + } + } + } + + va_end( status.arg ); + return status.i; +} + +#endif + +#ifdef TEST +#define _PDCLIB_FILEID "stdio/_vcbprintf.c" +#define _PDCLIB_STRINGIO +#include +#include +#include <_PDCLIB_test.h> + +#ifndef REGTEST + +static size_t testcb( void *p, const char *buf, size_t size ) +{ + char **destbuf = p; + memcpy(*destbuf, buf, size); + *destbuf += size; + return size; +} + +static int testprintf( char * s, const char * format, ... ) +{ + int i; + va_list arg; + va_start( arg, format ); + i = _vcbprintf( &s, testcb, format, arg ); + *s = 0; + va_end( arg ); + return i; +} + +#endif + +int main( void ) +{ + char target[100]; +#ifndef REGTEST +#include "printf_testcases.h" +#endif + return TEST_RESULTS; +} + +#endif +