00001 /* SVN FILE INFO 00002 * $Revision: 174 $ : Last Committed Revision 00003 * $Date: 2008年06月24日 10:50:29 -0700 (2008年6月24日) $ : Last Committed Date */ 00004 /* 00005 * "$Id: mxml-string.c,v 1.1 2007年05月23日 20:43:28 david_ko Exp $" 00006 * 00007 * String functions for Mini-XML, a small XML-like file parsing library. 00008 * 00009 * Copyright 2003-2005 by Michael Sweet. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Library General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 2, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * Contents: 00022 * 00023 * mxml_strdup() - Duplicate a string. 00024 * mxml_strdupf() - Format and duplicate a string. 00025 * mxml_vsnprintf() - Format a string into a fixed size buffer. 00026 */ 00027 00028 /* 00029 * Include necessary headers... 00030 */ 00031 00032 #include "config.h" 00033 00034 00035 /* 00036 * 'mxml_strdup()' - Duplicate a string. 00037 */ 00038 00039 #ifndef HAVE_STRDUP 00040 char * /* O - New string pointer */ 00041 mxml_strdup(const char *s) /* I - String to duplicate */ 00042 { 00043 char *t; /* New string pointer */ 00044 00045 00046 if (s == NULL) 00047 return (NULL); 00048 00049 if ((t = malloc(strlen(s) + 1)) == NULL) 00050 return (NULL); 00051 00052 return (strcpy(t, s)); 00053 } 00054 #endif /* !HAVE_STRDUP */ 00055 00056 00057 /* 00058 * 'mxml_strdupf()' - Format and duplicate a string. 00059 */ 00060 00061 char * /* O - New string pointer */ 00062 mxml_strdupf(const char *format, /* I - Printf-style format string */ 00063 va_list ap) /* I - Pointer to additional arguments */ 00064 { 00065 int bytes; /* Number of bytes required */ 00066 char *buffer, /* String buffer */ 00067 temp[256]; /* Small buffer for first vsnprintf */ 00068 00069 00070 /* 00071 * First format with a tiny buffer; this will tell us how many bytes are 00072 * needed... 00073 */ 00074 00075 bytes = mxml_vsnprintf(temp, sizeof(temp), format, ap); 00076 00077 if (bytes < sizeof(temp)) 00078 { 00079 /* 00080 * Hey, the formatted string fits in the tiny buffer, so just dup that... 00081 */ 00082 00083 return (strdup(temp)); 00084 } 00085 00086 /* 00087 * Allocate memory for the whole thing and reformat to the new, larger 00088 * buffer... 00089 */ 00090 00091 if ((buffer = calloc(1, bytes + 1)) != NULL) 00092 mxml_vsnprintf(buffer, bytes + 1, format, ap); 00093 00094 /* 00095 * Return the new string... 00096 */ 00097 00098 return (buffer); 00099 } 00100 00101 00102 /* 00103 * 'mxml_vsnprintf()' - Format a string into a fixed size buffer. 00104 */ 00105 00106 int /* O - Number of bytes formatted */ 00107 mxml_vsnprintf(char *buffer, /* O - Output buffer */ 00108 size_t bufsize, /* O - Size of output buffer */ 00109 const char *format, /* I - Printf-style format string */ 00110 va_list ap) /* I - Pointer to additional arguments */ 00111 { 00112 char *bufptr, /* Pointer to position in buffer */ 00113 *bufend, /* Pointer to end of buffer */ 00114 sign, /* Sign of format width */ 00115 size, /* Size character (h, l, L) */ 00116 type; /* Format type character */ 00117 const char *bufformat; /* Start of format */ 00118 int width, /* Width of field */ 00119 prec; /* Number of characters of precision */ 00120 char tformat[100], /* Temporary format string for sprintf() */ 00121 temp[1024]; /* Buffer for formatted numbers */ 00122 char *s; /* Pointer to string */ 00123 int slen; /* Length of string */ 00124 int bytes; /* Total number of bytes needed */ 00125 00126 00127 /* 00128 * Loop through the format string, formatting as needed... 00129 */ 00130 00131 bufptr = buffer; 00132 bufend = buffer + bufsize - 1; 00133 bytes = 0; 00134 00135 while (*format) 00136 { 00137 if (*format == '%') 00138 { 00139 bufformat = format; 00140 format ++; 00141 00142 if (*format == '%') 00143 { 00144 *bufptr++ = *format++; 00145 continue; 00146 } 00147 else if (strchr(" -+#\'", *format)) 00148 sign = *format++; 00149 else 00150 sign = 0; 00151 00152 width = 0; 00153 while (isdigit(*format)) 00154 width = width * 10 + *format++ - '0'; 00155 00156 if (*format == '.') 00157 { 00158 format ++; 00159 prec = 0; 00160 00161 while (isdigit(*format)) 00162 prec = prec * 10 + *format++ - '0'; 00163 } 00164 else 00165 prec = -1; 00166 00167 if (*format == 'l' && format[1] == 'l') 00168 { 00169 size = 'L'; 00170 format += 2; 00171 } 00172 else if (*format == 'h' || *format == 'l' || *format == 'L') 00173 size = *format++; 00174 00175 if (!*format) 00176 break; 00177 00178 type = *format++; 00179 00180 switch (type) 00181 { 00182 case 'E' : /* Floating point formats */ 00183 case 'G' : 00184 case 'e' : 00185 case 'f' : 00186 case 'g' : 00187 if ((format - bufformat + 1) > sizeof(tformat) || 00188 (width + 2) > sizeof(temp)) 00189 break; 00190 00191 strncpy(tformat, bufformat, format - bufformat); 00192 tformat[format - bufformat] = '0円'; 00193 00194 sprintf(temp, tformat, va_arg(ap, double)); 00195 00196 bytes += strlen(temp); 00197 00198 if (bufptr) 00199 { 00200 if ((bufptr + strlen(temp)) > bufend) 00201 { 00202 strncpy(bufptr, temp, bufend - bufptr); 00203 bufptr = bufend; 00204 break; 00205 } 00206 else 00207 { 00208 strcpy(bufptr, temp); 00209 bufptr += strlen(temp); 00210 } 00211 } 00212 break; 00213 00214 case 'B' : /* Integer formats */ 00215 case 'X' : 00216 case 'b' : 00217 case 'd' : 00218 case 'i' : 00219 case 'o' : 00220 case 'u' : 00221 case 'x' : 00222 if ((format - bufformat + 1) > sizeof(tformat) || 00223 (width + 2) > sizeof(temp)) 00224 break; 00225 00226 strncpy(tformat, bufformat, format - bufformat); 00227 tformat[format - bufformat] = '0円'; 00228 00229 sprintf(temp, tformat, va_arg(ap, int)); 00230 00231 bytes += strlen(temp); 00232 00233 if (bufptr) 00234 { 00235 if ((bufptr + strlen(temp)) > bufend) 00236 { 00237 strncpy(bufptr, temp, bufend - bufptr); 00238 bufptr = bufend; 00239 break; 00240 } 00241 else 00242 { 00243 strcpy(bufptr, temp); 00244 bufptr += strlen(temp); 00245 } 00246 } 00247 break; 00248 00249 case 'p' : /* Pointer value */ 00250 if ((format - bufformat + 1) > sizeof(tformat) || 00251 (width + 2) > sizeof(temp)) 00252 break; 00253 00254 strncpy(tformat, bufformat, format - bufformat); 00255 tformat[format - bufformat] = '0円'; 00256 00257 sprintf(temp, tformat, va_arg(ap, void *)); 00258 00259 bytes += strlen(temp); 00260 00261 if (bufptr) 00262 { 00263 if ((bufptr + strlen(temp)) > bufend) 00264 { 00265 strncpy(bufptr, temp, bufend - bufptr); 00266 bufptr = bufend; 00267 break; 00268 } 00269 else 00270 { 00271 strcpy(bufptr, temp); 00272 bufptr += strlen(temp); 00273 } 00274 } 00275 break; 00276 00277 case 'c' : /* Character or character array */ 00278 bytes += width; 00279 00280 if (bufptr) 00281 { 00282 if (width <= 1) 00283 *bufptr++ = va_arg(ap, int); 00284 else 00285 { 00286 if ((bufptr + width) > bufend) 00287 width = bufend - bufptr; 00288 00289 memcpy(bufptr, va_arg(ap, char *), width); 00290 bufptr += width; 00291 } 00292 } 00293 break; 00294 00295 case 's' : /* String */ 00296 if ((s = va_arg(ap, char *)) == NULL) 00297 s = "(null)"; 00298 00299 slen = strlen(s); 00300 if (slen > width && prec != width) 00301 width = slen; 00302 00303 bytes += width; 00304 00305 if (bufptr) 00306 { 00307 if ((bufptr + width) > bufend) 00308 width = bufend - bufptr; 00309 00310 if (slen > width) 00311 slen = width; 00312 00313 if (sign == '-') 00314 { 00315 strncpy(bufptr, s, slen); 00316 memset(bufptr + slen, ' ', width - slen); 00317 } 00318 else 00319 { 00320 memset(bufptr, ' ', width - slen); 00321 strncpy(bufptr + width - slen, s, slen); 00322 } 00323 00324 bufptr += width; 00325 } 00326 break; 00327 00328 case 'n' : /* Output number of chars so far */ 00329 if ((format - bufformat + 1) > sizeof(tformat) || 00330 (width + 2) > sizeof(temp)) 00331 break; 00332 00333 strncpy(tformat, bufformat, format - bufformat); 00334 tformat[format - bufformat] = '0円'; 00335 00336 sprintf(temp, tformat, va_arg(ap, int)); 00337 00338 bytes += strlen(temp); 00339 00340 if (bufptr) 00341 { 00342 if ((bufptr + strlen(temp)) > bufend) 00343 { 00344 strncpy(bufptr, temp, bufend - bufptr); 00345 bufptr = bufend; 00346 break; 00347 } 00348 else 00349 { 00350 strcpy(bufptr, temp); 00351 bufptr += strlen(temp); 00352 } 00353 } 00354 break; 00355 } 00356 } 00357 else 00358 { 00359 bytes ++; 00360 00361 if (bufptr && bufptr < bufend) 00362 *bufptr++ = *format++; 00363 } 00364 } 00365 00366 /* 00367 * Nul-terminate the string and return the number of characters needed. 00368 */ 00369 00370 *bufptr = '0円'; 00371 00372 return (bytes); 00373 } 00374 00375 00376 00377 /* 00378 * End of "$Id: mxml-string.c,v 1.1 2007年05月23日 20:43:28 david_ko Exp $". 00379 */