aboutsummaryrefslogtreecommitdiffstats
path: root/src/common/config-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/config-parser.c')
-rw-r--r--src/common/config-parser.c431
1 files changed, 0 insertions, 431 deletions
diff --git a/src/common/config-parser.c b/src/common/config-parser.c
deleted file mode 100644
index 235209e..0000000
--- a/src/common/config-parser.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2017 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include "error.h"
-#include "utils.h"
-#include "config-parser.h"
-
-
-typedef enum {
- CONFIG_START = 1,
- CONFIG_SECTION_START,
- CONFIG_SECTION,
- CONFIG_SECTION_KEY,
- CONFIG_SECTION_VALUE_START,
- CONFIG_SECTION_VALUE_QUOTE,
- CONFIG_SECTION_VALUE_POST_QUOTED,
- CONFIG_SECTION_VALUE,
- CONFIG_SECTION_LIST_START,
- CONFIG_SECTION_LIST_QUOTE,
- CONFIG_SECTION_LIST_POST_QUOTED,
- CONFIG_SECTION_LIST,
-} bc_configparser_state_t;
-
-typedef enum {
- CONFIG_SECTION_TYPE_MAP = 1,
- CONFIG_SECTION_TYPE_LIST,
-} bc_configparser_section_type_t;
-
-typedef struct {
- bc_configparser_section_type_t type;
- void *data;
-} bc_configparser_section_t;
-
-
-static void
-free_section(bc_configparser_section_t *section)
-{
- if (section == NULL)
- return;
-
- switch (section->type) {
- case CONFIG_SECTION_TYPE_MAP:
- bc_trie_free(section->data);
- break;
- case CONFIG_SECTION_TYPE_LIST:
- bc_slist_free_full(section->data, free);
- break;
- }
- free(section);
-}
-
-
-bc_config_t*
-bc_config_parse(const char *src, size_t src_len, const char *list_sections[],
- bc_error_t **err)
-{
- if (err == NULL || *err != NULL)
- return NULL;
-
- size_t current = 0;
- size_t start = 0;
-
- bc_configparser_section_t *section = NULL;
-
- char *section_name = NULL;
- char *key = NULL;
- bc_string_t *value = NULL;
- bool escaped = false;
-
- bc_config_t *rv = bc_malloc(sizeof(bc_config_t));
- rv->root = bc_trie_new((bc_free_func_t) free_section);
-
- bc_configparser_state_t state = CONFIG_START;
-
- while (current < src_len) {
- char c = src[current];
- bool is_last = current == src_len - 1;
-
- if (escaped) {
- bc_string_append_c(value, c);
- escaped = false;
- current++;
- continue;
- }
-
- if (value != NULL && c == '\\') {
- escaped = true;
- current++;
- continue;
- }
-
- switch (state) {
-
- case CONFIG_START:
- if (c == '#' || c == ';') {
- while (current < src_len) {
- if (src[current] == '\r' || src[current] == '\n')
- break;
- current++;
- }
- break;
- }
- if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- break;
- if (c == '[') {
- state = CONFIG_SECTION_START;
- break;
- }
- if (section != NULL) {
- start = current;
- switch (section->type) {
- case CONFIG_SECTION_TYPE_MAP:
- state = CONFIG_SECTION_KEY;
- break;
- case CONFIG_SECTION_TYPE_LIST:
- state = CONFIG_SECTION_LIST_START;
- if (value == NULL)
- value = bc_string_new();
- break;
- }
- continue;
- }
- *err = bc_error_parser(BC_ERROR_CONFIG_PARSER, src, src_len,
- current, "File must start with section.");
- break;
-
- case CONFIG_SECTION_START:
- start = current;
- state = CONFIG_SECTION;
- break;
-
- case CONFIG_SECTION:
- if (c == ']') {
- section_name = bc_strndup(src + start, current - start);
- section = bc_malloc(sizeof(bc_configparser_section_t));
- section->type = CONFIG_SECTION_TYPE_MAP;
- if (list_sections != NULL) {
- for (size_t i = 0; list_sections[i] != NULL; i++) {
- if (0 == strcmp(section_name, list_sections[i])) {
- section->type = CONFIG_SECTION_TYPE_LIST;
- break;
- }
- }
- }
- switch (section->type) {
- case CONFIG_SECTION_TYPE_MAP:
- section->data = bc_trie_new(free);
- break;
- case CONFIG_SECTION_TYPE_LIST:
- section->data = NULL;
- break;
- }
- bc_trie_insert(rv->root, section_name, section);
- free(section_name);
- section_name = NULL;
- state = CONFIG_START;
- break;
- }
- if (c != '\r' && c != '\n')
- break;
- *err = bc_error_parser(BC_ERROR_CONFIG_PARSER, src, src_len,
- current, "Section names can't have new lines.");
- break;
-
- case CONFIG_SECTION_KEY:
- if (c == '=') {
- key = bc_strndup(src + start, current - start);
- state = CONFIG_SECTION_VALUE_START;
- if (value == NULL)
- value = bc_string_new();
- break;
- }
- if (c != '\r' && c != '\n' && !is_last)
- break;
- // key without value, should we support it?
- size_t end = is_last && c != '\n' && c != '\r' ? src_len :
- current;
- key = bc_strndup(src + start, end - start);
- *err = bc_error_parser(BC_ERROR_CONFIG_PARSER, src, src_len,
- current, "Key without value: %s.", key);
- free(key);
- key = NULL;
- break;
-
- case CONFIG_SECTION_VALUE_START:
- if (c == ' ' || c == '\t' || c == '\f' || c == '\v')
- break;
- if (c == '"') {
- state = CONFIG_SECTION_VALUE_QUOTE;
- break;
- }
- bc_string_append_c(value, c);
- state = CONFIG_SECTION_VALUE;
- break;
-
- case CONFIG_SECTION_VALUE_QUOTE:
- if (c == '"') {
- bc_trie_insert(section->data, bc_str_strip(key),
- bc_string_free(value, false));
- free(key);
- key = NULL;
- value = NULL;
- state = CONFIG_SECTION_VALUE_POST_QUOTED;
- break;
- }
- bc_string_append_c(value, c);
- break;
-
- case CONFIG_SECTION_VALUE_POST_QUOTED:
- if (c == ' ' || c == '\t' || c == '\f' || c == '\v')
- break;
- if (c == '\r' || c == '\n' || is_last) {
- state = CONFIG_START;
- break;
- }
- *err = bc_error_parser(BC_ERROR_CONFIG_PARSER, src, src_len,
- current, "Invalid value for key, should not have anything "
- "after quotes.");
- break;
-
- case CONFIG_SECTION_VALUE:
- if (c == '\r' || c == '\n' || is_last) {
- if (is_last && c != '\r' && c != '\n')
- bc_string_append_c(value, c);
- bc_trie_insert(section->data, bc_str_strip(key),
- bc_strdup(bc_str_rstrip(value->str)));
- free(key);
- key = NULL;
- bc_string_free(value, true);
- value = NULL;
- state = CONFIG_START;
- break;
- }
- bc_string_append_c(value, c);
- break;
-
- case CONFIG_SECTION_LIST_START:
- if (c == ' ' || c == '\t' || c == '\f' || c == '\v')
- break;
- if (c == '"') {
- state = CONFIG_SECTION_LIST_QUOTE;
- break;
- }
- bc_string_append_c(value, c);
- state = CONFIG_SECTION_LIST;
- break;
-
- case CONFIG_SECTION_LIST_QUOTE:
- if (c == '"') {
- section->data = bc_slist_append(section->data,
- bc_string_free(value, false));
- value = NULL;
- state = CONFIG_SECTION_LIST_POST_QUOTED;
- break;
-
- }
- bc_string_append_c(value, c);
- break;
-
- case CONFIG_SECTION_LIST_POST_QUOTED:
- if (c == ' ' || c == '\t' || c == '\f' || c == '\v')
- break;
- if (c == '\r' || c == '\n' || is_last) {
- state = CONFIG_START;
- break;
- }
- *err = bc_error_parser(BC_ERROR_CONFIG_PARSER, src, src_len,
- current, "Invalid value for list item, should not have "
- "anything after quotes.");
- break;
-
- case CONFIG_SECTION_LIST:
- if (c == '\r' || c == '\n' || is_last) {
- if (is_last && c != '\r' && c != '\n')
- bc_string_append_c(value, c);
- section->data = bc_slist_append(section->data,
- bc_strdup(bc_str_strip(value->str)));
- bc_string_free(value, true);
- value = NULL;
- state = CONFIG_START;
- break;
-
- }
- bc_string_append_c(value, c);
- break;
-
- }
-
- if (*err != NULL) {
- bc_config_free(rv);
- rv = NULL;
- break;
- }
-
- current++;
- }
-
- free(section_name);
- free(key);
- bc_string_free(value, true);
-
- return rv;
-}
-
-
-static void
-list_keys(const char *key, const char *value, bc_slist_t **l)
-{
- *l = bc_slist_append(*l, bc_strdup(key));
-}
-
-
-char**
-bc_config_list_sections(bc_config_t *config)
-{
- if (config == NULL)
- return NULL;
-
- bc_slist_t *l = NULL;
- bc_trie_foreach(config->root, (bc_trie_foreach_func_t) list_keys, &l);
-
- char **rv = bc_malloc(sizeof(char*) * (bc_slist_length(l) + 1));
-
- size_t i = 0;
- for (bc_slist_t *tmp = l; tmp != NULL; tmp = tmp->next, i++)
- rv[i] = tmp->data;
- rv[i] = NULL;
-
- bc_slist_free(l);
-
- return rv;
-}
-
-
-char**
-bc_config_list_keys(bc_config_t *config, const char *section)
-{
- if (config == NULL)
- return NULL;
-
- bc_configparser_section_t *s = bc_trie_lookup(config->root, section);
- if (s == NULL)
- return NULL;
-
- if (s->type != CONFIG_SECTION_TYPE_MAP)
- return NULL;
-
- bc_slist_t *l = NULL;
- bc_trie_foreach(s->data, (bc_trie_foreach_func_t) list_keys, &l);
-
- char **rv = bc_malloc(sizeof(char*) * (bc_slist_length(l) + 1));
-
- size_t i = 0;
- for (bc_slist_t *tmp = l; tmp != NULL; tmp = tmp->next, i++)
- rv[i] = tmp->data;
- rv[i] = NULL;
-
- bc_slist_free(l);
-
- return rv;
-}
-
-
-const char*
-bc_config_get(bc_config_t *config, const char *section, const char *key)
-{
- if (config == NULL)
- return NULL;
-
- bc_configparser_section_t *s = bc_trie_lookup(config->root, section);
- if (s == NULL)
- return NULL;
-
- if (s->type != CONFIG_SECTION_TYPE_MAP)
- return NULL;
-
- return bc_trie_lookup(s->data, key);
-}
-
-
-const char*
-bc_config_get_with_default(bc_config_t *config, const char *section, const char *key,
- const char *default_)
-{
- const char *rv = bc_config_get(config, section, key);
- if (rv == NULL)
- return default_;
- return rv;
-}
-
-
-char**
-bc_config_get_list(bc_config_t *config, const char *section)
-{
- if (config == NULL)
- return NULL;
-
- bc_configparser_section_t *s = bc_trie_lookup(config->root, section);
- if (s == NULL)
- return NULL;
-
- if (s->type != CONFIG_SECTION_TYPE_LIST)
- return NULL;
-
- char **rv = bc_malloc(sizeof(char*) * (bc_slist_length(s->data) + 1));
-
- size_t i = 0;
- for (bc_slist_t *tmp = s->data; tmp != NULL; tmp = tmp->next, i++)
- rv[i] = bc_strdup(tmp->data);
- rv[i] = NULL;
-
- return rv;
-}
-
-
-void
-bc_config_free(bc_config_t *config)
-{
- if (config == NULL)
- return;
- bc_trie_free(config->root);
- free(config);
-}