src/server/config/serverconfig.c

changeset 417
90805bb9fbd6
parent 415
d938228c382e
child 418
b7dcc9c4f270
equal deleted inserted replaced
416:e2093ca0ef90 417:90805bb9fbd6
42 FILE *in = fopen(file, "r"); 42 FILE *in = fopen(file, "r");
43 if(in == NULL) { 43 if(in == NULL) {
44 return NULL; 44 return NULL;
45 } 45 }
46 46
47 CxMempool *mp = cxBasicMempoolCreate(512);
48 if(!mp) {
49 fclose(in);
50 return NULL;
51 }
52
47 CxBuffer buf; 53 CxBuffer buf;
48 cxBufferInit(&buf, NULL, 16384, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); 54 if(cxBufferInit(&buf, NULL, 16384, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS)) {
55 fclose(in);
56 cxMempoolDestroy(mp);
57 return NULL;
58 }
49 59
50 //ucx_stream_copy(in, buf, (read_func)fread, (write_func)ucx_buffer_write); 60 //ucx_stream_copy(in, buf, (read_func)fread, (write_func)ucx_buffer_write);
51 char readbuf[2048]; 61 char readbuf[2048];
52 size_t r; 62 size_t r;
53 while((r = fread(readbuf, 1, 2048, in)) > 0) { 63 while((r = fread(readbuf, 1, 2048, in)) > 0) {
54 cxBufferWrite(readbuf, 1, r, &buf); 64 cxBufferWrite(readbuf, 1, r, &buf);
55 } 65 }
56 fclose(in); 66 fclose(in);
57 67
58 ServerConfig *scfg = serverconfig_parse(cx_strn(buf.space, buf.size)); 68 ConfigParser2 parser;
69 ZERO(&parser, sizeof(ConfigParser2));
70 parser.mp = mp;
71 parser.allow_hierarchy = true;
72 ServerConfig *scfg = serverconfig_parse(&parser, cx_strn(buf.space, buf.size));
59 73
60 cxBufferDestroy(&buf); 74 cxBufferDestroy(&buf);
61 return scfg; 75 return scfg;
62 } 76 }
63 77
188 elm->next = NULL; 202 elm->next = NULL;
189 cx_linked_list_prepend((void**)stack, NULL, -1, offsetof(ConfigNodeStack, next), elm); 203 cx_linked_list_prepend((void**)stack, NULL, -1, offsetof(ConfigNodeStack, next), elm);
190 return 0; 204 return 0;
191 } 205 }
192 206
193 ServerConfig* serverconfig_parse(cxstring content) { 207 ServerConfig* serverconfig_parse(ConfigParser2 *parser, cxstring content) {
194 CxMempool *mp = cxBasicMempoolCreate(512); 208 CxMempool *mp = parser->mp;
195 if(!mp) return NULL;
196 CxAllocator *a = (CxAllocator*)mp->allocator; 209 CxAllocator *a = (CxAllocator*)mp->allocator;
197 210
198 ServerConfig *config = cxMalloc(a, sizeof(ServerConfig)); 211 ServerConfig *config = cxMalloc(a, sizeof(ServerConfig));
199 if(!config) { 212 if(!config) {
200 cxMempoolDestroy(mp); 213 cxMempoolDestroy(mp);
246 ConfigNode *parent = node_stack->node; 259 ConfigNode *parent = node_stack->node;
247 if(current->type == CONFIG_NODE_CLOSE_OBJECT) { 260 if(current->type == CONFIG_NODE_CLOSE_OBJECT) {
248 // this is a newline after a object is closed with '}' 261 // this is a newline after a object is closed with '}'
249 // the line containing "}\n" should be added to the object 262 // the line containing "}\n" should be added to the object
250 parent->text_end = line_cp; 263 parent->text_end = line_cp;
264 // validate
265 if(parser->validateObjEnd && parser->validateObjEnd(parser, parent)) {
266 // validation failed
267 err = 1;
268 break;
269 }
251 // done with this object, remove it from the stack 270 // done with this object, remove it from the stack
252 ConfigNodeStack *remove_item = node_stack; 271 ConfigNodeStack *remove_item = node_stack;
253 node_stack = node_stack->next; 272 node_stack = node_stack->next;
254 cxFree(a, remove_item); 273 cxFree(a, remove_item);
255 } else if(current->type == CONFIG_NODE_OPEN_OBJECT) { 274 } else if(current->type == CONFIG_NODE_OPEN_OBJECT) {
259 cxFree(a, obj->text_begin.ptr); 278 cxFree(a, obj->text_begin.ptr);
260 cxFree(a, line_cp.ptr); 279 cxFree(a, line_cp.ptr);
261 obj->text_begin = new_textbegin; 280 obj->text_begin = new_textbegin;
262 } else { 281 } else {
263 // normal line containing a directive, space or comment 282 // normal line containing a directive, space or comment
283 if(parser->validateDirective && parser->validateDirective(parser, current)) {
284 err = 1;
285 break;
286 }
264 // add it to parent node 287 // add it to parent node
265 current->text_begin = line_cp; 288 current->text_begin = line_cp;
266 CFG_NODE_ADD(&parent->children_begin, &parent->children_end, current); 289 CFG_NODE_ADD(&parent->children_begin, &parent->children_end, current);
267 } 290 }
268 291
269 // obj points to the previous node that started as a directive 292 // obj points to the previous node that started as a directive
270 // the type is set to CONFIG_NODE_OBECT if it was followed by 293 // the type is set to CONFIG_NODE_OBECT if it was followed by
271 // a '{' character 294 // a '{' character
272 if(obj && obj->type == CONFIG_NODE_OBJECT) { 295 if(obj && obj->type == CONFIG_NODE_OBJECT) {
273 // new object started, add it to the stack 296 // new object started
297 if(parser->validateObjBegin && parser->validateObjBegin(parser, obj)) {
298 // validation callback failed
299 err = 1;
300 break;
301 }
302
303 // add it to the stack
274 nodestack_prepend(a, &node_stack, obj); 304 nodestack_prepend(a, &node_stack, obj);
275 obj = NULL; 305 obj = NULL;
276 } 306 }
277 307
278 current = cxCalloc(a, 1, sizeof(ConfigNode)); 308 current = cxCalloc(a, 1, sizeof(ConfigNode));
284 case CFG_TOKEN: { 314 case CFG_TOKEN: {
285 // normal text token 315 // normal text token
286 // either a directive/obj name, parameter or { } 316 // either a directive/obj name, parameter or { }
287 317
288 if(!cx_strcmp(token.content, cx_str("{"))) { 318 if(!cx_strcmp(token.content, cx_str("{"))) {
319 // check if the parser allows an object hierarchy
320 if(!parser->allow_hierarchy) {
321 parser->error = CONFIG_PARSER_SYNTAX_ERROR;
322 err = 1;
323 break;
324 }
325
289 // obj is pointing to the previous node that started 326 // obj is pointing to the previous node that started
290 // a directive 327 // a directive
291 if(!obj) { 328 if(!obj) {
292 err = 1; 329 err = 1;
293 break; 330 break;
295 obj->type = CONFIG_NODE_OBJECT; 332 obj->type = CONFIG_NODE_OBJECT;
296 if(current != obj) { 333 if(current != obj) {
297 current->type = CONFIG_NODE_OPEN_OBJECT; 334 current->type = CONFIG_NODE_OPEN_OBJECT;
298 } 335 }
299 } else if(!cx_strcmp(token.content, cx_str("}"))) { 336 } else if(!cx_strcmp(token.content, cx_str("}"))) {
337 // check if the parser allows an object hierarchy
338 if(!parser->allow_hierarchy) {
339 parser->error = CONFIG_PARSER_SYNTAX_ERROR;
340 err = 1;
341 break;
342 }
343
300 obj_closed = 1; // force newline before next directive 344 obj_closed = 1; // force newline before next directive
301 obj = NULL; 345 obj = NULL;
302 current->type = CONFIG_NODE_CLOSE_OBJECT; 346 current->type = CONFIG_NODE_CLOSE_OBJECT;
303 } else { 347 } else {
304 if(obj_closed) { 348 if(obj_closed) {

mercurial