2 * Copyright 2014, Nathaniel Wesley Filardo.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to permit
9 * persons to whom the Software is furnished to do so, subject to the
10 * following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
18 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include <afsconfig.h>
25 #include <afs/param.h>
30 struct opr_fmt_ctx_priv_s
{
38 opr_fmt_cb(opr_fmt_ctx
*x
, char c
) {
41 if(x
->priv
->outleft
> 0) {
42 *(x
->priv
->outp
++) = c
;
48 opr_fmt_internal(opr_fmt_ctx
*ctx
, va_list va
)
50 opr_fmt_ctx_priv
*priv
= ctx
->priv
;
53 while((c
= *(priv
->inp
++))) {
62 if((fmtr
= ctx
->fmtrs
[(unsigned int) c
]) != NULL
) {
63 switch(fmtr(ctx
, c
, va
)) {
65 case 0: sawpct
= 0; break;
67 default: opr_Assert(0);
75 opr_fmt_cb(ctx
, '\0'); priv
->written
--;
81 * Carry out a %-escaped variable interpolation according to a given set of
82 * callbacks, user data, and format string. Output is placed into the given
83 * buffer, and no more than the indicated number of bytes will be written.
85 * Each formatter callback receives
86 * - the formatting context
87 * - the escape character being processed
88 * - the suffix of the varargs passed to opr_fmt
89 * To write to the output buffer, it should invoke ctx->put with ctx and the
90 * desired emission character. It should return one of 0 to indicate
91 * success and exit from escape state; 1 to indicate success and a desire
92 * to continue in escape state (e.g. while scanning for modifiers as in
93 * %0x); or -1 to indicate failure, which will abort the whole opr_fmt call.
95 * @param fmtrs Is a 256-entry array of callbacks, one for each possible
96 * unsigned char value. (char is cast to an unsigned int,
98 * @param user Passed through to the callbacks for callee's use.
99 * @param out Output buffer. Will always be properly nul-terminated on
100 * successful (i.e. non-negative) return.
101 * @param n Maximum number of bytes to write to the output buffer.
102 * @param fstr The format string. Additional arguments are passed to the
103 * callbacks for their use ala printf.
105 * @return The number of bytes that were (if >= 0 and < n) or would have been
106 * (if >= n) written to the buffer, excluding the terminating nul
107 * byte; in the latter case, the buffer is full of the first n-1
108 * bytes of the string (and is properly nul-terminated). (This
109 * follows C99's printf conventions and may allow user code to
110 * repeat the call with a big enough buffer the next time, rather
111 * than needing to probe for a large enough buffer.) If the return
112 * value is < 0, an error occurred during one of the callbacks'
116 opr_fmt(opr_fmtr
*fmtrs
, void *user
, char *out
, int n
, const char *fstr
, ...)
118 opr_fmt_ctx_priv priv
;
130 ctx
.put
= opr_fmt_cb
;
134 ret
= opr_fmt_internal(&ctx
, va
);
137 if (ret
> 0 && ret
>= n
) {