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:
* @haystack: the source string to process
}
+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;
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 = { \