1 // Supports very simple ini files. Structure:
2 // - data is in lines, key=value
3 // - # or ; starts a comment line
4 // - lines without = are ignored, too
6 HEADER #include <string.h>
13 HEADER struct inifile_entry {
16 HEADER struct inifile_entry *next;
19 HEADER struct inifile {
20 HEADER struct inifile_entry *first;
23 // Parses an inifile. When you're done, you can free the whole thing
24 // (including all the entries and the strings) by freeing the pointer
25 // that this function returns.
26 PUBLIC_FN struct inifile *parse_inifile(char *f) {
27 int n_of_lines = count_char_occurences(f, '\n')+1;
28 size_t worst_case_size = strlen(f) +
29 n_of_lines*sizeof(struct inifile_entry) +
30 sizeof(struct inifile);
32 char *buf = malloc(worst_case_size);
33 if (buf == NULL) return NULL;
35 struct inifile *head = (void*)buf;
36 void *buf_ = (void*)(head+1);
38 struct inifile_entry **nextp = &head->first;
41 char *nl = strchr(f, '\n');
42 if (!nl) nl=f+strlen(f);
43 if (*f == '#' || *f == ';') goto next;
44 char *eqsign = strchr(f, '=');
46 if (eqsign > nl) goto next;
48 struct inifile_entry *e = buf_; buf_ = e+1;
49 *nextp = e; nextp = &e->next;
51 int keylen = eqsign-key;
52 char *value = eqsign+1;
53 int valuelen = nl-value;
54 e->key = buf_; buf_+=keylen+1;
55 memcpyn(e->key, key, keylen);
56 trim_end(e->key, " \r");
57 e->value = buf_; buf_+=valuelen+1;
58 memcpyn(e->value, value, valuelen);
59 trim_end(e->value, " \r");
71 PUBLIC_FN struct inifile *fslurp_inifile(int fd) {
72 char *f = slurp_fd(fd, NULL, 0);
73 if (f == NULL) return NULL;
74 struct inifile *r = parse_inifile(f);
81 PUBLIC_FN struct inifile *slurp_inifile(char *path) {
82 int fd = open(path, O_RDONLY);
83 if (fd == -1) return NULL;
84 struct inifile *r = fslurp_inifile(fd);
91 PUBLIC_FN char *inifile_lookup(struct inifile *inf, char *key) {
92 for (struct inifile_entry *e = inf->first; e; e=e->next) {
93 if (streq(e->key, key)) return e->value;