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