]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/snprintf.c
Update ipp documentation to reflect the behavior of configuring WiFi on IPP USB printers.
[thirdparty/cups.git] / cups / snprintf.c
CommitLineData
ef416fc2 1/*
503b54c9 2 * snprintf functions for CUPS.
ef416fc2 3 *
51998f16 4 * Copyright © 2021 by OpenPrinting
b2ad86e0
MS
5 * Copyright © 2007-2019 by Apple Inc.
6 * Copyright © 1997-2007 by Easy Software Products.
ef416fc2 7 *
b2ad86e0
MS
8 * Licensed under Apache License v2.0. See the file "LICENSE" for more
9 * information.
ef416fc2 10 */
11
12/*
13 * Include necessary headers...
14 */
15
71e16022 16#include "string-private.h"
ef416fc2 17
18
19#ifndef HAVE_VSNPRINTF
20/*
21 * '_cups_vsnprintf()' - Format a string into a fixed size buffer.
22 */
23
24int /* O - Number of bytes formatted */
25_cups_vsnprintf(char *buffer, /* O - Output buffer */
26 size_t bufsize, /* O - Size of output buffer */
27 const char *format, /* I - printf-style format string */
28 va_list ap) /* I - Pointer to additional arguments */
29{
30 char *bufptr, /* Pointer to position in buffer */
31 *bufend, /* Pointer to end of buffer */
32 sign, /* Sign of format width */
33 size, /* Size character (h, l, L) */
34 type; /* Format type character */
35 int width, /* Width of field */
36 prec; /* Number of characters of precision */
37 char tformat[100], /* Temporary format string for sprintf() */
38 *tptr, /* Pointer into temporary format */
39 temp[1024]; /* Buffer for formatted numbers */
5a9febac 40 size_t templen; /* Length of "temp" */
ef416fc2 41 char *s; /* Pointer to string */
42 int slen; /* Length of string */
43 int bytes; /* Total number of bytes needed */
44
45
46 /*
47 * Loop through the format string, formatting as needed...
48 */
49
50 bufptr = buffer;
51 bufend = buffer + bufsize - 1;
52 bytes = 0;
53
54 while (*format)
55 {
56 if (*format == '%')
57 {
58 tptr = tformat;
59 *tptr++ = *format++;
60
61 if (*format == '%')
62 {
63 if (bufptr && bufptr < bufend) *bufptr++ = *format;
64 bytes ++;
65 format ++;
66 continue;
67 }
68 else if (strchr(" -+#\'", *format))
69 {
70 *tptr++ = *format;
71 sign = *format++;
72 }
73 else
74 sign = 0;
75
76 if (*format == '*')
77 {
f301802f 78 /*
79 * Get width from argument...
80 */
81
ef416fc2 82 format ++;
83 width = va_arg(ap, int);
84
064e50fb
MS
85 /* Note: Can't use snprintf here since we are implementing this function... */
86 sprintf(tptr, "%d", width);
ef416fc2 87 tptr += strlen(tptr);
88 }
89 else
90 {
91 width = 0;
92
93 while (isdigit(*format & 255))
94 {
95 if (tptr < (tformat + sizeof(tformat) - 1))
96 *tptr++ = *format;
97
98 width = width * 10 + *format++ - '0';
99 }
100 }
101
102 if (*format == '.')
103 {
104 if (tptr < (tformat + sizeof(tformat) - 1))
105 *tptr++ = *format;
106
107 format ++;
108
109 if (*format == '*')
110 {
f301802f 111 /*
112 * Get precision from argument...
113 */
114
ef416fc2 115 format ++;
116 prec = va_arg(ap, int);
117
064e50fb
MS
118 /* Note: Can't use snprintf here since we are implementing this function... */
119 sprintf(tptr, "%d", prec);
ef416fc2 120 tptr += strlen(tptr);
121 }
122 else
123 {
124 prec = 0;
125
126 while (isdigit(*format & 255))
127 {
128 if (tptr < (tformat + sizeof(tformat) - 1))
129 *tptr++ = *format;
130
131 prec = prec * 10 + *format++ - '0';
132 }
133 }
134 }
135 else
136 prec = -1;
137
138 if (*format == 'l' && format[1] == 'l')
139 {
140 size = 'L';
141
142 if (tptr < (tformat + sizeof(tformat) - 2))
143 {
144 *tptr++ = 'l';
145 *tptr++ = 'l';
146 }
147
148 format += 2;
149 }
150 else if (*format == 'h' || *format == 'l' || *format == 'L')
151 {
152 if (tptr < (tformat + sizeof(tformat) - 1))
153 *tptr++ = *format;
154
155 size = *format++;
156 }
157
158 if (!*format)
159 break;
160
161 if (tptr < (tformat + sizeof(tformat) - 1))
162 *tptr++ = *format;
163
164 type = *format++;
165 *tptr = '\0';
166
167 switch (type)
168 {
169 case 'E' : /* Floating point formats */
170 case 'G' :
171 case 'e' :
172 case 'f' :
173 case 'g' :
174 if ((width + 2) > sizeof(temp))
175 break;
176
064e50fb 177 /* Note: Can't use snprintf here since we are implementing this function... */
ef416fc2 178 sprintf(temp, tformat, va_arg(ap, double));
b2ad86e0 179 templen = strlen(temp);
ef416fc2 180
5a9febac 181 bytes += (int)templen;
ef416fc2 182
183 if (bufptr)
184 {
5a9febac 185 if ((bufptr + templen) > bufend)
ef416fc2 186 {
5a9febac 187 strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
ef416fc2 188 bufptr = bufend;
189 }
190 else
191 {
5a9febac
MS
192 memcpy(bufptr, temp, templen + 1);
193 bufptr += templen;
ef416fc2 194 }
195 }
196 break;
197
198 case 'B' : /* Integer formats */
199 case 'X' :
200 case 'b' :
201 case 'd' :
202 case 'i' :
203 case 'o' :
204 case 'u' :
205 case 'x' :
206 if ((width + 2) > sizeof(temp))
207 break;
208
064e50fb 209 /* Note: Can't use snprintf here since we are implementing this function... */
ef416fc2 210 sprintf(temp, tformat, va_arg(ap, int));
b2ad86e0 211 templen = strlen(temp);
ef416fc2 212
5a9febac 213 bytes += (int)templen;
ef416fc2 214
215 if (bufptr)
216 {
5a9febac 217 if ((bufptr + templen) > bufend)
ef416fc2 218 {
5a9febac 219 strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
ef416fc2 220 bufptr = bufend;
221 }
222 else
223 {
5a9febac
MS
224 memcpy(bufptr, temp, templen + 1);
225 bufptr += templen;
ef416fc2 226 }
227 }
228 break;
229
230 case 'p' : /* Pointer value */
231 if ((width + 2) > sizeof(temp))
232 break;
233
064e50fb 234 /* Note: Can't use snprintf here since we are implementing this function... */
ef416fc2 235 sprintf(temp, tformat, va_arg(ap, void *));
b2ad86e0 236 templen = strlen(temp);
ef416fc2 237
5a9febac 238 bytes += (int)templen;
ef416fc2 239
240 if (bufptr)
241 {
5a9febac 242 if ((bufptr + templen) > bufend)
ef416fc2 243 {
5a9febac 244 strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
ef416fc2 245 bufptr = bufend;
246 }
247 else
248 {
5a9febac
MS
249 memcpy(bufptr, temp, templen + 1);
250 bufptr += templen;
ef416fc2 251 }
252 }
253 break;
254
255 case 'c' : /* Character or character array */
256 bytes += width;
257
258 if (bufptr)
259 {
260 if (width <= 1)
261 *bufptr++ = va_arg(ap, int);
262 else
263 {
264 if ((bufptr + width) > bufend)
b86bc4cf 265 width = (int)(bufend - bufptr);
ef416fc2 266
267 memcpy(bufptr, va_arg(ap, char *), (size_t)width);
268 bufptr += width;
269 }
270 }
271 break;
272
273 case 's' : /* String */
274 if ((s = va_arg(ap, char *)) == NULL)
275 s = "(null)";
276
b86bc4cf 277 slen = (int)strlen(s);
ef416fc2 278 if (slen > width && prec != width)
279 width = slen;
280
281 bytes += width;
282
283 if (bufptr)
284 {
285 if ((bufptr + width) > bufend)
b86bc4cf 286 width = (int)(bufend - bufptr);
ef416fc2 287
288 if (slen > width)
289 slen = width;
290
291 if (sign == '-')
292 {
db8b865d 293 memcpy(bufptr, s, (size_t)slen);
ef416fc2 294 memset(bufptr + slen, ' ', (size_t)(width - slen));
295 }
296 else
297 {
298 memset(bufptr, ' ', (size_t)(width - slen));
db8b865d 299 memcpy(bufptr + width - slen, s, (size_t)slen);
ef416fc2 300 }
301
302 bufptr += width;
303 }
304 break;
305
306 case 'n' : /* Output number of chars so far */
307 *(va_arg(ap, int *)) = bytes;
308 break;
309 }
310 }
311 else
312 {
313 bytes ++;
314
315 if (bufptr && bufptr < bufend)
316 *bufptr++ = *format;
317
318 format ++;
319 }
320 }
321
322 /*
323 * Nul-terminate the string and return the number of characters needed.
324 */
325
092c373e
R
326 if (bufptr && bufptr < bufend)
327 *bufptr = '\0';
ef416fc2 328
329 return (bytes);
330}
331#endif /* !HAVE_VSNPRINT */
332
333
334#ifndef HAVE_SNPRINTF
335/*
336 * '_cups_snprintf()' - Format a string into a fixed size buffer.
337 */
338
339int /* O - Number of bytes formatted */
340_cups_snprintf(char *buffer, /* O - Output buffer */
341 size_t bufsize, /* O - Size of output buffer */
342 const char *format, /* I - printf-style format string */
343 ...) /* I - Additional arguments as needed */
344{
345 int bytes; /* Number of bytes formatted */
346 va_list ap; /* Pointer to additional arguments */
347
348
349 va_start(ap, format);
350 bytes = vsnprintf(buffer, bufsize, format, ap);
351 va_end(ap);
352
353 return (bytes);
354}
355#endif /* !HAVE_SNPRINTF */