iniparser/src/iniparser.c

説明を見る。
00001 
00002 /*-------------------------------------------------------------------------*/
00003 /**
00004    @file    iniparser.c
00005    @author  N. Devillard
00006    @date    Mar 2000
00007    @version $Revision: 2.14 $
00008    @brief   Parser for ini files.
00009 */
00010 /*--------------------------------------------------------------------------*/
00011 
00012 /*
00013     $Id: iniparser.c,v 2.14 2002/12/12 10:49:01 ndevilla Exp $
00014     $Author: ndevilla $
00015     $Date: 2002/12/12 10:49:01 $
00016     $Revision: 2.14 $
00017 */
00018 
00019 /*---------------------------------------------------------------------------
00020                                 Includes
00021  ---------------------------------------------------------------------------*/
00022 
00023 #include "iniparser.h"
00024 #include "strlib.h"
00025 
00026 #define ASCIILINESZ         1024
00027 #define INI_INVALID_KEY     ((char*)-1)
00028 
00029 /*---------------------------------------------------------------------------
00030                         Private to this module
00031  ---------------------------------------------------------------------------*/
00032 
00033 /* Private: add an entry to the dictionary */
00034 static void iniparser_add_entry(
00035     dictionary * d,
00036     char * sec,
00037     char * key,
00038     char * val)
00039 {
00040     char longkey[2*ASCIILINESZ+1];
00041 
00042     /* Make a key as section:keyword */
00043     if (key!=NULL) {
00044         sprintf(longkey, "%s:%s", sec, key);
00045     } else {
00046         strcpy(longkey, sec);
00047     }
00048 
00049     /* Add (key,val) to dictionary */
00050     dictionary_set(d, longkey, val);
00051     return ;
00052 }
00053 
00054 
00055 /*-------------------------------------------------------------------------*/
00056 /**
00057   @brief    Get number of sections in a dictionary
00058   @param    d   Dictionary to examine
00059   @return   int Number of sections found in dictionary
00060 
00061   This function returns the number of sections found in a dictionary.
00062   The test to recognize sections is done on the string stored in the
00063   dictionary: a section name is given as "section" whereas a key is
00064   stored as "section:key", thus the test looks for entries that do not
00065   contain a colon.
00066 
00067   This clearly fails in the case a section name contains a colon, but
00068   this should simply be avoided.
00069 
00070   This function returns -1 in case of error.
00071  */
00072 /*--------------------------------------------------------------------------*/
00073 
00074 int iniparser_getnsec(dictionary * d)
00075 {
00076     int i ;
00077     int nsec ;
00078 
00079     if (d==NULL) return -1 ;
00080     nsec=0 ;
00081     for (i=0 ; i<d->size ; i++) {
00082         if (d->key[i]==NULL)
00083             continue ;
00084         if (strchr(d->key[i], ':')==NULL) {
00085             nsec ++ ;
00086         }
00087     }
00088     return nsec ;
00089 }
00090 
00091 
00092 /*-------------------------------------------------------------------------*/
00093 /**
00094   @brief    Get name for section n in a dictionary.
00095   @param    d   Dictionary to examine
00096   @param    n   Section number (from 0 to nsec-1).
00097   @return   Pointer to char string
00098 
00099   This function locates the n-th section in a dictionary and returns
00100   its name as a pointer to a string statically allocated inside the
00101   dictionary. Do not free or modify the returned string!
00102 
00103   This function returns NULL in case of error.
00104  */
00105 /*--------------------------------------------------------------------------*/
00106 
00107 char * iniparser_getsecname(dictionary * d, int n)
00108 {
00109     int i ;
00110     int foundsec ;
00111 
00112     if (d==NULL || n<0) return NULL ;
00113     foundsec=0 ;
00114     for (i=0 ; i<d->size ; i++) {
00115         if (d->key[i]==NULL)
00116             continue ;
00117         if (strchr(d->key[i], ':')==NULL) {
00118             foundsec++ ;
00119             if (foundsec>n)
00120                 break ;
00121         }
00122     }
00123     if (foundsec<=n) {
00124         return NULL ;
00125     }
00126     return d->key[i] ;
00127 }
00128 
00129 
00130 /*-------------------------------------------------------------------------*/
00131 /**
00132   @brief    Dump a dictionary to an opened file pointer.
00133   @param    d   Dictionary to dump.
00134   @param    f   Opened file pointer to dump to.
00135   @return   void
00136 
00137   This function prints out the contents of a dictionary, one element by
00138   line, onto the provided file pointer. It is OK to specify @c stderr
00139   or @c stdout as output files. This function is meant for debugging
00140   purposes mostly.
00141  */
00142 /*--------------------------------------------------------------------------*/
00143 void iniparser_dump(dictionary * d, FILE * f)
00144 {
00145     int     i ;
00146 
00147     if (d==NULL || f==NULL) return ;
00148     for (i=0 ; i<d->size ; i++) {
00149         if (d->key[i]==NULL)
00150             continue ;
00151         if (d->val[i]!=NULL) {
00152             fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
00153         } else {
00154             fprintf(f, "[%s]=UNDEF\n", d->key[i]);
00155         }
00156     }
00157     return ;
00158 }
00159 
00160 /*-------------------------------------------------------------------------*/
00161 /**
00162   @brief    Save a dictionary to a loadable ini file
00163   @param    d   Dictionary to dump
00164   @param    f   Opened file pointer to dump to
00165   @return   void
00166 
00167   This function dumps a given dictionary into a loadable ini file.
00168   It is Ok to specify @c stderr or @c stdout as output files.
00169  */
00170 /*--------------------------------------------------------------------------*/
00171 
00172 void iniparser_dump_ini(dictionary * d, FILE * f)
00173 {
00174     int     i, j ;
00175     char    keym[ASCIILINESZ+1];
00176     int     nsec ;
00177     char *  secname ;
00178     int     seclen ;
00179 
00180     if (d==NULL || f==NULL) return ;
00181 
00182     nsec = iniparser_getnsec(d);
00183     if (nsec<1) {
00184         /* No section in file: dump all keys as they are */
00185         for (i=0 ; i<d->size ; i++) {
00186             if (d->key[i]==NULL)
00187                 continue ;
00188             fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
00189         }
00190         return ;
00191     }
00192     for (i=0 ; i<nsec ; i++) {
00193         secname = iniparser_getsecname(d, i) ;
00194         seclen  = (int)strlen(secname);
00195         fprintf(f, "\n[%s]\n", secname);
00196         sprintf(keym, "%s:", secname);
00197         for (j=0 ; j<d->size ; j++) {
00198             if (d->key[j]==NULL)
00199                 continue ;
00200             if (!strncmp(d->key[j], keym, seclen+1)) {
00201                 fprintf(f,
00202                         "%-30s = %s\n",
00203                         d->key[j]+seclen+1,
00204                         d->val[j] ? d->val[j] : "");
00205             }
00206         }
00207     }
00208     fprintf(f, "\n");
00209     return ;
00210 }
00211 
00212 
00213 
00214 
00215 /*-------------------------------------------------------------------------*/
00216 /**
00217   @brief        Get the string associated to a key, return NULL if not found
00218   @param    d   Dictionary to search
00219   @param    key Key string to look for
00220   @return   pointer to statically allocated character string, or NULL.
00221 
00222   This function queries a dictionary for a key. A key as read from an
00223   ini file is given as "section:key". If the key cannot be found,
00224   NULL is returned.
00225   The returned char pointer is pointing to a string allocated in
00226   the dictionary, do not free or modify it.
00227 
00228   This function is only provided for backwards compatibility with 
00229   previous versions of iniparser. It is recommended to use
00230   iniparser_getstring() instead.
00231  */
00232 /*--------------------------------------------------------------------------*/
00233 char * iniparser_getstr(dictionary * d, const char * key)
00234 {
00235     return iniparser_getstring(d, key, NULL);
00236 }
00237 
00238 
00239 /*-------------------------------------------------------------------------*/
00240 /**
00241   @brief    Get the string associated to a key
00242   @param    d       Dictionary to search
00243   @param    key     Key string to look for
00244   @param    def     Default value to return if key not found.
00245   @return   pointer to statically allocated character string
00246 
00247   This function queries a dictionary for a key. A key as read from an
00248   ini file is given as "section:key". If the key cannot be found,
00249   the pointer passed as 'def' is returned.
00250   The returned char pointer is pointing to a string allocated in
00251   the dictionary, do not free or modify it.
00252  */
00253 /*--------------------------------------------------------------------------*/
00254 char * iniparser_getstring(dictionary * d, const char * key, char * def)
00255 {
00256     char * lc_key ;
00257     char * sval ;
00258 
00259     if (d==NULL || key==NULL)
00260         return def ;
00261 
00262     if (!(lc_key = strdup(strlwc(key)))) {
00263             return NULL;
00264     }
00265     sval = dictionary_get(d, lc_key, def);
00266     free(lc_key);
00267     return sval ;
00268 }
00269 
00270 
00271 
00272 /*-------------------------------------------------------------------------*/
00273 /**
00274   @brief    Get the string associated to a key, convert to an int
00275   @param    d Dictionary to search
00276   @param    key Key string to look for
00277   @param    notfound Value to return in case of error
00278   @return   integer
00279 
00280   This function queries a dictionary for a key. A key as read from an
00281   ini file is given as "section:key". If the key cannot be found,
00282   the notfound value is returned.
00283  */
00284 /*--------------------------------------------------------------------------*/
00285 int iniparser_getint(dictionary * d, const char * key, int notfound)
00286 {
00287     char    *   str ;
00288 
00289     str = iniparser_getstring(d, key, INI_INVALID_KEY);
00290     if (str==INI_INVALID_KEY) return notfound ;
00291     return atoi(str);
00292 }
00293 
00294 
00295 /*-------------------------------------------------------------------------*/
00296 /**
00297   @brief    Get the string associated to a key, convert to a double
00298   @param    d Dictionary to search
00299   @param    key Key string to look for
00300   @param    notfound Value to return in case of error
00301   @return   double
00302 
00303   This function queries a dictionary for a key. A key as read from an
00304   ini file is given as "section:key". If the key cannot be found,
00305   the notfound value is returned.
00306  */
00307 /*--------------------------------------------------------------------------*/
00308 double iniparser_getdouble(dictionary * d, char * key, double notfound)
00309 {
00310     char    *   str ;
00311 
00312     str = iniparser_getstring(d, key, INI_INVALID_KEY);
00313     if (str==INI_INVALID_KEY) return notfound ;
00314     return atof(str);
00315 }
00316 
00317 
00318 
00319 /*-------------------------------------------------------------------------*/
00320 /**
00321   @brief    Get the string associated to a key, convert to a boolean
00322   @param    d Dictionary to search
00323   @param    key Key string to look for
00324   @param    notfound Value to return in case of error
00325   @return   integer
00326 
00327   This function queries a dictionary for a key. A key as read from an
00328   ini file is given as "section:key". If the key cannot be found,
00329   the notfound value is returned.
00330 
00331   A true boolean is found if one of the following is matched:
00332 
00333   - A string starting with 'y'
00334   - A string starting with 'Y'
00335   - A string starting with 't'
00336   - A string starting with 'T'
00337   - A string starting with '1'
00338 
00339   A false boolean is found if one of the following is matched:
00340 
00341   - A string starting with 'n'
00342   - A string starting with 'N'
00343   - A string starting with 'f'
00344   - A string starting with 'F'
00345   - A string starting with '0'
00346 
00347   The notfound value returned if no boolean is identified, does not
00348   necessarily have to be 0 or 1.
00349  */
00350 /*--------------------------------------------------------------------------*/
00351 int iniparser_getboolean(dictionary * d, const char * key, int notfound)
00352 {
00353     char    *   c ;
00354     int         ret ;
00355 
00356     c = iniparser_getstring(d, key, INI_INVALID_KEY);
00357     if (c==INI_INVALID_KEY) return notfound ;
00358     if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
00359         ret = 1 ;
00360     } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
00361         ret = 0 ;
00362     } else {
00363         ret = notfound ;
00364     }
00365     return ret;
00366 }
00367 
00368 
00369 /*-------------------------------------------------------------------------*/
00370 /**
00371   @brief    Finds out if a given entry exists in a dictionary
00372   @param    ini     Dictionary to search
00373   @param    entry   Name of the entry to look for
00374   @return   integer 1 if entry exists, 0 otherwise
00375 
00376   Finds out if a given entry exists in the dictionary. Since sections
00377   are stored as keys with NULL associated values, this is the only way
00378   of querying for the presence of sections in a dictionary.
00379  */
00380 /*--------------------------------------------------------------------------*/
00381 
00382 int iniparser_find_entry(
00383     dictionary  *   ini,
00384     char        *   entry
00385 )
00386 {
00387     int found=0 ;
00388     if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
00389         found = 1 ;
00390     }
00391     return found ;
00392 }
00393 
00394 
00395 
00396 /*-------------------------------------------------------------------------*/
00397 /**
00398   @brief    Set an entry in a dictionary.
00399   @param    ini     Dictionary to modify.
00400   @param    entry   Entry to modify (entry name)
00401   @param    val     New value to associate to the entry.
00402   @return   int 0 if Ok, -1 otherwise.
00403 
00404   If the given entry can be found in the dictionary, it is modified to
00405   contain the provided value. If it cannot be found, -1 is returned.
00406   It is Ok to set val to NULL.
00407  */
00408 /*--------------------------------------------------------------------------*/
00409 
00410 int iniparser_setstr(dictionary * ini, char * entry, char * val)
00411 {
00412     dictionary_set(ini, strlwc(entry), val);
00413     return 0 ;
00414 }
00415 
00416 /*-------------------------------------------------------------------------*/
00417 /**
00418   @brief    Delete an entry in a dictionary
00419   @param    ini     Dictionary to modify
00420   @param    entry   Entry to delete (entry name)
00421   @return   void
00422 
00423   If the given entry can be found, it is deleted from the dictionary.
00424  */
00425 /*--------------------------------------------------------------------------*/
00426 void iniparser_unset(dictionary * ini, char * entry)
00427 {
00428     dictionary_unset(ini, strlwc(entry));
00429 }
00430 
00431 
00432 /*-------------------------------------------------------------------------*/
00433 /**
00434   @brief    Parse an ini file and return an allocated dictionary object
00435   @param    ininame Name of the ini file to read.
00436   @return   Pointer to newly allocated dictionary
00437 
00438   This is the parser for ini files. This function is called, providing
00439   the name of the file to be read. It returns a dictionary object that
00440   should not be accessed directly, but through accessor functions
00441   instead.
00442 
00443   The returned dictionary must be freed using iniparser_freedict().
00444  */
00445 /*--------------------------------------------------------------------------*/
00446 
00447 dictionary * iniparser_load(const char * ininame)
00448 {
00449     dictionary  *   d ;
00450     char        lin[ASCIILINESZ+1];
00451     char        sec[ASCIILINESZ+1];
00452     char        key[ASCIILINESZ+1];
00453     char        val[ASCIILINESZ+1];
00454     char    *   where ;
00455     FILE    *   ini ;
00456     int         lineno ;
00457 
00458     if ((ini=fopen(ininame, "r"))==NULL) {
00459         return NULL ;
00460     }
00461 
00462     sec[0]=0;
00463 
00464     /*
00465      * Initialize a new dictionary entry
00466      */
00467     if (!(d = dictionary_new(0))) {
00468             fclose(ini);
00469             return NULL;
00470     }
00471     lineno = 0 ;
00472     while (fgets(lin, ASCIILINESZ, ini)!=NULL) {
00473         lineno++ ;
00474         where = strskp(lin); /* Skip leading spaces */
00475         if (*where==';' || *where=='#' || *where==0)
00476             continue ; /* Comment lines */
00477         else {
00478             if (sscanf(where, "[%[^]]", sec)==1) {
00479                 /* Valid section name */
00480                 strcpy(sec, strlwc(sec));
00481                 iniparser_add_entry(d, sec, NULL, NULL);
00482             } else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2
00483                    ||  sscanf (where, "%[^=] = '%[^\']'",   key, val) == 2
00484                    ||  sscanf (where, "%[^=] = %[^;#]",     key, val) == 2) {
00485                 strcpy(key, strlwc(strcrop(key)));
00486                 /*
00487                  * sscanf cannot handle "" or '' as empty value,
00488                  * this is done here
00489                  */
00490                 if (!strcmp(val, "\"\"") || !strcmp(val, "''")) {
00491                     val[0] = (char)0;
00492                 } else {
00493                     strcpy(val, strcrop(val));
00494                 }
00495                 iniparser_add_entry(d, sec, key, val);
00496             }
00497         }
00498     }
00499     fclose(ini);
00500     return d ;
00501 }
00502 
00503 
00504 
00505 /*-------------------------------------------------------------------------*/
00506 /**
00507   @brief    Free all memory associated to an ini dictionary
00508   @param    d Dictionary to free
00509   @return   void
00510 
00511   Free all memory associated to an ini dictionary.
00512   It is mandatory to call this function before the dictionary object
00513   gets out of the current context.
00514  */
00515 /*--------------------------------------------------------------------------*/
00516 
00517 void iniparser_freedict(dictionary * d)
00518 {
00519     dictionary_del(d);
00520 }
00521 
00522 /* vim: set ts=4 et sw=4 tw=75 */

Sambaに対してSat Aug 29 21:22:58 2009に生成されました。  doxygen 1.4.7