]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
f2d18633 | 2 | * "$Id$" |
ef416fc2 | 3 | * |
71e16022 | 4 | * snprintf functions for CUPS. |
ef416fc2 | 5 | * |
db8b865d | 6 | * Copyright 2007-2013 by Apple Inc. |
b86bc4cf | 7 | * Copyright 1997-2007 by Easy Software Products. |
ef416fc2 | 8 | * |
9 | * These coded instructions, statements, and computer programs are the | |
bc44d920 | 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/". | |
ef416fc2 | 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 | ||
71e16022 | 27 | #include "string-private.h" |
ef416fc2 | 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 */ | |
5a9febac | 51 | size_t templen; /* Length of "temp" */ |
ef416fc2 | 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 | { | |
f301802f | 89 | /* |
90 | * Get width from argument... | |
91 | */ | |
92 | ||
ef416fc2 | 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 | { | |
f301802f | 121 | /* |
122 | * Get precision from argument... | |
123 | */ | |
124 | ||
ef416fc2 | 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)); | |
5a9febac | 187 | templen = strlen(temp): |
ef416fc2 | 188 | |
5a9febac | 189 | bytes += (int)templen; |
ef416fc2 | 190 | |
191 | if (bufptr) | |
192 | { | |
5a9febac | 193 | if ((bufptr + templen) > bufend) |
ef416fc2 | 194 | { |
5a9febac | 195 | strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); |
ef416fc2 | 196 | bufptr = bufend; |
197 | } | |
198 | else | |
199 | { | |
5a9febac MS |
200 | memcpy(bufptr, temp, templen + 1); |
201 | bufptr += templen; | |
ef416fc2 | 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)); | |
5a9febac | 218 | templen = strlen(temp): |
ef416fc2 | 219 | |
5a9febac | 220 | bytes += (int)templen; |
ef416fc2 | 221 | |
222 | if (bufptr) | |
223 | { | |
5a9febac | 224 | if ((bufptr + templen) > bufend) |
ef416fc2 | 225 | { |
5a9febac | 226 | strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); |
ef416fc2 | 227 | bufptr = bufend; |
228 | } | |
229 | else | |
230 | { | |
5a9febac MS |
231 | memcpy(bufptr, temp, templen + 1); |
232 | bufptr += templen; | |
ef416fc2 | 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 *)); | |
5a9febac | 242 | templen = strlen(temp): |
ef416fc2 | 243 | |
5a9febac | 244 | bytes += (int)templen; |
ef416fc2 | 245 | |
246 | if (bufptr) | |
247 | { | |
5a9febac | 248 | if ((bufptr + templen) > bufend) |
ef416fc2 | 249 | { |
5a9febac | 250 | strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); |
ef416fc2 | 251 | bufptr = bufend; |
252 | } | |
253 | else | |
254 | { | |
5a9febac MS |
255 | memcpy(bufptr, temp, templen + 1); |
256 | bufptr += templen; | |
ef416fc2 | 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) | |
b86bc4cf | 271 | width = (int)(bufend - bufptr); |
ef416fc2 | 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 | ||
b86bc4cf | 283 | slen = (int)strlen(s); |
ef416fc2 | 284 | if (slen > width && prec != width) |
285 | width = slen; | |
286 | ||
287 | bytes += width; | |
288 | ||
289 | if (bufptr) | |
290 | { | |
291 | if ((bufptr + width) > bufend) | |
b86bc4cf | 292 | width = (int)(bufend - bufptr); |
ef416fc2 | 293 | |
294 | if (slen > width) | |
295 | slen = width; | |
296 | ||
297 | if (sign == '-') | |
298 | { | |
db8b865d | 299 | memcpy(bufptr, s, (size_t)slen); |
ef416fc2 | 300 | memset(bufptr + slen, ' ', (size_t)(width - slen)); |
301 | } | |
302 | else | |
303 | { | |
304 | memset(bufptr, ' ', (size_t)(width - slen)); | |
db8b865d | 305 | memcpy(bufptr + width - slen, s, (size_t)slen); |
ef416fc2 | 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 | /* | |
f2d18633 | 364 | * End of "$Id$". |
ef416fc2 | 365 | */ |
366 |