aboutsummaryrefslogtreecommitdiff
path: root/src/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/block.c')
-rw-r--r--src/block.c93
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)