]> pd.if.org Git - pdclib/blob - functions/stdio/_vcbprintf.c
Cosmetic comment fixes.
[pdclib] / functions / stdio / _vcbprintf.c
1 /* vsnprintf( char *, size_t, const char *, va_list )
2
3    This file is part of the Public Domain C Library (PDCLib).
4    Permission is granted to use, modify, and / or redistribute at will.
5 */
6
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <stdbool.h>
10
11 #ifndef REGTEST
12 #include "_PDCLIB_io.h"
13
14 /* returns true if callback-based output succeeded; else false */
15 static inline bool cbout(
16     struct _PDCLIB_status_t * status,
17     const char *buf,
18     size_t size )
19 {
20     size_t rv = status->write( status->ctx, buf, size );
21     status->i += rv;
22     return rv == size;
23 }
24
25 int _vcbprintf(
26     void *p,
27     size_t ( *cb ) ( void *p, const char *buf, size_t size ),
28     const char *format,
29     va_list arg )
30 {
31     struct _PDCLIB_status_t status;
32     status.base     = 0;
33     status.flags    = 0;
34     status.n        = 0;
35     status.i        = 0;
36     status.current  = 0;
37     status.width    = 0;
38     status.prec     = 0;
39     status.ctx      = p;
40     status.write    = cb;
41     va_copy( status.arg, arg );
42
43     /* Alternate between outputing runs of verbatim text and conversions */
44     while ( *format != '\0' )
45     {
46         const char *mark = format;
47         while ( *format != '\0' && *format != '%')
48         {
49             format++;
50         }
51
52         if ( mark != format )
53         {
54             if ( !cbout(&status, mark, format - mark) )
55                 return -1;
56         }
57
58         if ( *format == '%' ) {
59             int consumed = _PDCLIB_print( format, &status );
60             if ( consumed > 0 )
61             {
62                 format += consumed;
63             }
64             else if ( consumed == 0 )
65             {
66                 /* not a conversion specifier, print verbatim */
67                 if ( !cbout(&status, format++, 1) )
68                     return -1;
69             }
70             else
71             {
72                 /* I/O callback error */
73                 return -1;
74             }
75         }
76     }
77
78     va_end( status.arg );
79     return status.i;
80 }
81
82 #endif
83
84 #ifdef TEST
85 #define _PDCLIB_FILEID "stdio/_vcbprintf.c"
86 #define _PDCLIB_STRINGIO
87 #include <stdint.h>
88 #include <stddef.h>
89 #include "_PDCLIB_test.h"
90
91 #ifndef REGTEST
92
93 static size_t testcb( void *p, const char *buf, size_t size )
94 {
95     char **destbuf = p;
96     memcpy(*destbuf, buf, size);
97     *destbuf += size;
98     return size;
99 }
100
101 static int testprintf( char * s, const char * format, ... )
102 {
103     int i;
104     va_list arg;
105     va_start( arg, format );
106     i = _vcbprintf( &s, testcb, format, arg );
107     *s = 0;
108     va_end( arg );
109     return i;
110 }
111
112 #endif
113
114 int main( void )
115 {
116 #ifndef REGTEST
117     char target[100];
118 #include "printf_testcases.h"
119 #endif
120     return TEST_RESULTS;
121 }
122
123 #endif
124