00001 /* 00002 * $Id: iniparser.c 4585 2008-08-06 08:20:30Z klaus_darilion $ 00003 * 00004 * Kamailio LDAP Module 00005 * 00006 * Copyright (C) 2007 University of North Carolina 00007 * 00008 * Original author: Christian Schlatter, cs@unc.edu 00009 * 00010 * 00011 * This file is part of Kamailio, a free SIP server. 00012 * 00013 * Kamailio is free software; you can redistribute it and/or modify 00014 * it under the terms of the GNU General Public License as published by 00015 * the Free Software Foundation; either version 2 of the License, or 00016 * (at your option) any later version 00017 * 00018 * Kamailio is distributed in the hope that it will be useful, 00019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00021 * GNU General Public License for more details. 00022 * 00023 * You should have received a copy of the GNU General Public License 00024 * along with this program; if not, write to the Free Software 00025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00026 * 00027 * History: 00028 * -------- 00029 * 2007-02-18: Initial version 00030 */ 00031 00032 00033 00034 /* 00035 Based upon libiniparser, by Nicolas Devillard 00036 Hacked into 1 file (m-iniparser) by Freek/2005 00037 Original terms following: 00038 00039 -- - 00040 00041 Copyright (c) 2000 by Nicolas Devillard (ndevilla AT free DOT fr). 00042 00043 Written by Nicolas Devillard. Not derived from licensed software. 00044 00045 Permission is granted to anyone to use this software for any 00046 purpose on any computer system, and to redistribute it freely, 00047 subject to the following restrictions: 00048 00049 1. The author is not responsible for the consequences of use of 00050 this software, no matter how awful, even if they arise 00051 from defects in it. 00052 00053 2. The origin of this software must not be misrepresented, either 00054 by explicit claim or by omission. 00055 00056 3. Altered versions must be plainly marked as such, and must not 00057 be misrepresented as being the original software. 00058 00059 4. This notice may not be removed or altered. 00060 00061 */ 00062 00063 00064 #include <stdio.h> 00065 #include <stdlib.h> 00066 #include <string.h> 00067 #include <unistd.h> 00068 00069 #include "iniparser.h" 00070 00071 #ifdef __cplusplus 00072 extern "C" { 00073 #endif 00074 00075 /* strlib.c following */ 00076 00077 #define ASCIILINESZ 1024 00078 /*-------------------------------------------------------------------------*/ 00079 /** 00080 @brief Convert a string to lowercase. 00081 @param s String to convert. 00082 @return ptr to statically allocated string. 00083 00084 This function returns a pointer to a statically allocated string 00085 containing a lowercased version of the input string. Do not free 00086 or modify the returned string! Since the returned string is statically 00087 allocated, it will be modified at each function call (not re-entrant). 00088 */ 00089 /*--------------------------------------------------------------------------*/ 00090 00091 static char * strlwc(char * s) 00092 { 00093 static char l[ASCIILINESZ+1]; 00094 int i ; 00095 00096 if (s==NULL) return NULL ; 00097 memset(l, 0, ASCIILINESZ+1); 00098 i=0 ; 00099 while (s[i] && i<ASCIILINESZ) { 00100 l[i] = (char)tolower((int)s[i]); 00101 i++ ; 00102 } 00103 l[ASCIILINESZ]=(char)0; 00104 return l ; 00105 } 00106 00107 00108 00109 /*-------------------------------------------------------------------------*/ 00110 /** 00111 @brief Convert a string to uppercase. 00112 @param s String to convert. 00113 @return ptr to statically allocated string. 00114 00115 This function returns a pointer to a statically allocated string 00116 containing an uppercased version of the input string. Do not free 00117 or modify the returned string! Since the returned string is statically 00118 allocated, it will be modified at each function call (not re-entrant). 00119 */ 00120 /*--------------------------------------------------------------------------*/ 00121 00122 /* 00123 static char * strupc(char * s) 00124 { 00125 static char l[ASCIILINESZ+1]; 00126 int i ; 00127 00128 if (s==NULL) return NULL ; 00129 memset(l, 0, ASCIILINESZ+1); 00130 i=0 ; 00131 while (s[i] && i<ASCIILINESZ) { 00132 l[i] = (char)toupper((int)s[i]); 00133 i++ ; 00134 } 00135 l[ASCIILINESZ]=(char)0; 00136 return l ; 00137 } 00138 */ 00139 00140 00141 00142 /*-------------------------------------------------------------------------*/ 00143 /** 00144 @brief Skip blanks until the first non-blank character. 00145 @param s String to parse. 00146 @return Pointer to char inside given string. 00147 00148 This function returns a pointer to the first non-blank character in the 00149 given string. 00150 */ 00151 /*--------------------------------------------------------------------------*/ 00152 00153 static char * strskp(char * s) 00154 { 00155 char * skip = s; 00156 if (s==NULL) return NULL ; 00157 while (isspace((int)*skip) && *skip) skip++; 00158 return skip ; 00159 } 00160 00161 00162 00163 /*-------------------------------------------------------------------------*/ 00164 /** 00165 @brief Remove blanks at the end of a string. 00166 @param s String to parse. 00167 @return ptr to statically allocated string. 00168 00169 This function returns a pointer to a statically allocated string, 00170 which is identical to the input string, except that all blank 00171 characters at the end of the string have been removed. 00172 Do not free or modify the returned string! Since the returned string 00173 is statically allocated, it will be modified at each function call 00174 (not re-entrant). 00175 */ 00176 /*--------------------------------------------------------------------------*/ 00177 00178 static char * strcrop(char * s) 00179 { 00180 static char l[ASCIILINESZ+1]; 00181 char * last ; 00182 00183 if (s==NULL) return NULL ; 00184 memset(l, 0, ASCIILINESZ+1); 00185 strcpy(l, s); 00186 last = l + strlen(l); 00187 while (last > l) { 00188 if (!isspace((int)*(last-1))) 00189 break ; 00190 last -- ; 00191 } 00192 *last = (char)0; 00193 return l ; 00194 } 00195 00196 00197 00198 /*-------------------------------------------------------------------------*/ 00199 /** 00200 @brief Remove blanks at the beginning and the end of a string. 00201 @param s String to parse. 00202 @return ptr to statically allocated string. 00203 00204 This function returns a pointer to a statically allocated string, 00205 which is identical to the input string, except that all blank 00206 characters at the end and the beg. of the string have been removed. 00207 Do not free or modify the returned string! Since the returned string 00208 is statically allocated, it will be modified at each function call 00209 (not re-entrant). 00210 */ 00211 /*--------------------------------------------------------------------------*/ 00212 /* 00213 static char * strstrip(char * s) 00214 { 00215 static char l[ASCIILINESZ+1]; 00216 char * last ; 00217 00218 if (s==NULL) return NULL ; 00219 00220 while (isspace((int)*s) && *s) s++; 00221 00222 memset(l, 0, ASCIILINESZ+1); 00223 strcpy(l, s); 00224 last = l + strlen(l); 00225 while (last > l) { 00226 if (!isspace((int)*(last-1))) 00227 break ; 00228 last -- ; 00229 } 00230 *last = (char)0; 00231 00232 return (char*)l ; 00233 } 00234 */ 00235 00236 /* dictionary.c.c following */ 00237 /** Maximum value size for integers and doubles. */ 00238 #define MAXVALSZ 1024 00239 00240 /** Minimal allocated number of entries in a dictionary */ 00241 #define DICTMINSZ 128 00242 00243 /** Invalid key token */ 00244 #define DICT_INVALID_KEY ((char*)-1) 00245 00246 /* 00247 Doubles the allocated size associated to a pointer 00248 'size' is the current allocated size. 00249 */ 00250 static void * mem_double(void * ptr, int size) 00251 { 00252 void *newptr; 00253 00254 newptr = calloc(2*size, 1); 00255 memcpy(newptr, ptr, size); 00256 free(ptr); 00257 return newptr ; 00258 } 00259 00260 00261 /*--------------------------------------------------------------------------- 00262 Function codes 00263 ---------------------------------------------------------------------------*/ 00264 00265 /*-------------------------------------------------------------------------*/ 00266 /** 00267 @brief Compute the hash key for a string. 00268 @param key Character string to use for key. 00269 @return 1 unsigned int on at least 32 bits. 00270 00271 This hash function has been taken from an Article in Dr Dobbs Journal. 00272 This is normally a collision-free function, distributing keys evenly. 00273 The key is stored anyway in the struct so that collision can be avoided 00274 by comparing the key itself in last resort. 00275 */ 00276 /*--------------------------------------------------------------------------*/ 00277 00278 static unsigned dictionary_hash(char * key) 00279 { 00280 int len ; 00281 unsigned hash ; 00282 int i ; 00283 00284 len = strlen(key); 00285 for (hash=0, i=0 ; i<len ; i++) { 00286 hash += (unsigned)key[i] ; 00287 hash += (hash<<10); 00288 hash ^= (hash>>6) ; 00289 } 00290 hash += (hash <<3); 00291 hash ^= (hash >>11); 00292 hash += (hash <<15); 00293 return hash ; 00294 } 00295 00296 00297 /*-------------------------------------------------------------------------*/ 00298 /** 00299 @brief Create a new dictionary object. 00300 @param size Optional initial size of the dictionary. 00301 @return 1 newly allocated dictionary objet. 00302 00303 This function allocates a new dictionary object of given size and returns 00304 it. If you do not know in advance (roughly) the number of entries in the 00305 dictionary, give size=0. 00306 */ 00307 /*--------------------------------------------------------------------------*/ 00308 00309 static dictionary * dictionary_new(int size) 00310 { 00311 dictionary *d ; 00312 00313 /* If no size was specified, allocate space for DICTMINSZ */ 00314 if (size<DICTMINSZ) size=DICTMINSZ ; 00315 00316 d = (dictionary *)calloc(1, sizeof(dictionary)); 00317 d->size = size ; 00318 d->val = (char **)calloc(size, sizeof(char*)); 00319 d->key = (char **)calloc(size, sizeof(char*)); 00320 d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); 00321 00322 return d; 00323 } 00324 00325 00326 /*-------------------------------------------------------------------------*/ 00327 /** 00328 @brief Delete a dictionary object 00329 @param d dictionary object to deallocate. 00330 @return void 00331 00332 Deallocate a dictionary object and all memory associated to it. 00333 */ 00334 /*--------------------------------------------------------------------------*/ 00335 00336 static void dictionary_del(dictionary * d) 00337 { 00338 int i ; 00339 00340 if (d==NULL) return ; 00341 for (i=0 ; i<d->size ; i++) { 00342 if (d->key[i]!=NULL) 00343 free(d->key[i]); 00344 if (d->val[i]!=NULL) 00345 free(d->val[i]); 00346 } 00347 free(d->val); 00348 free(d->key); 00349 free(d->hash); 00350 free(d); 00351 00352 return; 00353 } 00354 00355 00356 00357 /*-------------------------------------------------------------------------*/ 00358 /** 00359 @brief Get a value from a dictionary. 00360 @param d dictionary object to search. 00361 @param key Key to look for in the dictionary. 00362 @param def Default value to return if key not found. 00363 @return 1 pointer to internally allocated character string. 00364 00365 This function locates a key in a dictionary and returns a pointer to its 00366 value, or the passed 'def' pointer if no such key can be found in 00367 dictionary. The returned character pointer points to data internal to the 00368 dictionary object, you should not try to free it or modify it. 00369 */ 00370 /*--------------------------------------------------------------------------*/ 00371 static char * dictionary_get(dictionary * d, char * key, char * def) 00372 { 00373 unsigned hash ; 00374 int i ; 00375 00376 hash = dictionary_hash(key); 00377 for (i=0 ; i<d->size ; i++) { 00378 if (d->key==NULL) 00379 continue ; 00380 /* Compare hash */ 00381 if (hash==d->hash[i]) { 00382 /* Compare string, to avoid hash collisions */ 00383 if (!strcmp(key, d->key[i])) { 00384 return d->val[i] ; 00385 } 00386 } 00387 } 00388 return def ; 00389 } 00390 00391 00392 /*-------------------------------------------------------------------------*/ 00393 /** 00394 @brief Set a value in a dictionary. 00395 @param d dictionary object to modify. 00396 @param key Key to modify or add. 00397 @param val Value to add. 00398 @return void 00399 00400 If the given key is found in the dictionary, the associated value is 00401 replaced by the provided one. If the key cannot be found in the 00402 dictionary, it is added to it. 00403 00404 It is Ok to provide a NULL value for val, but NULL values for the dictionary 00405 or the key are considered as errors: the function will return immediately 00406 in such a case. 00407 00408 Notice that if you dictionary_set a variable to NULL, a call to 00409 dictionary_get will return a NULL value: the variable will be found, and 00410 its value (NULL) is returned. In other words, setting the variable 00411 content to NULL is equivalent to deleting the variable from the 00412 dictionary. It is not possible (in this implementation) to have a key in 00413 the dictionary without value. 00414 */ 00415 /*--------------------------------------------------------------------------*/ 00416 00417 static void dictionary_set(dictionary * d, char * key, char * val) 00418 { 00419 int i ; 00420 unsigned hash ; 00421 00422 if (d==NULL || key==NULL) return ; 00423 00424 /* Compute hash for this key */ 00425 hash = dictionary_hash(key) ; 00426 /* Find if value is already in blackboard */ 00427 if (d->n>0) { 00428 for (i=0 ; i<d->size ; i++) { 00429 if (d->key[i]==NULL) 00430 continue ; 00431 if (hash==d->hash[i]) { /* Same hash value */ 00432 if (!strcmp(key, d->key[i])) { /* Same key */ 00433 /* Found a value: modify and return */ 00434 if (d->val[i]!=NULL) 00435 free(d->val[i]); 00436 d->val[i] = val ? strdup(val) : NULL ; 00437 /* Value has been modified: return */ 00438 return ; 00439 } 00440 } 00441 } 00442 } 00443 /* Add a new value */ 00444 /* See if dictionary needs to grow */ 00445 if (d->n==d->size) { 00446 00447 /* Reached maximum size: reallocate blackboard */ 00448 d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ; 00449 d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ; 00450 d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ; 00451 00452 /* Double size */ 00453 d->size *= 2 ; 00454 } 00455 00456 /* Insert key in the first empty slot */ 00457 for (i=0 ; i<d->size ; i++) { 00458 if (d->key[i]==NULL) { 00459 /* Add key here */ 00460 break ; 00461 } 00462 } 00463 /* Copy key */ 00464 d->key[i] = strdup(key); 00465 d->val[i] = val ? strdup(val) : NULL ; 00466 d->hash[i] = hash; 00467 d->n ++ ; 00468 return ; 00469 } 00470 00471 /*-------------------------------------------------------------------------*/ 00472 /** 00473 @brief Delete a key in a dictionary 00474 @param d dictionary object to modify. 00475 @param key Key to remove. 00476 @return void 00477 00478 This function deletes a key in a dictionary. Nothing is done if the 00479 key cannot be found. 00480 */ 00481 /*--------------------------------------------------------------------------*/ 00482 static void dictionary_unset(dictionary * d, char * key) 00483 { 00484 unsigned hash ; 00485 int i ; 00486 00487 hash = dictionary_hash(key); 00488 for (i=0 ; i<d->size ; i++) { 00489 if (d->key[i]==NULL) 00490 continue ; 00491 /* Compare hash */ 00492 if (hash==d->hash[i]) { 00493 /* Compare string, to avoid hash collisions */ 00494 if (!strcmp(key, d->key[i])) { 00495 /* Found key */ 00496 break ; 00497 } 00498 } 00499 } 00500 if (i>=d->size) 00501 /* Key not found */ 00502 return ; 00503 00504 free(d->key[i]); 00505 d->key[i] = NULL ; 00506 if (d->val[i]!=NULL) { 00507 free(d->val[i]); 00508 d->val[i] = NULL ; 00509 } 00510 d->hash[i] = 0 ; 00511 d->n -- ; 00512 return ; 00513 } 00514 00515 00516 /*-------------------------------------------------------------------------*/ 00517 /** 00518 @brief Dump a dictionary to an opened file pointer. 00519 @param d Dictionary to dump 00520 @param f Opened file pointer. 00521 @return void 00522 00523 Dumps a dictionary onto an opened file pointer. Key pairs are printed out 00524 as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as 00525 output file pointers. 00526 */ 00527 /*--------------------------------------------------------------------------*/ 00528 00529 static void dictionary_dump(dictionary *d, FILE *f) 00530 { 00531 int i; 00532 00533 if (d==NULL || f==NULL) return; 00534 00535 for (i=0; i<d->size; i++) { 00536 if (d->key[i] == NULL) 00537 continue ; 00538 if (d->val[i] != NULL) { 00539 fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); 00540 } else { 00541 fprintf(f, "[%s]=UNDEF\n", d->key[i]); 00542 } 00543 } 00544 00545 return; 00546 } 00547 00548 00549 /* iniparser.c.c following */ 00550 #define ASCIILINESZ 1024 00551 #define INI_INVALID_KEY ((char*)-1) 00552 00553 /* Private: add an entry to the dictionary */ 00554 static void iniparser_add_entry( 00555 dictionary * d, 00556 char * sec, 00557 char * key, 00558 char * val) 00559 { 00560 char longkey[2*ASCIILINESZ+1]; 00561 00562 /* Make a key as section:keyword */ 00563 if (key!=NULL) { 00564 sprintf(longkey, "%s:%s", sec, key); 00565 } else { 00566 strcpy(longkey, sec); 00567 } 00568 00569 /* Add (key,val) to dictionary */ 00570 dictionary_set(d, longkey, val); 00571 return ; 00572 } 00573 00574 00575 /*-------------------------------------------------------------------------*/ 00576 /** 00577 @brief Get number of sections in a dictionary 00578 @param d Dictionary to examine 00579 @return int Number of sections found in dictionary 00580 00581 This function returns the number of sections found in a dictionary. 00582 The test to recognize sections is done on the string stored in the 00583 dictionary: a section name is given as "section" whereas a key is 00584 stored as "section:key", thus the test looks for entries that do not 00585 contain a colon. 00586 00587 This clearly fails in the case a section name contains a colon, but 00588 this should simply be avoided. 00589 00590 This function returns -1 in case of error. 00591 */ 00592 /*--------------------------------------------------------------------------*/ 00593 00594 int iniparser_getnsec(dictionary * d) 00595 { 00596 int i ; 00597 int nsec ; 00598 00599 if (d==NULL) return -1 ; 00600 nsec=0 ; 00601 for (i=0 ; i<d->size ; i++) { 00602 if (d->key[i]==NULL) 00603 continue ; 00604 if (strchr(d->key[i], ':')==NULL) { 00605 nsec ++ ; 00606 } 00607 } 00608 return nsec ; 00609 } 00610 00611 00612 /*-------------------------------------------------------------------------*/ 00613 /** 00614 @brief Get name for section n in a dictionary. 00615 @param d Dictionary to examine 00616 @param n Section number (from 0 to nsec-1). 00617 @return Pointer to char string 00618 00619 This function locates the n-th section in a dictionary and returns 00620 its name as a pointer to a string statically allocated inside the 00621 dictionary. Do not free or modify the returned string! 00622 00623 This function returns NULL in case of error. 00624 */ 00625 /*--------------------------------------------------------------------------*/ 00626 00627 char * iniparser_getsecname(dictionary * d, int n) 00628 { 00629 int i ; 00630 int foundsec ; 00631 00632 if (d==NULL || n<0) return NULL ; 00633 foundsec=0 ; 00634 for (i=0 ; i<d->size ; i++) { 00635 if (d->key[i]==NULL) 00636 continue ; 00637 if (strchr(d->key[i], ':')==NULL) { 00638 foundsec++ ; 00639 if (foundsec>n) 00640 break ; 00641 } 00642 } 00643 if (foundsec<=n) { 00644 return NULL ; 00645 } 00646 return d->key[i] ; 00647 } 00648 00649 00650 /*-------------------------------------------------------------------------*/ 00651 /** 00652 @brief Dump a dictionary to an opened file pointer. 00653 @param d Dictionary to dump. 00654 @param f Opened file pointer to dump to. 00655 @return void 00656 00657 This function prints out the contents of a dictionary, one element by 00658 line, onto the provided file pointer. It is OK to specify @c stderr 00659 or @c stdout as output files. This function is meant for debugging 00660 purposes mostly. 00661 */ 00662 /*--------------------------------------------------------------------------*/ 00663 void iniparser_dump(dictionary * d, FILE * f) 00664 { 00665 dictionary_dump(d,f); 00666 } 00667 00668 00669 /*-------------------------------------------------------------------------*/ 00670 /** 00671 @brief Save a dictionary to a loadable ini file 00672 @param d Dictionary to dump 00673 @param f Opened file pointer to dump to 00674 @return void 00675 00676 This function dumps a given dictionary into a loadable ini file. 00677 It is Ok to specify @c stderr or @c stdout as output files. 00678 */ 00679 /*--------------------------------------------------------------------------*/ 00680 00681 void iniparser_dump_ini(dictionary * d, FILE * f) 00682 { 00683 int i, j ; 00684 char keym[ASCIILINESZ+1]; 00685 int nsec ; 00686 char * secname ; 00687 int seclen ; 00688 00689 if (d==NULL || f==NULL) return ; 00690 00691 nsec = iniparser_getnsec(d); 00692 if (nsec<1) { 00693 /* No section in file: dump all keys as they are */ 00694 for (i=0 ; i<d->size ; i++) { 00695 if (d->key[i]==NULL) 00696 continue ; 00697 fprintf(f, "%s = %s\n", d->key[i], d->val[i]); 00698 } 00699 return ; 00700 } 00701 for (i=0 ; i<nsec ; i++) { 00702 secname = iniparser_getsecname(d, i) ; 00703 seclen = (int)strlen(secname); 00704 fprintf(f, "\n[%s]\n", secname); 00705 sprintf(keym, "%s:", secname); 00706 for (j=0 ; j<d->size ; j++) { 00707 if (d->key[j]==NULL) 00708 continue ; 00709 if (!strncmp(d->key[j], keym, seclen+1)) { 00710 fprintf(f, 00711 "%-30s = %s\n", 00712 d->key[j]+seclen+1, 00713 d->val[j] ? d->val[j] : ""); 00714 } 00715 } 00716 } 00717 fprintf(f, "\n"); 00718 return ; 00719 } 00720 00721 /*-------------------------------------------------------------------------*/ 00722 /** 00723 @brief Get the string associated to a key, return NULL if not found 00724 @param d Dictionary to search 00725 @param key Key string to look for 00726 @return pointer to statically allocated character string, or NULL. 00727 00728 This function queries a dictionary for a key. A key as read from an 00729 ini file is given as "section:key". If the key cannot be found, 00730 NULL is returned. 00731 The returned char pointer is pointing to a string allocated in 00732 the dictionary, do not free or modify it. 00733 00734 This function is only provided for backwards compatibility with 00735 previous versions of iniparser. It is recommended to use 00736 iniparser_getstring() instead. 00737 */ 00738 /*--------------------------------------------------------------------------*/ 00739 char * iniparser_getstr(dictionary * d, char * key) 00740 { 00741 return iniparser_getstring(d, key, NULL); 00742 } 00743 00744 00745 /*-------------------------------------------------------------------------*/ 00746 /** 00747 @brief Get the string associated to a key 00748 @param d Dictionary to search 00749 @param key Key string to look for 00750 @param def Default value to return if key not found. 00751 @return pointer to statically allocated character string 00752 00753 This function queries a dictionary for a key. A key as read from an 00754 ini file is given as "section:key". If the key cannot be found, 00755 the pointer passed as 'def' is returned. 00756 The returned char pointer is pointing to a string allocated in 00757 the dictionary, do not free or modify it. 00758 */ 00759 /*--------------------------------------------------------------------------*/ 00760 char * iniparser_getstring(dictionary * d, char * key, char * def) 00761 { 00762 char * lc_key ; 00763 char * sval ; 00764 00765 if (d==NULL || key==NULL) 00766 return def ; 00767 00768 lc_key = strdup(strlwc(key)); 00769 sval = dictionary_get(d, lc_key, def); 00770 free(lc_key); 00771 return sval ; 00772 } 00773 00774 00775 00776 /*-------------------------------------------------------------------------*/ 00777 /** 00778 @brief Get the string associated to a key, convert to an int 00779 @param d Dictionary to search 00780 @param key Key string to look for 00781 @param notfound Value to return in case of error 00782 @return integer 00783 00784 This function queries a dictionary for a key. A key as read from an 00785 ini file is given as "section:key". If the key cannot be found, 00786 the notfound value is returned. 00787 */ 00788 /*--------------------------------------------------------------------------*/ 00789 int iniparser_getint(dictionary * d, char * key, int notfound) 00790 { 00791 char * str ; 00792 00793 str = iniparser_getstring(d, key, INI_INVALID_KEY); 00794 if (str==INI_INVALID_KEY) return notfound ; 00795 return atoi(str); 00796 } 00797 00798 00799 /*-------------------------------------------------------------------------*/ 00800 /** 00801 @brief Get the string associated to a key, convert to a double 00802 @param d Dictionary to search 00803 @param key Key string to look for 00804 @param notfound Value to return in case of error 00805 @return double 00806 00807 This function queries a dictionary for a key. A key as read from an 00808 ini file is given as "section:key". If the key cannot be found, 00809 the notfound value is returned. 00810 */ 00811 /*--------------------------------------------------------------------------*/ 00812 double iniparser_getdouble(dictionary * d, char * key, double notfound) 00813 { 00814 char * str ; 00815 00816 str = iniparser_getstring(d, key, INI_INVALID_KEY); 00817 if (str==INI_INVALID_KEY) return notfound ; 00818 return atof(str); 00819 } 00820 00821 00822 00823 /*-------------------------------------------------------------------------*/ 00824 /** 00825 @brief Get the string associated to a key, convert to a boolean 00826 @param d Dictionary to search 00827 @param key Key string to look for 00828 @param notfound Value to return in case of error 00829 @return integer 00830 00831 This function queries a dictionary for a key. A key as read from an 00832 ini file is given as "section:key". If the key cannot be found, 00833 the notfound value is returned. 00834 00835 A true boolean is found if one of the following is matched: 00836 00837 - A string starting with 'y' 00838 - A string starting with 'Y' 00839 - A string starting with 't' 00840 - A string starting with 'T' 00841 - A string starting with '1' 00842 00843 A false boolean is found if one of the following is matched: 00844 00845 - A string starting with 'n' 00846 - A string starting with 'N' 00847 - A string starting with 'f' 00848 - A string starting with 'F' 00849 - A string starting with '0' 00850 00851 The notfound value returned if no boolean is identified, does not 00852 necessarily have to be 0 or 1. 00853 */ 00854 /*--------------------------------------------------------------------------*/ 00855 int iniparser_getboolean(dictionary * d, char * key, int notfound) 00856 { 00857 char * c ; 00858 int ret ; 00859 00860 c = iniparser_getstring(d, key, INI_INVALID_KEY); 00861 if (c==INI_INVALID_KEY) return notfound ; 00862 if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { 00863 ret = 1 ; 00864 } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { 00865 ret = 0 ; 00866 } else { 00867 ret = notfound ; 00868 } 00869 return ret; 00870 } 00871 00872 00873 /*-------------------------------------------------------------------------*/ 00874 /** 00875 @brief Finds out if a given entry exists in a dictionary 00876 @param ini Dictionary to search 00877 @param entry Name of the entry to look for 00878 @return integer 1 if entry exists, 0 otherwise 00879 00880 Finds out if a given entry exists in the dictionary. Since sections 00881 are stored as keys with NULL associated values, this is the only way 00882 of querying for the presence of sections in a dictionary. 00883 */ 00884 /*--------------------------------------------------------------------------*/ 00885 00886 int iniparser_find_entry( 00887 dictionary * ini, 00888 char * entry 00889 ) 00890 { 00891 int found=0 ; 00892 if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { 00893 found = 1 ; 00894 } 00895 return found ; 00896 } 00897 00898 00899 00900 /*-------------------------------------------------------------------------*/ 00901 /** 00902 @brief Set an entry in a dictionary. 00903 @param ini Dictionary to modify. 00904 @param entry Entry to modify (entry name) 00905 @param val New value to associate to the entry. 00906 @return int 0 if Ok, -1 otherwise. 00907 00908 If the given entry can be found in the dictionary, it is modified to 00909 contain the provided value. If it cannot be found, -1 is returned. 00910 It is Ok to set val to NULL. 00911 */ 00912 /*--------------------------------------------------------------------------*/ 00913 00914 int iniparser_setstr(dictionary * ini, char * entry, char * val) 00915 { 00916 dictionary_set(ini, strlwc(entry), val); 00917 return 0 ; 00918 } 00919 00920 /*-------------------------------------------------------------------------*/ 00921 /** 00922 @brief Delete an entry in a dictionary 00923 @param ini Dictionary to modify 00924 @param entry Entry to delete (entry name) 00925 @return void 00926 00927 If the given entry can be found, it is deleted from the dictionary. 00928 */ 00929 /*--------------------------------------------------------------------------*/ 00930 void iniparser_unset(dictionary * ini, char * entry) 00931 { 00932 dictionary_unset(ini, strlwc(entry)); 00933 } 00934 00935 00936 /*-------------------------------------------------------------------------*/ 00937 /** 00938 @brief Parse an ini file and return an allocated dictionary object 00939 @param ininame Name of the ini file to read. 00940 @return Pointer to newly allocated dictionary 00941 00942 This is the parser for ini files. This function is called, providing 00943 the name of the file to be read. It returns a dictionary object that 00944 should not be accessed directly, but through accessor functions 00945 instead. 00946 00947 The returned dictionary must be freed using iniparser_free(). 00948 */ 00949 /*--------------------------------------------------------------------------*/ 00950 00951 dictionary * iniparser_new(char *ininame) 00952 { 00953 dictionary * d ; 00954 char lin[ASCIILINESZ+1]; 00955 char sec[ASCIILINESZ+1]; 00956 char key[ASCIILINESZ+1]; 00957 char val[ASCIILINESZ+1]; 00958 char * where ; 00959 FILE * ini ; 00960 int lineno ; 00961 00962 if ((ini=fopen(ininame, "r"))==NULL) { 00963 return NULL ; 00964 } 00965 00966 sec[0]=0; 00967 00968 /* 00969 * Initialize a new dictionary entry 00970 */ 00971 d = dictionary_new(0); 00972 lineno = 0 ; 00973 while (fgets(lin, ASCIILINESZ, ini)!=NULL) { 00974 lineno++ ; 00975 where = strskp(lin); /* Skip leading spaces */ 00976 if (*where==';' || *where=='#' || *where==0) 00977 continue ; /* Comment lines */ 00978 else { 00979 if (sscanf(where, "[%[^]]", sec)==1) { 00980 /* Valid section name */ 00981 strcpy(sec, strlwc(sec)); 00982 iniparser_add_entry(d, sec, NULL, NULL); 00983 } else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2 00984 || sscanf (where, "%[^=] = '%[^\']'", key, val) == 2 00985 || sscanf (where, "%[^=] = %[^;#]", key, val) == 2) { 00986 strcpy(key, strlwc(strcrop(key))); 00987 /* 00988 * sscanf cannot handle "" or '' as empty value, 00989 * this is done here 00990 */ 00991 if (!strcmp(val, "\"\"") || !strcmp(val, "''")) { 00992 val[0] = (char)0; 00993 } else { 00994 strcpy(val, strcrop(val)); 00995 } 00996 iniparser_add_entry(d, sec, key, val); 00997 } 00998 } 00999 } 01000 fclose(ini); 01001 return d ; 01002 } 01003 01004 01005 01006 /*-------------------------------------------------------------------------*/ 01007 /** 01008 @brief Free all memory associated to an ini dictionary 01009 @param d Dictionary to free 01010 @return void 01011 01012 Free all memory associated to an ini dictionary. 01013 It is mandatory to call this function before the dictionary object 01014 gets out of the current context. 01015 */ 01016 /*--------------------------------------------------------------------------*/ 01017 01018 void iniparser_free(dictionary * d) 01019 { 01020 dictionary_del(d); 01021 } 01022 01023 #ifdef __cplusplus 01024 } 01025 #endif
1.5.6