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