aboutsummaryrefslogtreecommitdiff
path: root/src/config.c
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-09-09 00:54:18 +0200
committerFederico Angelilli <code@fedang.net>2024-09-09 00:54:18 +0200
commitee3ea3be13744f766af57e4ae4504b5942655184 (patch)
tree6aecd9f5a93d4ee492155b89a453d722a61d5d81 /src/config.c
parentbdfa5a92e2bededb520dad6741e81128c67fb502 (diff)
Refactor and simplify config
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c231
1 files changed, 115 insertions, 116 deletions
diff --git a/src/config.c b/src/config.c
index 93d123f..99888da 100644
--- a/src/config.c
+++ b/src/config.c
@@ -23,12 +23,10 @@ typedef enum {
static const config_entry_t bar_entries[] = {
{ "width", CONFIG_UINT, NULL, offsetof(config_t, width) },
{ "height", CONFIG_UINT, NULL, offsetof(config_t, height) },
- { "spacing", CONFIG_UINT, NULL, offsetof(config_t, spacing) },
{ "font", CONFIG_STRING, NULL, offsetof(config_t, font) },
{ "monitor", CONFIG_STRING, NULL, offsetof(config_t, monitor) },
{ "override-redirect", CONFIG_BOOL, NULL, offsetof(config_t, override_redirect) },
{ "background", CONFIG_COLOR, NULL, offsetof(config_t, background) },
- { "blocks", CONFIG_LIST, NULL, offsetof(config_t, children) },
{ 0 },
};
@@ -36,17 +34,17 @@ static const config_entry_t block_entries[] = {
{ "hidden", CONFIG_BOOL, NULL, offsetof(block_t, hidden) },
{ "color", CONFIG_COLOR, NULL, offsetof(block_t, color) },
{ "line-color", CONFIG_COLOR, NULL, offsetof(block_t, line_color) },
- { "line-width", CONFIG_INT, NULL, offsetof(block_t, line_width) },
- { "x-padding", CONFIG_INT, NULL, offsetof(block_t, x_padding) },
- { "y-padding", CONFIG_INT, NULL, offsetof(block_t, y_padding) },
- { "min-width", CONFIG_INT, NULL, offsetof(block_t, min_width) },
- { "max-width", CONFIG_INT, NULL, offsetof(block_t, max_width) },
+ { "line-width", CONFIG_UINT, NULL, offsetof(block_t, line_width) },
+ { "x-padding", CONFIG_UINT, NULL, offsetof(block_t, x_padding) },
+ { "y-padding", CONFIG_UINT, NULL, offsetof(block_t, y_padding) },
+ { "min-width", CONFIG_UINT, NULL, offsetof(block_t, min_width) },
+ { "max-width", CONFIG_UINT, NULL, offsetof(block_t, max_width) },
{ "interval", CONFIG_TIME, NULL, offsetof(block_t, update_interval) },
{ 0 },
};
static const config_entry_t block_group_entries[] = {
- { "spacing", CONFIG_INT, NULL, offsetof(block_t, group.spacing) },
+ { "spacing", CONFIG_UINT, NULL, offsetof(block_t, group.spacing) },
{ "blocks", CONFIG_LIST, NULL, offsetof(block_t, group.children) },
{ 0 },
};
@@ -61,7 +59,7 @@ static config_enum_t text_align_enum[] = {
static const config_entry_t block_text_entries[] = {
{ "text", CONFIG_STRING, NULL, offsetof(block_t, text.text) },
{ "text-color", CONFIG_COLOR, NULL, offsetof(block_t, text.text_color) },
- { "text-size", CONFIG_INT, NULL, offsetof(block_t, text.text_size) },
+ { "text-size", CONFIG_UINT, NULL, offsetof(block_t, text.text_size) },
{ "text-align", CONFIG_ENUM, text_align_enum, offsetof(block_t, text.text_size) },
{ 0 },
};
@@ -187,6 +185,7 @@ static bool config_read_enum(const char *value, config_enum_t *data, int *result
return false;
}
+// TODO: More robust parsing
static bool config_read_time(const char *value, struct timespec *result)
{
unsigned int ms;
@@ -233,87 +232,6 @@ static bool config_read_list(const char *value, char ***result)
return true;
}
-static config_status_t config_read_any(void *result, config_type_t type, void *data,
- const char *section, const char *key, const char *value)
-{
- bool nullable = type == CONFIG_STRING;
- if ((value == NULL || *value == '\0') && !nullable)
- return CONFIG_INVALID;
-
- switch (type) {
- case CONFIG_STRING:
- // NOTE: The previous string is freed by config_read_string
- if (config_read_string(value, (char **)result)) {
- log_debug("Set '%s.%s' to '%s'", section, key, *(char **)result);
- return CONFIG_SUCCESS;
- }
- break;
-
- case CONFIG_INT:
- if (config_read_int(value, (int *)result)) {
- log_debug("Set '%s.%s' to '%d'", section, key, *(int *)result);
- return CONFIG_SUCCESS;
- }
- break;
-
- case CONFIG_UINT:
- if (config_read_uint(value, (unsigned int *)result)) {
- log_debug("Set '%s.%s' to '%u'", section, key, *(unsigned int *)result);
- return CONFIG_SUCCESS;
- }
- break;
-
- case CONFIG_DOUBLE:
- if (config_read_double(value, (double *)result)) {
- log_debug("Set '%s.%s' to '%lf'", section, key, *(double *)result);
- return CONFIG_SUCCESS;
- }
- break;
-
- case CONFIG_BOOL:
- if (config_read_bool(value, (bool *)result)) {
- log_debug("Set '%s.%s' to '%s'", section, key, *(bool *)result ? "true" : "false");
- return CONFIG_SUCCESS;
- }
- break;
-
- case CONFIG_COLOR:
- if (config_read_color(value, (color_t *)result)) {
- char *color = color_to_string((color_t *)result);
- log_debug("Set '%s.%s' to '%s'", section, key, color);
- free(color);
- return CONFIG_SUCCESS;
- }
- break;
-
- case CONFIG_ENUM:
- if (config_read_enum(value, (config_enum_t *)data, (int *)result)) {
- log_debug("Set '%s.%s' to '%d'", section, key, *(int *)result);
- return CONFIG_SUCCESS;
- }
- break;
-
- case CONFIG_TIME:
- if (config_read_time(value, (struct timespec *)result)) {
- log_debug("Set '%s.%s' to '%s'", section, key, value);
- return CONFIG_SUCCESS;
- }
- break;
-
- case CONFIG_LIST:
- if (config_read_list(value, (char ***)result)) {
- log_debug("Set '%s.%s' to '%s'", section, key, value);
- return CONFIG_SUCCESS;
- }
- break;
-
- default:
- unreachable();
- }
-
- return CONFIG_INVALID;
-}
-
static config_status_t config_read_entry(const config_entry_t *entries, void *result, const char **type,
const char *section, const char *key, const char *value)
{
@@ -335,7 +253,82 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re
*type = types[entries[i].type];
result += entries[i].offset;
- return config_read_any(result, entries[i].type, entries[i].data, section, key, value);
+ bool nullable = type == CONFIG_STRING;
+ if ((value == NULL || *value == '\0') && !nullable)
+ return CONFIG_INVALID;
+
+ switch (entries[i].type) {
+ case CONFIG_STRING:
+ // NOTE: The previous string is freed by config_read_string
+ if (config_read_string(value, (char **)result)) {
+ log_debug("Set '%s.%s' to '%s'", section, key, *(char **)result);
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ case CONFIG_INT:
+ if (config_read_int(value, (int *)result)) {
+ log_debug("Set '%s.%s' to '%d'", section, key, *(int *)result);
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ case CONFIG_UINT:
+ if (config_read_uint(value, (unsigned int *)result)) {
+ log_debug("Set '%s.%s' to '%u'", section, key, *(unsigned int *)result);
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ case CONFIG_DOUBLE:
+ if (config_read_double(value, (double *)result)) {
+ log_debug("Set '%s.%s' to '%lf'", section, key, *(double *)result);
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ case CONFIG_BOOL:
+ if (config_read_bool(value, (bool *)result)) {
+ log_debug("Set '%s.%s' to '%s'", section, key, *(bool *)result ? "true" : "false");
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ case CONFIG_COLOR:
+ if (config_read_color(value, (color_t *)result)) {
+ char *color = color_to_string((color_t *)result);
+ log_debug("Set '%s.%s' to '%s'", section, key, color);
+ free(color);
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ case CONFIG_ENUM:
+ if (config_read_enum(value, (config_enum_t *)entries[i].data, (int *)result)) {
+ log_debug("Set '%s.%s' to '%d'", section, key, *(int *)result);
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ case CONFIG_TIME:
+ if (config_read_time(value, (struct timespec *)result)) {
+ log_debug("Set '%s.%s' to '%s'", section, key, value);
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ case CONFIG_LIST:
+ if (config_read_list(value, (char ***)result)) {
+ log_debug("Set '%s.%s' to '%s'", section, key, value);
+ return CONFIG_SUCCESS;
+ }
+ break;
+
+ default:
+ unreachable();
+ }
+
+ return CONFIG_INVALID;
}
}
@@ -351,7 +344,7 @@ static config_status_t config_read_block(const block_scheme_t *scheme, block_t *
status = config_read_entry(block->type == BLOCK_GROUP ? block_group_entries : block_text_entries,
block, type, section, key, value);
- return status != CONFIG_UNKNOWN || scheme->entries == NULL
+ return status != CONFIG_UNKNOWN || scheme == NULL || scheme->entries == NULL
? status
: config_read_entry(scheme->entries, block->state, type, section, key, value);
}
@@ -361,15 +354,19 @@ void config_init(config_t *config)
const config_t config_default = {
.font = "monospace 10",
.monitor = NULL,
- .height = 50,
.width = 100,
- .spacing = 10,
+ .height = 50,
.override_redirect = false,
};
memcpy(config, &config_default, sizeof(config_t));
config->font = strcopy(config_default.font);
- config->monitor = strcopy(config_default.monitor);
+
+ config->n_blocks = 1;
+ config->blocks = malloc(sizeof(block_t));
+ config->blocks->label = strcopy("bar");
+ config->blocks->type = BLOCK_GROUP;
+ config->blocks->group.spacing = 10;
}
void config_read(config_t *config, FILE *file)
@@ -384,8 +381,8 @@ void config_read(config_t *config, FILE *file)
char *key = NULL, *value = NULL;
int errors = 0;
+ bool bar_section = false;
const block_scheme_t *scheme = NULL;
- const config_entry_t *entries = NULL;
block_t *block = NULL;
if (section != NULL) {
@@ -453,10 +450,8 @@ void config_read(config_t *config, FILE *file)
"i:line", ini.line);
goto skip_pair;
- } else if (!strncmp(section, "action.", 7)) {
- // TODO
} else if (!strcmp(section, "bar")) {
- entries = bar_entries;
+ bar_section = true;
} else
log_warn("Unknown section '%s'", section);
}
@@ -470,16 +465,24 @@ void config_read(config_t *config, FILE *file)
"s:value", value,
"i:line", ini.line);
+ if (!bar_section && block == NULL)
+ goto skip_pair;
+
const char *type;
config_status_t status;
- if (block != NULL)
+ if (bar_section) {
+ status = config_read_entry(bar_entries, config, &type, section, key, value);
+
+ // Try the block entries
+ if (status == CONFIG_UNKNOWN)
+ block = config->blocks;
+ }
+
+ if (block != NULL) {
status = config_read_block(scheme, &config->blocks[config->n_blocks - 1],
&type, section, key, value);
- else if (entries != NULL)
- status = config_read_entry(entries, config, &type, section, key, value);
- else
- goto skip_pair;
+ }
switch (status) {
case CONFIG_SUCCESS:
@@ -512,7 +515,7 @@ skip_pair:
free(value);
}
- if (block != NULL && scheme->validate != NULL) {
+ if (block != NULL && scheme != NULL && scheme->validate != NULL) {
if (errors != 0)
log_trace("Skipped validation for block '%s'", section);
else
@@ -574,25 +577,21 @@ next:
return true;
}
-void config_resolve(config_t *config, block_t *block)
+block_t *config_resolve(config_t *config)
{
int errors = 0;
-
- block->label = strcopy("bar");
- block->type = BLOCK_GROUP;
- block->min_width = block->max_width = config->width;
- block->group.spacing = config->spacing;
- block->group.children = (void *)config->children;
-
- if (config->children == NULL) {
+ if (config->blocks->group.children == NULL) {
errors++;
- log_error("Config should specify at least one block");
+ log_error("Section '%s' requires at least one child", "bar");
} else {
- errors += !config_resolve_children(config, block);
+ config->blocks->min_width = config->blocks->max_width = config->width;
+ errors += !config_resolve_children(config, config->blocks);
}
if (errors > 0)
log_panic("Config could not be resolved");
+
+ return config->blocks;
}
void config_free(config_t *config)