~ubuntu-branches/debian/squeeze/stellarium/squeeze

« back to all changes in this revision

Viewing changes to src/stelutils/iniparser/iniparser.c

  • Committer: Bazaar Package Importer
  • Author(s): Cédric Delfosse
  • Date: 2008-05-19 21:28:23 UTC
  • mfrom: (3.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080519212823-m5nfiuntxstxzxj7
Tags: 0.9.1-4
Add libxcursor-dev, libxfixes-dev, libxinerama-dev, libqt4-opengl-dev to
build-deps (Closes: #479906)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*-------------------------------------------------------------------------*/
 
3
/**
 
4
   @file    iniparser.c
 
5
   @author  N. Devillard
 
6
   @date    Mar 2000
 
7
   @version $Revision: 1753 $
 
8
   @brief   Parser for ini files.
 
9
*/
 
10
/*--------------------------------------------------------------------------*/
 
11
 
 
12
/*
 
13
    $Id: iniparser.c 1753 2007-01-31 09:36:08Z xalioth $
 
14
    $Author: xalioth $
 
15
    $Date: 2007-01-31 04:36:08 -0500 (Wed, 31 Jan 2007) $
 
16
    $Revision: 1753 $
 
17
*/
 
18
 
 
19
/*---------------------------------------------------------------------------
 
20
                                Includes
 
21
 ---------------------------------------------------------------------------*/
 
22
 
 
23
#include "iniparser.h"
 
24
#include "strlib.h"
 
25
 
 
26
#define ASCIILINESZ         1024
 
27
#define INI_INVALID_KEY     ((char*)-1)
 
28
 
 
29
/*---------------------------------------------------------------------------
 
30
                        Private to this module
 
31
 ---------------------------------------------------------------------------*/
 
32
 
 
33
/* Private: add an entry to the dictionary */
 
34
static void iniparser_add_entry(
 
35
    dictionary * d,
 
36
    char * sec,
 
37
    char * key,
 
38
    char * val)
 
39
{
 
40
    char longkey[2*ASCIILINESZ+1];
 
41
 
 
42
    /* Make a key as section:keyword */
 
43
    if (key!=NULL) {
 
44
        sprintf(longkey, "%s:%s", sec, key);
 
45
    } else {
 
46
        strcpy(longkey, sec);
 
47
    }
 
48
 
 
49
    /* Add (key,val) to dictionary */
 
50
    dictionary_set(d, longkey, val);
 
51
    return ;
 
52
}
 
53
 
 
54
 
 
55
/*-------------------------------------------------------------------------*/
 
56
/**
 
57
  @brief    Get number of sections in a dictionary
 
58
  @param    d   Dictionary to examine
 
59
  @return   int Number of sections found in dictionary
 
60
 
 
61
  This function returns the number of sections found in a dictionary.
 
62
  The test to recognize sections is done on the string stored in the
 
63
  dictionary: a section name is given as "section" whereas a key is
 
64
  stored as "section:key", thus the test looks for entries that do not
 
65
  contain a colon.
 
66
 
 
67
  This clearly fails in the case a section name contains a colon, but
 
68
  this should simply be avoided.
 
69
 
 
70
  This function returns -1 in case of error.
 
71
 */
 
72
/*--------------------------------------------------------------------------*/
 
73
 
 
74
int iniparser_getnsec(dictionary * d)
 
75
{
 
76
    int i ;
 
77
    int nsec ;
 
78
 
 
79
    if (d==NULL) return -1 ;
 
80
    nsec=0 ;
 
81
    for (i=0 ; i<d->size ; i++) {
 
82
        if (d->key[i]==NULL)
 
83
            continue ;
 
84
        if (strchr(d->key[i], ':')==NULL) {
 
85
            nsec ++ ;
 
86
        }
 
87
    }
 
88
    return nsec ;
 
89
}
 
90
 
 
91
 
 
92
/*-------------------------------------------------------------------------*/
 
93
/**
 
94
  @brief    Get name for section n in a dictionary.
 
95
  @param    d   Dictionary to examine
 
96
  @param    n   Section number (from 0 to nsec-1).
 
97
  @return   Pointer to char string
 
98
 
 
99
  This function locates the n-th section in a dictionary and returns
 
100
  its name as a pointer to a string statically allocated inside the
 
101
  dictionary. Do not free or modify the returned string!
 
102
 
 
103
  This function returns NULL in case of error.
 
104
 */
 
105
/*--------------------------------------------------------------------------*/
 
106
 
 
107
char * iniparser_getsecname(dictionary * d, int n)
 
108
{
 
109
    int i ;
 
110
    int foundsec ;
 
111
 
 
112
    if (d==NULL || n<0) return NULL ;
 
113
    foundsec=0 ;
 
114
    for (i=0 ; i<d->size ; i++) {
 
115
        if (d->key[i]==NULL)
 
116
            continue ;
 
117
        if (strchr(d->key[i], ':')==NULL) {
 
118
            foundsec++ ;
 
119
            if (foundsec>n)
 
120
                break ;
 
121
        }
 
122
    }
 
123
    if (foundsec<=n) {
 
124
        return NULL ;
 
125
    }
 
126
    return d->key[i] ;
 
127
}
 
128
 
 
129
 
 
130
/*-------------------------------------------------------------------------*/
 
131
/**
 
132
  @brief    Dump a dictionary to an opened file pointer.
 
133
  @param    d   Dictionary to dump.
 
134
  @param    f   Opened file pointer to dump to.
 
135
  @return   void
 
136
 
 
137
  This function prints out the contents of a dictionary, one element by
 
138
  line, onto the provided file pointer. It is OK to specify @c stderr
 
139
  or @c stdout as output files. This function is meant for debugging
 
140
  purposes mostly.
 
141
 */
 
142
/*--------------------------------------------------------------------------*/
 
143
void iniparser_dump(dictionary * d, FILE * f)
 
144
{
 
145
    int     i ;
 
146
 
 
147
    if (d==NULL || f==NULL) return ;
 
148
    for (i=0 ; i<d->size ; i++) {
 
149
        if (d->key[i]==NULL)
 
150
            continue ;
 
151
        if (d->val[i]!=NULL) {
 
152
            fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
 
153
        } else {
 
154
            fprintf(f, "[%s]=UNDEF\n", d->key[i]);
 
155
        }
 
156
    }
 
157
    return ;
 
158
}
 
159
 
 
160
/*-------------------------------------------------------------------------*/
 
161
/**
 
162
  @brief    Save a dictionary to a loadable ini file
 
163
  @param    d   Dictionary to dump
 
164
  @param    f   Opened file pointer to dump to
 
165
  @return   void
 
166
 
 
167
  This function dumps a given dictionary into a loadable ini file.
 
168
  It is Ok to specify @c stderr or @c stdout as output files.
 
169
 */
 
170
/*--------------------------------------------------------------------------*/
 
171
 
 
172
void iniparser_dump_ini(dictionary * d, FILE * f)
 
173
{
 
174
    int     i, j ;
 
175
    char    keym[ASCIILINESZ+1];
 
176
    int     nsec ;
 
177
    char *  secname ;
 
178
    int     seclen ;
 
179
 
 
180
    if (d==NULL || f==NULL) return ;
 
181
 
 
182
    nsec = iniparser_getnsec(d);
 
183
    if (nsec<1) {
 
184
        /* No section in file: dump all keys as they are */
 
185
        for (i=0 ; i<d->size ; i++) {
 
186
            if (d->key[i]==NULL)
 
187
                continue ;
 
188
            fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
 
189
        }
 
190
        return ;
 
191
    }
 
192
    for (i=0 ; i<nsec ; i++) {
 
193
        secname = iniparser_getsecname(d, i) ;
 
194
        seclen  = (int)strlen(secname);
 
195
        fprintf(f, "\n[%s]\n", secname);
 
196
        sprintf(keym, "%s:", secname);
 
197
        for (j=0 ; j<d->size ; j++) {
 
198
            if (d->key[j]==NULL)
 
199
                continue ;
 
200
            if (!strncmp(d->key[j], keym, seclen+1)) {
 
201
                fprintf(f,
 
202
                        "%-30s = %s\n",
 
203
                        d->key[j]+seclen+1,
 
204
                        d->val[j] ? d->val[j] : "");
 
205
            }
 
206
        }
 
207
    }
 
208
    fprintf(f, "\n");
 
209
    return ;
 
210
}
 
211
 
 
212
 
 
213
 
 
214
 
 
215
/*-------------------------------------------------------------------------*/
 
216
/**
 
217
  @brief        Get the string associated to a key, return NULL if not found
 
218
  @param    d   Dictionary to search
 
219
  @param    key Key string to look for
 
220
  @return   pointer to statically allocated character string, or NULL.
 
221
 
 
222
  This function queries a dictionary for a key. A key as read from an
 
223
  ini file is given as "section:key". If the key cannot be found,
 
224
  NULL is returned.
 
225
  The returned char pointer is pointing to a string allocated in
 
226
  the dictionary, do not free or modify it.
 
227
 
 
228
  This function is only provided for backwards compatibility with 
 
229
  previous versions of iniparser. It is recommended to use
 
230
  iniparser_getstring() instead.
 
231
 */
 
232
/*--------------------------------------------------------------------------*/
 
233
const char * iniparser_getstr(const dictionary * d, const char * key)
 
234
{
 
235
    return iniparser_getstring(d, key, NULL);
 
236
}
 
237
 
 
238
 
 
239
/*-------------------------------------------------------------------------*/
 
240
/**
 
241
  @brief    Get the string associated to a key
 
242
  @param    d       Dictionary to search
 
243
  @param    key     Key string to look for
 
244
  @param    def     Default value to return if key not found.
 
245
  @return   pointer to statically allocated character string
 
246
 
 
247
  This function queries a dictionary for a key. A key as read from an
 
248
  ini file is given as "section:key". If the key cannot be found,
 
249
  the pointer passed as 'def' is returned.
 
250
  The returned char pointer is pointing to a string allocated in
 
251
  the dictionary, do not free or modify it.
 
252
 */
 
253
/*--------------------------------------------------------------------------*/
 
254
const char * iniparser_getstring(const dictionary * d, const char * key, const char * def)
 
255
{
 
256
    const char * lc_key ;
 
257
    const char * sval ;
 
258
 
 
259
    if (d==NULL || key==NULL)
 
260
        return def ;
 
261
 
 
262
    lc_key = strlwc(key);
 
263
    sval = dictionary_get(d, lc_key, def);
 
264
 
 
265
    return sval ;
 
266
}
 
267
 
 
268
 
 
269
 
 
270
/*-------------------------------------------------------------------------*/
 
271
/**
 
272
  @brief    Get the string associated to a key, convert to an int
 
273
  @param    d Dictionary to search
 
274
  @param    key Key string to look for
 
275
  @param    notfound Value to return in case of error
 
276
  @return   integer
 
277
 
 
278
  This function queries a dictionary for a key. A key as read from an
 
279
  ini file is given as "section:key". If the key cannot be found,
 
280
  the notfound value is returned.
 
281
 */
 
282
/*--------------------------------------------------------------------------*/
 
283
int iniparser_getint(dictionary * d, const char * key, int notfound)
 
284
{
 
285
    const char * str ;
 
286
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
 
287
    if (str==INI_INVALID_KEY) return notfound ;
 
288
    return atoi(str);
 
289
}
 
290
 
 
291
 
 
292
/*-------------------------------------------------------------------------*/
 
293
/**
 
294
  @brief    Get the string associated to a key, convert to a double
 
295
  @param    d Dictionary to search
 
296
  @param    key Key string to look for
 
297
  @param    notfound Value to return in case of error
 
298
  @return   double
 
299
 
 
300
  This function queries a dictionary for a key. A key as read from an
 
301
  ini file is given as "section:key". If the key cannot be found,
 
302
  the notfound value is returned.
 
303
 */
 
304
/*--------------------------------------------------------------------------*/
 
305
double iniparser_getdouble(dictionary * d, const char * key, double notfound)
 
306
{
 
307
    const char * str;
 
308
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
 
309
    if (str==INI_INVALID_KEY) return notfound ;
 
310
    return atof(str);
 
311
}
 
312
 
 
313
 
 
314
 
 
315
/*-------------------------------------------------------------------------*/
 
316
/**
 
317
  @brief    Get the string associated to a key, convert to a boolean
 
318
  @param    d Dictionary to search
 
319
  @param    key Key string to look for
 
320
  @param    notfound Value to return in case of error
 
321
  @return   integer
 
322
 
 
323
  This function queries a dictionary for a key. A key as read from an
 
324
  ini file is given as "section:key". If the key cannot be found,
 
325
  the notfound value is returned.
 
326
 
 
327
  A true boolean is found if one of the following is matched:
 
328
 
 
329
  - A string starting with 'y'
 
330
  - A string starting with 'Y'
 
331
  - A string starting with 't'
 
332
  - A string starting with 'T'
 
333
  - A string starting with '1'
 
334
 
 
335
  A false boolean is found if one of the following is matched:
 
336
 
 
337
  - A string starting with 'n'
 
338
  - A string starting with 'N'
 
339
  - A string starting with 'f'
 
340
  - A string starting with 'F'
 
341
  - A string starting with '0'
 
342
 
 
343
  The notfound value returned if no boolean is identified, does not
 
344
  necessarily have to be 0 or 1.
 
345
 */
 
346
/*--------------------------------------------------------------------------*/
 
347
int iniparser_getboolean(dictionary * d, const char * key, int notfound)
 
348
{
 
349
    const char * c;
 
350
    int         ret ;
 
351
 
 
352
    c = iniparser_getstring(d, key, INI_INVALID_KEY);
 
353
    if (c==INI_INVALID_KEY) return notfound ;
 
354
    if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
 
355
        ret = 1 ;
 
356
    } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
 
357
        ret = 0 ;
 
358
    } else {
 
359
        ret = notfound ;
 
360
    }
 
361
    return ret;
 
362
}
 
363
 
 
364
 
 
365
/*-------------------------------------------------------------------------*/
 
366
/**
 
367
  @brief    Finds out if a given entry exists in a dictionary
 
368
  @param    ini     Dictionary to search
 
369
  @param    entry   Name of the entry to look for
 
370
  @return   integer 1 if entry exists, 0 otherwise
 
371
 
 
372
  Finds out if a given entry exists in the dictionary. Since sections
 
373
  are stored as keys with NULL associated values, this is the only way
 
374
  of querying for the presence of sections in a dictionary.
 
375
 */
 
376
/*--------------------------------------------------------------------------*/
 
377
 
 
378
int iniparser_find_entry(
 
379
    dictionary  *   ini,
 
380
    const char        *   entry
 
381
)
 
382
{
 
383
    int found=0 ;
 
384
    if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
 
385
        found = 1 ;
 
386
    }
 
387
    return found ;
 
388
}
 
389
 
 
390
 
 
391
 
 
392
/*-------------------------------------------------------------------------*/
 
393
/**
 
394
  @brief    Set an entry in a dictionary.
 
395
  @param    ini     Dictionary to modify.
 
396
  @param    entry   Entry to modify (entry name)
 
397
  @param    val     New value to associate to the entry.
 
398
  @return   int 0 if Ok, -1 otherwise.
 
399
 
 
400
  If the given entry can be found in the dictionary, it is modified to
 
401
  contain the provided value. If it cannot be found the entry is created.
 
402
  It is Ok to set val to NULL.
 
403
 */
 
404
/*--------------------------------------------------------------------------*/
 
405
 
 
406
int iniparser_setstr(dictionary * ini, const char * entry, const char * val)
 
407
{
 
408
    dictionary_set(ini, strlwc(entry), val);
 
409
    return 0 ;
 
410
}
 
411
 
 
412
/*-------------------------------------------------------------------------*/
 
413
/**
 
414
  @brief    Delete an entry in a dictionary
 
415
  @param    ini     Dictionary to modify
 
416
  @param    entry   Entry to delete (entry name)
 
417
  @return   void
 
418
 
 
419
  If the given entry can be found, it is deleted from the dictionary.
 
420
 */
 
421
/*--------------------------------------------------------------------------*/
 
422
void iniparser_unset(dictionary * ini, const char * entry)
 
423
{
 
424
    dictionary_unset(ini, strlwc(entry));
 
425
}
 
426
 
 
427
 
 
428
/*-------------------------------------------------------------------------*/
 
429
/**
 
430
  @brief    Parse an ini file and return an allocated dictionary object
 
431
  @param    ininame Name of the ini file to read.
 
432
  @return   Pointer to newly allocated dictionary
 
433
 
 
434
  This is the parser for ini files. This function is called, providing
 
435
  the name of the file to be read. It returns a dictionary object that
 
436
  should not be accessed directly, but through accessor functions
 
437
  instead.
 
438
 
 
439
  The returned dictionary must be freed using iniparser_freedict().
 
440
 */
 
441
/*--------------------------------------------------------------------------*/
 
442
 
 
443
dictionary * iniparser_load(const char * ininame)
 
444
{
 
445
    dictionary  *   d ;
 
446
    char        lin[ASCIILINESZ+1];
 
447
    char        sec[ASCIILINESZ+1];
 
448
    char        key[ASCIILINESZ+1];
 
449
    char        val[ASCIILINESZ+1];
 
450
    char    *   where ;
 
451
    FILE    *   ini ;
 
452
    int         lineno ;
 
453
 
 
454
    if ((ini=fopen(ininame, "rb"))==NULL) {
 
455
        return NULL ;
 
456
    }
 
457
 
 
458
    sec[0]=0;
 
459
 
 
460
    /*
 
461
     * Initialize a new dictionary entry
 
462
     */
 
463
    d = dictionary_new(0);
 
464
    lineno = 0 ;
 
465
    while (fgets(lin, ASCIILINESZ, ini)!=NULL) {
 
466
        lineno++ ;
 
467
        where = strskp(lin); /* Skip leading spaces */
 
468
        if (*where==';' || *where=='#' || *where==0)
 
469
            continue ; /* Comment lines */
 
470
        else {
 
471
            if (sscanf(where, "[%[^]]", sec)==1) {
 
472
                /* Valid section name */
 
473
                strcpy(sec, strlwc(sec));
 
474
                iniparser_add_entry(d, sec, NULL, NULL);
 
475
            } else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2
 
476
                   ||  sscanf (where, "%[^=] = '%[^\']'",   key, val) == 2
 
477
                   ||  sscanf (where, "%[^=] = %[^;#]",     key, val) == 2) {
 
478
                strcpy(key, strlwc(strcrop(key)));
 
479
                /*
 
480
                 * sscanf cannot handle "" or '' as empty value,
 
481
                 * this is done here
 
482
                 */
 
483
                if (!strcmp(val, "\"\"") || !strcmp(val, "''")) {
 
484
                    val[0] = (char)0;
 
485
                } else {
 
486
                    strcpy(val, strcrop(val));
 
487
                }
 
488
                iniparser_add_entry(d, sec, key, val);
 
489
            }
 
490
        }
 
491
    }
 
492
    fclose(ini);
 
493
    return d ;
 
494
}
 
495
 
 
496
 
 
497
 
 
498
/*-------------------------------------------------------------------------*/
 
499
/**
 
500
  @brief    Free all memory associated to an ini dictionary
 
501
  @param    d Dictionary to free
 
502
  @return   void
 
503
 
 
504
  Free all memory associated to an ini dictionary.
 
505
  It is mandatory to call this function before the dictionary object
 
506
  gets out of the current context.
 
507
 */
 
508
/*--------------------------------------------------------------------------*/
 
509
 
 
510
void iniparser_freedict(dictionary * d)
 
511
{
 
512
    dictionary_del(d);
 
513
}
 
514
 
 
515
/* vim: set ts=4 et sw=4 tw=75 */