On Fri, May 18, 2012 at 04:42:36PM -0600, Eric Blake wrote: > I'm tired of writing: > > bool sep = false; > while (...) { > if (sep) > virBufferAddChar(buf, ','); > sep = true; > virBufferAdd(buf, str); > } > > This makes it easier, allowing one to write: > > while (...) > virBufferAsprintf(buf, "%s,", str); > virBufferTrim(buf, ",", -1); > > to trim any remaining comma. > > * src/util/buf.h (virBufferTrim): Declare. > * src/util/buf.c (virBufferTrim): New function. > * tests/virbuftest.c (testBufTrim): Test it. > --- > > I've threatened to do this enough times, so I finally carried through > with my threat :) > > src/util/buf.c | 36 +++++++++++++++++++++++++++++++++ > src/util/buf.h | 2 + > tests/virbuftest.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 94 insertions(+), 0 deletions(-) > > diff --git a/src/util/buf.c b/src/util/buf.c > index d18f6af..630e4c9 100644 > --- a/src/util/buf.c > +++ b/src/util/buf.c > @@ -612,3 +612,39 @@ virBufferStrcat(virBufferPtr buf, ...) > virBufferAdd(buf, str, -1); > va_end(ap); > } > + > +/** > + * virBufferTrim: > + * @buf: the buffer to trim > + * @str: the optional string, to force an exact trim > + * @len: the number of bytes to trim, or -1 to use @str > + * > + * Trim the tail of a buffer. If @str is provided, the trim only occurs > + * if the current tail of the buffer matches @str; a non-negative @len > + * further limits how much of the tail is trimmed. If @str is NULL, then > + * @len must be non-negative. > + * > + * Returns -1 if @buf has previously encountered an error or if @len is > + * invalid, 0 if there was nothing to trim (@buf was too short or @str > + * didn't match), and 1 if the trim was successful. > + */ > +int > +virBufferTrim(virBufferPtr buf, const char *str, int len) > +{ > + size_t len2 = 0; > + > + if (!buf || buf->error || (!str && len < 0)) > + return -1; > + > + if (len > 0 && len > buf->use) > + return 0; > + if (str) { > + len2 = strlen(str); > + if (len2 > buf->use || > + memcmp(&buf->content[buf->use - len2], str, len2) != 0) > + return 0; > + } > + buf->use -= len < 0 ? len2 : len; > + buf->content[buf->use] = '\0'; > + return 1; > +} > diff --git a/src/util/buf.h b/src/util/buf.h > index d6bc8f3..a8e2eb5 100644 > --- a/src/util/buf.h > +++ b/src/util/buf.h > @@ -64,4 +64,6 @@ void virBufferURIEncodeString(virBufferPtr buf, const char *str); > void virBufferAdjustIndent(virBufferPtr buf, int indent); > int virBufferGetIndent(const virBufferPtr buf, bool dynamic); > > +int virBufferTrim(virBufferPtr buf, const char *trim, int len); > + > #endif /* __VIR_BUFFER_H__ */ > diff --git a/tests/virbuftest.c b/tests/virbuftest.c > index 9058920..cd02db1 100644 > --- a/tests/virbuftest.c > +++ b/tests/virbuftest.c > @@ -133,6 +133,61 @@ static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED) > return ret; > } > > +static int testBufTrim(const void *data ATTRIBUTE_UNUSED) > +{ > + virBuffer bufinit = VIR_BUFFER_INITIALIZER; > + virBufferPtr buf = NULL; > + char *result = NULL; > + const char *expected = "a,b"; > + int ret = -1; > + int i = 1; > + > +#define ACT(str, len, result) \ > + do { \ > + if (virBufferTrim(buf, str, len) != result) { \ > + TEST_ERROR("trim %d failed", i); \ > + goto cleanup; \ > + } \ > + i++; \ > + } while (0); > + > + if (virBufferTrim(buf, "", 0) != -1) { > + TEST_ERROR("Wrong failure detection 1"); > + goto cleanup; > + } > + buf = &bufinit; > + if (virBufferTrim(buf, NULL, -1) != -1) { > + TEST_ERROR("Wrong failure detection 2"); > + goto cleanup; > + } > + > + virBufferAddLit(buf, "a;"); > + ACT("", 0, 1); > + ACT("", -1, 1); > + ACT(NULL, 1, 1); > + ACT(NULL, 5, 0); > + ACT("a", 2, 0); > + > + virBufferAddLit(buf, ",b,,"); > + ACT("b", -1, 0); > + ACT("b,,", 1, 1); > + ACT(",", -1, 1); > + > + result = virBufferContentAndReset(buf); > + if (!result || STRNEQ(result, expected)) { > + virtTestDifference(stderr, expected, result); > + goto cleanup; > + } > + > + ret = 0; > + > +cleanup: > + virBufferFreeAndReset(buf); > + VIR_FREE(result); > + return ret; > +} > + > + > static int > mymain(void) > { > @@ -149,6 +204,7 @@ mymain(void) > DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1); > DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0); > DO_TEST("Auto-indentation", testBufAutoIndent, 0); > + DO_TEST("Trim", testBufTrim, 0); > > return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; > } ACK, interesting addition :-) Code looks fine, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list