modified: makefile
[GalaxyCodeBases.git] / BGI / soap_src / soap_builder / iniparser.c
blob5592d38eb56b697882038335f627fd3f5ab87b31
2 /*-------------------------------------------------------------------------*/
3 /**
4 @file iniparser.c
5 @author N. Devillard
6 @date Mar 2000
7 @version $Revision: 2.14 $
8 @brief Parser for ini files.
10 The following four functions are added by Wong Chi Kwong (2004).
11 No warranty is given regarding the quality of this software.
13 dictionary * paraparser_load(int argc, char **argv, int booleanc, char **booleanv);
14 char* paraparser_argument(dictionary *d, int argumentNumber);
15 int paraparser_getnargument(dictionary * d);
16 unsigned int iniparser_getuint(dictionary * d, char * key, int notfound);
19 /*--------------------------------------------------------------------------*/
22 $Id: iniparser.c,v 2.14 2002/12/12 10:49:01 ndevilla Exp $
23 $Author: ndevilla $
24 $Date: 2002/12/12 10:49:01 $
25 $Revision: 2.14 $
28 /*---------------------------------------------------------------------------
29 Includes
30 ---------------------------------------------------------------------------*/
32 #include "iniparser.h"
33 #include "inistrlib.h"
35 #define ASCIILINESZ 1024
36 #define INI_INVALID_KEY ((char*)-1)
38 /*---------------------------------------------------------------------------
39 Private to this module
40 ---------------------------------------------------------------------------*/
42 /* Private: add an entry to the dictionary */
43 static void iniparser_add_entry(
44 dictionary * d,
45 char * sec,
46 char * key,
47 char * val)
49 char longkey[2*ASCIILINESZ+1];
51 /* Make a key as section:keyword */
52 if (key!=NULL) {
53 sprintf(longkey, "%s:%s", sec, key);
54 } else {
55 strcpy(longkey, sec);
58 /* Add (key,val) to dictionary */
59 dictionary_set(d, longkey, val);
60 return ;
64 /*-------------------------------------------------------------------------*/
65 /**
66 @brief Get number of sections in a dictionary
67 @param d Dictionary to examine
68 @return int Number of sections found in dictionary
70 This function returns the number of sections found in a dictionary.
71 The test to recognize sections is done on the string stored in the
72 dictionary: a section name is given as "section" whereas a key is
73 stored as "section:key", thus the test looks for entries that do not
74 contain a colon.
76 This clearly fails in the case a section name contains a colon, but
77 this should simply be avoided.
79 This function returns -1 in case of error.
81 /*--------------------------------------------------------------------------*/
83 int iniparser_getnsec(dictionary * d)
85 int i ;
86 int nsec ;
88 if (d==NULL) return -1 ;
89 nsec=0 ;
90 for (i=0 ; i<d->size ; i++) {
91 if (d->key[i]==NULL)
92 continue ;
93 if (strchr(d->key[i], ':')==NULL) {
94 nsec ++ ;
97 return nsec ;
101 /*-------------------------------------------------------------------------*/
103 @brief Get name for section n in a dictionary.
104 @param d Dictionary to examine
105 @param n Section number (from 0 to nsec-1).
106 @return Pointer to char string
108 This function locates the n-th section in a dictionary and returns
109 its name as a pointer to a string statically allocated inside the
110 dictionary. Do not free or modify the returned string!
112 This function returns NULL in case of error.
114 /*--------------------------------------------------------------------------*/
116 char * iniparser_getsecname(dictionary * d, int n)
118 int i ;
119 int foundsec ;
121 if (d==NULL || n<0) return NULL ;
122 foundsec=0 ;
123 for (i=0 ; i<d->size ; i++) {
124 if (d->key[i]==NULL)
125 continue ;
126 if (strchr(d->key[i], ':')==NULL) {
127 foundsec++ ;
128 if (foundsec>n)
129 break ;
132 if (foundsec<=n) {
133 return NULL ;
135 return d->key[i] ;
139 /*-------------------------------------------------------------------------*/
141 @brief Dump a dictionary to an opened file pointer.
142 @param d Dictionary to dump.
143 @param f Opened file pointer to dump to.
144 @return void
146 This function prints out the contents of a dictionary, one element by
147 line, onto the provided file pointer. It is OK to specify @c stderr
148 or @c stdout as output files. This function is meant for debugging
149 purposes mostly.
151 /*--------------------------------------------------------------------------*/
152 void iniparser_dump(dictionary * d, FILE * f)
154 int i ;
156 if (d==NULL || f==NULL) return ;
157 for (i=0 ; i<d->size ; i++) {
158 if (d->key[i]==NULL)
159 continue ;
160 if (d->val[i]!=NULL) {
161 fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
162 } else {
163 fprintf(f, "[%s]=UNDEF\n", d->key[i]);
166 return ;
169 /*-------------------------------------------------------------------------*/
171 @brief Save a dictionary to a loadable ini file
172 @param d Dictionary to dump
173 @param f Opened file pointer to dump to
174 @return void
176 This function dumps a given dictionary into a loadable ini file.
177 It is Ok to specify @c stderr or @c stdout as output files.
179 /*--------------------------------------------------------------------------*/
181 void iniparser_dump_ini(dictionary * d, FILE * f)
183 int i, j ;
184 char keym[ASCIILINESZ+1];
185 int nsec ;
186 char * secname ;
187 int seclen ;
189 if (d==NULL || f==NULL) return ;
191 nsec = iniparser_getnsec(d);
192 if (nsec<1) {
193 /* No section in file: dump all keys as they are */
194 for (i=0 ; i<d->size ; i++) {
195 if (d->key[i]==NULL)
196 continue ;
197 fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
199 return ;
201 for (i=0 ; i<nsec ; i++) {
202 secname = iniparser_getsecname(d, i) ;
203 seclen = (int)strlen(secname);
204 fprintf(f, "\n[%s]\n", secname);
205 sprintf(keym, "%s:", secname);
206 for (j=0 ; j<d->size ; j++) {
207 if (d->key[j]==NULL)
208 continue ;
209 if (!strncmp(d->key[j], keym, seclen+1)) {
210 fprintf(f,
211 "%-30s = %s\n",
212 d->key[j]+seclen+1,
213 d->val[j] ? d->val[j] : "");
217 fprintf(f, "\n");
218 return ;
224 /*-------------------------------------------------------------------------*/
226 @brief Get the string associated to a key, return NULL if not found
227 @param d Dictionary to search
228 @param key Key string to look for
229 @return pointer to statically allocated character string, or NULL.
231 This function queries a dictionary for a key. A key as read from an
232 ini file is given as "section:key". If the key cannot be found,
233 NULL is returned.
234 The returned char pointer is pointing to a string allocated in
235 the dictionary, do not free or modify it.
237 This function is only provided for backwards compatibility with
238 previous versions of iniparser. It is recommended to use
239 iniparser_getstring() instead.
241 /*--------------------------------------------------------------------------*/
242 char * iniparser_getstr(dictionary * d, char * key)
244 return iniparser_getstring(d, key, NULL);
248 /*-------------------------------------------------------------------------*/
250 @brief Get the string associated to a key
251 @param d Dictionary to search
252 @param key Key string to look for
253 @param def Default value to return if key not found.
254 @return pointer to statically allocated character string
256 This function queries a dictionary for a key. A key as read from an
257 ini file is given as "section:key". If the key cannot be found,
258 the pointer passed as 'def' is returned.
259 The returned char pointer is pointing to a string allocated in
260 the dictionary, do not free or modify it.
262 /*--------------------------------------------------------------------------*/
263 char * iniparser_getstring(dictionary * d, char * key, char * def)
265 char * lc_key ;
266 char * sval ;
268 if (d==NULL || key==NULL)
269 return def ;
271 // Check whether the dictionary is case-sensitive
272 if (d->caseSensitive) {
273 lc_key = inistrdup(key);
274 } else {
275 lc_key = inistrdup(inistrlwc(key));
277 sval = dictionary_get(d, lc_key, def);
278 free(lc_key);
279 return sval ;
282 /*-------------------------------------------------------------------------*/
284 @brief Copy the string associated to a key
285 @param d Dictionary to search
286 @param key Key string to look for
287 @param target target address to copy to
288 @param def Default value if key not found, which can be the same pointer as target
289 @param maxLen Maximum length of target
291 This function queries a dictionary for a key. A key as read from an
292 ini file is given as "section:key".
293 The dictionary content for the key will be copied into target for maxLen.
294 If the key cannot be found, the content in 'def' will be copied instead.
295 def can be the same pointer as target.
297 /*--------------------------------------------------------------------------*/
298 void iniparser_copystring(dictionary * d, char * key, char *target, char * def, int maxLen)
300 char * lc_key ;
301 char * sval ;
303 if (d==NULL || key==NULL)
304 return;
306 // Check whether the dictionary is case-sensitive
307 if (d->caseSensitive) {
308 lc_key = inistrdup(key);
309 } else {
310 lc_key = inistrdup(inistrlwc(key));
312 sval = dictionary_get(d, lc_key, def);
313 free(lc_key);
315 if (target != sval) {
316 strncpy(target, sval, maxLen);
317 target[maxLen] = '\0';
325 /*-------------------------------------------------------------------------*/
327 @brief Get the string associated to a key, convert to an int
328 @param d Dictionary to search
329 @param key Key string to look for
330 @param notfound Value to return in case of error
331 @return integer
333 This function queries a dictionary for a key. A key as read from an
334 ini file is given as "section:key". If the key cannot be found,
335 the notfound value is returned.
337 /*--------------------------------------------------------------------------*/
338 int iniparser_getint(dictionary * d, char * key, int notfound)
340 char * str ;
342 str = iniparser_getstring(d, key, INI_INVALID_KEY);
343 if (str==INI_INVALID_KEY) return notfound ;
344 return atoi(str);
347 /*-------------------------------------------------------------------------*/
349 @brief Get the string associated to a key, convert to an unsigned int
350 @param d Dictionary to search
351 @param key Key string to look for
352 @param notfound Value to return in case of error
353 @return unsigned integer
355 This function queries a dictionary for a key. A key as read from an
356 ini file is given as "section:key". If the key cannot be found,
357 the notfound value is returned.
359 /*--------------------------------------------------------------------------*/
360 unsigned int iniparser_getuint(dictionary * d, char * key, int notfound)
362 char * str ;
363 char * stopstr;
365 str = iniparser_getstring(d, key, INI_INVALID_KEY);
366 if (str==INI_INVALID_KEY) return notfound ;
367 return strtoul(str, &stopstr, 10);
372 /*-------------------------------------------------------------------------*/
374 @brief Get the string associated to a key, convert to a double
375 @param d Dictionary to search
376 @param key Key string to look for
377 @param notfound Value to return in case of error
378 @return double
380 This function queries a dictionary for a key. A key as read from an
381 ini file is given as "section:key". If the key cannot be found,
382 the notfound value is returned.
384 /*--------------------------------------------------------------------------*/
385 double iniparser_getdouble(dictionary * d, char * key, double notfound)
387 char * str ;
389 str = iniparser_getstring(d, key, INI_INVALID_KEY);
390 if (str==INI_INVALID_KEY) return notfound ;
391 return atof(str);
396 /*-------------------------------------------------------------------------*/
398 @brief Get the string associated to a key, convert to a boolean
399 @param d Dictionary to search
400 @param key Key string to look for
401 @param notfound Value to return in case of error
402 @return integer
404 This function queries a dictionary for a key. A key as read from an
405 ini file is given as "section:key". If the key cannot be found,
406 the notfound value is returned.
408 A true boolean is found if one of the following is matched:
410 - A string starting with 'y'
411 - A string starting with 'Y'
412 - A string starting with 't'
413 - A string starting with 'T'
414 - A string starting with '1'
416 A false boolean is found if one of the following is matched:
418 - A string starting with 'n'
419 - A string starting with 'N'
420 - A string starting with 'f'
421 - A string starting with 'F'
422 - A string starting with '0'
424 The notfound value returned if no boolean is identified, does not
425 necessarily have to be 0 or 1.
427 /*--------------------------------------------------------------------------*/
428 int iniparser_getboolean(dictionary * d, char * key, int notfound)
430 char * c ;
431 int ret ;
433 c = iniparser_getstring(d, key, INI_INVALID_KEY);
434 if (c==INI_INVALID_KEY) return notfound ;
435 if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
436 ret = 1 ;
437 } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
438 ret = 0 ;
439 } else {
440 ret = notfound ;
442 return ret;
446 /*-------------------------------------------------------------------------*/
448 @brief Finds out if a given entry exists in a dictionary
449 @param ini Dictionary to search
450 @param entry Name of the entry to look for
451 @return integer 1 if entry exists, 0 otherwise
453 Finds out if a given entry exists in the dictionary. Since sections
454 are stored as keys with NULL associated values, this is the only way
455 of querying for the presence of sections in a dictionary.
457 /*--------------------------------------------------------------------------*/
459 int iniparser_find_entry(
460 dictionary * ini,
461 char * entry
464 int found=0 ;
465 if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
466 found = 1 ;
468 return found ;
473 /*-------------------------------------------------------------------------*/
475 @brief Set an entry in a dictionary.
476 @param ini Dictionary to modify.
477 @param entry Entry to modify (entry name)
478 @param val New value to associate to the entry.
479 @return int 0 if Ok, -1 otherwise.
481 If the given entry can be found in the dictionary, it is modified to
482 contain the provided value. If it cannot be found, -1 is returned.
483 It is Ok to set val to NULL.
485 /*--------------------------------------------------------------------------*/
487 int iniparser_setstr(dictionary * ini, char * entry, char * val)
489 // Check whether the dictionary is case-sensitive
490 if (ini->caseSensitive) {
491 dictionary_set(ini, entry, val);
492 } else {
493 dictionary_set(ini, inistrlwc(entry), val);
496 return 0 ;
499 /*-------------------------------------------------------------------------*/
501 @brief Delete an entry in a dictionary
502 @param ini Dictionary to modify
503 @param entry Entry to delete (entry name)
504 @return void
506 If the given entry can be found, it is deleted from the dictionary.
508 /*--------------------------------------------------------------------------*/
509 void iniparser_unset(dictionary * ini, char * entry)
511 // Check whether the dictionary is case-sensitive
512 if (ini->caseSensitive) {
513 dictionary_unset(ini, entry);
514 } else {
515 dictionary_unset(ini, inistrlwc(entry));
521 /*-------------------------------------------------------------------------*/
523 @brief Parse an ini file and return an allocated dictionary object
524 @param ininame Name of the ini file to read.
525 @return Pointer to newly allocated dictionary
527 This is the parser for ini files. This function is called, providing
528 the name of the file to be read. It returns a dictionary object that
529 should not be accessed directly, but through accessor functions
530 instead.
532 The returned dictionary must be freed using iniparser_freedict().
534 /*--------------------------------------------------------------------------*/
536 dictionary * iniparser_load(char * ininame, int caseSensitive)
538 dictionary * d ;
539 char lin[ASCIILINESZ+1];
540 char sec[ASCIILINESZ+1];
541 char key[ASCIILINESZ+1];
542 char val[ASCIILINESZ+1];
543 char * where ;
544 FILE * ini ;
545 int lineno ;
547 if ((ini=fopen(ininame, "r"))==NULL) {
548 return NULL ;
551 sec[0]=0;
554 * Initialize a new dictionary entry
556 d = dictionary_new(0, caseSensitive); // Added case sensitive setting;
557 //d = dictionary_new(0);
558 lineno = 0 ;
559 while (fgets(lin, ASCIILINESZ, ini)!=NULL) {
560 lineno++ ;
561 where = inistrskp(lin); /* Skip leading spaces */
562 if (*where==';' || *where=='#' || *where==0)
563 continue ; /* Comment lines */
564 else {
565 if (sscanf(where, "[%[^]]", sec)==1) {
566 /* Valid section name */
567 if (caseSensitive) {
568 strcpy(sec, sec);
569 } else {
570 strcpy(sec, inistrlwc(sec));
572 iniparser_add_entry(d, sec, NULL, NULL);
573 } else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2
574 || sscanf (where, "%[^=] = '%[^\']'", key, val) == 2
575 || sscanf (where, "%[^=] = %[^;#]", key, val) == 2) {
576 if (caseSensitive) {
577 strcpy(key, inistrcrop(key));
578 } else {
579 strcpy(key, inistrlwc(inistrcrop(key)));
582 * sscanf cannot handle "" or '' as empty value,
583 * this is done here
585 if (!strcmp(val, "\"\"") || !strcmp(val, "''")) {
586 val[0] = (char)0;
587 } else {
588 strcpy(val, inistrcrop(val));
590 iniparser_add_entry(d, sec, key, val);
594 fclose(ini);
595 return d ;
600 /*-------------------------------------------------------------------------*/
602 @brief Free all memory associated to an ini dictionary
603 @param d Dictionary to free
604 @return void
606 Free all memory associated to an ini dictionary.
607 It is mandatory to call this function before the dictionary object
608 gets out of the current context.
610 /*--------------------------------------------------------------------------*/
612 void iniparser_freedict(dictionary * d)
614 dictionary_del(d);
617 /* vim: set ts=4 et sw=4 tw=75 */
620 dictionary * paraparser_load(int argc, char *argv[], int booleanc, char *booleanv[])
622 dictionary *d;
623 int i, j;
624 int booleanParameter;
625 char trueValue[2];
626 char argumentNumber[3];
629 * Initialize a new dictionary entry
631 d = dictionary_new(0, 1); // Case sensitive
633 argumentNumber[0] = '0';
634 argumentNumber[1] = '\0';
635 argumentNumber[2] = '\0';
637 trueValue[0] = 'Y';
638 trueValue[1] = '\0';
640 for(i=0;i<argc;i++) {
641 if (*argv[i] == '-') {
642 if (*(argv[i]+1) != '\0') {
643 // check if it is a boolean parameters
644 booleanParameter = 0;
645 for (j=0; j<booleanc; j++) {
646 if (strcmp(argv[i], booleanv[j]) == 0) {
647 booleanParameter = 1;
648 break;
651 if (booleanParameter == 1) {
652 iniparser_add_entry(d, "parameter", argv[i], trueValue);
653 } else {
654 if (i+1 >= argc) {
655 // invalid input! Do nothing!
656 } else {
657 iniparser_add_entry(d, "parameter", argv[i], argv[i+1]);
658 i++;
662 } else {
663 iniparser_add_entry(d, "argument", argumentNumber, argv[i]);
664 if (argumentNumber[1] != '\0') {
665 if (argumentNumber[1] == '9') {
666 if (argumentNumber[0] == '9') {
667 break;
668 } else {
669 argumentNumber[0]++;
670 argumentNumber[1] = '0';
672 } else {
673 argumentNumber[1]++;
675 } else {
676 if (argumentNumber[0] == '9') {
677 argumentNumber[0] = '1';
678 argumentNumber[1] = '0';
679 } else {
680 argumentNumber[0]++;
686 return d ;
691 /*-------------------------------------------------------------------------*/
693 @brief Return the dictionary entry for an argument
694 @param dictionary, argument number
695 @return dictionary entry
697 Return the dictionary entry for an argument.
698 Used for looping on variable argument list.
700 /*--------------------------------------------------------------------------*/
702 char* paraparser_argument(dictionary *d, int argumentNumber)
704 int i ;
705 int foundsec ;
707 if (d==NULL || argumentNumber<0) return NULL ;
708 foundsec=0 ;
709 for (i=0 ; i<d->size ; i++) {
710 if (d->key[i]==NULL)
711 continue ;
712 if (strncmp(d->key[i], "argument:", 9)==0) {
713 foundsec++ ;
714 if (foundsec>argumentNumber)
715 break ;
718 if (foundsec<=argumentNumber) {
719 return NULL ;
721 return d->key[i] ;
724 /*-------------------------------------------------------------------------*/
726 @brief Get number of argument in a dictionary
727 @param d Dictionary to examine
728 @return int Number of argument found in dictionary
730 This function returns the number of argument found in a dictionary.
731 This function returns -1 in case of error.
733 /*--------------------------------------------------------------------------*/
735 int paraparser_getnargument(dictionary * d)
737 int i ;
738 int nsec ;
740 if (d==NULL) return -1 ;
741 nsec=0 ;
742 for (i=0 ; i<d->size ; i++) {
743 if (d->key[i]==NULL)
744 continue ;
745 if (strncmp(d->key[i], "argument:", 9)==0) {
746 nsec ++ ;
749 return nsec ;