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