port iniparser code for iRobotwithWIFI
Fork of iniparser by
iniparser.cpp@1:452fd0d30ac6, 2013-12-10 (annotated)
- Committer:
- 4180skrw
- Date:
- Tue Dec 10 02:16:00 2013 +0000
- Revision:
- 1:452fd0d30ac6
- Parent:
- iniparser.c@0:1a9f9f36242e
ported for our code
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) { |
4180skrw | 1:452fd0d30ac6 | 187 | int length = strlen(d->key[i]); |
4180skrw | 1:452fd0d30ac6 | 188 | char buff[4]; |
4180skrw | 1:452fd0d30ac6 | 189 | memcpy(buff, &(d->key[i][13]),length-13); |
4180skrw | 1:452fd0d30ac6 | 190 | buff[3] = '\0'; |
4180skrw | 1:452fd0d30ac6 | 191 | |
4180skrw | 1:452fd0d30ac6 | 192 | fprintf(f, "%s=%s\n", buff, d->val[i]); |
tobyspark | 0:1a9f9f36242e | 193 | } else { |
4180skrw | 1:452fd0d30ac6 | 194 | fprintf(f, "[%s]\n", d->key[i]); |
tobyspark | 0:1a9f9f36242e | 195 | } |
tobyspark | 0:1a9f9f36242e | 196 | } |
tobyspark | 0:1a9f9f36242e | 197 | return ; |
tobyspark | 0:1a9f9f36242e | 198 | } |
tobyspark | 0:1a9f9f36242e | 199 | |
tobyspark | 0:1a9f9f36242e | 200 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 201 | /** |
tobyspark | 0:1a9f9f36242e | 202 | @brief Save a dictionary to a loadable ini file |
tobyspark | 0:1a9f9f36242e | 203 | @param d Dictionary to dump |
tobyspark | 0:1a9f9f36242e | 204 | @param f Opened file pointer to dump to |
tobyspark | 0:1a9f9f36242e | 205 | @return void |
tobyspark | 0:1a9f9f36242e | 206 | |
tobyspark | 0:1a9f9f36242e | 207 | This function dumps a given dictionary into a loadable ini file. |
tobyspark | 0:1a9f9f36242e | 208 | It is Ok to specify @c stderr or @c stdout as output files. |
tobyspark | 0:1a9f9f36242e | 209 | */ |
tobyspark | 0:1a9f9f36242e | 210 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 211 | void iniparser_dump_ini(dictionary * d, FILE * f) |
tobyspark | 0:1a9f9f36242e | 212 | { |
tobyspark | 0:1a9f9f36242e | 213 | int i ; |
tobyspark | 0:1a9f9f36242e | 214 | int nsec ; |
tobyspark | 0:1a9f9f36242e | 215 | char * secname ; |
tobyspark | 0:1a9f9f36242e | 216 | |
tobyspark | 0:1a9f9f36242e | 217 | if (d==NULL || f==NULL) return ; |
tobyspark | 0:1a9f9f36242e | 218 | |
tobyspark | 0:1a9f9f36242e | 219 | nsec = iniparser_getnsec(d); |
tobyspark | 0:1a9f9f36242e | 220 | if (nsec<1) { |
tobyspark | 0:1a9f9f36242e | 221 | /* No section in file: dump all keys as they are */ |
tobyspark | 0:1a9f9f36242e | 222 | for (i=0 ; i<d->size ; i++) { |
tobyspark | 0:1a9f9f36242e | 223 | if (d->key[i]==NULL) |
tobyspark | 0:1a9f9f36242e | 224 | continue ; |
tobyspark | 0:1a9f9f36242e | 225 | fprintf(f, "%s = %s\n", d->key[i], d->val[i]); |
tobyspark | 0:1a9f9f36242e | 226 | } |
tobyspark | 0:1a9f9f36242e | 227 | return ; |
tobyspark | 0:1a9f9f36242e | 228 | } |
tobyspark | 0:1a9f9f36242e | 229 | for (i=0 ; i<nsec ; i++) { |
tobyspark | 0:1a9f9f36242e | 230 | secname = iniparser_getsecname(d, i) ; |
tobyspark | 0:1a9f9f36242e | 231 | iniparser_dumpsection_ini(d, secname, f) ; |
tobyspark | 0:1a9f9f36242e | 232 | } |
tobyspark | 0:1a9f9f36242e | 233 | fprintf(f, "\n"); |
tobyspark | 0:1a9f9f36242e | 234 | return ; |
tobyspark | 0:1a9f9f36242e | 235 | } |
tobyspark | 0:1a9f9f36242e | 236 | |
tobyspark | 0:1a9f9f36242e | 237 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 238 | /** |
tobyspark | 0:1a9f9f36242e | 239 | @brief Save a dictionary section to a loadable ini file |
tobyspark | 0:1a9f9f36242e | 240 | @param d Dictionary to dump |
tobyspark | 0:1a9f9f36242e | 241 | @param s Section name of dictionary to dump |
tobyspark | 0:1a9f9f36242e | 242 | @param f Opened file pointer to dump to |
tobyspark | 0:1a9f9f36242e | 243 | @return void |
tobyspark | 0:1a9f9f36242e | 244 | |
tobyspark | 0:1a9f9f36242e | 245 | This function dumps a given section of a given dictionary into a loadable ini |
tobyspark | 0:1a9f9f36242e | 246 | file. It is Ok to specify @c stderr or @c stdout as output files. |
tobyspark | 0:1a9f9f36242e | 247 | */ |
tobyspark | 0:1a9f9f36242e | 248 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 249 | void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f) |
tobyspark | 0:1a9f9f36242e | 250 | { |
tobyspark | 0:1a9f9f36242e | 251 | int j ; |
tobyspark | 0:1a9f9f36242e | 252 | char keym[ASCIILINESZ+1]; |
tobyspark | 0:1a9f9f36242e | 253 | int seclen ; |
tobyspark | 0:1a9f9f36242e | 254 | |
tobyspark | 0:1a9f9f36242e | 255 | if (d==NULL || f==NULL) return ; |
tobyspark | 0:1a9f9f36242e | 256 | if (! iniparser_find_entry(d, s)) return ; |
tobyspark | 0:1a9f9f36242e | 257 | |
tobyspark | 0:1a9f9f36242e | 258 | seclen = (int)strlen(s); |
tobyspark | 0:1a9f9f36242e | 259 | fprintf(f, "\n[%s]\n", s); |
tobyspark | 0:1a9f9f36242e | 260 | sprintf(keym, "%s:", s); |
tobyspark | 0:1a9f9f36242e | 261 | for (j=0 ; j<d->size ; j++) { |
tobyspark | 0:1a9f9f36242e | 262 | if (d->key[j]==NULL) |
tobyspark | 0:1a9f9f36242e | 263 | continue ; |
tobyspark | 0:1a9f9f36242e | 264 | if (!strncmp(d->key[j], keym, seclen+1)) { |
tobyspark | 0:1a9f9f36242e | 265 | fprintf(f, |
tobyspark | 0:1a9f9f36242e | 266 | "%-30s = %s\n", |
tobyspark | 0:1a9f9f36242e | 267 | d->key[j]+seclen+1, |
tobyspark | 0:1a9f9f36242e | 268 | d->val[j] ? d->val[j] : ""); |
tobyspark | 0:1a9f9f36242e | 269 | } |
tobyspark | 0:1a9f9f36242e | 270 | } |
tobyspark | 0:1a9f9f36242e | 271 | fprintf(f, "\n"); |
tobyspark | 0:1a9f9f36242e | 272 | return ; |
tobyspark | 0:1a9f9f36242e | 273 | } |
tobyspark | 0:1a9f9f36242e | 274 | |
tobyspark | 0:1a9f9f36242e | 275 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 276 | /** |
tobyspark | 0:1a9f9f36242e | 277 | @brief Get the number of keys in a section of a dictionary. |
tobyspark | 0:1a9f9f36242e | 278 | @param d Dictionary to examine |
tobyspark | 0:1a9f9f36242e | 279 | @param s Section name of dictionary to examine |
tobyspark | 0:1a9f9f36242e | 280 | @return Number of keys in section |
tobyspark | 0:1a9f9f36242e | 281 | */ |
tobyspark | 0:1a9f9f36242e | 282 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 283 | int iniparser_getsecnkeys(dictionary * d, char * s) |
tobyspark | 0:1a9f9f36242e | 284 | { |
tobyspark | 0:1a9f9f36242e | 285 | int seclen, nkeys ; |
tobyspark | 0:1a9f9f36242e | 286 | char keym[ASCIILINESZ+1]; |
tobyspark | 0:1a9f9f36242e | 287 | int j ; |
tobyspark | 0:1a9f9f36242e | 288 | |
tobyspark | 0:1a9f9f36242e | 289 | nkeys = 0; |
tobyspark | 0:1a9f9f36242e | 290 | |
tobyspark | 0:1a9f9f36242e | 291 | if (d==NULL) return nkeys; |
tobyspark | 0:1a9f9f36242e | 292 | if (! iniparser_find_entry(d, s)) return nkeys; |
tobyspark | 0:1a9f9f36242e | 293 | |
tobyspark | 0:1a9f9f36242e | 294 | seclen = (int)strlen(s); |
tobyspark | 0:1a9f9f36242e | 295 | sprintf(keym, "%s:", s); |
tobyspark | 0:1a9f9f36242e | 296 | |
tobyspark | 0:1a9f9f36242e | 297 | for (j=0 ; j<d->size ; j++) { |
tobyspark | 0:1a9f9f36242e | 298 | if (d->key[j]==NULL) |
tobyspark | 0:1a9f9f36242e | 299 | continue ; |
tobyspark | 0:1a9f9f36242e | 300 | if (!strncmp(d->key[j], keym, seclen+1)) |
tobyspark | 0:1a9f9f36242e | 301 | nkeys++; |
tobyspark | 0:1a9f9f36242e | 302 | } |
tobyspark | 0:1a9f9f36242e | 303 | |
tobyspark | 0:1a9f9f36242e | 304 | return nkeys; |
tobyspark | 0:1a9f9f36242e | 305 | |
tobyspark | 0:1a9f9f36242e | 306 | } |
tobyspark | 0:1a9f9f36242e | 307 | |
tobyspark | 0:1a9f9f36242e | 308 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 309 | /** |
tobyspark | 0:1a9f9f36242e | 310 | @brief Get the number of keys in a section of a dictionary. |
tobyspark | 0:1a9f9f36242e | 311 | @param d Dictionary to examine |
tobyspark | 0:1a9f9f36242e | 312 | @param s Section name of dictionary to examine |
tobyspark | 0:1a9f9f36242e | 313 | @return pointer to statically allocated character strings |
tobyspark | 0:1a9f9f36242e | 314 | |
tobyspark | 0:1a9f9f36242e | 315 | This function queries a dictionary and finds all keys in a given section. |
tobyspark | 0:1a9f9f36242e | 316 | Each pointer in the returned char pointer-to-pointer is pointing to |
tobyspark | 0:1a9f9f36242e | 317 | a string allocated in the dictionary; do not free or modify them. |
tobyspark | 0:1a9f9f36242e | 318 | |
tobyspark | 0:1a9f9f36242e | 319 | This function returns NULL in case of error. |
tobyspark | 0:1a9f9f36242e | 320 | */ |
tobyspark | 0:1a9f9f36242e | 321 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 322 | char ** iniparser_getseckeys(dictionary * d, char * s) |
tobyspark | 0:1a9f9f36242e | 323 | { |
tobyspark | 0:1a9f9f36242e | 324 | |
tobyspark | 0:1a9f9f36242e | 325 | char **keys; |
tobyspark | 0:1a9f9f36242e | 326 | |
tobyspark | 0:1a9f9f36242e | 327 | int i, j ; |
tobyspark | 0:1a9f9f36242e | 328 | char keym[ASCIILINESZ+1]; |
tobyspark | 0:1a9f9f36242e | 329 | int seclen, nkeys ; |
tobyspark | 0:1a9f9f36242e | 330 | |
tobyspark | 0:1a9f9f36242e | 331 | keys = NULL; |
tobyspark | 0:1a9f9f36242e | 332 | |
tobyspark | 0:1a9f9f36242e | 333 | if (d==NULL) return keys; |
tobyspark | 0:1a9f9f36242e | 334 | if (! iniparser_find_entry(d, s)) return keys; |
tobyspark | 0:1a9f9f36242e | 335 | |
tobyspark | 0:1a9f9f36242e | 336 | nkeys = iniparser_getsecnkeys(d, s); |
tobyspark | 0:1a9f9f36242e | 337 | |
tobyspark | 0:1a9f9f36242e | 338 | keys = (char**) malloc(nkeys*sizeof(char*)); |
tobyspark | 0:1a9f9f36242e | 339 | |
tobyspark | 0:1a9f9f36242e | 340 | seclen = (int)strlen(s); |
tobyspark | 0:1a9f9f36242e | 341 | sprintf(keym, "%s:", s); |
tobyspark | 0:1a9f9f36242e | 342 | |
tobyspark | 0:1a9f9f36242e | 343 | i = 0; |
tobyspark | 0:1a9f9f36242e | 344 | |
tobyspark | 0:1a9f9f36242e | 345 | for (j=0 ; j<d->size ; j++) { |
tobyspark | 0:1a9f9f36242e | 346 | if (d->key[j]==NULL) |
tobyspark | 0:1a9f9f36242e | 347 | continue ; |
tobyspark | 0:1a9f9f36242e | 348 | if (!strncmp(d->key[j], keym, seclen+1)) { |
tobyspark | 0:1a9f9f36242e | 349 | keys[i] = d->key[j]; |
tobyspark | 0:1a9f9f36242e | 350 | i++; |
tobyspark | 0:1a9f9f36242e | 351 | } |
tobyspark | 0:1a9f9f36242e | 352 | } |
tobyspark | 0:1a9f9f36242e | 353 | |
tobyspark | 0:1a9f9f36242e | 354 | return keys; |
tobyspark | 0:1a9f9f36242e | 355 | |
tobyspark | 0:1a9f9f36242e | 356 | } |
tobyspark | 0:1a9f9f36242e | 357 | |
tobyspark | 0:1a9f9f36242e | 358 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 359 | /** |
tobyspark | 0:1a9f9f36242e | 360 | @brief Get the string associated to a key |
tobyspark | 0:1a9f9f36242e | 361 | @param d Dictionary to search |
tobyspark | 0:1a9f9f36242e | 362 | @param key Key string to look for |
tobyspark | 0:1a9f9f36242e | 363 | @param def Default value to return if key not found. |
tobyspark | 0:1a9f9f36242e | 364 | @return pointer to statically allocated character string |
tobyspark | 0:1a9f9f36242e | 365 | |
tobyspark | 0:1a9f9f36242e | 366 | This function queries a dictionary for a key. A key as read from an |
tobyspark | 0:1a9f9f36242e | 367 | ini file is given as "section:key". If the key cannot be found, |
tobyspark | 0:1a9f9f36242e | 368 | the pointer passed as 'def' is returned. |
tobyspark | 0:1a9f9f36242e | 369 | The returned char pointer is pointing to a string allocated in |
tobyspark | 0:1a9f9f36242e | 370 | the dictionary, do not free or modify it. |
tobyspark | 0:1a9f9f36242e | 371 | */ |
tobyspark | 0:1a9f9f36242e | 372 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 373 | char * iniparser_getstring(dictionary * d, const char * key, char * def) |
tobyspark | 0:1a9f9f36242e | 374 | { |
tobyspark | 0:1a9f9f36242e | 375 | char * lc_key ; |
tobyspark | 0:1a9f9f36242e | 376 | char * sval ; |
tobyspark | 0:1a9f9f36242e | 377 | |
tobyspark | 0:1a9f9f36242e | 378 | if (d==NULL || key==NULL) |
tobyspark | 0:1a9f9f36242e | 379 | return def ; |
tobyspark | 0:1a9f9f36242e | 380 | |
tobyspark | 0:1a9f9f36242e | 381 | lc_key = strlwc(key); |
tobyspark | 0:1a9f9f36242e | 382 | sval = dictionary_get(d, lc_key, def); |
tobyspark | 0:1a9f9f36242e | 383 | return sval ; |
tobyspark | 0:1a9f9f36242e | 384 | } |
tobyspark | 0:1a9f9f36242e | 385 | |
tobyspark | 0:1a9f9f36242e | 386 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 387 | /** |
tobyspark | 0:1a9f9f36242e | 388 | @brief Get the string associated to a key, convert to an int |
tobyspark | 0:1a9f9f36242e | 389 | @param d Dictionary to search |
tobyspark | 0:1a9f9f36242e | 390 | @param key Key string to look for |
tobyspark | 0:1a9f9f36242e | 391 | @param notfound Value to return in case of error |
tobyspark | 0:1a9f9f36242e | 392 | @return integer |
tobyspark | 0:1a9f9f36242e | 393 | |
tobyspark | 0:1a9f9f36242e | 394 | This function queries a dictionary for a key. A key as read from an |
tobyspark | 0:1a9f9f36242e | 395 | ini file is given as "section:key". If the key cannot be found, |
tobyspark | 0:1a9f9f36242e | 396 | the notfound value is returned. |
tobyspark | 0:1a9f9f36242e | 397 | |
tobyspark | 0:1a9f9f36242e | 398 | Supported values for integers include the usual C notation |
tobyspark | 0:1a9f9f36242e | 399 | so decimal, octal (starting with 0) and hexadecimal (starting with 0x) |
tobyspark | 0:1a9f9f36242e | 400 | are supported. Examples: |
tobyspark | 0:1a9f9f36242e | 401 | |
tobyspark | 0:1a9f9f36242e | 402 | "42" -> 42 |
tobyspark | 0:1a9f9f36242e | 403 | "042" -> 34 (octal -> decimal) |
tobyspark | 0:1a9f9f36242e | 404 | "0x42" -> 66 (hexa -> decimal) |
tobyspark | 0:1a9f9f36242e | 405 | |
tobyspark | 0:1a9f9f36242e | 406 | Warning: the conversion may overflow in various ways. Conversion is |
tobyspark | 0:1a9f9f36242e | 407 | totally outsourced to strtol(), see the associated man page for overflow |
tobyspark | 0:1a9f9f36242e | 408 | handling. |
tobyspark | 0:1a9f9f36242e | 409 | |
tobyspark | 0:1a9f9f36242e | 410 | Credits: Thanks to A. Becker for suggesting strtol() |
tobyspark | 0:1a9f9f36242e | 411 | */ |
tobyspark | 0:1a9f9f36242e | 412 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 413 | int iniparser_getint(dictionary * d, const char * key, int notfound) |
tobyspark | 0:1a9f9f36242e | 414 | { |
tobyspark | 0:1a9f9f36242e | 415 | char * str ; |
tobyspark | 0:1a9f9f36242e | 416 | |
tobyspark | 0:1a9f9f36242e | 417 | str = iniparser_getstring(d, key, INI_INVALID_KEY); |
tobyspark | 0:1a9f9f36242e | 418 | if (str==INI_INVALID_KEY) return notfound ; |
tobyspark | 0:1a9f9f36242e | 419 | return (int)strtol(str, NULL, 0); |
tobyspark | 0:1a9f9f36242e | 420 | } |
tobyspark | 0:1a9f9f36242e | 421 | |
tobyspark | 0:1a9f9f36242e | 422 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 423 | /** |
tobyspark | 0:1a9f9f36242e | 424 | @brief Get the string associated to a key, convert to a double |
tobyspark | 0:1a9f9f36242e | 425 | @param d Dictionary to search |
tobyspark | 0:1a9f9f36242e | 426 | @param key Key string to look for |
tobyspark | 0:1a9f9f36242e | 427 | @param notfound Value to return in case of error |
tobyspark | 0:1a9f9f36242e | 428 | @return double |
tobyspark | 0:1a9f9f36242e | 429 | |
tobyspark | 0:1a9f9f36242e | 430 | This function queries a dictionary for a key. A key as read from an |
tobyspark | 0:1a9f9f36242e | 431 | ini file is given as "section:key". If the key cannot be found, |
tobyspark | 0:1a9f9f36242e | 432 | the notfound value is returned. |
tobyspark | 0:1a9f9f36242e | 433 | */ |
tobyspark | 0:1a9f9f36242e | 434 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 435 | double iniparser_getdouble(dictionary * d, const char * key, double notfound) |
tobyspark | 0:1a9f9f36242e | 436 | { |
tobyspark | 0:1a9f9f36242e | 437 | char * str ; |
tobyspark | 0:1a9f9f36242e | 438 | |
tobyspark | 0:1a9f9f36242e | 439 | str = iniparser_getstring(d, key, INI_INVALID_KEY); |
tobyspark | 0:1a9f9f36242e | 440 | if (str==INI_INVALID_KEY) return notfound ; |
tobyspark | 0:1a9f9f36242e | 441 | return atof(str); |
tobyspark | 0:1a9f9f36242e | 442 | } |
tobyspark | 0:1a9f9f36242e | 443 | |
tobyspark | 0:1a9f9f36242e | 444 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 445 | /** |
tobyspark | 0:1a9f9f36242e | 446 | @brief Get the string associated to a key, convert to a boolean |
tobyspark | 0:1a9f9f36242e | 447 | @param d Dictionary to search |
tobyspark | 0:1a9f9f36242e | 448 | @param key Key string to look for |
tobyspark | 0:1a9f9f36242e | 449 | @param notfound Value to return in case of error |
tobyspark | 0:1a9f9f36242e | 450 | @return integer |
tobyspark | 0:1a9f9f36242e | 451 | |
tobyspark | 0:1a9f9f36242e | 452 | This function queries a dictionary for a key. A key as read from an |
tobyspark | 0:1a9f9f36242e | 453 | ini file is given as "section:key". If the key cannot be found, |
tobyspark | 0:1a9f9f36242e | 454 | the notfound value is returned. |
tobyspark | 0:1a9f9f36242e | 455 | |
tobyspark | 0:1a9f9f36242e | 456 | A true boolean is found if one of the following is matched: |
tobyspark | 0:1a9f9f36242e | 457 | |
tobyspark | 0:1a9f9f36242e | 458 | - A string starting with 'y' |
tobyspark | 0:1a9f9f36242e | 459 | - A string starting with 'Y' |
tobyspark | 0:1a9f9f36242e | 460 | - A string starting with 't' |
tobyspark | 0:1a9f9f36242e | 461 | - A string starting with 'T' |
tobyspark | 0:1a9f9f36242e | 462 | - A string starting with '1' |
tobyspark | 0:1a9f9f36242e | 463 | |
tobyspark | 0:1a9f9f36242e | 464 | A false boolean is found if one of the following is matched: |
tobyspark | 0:1a9f9f36242e | 465 | |
tobyspark | 0:1a9f9f36242e | 466 | - A string starting with 'n' |
tobyspark | 0:1a9f9f36242e | 467 | - A string starting with 'N' |
tobyspark | 0:1a9f9f36242e | 468 | - A string starting with 'f' |
tobyspark | 0:1a9f9f36242e | 469 | - A string starting with 'F' |
tobyspark | 0:1a9f9f36242e | 470 | - A string starting with '0' |
tobyspark | 0:1a9f9f36242e | 471 | |
tobyspark | 0:1a9f9f36242e | 472 | The notfound value returned if no boolean is identified, does not |
tobyspark | 0:1a9f9f36242e | 473 | necessarily have to be 0 or 1. |
tobyspark | 0:1a9f9f36242e | 474 | */ |
tobyspark | 0:1a9f9f36242e | 475 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 476 | int iniparser_getboolean(dictionary * d, const char * key, int notfound) |
tobyspark | 0:1a9f9f36242e | 477 | { |
tobyspark | 0:1a9f9f36242e | 478 | char * c ; |
tobyspark | 0:1a9f9f36242e | 479 | int ret ; |
tobyspark | 0:1a9f9f36242e | 480 | |
tobyspark | 0:1a9f9f36242e | 481 | c = iniparser_getstring(d, key, INI_INVALID_KEY); |
tobyspark | 0:1a9f9f36242e | 482 | if (c==INI_INVALID_KEY) return notfound ; |
tobyspark | 0:1a9f9f36242e | 483 | if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { |
tobyspark | 0:1a9f9f36242e | 484 | ret = 1 ; |
tobyspark | 0:1a9f9f36242e | 485 | } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { |
tobyspark | 0:1a9f9f36242e | 486 | ret = 0 ; |
tobyspark | 0:1a9f9f36242e | 487 | } else { |
tobyspark | 0:1a9f9f36242e | 488 | ret = notfound ; |
tobyspark | 0:1a9f9f36242e | 489 | } |
tobyspark | 0:1a9f9f36242e | 490 | return ret; |
tobyspark | 0:1a9f9f36242e | 491 | } |
tobyspark | 0:1a9f9f36242e | 492 | |
tobyspark | 0:1a9f9f36242e | 493 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 494 | /** |
tobyspark | 0:1a9f9f36242e | 495 | @brief Finds out if a given entry exists in a dictionary |
tobyspark | 0:1a9f9f36242e | 496 | @param ini Dictionary to search |
tobyspark | 0:1a9f9f36242e | 497 | @param entry Name of the entry to look for |
tobyspark | 0:1a9f9f36242e | 498 | @return integer 1 if entry exists, 0 otherwise |
tobyspark | 0:1a9f9f36242e | 499 | |
tobyspark | 0:1a9f9f36242e | 500 | Finds out if a given entry exists in the dictionary. Since sections |
tobyspark | 0:1a9f9f36242e | 501 | are stored as keys with NULL associated values, this is the only way |
tobyspark | 0:1a9f9f36242e | 502 | of querying for the presence of sections in a dictionary. |
tobyspark | 0:1a9f9f36242e | 503 | */ |
tobyspark | 0:1a9f9f36242e | 504 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 505 | int iniparser_find_entry( |
tobyspark | 0:1a9f9f36242e | 506 | dictionary * ini, |
tobyspark | 0:1a9f9f36242e | 507 | const char * entry |
tobyspark | 0:1a9f9f36242e | 508 | ) |
tobyspark | 0:1a9f9f36242e | 509 | { |
tobyspark | 0:1a9f9f36242e | 510 | int found=0 ; |
tobyspark | 0:1a9f9f36242e | 511 | if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { |
tobyspark | 0:1a9f9f36242e | 512 | found = 1 ; |
tobyspark | 0:1a9f9f36242e | 513 | } |
tobyspark | 0:1a9f9f36242e | 514 | return found ; |
tobyspark | 0:1a9f9f36242e | 515 | } |
tobyspark | 0:1a9f9f36242e | 516 | |
tobyspark | 0:1a9f9f36242e | 517 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 518 | /** |
tobyspark | 0:1a9f9f36242e | 519 | @brief Set an entry in a dictionary. |
tobyspark | 0:1a9f9f36242e | 520 | @param ini Dictionary to modify. |
tobyspark | 0:1a9f9f36242e | 521 | @param entry Entry to modify (entry name) |
tobyspark | 0:1a9f9f36242e | 522 | @param val New value to associate to the entry. |
tobyspark | 0:1a9f9f36242e | 523 | @return int 0 if Ok, -1 otherwise. |
tobyspark | 0:1a9f9f36242e | 524 | |
tobyspark | 0:1a9f9f36242e | 525 | If the given entry can be found in the dictionary, it is modified to |
tobyspark | 0:1a9f9f36242e | 526 | contain the provided value. If it cannot be found, -1 is returned. |
tobyspark | 0:1a9f9f36242e | 527 | It is Ok to set val to NULL. |
tobyspark | 0:1a9f9f36242e | 528 | */ |
tobyspark | 0:1a9f9f36242e | 529 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 530 | int iniparser_set(dictionary * ini, const char * entry, const char * val) |
tobyspark | 0:1a9f9f36242e | 531 | { |
tobyspark | 0:1a9f9f36242e | 532 | return dictionary_set(ini, strlwc(entry), val) ; |
tobyspark | 0:1a9f9f36242e | 533 | } |
tobyspark | 0:1a9f9f36242e | 534 | |
tobyspark | 0:1a9f9f36242e | 535 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 536 | /** |
tobyspark | 0:1a9f9f36242e | 537 | @brief Delete an entry in a dictionary |
tobyspark | 0:1a9f9f36242e | 538 | @param ini Dictionary to modify |
tobyspark | 0:1a9f9f36242e | 539 | @param entry Entry to delete (entry name) |
tobyspark | 0:1a9f9f36242e | 540 | @return void |
tobyspark | 0:1a9f9f36242e | 541 | |
tobyspark | 0:1a9f9f36242e | 542 | If the given entry can be found, it is deleted from the dictionary. |
tobyspark | 0:1a9f9f36242e | 543 | */ |
tobyspark | 0:1a9f9f36242e | 544 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 545 | void iniparser_unset(dictionary * ini, const char * entry) |
tobyspark | 0:1a9f9f36242e | 546 | { |
tobyspark | 0:1a9f9f36242e | 547 | dictionary_unset(ini, strlwc(entry)); |
tobyspark | 0:1a9f9f36242e | 548 | } |
tobyspark | 0:1a9f9f36242e | 549 | |
tobyspark | 0:1a9f9f36242e | 550 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 551 | /** |
tobyspark | 0:1a9f9f36242e | 552 | @brief Load a single line from an INI file |
tobyspark | 0:1a9f9f36242e | 553 | @param input_line Input line, may be concatenated multi-line input |
tobyspark | 0:1a9f9f36242e | 554 | @param section Output space to store section |
tobyspark | 0:1a9f9f36242e | 555 | @param key Output space to store key |
tobyspark | 0:1a9f9f36242e | 556 | @param value Output space to store value |
tobyspark | 0:1a9f9f36242e | 557 | @return line_status value |
tobyspark | 0:1a9f9f36242e | 558 | */ |
tobyspark | 0:1a9f9f36242e | 559 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 560 | static line_status iniparser_line( |
tobyspark | 0:1a9f9f36242e | 561 | const char * input_line, |
tobyspark | 0:1a9f9f36242e | 562 | char * section, |
tobyspark | 0:1a9f9f36242e | 563 | char * key, |
tobyspark | 0:1a9f9f36242e | 564 | char * value) |
tobyspark | 0:1a9f9f36242e | 565 | { |
tobyspark | 0:1a9f9f36242e | 566 | line_status sta ; |
tobyspark | 0:1a9f9f36242e | 567 | char line[ASCIILINESZ+1]; |
tobyspark | 0:1a9f9f36242e | 568 | int len ; |
tobyspark | 0:1a9f9f36242e | 569 | |
tobyspark | 0:1a9f9f36242e | 570 | strcpy(line, strstrip(input_line)); |
tobyspark | 0:1a9f9f36242e | 571 | len = (int)strlen(line); |
tobyspark | 0:1a9f9f36242e | 572 | |
tobyspark | 0:1a9f9f36242e | 573 | sta = LINE_UNPROCESSED ; |
tobyspark | 0:1a9f9f36242e | 574 | if (len<1) { |
tobyspark | 0:1a9f9f36242e | 575 | /* Empty line */ |
tobyspark | 0:1a9f9f36242e | 576 | sta = LINE_EMPTY ; |
tobyspark | 0:1a9f9f36242e | 577 | } else if (line[0]=='#' || line[0]==';') { |
tobyspark | 0:1a9f9f36242e | 578 | /* Comment line */ |
tobyspark | 0:1a9f9f36242e | 579 | sta = LINE_COMMENT ; |
tobyspark | 0:1a9f9f36242e | 580 | } else if (line[0]=='[' && line[len-1]==']') { |
tobyspark | 0:1a9f9f36242e | 581 | /* Section name */ |
tobyspark | 0:1a9f9f36242e | 582 | sscanf(line, "[%[^]]", section); |
tobyspark | 0:1a9f9f36242e | 583 | strcpy(section, strstrip(section)); |
tobyspark | 0:1a9f9f36242e | 584 | strcpy(section, strlwc(section)); |
tobyspark | 0:1a9f9f36242e | 585 | sta = LINE_SECTION ; |
tobyspark | 0:1a9f9f36242e | 586 | } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 |
tobyspark | 0:1a9f9f36242e | 587 | || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2 |
tobyspark | 0:1a9f9f36242e | 588 | || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { |
tobyspark | 0:1a9f9f36242e | 589 | /* Usual key=value, with or without comments */ |
tobyspark | 0:1a9f9f36242e | 590 | strcpy(key, strstrip(key)); |
tobyspark | 0:1a9f9f36242e | 591 | strcpy(key, strlwc(key)); |
tobyspark | 0:1a9f9f36242e | 592 | strcpy(value, strstrip(value)); |
tobyspark | 0:1a9f9f36242e | 593 | /* |
tobyspark | 0:1a9f9f36242e | 594 | * sscanf cannot handle '' or "" as empty values |
tobyspark | 0:1a9f9f36242e | 595 | * this is done here |
tobyspark | 0:1a9f9f36242e | 596 | */ |
tobyspark | 0:1a9f9f36242e | 597 | if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) { |
tobyspark | 0:1a9f9f36242e | 598 | value[0]=0 ; |
tobyspark | 0:1a9f9f36242e | 599 | } |
tobyspark | 0:1a9f9f36242e | 600 | sta = LINE_VALUE ; |
tobyspark | 0:1a9f9f36242e | 601 | } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 |
tobyspark | 0:1a9f9f36242e | 602 | || sscanf(line, "%[^=] %[=]", key, value) == 2) { |
tobyspark | 0:1a9f9f36242e | 603 | /* |
tobyspark | 0:1a9f9f36242e | 604 | * Special cases: |
tobyspark | 0:1a9f9f36242e | 605 | * key= |
tobyspark | 0:1a9f9f36242e | 606 | * key=; |
tobyspark | 0:1a9f9f36242e | 607 | * key=# |
tobyspark | 0:1a9f9f36242e | 608 | */ |
tobyspark | 0:1a9f9f36242e | 609 | strcpy(key, strstrip(key)); |
tobyspark | 0:1a9f9f36242e | 610 | strcpy(key, strlwc(key)); |
tobyspark | 0:1a9f9f36242e | 611 | value[0]=0 ; |
tobyspark | 0:1a9f9f36242e | 612 | sta = LINE_VALUE ; |
tobyspark | 0:1a9f9f36242e | 613 | } else { |
tobyspark | 0:1a9f9f36242e | 614 | /* Generate syntax error */ |
tobyspark | 0:1a9f9f36242e | 615 | sta = LINE_ERROR ; |
tobyspark | 0:1a9f9f36242e | 616 | } |
tobyspark | 0:1a9f9f36242e | 617 | return sta ; |
tobyspark | 0:1a9f9f36242e | 618 | } |
tobyspark | 0:1a9f9f36242e | 619 | |
tobyspark | 0:1a9f9f36242e | 620 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 621 | /** |
tobyspark | 0:1a9f9f36242e | 622 | @brief Parse an ini file and return an allocated dictionary object |
tobyspark | 0:1a9f9f36242e | 623 | @param ininame Name of the ini file to read. |
tobyspark | 0:1a9f9f36242e | 624 | @return Pointer to newly allocated dictionary |
tobyspark | 0:1a9f9f36242e | 625 | |
tobyspark | 0:1a9f9f36242e | 626 | This is the parser for ini files. This function is called, providing |
tobyspark | 0:1a9f9f36242e | 627 | the name of the file to be read. It returns a dictionary object that |
tobyspark | 0:1a9f9f36242e | 628 | should not be accessed directly, but through accessor functions |
tobyspark | 0:1a9f9f36242e | 629 | instead. |
tobyspark | 0:1a9f9f36242e | 630 | |
tobyspark | 0:1a9f9f36242e | 631 | The returned dictionary must be freed using iniparser_freedict(). |
tobyspark | 0:1a9f9f36242e | 632 | */ |
tobyspark | 0:1a9f9f36242e | 633 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 634 | dictionary * iniparser_load(const char * ininame) |
tobyspark | 0:1a9f9f36242e | 635 | { |
tobyspark | 0:1a9f9f36242e | 636 | FILE * in ; |
tobyspark | 0:1a9f9f36242e | 637 | |
tobyspark | 0:1a9f9f36242e | 638 | char line [ASCIILINESZ+1] ; |
tobyspark | 0:1a9f9f36242e | 639 | char section [ASCIILINESZ+1] ; |
tobyspark | 0:1a9f9f36242e | 640 | char key [ASCIILINESZ+1] ; |
tobyspark | 0:1a9f9f36242e | 641 | char tmp [ASCIILINESZ+1] ; |
tobyspark | 0:1a9f9f36242e | 642 | char val [ASCIILINESZ+1] ; |
tobyspark | 0:1a9f9f36242e | 643 | |
tobyspark | 0:1a9f9f36242e | 644 | int last=0 ; |
tobyspark | 0:1a9f9f36242e | 645 | int len ; |
tobyspark | 0:1a9f9f36242e | 646 | int lineno=0 ; |
tobyspark | 0:1a9f9f36242e | 647 | int errs=0; |
tobyspark | 0:1a9f9f36242e | 648 | |
tobyspark | 0:1a9f9f36242e | 649 | dictionary * dict ; |
tobyspark | 0:1a9f9f36242e | 650 | |
tobyspark | 0:1a9f9f36242e | 651 | if ((in=fopen(ininame, "r"))==NULL) { |
tobyspark | 0:1a9f9f36242e | 652 | fprintf(stderr, "iniparser: cannot open %s\n", ininame); |
tobyspark | 0:1a9f9f36242e | 653 | return NULL ; |
tobyspark | 0:1a9f9f36242e | 654 | } |
tobyspark | 0:1a9f9f36242e | 655 | |
tobyspark | 0:1a9f9f36242e | 656 | dict = dictionary_new(0) ; |
tobyspark | 0:1a9f9f36242e | 657 | if (!dict) { |
tobyspark | 0:1a9f9f36242e | 658 | fclose(in); |
tobyspark | 0:1a9f9f36242e | 659 | return NULL ; |
tobyspark | 0:1a9f9f36242e | 660 | } |
tobyspark | 0:1a9f9f36242e | 661 | |
tobyspark | 0:1a9f9f36242e | 662 | memset(line, 0, ASCIILINESZ); |
tobyspark | 0:1a9f9f36242e | 663 | memset(section, 0, ASCIILINESZ); |
tobyspark | 0:1a9f9f36242e | 664 | memset(key, 0, ASCIILINESZ); |
tobyspark | 0:1a9f9f36242e | 665 | memset(val, 0, ASCIILINESZ); |
tobyspark | 0:1a9f9f36242e | 666 | last=0 ; |
tobyspark | 0:1a9f9f36242e | 667 | |
tobyspark | 0:1a9f9f36242e | 668 | while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { |
tobyspark | 0:1a9f9f36242e | 669 | lineno++ ; |
tobyspark | 0:1a9f9f36242e | 670 | len = (int)strlen(line)-1; |
tobyspark | 0:1a9f9f36242e | 671 | if (len==0) |
tobyspark | 0:1a9f9f36242e | 672 | continue; |
tobyspark | 0:1a9f9f36242e | 673 | /* Safety check against buffer overflows */ |
tobyspark | 0:1a9f9f36242e | 674 | if (line[len]!='\n') { |
tobyspark | 0:1a9f9f36242e | 675 | fprintf(stderr, |
tobyspark | 0:1a9f9f36242e | 676 | "iniparser: input line too long in %s (%d)\n", |
tobyspark | 0:1a9f9f36242e | 677 | ininame, |
tobyspark | 0:1a9f9f36242e | 678 | lineno); |
tobyspark | 0:1a9f9f36242e | 679 | dictionary_del(dict); |
tobyspark | 0:1a9f9f36242e | 680 | fclose(in); |
tobyspark | 0:1a9f9f36242e | 681 | return NULL ; |
tobyspark | 0:1a9f9f36242e | 682 | } |
tobyspark | 0:1a9f9f36242e | 683 | /* Get rid of \n and spaces at end of line */ |
tobyspark | 0:1a9f9f36242e | 684 | while ((len>=0) && |
tobyspark | 0:1a9f9f36242e | 685 | ((line[len]=='\n') || (isspace(line[len])))) { |
tobyspark | 0:1a9f9f36242e | 686 | line[len]=0 ; |
tobyspark | 0:1a9f9f36242e | 687 | len-- ; |
tobyspark | 0:1a9f9f36242e | 688 | } |
tobyspark | 0:1a9f9f36242e | 689 | /* Detect multi-line */ |
tobyspark | 0:1a9f9f36242e | 690 | if (line[len]=='\\') { |
tobyspark | 0:1a9f9f36242e | 691 | /* Multi-line value */ |
tobyspark | 0:1a9f9f36242e | 692 | last=len ; |
tobyspark | 0:1a9f9f36242e | 693 | continue ; |
tobyspark | 0:1a9f9f36242e | 694 | } else { |
tobyspark | 0:1a9f9f36242e | 695 | last=0 ; |
tobyspark | 0:1a9f9f36242e | 696 | } |
tobyspark | 0:1a9f9f36242e | 697 | switch (iniparser_line(line, section, key, val)) { |
tobyspark | 0:1a9f9f36242e | 698 | case LINE_EMPTY: |
tobyspark | 0:1a9f9f36242e | 699 | case LINE_COMMENT: |
tobyspark | 0:1a9f9f36242e | 700 | break ; |
tobyspark | 0:1a9f9f36242e | 701 | |
tobyspark | 0:1a9f9f36242e | 702 | case LINE_SECTION: |
tobyspark | 0:1a9f9f36242e | 703 | errs = dictionary_set(dict, section, NULL); |
tobyspark | 0:1a9f9f36242e | 704 | break ; |
tobyspark | 0:1a9f9f36242e | 705 | |
tobyspark | 0:1a9f9f36242e | 706 | case LINE_VALUE: |
tobyspark | 0:1a9f9f36242e | 707 | sprintf(tmp, "%s:%s", section, key); |
tobyspark | 0:1a9f9f36242e | 708 | errs = dictionary_set(dict, tmp, val) ; |
tobyspark | 0:1a9f9f36242e | 709 | break ; |
tobyspark | 0:1a9f9f36242e | 710 | |
tobyspark | 0:1a9f9f36242e | 711 | case LINE_ERROR: |
tobyspark | 0:1a9f9f36242e | 712 | fprintf(stderr, "iniparser: syntax error in %s (%d):\n", |
tobyspark | 0:1a9f9f36242e | 713 | ininame, |
tobyspark | 0:1a9f9f36242e | 714 | lineno); |
tobyspark | 0:1a9f9f36242e | 715 | fprintf(stderr, "-> %s\n", line); |
tobyspark | 0:1a9f9f36242e | 716 | errs++ ; |
tobyspark | 0:1a9f9f36242e | 717 | break; |
tobyspark | 0:1a9f9f36242e | 718 | |
tobyspark | 0:1a9f9f36242e | 719 | default: |
tobyspark | 0:1a9f9f36242e | 720 | break ; |
tobyspark | 0:1a9f9f36242e | 721 | } |
tobyspark | 0:1a9f9f36242e | 722 | memset(line, 0, ASCIILINESZ); |
tobyspark | 0:1a9f9f36242e | 723 | last=0; |
tobyspark | 0:1a9f9f36242e | 724 | if (errs<0) { |
tobyspark | 0:1a9f9f36242e | 725 | fprintf(stderr, "iniparser: memory allocation failure\n"); |
tobyspark | 0:1a9f9f36242e | 726 | break ; |
tobyspark | 0:1a9f9f36242e | 727 | } |
tobyspark | 0:1a9f9f36242e | 728 | } |
tobyspark | 0:1a9f9f36242e | 729 | if (errs) { |
tobyspark | 0:1a9f9f36242e | 730 | dictionary_del(dict); |
tobyspark | 0:1a9f9f36242e | 731 | dict = NULL ; |
tobyspark | 0:1a9f9f36242e | 732 | } |
tobyspark | 0:1a9f9f36242e | 733 | fclose(in); |
tobyspark | 0:1a9f9f36242e | 734 | return dict ; |
tobyspark | 0:1a9f9f36242e | 735 | } |
tobyspark | 0:1a9f9f36242e | 736 | |
tobyspark | 0:1a9f9f36242e | 737 | /*-------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 738 | /** |
tobyspark | 0:1a9f9f36242e | 739 | @brief Free all memory associated to an ini dictionary |
tobyspark | 0:1a9f9f36242e | 740 | @param d Dictionary to free |
tobyspark | 0:1a9f9f36242e | 741 | @return void |
tobyspark | 0:1a9f9f36242e | 742 | |
tobyspark | 0:1a9f9f36242e | 743 | Free all memory associated to an ini dictionary. |
tobyspark | 0:1a9f9f36242e | 744 | It is mandatory to call this function before the dictionary object |
tobyspark | 0:1a9f9f36242e | 745 | gets out of the current context. |
tobyspark | 0:1a9f9f36242e | 746 | */ |
tobyspark | 0:1a9f9f36242e | 747 | /*--------------------------------------------------------------------------*/ |
tobyspark | 0:1a9f9f36242e | 748 | void iniparser_freedict(dictionary * d) |
tobyspark | 0:1a9f9f36242e | 749 | { |
tobyspark | 0:1a9f9f36242e | 750 | dictionary_del(d); |
tobyspark | 0:1a9f9f36242e | 751 | } |
tobyspark | 0:1a9f9f36242e | 752 | |
tobyspark | 0:1a9f9f36242e | 753 | /* vim: set ts=4 et sw=4 tw=75 */ |