|
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 */ |