From 743da9300b839b558bb912235ac0dacbe5e1b681 Mon Sep 17 00:00:00 2001 From: Themaister Date: Wed, 29 Dec 2010 14:27:44 +0100 Subject: [PATCH] Add config file API. --- config_file.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++ config_file.h | 20 ++++ 2 files changed, 291 insertions(+) create mode 100644 config_file.c create mode 100644 config_file.h diff --git a/config_file.c b/config_file.c new file mode 100644 index 0000000000..a27e2e9e37 --- /dev/null +++ b/config_file.c @@ -0,0 +1,271 @@ +#include "config_file.h" +#include +#include +#include +#include + +struct entry_list +{ + char *key; + char *value; + struct entry_list *next; +}; + +struct config_file +{ + struct entry_list *entries; +}; + +static char *getaline(FILE *file) +{ + char *newline = malloc(8); + size_t cur_size = 8; + size_t index = 0; + + int in = getc(file); + while (in != EOF && in != '\n') + { + if (index == cur_size) + { + cur_size *= 2; + newline = realloc(newline, cur_size); + } + + newline[index++] = in; + in = getc(file); + } + return newline; +} + +static bool parse_line(struct entry_list *list, char *line) +{ + // Remove everything after comment. + char *comment = strchr(line, '#'); + if (comment) + *comment = '\0'; + + // Skips to first character. + while (isspace(*line)) + line++; + + char *key = malloc(8); + size_t cur_size = 8; + size_t index = 0; + + while (isgraph(*line)) + { + if (index == cur_size) + { + cur_size *= 2; + key = realloc(key, cur_size); + } + + key[index++] = *line++; + } + list->key = key; + + while (isspace(*line)) + line++; + + // If we don't have an equal sign here, we've got an invalid string... + if (*line != '=') + { + list->key = NULL; + free(key); + return false; + } + line++; + + while (isspace(*line)) + line++; + + // We have a full string. Read until next ". + if (*line == '"') + { + char *tok = strtok(line + 1, "\""); + if (tok == NULL) + { + list->key = NULL; + free(key); + return false; + } + list->value = strdup(tok); + } + else // We don't have that... Read till next space. + { + char *tok = strtok(line, " \t\f"); + if (tok == NULL) + { + list->key = NULL; + free(key); + return false; + } + list->value = strdup(tok); + } + + return true; +} + +static void print_config(config_file_t *conf) +{ + struct entry_list *tmp = conf->entries; + while (tmp != NULL) + { + printf("Key: \"%s\", Value: \"%s\"\n", tmp->key, tmp->value); + tmp = tmp->next; + } +} + +config_file_t *config_file_new(const char *path) +{ + FILE *file = fopen(path, "r"); + if (!file) + return NULL; + + struct config_file *conf = calloc(1, sizeof(*conf)); + if (conf == NULL) + return NULL; + + struct entry_list *tail = conf->entries; + + while (!feof(file)) + { + struct entry_list *list = calloc(1, sizeof(*list)); + char *line = getaline(file); + + if (line) + { + if (parse_line(list, line)) + { + if (conf->entries == NULL) + { + conf->entries = list; + tail = list; + } + else + { + tail->next = list; + tail = list; + } + } + free(line); + } + } + fclose(file); + + //print_config(conf); + + return conf; +} + +void config_file_free(config_file_t *conf) +{ + if (conf != NULL) + { + struct entry_list *tmp = conf->entries; + struct entry_list *old = tmp; + while (tmp != NULL) + { + free(tmp->key); + free(tmp->value); + old = tmp; + tmp = tmp->next; + free(old); + } + free(conf); + } +} + +bool config_get_double(config_file_t *conf, const char *key, double *in) +{ + struct entry_list *list = conf->entries; + + while (list != NULL) + { + if (strcmp(key, list->key) == 0) + { + *in = strtod(list->value, NULL); + return true; + } + list = list->next; + } + return false; +} + +bool config_get_int(config_file_t *conf, const char *key, int *in) +{ + struct entry_list *list = conf->entries; + + while (list != NULL) + { + if (strcmp(key, list->key) == 0) + { + *in = strtol(list->value, NULL, 0); + return true; + } + list = list->next; + } + return false; +} + +bool config_get_char(config_file_t *conf, const char *key, char *in) +{ + struct entry_list *list = conf->entries; + + while (list != NULL) + { + if (strcmp(key, list->key) == 0) + { + if (strlen(list->value) > 1) + return false; + *in = *list->value; + return true; + } + list = list->next; + } + return false; +} + +bool config_get_string(config_file_t *conf, const char *key, char **str) +{ + struct entry_list *list = conf->entries; + + while (list != NULL) + { + if (strcmp(key, list->key) == 0) + { + *str = strdup(list->value); + return true; + } + list = list->next; + } + return false; +} + +bool config_get_bool(config_file_t *conf, const char *key, bool *in) +{ + struct entry_list *list = conf->entries; + + while (list != NULL) + { + if (strcmp(key, list->key) == 0) + { + if (strcasecmp(list->value, "true") == 0) + *in = true; + else if (strcasecmp(list->value, "1") == 0) + *in = true; + else if (strcasecmp(list->value, "false") == 0) + *in = false; + else if (strcasecmp(list->value, "0") == 0) + *in = false; + else + return false; + + return true; + } + list = list->next; + } + return false; +} + + diff --git a/config_file.h b/config_file.h new file mode 100644 index 0000000000..67e083e7db --- /dev/null +++ b/config_file.h @@ -0,0 +1,20 @@ +#ifndef __CONFIG_FILE_H +#define __CONFIG_FILE_H + +#include +#include + +typedef struct config_file config_file_t; + +config_file_t *config_file_new(const char *path); +void config_file_free(config_file_t *conf); + +bool config_get_double(config_file_t *conf, const char *entry, double *in); +bool config_get_int(config_file_t *conf, const char *entry, int *in); +bool config_get_char(config_file_t *conf, const char *entry, char *in); +bool config_get_string(config_file_t *conf, const char *entry, char **in); +bool config_get_bool(config_file_t *conf, const char *entry, bool *in); + + + +#endif