/src/wget2/libwget/buffer_printf.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2012 Tim Ruehsen |
3 | | * Copyright (c) 2015-2024 Free Software Foundation, Inc. |
4 | | * |
5 | | * This file is part of libwget. |
6 | | * |
7 | | * Libwget is free software: you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as published by |
9 | | * the Free Software Foundation, either version 3 of the License, or |
10 | | * (at your option) any later version. |
11 | | * |
12 | | * Libwget is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public License |
18 | | * along with libwget. If not, see <https://www.gnu.org/licenses/>. |
19 | | * |
20 | | * |
21 | | * Memory buffer printf routines |
22 | | * |
23 | | * Changelog |
24 | | * 24.09.2012 Tim Ruehsen created |
25 | | * |
26 | | */ |
27 | | |
28 | | #include <config.h> |
29 | | |
30 | | #include <stdio.h> |
31 | | #include <stdlib.h> |
32 | | #include <string.h> |
33 | | #include <stdbool.h> |
34 | | #include <c-ctype.h> |
35 | | |
36 | | #include <wget.h> |
37 | | #include "private.h" |
38 | | |
39 | | /** |
40 | | * \file |
41 | | * \brief Buffer management functions |
42 | | * \defgroup libwget-buffer Buffer management functions |
43 | | * @{ |
44 | | */ |
45 | | |
46 | | /* \cond _hide_internal_symbols */ |
47 | 2.65M | #define FLAG_ZERO_PADDED 1U |
48 | 42.2k | #define FLAG_LEFT_ADJUST 2U |
49 | 0 | #define FLAG_ALTERNATE 4U |
50 | 32.2k | #define FLAG_SIGNED 8U |
51 | 2.64M | #define FLAG_DECIMAL 16U |
52 | 0 | #define FLAG_OCTAL 32U |
53 | 2.61M | #define FLAG_HEXLO 64U |
54 | 5.23M | #define FLAG_HEXUP 128U |
55 | | /* \endcond */ |
56 | | |
57 | | static void copy_string(wget_buffer *buf, unsigned int flags, int field_width, int precision, const char *arg) |
58 | 389k | { |
59 | 389k | size_t length; |
60 | | |
61 | 389k | if (!arg) { |
62 | 402 | wget_buffer_strcat(buf, "(null)"); |
63 | 402 | return; |
64 | 402 | } |
65 | | |
66 | 388k | if (precision >= 0) { |
67 | 387k | length = strnlen(arg, precision); |
68 | 387k | } else { |
69 | 1.20k | length = strlen(arg); |
70 | 1.20k | } |
71 | | |
72 | | // debug_printf("flags=0x%02x field_width=%d precision=%d length=%zu arg='%s'\n", |
73 | | // flags,field_width,precision,length,arg); |
74 | | |
75 | 388k | if (field_width) { |
76 | 1.60k | if ((unsigned)field_width > length) { |
77 | 1.53k | if (flags & FLAG_LEFT_ADJUST) { |
78 | 331 | wget_buffer_memcat(buf, arg, length); |
79 | 331 | wget_buffer_memset_append(buf, ' ', field_width - length); |
80 | 1.20k | } else { |
81 | 1.20k | wget_buffer_memset_append(buf, ' ', field_width - length); |
82 | 1.20k | wget_buffer_memcat(buf, arg, length); |
83 | 1.20k | } |
84 | 1.53k | } else { |
85 | 71 | wget_buffer_memcat(buf, arg, length); |
86 | 71 | } |
87 | 387k | } else { |
88 | 387k | wget_buffer_memcat(buf, arg, length); |
89 | 387k | } |
90 | 388k | } |
91 | | |
92 | | static void convert_dec_fast(wget_buffer *buf, int arg) |
93 | 11.2k | { |
94 | 11.2k | char str[32]; // long enough to hold decimal long long |
95 | 11.2k | char *dst = str + sizeof(str) - 1; |
96 | 11.2k | int minus; |
97 | | |
98 | 11.2k | if (arg < 0) { |
99 | 5.65k | minus = 1; |
100 | 5.65k | arg = -arg; |
101 | 5.65k | } else |
102 | 5.58k | minus = 0; |
103 | | |
104 | 16.1k | while (arg >= 10) { |
105 | 4.87k | *dst-- = (arg % 10) + '0'; |
106 | 4.87k | arg /= 10; |
107 | 4.87k | } |
108 | 11.2k | *dst-- = (arg % 10) + '0'; |
109 | | |
110 | 11.2k | if (minus) |
111 | 5.65k | *dst-- = '-'; |
112 | | |
113 | 11.2k | wget_buffer_memcat(buf, dst + 1, sizeof(str) - (dst - str) - 1); |
114 | 11.2k | } |
115 | | |
116 | | static void convert_dec(wget_buffer *buf, unsigned int flags, int field_width, int precision, long long arg) |
117 | 2.63M | { |
118 | 2.63M | unsigned long long argu = (unsigned long long) arg; |
119 | 2.63M | char str[32], minus = 0; // long enough to hold decimal long long |
120 | 2.63M | char *dst = str + sizeof(str) - 1; |
121 | 2.63M | unsigned char c; |
122 | 2.63M | size_t length; |
123 | | |
124 | | // info_printf("arg1 = %lld %lld\n",arg,-arg); |
125 | | |
126 | 2.63M | if (flags & FLAG_DECIMAL) { |
127 | 15.1k | if (flags & FLAG_SIGNED && arg < 0) { |
128 | 0 | minus = 1; |
129 | 0 | argu = -arg; |
130 | 0 | } |
131 | | |
132 | 27.2k | while (argu) { |
133 | 12.0k | *dst-- = argu % 10 + '0'; |
134 | 12.0k | argu /= 10; |
135 | 12.0k | } |
136 | 2.61M | } else if (flags & FLAG_HEXLO) { |
137 | 0 | while (argu) { |
138 | | // slightly faster than having a HEX[] lookup table |
139 | 0 | *dst-- = (c = (argu & 0xf)) >= 10 ? c + 'a' - 10 : c + '0'; |
140 | 0 | argu >>= 4; |
141 | 0 | } |
142 | 2.61M | } else if (flags & FLAG_HEXUP) { |
143 | 7.81M | while (argu) { |
144 | | // slightly faster than having a HEX[] lookup table |
145 | 5.19M | *dst-- = (c = (argu & 0xf)) >= 10 ? c + 'A' - 10 : c + '0'; |
146 | 5.19M | argu >>= 4; |
147 | 5.19M | } |
148 | 2.61M | } else if (flags & FLAG_OCTAL) { |
149 | 0 | while (argu) { |
150 | 0 | *dst-- = (argu & 0x07) + '0'; |
151 | 0 | argu >>= 3; |
152 | 0 | } |
153 | 0 | } |
154 | | |
155 | | // info_printf("arg2 = %lld\n",arg); |
156 | | |
157 | | |
158 | 2.63M | dst++; |
159 | | |
160 | 2.63M | length = sizeof(str) - (dst - str); |
161 | | |
162 | 2.63M | if (precision < 0) { |
163 | 2.63M | precision = 1; |
164 | 2.63M | } else { |
165 | 0 | flags &= ~FLAG_ZERO_PADDED; |
166 | 0 | } |
167 | | |
168 | | // info_printf("flags=0x%02x field_width=%d precision=%d length=%zd dst='%.*s'\n", |
169 | | // flags,field_width,precision,length,length,dst); |
170 | | |
171 | 2.63M | if (field_width) { |
172 | 2.61M | if ((unsigned)field_width > length + minus) { |
173 | 39.8k | if (flags & FLAG_LEFT_ADJUST) { |
174 | 0 | if (minus) |
175 | 0 | wget_buffer_memset_append(buf, '-', 1); |
176 | |
|
177 | 0 | if (length < (unsigned)precision) { |
178 | 0 | wget_buffer_memset_append(buf, '0', precision - length); |
179 | 0 | wget_buffer_memcat(buf, dst, length); |
180 | 0 | if (field_width > precision + minus) |
181 | 0 | wget_buffer_memset_append(buf, ' ', field_width - precision - minus); |
182 | 0 | } else { |
183 | 0 | wget_buffer_memcat(buf, dst, length); |
184 | 0 | wget_buffer_memset_append(buf, ' ', field_width - length - minus); |
185 | 0 | } |
186 | 39.8k | } else { |
187 | 39.8k | if (length < (unsigned)precision) { |
188 | 540 | if (field_width > precision + minus) { |
189 | 540 | if (flags & FLAG_ZERO_PADDED) { |
190 | 89 | if (minus) |
191 | 0 | wget_buffer_memset_append(buf, '-', 1); |
192 | 89 | wget_buffer_memset_append(buf, '0', field_width - precision - minus); |
193 | 451 | } else { |
194 | 451 | wget_buffer_memset_append(buf, ' ', field_width - precision - minus); |
195 | 451 | if (minus) |
196 | 0 | wget_buffer_memset_append(buf, '-', 1); |
197 | 451 | } |
198 | 540 | } else { |
199 | 0 | if (minus) |
200 | 0 | wget_buffer_memset_append(buf, '-', 1); |
201 | 0 | } |
202 | 540 | wget_buffer_memset_append(buf, '0', precision - length); |
203 | 39.3k | } else { |
204 | 39.3k | if (flags & FLAG_ZERO_PADDED) { |
205 | 39.3k | if (minus) |
206 | 0 | wget_buffer_memset_append(buf, '-', 1); |
207 | 39.3k | wget_buffer_memset_append(buf, '0', field_width - length - minus); |
208 | 39.3k | } else { |
209 | 33 | wget_buffer_memset_append(buf, ' ', field_width - length - minus); |
210 | 33 | if (minus) |
211 | 0 | wget_buffer_memset_append(buf, '-', 1); |
212 | 33 | } |
213 | 39.3k | } |
214 | 39.8k | wget_buffer_memcat(buf, dst, length); |
215 | 39.8k | } |
216 | 2.57M | } else { |
217 | 2.57M | if (minus) |
218 | 0 | wget_buffer_memset_append(buf, '-', 1); |
219 | 2.57M | if (length < (unsigned)precision) |
220 | 0 | wget_buffer_memset_append(buf, '0', precision - length); |
221 | 2.57M | wget_buffer_memcat(buf, dst, length); |
222 | 2.57M | } |
223 | 2.61M | } else { |
224 | 13.9k | if (minus) |
225 | 0 | wget_buffer_memset_append(buf, '-', 1); |
226 | | |
227 | 13.9k | if (length < (unsigned)precision) |
228 | 9.54k | wget_buffer_memset_append(buf, '0', precision - length); |
229 | | |
230 | 13.9k | wget_buffer_memcat(buf, dst, length); |
231 | 13.9k | } |
232 | 2.63M | } |
233 | | |
234 | | static void convert_pointer(wget_buffer *buf, void *pointer) |
235 | 0 | { |
236 | 0 | static const char HEX[16] = "0123456789abcdef"; |
237 | 0 | char str[32]; // long enough to hold hexadecimal pointer |
238 | 0 | char *dst; |
239 | 0 | int length; |
240 | 0 | size_t arg; |
241 | |
|
242 | 0 | if (!pointer) { |
243 | 0 | wget_buffer_memcat(buf, "0x0", 3); |
244 | 0 | return; |
245 | 0 | } else { |
246 | 0 | wget_buffer_memcat(buf, "0x", 2); |
247 | 0 | } |
248 | | |
249 | | // convert to a size_t (covers full address room) tp allow integer arithmetic |
250 | 0 | arg = (size_t)pointer; |
251 | |
|
252 | 0 | length = 0; |
253 | 0 | dst = str + sizeof(str); |
254 | 0 | *--dst = 0; |
255 | 0 | do { |
256 | 0 | *--dst = HEX[arg&0xF]; |
257 | 0 | arg >>= 4; |
258 | 0 | length++; |
259 | 0 | } while (arg); |
260 | |
|
261 | 0 | wget_buffer_memcat(buf, dst, length); |
262 | 0 | } |
263 | | |
264 | | static const char *read_precision(const char *p, int *out, bool precision_is_external) |
265 | 387k | { |
266 | 387k | int precision; |
267 | | |
268 | 387k | if (precision_is_external) { |
269 | 387k | precision = *out; |
270 | 387k | if (precision < 0 ) |
271 | 0 | precision = 0; |
272 | 387k | p++; |
273 | 387k | } else if (c_isdigit(*p)) { |
274 | 0 | precision = 0; |
275 | 0 | do { |
276 | 0 | precision = precision * 10 + (*p - '0'); |
277 | 0 | } while (c_isdigit(*++p)); |
278 | 0 | } else { |
279 | 0 | precision = -1; |
280 | 0 | } |
281 | | |
282 | 387k | *out = precision; |
283 | 387k | return p; |
284 | 387k | } |
285 | | |
286 | | static const char *read_flag_chars(const char *p, unsigned int *out) |
287 | 3.02M | { |
288 | 3.02M | unsigned int flags; |
289 | | |
290 | 5.64M | for (flags = 0; *p; p++) { |
291 | 5.64M | if (*p == '0') |
292 | 2.61M | flags |= FLAG_ZERO_PADDED; |
293 | 3.02M | else if (*p == '-') |
294 | 804 | flags |= FLAG_LEFT_ADJUST; |
295 | 3.02M | else if (*p == '#') |
296 | 0 | flags |= FLAG_ALTERNATE; |
297 | 3.02M | else |
298 | 3.02M | break; |
299 | 5.64M | } |
300 | | |
301 | 3.02M | *out = flags; |
302 | 3.02M | return p; |
303 | 3.02M | } |
304 | | |
305 | | static const char *read_field_width(const char *p, int *out, unsigned int *flags, bool width_is_external) |
306 | 3.02M | { |
307 | 3.02M | int field_width; |
308 | | |
309 | 3.02M | if (width_is_external) { |
310 | 2.61k | field_width = *out; |
311 | | |
312 | 2.61k | if (field_width < 0) { |
313 | 0 | *flags |= FLAG_LEFT_ADJUST; |
314 | 0 | field_width = -field_width; |
315 | 0 | } |
316 | | |
317 | 2.61k | p++; |
318 | 3.01M | } else { |
319 | 5.63M | for (field_width = 0; c_isdigit(*p); p++) |
320 | 2.61M | field_width = field_width * 10 + (*p - '0'); |
321 | 3.01M | } |
322 | | |
323 | 3.02M | *out = field_width; |
324 | 3.02M | return p; |
325 | 3.02M | } |
326 | | |
327 | | /** |
328 | | * \param[in] buf A buffer, created with wget_buffer_init() or wget_buffer_alloc() |
329 | | * \param[in] fmt A `printf(3)`-like format string |
330 | | * \param[in] args A `va_list` with the format string placeholders' values |
331 | | * \return Length of the buffer after appending the formatted string |
332 | | * |
333 | | * Formats the string \p fmt (with `printf(3)`-like args) and appends the result to the end |
334 | | * of the buffer \p buf (using wget_buffer_memcat()). |
335 | | * |
336 | | * For more information, see `vprintf(3)`. |
337 | | */ |
338 | | size_t wget_buffer_vprintf_append(wget_buffer *buf, const char *fmt, va_list args) |
339 | 3.14M | { |
340 | 3.14M | const char *p = fmt, *begin; |
341 | 3.14M | int field_width, precision; |
342 | 3.14M | unsigned int flags; |
343 | 3.14M | long long arg; |
344 | 3.14M | unsigned long long argu; |
345 | | |
346 | 3.14M | if (!p) |
347 | 0 | return 0; |
348 | | |
349 | 9.02M | for (;*p;) { |
350 | | |
351 | | /* |
352 | | * Collect plain char sequence. |
353 | | * Walk the string until we find a '%' character. |
354 | | */ |
355 | 6.82M | for (begin = p; *p && *p != '%'; p++); |
356 | 5.93M | if (p != begin) |
357 | 228k | wget_buffer_memcat(buf, begin, p - begin); |
358 | | |
359 | 5.93M | if (!*p) |
360 | 61.2k | break; |
361 | | |
362 | | /* Shortcut to %s and %p, handle %% */ |
363 | 5.87M | if (*++p == 's') { |
364 | 226k | const char *s = va_arg(args, const char *); |
365 | 226k | wget_buffer_strcat(buf, s ? s : "(null)"); |
366 | 226k | p++; |
367 | 226k | continue; |
368 | 5.65M | } else if (*p == 'd') { |
369 | 11.2k | convert_dec_fast(buf, va_arg(args, int)); |
370 | 11.2k | p++; |
371 | 11.2k | continue; |
372 | 5.64M | } else if (*p == 'c') { |
373 | 823 | char c = (char ) va_arg(args, int); |
374 | 823 | wget_buffer_memcat(buf, &c, 1); |
375 | 823 | p++; |
376 | 823 | continue; |
377 | 5.63M | } else if (*p == 'p') { |
378 | 0 | convert_pointer(buf, va_arg(args, void *)); |
379 | 0 | p++; |
380 | 0 | continue; |
381 | 5.63M | } else if (*p == '%') { |
382 | 2.61M | wget_buffer_memset_append(buf, '%', 1); |
383 | 2.61M | p++; |
384 | 2.61M | continue; |
385 | 2.61M | } |
386 | | |
387 | | /* Read the flag chars (optional, simplified) */ |
388 | 3.02M | p = read_flag_chars(p, &flags); |
389 | | |
390 | | /* |
391 | | * Read field width (optional). |
392 | | * If '*', then the field width is given as an additional argument, |
393 | | * which precedes the argument to be formatted. |
394 | | */ |
395 | 3.02M | if (*p == '*') { |
396 | 2.61k | field_width = va_arg(args, int); |
397 | 2.61k | p = read_field_width(p, &field_width, &flags, 1); |
398 | 3.01M | } else { |
399 | 3.01M | p = read_field_width(p, &field_width, &flags, 0); |
400 | 3.01M | } |
401 | | |
402 | | /* |
403 | | * Read precision (optional). |
404 | | * If '*', the precision is given as an additional argument, |
405 | | * just as the case for the field width. |
406 | | */ |
407 | 3.02M | if (*p == '.') { |
408 | 387k | if (*++p == '*') { |
409 | 387k | precision = va_arg(args, int); |
410 | 387k | p = read_precision(p, &precision, 1); |
411 | 387k | } else { |
412 | 0 | p = read_precision(p, &precision, 0); |
413 | 0 | } |
414 | 387k | } else |
415 | 2.63M | precision = -1; |
416 | | |
417 | | /* Read length modifier (optional) */ |
418 | 3.02M | switch (*p) { |
419 | 0 | case 'z': |
420 | 0 | arg = va_arg(args, ssize_t); |
421 | 0 | argu = (size_t)arg; |
422 | 0 | p++; |
423 | 0 | break; |
424 | | |
425 | 681 | case 'l': |
426 | 681 | if (p[1] == 'l') { |
427 | 681 | p += 2; |
428 | 681 | arg = va_arg(args, long long); |
429 | 681 | argu = (unsigned long long)arg; |
430 | 681 | } else { |
431 | 0 | p++; |
432 | 0 | arg = (long)va_arg(args, long); |
433 | 0 | argu = (unsigned long)arg; |
434 | 0 | } |
435 | 681 | break; |
436 | | |
437 | 0 | case 'L': |
438 | 0 | p++; |
439 | 0 | arg = va_arg(args, long long); |
440 | 0 | argu = (unsigned long long)arg; |
441 | 0 | break; |
442 | | |
443 | 3.94k | case 'h': |
444 | 3.94k | if (p[1] == 'h') { |
445 | 0 | p += 2; |
446 | 0 | arg = (signed char) va_arg(args, int); |
447 | 0 | argu = (unsigned char) arg; |
448 | 3.94k | } else { |
449 | 3.94k | p++; |
450 | 3.94k | arg = (short) va_arg(args, int); |
451 | 3.94k | argu = (unsigned short) arg; |
452 | 3.94k | } |
453 | 3.94k | break; |
454 | | |
455 | 389k | case 's': |
456 | 389k | p++; |
457 | 389k | copy_string(buf, flags, field_width, precision, va_arg(args, const char *)); |
458 | 389k | continue; |
459 | | |
460 | 0 | case 'c': |
461 | 0 | { |
462 | 0 | char c[2] = { (char) va_arg(args, int), 0 }; |
463 | 0 | p++; |
464 | 0 | copy_string(buf, flags, field_width, precision, c); |
465 | 0 | continue; |
466 | 0 | } |
467 | | |
468 | 0 | case 'p': // %p shortcut |
469 | 0 | p++; |
470 | 0 | convert_dec(buf, flags | FLAG_HEXLO | FLAG_ALTERNATE, field_width, precision, (long long)(ptrdiff_t)va_arg(args, void *)); |
471 | 0 | continue; |
472 | | |
473 | 2.62M | default: |
474 | 2.62M | arg = va_arg(args, int); |
475 | 2.62M | argu = (unsigned int)arg; |
476 | 3.02M | } |
477 | | |
478 | 2.63M | if (*p == 'd' || *p == 'i') { |
479 | 1.89k | convert_dec(buf, flags | FLAG_SIGNED | FLAG_DECIMAL, field_width, precision, arg); |
480 | 2.63M | } else if (*p == 'u') { |
481 | 13.2k | convert_dec(buf, flags | FLAG_DECIMAL, field_width, precision, (long long) argu); |
482 | 2.61M | } else if (*p == 'x') { |
483 | 0 | convert_dec(buf, flags | FLAG_HEXLO, field_width, precision, (long long) argu); |
484 | 2.61M | } else if (*p == 'X') { |
485 | 2.61M | convert_dec(buf, flags | FLAG_HEXUP, field_width, precision, (long long) argu); |
486 | 2.61M | } else if (*p == 'o') { |
487 | 0 | convert_dec(buf, flags | FLAG_OCTAL, field_width, precision, (long long) argu); |
488 | 0 | } else { |
489 | | /* |
490 | | * This is an unknown conversion specifier, |
491 | | * so just put '%' and move on. |
492 | | */ |
493 | 0 | wget_buffer_memset_append(buf, '%', 1); |
494 | 0 | p = begin + 1; |
495 | 0 | continue; |
496 | 0 | } |
497 | | |
498 | 2.63M | p++; |
499 | 2.63M | } |
500 | | |
501 | 3.14M | return buf->length; |
502 | 3.14M | } |
503 | | |
504 | | /** |
505 | | * \param[in] buf A buffer, created with wget_buffer_init() or wget_buffer_alloc() |
506 | | * \param[in] fmt A `printf(3)`-like format string |
507 | | * \param[in] args A `va_list` with the format string placeholders' values |
508 | | * \return Length of the buffer after appending the formatted string |
509 | | * |
510 | | * Formats the string \p fmt (with `printf(3)`-like args) and overwrites the contents |
511 | | * of the buffer \p buf with that formatted string. |
512 | | * |
513 | | * This is equivalent to the following code: |
514 | | * |
515 | | * buf->length = 0; |
516 | | * wget_buffer_vprintf_append(buf, fmt, args); |
517 | | * |
518 | | * For more information, see `vprintf(3)`. |
519 | | */ |
520 | | size_t wget_buffer_vprintf(wget_buffer *buf, const char *fmt, va_list args) |
521 | 496k | { |
522 | 496k | buf->length = 0; |
523 | | |
524 | 496k | return wget_buffer_vprintf_append(buf, fmt, args); |
525 | 496k | } |
526 | | |
527 | | /** |
528 | | * \param[in] buf A buffer, created with wget_buffer_init() or wget_buffer_alloc() |
529 | | * \param[in] fmt A `printf(3)`-like format string |
530 | | * \param[in] ... Variable arguments |
531 | | * \return Length of the buffer after appending the formatted string |
532 | | * |
533 | | * Formats the string \p fmt (with `printf(3)`-like args) and appends the result to the end |
534 | | * of the buffer \p buf (using wget_buffer_memcat()). |
535 | | * |
536 | | * This function is equivalent to wget_buffer_vprintf_append(), except in that it uses |
537 | | * a variable number of arguments rather than a `va_list`. |
538 | | * |
539 | | * For more information, see `printf(3)`. |
540 | | */ |
541 | | size_t wget_buffer_printf_append(wget_buffer *buf, const char *fmt, ...) |
542 | 2.65M | { |
543 | 2.65M | va_list args; |
544 | | |
545 | 2.65M | va_start(args, fmt); |
546 | 2.65M | wget_buffer_vprintf_append(buf, fmt, args); |
547 | 2.65M | va_end(args); |
548 | | |
549 | 2.65M | return buf->length; |
550 | 2.65M | } |
551 | | |
552 | | /** |
553 | | * \param[in] buf A buffer, created with wget_buffer_init() or wget_buffer_alloc() |
554 | | * \param[in] fmt A `printf(3)`-like format string |
555 | | * \param[in] ... Variable arguments |
556 | | * \return Length of the buffer after appending the formatted string |
557 | | * |
558 | | * Formats the string \p fmt (with `printf(3)`-like args) and overwrites the contents |
559 | | * of the buffer \p buf with that formatted string. |
560 | | * |
561 | | * This function is equivalent to wget_buffer_vprintf(), except in that it uses |
562 | | * a variable number of arguments rather than a `va_list`. |
563 | | * |
564 | | * For more information, see `printf(3)`. |
565 | | */ |
566 | | size_t wget_buffer_printf(wget_buffer *buf, const char *fmt, ...) |
567 | 8.39k | { |
568 | 8.39k | va_list args; |
569 | | |
570 | 8.39k | va_start(args, fmt); |
571 | 8.39k | size_t len = wget_buffer_vprintf(buf, fmt, args); |
572 | 8.39k | va_end(args); |
573 | | |
574 | 8.39k | return len; |
575 | 8.39k | } |
576 | | /** @} */ |