
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 :|