summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--options/m_option.c64
-rw-r--r--options/m_option.h5
2 files changed, 69 insertions, 0 deletions
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, &param, &key);
+ if (r < 0)
+ break;
+ if (!bstr_eatstart0(&param, "=")) {
+ mp_err(log, "Expected '=' and a value.\n");
+ r = M_OPT_INVALID;
+ break;
+ }
+ r = read_subparam(log, name, &param, &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(&param, ","))
+ 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)