UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2020 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef WS_CONFIG_SERVERCONFIG_H 30 #define WS_CONFIG_SERVERCONFIG_H 31 32 #include <cx/linked_list.h> 33 #include <cx/hash_map.h> 34 #include <cx/mempool.h> 35 #include <cx/string.h> 36 37 #include <stdbool.h> 38 39 #include "conf.h" 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 #define CFG_NODE_ADD(list_begin, list_end, elm) \ 46 cx_linked_list_add((void**)list_begin, (void**)list_end, offsetof(ConfigNode, prev), offsetof(ConfigNode, next), elm) 47 48 typedef struct ServerConfig ServerConfig; 49 typedef struct ConfigNode ConfigNode; 50 typedef struct CFGToken CFGToken; 51 typedef struct ConfigParser2 ConfigParser2; // TODO: rename to ConfigParser after old ConfigParser is removed 52 53 typedef enum ConfigNodeType ConfigNodeType; 54 typedef enum CFGTokenType CFGTokenType; 55 56 struct ServerConfig { 57 CxMempool *mp; 58 ConfigNode *root; 59 cxstring tab; 60 }; 61 62 enum ConfigNodeType { 63 CONFIG_NODE_SPACE = 0, 64 CONFIG_NODE_COMMENT, 65 CONFIG_NODE_OBJECT, 66 CONFIG_NODE_DIRECTIVE, 67 CONFIG_NODE_OPEN_OBJECT, 68 CONFIG_NODE_CLOSE_OBJECT 69 }; 70 71 struct ConfigNode { 72 cxmutstr text_begin; 73 cxmutstr text_end; 74 ConfigNodeType type; 75 76 cxmutstr name; 77 ConfigParam *args; 78 ConfigNode *children_begin; 79 ConfigNode *children_end; 80 81 ConfigNode *prev; 82 ConfigNode *next; 83 }; 84 85 typedef struct ConfigNodeStack ConfigNodeStack; 86 struct ConfigNodeStack { 87 ConfigNode *node; 88 ConfigNodeStack *next; 89 }; 90 91 enum CFGTokenType { 92 CFG_NO_TOKEN = 0, 93 CFG_TOKEN_COMMENT, 94 CFG_TOKEN_SPACE, 95 CFG_TOKEN_NEWLINE, 96 CFG_TOKEN 97 }; 98 99 struct CFGToken { 100 cxstring content; 101 CFGTokenType type; 102 }; 103 104 enum ConfigParserError { 105 CONFIG_PARSER_OOM = 0, 106 CONFIG_PARSER_IO_ERROR, 107 CONFIG_PARSER_SYNTAX_ERROR 108 }; 109 110 /* 111 * CfgValidateNodeFunc functions are called by the parser to validate 112 * objects and directives. 113 * 114 * The function must return 0 if the validation was successful. If the 115 * functions returns a value != 0, the parser aborts. 116 */ 117 typedef int(*CfgValidateNodeFunc)(ConfigParser2 *parser, ConfigNode *node); 118 119 struct ConfigParser2 { 120 CxMempool *mp; 121 122 const char *filename; 123 124 int linenum; 125 int linepos; 126 127 enum ConfigParserError error; 128 129 const char *delim; 130 131 /* 132 * errno in case of IO errors (parser.error == CONFIG_PARSER_IO_ERROR) 133 */ 134 int io_errno; 135 136 /* 137 * called when an object is started 138 */ 139 CfgValidateNodeFunc validateObjBegin; 140 141 /* 142 * called when an object is closed 143 */ 144 CfgValidateNodeFunc validateObjEnd; 145 146 /* 147 * called before a directive is added 148 */ 149 CfgValidateNodeFunc validateDirective; 150 151 /* 152 * true: store result in a tree 153 * false: flat list of directives, don't allow '{' and '}' 154 */ 155 bool allow_hierarchy; 156 }; 157 158 ServerConfig* serverconfig_load(const char *file); 159 160 ConfigNode* serverconfig_load_file(ConfigParser2 *parser, const char *file); 161 162 ConfigNode* serverconfig_parse(ConfigParser2 *parser, cxstring content); 163 164 void serverconfig_free(ServerConfig *cfg); 165 166 ConfigNode* serverconfig_get_node(ConfigNode *parent, ConfigNodeType type, cxstring name); 167 168 CxList* serverconfig_get_node_list(ConfigNode *parent, ConfigNodeType type, cxstring name); 169 170 /* 171 * Searches in the specified object for the directive with the name 172 * directive_name and returns the value 173 * 174 * Directives only have a value, if they have one argument 175 */ 176 cxstring serverconfig_object_directive_value(ConfigNode *obj, cxstring directive_name); 177 178 /* 179 * Returns the directive parameter value that has the specified name 180 */ 181 cxstring serverconfig_directive_get_arg(ConfigNode *directive, cxstring param_name); 182 183 184 /* 185 * Checks if the directive name matches any string in the names array. 186 * If it matches a name, the function returns 0 and stores the index of the 187 * matched name in nameindex 188 * If it doesn't match a name, the function returns 1 189 */ 190 int serverconfig_validate_directive_name( 191 ConfigNode *directive, 192 const char *names[], 193 size_t numnames, 194 size_t *nameindex); 195 196 /* 197 * Checks if all directive parameters have a name 198 * If every parameter has a name, the function returns 0 199 * otherwise it returns 1 200 * 201 * If a parameter doesn't contain a name, err is set to this parameter 202 * 203 * config file syntax: paramname="value" 204 */ 205 int serverconfig_check_param_names(ConfigNode *directive, ConfigParam **err); 206 207 /* 208 * Returns the previous node that is a directive or object 209 */ 210 ConfigNode* serverconfig_previous_dir_or_obj(ConfigNode *node); 211 212 /* 213 * Count the direct children that have the specified type 214 */ 215 size_t serverconfig_children_count(ConfigNode *node, ConfigNodeType type); 216 217 #ifdef __cplusplus 218 } 219 #endif 220 221 #endif /* WS_CONFIG_SERVERCONFIG_H */ 222 223