Lines 1-929
Link Here
|
1 |
/* |
|
|
2 |
Based upon libiniparser, by Nicolas Devillard |
3 |
Hacked into 1 file (m-iniparser) by Freek/2005 |
4 |
Original terms following: |
5 |
|
6 |
-- - |
7 |
|
8 |
Copyright (c) 2000 by Nicolas Devillard (ndevilla AT free DOT fr). |
9 |
|
10 |
Written by Nicolas Devillard. Not derived from licensed software. |
11 |
|
12 |
Permission is granted to anyone to use this software for any |
13 |
purpose on any computer system, and to redistribute it freely, |
14 |
subject to the following restrictions: |
15 |
|
16 |
1. The author is not responsible for the consequences of use of |
17 |
this software, no matter how awful, even if they arise |
18 |
from defects in it. |
19 |
|
20 |
2. The origin of this software must not be misrepresented, either |
21 |
by explicit claim or by omission. |
22 |
|
23 |
3. Altered versions must be plainly marked as such, and must not |
24 |
be misrepresented as being the original software. |
25 |
|
26 |
4. This notice may not be removed or altered. |
27 |
|
28 |
*/ |
29 |
|
30 |
|
31 |
#include <stdio.h> |
32 |
#include <stdlib.h> |
33 |
#include <string.h> |
34 |
#include <unistd.h> |
35 |
|
36 |
#include <sys/types.h> |
37 |
#include <sys/stat.h> |
38 |
#include <fcntl.h> |
39 |
#include <sys/file.h> |
40 |
|
41 |
#include "iniparser.h" |
42 |
|
43 |
#ifdef __cplusplus |
44 |
|
45 |
extern "C" |
46 |
{ |
47 |
#endif |
48 |
|
49 |
/* lock INI file access against concurrent access */ |
50 |
|
51 |
static FileLock* |
52 |
ini_file_lock (const char *fileName, Bool exclusive) |
53 |
{ |
54 |
int fd; |
55 |
FileLock *lock; |
56 |
struct flock lockinfo; |
57 |
|
58 |
if (exclusive) |
59 |
fd = open (fileName, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
60 |
else |
61 |
fd = open (fileName, O_RDONLY | O_CREAT, 0666); |
62 |
if (fd < 0) |
63 |
return NULL; |
64 |
|
65 |
lock = malloc (sizeof (FileLock)); |
66 |
if (!lock) |
67 |
return NULL; |
68 |
|
69 |
lock->fd = fd; |
70 |
memset (&lockinfo, 0, sizeof (struct flock)); |
71 |
|
72 |
if (exclusive) |
73 |
lockinfo.l_type = F_WRLCK; |
74 |
else |
75 |
lockinfo.l_type = F_RDLCK; |
76 |
lockinfo.l_pid = getpid(); |
77 |
fcntl (fd, F_SETLKW, &lockinfo); |
78 |
|
79 |
return lock; |
80 |
} |
81 |
|
82 |
static void |
83 |
ini_file_unlock (FileLock *lock) |
84 |
{ |
85 |
struct flock lockinfo; |
86 |
|
87 |
memset (&lockinfo, 0, sizeof (struct flock)); |
88 |
lockinfo.l_type = F_UNLCK; |
89 |
lockinfo.l_pid = getpid(); |
90 |
|
91 |
fcntl (lock ->fd, F_SETLKW, &lockinfo); |
92 |
close (lock ->fd); |
93 |
free (lock ); |
94 |
} |
95 |
|
96 |
/* strlib.c following */ |
97 |
|
98 |
#define ASCIILINESZ 1024 |
99 |
/*-------------------------------------------------------------------------*/ |
100 |
/** |
101 |
@brief Convert a string to lowercase. |
102 |
@param s String to convert. |
103 |
@return ptr to statically allocated string. |
104 |
|
105 |
This function returns a pointer to a statically allocated string |
106 |
containing a lowercased version of the input string. Do not free |
107 |
or modify the returned string! Since the returned string is statically |
108 |
allocated, it will be modified at each function call (not re-entrant). |
109 |
*/ |
110 |
/*--------------------------------------------------------------------------*/ |
111 |
static char* |
112 |
strlwc (char * s) |
113 |
{ |
114 |
static char l[ASCIILINESZ+1]; |
115 |
int i; |
116 |
|
117 |
if (!s) |
118 |
return NULL; |
119 |
|
120 |
memset (l, 0, ASCIILINESZ + 1); |
121 |
i = 0; |
122 |
|
123 |
while (s[i] && i < ASCIILINESZ) |
124 |
{ |
125 |
l[i] = (char) tolower ((int) s[i]); |
126 |
i++; |
127 |
} |
128 |
|
129 |
l[ASCIILINESZ] = (char) 0; |
130 |
|
131 |
return l; |
132 |
} |
133 |
|
134 |
/*-------------------------------------------------------------------------*/ |
135 |
/** |
136 |
@brief Skip blanks until the first non-blank character. |
137 |
@param s String to parse. |
138 |
@return Pointer to char inside given string. |
139 |
|
140 |
This function returns a pointer to the first non-blank character in the |
141 |
given string. |
142 |
*/ |
143 |
/*--------------------------------------------------------------------------*/ |
144 |
static char* |
145 |
strskp (char * s) |
146 |
{ |
147 |
char * skip = s; |
148 |
|
149 |
if (!s) |
150 |
return NULL; |
151 |
|
152 |
while (isspace ((int) *skip) && *skip) |
153 |
skip++; |
154 |
|
155 |
return skip; |
156 |
} |
157 |
|
158 |
/*-------------------------------------------------------------------------*/ |
159 |
/** |
160 |
@brief Remove blanks at the end of a string. |
161 |
@param s String to parse. |
162 |
@return ptr to statically allocated string. |
163 |
|
164 |
This function returns a pointer to a statically allocated string, |
165 |
which is identical to the input string, except that all blank |
166 |
characters at the end of the string have been removed. |
167 |
Do not free or modify the returned string! Since the returned string |
168 |
is statically allocated, it will be modified at each function call |
169 |
(not re-entrant). |
170 |
*/ |
171 |
/*--------------------------------------------------------------------------*/ |
172 |
static char* |
173 |
strcrop (char * s) |
174 |
{ |
175 |
static char l[ASCIILINESZ+1]; |
176 |
char *last; |
177 |
|
178 |
if (!s) |
179 |
return NULL; |
180 |
|
181 |
memset (l, 0, ASCIILINESZ + 1); |
182 |
strcpy (l, s); |
183 |
|
184 |
last = l + strlen (l); |
185 |
while (last > l) |
186 |
{ |
187 |
if (!isspace ((int) * (last - 1))) |
188 |
break; |
189 |
|
190 |
last --; |
191 |
} |
192 |
|
193 |
*last = (char) 0; |
194 |
return l; |
195 |
} |
196 |
|
197 |
/* dictionary.c.c following */ |
198 |
|
199 |
/** Maximum value size for integers and doubles. */ |
200 |
#define MAXVALSZ 1024 |
201 |
|
202 |
/** Minimal allocated number of entries in a dictionary */ |
203 |
#define DICTMINSZ 128 |
204 |
|
205 |
/** Invalid key token */ |
206 |
#define DICT_INVALID_KEY ((char*)-1) |
207 |
|
208 |
/* |
209 |
Doubles the allocated size associated to a pointer |
210 |
'size' is the current allocated size. |
211 |
*/ |
212 |
static void* |
213 |
mem_double (void * ptr, int size) |
214 |
{ |
215 |
void *newptr; |
216 |
|
217 |
newptr = calloc (2 * size, 1); |
218 |
if (!newptr) |
219 |
return NULL; |
220 |
|
221 |
memcpy (newptr, ptr, size); |
222 |
free (ptr); |
223 |
return newptr; |
224 |
} |
225 |
|
226 |
/*--------------------------------------------------------------------------- |
227 |
Function codes |
228 |
---------------------------------------------------------------------------*/ |
229 |
|
230 |
/*-------------------------------------------------------------------------*/ |
231 |
/** |
232 |
@brief Compute the hash key for a string. |
233 |
@param key Character string to use for key. |
234 |
@return 1 unsigned int on at least 32 bits. |
235 |
|
236 |
This hash function has been taken from an Article in Dr Dobbs Journal. |
237 |
This is normally a collision-free function, distributing keys evenly. |
238 |
The key is stored anyway in the struct so that collision can be avoided |
239 |
by comparing the key itself in last resort. |
240 |
*/ |
241 |
/*--------------------------------------------------------------------------*/ |
242 |
static unsigned dictionary_hash (char * key) |
243 |
{ |
244 |
int len; |
245 |
unsigned hash; |
246 |
int i; |
247 |
|
248 |
len = strlen (key); |
249 |
|
250 |
for (hash = 0, i = 0; i < len; i++) |
251 |
{ |
252 |
hash += (unsigned) key[i]; |
253 |
hash += (hash << 10); |
254 |
hash ^= (hash >> 6); |
255 |
} |
256 |
|
257 |
hash += (hash << 3); |
258 |
|
259 |
hash ^= (hash >> 11); |
260 |
hash += (hash << 15); |
261 |
return hash; |
262 |
} |
263 |
|
264 |
/*-------------------------------------------------------------------------*/ |
265 |
/** |
266 |
@brief Create a new dictionary object. |
267 |
@param size Optional initial size of the dictionary. |
268 |
@return 1 newly allocated dictionary objet. |
269 |
|
270 |
This function allocates a new dictionary object of given size and returns |
271 |
it. If you do not know in advance (roughly) the number of entries in the |
272 |
dictionary, give size=0. |
273 |
*/ |
274 |
/*--------------------------------------------------------------------------*/ |
275 |
dictionary* |
276 |
dictionary_new (int size) |
277 |
{ |
278 |
dictionary *d; |
279 |
|
280 |
/* If no size was specified, allocate space for DICTMINSZ */ |
281 |
if (size < DICTMINSZ) |
282 |
size = DICTMINSZ; |
283 |
|
284 |
d = (dictionary *) calloc (1, sizeof (dictionary)); |
285 |
if (!d) |
286 |
return NULL; |
287 |
|
288 |
d->size = size; |
289 |
d->val = (char **) calloc (size, sizeof (char*)); |
290 |
if (!d->val) |
291 |
{ |
292 |
free (d); |
293 |
return NULL; |
294 |
} |
295 |
|
296 |
d->key = (char **) calloc (size, sizeof (char*)); |
297 |
if (!d->key) |
298 |
{ |
299 |
free (d->val); |
300 |
free (d); |
301 |
return NULL; |
302 |
} |
303 |
|
304 |
d->hash = (unsigned int *) calloc (size, sizeof (unsigned)); |
305 |
if (!d->hash) |
306 |
{ |
307 |
free (d->key); |
308 |
free (d->val); |
309 |
free (d); |
310 |
return NULL; |
311 |
} |
312 |
|
313 |
return d; |
314 |
} |
315 |
|
316 |
/*-------------------------------------------------------------------------*/ |
317 |
/** |
318 |
@brief Delete a dictionary object |
319 |
@param d dictionary object to deallocate. |
320 |
@return void |
321 |
|
322 |
Deallocate a dictionary object and all memory associated to it. |
323 |
*/ |
324 |
/*--------------------------------------------------------------------------*/ |
325 |
static void |
326 |
dictionary_del (dictionary * d) |
327 |
{ |
328 |
int i; |
329 |
|
330 |
if (!d) |
331 |
return; |
332 |
|
333 |
for (i = 0; i < d->size; i++) |
334 |
{ |
335 |
if (d->key[i]) |
336 |
free (d->key[i]); |
337 |
|
338 |
if (d->val[i]) |
339 |
free (d->val[i]); |
340 |
} |
341 |
|
342 |
free (d->val); |
343 |
free (d->key); |
344 |
free (d->hash); |
345 |
free (d); |
346 |
|
347 |
return; |
348 |
} |
349 |
|
350 |
/*-------------------------------------------------------------------------*/ |
351 |
/** |
352 |
@brief Get a value from a dictionary. |
353 |
@param d dictionary object to search. |
354 |
@param key Key to look for in the dictionary. |
355 |
@param def Default value to return if key not found. |
356 |
@return 1 pointer to internally allocated character string. |
357 |
|
358 |
This function locates a key in a dictionary and returns a pointer to its |
359 |
value, or the passed 'def' pointer if no such key can be found in |
360 |
dictionary. The returned character pointer points to data internal to the |
361 |
dictionary object, you should not try to free it or modify it. |
362 |
*/ |
363 |
/*--------------------------------------------------------------------------*/ |
364 |
static char* |
365 |
dictionary_get (dictionary * d, char * key, char * def) |
366 |
{ |
367 |
unsigned hash; |
368 |
int i; |
369 |
|
370 |
hash = dictionary_hash (key); |
371 |
|
372 |
for (i = 0; i < d->size; i++) |
373 |
{ |
374 |
if (!d->key) |
375 |
continue; |
376 |
|
377 |
/* Compare hash */ |
378 |
if (hash == d->hash[i]) |
379 |
{ |
380 |
/* Compare string, to avoid hash collisions */ |
381 |
if (!strcmp (key, d->key[i])) |
382 |
{ |
383 |
return d->val[i]; |
384 |
} |
385 |
} |
386 |
} |
387 |
|
388 |
return def; |
389 |
} |
390 |
|
391 |
|
392 |
/*-------------------------------------------------------------------------*/ |
393 |
/** |
394 |
@brief Set a value in a dictionary. |
395 |
@param d dictionary object to modify. |
396 |
@param key Key to modify or add. |
397 |
@param val Value to add. |
398 |
@return void |
399 |
|
400 |
If the given key is found in the dictionary, the associated value is |
401 |
replaced by the provided one. If the key cannot be found in the |
402 |
dictionary, it is added to it. |
403 |
|
404 |
It is Ok to provide a NULL value for val, but NULL values for the dictionary |
405 |
or the key are considered as errors: the function will return immediately |
406 |
in such a case. |
407 |
|
408 |
Notice that if you dictionary_set a variable to NULL, a call to |
409 |
dictionary_get will return a NULL value: the variable will be found, and |
410 |
its value (NULL) is returned. In other words, setting the variable |
411 |
content to NULL is equivalent to deleting the variable from the |
412 |
dictionary. It is not possible (in this implementation) to have a key in |
413 |
the dictionary without value. |
414 |
*/ |
415 |
/*--------------------------------------------------------------------------*/ |
416 |
static void |
417 |
dictionary_set (dictionary * d, char * key, char * val) |
418 |
{ |
419 |
int i; |
420 |
unsigned hash; |
421 |
|
422 |
if (!d || !key) |
423 |
return; |
424 |
|
425 |
/* Compute hash for this key */ |
426 |
hash = dictionary_hash (key); |
427 |
|
428 |
/* Find if value is already in blackboard */ |
429 |
if (d->n > 0) |
430 |
{ |
431 |
for (i = 0; i < d->size; i++) |
432 |
{ |
433 |
if (!d->key[i]) |
434 |
continue; |
435 |
|
436 |
if (hash == d->hash[i]) |
437 |
{ |
438 |
/* Same hash value */ |
439 |
if (!strcmp (key, d->key[i])) |
440 |
{ |
441 |
/* Same key */ |
442 |
/* Found a value: modify and return */ |
443 |
if (d->val[i]) |
444 |
free (d->val[i]); |
445 |
|
446 |
d->val[i] = val ? strdup (val) : NULL; |
447 |
/* Value has been modified: return */ |
448 |
return; |
449 |
} |
450 |
} |
451 |
} |
452 |
} |
453 |
|
454 |
/* Add a new value */ |
455 |
/* See if dictionary needs to grow */ |
456 |
if (d->n == d->size) |
457 |
{ |
458 |
/* Reached maximum size: reallocate blackboard */ |
459 |
d->val = (char **) mem_double (d->val, d->size * sizeof (char*)); |
460 |
d->key = (char **) mem_double (d->key, d->size * sizeof (char*)); |
461 |
d->hash = (unsigned int *) mem_double (d->hash, |
462 |
d->size * sizeof (unsigned)); |
463 |
|
464 |
/* Double size */ |
465 |
d->size *= 2; |
466 |
} |
467 |
|
468 |
/* Insert key in the first empty slot */ |
469 |
for (i = 0; i < d->size; i++) |
470 |
{ |
471 |
if (!d->key[i]) |
472 |
{ |
473 |
/* Add key here */ |
474 |
break; |
475 |
} |
476 |
} |
477 |
|
478 |
/* Copy key */ |
479 |
d->key[i] = strdup (key); |
480 |
d->val[i] = val ? strdup (val) : NULL; |
481 |
d->hash[i] = hash; |
482 |
d->n++; |
483 |
} |
484 |
|
485 |
/*-------------------------------------------------------------------------*/ |
486 |
/** |
487 |
@brief Delete a key in a dictionary |
488 |
@param d dictionary object to modify. |
489 |
@param key Key to remove. |
490 |
@return void |
491 |
|
492 |
This function deletes a key in a dictionary. Nothing is done if the |
493 |
key cannot be found. |
494 |
*/ |
495 |
/*--------------------------------------------------------------------------*/ |
496 |
static void |
497 |
dictionary_unset (dictionary * d, char * key) |
498 |
{ |
499 |
unsigned hash; |
500 |
int i; |
501 |
|
502 |
hash = dictionary_hash (key); |
503 |
|
504 |
for (i = 0; i < d->size; i++) |
505 |
{ |
506 |
if (!d->key[i]) |
507 |
continue; |
508 |
|
509 |
/* Compare hash */ |
510 |
if (hash == d->hash[i]) |
511 |
{ |
512 |
/* Compare string, to avoid hash collisions */ |
513 |
if (!strcmp (key, d->key[i])) |
514 |
{ |
515 |
/* Found key */ |
516 |
break; |
517 |
} |
518 |
} |
519 |
} |
520 |
|
521 |
if (i >= d->size) |
522 |
/* Key not found */ |
523 |
return; |
524 |
|
525 |
free (d->key[i]); |
526 |
|
527 |
d->key[i] = NULL; |
528 |
if (d->val[i]) |
529 |
{ |
530 |
free (d->val[i]); |
531 |
d->val[i] = NULL; |
532 |
} |
533 |
|
534 |
d->hash[i] = 0; |
535 |
d->n --; |
536 |
} |
537 |
|
538 |
/* iniparser.c.c following */ |
539 |
#define ASCIILINESZ 1024 |
540 |
#define INI_INVALID_KEY ((char*)-1) |
541 |
|
542 |
/* Private: add an entry to the dictionary */ |
543 |
void |
544 |
iniparser_add_entry (dictionary * d, |
545 |
char * sec, |
546 |
char * key, |
547 |
char * val) |
548 |
{ |
549 |
char longkey[2*ASCIILINESZ+1]; |
550 |
|
551 |
/* Make a key as section:keyword */ |
552 |
|
553 |
if (key) |
554 |
sprintf (longkey, "%s:%s", sec, key); |
555 |
else |
556 |
strcpy (longkey, sec); |
557 |
|
558 |
/* Add (key,val) to dictionary */ |
559 |
dictionary_set (d, longkey, val); |
560 |
} |
561 |
|
562 |
/*-------------------------------------------------------------------------*/ |
563 |
/** |
564 |
@brief Get number of sections in a dictionary |
565 |
@param d Dictionary to examine |
566 |
@return int Number of sections found in dictionary |
567 |
|
568 |
This function returns the number of sections found in a dictionary. |
569 |
The test to recognize sections is done on the string stored in the |
570 |
dictionary: a section name is given as "section" whereas a key is |
571 |
stored as "section:key", thus the test looks for entries that do not |
572 |
contain a colon. |
573 |
|
574 |
This clearly fails in the case a section name contains a colon, but |
575 |
this should simply be avoided. |
576 |
|
577 |
This function returns -1 in case of error. |
578 |
*/ |
579 |
/*--------------------------------------------------------------------------*/ |
580 |
int |
581 |
iniparser_getnsec (dictionary * d) |
582 |
{ |
583 |
int i; |
584 |
int nsec; |
585 |
|
586 |
if (!d) |
587 |
return -1; |
588 |
|
589 |
nsec = 0; |
590 |
for (i = 0; i < d->size; i++) |
591 |
{ |
592 |
if (!d->key[i]) |
593 |
continue; |
594 |
|
595 |
if (!strchr (d->key[i], ':')) |
596 |
nsec++; |
597 |
} |
598 |
|
599 |
return nsec; |
600 |
} |
601 |
|
602 |
/*-------------------------------------------------------------------------*/ |
603 |
/** |
604 |
@brief Get name for section n in a dictionary. |
605 |
@param d Dictionary to examine |
606 |
@param n Section number (from 0 to nsec-1). |
607 |
@return Pointer to char string |
608 |
|
609 |
This function locates the n-th section in a dictionary and returns |
610 |
its name as a pointer to a string statically allocated inside the |
611 |
dictionary. Do not free or modify the returned string! |
612 |
|
613 |
This function returns NULL in case of error. |
614 |
*/ |
615 |
/*--------------------------------------------------------------------------*/ |
616 |
char* |
617 |
iniparser_getsecname (dictionary * d, int n) |
618 |
{ |
619 |
int i; |
620 |
int foundsec; |
621 |
|
622 |
if (!d || n < 0) |
623 |
return NULL; |
624 |
|
625 |
foundsec = 0; |
626 |
for (i = 0; i < d->size; i++) |
627 |
{ |
628 |
if (!d->key[i]) |
629 |
continue; |
630 |
|
631 |
if (!strchr (d->key[i], ':')) |
632 |
{ |
633 |
foundsec++; |
634 |
if (foundsec > n) |
635 |
break; |
636 |
} |
637 |
} |
638 |
|
639 |
if (foundsec <= n) |
640 |
return NULL; |
641 |
|
642 |
return d->key[i]; |
643 |
} |
644 |
|
645 |
/*-------------------------------------------------------------------------*/ |
646 |
/** |
647 |
@brief Save a dictionary to a loadable ini file |
648 |
@param d Dictionary to dump |
649 |
@param f Opened file pointer to dump to |
650 |
@return void |
651 |
|
652 |
This function dumps a given dictionary into a loadable ini file. |
653 |
It is Ok to specify @c stderr or @c stdout as output files. |
654 |
*/ |
655 |
/*--------------------------------------------------------------------------*/ |
656 |
void |
657 |
iniparser_dump_ini (dictionary * d, const char * file_name) |
658 |
{ |
659 |
int i, j; |
660 |
char keym[ASCIILINESZ+1]; |
661 |
int nsec; |
662 |
char * secname; |
663 |
int seclen; |
664 |
FILE * f; |
665 |
FileLock *lock; |
666 |
|
667 |
if (!d) |
668 |
return; |
669 |
|
670 |
lock = ini_file_lock (file_name, TRUE); |
671 |
if (!lock) |
672 |
return; |
673 |
|
674 |
f = fdopen (lock->fd, "w"); |
675 |
if (!f) |
676 |
{ |
677 |
ini_file_unlock (lock); |
678 |
return; |
679 |
} |
680 |
|
681 |
nsec = iniparser_getnsec (d); |
682 |
if (nsec < 1) |
683 |
{ |
684 |
/* No section in file: dump all keys as they are */ |
685 |
for (i = 0; i < d->size; i++) |
686 |
{ |
687 |
if (!d->key[i]) |
688 |
continue; |
689 |
fprintf (f, "%s = %s\n", d->key[i], d->val[i]); |
690 |
} |
691 |
|
692 |
fflush (f); |
693 |
ini_file_unlock (lock); |
694 |
return; |
695 |
} |
696 |
|
697 |
for (i = 0; i < nsec; i++) |
698 |
{ |
699 |
secname = iniparser_getsecname (d, i); |
700 |
seclen = (int) strlen (secname); |
701 |
fprintf (f, "[%s]\n", secname); |
702 |
sprintf (keym, "%s:", secname); |
703 |
|
704 |
for (j = 0; j < d->size; j++) |
705 |
{ |
706 |
if (!d->key[j]) |
707 |
continue; |
708 |
|
709 |
if (!strncmp (d->key[j], keym, seclen + 1)) |
710 |
{ |
711 |
fprintf (f, "%s = %s\n", |
712 |
d->key[j] + seclen + 1, |
713 |
d->val[j] ? d->val[j] : ""); |
714 |
} |
715 |
} |
716 |
|
717 |
fprintf (f, "\n"); |
718 |
} |
719 |
|
720 |
fflush (f); |
721 |
ini_file_unlock (lock ); |
722 |
} |
723 |
|
724 |
/*-------------------------------------------------------------------------*/ |
725 |
/** |
726 |
@brief Get the string associated to a key |
727 |
@param d Dictionary to search |
728 |
@param key Key string to look for |
729 |
@param def Default value to return if key not found. |
730 |
@return pointer to statically allocated character string |
731 |
|
732 |
This function queries a dictionary for a key. A key as read from an |
733 |
ini file is given as "section:key". If the key cannot be found, |
734 |
the pointer passed as 'def' is returned. |
735 |
The returned char pointer is pointing to a string allocated in |
736 |
the dictionary, do not free or modify it. |
737 |
*/ |
738 |
/*--------------------------------------------------------------------------*/ |
739 |
char* |
740 |
iniparser_getstring (dictionary * d, char * key, char * def) |
741 |
{ |
742 |
char * lc_key; |
743 |
char * sval; |
744 |
|
745 |
if (!d || !key) |
746 |
return def; |
747 |
|
748 |
lc_key = strdup (strlwc (key)); |
749 |
sval = dictionary_get (d, lc_key, def); |
750 |
free (lc_key); |
751 |
|
752 |
return sval; |
753 |
} |
754 |
|
755 |
/*-------------------------------------------------------------------------*/ |
756 |
/** |
757 |
@brief Finds out if a given entry exists in a dictionary |
758 |
@param ini Dictionary to search |
759 |
@param entry Name of the entry to look for |
760 |
@return integer 1 if entry exists, 0 otherwise |
761 |
|
762 |
Finds out if a given entry exists in the dictionary. Since sections |
763 |
are stored as keys with NULL associated values, this is the only way |
764 |
of querying for the presence of sections in a dictionary. |
765 |
*/ |
766 |
/*--------------------------------------------------------------------------*/ |
767 |
int |
768 |
iniparser_find_entry (dictionary *ini, char *entry) |
769 |
{ |
770 |
int found = 0; |
771 |
|
772 |
if (iniparser_getstring (ini, entry, INI_INVALID_KEY) != INI_INVALID_KEY) |
773 |
{ |
774 |
found = 1; |
775 |
} |
776 |
|
777 |
return found; |
778 |
} |
779 |
|
780 |
/*-------------------------------------------------------------------------*/ |
781 |
/** |
782 |
@brief Set an entry in a dictionary. |
783 |
@param ini Dictionary to modify. |
784 |
@param entry Entry to modify (entry name) |
785 |
@param val New value to associate to the entry. |
786 |
@return int 0 if Ok, -1 otherwise. |
787 |
|
788 |
If the given entry can be found in the dictionary, it is modified to |
789 |
contain the provided value. If it cannot be found, -1 is returned. |
790 |
It is Ok to set val to NULL. |
791 |
*/ |
792 |
/*--------------------------------------------------------------------------*/ |
793 |
int |
794 |
iniparser_setstr (dictionary * ini, char * entry, char * val) |
795 |
{ |
796 |
dictionary_set (ini, strlwc (entry), val); |
797 |
return 0; |
798 |
} |
799 |
|
800 |
/*-------------------------------------------------------------------------*/ |
801 |
/** |
802 |
@brief Delete an entry in a dictionary |
803 |
@param ini Dictionary to modify |
804 |
@param entry Entry to delete (entry name) |
805 |
@return void |
806 |
|
807 |
If the given entry can be found, it is deleted from the dictionary. |
808 |
*/ |
809 |
/*--------------------------------------------------------------------------*/ |
810 |
void |
811 |
iniparser_unset (dictionary * ini, char * entry) |
812 |
{ |
813 |
dictionary_unset (ini, strlwc (entry)); |
814 |
} |
815 |
|
816 |
/*-------------------------------------------------------------------------*/ |
817 |
/** |
818 |
@brief Parse an ini file and return an allocated dictionary object |
819 |
@param ininame Name of the ini file to read. |
820 |
@return Pointer to newly allocated dictionary |
821 |
|
822 |
This is the parser for ini files. This function is called, providing |
823 |
the name of the file to be read. It returns a dictionary object that |
824 |
should not be accessed directly, but through accessor functions |
825 |
instead. |
826 |
|
827 |
The returned dictionary must be freed using iniparser_free(). |
828 |
*/ |
829 |
/*--------------------------------------------------------------------------*/ |
830 |
dictionary* |
831 |
iniparser_new (char *ininame) |
832 |
{ |
833 |
dictionary * d; |
834 |
char lin[ASCIILINESZ+1]; |
835 |
char sec[ASCIILINESZ+1]; |
836 |
char key[ASCIILINESZ+1]; |
837 |
char val[ASCIILINESZ+1]; |
838 |
char * where; |
839 |
FILE * ini; |
840 |
int lineno; |
841 |
FileLock * lock; |
842 |
|
843 |
lock = ini_file_lock (ininame, FALSE); |
844 |
if (!lock) |
845 |
return NULL; |
846 |
|
847 |
ini = fopen (ininame, "r"); |
848 |
if (!ini) |
849 |
{ |
850 |
ini_file_unlock (lock ); |
851 |
return NULL; |
852 |
} |
853 |
|
854 |
sec[0] = 0; |
855 |
|
856 |
/* |
857 |
* Initialize a new dictionary entry |
858 |
*/ |
859 |
d = dictionary_new (0); |
860 |
lineno = 0; |
861 |
|
862 |
while (fgets (lin, ASCIILINESZ, ini) != NULL) |
863 |
{ |
864 |
lineno++; |
865 |
where = strskp (lin); /* Skip leading spaces */ |
866 |
|
867 |
if (*where == ';' || *where == '#' || *where == 0) |
868 |
continue; /* Comment lines */ |
869 |
else |
870 |
{ |
871 |
val[0] = '\0'; |
872 |
|
873 |
if (sscanf (where, "[%[^]]", sec) == 1) |
874 |
{ |
875 |
/* Valid section name */ |
876 |
strcpy (sec, strlwc (sec)); |
877 |
iniparser_add_entry (d, sec, NULL, NULL); |
878 |
} |
879 |
else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2 || |
880 |
sscanf (where, "%[^=] = '%[^\']'", key, val) == 2 || |
881 |
sscanf (where, "%[^=] = %[^\n]", key, val) >= 1) |
882 |
{ |
883 |
strcpy (key, strlwc (strcrop (key))); |
884 |
/* |
885 |
* sscanf cannot handle "" or '' as empty value, |
886 |
* this is done here |
887 |
*/ |
888 |
|
889 |
if (!strcmp (val, "\"\"") || !strcmp (val, "''")) |
890 |
{ |
891 |
val[0] = (char) 0; |
892 |
} |
893 |
else |
894 |
{ |
895 |
strcpy (val, strcrop (val)); |
896 |
} |
897 |
|
898 |
iniparser_add_entry (d, sec, key, val); |
899 |
} |
900 |
} |
901 |
} |
902 |
|
903 |
fclose (ini); |
904 |
ini_file_unlock (lock ); |
905 |
|
906 |
return d; |
907 |
} |
908 |
|
909 |
/*-------------------------------------------------------------------------*/ |
910 |
/** |
911 |
@brief Free all memory associated to an ini dictionary |
912 |
@param d Dictionary to free |
913 |
@return void |
914 |
|
915 |
Free all memory associated to an ini dictionary. |
916 |
It is mandatory to call this function before the dictionary object |
917 |
gets out of the current context. |
918 |
*/ |
919 |
/*--------------------------------------------------------------------------*/ |
920 |
void |
921 |
iniparser_free (dictionary * d) |
922 |
{ |
923 |
dictionary_del (d); |
924 |
} |
925 |
|
926 |
#ifdef __cplusplus |
927 |
} |
928 |
|
929 |
#endif |