On 02/19/2014 09:36 PM, Daniel P. Berrange wrote: > 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: > * Unrelated whitespace change. > @@ -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)) virBufferError doesn't report an error, but I think this function should. > + return NULL; > + > + return virBufferContentAndReset(&buf); > +} > diff --git a/tests/virstringtest.c b/tests/virstringtest.c > index b8c6115..43023d5 100644 > --- a/tests/virstringtest.c > +++ b/tests/virstringtest.c > @@ -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; > } > A test with different length of old and new needles would be nice. ACK with error reporting. Jan
Attachment:
signature.asc
Description: OpenPGP digital signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list