From 336a336e45c90851dcc8430f7f8eeabc9f3399e1 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sat, 17 Jun 2023 18:54:44 +0200 Subject: Implement configuration parser --- config.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 185 insertions(+), 8 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index f11bbb6..306e578 100644 --- a/config.c +++ b/config.c @@ -1,29 +1,206 @@ #include #include +#include #include "nfcommander.h" #include "config.h" +typedef struct /*_config_section*/ { + char* name; + size_t entries; + char** keys; + char** values; +} config_section_t; + +size_t nsections = 0, current_section = 0; +config_section_t* sections = NULL; + +static int config_section(char* section){ + size_t n = 0; + + //check if section already exists + for(n = 0; n < nsections; n++){ + if(!strcmp(sections[n].name, section)){ + current_section = n; + return 0; + } + } + + //create new section + sections = realloc(sections, (nsections + 1) * sizeof(config_section_t)); + if(!sections){ + nsections = 0; + printf("Failed to allocate memory\n"); + return -1; + } + + memset(sections + nsections, 0, sizeof(config_section_t)); + sections[nsections].name = strdup(section); + if(!sections[nsections].name){ + printf("Failed to allocate memory\n"); + return -1; + } + + current_section = nsections; + nsections++; + return 0; +} + +static int config_set(char* key, char* value){ + size_t n = 0; + if(!sections || !nsections){ + printf("Assignment outside of section\n"); + return 1; + } + + //check if property already present + for(n = 0; n < sections[current_section].entries; n++){ + if(!strcmp(sections[current_section].keys[n], key)){ + printf("Overriding previous value of %s.%s with %s\n", + sections[current_section].name, + key, value); + free(sections[current_section].values[n]); + sections[current_section].values[n] = strdup(value); + return 0; + } + } + + //add property + sections[current_section].keys = realloc(sections[current_section].keys, (sections[current_section].entries + 1) * sizeof(char*)); + sections[current_section].values = realloc(sections[current_section].values, (sections[current_section].entries + 1) * sizeof(char*)); + + if(!sections[current_section].keys || !sections[current_section].values){ + printf("Filed to allocate memory\n"); + sections[current_section].entries = 0; + return 1; + } + + sections[current_section].keys[sections[current_section].entries] = strdup(key); + sections[current_section].values[sections[current_section].entries] = strdup(value); + sections[current_section].entries++; + return 0; +} + +static int config_handle_line(char* line){ + char* next_token = NULL; + size_t len = 0; + + //ignore comments + if(line[0] == ';'){ + return 0; + } + + //select or create section + if(line[0] == '['){ + next_token = strchr(line, ']'); + if(!next_token){ + printf("Unterminated start of section\n"); + return 1; + } + + *next_token = 0; + return config_section(line + 1); + } + + next_token = strchr(line, '='); + if(!next_token){ + printf("Not an assignment: %s\n", line); + return 1; + } + + *next_token = 0; + next_token++; + + //rtrim line + len = strlen(line); + for(; len && !isgraph(line[len]); len--){ + line[len] = 0; + } + + //ltrim value + for(; *next_token && !isgraph(*next_token); next_token++){ + } + + if(len && strlen(next_token)){ + return config_set(line, next_token); + } + printf("Invalid assignment\n"); + return 1; +} + int config_read(char* path){ - //TODO + ssize_t line_len = 0; + size_t line_alloc = 0, line_number = 1; + char* line = NULL; + FILE* input = fopen(path, "r"); + if(!input){ + printf("Failed to open %s as configuration file\n", path); + return 1; + } + printf("Reading config file %s\n", path); + for(line_len = getline(&line, &line_alloc, input); line_len >= 0; line_len = getline(&line, &line_alloc, input)){ + //right-trim + for(; line_len && !isgraph(line[line_len]); line_len--){ + line[line_len] = 0; + } + + if(!line_len){ + continue; + } + if(config_handle_line(line)){ + printf("Failed parsing %s at line %lu\n", path, line_number); + return 1; + } + line_number++; + } + + free(line); + fclose(input); return 0; } char* config_get(char* section, char* property){ - //TODO - printf("Querying for config property %s->%s\n", section, property); + size_t n = 0, p = 0; + + //find section + for(n = 0; n < nsections; n++){ + if(!strcmp(section, sections[n].name)){ + break; + } + } + + if(n == nsections){ + printf("Requested config section %s not found\n", section); + return NULL; + } - //TEMP - if(!strcmp(property, "reader")){ - return "yhy"; + //find key + for(p = 0; p < sections[n].entries; p++){ + if(!strcmp(sections[n].keys[p], property)){ + return sections[n].values[p]; + } } + printf("Requested property %s.%s not configured\n", section, property); return NULL; } void config_free(){ - //TODO - printf("Cleaning up config data\n"); + size_t n = 0, p = 0; + + for(n = 0; n < nsections; n++){ + free(sections[n].name); + for(p = 0; p < sections[n].entries; p++){ + free(sections[n].keys[p]); + free(sections[n].values[p]); + } + free(sections[n].keys); + free(sections[n].values); + } + + free(sections); + sections = NULL; + nsections = 0; } -- cgit v1.2.3