The current auto-indentation buffer code applies indentation only on complete strings. To allow adding a string containing newlines and having it properly indented this patch adds virBufferAddStr. --- src/libvirt_private.syms | 1 + src/util/virbuffer.c | 38 ++++++++++++++++++++++++++++++++++++ src/util/virbuffer.h | 1 + tests/virbuftest.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 33222f0..0beb44f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1099,6 +1099,7 @@ virBitmapToData; virBufferAdd; virBufferAddBuffer; virBufferAddChar; +virBufferAddStr; virBufferAdjustIndent; virBufferAsprintf; virBufferCheckErrorInternal; diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c index 0089d1b..50d953e 100644 --- a/src/util/virbuffer.c +++ b/src/util/virbuffer.c @@ -756,3 +756,41 @@ virBufferTrim(virBufferPtr buf, const char *str, int len) buf->use -= len < 0 ? len2 : len; buf->content[buf->use] = '\0'; } + + +/** + * virBufferAddStr: + * @buf: the buffer to append to + * @str: string to append + * + * Appends @str to @buffer. Applies autoindentation on the separate lines of + * @str. + */ +void +virBufferAddStr(virBufferPtr buf, + const char *str) +{ + size_t len = 0; + const char *start = str; + + if (!buf || !str || buf->error) + return; + + while (*str) { + len++; + + if (*str == '\n') { + virBufferAdd(buf, start, len); + str++; + len = 0; + start = str; + + continue; + } + + str++; + } + + if (len > 0) + virBufferAdd(buf, start, len); +} diff --git a/src/util/virbuffer.h b/src/util/virbuffer.h index 24e81c7..144a1ba 100644 --- a/src/util/virbuffer.h +++ b/src/util/virbuffer.h @@ -96,5 +96,6 @@ void virBufferAdjustIndent(virBufferPtr buf, int indent); int virBufferGetIndent(const virBuffer *buf, bool dynamic); void virBufferTrim(virBufferPtr buf, const char *trim, int len); +void virBufferAddStr(virBufferPtr buf, const char *str); #endif /* __VIR_BUFFER_H__ */ diff --git a/tests/virbuftest.c b/tests/virbuftest.c index f964feb..067a77e 100644 --- a/tests/virbuftest.c +++ b/tests/virbuftest.c @@ -310,6 +310,44 @@ static int testBufAddBuffer(const void *data ATTRIBUTE_UNUSED) return ret; } +struct testBufAddStrData { + const char *data; + const char *expect; +}; + +static int +testBufAddStr(const void *opaque ATTRIBUTE_UNUSED) +{ + const struct testBufAddStrData *data = opaque; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *actual; + int ret = -1; + + virBufferAddLit(&buf, "<c>\n"); + virBufferAdjustIndent(&buf, 2); + virBufferAddStr(&buf, data->data); + virBufferAdjustIndent(&buf, -2); + virBufferAddLit(&buf, "</c>"); + + if (!(actual = virBufferContentAndReset(&buf))) { + TEST_ERROR("buf is empty"); + goto cleanup; + } + + if (STRNEQ_NULLABLE(actual, data->expect)) { + TEST_ERROR("testBufAddStr(): Strings don't match:\n" + "Expected:\n%s\nActual:\n%s\n", + data->expect, actual); + goto cleanup; + } + + ret = 0; + + cleanup: + VIR_FREE(actual); + return ret; +} + static int mymain(void) @@ -330,6 +368,18 @@ mymain(void) DO_TEST("Trim", testBufTrim, 0); DO_TEST("AddBuffer", testBufAddBuffer, 0); +#define DO_TEST_ADD_STR(DATA, EXPECT) \ + do { \ + struct testBufAddStrData info = { DATA, EXPECT }; \ + if (virtTestRun("Buf: AddStr", testBufAddStr, &info) < 0) \ + ret = -1; \ + } while (0) + + DO_TEST_ADD_STR("", "<c>\n</c>"); + DO_TEST_ADD_STR("<a/>", "<c>\n <a/></c>"); + DO_TEST_ADD_STR("<a/>\n", "<c>\n <a/>\n</c>"); + DO_TEST_ADD_STR("<b>\n <a/>\n</b>\n", "<c>\n <b>\n <a/>\n </b>\n</c>"); + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 2.2.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list