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