1 /* ConfigParser.c - NeonServ v5.2
2 * Copyright (C) 2011 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);
49 if (buffer == NULL) return 0;
51 // copy the file into the buffer:
52 size_t result = fread (buffer, 1, lSize, f);
53 if (result != lSize) return 0;
56 // now parse the config file...
60 root_entry = malloc(sizeof(*root_entry));
61 if (!root_entry) return 0;
62 parse_config_recursive(root_entry, buffer, 1);
69 #define PARSER_FLAG_ESCAPED 0x01
70 #define PARSER_FLAG_BLOCK 0x02
71 #define PARSER_FLAG_STRING 0x04
72 #define PARSER_FLAG_EXPECT_END 0x08
73 #define PARSER_FLAG_NEXTCHAR 0x10
74 #define PARSER_FLAG_INTEGER 0x20
75 #define PARSER_FLAG_EOBN 0x40 /* End of Block name */
76 #define PARSER_FLAG_COMMAND 0x80
77 static char *parse_config_recursive(struct ConfigEntry *centry, char *buffer, int root_element) {
79 int type = (root_element ? ENTRYTYPE_BLOCK : 0);
82 struct ConfigEntry *sub_entrys = NULL;
84 if(flags & PARSER_FLAG_NEXTCHAR) {
89 flags |= PARSER_FLAG_NEXTCHAR;
90 if(flags & PARSER_FLAG_EOBN) {
91 flags &= ~(PARSER_FLAG_EOBN | PARSER_FLAG_NEXTCHAR);
92 struct ConfigEntry *new_entry = malloc(sizeof(*new_entry));
93 if (!new_entry) return buffer;
94 new_entry->name = strdup(cbuf);
95 buffer = parse_config_recursive(new_entry, buffer, 0);
97 new_entry->next = sub_entrys;
99 new_entry->next = NULL;
100 sub_entrys = new_entry;
101 centry->value = sub_entrys;
103 if(flags & PARSER_FLAG_ESCAPED) {
104 cbuf[cbufpos++] = *buffer;
105 flags &= ~PARSER_FLAG_ESCAPED;
108 if(flags & PARSER_FLAG_EXPECT_END) {
115 if(flags & PARSER_FLAG_STRING) {
117 cbuf[cbufpos] = '\0';
118 flags &= ~PARSER_FLAG_STRING;
119 if(type == ENTRYTYPE_STRING) {
120 flags |= PARSER_FLAG_EXPECT_END;
121 centry->value = strdup(cbuf);
122 } else if(type == ENTRYTYPE_BLOCK) {
123 flags |= PARSER_FLAG_EOBN;
125 } else if(*buffer == '\\')
126 flags |= PARSER_FLAG_ESCAPED;
128 cbuf[cbufpos++] = *buffer;
131 if(flags & PARSER_FLAG_INTEGER) {
132 if(!isdigit(*buffer)) {
133 cbuf[cbufpos] = '\0';
134 flags &= ~PARSER_FLAG_INTEGER;
135 if(type == ENTRYTYPE_INTEGER) {
136 flags |= PARSER_FLAG_EXPECT_END;
137 int *intbuf = malloc(sizeof(int));
138 *intbuf = atoi(cbuf);
139 centry->value = intbuf;
146 cbuf[cbufpos++] = *buffer;
149 if(flags & PARSER_FLAG_COMMAND) {
150 int found_command = 0;
153 buffer = strstr(buffer, "\n");
157 //simple search for the next */
158 buffer = strstr(buffer, "*/")+1;
161 flags &= ~PARSER_FLAG_COMMAND;
167 flags |= PARSER_FLAG_ESCAPED;
170 if(!(flags & PARSER_FLAG_STRING)) {
171 flags |= PARSER_FLAG_COMMAND;
175 flags |= PARSER_FLAG_BLOCK;
176 type = ENTRYTYPE_BLOCK;
179 if(flags & PARSER_FLAG_BLOCK)
180 flags &= ~PARSER_FLAG_BLOCK;
181 flags |= PARSER_FLAG_EXPECT_END;
184 flags |= PARSER_FLAG_STRING;
186 type = ENTRYTYPE_STRING;
203 type = ENTRYTYPE_INTEGER;
204 flags |= PARSER_FLAG_INTEGER;
206 cbuf[cbufpos++] = *buffer;
213 return buffer; //end of the buffer
216 int get_int_field(char *field_path) {
217 struct ConfigEntry *centry = root_entry;
218 char *a, *b = field_path;
219 struct ConfigEntry *subentry;
220 while((a = strstr(b, ".")) && centry) {
221 if(centry->type == ENTRYTYPE_BLOCK) {
223 for(subentry = centry->value; subentry; subentry = subentry->next) {
224 if(!stricmplen(subentry->name, b, a-b)) {
236 if(centry->type == ENTRYTYPE_BLOCK) {
238 for(subentry = centry->value; subentry; subentry = subentry->next) {
239 if(!stricmp(subentry->name, b)) {
249 if(centry->type == ENTRYTYPE_INTEGER)
250 return ((int *)centry->value)[0];
255 char *get_string_field(char *field_path) {
256 struct ConfigEntry *centry = root_entry;
257 char *a, *b = field_path;
258 struct ConfigEntry *subentry;
259 while((a = strstr(b, ".")) && centry) {
260 if(centry->type == ENTRYTYPE_BLOCK) {
262 for(subentry = centry->value; subentry; subentry = subentry->next) {
263 if(!stricmplen(subentry->name, b, a-b)) {
275 if(centry->type == ENTRYTYPE_BLOCK) {
277 for(subentry = centry->value; subentry; subentry = subentry->next) {
278 if(!stricmp(subentry->name, b)) {
288 if(centry->type == ENTRYTYPE_STRING)
289 return centry->value;
294 void free_loaded_config() {
296 free_entry_rekursiv(root_entry, 1);
301 static void free_entry_rekursiv(struct ConfigEntry *centry, int is_root_entry) {
302 if(centry->type == ENTRYTYPE_BLOCK) {
303 struct ConfigEntry *subentry, *nextentry;
304 for(subentry = centry->value; subentry; subentry = nextentry) {
305 nextentry = subentry->next;
306 free_entry_rekursiv(subentry, 0);
308 } else if(centry->type == ENTRYTYPE_STRING) {
310 } else if(centry->type == ENTRYTYPE_INTEGER) {