/home/dko/projects/mobilec/trunk/src/mxml-2.2.2/mxml-string.c

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

Generated on Fri May 16 14:49:54 2008 for Mobile-C by  doxygen 1.5.4