diff options
Diffstat (limited to 'src/block.c')
| -rw-r--r-- | src/block.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/block.c b/src/block.c index 97bc3e8..42a6ebc 100644 --- a/src/block.c +++ b/src/block.c @@ -4,6 +4,7 @@ #include "block.h" #include "util.h" #include "action.h" +#include "config.h" #include "any_log.h" extern const block_scheme_t block_text_scheme; @@ -57,6 +58,98 @@ void block_update(block_t *block) } } +int block_validate_entry(block_t *block, const config_entry_t *entry) +{ + if (entry->checks == NULL) + return 0; + + int errors = 0; + for (size_t i = 0; entry->checks[i].type != CHECK_NONE; i++) { + + void *result = (void *)block + entry->offset; + switch (entry->checks[i].type) { + case CHECK_POSITIVE: { + assert(entry->type == CONFIG_INT || entry->type == CONFIG_DOUBLE); + + bool positive = entry->type == CONFIG_INT + ? *(int *)result >= 0 + : *(double *)result >= 0.0; + + if (!positive) { + log_error("Value 'block.%s.%s' violates constraint '%s'", block->label, entry->key, "positive"); + errors++; + } + break; + } + + case CHECK_IN_RANGE: { + assert(entry->type == CONFIG_INT || entry->type == CONFIG_UINT || entry->type == CONFIG_DOUBLE); + + double min = entry->checks[i].range.min, + max = entry->checks[i].range.max, + value = entry->type == CONFIG_INT + ? *(int *)result + : entry->type == CONFIG_UINT + ? *(unsigned int *)result + : *(double *)result; + + if (value <= min || value >= max) { + log_error("Value 'block.%s.%s' violates constraint '%s(%g, %g)'", + block->label, entry->key, "in_range", min, max); + errors++; + } + break; + } + + case CHECK_GT_OTHER: { + void *other = (void *)block + entry->checks[i].compare.offset; + assert(entry->type == CONFIG_INT || entry->type == CONFIG_UINT || entry->type == CONFIG_DOUBLE); + assert(entry->type == entry->checks[i].compare.type); + + double value1 = entry->type == CONFIG_INT + ? *(int *)result + : entry->type == CONFIG_UINT + ? *(unsigned int *)result + : *(double *)result; + + double value2 = entry->type == CONFIG_INT + ? *(int *)other + : entry->type == CONFIG_UINT + ? *(unsigned int *)other + : *(double *)other; + + if (value1 <= value2) { + log_error("Value 'block.%s.%s' violates constraint '%s(%p)'", + block->label, entry->key, "gt_memebr", other); + errors++; + } + break; + } + + default: + unreachable(); + } + } + + return errors; +} + +int block_validate(block_t *block, config_t *config) +{ + if (block->scheme->validate_fn != NULL) + return block->scheme->validate_fn(block, config); + + if (block->scheme->entries == NULL) + return 0; + + int errors = 0; + for (size_t i = 0; block->scheme->entries[i].key != NULL; i++) { + errors += block_validate_entry(block, &block->scheme->entries[i]); + } + + return errors; +} + bool block_resolve_action(block_t *block, config_t *config, action_t **action) { if (action == NULL || *action == NULL) |
