On Thu, Sep 22, 2011 at 02:34:55PM -0600, Eric Blake wrote: > Future patches can take advantage of this to generate nicer > XML output with parameterizable indentation. > > On the side, I had some temporary test failures as I was using > these functions in later patches, with output that looked like: > > Expected [<] > Actual [ <] > > which is pretty hard to figure out. Adding an Offset designation > made it much easier to find which particular '<' was at the > wrong indentation, to fix the right part of the code. > > * src/util/buf.h (virBufferIndentAdd, virBufferIndentAddLit) > (virBufferIndentEscapeString): New prototypes and macro. > * src/libvirt_private.syms (buf.h): Export new functions. > * src/util/buf.c (virBufferAdd): Move body... > (virBufferIndentAdd): ...to new function. > (virBufferIndentEscapeString): New function. > * tests/virbuftest.c (testBufIndentation): Test it. > * tests/testutils.c (virtTestDifference): Make it easier to > diagnose test failures. > --- > src/libvirt_private.syms | 2 + > src/util/buf.c | 70 ++++++++++++++++++++++++++++++++++++--------- > src/util/buf.h | 19 ++++++++++-- > tests/testutils.c | 2 +- > tests/virbuftest.c | 32 ++++++++++++++++++++- > 5 files changed, 105 insertions(+), 20 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 8235ea1..1523289 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -28,6 +28,8 @@ virBufferError; > virBufferEscapeSexpr; > virBufferEscapeString; > virBufferFreeAndReset; > +virBufferIndentAdd; > +virBufferIndentEscapeString; > virBufferStrcat; > virBufferURIEncodeString; > virBufferUse; > diff --git a/src/util/buf.c b/src/util/buf.c > index 5002486..061d83b 100644 > --- a/src/util/buf.c > +++ b/src/util/buf.c > @@ -78,21 +78,23 @@ virBufferGrow(virBufferPtr buf, unsigned int len) > } > > /** > - * virBufferAdd: > - * @buf: the buffer to add to > - * @str: the string > - * @len: the number of bytes to add > + * virBufferIndentAdd: > + * @buf: the buffer to add to > + * @indent: amount of indentation > + * @str: the string, or NULL to skip indentation > + * @len: the number of bytes to add > * > - * Add a string range to an XML buffer. if len == -1, the length of > - * str is recomputed to the full string. > + * Add indentation, then a string range to an XML buffer. if len == -1, the > + * length of str is recomputed to the full string. > * > */ > void > -virBufferAdd(const virBufferPtr buf, const char *str, int len) > +virBufferIndentAdd(const virBufferPtr buf, int indent, > + const char *str, int len) > { > unsigned int needSize; > > - if ((str == NULL) || (buf == NULL) || (len == 0)) > + if (!str || !buf || (len == 0 && indent == 0)) > return; > > if (buf->error) > @@ -101,17 +103,34 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len) > if (len < 0) > len = strlen(str); > > - needSize = buf->use + len + 2; > + needSize = buf->use + indent + len + 2; > if (needSize > buf->size && > virBufferGrow(buf, needSize - buf->use) < 0) > return; > > - memcpy (&buf->content[buf->use], str, len); > - buf->use += len; > + memset (&buf->content[buf->use], ' ', indent); > + memcpy (&buf->content[buf->use + indent], str, len); > + buf->use += indent + len; > buf->content[buf->use] = '\0'; > } > > /** > + * virBufferAdd: > + * @buf: the buffer to add to > + * @str: the string > + * @len: the number of bytes to add > + * > + * Add a string range to an XML buffer. if len == -1, the length of > + * str is recomputed to the full string. > + * > + */ > +void > +virBufferAdd(const virBufferPtr buf, const char *str, int len) > +{ > + virBufferIndentAdd(buf, 0, str, len); > +} > + > +/** > * virBufferAddChar: > * @buf: the buffer to add to > * @c: the character to add > @@ -120,7 +139,7 @@ virBufferAdd(const virBufferPtr buf, const char *str, int len) > * > */ > void > -virBufferAddChar (virBufferPtr buf, char c) > +virBufferAddChar(virBufferPtr buf, char c) > { > unsigned int needSize; > > @@ -290,10 +309,12 @@ virBufferVasprintf(const virBufferPtr buf, const char *format, va_list argptr) > * @str: the string argument which need to be escaped > * > * Do a formatted print with a single string to an XML buffer. The string > - * is escaped to avoid generating a not well-formed XML instance. > + * is escaped to avoid generating a not well-formed XML instance. If > + * @str is NULL, nothing is added (not even the rest of @format). > */ > void > -virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str) > +virBufferEscapeString(const virBufferPtr buf, const char *format, > + const char *str) > { > int len; > char *escaped, *out; > @@ -369,6 +390,27 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st > } > > /** > + * virBufferIndentEscapeString: > + * @buf: the buffer to dump > + * @indent: amount of indentation > + * @format: a printf like format string but with only one %s parameter > + * @str: the string argument which need to be escaped, or NULL for no action > + * > + * Do a formatted print with a single string to an XML buffer, with leading > + * indentation. The single %s string is escaped to avoid generating a not > + * well-formed XML instance. > + */ > +void > +virBufferIndentEscapeString(const virBufferPtr buf, int indent, > + const char *format, const char *str) > +{ > + if (str) { > + virBufferIndentAdd(buf, indent, "", 0); > + virBufferEscapeString(buf, format, str); > + } > +} > + > +/** > * virBufferEscapeSexpr: > * @buf: the buffer to dump > * @format: a printf like format string but with only one %s parameter > diff --git a/src/util/buf.h b/src/util/buf.h > index 06d01ba..c5e2874 100644 > --- a/src/util/buf.h > +++ b/src/util/buf.h > @@ -48,11 +48,22 @@ void virBufferVasprintf(const virBufferPtr buf, const char *format, va_list ap) > ATTRIBUTE_FMT_PRINTF(2, 0); > void virBufferStrcat(const virBufferPtr buf, ...) > ATTRIBUTE_SENTINEL; > -void virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str); > -void virBufferEscapeSexpr(const virBufferPtr buf, const char *format, const char *str); > -void virBufferURIEncodeString (const virBufferPtr buf, const char *str); > +void virBufferEscapeString(const virBufferPtr buf, const char *format, > + const char *str); > +void virBufferEscapeSexpr(const virBufferPtr buf, const char *format, > + const char *str); > +void virBufferURIEncodeString(const virBufferPtr buf, const char *str); > > # define virBufferAddLit(buf_, literal_string_) \ > - virBufferAdd (buf_, "" literal_string_ "", sizeof literal_string_ - 1) > + virBufferAdd(buf_, "" literal_string_ "", sizeof literal_string_ - 1) > + > +void virBufferIndentAdd(const virBufferPtr buf, int indent, > + const char *str, int len); > +void virBufferIndentEscapeString(const virBufferPtr buf, int indent, > + const char *format, const char *str); > + > +# define virBufferIndentAddLit(buf_, indent_, literal_string_) \ > + virBufferIndentAdd(buf_, indent_, "" literal_string_ "", \ > + sizeof literal_string_ - 1) > > #endif /* __VIR_BUFFER_H__ */ > diff --git a/tests/testutils.c b/tests/testutils.c > index d9582af..b107d3c 100644 > --- a/tests/testutils.c > +++ b/tests/testutils.c > @@ -359,7 +359,7 @@ int virtTestDifference(FILE *stream, > } > > /* Show the trimmed differences */ > - fprintf(stream, "\nExpect ["); > + fprintf(stream, "\nOffset %d\nExpect [", (int) (expectStart - expect)); > if ((expectEnd - expectStart + 1) && > fwrite(expectStart, (expectEnd-expectStart+1), 1, stream) != 1) > return -1; > diff --git a/tests/virbuftest.c b/tests/virbuftest.c > index 01db313..0a99e78 100644 > --- a/tests/virbuftest.c > +++ b/tests/virbuftest.c > @@ -20,7 +20,7 @@ struct testInfo { > int doEscape; > }; > > -static int testBufInfiniteLoop(const void *data ATTRIBUTE_UNUSED) > +static int testBufInfiniteLoop(const void *data) > { > virBuffer bufinit = VIR_BUFFER_INITIALIZER; > virBufferPtr buf = &bufinit; > @@ -63,6 +63,35 @@ out: > return ret; > } > > +static int testBufIndentation(const void *data ATTRIBUTE_UNUSED) > +{ > + virBuffer bufinit = VIR_BUFFER_INITIALIZER; > + virBufferPtr buf = &bufinit; > + const char expected[] = "ab c d &"; > + char *result = NULL; > + int ret = 0; > + > + virBufferIndentAdd(buf, 0, "a", -1); > + virBufferIndentAdd(buf, 0, "", -1); > + virBufferIndentAdd(buf, 0, "", 0); > + virBufferIndentAddLit(buf, 0, ""); > + virBufferIndentAddLit(buf, 0, "b"); > + virBufferIndentAdd(buf, 3, NULL, -1); > + virBufferIndentAdd(buf, 2, "c", -1); > + virBufferIndentAddLit(buf, 1, ""); > + virBufferIndentEscapeString(buf, 1, "%s", "d"); > + virBufferIndentEscapeString(buf, 3, "%s", NULL); > + virBufferIndentEscapeString(buf, 2, "%s", "&"); > + > + result = virBufferContentAndReset(buf); > + if (!result || STRNEQ(result, expected)) { > + TEST_ERROR("Built buffer was wrong: %s", NULLSTR(result)); > + ret = -1; > + } > + VIR_FREE(result); > + return ret; > +} > + > static int > mymain(void) > { > @@ -78,6 +107,7 @@ mymain(void) > > DO_TEST("EscapeString infinite loop", testBufInfiniteLoop, 1); > DO_TEST("VSprintf infinite loop", testBufInfiniteLoop, 0); > + DO_TEST("Indentation", testBufIndentation, 0); > > return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); > } Looks fine to me, ACK 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