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