diff --git a/spa/include/spa/utils/string.h b/spa/include/spa/utils/string.h index 393f272cb..a41d07936 100644 --- a/spa/include/spa/utils/string.h +++ b/spa/include/spa/utils/string.h @@ -62,6 +62,26 @@ static inline bool spa_strneq(const char *s1, const char *s2, size_t len) return SPA_LIKELY(s1 && s2) ? strncmp(s1, s2, len) == 0 : s1 == s2; } + +/** + * \return true if \a s ends with the \a suffix or false otherwise. + * A \a s is NULL, it never ends with the given \a suffix. A \a suffix of + * NULL is a bug in the caller. + */ +static inline bool spa_strendswith(const char *s, const char *suffix) +{ + size_t l1, l2; + + if (SPA_UNLIKELY(s == NULL)) + return false; + + spa_assert(suffix); + + l1 = strlen(s); + l2 = strlen(suffix); + return l1 >= l2 && spa_streq(s + l1 - l2, suffix); +} + /** * Convert \a str to an int32_t with the given \a base and store the * result in \a val. diff --git a/src/modules/module-protocol-pulse/defs.h b/src/modules/module-protocol-pulse/defs.h index 780a02d53..ce3e0b366 100644 --- a/src/modules/module-protocol-pulse/defs.h +++ b/src/modules/module-protocol-pulse/defs.h @@ -197,14 +197,6 @@ static inline int node_state(enum pw_node_state state) return STATE_INVALID; } -static inline bool pw_endswith(const char *s, const char *sfx) -{ - size_t l1, l2; - l1 = strlen(s); - l2 = strlen(sfx); - return l1 >= l2 && strcmp(s + l1 - l2, sfx) == 0; -} - enum { SINK_HW_VOLUME_CTRL = 0x0001U, SINK_LATENCY = 0x0002U, diff --git a/src/modules/module-protocol-pulse/modules/module-echo-cancel.c b/src/modules/module-protocol-pulse/modules/module-echo-cancel.c index f5a6db3e4..8a919d1c5 100644 --- a/src/modules/module-protocol-pulse/modules/module-echo-cancel.c +++ b/src/modules/module-protocol-pulse/modules/module-echo-cancel.c @@ -190,7 +190,7 @@ struct module *create_module_echo_cancel(struct impl *impl, const char *argument } if ((str = pw_properties_get(props, "source_master")) != NULL) { - if (pw_endswith(str, ".monitor")) { + if (spa_strendswith(str, ".monitor")) { pw_properties_setf(source_props, PW_KEY_NODE_TARGET, "%.*s", (int)strlen(str)-8, str); } else { diff --git a/src/modules/module-protocol-pulse/modules/module-loopback.c b/src/modules/module-protocol-pulse/modules/module-loopback.c index f943389db..568f50a66 100644 --- a/src/modules/module-protocol-pulse/modules/module-loopback.c +++ b/src/modules/module-protocol-pulse/modules/module-loopback.c @@ -157,7 +157,7 @@ struct module *create_module_loopback(struct impl *impl, const char *argument) */ if ((str = pw_properties_get(props, "source")) != NULL) { - if (pw_endswith(str, ".monitor")) { + if (spa_strendswith(str, ".monitor")) { pw_properties_setf(capture_props, PW_KEY_NODE_TARGET, "%.*s", (int)strlen(str)-8, str); } else { diff --git a/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c b/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c index eab5ace09..8ab1420bd 100644 --- a/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c +++ b/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c @@ -171,7 +171,7 @@ struct module *create_module_simple_protocol_tcp(struct impl *impl, const char * } if ((str = pw_properties_get(props, "source")) != NULL) { - if (pw_endswith(str, ".monitor")) { + if (spa_strendswith(str, ".monitor")) { pw_properties_setf(module_props, "capture.node", "%.*s", (int)strlen(str)-8, str); } else { diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index 4ba5e26f5..5ab23db2f 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -1726,7 +1726,7 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint pw_properties_setf(props, PW_KEY_NODE_TARGET, "%u", source_index); } else if (source_name != NULL) { - if (pw_endswith(source_name, ".monitor")) { + if (spa_strendswith(source_name, ".monitor")) { pw_properties_setf(props, PW_KEY_NODE_TARGET, "%.*s", (int)strlen(source_name)-8, source_name); @@ -2125,7 +2125,7 @@ static struct pw_manager_object *find_device(struct client *client, id = SPA_ID_INVALID; if (name != NULL && !sink) { - if (pw_endswith(name, ".monitor")) { + if (spa_strendswith(name, ".monitor")) { name = strndupa(name, strlen(name)-8); monitor = true; } else if (spa_streq(name, DEFAULT_MONITOR)) { @@ -3903,7 +3903,7 @@ static int do_get_info(struct client *client, uint32_t command, uint32_t tag, st } if (command == COMMAND_GET_SOURCE_INFO && - sel.value != NULL && pw_endswith(sel.value, ".monitor")) { + sel.value != NULL && spa_strendswith(sel.value, ".monitor")) { sel.value = strndupa(sel.value, strlen(sel.value)-8); } @@ -4314,7 +4314,7 @@ static int do_set_default(struct client *client, uint32_t command, uint32_t tag, if (name != NULL) { if (o->props && (str = pw_properties_get(o->props, PW_KEY_NODE_NAME)) != NULL) name = str; - else if (pw_endswith(name, ".monitor")) + else if (spa_strendswith(name, ".monitor")) name = strndupa(name, strlen(name)-8); res = pw_manager_set_metadata(manager, client->metadata_default, diff --git a/test/test-spa-utils.c b/test/test-spa-utils.c index ad2d22646..9ed2311c3 100644 --- a/test/test-spa-utils.c +++ b/test/test-spa-utils.c @@ -694,6 +694,26 @@ PWTEST(utils_streq) return PWTEST_PASS; } +PWTEST(utils_strendswith) +{ + pwtest_bool_true(spa_strendswith("foo", "o")); + pwtest_bool_true(spa_strendswith("foobar", "bar")); + + pwtest_bool_false(spa_strendswith(NULL, "bar")); + pwtest_bool_false(spa_strendswith("foo", "f")); + pwtest_bool_false(spa_strendswith("foo", "fo")); + pwtest_bool_false(spa_strendswith("foo", "foobar")); + + return PWTEST_PASS; +} + +PWTEST(utils_strendswith_null_suffix) +{ + spa_strendswith("foo", NULL); + + return PWTEST_FAIL; +} + PWTEST(utils_atob) { pwtest_bool_true(spa_atob("true")); @@ -862,6 +882,9 @@ PWTEST_SUITE(spa_utils) pwtest_add(utils_strtof, PWTEST_NOARG); pwtest_add(utils_strtod, PWTEST_NOARG); pwtest_add(utils_streq, PWTEST_NOARG); + pwtest_add(utils_strendswith, PWTEST_NOARG); + pwtest_add(utils_strendswith_null_suffix, + PWTEST_ARG_SIGNAL, SIGABRT); pwtest_add(utils_snprintf, PWTEST_NOARG); pwtest_add(utils_snprintf_abort_neg_size, PWTEST_ARG_SIGNAL, SIGABRT,