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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list