@@@ man wip
[mLib] / utils / gprintf.3
CommitLineData
adec5584
MW
1.\" -*-nroff-*-
2.de VS
3.sp 1
4.RS
5.nf
6.ft B
7..
8.de VE
9.ft R
10.fi
11.RE
12.sp 1
13..
14.de hP
15.IP
16.ft B
17\h'-\w'\\$1\ 'u'\\$1\ \c
18.ft P
19..
d056fbdf
MW
20.ie t \{\
21. ds o \(bu
22. de VP
23. sp .4v
24..
25\}
26.el \{\
27. ds o o
28. de VP
29. sp
30..
31\}
adec5584
MW
32.
33.TH gprintf 3 "9 March 2024" "Straylight/Edgeware" "mLib utilities library"
34.
35.SH NAME
36gprintf \- generalized output formatting
37.
38.SH SYNOPSIS
39.nf
40.B "#include <mLib/gprintf.h>"
d056fbdf 41.PP
adec5584
MW
42.ta 2n
43.B "struct gprintf_ops {"
44.BI " int (*putch)(void *" out ", int " ch ");"
45.BI " int (*putm)(void *" out ", const char *" p ", size_t " sz ");"
46.BI " int (*nputf)(void *" out ", size_t " maxsz ", const char *" p ", ...);"
47.B "};"
d056fbdf 48.PP
adec5584
MW
49.BI "int gprintf(const struct gprintf_ops *" ops ", void *" out ","
50.ta \w'\fBint gprintf('u
51.BI " const char *" p ", ...);"
52.BI "int vgprintf(const struct gprintf_ops *" ops ", void *" out ","
53.ta \w'\fBint vgprintf('u
54.BI " const char *" p ", va_list *" ap ");"
d056fbdf 55.PP
adec5584
MW
56.BI "int gprintf_memputf(char **" buf_inout ", size_t *" sz_inout ","
57.ta \w'\fBint gprintf_memputf('u
58.BI " size_t " maxsz ", const char *" p ", va_list " ap ");"
d056fbdf 59.PP
adec5584
MW
60.B "const struct gprintf_ops file_printops;"
61.fi
62.
63.SH DESCRIPTION
64The
65.B "<mLib/gprintf.h>"
66header file declares facilities for generalized output formatting
67\(en i.e.,
68.BR printf (3)-like
69formatting to arbitrary output sinks.
70This is the mechanism underlying the
71.BR dstr_putf (3)
72and
73.BR buf_putstrf...(3)
74functions.
75.PP
76To use it, you must define a
77.B "struct gprintf_ops"
78structure,
79providing functions to write the formatted output to your chosen sink.
80Each function receives a void pointer argument named
81.IR out ,
82which is simply the
83.I out
84argument passed to
85.RB ( v ) gprintf ,
86and should return the number of characters that it wrote
87\(en or at least some nonnegative value \(en
88on success,
89or \-1 if it encountered an error.
90.PP
91The three functions are:
92.hP \*o
93.BR putch :
94write out the single character
95.IR ch ,
96which is an integer holding an
97.B "unsigned char"
98value, as used by
99.BR fputc (3).
100.hP \*o
101.BR putm :
102write out
103.I sz
104characters from the buffer starting at
105.IR p .
106.hP \*o
107.BR nputf :
108process the format string
109.I p
110and arguments
111.IR ap ,
112writing out the formatted output;
113the output will not be longer than
114.I maxsz
115characters.
116.PP
117It may seem paradoxical for
118.B gprintf
119to require the backend to do string formatting,
120since its entire purpose is to do string formatting for you;
121but implementing the
122.B nputf
123function can typically be done straightforwardly enough by calling
124.BR snprintf (3)
125or similar.
126Difficult cases can be dealt with using
127.BR gprintf_memputf ,
128described below.
129.PP
130The
131.B gprintf
132function formats a string
133.I p
134together with its variable argument list,
135using the provided output operations
136.IR ops ,
137and passing them the pointer
138.I out
139when it calls on them.
140The
141.B vgprintf
142function is similar,
143except that it receives the format arguments as
144.I "a pointer to"
145a captured
146.B va_list
147argument tail.
148The argument tail is updated in place,
149and (on successful completion)
150is left referring to the first unused argument.
151.PP
152The
153.B gprintf_memputf
154function is a utility for implementing
155.B nputf
156operations.
157On entry,
158.BI * buf_inout
159should be a pointer to a buffer of
160.BI * sz_inout
161bytes, allocated from
162.BR arena_global (3);
163instead,
164.BI * buf_inout
165may be null
166if
167.BI * sz_inout
168is zero.
169The
170.I maxsz
171and
172.I p
173arguments are the maximum output size and format string passed to the
174.B nputf
175function,
176and
177.I ap
178is the format-argument list, captured using
179.BR va_start (3).
180The function will adjust the buffer pointer and size as necessary,
181write the formatted result to the buffer, null-terminated,
182and return the actual output length.
183The function is designed to be efficient when called multiple times,
184retaining the same buffer across calls,
185resizing it as necessary in a geometric progression.
186When the buffer is no longer wanted, free it using
187.BR xfree (3).
188.PP
189A typical
190.B nputf
191function using
192.B gprintf_memputf
193might look something like this.
194.VS
195.ta 2n
196struct my_output {
197 /* output state */
198 char *buf;
199 size_t sz;
200 /* ...\& other members ...\& */
201};
d056fbdf 202.VP
adec5584 203/* ...\& define putch and putm ...\& */
d056fbdf 204.VP
adec5584
MW
205static int nputf(void *out, size_t maxsz, const char *p, ...)
206{
207 struct my_output *myout = out;
208 va_list ap;
209 int n;
d056fbdf 210.VP
adec5584
MW
211 va_start(ap, p);
212 n = gprintf_memputf(&myout->buf, &myout->sz, maxsz, p, ap);
213 va_end(ap);
214 if (n > 0) n = putm(myout, myout->buf, n);
215 return (n);
216}
d056fbdf 217.VP
adec5584 218const struct gprintf_ops my_output_ops = { putch, putm, nputf };
d056fbdf 219.VP
adec5584 220/* ...\& */
d056fbdf 221.VP
adec5584 222struct my_output myout;
d056fbdf 223.VP
adec5584
MW
224myout.buf = 0; myout.sz = 0;
225/* ...\& other initialization ...\& */
226gprintf(&my_output_ops, &myout, "Hello, %s!", "world");
227xfree(myout.buf); myout.buf = 0; myout.sz = 0;
228/* ...\& other cleanup ...\& */
229.VE
230.
231.SH "SEE ALSO"
232.BR buf (3),
233.BR dstr (3),
234.BR mLib (3).
235.
236.SH AUTHOR
237Mark Wooding, <mdw@distorted.org.uk>