diff options
| author | Federico Angelilli <code@fedang.net> | 2024-11-24 17:40:26 +0100 |
|---|---|---|
| committer | Federico Angelilli <code@fedang.net> | 2024-11-24 17:40:26 +0100 |
| commit | 76ad6b0d404d40f08b73d90ac5f66564c29feb95 (patch) | |
| tree | 59e2c0b0c5ecd0e092a295352f8b7fa0bc15db4e /src | |
| parent | 30020a08392c959505bd27388564f7436a04bace (diff) | |
Refactor config parser
Diffstat (limited to 'src')
| -rw-r--r-- | src/action.c | 8 | ||||
| -rw-r--r-- | src/block.c | 12 | ||||
| -rw-r--r-- | src/block.h | 6 | ||||
| -rw-r--r-- | src/blocks/date.c | 2 | ||||
| -rw-r--r-- | src/blocks/fs.c | 2 | ||||
| -rw-r--r-- | src/blocks/ram.c | 2 | ||||
| -rw-r--r-- | src/blocks/script.c | 2 | ||||
| -rw-r--r-- | src/blocks/slider.c | 8 | ||||
| -rw-r--r-- | src/blocks/text.c | 14 | ||||
| -rw-r--r-- | src/config.c | 269 | ||||
| -rw-r--r-- | src/config.h | 21 |
11 files changed, 208 insertions, 138 deletions
diff --git a/src/action.c b/src/action.c index 81995e6..0ae0c0a 100644 --- a/src/action.c +++ b/src/action.c @@ -9,6 +9,7 @@ void action_perform(action_t *action, block_t *block, config_t *config) { block_t *target = block; + bool warned = false; for (size_t i = 0; i < action->length; i++) { const char *key = action->parts[i].key; @@ -29,19 +30,20 @@ void action_perform(action_t *action, block_t *block, config_t *config) } } } + warned = false; break; } case ACTION_SET_PAIR: { assert(target != NULL); - - if (target->scheme->change_fn == NULL) { + if (!warned && target->scheme->change_fn == NULL) { log_warn("Block '%s' does not support changing values", target->label); + warned = true; continue; } // Skip "set-" - block_change(target, key + 4, value); + target->scheme->change_fn(target, config, key + 4, value); break; } diff --git a/src/block.c b/src/block.c index f3283e9..00a0dde 100644 --- a/src/block.c +++ b/src/block.c @@ -50,17 +50,11 @@ void block_update(block_t *block) } } -int block_change(block_t *block, const char *key, const char *value) +config_status_t block_change(block_t *block, const char *key, const char *value) { - if (block->scheme->change_fn == NULL) { - log_value_debug("Ignored block change", - "s:label", block->label, - "s:key", key, - "s:value", value); - return 0; - } - return block->scheme->change_fn(block, key, value); + + return CONFIG_UNKNOWN; } void block_free(block_t *block) diff --git a/src/block.h b/src/block.h index 73490ad..ca4f4ab 100644 --- a/src/block.h +++ b/src/block.h @@ -102,11 +102,11 @@ typedef void (*block_clean_t)(block_t *block); // Called to validate the block after parsing the config // -typedef int (*block_validate_t)(block_t *block); +typedef int (*block_validate_t)(block_t *block, config_t *config); // Called to validate changes to a block variable // -typedef int (*block_change_t)(block_t *block, const char *key, const char *value); +typedef config_status_t (*block_change_t)(block_t *block, config_t *config, const char *key, const char *value); struct block_scheme { const char *name; @@ -122,7 +122,7 @@ extern const block_scheme_t *block_schemes[]; void block_update(block_t *block); -int block_change(block_t *block, const char *key, const char *value); +config_status_t block_change(block_t *block, const char *key, const char *value); void block_free(block_t *block); diff --git a/src/blocks/date.c b/src/blocks/date.c index 1cb9da9..cd1adce 100644 --- a/src/blocks/date.c +++ b/src/blocks/date.c @@ -46,7 +46,7 @@ static void block_date_clean(block_t *block) free(date->block.text); } -static int block_date_validate(block_t *block) +static int block_date_validate(block_t *block, config_t *config) { block_date_t *date = (block_date_t *)block; int errors = 0; diff --git a/src/blocks/fs.c b/src/blocks/fs.c index 688956d..1196c68 100644 --- a/src/blocks/fs.c +++ b/src/blocks/fs.c @@ -135,7 +135,7 @@ static void block_fs_clean(block_t *block) free(fs->block.text); } -static int block_fs_validate(block_t *block) +static int block_fs_validate(block_t *block, config_t *config) { block_fs_t *fs = (block_fs_t *)block; int errors = 0; diff --git a/src/blocks/ram.c b/src/blocks/ram.c index 2aae5ac..28af60c 100644 --- a/src/blocks/ram.c +++ b/src/blocks/ram.c @@ -143,7 +143,7 @@ static void block_ram_clean(block_t *block) free(ram->block.text); } -static int block_ram_validate(block_t *block) +static int block_ram_validate(block_t *block, config_t *config) { block_ram_t *ram = (block_ram_t *)block; int errors = 0; diff --git a/src/blocks/script.c b/src/blocks/script.c index bcbb1b2..6fa5f6d 100644 --- a/src/blocks/script.c +++ b/src/blocks/script.c @@ -58,7 +58,7 @@ static void block_script_clean(block_t *block) free(script->block.text); } -static int block_script_validate(block_t *block) +static int block_script_validate(block_t *block, config_t *config) { block_script_t *script = (block_script_t *)block; int errors = 0; diff --git a/src/blocks/slider.c b/src/blocks/slider.c index 7050faf..f568105 100644 --- a/src/blocks/slider.c +++ b/src/blocks/slider.c @@ -216,7 +216,7 @@ static void block_slider_clean(block_t *block) gradient_free(&slider->knob_line_color); } -static int block_slider_validate(block_t *block) +static int block_slider_validate(block_t *block, config_t *config) { block_slider_t *slider = (block_slider_t *)block; int errors = 0; @@ -242,6 +242,11 @@ static int block_slider_validate(block_t *block) return errors; } +static config_status_t block_slider_change(block_t *block, config_t *config, const char *key, const char *value) +{ + return 0; +} + static config_enum_t knob_shape_enum[] = { { "none", KNOB_NONE }, { "capsule", KNOB_CAPSULE }, @@ -279,4 +284,5 @@ const block_scheme_t block_slider_scheme = { .init_fn = block_slider_init, .clean_fn = block_slider_clean, .validate_fn = block_slider_validate, + .change_fn = block_slider_change, }; diff --git a/src/blocks/text.c b/src/blocks/text.c index be4c398..bfaefe8 100644 --- a/src/blocks/text.c +++ b/src/blocks/text.c @@ -13,7 +13,7 @@ static void block_text_clean(block_t *block) free(text->text); } -static int block_text_validate(block_t *block) +static int block_text_validate(block_t *block, config_t *config) { block_text_t *text = (block_text_t *)block; int errors = 0; @@ -26,6 +26,17 @@ static int block_text_validate(block_t *block) return errors; } +static config_status_t block_text_change(block_t *block, config_t *config, const char *key, const char *value) +{ + + // text + // text_color + // text_align + // text_size + + return CONFIG_UNKNOWN; +} + const block_scheme_t block_text_scheme = { .name = "text", .entries = NULL, @@ -33,4 +44,5 @@ const block_scheme_t block_text_scheme = { .init_fn = block_text_init, .clean_fn = block_text_clean, .validate_fn = block_text_validate, + .change_fn = block_text_change, }; diff --git a/src/config.c b/src/config.c index f76065c..c8f53f9 100644 --- a/src/config.c +++ b/src/config.c @@ -14,13 +14,14 @@ #define ANY_INI_IMPLEMENT #include "any_ini.h" -typedef enum { - CONFIG_SUCCESS, - CONFIG_INVALID, - CONFIG_UNKNOWN, -} config_status_t; +config_enum_t text_align_enum[] = { + { "left", ALIGN_LEFT }, + { "center", ALIGN_CENTER }, + { "right", ALIGN_RIGHT }, + { 0 }, +}; -static const config_entry_t bar_entries[] = { +const config_entry_t bar_entries[] = { { "width", CONFIG_UINT, NULL, offsetof(config_t, width) }, { "height", CONFIG_UINT, NULL, offsetof(config_t, height) }, { "font", CONFIG_STRING, NULL, offsetof(config_t, font) }, @@ -31,7 +32,7 @@ static const config_entry_t bar_entries[] = { { 0 }, }; -static const config_entry_t block_entries[] = { +const config_entry_t block_entries[] = { { "hidden", CONFIG_BOOL, NULL, offsetof(block_t, hidden) }, { "color", CONFIG_GRADIENT, NULL, offsetof(block_t, bg_color) }, { "line-color", CONFIG_GRADIENT, NULL, offsetof(block_t, line_color) }, @@ -45,21 +46,14 @@ static const config_entry_t block_entries[] = { { 0 }, }; -static const config_entry_t block_group_entries[] = { +const config_entry_t block_group_entries[] = { { "spacing", CONFIG_UINT, NULL, offsetof(block_group_t, spacing) }, { "blocks", CONFIG_LIST, NULL, offsetof(block_group_t, children) }, { "collapse", CONFIG_BOOL, NULL, offsetof(block_group_t, collapse) }, { 0 }, }; -static config_enum_t text_align_enum[] = { - { "left", ALIGN_LEFT }, - { "center", ALIGN_CENTER }, - { "right", ALIGN_RIGHT }, - { 0 }, -}; - -static const config_entry_t block_text_entries[] = { +const config_entry_t block_text_entries[] = { { "text", CONFIG_STRING, NULL, offsetof(block_text_t, text) }, { "text-color", CONFIG_COLOR, NULL, offsetof(block_text_t, text_color) }, { "text-size", CONFIG_UINT, NULL, offsetof(block_text_t, text_size) }, @@ -67,6 +61,25 @@ static const config_entry_t block_text_entries[] = { { 0 }, }; +const char *config_type_to_string(config_type_t type) +{ + static const char *types[] = { + "string", + "integer", + "unsigned integer", + "double float", + "boolean", + "color", + "gradient", + "enum", + "time", + "list", + }; + + assert(type >= CONFIG_STRING && type <= CONFIG_LIST); + return types[type]; +} + static bool config_read_string(const char *value, char **result) { if (value == NULL) @@ -290,29 +303,98 @@ static bool config_read_list(const char *value, char ***result) return true; } -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) +static config_status_t config_read_block(const block_scheme_t *scheme, block_t *block, const char **type, + const char *key, const char *value) { - static const char *types[] = { - "string", - "integer", - "unsigned integer", - "double float", - "boolean", - "color", - "gradient", - "enum", - "time", - "list", + const char *section = "block"; + size_t index = 0; + + config_status_t status = config_read_entry(block_entries, block, &index, section, block->label, key, value); + *type = config_type_to_string(block_entries[index].type); + + if (status != CONFIG_UNKNOWN) return status; + + if (block->type == BLOCK_GROUP) + status = config_read_entry(block_group_entries, block, &index, section, block->label, key, value); + else if (block->type == BLOCK_TEXT) + status = config_read_entry(block_text_entries, block, &index, section, block->label, key, value); + + *type = config_type_to_string(block_entries[index].type); + if (status != CONFIG_UNKNOWN || scheme->entries == NULL) + return status; + + status = config_read_entry(scheme->entries, block, &index, section, block->label, key, value); + *type = config_type_to_string(block_entries[index].type); + return status; +} + +static block_t *config_alloc_block(config_t *config, const block_scheme_t *scheme, char *label) +{ + config->blocks = realloc(config->blocks, ++config->n_blocks * sizeof(block_t *)); + assert(config->blocks != NULL); + + block_t *block = config->blocks[config->n_blocks - 1] = calloc(1, scheme->size); + assert(block != NULL); + + block->label = label; + block->scheme = scheme; + scheme->init_fn(block); + + return block; +} + +static config_status_t config_read_action(action_t *action, const char *key, const char *value) +{ + action_type_t type; + + if (!strcmp(key, "target")) + type = ACTION_TARGET; + else if (!strncmp(key, "set-", 4)) + type = ACTION_SET_PAIR; + else if (!strcmp(key, "run-script")) + type = ACTION_RUN_SCRIPT; + else + return CONFIG_UNKNOWN; + + action->parts = realloc(action->parts, ++action->length * sizeof(action_part_t)); + assert(action->parts != NULL); + + action->parts[action->length - 1].type = type; + action->parts[action->length - 1].key = strcopy(key); + action->parts[action->length - 1].value = strcopy(value); + + return CONFIG_SUCCESS; +} + +// TODO: More robust way to define defaults +void config_init(config_t *config) +{ + const config_t config_default = { + .font = "monospace 10", + .monitor = NULL, + .width = 100, + .height = 50, + .override_redirect = false, }; + memcpy(config, &config_default, sizeof(config_t)); + config->font = strcopy(config_default.font); + + extern const block_scheme_t block_group_scheme; + block_group_t *bar = (block_group_t *)config_alloc_block(config, &block_group_scheme, strcopy("bar")); + bar->spacing = 10; +} + +config_status_t config_read_entry(const config_entry_t *entries, void *result, size_t *index, + const char *section, const char *label, const char *key, const char *value) +{ for (size_t i = 0; entries[i].key != NULL; i++) { if (!strcmp(key, entries[i].key)) { - if (type != NULL) - *type = types[entries[i].type]; + if (index != NULL) *index = i; result += entries[i].offset; - bool nullable = type == CONFIG_STRING; + bool nullable = entries[i].type == CONFIG_STRING || entries[i].type == CONFIG_LIST; + if ((value == NULL || *value == '\0') && !nullable) return CONFIG_INVALID; @@ -320,35 +402,45 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re 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); + log_debug("Set '%s%s%s.%s' to '%s'", + section != NULL ? section : "", section != NULL ? "." : "", + label, 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); + log_debug("Set '%s%s%s.%s' to '%d'", + section != NULL ? section : "", section != NULL ? "." : "", + label, 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); + log_debug("Set '%s%s%s.%s' to '%u'", + section != NULL ? section : "", section != NULL ? "." : "", + label, 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); + log_debug("Set '%s%s%s.%s' to '%g'", + section != NULL ? section : "", section != NULL ? "." : "", + label, 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"); + log_debug("Set '%s%s%s.%s' to '%s'", + section != NULL ? section : "", section != NULL ? "." : "", + label, key, *(bool *)result ? "true" : "false"); return CONFIG_SUCCESS; } break; @@ -356,7 +448,9 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re 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); + log_debug("Set '%s%s%s.%s' to '%s'", + section != NULL ? section : "", section != NULL ? "." : "", + label, key, color); free(color); return CONFIG_SUCCESS; } @@ -365,7 +459,9 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re case CONFIG_GRADIENT: if (config_read_gradient(value, (gradient_t *)result)) { char *gradient = gradient_to_string((gradient_t *)result); - log_debug("Set '%s.%s' to '%s'", section, key, gradient); + log_debug("Set '%s%s%s.%s' to '%s'", + section != NULL ? section : "", section != NULL ? "." : "", + label, key, gradient); free(gradient); return CONFIG_SUCCESS; } @@ -373,21 +469,28 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re 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); + log_debug("Set '%s%s%s.%s' to '%d'", + section != NULL ? section : "", section != NULL ? "." : "", + label, 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); + // TODO: Print + log_debug("Set '%s%s%s.%s' to '%s'", + section != NULL ? section : "", section != NULL ? "." : "", + label, 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); + log_debug("Set '%s%s%s.%s' to '%s'", + section != NULL ? section : "", section != NULL ? "." : "", + label, key, value); return CONFIG_SUCCESS; } break; @@ -403,77 +506,6 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re return CONFIG_UNKNOWN; } -static config_status_t config_read_block(const block_scheme_t *scheme, block_t *block, const char **type, - const char *section, const char *key, const char *value) -{ - config_status_t status = config_read_entry(block_entries, block, type, section, key, value); - if (status != CONFIG_UNKNOWN) return status; - - status = config_read_entry(block->type == BLOCK_GROUP ? block_group_entries : block_text_entries, - block, type, section, key, value); - - return status != CONFIG_UNKNOWN || scheme == NULL || scheme->entries == NULL - ? status - : config_read_entry(scheme->entries, block, type, section, key, value); -} - -static block_t *config_alloc_block(config_t *config, const block_scheme_t *scheme, char *label) -{ - config->blocks = realloc(config->blocks, ++config->n_blocks * sizeof(block_t *)); - assert(config->blocks != NULL); - - block_t *block = config->blocks[config->n_blocks - 1] = calloc(1, scheme->size); - assert(block != NULL); - - block->label = label; - block->scheme = scheme; - scheme->init_fn(block); - - return block; -} - -static config_status_t config_read_action(action_t *action, const char *section, const char *key, const char *value) -{ - action_type_t type; - - if (!strcmp(key, "target")) - type = ACTION_TARGET; - else if (!strncmp(key, "set-", 4)) - type = ACTION_SET_PAIR; - else if (!strcmp(key, "run-script")) - type = ACTION_RUN_SCRIPT; - else - return CONFIG_UNKNOWN; - - action->parts = realloc(action->parts, ++action->length * sizeof(action_part_t)); - assert(action->parts != NULL); - - action->parts[action->length - 1].type = type; - action->parts[action->length - 1].key = strcopy(key); - action->parts[action->length - 1].value = strcopy(value); - - return CONFIG_SUCCESS; -} - -// TODO: More robust way to define defaults -void config_init(config_t *config) -{ - const config_t config_default = { - .font = "monospace 10", - .monitor = NULL, - .width = 100, - .height = 50, - .override_redirect = false, - }; - - memcpy(config, &config_default, sizeof(config_t)); - config->font = strcopy(config_default.font); - - extern const block_scheme_t block_group_scheme; - block_group_t *bar = (block_group_t *)config_alloc_block(config, &block_group_scheme, strcopy("bar")); - bar->spacing = 10; -} - int config_read(config_t *config, FILE *file) { any_ini_stream_t ini; @@ -601,19 +633,22 @@ int config_read(config_t *config, FILE *file) config_status_t status; if (bar_section) { - status = config_read_entry(bar_entries, config, &type, section, key, value); + size_t index = 0; + status = config_read_entry(bar_entries, config, &index, NULL, "bar", key, value); // Try the block entries if (status == CONFIG_UNKNOWN) block = config->blocks[0]; + else + type = config_type_to_string(bar_entries[index].type); } if (block != NULL) { - status = config_read_block(scheme, block, &type, section, key, value); + status = config_read_block(scheme, block, &type, key, value); } if (action != NULL) { - status = config_read_action(action, section, key, value); + status = config_read_action(action, key, value); } switch (status) { @@ -672,7 +707,7 @@ int config_validate(config_t *config) if (scheme->validate_fn == NULL) continue; log_debug("Validating 'block.%s'", block->label); - int tmp = scheme->validate_fn(block); + int tmp = scheme->validate_fn(block, config); errors += tmp; block->validated = tmp == 0; } diff --git a/src/config.h b/src/config.h index e005dff..e56de55 100644 --- a/src/config.h +++ b/src/config.h @@ -30,6 +30,12 @@ typedef struct { size_t offset; } config_entry_t; +typedef enum { + CONFIG_SUCCESS, + CONFIG_INVALID, + CONFIG_UNKNOWN, +} config_status_t; + typedef struct { size_t n_blocks; block_t **blocks; @@ -49,8 +55,23 @@ typedef struct { int value; } config_enum_t; +extern config_enum_t text_align_enum[]; + +extern const config_entry_t bar_entries[]; + +extern const config_entry_t block_entries[]; + +extern const config_entry_t block_group_entries[]; + +extern const config_entry_t block_text_entries[]; + +const char *config_type_to_string(config_type_t type); + void config_init(config_t *config); +config_status_t config_read_entry(const config_entry_t *entries, void *result, size_t *index, + const char *section, const char *label, const char *key, const char *value); + int config_read(config_t *config, FILE *file); int config_validate(config_t *config); |
