--- a/src/server/config/serverconfig.c Sun Nov 06 17:41:39 2022 +0100 +++ b/src/server/config/serverconfig.c Mon Nov 07 17:59:44 2022 +0100 @@ -34,26 +34,52 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> +#include <errno.h> #include <cx/buffer.h> #include <cx/utils.h> ServerConfig* serverconfig_load(const char *file) { - FILE *in = fopen(file, "r"); - if(in == NULL) { + CxMempool *mp = cxBasicMempoolCreate(512); + if(!mp) { + return NULL; + } + + ConfigParser2 parser; + memset(&parser, 0, sizeof(ConfigParser2)); + parser.mp = mp; + parser.allow_hierarchy = true; + ConfigNode *root = serverconfig_load_file(&parser, file); + if(!root) { + cxMempoolDestroy(mp); return NULL; } - CxMempool *mp = cxBasicMempoolCreate(512); - if(!mp) { - fclose(in); + ServerConfig *scfg = cxMalloc(mp->allocator, sizeof(ServerConfig)); + if(!scfg) { + cxMempoolDestroy(mp); + return NULL; + } + scfg->root = root; + scfg->mp = mp; + scfg->tab = cx_str("\t"); + + return scfg; +} + +ConfigNode* serverconfig_load_file(ConfigParser2 *parser, const char *file) { + FILE *in = fopen(file, "r"); + if(in == NULL) { + parser->error = CONFIG_PARSER_IO_ERROR; + parser->io_errno = errno; return NULL; } + // temporary buffer to store the file content CxBuffer buf; if(cxBufferInit(&buf, NULL, 16384, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS)) { fclose(in); - cxMempoolDestroy(mp); + parser->error = CONFIG_PARSER_OOM; return NULL; } @@ -65,14 +91,9 @@ } fclose(in); - ConfigParser2 parser; - ZERO(&parser, sizeof(ConfigParser2)); - parser.mp = mp; - parser.allow_hierarchy = true; - ServerConfig *scfg = serverconfig_parse(&parser, cx_strn(buf.space, buf.size)); - + ConfigNode *root = serverconfig_parse(parser, cx_strn(buf.space, buf.size)); cxBufferDestroy(&buf); - return scfg; + return root; } @@ -204,17 +225,10 @@ return 0; } -ServerConfig* serverconfig_parse(ConfigParser2 *parser, cxstring content) { +ConfigNode* serverconfig_parse(ConfigParser2 *parser, cxstring content) { CxMempool *mp = parser->mp; CxAllocator *a = (CxAllocator*)mp->allocator; - ServerConfig *config = cxMalloc(a, sizeof(ServerConfig)); - if(!config) { - cxMempoolDestroy(mp); - return NULL; - } - config->mp = mp; - // PARSE: // first non space/comment token is directive/object name // following tokens are arguments @@ -280,7 +294,10 @@ obj->text_begin = new_textbegin; } else { // normal line containing a directive, space or comment - if(parser->validateDirective && parser->validateDirective(parser, current)) { + if(current->type == CONFIG_NODE_DIRECTIVE && + parser->validateDirective && + parser->validateDirective(parser, current)) + { err = 1; break; } @@ -379,10 +396,7 @@ } //test_print_config(&root_obj); - config->root = root_obj; - config->tab = cx_strdup_a(a, cx_str("\t")); - - return config; + return root_obj; } void serverconfig_free(ServerConfig *cfg) { @@ -410,7 +424,7 @@ return nodes; } -cxstring serverconfig_directive_value(ConfigNode *obj, cxstring name) { +cxstring serverconfig_object_directive_value(ConfigNode *obj, cxstring name) { ConfigNode *node = serverconfig_get_node(obj, CONFIG_NODE_DIRECTIVE, name); if(node && CFG_NUM_PARAMS(node->args) == 1) { ConfigParam *arg = node->args; @@ -419,19 +433,48 @@ return (cxstring){ NULL, 0 }; } -cxmutstr serverconfig_arg_name_value(CxAllocator *a, cxstring str, cxstring *name) { - int valstart = 0; - for(int i=0;i<str.length;i++) { - if(str.ptr[i] == '=') { - if(name) { - name->ptr = str.ptr; - name->length = i; - } - valstart = i + 1; +cxstring serverconfig_directive_get_arg(ConfigNode *directive, cxstring arg_name) { + cxstring ret = (cxstring){ NULL, 0 }; + ConfigParam *arg = directive->args; + while(arg) { + if(!cx_strcmp(arg_name, cx_strcast(arg->name))) { + ret = cx_strcast(arg->value); break; } + arg = arg->next; } - cxmutstr ret; return ret; } + + + + +/* -------------------------- utility functions -------------------------- */ + +int serverconfig_validate_directive_name( + ConfigNode *directive, + const char *names[], + size_t numnames, + size_t *nameindex) +{ + for(size_t i=0;i<numnames;i++) { + if(!cx_strcmp(cx_strcast(directive->name), cx_str(names[i]))) { + *nameindex = i; + return 0; + } + } + return 1; +} + +int serverconfig_check_param_names(ConfigNode *directive, ConfigParam **err) { + ConfigParam *arg = directive->args; + while(arg) { + if(arg->name.length == 0) { + *err = arg; + return 1; + } + arg = arg->next; + } + return 0; +}