1 /*
2 * ini.c
3 */
4
5 #include "private.h"
6 #include "lub/string.h"
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <assert.h>
12 #include <ctype.h>
13
14 /*--------------------------------------------------------- */
lub_ini_init(lub_ini_t * this)15 void lub_ini_init(lub_ini_t *this)
16 {
17 assert(this);
18 memset(this, 0, sizeof(*this));
19 this->list = lub_list_new(lub_pair_compare);
20 }
21
22 /*--------------------------------------------------------- */
lub_ini_new(void)23 lub_ini_t *lub_ini_new(void)
24 {
25 lub_ini_t *this;
26
27 this = malloc(sizeof(*this));
28 if (this)
29 lub_ini_init(this);
30
31 return this;
32 }
33
34 /*--------------------------------------------------------- */
lub_ini_fini(lub_ini_t * this)35 void lub_ini_fini(lub_ini_t *this)
36 {
37 lub_list_node_t *iter;
38
39 assert(this);
40 while ((iter = lub_list__get_head(this->list))) {
41 lub_list_del(this->list, iter);
42 lub_pair_free((lub_pair_t *)lub_list_node__get_data(iter));
43 lub_list_node_free(iter);
44 }
45 lub_list_free(this->list);
46 }
47
48 /*--------------------------------------------------------- */
lub_ini_free(lub_ini_t * this)49 void lub_ini_free(lub_ini_t *this)
50 {
51 assert(this);
52 lub_ini_fini(this);
53 free(this);
54 }
55
56 /*--------------------------------------------------------- */
lub_ini_add(lub_ini_t * this,lub_pair_t * pair)57 void lub_ini_add(lub_ini_t *this, lub_pair_t *pair)
58 {
59 assert(this);
60 lub_list_add(this->list, pair);
61 }
62
63 /*--------------------------------------------------------- */
64 /* Find pair by name */
lub_ini_find_pair(const lub_ini_t * this,const char * name)65 lub_pair_t *lub_ini_find_pair(const lub_ini_t *this, const char *name)
66 {
67 lub_list_node_t *iter;
68 lub_pair_t *pair;
69
70 if (!this || !name)
71 return NULL;
72 /* Iterate elements */
73 for(iter = lub_list__get_head(this->list);
74 iter; iter = lub_list_node__get_next(iter)) {
75 int res;
76 pair = (lub_pair_t *)lub_list_node__get_data(iter);
77 res = strcmp(lub_pair__get_name(pair), name);
78 if (!res)
79 return pair;
80 if (res > 0) /* No chance to find name */
81 break;
82 }
83
84 return NULL;
85 }
86
87 /*--------------------------------------------------------- */
88 /* Find pair by name */
lub_ini_find(const lub_ini_t * this,const char * name)89 const char *lub_ini_find(const lub_ini_t *this, const char *name)
90 {
91 lub_pair_t *pair = lub_ini_find_pair(this, name);
92
93 if (!pair)
94 return NULL;
95 return lub_pair__get_value(pair);
96 }
97
98 /*--------------------------------------------------------- */
lub_ini_parse_str(lub_ini_t * this,const char * ini)99 int lub_ini_parse_str(lub_ini_t *this, const char *ini)
100 {
101 char *buffer;
102 char *saveptr = NULL;
103 char *line;
104
105 buffer = lub_string_dup(ini);
106 /* Now loop though each line */
107 for (line = strtok_r(buffer, "\n", &saveptr);
108 line; line = strtok_r(NULL, "\n", &saveptr)) {
109
110 char *str, *name, *value, *savestr = NULL, *ns = line;
111 const char *begin;
112 size_t len, offset, quoted;
113 char *rname, *rvalue;
114 lub_pair_t *pair;
115
116 if (!*ns) /* Empty */
117 continue;
118 while (*ns && isspace(*ns))
119 ns++;
120 if ('#' == *ns) /* Comment */
121 continue;
122 if ('=' == *ns) /* Broken string */
123 continue;
124 str = lub_string_dup(ns);
125 name = strtok_r(str, "=", &savestr);
126 if (!name) {
127 lub_string_free(str);
128 continue;
129 }
130 value = strtok_r(NULL, "=", &savestr);
131 begin = lub_string_nextword(name, &len, &offset, "ed);
132 rname = lub_string_dupn(begin, len);
133 if (!value) /* Empty value */
134 rvalue = NULL;
135 else {
136 begin = lub_string_nextword(value, &len, &offset, "ed);
137 rvalue = lub_string_dupn(begin, len);
138 }
139 pair = lub_pair_new(rname, rvalue);
140 lub_ini_add(this, pair);
141 lub_string_free(rname);
142 lub_string_free(rvalue);
143 lub_string_free(str);
144 }
145 lub_string_free(buffer);
146
147 return 0;
148 }
149
150 /*--------------------------------------------------------- */
lub_ini_parse_file(lub_ini_t * this,const char * fn)151 int lub_ini_parse_file(lub_ini_t *this, const char *fn)
152 {
153 int ret = -1;
154 FILE *f;
155 char *buf;
156 unsigned int p = 0;
157 const int chunk_size = 128;
158 int size = chunk_size;
159
160 if (!fn || !*fn)
161 return -1;
162 f = fopen(fn, "r");
163 if (!f)
164 return -1;
165
166 buf = malloc(size);
167 while (fgets(buf + p, size - p, f)) {
168 char *tmp;
169 if (feof(f) || strchr(buf + p, '\n') || strchr(buf + p, '\r')) {
170 lub_ini_parse_str(this, buf);
171 p = 0;
172 continue;
173 }
174 p = size - 1;
175 size += chunk_size;
176 tmp = realloc(buf, size);
177 if (!tmp)
178 goto error;
179 buf = tmp;
180 }
181
182 ret = 0;
183 error:
184 free(buf);
185 fclose(f);
186
187 return ret;
188 }
189
190 /*--------------------------------------------------------- */
lub_ini__get_head(lub_ini_t * this)191 lub_ini_node_t *lub_ini__get_head(lub_ini_t *this)
192 {
193 return lub_list__get_head(this->list);
194 }
195
196 /*--------------------------------------------------------- */
lub_ini__get_tail(lub_ini_t * this)197 lub_ini_node_t *lub_ini__get_tail(lub_ini_t *this)
198 {
199 return lub_list__get_tail(this->list);
200 }
201
202 /*--------------------------------------------------------- */
203
lub_ini__get_next(lub_ini_node_t * node)204 lub_ini_node_t *lub_ini__get_next(lub_ini_node_t *node)
205 {
206 return lub_list_node__get_next(node);
207 }
208
209 /*--------------------------------------------------------- */
210
lub_ini__get_prev(lub_ini_node_t * node)211 lub_ini_node_t *lub_ini__get_prev(lub_ini_node_t *node)
212 {
213 return lub_list_node__get_next(node);
214 }
215
216 /*--------------------------------------------------------- */
217
lub_ini__iter_data(lub_ini_node_t * node)218 lub_pair_t *lub_ini__iter_data(lub_ini_node_t *node)
219 {
220 return (lub_pair_t *)lub_list_node__get_data(node);
221 }
222
223 /*--------------------------------------------------------- */
224