src/server/config/serverconfig.c

changeset 415
d938228c382e
parent 367
1592224f6059
child 417
90805bb9fbd6
--- a/src/server/config/serverconfig.c	Wed Nov 02 19:19:01 2022 +0100
+++ b/src/server/config/serverconfig.c	Sun Nov 06 15:53:32 2022 +0100
@@ -28,14 +28,15 @@
 
 
 #include "serverconfig.h"
+#include "conf.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
-#include <ucx/buffer.h>
-#include <ucx/utils.h>
+#include <cx/buffer.h>
+#include <cx/utils.h>
 
 ServerConfig* serverconfig_load(const char *file) {
     FILE *in = fopen(file, "r");
@@ -43,23 +44,25 @@
         return NULL;
     }
     
-    UcxBuffer *buf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND);
-    if(!buf) {
-        fclose(in);
-        return NULL;
+    CxBuffer buf;
+    cxBufferInit(&buf, NULL, 16384, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
+    
+    //ucx_stream_copy(in, buf, (read_func)fread, (write_func)ucx_buffer_write);
+    char readbuf[2048];
+    size_t r;
+    while((r = fread(readbuf, 1, 2048, in)) > 0) {
+        cxBufferWrite(readbuf, 1, r, &buf);
     }
-    
-    ucx_stream_copy(in, buf, (read_func)fread, (write_func)ucx_buffer_write);
     fclose(in);
     
-    ServerConfig *scfg = serverconfig_parse(scstrn(buf->space, buf->size));
+    ServerConfig *scfg = serverconfig_parse(cx_strn(buf.space, buf.size));
     
-    ucx_buffer_free(buf);
+    cxBufferDestroy(&buf);
     return scfg;
 }
 
 
-static CFGToken get_next_token(scstr_t content, int *pos) {
+static CFGToken get_next_token(cxstring content, int *pos) {
     CFGToken token = { {NULL, 0}, CFG_NO_TOKEN };
     CFGTokenType type = CFG_TOKEN;
     
@@ -130,7 +133,7 @@
     }
     
     token.type = type;
-    token.content = scstrsubsl(content, token_begin, token_end - token_begin);
+    token.content = cx_strsubsl(content, token_begin, token_end - token_begin);
     return token;
 }
 
@@ -156,16 +159,16 @@
 }
 */
 
-static void config_arg_set_value(UcxAllocator *a, ConfigArg *arg, CFGToken token) {
-    scstr_t nv = scstrchr(token.content, '=');
+static void config_arg_set_value(CxAllocator *a, ConfigParam *arg, CFGToken token) {
+    cxstring nv = cx_strchr(token.content, '=');
     if(!nv.ptr) {
-        arg->value = sstrdup_a(a, token.content);
+        arg->value = cx_strdup_a(a, token.content);
     } else {
         intptr_t eq = (intptr_t)(nv.ptr - token.content.ptr);
-        scstr_t name = token.content;
+        cxstring name = token.content;
         name.length = (size_t)eq;
         
-        scstr_t value = nv;
+        cxstring value = nv;
         value.ptr++;
         value.length--;
         if(value.length > 1 && value.ptr[0] == '"' && value.ptr[value.length-1] == '"') {
@@ -173,19 +176,28 @@
             value.length -= 2; // remove quote
         }
         
-        arg->name = sstrdup_a(a, name);
-        arg->value = sstrdup_a(a, value);
+        arg->name = cx_strdup_a(a, name);
+        arg->value = cx_strdup_a(a, value);
     }
 }
 
-ServerConfig* serverconfig_parse(scstr_t content) {
-    UcxMempool *mp = ucx_mempool_new(512);
+static int nodestack_prepend(CxAllocator *a, ConfigNodeStack **stack, ConfigNode *node) {
+    ConfigNodeStack *elm = cxMalloc(a, sizeof(ConfigNodeStack));
+    if(!elm) return 1;
+    elm->node = node;
+    elm->next = NULL;
+    cx_linked_list_prepend((void**)stack, NULL, -1, offsetof(ConfigNodeStack, next), elm);
+    return 0;
+}
+
+ServerConfig* serverconfig_parse(cxstring content) {
+    CxMempool *mp = cxBasicMempoolCreate(512);
     if(!mp) return NULL;
-    UcxAllocator *a = mp->allocator;
+    CxAllocator *a = (CxAllocator*)mp->allocator;
     
-    ServerConfig *config = ucx_mempool_malloc(mp, sizeof(ServerConfig));
+    ServerConfig *config = cxMalloc(a, sizeof(ServerConfig));
     if(!config) {
-        ucx_mempool_destroy(mp);
+        cxMempoolDestroy(mp);
         return NULL;
     }
     config->mp = mp;
@@ -199,12 +211,14 @@
     int pos = 0; // needed for tokenizer
     CFGToken token;
     
-    ConfigNode *root_obj = ucx_mempool_calloc(mp, 1, sizeof(ConfigNode));
+    ConfigNode *root_obj = cxCalloc(a, 1, sizeof(ConfigNode));
     root_obj->type = CONFIG_NODE_OBJECT;
     
-    UcxList *node_stack = ucx_list_prepend(NULL, root_obj);
+    ConfigNodeStack *node_stack = cxMalloc(a, sizeof(ConfigNodeStack));
+    node_stack->node = root_obj;
+    node_stack->next = NULL;
     
-    ConfigNode *current = ucx_mempool_calloc(mp, 1, sizeof(ConfigNode));
+    ConfigNode *current = cxCalloc(a, 1, sizeof(ConfigNode));
     current->type = CONFIG_NODE_SPACE;
     ConfigNode *obj = NULL;
     int obj_closed = 0;
@@ -213,7 +227,7 @@
     int err = 0;
     while((token = get_next_token(content, &pos)).type != CFG_NO_TOKEN) {
         //printf("%s [%.*s]\n", token_type_str(token.type), (int)token.content.length, token.content.ptr);
-        
+
         switch(token.type) {
             case CFG_NO_TOKEN: break;
             case CFG_TOKEN_COMMENT: {
@@ -224,39 +238,56 @@
             }
             case CFG_TOKEN_SPACE: break;
             case CFG_TOKEN_NEWLINE: {
-                scstr_t line = scstrsubsl(content, text_start, pos - text_start);
+                cxstring line = cx_strsubsl(content, text_start, pos - text_start);
                 text_start = pos;
                 
-                sstr_t line_cp = sstrdup_a(a, line);
+                cxmutstr line_cp = cx_strdup_a(a, line);
 
-                ConfigNode *parent = node_stack->data;
+                ConfigNode *parent = node_stack->node;
                 if(current->type == CONFIG_NODE_CLOSE_OBJECT) {
+                    // this is a newline after a object is closed with '}'
+                    // the line containing "}\n" should be added to the object
                     parent->text_end = line_cp;
-                    node_stack = ucx_list_remove_a(a, node_stack, node_stack);
+                    // done with this object, remove it from the stack
+                    ConfigNodeStack *remove_item = node_stack;
+                    node_stack = node_stack->next;
+                    cxFree(a, remove_item);
                 } else if(current->type == CONFIG_NODE_OPEN_OBJECT) {
-                    sstr_t new_textbegin = sstrcat_a(a, 2, obj->text_begin, line_cp);
-                    alfree(a, obj->text_begin.ptr);
-                    alfree(a, line_cp.ptr);
+                    // newline after a object is opened with '{'
+                    // append '{' to the object text
+                    cxmutstr new_textbegin = cx_strcat_a(a, 2, obj->text_begin, line_cp);
+                    cxFree(a, obj->text_begin.ptr);
+                    cxFree(a, line_cp.ptr);
                     obj->text_begin = new_textbegin;
                 } else {
+                    // normal line containing a directive, space or comment
+                    // add it to parent node
                     current->text_begin = line_cp;
-                    ConfigNode *parent = node_stack->data;
-                    parent->children = ucx_list_append_a(a, parent->children, current);
+                    CFG_NODE_ADD(&parent->children_begin, &parent->children_end, current);
                 }
                 
+                // obj points to the previous node that started as a directive
+                // the type is set to CONFIG_NODE_OBECT if it was followed by
+                // a '{' character
                 if(obj && obj->type == CONFIG_NODE_OBJECT) {
-                    node_stack = ucx_list_prepend_a(a, node_stack, obj);
+                    // new object started, add it to the stack
+                    nodestack_prepend(a, &node_stack, obj);
                     obj = NULL;
                 }
 
-                current = ucx_mempool_calloc(mp, 1, sizeof(ConfigNode));
+                current = cxCalloc(a, 1, sizeof(ConfigNode));
                 current->type = CONFIG_NODE_SPACE;
                 
                 obj_closed = 0;
                 break;
             }
             case CFG_TOKEN: {
-                if(!sstrcmp(token.content, S("{"))) {
+                // normal text token
+                // either a directive/obj name, parameter or { }
+                
+                if(!cx_strcmp(token.content, cx_str("{"))) {
+                    // obj is pointing to the previous node that started
+                    // a directive
                     if(!obj) {
                         err = 1;
                         break;
@@ -265,7 +296,7 @@
                     if(current != obj) {
                         current->type = CONFIG_NODE_OPEN_OBJECT;
                     }
-                } else if(!sstrcmp(token.content, S("}"))) {
+                } else if(!cx_strcmp(token.content, cx_str("}"))) {
                     obj_closed = 1; // force newline before next directive
                     obj = NULL;
                     current->type = CONFIG_NODE_CLOSE_OBJECT;
@@ -276,13 +307,16 @@
                     }
                     
                     if(!current->name.ptr) {
-                        current->name = sstrdup_a(a, token.content);
+                        // currently this could be a directive or object
+                        current->name = cx_strdup_a(a, token.content);
                         current->type = CONFIG_NODE_DIRECTIVE;
-                        obj = current;
+                        obj = current; // potential object
                     } else {
-                        ConfigArg *arg = ucx_mempool_calloc(mp, 1, sizeof(ConfigArg));
+                        // name already set, therefore this token must
+                        // be a parameter
+                        ConfigParam *arg = cxCalloc(a, 1, sizeof(ConfigParam));
                         config_arg_set_value(a, arg, token);
-                        current->args = ucx_list_append_a(a, current->args, arg);
+                        CFG_PARAM_ADD(&current->args, NULL, arg);
                     }
                 }
                 break;
@@ -296,54 +330,52 @@
     
     if(pos < content.length || err) {
         // content not fully parsed because of an error
-        ucx_mempool_destroy(mp);
+        cxMempoolDestroy(mp);
         return NULL;
     }
     
     //test_print_config(&root_obj);
     config->root = root_obj;
-    config->tab = sstrdup_a(a, SC("\t"));
+    config->tab = cx_strdup_a(a, cx_str("\t"));
     
     return config;
 }
 
 void serverconfig_free(ServerConfig *cfg) {
-    ucx_mempool_destroy(cfg->mp);
+    cxMempoolDestroy(cfg->mp);
 }
 
-ConfigNode* serverconfig_get_node(ConfigNode *parent, ConfigNodeType type, scstr_t name) {
-    UCX_FOREACH(elm, parent->children) {
-        ConfigNode *node = elm->data;
-        if(node->type == type && !sstrcasecmp(node->name, name)) {
+ConfigNode* serverconfig_get_node(ConfigNode *parent, ConfigNodeType type, cxstring name) {
+    for(ConfigNode *node=parent->children_begin;node;node=node->next) {
+        if(node->type == type && !cx_strcasecmp(cx_strcast(node->name), name)) {
             return node;
         }
     }
     return NULL;
 }
 
-UcxList* serverconfig_get_node_list(ConfigNode *parent, ConfigNodeType type, scstr_t name) {
-    UcxList *nodes = NULL;
+CxList* serverconfig_get_node_list(ConfigNode *parent, ConfigNodeType type, cxstring name) {
+    CxList *nodes = cxPointerLinkedListCreate(cxDefaultAllocator, cx_cmp_ptr);
     
-    UCX_FOREACH(elm, parent->children) {
-        ConfigNode *node = elm->data;
-        if(node->type == type && !sstrcasecmp(node->name, name)) {
-            nodes = ucx_list_append(nodes, node);
+    for(ConfigNode *node=parent->children_begin;node;node=node->next) {
+        if(node->type == type && !cx_strcasecmp(cx_strcast(node->name), name)) {
+            cxListAdd(nodes, node);
         }
     }
     
     return nodes;
 }
 
-scstr_t serverconfig_directive_value(ConfigNode *obj, scstr_t name) {
+cxstring serverconfig_directive_value(ConfigNode *obj, cxstring name) {
     ConfigNode *node = serverconfig_get_node(obj, CONFIG_NODE_DIRECTIVE, name);
-    if(node && ucx_list_size(node->args) == 1) {
-        ConfigArg *arg = node->args->data;
-        return SCSTR(arg->value);
+    if(node && CFG_NUM_PARAMS(node->args) == 1) {
+        ConfigParam *arg = node->args;
+        return (cxstring){ arg->value.ptr, arg->value.length };
     }
-    return scstrn(NULL, 0);
+    return (cxstring){ NULL, 0 };
 }
 
-sstr_t serverconfig_arg_name_value(UcxAllocator *a, scstr_t str, scstr_t *name) {
+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] == '=') {
@@ -356,6 +388,6 @@
         }
     }
     
-    sstr_t ret;
+    cxmutstr ret;
     return ret;
 }

mercurial