Merge branch 'master' into 'master'

conf: add @ modifier for JSON array element matching

See merge request pipewire/pipewire!2840
This commit is contained in:
Torkel Niklasson 2026-05-26 13:23:46 +00:00
commit d95613322c

View file

@ -625,6 +625,7 @@ static int load_module(struct pw_context *context, const char *key, const char *
* {
* # all keys must match the value. ~ in value starts regex.
* # ! as the first char of the value negates the match
* # @ checks if the value is an element in a JSON array property
* <key> = <value>
* ...
* }
@ -636,6 +637,8 @@ static int load_module(struct pw_context *context, const char *key, const char *
* !null -> matches when the property is found (any value)
* "!null" -> same as !null
* !"null" and "!\"null\"" matches anything that is not the string "null"
* @138 -> matches when the property is a JSON array containing "138"
* !@138 -> matches when the property is a JSON array not containing "138"
*/
SPA_EXPORT
bool pw_conf_find_match(struct spa_json *arr, const struct spa_dict *props, bool condition)
@ -651,7 +654,7 @@ bool pw_conf_find_match(struct spa_json *arr, const struct spa_dict *props, bool
int len;
while ((len = spa_json_object_next(&it[0], key, sizeof(key), &value)) > 0) {
bool success = false, is_null, reg = false, parse_string = true;
bool success = false, is_null, reg = false, in_array = false, parse_string = true;
int skip = 0;
/* first decode a string, when there was a string, we assume it
@ -680,6 +683,16 @@ bool pw_conf_find_match(struct spa_json *arr, const struct spa_dict *props, bool
skip++;
parse_string = true;
}
if (len > skip && value[skip] == '@') {
in_array = true;
skip++;
parse_string = true;
}
if (SPA_UNLIKELY(in_array && reg)) {
pw_log_warn("@ and ~ modifiers cannot be combined in '%.*s'",
az, as);
continue;
}
str = spa_dict_lookup(props, key);
@ -701,7 +714,18 @@ bool pw_conf_find_match(struct spa_json *arr, const struct spa_dict *props, bool
continue;
}
if (reg) {
if (in_array) {
struct spa_json arr_iter;
char elem[256];
if (spa_json_begin_array_relax(&arr_iter, str, strlen(str)) > 0) {
while (spa_json_get_string(&arr_iter, elem, sizeof(elem)) > 0) {
if (strcmp(elem, val) == 0) {
success = !success;
break;
}
}
}
} else if (reg) {
regex_t preg;
int res;
if ((res = regcomp(&preg, val, REG_EXTENDED | REG_NOSUB)) != 0) {