From cbfe780b20ced576c2e3d41361a9036210ab5c9b Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Wed, 20 Jul 2022 23:33:55 -0700 Subject: 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. --- src/til_settings.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'src/til_settings.c') 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 #include #include +#include #include #include @@ -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); } -- cgit v1.2.1