diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2022-07-20 23:33:55 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2022-07-20 23:33:55 -0700 |
commit | cbfe780b20ced576c2e3d41361a9036210ab5c9b (patch) | |
tree | 1f742aad1d71b39de9d1c87b500953fc6f28c3a1 | |
parent | c69917862a58cac01d9deca2b91255f0510b243c (diff) |
til_settings: support rudimentary =value escaping
This is a step towards properly handling nested settings, so we
can do stuff like:
--module=rtv,channels=compose\,layers=checkers\\\,fill_module=shapes\\\,size=64\,texture=plasma
and have rtv actually cycle through just compose with
checkers+plasma layers but holding the specified checkers
settings to shapes filler with a size of 64, randomizing the
rest.
There's more work to do before that can actually happen, but
first thing is to just support escaping the settings values.
-rw-r--r-- | src/til_settings.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/til_settings.c b/src/til_settings.c index 01b27b7..3e26686 100644 --- a/src/til_settings.c +++ b/src/til_settings.c @@ -1,6 +1,7 @@ #include <assert.h> #include <errno.h> #include <stdarg.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -38,6 +39,7 @@ typedef enum til_settings_fsm_state_t { TIL_SETTINGS_FSM_STATE_KEY, TIL_SETTINGS_FSM_STATE_EQUAL, TIL_SETTINGS_FSM_STATE_VALUE, + TIL_SETTINGS_FSM_STATE_VALUE_ESCAPED, TIL_SETTINGS_FSM_STATE_COMMA, } til_settings_fsm_state_t; @@ -65,6 +67,9 @@ til_settings_t * til_settings_new(const char *settings_string) til_settings_fsm_state_t state = TIL_SETTINGS_FSM_STATE_KEY; const char *p, *token; til_settings_t *settings; + FILE *value_fp; + char *value_buf; + size_t value_sz; settings = calloc(1, sizeof(til_settings_t)); if (!settings) @@ -73,7 +78,6 @@ til_settings_t * til_settings_new(const char *settings_string) if (!settings_string) return settings; - /* TODO: unescaping? */ for (token = p = settings_string; ;p++) { switch (state) { @@ -94,15 +98,29 @@ til_settings_t * til_settings_new(const char *settings_string) break; case TIL_SETTINGS_FSM_STATE_EQUAL: + value_fp = open_memstream(&value_buf, &value_sz); + if (!value_fp) + goto _err; + token = p; state = TIL_SETTINGS_FSM_STATE_VALUE; /* fallthrough, necessary to not leave NULL values for empty "key=\0" settings */ case TIL_SETTINGS_FSM_STATE_VALUE: - if (*p == ',' || *p == '\0') { - settings->settings[settings->num - 1]->value = strndup(token, p - token); + if (*p == '\\') + state = TIL_SETTINGS_FSM_STATE_VALUE_ESCAPED; + else if (*p == ',' || *p == '\0') { + fclose(value_fp); + settings->settings[settings->num - 1]->value = value_buf; state = TIL_SETTINGS_FSM_STATE_COMMA; - } + } else + fputc(*p, value_fp); + + break; + + case TIL_SETTINGS_FSM_STATE_VALUE_ESCAPED: + fputc(*p, value_fp); + state = TIL_SETTINGS_FSM_STATE_VALUE; break; default: @@ -116,6 +134,9 @@ til_settings_t * til_settings_new(const char *settings_string) /* FIXME: this should probably never leave a value or key entry NULL */ return settings; + +_err: + return til_settings_free(settings); } |