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