From e93e65f88214ec4a3749be17b0cef44e172e6f53 Mon Sep 17 00:00:00 2001 From: Azreyo <58790873+Azreyo@users.noreply.github.com> Date: Thu, 2 Oct 2025 21:46:42 +0000 Subject: [PATCH] Refactor config parsing to use a switch statement for improved readability and maintainability --- src/config_parser.c | 215 +++++++++++++++++++++++++++----------------- 1 file changed, 133 insertions(+), 82 deletions(-) diff --git a/src/config_parser.c b/src/config_parser.c index a52f904..4e9f340 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -5,6 +5,20 @@ #include #include "server_config.h" +typedef enum { + CONFIG_PORT, + CONFIG_USE_HTTPS, + CONFIG_LOG_FILE, + CONFIG_MAX_THREADS, + CONFIG_RUNNING, + CONFIG_SERVER_NAME, + CONFIG_VERBOSE, + CONFIG_ENABLE_HTTP2, + CONFIG_ENABLE_WEBSOCKET, + CONFIG_UNKNOWN + +} ConfigKey; + // Trim whitespace from both ends of a string static char* trim_whitespace(char *str) { char *end; @@ -32,6 +46,32 @@ static bool parse_bool(const char *value) { } return false; } +// Map string to enum +static ConfigKey get_config_key(const char *key) { + static const struct + { + const char *name; + ConfigKey key; + } key_map[] = { + {"port", CONFIG_PORT}, + {"use_https", CONFIG_USE_HTTPS}, + {"log_file", CONFIG_LOG_FILE}, + {"max_threads", CONFIG_MAX_THREADS}, + {"running", CONFIG_RUNNING}, + {"server_name", CONFIG_SERVER_NAME}, + {"verbose", CONFIG_VERBOSE}, + {"enable_http2", CONFIG_ENABLE_HTTP2}, + {"enable_websocket",CONFIG_ENABLE_WEBSOCKET}, + {NULL, CONFIG_UNKNOWN} + + }; + for (int i = 0;key_map[i].name != NULL; i++) { + if (strcasecmp(key, key_map[i].name) == 0) { + return key_map[i].key; + } + } + return CONFIG_UNKNOWN; +} int load_config(const char *filename, ServerConfig *config) { FILE *fp = fopen(filename, "r"); @@ -44,90 +84,101 @@ int load_config(const char *filename, ServerConfig *config) { int line_number = 0; while (fgets(line, sizeof(line), fp)) { - line_number++; - - // Remove newline - line[strcspn(line, "\r\n")] = 0; - - // Trim whitespace - char *trimmed = trim_whitespace(line); - - // Skip empty lines and comments - if (trimmed[0] == '\0' || trimmed[0] == '#' || trimmed[0] == ';') { - continue; - } - - // Find the delimiter (= or space) - char *delim = strchr(trimmed, '='); - if (!delim) { - // Try space as delimiter - delim = strchr(trimmed, ' '); - } - - if (!delim) { - fprintf(stderr, "Warning: Invalid config line %d: %s\n", line_number, trimmed); - continue; - } - - // Split into key and value - *delim = '\0'; - char *key = trim_whitespace(trimmed); - char *value = trim_whitespace(delim + 1); - - // Remove quotes from value if present - if ((value[0] == '"' || value[0] == '\'') && - value[strlen(value) - 1] == value[0]) { - value[strlen(value) - 1] = '\0'; - value++; - } - - // Parse configuration options - if (strcasecmp(key, "port") == 0) { - config->port = atoi(value); - printf("load_config: port = %d\n", config->port); - } - else if (strcasecmp(key, "use_https") == 0) { - config->use_https = parse_bool(value); - printf("load_config: use_https = %d\n", config->use_https); - } - else if (strcasecmp(key, "log_file") == 0) { - strncpy(config->log_file, value, sizeof(config->log_file) - 1); - config->log_file[sizeof(config->log_file) - 1] = '\0'; - printf("load_config: log_file = %s\n", config->log_file); - } - else if (strcasecmp(key, "max_threads") == 0) { - config->max_threads = atoi(value); - printf("load_config: max_threads = %d\n", config->max_threads); - } - else if (strcasecmp(key, "running") == 0) { - config->running = parse_bool(value); - printf("load_config: running = %d\n", config->running); - } - else if (strcasecmp(key, "server_name") == 0) { - strncpy(config->server_name, value, sizeof(config->server_name) - 1); - config->server_name[sizeof(config->server_name) - 1] = '\0'; - printf("load_config: server_name = %s\n", config->server_name); - if (strcmp(config->server_name, "Your_domain/IP") == 0) { - fprintf(stderr, "WARNING: server_name is set to default\nPlease set server_name in server.conf to the server's IP address or domain name for proper operation.\n"); + line_number++; + + // Remove newline + line[strcspn(line, "\r\n")] = 0; + + // Trim whitespace + char *trimmed = trim_whitespace(line); + + // Skip empty lines and comments + if (trimmed[0] == '\0' || trimmed[0] == '#' || trimmed[0] == ';') { + continue; } - } - else if (strcasecmp(key, "verbose") == 0) { - config->verbose = parse_bool(value); - printf("load_config: verbose = %d\n", config->verbose); - } - else if (strcasecmp(key, "enable_http2") == 0) { - config->enable_http2 = parse_bool(value); - printf("load_config: enable_http2 = %d\n", config->enable_http2); - } - else if (strcasecmp(key, "enable_websocket") == 0) { - config->enable_websocket = parse_bool(value); - printf("load_config: enable_websocket = %d\n", config->enable_websocket); - } - else { - fprintf(stderr, "Warning: Unknown config option '%s' on line %d\n", key, line_number); + + // Find the delimiter (= or space) + char *delim = strchr(trimmed, '='); + if (!delim) { + // Try space as delimiter + delim = strchr(trimmed, ' '); + } + + if (!delim) { + fprintf(stderr, "Warning: Invalid config line %d: %s\n", line_number, trimmed); + continue; + } + + // Split into key and value + *delim = '\0'; + char *key = trim_whitespace(trimmed); + char *value = trim_whitespace(delim + 1); + + // Remove quotes from value if present + if ((value[0] == '"' || value[0] == '\'') && + value[strlen(value) - 1] == value[0]) { + value[strlen(value) - 1] = '\0'; + value++; + } + // Parse configuration options + switch (get_config_key(key)) { + case CONFIG_PORT: + config->port = atoi(value); + printf("load_config: port = %d\n", config->port); + break; + + case CONFIG_USE_HTTPS: + config->use_https = parse_bool(value); + printf("load_config: use_https = %d\n", config->use_https); + break; + + case CONFIG_LOG_FILE: + strncpy(config->log_file, value, sizeof(config->log_file) - 1); + config->log_file[sizeof(config->log_file) - 1] = '\0'; + printf("load_config: log_file = %s\n", config->log_file); + break; + + case CONFIG_MAX_THREADS: + config->max_threads = atoi(value); + printf("load_config: max_threads = %d\n", config->max_threads); + break; + + case CONFIG_RUNNING: + config->running = parse_bool(value); + printf("load_config: running = %d\n", config->running); + break; + + case CONFIG_SERVER_NAME: + strncpy(config->server_name, value, sizeof(config->server_name) - 1); + config->server_name[sizeof(config->server_name) - 1] = '\0'; + printf("load_config: server_name = %s\n", config->server_name); + if (strcmp(config->server_name, "Your_domain/IP") == 0) { + fprintf(stderr, "WARNING: server_name is set to default\n" + "Please set server_name in server.conf to the server's IP address or domain name for proper operation.\n"); + } + break; + + case CONFIG_VERBOSE: + config->verbose = parse_bool(value); + printf("load_config: verbose = %d\n", config->verbose); + break; + + case CONFIG_ENABLE_HTTP2: + config->enable_http2 = parse_bool(value); + printf("load_config: enable_http2 = %d\n", config->enable_http2); + break; + + case CONFIG_ENABLE_WEBSOCKET: + config->enable_websocket = parse_bool(value); + printf("load_config: enable_websocket = %d\n", config->enable_websocket); + break; + + case CONFIG_UNKNOWN: + default: + fprintf(stderr, "Warning: Unknown config option '%s' on line %d\n", key, line_number); + break; } } - fclose(fp); return 0; -} +} \ No newline at end of file