summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-07-30 10:34:44 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-09-04 12:59:26 +0200
commit46bf625aca8aa6f1f8608611dccddce948ded4d6 (patch)
tree80f73faafe30218572b6c15c98fbac82a1e44dbb
parentsd-login: use string_contains_word() (diff)
downloadsystemd-46bf625aca8aa6f1f8608611dccddce948ded4d6.tar.xz
systemd-46bf625aca8aa6f1f8608611dccddce948ded4d6.zip
Add string_contains_word_strv()
I had to move STRV_MAKE to macro.h. There is a circular dependency between extract-word.h, strv.h, and string-util.h that makes it hard to define the inline function otherwise.
-rw-r--r--src/basic/extract-word.c1
-rw-r--r--src/basic/macro.h3
-rw-r--r--src/basic/string-util.c17
-rw-r--r--src/basic/string-util.h6
-rw-r--r--src/basic/strv.h4
-rw-r--r--src/test/test-string-util.c30
6 files changed, 52 insertions, 9 deletions
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index 1a53da334a..d64dddd641 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -14,6 +14,7 @@
#include "log.h"
#include "macro.h"
#include "string-util.h"
+#include "strv.h"
#include "utf8.h"
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
diff --git a/src/basic/macro.h b/src/basic/macro.h
index ceea8176f5..41c2c3289e 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -538,6 +538,9 @@ static inline int __coverity_check_and_return__(int condition) {
(y) = (_t); \
} while (false)
+#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
+#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
+
/* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */
#define FOREACH_POINTER(p, x, ...) \
for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index 6d366a3510..c4f86b4ee2 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -15,6 +15,7 @@
#include "macro.h"
#include "memory-util.h"
#include "string-util.h"
+#include "strv.h"
#include "terminal-util.h"
#include "utf8.h"
#include "util.h"
@@ -1209,11 +1210,13 @@ int string_extract_line(const char *s, size_t i, char **ret) {
}
}
-int string_contains_word(const char *string, const char *separators, const char *word) {
+int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word) {
/* In the default mode with no separators specified, we split on whitespace and
* don't coalesce separators. */
const ExtractFlags flags = separators ? EXTRACT_DONT_COALESCE_SEPARATORS : 0;
+ const char *found = NULL;
+
for (const char *p = string;;) {
_cleanup_free_ char *w = NULL;
int r;
@@ -1222,8 +1225,14 @@ int string_contains_word(const char *string, const char *separators, const char
if (r < 0)
return r;
if (r == 0)
- return false;
- if (streq(w, word))
- return true;
+ break;
+
+ found = strv_find(words, w);
+ if (found)
+ break;
}
+
+ if (ret_word)
+ *ret_word = found;
+ return !!found;
}
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index e0ed5cee8c..087fb7c907 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -280,4 +280,8 @@ char* string_erase(char *x);
int string_truncate_lines(const char *s, size_t n_lines, char **ret);
int string_extract_line(const char *s, size_t i, char **ret);
-int string_contains_word(const char *string, const char *separators, const char *word);
+
+int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word);
+static inline int string_contains_word(const char *string, const char *separators, const char *word) {
+ return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL);
+}
diff --git a/src/basic/strv.h b/src/basic/strv.h
index e57dfff69b..bc0b04b56b 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -123,10 +123,6 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;
char **strv_sort(char **l);
void strv_print(char * const *l);
-#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
-
-#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
-
#define strv_from_stdarg_alloca(first) \
({ \
char **_l; \
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 0834e0b969..b39fda0313 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -796,6 +796,35 @@ static void test_string_extract_line(void) {
test_string_extract_lines_one("\n\n\nx\n", 3, "x", false);
}
+static void test_string_contains_word_strv(void) {
+ log_info("/* %s */", __func__);
+
+ const char *w;
+
+ assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), NULL));
+
+ assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), &w));
+ assert_se(streq(w, "a"));
+
+ assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE("d"), &w));
+ assert_se(w == NULL);
+
+ assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", "a"), &w));
+ assert_se(streq(w, "a"));
+
+ assert_se(string_contains_word_strv("b a b cc", NULL, STRV_MAKE("b", "a", "b"), &w));
+ assert_se(streq(w, "b"));
+
+ assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", ""), &w));
+ assert_se(streq(w, "b"));
+
+ assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE(""), &w));
+ assert_se(w == NULL);
+
+ assert_se(string_contains_word_strv("a b cc", " ", STRV_MAKE(""), &w));
+ assert_se(streq(w, ""));
+}
+
static void test_string_contains_word(void) {
log_info("/* %s */", __func__);
@@ -884,6 +913,7 @@ int main(int argc, char *argv[]) {
test_memory_startswith_no_case();
test_string_truncate_lines();
test_string_extract_line();
+ test_string_contains_word_strv();
test_string_contains_word();
return 0;