@@@ doc wip
[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,
c752173d
MW
182.I a
183should be a pointer to an arena,
184typically
185.BR arena_global (3);
adec5584
MW
186.BI * buf_inout
187should be a pointer to a buffer of
188.BI * sz_inout
c752173d
MW
189bytes, allocated from the arena
190.IR a ;
adec5584
MW
191instead,
192.BI * buf_inout
193may be null
194if
195.BI * sz_inout
196is zero.
197The
198.I maxsz
199and
200.I p
201arguments are the maximum output size and format string passed to the
202.B nputf
203function,
204and
205.I ap
206is the format-argument list, captured using
207.BR va_start (3).
208The function will adjust the buffer pointer and size as necessary,
209write the formatted result to the buffer, null-terminated,
210and return the actual output length.
211The function is designed to be efficient when called multiple times,
212retaining the same buffer across calls,
213resizing it as necessary in a geometric progression.
adec5584
MW
214.PP
215A typical
216.B nputf
217function using
218.B gprintf_memputf
219might look something like this.
220.VS
221.ta 2n
222struct my_output {
223 /* output state */
224 char *buf;
225 size_t sz;
226 /* ...\& other members ...\& */
227};
d056fbdf 228.VP
adec5584 229/* ...\& define putch and putm ...\& */
d056fbdf 230.VP
adec5584
MW
231static int nputf(void *out, size_t maxsz, const char *p, ...)
232{
233 struct my_output *myout = out;
234 va_list ap;
235 int n;
d056fbdf 236.VP
adec5584
MW
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}
d056fbdf 243.VP
adec5584 244const struct gprintf_ops my_output_ops = { putch, putm, nputf };
d056fbdf 245.VP
adec5584 246/* ...\& */
d056fbdf 247.VP
adec5584 248struct my_output myout;
d056fbdf 249.VP
adec5584
MW
250myout.buf = 0; myout.sz = 0;
251/* ...\& other initialization ...\& */
252gprintf(&my_output_ops, &myout, "Hello, %s!", "world");
253xfree(myout.buf); myout.buf = 0; myout.sz = 0;
254/* ...\& other cleanup ...\& */
255.VE
256.
c4ccbbf9 257.\"--------------------------------------------------------------------------
adec5584 258.SH "SEE ALSO"
c4ccbbf9 259.
adec5584
MW
260.BR buf (3),
261.BR dstr (3),
262.BR mLib (3).
263.
c4ccbbf9 264.\"--------------------------------------------------------------------------
adec5584 265.SH AUTHOR
c4ccbbf9
MW
266.
267.\"--------------------------------------------------------------------------
adec5584 268Mark Wooding, <mdw@distorted.org.uk>
c4ccbbf9
MW
269.
270.\"----- That's all, folks --------------------------------------------------