--- 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(¤t->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; }