|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 /* 00002 * "$Id: vsnprintf.c 7903 2010-11-28 21:06:39Z matt $" 00003 * 00004 * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK). 00005 * 00006 * Copyright 1998-2010 by Bill Spitzak and others. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Library General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Library General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Library General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 * USA. 00022 * 00023 * Please report all bugs and problems on the following page: 00024 * 00025 * http://www.fltk.org/str.php 00026 */ 00027 00028 #include <stdio.h> 00029 #include "flstring.h" 00030 00031 #ifdef HAVE_SYS_STDTYPES_H 00032 # include <sys/stdtypes.h> 00033 #endif /* HAVE_SYS_STDTYPES_H */ 00034 00035 #ifdef __cplusplus 00036 extern "C" { 00037 #endif 00038 00039 int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) { 00040 char *bufptr, /* Pointer to position in buffer */ 00041 *bufend, /* Pointer to end of buffer */ 00042 sign, /* Sign of format width */ 00043 size, /* Size character (h, l, L) */ 00044 type; /* Format type character */ 00045 int width, /* Width of field */ 00046 prec; /* Number of characters of precision */ 00047 char tformat[100], /* Temporary format string for sprintf() */ 00048 *tptr, /* Pointer into temporary format */ 00049 temp[1024]; /* Buffer for formatted numbers */ 00050 char *s; /* Pointer to string */ 00051 int slen; /* Length of string */ 00052 int bytes; /* Total number of bytes needed */ 00053 00054 00055 /* 00056 * Loop through the format string, formatting as needed... 00057 */ 00058 00059 bufptr = buffer; 00060 bufend = buffer + bufsize - 1; 00061 bytes = 0; 00062 00063 while (*format) { 00064 if (*format == '%') { 00065 tptr = tformat; 00066 *tptr++ = *format++; 00067 00068 if (*format == '%') { 00069 if (bufptr && bufptr < bufend) *bufptr++ = *format; 00070 bytes ++; 00071 format ++; 00072 continue; 00073 } else if (strchr(" -+#\'", *format)) { 00074 *tptr++ = *format; 00075 sign = *format++; 00076 } else sign = 0; 00077 00078 if (*format == '*') { 00079 /* Get width from argument... */ 00080 format ++; 00081 width = va_arg(ap, int); 00082 snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width); 00083 tptr += strlen(tptr); 00084 } else { 00085 width = 0; 00086 while (isdigit(*format & 255)) { 00087 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; 00088 width = width * 10 + *format++ - '0'; 00089 } 00090 } 00091 00092 if (*format == '.') { 00093 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; 00094 format ++; 00095 00096 if (*format == '*') { 00097 /* Get precision from argument... */ 00098 format ++; 00099 prec = va_arg(ap, int); 00100 snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec); 00101 tptr += strlen(tptr); 00102 } else { 00103 prec = 0; 00104 while (isdigit(*format & 255)) { 00105 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; 00106 prec = prec * 10 + *format++ - '0'; 00107 } 00108 } 00109 } else prec = -1; 00110 00111 size = '\0'; 00112 00113 if (*format == 'l' && format[1] == 'l') { 00114 size = 'L'; 00115 if (tptr < (tformat + sizeof(tformat) - 2)) { 00116 *tptr++ = 'l'; 00117 *tptr++ = 'l'; 00118 } 00119 format += 2; 00120 } else if (*format == 'h' || *format == 'l' || *format == 'L') { 00121 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; 00122 size = *format++; 00123 } 00124 00125 if (!*format) break; 00126 00127 if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; 00128 type = *format++; 00129 *tptr = '\0'; 00130 00131 switch (type) { 00132 case 'E' : /* Floating point formats */ 00133 case 'G' : 00134 case 'e' : 00135 case 'f' : 00136 case 'g' : 00137 if ((width + 2) > sizeof(temp)) break; 00138 00139 sprintf(temp, tformat, va_arg(ap, double)); 00140 00141 bytes += strlen(temp); 00142 00143 if (bufptr) { 00144 if ((bufptr + strlen(temp)) > bufend) { 00145 strncpy(bufptr, temp, (size_t)(bufend - bufptr)); 00146 bufptr = bufend; 00147 } else { 00148 strcpy(bufptr, temp); 00149 bufptr += strlen(temp); 00150 } 00151 } 00152 break; 00153 00154 case 'B' : /* Integer formats */ 00155 case 'X' : 00156 case 'b' : 00157 case 'd' : 00158 case 'i' : 00159 case 'o' : 00160 case 'u' : 00161 case 'x' : 00162 if ((width + 2) > sizeof(temp)) break; 00163 00164 #ifdef HAVE_LONG_LONG 00165 if (size == 'L') 00166 sprintf(temp, tformat, va_arg(ap, long long)); 00167 else 00168 #endif /* HAVE_LONG_LONG */ 00169 if (size == 'l') 00170 sprintf(temp, tformat, va_arg(ap, long)); 00171 else 00172 sprintf(temp, tformat, va_arg(ap, int)); 00173 00174 bytes += strlen(temp); 00175 00176 if (bufptr) { 00177 if ((bufptr + strlen(temp)) > bufend) { 00178 strncpy(bufptr, temp, (size_t)(bufend - bufptr)); 00179 bufptr = bufend; 00180 } else { 00181 strcpy(bufptr, temp); 00182 bufptr += strlen(temp); 00183 } 00184 } 00185 break; 00186 00187 case 'p' : /* Pointer value */ 00188 if ((width + 2) > sizeof(temp)) break; 00189 00190 sprintf(temp, tformat, va_arg(ap, void *)); 00191 00192 bytes += strlen(temp); 00193 00194 if (bufptr) { 00195 if ((bufptr + strlen(temp)) > bufend) { 00196 strncpy(bufptr, temp, (size_t)(bufend - bufptr)); 00197 bufptr = bufend; 00198 } else { 00199 strcpy(bufptr, temp); 00200 bufptr += strlen(temp); 00201 } 00202 } 00203 break; 00204 00205 case 'c' : /* Character or character array */ 00206 bytes += width; 00207 00208 if (bufptr) { 00209 if (width <= 1) *bufptr++ = va_arg(ap, int); 00210 else { 00211 if ((bufptr + width) > bufend) width = bufend - bufptr; 00212 00213 memcpy(bufptr, va_arg(ap, char *), (size_t)width); 00214 bufptr += width; 00215 } 00216 } 00217 break; 00218 00219 case 's' : /* String */ 00220 if ((s = va_arg(ap, char *)) == NULL) s = "(null)"; 00221 00222 slen = strlen(s); 00223 if (slen > width && prec != width) width = slen; 00224 00225 bytes += width; 00226 00227 if (bufptr) { 00228 if ((bufptr + width) > bufend) width = bufend - bufptr; 00229 00230 if (slen > width) slen = width; 00231 00232 if (sign == '-') { 00233 strncpy(bufptr, s, (size_t)slen); 00234 memset(bufptr + slen, ' ', (size_t)(width - slen)); 00235 } else { 00236 memset(bufptr, ' ', (size_t)(width - slen)); 00237 strncpy(bufptr + width - slen, s, (size_t)slen); 00238 } 00239 00240 bufptr += width; 00241 } 00242 break; 00243 00244 case 'n' : /* Output number of chars so far */ 00245 *(va_arg(ap, int *)) = bytes; 00246 break; 00247 } 00248 } else { 00249 bytes ++; 00250 00251 if (bufptr && bufptr < bufend) *bufptr++ = *format; 00252 format ++; 00253 } 00254 } 00255 00256 /* 00257 * Nul-terminate the string and return the number of characters needed. 00258 */ 00259 00260 if (bufptr) *bufptr = '\0'; 00261 00262 return (bytes); 00263 } 00264 00265 int fl_snprintf(char* str, size_t size, const char* fmt, ...) { 00266 int ret; 00267 va_list ap; 00268 va_start(ap, fmt); 00269 ret = vsnprintf(str, size, fmt, ap); 00270 va_end(ap); 00271 return ret; 00272 } 00273 00274 #ifdef __cplusplus 00275 } 00276 #endif 00277 00278 /* 00279 * End of "$Id: vsnprintf.c 7903 2010-11-28 21:06:39Z matt $". 00280 */ 00281