conf: support ! to negate the match

So that you can do "application.name" = "!pw-cat" to match anything
that is not pw-cat and "application.name" = "!~pw-cat$".

Fixes #3460
This commit is contained in:
Wim Taymans 2023-08-25 11:39:28 +02:00
parent 0bfc02581f
commit 8dd294bf44
5 changed files with 21 additions and 14 deletions

View file

@ -95,7 +95,7 @@ jack.properties = {
jack.rules = [
{ matches = [
{
# all keys must match the value. ~ starts regex.
# all keys must match the value. ! negates. ~ starts regex.
#client.name = "Carla"
#application.process.binary = "jack_simple_client"
#application.name = "~jack_simple_client.*"

View file

@ -116,7 +116,7 @@ pulse.rules = [
{
matches = [
{
# all keys must match the value. ~ starts regex.
# all keys must match the value. ! negates. ~ starts regex.
#client.name = "Firefox"
#application.process.binary = "teams"
#application.name = "~speech-dispatcher.*"

View file

@ -93,7 +93,7 @@
* # any of the items in matches needs to match, if one does,
* # actions are emited.
* {
* # all keys must match the value. ~ in value starts regex.
* # all keys must match the value. ! negates. ~ starts regex.
* #node.name = "~alsa_input.*"
* media.class = "Audio/Sink"
* }

View file

@ -75,7 +75,7 @@
* { matches = [
* # any of the items in matches needs to match, if one does,
* # actions are emited.
* { # all keys must match the value. ~ in value starts regex.
* { # all keys must match the value. ! negates. ~ starts regex.
* #rtp.origin = "wim 3883629975 0 IN IP4 0.0.0.0"
* #rtp.payload = "127"
* #rtp.fmt = "L16/48000/2"
@ -91,7 +91,7 @@
* }
* }
* { matches = [
* { # all keys must match the value. ~ in value starts regex.
* { # all keys must match the value. ! negates. ~ starts regex.
* #rtp.origin = "wim 3883629975 0 IN IP4 0.0.0.0"
* #rtp.payload = "127"
* #rtp.fmt = "L16/48000/2"

View file

@ -586,6 +586,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
* <key> = <value>
* ...
* }
@ -598,7 +599,7 @@ static bool find_match(struct spa_json *arr, const struct spa_dict *props)
char key[256], val[1024];
const char *str, *value;
int match = 0, fail = 0;
int len;
int len, skip = 0;
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
bool success = false;
@ -615,23 +616,28 @@ static bool find_match(struct spa_json *arr, const struct spa_dict *props)
continue;
value = val;
len = strlen(val);
if (len > 0 && value[0] == '!') {
success = !success;
skip++;
}
}
if (str != NULL) {
if (value[0] == '~') {
if (value[skip] == '~') {
regex_t preg;
int res;
if ((res = regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB)) != 0) {
skip++;
if ((res = regcomp(&preg, value+skip, REG_EXTENDED | REG_NOSUB)) != 0) {
char errbuf[1024];
regerror(res, &preg, errbuf, sizeof(errbuf));
pw_log_warn("invalid regex %s: %s", value+1, errbuf);
pw_log_warn("invalid regex %s: %s", value+skip, errbuf);
} else {
if (regexec(&preg, str, 0, NULL, 0) == 0)
success = true;
success = !success;
regfree(&preg);
}
} else if (strncmp(str, value, len) == 0 &&
strlen(str) == (size_t)len) {
success = true;
} else if (strncmp(str, value+skip, len-skip) == 0 &&
strlen(str) == (size_t)(len-skip)) {
success = !success;
}
}
if (success) {
@ -639,6 +645,7 @@ static bool find_match(struct spa_json *arr, const struct spa_dict *props)
pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value);
}
else {
pw_log_debug("'%s' fail '%s' < > '%.*s'", key, str, len, value);
fail++;
break;
}
@ -1080,7 +1087,7 @@ int pw_conf_load_conf_for_context(struct pw_properties *props, struct pw_propert
* # any of the items in matches needs to match, if one does,
* # actions are emited.
* {
* # all keys must match the value. ~ in value starts regex.
* # all keys must match the value. ! negates. ~ starts regex.
* <key> = <value>
* ...
* }