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