ini_reader.c
Go to the documentation of this file.
00001 00038 #include "ini_reader.h" 00039 #include "cfg/cfg_ini_reader.h" 00040 #include <string.h> 00041 #include <stdio.h> 00042 #include <stdlib.h> //strtol 00043 #include <ctype.h> 00044 00045 static bool lineEmpty(const char *line) 00046 { 00047 while (*line) 00048 { 00049 if (!isspace((unsigned char)*line++)) 00050 return false; 00051 } 00052 return true; 00053 } 00054 00055 /* 00056 * Returns when the line containing the section is found. 00057 * The file pointer is positioned at the start of the next line or 00058 * after the last non-empty line if the section is not found. 00059 * Returns EOF if no section was found, 0 otherwise. 00060 */ 00061 static int findSection(KFile *fd, const char *section, size_t section_len, char *line, size_t size) 00062 { 00063 kfile_off_t last_full = fd->seek_pos; 00064 00065 int err; 00066 do 00067 { 00068 char *ptr = line; 00069 unsigned i; 00070 err = kfile_gets(fd, line, size); 00071 00072 /* Remember the last filled line in file */ 00073 if (!lineEmpty(line)) 00074 last_full = fd->seek_pos; 00075 00076 /* accept only sections that begin at first char */ 00077 if (*ptr++ != '[') 00078 continue; 00079 00080 /* find the end-of-section character */ 00081 for (i = 0; i < size && *ptr != ']'; ++i, ++ptr) 00082 ; 00083 00084 /* The found section could be long that our section key */ 00085 if (section_len != i) 00086 continue; 00087 00088 /* did we find the correct section? */ 00089 if(strncmp(&line[1], section, section_len)) 00090 continue; 00091 else 00092 return 0; 00093 } 00094 while (err != EOF); 00095 00096 kfile_seek(fd, last_full, KSM_SEEK_SET); 00097 return EOF; 00098 } 00099 00100 /* 00101 * Fills the argument with the key found in line 00102 */ 00103 static char *getKey(const char *line, char *key, size_t size) 00104 { 00105 /* null-terminated string */ 00106 while (isspace((unsigned char)*line)) 00107 ++line; 00108 int i = 0; 00109 while (*line != '=' && !isspace((unsigned char)*line) && size) 00110 { 00111 key[i++] = *line; 00112 ++line; 00113 --size; 00114 } 00115 size ? (key[i] = '\0') : (key[i-1] = '\0'); 00116 return key; 00117 } 00118 00119 /* 00120 * Fills the argument with the value found in line. 00121 */ 00122 static char *getValue(const char *line, char *value, size_t size) 00123 { 00124 while (*line++ != '=') 00125 ; 00126 while (isspace((unsigned char)*line)) 00127 ++line; 00128 int i = 0; 00129 while (*line && size) 00130 { 00131 value[i++] = *line++; 00132 --size; 00133 } 00134 size ? (value[i] = '\0') : (value[i-1] = '\0'); 00135 return value; 00136 } 00137 00145 static int findKey(KFile *fd, const char *key, char *line, size_t size) 00146 { 00147 int err; 00148 char curr_key[30]; 00149 kfile_off_t last_full = fd->seek_pos; 00150 kfile_off_t key_pos = fd->seek_pos; 00151 00152 do 00153 { 00154 err = kfile_gets(fd, line, size); 00155 00156 getKey(line, curr_key, 30); 00157 /* check key */ 00158 if (!strcmp(curr_key, key)) 00159 { 00160 kfile_seek(fd, key_pos, KSM_SEEK_SET); 00161 return 0; 00162 } 00163 00164 /* Remember the last filled line in the section */ 00165 if (!lineEmpty(line) && *line != '[') 00166 last_full = fd->seek_pos; 00167 key_pos = fd->seek_pos; 00168 } 00169 while (err != EOF && *line != '['); 00170 kfile_seek(fd, last_full, KSM_SEEK_SET); 00171 return EOF; 00172 } 00173 00174 /* 00175 * On errors, the function returns EOF and fills the buffer with the default value. 00176 */ 00177 int ini_getString(KFile *fd, const char *section, const char *key, const char *default_value, char *buf, size_t size) 00178 { 00179 char line[CONFIG_INI_MAX_LINE_LEN]; 00180 00181 if (kfile_seek(fd, 0, KSM_SEEK_SET) == EOF) 00182 goto error; 00183 00184 if (findSection(fd, section, strlen(section), line, CONFIG_INI_MAX_LINE_LEN) == EOF) 00185 goto error; 00186 00187 if (findKey(fd, key, line, CONFIG_INI_MAX_LINE_LEN) == EOF) 00188 goto error; 00189 else 00190 getValue(line, buf, size); 00191 return 0; 00192 00193 error: 00194 strncpy(buf, default_value, size); 00195 if (size > 0) 00196 buf[size - 1] = '\0'; 00197 return EOF; 00198 } 00199 00200 int ini_getInteger(KFile *fd, const char *section, const char *key, long default_value, long *val, int base) 00201 { 00202 char buf[CONFIG_INI_MAX_LINE_LEN]; 00203 00204 if (ini_getString(fd, section, key, "", buf, sizeof(buf)) == EOF) 00205 goto error; 00206 00207 char **endptr = NULL; 00208 *val = strtol(buf, endptr, base); 00209 00210 if (buf[0] == 0 || **endptr != 0) 00211 goto error; 00212 00213 return 0; 00214 00215 error: 00216 *val = default_value; 00217 return EOF; 00218 } 00219 00220 /* 00221 * Return the position immediatly following the last non-empty line in the file, 00222 * starting from current position. 00223 * The file seek position is unchanged at function exit. 00224 */ 00225 static kfile_off_t findLastLine(KFile *fd, char *line, size_t size) 00226 { 00227 kfile_off_t start = fd->seek_pos; 00228 kfile_off_t last_full = start; 00229 00230 int err; 00231 do 00232 { 00233 err = kfile_gets(fd, line, size); 00234 if (!lineEmpty(line)) 00235 last_full = fd->seek_pos; 00236 } 00237 while (err != EOF); 00238 kfile_seek(fd, start, KSM_SEEK_SET); 00239 return last_full; 00240 } 00241 00242 int ini_setString(KFile *in, KFile *out, const char *section, const char *key, const char *value) 00243 { 00244 char line[CONFIG_INI_MAX_LINE_LEN]; 00245 00246 if (kfile_seek(in, 0, KSM_SEEK_SET) == EOF) 00247 return EOF; 00248 00249 if (kfile_seek(out, 0, KSM_SEEK_SET) == EOF) 00250 return EOF; 00251 00252 bool section_found = false; 00253 bool key_found = false; 00254 if (findSection(in, section, strlen(section), line, CONFIG_INI_MAX_LINE_LEN) != EOF) 00255 { 00256 section_found = true; 00257 key_found = (findKey(in, key, line, CONFIG_INI_MAX_LINE_LEN) != EOF); 00258 } 00259 00260 kfile_off_t len = in->seek_pos; 00261 00262 /* Copy until key */ 00263 if (kfile_seek(in, 0, KSM_SEEK_SET) == EOF) 00264 return EOF; 00265 if (kfile_copy(in, out, len) != len) 00266 return EOF; 00267 00268 if (!section_found && value) 00269 { 00270 if ((size_t)kfile_printf(out, "\n[%s]\n", section) != (strlen(section) + 4)) 00271 return EOF; 00272 } 00273 if (value) 00274 { 00275 if ((size_t)kfile_printf(out, "%s=%s\n", key, value) != (strlen(key) + strlen(value) + 2)) 00276 return EOF; 00277 } 00278 00279 /* Skip the old line with the key */ 00280 if (key_found) 00281 kfile_gets(in, line, CONFIG_INI_MAX_LINE_LEN); 00282 00283 /* 00284 * Copy the rest of the input file. 00285 * Do not return error if the copied bytes are less than expected 00286 * but at least enough to write the last non-empty line. 00287 * This is needed for example if the out KFile is of fixed size (like memories). 00288 */ 00289 len = in->size - in->seek_pos; 00290 kfile_off_t bytes_needed = findLastLine(in, line, CONFIG_INI_MAX_LINE_LEN) - in->seek_pos; 00291 if (kfile_copy(in, out, len) < bytes_needed) 00292 return EOF; 00293 00294 /* 00295 * Clear the rest of the out file in order to wipe out garbage if the resulting 00296 * file is shorter than before. 00297 */ 00298 kfile_off_t fill = out->size - out->seek_pos; 00299 00300 if (fill--) 00301 { 00302 if (kfile_putc('\n', out) == EOF) 00303 return EOF; 00304 while (fill--) 00305 { 00306 if (kfile_putc(' ', out) == EOF) 00307 return EOF; 00308 } 00309 } 00310 00311 return 0; 00312 } 00313
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)