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 <phrdina@redhat.com>
This commit is contained in:
Pavel Hrdina 2017-05-11 17:16:13 +02:00
parent bb9055b87e
commit f15f155403
4 changed files with 83 additions and 0 deletions

View File

@ -2621,6 +2621,7 @@ virStringListHasString;
virStringListJoin; virStringListJoin;
virStringListLength; virStringListLength;
virStringListRemove; virStringListRemove;
virStringMatch;
virStringReplace; virStringReplace;
virStringSearch; virStringSearch;
virStringSortCompare; virStringSortCompare;

View File

@ -978,6 +978,38 @@ virStringSearch(const char *str,
return ret; return ret;
} }
/**
* 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: * virStringReplace:
* @haystack: the source string to process * @haystack: the source string to process

View File

@ -274,6 +274,9 @@ ssize_t virStringSearch(const char *str,
char ***matches) char ***matches)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
bool virStringMatch(const char *str,
const char *regexp);
char *virStringReplace(const char *haystack, char *virStringReplace(const char *haystack,
const char *oldneedle, const char *oldneedle,
const char *newneedle) const char *newneedle)

View File

@ -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 { struct stringReplaceData {
const char *haystack; const char *haystack;
const char *oldneedle; const char *oldneedle;
@ -803,6 +835,21 @@ mymain(void)
const char *matches3[] = { "foo", "bar" }; const char *matches3[] = { "foo", "bar" };
TEST_SEARCH("1foo2bar3eek", "([a-z]+)", 2, 2, matches3, false); 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) \ #define TEST_REPLACE(h, o, n, r) \
do { \ do { \
struct stringReplaceData data = { \ struct stringReplaceData data = { \