diff options
author | wm4 <wm4@nowhere> | 2019-12-18 06:00:37 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2019-12-18 06:03:39 +0100 |
commit | 8bdedf9062074f03b13820487fccc892105eb472 (patch) | |
tree | 8a5efd7ebd78994d4085865fe2663949988eadcb | |
parent | d3e3bd43074ddd8f4c8829a7454b9f855454f462 (diff) | |
download | mpv-8bdedf9062074f03b13820487fccc892105eb472.tar.bz2 mpv-8bdedf9062074f03b13820487fccc892105eb472.tar.xz |
options: make keys in key/value lists unique
I don't even know anymore whether this was intended or not. Certain use
cases for the "-o" options might require this. These options are for
passing general FFmpeg options. These are translated to av_opt_set()
calls, which may or may not accumulate the option values on multiple
calls with the same option name (how should I know?).
Anyway, it seems crazy to allow non-unique keys, so make them unique.
The ad-hoc nature of the option code makes this wonderfully complicated
(when I wrote that this code is cursed, I meant it). In combination with
lazy testing, it probably means there are lots of bugs here.
-rw-r--r-- | DOCS/man/mpv.rst | 3 | ||||
-rw-r--r-- | options/m_option.c | 27 |
2 files changed, 30 insertions, 0 deletions
diff --git a/DOCS/man/mpv.rst b/DOCS/man/mpv.rst index eaced80082..9ff62ae4f0 100644 --- a/DOCS/man/mpv.rst +++ b/DOCS/man/mpv.rst @@ -520,6 +520,9 @@ Suffix Meaning -add Append 1 or more items (same syntax as -set) ============= =============================================== +Keys are unique within the list. If an already present key is set, the existing +key is removed before the new value is appended. + Filter options ~~~~~~~~~~~~~~ diff --git a/options/m_option.c b/options/m_option.c index 1ff3d26d22..2ebe79cff3 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -1621,6 +1621,28 @@ const m_option_type_t m_option_type_string_list = { static int read_subparam(struct mp_log *log, bstr optname, char *termset, bstr *str, bstr *out_subparam); +static int keyvalue_list_find_key(char **lst, bstr str) +{ + for (int n = 0; lst && lst[n] && lst[n + 1]; n += 2) { + if (bstr_equals0(str, lst[n])) + return n / 2; + } + return -1; +} + +static void keyvalue_list_del_key(char **lst, int index) +{ + int count = 0; + for (int n = 0; lst && lst[n]; n++) + count++; + assert(index * 2 + 1 < count); + count += 1; // terminating item + talloc_free(lst[index * 2 + 0]); + talloc_free(lst[index * 2 + 1]); + MP_TARRAY_REMOVE_AT(lst, count, index * 2 + 1); + MP_TARRAY_REMOVE_AT(lst, count, index * 2 + 0); +} + static int parse_keyvalue_list(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param, void *dst) { @@ -1664,6 +1686,11 @@ static int parse_keyvalue_list(struct mp_log *log, const m_option_t *opt, break; } if (dst) { + int index = keyvalue_list_find_key(lst, key); + if (index >= 0) { + keyvalue_list_del_key(lst, index); + num -= 2; + } MP_TARRAY_APPEND(NULL, lst, num, bstrto0(NULL, key)); MP_TARRAY_APPEND(NULL, lst, num, bstrto0(NULL, val)); } |