Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(485)

Side by Side Diff: third_party/mozprocess/tests/iniparser/iniparser.c

Issue 108313011: Adding mozilla libraries required by Firefox interop test. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1
2 /*-------------------------------------------------------------------------*/
3 /**
4 @file iniparser.c
5 @author N. Devillard
6 @date Sep 2007
7 @version 3.0
8 @brief Parser for ini files.
9 */
10 /*--------------------------------------------------------------------------*/
11 /*
12 $Id: iniparser.c,v 2.19 2011-03-02 20:15:13 ndevilla Exp $
13 $Revision: 2.19 $
14 $Date: 2011-03-02 20:15:13 $
15 */
16 /*---------------------------- Includes ------------------------------------*/
17 #include <ctype.h>
18 #include "iniparser.h"
19
20 /*---------------------------- Defines -------------------------------------*/
21 #define ASCIILINESZ (1024)
22 #define INI_INVALID_KEY ((char*)-1)
23
24 /*---------------------------------------------------------------------------
25 Private to this module
26 ---------------------------------------------------------------------------*/
27 /**
28 * This enum stores the status for each parsed line (internal use only).
29 */
30 typedef enum _line_status_ {
31 LINE_UNPROCESSED,
32 LINE_ERROR,
33 LINE_EMPTY,
34 LINE_COMMENT,
35 LINE_SECTION,
36 LINE_VALUE
37 } line_status ;
38
39 /*-------------------------------------------------------------------------*/
40 /**
41 @brief Convert a string to lowercase.
42 @param s String to convert.
43 @return ptr to statically allocated string.
44
45 This function returns a pointer to a statically allocated string
46 containing a lowercased version of the input string. Do not free
47 or modify the returned string! Since the returned string is statically
48 allocated, it will be modified at each function call (not re-entrant).
49 */
50 /*--------------------------------------------------------------------------*/
51 static char * strlwc(char * s)
52 {
53 static char l[ASCIILINESZ+1];
54 int i ;
55
56 if (s==NULL) return NULL ;
57 memset(l, 0, ASCIILINESZ+1);
58 i=0 ;
59 while (s[i] && i<ASCIILINESZ) {
60 l[i] = (char)tolower((int)s[i]);
61 i++ ;
62 }
63 l[ASCIILINESZ]=(char)0;
64 return l ;
65 }
66
67 /*-------------------------------------------------------------------------*/
68 /**
69 @brief Remove blanks at the beginning and the end of a string.
70 @param s String to parse.
71 @return ptr to statically allocated string.
72
73 This function returns a pointer to a statically allocated string,
74 which is identical to the input string, except that all blank
75 characters at the end and the beg. of the string have been removed.
76 Do not free or modify the returned string! Since the returned string
77 is statically allocated, it will be modified at each function call
78 (not re-entrant).
79 */
80 /*--------------------------------------------------------------------------*/
81 static char * strstrip(char * s)
82 {
83 static char l[ASCIILINESZ+1];
84 char * last ;
85
86 if (s==NULL) return NULL ;
87
88 while (isspace((int)*s) && *s) s++;
89 memset(l, 0, ASCIILINESZ+1);
90 strcpy(l, s);
91 last = l + strlen(l);
92 while (last > l) {
93 if (!isspace((int)*(last-1)))
94 break ;
95 last -- ;
96 }
97 *last = (char)0;
98 return (char*)l ;
99 }
100
101 /*-------------------------------------------------------------------------*/
102 /**
103 @brief Get number of sections in a dictionary
104 @param d Dictionary to examine
105 @return int Number of sections found in dictionary
106
107 This function returns the number of sections found in a dictionary.
108 The test to recognize sections is done on the string stored in the
109 dictionary: a section name is given as "section" whereas a key is
110 stored as "section:key", thus the test looks for entries that do not
111 contain a colon.
112
113 This clearly fails in the case a section name contains a colon, but
114 this should simply be avoided.
115
116 This function returns -1 in case of error.
117 */
118 /*--------------------------------------------------------------------------*/
119 int iniparser_getnsec(dictionary * d)
120 {
121 int i ;
122 int nsec ;
123
124 if (d==NULL) return -1 ;
125 nsec=0 ;
126 for (i=0 ; i<d->size ; i++) {
127 if (d->key[i]==NULL)
128 continue ;
129 if (strchr(d->key[i], ':')==NULL) {
130 nsec ++ ;
131 }
132 }
133 return nsec ;
134 }
135
136 /*-------------------------------------------------------------------------*/
137 /**
138 @brief Get name for section n in a dictionary.
139 @param d Dictionary to examine
140 @param n Section number (from 0 to nsec-1).
141 @return Pointer to char string
142
143 This function locates the n-th section in a dictionary and returns
144 its name as a pointer to a string statically allocated inside the
145 dictionary. Do not free or modify the returned string!
146
147 This function returns NULL in case of error.
148 */
149 /*--------------------------------------------------------------------------*/
150 char * iniparser_getsecname(dictionary * d, int n)
151 {
152 int i ;
153 int foundsec ;
154
155 if (d==NULL || n<0) return NULL ;
156 foundsec=0 ;
157 for (i=0 ; i<d->size ; i++) {
158 if (d->key[i]==NULL)
159 continue ;
160 if (strchr(d->key[i], ':')==NULL) {
161 foundsec++ ;
162 if (foundsec>n)
163 break ;
164 }
165 }
166 if (foundsec<=n) {
167 return NULL ;
168 }
169 return d->key[i] ;
170 }
171
172 /*-------------------------------------------------------------------------*/
173 /**
174 @brief Dump a dictionary to an opened file pointer.
175 @param d Dictionary to dump.
176 @param f Opened file pointer to dump to.
177 @return void
178
179 This function prints out the contents of a dictionary, one element by
180 line, onto the provided file pointer. It is OK to specify @c stderr
181 or @c stdout as output files. This function is meant for debugging
182 purposes mostly.
183 */
184 /*--------------------------------------------------------------------------*/
185 void iniparser_dump(dictionary * d, FILE * f)
186 {
187 int i ;
188
189 if (d==NULL || f==NULL) return ;
190 for (i=0 ; i<d->size ; i++) {
191 if (d->key[i]==NULL)
192 continue ;
193 if (d->val[i]!=NULL) {
194 fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
195 } else {
196 fprintf(f, "[%s]=UNDEF\n", d->key[i]);
197 }
198 }
199 return ;
200 }
201
202 /*-------------------------------------------------------------------------*/
203 /**
204 @brief Save a dictionary to a loadable ini file
205 @param d Dictionary to dump
206 @param f Opened file pointer to dump to
207 @return void
208
209 This function dumps a given dictionary into a loadable ini file.
210 It is Ok to specify @c stderr or @c stdout as output files.
211 */
212 /*--------------------------------------------------------------------------*/
213 void iniparser_dump_ini(dictionary * d, FILE * f)
214 {
215 int i, j ;
216 char keym[ASCIILINESZ+1];
217 int nsec ;
218 char * secname ;
219 int seclen ;
220
221 if (d==NULL || f==NULL) return ;
222
223 nsec = iniparser_getnsec(d);
224 if (nsec<1) {
225 /* No section in file: dump all keys as they are */
226 for (i=0 ; i<d->size ; i++) {
227 if (d->key[i]==NULL)
228 continue ;
229 fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
230 }
231 return ;
232 }
233 for (i=0 ; i<nsec ; i++) {
234 secname = iniparser_getsecname(d, i) ;
235 seclen = (int)strlen(secname);
236 fprintf(f, "\n[%s]\n", secname);
237 sprintf(keym, "%s:", secname);
238 for (j=0 ; j<d->size ; j++) {
239 if (d->key[j]==NULL)
240 continue ;
241 if (!strncmp(d->key[j], keym, seclen+1)) {
242 fprintf(f,
243 "%-30s = %s\n",
244 d->key[j]+seclen+1,
245 d->val[j] ? d->val[j] : "");
246 }
247 }
248 }
249 fprintf(f, "\n");
250 return ;
251 }
252
253 /*-------------------------------------------------------------------------*/
254 /**
255 @brief Get the string associated to a key
256 @param d Dictionary to search
257 @param key Key string to look for
258 @param def Default value to return if key not found.
259 @return pointer to statically allocated character string
260
261 This function queries a dictionary for a key. A key as read from an
262 ini file is given as "section:key". If the key cannot be found,
263 the pointer passed as 'def' is returned.
264 The returned char pointer is pointing to a string allocated in
265 the dictionary, do not free or modify it.
266 */
267 /*--------------------------------------------------------------------------*/
268 char * iniparser_getstring(dictionary * d, char * key, char * def)
269 {
270 char * lc_key ;
271 char * sval ;
272
273 if (d==NULL || key==NULL)
274 return def ;
275
276 lc_key = strlwc(key);
277 sval = dictionary_get(d, lc_key, def);
278 return sval ;
279 }
280
281 /*-------------------------------------------------------------------------*/
282 /**
283 @brief Get the string associated to a key, convert to an int
284 @param d Dictionary to search
285 @param key Key string to look for
286 @param notfound Value to return in case of error
287 @return integer
288
289 This function queries a dictionary for a key. A key as read from an
290 ini file is given as "section:key". If the key cannot be found,
291 the notfound value is returned.
292
293 Supported values for integers include the usual C notation
294 so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
295 are supported. Examples:
296
297 "42" -> 42
298 "042" -> 34 (octal -> decimal)
299 "0x42" -> 66 (hexa -> decimal)
300
301 Warning: the conversion may overflow in various ways. Conversion is
302 totally outsourced to strtol(), see the associated man page for overflow
303 handling.
304
305 Credits: Thanks to A. Becker for suggesting strtol()
306 */
307 /*--------------------------------------------------------------------------*/
308 int iniparser_getint(dictionary * d, char * key, int notfound)
309 {
310 char * str ;
311
312 str = iniparser_getstring(d, key, INI_INVALID_KEY);
313 if (str==INI_INVALID_KEY) return notfound ;
314 return (int)strtol(str, NULL, 0);
315 }
316
317 /*-------------------------------------------------------------------------*/
318 /**
319 @brief Get the string associated to a key, convert to a double
320 @param d Dictionary to search
321 @param key Key string to look for
322 @param notfound Value to return in case of error
323 @return double
324
325 This function queries a dictionary for a key. A key as read from an
326 ini file is given as "section:key". If the key cannot be found,
327 the notfound value is returned.
328 */
329 /*--------------------------------------------------------------------------*/
330 double iniparser_getdouble(dictionary * d, char * key, double notfound)
331 {
332 char * str ;
333
334 str = iniparser_getstring(d, key, INI_INVALID_KEY);
335 if (str==INI_INVALID_KEY) return notfound ;
336 return atof(str);
337 }
338
339 /*-------------------------------------------------------------------------*/
340 /**
341 @brief Get the string associated to a key, convert to a boolean
342 @param d Dictionary to search
343 @param key Key string to look for
344 @param notfound Value to return in case of error
345 @return integer
346
347 This function queries a dictionary for a key. A key as read from an
348 ini file is given as "section:key". If the key cannot be found,
349 the notfound value is returned.
350
351 A true boolean is found if one of the following is matched:
352
353 - A string starting with 'y'
354 - A string starting with 'Y'
355 - A string starting with 't'
356 - A string starting with 'T'
357 - A string starting with '1'
358
359 A false boolean is found if one of the following is matched:
360
361 - A string starting with 'n'
362 - A string starting with 'N'
363 - A string starting with 'f'
364 - A string starting with 'F'
365 - A string starting with '0'
366
367 The notfound value returned if no boolean is identified, does not
368 necessarily have to be 0 or 1.
369 */
370 /*--------------------------------------------------------------------------*/
371 int iniparser_getboolean(dictionary * d, char * key, int notfound)
372 {
373 char * c ;
374 int ret ;
375
376 c = iniparser_getstring(d, key, INI_INVALID_KEY);
377 if (c==INI_INVALID_KEY) return notfound ;
378 if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
379 ret = 1 ;
380 } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
381 ret = 0 ;
382 } else {
383 ret = notfound ;
384 }
385 return ret;
386 }
387
388 /*-------------------------------------------------------------------------*/
389 /**
390 @brief Finds out if a given entry exists in a dictionary
391 @param ini Dictionary to search
392 @param entry Name of the entry to look for
393 @return integer 1 if entry exists, 0 otherwise
394
395 Finds out if a given entry exists in the dictionary. Since sections
396 are stored as keys with NULL associated values, this is the only way
397 of querying for the presence of sections in a dictionary.
398 */
399 /*--------------------------------------------------------------------------*/
400 int iniparser_find_entry(
401 dictionary * ini,
402 char * entry
403 )
404 {
405 int found=0 ;
406 if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
407 found = 1 ;
408 }
409 return found ;
410 }
411
412 /*-------------------------------------------------------------------------*/
413 /**
414 @brief Set an entry in a dictionary.
415 @param ini Dictionary to modify.
416 @param entry Entry to modify (entry name)
417 @param val New value to associate to the entry.
418 @return int 0 if Ok, -1 otherwise.
419
420 If the given entry can be found in the dictionary, it is modified to
421 contain the provided value. If it cannot be found, -1 is returned.
422 It is Ok to set val to NULL.
423 */
424 /*--------------------------------------------------------------------------*/
425 int iniparser_set(dictionary * ini, char * entry, char * val)
426 {
427 return dictionary_set(ini, strlwc(entry), val) ;
428 }
429
430 /*-------------------------------------------------------------------------*/
431 /**
432 @brief Delete an entry in a dictionary
433 @param ini Dictionary to modify
434 @param entry Entry to delete (entry name)
435 @return void
436
437 If the given entry can be found, it is deleted from the dictionary.
438 */
439 /*--------------------------------------------------------------------------*/
440 void iniparser_unset(dictionary * ini, char * entry)
441 {
442 dictionary_unset(ini, strlwc(entry));
443 }
444
445 /*-------------------------------------------------------------------------*/
446 /**
447 @brief Load a single line from an INI file
448 @param input_line Input line, may be concatenated multi-line input
449 @param section Output space to store section
450 @param key Output space to store key
451 @param value Output space to store value
452 @return line_status value
453 */
454 /*--------------------------------------------------------------------------*/
455 static line_status iniparser_line(
456 char * input_line,
457 char * section,
458 char * key,
459 char * value)
460 {
461 line_status sta ;
462 char line[ASCIILINESZ+1];
463 int len ;
464
465 strcpy(line, strstrip(input_line));
466 len = (int)strlen(line);
467
468 sta = LINE_UNPROCESSED ;
469 if (len<1) {
470 /* Empty line */
471 sta = LINE_EMPTY ;
472 } else if (line[0]=='#' || line[0]==';') {
473 /* Comment line */
474 sta = LINE_COMMENT ;
475 } else if (line[0]=='[' && line[len-1]==']') {
476 /* Section name */
477 sscanf(line, "[%[^]]", section);
478 strcpy(section, strstrip(section));
479 strcpy(section, strlwc(section));
480 sta = LINE_SECTION ;
481 } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
482 || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2
483 || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) {
484 /* Usual key=value, with or without comments */
485 strcpy(key, strstrip(key));
486 strcpy(key, strlwc(key));
487 strcpy(value, strstrip(value));
488 /*
489 * sscanf cannot handle '' or "" as empty values
490 * this is done here
491 */
492 if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
493 value[0]=0 ;
494 }
495 sta = LINE_VALUE ;
496 } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
497 || sscanf(line, "%[^=] %[=]", key, value) == 2) {
498 /*
499 * Special cases:
500 * key=
501 * key=;
502 * key=#
503 */
504 strcpy(key, strstrip(key));
505 strcpy(key, strlwc(key));
506 value[0]=0 ;
507 sta = LINE_VALUE ;
508 } else {
509 /* Generate syntax error */
510 sta = LINE_ERROR ;
511 }
512 return sta ;
513 }
514
515 /*-------------------------------------------------------------------------*/
516 /**
517 @brief Parse an ini file and return an allocated dictionary object
518 @param ininame Name of the ini file to read.
519 @return Pointer to newly allocated dictionary
520
521 This is the parser for ini files. This function is called, providing
522 the name of the file to be read. It returns a dictionary object that
523 should not be accessed directly, but through accessor functions
524 instead.
525
526 The returned dictionary must be freed using iniparser_freedict().
527 */
528 /*--------------------------------------------------------------------------*/
529 dictionary * iniparser_load(char * ininame)
530 {
531 FILE * in ;
532
533 char line [ASCIILINESZ+1] ;
534 char section [ASCIILINESZ+1] ;
535 char key [ASCIILINESZ+1] ;
536 char tmp [ASCIILINESZ+1] ;
537 char val [ASCIILINESZ+1] ;
538
539 int last=0 ;
540 int len ;
541 int lineno=0 ;
542 int errs=0;
543
544 dictionary * dict ;
545
546 if ((in=fopen(ininame, "r"))==NULL) {
547 fprintf(stderr, "iniparser: cannot open %s\n", ininame);
548 return NULL ;
549 }
550
551 dict = dictionary_new(0) ;
552 if (!dict) {
553 fclose(in);
554 return NULL ;
555 }
556
557 memset(line, 0, ASCIILINESZ);
558 memset(section, 0, ASCIILINESZ);
559 memset(key, 0, ASCIILINESZ);
560 memset(val, 0, ASCIILINESZ);
561 last=0 ;
562
563 while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
564 lineno++ ;
565 len = (int)strlen(line)-1;
566 if (len==0)
567 continue;
568 /* Safety check against buffer overflows */
569 if (line[len]!='\n') {
570 fprintf(stderr,
571 "iniparser: input line too long in %s (%d)\n",
572 ininame,
573 lineno);
574 dictionary_del(dict);
575 fclose(in);
576 return NULL ;
577 }
578 /* Get rid of \n and spaces at end of line */
579 while ((len>=0) &&
580 ((line[len]=='\n') || (isspace(line[len])))) {
581 line[len]=0 ;
582 len-- ;
583 }
584 /* Detect multi-line */
585 if (line[len]=='\\') {
586 /* Multi-line value */
587 last=len ;
588 continue ;
589 } else {
590 last=0 ;
591 }
592 switch (iniparser_line(line, section, key, val)) {
593 case LINE_EMPTY:
594 case LINE_COMMENT:
595 break ;
596
597 case LINE_SECTION:
598 errs = dictionary_set(dict, section, NULL);
599 break ;
600
601 case LINE_VALUE:
602 sprintf(tmp, "%s:%s", section, key);
603 errs = dictionary_set(dict, tmp, val) ;
604 break ;
605
606 case LINE_ERROR:
607 fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
608 ininame,
609 lineno);
610 fprintf(stderr, "-> %s\n", line);
611 errs++ ;
612 break;
613
614 default:
615 break ;
616 }
617 memset(line, 0, ASCIILINESZ);
618 last=0;
619 if (errs<0) {
620 fprintf(stderr, "iniparser: memory allocation failure\n");
621 break ;
622 }
623 }
624 if (errs) {
625 dictionary_del(dict);
626 dict = NULL ;
627 }
628 fclose(in);
629 return dict ;
630 }
631
632 /*-------------------------------------------------------------------------*/
633 /**
634 @brief Free all memory associated to an ini dictionary
635 @param d Dictionary to free
636 @return void
637
638 Free all memory associated to an ini dictionary.
639 It is mandatory to call this function before the dictionary object
640 gets out of the current context.
641 */
642 /*--------------------------------------------------------------------------*/
643 void iniparser_freedict(dictionary * d)
644 {
645 dictionary_del(d);
646 }
647
648 /* vim: set ts=4 et sw=4 tw=75 */
OLDNEW
« no previous file with comments | « third_party/mozprocess/tests/iniparser/iniparser.h ('k') | third_party/mozprocess/tests/manifest.ini » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698