mirror of
https://github.com/mpv-player/mpv
synced 2025-03-11 08:37:59 +00:00
m_option: reintroduce -del to string list and keyvalue list
b56e63e2a9
removed this because it was
deprecated and not clearly useful. This commit adds this operation back
to string lists and keyvalue lists, but with one important change. It
operates via the actual values and not indexes. So you can use
--foo-del=bar,bar2 to remove bar and bar2 from foo. The difference from
using -remove is that this is subject to escaping rules and has the same
caveats as -add. Note that -del wasn't added back to the object settings
list because you can already remove multiple items with -remove from it.
This commit is contained in:
parent
7456816217
commit
d2c409c56b
@ -1 +1,2 @@
|
||||
undeprecate list option suffixes that work with multiple items
|
||||
add `-del` to string list and keyvalue list options
|
||||
|
@ -653,6 +653,7 @@ Suffix Meaning
|
||||
-add Append 1 or more items (same syntax as -set)
|
||||
-pre Prepend 1 or more items (same syntax as -set)
|
||||
-clr Clear the option (remove all items)
|
||||
-del Delete 1 or more items if present (same syntax as -set)
|
||||
-remove Delete item if present (does not interpret escapes)
|
||||
-toggle Append an item, or remove it if it already exists (no escapes)
|
||||
============= ===============================================
|
||||
@ -675,6 +676,7 @@ Suffix Meaning
|
||||
-set Set a list of items (using ``,`` as separator)
|
||||
-append Append a single item (escapes for the key, no escapes for the value)
|
||||
-add Append 1 or more items (same syntax as -set)
|
||||
-del Delete 1 or more keys if present (same syntax as -set)
|
||||
-remove Delete item by key if present (does not interpret escapes)
|
||||
============= ===============================================
|
||||
|
||||
|
@ -1319,9 +1319,10 @@ const m_option_type_t m_option_type_string = {
|
||||
#define OP_ADD 1
|
||||
#define OP_PRE 2
|
||||
#define OP_CLR 3
|
||||
#define OP_TOGGLE 4
|
||||
#define OP_APPEND 5
|
||||
#define OP_REMOVE 6
|
||||
#define OP_DEL 4
|
||||
#define OP_TOGGLE 5
|
||||
#define OP_APPEND 6
|
||||
#define OP_REMOVE 7
|
||||
|
||||
static void free_str_list(void *dst)
|
||||
{
|
||||
@ -1403,23 +1404,84 @@ static int find_list_bstr(char **list, bstr item)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char **separate_input_param(const m_option_t *opt, bstr param,
|
||||
int *len, int op)
|
||||
{
|
||||
char separator = opt->priv ? *(char *)opt->priv : OPTION_LIST_SEPARATOR;
|
||||
if (op == OP_REMOVE)
|
||||
separator = 0; // specially handled
|
||||
struct bstr str = param;
|
||||
int n = *len;
|
||||
while (str.len) {
|
||||
get_nextsep(&str, separator, 0);
|
||||
str = bstr_cut(str, 1);
|
||||
n++;
|
||||
}
|
||||
if (n == 0)
|
||||
return NULL;
|
||||
|
||||
char **list = talloc_array(NULL, char *, n + 2);
|
||||
str = bstrdup(NULL, param);
|
||||
char *ptr = str.start;
|
||||
n = 0;
|
||||
|
||||
while (1) {
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
if (n >= 100)
|
||||
break;
|
||||
#endif
|
||||
struct bstr el = get_nextsep(&str, separator, 1);
|
||||
list[n] = bstrdup0(NULL, el);
|
||||
n++;
|
||||
if (!str.len)
|
||||
break;
|
||||
str = bstr_cut(str, 1);
|
||||
}
|
||||
list[n] = NULL;
|
||||
*len = n;
|
||||
talloc_free(ptr);
|
||||
return list;
|
||||
}
|
||||
|
||||
static int str_list_remove(char **remove, int n, void *dst)
|
||||
{
|
||||
bool found = false;
|
||||
char **list = VAL(dst);
|
||||
for (int i = 0; i < n; i++) {
|
||||
int index = 0;
|
||||
do {
|
||||
index = find_list_bstr(list, bstr0(remove[i]));
|
||||
if (index >= 0) {
|
||||
found = true;
|
||||
char *old = list[index];
|
||||
for (int j = index; list[j]; j++)
|
||||
list[j] = list[j + 1];
|
||||
talloc_free(old);
|
||||
}
|
||||
} while (index >= 0);
|
||||
talloc_free(remove[i]);
|
||||
}
|
||||
talloc_free(remove);
|
||||
return found;
|
||||
}
|
||||
|
||||
static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt,
|
||||
struct bstr name, struct bstr param, void *dst,
|
||||
int default_op)
|
||||
{
|
||||
char **res;
|
||||
int op = default_op;
|
||||
bool multi = true;
|
||||
|
||||
if (bstr_endswith0(name, "-add")) {
|
||||
op = OP_ADD;
|
||||
} else if (bstr_endswith0(name, "-append")) {
|
||||
op = OP_ADD;
|
||||
multi = false;
|
||||
op = OP_APPEND;
|
||||
} else if (bstr_endswith0(name, "-pre")) {
|
||||
op = OP_PRE;
|
||||
} else if (bstr_endswith0(name, "-clr")) {
|
||||
op = OP_CLR;
|
||||
} else if (bstr_endswith0(name, "-del")) {
|
||||
op = OP_DEL;
|
||||
} else if (bstr_endswith0(name, "-set")) {
|
||||
op = OP_NONE;
|
||||
} else if (bstr_endswith0(name, "-toggle")) {
|
||||
@ -1430,26 +1492,16 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt,
|
||||
|
||||
if (op == OP_TOGGLE || op == OP_REMOVE) {
|
||||
if (dst) {
|
||||
char **list = VAL(dst);
|
||||
bool found = false;
|
||||
int index = 0;
|
||||
do {
|
||||
index = find_list_bstr(list, param);
|
||||
if (index >= 0) {
|
||||
found = true;
|
||||
char *old = list[index];
|
||||
for (int n = index; list[n]; n++)
|
||||
list[n] = list[n + 1];
|
||||
talloc_free(old);
|
||||
}
|
||||
} while (index >= 0);
|
||||
res = talloc_array(NULL, char *, 2);
|
||||
res[0] = bstrdup0(res, param);
|
||||
res[1] = NULL;
|
||||
bool found = str_list_remove(res, 2, dst);
|
||||
if (found)
|
||||
return 1;
|
||||
}
|
||||
if (op == OP_REMOVE)
|
||||
return 1; // ignore if not found
|
||||
op = OP_ADD;
|
||||
multi = false;
|
||||
op = OP_APPEND;
|
||||
}
|
||||
|
||||
// Clear the list ??
|
||||
@ -1463,47 +1515,22 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt,
|
||||
if (param.len == 0 && op != OP_NONE)
|
||||
return M_OPT_MISSING_PARAM;
|
||||
|
||||
char separator = opt->priv ? *(char *)opt->priv : OPTION_LIST_SEPARATOR;
|
||||
if (!multi)
|
||||
separator = 0; // specially handled
|
||||
int n = 0;
|
||||
struct bstr str = param;
|
||||
while (str.len) {
|
||||
get_nextsep(&str, separator, 0);
|
||||
str = bstr_cut(str, 1);
|
||||
n++;
|
||||
}
|
||||
if (n == 0 && op != OP_NONE)
|
||||
return M_OPT_INVALID;
|
||||
|
||||
if (!dst)
|
||||
return 1;
|
||||
|
||||
res = talloc_array(NULL, char *, n + 2);
|
||||
str = bstrdup(NULL, param);
|
||||
char *ptr = str.start;
|
||||
n = 0;
|
||||
|
||||
while (1) {
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
if (n >= 100)
|
||||
break;
|
||||
#endif
|
||||
struct bstr el = get_nextsep(&str, separator, 1);
|
||||
res[n] = bstrdup0(NULL, el);
|
||||
n++;
|
||||
if (!str.len)
|
||||
break;
|
||||
str = bstr_cut(str, 1);
|
||||
}
|
||||
res[n] = NULL;
|
||||
talloc_free(ptr);
|
||||
int n = 0;
|
||||
res = separate_input_param(opt, param, &n, op);
|
||||
if (!res)
|
||||
return M_OPT_INVALID;
|
||||
|
||||
switch (op) {
|
||||
case OP_ADD:
|
||||
case OP_APPEND:
|
||||
return str_list_add(res, n, dst, 0);
|
||||
case OP_PRE:
|
||||
return str_list_add(res, n, dst, 1);
|
||||
case OP_DEL:
|
||||
return str_list_remove(res, n, dst);
|
||||
}
|
||||
|
||||
if (VAL(dst))
|
||||
@ -1634,6 +1661,7 @@ const m_option_type_t m_option_type_string_list = {
|
||||
{"add"},
|
||||
{"append"},
|
||||
{"clr", M_OPT_TYPE_OPTIONAL_PARAM},
|
||||
{"del"},
|
||||
{"pre"},
|
||||
{"set"},
|
||||
{"toggle"},
|
||||
@ -1679,17 +1707,32 @@ static int parse_keyvalue_list(struct mp_log *log, const m_option_t *opt,
|
||||
if ((opt->flags & M_OPT_HAVE_HELP) && bstr_equals0(param, "help"))
|
||||
param = bstr0("help=");
|
||||
|
||||
int op = 0;
|
||||
if (bstr_endswith0(name, "-del")) {
|
||||
op = OP_DEL;
|
||||
} else if (bstr_endswith0(name, "-remove")) {
|
||||
op = OP_REMOVE;
|
||||
}
|
||||
|
||||
if (bstr_endswith0(name, "-add")) {
|
||||
append = true;
|
||||
} else if (bstr_endswith0(name, "-append")) {
|
||||
append = full_value = true;
|
||||
} else if (bstr_endswith0(name, "-remove")) {
|
||||
} else if (op == OP_DEL || op == OP_REMOVE) {
|
||||
int n = 0;
|
||||
char **res = separate_input_param(opt, param, &n, op);
|
||||
if (!res)
|
||||
return M_OPT_INVALID;
|
||||
lst = dst ? VAL(dst) : NULL;
|
||||
int index = dst ? keyvalue_list_find_key(lst, param) : -1;
|
||||
if (index >= 0) {
|
||||
keyvalue_list_del_key(lst, index);
|
||||
VAL(dst) = lst;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int index = dst ? keyvalue_list_find_key(lst, bstr0(res[i])) : -1;
|
||||
if (index >= 0) {
|
||||
keyvalue_list_del_key(lst, index);
|
||||
VAL(dst) = lst;
|
||||
}
|
||||
talloc_free(res[i]);
|
||||
}
|
||||
talloc_free(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1818,6 +1861,7 @@ const m_option_type_t m_option_type_keyvalue_list = {
|
||||
.actions = (const struct m_option_action[]){
|
||||
{"add"},
|
||||
{"append"},
|
||||
{"del"},
|
||||
{"set"},
|
||||
{"remove"},
|
||||
{0}
|
||||
|
Loading…
Reference in New Issue
Block a user