2 * "$Id: vsnprintf.c 7903 2010-11-28 21:06:39Z matt $"
4 * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK).
6 * Copyright 1998-2010 by Bill Spitzak and others.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 * Please report all bugs and problems on the following page:
25 * http://www.fltk.org/str.php
33 #ifdef HAVE_SYS_STDTYPES_H
34 # include <sys/stdtypes.h>
35 #endif /* HAVE_SYS_STDTYPES_H */
41 int fl_vsnprintf(char* buffer
, size_t bufsize
, const char* format
, va_list ap
) {
42 char *bufptr
, /* Pointer to position in buffer */
43 *bufend
, /* Pointer to end of buffer */
44 sign
, /* Sign of format width */
45 size
, /* Size character (h, l, L) */
46 type
; /* Format type character */
47 int width
, /* Width of field */
48 prec
; /* Number of characters of precision */
49 char tformat
[100], /* Temporary format string for sprintf() */
50 *tptr
, /* Pointer into temporary format */
51 temp
[1024]; /* Buffer for formatted numbers */
52 char *s
; /* Pointer to string */
53 int slen
; /* Length of string */
54 int bytes
; /* Total number of bytes needed */
58 * Loop through the format string, formatting as needed...
62 bufend
= buffer
+ bufsize
- 1;
71 if (bufptr
&& bufptr
< bufend
) *bufptr
++ = *format
;
75 } else if (strchr(" -+#\'", *format
)) {
81 /* Get width from argument... */
83 width
= va_arg(ap
, int);
84 snprintf(tptr
, sizeof(tformat
) - (tptr
- tformat
), "%d", width
);
88 while (isdigit(*format
& 255)) {
89 if (tptr
< (tformat
+ sizeof(tformat
) - 1)) *tptr
++ = *format
;
90 width
= width
* 10 + *format
++ - '0';
95 if (tptr
< (tformat
+ sizeof(tformat
) - 1)) *tptr
++ = *format
;
99 /* Get precision from argument... */
101 prec
= va_arg(ap
, int);
102 snprintf(tptr
, sizeof(tformat
) - (tptr
- tformat
), "%d", prec
);
103 tptr
+= strlen(tptr
);
106 while (isdigit(*format
& 255)) {
107 if (tptr
< (tformat
+ sizeof(tformat
) - 1)) *tptr
++ = *format
;
108 prec
= prec
* 10 + *format
++ - '0';
115 if (*format
== 'l' && format
[1] == 'l') {
117 if (tptr
< (tformat
+ sizeof(tformat
) - 2)) {
122 } else if (*format
== 'h' || *format
== 'l' || *format
== 'L') {
123 if (tptr
< (tformat
+ sizeof(tformat
) - 1)) *tptr
++ = *format
;
129 if (tptr
< (tformat
+ sizeof(tformat
) - 1)) *tptr
++ = *format
;
134 case 'E' : /* Floating point formats */
139 if ((width
+ 2) > sizeof(temp
)) break;
141 sprintf(temp
, tformat
, va_arg(ap
, double));
143 bytes
+= strlen(temp
);
146 if ((bufptr
+ strlen(temp
)) > bufend
) {
147 strncpy(bufptr
, temp
, (size_t)(bufend
- bufptr
));
150 strcpy(bufptr
, temp
);
151 bufptr
+= strlen(temp
);
156 case 'B' : /* Integer formats */
164 if ((width
+ 2) > sizeof(temp
)) break;
166 #ifdef HAVE_LONG_LONG
168 sprintf(temp
, tformat
, va_arg(ap
, long long));
170 #endif /* HAVE_LONG_LONG */
172 sprintf(temp
, tformat
, va_arg(ap
, long));
174 sprintf(temp
, tformat
, va_arg(ap
, int));
176 bytes
+= strlen(temp
);
179 if ((bufptr
+ strlen(temp
)) > bufend
) {
180 strncpy(bufptr
, temp
, (size_t)(bufend
- bufptr
));
183 strcpy(bufptr
, temp
);
184 bufptr
+= strlen(temp
);
189 case 'p' : /* Pointer value */
190 if ((width
+ 2) > sizeof(temp
)) break;
192 sprintf(temp
, tformat
, va_arg(ap
, void *));
194 bytes
+= strlen(temp
);
197 if ((bufptr
+ strlen(temp
)) > bufend
) {
198 strncpy(bufptr
, temp
, (size_t)(bufend
- bufptr
));
201 strcpy(bufptr
, temp
);
202 bufptr
+= strlen(temp
);
207 case 'c' : /* Character or character array */
211 if (width
<= 1) *bufptr
++ = va_arg(ap
, int);
213 if ((bufptr
+ width
) > bufend
) width
= bufend
- bufptr
;
215 memcpy(bufptr
, va_arg(ap
, char *), (size_t)width
);
221 case 's' : /* String */
222 if ((s
= va_arg(ap
, char *)) == NULL
) s
= "(null)";
225 if (slen
> width
&& prec
!= width
) width
= slen
;
230 if ((bufptr
+ width
) > bufend
) width
= bufend
- bufptr
;
232 if (slen
> width
) slen
= width
;
235 strncpy(bufptr
, s
, (size_t)slen
);
236 memset(bufptr
+ slen
, ' ', (size_t)(width
- slen
));
238 memset(bufptr
, ' ', (size_t)(width
- slen
));
239 strncpy(bufptr
+ width
- slen
, s
, (size_t)slen
);
246 case 'n' : /* Output number of chars so far */
247 *(va_arg(ap
, int *)) = bytes
;
253 if (bufptr
&& bufptr
< bufend
) *bufptr
++ = *format
;
259 * Nul-terminate the string and return the number of characters needed.
262 if (bufptr
) *bufptr
= '\0';
267 int fl_snprintf(char* str
, size_t size
, const char* fmt
, ...) {
271 ret
= vsnprintf(str
, size
, fmt
, ap
);
281 * End of "$Id: vsnprintf.c 7903 2010-11-28 21:06:39Z matt $".