--- po/POTFILES.in | 1 + src/libvirt_private.syms | 1 + src/util/virstring.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/virstring.h | 3 ++ 4 files changed, 102 insertions(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index 0359b2f..738cfb1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -188,6 +188,7 @@ src/util/virscsi.c src/util/virsocketaddr.c src/util/virstatslinux.c src/util/virstoragefile.c +src/util/virstring.c src/util/virsysinfo.c src/util/virerror.c src/util/virerror.h 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; virSkipSpaces; virSkipSpacesAndBackslash; virSkipSpacesBackwards; 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) +{ + regex_t pregUuidBracket; + 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; +} diff --git a/src/util/virstring.h b/src/util/virstring.h index 13a6e5a..fe05403 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -226,4 +226,7 @@ size_t virStringListLength(char **strings); int virStringSortCompare(const void *a, const void *b); int virStringSortRevCompare(const void *a, const void *b); +int virSearchRegex(const char *sourceString, unsigned int occurrence, const char *regexp, char **result); + + #endif /* __VIR_STRING_H__ */ -- 1.7.10.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list