src/server/config/serverconfig.c

changeset 418
b7dcc9c4f270
parent 417
90805bb9fbd6
child 419
f1d29785ad2d
--- 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;
+}

mercurial