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