4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2009 Develer S.r.l. (http://www.develer.com/)
33 * \brief Ini file reader module.
35 * \author Luca Ottaviano <lottaviano@develer.com>
38 #include "ini_reader.h"
39 #include "cfg/cfg_ini_reader.h"
42 #include <stdlib.h> //strtol
45 static bool lineEmpty(const char *line)
49 if (!isspace((unsigned char)*line++))
56 * Returns when the line containing the section is found.
57 * The file pointer is positioned at the start of the next line or
58 * after the last non-empty line if the section is not found.
59 * Returns EOF if no section was found, 0 otherwise.
61 static int findSection(KFile *fd, const char *section, size_t section_len, char *line, size_t size)
63 kfile_off_t last_full = fd->seek_pos;
70 err = kfile_gets(fd, line, size);
72 /* Remember the last filled line in file */
74 last_full = fd->seek_pos;
76 /* accept only sections that begin at first char */
80 /* find the end-of-section character */
81 for (i = 0; i < size && *ptr != ']'; ++i, ++ptr)
84 /* The found section could be long that our section key */
88 /* did we find the correct section? */
89 if(strncmp(&line[1], section, section_len))
96 kfile_seek(fd, last_full, KSM_SEEK_SET);
101 * Fills the argument with the key found in line
103 static char *getKey(const char *line, char *key, size_t size)
105 /* null-terminated string */
106 while (isspace((unsigned char)*line))
109 while (*line != '=' && !isspace((unsigned char)*line) && size)
115 size ? (key[i] = '\0') : (key[i-1] = '\0');
120 * Fills the argument with the value found in line.
122 static char *getValue(const char *line, char *value, size_t size)
124 while (*line++ != '=')
126 while (isspace((unsigned char)*line))
129 while (*line && size)
131 value[i++] = *line++;
134 size ? (value[i] = '\0') : (value[i-1] = '\0');
139 * Look for key inside a section.
141 * The function reads lines from input file. It fills the line parameter to allow splitting
142 * the key-value couple. It returns with error if a new section begins and no key was found.
143 * \return 0 if key was found, EOF on errors.
145 static int findKey(KFile *fd, const char *key, char *line, size_t size)
149 kfile_off_t last_full = fd->seek_pos;
150 kfile_off_t key_pos = fd->seek_pos;
154 err = kfile_gets(fd, line, size);
156 getKey(line, curr_key, 30);
158 if (!strcmp(curr_key, key))
160 kfile_seek(fd, key_pos, KSM_SEEK_SET);
164 /* Remember the last filled line in the section */
165 if (!lineEmpty(line) && *line != '[')
166 last_full = fd->seek_pos;
167 key_pos = fd->seek_pos;
169 while (err != EOF && *line != '[');
170 kfile_seek(fd, last_full, KSM_SEEK_SET);
175 * On errors, the function returns EOF and fills the buffer with the default value.
177 int ini_getString(KFile *fd, const char *section, const char *key, const char *default_value, char *buf, size_t size)
179 char line[CONFIG_INI_MAX_LINE_LEN];
181 if (kfile_seek(fd, 0, KSM_SEEK_SET) == EOF)
184 if (findSection(fd, section, strlen(section), line, CONFIG_INI_MAX_LINE_LEN) == EOF)
187 if (findKey(fd, key, line, CONFIG_INI_MAX_LINE_LEN) == EOF)
190 getValue(line, buf, size);
194 strncpy(buf, default_value, size);
196 buf[size - 1] = '\0';
200 int ini_getInteger(KFile *fd, const char *section, const char *key, long default_value, long *val, int base)
202 char buf[CONFIG_INI_MAX_LINE_LEN];
204 if (ini_getString(fd, section, key, "", buf, sizeof(buf)) == EOF)
207 char **endptr = NULL;
208 *val = strtol(buf, endptr, base);
210 if (buf[0] == 0 || **endptr != 0)
216 *val = default_value;
221 * Return the position immediatly following the last non-empty line in the file,
222 * starting from current position.
223 * The file seek position is unchanged at function exit.
225 static kfile_off_t findLastLine(KFile *fd, char *line, size_t size)
227 kfile_off_t start = fd->seek_pos;
228 kfile_off_t last_full = start;
233 err = kfile_gets(fd, line, size);
234 if (!lineEmpty(line))
235 last_full = fd->seek_pos;
238 kfile_seek(fd, start, KSM_SEEK_SET);
242 int ini_setString(KFile *in, KFile *out, const char *section, const char *key, const char *value)
244 char line[CONFIG_INI_MAX_LINE_LEN];
246 if (kfile_seek(in, 0, KSM_SEEK_SET) == EOF)
249 if (kfile_seek(out, 0, KSM_SEEK_SET) == EOF)
252 bool section_found = false;
253 bool key_found = false;
254 if (findSection(in, section, strlen(section), line, CONFIG_INI_MAX_LINE_LEN) != EOF)
256 section_found = true;
257 key_found = (findKey(in, key, line, CONFIG_INI_MAX_LINE_LEN) != EOF);
260 kfile_off_t len = in->seek_pos;
263 if (kfile_seek(in, 0, KSM_SEEK_SET) == EOF)
265 if (kfile_copy(in, out, len) != len)
268 if (!section_found && value)
270 if ((size_t)kfile_printf(out, "\n[%s]\n", section) != (strlen(section) + 4))
275 if ((size_t)kfile_printf(out, "%s=%s\n", key, value) != (strlen(key) + strlen(value) + 2))
279 /* Skip the old line with the key */
281 kfile_gets(in, line, CONFIG_INI_MAX_LINE_LEN);
284 * Copy the rest of the input file.
285 * Do not return error if the copied bytes are less than expected
286 * but at least enough to write the last non-empty line.
287 * This is needed for example if the out KFile is of fixed size (like memories).
289 len = in->size - in->seek_pos;
290 kfile_off_t bytes_needed = findLastLine(in, line, CONFIG_INI_MAX_LINE_LEN) - in->seek_pos;
291 if (kfile_copy(in, out, len) < bytes_needed)
295 * Clear the rest of the out file in order to wipe out garbage if the resulting
296 * file is shorter than before.
298 kfile_off_t fill = out->size - out->seek_pos;
302 if (kfile_putc('\n', out) == EOF)
306 if (kfile_putc(' ', out) == EOF)