[libvirt] [PATCH 01/14] snapshot: indent domain xml when nesting, round 1

Eric Blake eblake at redhat.com
Thu Sep 22 20:34:55 UTC 2011


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);
 }
-- 
1.7.4.4




More information about the libvir-list mailing list