diff options
author | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2021-11-07 02:02:45 +0300 |
---|---|---|
committer | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2021-11-07 02:02:45 +0300 |
commit | e3a41da5a0a3d70ac53591f2b66144f2be2b3871 (patch) | |
tree | 789cc69b05f2447c11f04dbb6ae972ffa0acd1c9 /src/config.c | |
download | revela-e3a41da5a0a3d70ac53591f2b66144f2be2b3871.tar.gz revela-e3a41da5a0a3d70ac53591f2b66144f2be2b3871.zip |
Initial commit.
Almost functional but still missing features and lacking testing.
Diffstat (limited to 'src/config.c')
-rw-r--r-- | src/config.c | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..e9dd609 --- /dev/null +++ b/src/config.c @@ -0,0 +1,264 @@ +#include "config.h" + +#include <errno.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#include "fs.h" +#include "log.h" +#include "parcini.h" + +typedef enum kv_handler_result (*ini_keyvalue_handler_fn)(struct parcini_line *, void *dst); + +enum config_key_result { + CONFIG_KEY_NONE, + CONFIG_KEY_OK, + CONFIG_KEY_BADKEY, + CONFIG_KEY_BADVALUE, +}; + +enum kv_handler_result { + KV_HANDLER_OK, + KV_HANDLER_NOMATCH, + KV_HANDLER_BADVALUE, +}; + +static int +site_config_images_keyvalue_handler(struct parcini_line *parsed, + struct image_config *iconfig) +{ + int res = CONFIG_KEY_BADKEY; + if (!strcmp(parsed->key, "strip")) { + res = parcini_value_handle(&parsed->value, PARCINI_VALUE_BOOLEAN, + &iconfig->strip) ? CONFIG_KEY_OK : CONFIG_KEY_BADVALUE; + } + if (!strcmp(parsed->key, "quality")) { + long int temp; + res = parcini_value_handle(&parsed->value, PARCINI_VALUE_INTEGER, + &temp) ? CONFIG_KEY_OK : CONFIG_KEY_BADVALUE; + if (res == CONFIG_KEY_OK) { + if (temp > 100 || temp < 0) { + res = CONFIG_KEY_BADVALUE; + } else { + iconfig->quality = (uint8_t)temp; + } + } + } + if (!strcmp(parsed->key, "max_width")) { + long int temp; + res = parcini_value_handle(&parsed->value, PARCINI_VALUE_INTEGER, + &temp) ? CONFIG_KEY_OK : CONFIG_KEY_BADVALUE; + if (res == CONFIG_KEY_OK) { + if (temp < 1) { + res = CONFIG_KEY_BADVALUE; + } else { + iconfig->max_width = (size_t)temp; + } + } + } + if (!strcmp(parsed->key, "max_height")) { + long int temp; + res = parcini_value_handle(&parsed->value, PARCINI_VALUE_INTEGER, + &temp) ? CONFIG_KEY_OK : CONFIG_KEY_BADVALUE; + if (res == CONFIG_KEY_OK) { + if (temp < 1) { + res = CONFIG_KEY_BADVALUE; + } else { + iconfig->max_height = (size_t)temp; + } + } + } + if (!strcmp(parsed->key, "smart_resize")) { + res = parcini_value_handle(&parsed->value, PARCINI_VALUE_BOOLEAN, + &iconfig->smart_resize) ? CONFIG_KEY_OK : CONFIG_KEY_BADVALUE; + } + + return res; +} + +#define MATCHSK(s, k, p) !strcmp(s, p->section) && !strcmp(k, p->key) + +static enum kv_handler_result +site_config_keyvalue_handler(struct parcini_line *parsed, void *dst) +{ + struct site_config *config = dst; + enum config_key_result subconf = CONFIG_KEY_NONE; + if (!strcmp(parsed->section, "images")) { + subconf = site_config_images_keyvalue_handler(parsed, &config->images); + } else if (!strcmp(parsed->section, "thumbnails")) { + subconf = site_config_images_keyvalue_handler(parsed, + &config->thumbnails); + } + switch (subconf) { + case CONFIG_KEY_OK: + return KV_HANDLER_OK; + case CONFIG_KEY_BADKEY: + goto out; + case CONFIG_KEY_BADVALUE: + return KV_HANDLER_BADVALUE; + default: + break; + } + if (MATCHSK("", "title", parsed)) { + free(config->title); + return parcini_value_handle(&parsed->value, PARCINI_VALUE_STRING, + &config->title)? + KV_HANDLER_OK : KV_HANDLER_BADVALUE; + } + if (MATCHSK("", "base_url", parsed)) { + free(config->base_url); + return parcini_value_handle(&parsed->value, PARCINI_VALUE_STRING, + &config->base_url)? + KV_HANDLER_OK : KV_HANDLER_BADVALUE; + } + if (MATCHSK("", "max_previews", parsed)) { + return parcini_value_handle(&parsed->value, PARCINI_VALUE_INTEGER, + &config->max_previews)? + KV_HANDLER_OK : KV_HANDLER_BADVALUE; + } + + +out: + return KV_HANDLER_NOMATCH; +} + +static enum kv_handler_result +album_config_keyvalue_handler(struct parcini_line *parsed, void *dst) +{ + struct album_config *config = dst; + if (MATCHSK("", "title", parsed)) { + free(config->title); + return parcini_value_handle(&parsed->value, PARCINI_VALUE_STRING, + &config->title) ? + KV_HANDLER_OK : KV_HANDLER_BADVALUE; + } + if (MATCHSK("", "desc", parsed)) { + free(config->desc); + return parcini_value_handle(&parsed->value, PARCINI_VALUE_STRING, + &config->desc) ? + KV_HANDLER_OK : KV_HANDLER_BADVALUE; + } + + return KV_HANDLER_NOMATCH; +} + +static bool ini_handler(const char *fpath, ini_keyvalue_handler_fn kvhandler, + void *dst) +{ + struct parcini_line parsed; + enum parcini_result res; + parcini_t *parser = parcini_from_file(fpath); + if (parser == NULL){ + log_printl_errno(LOG_FATAL, "Couldn't open %s", fpath); + return false; + } + + bool ok = true; + enum kv_handler_result hres; + while ((res = parcini_parse_next_line(parser, &parsed)) != PARCINI_EOF + && ok) { + switch (res) { + case PARCINI_KEYVALUE: + if ((hres = kvhandler(&parsed, dst)) == KV_HANDLER_BADVALUE) { + log_printl(LOG_ERROR, "Error parsing %s:%ld, bad value for key" + "%s", fpath, parsed.lineno, parsed.key); + ok = false; + } else if(hres == KV_HANDLER_NOMATCH) { + log_printl(LOG_ERROR, + "Warning: key '%s' in section '%s' is not a valid " + "section-key combination for %s, ignoring.", + parsed.key, parsed.section, fpath); + } + continue; + + case PARCINI_EMPTY_LINE: + case PARCINI_SECTION: + continue; + + case PARCINI_STREAM_ERROR: + case PARCINI_MEMORY_ERROR: + log_printl_errno(LOG_FATAL, "Error reading %s", fpath); + ok = false; + break; + + default: + log_printl(LOG_FATAL, "Error parsing %s:%ld", fpath, parsed.lineno); + ok = false; + break; + } + } + + parcini_destroy(parser); + return ok; +} + +bool +site_config_read_ini(const char *wdir, struct site_config *config) +{ + if (wdir == NULL) { + return ini_handler(SITE_CONF, site_config_keyvalue_handler, + config); + } + char *fpath = joinpath(wdir, SITE_CONF); + bool ok = ini_handler(fpath, site_config_keyvalue_handler, config); + free(fpath); + return ok; +} + +bool +album_config_read_ini(const char *fpath, struct album_config *config) +{ + bool ok = ini_handler(fpath, album_config_keyvalue_handler, config); + return ok; +} + +struct site_config * +site_config_init(void) +{ + struct site_config *config = calloc(1, sizeof *config); + if (config != NULL) { + config->max_previews = 10; + config->images = (struct image_config) { + .strip = true, + .quality = 80, + .max_width = 3000, + .max_height = 2000, + .smart_resize = true, + }; + config->thumbnails = (struct image_config) { + .strip = true, + .quality = 60, + .max_width = 400, + .max_height = 270, + .smart_resize = true, + }; + } + + return config; +} + +struct album_config * +album_config_init(void) +{ + struct album_config *config = calloc(1, sizeof *config); + return config; +} + +void +site_config_destroy(struct site_config *config) +{ + free(config->title); + free(config->base_url); + free(config); +} + +void +album_config_destroy(struct album_config *config) +{ + free(config->title); + free(config->desc); + free(config); +} |