chiark / gitweb /
@@@ more tty mess
[mLib] / utils / gprintf.3.in
1 .\" -*-nroff-*-
2 .\"
3 .\" Manual for generalized output formatting
4 .\"
5 .\" (c) 2024 Straylight/Edgeware
6 .\"
7 .
8 .\"----- Licensing notice ---------------------------------------------------
9 .\"
10 .\" This file is part of the mLib utilities library.
11 .\"
12 .\" mLib is free software: you can redistribute it and/or modify it under
13 .\" the terms of the GNU Library General Public License as published by
14 .\" the Free Software Foundation; either version 2 of the License, or (at
15 .\" your option) any later version.
16 .\"
17 .\" mLib is distributed in the hope that it will be useful, but WITHOUT
18 .\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 .\" FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
20 .\" License for more details.
21 .\"
22 .\" You should have received a copy of the GNU Library General Public
23 .\" License along with mLib.  If not, write to the Free Software
24 .\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 .\" USA.
26 .
27 .\"--------------------------------------------------------------------------
28 .so ../defs.man \" @@@PRE@@@
29 .
30 .\"--------------------------------------------------------------------------
31 .TH gprintf 3mLib "9 March 2024" "Straylight/Edgeware" "mLib utilities library"
32 .\" @gprintf
33 .\" @vgprintf
34 .\" @gprintf_memputf
35 .
36 .\" @file_printops
37 .
38 .\"--------------------------------------------------------------------------
39 .SH NAME
40 gprintf \- generalized output formatting
41 .
42 .\"--------------------------------------------------------------------------
43 .SH SYNOPSIS
44 .
45 .nf
46 .B "#include <mLib/gprintf.h>"
47 .PP
48 .ta 2n
49 .B "struct gprintf_ops {"
50 .BI "   int (*putch)(void *" out ", int " ch ");"
51 .BI "   int (*putm)(void *" out ", const char *" p ", size_t " sz ");"
52 .BI "   int (*nputf)(void *" out ", size_t " maxsz ", const char *" p ", ...);"
53 .B "};"
54 .PP
55 .BI "int gprintf(const struct gprintf_ops *" ops ", void *" out ","
56 .ta \w'\fBint gprintf('u
57 .BI "   const char *" p ", ...);"
58 .BI "int vgprintf(const struct gprintf_ops *" ops ", void *" out ","
59 .ta \w'\fBint vgprintf('u
60 .BI "   const char *" p ", va_list *" ap ");"
61 .PP
62 .BI "int gprintf_memputf(char **" buf_inout ", size_t *" sz_inout ","
63 .ta \w'\fBint gprintf_memputf('u
64 .BI "   size_t " maxsz ", const char *" p ", va_list " ap ");"
65 .PP
66 .B "const struct gprintf_ops file_printops;"
67 .fi
68 .
69 .\"--------------------------------------------------------------------------
70 .SH DESCRIPTION
71 .
72 The
73 .B "<mLib/gprintf.h>"
74 header file declares facilities for generalized output formatting
75 \(en i.e.,
76 .BR printf (3)-like
77 formatting to arbitrary output sinks.
78 This is the mechanism underlying the
79 .BR dstr_putf (3)
80 and
81 .BR buf_putstrf...(3)
82 functions.
83 .PP
84 The formatting is intended to be convenient and safe
85 rather than efficient,
86 so don't expect blistering performance.
87 Similarly, there may be differences
88 between the formatting done by
89 .B gprintf
90 and the C ilbrary's
91 .BR sprintf (3)
92 because the former has to do most of its work itself.
93 In particular,
94 .B gprintf
95 understands the POSIX
96 .RB ` n$ '
97 positional parameter notation accepted by many Unix C libraries,
98 even if the underlying C library does not.
99 .PP
100 To use it, you must define a
101 .B "struct gprintf_ops"
102 structure,
103 providing functions to write the formatted output to your chosen sink.
104 Each function receives a void pointer argument named
105 .IR out ,
106 which is simply the
107 .I out
108 argument passed to
109 .RB ( v ) gprintf ,
110 and should return the number of characters that it wrote
111 \(en or at least some nonnegative value \(en
112 on success,
113 or \-1 if it encountered an error.
114 .PP
115 The three functions are:
116 .hP \*o
117 .BR putch :
118 write out the single character
119 .IR ch ,
120 which is an integer holding an
121 .B "unsigned char"
122 value, as used by
123 .BR fputc (3).
124 .hP \*o
125 .BR putm :
126 write out
127 .I sz
128 characters from the buffer starting at
129 .IR p .
130 .hP \*o
131 .BR nputf :
132 process the format string
133 .I p
134 and arguments
135 .IR ap ,
136 writing out the formatted output;
137 the output will not be longer than
138 .I maxsz
139 characters.
140 .PP
141 It may seem paradoxical for
142 .B gprintf
143 to require the backend to do string formatting,
144 since its entire purpose is to do string formatting for you;
145 but implementing the
146 .B nputf
147 function can typically be done straightforwardly enough by calling
148 .BR snprintf (3)
149 or similar.
150 Difficult cases can be dealt with using
151 .BR gprintf_memputf ,
152 described below.
153 .PP
154 The
155 .B gprintf
156 function formats a string
157 .I p
158 together with its variable argument list,
159 using the provided output operations
160 .IR ops ,
161 and passing them the pointer
162 .I out
163 when it calls on them.
164 The
165 .B vgprintf
166 function is similar,
167 except that it receives the format arguments as
168 .I "a pointer to"
169 a captured
170 .B va_list
171 argument tail.
172 The argument tail is updated in place,
173 and (on successful completion)
174 is left referring to the first unused argument.
175 .PP
176 The
177 .B gprintf_memputf
178 function is a utility for implementing
179 .B nputf
180 operations.
181 On entry,
182 .I a
183 should be a pointer to an arena,
184 typically
185 .BR arena_global (3);
186 .BI * buf_inout
187 should be a pointer to a buffer of
188 .BI * sz_inout
189 bytes, allocated from the arena
190 .IR a ;
191 instead,
192 .BI * buf_inout
193 may be null
194 if
195 .BI * sz_inout
196 is zero.
197 The
198 .I maxsz
199 and
200 .I p
201 arguments are the maximum output size and format string passed to the
202 .B nputf
203 function,
204 and
205 .I ap
206 is the format-argument list, captured using
207 .BR va_start (3).
208 The function will adjust the buffer pointer and size as necessary,
209 write the formatted result to the buffer, null-terminated,
210 and return the actual output length.
211 The function is designed to be efficient when called multiple times,
212 retaining the same buffer across calls,
213 resizing it as necessary in a geometric progression.
214 .PP
215 A typical
216 .B nputf
217 function using
218 .B gprintf_memputf
219 might look something like this.
220 .VS
221 .ta 2n
222 struct my_output {
223         /* output state */
224         char *buf;
225         size_t sz;
226         /* ...\& other members ...\& */
227 };
228 .VP
229 /* ...\& define putch and putm ...\& */
230 .VP
231 static int nputf(void *out, size_t maxsz, const char *p, ...)
232 {
233         struct my_output *myout = out;
234         va_list ap;
235         int n;
236 .VP
237         va_start(ap, p);
238         n = gprintf_memputf(&myout->buf, &myout->sz, maxsz, p, ap);
239         va_end(ap);
240         if (n > 0) n = putm(myout, myout->buf, n);
241         return (n);
242 }
243 .VP
244 const struct gprintf_ops my_output_ops = { putch, putm, nputf };
245 .VP
246 /* ...\& */
247 .VP
248 struct my_output myout;
249 .VP
250 myout.buf = 0; myout.sz = 0;
251 /* ...\& other initialization ...\& */
252 gprintf(&my_output_ops, &myout, "Hello, %s!", "world");
253 xfree(myout.buf); myout.buf = 0; myout.sz = 0;
254 /* ...\& other cleanup ...\& */
255 .VE
256 .
257 .\"--------------------------------------------------------------------------
258 .SH "SEE ALSO"
259 .
260 .BR buf (3),
261 .BR dstr (3),
262 .BR mLib (3).
263 .
264 .\"--------------------------------------------------------------------------
265 .SH AUTHOR
266 .
267 .\"--------------------------------------------------------------------------
268 Mark Wooding, <mdw@distorted.org.uk>
269 .
270 .\"----- That's all, folks --------------------------------------------------