[libvirt] [PATCH] virBuffer: add way to trim back extra text

Daniel Veillard veillard at redhat.com
Mon May 21 08:26:26 UTC 2012


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 at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list