From 5e7f66b34826697537bcdcb60c81f56da956a32b Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Sun, 8 Sep 2024 15:45:57 +0200 Subject: Add ram formatting --- src/block.c | 2 - src/block.h | 1 + src/blocks/group.c | 2 +- src/blocks/ram.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/blocks/scheme.h | 5 ++- src/blocks/text.c | 14 ++++++- src/config.c | 11 ++++++ 7 files changed, 137 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/block.c b/src/block.c index a3e7acb..fb35605 100644 --- a/src/block.c +++ b/src/block.c @@ -60,6 +60,4 @@ void block_free(block_t *block) if (block->finalize_cb != NULL) block->finalize_cb(block); - - free(block->state); } diff --git a/src/block.h b/src/block.h index 1ceedf1..715e6c4 100644 --- a/src/block.h +++ b/src/block.h @@ -35,6 +35,7 @@ typedef void (*block_event_t)(block_t *block, event_t event); typedef void (*block_update_t)(block_t *block); // Block finalization routine +// NOTE: The block state must be freed by this function // typedef void (*block_finalize_t)(block_t *block); diff --git a/src/blocks/group.c b/src/blocks/group.c index fb4457e..4fcb420 100644 --- a/src/blocks/group.c +++ b/src/blocks/group.c @@ -7,6 +7,6 @@ const block_scheme_t block_group_scheme = { }, .size = 0, .entries = NULL, - .verify = NULL, + .validate = NULL, }; diff --git a/src/blocks/ram.c b/src/blocks/ram.c index a626413..44dd1a3 100644 --- a/src/blocks/ram.c +++ b/src/blocks/ram.c @@ -1,12 +1,118 @@ +#include +#include +#include +#include + #include "scheme.h" +#include "../any_log.h" + +char *str_replace(char *orig, char *rep, char *with) { + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; (tmp = strstr(ins, rep)); ++count) { + ins = tmp + len_rep; + } + + tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if (!result) + return NULL; + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} + +static void block_ram_update(block_t *block) +{ + FILE *meminfo = fopen("/proc/meminfo", "rb"); + assert(meminfo != NULL); + + uintmax_t total, unused, buffers, cached; + assert(5 == fscanf(meminfo, + "MemTotal: %ju kB\n" + "MemFree: %ju kB\n" + "MemAvailable: %ju kB\n" + "Buffers: %ju kB\n" + "Cached: %ju kB\n", + &total, &unused, &buffers, &buffers, &cached)); + + int usage = 100 * (total - unused - buffers - cached) / total; + fclose(meminfo); + + free(block->text.text); + + char str[100]; + sprintf(str, "%d", usage); + + block->text.text = str_replace(block->state, "%{ram}", str); + assert(block->text.text != NULL); +} + +static void block_ram_finalize(block_t *block) +{ + free(block->state); +} + +static bool block_ram_validate(block_t *block, const block_scheme_t *scheme) +{ + block->state = block->text.text; + block->text.text = NULL; + + if (block->state == NULL) { + log_error("Block '%s' requires key '%s'", block->label, "text"); + return false; + } + + if (strstr(block->state, "%{ram}") != NULL) + log_warn("Block '%s' does not have a ram format", block->label); + + return true; +} + const block_scheme_t block_ram_scheme = { .name = "ram", .block = { .type = BLOCK_TEXT, + .update_interval = { + .tv_sec = 1, + .tv_nsec = 0, + }, + .update_cb = block_ram_update, + .finalize_cb = block_ram_finalize, }, - .size = 0, + .size = sizeof(char *), .entries = NULL, - .verify = NULL, + .validate = block_ram_validate, }; diff --git a/src/blocks/scheme.h b/src/blocks/scheme.h index 2bcca97..1795013 100644 --- a/src/blocks/scheme.h +++ b/src/blocks/scheme.h @@ -5,14 +5,15 @@ typedef struct block_scheme block_scheme_t; -typedef bool (*block_scheme_verify_t)(block_t *block, block_scheme_t *scheme); +typedef bool (*block_validate_t)(block_t *block, const block_scheme_t *scheme); struct block_scheme { const char *name; block_t block; size_t size; const config_entry_t *entries; - block_scheme_verify_t verify; + block_validate_t validate; + //block_resolve_t resolve; }; extern const block_scheme_t *block_schemes[]; diff --git a/src/blocks/text.c b/src/blocks/text.c index 0e5fc31..f2c1651 100644 --- a/src/blocks/text.c +++ b/src/blocks/text.c @@ -1,5 +1,17 @@ #include "scheme.h" +#include "../any_log.h" + +static bool block_text_validate(block_t *block, const block_scheme_t *scheme) +{ + if (block->text.text == NULL) { + log_error("Block '%s' requires key '%s'", block->label, "text"); + return false; + } + + return true; +} + const block_scheme_t block_text_scheme = { .name = "text", .block = { @@ -7,5 +19,5 @@ const block_scheme_t block_text_scheme = { }, .size = 0, .entries = NULL, - .verify = NULL, + .validate = block_text_validate, }; diff --git a/src/config.c b/src/config.c index 38413f4..cde4af1 100644 --- a/src/config.c +++ b/src/config.c @@ -205,6 +205,10 @@ static config_status_t config_read_entry(const config_entry_t *entries, void *re "integer", "unsigned integer", "double float", + "boolean", + "color", + "enum", + "time", }; for (int i = 0; entries[i].key != NULL; i++) { @@ -447,6 +451,13 @@ skip_pair: free(value); } + if (block != NULL && scheme->validate != NULL) { + if (errors != 0) + log_trace("Skipped validation for block '%s'", section); + else + errors += !scheme->validate(block, scheme); + } + free(section); n_errors += errors; } while ((section = any_ini_stream_next_section(&ini)) != NULL); -- cgit v1.2.3