Coverage Report

Created: 2025-03-18 06:55

/src/wget2/libwget/printf.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016-2024 Free Software Foundation, Inc.
3
 *
4
 * This file is part of libwget.
5
 *
6
 * Libwget is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * Libwget is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with libwget.  If not, see <https://www.gnu.org/licenses/>.
18
 *
19
 *
20
 * printf-style routines using buffer functions
21
 *
22
 * Changelog
23
 * 13.01.2016  Tim Ruehsen  created
24
 *
25
 */
26
27
#include <config.h>
28
29
#include <wget.h>
30
#include "private.h"
31
32
/**
33
 * \file
34
 * \brief Libwget printf functions
35
 * \defgroup libwget-printf Libwget printf functions
36
 * @{
37
 *
38
 * This is a collection of printf-style functions that are used with libwget and/or Wget2 code.
39
 * They may be useful to other developers that is why they are exported.
40
 */
41
42
/**
43
 * \param[in] strp Pointer to hold the string output
44
 * \param[in] fmt Printf-like format specifier
45
 * \param[in] args va_list of arguments
46
 * \return Length of the string returned via \p strp or `(size_t) -1` on error
47
 *
48
 * Prints arguments to allocated memory and 0-terminates it. The string is returned via the first argument.
49
 * It has to be free()'d by the caller when it is no longer needed.
50
 */
51
size_t wget_vasprintf(char **strp, const char *fmt, va_list args)
52
91.4k
{
53
91.4k
  wget_buffer buf;
54
55
91.4k
  wget_buffer_init(&buf, NULL, 128);
56
57
91.4k
  size_t len = wget_buffer_vprintf(&buf, fmt, args);
58
59
91.4k
  if (unlikely(buf.error)) {
60
0
    xfree(buf.data);
61
0
    return (size_t) -1;
62
0
  }
63
64
91.4k
  if (strp) {
65
    // shrink memory to real usage
66
91.4k
    *strp = wget_realloc(buf.data, len + 1);
67
91.4k
  } else {
68
    // behave like C99/POSIX snprintf - just return the length
69
0
    xfree(buf.data);
70
0
  }
71
72
91.4k
  return len;
73
91.4k
}
74
75
/**
76
 * \param[in] strp Pointer to hold the string output
77
 * \param[in] fmt Printf-like format specifier
78
 * \param[in] ... List of arguments
79
 * \return Length of the string returned via \p strp
80
 *
81
 * Prints arguments to allocated memory and 0-terminates it. The string is returned via the first argument.
82
 * It has to be free()'d by the caller when it is no longer needed.
83
 */
84
size_t wget_asprintf(char **strp, const char *fmt, ...)
85
0
{
86
0
  va_list args;
87
88
0
  va_start(args, fmt);
89
0
  size_t len = wget_vasprintf(strp, fmt, args);
90
0
  va_end(args);
91
92
0
  return len;
93
0
}
94
95
/**
96
 * \param[in] fmt Printf-like format specifier
97
 * \param[in] args va_list of arguments
98
 * \return Pointer to 0-terminated string in memory
99
 *
100
 * Prints arguments to memory and returns a pointer to allocated and 0-terminated chunk of memory.
101
 * The return value has to be free()'d by the caller when it is no longer needed.
102
 */
103
char *wget_vaprintf(const char *fmt, va_list args)
104
111
{
105
111
  char *s = NULL;
106
107
111
  wget_vasprintf(&s, fmt, args);
108
109
111
  return s;
110
111
}
111
112
/**
113
 * \param[in] fmt Printf-like format specifier
114
 * \param[in] ... List of arguments
115
 * \return Pointer to 0-terminated string in memory
116
 *
117
 * Prints arguments to memory and returns a pointer to allocated and 0-terminated chunk of memory.
118
 * The return value has to be free()'d by the caller when it is no longer needed.
119
 */
120
char *wget_aprintf(const char *fmt, ...)
121
91.2k
{
122
91.2k
  va_list args;
123
91.2k
  char *s = NULL;
124
125
91.2k
  va_start(args, fmt);
126
91.2k
  wget_vasprintf(&s, fmt, args);
127
91.2k
  va_end(args);
128
129
91.2k
  return s;
130
91.2k
}
131
132
/**
133
 * \param[in] fp FILE pointer
134
 * \param[in] fmt Printf-like format specifier
135
 * \param[in] args List of arguments
136
 * \return Number of bytes written or -1 on error
137
 *
138
 * Prints arguments to stream \p fp and returns number of bytes written.
139
 */
140
size_t wget_vfprintf(FILE *fp, const char *fmt, va_list args)
141
2.67k
{
142
2.67k
  wget_buffer buf;
143
2.67k
  char sbuf[1024];
144
2.67k
  size_t rc;
145
146
2.67k
  wget_buffer_init(&buf, sbuf, sizeof(sbuf));
147
148
2.67k
  size_t len = wget_buffer_vprintf(&buf, fmt, args);
149
150
2.67k
  if (unlikely(buf.error)) {
151
0
    wget_buffer_deinit(&buf);
152
0
    return (size_t) -1;
153
0
  }
154
155
2.67k
  if (len > 0)
156
2.67k
    rc = fwrite(buf.data, 1, len, fp);
157
0
  else
158
0
    rc = 0;
159
160
2.67k
  wget_buffer_deinit(&buf);
161
162
2.67k
  return rc;
163
2.67k
}
164
165
/**
166
 * \param[in] fp FILE pointer
167
 * \param[in] fmt Printf-like format specifier
168
 * \param[in] ... List of arguments
169
 * \return Number of bytes written or -1 on error
170
 *
171
 * Prints arguments to stream \p fp and returns number of bytes written.
172
 */
173
size_t wget_fprintf(FILE *fp, const char *fmt, ...)
174
2.67k
{
175
2.67k
  va_list args;
176
177
2.67k
  va_start(args, fmt);
178
2.67k
  size_t rc = wget_vfprintf(fp, fmt, args);
179
2.67k
  va_end(args);
180
181
2.67k
  return rc;
182
2.67k
}
183
184
/**
185
 * \param[in] fmt Printf-like format specifier
186
 * \param[in] ... List of arguments
187
 * \return Number of bytes written or -1 on error
188
 *
189
 * Prints arguments to `stdout` and returns number of bytes written.
190
 */
191
size_t wget_printf(const char *fmt, ...)
192
0
{
193
0
  va_list args;
194
195
0
  va_start(args, fmt);
196
0
  size_t rc = wget_vfprintf(stdout, fmt, args);
197
0
  va_end(args);
198
199
0
  return rc;
200
0
}
201
202
/**
203
 * \param[in] str Destination buffer
204
 * \param[in] size Size of \p str
205
 * \param[in] fmt Printf-like format specifier
206
 * \param[in] args List of arguments
207
 * \return Number of bytes written, or, on truncation, that would have been written
208
 *
209
 * Prints arguments to buffer \p str and returns number of bytes written,
210
 * or on truncation: that would have been written.
211
 *
212
 * If \p str is %NULL the return value are the number of bytes that would have been written.
213
 */
214
size_t wget_vsnprintf(char *str, size_t size, const char *fmt, va_list args)
215
399k
{
216
399k
  wget_buffer buf;
217
218
399k
  wget_buffer_init(&buf, str, size);
219
220
399k
  size_t len = wget_buffer_vprintf(&buf, fmt, args);
221
222
399k
  if (unlikely(buf.error)) {
223
0
    wget_buffer_deinit(&buf);
224
0
    return (size_t) -1;
225
0
  }
226
227
399k
  if (str) {
228
399k
    if (buf.data == str) {
229
88.4k
      buf.data = NULL;
230
311k
    } else if (len < size) {
231
0
      memcpy(str, buf.data, len + 1);
232
311k
    } else {
233
311k
      memcpy(str, buf.data, size - 1);
234
311k
      str[size - 1] = 0;
235
311k
    }
236
399k
  }
237
238
399k
  wget_buffer_deinit(&buf);
239
240
399k
  return len;
241
399k
}
242
243
/**
244
 * \param[in] str Destination buffer
245
 * \param[in] size Size of \p str
246
 * \param[in] fmt Printf-like format specifier
247
 * \param[in] ... List of arguments
248
 * \return Number of bytes written, or, on truncation, that would have been written
249
 *
250
 * Prints arguments to buffer \p str and returns number of bytes written,
251
 * or on truncation: that would have been written.
252
 *
253
 * If \p str is %NULL the return value are the number of bytes that would have been written.
254
 */
255
size_t wget_snprintf(char *str, size_t size, const char *fmt, ...)
256
399k
{
257
399k
  va_list args;
258
259
399k
  va_start(args, fmt);
260
399k
  size_t len = wget_vsnprintf(str, size, fmt, args);
261
399k
  va_end(args);
262
263
399k
  return len;
264
399k
}
265
266
/**@}*/