On Thu, Jan 23, 2014 at 10:28:29AM +0100, Manuel VIVES wrote:
---
po/POTFILES.in | 1 +
src/libvirt_private.syms | 1 +
src/util/virstring.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/virstring.h | 3 ++
4 files changed, 102 insertions(+)
Can you add something to tests/virstringtest.c to validate your
new method with various interesting input strings.
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d1a58f9..68ca39d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1763,6 +1763,7 @@ virStorageFileResize;
# util/virstring.h
virArgvToString;
virAsprintfInternal;
+virSearchRegex;
Lets call this new method 'virStringSearchRegex' so we have a normal
name prefix
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 8d0ca70..3c93450 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include <regex.h>
#include "c-ctype.h"
#include "virstring.h"
@@ -645,3 +646,99 @@ int virStringSortRevCompare(const void *a, const void *b)
return strcmp(*sb, *sa);
}
+
+/**
+ * virSearchRegex:
+ * Allows you to get the nth occurrence of a substring in sourceString which matches
+ * a POSIX Extended regular expression pattern.
+ * If there is no substring, result is not modified.
+ * return -1 on error, 0 if not found and 1 if found.
+ *
+ * @sourceString: String to parse
+ * @occurrence: return occurrence 'n' (starting from 0) of a sub-string that
+ * matches the pattern.
+ * @regexp: POSIX Extended regular expression pattern used for matching
+ * @result: nth occurrence substring matching the @regexp pattern
+ * @code
+ char *source = "6853a496-1c10-472e-867a-8244937bd6f0
+ 773ab075-4cd7-4fc2-8b6e-21c84e9cb391
+ bbb3c75c-d60f-43b0-b802-fd56b84a4222
+ 60c04aa1-0375-4654-8d9f-e149d9885273
+ 4548d465-9891-4c34-a184-3b1c34a26aa8";
+ char *ret1=NULL;
+ char *ret2=NULL;
+ char *ret3=NULL;
+ virSearchRegex(source,
+ 4,
+
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+ &ret1);
+ //ret1 = "4548d465-9891-4c34-a184-3b1c34a26aa8"
+ virSearchRegex(source,
+ 0,
+
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+ &ret2);
+ //ret2 = "6853a496-1c10-472e-867a-8244937bd6f0"
+ virSearchRegex(source,
+ 1,
+
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+ &ret3);
+ //ret3 = "773ab075-4cd7-4fc2-8b6e-21c84e9cb391"
+ * @endcode
+int
+virSearchRegex(const char *sourceString,
+ unsigned int occurrence,
+ const char *regexp,
+ char **result)
This kind of usage leads to pretty inefficient code. Why not just
change it to return 'char ***matches' and thus give the caller all
possible matches in one call. And 'unsigned int occurrence' could
be 'size_t maxMatches' to limit it.
+{
+ regex_t pregUuidBracket;
This variable name is a little odd - lets just call it 're'.
+ size_t i = 0;
+ size_t nmatch = 0;
+ regmatch_t *pmatch = NULL;
+ int ret = -1;
+ int regError = -1;
+
+ regError = regcomp(&pregUuidBracket, regexp, REG_EXTENDED);
+ if (regError != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Error while compiling regular expression: %d"),
+ regError);
+ goto cleanup;
+ }
+ nmatch = pregUuidBracket.re_nsub;
+ if (VIR_ALLOC_N(pmatch, nmatch) < 0)
+ goto cleanup;
+
+ while (i < (occurrence+1)) {
+ if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+ regoff_t start = pmatch[0].rm_so;
+ regoff_t end = pmatch[0].rm_eo;
+ if (i == occurrence ||
+ (occurrence > i && regexec(&pregUuidBracket,
&sourceString[end],
+ nmatch, pmatch, 0) != 0)) {
+ /* We copy only if i == position (so that it is the uuid we're
looking for),
+ * or position > i AND there is no matches left in the rest of the
string
+ * (this is the case where we give a biggest @occurence than the
+ * number of matches and we want to return the last one)
+ */
+ if (VIR_STRNDUP(*result, sourceString + start, end - start) < 0)
+ goto cleanup;
+
+ ret = 1;
+ goto cleanup;
+ }
+ sourceString = &sourceString[end];
+ } else {
+ break;
+ ret = 0;
+ goto cleanup;
+ }
+ ++i;
+ }
+
+cleanup:
+ regfree(&pregUuidBracket);
+ VIR_FREE(pmatch);
+ return ret;
+}
Daniel
--
|:
http://berrange.com -o-
http://www.flickr.com/photos/dberrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|:
http://entangle-photo.org -o-
http://live.gnome.org/gtk-vnc :|