(config_file) Cleanups
This commit is contained in:
parent
f18af41876
commit
b7b96fb142
|
@ -56,10 +56,11 @@ struct config_include_list
|
||||||
struct config_include_list *next;
|
struct config_include_list *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static config_file_t *config_file_new_internal(
|
/* Forward declaration */
|
||||||
const char *path, unsigned depth, config_file_cb_t *cb);
|
static bool config_file_parse_line(config_file_t *conf,
|
||||||
|
struct config_entry_list *list, char *line, config_file_cb_t *cb);
|
||||||
|
|
||||||
static int config_sort_compare_func(struct config_entry_list *a,
|
static int config_file_sort_compare_func(struct config_entry_list *a,
|
||||||
struct config_entry_list *b)
|
struct config_entry_list *b)
|
||||||
{
|
{
|
||||||
if (a && b)
|
if (a && b)
|
||||||
|
@ -78,7 +79,7 @@ static int config_sort_compare_func(struct config_entry_list *a,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://stackoverflow.com/questions/7685/merge-sort-a-linked-list */
|
/* https://stackoverflow.com/questions/7685/merge-sort-a-linked-list */
|
||||||
static struct config_entry_list* merge_sort_linked_list(
|
static struct config_entry_list* config_file_merge_sort_linked_list(
|
||||||
struct config_entry_list *list, int (*compare)(
|
struct config_entry_list *list, int (*compare)(
|
||||||
struct config_entry_list *one,struct config_entry_list *two))
|
struct config_entry_list *one,struct config_entry_list *two))
|
||||||
{
|
{
|
||||||
|
@ -108,8 +109,8 @@ static struct config_entry_list* merge_sort_linked_list(
|
||||||
last->next = 0;
|
last->next = 0;
|
||||||
|
|
||||||
/* Recurse on the two smaller lists: */
|
/* Recurse on the two smaller lists: */
|
||||||
list = merge_sort_linked_list(list, compare);
|
list = config_file_merge_sort_linked_list(list, compare);
|
||||||
right = merge_sort_linked_list(right, compare);
|
right = config_file_merge_sort_linked_list(right, compare);
|
||||||
|
|
||||||
/* Merge: */
|
/* Merge: */
|
||||||
while (list || right)
|
while (list || right)
|
||||||
|
@ -162,7 +163,7 @@ static struct config_entry_list* merge_sort_linked_list(
|
||||||
* comment text is a suffix of the input string and
|
* comment text is a suffix of the input string and
|
||||||
* has no programmatic value. In this case, the comment
|
* has no programmatic value. In this case, the comment
|
||||||
* is removed from the end of 'str' and NULL is returned */
|
* is removed from the end of 'str' and NULL is returned */
|
||||||
static char *strip_comment(char *str)
|
static char *config_file_strip_comment(char *str)
|
||||||
{
|
{
|
||||||
/* Search for a comment (#) character */
|
/* Search for a comment (#) character */
|
||||||
char *comment = strchr(str, '#');
|
char *comment = strchr(str, '#');
|
||||||
|
@ -211,7 +212,7 @@ static char *strip_comment(char *str)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *extract_value(char *line, bool is_value)
|
static char *config_file_extract_value(char *line, bool is_value)
|
||||||
{
|
{
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
char *value = NULL;
|
char *value = NULL;
|
||||||
|
@ -277,7 +278,7 @@ static char *extract_value(char *line, bool is_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move semantics? */
|
/* Move semantics? */
|
||||||
static void add_child_list(config_file_t *parent, config_file_t *child)
|
static void config_file_add_child_list(config_file_t *parent, config_file_t *child)
|
||||||
{
|
{
|
||||||
struct config_entry_list *list = child->entries;
|
struct config_entry_list *list = child->entries;
|
||||||
if (parent->entries)
|
if (parent->entries)
|
||||||
|
@ -348,7 +349,7 @@ static void config_file_get_realpath(char *s, size_t len,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_sub_conf(config_file_t *conf, char *path,
|
static void config_file_add_sub_conf(config_file_t *conf, char *path,
|
||||||
char *real_path, size_t len, config_file_cb_t *cb)
|
char *real_path, size_t len, config_file_cb_t *cb)
|
||||||
{
|
{
|
||||||
struct config_include_list *head = conf->includes;
|
struct config_include_list *head = conf->includes;
|
||||||
|
@ -376,117 +377,6 @@ static void add_sub_conf(config_file_t *conf, char *path,
|
||||||
conf->path);
|
conf->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_line(config_file_t *conf,
|
|
||||||
struct config_entry_list *list, char *line, config_file_cb_t *cb)
|
|
||||||
{
|
|
||||||
size_t cur_size = 32;
|
|
||||||
size_t idx = 0;
|
|
||||||
char *key = NULL;
|
|
||||||
char *key_tmp = NULL;
|
|
||||||
/* Remove any comment text */
|
|
||||||
char *comment = strip_comment(line);
|
|
||||||
|
|
||||||
/* Check whether entire line is a comment */
|
|
||||||
if (comment)
|
|
||||||
{
|
|
||||||
char real_path[PATH_MAX_LENGTH];
|
|
||||||
char *path = NULL;
|
|
||||||
char *include_line = NULL;
|
|
||||||
config_file_t *sub_conf = NULL;
|
|
||||||
|
|
||||||
/* Starting a line with an 'include' directive
|
|
||||||
* appends a sub-config file
|
|
||||||
* > All other comments are ignored */
|
|
||||||
if (!string_starts_with_size(comment, "include ",
|
|
||||||
STRLEN_CONST("include ")))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
include_line = comment + STRLEN_CONST("include ");
|
|
||||||
|
|
||||||
if (string_is_empty(include_line))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
path = extract_value(include_line, false);
|
|
||||||
|
|
||||||
if (!path)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (string_is_empty(path))
|
|
||||||
{
|
|
||||||
free(path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf->include_depth >= MAX_INCLUDE_DEPTH)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n");
|
|
||||||
free(path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
real_path[0] = '\0';
|
|
||||||
add_sub_conf(conf, path, real_path, sizeof(real_path), cb);
|
|
||||||
|
|
||||||
if ((sub_conf = (config_file_t*)
|
|
||||||
config_file_new_internal(real_path, conf->include_depth + 1, cb)))
|
|
||||||
{
|
|
||||||
/* Pilfer internal list. */
|
|
||||||
add_child_list(conf, sub_conf);
|
|
||||||
config_file_free(sub_conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(path);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip to first non-space character */
|
|
||||||
while (isspace((int)*line))
|
|
||||||
line++;
|
|
||||||
|
|
||||||
/* Allocate storage for key */
|
|
||||||
key = (char*)malloc(cur_size + 1);
|
|
||||||
if (!key)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Copy line contents into key until we
|
|
||||||
* reach the next space character */
|
|
||||||
while (isgraph((int)*line))
|
|
||||||
{
|
|
||||||
/* If current key storage is too small,
|
|
||||||
* double its size */
|
|
||||||
if (idx == cur_size)
|
|
||||||
{
|
|
||||||
cur_size *= 2;
|
|
||||||
key_tmp = (char*)realloc(key, cur_size + 1);
|
|
||||||
|
|
||||||
if (!key_tmp)
|
|
||||||
{
|
|
||||||
free(key);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = key_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
key[idx++] = *line++;
|
|
||||||
}
|
|
||||||
key[idx] = '\0';
|
|
||||||
|
|
||||||
/* Add key and value entries to list */
|
|
||||||
list->key = key;
|
|
||||||
list->value = extract_value(line, true);
|
|
||||||
|
|
||||||
/* An entry without a value is invalid */
|
|
||||||
if (!list->value)
|
|
||||||
{
|
|
||||||
list->key = NULL;
|
|
||||||
free(key);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static config_file_t *config_file_new_internal(
|
static config_file_t *config_file_new_internal(
|
||||||
const char *path, unsigned depth, config_file_cb_t *cb)
|
const char *path, unsigned depth, config_file_cb_t *cb)
|
||||||
{
|
{
|
||||||
|
@ -538,7 +428,7 @@ static config_file_t *config_file_new_internal(
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!string_is_empty(line)
|
!string_is_empty(line)
|
||||||
&& parse_line(conf, list, line, cb))
|
&& config_file_parse_line(conf, list, line, cb))
|
||||||
{
|
{
|
||||||
if (conf->entries)
|
if (conf->entries)
|
||||||
conf->tail->next = list;
|
conf->tail->next = list;
|
||||||
|
@ -567,6 +457,117 @@ error:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool config_file_parse_line(config_file_t *conf,
|
||||||
|
struct config_entry_list *list, char *line, config_file_cb_t *cb)
|
||||||
|
{
|
||||||
|
size_t cur_size = 32;
|
||||||
|
size_t idx = 0;
|
||||||
|
char *key = NULL;
|
||||||
|
char *key_tmp = NULL;
|
||||||
|
/* Remove any comment text */
|
||||||
|
char *comment = config_file_strip_comment(line);
|
||||||
|
|
||||||
|
/* Check whether entire line is a comment */
|
||||||
|
if (comment)
|
||||||
|
{
|
||||||
|
char real_path[PATH_MAX_LENGTH];
|
||||||
|
char *path = NULL;
|
||||||
|
char *include_line = NULL;
|
||||||
|
config_file_t *sub_conf = NULL;
|
||||||
|
|
||||||
|
/* Starting a line with an 'include' directive
|
||||||
|
* appends a sub-config file
|
||||||
|
* > All other comments are ignored */
|
||||||
|
if (!string_starts_with_size(comment, "include ",
|
||||||
|
STRLEN_CONST("include ")))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
include_line = comment + STRLEN_CONST("include ");
|
||||||
|
|
||||||
|
if (string_is_empty(include_line))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
path = config_file_extract_value(include_line, false);
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (string_is_empty(path))
|
||||||
|
{
|
||||||
|
free(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->include_depth >= MAX_INCLUDE_DEPTH)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n");
|
||||||
|
free(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
real_path[0] = '\0';
|
||||||
|
config_file_add_sub_conf(conf, path, real_path, sizeof(real_path), cb);
|
||||||
|
|
||||||
|
if ((sub_conf = (config_file_t*)
|
||||||
|
config_file_new_internal(real_path, conf->include_depth + 1, cb)))
|
||||||
|
{
|
||||||
|
/* Pilfer internal list. */
|
||||||
|
config_file_add_child_list(conf, sub_conf);
|
||||||
|
config_file_free(sub_conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip to first non-space character */
|
||||||
|
while (isspace((int)*line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
/* Allocate storage for key */
|
||||||
|
key = (char*)malloc(cur_size + 1);
|
||||||
|
if (!key)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Copy line contents into key until we
|
||||||
|
* reach the next space character */
|
||||||
|
while (isgraph((int)*line))
|
||||||
|
{
|
||||||
|
/* If current key storage is too small,
|
||||||
|
* double its size */
|
||||||
|
if (idx == cur_size)
|
||||||
|
{
|
||||||
|
cur_size *= 2;
|
||||||
|
key_tmp = (char*)realloc(key, cur_size + 1);
|
||||||
|
|
||||||
|
if (!key_tmp)
|
||||||
|
{
|
||||||
|
free(key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = key_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
key[idx++] = *line++;
|
||||||
|
}
|
||||||
|
key[idx] = '\0';
|
||||||
|
|
||||||
|
/* Add key and value entries to list */
|
||||||
|
list->key = key;
|
||||||
|
list->value = config_file_extract_value(line, true);
|
||||||
|
|
||||||
|
/* An entry without a value is invalid */
|
||||||
|
if (!list->value)
|
||||||
|
{
|
||||||
|
list->key = NULL;
|
||||||
|
free(key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void config_file_free(config_file_t *conf)
|
void config_file_free(config_file_t *conf)
|
||||||
{
|
{
|
||||||
struct config_include_list *inc_tmp = NULL;
|
struct config_include_list *inc_tmp = NULL;
|
||||||
|
@ -630,26 +631,16 @@ bool config_append_file(config_file_t *conf, const char *path)
|
||||||
config_file_t *config_file_new_from_string(char *from_string,
|
config_file_t *config_file_new_from_string(char *from_string,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
char *lines = from_string;
|
char *lines = from_string;
|
||||||
char *save_ptr = NULL;
|
char *save_ptr = NULL;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
struct config_file *conf = (struct config_file*)malloc(sizeof(*conf));
|
struct config_file *conf = config_file_new_alloc();
|
||||||
|
|
||||||
if (!conf)
|
if (!conf)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
conf->path = NULL;
|
|
||||||
conf->entries = NULL;
|
|
||||||
conf->tail = NULL;
|
|
||||||
conf->last = NULL;
|
|
||||||
conf->includes = NULL;
|
|
||||||
conf->include_depth = 0;
|
|
||||||
conf->guaranteed_no_duplicates = false;
|
|
||||||
conf->modified = false;
|
|
||||||
|
|
||||||
if (!string_is_empty(path))
|
if (!string_is_empty(path))
|
||||||
conf->path = strdup(path);
|
conf->path = strdup(path);
|
||||||
|
|
||||||
if (string_is_empty(lines))
|
if (string_is_empty(lines))
|
||||||
return conf;
|
return conf;
|
||||||
|
|
||||||
|
@ -675,7 +666,7 @@ config_file_t *config_file_new_from_string(char *from_string,
|
||||||
/* Parse current line */
|
/* Parse current line */
|
||||||
if (
|
if (
|
||||||
!string_is_empty(line)
|
!string_is_empty(line)
|
||||||
&& parse_line(conf, list, line, NULL))
|
&& config_file_parse_line(conf, list, line, NULL))
|
||||||
{
|
{
|
||||||
if (conf->entries)
|
if (conf->entries)
|
||||||
conf->tail->next = list;
|
conf->tail->next = list;
|
||||||
|
@ -1198,8 +1189,9 @@ void config_file_dump_orbis(config_file_t *conf, int fd)
|
||||||
includes = includes->next;
|
includes = includes->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
list = merge_sort_linked_list((struct config_entry_list*)
|
list = config_file_merge_sort_linked_list(
|
||||||
conf->entries, config_sort_compare_func);
|
(struct config_entry_list*)conf->entries,
|
||||||
|
config_file_sort_compare_func);
|
||||||
conf->entries = list;
|
conf->entries = list;
|
||||||
|
|
||||||
while (list)
|
while (list)
|
||||||
|
@ -1228,8 +1220,9 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sort)
|
if (sort)
|
||||||
list = merge_sort_linked_list((struct config_entry_list*)
|
list = config_file_merge_sort_linked_list(
|
||||||
conf->entries, config_sort_compare_func);
|
(struct config_entry_list*)conf->entries,
|
||||||
|
config_file_sort_compare_func);
|
||||||
else
|
else
|
||||||
list = (struct config_entry_list*)conf->entries;
|
list = (struct config_entry_list*)conf->entries;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue