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