(config_file) Optimise parsing of 'comment' lines in configuration files

This commit is contained in:
jdgleaver 2020-06-24 14:30:41 +01:00
parent b9f65af98a
commit 9b22874c73

View File

@ -146,42 +146,35 @@ static struct config_entry_list* merge_sort_linked_list(
return result; return result;
} }
/* Searches input string for a comment ('#') entry
* > If a comment is found, returns everything after
* the '#' character and sets 'str' to an empty string
* > If a comment is not found, returns NULL and leaves
* 'str' untouched */
static char *strip_comment(char *str) static char *strip_comment(char *str)
{ {
/* Remove everything after comment. /* Search for a comment (#) character */
* Keep #s inside string literals. */ char *comment = strchr(str, '#');
char *string_end = str + strlen(str);
bool cut_comment = true;
while (!string_is_empty(str)) if (comment)
{ {
char *comment = NULL; /* Check whether comment character occurs
char *literal = strchr(str, '\"'); * within a string literal (i.e. after the
if (!literal) * first (") character) */
literal = string_end; char *literal = strchr(str, '\"');
comment = (char*)strchr(str, '#');
if (!comment) if (!literal || (literal > comment))
comment = string_end;
if (cut_comment && literal < comment)
{ {
cut_comment = false; /* This line is a valid comment
str = literal + 1; * > Set input 'str' to NUL
} * > Return everything after the
else if (!cut_comment && literal) * comment (#) character */
{ *str = '\0';
cut_comment = true; return ++comment;
str = (literal < string_end) ? literal + 1 : string_end;
}
else
{
*comment = '\0';
str = comment;
} }
} }
return str; return NULL;
} }
static char *extract_value(char *line, bool is_value) static char *extract_value(char *line, bool is_value)
@ -337,26 +330,52 @@ static bool parse_line(config_file_t *conf,
char *key_tmp = NULL; char *key_tmp = NULL;
size_t cur_size = 8; size_t cur_size = 8;
size_t idx = 0; size_t idx = 0;
char *comment = strip_comment(line); char *comment = NULL;
/* Starting line with #include includes config files. */ /* Ignore empty lines */
if (comment == line) if (string_is_empty(line))
return false;
/* Check whether line is a comment */
comment = strip_comment(line);
if (comment)
{ {
comment++; /* Starting a line with '#include' appends a
if (strstr(comment, "include ") == comment) * sub-config file */
if (string_starts_with(comment, "include "))
{ {
char *include_line = comment + STRLEN_CONST("include "); char *include_line = comment + STRLEN_CONST("include ");
char *path = extract_value(include_line, false); char *path = NULL;
if (string_is_empty(path)) if (string_is_empty(include_line))
return false; 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) if (conf->include_depth >= MAX_INCLUDE_DEPTH)
{
fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n"); fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n");
else free(path);
add_sub_conf(conf, path, cb); return false;
}
add_sub_conf(conf, path, cb);
free(path); free(path);
return true;
} }
/* All other comment lines are ignored */
else
return false;
} }
/* Skips to first character. */ /* Skips to first character. */