From a05097ee436b03de9280a9ae25f85a150ddaa327 Mon Sep 17 00:00:00 2001 Message-Id: From: Pavel Hrdina Date: Tue, 16 May 2017 11:46:11 +0200 Subject: [PATCH] util: introduce virStringMatch Simply tries to match the provided regex on a string and returns the result. Useful if caller don't care about the matched substring and want to just test if some pattern patches a string. Signed-off-by: Pavel Hrdina (cherry picked from commit f15f155403e36a66e3568676105fdca725ad2c52) Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1446980 Signed-off-by: Pavel Hrdina Signed-off-by: Jiri Denemark --- src/libvirt_private.syms | 1 + src/util/virstring.c | 32 ++++++++++++++++++++++++++++++++ src/util/virstring.h | 3 +++ tests/virstringtest.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 134d4a832..06c338384 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2599,6 +2599,7 @@ virStringListHasString; virStringListJoin; virStringListLength; virStringListRemove; +virStringMatch; virStringReplace; virStringSearch; virStringSortCompare; diff --git a/src/util/virstring.c b/src/util/virstring.c index 69abc267b..5b2be317b 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -979,6 +979,38 @@ virStringSearch(const char *str, } /** + * virStringMatch: + * @str: string to match + * @regexp: POSIX Extended regular expression pattern used for matching + * + * Performs a POSIX extended regex match against a string. + * Returns true on match, false on error or no match. + */ +bool +virStringMatch(const char *str, + const char *regexp) +{ + regex_t re; + int rv; + + VIR_DEBUG("match '%s' for '%s'", str, regexp); + + if ((rv = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB)) != 0) { + char error[100]; + regerror(rv, &re, error, sizeof(error)); + VIR_WARN("error while compiling regular expression '%s': %s", + regexp, error); + return false; + } + + rv = regexec(&re, str, 0, NULL, 0); + + regfree(&re); + + return rv == 0; +} + +/** * virStringReplace: * @haystack: the source string to process * @oldneedle: the substring to locate diff --git a/src/util/virstring.h b/src/util/virstring.h index a5550e30d..0df03473a 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -274,6 +274,9 @@ ssize_t virStringSearch(const char *str, char ***matches) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4); +bool virStringMatch(const char *str, + const char *regexp); + char *virStringReplace(const char *haystack, const char *oldneedle, const char *newneedle) diff --git a/tests/virstringtest.c b/tests/virstringtest.c index db1731f96..d27c8a5a8 100644 --- a/tests/virstringtest.c +++ b/tests/virstringtest.c @@ -480,6 +480,38 @@ testStringSearch(const void *opaque) } +struct stringMatchData { + const char *str; + const char *regexp; + bool expectMatch; +}; + +static int +testStringMatch(const void *opaque) +{ + const struct stringMatchData *data = opaque; + bool match; + + match = virStringMatch(data->str, data->regexp); + + if (data->expectMatch) { + if (!match) { + fprintf(stderr, "expected match for '%s' on '%s' but got no match\n", + data->regexp, data->str); + return -1; + } + } else { + if (match) { + fprintf(stderr, "expected no match for '%s' on '%s' but got match\n", + data->regexp, data->str); + return -1; + } + } + + return 0; +} + + struct stringReplaceData { const char *haystack; const char *oldneedle; @@ -803,6 +835,21 @@ mymain(void) const char *matches3[] = { "foo", "bar" }; TEST_SEARCH("1foo2bar3eek", "([a-z]+)", 2, 2, matches3, false); +#define TEST_MATCH(s, r, m) \ + do { \ + struct stringMatchData data = { \ + .str = s, \ + .regexp = r, \ + .expectMatch = m, \ + }; \ + if (virTestRun("virStringMatch " s, testStringMatch, &data) < 0) \ + ret = -1; \ + } while (0) + + TEST_MATCH("foo", "foo", true); + TEST_MATCH("foobar", "f[o]+", true); + TEST_MATCH("foobar", "^f[o]+$", false); + #define TEST_REPLACE(h, o, n, r) \ do { \ struct stringReplaceData data = { \ -- 2.13.0