1 // Copyright (2013) Jann Horn <jann@thejh.net>
3 // Supports very simple ini files. Structure:
4 // - data is in lines, key=value
5 // - # or ; starts a comment line
6 // - lines without = are ignored, too
8 HEADER #include <string.h>
15 HEADER struct inifile_entry {
18 HEADER struct inifile_entry *next;
21 HEADER struct inifile {
22 HEADER struct inifile_entry *first;
25 // Parses an inifile. When you're done, you can free the whole thing
26 // (including all the entries and the strings) by freeing the pointer
27 // that this function returns.
28 PUBLIC_FN struct inifile *parse_inifile(char *f) {
29 int n_of_lines = count_char_occurences(f, '\n')+1;
30 size_t worst_case_size = strlen(f) +
31 n_of_lines*sizeof(struct inifile_entry) +
32 sizeof(struct inifile);
34 char *buf = malloc(worst_case_size);
35 if (buf == NULL) return NULL;
37 struct inifile *head = (void*)buf;
38 void *buf_ = (void*)(head+1);
40 struct inifile_entry **nextp = &head->first;
43 char *nl = strchr(f, '\n');
44 if (!nl) nl=f+strlen(f);
45 if (*f == '#' || *f == ';') goto next;
46 char *eqsign = strchr(f, '=');
48 if (eqsign > nl) goto next;
50 struct inifile_entry *e = buf_; buf_ = e+1;
51 *nextp = e; nextp = &e->next;
53 int keylen = eqsign-key;
54 char *value = eqsign+1;
55 int valuelen = nl-value;
56 e->key = buf_; buf_+=keylen+1;
57 memcpyn(e->key, key, keylen);
58 trim_end(e->key, " \r");
59 e->value = buf_; buf_+=valuelen+1;
60 memcpyn(e->value, value, valuelen);
61 trim_end(e->value, " \r");
73 PUBLIC_FN struct inifile *fslurp_inifile(int fd) {
74 char *f = slurp_fd(fd, NULL, 0);
75 if (f == NULL) return NULL;
76 struct inifile *r = parse_inifile(f);
83 PUBLIC_FN struct inifile *slurp_inifile(char *path) {
84 int fd = open(path, O_RDONLY);
85 if (fd == -1) return NULL;
86 struct inifile *r = fslurp_inifile(fd);
93 PUBLIC_FN char *inifile_lookup(struct inifile *inf, char *key) {
94 for (struct inifile_entry *e = inf->first; e; e=e->next) {
95 if (streq(e->key, key)) return e->value;