1/* 2 * "$Id: snprintf.c 11093 2013-07-03 20:48:42Z msweet $" 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 35int /* 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 344int /* 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: snprintf.c 11093 2013-07-03 20:48:42Z msweet $". 365 */ 366 367