From 82067e6ac37f73099923c86cf38fc44100a8d3c2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 16 Jan 2014 23:03:40 +0100 Subject: options: add key/value pair list option type --- options/m_option.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ options/m_option.h | 5 +++++ 2 files changed, 69 insertions(+) diff --git a/options/m_option.c b/options/m_option.c index 36e0678593..339449b9b6 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -1145,6 +1145,70 @@ const m_option_type_t m_option_type_string_list = { .free = free_str_list, }; +static int read_subparam(struct mp_log *log, bstr optname, + bstr *str, bstr *out_subparam); + +static int parse_keyvalue_list(struct mp_log *log, const m_option_t *opt, + struct bstr name, struct bstr param, void *dst) +{ + char **lst = NULL; + int num = 0; + int r = 0; + + while (param.len) { + bstr key, val; + r = read_subparam(log, name, ¶m, &key); + if (r < 0) + break; + if (!bstr_eatstart0(¶m, "=")) { + mp_err(log, "Expected '=' and a value.\n"); + r = M_OPT_INVALID; + break; + } + r = read_subparam(log, name, ¶m, &val); + if (r < 0) + break; + MP_TARRAY_APPEND(NULL, lst, num, bstrto0(NULL, key)); + MP_TARRAY_APPEND(NULL, lst, num, bstrto0(NULL, val)); + + if (!bstr_eatstart0(¶m, ",")) + break; + } + MP_TARRAY_APPEND(NULL, lst, num, NULL); + + if (param.len) { + mp_err(log, "Unparseable garbage at end of option value: '%.*s'\n", + BSTR_P(param)); + r = M_OPT_INVALID; + } + + VAL(dst) = lst; + if (r < 0) + free_str_list(dst); + return r; +} + +static char *print_keyvalue_list(const m_option_t *opt, const void *src) +{ + char **lst = VAL(src); + char *ret = talloc_strdup(NULL, ""); + for (int n = 0; lst && lst[n] && lst[n + 1]; n += 2) { + if (ret[0]) + ret = talloc_strdup_append(ret, ","); + ret = talloc_asprintf_append("%s%s=%s", ret, lst[n], lst[n + 1]); + } + return ret; +} + +const m_option_type_t m_option_type_keyvalue_list = { + .name = "Key/value list", + .size = sizeof(char **), + .flags = M_OPT_TYPE_DYNAMIC, + .parse = parse_keyvalue_list, + .print = print_keyvalue_list, + .copy = copy_str_list, + .free = free_str_list, +}; /////////////////// Print diff --git a/options/m_option.h b/options/m_option.h index 7f9b89bea1..9178231b2b 100644 --- a/options/m_option.h +++ b/options/m_option.h @@ -46,6 +46,7 @@ extern const m_option_type_t m_option_type_float; extern const m_option_type_t m_option_type_double; extern const m_option_type_t m_option_type_string; extern const m_option_type_t m_option_type_string_list; +extern const m_option_type_t m_option_type_keyvalue_list; extern const m_option_type_t m_option_type_time; extern const m_option_type_t m_option_type_rel_time; extern const m_option_type_t m_option_type_choice; @@ -199,6 +200,7 @@ union m_option_value { double double_; char *string; char **string_list; + char **keyvalue_list; int imgfmt; unsigned int fourcc; int afmt; @@ -534,6 +536,9 @@ extern const char m_option_path_separator; #define OPT_STRINGLIST(...) \ OPT_GENERAL(char**, __VA_ARGS__, .type = &m_option_type_string_list) +#define OPT_KEYVALUELIST(...) \ + OPT_GENERAL(char**, __VA_ARGS__, .type = &m_option_type_keyvalue_list) + #define OPT_PATHLIST(...) \ OPT_GENERAL(char**, __VA_ARGS__, .type = &m_option_type_string_list, \ .priv = (void *)&m_option_path_separator) -- cgit v1.2.3