From ee3ea3be13744f766af57e4ae4504b5942655184 Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Mon, 9 Sep 2024 00:54:18 +0200 Subject: Refactor and simplify config --- src/block.c | 4 +- src/block.h | 12 ++-- src/comet.c | 12 ++-- src/config.c | 231 +++++++++++++++++++++++++++++------------------------------ src/config.h | 9 +-- 5 files changed, 131 insertions(+), 137 deletions(-) diff --git a/src/block.c b/src/block.c index fb35605..9a65d84 100644 --- a/src/block.c +++ b/src/block.c @@ -45,6 +45,7 @@ void block_copy(block_t *copy, const block_t *block) } } +// NOTE: This does not recursively free groups! void block_free(block_t *block) { free(block->label); @@ -52,9 +53,6 @@ void block_free(block_t *block) if (block->type == BLOCK_TEXT) { free(block->text.text); } else if (block->type == BLOCK_GROUP) { - for (int i = 0; i < block->group.n_children; i++) - block_free(block->group.children[i]); - free(block->group.children); } diff --git a/src/block.h b/src/block.h index 845ccfd..7d37c3d 100644 --- a/src/block.h +++ b/src/block.h @@ -54,19 +54,19 @@ struct block { block_finalize_t finalize_cb; color_t color; color_t line_color; - int line_width; - int x_padding, y_padding; - int min_width, max_width; + unsigned int line_width; + unsigned int x_padding, y_padding; + unsigned int min_width, max_width; union { struct { char *text; color_t text_color; align_t text_align; - int text_size; + unsigned int text_size; } text; struct { - int spacing; - int n_children; + unsigned int spacing; + size_t n_children; struct block **children; } group; }; diff --git a/src/comet.c b/src/comet.c index dda183b..6fccb3d 100644 --- a/src/comet.c +++ b/src/comet.c @@ -95,12 +95,12 @@ int main(int argc, char **argv) .height = config.height, }; + block_t *block = config_resolve(&config); + log_debug("Starting bar"); + window_resize(&window, config.width, config.height); window_move(&window, x_padding, y_padding); - block_t main_block = { 0 }; - config_resolve(&config, &main_block); - // TODO: Allow ondemand rendering struct timespec rate, start, end, diff; @@ -111,10 +111,10 @@ int main(int argc, char **argv) while (running) { timespec_get(&start, TIME_UTC); - block_update(&main_block); + block_update(block); layout_t layout; - layout_init(&layout, &main_block, info); + layout_init(&layout, block, info); event_dispatch(&display, &layout); @@ -128,7 +128,7 @@ int main(int argc, char **argv) nanosleep(&diff, NULL); } - log_debug("Quitting"); + log_debug("Quitting bar"); g_object_unref(info.context); pango_font_description_free(fontdesc); 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) diff --git a/src/config.h b/src/config.h index 726006e..a7d196f 100644 --- a/src/config.h +++ b/src/config.h @@ -34,11 +34,8 @@ typedef struct { char *monitor; bool override_redirect; color_t background; - - uint32_t height; - uint32_t width; - uint32_t spacing; - char **children; + unsigned int width; + unsigned int height; } config_t; typedef struct { @@ -50,7 +47,7 @@ void config_init(config_t *config); void config_read(config_t *config, FILE *file); -void config_resolve(config_t *config, block_t *block); +block_t *config_resolve(config_t *config); void config_free(config_t *config); -- cgit v1.2.3