Add a virStringReplace method to virstring.{h,c} to perform substring matching and replacement Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- src/libvirt_private.syms | 1 + src/util/virstring.c | 44 +++++++++++++++++++++++++++++++++++- src/util/virstring.h | 5 ++++ tests/virstringtest.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f26190d..f7379a2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1794,6 +1794,7 @@ virStringArrayHasString; virStringFreeList; virStringJoin; virStringListLength; +virStringReplace; virStringSearch; virStringSortCompare; virStringSortRevCompare; diff --git a/src/util/virstring.c b/src/util/virstring.c index 67a87d3..3e42b06 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -619,7 +619,6 @@ size_t virStringListLength(char **strings) return i; } - /** * virStringSortCompare: * @@ -747,3 +746,46 @@ cleanup: } return ret; } + +/** + * virStringReplace: + * @haystack: the source string to process + * @oldneedle: the substring to locate + * @newneedle: the substring to insert + * + * Search @haystack and replace all occurences of @oldneedle with @newneedle. + * + * Returns: a new string with all the replacements, or NULL on error + */ +char * +virStringReplace(const char *haystack, + const char *oldneedle, + const char *newneedle) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *tmp1, *tmp2; + size_t oldneedlelen = strlen(oldneedle); + size_t newneedlelen = strlen(newneedle); + + tmp1 = haystack; + tmp2 = NULL; + + while (tmp1) { + tmp2 = strstr(tmp1, oldneedle); + + if (tmp2) { + virBufferAdd(&buf, tmp1, (tmp2 - tmp1)); + virBufferAdd(&buf, newneedle, newneedlelen); + tmp2 += oldneedlelen; + } else { + virBufferAdd(&buf, tmp1, -1); + } + + tmp1 = tmp2; + } + + if (virBufferError(&buf)) + return NULL; + + return virBufferContentAndReset(&buf); +} diff --git a/src/util/virstring.h b/src/util/virstring.h index 8efc80c..5b77581 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -232,5 +232,10 @@ ssize_t virStringSearch(const char *str, char ***matches) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4); +char *virStringReplace(const char *haystack, + const char *oldneedle, + const char *newneedle) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + #endif /* __VIR_STRING_H__ */ diff --git a/tests/virstringtest.c b/tests/virstringtest.c index b8c6115..43023d5 100644 --- a/tests/virstringtest.c +++ b/tests/virstringtest.c @@ -338,6 +338,38 @@ testStringSearch(const void *opaque ATTRIBUTE_UNUSED) return ret; } + +struct stringReplaceData { + const char *haystack; + const char *oldneedle; + const char *newneedle; + const char *result; +}; + +static int +testStringReplace(const void *opaque ATTRIBUTE_UNUSED) +{ + const struct stringReplaceData *data = opaque; + char *result; + int ret = -1; + + result = virStringReplace(data->haystack, + data->oldneedle, + data->newneedle); + + if (STRNEQ_NULLABLE(data->result, result)) { + fprintf(stderr, "Expected '%s' but got '%s'\n", + data->result, NULLSTR(result)); + goto cleanup; + } + + ret = 0; + + cleanup: + return ret; +} + + static int mymain(void) { @@ -428,6 +460,33 @@ mymain(void) const char *matches3[] = { "foo", "bar" }; TEST_SEARCH("1foo2bar3eek", "([a-z]+)", 2, 2, matches3, false); +#define TEST_REPLACE(h, o, n, r) \ + do { \ + struct stringReplaceData data = { \ + .haystack = h, \ + .oldneedle = o, \ + .newneedle = n, \ + .result = r \ + }; \ + if (virtTestRun("virStringReplace " h, testStringReplace, &data) < 0) \ + ret = -1; \ + } while (0) + + /* no matches */ + TEST_REPLACE("foo", "bar", "eek", "foo"); + + /* complete match */ + TEST_REPLACE("foo", "foo", "bar", "bar"); + + /* middle match */ + TEST_REPLACE("foobarwizz", "bar", "eek", "fooeekwizz"); + + /* many matches */ + TEST_REPLACE("foofoofoofoo", "foo", "bar", "barbarbarbar"); + + /* many matches */ + TEST_REPLACE("fooooofoooo", "foo", "bar", "barooobaroo"); + return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.8.5.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list