.\" -*-nroff-*- .\" .\" Manual for generalized output formatting .\" .\" (c) 2024 Straylight/Edgeware .\" . .\"----- Licensing notice --------------------------------------------------- .\" .\" This file is part of the mLib utilities library. .\" .\" mLib is free software: you can redistribute it and/or modify it under .\" the terms of the GNU Library General Public License as published by .\" the Free Software Foundation; either version 2 of the License, or (at .\" your option) any later version. .\" .\" mLib is distributed in the hope that it will be useful, but WITHOUT .\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or .\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public .\" License for more details. .\" .\" You should have received a copy of the GNU Library General Public .\" License along with mLib. If not, write to the Free Software .\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, .\" USA. . .\"-------------------------------------------------------------------------- .so ../defs.man \" @@@PRE@@@ . .\"-------------------------------------------------------------------------- .TH gprintf 3mLib "9 March 2024" "Straylight/Edgeware" "mLib utilities library" .\" @gprintf .\" @vgprintf .\" @gprintf_memputf . .\" @file_printops . .\"-------------------------------------------------------------------------- .SH NAME gprintf \- generalized output formatting . .\"-------------------------------------------------------------------------- .SH SYNOPSIS . .nf .B "#include " .PP .ta 2n .B "struct gprintf_ops {" .BI " int (*putch)(void *" out ", int " ch ");" .BI " int (*putm)(void *" out ", const char *" p ", size_t " sz ");" .BI " int (*nputf)(void *" out ", size_t " maxsz ", const char *" p ", ...);" .B "};" .PP .BI "int gprintf(const struct gprintf_ops *" ops ", void *" out "," .ta \w'\fBint gprintf('u .BI " const char *" p ", ...);" .BI "int vgprintf(const struct gprintf_ops *" ops ", void *" out "," .ta \w'\fBint vgprintf('u .BI " const char *" p ", va_list *" ap ");" .PP .BI "int gprintf_memputf(char **" buf_inout ", size_t *" sz_inout "," .ta \w'\fBint gprintf_memputf('u .BI " size_t " maxsz ", const char *" p ", va_list " ap ");" .PP .B "const struct gprintf_ops file_printops;" .fi . .\"-------------------------------------------------------------------------- .SH DESCRIPTION . The .B "" header file declares facilities for generalized output formatting \(en i.e., .BR printf (3)-like formatting to arbitrary output sinks. This is the mechanism underlying the .BR dstr_putf (3) and .BR buf_putstrf...(3) functions. .PP The formatting is intended to be convenient and safe rather than efficient, so don't expect blistering performance. Similarly, there may be differences between the formatting done by .B gprintf and the C ilbrary's .BR sprintf (3) because the former has to do most of its work itself. In particular, .B gprintf understands the POSIX .RB ` n$ ' positional parameter notation accepted by many Unix C libraries, even if the underlying C library does not. .PP To use it, you must define a .B "struct gprintf_ops" structure, providing functions to write the formatted output to your chosen sink. Each function receives a void pointer argument named .IR out , which is simply the .I out argument passed to .RB ( v ) gprintf , and should return the number of characters that it wrote \(en or at least some nonnegative value \(en on success, or \-1 if it encountered an error. .PP The three functions are: .hP \*o .BR putch : write out the single character .IR ch , which is an integer holding an .B "unsigned char" value, as used by .BR fputc (3). .hP \*o .BR putm : write out .I sz characters from the buffer starting at .IR p . .hP \*o .BR nputf : process the format string .I p and arguments .IR ap , writing out the formatted output; the output will not be longer than .I maxsz characters. .PP It may seem paradoxical for .B gprintf to require the backend to do string formatting, since its entire purpose is to do string formatting for you; but implementing the .B nputf function can typically be done straightforwardly enough by calling .BR snprintf (3) or similar. Difficult cases can be dealt with using .BR gprintf_memputf , described below. .PP The .B gprintf function formats a string .I p together with its variable argument list, using the provided output operations .IR ops , and passing them the pointer .I out when it calls on them. The .B vgprintf function is similar, except that it receives the format arguments as .I "a pointer to" a captured .B va_list argument tail. The argument tail is updated in place, and (on successful completion) is left referring to the first unused argument. .PP The .B gprintf_memputf function is a utility for implementing .B nputf operations. On entry, .I a should be a pointer to an arena, typically .BR arena_global (3); .BI * buf_inout should be a pointer to a buffer of .BI * sz_inout bytes, allocated from the arena .IR a ; instead, .BI * buf_inout may be null if .BI * sz_inout is zero. The .I maxsz and .I p arguments are the maximum output size and format string passed to the .B nputf function, and .I ap is the format-argument list, captured using .BR va_start (3). The function will adjust the buffer pointer and size as necessary, write the formatted result to the buffer, null-terminated, and return the actual output length. The function is designed to be efficient when called multiple times, retaining the same buffer across calls, resizing it as necessary in a geometric progression. .PP A typical .B nputf function using .B gprintf_memputf might look something like this. .VS .ta 2n struct my_output { /* output state */ char *buf; size_t sz; /* ...\& other members ...\& */ }; .VP /* ...\& define putch and putm ...\& */ .VP static int nputf(void *out, size_t maxsz, const char *p, ...) { struct my_output *myout = out; va_list ap; int n; .VP va_start(ap, p); n = gprintf_memputf(&myout->buf, &myout->sz, maxsz, p, ap); va_end(ap); if (n > 0) n = putm(myout, myout->buf, n); return (n); } .VP const struct gprintf_ops my_output_ops = { putch, putm, nputf }; .VP /* ...\& */ .VP struct my_output myout; .VP myout.buf = 0; myout.sz = 0; /* ...\& other initialization ...\& */ gprintf(&my_output_ops, &myout, "Hello, %s!", "world"); xfree(myout.buf); myout.buf = 0; myout.sz = 0; /* ...\& other cleanup ...\& */ .VE . .\"-------------------------------------------------------------------------- .SH "SEE ALSO" . .BR buf (3), .BR dstr (3), .BR mLib (3). . .\"-------------------------------------------------------------------------- .SH AUTHOR . .\"-------------------------------------------------------------------------- Mark Wooding, . .\"----- That's all, folks --------------------------------------------------