1 /* ConfigParser.c - NeonServ v5.3
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "ConfigParser.h"
20 #define ENTRYTYPE_BLOCK 1
21 #define ENTRYTYPE_STRING 2
22 #define ENTRYTYPE_INTEGER 3
28 struct ConfigEntry *next;
31 static struct ConfigEntry *root_entry = NULL;
33 static char *parse_config_recursive(struct ConfigEntry *centry, char *buffer, int root_element);
34 static void free_entry_rekursiv(struct ConfigEntry *centry, int is_root_entry);
36 int loadConfig(const char *filename) {
38 f = fopen(filename, "rb");
43 fseek (f, 0, SEEK_END);
47 // allocate memory to contain the whole file:
48 char *buffer = (char*) malloc (sizeof(char)*lSize + 1);
54 // copy the file into the buffer:
55 size_t result = fread (buffer, 1, lSize, f);
56 if (result != lSize) {
64 // now parse the config file...
68 root_entry = malloc(sizeof(*root_entry));
69 if (!root_entry) return 0;
70 parse_config_recursive(root_entry, buffer, 1);
77 #define PARSER_FLAG_ESCAPED 0x01
78 #define PARSER_FLAG_BLOCK 0x02
79 #define PARSER_FLAG_STRING 0x04
80 #define PARSER_FLAG_EXPECT_END 0x08
81 #define PARSER_FLAG_NEXTCHAR 0x10
82 #define PARSER_FLAG_INTEGER 0x20
83 #define PARSER_FLAG_EOBN 0x40 /* End of Block name */
84 #define PARSER_FLAG_COMMAND 0x80
85 static char *parse_config_recursive(struct ConfigEntry *centry, char *buffer, int root_element) {
87 int type = (root_element ? ENTRYTYPE_BLOCK : 0);
90 struct ConfigEntry *sub_entrys = NULL;
92 if(flags & PARSER_FLAG_NEXTCHAR) {
97 flags |= PARSER_FLAG_NEXTCHAR;
98 if(flags & PARSER_FLAG_EOBN) {
99 flags &= ~(PARSER_FLAG_EOBN | PARSER_FLAG_NEXTCHAR);
100 struct ConfigEntry *new_entry = malloc(sizeof(*new_entry));
101 if (!new_entry) return buffer;
102 new_entry->name = strdup(cbuf);
103 buffer = parse_config_recursive(new_entry, buffer, 0);
105 new_entry->next = sub_entrys;
107 new_entry->next = NULL;
108 sub_entrys = new_entry;
109 centry->value = sub_entrys;
111 if(flags & PARSER_FLAG_ESCAPED) {
112 cbuf[cbufpos++] = *buffer;
113 flags &= ~PARSER_FLAG_ESCAPED;
116 if(flags & PARSER_FLAG_EXPECT_END) {
123 if(flags & PARSER_FLAG_STRING) {
125 cbuf[cbufpos] = '\0';
126 flags &= ~PARSER_FLAG_STRING;
127 if(type == ENTRYTYPE_STRING) {
128 flags |= PARSER_FLAG_EXPECT_END;
129 centry->value = strdup(cbuf);
130 } else if(type == ENTRYTYPE_BLOCK) {
131 flags |= PARSER_FLAG_EOBN;
133 } else if(*buffer == '\\')
134 flags |= PARSER_FLAG_ESCAPED;
136 cbuf[cbufpos++] = *buffer;
139 if(flags & PARSER_FLAG_INTEGER) {
140 if(!isdigit(*buffer)) {
141 cbuf[cbufpos] = '\0';
142 flags &= ~PARSER_FLAG_INTEGER;
143 if(type == ENTRYTYPE_INTEGER) {
144 flags |= PARSER_FLAG_EXPECT_END;
145 int *intbuf = malloc(sizeof(int));
146 *intbuf = atoi(cbuf);
147 centry->value = intbuf;
154 cbuf[cbufpos++] = *buffer;
157 if(flags & PARSER_FLAG_COMMAND) {
158 int found_command = 0;
161 buffer = strstr(buffer, "\n");
165 //simple search for the next */
166 buffer = strstr(buffer, "*/")+1;
169 flags &= ~PARSER_FLAG_COMMAND;
175 flags |= PARSER_FLAG_ESCAPED;
178 if(!(flags & PARSER_FLAG_STRING)) {
179 flags |= PARSER_FLAG_COMMAND;
183 flags |= PARSER_FLAG_BLOCK;
184 type = ENTRYTYPE_BLOCK;
187 if(flags & PARSER_FLAG_BLOCK)
188 flags &= ~PARSER_FLAG_BLOCK;
189 flags |= PARSER_FLAG_EXPECT_END;
192 flags |= PARSER_FLAG_STRING;
194 type = ENTRYTYPE_STRING;
211 type = ENTRYTYPE_INTEGER;
212 flags |= PARSER_FLAG_INTEGER;
214 cbuf[cbufpos++] = *buffer;
221 return buffer; //end of the buffer
224 int get_int_field(char *field_path) {
225 struct ConfigEntry *centry = root_entry;
226 char *a, *b = field_path;
227 struct ConfigEntry *subentry;
228 while((a = strstr(b, ".")) && centry) {
229 if(centry->type == ENTRYTYPE_BLOCK) {
231 for(subentry = centry->value; subentry; subentry = subentry->next) {
232 if(!stricmplen(subentry->name, b, a-b)) {
244 if(centry->type == ENTRYTYPE_BLOCK) {
246 for(subentry = centry->value; subentry; subentry = subentry->next) {
247 if(!stricmp(subentry->name, b)) {
257 if(centry->type == ENTRYTYPE_INTEGER)
258 return ((int *)centry->value)[0];
263 char *get_string_field(char *field_path) {
264 struct ConfigEntry *centry = root_entry;
265 char *a, *b = field_path;
266 struct ConfigEntry *subentry;
267 while((a = strstr(b, ".")) && centry) {
268 if(centry->type == ENTRYTYPE_BLOCK) {
270 for(subentry = centry->value; subentry; subentry = subentry->next) {
271 if(!stricmplen(subentry->name, b, a-b)) {
283 if(centry->type == ENTRYTYPE_BLOCK) {
285 for(subentry = centry->value; subentry; subentry = subentry->next) {
286 if(!stricmp(subentry->name, b)) {
296 if(centry->type == ENTRYTYPE_STRING)
297 return centry->value;
302 void free_loaded_config() {
304 free_entry_rekursiv(root_entry, 1);
309 static void free_entry_rekursiv(struct ConfigEntry *centry, int is_root_entry) {
310 if(centry->type == ENTRYTYPE_BLOCK) {
311 struct ConfigEntry *subentry, *nextentry;
312 for(subentry = centry->value; subentry; subentry = nextentry) {
313 nextentry = subentry->next;
314 free_entry_rekursiv(subentry, 0);
316 } else if(centry->type == ENTRYTYPE_STRING) {
318 } else if(centry->type == ENTRYTYPE_INTEGER) {