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>
---
src/libvirt_private.syms | 1 +
src/util/virstring.c | 34 ++++++++++++++++++++++++++++++++++
src/util/virstring.h | 3 +++
tests/virstringtest.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 85 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index afb9100c50..d32c6e7549 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2621,6 +2621,7 @@ virStringListHasString;
virStringListJoin;
virStringListLength;
virStringListRemove;
+virStringMatch;
virStringReplace;
virStringSearch;
virStringSortCompare;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 335e773d78..b95a8926bd 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -979,6 +979,40 @@ virStringSearch(const char *str,
}
/**
+ * virStringMatch:
+ * @str: string to match
+ * @regexp: POSIX Extended regular expression pattern used for matching
+ *
+ * Performs a POSIX extended regex search against a string.
+ * Returns 0 on match, -1 on error, 1 on no match.
+ */
+int
+virStringMatch(const char *str,
+ const char *regexp)
+{
+ regex_t re;
+ int ret = -1;
+ 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));
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("error while compiling regular expression '%s': %s"),
+ regexp, error);
+ return -1;
+ }
+
+ if ((ret = regexec(&re, str, 0, NULL, 0)) != 0)
+ ret = 1;
+
+ regfree(&re);
+ return ret;
+}
+
+/**
* 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 c545ca3f0d..3221d99752 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);
+int 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 96bc79f832..f8402cd163 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;
+ int rv;
+
+ rv = virStringMatch(data->str, data->regexp);
+
+ if (data->expectMatch) {
+ if (rv != 0) {
+ fprintf(stderr, "expected match for '%s' on '%s' but got no match\n",
+ data->regexp, data->str);
+ return -1;
+ }
+ } else {
+ if (rv != 1) {
+ 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.12.2
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Thu, May 11, 2017 at 05:49:53PM +0200, Pavel Hrdina wrote: >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> >--- > src/libvirt_private.syms | 1 + > src/util/virstring.c | 34 ++++++++++++++++++++++++++++++++++ > src/util/virstring.h | 3 +++ > tests/virstringtest.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 85 insertions(+) > >diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms >index afb9100c50..d32c6e7549 100644 >--- a/src/libvirt_private.syms >+++ b/src/libvirt_private.syms >@@ -2621,6 +2621,7 @@ virStringListHasString; > virStringListJoin; > virStringListLength; > virStringListRemove; >+virStringMatch; > virStringReplace; > virStringSearch; > virStringSortCompare; >diff --git a/src/util/virstring.c b/src/util/virstring.c >index 335e773d78..b95a8926bd 100644 >--- a/src/util/virstring.c >+++ b/src/util/virstring.c >@@ -979,6 +979,40 @@ virStringSearch(const char *str, > } > > /** >+ * virStringMatch: >+ * @str: string to match >+ * @regexp: POSIX Extended regular expression pattern used for matching >+ * >+ * Performs a POSIX extended regex search against a string. >+ * Returns 0 on match, -1 on error, 1 on no match. >+ */ >+int >+virStringMatch(const char *str, >+ const char *regexp) >+{ >+ regex_t re; >+ int ret = -1; >+ 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)); >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ _("error while compiling regular expression '%s': %s"), >+ regexp, error); >+ return -1; >+ } >+ >+ if ((ret = regexec(&re, str, 0, NULL, 0)) != 0) >+ ret = 1; This could be made easier if you just retuned bool true on match and false on no match/error. Even though that would ignore one (very unlikely) error, it works much more nicely with any usage this might get in libvirt. ACK with that changed. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
On 05/11/2017 11:49 AM, Pavel Hrdina wrote: > 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> > --- > src/libvirt_private.syms | 1 + > src/util/virstring.c | 34 ++++++++++++++++++++++++++++++++++ > src/util/virstring.h | 3 +++ > tests/virstringtest.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 85 insertions(+) > Something to consider seeing as this function could be "reused" if made a bit more generic... > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index afb9100c50..d32c6e7549 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -2621,6 +2621,7 @@ virStringListHasString; > virStringListJoin; > virStringListLength; > virStringListRemove; > +virStringMatch; > virStringReplace; > virStringSearch; > virStringSortCompare; > diff --git a/src/util/virstring.c b/src/util/virstring.c > index 335e773d78..b95a8926bd 100644 > --- a/src/util/virstring.c > +++ b/src/util/virstring.c > @@ -979,6 +979,40 @@ virStringSearch(const char *str, > } > > /** > + * virStringMatch: > + * @str: string to match > + * @regexp: POSIX Extended regular expression pattern used for matching > + * > + * Performs a POSIX extended regex search against a string. > + * Returns 0 on match, -1 on error, 1 on no match. > + */ > +int > +virStringMatch(const char *str, > + const char *regexp) > +{ > + regex_t re; > + int ret = -1; > + int rv; > + > + VIR_DEBUG("match '%s' for '%s'", str, regexp); > + > + if ((rv = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB)) != 0) { Why not pass the last arg as @flags > + char error[100]; > + regerror(rv, &re, error, sizeof(error)); > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("error while compiling regular expression '%s': %s"), > + regexp, error); > + return -1; > + } > + > + if ((ret = regexec(&re, str, 0, NULL, 0)) != 0) and perhaps the 3rd/4th args as params... Could lead to some reuse of this particular function by others that also call regcomp and regexec (virStorageBackendLogicalParseVolExtents has an example of the args to regexec) John > + ret = 1; > + > + regfree(&re); > + return ret; > +} > + > +/** > * 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 c545ca3f0d..3221d99752 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); > > +int 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 96bc79f832..f8402cd163 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; > + int rv; > + > + rv = virStringMatch(data->str, data->regexp); > + > + if (data->expectMatch) { > + if (rv != 0) { > + fprintf(stderr, "expected match for '%s' on '%s' but got no match\n", > + data->regexp, data->str); > + return -1; > + } > + } else { > + if (rv != 1) { > + 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 = { \ > -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
On Fri, May 12, 2017 at 06:44:16AM -0400, John Ferlan wrote: > > > On 05/11/2017 11:49 AM, Pavel Hrdina wrote: > > 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> > > --- > > src/libvirt_private.syms | 1 + > > src/util/virstring.c | 34 ++++++++++++++++++++++++++++++++++ > > src/util/virstring.h | 3 +++ > > tests/virstringtest.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 85 insertions(+) > > > > Something to consider seeing as this function could be "reused" if made > a bit more generic... > > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > > index afb9100c50..d32c6e7549 100644 > > --- a/src/libvirt_private.syms > > +++ b/src/libvirt_private.syms > > @@ -2621,6 +2621,7 @@ virStringListHasString; > > virStringListJoin; > > virStringListLength; > > virStringListRemove; > > +virStringMatch; > > virStringReplace; > > virStringSearch; > > virStringSortCompare; > > diff --git a/src/util/virstring.c b/src/util/virstring.c > > index 335e773d78..b95a8926bd 100644 > > --- a/src/util/virstring.c > > +++ b/src/util/virstring.c > > @@ -979,6 +979,40 @@ virStringSearch(const char *str, > > } > > > > /** > > + * virStringMatch: > > + * @str: string to match > > + * @regexp: POSIX Extended regular expression pattern used for matching > > + * > > + * Performs a POSIX extended regex search against a string. > > + * Returns 0 on match, -1 on error, 1 on no match. > > + */ > > +int > > +virStringMatch(const char *str, > > + const char *regexp) > > +{ > > + regex_t re; > > + int ret = -1; > > + int rv; > > + > > + VIR_DEBUG("match '%s' for '%s'", str, regexp); > > + > > + if ((rv = regcomp(&re, regexp, REG_EXTENDED | REG_NOSUB)) != 0) { > > Why not pass the last arg as @flags In most cases there is no need to change those @flags, other possible are REG_ICASE and REG_NEWLINE. > > + char error[100]; > > + regerror(rv, &re, error, sizeof(error)); > > + virReportError(VIR_ERR_INTERNAL_ERROR, > > + _("error while compiling regular expression '%s': %s"), > > + regexp, error); > > + return -1; > > + } > > + > > + if ((ret = regexec(&re, str, 0, NULL, 0)) != 0) > > and perhaps the 3rd/4th args as params... > > Could lead to some reuse of this particular function by others that also > call regcomp and regexec (virStorageBackendLogicalParseVolExtents has an > example of the args to regexec) There is virStringSearch() that does exactly what you are referring to. However, virStringSearch() doesn't allow more than one match group, which virStorageBackendLogicalParseVolExtents uses. The purpose of virStringMatch is to match the regex in cases where you don't need the matched groups. We might extend/improve virStringSearch(). Pavel -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2025 Red Hat, Inc.